| /** | |
| * @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(); |