import type { ClassList, PropsOf } from "@builder.io/qwik"; import { $, component$, useSignal, useTask$, useVisibleTask$, } from "@builder.io/qwik"; import { isDev } from "@builder.io/qwik/build"; import { getHighlighterCore } from "shiki"; import css from "shiki/langs/css.mjs"; import html from "shiki/langs/html.mjs"; import tsx from "shiki/langs/tsx.mjs"; import poimandres from "shiki/themes/poimandres.mjs"; import { CopyButton } from "../CopyButton/CopyButton"; export type HighlightProps = PropsOf<"div"> & { code: string; copyCodeClass?: ClassList; language?: "tsx" | "html" | "css"; splitCommentStart?: string; splitCommentEnd?: string; }; export const Highlight = component$( ({ code, copyCodeClass, language = "tsx", splitCommentStart = "{/* start */}", splitCommentEnd = "{/* end */}", ...props }: HighlightProps) => { const codeSig = useSignal(""); const addShiki$ = $(async () => { let modifiedCode: string = code; let partsOfCode = modifiedCode.split(splitCommentStart); if (partsOfCode.length > 1) { modifiedCode = partsOfCode[1]; } partsOfCode = modifiedCode.split(splitCommentEnd); if (partsOfCode.length > 1) { modifiedCode = partsOfCode[0]; } const highlighter = await getHighlighterCore({ themes: [poimandres], langs: [html, css, tsx], loadWasm: import("shiki/wasm"), }); const str = highlighter.codeToHtml(modifiedCode, { lang: language, themes: { light: "poimandres", dark: "poimandres", }, }); codeSig.value = str.toString(); }); useTask$(async ({ track }) => { track(() => code); if (!isDev) { await addShiki$(); } }); // eslint-disable-next-line qwik/no-use-visible-task useVisibleTask$(async ({ track }) => { track(() => code); if (isDev) { await addShiki$(); } }); return (
); }, );