import { createSignal, onMount, Show, createEffect } from "solid-js" import type { Highlighter } from "shiki/bundle/full" import { useTheme } from "../lib/theme" import { getSharedHighlighter, escapeHtml } from "../lib/markdown" const inlineLoadedLanguages = new Set() type LoadLanguageArg = Parameters[0] type CodeToHtmlOptions = Parameters[1] interface CodeBlockInlineProps { code: string language?: string } export function CodeBlockInline(props: CodeBlockInlineProps) { const { isDark } = useTheme() const [html, setHtml] = createSignal("") const [copied, setCopied] = createSignal(false) const [ready, setReady] = createSignal(false) let highlighter: Highlighter | null = null onMount(async () => { highlighter = await getSharedHighlighter() setReady(true) await updateHighlight() }) createEffect(() => { if (ready()) { isDark() props.code props.language void updateHighlight() } }) const updateHighlight = async () => { if (!highlighter) return if (!props.language) { setHtml(`
${escapeHtml(props.code)}
`) return } try { const language = props.language as LoadLanguageArg if (!inlineLoadedLanguages.has(props.language)) { await highlighter.loadLanguage(language) inlineLoadedLanguages.add(props.language) } const highlighted = highlighter.codeToHtml(props.code, { lang: props.language as CodeToHtmlOptions["lang"], theme: isDark() ? "github-dark" : "github-light", }) setHtml(highlighted) } catch { setHtml(`
${escapeHtml(props.code)}
`) } } const copyCode = async () => { await navigator.clipboard.writeText(props.code) setCopied(true) setTimeout(() => setCopied(false), 2000) } return ( {props.code} } >
{props.language}
) }