CodeBlock.tsx 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. import {
  2. type JSX,
  3. onCleanup,
  4. splitProps,
  5. createEffect,
  6. createResource,
  7. } from "solid-js"
  8. import { codeToHtml } from "shiki"
  9. import styles from "./codeblock.module.css"
  10. import { transformerNotationDiff } from "@shikijs/transformers"
  11. interface CodeBlockProps extends JSX.HTMLAttributes<HTMLDivElement> {
  12. code: string
  13. lang?: string
  14. onRendered?: () => void
  15. }
  16. function CodeBlock(props: CodeBlockProps) {
  17. const [local, rest] = splitProps(props, ["code", "lang", "onRendered"])
  18. let containerRef!: HTMLDivElement
  19. const [html] = createResource(async () => {
  20. return (await codeToHtml(local.code, {
  21. lang: local.lang || "text",
  22. themes: {
  23. light: "github-light",
  24. dark: "github-dark",
  25. },
  26. transformers: [transformerNotationDiff()],
  27. })) as string
  28. })
  29. onCleanup(() => {
  30. if (containerRef) containerRef.innerHTML = ""
  31. })
  32. createEffect(() => {
  33. if (html() && containerRef) {
  34. containerRef.innerHTML = html() as string
  35. local.onRendered?.()
  36. }
  37. })
  38. return <div ref={containerRef} class={styles.codeblock} {...rest}></div>
  39. }
  40. export default CodeBlock