cloudaxe-opencode/packages/web/src/components/CodeBlock.tsx

48 lines
1.1 KiB
TypeScript
Raw Normal View History

2025-05-30 17:58:32 +00:00
import {
type JSX,
onCleanup,
splitProps,
createEffect,
createResource,
} from "solid-js"
import { codeToHtml } from "shiki"
2025-06-03 19:55:31 +00:00
import styles from "./codeblock.module.css"
2025-05-31 18:41:00 +00:00
import { transformerNotationDiff } from "@shikijs/transformers"
2025-05-30 17:58:32 +00:00
interface CodeBlockProps extends JSX.HTMLAttributes<HTMLDivElement> {
code: string
lang?: string
2025-06-03 21:20:24 +00:00
onRendered?: () => void
2025-05-30 17:58:32 +00:00
}
function CodeBlock(props: CodeBlockProps) {
2025-06-03 21:20:24 +00:00
const [local, rest] = splitProps(props, ["code", "lang", "onRendered"])
2025-05-30 17:58:32 +00:00
let containerRef!: HTMLDivElement
2025-06-18 00:26:09 +00:00
const [html] = createResource(() => [local.code, local.lang], async ([code, lang]) => {
return (await codeToHtml(code || "", {
lang: lang || "text",
2025-05-30 17:58:32 +00:00
themes: {
2025-05-31 18:41:00 +00:00
light: "github-light",
dark: "github-dark",
2025-05-30 17:58:32 +00:00
},
2025-05-31 18:41:00 +00:00
transformers: [transformerNotationDiff()],
2025-05-30 17:58:32 +00:00
})) as string
})
onCleanup(() => {
if (containerRef) containerRef.innerHTML = ""
})
createEffect(() => {
if (html() && containerRef) {
containerRef.innerHTML = html() as string
2025-06-03 21:20:24 +00:00
local.onRendered?.()
2025-05-30 17:58:32 +00:00
}
})
2025-06-03 19:55:31 +00:00
return <div ref={containerRef} class={styles.codeblock} {...rest}></div>
2025-05-30 17:58:32 +00:00
}
export default CodeBlock