diff options
Diffstat (limited to 'polygerrit-ui/app/workers/syntax-worker.ts')
-rw-r--r-- | polygerrit-ui/app/workers/syntax-worker.ts | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/polygerrit-ui/app/workers/syntax-worker.ts b/polygerrit-ui/app/workers/syntax-worker.ts new file mode 100644 index 0000000000..1ddb9c67dd --- /dev/null +++ b/polygerrit-ui/app/workers/syntax-worker.ts @@ -0,0 +1,84 @@ +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import {HighlightJS} from '../types/types'; +import { + SyntaxWorkerMessage, + SyntaxWorkerResult, + isRequest, + isInit, +} from '../types/syntax-worker-api'; +import {highlightedStringToRanges} from '../utils/syntax-util'; +import {importScript} from '../utils/worker-util'; + +// This is an entry point file of a bundle. Keep free of exports! + +/** + * This is a web worker for calling the HighlightJS library for syntax + * highlighting. Files can be large and highlighting does not require + * the `document` or the `DOM`, so it is a perfect fit for a web worker. + * + * This file is a just a hub hooking into the web worker API. The message + * events for communicating with the main app are defined in the file + * `types/worker-api.ts`. And the `meat` of the computation is done in the + * file `syntax-util.ts`. + */ + +/** + * `self` is for a worker what `window` is for the web app. It is called + * the `DedicatedWorkerGlobalScope`, see + * https://developer.mozilla.org/en-US/docs/Web/API/DedicatedWorkerGlobalScope + * + * Once imported the HighlightJS lib exposes its functionality via the global + * `hljs` variable. + */ +const ctx = self as DedicatedWorkerGlobalScope & {hljs?: HighlightJS}; + +/** + * We are encapsulating the web worker API here, so this is the only place + * where you need to know about it and the MessageEvents in this file. + */ +ctx.onmessage = function (e: MessageEvent<SyntaxWorkerMessage>) { + try { + const message = e.data; + if (isInit(message)) { + worker.init(message.url); + const result: SyntaxWorkerResult = {ranges: []}; + ctx.postMessage(result); + } + if (isRequest(message)) { + const ranges = worker.highlightCode(message.language, message.code); + const result: SyntaxWorkerResult = {ranges}; + ctx.postMessage(result); + } + } catch (err) { + let error = 'syntax worker error'; + if (err instanceof Error) error = err.message; + const result: SyntaxWorkerResult = {error, ranges: []}; + ctx.postMessage(result); + } +}; + +class SyntaxWorker { + private highlightJsLib?: HighlightJS; + + init(highlightJsLibUrl: string) { + importScript(ctx, highlightJsLibUrl); + if (!ctx.hljs) { + throw new Error('HighlightJS lib not available after import'); + } + this.highlightJsLib = ctx.hljs; + this.highlightJsLib.configure({classPrefix: ''}); + } + + highlightCode(language: string, code: string) { + if (!this.highlightJsLib) throw new Error('worker not initialized'); + const highlighted = this.highlightJsLib.highlight(language, code, true); + return highlightedStringToRanges(highlighted.value); + } +} + +/** Singleton instance being referenced in `onmessage` function above. */ +const worker = new SyntaxWorker(); |