From f1701822ed069d70841e8b40392e55bb28bf3eb6 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Thu, 20 Mar 2025 21:58:21 +0900 Subject: fix(frontend): prevent flickering --- frontend/app/components/Gaming/CodeBlock.tsx | 32 ++++++---------------------- frontend/app/highlight.ts | 20 +++++++++++++++++ 2 files changed, 27 insertions(+), 25 deletions(-) create mode 100644 frontend/app/highlight.ts (limited to 'frontend/app') diff --git a/frontend/app/components/Gaming/CodeBlock.tsx b/frontend/app/components/Gaming/CodeBlock.tsx index 16ff84e..019709a 100644 --- a/frontend/app/components/Gaming/CodeBlock.tsx +++ b/frontend/app/components/Gaming/CodeBlock.tsx @@ -1,39 +1,21 @@ -import { useEffect, useState } from "react"; -import { codeToHtml } from "../../shiki.bundle"; +import { JSX, useLayoutEffect, useState } from "react"; +import { type BundledLanguage, highlight } from "../../highlight"; type Props = { code: string; - language: string; + language: BundledLanguage; }; export default function CodeBlock({ code, language }: Props) { - const [highlightedCode, setHighlightedCode] = useState(null); + const [nodes, setNodes] = useState(null); - useEffect(() => { - let isMounted = true; - - (async () => { - const highlighted = await codeToHtml(code, { - lang: language, - theme: "github-light", - }); - if (isMounted) { - setHighlightedCode(highlighted); - } - })(); - - return () => { - isMounted = false; - }; + useLayoutEffect(() => { + highlight(code, language).then(setNodes); }, [code, language]); return (
-			{highlightedCode === null ? (
-				{code}
-			) : (
-				
-			)}
+			{nodes === null ? {code} : nodes}
 		
); } diff --git a/frontend/app/highlight.ts b/frontend/app/highlight.ts new file mode 100644 index 0000000..1eea8a2 --- /dev/null +++ b/frontend/app/highlight.ts @@ -0,0 +1,20 @@ +import { toJsxRuntime } from "hast-util-to-jsx-runtime"; +import { Fragment, type JSX } from "react"; +import { jsx, jsxs } from "react/jsx-runtime"; +import { type BundledLanguage, codeToHast } from "./shiki.bundle"; + +export type { BundledLanguage }; + +// https://shiki.matsu.io/packages/next +export async function highlight(code: string, lang: BundledLanguage) { + const out = await codeToHast(code.trimEnd(), { + lang, + theme: "github-light", + }); + + return toJsxRuntime(out, { + Fragment, + jsx, + jsxs, + }) as JSX.Element; +} -- cgit v1.2.3-70-g09d2