blob: 1ddb9c67dd59ee4d0d7d4d9d30f66dc9ec9740b3 [file] [log] [blame]
/**
* @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();