@mintlify/common 1.0.1257 → 1.0.1259
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/islands/extractPackageIslands.js +16 -3
- package/dist/mdx/islands/island-module-builder.d.ts +9 -2
- package/dist/mdx/islands/island-module-builder.js +72 -3
- package/dist/mdx/islands/remarkPackageIslands.js +6 -3
- package/dist/mdx/islands/types.d.ts +11 -0
- package/dist/mdx/lib/slug-deduplicator.d.ts +5 -0
- package/dist/mdx/lib/slug-deduplicator.js +24 -0
- package/dist/mdx/plugins/rehype/rehypeDynamicTailwindCss.js +401 -56
- package/dist/mdx/plugins/remark/remarkExtractTableOfContents.js +36 -27
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -2,93 +2,438 @@ import { walk } from 'estree-walker';
|
|
|
2
2
|
import { visit } from 'unist-util-visit';
|
|
3
3
|
import { segment } from './segment.js';
|
|
4
4
|
export const MINTLIFY_TAILWIND_PREFIX = 'mint-';
|
|
5
|
+
const CLASS_HELPERS = new Set(['cn', 'clsx', 'classNames', 'classnames', 'twMerge', 'twJoin']);
|
|
5
6
|
export const rehypeDynamicTailwindCss = (tailwindSelectors) => (tree) => {
|
|
6
7
|
const normalizedTailwindSelectors = tailwindSelectors === null || tailwindSelectors === void 0 ? void 0 : tailwindSelectors.map(normalizeSelector);
|
|
8
|
+
if (!(normalizedTailwindSelectors === null || normalizedTailwindSelectors === void 0 ? void 0 : normalizedTailwindSelectors.length))
|
|
9
|
+
return;
|
|
10
|
+
const moduleScope = new Map();
|
|
11
|
+
const moduleScopes = [moduleScope];
|
|
12
|
+
visit(tree, (node) => {
|
|
13
|
+
if (node.type === 'mdxjsEsm' && node.data && node.data.estree) {
|
|
14
|
+
collectDeclarations(node.data.estree.body, moduleScope, moduleScopes);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
7
17
|
visit(tree, (node) => {
|
|
18
|
+
var _a;
|
|
8
19
|
if ((node.type === 'mdxJsxFlowElement' || node.type === 'mdxJsxTextElement') &&
|
|
9
20
|
node.name &&
|
|
10
21
|
typeof node.name === 'string' &&
|
|
11
22
|
node.attributes.length > 0) {
|
|
12
|
-
const className = node.attributes.find((attr) => attr.type === 'mdxJsxAttribute' && attr.name === 'className');
|
|
13
|
-
|
|
14
|
-
|
|
23
|
+
const className = node.attributes.find((attr) => attr.type === 'mdxJsxAttribute' && (attr.name === 'className' || attr.name === 'class'));
|
|
24
|
+
const value = className === null || className === void 0 ? void 0 : className.value;
|
|
25
|
+
if (className && typeof value === 'string') {
|
|
26
|
+
className.value = transformClassNames(value, normalizedTailwindSelectors);
|
|
27
|
+
}
|
|
28
|
+
else if (value && typeof value !== 'string' && ((_a = value.data) === null || _a === void 0 ? void 0 : _a.estree)) {
|
|
29
|
+
// example: <div className={isActive ? "bg-red-500" : "bg-blue-500"}>
|
|
30
|
+
const [statement] = value.data.estree.body;
|
|
31
|
+
if (statement && statement.type === 'ExpressionStatement') {
|
|
32
|
+
statement.expression = transformExpressionClassNames(statement.expression, moduleScopes, normalizedTailwindSelectors);
|
|
33
|
+
}
|
|
15
34
|
}
|
|
16
35
|
}
|
|
17
36
|
if (node.type === 'mdxjsEsm' && node.data && node.data.estree) {
|
|
18
|
-
transformMdxJsEsmNode(node.data.estree, normalizedTailwindSelectors);
|
|
37
|
+
transformMdxJsEsmNode(node.data.estree, moduleScopes, normalizedTailwindSelectors);
|
|
19
38
|
}
|
|
20
39
|
});
|
|
21
40
|
};
|
|
22
|
-
const
|
|
41
|
+
const collectDeclarations = (statements, scope, scopes) => {
|
|
42
|
+
for (const statement of statements) {
|
|
43
|
+
const declaration = statement.type === 'ExportNamedDeclaration' ? statement.declaration : statement;
|
|
44
|
+
if ((declaration === null || declaration === void 0 ? void 0 : declaration.type) === 'FunctionDeclaration' && declaration.id) {
|
|
45
|
+
scope.set(declaration.id.name, { scopes });
|
|
46
|
+
}
|
|
47
|
+
if ((declaration === null || declaration === void 0 ? void 0 : declaration.type) !== 'VariableDeclaration')
|
|
48
|
+
continue;
|
|
49
|
+
for (const declarator of declaration.declarations) {
|
|
50
|
+
if (declaration.kind === 'const' && declarator.id.type === 'Identifier' && declarator.init) {
|
|
51
|
+
scope.set(declarator.id.name, { init: declarator.init, scopes });
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
getPatternNames(declarator.id).forEach((name) => scope.set(name, { scopes }));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const getPatternNames = (pattern) => {
|
|
60
|
+
switch (pattern.type) {
|
|
61
|
+
case 'Identifier':
|
|
62
|
+
return [pattern.name];
|
|
63
|
+
case 'AssignmentPattern':
|
|
64
|
+
return getPatternNames(pattern.left);
|
|
65
|
+
case 'RestElement':
|
|
66
|
+
return getPatternNames(pattern.argument);
|
|
67
|
+
case 'ArrayPattern':
|
|
68
|
+
return pattern.elements.flatMap((element) => (element ? getPatternNames(element) : []));
|
|
69
|
+
case 'ObjectPattern':
|
|
70
|
+
return pattern.properties.flatMap((property) => getPatternNames(property.type === 'Property' ? property.value : property));
|
|
71
|
+
default:
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const resolveBinding = (name, scopes) => {
|
|
76
|
+
var _a;
|
|
77
|
+
for (let i = scopes.length - 1; i >= 0; i--) {
|
|
78
|
+
const binding = (_a = scopes[i]) === null || _a === void 0 ? void 0 : _a.get(name);
|
|
79
|
+
if (binding)
|
|
80
|
+
return binding;
|
|
81
|
+
}
|
|
82
|
+
return undefined;
|
|
83
|
+
};
|
|
84
|
+
const isFunctionNode = (node) => node.type === 'FunctionDeclaration' ||
|
|
85
|
+
node.type === 'FunctionExpression' ||
|
|
86
|
+
node.type === 'ArrowFunctionExpression';
|
|
87
|
+
const transformMdxJsEsmNode = (estreeNode, moduleScopes, tailwindSelectors) => {
|
|
88
|
+
const scopes = [...moduleScopes];
|
|
23
89
|
walk(estreeNode, {
|
|
24
90
|
enter(node) {
|
|
91
|
+
if (isFunctionNode(node)) {
|
|
92
|
+
const scope = new Map();
|
|
93
|
+
const chain = [...scopes, scope];
|
|
94
|
+
node.params.flatMap(getPatternNames).forEach((name) => scope.set(name, { scopes: chain }));
|
|
95
|
+
scopes.push(scope);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (node.type === 'BlockStatement') {
|
|
99
|
+
const scope = new Map();
|
|
100
|
+
collectDeclarations(node.body, scope, [...scopes, scope]);
|
|
101
|
+
scopes.push(scope);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
25
104
|
if (node.type === 'JSXAttribute' &&
|
|
26
105
|
node.name.type === 'JSXIdentifier' &&
|
|
27
106
|
(node.name.name === 'className' || node.name.name === 'class')) {
|
|
28
|
-
if (node.value && node.value.type === 'JSXExpressionContainer') {
|
|
29
|
-
const expression = node.value.expression;
|
|
30
|
-
if (expression.type === 'TemplateLiteral') {
|
|
31
|
-
// example: className={`bg-green-500`}
|
|
32
|
-
expression.quasis.forEach((quasi) => {
|
|
33
|
-
if (quasi.value.cooked) {
|
|
34
|
-
const originalValue = quasi.value.cooked;
|
|
35
|
-
const transformedValue = transformClassNames(originalValue, tailwindSelectors);
|
|
36
|
-
if (originalValue !== transformedValue) {
|
|
37
|
-
quasi.value.cooked = transformedValue;
|
|
38
|
-
quasi.value.raw = transformedValue;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
// example: className={`${isActive ? "bg-red-500" : "bg-blue-500"}`}
|
|
43
|
-
expression.expressions.forEach((expr) => {
|
|
44
|
-
transformExpressionClassNames(expr, tailwindSelectors);
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
107
|
// example: className="bg-green-500"
|
|
49
|
-
if (node.value && node.value.type === 'Literal'
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
}
|
|
108
|
+
if (node.value && node.value.type === 'Literal') {
|
|
109
|
+
transformLiteral(node.value, tailwindSelectors);
|
|
110
|
+
}
|
|
111
|
+
if (node.value &&
|
|
112
|
+
node.value.type === 'JSXExpressionContainer' &&
|
|
113
|
+
node.value.expression.type !== 'JSXEmptyExpression') {
|
|
114
|
+
node.value.expression = transformExpressionClassNames(node.value.expression, scopes, tailwindSelectors);
|
|
58
115
|
}
|
|
59
116
|
}
|
|
60
117
|
},
|
|
118
|
+
leave(node) {
|
|
119
|
+
if (node.type === 'BlockStatement' || isFunctionNode(node)) {
|
|
120
|
+
scopes.pop();
|
|
121
|
+
}
|
|
122
|
+
},
|
|
61
123
|
});
|
|
62
124
|
};
|
|
63
|
-
const transformExpressionClassNames = (expr, tailwindSelectors) => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
125
|
+
const transformExpressionClassNames = (expr, scopes, tailwindSelectors, inlining = new Set()) => {
|
|
126
|
+
const transform = (child) => transformExpressionClassNames(child, scopes, tailwindSelectors, inlining);
|
|
127
|
+
const transformElement = (element) => {
|
|
128
|
+
if (element.type !== 'SpreadElement')
|
|
129
|
+
return transform(element);
|
|
130
|
+
element.argument = transform(element.argument);
|
|
131
|
+
return element;
|
|
132
|
+
};
|
|
133
|
+
switch (expr.type) {
|
|
134
|
+
case 'Literal':
|
|
135
|
+
transformLiteral(expr, tailwindSelectors);
|
|
136
|
+
return expr;
|
|
137
|
+
case 'TemplateLiteral':
|
|
138
|
+
// example: className={`bg-green-500`}
|
|
139
|
+
expr.quasis.forEach((quasi) => {
|
|
140
|
+
if (quasi.value.cooked) {
|
|
141
|
+
const transformedValue = transformClassNames(quasi.value.cooked, tailwindSelectors);
|
|
142
|
+
if (quasi.value.cooked !== transformedValue) {
|
|
143
|
+
quasi.value.cooked = transformedValue;
|
|
144
|
+
quasi.value.raw = transformedValue;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
// example: className={`${isActive ? "bg-red-500" : "bg-blue-500"}`}
|
|
149
|
+
expr.expressions = expr.expressions.map(transform);
|
|
150
|
+
return expr;
|
|
151
|
+
case 'ConditionalExpression':
|
|
152
|
+
// example: ${isActive ? "bg-red-500" : "bg-blue-500"}
|
|
153
|
+
expr.consequent = transform(expr.consequent);
|
|
154
|
+
expr.alternate = transform(expr.alternate);
|
|
155
|
+
return expr;
|
|
156
|
+
case 'LogicalExpression':
|
|
157
|
+
// example: ${isActive && "bg-red-500"}
|
|
158
|
+
expr.left = transform(expr.left);
|
|
159
|
+
expr.right = transform(expr.right);
|
|
160
|
+
return expr;
|
|
161
|
+
case 'BinaryExpression':
|
|
162
|
+
if (expr.operator === '+') {
|
|
163
|
+
// example: ${"bg-red-500" + "bg-blue-500"}
|
|
164
|
+
expr.left = transform(expr.left);
|
|
165
|
+
expr.right = transform(expr.right);
|
|
166
|
+
}
|
|
167
|
+
return expr;
|
|
168
|
+
case 'ArrayExpression':
|
|
169
|
+
// example: ["bg-red-500", "bg-blue-500"]
|
|
170
|
+
expr.elements = expr.elements.map((element) => element && transformElement(element));
|
|
171
|
+
return expr;
|
|
172
|
+
case 'CallExpression':
|
|
173
|
+
if (!isClassCall(expr))
|
|
174
|
+
return expr;
|
|
175
|
+
// example: ["bg-red-500", "bg-blue-500"].join(" ")
|
|
176
|
+
if (expr.callee.type === 'MemberExpression' && expr.callee.object.type !== 'Super') {
|
|
177
|
+
expr.callee.object = transform(expr.callee.object);
|
|
178
|
+
}
|
|
179
|
+
expr.arguments = expr.arguments.map(transformElement);
|
|
180
|
+
return expr;
|
|
181
|
+
case 'ObjectExpression':
|
|
182
|
+
// example: cn({ "bg-blue-500": isActive })
|
|
183
|
+
transformObjectKeys(expr, transform, tailwindSelectors);
|
|
184
|
+
return expr;
|
|
185
|
+
case 'MemberExpression':
|
|
186
|
+
// example: const styles = { active: "bg-red-500" }; className={styles.active}
|
|
187
|
+
return transformMemberExpression(expr, scopes, transform);
|
|
188
|
+
case 'Identifier': {
|
|
189
|
+
// example: const classes = "bg-red-500"; className={classes}
|
|
190
|
+
const binding = resolveBinding(expr.name, scopes);
|
|
191
|
+
if (!(binding === null || binding === void 0 ? void 0 : binding.init) || inlining.has(binding))
|
|
192
|
+
return expr;
|
|
193
|
+
const inlined = cloneForUse(binding.init, binding.scopes, scopes, new Set([binding]));
|
|
194
|
+
if (!inlined)
|
|
195
|
+
return expr;
|
|
196
|
+
const before = serialize(inlined);
|
|
197
|
+
const transformed = transformExpressionClassNames(inlined, scopes, tailwindSelectors, new Set([...inlining, binding]));
|
|
198
|
+
return serialize(transformed) === before ? expr : transformed;
|
|
199
|
+
}
|
|
200
|
+
default:
|
|
201
|
+
return expr;
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
const transformMemberExpression = (expr, scopes, transform) => {
|
|
205
|
+
if (getStaticKey(expr) !== undefined) {
|
|
206
|
+
const resolved = resolveStaticValue(expr, scopes);
|
|
207
|
+
const inlined = resolved && cloneForUse(resolved.expr, resolved.scopes, scopes, new Set());
|
|
208
|
+
if (!inlined)
|
|
209
|
+
return expr;
|
|
210
|
+
const before = serialize(inlined);
|
|
211
|
+
const transformed = transform(inlined);
|
|
212
|
+
return serialize(transformed) === before ? expr : transformed;
|
|
213
|
+
}
|
|
214
|
+
const object = resolveObject(expr.object, scopes);
|
|
215
|
+
if (!object)
|
|
216
|
+
return expr;
|
|
217
|
+
const before = serialize(object);
|
|
218
|
+
object.properties.forEach((property) => {
|
|
219
|
+
const value = property.type === 'Property' ? asExpression(property.value) : undefined;
|
|
220
|
+
if (property.type === 'Property' && value)
|
|
221
|
+
property.value = transform(value);
|
|
222
|
+
});
|
|
223
|
+
if (serialize(object) !== before)
|
|
224
|
+
expr.object = object;
|
|
225
|
+
return expr;
|
|
226
|
+
};
|
|
227
|
+
const transformObjectKeys = (expr, transform, tailwindSelectors) => {
|
|
228
|
+
expr.properties.forEach((property) => {
|
|
229
|
+
if (property.type === 'SpreadElement') {
|
|
230
|
+
property.argument = transform(property.argument);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (property.computed) {
|
|
234
|
+
if (property.key.type !== 'PrivateIdentifier')
|
|
235
|
+
property.key = transform(property.key);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const keyName = getPropertyKeyName(property);
|
|
239
|
+
if (keyName === undefined)
|
|
240
|
+
return;
|
|
241
|
+
const transformedValue = transformClassNames(keyName, tailwindSelectors);
|
|
242
|
+
if (keyName !== transformedValue) {
|
|
243
|
+
property.key = toLiteral(transformedValue);
|
|
244
|
+
property.shorthand = false;
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
};
|
|
248
|
+
const resolveObject = (node, scopes) => {
|
|
249
|
+
if (node.type === 'ObjectExpression')
|
|
250
|
+
return node;
|
|
251
|
+
const resolved = resolveStaticValue(node, scopes);
|
|
252
|
+
if ((resolved === null || resolved === void 0 ? void 0 : resolved.expr.type) !== 'ObjectExpression')
|
|
253
|
+
return undefined;
|
|
254
|
+
const cloned = cloneForUse(resolved.expr, resolved.scopes, scopes, new Set());
|
|
255
|
+
return (cloned === null || cloned === void 0 ? void 0 : cloned.type) === 'ObjectExpression' ? cloned : undefined;
|
|
256
|
+
};
|
|
257
|
+
const resolveStaticValue = (node, scopes, resolving = new Set()) => {
|
|
258
|
+
if (node.type === 'Super')
|
|
259
|
+
return undefined;
|
|
260
|
+
if (node.type === 'Identifier') {
|
|
261
|
+
const binding = resolveBinding(node.name, scopes);
|
|
262
|
+
if (!(binding === null || binding === void 0 ? void 0 : binding.init))
|
|
263
|
+
return { expr: node, scopes };
|
|
264
|
+
if (resolving.has(binding))
|
|
265
|
+
return undefined;
|
|
266
|
+
return resolveStaticValue(binding.init, binding.scopes, new Set([...resolving, binding]));
|
|
267
|
+
}
|
|
268
|
+
if (node.type === 'MemberExpression') {
|
|
269
|
+
const key = getStaticKey(node);
|
|
270
|
+
if (key === undefined)
|
|
271
|
+
return { expr: node, scopes };
|
|
272
|
+
const object = resolveStaticValue(node.object, scopes, resolving);
|
|
273
|
+
if ((object === null || object === void 0 ? void 0 : object.expr.type) !== 'ObjectExpression')
|
|
274
|
+
return undefined;
|
|
275
|
+
const value = findPropertyValue(object.expr, key);
|
|
276
|
+
return value && resolveStaticValue(value, object.scopes, resolving);
|
|
277
|
+
}
|
|
278
|
+
return { expr: node, scopes };
|
|
279
|
+
};
|
|
280
|
+
const cloneForUse = (expr, declarationScopes, useScopes, inlining) => {
|
|
281
|
+
const clone = (child) => cloneForUse(child, declarationScopes, useScopes, inlining);
|
|
282
|
+
const cloneElement = (element) => {
|
|
283
|
+
if (element.type !== 'SpreadElement')
|
|
284
|
+
return clone(element);
|
|
285
|
+
const argument = clone(element.argument);
|
|
286
|
+
return argument && Object.assign(Object.assign({}, element), { argument });
|
|
287
|
+
};
|
|
288
|
+
const cloneAll = (items, cloneItem) => {
|
|
289
|
+
const cloned = [];
|
|
290
|
+
for (const item of items) {
|
|
291
|
+
const result = cloneItem(item);
|
|
292
|
+
if (result === undefined)
|
|
293
|
+
return undefined;
|
|
294
|
+
cloned.push(result);
|
|
295
|
+
}
|
|
296
|
+
return cloned;
|
|
297
|
+
};
|
|
298
|
+
switch (expr.type) {
|
|
299
|
+
case 'Literal':
|
|
300
|
+
return structuredClone(expr);
|
|
301
|
+
case 'TemplateLiteral': {
|
|
302
|
+
const expressions = cloneAll(expr.expressions, clone);
|
|
303
|
+
return expressions && Object.assign(Object.assign({}, expr), { quasis: structuredClone(expr.quasis), expressions });
|
|
304
|
+
}
|
|
305
|
+
case 'ArrayExpression': {
|
|
306
|
+
const elements = cloneAll(expr.elements, (element) => element === null ? null : cloneElement(element));
|
|
307
|
+
return elements && Object.assign(Object.assign({}, expr), { elements });
|
|
308
|
+
}
|
|
309
|
+
case 'BinaryExpression': {
|
|
310
|
+
const left = clone(expr.left);
|
|
311
|
+
const right = clone(expr.right);
|
|
312
|
+
return left && right && Object.assign(Object.assign({}, expr), { left, right });
|
|
313
|
+
}
|
|
314
|
+
case 'LogicalExpression': {
|
|
315
|
+
const left = clone(expr.left);
|
|
316
|
+
const right = clone(expr.right);
|
|
317
|
+
return left && right && Object.assign(Object.assign({}, expr), { left, right });
|
|
318
|
+
}
|
|
319
|
+
case 'ConditionalExpression': {
|
|
320
|
+
const test = clone(expr.test);
|
|
321
|
+
const consequent = clone(expr.consequent);
|
|
322
|
+
const alternate = clone(expr.alternate);
|
|
323
|
+
return test && consequent && alternate && Object.assign(Object.assign({}, expr), { test, consequent, alternate });
|
|
324
|
+
}
|
|
325
|
+
case 'UnaryExpression': {
|
|
326
|
+
const argument = clone(expr.argument);
|
|
327
|
+
return argument && Object.assign(Object.assign({}, expr), { argument });
|
|
328
|
+
}
|
|
329
|
+
case 'ObjectExpression': {
|
|
330
|
+
const properties = cloneAll(expr.properties, (property) => {
|
|
331
|
+
if (property.type === 'SpreadElement') {
|
|
332
|
+
const argument = clone(property.argument);
|
|
333
|
+
return argument && Object.assign(Object.assign({}, property), { argument });
|
|
334
|
+
}
|
|
335
|
+
if (property.kind !== 'init' || property.method)
|
|
336
|
+
return undefined;
|
|
337
|
+
const value = asExpression(property.value);
|
|
338
|
+
const clonedValue = value && clone(value);
|
|
339
|
+
if (!clonedValue)
|
|
340
|
+
return undefined;
|
|
341
|
+
if (!property.computed) {
|
|
342
|
+
return Object.assign(Object.assign({}, property), { key: structuredClone(property.key), value: clonedValue, shorthand: false });
|
|
343
|
+
}
|
|
344
|
+
if (property.key.type === 'PrivateIdentifier')
|
|
345
|
+
return undefined;
|
|
346
|
+
const key = clone(property.key);
|
|
347
|
+
return key && Object.assign(Object.assign({}, property), { key, value: clonedValue, shorthand: false });
|
|
348
|
+
});
|
|
349
|
+
return properties && Object.assign(Object.assign({}, expr), { properties });
|
|
350
|
+
}
|
|
351
|
+
case 'MemberExpression': {
|
|
352
|
+
if (expr.object.type === 'Super' || expr.property.type === 'PrivateIdentifier') {
|
|
353
|
+
return undefined;
|
|
354
|
+
}
|
|
355
|
+
const object = clone(expr.object);
|
|
356
|
+
const property = expr.computed ? clone(expr.property) : structuredClone(expr.property);
|
|
357
|
+
return object && property && Object.assign(Object.assign({}, expr), { object, property });
|
|
358
|
+
}
|
|
359
|
+
case 'CallExpression': {
|
|
360
|
+
if (!isClassCall(expr) || expr.callee.type === 'Super')
|
|
361
|
+
return undefined;
|
|
362
|
+
const callee = clone(expr.callee);
|
|
363
|
+
const args = cloneAll(expr.arguments, cloneElement);
|
|
364
|
+
return callee && args && Object.assign(Object.assign({}, expr), { callee, arguments: args });
|
|
365
|
+
}
|
|
366
|
+
case 'Identifier': {
|
|
367
|
+
const binding = resolveBinding(expr.name, declarationScopes);
|
|
368
|
+
if ((binding === null || binding === void 0 ? void 0 : binding.init) && !inlining.has(binding)) {
|
|
369
|
+
const inlined = cloneForUse(binding.init, binding.scopes, useScopes, new Set([...inlining, binding]));
|
|
370
|
+
if (inlined)
|
|
371
|
+
return inlined;
|
|
73
372
|
}
|
|
373
|
+
return binding === resolveBinding(expr.name, useScopes) ? structuredClone(expr) : undefined;
|
|
74
374
|
}
|
|
375
|
+
default:
|
|
376
|
+
return undefined;
|
|
75
377
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
378
|
+
};
|
|
379
|
+
const isClassCall = (expr) => {
|
|
380
|
+
const { callee } = expr;
|
|
381
|
+
if (callee.type === 'Identifier')
|
|
382
|
+
return CLASS_HELPERS.has(callee.name);
|
|
383
|
+
return (callee.type === 'MemberExpression' &&
|
|
384
|
+
!callee.computed &&
|
|
385
|
+
callee.property.type === 'Identifier' &&
|
|
386
|
+
(callee.property.name === 'join' || callee.property.name === 'concat'));
|
|
387
|
+
};
|
|
388
|
+
const getStaticKey = (expr) => {
|
|
389
|
+
if (!expr.computed && expr.property.type === 'Identifier')
|
|
390
|
+
return expr.property.name;
|
|
391
|
+
if (expr.property.type === 'Literal' && typeof expr.property.value === 'string') {
|
|
392
|
+
return expr.property.value;
|
|
393
|
+
}
|
|
394
|
+
return undefined;
|
|
395
|
+
};
|
|
396
|
+
const getPropertyKeyName = (property) => {
|
|
397
|
+
if (!property.computed && property.key.type === 'Identifier')
|
|
398
|
+
return property.key.name;
|
|
399
|
+
if (property.key.type === 'Literal' && typeof property.key.value === 'string') {
|
|
400
|
+
return property.key.value;
|
|
80
401
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
402
|
+
return undefined;
|
|
403
|
+
};
|
|
404
|
+
const findPropertyValue = (object, key) => {
|
|
405
|
+
for (let i = object.properties.length - 1; i >= 0; i--) {
|
|
406
|
+
const property = object.properties[i];
|
|
407
|
+
if (!property || property.type === 'SpreadElement')
|
|
408
|
+
return undefined;
|
|
409
|
+
if (getPropertyKeyName(property) === key)
|
|
410
|
+
return asExpression(property.value);
|
|
85
411
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
412
|
+
return undefined;
|
|
413
|
+
};
|
|
414
|
+
const asExpression = (node) => node.type === 'ObjectPattern' ||
|
|
415
|
+
node.type === 'ArrayPattern' ||
|
|
416
|
+
node.type === 'RestElement' ||
|
|
417
|
+
node.type === 'AssignmentPattern'
|
|
418
|
+
? undefined
|
|
419
|
+
: node;
|
|
420
|
+
const transformLiteral = (expr, tailwindSelectors) => {
|
|
421
|
+
if (typeof expr.value !== 'string')
|
|
422
|
+
return;
|
|
423
|
+
const transformedValue = transformClassNames(expr.value, tailwindSelectors);
|
|
424
|
+
if (expr.value !== transformedValue) {
|
|
425
|
+
expr.value = transformedValue;
|
|
426
|
+
if (typeof expr.raw === 'string') {
|
|
427
|
+
expr.raw = JSON.stringify(transformedValue);
|
|
428
|
+
}
|
|
90
429
|
}
|
|
91
430
|
};
|
|
431
|
+
const toLiteral = (value) => ({
|
|
432
|
+
type: 'Literal',
|
|
433
|
+
value,
|
|
434
|
+
raw: JSON.stringify(value),
|
|
435
|
+
});
|
|
436
|
+
const serialize = (node) => JSON.stringify(node, (_key, value) => typeof value === 'bigint' ? value.toString() : value);
|
|
92
437
|
const transformClassNames = (value, tailwindSelectors) => {
|
|
93
438
|
var _a, _b, _c, _d;
|
|
94
439
|
if (!tailwindSelectors || !tailwindSelectors.length)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { visit } from 'unist-util-visit';
|
|
2
2
|
import { normalizeGroups } from '../../../navigation/groupAccess.js';
|
|
3
3
|
import { safeCleanHeadingId, slugify } from '../../../slugify.js';
|
|
4
|
+
import { MINT_ISLAND_COMPONENT } from '../../islands/packageImports.js';
|
|
4
5
|
import { createMdxJsxAttribute, getTableOfContentsTitle, getTitleMarkdownText, } from '../../lib/remark-utils.js';
|
|
6
|
+
import { createSlugDeduplicator } from '../../lib/slug-deduplicator.js';
|
|
5
7
|
import { isMdxJsxFragment } from '../../utils.js';
|
|
6
8
|
import { AVOIDED_PAGE_MODES, HEADING_LEVELS } from './remarkComponentIds.js';
|
|
7
9
|
import { isHiddenFromHumans, isVisibilityElement, resolveVisibilityFor, toPageGroups, toVisibilityAuthRule, } from './remarkVisibilityForMarkdown.js';
|
|
@@ -37,23 +39,9 @@ const hasAuthRules = (childRules, parentRules) => {
|
|
|
37
39
|
export const remarkExtractTableOfContents = (mdxExtracts, pageMetadata) => {
|
|
38
40
|
// Unified slug deduplication: both custom IDs and auto-generated slugs
|
|
39
41
|
// share the same seen-slug state so they cannot collide.
|
|
40
|
-
const
|
|
41
|
-
const deduplicateSlug = (slug) => {
|
|
42
|
-
var _a;
|
|
43
|
-
const count = (_a = seenSlugs.get(slug)) !== null && _a !== void 0 ? _a : 0;
|
|
44
|
-
seenSlugs.set(slug, count + 1);
|
|
45
|
-
if (count === 0)
|
|
46
|
-
return slug;
|
|
47
|
-
let suffix = count + 1;
|
|
48
|
-
let suffixed = `${slug}-${suffix}`;
|
|
49
|
-
while (seenSlugs.has(suffixed)) {
|
|
50
|
-
suffix += 1;
|
|
51
|
-
suffixed = `${slug}-${suffix}`;
|
|
52
|
-
}
|
|
53
|
-
seenSlugs.set(suffixed, 1);
|
|
54
|
-
return suffixed;
|
|
55
|
-
};
|
|
42
|
+
const slugs = createSlugDeduplicator();
|
|
56
43
|
return (tree) => {
|
|
44
|
+
var _a;
|
|
57
45
|
const contents = [];
|
|
58
46
|
let hasTopLayer = false;
|
|
59
47
|
// the key is the node in unist
|
|
@@ -66,7 +54,13 @@ export const remarkExtractTableOfContents = (mdxExtracts, pageMetadata) => {
|
|
|
66
54
|
// doesn't set its own titleSize, so the TOC must honor the same fallback.
|
|
67
55
|
const inheritedStepTitleSizeMap = new Map();
|
|
68
56
|
const excludedNodes = new Set();
|
|
57
|
+
const isAvoidedPageMode = AVOIDED_PAGE_MODES.includes((_a = pageMetadata === null || pageMetadata === void 0 ? void 0 : pageMetadata.mode) !== null && _a !== void 0 ? _a : '');
|
|
69
58
|
visit(tree, (node) => {
|
|
59
|
+
var _a, _b;
|
|
60
|
+
if (node.type === 'mdxJsxFlowElement' && node.name === MINT_ISLAND_COMPONENT) {
|
|
61
|
+
for (const heading of (_b = (_a = node.data) === null || _a === void 0 ? void 0 : _a.islandHeadings) !== null && _b !== void 0 ? _b : [])
|
|
62
|
+
slugs.reserve(heading.slug);
|
|
63
|
+
}
|
|
70
64
|
if (node.type === 'mdxJsxFlowElement' &&
|
|
71
65
|
node.name &&
|
|
72
66
|
COMPONENTS_TO_EXCLUDE_HEADINGS.includes(node.name)) {
|
|
@@ -177,7 +171,7 @@ export const remarkExtractTableOfContents = (mdxExtracts, pageMetadata) => {
|
|
|
177
171
|
arrToPushInto.push(entry);
|
|
178
172
|
};
|
|
179
173
|
visit(tree, (node) => {
|
|
180
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
174
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
181
175
|
if (excludedNodes.has(node))
|
|
182
176
|
return;
|
|
183
177
|
const currentTabId = tabContentMap.get(node);
|
|
@@ -191,9 +185,8 @@ export const remarkExtractTableOfContents = (mdxExtracts, pageMetadata) => {
|
|
|
191
185
|
// headings compiled inside an <MDX> fragment (see remarkMdxExpandExpressions); merged in
|
|
192
186
|
// document order, slugs registered so later page headings do not reuse them
|
|
193
187
|
const register = (entries) => {
|
|
194
|
-
var _a;
|
|
195
188
|
for (const entry of entries) {
|
|
196
|
-
|
|
189
|
+
slugs.reserve(entry.slug);
|
|
197
190
|
register(entry.children);
|
|
198
191
|
}
|
|
199
192
|
};
|
|
@@ -205,14 +198,31 @@ export const remarkExtractTableOfContents = (mdxExtracts, pageMetadata) => {
|
|
|
205
198
|
}
|
|
206
199
|
return;
|
|
207
200
|
}
|
|
201
|
+
if (node.type === 'mdxJsxFlowElement' && node.name === MINT_ISLAND_COMPONENT) {
|
|
202
|
+
if (isAvoidedPageMode)
|
|
203
|
+
return;
|
|
204
|
+
for (const { title, slug, depth } of (_d = (_c = node.data) === null || _c === void 0 ? void 0 : _c.islandHeadings) !== null && _d !== void 0 ? _d : []) {
|
|
205
|
+
pushEntry({
|
|
206
|
+
title,
|
|
207
|
+
slug,
|
|
208
|
+
depth,
|
|
209
|
+
children: [],
|
|
210
|
+
tabId: currentTabId,
|
|
211
|
+
viewId: currentViewId,
|
|
212
|
+
variationIds: currentVariationIds,
|
|
213
|
+
authRules: currentAuthRules,
|
|
214
|
+
}, depth);
|
|
215
|
+
}
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
208
218
|
const isValidHeading = node.type === 'heading' && HEADING_LEVELS.includes(node.depth);
|
|
209
|
-
const isValidMdxHeading = node.type === 'mdxJsxFlowElement' && HEADING_NAMES.includes((
|
|
219
|
+
const isValidMdxHeading = node.type === 'mdxJsxFlowElement' && HEADING_NAMES.includes((_e = node.name) !== null && _e !== void 0 ? _e : '');
|
|
210
220
|
const isTransformedHeading = node.type === 'mdxJsxFlowElement' && node.name === 'Heading';
|
|
211
221
|
const isValidUpdate = node.type === 'mdxJsxFlowElement' &&
|
|
212
222
|
node.name === 'Update' &&
|
|
213
223
|
node.attributes.some((attr) => 'name' in attr && attr.name === 'label');
|
|
214
224
|
const stepTitleSize = node.type === 'mdxJsxFlowElement' && node.name === 'Step'
|
|
215
|
-
? ((
|
|
225
|
+
? ((_f = getStringAttribute(node.attributes, 'titleSize')) !== null && _f !== void 0 ? _f : inheritedStepTitleSizeMap.get(node))
|
|
216
226
|
: undefined;
|
|
217
227
|
const hasNoAnchor = node.type === 'mdxJsxFlowElement' &&
|
|
218
228
|
node.attributes.some((attr) => 'name' in attr &&
|
|
@@ -221,7 +231,7 @@ export const remarkExtractTableOfContents = (mdxExtracts, pageMetadata) => {
|
|
|
221
231
|
attr.value === 'true' ||
|
|
222
232
|
(typeof attr.value === 'object' && attr.value.value === 'true')));
|
|
223
233
|
const stepTitle = node.type === 'mdxJsxFlowElement' && node.name === 'Step'
|
|
224
|
-
? getTitleMarkdownText(node, (
|
|
234
|
+
? getTitleMarkdownText(node, (_g = getStringAttribute(node.attributes, 'title')) !== null && _g !== void 0 ? _g : '')
|
|
225
235
|
: undefined;
|
|
226
236
|
const isValidStep = node.type === 'mdxJsxFlowElement' &&
|
|
227
237
|
node.name === 'Step' &&
|
|
@@ -230,7 +240,6 @@ export const remarkExtractTableOfContents = (mdxExtracts, pageMetadata) => {
|
|
|
230
240
|
(stepTitle === null || stepTitle === void 0 ? void 0 : stepTitle.trim()) !== '';
|
|
231
241
|
const hasIdAttribute = node.type === 'mdxJsxFlowElement' &&
|
|
232
242
|
node.attributes.some((attr) => 'name' in attr && attr.name === 'id');
|
|
233
|
-
const isAvoidedPageMode = AVOIDED_PAGE_MODES.includes((_f = pageMetadata === null || pageMetadata === void 0 ? void 0 : pageMetadata.mode) !== null && _f !== void 0 ? _f : '');
|
|
234
243
|
if (!isValidHeading &&
|
|
235
244
|
!isValidMdxHeading &&
|
|
236
245
|
!isTransformedHeading &&
|
|
@@ -248,7 +257,7 @@ export const remarkExtractTableOfContents = (mdxExtracts, pageMetadata) => {
|
|
|
248
257
|
}
|
|
249
258
|
else if ('name' in node && node.name === 'Step') {
|
|
250
259
|
const titleSizeToLevel = { h2: 2, h3: 3, h4: 4 };
|
|
251
|
-
level = (
|
|
260
|
+
level = (_h = titleSizeToLevel[stepTitleSize !== null && stepTitleSize !== void 0 ? stepTitleSize : '']) !== null && _h !== void 0 ? _h : 3;
|
|
252
261
|
// @ts-expect-error we're assigning to depth despite the node not containing depth in the type
|
|
253
262
|
node.depth = level;
|
|
254
263
|
}
|
|
@@ -261,7 +270,7 @@ export const remarkExtractTableOfContents = (mdxExtracts, pageMetadata) => {
|
|
|
261
270
|
level = levelAttr.value;
|
|
262
271
|
}
|
|
263
272
|
}
|
|
264
|
-
else if ('name' in node && ((
|
|
273
|
+
else if ('name' in node && ((_j = node.name) === null || _j === void 0 ? void 0 : _j[1])) {
|
|
265
274
|
const num = Number(node.name[1]);
|
|
266
275
|
level = !isNaN(num) ? num : undefined;
|
|
267
276
|
if (level !== undefined) {
|
|
@@ -277,10 +286,10 @@ export const remarkExtractTableOfContents = (mdxExtracts, pageMetadata) => {
|
|
|
277
286
|
? getStringAttribute(node.attributes, 'id')
|
|
278
287
|
: undefined;
|
|
279
288
|
if (explicitId) {
|
|
280
|
-
slug =
|
|
289
|
+
slug = slugs.claim(safeCleanHeadingId(explicitId) || slugify(title));
|
|
281
290
|
}
|
|
282
291
|
else {
|
|
283
|
-
slug =
|
|
292
|
+
slug = slugs.claim(slugify(title));
|
|
284
293
|
}
|
|
285
294
|
let mdxJsxAttributes;
|
|
286
295
|
if ('name' in node && node.name === 'Update') {
|