Replace direct Shiki usage with @pierre/diffs File component

Use the File component from @pierre/diffs/react instead of manually
creating a Shiki highlighter instance. Register the custom DOT grammar
via attachResolvedLanguages and drop the direct shiki dependency.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-02-28 16:49:43 -05:00
parent 664dc91bf5
commit 615a3a2dbf
5 changed files with 48 additions and 105 deletions

View file

@ -35,21 +35,6 @@
radial-gradient(ellipse 80% 50% at 85% 90%, rgba(90, 200, 168, 0.07) 0%, transparent 45%);
background-attachment: fixed;
}
/* ── Shiki syntax highlighting ── */
.shiki-container pre.shiki {
background: transparent !important;
margin: 0;
padding: 1rem 1.25rem;
font-family: var(--font-mono);
font-size: 0.8125rem;
line-height: 1.7;
}
.shiki-container pre.shiki code {
font-family: inherit;
}
/* ── @pierre/diffs brand overrides ── */
:root {

View file

@ -1,4 +1,4 @@
import type { LanguageRegistration } from "shiki";
import type { LanguageRegistration } from "@pierre/diffs";
export const dotLanguage: LanguageRegistration = {
name: "dot",

View file

@ -0,0 +1,17 @@
import type { BundledLanguage } from "@pierre/diffs";
import {
attachResolvedLanguages,
getSharedHighlighter,
} from "@pierre/diffs";
import { dotLanguage } from "./dot-grammar";
export async function registerDotLanguage(): Promise<void> {
const highlighter = await getSharedHighlighter({
themes: ["pierre-dark"],
langs: [],
});
attachResolvedLanguages(
{ name: "dot" as BundledLanguage, data: [dotLanguage] },
highlighter,
);
}

View file

@ -1,94 +1,24 @@
import { ChevronRightIcon } from "@heroicons/react/20/solid";
import { useEffect, useRef, useState } from "react";
import { useEffect, useState } from "react";
import { useParams } from "react-router";
import type { BundledLanguage } from "@pierre/diffs";
import { File } from "@pierre/diffs/react";
import { registerDotLanguage } from "../data/register-dot-language";
import { workflowData } from "./workflow-detail";
import { dotLanguage } from "../data/dot-grammar";
function CodeBlock({
code,
lang,
filename,
defaultOpen = true,
}: {
code: string;
lang: string;
filename: string;
defaultOpen?: boolean;
}) {
const containerRef = useRef<HTMLDivElement>(null);
const [ready, setReady] = useState(false);
const [open, setOpen] = useState(defaultOpen);
useEffect(() => {
let cancelled = false;
async function highlight() {
const { createHighlighter } = await import("shiki");
if (cancelled) return;
const highlighter = await createHighlighter({
themes: ["nord"],
langs: lang === "dot" ? [dotLanguage] : [lang],
});
if (cancelled) return;
const html = highlighter.codeToHtml(code, {
lang,
theme: "nord",
});
if (cancelled || containerRef.current == null) return;
containerRef.current.innerHTML = html;
setReady(true);
}
highlight();
return () => {
cancelled = true;
};
}, [code, lang]);
const lines = code.split("\n");
const lineCount = lines.length;
const loc = lines.filter((l) => l.trim().length > 0).length;
return (
<div className="rounded-lg border border-white/[0.06] bg-navy-800/50 overflow-hidden">
<button
type="button"
onClick={() => setOpen((v) => !v)}
className="flex w-full items-center gap-2 px-4 py-2.5 text-left hover:bg-white/[0.02] transition-colors"
>
<ChevronRightIcon
className={`size-4 text-navy-600 transition-transform duration-150 ${open ? "rotate-90" : ""}`}
/>
<span className="font-mono text-xs text-navy-600">{filename}</span>
<span className="ml-auto font-mono text-xs text-navy-600/60">
{lineCount} lines ({loc} loc)
</span>
</button>
<div className={open ? "" : "hidden"}>
<div className="border-t border-white/[0.06]" />
<div
ref={containerRef}
className={`shiki-container overflow-x-auto transition-opacity duration-200 ${ready ? "opacity-100" : "opacity-0"}`}
/>
{!ready && (
<pre className="px-4 py-4 font-mono text-sm leading-relaxed text-navy-600">
{code}
</pre>
)}
</div>
</div>
);
}
export default function WorkflowDefinition() {
const { name } = useParams();
const workflow = workflowData[name ?? ""];
const [dotReady, setDotReady] = useState(false);
useEffect(() => {
let cancelled = false;
registerDotLanguage().then(() => {
if (!cancelled) setDotReady(true);
});
return () => {
cancelled = true;
};
}, []);
if (workflow == null) {
return <p className="text-sm text-navy-600">No configuration found.</p>;
@ -96,8 +26,20 @@ export default function WorkflowDefinition() {
return (
<div className="flex flex-col gap-6">
<CodeBlock code={workflow.config} lang="toml" filename="task.toml" defaultOpen={false} />
<CodeBlock code={workflow.graph} lang="dot" filename={workflow.filename} />
<File
file={{ name: "task.toml", contents: workflow.config, lang: "toml" }}
options={{ theme: "pierre-dark" }}
/>
{dotReady && (
<File
file={{
name: workflow.filename,
contents: workflow.graph,
lang: "dot" as BundledLanguage,
}}
options={{ theme: "pierre-dark" }}
/>
)}
</div>
);
}

View file

@ -18,8 +18,7 @@
"isbot": "^5.1.31",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-router": "7.12.0",
"shiki": "^4.0.0"
"react-router": "7.12.0"
},
"devDependencies": {
"@react-router/dev": "7.12.0",