@mintlify/common 1.0.1268 → 1.0.1270

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.
Files changed (26) hide show
  1. package/dist/mdx/estreeReferences.d.ts +39 -0
  2. package/dist/mdx/estreeReferences.js +963 -0
  3. package/dist/mdx/plugins/remark/firstPartyMarkdownComponents.d.ts +3 -0
  4. package/dist/mdx/plugins/remark/firstPartyMarkdownComponents.js +29 -0
  5. package/dist/mdx/plugins/remark/remarkMdxRemoveUnknownJsx/index.d.ts +1 -1
  6. package/dist/mdx/plugins/remark/remarkVisibilityForMarkdown.d.ts +7 -1
  7. package/dist/mdx/plugins/remark/remarkVisibilityForMarkdown.js +581 -177
  8. package/dist/mdx/plugins/remark/staticEvaluator.d.ts +55 -0
  9. package/dist/mdx/plugins/remark/staticEvaluator.js +639 -0
  10. package/dist/mdx/plugins/remark/unfoldComponentsForMarkdown.d.ts +71 -0
  11. package/dist/mdx/plugins/remark/unfoldComponentsForMarkdown.js +1414 -0
  12. package/dist/mdx/remark-core.d.ts +7 -0
  13. package/dist/mdx/remark-core.js +32 -0
  14. package/dist/mdx/remark.d.ts +1 -7
  15. package/dist/mdx/remark.js +2 -32
  16. package/dist/mdx/snippets/getExportMap.js +33 -5
  17. package/dist/mdx/snippets/resolveAllImports.js +3 -2
  18. package/dist/mdx/snippets/resolveImport/exportCollision.d.ts +1 -0
  19. package/dist/mdx/snippets/resolveImport/exportCollision.js +2 -1
  20. package/dist/mdx/snippets/resolveImport/index.d.ts +11 -1
  21. package/dist/mdx/snippets/resolveImport/index.js +129 -16
  22. package/dist/mdx/snippets/resolveImport/resolveComponentWithContent.js +38 -5
  23. package/dist/mdx/snippets/resolveImport/snippetDeclarations.d.ts +56 -0
  24. package/dist/mdx/snippets/resolveImport/snippetDeclarations.js +655 -0
  25. package/dist/tsconfig.build.tsbuildinfo +1 -1
  26. package/package.json +6 -5
@@ -0,0 +1,1414 @@
1
+ import { jsx, toJs } from 'estree-util-to-js';
2
+ import { isObject } from '../../../types/guards.js';
3
+ import { collectModuleWrites, collectPatternNames, forEachCodeChild, } from '../../estreeReferences.js';
4
+ import { getJsxEsmTree } from '../../snippets/getJsxEsmTree.js';
5
+ import { BLOCK_LINK_LABEL, FIRST_PARTY_MARKDOWN_COMPONENT_SOURCE, } from './firstPartyMarkdownComponents.js';
6
+ import { VISIBILITY_FOR_EXPECTED, isVisibilityAudience } from './remarkVisibilityForMarkdown.js';
7
+ import { bindPattern, collectContextFromTree, EVAL_FAILED, evaluateStatic, identifierName, isNoOpSpreadValue, isStaticObject, nodeType, serializeStaticValue, unbindPattern, } from './staticEvaluator.js';
8
+ export const MAX_UNFOLD_OUTPUT_BYTES = 2000000;
9
+ // Charged before each materialization so branching definition chains cannot run
10
+ // exponential call volumes under the byte budget.
11
+ export const MAX_UNFOLD_CALLS = 20000;
12
+ export const MAX_UNFOLD_DEPTH = 24;
13
+ export function createUnfoldBudget() {
14
+ return {
15
+ remainingBytes: MAX_UNFOLD_OUTPUT_BYTES,
16
+ remainingCalls: MAX_UNFOLD_CALLS,
17
+ };
18
+ }
19
+ export function chargeUnfoldBudget(ctx, cost) {
20
+ ctx.budget.remainingBytes -= cost;
21
+ return ctx.budget.remainingBytes >= 0;
22
+ }
23
+ /**
24
+ * A `for` that statically resolves to `agents` or `signed-out`, as a literal or an expression such
25
+ * as `for={"agents"}`, with no spread, can never hide content from agents.
26
+ */
27
+ function isAgentVisibleAudience(openingElement) {
28
+ const attributes = Array.isArray(openingElement.attributes) ? openingElement.attributes : [];
29
+ if (attributes.some((attribute) => isObject(attribute) && attribute.type === 'JSXSpreadAttribute')) {
30
+ return false;
31
+ }
32
+ // JSX applies the last of repeated attributes
33
+ const audience = attributes.findLast((attribute) => isObject(attribute) &&
34
+ attribute.type === 'JSXAttribute' &&
35
+ isObject(attribute.name) &&
36
+ attribute.name.name === 'for');
37
+ if (!isObject(audience) || !isObject(audience.value))
38
+ return false;
39
+ const raw = audience.value;
40
+ let value = raw.value;
41
+ if (raw.type === 'JSXExpressionContainer') {
42
+ // Only literal expressions: the scan has no scope, so names must stay gating
43
+ const evaluated = evaluateStatic(raw.expression, { scope: new Map() });
44
+ value = evaluated.ok ? evaluated.value : undefined;
45
+ }
46
+ return value === 'agents' || value === 'signed-out';
47
+ }
48
+ /** Collects the components a definition renders; returns true as soon as it finds a gating `Visibility`. */
49
+ function scanRenderedComponents(node, rendered) {
50
+ if (Array.isArray(node))
51
+ return node.some((child) => scanRenderedComponents(child, rendered));
52
+ if (!isObject(node))
53
+ return false;
54
+ if (node.type === 'JSXOpeningElement' && isObject(node.name)) {
55
+ let root = node.name;
56
+ while (isObject(root) && root.type === 'JSXMemberExpression')
57
+ root = root.object;
58
+ if (isObject(root) && typeof root.name === 'string') {
59
+ if (root.name === 'Visibility' && !isAgentVisibleAudience(node))
60
+ return true;
61
+ rendered.add(root.name);
62
+ }
63
+ }
64
+ return Object.entries(node).some(([key, child]) => key !== 'loc' && key !== 'range' && scanRenderedComponents(child, rendered));
65
+ }
66
+ /**
67
+ * Whether a definition, or any component it renders, may hide content from agents. Degrading such
68
+ * a usage to its raw children when an unfold limit is hit could expose what its `Visibility`
69
+ * gates, so it is dropped instead.
70
+ */
71
+ export function definitionGatesContent(def, defs, seen = new Set()) {
72
+ if (seen.has(def))
73
+ return false;
74
+ seen.add(def);
75
+ const rendered = new Set();
76
+ if (scanRenderedComponents(def.body, rendered))
77
+ return true;
78
+ for (const name of rendered) {
79
+ const inner = defs.get(name);
80
+ if (inner !== undefined && definitionGatesContent(inner, defs, seen))
81
+ return true;
82
+ }
83
+ return false;
84
+ }
85
+ export function chargeUnfoldCall(ctx) {
86
+ ctx.budget.remainingCalls -= 1;
87
+ return ctx.budget.remainingCalls >= 0;
88
+ }
89
+ /** The environment holding only values that no write the evaluator cannot see can make stale. */
90
+ export function trustedEnv(ctx) {
91
+ var _a;
92
+ return (_a = ctx.trusted) !== null && _a !== void 0 ? _a : { scope: ctx.literalScope };
93
+ }
94
+ // Sentinel in the failed-props set for a spread that could not be evaluated;
95
+ // `*` is not a valid JSX attribute name, so it cannot collide with a real prop.
96
+ export const FAILED_SPREAD = '*';
97
+ export function collectMarkdownComponentContext(tree) {
98
+ const context = collectContextFromTree(tree);
99
+ const defs = new Map(getFirstPartyComponentDefs());
100
+ for (const [name, def] of context.defs)
101
+ defs.set(name, def);
102
+ return { defs, moduleScope: context.moduleScope, literalScope: context.literalScope };
103
+ }
104
+ let firstPartyDefsCache;
105
+ export function getFirstPartyComponentDefs() {
106
+ if (firstPartyDefsCache === undefined) {
107
+ const tree = getJsxEsmTree(FIRST_PARTY_MARKDOWN_COMPONENT_SOURCE, 'first-party-markdown.jsx');
108
+ firstPartyDefsCache = collectContextFromTree(tree).defs;
109
+ }
110
+ return firstPartyDefsCache;
111
+ }
112
+ export const DROP_ELEMENTS = new Set([
113
+ 'svg',
114
+ 'path',
115
+ 'g',
116
+ 'defs',
117
+ 'clipPath',
118
+ 'rect',
119
+ 'circle',
120
+ 'ellipse',
121
+ 'line',
122
+ 'polygon',
123
+ 'polyline',
124
+ 'use',
125
+ 'script',
126
+ 'style',
127
+ 'head',
128
+ 'link',
129
+ 'meta',
130
+ 'noscript',
131
+ 'template',
132
+ 'canvas',
133
+ ]);
134
+ export const UNWRAP_BLOCK_ELEMENTS = new Set([
135
+ 'div',
136
+ 'section',
137
+ 'article',
138
+ 'main',
139
+ 'aside',
140
+ 'header',
141
+ 'footer',
142
+ 'nav',
143
+ 'figure',
144
+ 'figcaption',
145
+ 'p',
146
+ ]);
147
+ export const UNWRAP_INLINE_ELEMENTS = new Set(['span', 'label', 'button', 'small', 'u', 'center']);
148
+ const MARKDOWN_INLINE_WRAPPERS = {
149
+ strong: ['**', '**'],
150
+ b: ['**', '**'],
151
+ em: ['*', '*'],
152
+ i: ['*', '*'],
153
+ code: ['`', '`'],
154
+ del: ['~~', '~~'],
155
+ s: ['~~', '~~'],
156
+ };
157
+ export const HEADING_ELEMENTS = {
158
+ h1: 1,
159
+ h2: 2,
160
+ h3: 3,
161
+ h4: 4,
162
+ h5: 5,
163
+ h6: 6,
164
+ };
165
+ /** Styling and internal hooks that mean nothing once the page is plain markdown. */
166
+ export function isPresentationalAttribute(name) {
167
+ return name === 'className' || name === 'class' || name === 'style' || name.startsWith('data-');
168
+ }
169
+ const DARK_DISPLAY_CLASSES = new Set([
170
+ 'dark:block',
171
+ 'dark:inline',
172
+ 'dark:inline-block',
173
+ 'dark:flex',
174
+ 'dark:grid',
175
+ ]);
176
+ /** Which color scheme a Tailwind class list limits an element to, if any. */
177
+ function colorSchemeOnly(className) {
178
+ if (typeof className !== 'string')
179
+ return undefined;
180
+ const classes = className.split(/\s+/);
181
+ if (classes.includes('dark:hidden'))
182
+ return 'light';
183
+ if (classes.includes('hidden') && classes.some((name) => DARK_DISPLAY_CLASSES.has(name))) {
184
+ return 'dark';
185
+ }
186
+ return undefined;
187
+ }
188
+ function isBlankChild(child) {
189
+ if (!isObject(child))
190
+ return false;
191
+ if (child.type !== 'text' && child.type !== 'JSXText')
192
+ return false;
193
+ return typeof child.value === 'string' && child.value.trim() === '';
194
+ }
195
+ /**
196
+ * Drops a dark-mode-only copy when its light-mode-only twin sits right next to it, since both
197
+ * carry the same content once their classes are gone. Each light copy pairs with one dark copy,
198
+ * and a dark-only element without an adjacent twin stays.
199
+ */
200
+ export function dropPairedDarkOnly(children, classOf) {
201
+ const schemes = children.map((child) => colorSchemeOnly(classOf(child)));
202
+ if (!schemes.includes('light') || !schemes.includes('dark'))
203
+ return [...children];
204
+ const neighbor = (from, step) => {
205
+ for (let index = from + step; index >= 0 && index < children.length; index += step) {
206
+ if (!isBlankChild(children[index]))
207
+ return index;
208
+ }
209
+ return -1;
210
+ };
211
+ const pairedLight = new Set();
212
+ const dropped = new Set();
213
+ schemes.forEach((scheme, index) => {
214
+ if (scheme !== 'dark')
215
+ return;
216
+ for (const twin of [neighbor(index, -1), neighbor(index, 1)]) {
217
+ if (twin === -1 || schemes[twin] !== 'light' || pairedLight.has(twin))
218
+ continue;
219
+ pairedLight.add(twin);
220
+ dropped.add(index);
221
+ return;
222
+ }
223
+ });
224
+ return children.filter((_, index) => !dropped.has(index));
225
+ }
226
+ export const KEEP_TAG_COMPONENTS = new Set(['Variation', 'View', 'Snippet']);
227
+ export const HEADLINE_ATTRIBUTES = ['title', 'label', 'name', 'path'];
228
+ export const GFM_ALERT_PATTERN = /^\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]/;
229
+ export function prefixBlockquoteLines(text) {
230
+ return text
231
+ .split('\n')
232
+ .map((line) => (line.trim() === '' ? '>' : `> ${line}`))
233
+ .join('\n');
234
+ }
235
+ function unfoldForeignComponent(node, ctx) {
236
+ let children = serializeJsxChildren(node.children, ctx).trim();
237
+ if (children === '') {
238
+ const childrenAttr = findStaticAttribute(node, 'children', ctx);
239
+ if (typeof childrenAttr === 'string')
240
+ children = escapeInterpolatedText(childrenAttr).trim();
241
+ else if (typeof childrenAttr === 'number')
242
+ children = String(childrenAttr);
243
+ }
244
+ const description = findStaticAttribute(node, 'description', ctx);
245
+ const alt = findStaticAttribute(node, 'alt', ctx);
246
+ const body = children !== ''
247
+ ? children
248
+ : typeof description === 'string'
249
+ ? escapeInterpolatedText(description)
250
+ : typeof alt === 'string'
251
+ ? escapeInterpolatedText(alt)
252
+ : '';
253
+ let title;
254
+ for (const attributeName of HEADLINE_ATTRIBUTES) {
255
+ const value = findStaticAttribute(node, attributeName, ctx);
256
+ if (typeof value === 'string' && value.trim() !== '') {
257
+ title = value;
258
+ break;
259
+ }
260
+ }
261
+ const href = findStaticAttribute(node, 'href', ctx);
262
+ const headline = title === undefined
263
+ ? undefined
264
+ : typeof href === 'string' && href !== ''
265
+ ? `[${escapeLinkLabel(escapeInterpolatedText(title))}](${markdownLinkDestination(href)})`
266
+ : `**${escapeInterpolatedText(title)}**`;
267
+ const parts = [headline, body].filter((part) => part !== undefined && part !== '');
268
+ if (parts.length === 0)
269
+ return accessibleFallback(node, ctx);
270
+ return `\n\n${parts.join('\n\n')}\n\n`;
271
+ }
272
+ function carriesChildren(name, ctx) {
273
+ if (name === undefined)
274
+ return false;
275
+ return (name === ctx.propsObjectName || (ctx.restCarriesChildren === true && name === ctx.restName));
276
+ }
277
+ export function escapeInterpolatedText(value) {
278
+ return value.replace(/[\\{}<>]/g, '\\$&');
279
+ }
280
+ export function markdownLinkDestination(url) {
281
+ return /[\s()]/.test(url) ? `<${url.replace(/[<>]/g, '\\$&')}>` : url;
282
+ }
283
+ function getJsxElementName(node) {
284
+ let current = isObject(node.openingElement) ? node.openingElement.name : undefined;
285
+ const parts = [];
286
+ while (isObject(current) && current.type === 'JSXMemberExpression') {
287
+ const property = current.property;
288
+ if (isObject(property) && typeof property.name === 'string')
289
+ parts.unshift(property.name);
290
+ current = current.object;
291
+ }
292
+ if (isObject(current) && current.type === 'JSXIdentifier' && typeof current.name === 'string') {
293
+ parts.unshift(current.name);
294
+ return parts.join('.');
295
+ }
296
+ return undefined;
297
+ }
298
+ function jsxAttributes(node) {
299
+ const opening = node.openingElement;
300
+ if (!isObject(opening) || !Array.isArray(opening.attributes))
301
+ return [];
302
+ return opening.attributes.filter(isObject);
303
+ }
304
+ function resolveJsxAttribute(attribute, ctx) {
305
+ const value = attribute.value;
306
+ if (value === null || value === undefined)
307
+ return { ok: true, value: true };
308
+ if (nodeType(value) === 'Literal' && isObject(value) && typeof value.value === 'string') {
309
+ return { ok: true, value: value.value };
310
+ }
311
+ if (nodeType(value) === 'JSXExpressionContainer' && isObject(value)) {
312
+ return evaluateStatic(value.expression, ctx);
313
+ }
314
+ return EVAL_FAILED;
315
+ }
316
+ function findStaticAttribute(node, name, ctx) {
317
+ const resolved = resolveEffectiveAttribute(node, name, ctx);
318
+ return resolved.ok ? resolved.value : undefined;
319
+ }
320
+ /** The effective attribute value, honoring order; a spread that may supply it makes it unknown. */
321
+ function resolveEffectiveAttribute(node, name, ctx) {
322
+ let effective = { ok: true, value: undefined };
323
+ for (const attribute of jsxAttributes(node)) {
324
+ if (attribute.type === 'JSXSpreadAttribute') {
325
+ const spreadName = identifierName(attribute.argument);
326
+ const unknownKeys = spreadName === undefined
327
+ ? undefined
328
+ : spreadName === ctx.propsObjectName
329
+ ? ctx.failedProps
330
+ : spreadName === ctx.restName
331
+ ? ctx.restFailedProps
332
+ : undefined;
333
+ // Unknown keys of a props or rest spread matter only when `name` is one of them
334
+ const spread = spreadName !== undefined && unknownKeys !== undefined && unknownKeys.size > 0
335
+ ? unknownKeys.has(name)
336
+ ? EVAL_FAILED
337
+ : { ok: true, value: ctx.scope.get(spreadName) }
338
+ : evaluateStatic(attribute.argument, ctx);
339
+ // Arrays and strings spread only indexed keys, so they cannot supply a named attribute
340
+ if (spread.ok &&
341
+ (isNoOpSpreadValue(spread.value) ||
342
+ Array.isArray(spread.value) ||
343
+ typeof spread.value === 'string')) {
344
+ continue;
345
+ }
346
+ if (!spread.ok || !isStaticObject(spread.value))
347
+ effective = EVAL_FAILED;
348
+ else if (Object.hasOwn(spread.value, name)) {
349
+ effective = { ok: true, value: spread.value[name] };
350
+ }
351
+ continue;
352
+ }
353
+ const attrName = attribute.name;
354
+ if (attribute.type === 'JSXAttribute' && isObject(attrName) && attrName.name === name) {
355
+ effective = resolveJsxAttribute(attribute, ctx);
356
+ }
357
+ }
358
+ return effective;
359
+ }
360
+ function accessibleFallback(node, ctx) {
361
+ const ariaLabel = findStaticAttribute(node, 'aria-label', ctx);
362
+ if (typeof ariaLabel === 'string' && ariaLabel.trim() !== '') {
363
+ return escapeInterpolatedText(ariaLabel);
364
+ }
365
+ const title = findStaticAttribute(node, 'title', ctx);
366
+ if (typeof title === 'string' && title.trim() !== '')
367
+ return escapeInterpolatedText(title);
368
+ return '';
369
+ }
370
+ function isAriaHidden(node, ctx) {
371
+ const value = findStaticAttribute(node, 'aria-hidden', ctx);
372
+ return value === true || value === 'true';
373
+ }
374
+ function dedentJsxText(raw) {
375
+ const lines = raw.split('\n');
376
+ if (lines.length === 1)
377
+ return raw;
378
+ let minIndent = Infinity;
379
+ for (const line of lines.slice(1)) {
380
+ if (line.trim() === '')
381
+ continue;
382
+ const match = line.match(/^[ \t]*/);
383
+ const indent = match ? match[0].length : 0;
384
+ minIndent = Math.min(minIndent, indent);
385
+ }
386
+ if (!Number.isFinite(minIndent) || minIndent === 0)
387
+ return raw;
388
+ return [lines[0], ...lines.slice(1).map((line) => line.slice(minIndent))].join('\n');
389
+ }
390
+ // Code spans and generated image markup keep their own brackets
391
+ const PROTECTED_LABEL_PATTERN = /(`+)[\s\S]*?\1|!\[(?:\\.|[^\]\\])*\]\((?:\\.|[^)\\])*\)/g;
392
+ function escapeBrackets(text) {
393
+ return text.replace(/(?<!\\)[[\]]/g, '\\$&');
394
+ }
395
+ /** Escapes brackets outside code spans and images, so a label cannot end its link early. */
396
+ export function escapeLinkLabel(text) {
397
+ var _a;
398
+ let result = '';
399
+ let lastIndex = 0;
400
+ for (const match of text.matchAll(PROTECTED_LABEL_PATTERN)) {
401
+ const index = (_a = match.index) !== null && _a !== void 0 ? _a : 0;
402
+ result += escapeBrackets(text.slice(lastIndex, index)) + match[0];
403
+ lastIndex = index + match[0].length;
404
+ }
405
+ return result + escapeBrackets(text.slice(lastIndex));
406
+ }
407
+ // A markdown link label can hold only inline content, so blank lines or headings need another shape
408
+ const BLOCK_CONTENT_PATTERN = /\n[ \t]*\n|^#{1,6}[ \t]/m;
409
+ const HEADING_LINE_PATTERN = /^(#{1,6})[ \t]+(.+?)[ \t]*$/;
410
+ const FENCE_PATTERN = /^ {0,3}(`{3,}|~{3,})(.*)$/;
411
+ /** The first ATX heading line outside fenced code, where `#` lines are comments, not headings. */
412
+ function firstHeadingLine(content) {
413
+ var _a, _b, _c, _d, _e;
414
+ let fence;
415
+ let offset = 0;
416
+ for (const line of content.split('\n')) {
417
+ const lineStart = offset;
418
+ offset += line.length + 1;
419
+ const fenceMatch = FENCE_PATTERN.exec(line);
420
+ if (fenceMatch !== null) {
421
+ const token = (_a = fenceMatch[1]) !== null && _a !== void 0 ? _a : '';
422
+ const marker = (_b = token[0]) !== null && _b !== void 0 ? _b : '`';
423
+ if (fence === undefined)
424
+ fence = { marker, length: token.length };
425
+ else if (marker === fence.marker &&
426
+ token.length >= fence.length &&
427
+ ((_c = fenceMatch[2]) !== null && _c !== void 0 ? _c : '').trim() === '') {
428
+ fence = undefined;
429
+ }
430
+ continue;
431
+ }
432
+ if (fence !== undefined)
433
+ continue;
434
+ const heading = HEADING_LINE_PATTERN.exec(line);
435
+ if (heading !== null) {
436
+ return { index: lineStart, line, hashes: (_d = heading[1]) !== null && _d !== void 0 ? _d : '#', title: (_e = heading[2]) !== null && _e !== void 0 ? _e : '' };
437
+ }
438
+ }
439
+ return undefined;
440
+ }
441
+ /** Links the first heading of block content, or follows the content with a link line. */
442
+ function linkBlockContent(content, href, node, ctx) {
443
+ const destination = markdownLinkDestination(href);
444
+ const heading = firstHeadingLine(content);
445
+ if (heading) {
446
+ const linked = `${heading.hashes} [${escapeLinkLabel(heading.title)}](${destination})`;
447
+ const before = content.slice(0, heading.index);
448
+ const after = content.slice(heading.index + heading.line.length);
449
+ return `\n\n${before}${linked}${after}\n\n`;
450
+ }
451
+ const fallback = accessibleFallback(node, ctx);
452
+ const label = fallback === '' ? BLOCK_LINK_LABEL : fallback;
453
+ return `\n\n${content}\n\n[${escapeLinkLabel(label)}](${destination})\n\n`;
454
+ }
455
+ /** A code span whose fence is longer than any backtick run inside it. */
456
+ function codeSpan(text) {
457
+ var _a;
458
+ const longestRun = ((_a = text.match(/`+/g)) !== null && _a !== void 0 ? _a : []).reduce((max, run) => Math.max(max, run.length), 0);
459
+ const fence = '`'.repeat(longestRun + 1);
460
+ const padding = text.startsWith('`') || text.endsWith('`') ? ' ' : '';
461
+ return `${fence}${padding}${text}${padding}${fence}`;
462
+ }
463
+ function escapeAttributeValue(value) {
464
+ return value.replace(/&/g, '&amp;').replace(/"/g, '&quot;');
465
+ }
466
+ function serializeExpressionSource(expression) {
467
+ if (!isObject(expression))
468
+ return undefined;
469
+ try {
470
+ const program = {
471
+ type: 'Program',
472
+ sourceType: 'module',
473
+ body: [{ type: 'ExpressionStatement', expression }],
474
+ };
475
+ const source = toJs(program, { handlers: jsx }).value.trim();
476
+ return source.endsWith(';') ? source.slice(0, -1) : source;
477
+ }
478
+ catch (_a) {
479
+ return undefined;
480
+ }
481
+ }
482
+ function renderAttribute(name, value) {
483
+ if (value === true)
484
+ return ` ${name}`;
485
+ if (typeof value === 'string')
486
+ return ` ${name}="${escapeAttributeValue(value)}"`;
487
+ if (value === false || value === null || value === undefined)
488
+ return '';
489
+ return ` ${name}={${serializeStaticValue(value)}}`;
490
+ }
491
+ const ATTRIBUTE_NAME_PATTERN = /^[A-Za-z_$][\w$:.-]*$/;
492
+ /** The keys a spread supplies; props and rest objects supply their known keys. */
493
+ function spreadAttributes(attribute, ctx) {
494
+ var _a, _b;
495
+ const spreadName = identifierName(attribute.argument);
496
+ const unknownKeys = spreadName === undefined
497
+ ? undefined
498
+ : spreadName === ctx.propsObjectName
499
+ ? ((_a = ctx.failedProps) !== null && _a !== void 0 ? _a : new Set())
500
+ : spreadName === ctx.restName
501
+ ? ((_b = ctx.restFailedProps) !== null && _b !== void 0 ? _b : new Set())
502
+ : undefined;
503
+ const spread = spreadName !== undefined && unknownKeys !== undefined
504
+ ? { ok: true, value: ctx.scope.get(spreadName) }
505
+ : evaluateStatic(attribute.argument, ctx);
506
+ // Arrays and strings spread only indexed keys, which are not attribute names
507
+ if (spread.ok &&
508
+ (isNoOpSpreadValue(spread.value) ||
509
+ Array.isArray(spread.value) ||
510
+ typeof spread.value === 'string')) {
511
+ return { known: [], unknown: new Set() };
512
+ }
513
+ if (!spread.ok || !isStaticObject(spread.value))
514
+ return { known: [], unknown: 'all' };
515
+ const known = Object.entries(spread.value).filter(([key]) => key !== 'children' && ATTRIBUTE_NAME_PATTERN.test(key));
516
+ return { known, unknown: unknownKeys !== null && unknownKeys !== void 0 ? unknownKeys : new Set() };
517
+ }
518
+ function regenerateTag(node, name, children, ctx) {
519
+ const attrs = new Map();
520
+ const isIntrinsic = /^[a-z]/.test(name);
521
+ const setAttribute = (attrName, rendered) => {
522
+ attrs.delete(attrName);
523
+ if (isIntrinsic && isPresentationalAttribute(attrName))
524
+ return;
525
+ attrs.set(attrName, rendered);
526
+ };
527
+ for (const attribute of jsxAttributes(node)) {
528
+ if (attribute.type === 'JSXSpreadAttribute') {
529
+ // A spread may override earlier attributes with values that are not known
530
+ const { known, unknown } = spreadAttributes(attribute, ctx);
531
+ if (unknown === 'all')
532
+ attrs.clear();
533
+ else
534
+ for (const key of unknown)
535
+ attrs.delete(key);
536
+ for (const [key, value] of known)
537
+ setAttribute(key, renderAttribute(key, value));
538
+ continue;
539
+ }
540
+ if (attribute.type !== 'JSXAttribute')
541
+ continue;
542
+ const attrName = attribute.name;
543
+ if (!isObject(attrName) || typeof attrName.name !== 'string')
544
+ continue;
545
+ const resolved = resolveJsxAttribute(attribute, ctx);
546
+ if (resolved.ok) {
547
+ setAttribute(attrName.name, renderAttribute(attrName.name, resolved.value));
548
+ continue;
549
+ }
550
+ const value = attribute.value;
551
+ const source = nodeType(value) === 'JSXExpressionContainer' && isObject(value)
552
+ ? serializeExpressionSource(value.expression)
553
+ : undefined;
554
+ setAttribute(attrName.name, source === undefined ? '' : ` ${attrName.name}={${source}}`);
555
+ }
556
+ const rendered = [...attrs.values()].join('');
557
+ if (children.trim() === '')
558
+ return `<${name}${rendered} />`;
559
+ // MDX only parses multi-paragraph content inside a tag when the tags stand on their own lines
560
+ if (children.includes('\n\n')) {
561
+ return `\n\n<${name}${rendered}>\n\n${children}\n\n</${name}>\n\n`;
562
+ }
563
+ return `<${name}${rendered}>${children}</${name}>`;
564
+ }
565
+ function serializeJsxChildren(children, ctx) {
566
+ if (!Array.isArray(children))
567
+ return '';
568
+ let result = '';
569
+ for (const child of dropPairedDarkOnly(children, (node) => jsxClassName(node, ctx))) {
570
+ result += serializeJsxNode(child, ctx);
571
+ }
572
+ return result;
573
+ }
574
+ function jsxClassName(node, ctx) {
575
+ var _a;
576
+ if (!isObject(node) || node.type !== 'JSXElement')
577
+ return undefined;
578
+ return (_a = findStaticAttribute(node, 'className', ctx)) !== null && _a !== void 0 ? _a : findStaticAttribute(node, 'class', ctx);
579
+ }
580
+ function serializeJsxNode(node, ctx) {
581
+ if (!isObject(node))
582
+ return '';
583
+ switch (node.type) {
584
+ case 'JSXText':
585
+ return typeof node.value === 'string' ? dedentJsxText(node.value) : '';
586
+ case 'JSXFragment':
587
+ return serializeJsxChildren(node.children, ctx);
588
+ case 'JSXExpressionContainer':
589
+ return serializeJsxExpression(node.expression, ctx);
590
+ case 'JSXElement':
591
+ return serializeJsxElement(node, ctx);
592
+ default:
593
+ return '';
594
+ }
595
+ }
596
+ function serializeJsxExpression(expression, ctx) {
597
+ if (!isObject(expression))
598
+ return '';
599
+ if (expression.type === 'JSXEmptyExpression')
600
+ return '';
601
+ if (expression.type === 'Identifier' &&
602
+ typeof expression.name === 'string' &&
603
+ expression.name === ctx.childrenName &&
604
+ ctx.childrenMarkdown !== '') {
605
+ return ctx.childrenMarkdown;
606
+ }
607
+ if (expression.type === 'MemberExpression' &&
608
+ expression.computed !== true &&
609
+ carriesChildren(identifierName(expression.object), ctx) &&
610
+ identifierName(expression.property) === 'children' &&
611
+ ctx.childrenMarkdown !== '') {
612
+ return ctx.childrenMarkdown;
613
+ }
614
+ if (expression.type === 'JSXElement' || expression.type === 'JSXFragment') {
615
+ return serializeJsxNode(expression, ctx);
616
+ }
617
+ if (expression.type === 'ConditionalExpression') {
618
+ const test = evaluateStatic(expression.test, ctx);
619
+ if (test.ok) {
620
+ const branch = test.value ? expression.consequent : expression.alternate;
621
+ return serializeJsxExpression(branch, ctx);
622
+ }
623
+ }
624
+ if (expression.type === 'LogicalExpression' && expression.operator === '&&') {
625
+ const test = evaluateStatic(expression.left, ctx);
626
+ if (test.ok) {
627
+ return test.value ? serializeJsxExpression(expression.right, ctx) : '';
628
+ }
629
+ }
630
+ if (expression.type === 'LogicalExpression' &&
631
+ (expression.operator === '||' || expression.operator === '??')) {
632
+ const left = evaluateStatic(expression.left, ctx);
633
+ if (left.ok) {
634
+ const takeLeft = expression.operator === '||'
635
+ ? Boolean(left.value)
636
+ : left.value !== null && left.value !== undefined;
637
+ return takeLeft
638
+ ? serializeJsxExpression(expression.left, ctx)
639
+ : serializeJsxExpression(expression.right, ctx);
640
+ }
641
+ }
642
+ const evaluated = evaluateStatic(expression, ctx);
643
+ if (evaluated.ok) {
644
+ const value = evaluated.value;
645
+ if (value === null || value === undefined || value === false || value === true)
646
+ return '';
647
+ if (typeof value === 'object')
648
+ return '';
649
+ const text = String(value);
650
+ return ctx.verbatim === true ? text : escapeInterpolatedText(text);
651
+ }
652
+ return '';
653
+ }
654
+ function serializeJsxElement(node, ctx) {
655
+ const name = getJsxElementName(node);
656
+ if (name === undefined)
657
+ return '';
658
+ if (isAriaHidden(node, ctx))
659
+ return '';
660
+ if (name === 'Visibility') {
661
+ const audience = visibilityAudience(node, ctx);
662
+ if (isAgentAudience(audience))
663
+ return serializeJsxChildren(node.children, ctx);
664
+ if (typeof audience === 'string' && !isVisibilityAudience(audience)) {
665
+ console.warn(`<Visibility for="${audience}"> has an unknown audience — expected ${VISIBILITY_FOR_EXPECTED}. The content was removed from the markdown output.`);
666
+ }
667
+ return '';
668
+ }
669
+ const isIntrinsic = /^[a-z]/.test(name);
670
+ if (isIntrinsic) {
671
+ if (DROP_ELEMENTS.has(name))
672
+ return accessibleFallback(node, ctx);
673
+ if (name === 'br')
674
+ return '\n';
675
+ if (name === 'hr')
676
+ return '\n\n---\n\n';
677
+ if (name === 'blockquote') {
678
+ const content = serializeJsxChildren(node.children, ctx).trim();
679
+ if (content === '')
680
+ return accessibleFallback(node, ctx);
681
+ return `\n\n${prefixBlockquoteLines(content)}\n\n`;
682
+ }
683
+ const headingDepth = HEADING_ELEMENTS[name];
684
+ if (headingDepth !== undefined) {
685
+ const text = serializeJsxChildren(node.children, ctx).trim();
686
+ return text === '' ? '' : `\n\n${'#'.repeat(headingDepth)} ${text}\n\n`;
687
+ }
688
+ const inlineWrapper = MARKDOWN_INLINE_WRAPPERS[name];
689
+ if (inlineWrapper !== undefined) {
690
+ const innerCtx = name === 'code' ? Object.assign(Object.assign({}, ctx), { verbatim: true }) : ctx;
691
+ const text = serializeJsxChildren(node.children, innerCtx).trim();
692
+ if (text === '')
693
+ return '';
694
+ return name === 'code' ? codeSpan(text) : `${inlineWrapper[0]}${text}${inlineWrapper[1]}`;
695
+ }
696
+ if (name === 'a') {
697
+ const text = serializeJsxChildren(node.children, ctx).trim();
698
+ const href = findStaticAttribute(node, 'href', ctx);
699
+ const label = text !== '' ? text : accessibleFallback(node, ctx);
700
+ if (typeof href === 'string' && href !== '') {
701
+ const destination = markdownLinkDestination(href);
702
+ if (BLOCK_CONTENT_PATTERN.test(text))
703
+ return linkBlockContent(text, href, node, ctx);
704
+ return label === ''
705
+ ? `[${escapeLinkLabel(escapeInterpolatedText(href))}](${destination})`
706
+ : `[${escapeLinkLabel(label)}](${destination})`;
707
+ }
708
+ return label;
709
+ }
710
+ if (name === 'img') {
711
+ const src = findStaticAttribute(node, 'src', ctx);
712
+ const alt = findStaticAttribute(node, 'alt', ctx);
713
+ const escapedAlt = typeof alt === 'string' ? escapeInterpolatedText(alt) : '';
714
+ if (typeof src === 'string' && src !== '') {
715
+ return `![${escapeLinkLabel(escapedAlt)}](${markdownLinkDestination(src)})`;
716
+ }
717
+ return escapedAlt;
718
+ }
719
+ if (name === 'iframe' || name === 'embed') {
720
+ const src = findStaticAttribute(node, 'src', ctx);
721
+ const label = accessibleFallback(node, ctx);
722
+ if (typeof src === 'string' && src !== '') {
723
+ return `\n\n[${escapeLinkLabel(label === '' ? escapeInterpolatedText(src) : label)}](${markdownLinkDestination(src)})\n\n`;
724
+ }
725
+ return label === '' ? '' : `\n\n${label}\n\n`;
726
+ }
727
+ if (UNWRAP_BLOCK_ELEMENTS.has(name)) {
728
+ const content = serializeJsxChildren(node.children, ctx);
729
+ if (content.trim() === '') {
730
+ const fallback = accessibleFallback(node, ctx);
731
+ return fallback === '' ? '' : `\n\n${fallback}\n\n`;
732
+ }
733
+ return `\n\n${content.trim()}\n\n`;
734
+ }
735
+ if (UNWRAP_INLINE_ELEMENTS.has(name)) {
736
+ const content = serializeJsxChildren(node.children, ctx);
737
+ return content.trim() === '' ? accessibleFallback(node, ctx) : content;
738
+ }
739
+ const children = serializeJsxChildren(node.children, ctx);
740
+ return regenerateTag(node, name, children.trim(), ctx);
741
+ }
742
+ if (KEEP_TAG_COMPONENTS.has(name)) {
743
+ const children = serializeJsxChildren(node.children, ctx);
744
+ return regenerateTag(node, name, children.trim(), ctx);
745
+ }
746
+ return serializeComponentElement(name === 'Steps' ? withStepDefaults(node, ctx) : node, name, ctx);
747
+ }
748
+ function visibilityAudience(node, ctx) {
749
+ const resolved = resolveEffectiveAttribute(node, 'for', ctx);
750
+ if (!resolved.ok)
751
+ return undefined;
752
+ // An audience that shows content to agents must resolve the same from literal values alone,
753
+ // since an object it was read from may have been changed by a write the evaluator cannot see
754
+ if (isAgentAudience(resolved.value)) {
755
+ const trusted = resolveEffectiveAttribute(node, 'for', Object.assign(Object.assign({}, ctx), trustedEnv(ctx)));
756
+ if (!trusted.ok || trusted.value !== resolved.value)
757
+ return undefined;
758
+ }
759
+ return resolved.value;
760
+ }
761
+ function isAgentAudience(audience) {
762
+ return audience === 'agents' || audience === 'signed-out';
763
+ }
764
+ /** `Steps` numbers its `Step` children and passes its `titleSize` down; a Step's own props win. */
765
+ function withStepDefaults(node, ctx) {
766
+ if (!Array.isArray(node.children))
767
+ return node;
768
+ const titleSize = findStaticAttribute(node, 'titleSize', ctx);
769
+ let index = 0;
770
+ // Steps flattens fragments before numbering, so a Step inside `<>…</>` keeps counting
771
+ const number = (child) => {
772
+ if (isObject(child) && child.type === 'JSXFragment' && Array.isArray(child.children)) {
773
+ return Object.assign(Object.assign({}, child), { children: child.children.map(number) });
774
+ }
775
+ // A Visibility agents can see is unwrapped, so its Steps keep counting
776
+ if (isObject(child) &&
777
+ child.type === 'JSXElement' &&
778
+ getJsxElementName(child) === 'Visibility' &&
779
+ Array.isArray(child.children) &&
780
+ isAgentAudience(visibilityAudience(child, ctx))) {
781
+ return Object.assign(Object.assign({}, child), { children: child.children.map(number) });
782
+ }
783
+ if (!isObject(child) || child.type !== 'JSXElement' || getJsxElementName(child) !== 'Step') {
784
+ return child;
785
+ }
786
+ const opening = child.openingElement;
787
+ if (!isObject(opening))
788
+ return child;
789
+ index += 1;
790
+ const defaults = [stringJsxAttribute('stepNumber', String(index))];
791
+ if (typeof titleSize === 'string')
792
+ defaults.push(stringJsxAttribute('titleSize', titleSize));
793
+ const attributes = Array.isArray(opening.attributes) ? opening.attributes : [];
794
+ return Object.assign(Object.assign({}, child), { openingElement: Object.assign(Object.assign({}, opening), { attributes: [...defaults, ...attributes] }) });
795
+ };
796
+ return Object.assign(Object.assign({}, node), { children: node.children.map(number) });
797
+ }
798
+ function stringJsxAttribute(name, value) {
799
+ return {
800
+ type: 'JSXAttribute',
801
+ name: { type: 'JSXIdentifier', name },
802
+ value: { type: 'Literal', value },
803
+ };
804
+ }
805
+ function serializeComponentElement(node, name, ctx) {
806
+ const def = ctx.defs.get(name);
807
+ if (def) {
808
+ const withinLimits = !ctx.stack.includes(def) && ctx.stack.length < MAX_UNFOLD_DEPTH && chargeUnfoldCall(ctx);
809
+ if (!withinLimits && definitionGatesContent(def, ctx.defs))
810
+ return '';
811
+ if (withinLimits) {
812
+ const failedProps = new Set();
813
+ const props = collectStaticProps(node, ctx, failedProps);
814
+ let childrenMarkdown = serializeJsxChildren(node.children, ctx).trim();
815
+ let bodyValue;
816
+ // Body children replace any children attribute or spread, even when they render nothing
817
+ if (hasJsxBodyChildren(node)) {
818
+ props.delete('children');
819
+ failedProps.delete('children');
820
+ bodyValue = jsxBodyValue(node, ctx);
821
+ }
822
+ else if (lastChildrenSource(node, ctx) === 'propsSpread') {
823
+ childrenMarkdown = ctx.childrenMarkdown;
824
+ props.delete('children');
825
+ }
826
+ const trustedFailed = new Set();
827
+ const trustedProps = collectStaticProps(node, Object.assign(Object.assign({}, ctx), trustedEnv(ctx)), trustedFailed);
828
+ const markdown = materializeComponent(def, name, props, childrenMarkdown, ctx, failedProps, bodyValue, { props: trustedProps, failedProps: trustedFailed });
829
+ if (markdown !== undefined) {
830
+ if (chargeUnfoldBudget(ctx, markdown.length))
831
+ return markdown;
832
+ return definitionGatesContent(def, ctx.defs) ? '' : childrenMarkdown;
833
+ }
834
+ if (definitionGatesContent(def, ctx.defs))
835
+ return '';
836
+ }
837
+ }
838
+ return unfoldForeignComponent(node, ctx);
839
+ }
840
+ function setKnownProp(props, failed, name, value) {
841
+ props.set(name, value);
842
+ if (name !== FAILED_SPREAD)
843
+ failed === null || failed === void 0 ? void 0 : failed.delete(name);
844
+ }
845
+ function setFailedProp(props, failed, name) {
846
+ props.delete(name);
847
+ failed === null || failed === void 0 ? void 0 : failed.add(name);
848
+ }
849
+ /**
850
+ * JSX drops whitespace-only text that spans lines and empty `{}` or `{/* comment *\/}`
851
+ * containers, so only other children count as a body.
852
+ */
853
+ function isJsxBodyChild(child) {
854
+ if (!isObject(child))
855
+ return true;
856
+ if (child.type === 'JSXText') {
857
+ return !(typeof child.value === 'string' &&
858
+ child.value.trim() === '' &&
859
+ child.value.includes('\n'));
860
+ }
861
+ if (child.type === 'JSXExpressionContainer') {
862
+ return nodeType(child.expression) !== 'JSXEmptyExpression';
863
+ }
864
+ return true;
865
+ }
866
+ function hasJsxBodyChildren(node) {
867
+ return Array.isArray(node.children) && node.children.some(isJsxBodyChild);
868
+ }
869
+ /**
870
+ * When the body is one static expression, such as `<Check>{0}</Check>`, `children` is that value
871
+ * rather than its markdown text, so `children ? … : …` takes the branch React would.
872
+ */
873
+ function jsxBodyValue(node, ctx) {
874
+ if (!Array.isArray(node.children))
875
+ return undefined;
876
+ const body = node.children.filter(isJsxBodyChild);
877
+ const only = body.length === 1 ? body[0] : undefined;
878
+ if (!isObject(only) || only.type !== 'JSXExpressionContainer')
879
+ return undefined;
880
+ const evaluated = evaluateStatic(only.expression, ctx);
881
+ if (!evaluated.ok || (typeof evaluated.value === 'object' && evaluated.value !== null)) {
882
+ return undefined;
883
+ }
884
+ return { value: evaluated.value };
885
+ }
886
+ function lastChildrenSource(node, ctx) {
887
+ let source;
888
+ for (const attribute of jsxAttributes(node)) {
889
+ if (attribute.type === 'JSXSpreadAttribute' &&
890
+ carriesChildren(identifierName(attribute.argument), ctx)) {
891
+ source = 'propsSpread';
892
+ continue;
893
+ }
894
+ if (attribute.type === 'JSXAttribute') {
895
+ const attrName = attribute.name;
896
+ if (isObject(attrName) && attrName.name === 'children')
897
+ source = 'attribute';
898
+ }
899
+ }
900
+ return source;
901
+ }
902
+ function collectStaticProps(node, ctx, failed) {
903
+ const props = new Map();
904
+ for (const attribute of jsxAttributes(node)) {
905
+ if (attribute.type === 'JSXSpreadAttribute') {
906
+ const spread = evaluateStatic(attribute.argument, ctx);
907
+ if (spread.ok && isStaticObject(spread.value)) {
908
+ for (const [key, value] of Object.entries(spread.value)) {
909
+ setKnownProp(props, failed, key, value);
910
+ }
911
+ }
912
+ else if (!spread.ok || !isNoOpSpreadValue(spread.value)) {
913
+ failed === null || failed === void 0 ? void 0 : failed.add(FAILED_SPREAD);
914
+ }
915
+ continue;
916
+ }
917
+ if (attribute.type !== 'JSXAttribute')
918
+ continue;
919
+ const attrName = attribute.name;
920
+ if (!isObject(attrName) || typeof attrName.name !== 'string')
921
+ continue;
922
+ const resolved = resolveJsxAttribute(attribute, ctx);
923
+ if (resolved.ok)
924
+ setKnownProp(props, failed, attrName.name, resolved.value);
925
+ else
926
+ setFailedProp(props, failed, attrName.name);
927
+ }
928
+ return props;
929
+ }
930
+ function isDestructuringPattern(node) {
931
+ const type = nodeType(node);
932
+ return type === 'ObjectPattern' || type === 'ArrayPattern';
933
+ }
934
+ /** A destructured key known without evaluation: identifiers and string or number literals. */
935
+ function staticPropertyKey(property) {
936
+ const key = property.key;
937
+ if (property.computed !== true) {
938
+ const name = identifierName(key);
939
+ if (name !== undefined)
940
+ return name;
941
+ }
942
+ if (nodeType(key) !== 'Literal' || !isObject(key))
943
+ return undefined;
944
+ return typeof key.value === 'string' || typeof key.value === 'number'
945
+ ? String(key.value)
946
+ : undefined;
947
+ }
948
+ function analyzeParams(params) {
949
+ var _a;
950
+ const bindings = [];
951
+ const unknownNames = new Set();
952
+ let childrenName = 'children';
953
+ let propsObjectName;
954
+ const [param] = params;
955
+ const first = nodeType(param) === 'AssignmentPattern' && isObject(param) ? param.left : param;
956
+ const firstName = identifierName(first);
957
+ if (firstName !== undefined)
958
+ propsObjectName = firstName;
959
+ let restName;
960
+ if (nodeType(first) === 'ObjectPattern' && isObject(first) && Array.isArray(first.properties)) {
961
+ for (const property of first.properties) {
962
+ if (nodeType(property) === 'RestElement' && isObject(property)) {
963
+ restName = identifierName(property.argument);
964
+ continue;
965
+ }
966
+ if (nodeType(property) !== 'Property' || !isObject(property))
967
+ continue;
968
+ const propName = staticPropertyKey(property);
969
+ if (propName === undefined) {
970
+ collectPatternNames(property.value, unknownNames);
971
+ continue;
972
+ }
973
+ const value = property.value;
974
+ let localName = propName;
975
+ let defaultExpression;
976
+ let pattern;
977
+ if (nodeType(value) === 'AssignmentPattern' && isObject(value)) {
978
+ const leftName = identifierName(value.left);
979
+ if (leftName === undefined && isDestructuringPattern(value.left)) {
980
+ pattern = value;
981
+ }
982
+ else {
983
+ localName = leftName !== null && leftName !== void 0 ? leftName : propName;
984
+ defaultExpression = value.right;
985
+ }
986
+ }
987
+ else if (isDestructuringPattern(value)) {
988
+ pattern = value;
989
+ }
990
+ else {
991
+ localName = (_a = identifierName(value)) !== null && _a !== void 0 ? _a : propName;
992
+ }
993
+ bindings.push({ propName, localName, defaultExpression, pattern });
994
+ if (propName === 'children')
995
+ childrenName = localName;
996
+ }
997
+ }
998
+ return { bindings, childrenName, propsObjectName, restName, unknownNames };
999
+ }
1000
+ function bindDeclarator(declarator, env) {
1001
+ if (nodeType(declarator) !== 'VariableDeclarator' || !isObject(declarator))
1002
+ return;
1003
+ const evaluated = evaluateStatic(declarator.init, env);
1004
+ if (evaluated.ok)
1005
+ bindPattern(declarator.id, evaluated.value, env);
1006
+ else
1007
+ unbindPattern(declarator.id, env);
1008
+ }
1009
+ function blockScopedNames(statements) {
1010
+ const names = new Set();
1011
+ for (const statement of statements) {
1012
+ if (nodeType(statement) !== 'VariableDeclaration' || !isObject(statement))
1013
+ continue;
1014
+ if (statement.kind === 'var' || !Array.isArray(statement.declarations))
1015
+ continue;
1016
+ for (const declarator of statement.declarations) {
1017
+ if (isObject(declarator))
1018
+ collectPatternNames(declarator.id, names);
1019
+ }
1020
+ }
1021
+ return names;
1022
+ }
1023
+ /** Function and class declarations, which bind their names for the whole block, not as reached. */
1024
+ function declaredFunctionNames(statements) {
1025
+ const names = new Set();
1026
+ for (const statement of statements) {
1027
+ const type = nodeType(statement);
1028
+ if (type !== 'FunctionDeclaration' && type !== 'ClassDeclaration')
1029
+ continue;
1030
+ const name = isObject(statement) ? identifierName(statement.id) : undefined;
1031
+ if (name !== undefined)
1032
+ names.add(name);
1033
+ }
1034
+ return names;
1035
+ }
1036
+ const NESTED_FUNCTION_TYPES = new Set([
1037
+ 'ArrowFunctionExpression',
1038
+ 'FunctionExpression',
1039
+ 'FunctionDeclaration',
1040
+ ]);
1041
+ /** `var` names anywhere in a body outside nested functions, which hoist to the whole function. */
1042
+ function hoistedVarNames(node, names = new Set()) {
1043
+ if (Array.isArray(node)) {
1044
+ for (const child of node)
1045
+ hoistedVarNames(child, names);
1046
+ return names;
1047
+ }
1048
+ if (!isObject(node) || typeof node.type !== 'string')
1049
+ return names;
1050
+ if (NESTED_FUNCTION_TYPES.has(node.type) || node.type === 'ClassBody')
1051
+ return names;
1052
+ if (node.type === 'VariableDeclaration' && node.kind === 'var') {
1053
+ const declarations = Array.isArray(node.declarations) ? node.declarations : [];
1054
+ for (const declarator of declarations) {
1055
+ if (isObject(declarator))
1056
+ collectPatternNames(declarator.id, names);
1057
+ }
1058
+ }
1059
+ forEachCodeChild(node, (child) => hoistedVarNames(child, names));
1060
+ return names;
1061
+ }
1062
+ function findReturnInBlock(block, env) {
1063
+ const statements = Array.isArray(block.body) ? block.body : [];
1064
+ const shadowed = new Map();
1065
+ // Block declarations shadow outer bindings from the start of the block: `let` and `const` are
1066
+ // in their temporal dead zone until reached, and functions and classes are bound throughout
1067
+ const localNames = new Set([
1068
+ ...blockScopedNames(statements),
1069
+ ...declaredFunctionNames(statements),
1070
+ ]);
1071
+ for (const name of localNames) {
1072
+ shadowed.set(name, env.scope.has(name) ? { value: env.scope.get(name) } : undefined);
1073
+ }
1074
+ for (const name of localNames)
1075
+ env.scope.delete(name);
1076
+ const nested = findReturnInStatements(statements, env);
1077
+ if (nested !== undefined)
1078
+ return nested;
1079
+ for (const [name, previous] of shadowed) {
1080
+ if (previous === undefined)
1081
+ env.scope.delete(name);
1082
+ else
1083
+ env.scope.set(name, previous.value);
1084
+ }
1085
+ return undefined;
1086
+ }
1087
+ const UNRESOLVED_RETURN = Symbol('unresolved-return');
1088
+ const STRAIGHT_LINE_STATEMENTS = new Set([
1089
+ 'ExpressionStatement',
1090
+ 'EmptyStatement',
1091
+ 'FunctionDeclaration',
1092
+ 'ClassDeclaration',
1093
+ 'DebuggerStatement',
1094
+ ]);
1095
+ function findReturnExpression(body, env) {
1096
+ var _a;
1097
+ const type = nodeType(body);
1098
+ if (type === 'ReturnStatement' && isObject(body))
1099
+ return (_a = body.argument) !== null && _a !== void 0 ? _a : null;
1100
+ if (type === 'IfStatement')
1101
+ return findReturnInStatements([body], env);
1102
+ if (type !== undefined && type !== 'BlockStatement')
1103
+ return body;
1104
+ if (!isObject(body) || !Array.isArray(body.body))
1105
+ return undefined;
1106
+ // Every local declaration shadows a page binding of the same name from the start of the body:
1107
+ // `var` hoists, `let` and `const` are in their temporal dead zone, and functions and classes are
1108
+ // bound throughout. Each is rebound as its declaration is reached.
1109
+ const localNames = [
1110
+ ...declaredFunctionNames(body.body),
1111
+ ...blockScopedNames(body.body),
1112
+ ...hoistedVarNames(body.body),
1113
+ ];
1114
+ for (const name of localNames)
1115
+ env.scope.delete(name);
1116
+ return findReturnInStatements(body.body, env);
1117
+ }
1118
+ /** Anything a statement assigns or writes through, even inside callbacks, is no longer known. */
1119
+ function unbindWrites(statement, env) {
1120
+ const { reassigned, mutated } = collectModuleWrites(statement);
1121
+ for (const name of reassigned)
1122
+ env.scope.delete(name);
1123
+ for (const name of mutated)
1124
+ env.scope.delete(name);
1125
+ }
1126
+ function findReturnInStatements(statements, env) {
1127
+ var _a, _b;
1128
+ for (const statement of statements) {
1129
+ if (nodeType(statement) === 'VariableDeclaration' && isObject(statement)) {
1130
+ const declarations = Array.isArray(statement.declarations) ? statement.declarations : [];
1131
+ for (const declarator of declarations)
1132
+ bindDeclarator(declarator, env);
1133
+ unbindWrites(statement, env);
1134
+ continue;
1135
+ }
1136
+ if (nodeType(statement) === 'ReturnStatement' && isObject(statement)) {
1137
+ return (_a = statement.argument) !== null && _a !== void 0 ? _a : null;
1138
+ }
1139
+ if (nodeType(statement) === 'IfStatement' && isObject(statement)) {
1140
+ const test = evaluateStatic(statement.test, env);
1141
+ if (!test.ok)
1142
+ return UNRESOLVED_RETURN;
1143
+ const branch = test.value ? statement.consequent : statement.alternate;
1144
+ if (branch === undefined || branch === null)
1145
+ continue;
1146
+ const nested = nodeType(branch) === 'BlockStatement' && isObject(branch)
1147
+ ? findReturnInBlock(branch, env)
1148
+ : findReturnInStatements([branch], env);
1149
+ if (nested === UNRESOLVED_RETURN)
1150
+ return UNRESOLVED_RETURN;
1151
+ if (nested !== undefined)
1152
+ return nested;
1153
+ continue;
1154
+ }
1155
+ if (nodeType(statement) === 'BlockStatement' && isObject(statement)) {
1156
+ const nested = findReturnInBlock(statement, env);
1157
+ if (nested === UNRESOLVED_RETURN)
1158
+ return UNRESOLVED_RETURN;
1159
+ if (nested !== undefined)
1160
+ return nested;
1161
+ continue;
1162
+ }
1163
+ if (!STRAIGHT_LINE_STATEMENTS.has((_b = nodeType(statement)) !== null && _b !== void 0 ? _b : ''))
1164
+ return UNRESOLVED_RETURN;
1165
+ unbindWrites(statement, env);
1166
+ }
1167
+ return undefined;
1168
+ }
1169
+ function isResolvedReturn(expression, env) {
1170
+ const type = nodeType(expression);
1171
+ if (type === 'ConditionalExpression' && isObject(expression)) {
1172
+ return evaluateStatic(expression.test, env).ok;
1173
+ }
1174
+ if (type === 'LogicalExpression' && isObject(expression)) {
1175
+ return evaluateStatic(expression.left, env).ok;
1176
+ }
1177
+ return true;
1178
+ }
1179
+ /** A definition's scope for one usage: `base` plus its parameters bound from `props`. */
1180
+ function bindComponentScope(paramInfo, base, props, failedProps, childrenMarkdown, effectiveChildren) {
1181
+ const scope = new Map(base);
1182
+ if (paramInfo.propsObjectName !== undefined) {
1183
+ const propsObject = {};
1184
+ for (const [propName, value] of props) {
1185
+ if ((failedProps === null || failedProps === void 0 ? void 0 : failedProps.has(propName)) !== true)
1186
+ propsObject[propName] = value;
1187
+ }
1188
+ if (childrenMarkdown !== '')
1189
+ propsObject.children = effectiveChildren;
1190
+ scope.set(paramInfo.propsObjectName, propsObject);
1191
+ }
1192
+ const named = new Set(paramInfo.bindings.map((binding) => binding.propName));
1193
+ let restFailedProps;
1194
+ if (paramInfo.restName !== undefined) {
1195
+ const restObject = {};
1196
+ for (const [propName, value] of props) {
1197
+ if (!named.has(propName) && (failedProps === null || failedProps === void 0 ? void 0 : failedProps.has(propName)) !== true) {
1198
+ restObject[propName] = value;
1199
+ }
1200
+ }
1201
+ if (childrenMarkdown !== '' && !named.has('children'))
1202
+ restObject.children = effectiveChildren;
1203
+ scope.set(paramInfo.restName, restObject);
1204
+ restFailedProps = new Set([...(failedProps !== null && failedProps !== void 0 ? failedProps : [])].filter((propName) => !named.has(propName)));
1205
+ }
1206
+ const env = {
1207
+ scope,
1208
+ propsObjectName: paramInfo.propsObjectName,
1209
+ failedProps,
1210
+ restName: paramInfo.restName,
1211
+ restFailedProps,
1212
+ };
1213
+ // Supplied children are bound first, so later parameter defaults can read them
1214
+ if (childrenMarkdown !== '')
1215
+ scope.set(paramInfo.childrenName, effectiveChildren);
1216
+ for (const binding of paramInfo.bindings) {
1217
+ if (binding.propName === 'children' &&
1218
+ childrenMarkdown !== '' &&
1219
+ binding.pattern === undefined) {
1220
+ continue;
1221
+ }
1222
+ if (binding.pattern !== undefined) {
1223
+ const boundNames = new Set();
1224
+ collectPatternNames(binding.pattern, boundNames);
1225
+ for (const boundName of boundNames)
1226
+ scope.delete(boundName);
1227
+ if (failedProps === null || failedProps === void 0 ? void 0 : failedProps.has(binding.propName))
1228
+ continue;
1229
+ const suppliedPattern = props.get(binding.propName);
1230
+ const hasSuppliedPattern = props.has(binding.propName) && suppliedPattern !== undefined;
1231
+ bindPattern(binding.pattern, hasSuppliedPattern ? suppliedPattern : undefined, env);
1232
+ continue;
1233
+ }
1234
+ if (failedProps === null || failedProps === void 0 ? void 0 : failedProps.has(binding.propName)) {
1235
+ scope.delete(binding.localName);
1236
+ continue;
1237
+ }
1238
+ const supplied = props.get(binding.propName);
1239
+ const hasSupplied = props.has(binding.propName) && supplied !== undefined;
1240
+ if (hasSupplied) {
1241
+ scope.set(binding.localName, supplied);
1242
+ continue;
1243
+ }
1244
+ if (binding.defaultExpression === undefined) {
1245
+ scope.set(binding.localName, undefined);
1246
+ continue;
1247
+ }
1248
+ const evaluated = evaluateStatic(binding.defaultExpression, env);
1249
+ if (evaluated.ok)
1250
+ scope.set(binding.localName, evaluated.value);
1251
+ else
1252
+ scope.delete(binding.localName);
1253
+ }
1254
+ for (const unknownName of paramInfo.unknownNames)
1255
+ scope.delete(unknownName);
1256
+ // A key that cannot be known may have been taken out of the rest object
1257
+ if (paramInfo.restName !== undefined && paramInfo.unknownNames.size > 0) {
1258
+ scope.delete(paramInfo.restName);
1259
+ }
1260
+ if (childrenMarkdown !== '') {
1261
+ scope.set(paramInfo.childrenName, effectiveChildren);
1262
+ }
1263
+ return env;
1264
+ }
1265
+ /** Every name a function body declares or binds, at any depth. */
1266
+ function collectDeclaredNames(node, names = new Set()) {
1267
+ if (Array.isArray(node)) {
1268
+ for (const child of node)
1269
+ collectDeclaredNames(child, names);
1270
+ return names;
1271
+ }
1272
+ if (!isObject(node))
1273
+ return names;
1274
+ if (node.type === 'VariableDeclarator')
1275
+ collectPatternNames(node.id, names);
1276
+ if ((node.type === 'FunctionDeclaration' || node.type === 'ClassDeclaration') &&
1277
+ isObject(node.id) &&
1278
+ typeof node.id.name === 'string') {
1279
+ names.add(node.id.name);
1280
+ }
1281
+ if (Array.isArray(node.params)) {
1282
+ for (const param of node.params)
1283
+ collectPatternNames(param, names);
1284
+ }
1285
+ if (node.type === 'CatchClause')
1286
+ collectPatternNames(node.param, names);
1287
+ forEachCodeChild(node, (child) => collectDeclaredNames(child, names));
1288
+ return names;
1289
+ }
1290
+ export function materializeComponent(def, name, props, childrenMarkdown, ctx, failedProps,
1291
+ // The static value of a body made of one expression, which `children` keeps over its markdown
1292
+ bodyValue, trusted) {
1293
+ var _a, _b;
1294
+ // A spread that could not be evaluated may supply any prop, so nothing about
1295
+ // the usage is knowable; fall back to unresolved instead of defaults.
1296
+ if (failedProps === null || failedProps === void 0 ? void 0 : failedProps.has(FAILED_SPREAD))
1297
+ return undefined;
1298
+ let scopeChildren = bodyValue === null || bodyValue === void 0 ? void 0 : bodyValue.value;
1299
+ if (childrenMarkdown === '') {
1300
+ const childrenProp = props.get('children');
1301
+ if (typeof childrenProp === 'string') {
1302
+ childrenMarkdown = escapeInterpolatedText(childrenProp);
1303
+ scopeChildren = childrenProp;
1304
+ }
1305
+ else if (typeof childrenProp === 'number') {
1306
+ childrenMarkdown = String(childrenProp);
1307
+ scopeChildren = childrenProp;
1308
+ }
1309
+ }
1310
+ const effectiveChildren = scopeChildren !== null && scopeChildren !== void 0 ? scopeChildren : childrenMarkdown;
1311
+ const paramInfo = analyzeParams(def.params);
1312
+ const named = new Set(paramInfo.bindings.map((binding) => binding.propName));
1313
+ const env = bindComponentScope(paramInfo, ctx.moduleScope, props, failedProps, childrenMarkdown, effectiveChildren);
1314
+ // Props not supplied from trusted values are unknown here, so a default cannot stand in for them
1315
+ const untrusted = new Set([...props.keys()].filter((key) => (trusted === null || trusted === void 0 ? void 0 : trusted.props.has(key)) !== true));
1316
+ const trustedEnvironment = bindComponentScope(paramInfo, trustedEnv(ctx).scope, (_a = trusted === null || trusted === void 0 ? void 0 : trusted.props) !== null && _a !== void 0 ? _a : new Map(), new Set([...((_b = trusted === null || trusted === void 0 ? void 0 : trusted.failedProps) !== null && _b !== void 0 ? _b : []), ...untrusted, ...(failedProps !== null && failedProps !== void 0 ? failedProps : [])]), '', '');
1317
+ // Locals may shadow trusted names with values that are not
1318
+ for (const local of collectDeclaredNames(def.body))
1319
+ trustedEnvironment.scope.delete(local);
1320
+ const returnExpression = findReturnExpression(def.body, env);
1321
+ if (returnExpression === UNRESOLVED_RETURN)
1322
+ return undefined;
1323
+ if (returnExpression === undefined)
1324
+ return '';
1325
+ if (!isResolvedReturn(returnExpression, env))
1326
+ return undefined;
1327
+ const serializeContext = Object.assign(Object.assign({ defs: ctx.defs, moduleScope: ctx.moduleScope, literalScope: ctx.literalScope, stack: [...ctx.stack, def], budget: ctx.budget }, env), { trusted: trustedEnvironment, restCarriesChildren: !named.has('children'), childrenMarkdown, childrenName: paramInfo.childrenName });
1328
+ return serializeJsxExpression(returnExpression, serializeContext);
1329
+ }
1330
+ export function collectUsageProps(node, ctx, failed) {
1331
+ var _a, _b;
1332
+ const props = new Map();
1333
+ for (const attribute of node.attributes) {
1334
+ if (attribute.type === 'mdxJsxExpressionAttribute') {
1335
+ const spread = evaluateStatic(extractProgramExpression((_a = attribute.data) === null || _a === void 0 ? void 0 : _a.estree), {
1336
+ scope: ctx.moduleScope,
1337
+ });
1338
+ if (spread.ok && isStaticObject(spread.value)) {
1339
+ for (const [key, value] of Object.entries(spread.value)) {
1340
+ setKnownProp(props, failed, key, value);
1341
+ }
1342
+ }
1343
+ else if (!spread.ok || !isNoOpSpreadValue(spread.value)) {
1344
+ failed === null || failed === void 0 ? void 0 : failed.add(FAILED_SPREAD);
1345
+ }
1346
+ continue;
1347
+ }
1348
+ if (attribute.type !== 'mdxJsxAttribute')
1349
+ continue;
1350
+ if (attribute.value === null || attribute.value === undefined) {
1351
+ setKnownProp(props, failed, attribute.name, true);
1352
+ continue;
1353
+ }
1354
+ if (typeof attribute.value === 'string') {
1355
+ setKnownProp(props, failed, attribute.name, attribute.value);
1356
+ continue;
1357
+ }
1358
+ const estree = (_b = attribute.value.data) === null || _b === void 0 ? void 0 : _b.estree;
1359
+ const expression = extractProgramExpression(estree);
1360
+ const evaluated = evaluateStatic(expression, { scope: ctx.moduleScope });
1361
+ if (evaluated.ok)
1362
+ setKnownProp(props, failed, attribute.name, evaluated.value);
1363
+ else
1364
+ setFailedProp(props, failed, attribute.name);
1365
+ }
1366
+ return props;
1367
+ }
1368
+ export function extractProgramExpression(estree) {
1369
+ if (!isObject(estree) || !Array.isArray(estree.body))
1370
+ return undefined;
1371
+ const [statement] = estree.body;
1372
+ if (nodeType(statement) === 'ExpressionStatement' && isObject(statement)) {
1373
+ return statement.expression;
1374
+ }
1375
+ return undefined;
1376
+ }
1377
+ /** Whether `node` contains a JSX element or fragment, or only one named `name` when given. */
1378
+ export function containsJsx(node, name) {
1379
+ if (Array.isArray(node))
1380
+ return node.some((child) => containsJsx(child, name));
1381
+ if (!isObject(node))
1382
+ return false;
1383
+ if (node.type === 'JSXFragment' && name === undefined)
1384
+ return true;
1385
+ if (node.type === 'JSXElement' && (name === undefined || getJsxElementName(node) === name)) {
1386
+ return true;
1387
+ }
1388
+ let found = false;
1389
+ forEachCodeChild(node, (child) => {
1390
+ found || (found = containsJsx(child, name));
1391
+ });
1392
+ return found;
1393
+ }
1394
+ /**
1395
+ * Serializes an expression that renders JSX: an element or fragment, or a conditional or logical
1396
+ * expression with JSX in a branch. A branch whose condition cannot be resolved is dropped.
1397
+ */
1398
+ export function serializeExpressionJsx(expression, ctx) {
1399
+ const type = nodeType(expression);
1400
+ const isBranching = (type === 'ConditionalExpression' || type === 'LogicalExpression') && containsJsx(expression);
1401
+ if (type !== 'JSXElement' && type !== 'JSXFragment' && !isBranching)
1402
+ return undefined;
1403
+ const serializeContext = {
1404
+ defs: ctx.defs,
1405
+ moduleScope: ctx.moduleScope,
1406
+ literalScope: ctx.literalScope,
1407
+ stack: ctx.stack,
1408
+ budget: ctx.budget,
1409
+ scope: new Map(ctx.moduleScope),
1410
+ childrenMarkdown: '',
1411
+ childrenName: 'children',
1412
+ };
1413
+ return serializeJsxExpression(expression, serializeContext);
1414
+ }