aboutsummaryrefslogtreecommitdiffhomepage
path: root/frontend/app
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/app')
-rw-r--r--frontend/app/components/Gaming/CodeBlock.tsx32
-rw-r--r--frontend/app/highlight.ts20
2 files changed, 27 insertions, 25 deletions
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<string | null>(null);
+ const [nodes, setNodes] = useState<JSX.Element | null>(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 (
<pre className="h-full w-full p-2 bg-gray-50 rounded-lg border border-gray-300 whitespace-pre-wrap break-words">
- {highlightedCode === null ? (
- <code>{code}</code>
- ) : (
- <code dangerouslySetInnerHTML={{ __html: highlightedCode }} />
- )}
+ {nodes === null ? <code>{code}</code> : nodes}
</pre>
);
}
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;
+}