Skip to content

Commit

Permalink
feat: load highlight to webworker if available
Browse files Browse the repository at this point in the history
  • Loading branch information
felixmosh committed Feb 16, 2023
1 parent 4154258 commit eb92f12
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 16 deletions.
1 change: 1 addition & 0 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"highlight.js": "^11.5.1",
"html-webpack-plugin": "^5.5.0",
"mini-css-extract-plugin": "^2.6.0",
"nanoid": "^4.0.1",
"postcss": "^8.4.12",
"postcss-loader": "^6.1.1",
"postcss-preset-env": "^7.4.3",
Expand Down
23 changes: 7 additions & 16 deletions packages/ui/src/components/Highlight/Highlight.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import hljs from 'highlight.js/lib/core';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import json from 'highlight.js/lib/languages/json';
import cn from 'clsx';
import React from 'react';
import { stacktraceJS } from './languages/stacktrace';

hljs.registerLanguage('json', json);
hljs.registerLanguage('stacktrace', stacktraceJS);
import { asyncHighlight } from '../../utils/highlight/highlight';

interface HighlightProps {
language: 'json' | 'stacktrace';
Expand All @@ -30,27 +22,26 @@ export class Highlight extends React.Component<HighlightProps> {
}

public componentDidMount() {
this.highlightCode();
return this.highlightCode();
}

public componentDidUpdate() {
this.highlightCode();
return this.highlightCode();
}

public render() {
const { language } = this.props;
return (
<pre ref={this.codeRef}>
<code className={language} />
<code className={cn('hljs', language)} />
</pre>
);
}

private highlightCode() {
private async highlightCode() {
const node = this.codeRef.current?.querySelector('code');
if (node) {
node.textContent = this.props.children;
hljs.highlightElement(node);
node.innerHTML = await asyncHighlight(this.props.children as string, this.props.language);
}
}
}
12 changes: 12 additions & 0 deletions packages/ui/src/utils/highlight/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import hljs from 'highlight.js/lib/core';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import json from 'highlight.js/lib/languages/json';
import { stacktraceJS } from './languages/stacktrace';

hljs.registerLanguage('json', json);
hljs.registerLanguage('stacktrace', stacktraceJS);

export const highlighter = hljs;
47 changes: 47 additions & 0 deletions packages/ui/src/utils/highlight/highlight.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { nanoid } from 'nanoid';

const isWebworkerSupported = typeof window.Worker !== 'undefined';
let highlightWorker: Worker | null = null;
const messageQueue = new Map<string, { resolve: any; reject: any }>();

export async function asyncHighlight(code: string, language: string): Promise<string> {
if (isWebworkerSupported) {
if (!highlightWorker) {
highlightWorker = new Worker(
/* webpackChunkName: "highlight-worker" */ new URL('./worker.ts', import.meta.url)
);
highlightWorker.onmessage = ({ data }) => {
const { id, code } = data;
if (messageQueue.has(id)) {
const { resolve } = messageQueue.get(id) as any;
resolve(code);
}
};
}

return new Promise((resolve, reject) => {
const messageId = nanoid(5);
highlightWorker?.postMessage({ id: messageId, code, language });
messageQueue.set(messageId, {
resolve: (formattedCode: string) => {
messageQueue.delete(messageId);
resolve(formattedCode);
},
reject: () => {
messageQueue.delete(messageId);
reject();
},
});
setTimeout(() => reject(), 60 * 1000);
});
} else {
const { highlighter } = await import(
/* webpackChunkName: "highlight" */
/* webpackMode: "lazy-once" */
/* webpackPreload: true */
'./config'
);

return highlighter.highlightAuto(code, [language]).value || '';
}
}
12 changes: 12 additions & 0 deletions packages/ui/src/utils/highlight/worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { highlighter } from './config';

self.onmessage = ({ data = {} }) => {
const { id = '', code = '', language = '' } = data;
if (!id || !code || !language) {
return;
}

const resp = highlighter.highlightAuto(code, [language]);

self.postMessage({ code: resp.value, id });
};
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9684,6 +9684,11 @@ nanoid@^3.3.1, nanoid@^3.3.4:
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==

nanoid@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-4.0.1.tgz#398d7ccfdbf9faf2231b2ca7e8fff5dbca6a509b"
integrity sha512-udKGtCCUafD3nQtJg9wBhRP3KMbPglUsgV5JVsXhvyBs/oefqb4sqMEhKBBgqZncYowu58p1prsZQBYvAj/Gww==

natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
Expand Down

0 comments on commit eb92f12

Please sign in to comment.