@mintlify/common 1.0.946 → 1.0.948
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/remarkMdxClientComponentBoundaries.d.ts +17 -0
- package/dist/mdx/plugins/remark/remarkMdxClientComponentBoundaries.js +135 -0
- package/dist/mdx/plugins/remark/remarkMdxRemoveUnknownJsx/index.js +6 -3
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +3 -3
|
@@ -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, remarkResolveRelativeLinks, remarkVideo, remarkExtractMultiView, remarkPrompt, remarkUnwrapJsxHeadings, } 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, remarkResolveRelativeLinks, remarkVideo, remarkMdxClientComponentBoundaries, 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
|
|
@@ -29,6 +29,7 @@ export const getMDXOptions = ({ data, remarkPlugins = [], rehypePlugins = [], md
|
|
|
29
29
|
remarkVideo,
|
|
30
30
|
...remarkPlugins,
|
|
31
31
|
[remarkMdxRemoveUnknownJsx, { allowlist: allowedComponents }],
|
|
32
|
+
remarkMdxClientComponentBoundaries,
|
|
32
33
|
],
|
|
33
34
|
rehypePlugins: [
|
|
34
35
|
rehypeCodeBlocks,
|
|
@@ -4,6 +4,7 @@ export * from './remarkRemoveImports.js';
|
|
|
4
4
|
export * from './remarkExtractTableOfContents.js';
|
|
5
5
|
export * from './remarkMdxRemoveUnusedVariables.js';
|
|
6
6
|
export * from './remarkMdxRemoveUnknownJsx/index.js';
|
|
7
|
+
export * from './remarkMdxClientComponentBoundaries.js';
|
|
7
8
|
export * from './remarkMermaid.js';
|
|
8
9
|
export * from './remarkMdxRemoveJs.js';
|
|
9
10
|
export * from './remarkExtractChangelogFilters.js';
|
|
@@ -4,6 +4,7 @@ export * from './remarkRemoveImports.js';
|
|
|
4
4
|
export * from './remarkExtractTableOfContents.js';
|
|
5
5
|
export * from './remarkMdxRemoveUnusedVariables.js';
|
|
6
6
|
export * from './remarkMdxRemoveUnknownJsx/index.js';
|
|
7
|
+
export * from './remarkMdxClientComponentBoundaries.js';
|
|
7
8
|
export * from './remarkMermaid.js';
|
|
8
9
|
export * from './remarkMdxRemoveJs.js';
|
|
9
10
|
export * from './remarkExtractChangelogFilters.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Root } from 'mdast';
|
|
2
|
+
export declare const MDX_COMPONENT_BOUNDARY_NAME = "_MdxComponentBoundary";
|
|
3
|
+
/**
|
|
4
|
+
* Collects the names of function-valued exports declared in the MDX itself — `export function X`,
|
|
5
|
+
* `export const X = () => …` / `function(){}`, and re-exported local functions (`export { X }`).
|
|
6
|
+
* These are the user-authored components we treat as renderable (and, in remarkMdxRemoveUnknownJsx,
|
|
7
|
+
* as "known"), as opposed to exported plain values which are not components.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getExportedFunctionNames(tree: Root): Set<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Wraps each user-authored component usage in a `_MdxComponentBoundary` element so the client can
|
|
12
|
+
* isolate it behind an error boundary — a single component that throws at render time then renders
|
|
13
|
+
* nothing instead of crashing the whole page.
|
|
14
|
+
*/
|
|
15
|
+
export declare const remarkMdxClientComponentBoundaries: ({ allowlist }?: {
|
|
16
|
+
allowlist?: string[];
|
|
17
|
+
}) => (tree: Root) => void;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { visit } from 'unist-util-visit';
|
|
2
|
+
import { isExportNode, isMdxJsEsm } from '../../utils.js';
|
|
3
|
+
// Underscore-prefixed so it cannot collide with a user-authored MDX component name. The client
|
|
4
|
+
// (MdxContent) maps this to an error boundary; see apps/client/src/ui/MdxContent.tsx.
|
|
5
|
+
export const MDX_COMPONENT_BOUNDARY_NAME = '_MdxComponentBoundary';
|
|
6
|
+
/**
|
|
7
|
+
* Collects the names of function-valued exports declared in the MDX itself — `export function X`,
|
|
8
|
+
* `export const X = () => …` / `function(){}`, and re-exported local functions (`export { X }`).
|
|
9
|
+
* These are the user-authored components we treat as renderable (and, in remarkMdxRemoveUnknownJsx,
|
|
10
|
+
* as "known"), as opposed to exported plain values which are not components.
|
|
11
|
+
*/
|
|
12
|
+
export function getExportedFunctionNames(tree) {
|
|
13
|
+
const names = new Set();
|
|
14
|
+
visit(tree, 'mdxjsEsm', (node) => {
|
|
15
|
+
var _a, _b, _c, _d, _e, _f;
|
|
16
|
+
if (!isMdxJsEsm(node) || !((_b = (_a = node.data) === null || _a === void 0 ? void 0 : _a.estree) === null || _b === void 0 ? void 0 : _b.body))
|
|
17
|
+
return;
|
|
18
|
+
const localFunctionNames = new Set();
|
|
19
|
+
for (const bodyChild of node.data.estree.body) {
|
|
20
|
+
if (bodyChild.type === 'FunctionDeclaration' && ((_c = bodyChild.id) === null || _c === void 0 ? void 0 : _c.name)) {
|
|
21
|
+
localFunctionNames.add(bodyChild.id.name);
|
|
22
|
+
}
|
|
23
|
+
if (bodyChild.type === 'VariableDeclaration') {
|
|
24
|
+
addExportedVariableFunctionNames(bodyChild, localFunctionNames);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
for (const bodyChild of node.data.estree.body) {
|
|
28
|
+
if (!isExportNode(bodyChild) || bodyChild.type === 'ExportAllDeclaration')
|
|
29
|
+
continue;
|
|
30
|
+
if (((_d = bodyChild.declaration) === null || _d === void 0 ? void 0 : _d.type) === 'FunctionDeclaration') {
|
|
31
|
+
if ((_e = bodyChild.declaration.id) === null || _e === void 0 ? void 0 : _e.name)
|
|
32
|
+
names.add(bodyChild.declaration.id.name);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (((_f = bodyChild.declaration) === null || _f === void 0 ? void 0 : _f.type) === 'VariableDeclaration') {
|
|
36
|
+
addExportedVariableFunctionNames(bodyChild.declaration, names);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (bodyChild.type === 'ExportNamedDeclaration') {
|
|
40
|
+
addExportedSpecifierNames(bodyChild, names, localFunctionNames);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
return names;
|
|
45
|
+
}
|
|
46
|
+
function addExportedVariableFunctionNames(declaration, names) {
|
|
47
|
+
var _a, _b;
|
|
48
|
+
for (const declarator of declaration.declarations) {
|
|
49
|
+
if (declarator.id.type !== 'Identifier')
|
|
50
|
+
continue;
|
|
51
|
+
if (((_a = declarator.init) === null || _a === void 0 ? void 0 : _a.type) === 'ArrowFunctionExpression' ||
|
|
52
|
+
((_b = declarator.init) === null || _b === void 0 ? void 0 : _b.type) === 'FunctionExpression') {
|
|
53
|
+
names.add(declarator.id.name);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function addExportedSpecifierNames(node, names, localFunctionNames) {
|
|
58
|
+
for (const specifier of node.specifiers) {
|
|
59
|
+
if (localFunctionNames.has(specifier.local.name)) {
|
|
60
|
+
names.add(specifier.exported.name);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function shouldWrapComponent(name, componentNames) {
|
|
65
|
+
if (!name)
|
|
66
|
+
return false;
|
|
67
|
+
if (name === MDX_COMPONENT_BOUNDARY_NAME)
|
|
68
|
+
return false;
|
|
69
|
+
return componentNames.has(name);
|
|
70
|
+
}
|
|
71
|
+
function wrapFlowNode(node) {
|
|
72
|
+
var _a;
|
|
73
|
+
return {
|
|
74
|
+
type: 'mdxJsxFlowElement',
|
|
75
|
+
name: MDX_COMPONENT_BOUNDARY_NAME,
|
|
76
|
+
attributes: [
|
|
77
|
+
{
|
|
78
|
+
type: 'mdxJsxAttribute',
|
|
79
|
+
name: 'name',
|
|
80
|
+
value: (_a = node.name) !== null && _a !== void 0 ? _a : 'MDX component',
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
children: [node],
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function wrapTextNode(node) {
|
|
87
|
+
var _a;
|
|
88
|
+
return {
|
|
89
|
+
type: 'mdxJsxTextElement',
|
|
90
|
+
name: MDX_COMPONENT_BOUNDARY_NAME,
|
|
91
|
+
attributes: [
|
|
92
|
+
{
|
|
93
|
+
type: 'mdxJsxAttribute',
|
|
94
|
+
name: 'name',
|
|
95
|
+
value: (_a = node.name) !== null && _a !== void 0 ? _a : 'MDX component',
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
children: [node],
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Wraps each user-authored component usage in a `_MdxComponentBoundary` element so the client can
|
|
103
|
+
* isolate it behind an error boundary — a single component that throws at render time then renders
|
|
104
|
+
* nothing instead of crashing the whole page.
|
|
105
|
+
*/
|
|
106
|
+
export const remarkMdxClientComponentBoundaries = ({ allowlist = [] } = {}) => (tree) => {
|
|
107
|
+
const componentNames = getExportedFunctionNames(tree);
|
|
108
|
+
for (const name of allowlist) {
|
|
109
|
+
componentNames.add(name);
|
|
110
|
+
}
|
|
111
|
+
if (componentNames.size === 0)
|
|
112
|
+
return;
|
|
113
|
+
const flowReplacements = [];
|
|
114
|
+
const textReplacements = [];
|
|
115
|
+
visit(tree, 'mdxJsxFlowElement', (node, index, parent) => {
|
|
116
|
+
if (index === undefined || !(parent === null || parent === void 0 ? void 0 : parent.children))
|
|
117
|
+
return;
|
|
118
|
+
if (!shouldWrapComponent(node.name, componentNames))
|
|
119
|
+
return;
|
|
120
|
+
flowReplacements.push({ parent, index, node });
|
|
121
|
+
});
|
|
122
|
+
visit(tree, 'mdxJsxTextElement', (node, index, parent) => {
|
|
123
|
+
if (index === undefined || !(parent === null || parent === void 0 ? void 0 : parent.children))
|
|
124
|
+
return;
|
|
125
|
+
if (!shouldWrapComponent(node.name, componentNames))
|
|
126
|
+
return;
|
|
127
|
+
textReplacements.push({ parent, index, node });
|
|
128
|
+
});
|
|
129
|
+
for (const { parent, index, node } of flowReplacements) {
|
|
130
|
+
parent.children[index] = wrapFlowNode(node);
|
|
131
|
+
}
|
|
132
|
+
for (const { parent, index, node } of textReplacements) {
|
|
133
|
+
parent.children[index] = wrapTextNode(node);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { map } from 'unist-util-map';
|
|
2
2
|
import { allowedComponents } from '../../../index.js';
|
|
3
|
-
import {
|
|
3
|
+
import { isMdxJsxFlowElementHast } from '../../../lib/index.js';
|
|
4
|
+
import { getExportedFunctionNames } from '../remarkMdxClientComponentBoundaries.js';
|
|
4
5
|
import { createCommentNode } from './createCommentNode.js';
|
|
5
6
|
export const remarkMdxRemoveUnknownJsx = ({ allowlist } = {}) => (tree) => {
|
|
6
|
-
|
|
7
|
+
// Components defined in the MDX itself are "known" and must not be stripped. Shared with
|
|
8
|
+
// remarkMdxClientComponentBoundaries so the two plugins agree on what counts as a component.
|
|
9
|
+
const exportedComponentNames = getExportedFunctionNames(tree);
|
|
7
10
|
return map(tree, (node) => {
|
|
8
11
|
if (isMdxJsxFlowElementHast(node)) {
|
|
9
12
|
if (node.name &&
|
|
10
13
|
Array.isArray(allowedComponents) &&
|
|
11
14
|
!allowedComponents.includes(node.name) &&
|
|
12
|
-
!exportedComponentNames.
|
|
15
|
+
!exportedComponentNames.has(node.name) &&
|
|
13
16
|
!(allowlist === null || allowlist === void 0 ? void 0 : allowlist.includes(node.name))) {
|
|
14
17
|
return createCommentNode(node.name);
|
|
15
18
|
}
|