import { createHighlighterCore, type HighlighterCore, type LanguageInput, } from "shiki/core"; import { createJavaScriptRegexEngine } from "shiki/engine/javascript"; // --------------------------------------------------------------------------- // Supported languages — explicit imports to avoid bundling all grammars // --------------------------------------------------------------------------- const SUPPORTED_LANGS = [ "json", "xml", "yaml", "shellscript", "typescript", "javascript", "python", "html", "css", "markdown", "sql", "graphql", "go", "rust", "java", "ruby", "php", "swift", "kotlin", "c", "cpp", "csharp", "tsx", "jsx", "toml", "dockerfile", "diff", "http", "jsonc", "log", "proto", ] as const; type SupportedLang = (typeof SUPPORTED_LANGS)[number]; const LANG_ALIASES: Record = { sh: "shellscript", shell: "shellscript", bash: "shellscript", zsh: "shellscript", ts: "typescript", js: "javascript", py: "python", rb: "ruby", rs: "rust", "c++": "cpp", "c#": "csharp", cs: "csharp", kt: "kotlin", md: "markdown", gql: "graphql", yml: "yaml", }; const LANG_LOADERS: Record LanguageInput> = { json: () => import("@shikijs/langs/json"), xml: () => import("@shikijs/langs/xml"), yaml: () => import("@shikijs/langs/yaml"), shellscript: () => import("@shikijs/langs/shellscript"), typescript: () => import("@shikijs/langs/typescript"), javascript: () => import("@shikijs/langs/javascript"), python: () => import("@shikijs/langs/python"), html: () => import("@shikijs/langs/html"), css: () => import("@shikijs/langs/css"), markdown: () => import("@shikijs/langs/markdown"), sql: () => import("@shikijs/langs/sql"), graphql: () => import("@shikijs/langs/graphql"), go: () => import("@shikijs/langs/go"), rust: () => import("@shikijs/langs/rust"), java: () => import("@shikijs/langs/java"), ruby: () => import("@shikijs/langs/ruby"), php: () => import("@shikijs/langs/php"), swift: () => import("@shikijs/langs/swift"), kotlin: () => import("@shikijs/langs/kotlin"), c: () => import("@shikijs/langs/c"), cpp: () => import("@shikijs/langs/cpp"), csharp: () => import("@shikijs/langs/csharp"), tsx: () => import("@shikijs/langs/tsx"), jsx: () => import("@shikijs/langs/jsx"), toml: () => import("@shikijs/langs/toml"), dockerfile: () => import("@shikijs/langs/dockerfile"), diff: () => import("@shikijs/langs/diff"), http: () => import("@shikijs/langs/http"), jsonc: () => import("@shikijs/langs/jsonc"), log: () => import("@shikijs/langs/log"), proto: () => import("@shikijs/langs/proto"), }; const supportedSet = new Set([ ...SUPPORTED_LANGS, ...Object.keys(LANG_ALIASES), ]); export const THEME = "vitesse-dark"; export function resolveLang(lang: string): SupportedLang | null { const l = lang.trim().toLowerCase(); if (l in LANG_LOADERS) return l as SupportedLang; if (l in LANG_ALIASES) return LANG_ALIASES[l]!; return null; } export function isSupportedLang(lang: string): boolean { return supportedSet.has(lang.trim().toLowerCase()); } // --------------------------------------------------------------------------- // Shared singleton highlighter — lazy, created on first use // --------------------------------------------------------------------------- const jsEngine = createJavaScriptRegexEngine({ forgiving: true }); let _promise: Promise | null = null; export function getHighlighter(): Promise { if (!_promise) { _promise = createHighlighterCore({ themes: [import("@shikijs/themes/vitesse-dark")], langs: Object.values(LANG_LOADERS).map((loader) => loader()), engine: jsEngine, }); } return _promise; } // --------------------------------------------------------------------------- // Streamdown code highlighter plugin // --------------------------------------------------------------------------- import type { CodeHighlighterPlugin, ThemeInput } from "streamdown"; const tokensCache = new Map(); const pendingCallbacks = new Map void>>(); export function createCodeHighlighterPlugin(): CodeHighlighterPlugin { return { name: "shiki" as const, type: "code-highlighter" as const, getSupportedLanguages: () => [...SUPPORTED_LANGS] as string[] as never, getThemes: () => [THEME as ThemeInput, THEME as ThemeInput], supportsLanguage: (language: string) => isSupportedLang(language), highlight(options, callback) { const resolved = resolveLang(options.language); const lang = resolved ?? "json"; const key = `${lang}:${options.code.length}:${options.code.slice(0, 128)}`; const cached = tokensCache.get(key); if (cached) return cached as never; if (callback) { if (!pendingCallbacks.has(key)) { pendingCallbacks.set(key, new Set()); } pendingCallbacks.get(key)!.add(callback as (result: unknown) => void); } void getHighlighter().then((highlighter) => { if (tokensCache.has(key)) { const result = tokensCache.get(key); pendingCallbacks.get(key)?.forEach((cb) => cb(result)); pendingCallbacks.delete(key); return; } const result = highlighter.codeToTokens(options.code, { lang, themes: { light: THEME, dark: THEME }, }); tokensCache.set(key, result); pendingCallbacks.get(key)?.forEach((cb) => cb(result)); pendingCallbacks.delete(key); }); return null; }, }; }