mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
Merge 131 upstream commits from fuma-nama/fumadocs dev branch, bringing framework packages to v16.6.17. All fumadocs-* and @fumadocs/* package references renamed to @hanzo/docs-* namespace. Upstream additions: - packages/content/ (@hanzo/docs-content) - Fuma Content adapter - packages/epub/ (@hanzo/docs-epub) - EPUB export support - MarkdownCopyButton, ViewOptionsPopover in docs page layout - Flexsearch, Orama search integration - Shiki v4 upgrade - Various UI framework improvements Hanzo customizations preserved: - apps/docs/content/ (all Hanzo service/project docs) - apps/docs/app/ (Hanzo homepage, AI chat, subdomain routing) - apps/docs/components/ (AI search, error boundaries, auth) - apps/docs/lib/ (source config, OpenAPI, metadata) - Webpack alias layer for upstream project doc imports - MdxErrorBoundary wrapper for graceful MDX failures
58 lines
1.4 KiB
TypeScript
58 lines
1.4 KiB
TypeScript
import type { TOCItemType } from '@hanzo/docs-core/toc';
|
|
import Slugger from 'github-slugger';
|
|
import parse, { type DOMNode, domToReact } from 'html-react-parser';
|
|
import { Heading } from '@hanzo/docs-ui/components/heading';
|
|
import { ServerCodeBlock } from '@hanzo/docs-ui/components/codeblock.rsc';
|
|
|
|
export function renderFromHtml(content: string) {
|
|
const toc: TOCItemType[] = [];
|
|
const slugger = new Slugger();
|
|
|
|
const node = parse(content, {
|
|
replace(node) {
|
|
if (node.type !== 'tag') return node;
|
|
|
|
const heading = /^h(\d)$/.exec(node.name);
|
|
if (heading) {
|
|
const depth = Number(heading[1]);
|
|
const string = stringify(node);
|
|
const id = slugger.slug(string);
|
|
|
|
toc.push({
|
|
title: string,
|
|
depth,
|
|
url: `#${id}`,
|
|
});
|
|
|
|
return (
|
|
<Heading as={`h${depth}` as 'h1'} id={id}>
|
|
{domToReact(node.children as DOMNode[])}
|
|
</Heading>
|
|
);
|
|
}
|
|
|
|
if (node.name === 'pre') {
|
|
return <ServerCodeBlock lang="tsx" code={stringify(node)} />;
|
|
}
|
|
},
|
|
});
|
|
|
|
return { node, toc };
|
|
}
|
|
|
|
function stringify(node: DOMNode): string {
|
|
if (node.type === 'text') return node.data;
|
|
if ('children' in node) {
|
|
return node.children
|
|
.map((node) => {
|
|
if (node.type === 'cdata' || node.type === 'root') return;
|
|
|
|
return stringify(node);
|
|
})
|
|
.filter(Boolean)
|
|
.join('');
|
|
}
|
|
|
|
return '';
|
|
}
|