g1t/apps/web/app/lib/highlight.server.ts

35 lines1,241 bytesCodeBlame
1// Shiki and its grammars load on the first file highlighted, not when the
2// Worker starts: most requests highlight nothing.
3const shiki = () => import("./shiki");
4
5const MAX_HIGHLIGHT_CHARS = 200_000;
6
7/**
8 * Highlighted HTML for a file, or null when its language is unknown or it
9 * is too large, in which case the caller shows plain text.
10 */
11export async function highlight(path: string, text: string): Promise<string | null> {
12 const { THEME, getHighlighter, languageOf } = await shiki();
13 const lang = languageOf(path);
14 if (!lang || text.length > MAX_HIGHLIGHT_CHARS) return null;
15 try {
16 return (await getHighlighter()).codeToHtml(text.replace(/\n$/, ""), { lang, theme: THEME });
17 } catch {
18 return null;
19 }
20}
21
22/**
23 * A file's lines as highlighted HTML, one string per line, or null when its
24 * language is unknown or it is too large.
25 */
26export async function highlightLines(path: string, text: string): Promise<string[] | null> {
27 const { getHighlighter, languageOf, linesToHtml } = await shiki();
28 const lang = languageOf(path);
29 if (!lang || text.length > MAX_HIGHLIGHT_CHARS) return null;
30 try {
31 return linesToHtml(await getHighlighter(), text.replace(/\n$/, ""), lang);
32 } catch {
33 return null;
34 }
35}