@blaaiz/docs-core 0.7.5 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { AI_PROVIDER_MODELS, AI_PROVIDER_NAMES, AiConfigError, DocsConfigError, InvalidNavigationError, OpenApiMergeError, ProxyTargetError, SESSION_COOKIE, assertAllowedTarget, buildLlmsTxt, buildMetadata, buildRobots, buildSearchIndex, buildSessionCookie, buildSitemap, buildThemeCss, clearSessionCookie, createAskAiRoute, createAuthGate, createEmailSignIn, createGoogleAuth, createMarkdownRoute, createSecretSignIn, createSignOut, createSiteAuth, createTryItProxy, createTryItProxyRoute, curlCodeUsage, defineDocsConfig, isAllowedEmail, isMarkdownRouteRequest, markdownRewriteTarget, mdxToMarkdown, mergeOpenApiDocuments, openApiOperationToMarkdown, parseNavigation, planDocsTree, readCookie, redirectTarget, resolveAiConfig, searchIndex, signSession, unwrapProxyTarget, validateDocsConfig, verifySession } from './chunk-G6EOGADC.js';
1
+ export { AI_PROVIDER_MODELS, AI_PROVIDER_NAMES, AiConfigError, DocsConfigError, InvalidNavigationError, OpenApiMergeError, ProxyTargetError, SESSION_COOKIE, assertAllowedTarget, buildLlmsTxt, buildMetadata, buildRobots, buildSearchIndex, buildSessionCookie, buildSitemap, buildThemeCss, clearSessionCookie, createAskAiRoute, createAuthGate, createEmailSignIn, createGoogleAuth, createMarkdownRoute, createSecretSignIn, createSignOut, createSiteAuth, createTryItProxy, createTryItProxyRoute, curlCodeUsage, defineDocsConfig, isAllowedEmail, isMarkdownRouteRequest, markdownRewriteTarget, mdxToMarkdown, mergeOpenApiDocuments, openApiOperationToMarkdown, parseNavigation, planDocsTree, readCookie, redirectTarget, resolveAiConfig, searchIndex, signSession, unwrapProxyTarget, validateDocsConfig, verifySession } from './chunk-W74K64WH.js';
2
2
  //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
package/dist/mdx.cjs ADDED
@@ -0,0 +1,104 @@
1
+ 'use strict';
2
+
3
+ // src/mdx/index.ts
4
+ function isCode(node) {
5
+ return node.type === "code";
6
+ }
7
+ function isJsxElement(node) {
8
+ return node.type === "mdxJsxFlowElement" || node.type === "mdxJsxTextElement";
9
+ }
10
+ function walk(node, visit) {
11
+ const children = node.children ?? [];
12
+ for (const [index, child] of children.entries()) {
13
+ visit(child, index, node);
14
+ walk(child, visit);
15
+ }
16
+ }
17
+ function parseMeta(meta) {
18
+ const tokens = meta.match(/[^\s"]*"[^"]*"|\S+/g) ?? [];
19
+ const bare = [];
20
+ const rest = [];
21
+ let explicit;
22
+ for (const token of tokens) {
23
+ const titled = /^title=(?:"([^"]*)"|(\S+))$/.exec(token);
24
+ if (titled) {
25
+ explicit ??= titled[1] ?? titled[2];
26
+ continue;
27
+ }
28
+ if (token.includes("=") || token.startsWith("{") || token.startsWith("[")) {
29
+ rest.push(token);
30
+ } else {
31
+ bare.push(token);
32
+ }
33
+ }
34
+ if (explicit !== void 0) {
35
+ return { title: explicit, rest: [...rest, ...bare] };
36
+ }
37
+ return { title: bare.length > 0 ? bare.join(" ") : void 0, rest };
38
+ }
39
+ function serializeMeta(parsed, withTitle) {
40
+ const tokens = withTitle && parsed.title !== void 0 ? [`title="${parsed.title.replaceAll('"', "")}"`, ...parsed.rest] : parsed.rest;
41
+ return tokens.length > 0 ? tokens.join(" ") : void 0;
42
+ }
43
+ function takeTitle(code) {
44
+ if (typeof code.meta !== "string" || code.meta === "") {
45
+ return void 0;
46
+ }
47
+ const parsed = parseMeta(code.meta);
48
+ code.meta = serializeMeta(parsed, false) ?? null;
49
+ return parsed.title;
50
+ }
51
+ function normalizeTitle(code) {
52
+ if (typeof code.meta !== "string" || code.meta === "") {
53
+ return;
54
+ }
55
+ code.meta = serializeMeta(parseMeta(code.meta), true) ?? null;
56
+ }
57
+ function remarkCodeTitles() {
58
+ return (tree) => {
59
+ const root = tree;
60
+ walk(root, (node) => {
61
+ if (!isJsxElement(node) || node.name !== "CodeGroup") {
62
+ return;
63
+ }
64
+ const fences = (node.children ?? []).filter(isCode);
65
+ if (fences.length === 0) {
66
+ return;
67
+ }
68
+ const labels = fences.map(
69
+ (fence, index) => takeTitle(fence) ?? fence.lang ?? `Code ${String(index + 1)}`
70
+ );
71
+ node.attributes ??= [];
72
+ node.attributes.push({
73
+ type: "mdxJsxAttribute",
74
+ name: "labels",
75
+ value: JSON.stringify(labels)
76
+ });
77
+ });
78
+ walk(root, (node) => {
79
+ if (isCode(node)) {
80
+ normalizeTitle(node);
81
+ }
82
+ });
83
+ };
84
+ }
85
+ function remarkMermaid() {
86
+ return (tree) => {
87
+ walk(tree, (node, index, parent) => {
88
+ if (isCode(node) && node.lang === "mermaid") {
89
+ const element = {
90
+ type: "mdxJsxFlowElement",
91
+ name: "Mermaid",
92
+ attributes: [{ type: "mdxJsxAttribute", name: "chart", value: node.value ?? "" }],
93
+ children: []
94
+ };
95
+ (parent.children ?? [])[index] = element;
96
+ }
97
+ });
98
+ };
99
+ }
100
+
101
+ exports.remarkCodeTitles = remarkCodeTitles;
102
+ exports.remarkMermaid = remarkMermaid;
103
+ //# sourceMappingURL=mdx.cjs.map
104
+ //# sourceMappingURL=mdx.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mdx/index.ts"],"names":[],"mappings":"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","file":"mdx.cjs","sourcesContent":["/**\n * Remark plugins for the docs MDX pipeline. A site wires them into\n * `source.config.ts`:\n *\n * ```ts\n * import { remarkCodeTitles, remarkMermaid } from '@blaaiz/docs-core/mdx';\n *\n * export default defineConfig({\n * mdxOptions: { remarkPlugins: [remarkGfm, remarkCodeTitles, remarkMermaid] },\n * });\n * ```\n *\n * `remarkCodeTitles` accepts both fence-title spellings — fumadocs' explicit\n * `title=\"NGN\"` and Mintlify's bare words after the language (`json NGN`) — so\n * content migrated from Mintlify keeps its code-block titles and `<CodeGroup>`\n * tab labels without a rewrite. `remarkMermaid` turns mermaid fences into the\n * `<Mermaid>` client component.\n *\n * @packageDocumentation\n */\n\ninterface MdastNode {\n type: string;\n children?: MdastNode[];\n}\n\ninterface CodeNode extends MdastNode {\n type: 'code';\n lang?: string | null;\n meta?: string | null;\n value?: string;\n}\n\ninterface MdxJsxAttribute {\n type: 'mdxJsxAttribute';\n name: string;\n value: unknown;\n}\n\ninterface MdxJsxElement extends MdastNode {\n name?: string | null;\n attributes?: MdxJsxAttribute[];\n}\n\nfunction isCode(node: MdastNode): node is CodeNode {\n return node.type === 'code';\n}\n\nfunction isJsxElement(node: MdastNode): node is MdxJsxElement {\n return node.type === 'mdxJsxFlowElement' || node.type === 'mdxJsxTextElement';\n}\n\nfunction walk(\n node: MdastNode,\n visit: (node: MdastNode, index: number, parent: MdastNode) => void,\n): void {\n const children = node.children ?? [];\n for (const [index, child] of children.entries()) {\n visit(child, index, node);\n walk(child, visit);\n }\n}\n\n/**\n * A fence's parsed info-string meta: the resolved title (explicit\n * `title=\"...\"` wins over bare words) and every other token, order preserved.\n */\ninterface ParsedMeta {\n title: string | undefined;\n rest: string[];\n}\n\nfunction parseMeta(meta: string): ParsedMeta {\n const tokens = meta.match(/[^\\s\"]*\"[^\"]*\"|\\S+/g) ?? [];\n const bare: string[] = [];\n const rest: string[] = [];\n let explicit: string | undefined;\n for (const token of tokens) {\n const titled = /^title=(?:\"([^\"]*)\"|(\\S+))$/.exec(token);\n if (titled) {\n explicit ??= titled[1] ?? titled[2];\n continue;\n }\n // A key=value option or a {1,3} highlight range is meta in its own right;\n // only plain words are a Mintlify-style title.\n if (token.includes('=') || token.startsWith('{') || token.startsWith('[')) {\n rest.push(token);\n } else {\n bare.push(token);\n }\n }\n if (explicit !== undefined) {\n return { title: explicit, rest: [...rest, ...bare] };\n }\n return { title: bare.length > 0 ? bare.join(' ') : undefined, rest };\n}\n\nfunction serializeMeta(parsed: ParsedMeta, withTitle: boolean): string | undefined {\n const tokens =\n withTitle && parsed.title !== undefined\n ? [`title=\"${parsed.title.replaceAll('\"', '')}\"`, ...parsed.rest]\n : parsed.rest;\n return tokens.length > 0 ? tokens.join(' ') : undefined;\n}\n\n/**\n * Reads and removes the title from a fence inside a `<CodeGroup>`. The group\n * shows the title on its tab, so leaving it on the fence would render a\n * duplicate per-block header inside the panel.\n */\nfunction takeTitle(code: CodeNode): string | undefined {\n if (typeof code.meta !== 'string' || code.meta === '') {\n return undefined;\n }\n const parsed = parseMeta(code.meta);\n code.meta = serializeMeta(parsed, false) ?? null;\n return parsed.title;\n}\n\nfunction normalizeTitle(code: CodeNode): void {\n if (typeof code.meta !== 'string' || code.meta === '') {\n return;\n }\n code.meta = serializeMeta(parseMeta(code.meta), true) ?? null;\n}\n\n/**\n * Fence-title compatibility for content written for Mintlify. Inside a\n * `<CodeGroup>`, each fence's title (either spelling) moves onto the group as\n * its tab label — the `labels` attribute `<CodeGroup>` reads — and comes off\n * the fence so the panel renders without its own header. Everywhere else a\n * bare-word meta becomes `title=\"...\"`, which the code-block component renders\n * as the block's header, exactly as it would the explicit spelling.\n *\n * @public\n */\nexport function remarkCodeTitles() {\n return (tree: unknown): void => {\n const root = tree as MdastNode;\n walk(root, (node) => {\n if (!isJsxElement(node) || node.name !== 'CodeGroup') {\n return;\n }\n const fences = (node.children ?? []).filter(isCode);\n if (fences.length === 0) {\n return;\n }\n const labels = fences.map(\n (fence, index) => takeTitle(fence) ?? fence.lang ?? `Code ${String(index + 1)}`,\n );\n node.attributes ??= [];\n node.attributes.push({\n type: 'mdxJsxAttribute',\n name: 'labels',\n value: JSON.stringify(labels),\n });\n });\n walk(root, (node) => {\n if (isCode(node)) {\n normalizeTitle(node);\n }\n });\n };\n}\n\n/**\n * Turns mermaid fences into a `<Mermaid chart=\"...\" />` element so\n * diagrams render as diagrams, not source. The site maps `Mermaid` to the\n * client component exported from `@blaaiz/docs-core/ui/mermaid`.\n *\n * @public\n */\nexport function remarkMermaid() {\n return (tree: unknown): void => {\n walk(tree as MdastNode, (node, index, parent) => {\n if (isCode(node) && node.lang === 'mermaid') {\n const element: MdxJsxElement = {\n type: 'mdxJsxFlowElement',\n name: 'Mermaid',\n attributes: [{ type: 'mdxJsxAttribute', name: 'chart', value: node.value ?? '' }],\n children: [],\n };\n (parent.children ?? [])[index] = element;\n }\n });\n };\n}\n"]}
package/dist/mdx.d.cts ADDED
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Remark plugins for the docs MDX pipeline. A site wires them into
3
+ * `source.config.ts`:
4
+ *
5
+ * ```ts
6
+ * import { remarkCodeTitles, remarkMermaid } from '@blaaiz/docs-core/mdx';
7
+ *
8
+ * export default defineConfig({
9
+ * mdxOptions: { remarkPlugins: [remarkGfm, remarkCodeTitles, remarkMermaid] },
10
+ * });
11
+ * ```
12
+ *
13
+ * `remarkCodeTitles` accepts both fence-title spellings — fumadocs' explicit
14
+ * `title="NGN"` and Mintlify's bare words after the language (`json NGN`) — so
15
+ * content migrated from Mintlify keeps its code-block titles and `<CodeGroup>`
16
+ * tab labels without a rewrite. `remarkMermaid` turns mermaid fences into the
17
+ * `<Mermaid>` client component.
18
+ *
19
+ * @packageDocumentation
20
+ */
21
+ /**
22
+ * Fence-title compatibility for content written for Mintlify. Inside a
23
+ * `<CodeGroup>`, each fence's title (either spelling) moves onto the group as
24
+ * its tab label — the `labels` attribute `<CodeGroup>` reads — and comes off
25
+ * the fence so the panel renders without its own header. Everywhere else a
26
+ * bare-word meta becomes `title="..."`, which the code-block component renders
27
+ * as the block's header, exactly as it would the explicit spelling.
28
+ *
29
+ * @public
30
+ */
31
+ declare function remarkCodeTitles(): (tree: unknown) => void;
32
+ /**
33
+ * Turns mermaid fences into a `<Mermaid chart="..." />` element so
34
+ * diagrams render as diagrams, not source. The site maps `Mermaid` to the
35
+ * client component exported from `@blaaiz/docs-core/ui/mermaid`.
36
+ *
37
+ * @public
38
+ */
39
+ declare function remarkMermaid(): (tree: unknown) => void;
40
+
41
+ export { remarkCodeTitles, remarkMermaid };
package/dist/mdx.d.ts ADDED
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Remark plugins for the docs MDX pipeline. A site wires them into
3
+ * `source.config.ts`:
4
+ *
5
+ * ```ts
6
+ * import { remarkCodeTitles, remarkMermaid } from '@blaaiz/docs-core/mdx';
7
+ *
8
+ * export default defineConfig({
9
+ * mdxOptions: { remarkPlugins: [remarkGfm, remarkCodeTitles, remarkMermaid] },
10
+ * });
11
+ * ```
12
+ *
13
+ * `remarkCodeTitles` accepts both fence-title spellings — fumadocs' explicit
14
+ * `title="NGN"` and Mintlify's bare words after the language (`json NGN`) — so
15
+ * content migrated from Mintlify keeps its code-block titles and `<CodeGroup>`
16
+ * tab labels without a rewrite. `remarkMermaid` turns mermaid fences into the
17
+ * `<Mermaid>` client component.
18
+ *
19
+ * @packageDocumentation
20
+ */
21
+ /**
22
+ * Fence-title compatibility for content written for Mintlify. Inside a
23
+ * `<CodeGroup>`, each fence's title (either spelling) moves onto the group as
24
+ * its tab label — the `labels` attribute `<CodeGroup>` reads — and comes off
25
+ * the fence so the panel renders without its own header. Everywhere else a
26
+ * bare-word meta becomes `title="..."`, which the code-block component renders
27
+ * as the block's header, exactly as it would the explicit spelling.
28
+ *
29
+ * @public
30
+ */
31
+ declare function remarkCodeTitles(): (tree: unknown) => void;
32
+ /**
33
+ * Turns mermaid fences into a `<Mermaid chart="..." />` element so
34
+ * diagrams render as diagrams, not source. The site maps `Mermaid` to the
35
+ * client component exported from `@blaaiz/docs-core/ui/mermaid`.
36
+ *
37
+ * @public
38
+ */
39
+ declare function remarkMermaid(): (tree: unknown) => void;
40
+
41
+ export { remarkCodeTitles, remarkMermaid };
package/dist/mdx.js ADDED
@@ -0,0 +1,101 @@
1
+ // src/mdx/index.ts
2
+ function isCode(node) {
3
+ return node.type === "code";
4
+ }
5
+ function isJsxElement(node) {
6
+ return node.type === "mdxJsxFlowElement" || node.type === "mdxJsxTextElement";
7
+ }
8
+ function walk(node, visit) {
9
+ const children = node.children ?? [];
10
+ for (const [index, child] of children.entries()) {
11
+ visit(child, index, node);
12
+ walk(child, visit);
13
+ }
14
+ }
15
+ function parseMeta(meta) {
16
+ const tokens = meta.match(/[^\s"]*"[^"]*"|\S+/g) ?? [];
17
+ const bare = [];
18
+ const rest = [];
19
+ let explicit;
20
+ for (const token of tokens) {
21
+ const titled = /^title=(?:"([^"]*)"|(\S+))$/.exec(token);
22
+ if (titled) {
23
+ explicit ??= titled[1] ?? titled[2];
24
+ continue;
25
+ }
26
+ if (token.includes("=") || token.startsWith("{") || token.startsWith("[")) {
27
+ rest.push(token);
28
+ } else {
29
+ bare.push(token);
30
+ }
31
+ }
32
+ if (explicit !== void 0) {
33
+ return { title: explicit, rest: [...rest, ...bare] };
34
+ }
35
+ return { title: bare.length > 0 ? bare.join(" ") : void 0, rest };
36
+ }
37
+ function serializeMeta(parsed, withTitle) {
38
+ const tokens = withTitle && parsed.title !== void 0 ? [`title="${parsed.title.replaceAll('"', "")}"`, ...parsed.rest] : parsed.rest;
39
+ return tokens.length > 0 ? tokens.join(" ") : void 0;
40
+ }
41
+ function takeTitle(code) {
42
+ if (typeof code.meta !== "string" || code.meta === "") {
43
+ return void 0;
44
+ }
45
+ const parsed = parseMeta(code.meta);
46
+ code.meta = serializeMeta(parsed, false) ?? null;
47
+ return parsed.title;
48
+ }
49
+ function normalizeTitle(code) {
50
+ if (typeof code.meta !== "string" || code.meta === "") {
51
+ return;
52
+ }
53
+ code.meta = serializeMeta(parseMeta(code.meta), true) ?? null;
54
+ }
55
+ function remarkCodeTitles() {
56
+ return (tree) => {
57
+ const root = tree;
58
+ walk(root, (node) => {
59
+ if (!isJsxElement(node) || node.name !== "CodeGroup") {
60
+ return;
61
+ }
62
+ const fences = (node.children ?? []).filter(isCode);
63
+ if (fences.length === 0) {
64
+ return;
65
+ }
66
+ const labels = fences.map(
67
+ (fence, index) => takeTitle(fence) ?? fence.lang ?? `Code ${String(index + 1)}`
68
+ );
69
+ node.attributes ??= [];
70
+ node.attributes.push({
71
+ type: "mdxJsxAttribute",
72
+ name: "labels",
73
+ value: JSON.stringify(labels)
74
+ });
75
+ });
76
+ walk(root, (node) => {
77
+ if (isCode(node)) {
78
+ normalizeTitle(node);
79
+ }
80
+ });
81
+ };
82
+ }
83
+ function remarkMermaid() {
84
+ return (tree) => {
85
+ walk(tree, (node, index, parent) => {
86
+ if (isCode(node) && node.lang === "mermaid") {
87
+ const element = {
88
+ type: "mdxJsxFlowElement",
89
+ name: "Mermaid",
90
+ attributes: [{ type: "mdxJsxAttribute", name: "chart", value: node.value ?? "" }],
91
+ children: []
92
+ };
93
+ (parent.children ?? [])[index] = element;
94
+ }
95
+ });
96
+ };
97
+ }
98
+
99
+ export { remarkCodeTitles, remarkMermaid };
100
+ //# sourceMappingURL=mdx.js.map
101
+ //# sourceMappingURL=mdx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mdx/index.ts"],"names":[],"mappings":"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","file":"mdx.js","sourcesContent":["/**\n * Remark plugins for the docs MDX pipeline. A site wires them into\n * `source.config.ts`:\n *\n * ```ts\n * import { remarkCodeTitles, remarkMermaid } from '@blaaiz/docs-core/mdx';\n *\n * export default defineConfig({\n * mdxOptions: { remarkPlugins: [remarkGfm, remarkCodeTitles, remarkMermaid] },\n * });\n * ```\n *\n * `remarkCodeTitles` accepts both fence-title spellings — fumadocs' explicit\n * `title=\"NGN\"` and Mintlify's bare words after the language (`json NGN`) — so\n * content migrated from Mintlify keeps its code-block titles and `<CodeGroup>`\n * tab labels without a rewrite. `remarkMermaid` turns mermaid fences into the\n * `<Mermaid>` client component.\n *\n * @packageDocumentation\n */\n\ninterface MdastNode {\n type: string;\n children?: MdastNode[];\n}\n\ninterface CodeNode extends MdastNode {\n type: 'code';\n lang?: string | null;\n meta?: string | null;\n value?: string;\n}\n\ninterface MdxJsxAttribute {\n type: 'mdxJsxAttribute';\n name: string;\n value: unknown;\n}\n\ninterface MdxJsxElement extends MdastNode {\n name?: string | null;\n attributes?: MdxJsxAttribute[];\n}\n\nfunction isCode(node: MdastNode): node is CodeNode {\n return node.type === 'code';\n}\n\nfunction isJsxElement(node: MdastNode): node is MdxJsxElement {\n return node.type === 'mdxJsxFlowElement' || node.type === 'mdxJsxTextElement';\n}\n\nfunction walk(\n node: MdastNode,\n visit: (node: MdastNode, index: number, parent: MdastNode) => void,\n): void {\n const children = node.children ?? [];\n for (const [index, child] of children.entries()) {\n visit(child, index, node);\n walk(child, visit);\n }\n}\n\n/**\n * A fence's parsed info-string meta: the resolved title (explicit\n * `title=\"...\"` wins over bare words) and every other token, order preserved.\n */\ninterface ParsedMeta {\n title: string | undefined;\n rest: string[];\n}\n\nfunction parseMeta(meta: string): ParsedMeta {\n const tokens = meta.match(/[^\\s\"]*\"[^\"]*\"|\\S+/g) ?? [];\n const bare: string[] = [];\n const rest: string[] = [];\n let explicit: string | undefined;\n for (const token of tokens) {\n const titled = /^title=(?:\"([^\"]*)\"|(\\S+))$/.exec(token);\n if (titled) {\n explicit ??= titled[1] ?? titled[2];\n continue;\n }\n // A key=value option or a {1,3} highlight range is meta in its own right;\n // only plain words are a Mintlify-style title.\n if (token.includes('=') || token.startsWith('{') || token.startsWith('[')) {\n rest.push(token);\n } else {\n bare.push(token);\n }\n }\n if (explicit !== undefined) {\n return { title: explicit, rest: [...rest, ...bare] };\n }\n return { title: bare.length > 0 ? bare.join(' ') : undefined, rest };\n}\n\nfunction serializeMeta(parsed: ParsedMeta, withTitle: boolean): string | undefined {\n const tokens =\n withTitle && parsed.title !== undefined\n ? [`title=\"${parsed.title.replaceAll('\"', '')}\"`, ...parsed.rest]\n : parsed.rest;\n return tokens.length > 0 ? tokens.join(' ') : undefined;\n}\n\n/**\n * Reads and removes the title from a fence inside a `<CodeGroup>`. The group\n * shows the title on its tab, so leaving it on the fence would render a\n * duplicate per-block header inside the panel.\n */\nfunction takeTitle(code: CodeNode): string | undefined {\n if (typeof code.meta !== 'string' || code.meta === '') {\n return undefined;\n }\n const parsed = parseMeta(code.meta);\n code.meta = serializeMeta(parsed, false) ?? null;\n return parsed.title;\n}\n\nfunction normalizeTitle(code: CodeNode): void {\n if (typeof code.meta !== 'string' || code.meta === '') {\n return;\n }\n code.meta = serializeMeta(parseMeta(code.meta), true) ?? null;\n}\n\n/**\n * Fence-title compatibility for content written for Mintlify. Inside a\n * `<CodeGroup>`, each fence's title (either spelling) moves onto the group as\n * its tab label — the `labels` attribute `<CodeGroup>` reads — and comes off\n * the fence so the panel renders without its own header. Everywhere else a\n * bare-word meta becomes `title=\"...\"`, which the code-block component renders\n * as the block's header, exactly as it would the explicit spelling.\n *\n * @public\n */\nexport function remarkCodeTitles() {\n return (tree: unknown): void => {\n const root = tree as MdastNode;\n walk(root, (node) => {\n if (!isJsxElement(node) || node.name !== 'CodeGroup') {\n return;\n }\n const fences = (node.children ?? []).filter(isCode);\n if (fences.length === 0) {\n return;\n }\n const labels = fences.map(\n (fence, index) => takeTitle(fence) ?? fence.lang ?? `Code ${String(index + 1)}`,\n );\n node.attributes ??= [];\n node.attributes.push({\n type: 'mdxJsxAttribute',\n name: 'labels',\n value: JSON.stringify(labels),\n });\n });\n walk(root, (node) => {\n if (isCode(node)) {\n normalizeTitle(node);\n }\n });\n };\n}\n\n/**\n * Turns mermaid fences into a `<Mermaid chart=\"...\" />` element so\n * diagrams render as diagrams, not source. The site maps `Mermaid` to the\n * client component exported from `@blaaiz/docs-core/ui/mermaid`.\n *\n * @public\n */\nexport function remarkMermaid() {\n return (tree: unknown): void => {\n walk(tree as MdastNode, (node, index, parent) => {\n if (isCode(node) && node.lang === 'mermaid') {\n const element: MdxJsxElement = {\n type: 'mdxJsxFlowElement',\n name: 'Mermaid',\n attributes: [{ type: 'mdxJsxAttribute', name: 'chart', value: node.value ?? '' }],\n children: [],\n };\n (parent.children ?? [])[index] = element;\n }\n });\n };\n}\n"]}
package/dist/ui.cjs CHANGED
@@ -429,6 +429,74 @@ function CardGroup({ cols = 2, children }) {
429
429
  };
430
430
  return /* @__PURE__ */ jsxRuntime.jsx("div", { style, children });
431
431
  }
432
+ function findLabel(node, depth = 0) {
433
+ if (depth > 4) {
434
+ return void 0;
435
+ }
436
+ for (const child of react.Children.toArray(node)) {
437
+ if (!react.isValidElement(child)) {
438
+ continue;
439
+ }
440
+ const { title, lang, children } = child.props;
441
+ if (typeof title === "string" && title !== "") {
442
+ return title;
443
+ }
444
+ if (typeof lang === "string" && lang !== "") {
445
+ return lang;
446
+ }
447
+ const nested = findLabel(children, depth + 1);
448
+ if (nested !== void 0) {
449
+ return nested;
450
+ }
451
+ }
452
+ return void 0;
453
+ }
454
+ function parseLabels(labels) {
455
+ if (labels === void 0) {
456
+ return [];
457
+ }
458
+ if (typeof labels !== "string") {
459
+ return labels;
460
+ }
461
+ try {
462
+ const parsed = JSON.parse(labels);
463
+ return Array.isArray(parsed) ? parsed.map(String) : [];
464
+ } catch {
465
+ return [];
466
+ }
467
+ }
468
+ function CodeGroup({
469
+ children,
470
+ labels
471
+ }) {
472
+ const group = react.useId();
473
+ const blocks = react.Children.toArray(children).filter(
474
+ (child) => react.isValidElement(child)
475
+ );
476
+ const named = parseLabels(labels);
477
+ const labelOf = (block, index) => named[index] ?? findLabel(block) ?? `Code ${String(index + 1)}`;
478
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "tabs tabs--code", children: [
479
+ blocks.map((_block, index) => /* @__PURE__ */ jsxRuntime.jsx(
480
+ "input",
481
+ {
482
+ className: "tabs__radio",
483
+ type: "radio",
484
+ name: group,
485
+ id: `${group}-${String(index)}`,
486
+ defaultChecked: index === 0
487
+ },
488
+ index
489
+ )),
490
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tabs__bar", children: blocks.map((block, index) => /* @__PURE__ */ jsxRuntime.jsx("label", { className: "tabs__trigger", htmlFor: `${group}-${String(index)}`, children: labelOf(block, index) }, index)) }),
491
+ blocks.map((block, index) => /* @__PURE__ */ jsxRuntime.jsx("section", { className: "tabs__panel", children: block }, index))
492
+ ] });
493
+ }
494
+ function Frame({ caption, children }) {
495
+ return /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: "frame", children: [
496
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "frame__body", children }),
497
+ caption === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx("figcaption", { className: "frame__caption", children: caption })
498
+ ] });
499
+ }
432
500
 
433
501
  // src/ui/docs-icons.tsx
434
502
  var ICONS = {
@@ -684,7 +752,9 @@ var mdxComponents = {
684
752
  Steps,
685
753
  Step,
686
754
  Tabs,
687
- Tab
755
+ Tab,
756
+ Frame,
757
+ CodeGroup
688
758
  };
689
759
  var defaultResolveHref = (page) => {
690
760
  if (page.kind === "openapi") {
@@ -781,8 +851,10 @@ exports.AuthScreen = AuthScreen;
781
851
  exports.Callout = Callout;
782
852
  exports.Card = Card;
783
853
  exports.CardGroup = CardGroup;
854
+ exports.CodeGroup = CodeGroup;
784
855
  exports.DocsSidebar = DocsSidebar;
785
856
  exports.ErrorScreen = ErrorScreen;
857
+ exports.Frame = Frame;
786
858
  exports.Info = Info;
787
859
  exports.MethodBadge = MethodBadge;
788
860
  exports.NavActions = NavActions;