@mintlify/common 1.0.817 → 1.0.818
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/mdx/getMDXOptions.js +2 -1
- package/dist/mdx/plugins/remark/index.d.ts +1 -0
- package/dist/mdx/plugins/remark/index.js +1 -0
- package/dist/mdx/plugins/remark/remarkExtractTableOfContents.js +0 -8
- package/dist/mdx/plugins/remark/remarkUnwrapJsxHeadings.d.ts +9 -0
- package/dist/mdx/plugins/remark/remarkUnwrapJsxHeadings.js +18 -0
- package/dist/mdx/preprocessCustomHeadingIds.d.ts +4 -0
- package/dist/mdx/preprocessCustomHeadingIds.js +59 -12
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { rehypeCodeBlocks, rehypeDynamicTailwindCss, rehypeKeyboardSymbols, rehypeListItemText, rehypeMdxExtractEndpoint, rehypeMdxExtractExamples, rehypeParamFieldIds, rehypeRawComponents, rehypeTable, rehypeUnicodeIds, rehypeZoomImages, remarkExtractChangelogFilters, remarkExtractTableOfContents, remarkFrames, remarkComponentIds, remarkMdxInjectSnippets, remarkMdxRemoveUnusedVariables, remarkRemoveImports, remarkMdxExtractPanel, remarkVideo, remarkExtractMultiView, remarkPrompt, } from './plugins/index.js';
|
|
1
|
+
import { rehypeCodeBlocks, rehypeDynamicTailwindCss, rehypeKeyboardSymbols, rehypeListItemText, rehypeMdxExtractEndpoint, rehypeMdxExtractExamples, rehypeParamFieldIds, rehypeRawComponents, rehypeTable, rehypeUnicodeIds, rehypeZoomImages, remarkExtractChangelogFilters, remarkExtractTableOfContents, remarkFrames, remarkComponentIds, remarkMdxInjectSnippets, remarkMdxRemoveUnusedVariables, remarkRemoveImports, remarkMdxExtractPanel, remarkVideo, remarkExtractMultiView, remarkPrompt, remarkUnwrapJsxHeadings, } from './plugins/index.js';
|
|
2
2
|
import { remarkMdxRemoveUnknownJsx } from './plugins/remark/remarkMdxRemoveUnknownJsx/index.js';
|
|
3
3
|
import { remarkMermaid } from './plugins/remark/remarkMermaid.js';
|
|
4
4
|
// avoid running extractors unnecessarily
|
|
@@ -16,6 +16,7 @@ export const getMDXOptions = ({ data, remarkPlugins = [], rehypePlugins = [], md
|
|
|
16
16
|
[remarkMdxInjectSnippets, data.snippetTreeMap],
|
|
17
17
|
remarkPrompt,
|
|
18
18
|
[remarkComponentIds, data.pageMetadata],
|
|
19
|
+
remarkUnwrapJsxHeadings,
|
|
19
20
|
[remarkExtractTableOfContents, mdxExtracts, data.pageMetadata], // modifies tree so cannot be excluded
|
|
20
21
|
[remarkExtractChangelogFilters, mdxExtracts],
|
|
21
22
|
[remarkMdxExtractPanel, mdxExtracts],
|
|
@@ -183,14 +183,6 @@ export const remarkExtractTableOfContents = (mdxExtracts, pageMetadata) => {
|
|
|
183
183
|
mdxJsxAttributes.push(...node.attributes);
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
|
-
// Unwrap paragraph children inside JSX headings (e.g. <h2>) so that the
|
|
187
|
-
// Heading component receives inline children instead of <p>-wrapped text.
|
|
188
|
-
// This happens because the preprocessor places text on its own line between
|
|
189
|
-
// JSX tags, which MDX parses as a paragraph block.
|
|
190
|
-
if (isValidMdxHeading && 'children' in node) {
|
|
191
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
192
|
-
node.children = node.children.flatMap((child) => child.type === 'paragraph' && 'children' in child ? child.children : [child]);
|
|
193
|
-
}
|
|
194
186
|
// @ts-expect-error we're assigning over 'attributes' if it doesn't exist
|
|
195
187
|
node.attributes = mdxJsxAttributes;
|
|
196
188
|
node.type = 'mdxJsxFlowElement';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Root } from 'mdast';
|
|
2
|
+
/**
|
|
3
|
+
* Unwraps paragraph children inside JSX heading elements (h1–h6).
|
|
4
|
+
*
|
|
5
|
+
* The custom-ID preprocessor emits headings like `<h2 id="x">\nText\n</h2>`,
|
|
6
|
+
* and MDX parses the text on its own line as a paragraph block. This plugin
|
|
7
|
+
* flattens those paragraphs so the heading receives inline children directly.
|
|
8
|
+
*/
|
|
9
|
+
export declare const remarkUnwrapJsxHeadings: () => (tree: Root) => void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { visit } from 'unist-util-visit';
|
|
2
|
+
import { ALL_HEADING_NAMES } from '../../preprocessCustomHeadingIds.js';
|
|
3
|
+
/**
|
|
4
|
+
* Unwraps paragraph children inside JSX heading elements (h1–h6).
|
|
5
|
+
*
|
|
6
|
+
* The custom-ID preprocessor emits headings like `<h2 id="x">\nText\n</h2>`,
|
|
7
|
+
* and MDX parses the text on its own line as a paragraph block. This plugin
|
|
8
|
+
* flattens those paragraphs so the heading receives inline children directly.
|
|
9
|
+
*/
|
|
10
|
+
export const remarkUnwrapJsxHeadings = () => (tree) => {
|
|
11
|
+
visit(tree, 'mdxJsxFlowElement', (node) => {
|
|
12
|
+
var _a;
|
|
13
|
+
if (!ALL_HEADING_NAMES.includes((_a = node.name) !== null && _a !== void 0 ? _a : ''))
|
|
14
|
+
return;
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
node.children = node.children.flatMap((child) => child.type === 'paragraph' && 'children' in child ? child.children : [child]);
|
|
17
|
+
});
|
|
18
|
+
};
|
|
@@ -6,9 +6,13 @@ import { MdxJsxFlowElement } from 'mdast-util-mdx-jsx';
|
|
|
6
6
|
* Transforms `## Heading text {#custom-id}` into `<h2 id="custom-id">Heading text</h2>`.
|
|
7
7
|
* This avoids MDX parsing errors (MDX treats `{...}` as JS expressions) and
|
|
8
8
|
* produces JSX heading elements that the existing remark pipeline already handles.
|
|
9
|
+
*
|
|
10
|
+
* Uses a line-by-line scan with fence state tracking to skip headings inside
|
|
11
|
+
* code blocks, avoiding backtracking over large documents.
|
|
9
12
|
*/
|
|
10
13
|
export declare function preprocessCustomHeadingIds(content: string): string;
|
|
11
14
|
export interface JsxHeadingElement extends MdxJsxFlowElement {
|
|
12
15
|
readonly __jsxHeading: true;
|
|
13
16
|
}
|
|
17
|
+
export declare const ALL_HEADING_NAMES: string[];
|
|
14
18
|
export declare const isJsxHeadingElement: (node: RootContent) => node is JsxHeadingElement;
|
|
@@ -1,27 +1,74 @@
|
|
|
1
1
|
import slugify from '@sindresorhus/slugify';
|
|
2
|
-
|
|
2
|
+
const HEADING_ID_RE = /^(#{1,6})\s+(.+?)\s*\{\s*#([^}]+?)\s*\}\s*$/;
|
|
3
3
|
/**
|
|
4
4
|
* Converts markdown headings with custom ID syntax into JSX heading elements.
|
|
5
5
|
*
|
|
6
6
|
* Transforms `## Heading text {#custom-id}` into `<h2 id="custom-id">Heading text</h2>`.
|
|
7
7
|
* This avoids MDX parsing errors (MDX treats `{...}` as JS expressions) and
|
|
8
8
|
* produces JSX heading elements that the existing remark pipeline already handles.
|
|
9
|
+
*
|
|
10
|
+
* Uses a line-by-line scan with fence state tracking to skip headings inside
|
|
11
|
+
* code blocks, avoiding backtracking over large documents.
|
|
9
12
|
*/
|
|
10
13
|
export function preprocessCustomHeadingIds(content) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
const lines = content.split('\n');
|
|
15
|
+
const result = [];
|
|
16
|
+
let fenceChar;
|
|
17
|
+
let fenceCount = 0;
|
|
18
|
+
for (const line of lines) {
|
|
19
|
+
const stripped = line.trimStart();
|
|
20
|
+
if (fenceChar !== undefined) {
|
|
21
|
+
if (isClosingFence(stripped, fenceChar, fenceCount)) {
|
|
22
|
+
fenceChar = undefined;
|
|
23
|
+
}
|
|
24
|
+
result.push(line);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const fence = parseOpeningFence(stripped);
|
|
28
|
+
if (fence) {
|
|
29
|
+
fenceChar = fence.char;
|
|
30
|
+
fenceCount = fence.count;
|
|
31
|
+
result.push(line);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const heading = HEADING_ID_RE.exec(line);
|
|
35
|
+
if ((heading === null || heading === void 0 ? void 0 : heading[1]) && heading[2] && heading[3]) {
|
|
36
|
+
const level = heading[1].length;
|
|
37
|
+
const sanitizedId = slugify(heading[3].trim(), { preserveCharacters: ['_'] });
|
|
38
|
+
result.push(`<h${level} id="${sanitizedId}">`, heading[2], `</h${level}>`);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
result.push(line);
|
|
42
|
+
}
|
|
43
|
+
return result.join('\n');
|
|
44
|
+
}
|
|
45
|
+
function parseOpeningFence(stripped) {
|
|
46
|
+
const char = stripped[0];
|
|
47
|
+
if (char !== '`' && char !== '~')
|
|
48
|
+
return undefined;
|
|
49
|
+
let count = 1;
|
|
50
|
+
while (count < stripped.length && stripped[count] === char)
|
|
51
|
+
count++;
|
|
52
|
+
if (count < 3)
|
|
53
|
+
return undefined;
|
|
54
|
+
return { char, count };
|
|
55
|
+
}
|
|
56
|
+
function isClosingFence(stripped, fenceChar, fenceCount) {
|
|
57
|
+
let i = 0;
|
|
58
|
+
while (i < stripped.length && stripped[i] === fenceChar)
|
|
59
|
+
i++;
|
|
60
|
+
if (i < fenceCount)
|
|
61
|
+
return false;
|
|
62
|
+
for (; i < stripped.length; i++) {
|
|
63
|
+
if (stripped[i] !== ' ' && stripped[i] !== '\t' && stripped[i] !== '\r')
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
21
67
|
}
|
|
68
|
+
export const ALL_HEADING_NAMES = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
|
|
22
69
|
export const isJsxHeadingElement = (node) => {
|
|
23
70
|
return (node.type === 'mdxJsxFlowElement' &&
|
|
24
71
|
'name' in node &&
|
|
25
72
|
typeof node.name === 'string' &&
|
|
26
|
-
|
|
73
|
+
ALL_HEADING_NAMES.includes(node.name));
|
|
27
74
|
};
|