e7738de6d2
CI / Deep Native Runtime Cases (1/6) (push) Has been skipped
CI / Native Preflight (push) Failing after 1s
CI / Native Runtime Cases (1/2) (push) Failing after 0s
CI / Native Runtime Cases (2/2) (push) Failing after 1s
CI / Native Metadata Reports (push) Failing after 0s
CI / Native Direct Backend Artifacts (push) Failing after 0s
CI / Native Sanitizer Smoke (push) Failing after 1s
CI / Command Contract Snapshots (push) Failing after 1s
CI / Deep Conformance Suite (push) Has been skipped
CI / Graph Build Perf (push) Failing after 1s
CI / Deep Native Preflight (push) Has been skipped
CI / Deep Native Runtime Cases (2/6) (push) Has been skipped
CI / Deep Native Runtime Cases (3/6) (push) Has been skipped
CI / Conformance Suite (push) Failing after 1s
CI / Workspace Checks (push) Failing after 0s
CI / Deep Native Runtime Cases (5/6) (push) Has been skipped
CI / Deep Native Runtime Cases (6/6) (push) Has been skipped
CI / Deep Native Runtime Cases (4/6) (push) Has been skipped
CI / Deep Graph Build Perf (push) Has been skipped
63 lines
2.1 KiB
TypeScript
63 lines
2.1 KiB
TypeScript
// Rewrites ```json-render fenced code blocks into custom elements carrying
|
|
// base64-encoded JSON, so the docs can embed structured React components
|
|
// without switching the pipeline to MDX. Runs before rehype-pretty-code so the
|
|
// block is never treated as a normal code fence.
|
|
|
|
type HastNode = {
|
|
type?: string;
|
|
tagName?: string;
|
|
value?: string;
|
|
properties?: Record<string, unknown>;
|
|
children?: HastNode[];
|
|
};
|
|
|
|
function getNodeText(node?: HastNode): string {
|
|
if (!node) return "";
|
|
if (node.type === "text") return node.value ?? "";
|
|
if (!Array.isArray(node.children)) return "";
|
|
return node.children.map(getNodeText).join("");
|
|
}
|
|
|
|
function getCodeLanguage(node: HastNode): string {
|
|
const className = node.properties?.className;
|
|
const classes = Array.isArray(className)
|
|
? className
|
|
: typeof className === "string"
|
|
? className.split(/\s+/)
|
|
: [];
|
|
const languageClass = classes.find(
|
|
(value) => typeof value === "string" && value.startsWith("language-"),
|
|
);
|
|
return typeof languageClass === "string" ? languageClass.slice("language-".length) : "";
|
|
}
|
|
|
|
function visit(node: HastNode | undefined, callback: (node: HastNode) => void): void {
|
|
if (!node) return;
|
|
callback(node);
|
|
if (Array.isArray(node.children)) {
|
|
for (const child of node.children) visit(child, callback);
|
|
}
|
|
}
|
|
|
|
export function rehypeJsonRender(): (tree: HastNode) => void {
|
|
return (tree: HastNode) => {
|
|
visit(tree, (node) => {
|
|
if (node.type !== "element" || node.tagName !== "pre") return;
|
|
const code = node.children?.find(
|
|
(child) => child.type === "element" && child.tagName === "code",
|
|
);
|
|
if (!code || getCodeLanguage(code) !== "json-render") return;
|
|
|
|
const raw = getNodeText(code).replace(/\n$/, "");
|
|
let tagName = "agentchat";
|
|
try {
|
|
const parsed = JSON.parse(raw) as { type?: string };
|
|
if (parsed.type === "flow") tagName = "flowchart";
|
|
} catch {}
|
|
node.tagName = tagName;
|
|
node.properties = { value: Buffer.from(raw, "utf8").toString("base64") };
|
|
node.children = [];
|
|
});
|
|
};
|
|
}
|