// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: MIT // cSpell: ignore shiki shikijs import { useEffect, useState, type ReactNode } from "react"; import parse from "html-react-parser"; import darkSlint from "./dark-theme.json"; import lightSlint from "./light-theme.json"; // The default Shiki bundle is >9MB due to all the default themes and languages. // The following setup if for a minimal bundle size of ~1MB. import { createHighlighterCore } from "shiki/core"; import { createOnigurumaEngine } from "shiki/engine/oniguruma"; import type { LanguageRegistration, ThemeRegistration, HighlighterCore, } from "@shikijs/types"; import OnigurumaEngine from "shiki/wasm"; import slintLang from "../../../../../docs/common/src/utils/slint.tmLanguage.json"; import { getColorTheme, subscribeColorTheme } from "../../utils/bolt-utils.js"; let highlighter: HighlighterCore | null = null; async function initHighlighter() { highlighter = await createHighlighterCore({ themes: [ darkSlint as ThemeRegistration, lightSlint as ThemeRegistration, ], langs: [slintLang as LanguageRegistration], engine: createOnigurumaEngine(OnigurumaEngine), }); } export default function CodeSnippet({ code }: { code: string }) { const [highlightedCode, setHighlightedCode] = useState( null, ); const [lightOrDarkMode, setLightOrDarkMode] = useState(getColorTheme()); useEffect(() => { subscribeColorTheme((mode) => { setLightOrDarkMode(mode); }); }, []); useEffect(() => { let isMounted = true; const highlightCode = async () => { if (!highlighter) { await initHighlighter(); } const html = highlighter!.codeToHtml(code, { lang: "slint", theme: lightOrDarkMode === "dark" ? "dark-slint" : "light-slint", }); if (isMounted) { setHighlightedCode(parse(html)); } }; highlightCode().catch(console.error); return () => { isMounted = false; }; }, [code, lightOrDarkMode]); return (
{highlightedCode}
); }