mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
Docgen: Support custom defaultValue for remark-ts2js
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'fumadocs-core': patch
|
||||
---
|
||||
|
||||
[Internal] `parseCodeBlockAttributes` include null values, restrict `rehype-code` to only parse `title` and `tab` attributes.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'fumadocs-docgen': patch
|
||||
---
|
||||
|
||||
Support custom `defaultValue` for `remark-ts2js`
|
||||
@@ -91,7 +91,7 @@ export function generateCodeBlockTabs({
|
||||
}
|
||||
|
||||
export interface CodeBlockAttributes<Name extends string = string> {
|
||||
attributes: Partial<Record<Name, string>>;
|
||||
attributes: Partial<Record<Name, string | null>>;
|
||||
rest: string;
|
||||
}
|
||||
|
||||
@@ -103,13 +103,13 @@ export function parseCodeBlockAttributes<Name extends string = string>(
|
||||
allowedNames?: Name[],
|
||||
): CodeBlockAttributes<Name> {
|
||||
let str = meta;
|
||||
const StringRegex = /(?<=^|\s)(?<name>\w+)=(?:"([^"]*)"|'([^']*)')/g;
|
||||
const attributes: Partial<Record<Name, string>> = {};
|
||||
const StringRegex = /(?<=^|\s)(?<name>\w+)(?:=(?:"([^"]*)"|'([^']*)'))?/g;
|
||||
const attributes: CodeBlockAttributes['attributes'] = {};
|
||||
|
||||
str = str.replaceAll(StringRegex, (match, name, value_1, value_2) => {
|
||||
if (allowedNames && !allowedNames.includes(name)) return match;
|
||||
|
||||
attributes[name as Name] = value_1 ?? value_2;
|
||||
attributes[name] = value_1 ?? value_2 ?? null;
|
||||
return '';
|
||||
});
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ export const rehypeCodeDefaultOptions: RehypeCodeOptions = {
|
||||
}),
|
||||
],
|
||||
parseMetaString(meta) {
|
||||
const parsed = parseCodeBlockAttributes(meta);
|
||||
const parsed = parseCodeBlockAttributes(meta, ['title', 'tab']);
|
||||
const data: Record<string, unknown> = parsed.attributes;
|
||||
parsed.rest = parseLineNumber(parsed.rest, data);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { readFileSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { remark } from 'remark';
|
||||
import {
|
||||
parseCodeBlockAttributes,
|
||||
rehypeToc,
|
||||
remarkAdmonition,
|
||||
remarkHeading,
|
||||
@@ -160,3 +161,21 @@ test('Rehype Toc', async () => {
|
||||
path.resolve(cwd, './fixtures/rehype-toc.output.js'),
|
||||
);
|
||||
});
|
||||
|
||||
test('parse meta strings', () => {
|
||||
expect(
|
||||
parseCodeBlockAttributes(
|
||||
`title="hello 'world'" tab='hello "world"' twoslash funny:invalid="" 'invalid'name="test"`,
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
{
|
||||
"attributes": {
|
||||
"funny": null,
|
||||
"tab": "hello "world"",
|
||||
"title": "hello 'world'",
|
||||
"twoslash": null,
|
||||
},
|
||||
"rest": " :invalid="" 'invalid'name="test"",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
@@ -18,6 +18,8 @@ export interface TypeScriptToJavaScriptOptions {
|
||||
}
|
||||
| false;
|
||||
|
||||
defaultValue?: 'js' | 'ts';
|
||||
|
||||
/**
|
||||
* Transform all TypeScript codeblocks by default, without a trigger
|
||||
*/
|
||||
@@ -40,6 +42,7 @@ export interface TypeScriptToJavaScriptOptions {
|
||||
*/
|
||||
export function remarkTypeScriptToJavaScript({
|
||||
persist = false,
|
||||
defaultValue = 'ts',
|
||||
disableTrigger = false,
|
||||
}: TypeScriptToJavaScriptOptions = {}): Transformer<Root> {
|
||||
return async (tree, file) => {
|
||||
@@ -48,7 +51,9 @@ export function remarkTypeScriptToJavaScript({
|
||||
visit(tree, 'code', (node) => {
|
||||
const lang = node.lang;
|
||||
if (lang !== 'ts' && lang !== 'tsx') return;
|
||||
if (!disableTrigger && !node.meta?.includes('ts2js')) return;
|
||||
|
||||
const meta = parseCodeBlockAttributes(node.meta ?? '', ['ts2js']);
|
||||
if (!disableTrigger && !('ts2js' in meta.attributes)) return;
|
||||
|
||||
const result = oxc.transform(
|
||||
`${file.path ?? 'test'}.${lang}`,
|
||||
@@ -60,11 +65,9 @@ export function remarkTypeScriptToJavaScript({
|
||||
);
|
||||
|
||||
const targetLang = lang === 'tsx' ? 'jsx' : 'js';
|
||||
const meta = parseCodeBlockAttributes(node.meta ?? '', ['ts2js']);
|
||||
|
||||
const replacement = generateCodeBlockTabs({
|
||||
persist,
|
||||
defaultValue: 'js',
|
||||
defaultValue,
|
||||
triggers: [
|
||||
{
|
||||
value: 'ts',
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ function _createMdxContent(props) {
|
||||
if (!CodeBlockTabs) _missingMdxReference("CodeBlockTabs", true);
|
||||
if (!CodeBlockTabsList) _missingMdxReference("CodeBlockTabsList", true);
|
||||
if (!CodeBlockTabsTrigger) _missingMdxReference("CodeBlockTabsTrigger", true);
|
||||
return <CodeBlockTabs defaultValue="js"><CodeBlockTabsList><CodeBlockTabsTrigger value="ts">{"TypeScript"}</CodeBlockTabsTrigger><CodeBlockTabsTrigger value="js">{"JavaScript"}</CodeBlockTabsTrigger></CodeBlockTabsList><CodeBlockTab value="ts"><_components.pre><_components.code className="language-tsx">{"import { ReactNode } from 'react';\n\nexport default function Layout({ children }: { children: ReactNode }) {\n const v: string = 'hello world' as any;\n\n return (\n <div>\n {children} {v}\n </div>\n );\n}\n"}</_components.code></_components.pre></CodeBlockTab><CodeBlockTab value="js"><_components.pre><_components.code className="language-jsx">{"export default function Layout({ children }) {\n\tconst v = \"hello world\";\n\treturn <div>\n {children} {v}\n </div>;\n}\n\n"}</_components.code></_components.pre></CodeBlockTab></CodeBlockTabs>;
|
||||
return <CodeBlockTabs defaultValue="ts"><CodeBlockTabsList><CodeBlockTabsTrigger value="ts">{"TypeScript"}</CodeBlockTabsTrigger><CodeBlockTabsTrigger value="js">{"JavaScript"}</CodeBlockTabsTrigger></CodeBlockTabsList><CodeBlockTab value="ts"><_components.pre><_components.code className="language-tsx">{"import { ReactNode } from 'react';\n\nexport default function Layout({ children }: { children: ReactNode }) {\n const v: string = 'hello world' as any;\n\n return (\n <div>\n {children} {v}\n </div>\n );\n}\n"}</_components.code></_components.pre></CodeBlockTab><CodeBlockTab value="js"><_components.pre><_components.code className="language-jsx">{"export default function Layout({ children }) {\n\tconst v = \"hello world\";\n\treturn <div>\n {children} {v}\n </div>;\n}\n\n"}</_components.code></_components.pre></CodeBlockTab></CodeBlockTabs>;
|
||||
}
|
||||
export default function MDXContent(props = {}) {
|
||||
const {wrapper: MDXLayout} = props.components || ({});
|
||||
|
||||
@@ -60,7 +60,7 @@ export function remarkPostprocess(
|
||||
if (includeProcessedMarkdown) {
|
||||
file.data._markdown = toMarkdown(tree, {
|
||||
...this.data('settings'),
|
||||
// @ts-expect-error - from https://github.com/remarkjs/remark/blob/main/packages/remark-stringify/lib/index.js
|
||||
// from https://github.com/remarkjs/remark/blob/main/packages/remark-stringify/lib/index.js
|
||||
extensions: this.data('toMarkdownExtensions') || [],
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user