@mintlify/common 1.0.797 → 1.0.798

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.
@@ -127,7 +127,7 @@ const DEFAULT_PROP_EXPRESSIONS = {
127
127
  examples: { value: '{}', estree: objectEstree },
128
128
  summary: { value: '""', estree: createStringEstree('') },
129
129
  value: { value: '{}', estree: objectEstree },
130
- contextual: { value: '{ "options": [] }', estree: falseEstree },
130
+ contextual: { value: '{}', estree: objectEstree },
131
131
  api: { value: '{}', estree: objectEstree },
132
132
  navigation: { value: '{}', estree: objectEstree },
133
133
  asyncapi: { value: '""', estree: createStringEstree('') },
@@ -142,9 +142,9 @@ export function isStringSafe(value) {
142
142
  // purely alphanumeric string
143
143
  case /^[_a-zA-Z0-9]+$/.test(value):
144
144
  // string literal with quotes
145
- case /^'[_a-zA-Z0-9\s`".\-\\{}\?\(\)&*^%#@!~=+\[\]|:;,\/]+'$/.test(value):
146
- case /^"[_a-zA-Z0-9\s`'.\-\\{}\?\(\)&*^%#@!~=+\[\]|:;,\/]+"$/.test(value):
147
- case /^`[_a-zA-Z0-9\s'".\-\\{}\?\(\)&*^%#@!~=+\[\]|:;,\/]+`$/.test(value):
145
+ case /^'[_a-zA-Z0-9\s`".\-\\${}?\(\)&*^%#@!~=+\[\]|:;,\/]+'$/.test(value):
146
+ case /^"[_a-zA-Z0-9\s`'.\-\\${}?\(\)&*^%#@!~=+\[\]|:;,\/]+"$/.test(value):
147
+ case /^`[_a-zA-Z0-9\s'".\-\\{}?\(\)&*^%#@!~=+\[\]|:;,\/]+`$/.test(value):
148
148
  // purely alphanumeric string prefixed with `!!`
149
149
  case /^!![_a-zA-Z0-9]+$/.test(value):
150
150
  // purely alphanumeric string wrapped in parens
@@ -238,41 +238,72 @@ function collectIdentifiersFromPattern(pattern, out) {
238
238
  collectIdentifiersFromPattern(pattern.argument, out);
239
239
  }
240
240
  }
241
+ // Returns the identifier name if the estree expression is a bare reference that will be kept
242
+ // by isStringSafe but needs a stub to avoid a ReferenceError at render time:
243
+ // {foo} → Identifier
244
+ // {!!foo} → UnaryExpression(! UnaryExpression(! Identifier))
245
+ // Parenthesised forms are transparent in ESTree so (foo) produces the same AST as foo.
246
+ function extractIdentifierRef(estree) {
247
+ const stmt = estree === null || estree === void 0 ? void 0 : estree.body[0];
248
+ if ((stmt === null || stmt === void 0 ? void 0 : stmt.type) !== 'ExpressionStatement')
249
+ return null;
250
+ const expr = stmt.expression;
251
+ if (expr.type === 'Identifier')
252
+ return expr.name;
253
+ if (expr.type === 'UnaryExpression' &&
254
+ expr.operator === '!' &&
255
+ expr.argument.type === 'UnaryExpression' &&
256
+ expr.argument.operator === '!' &&
257
+ expr.argument.argument.type === 'Identifier')
258
+ return expr.argument.argument.name;
259
+ return null;
260
+ }
241
261
  function collectExportedNames(estree) {
242
262
  var _a, _b;
243
263
  const names = [];
244
264
  for (const node of estree.body) {
245
- if (node.type !== 'ExportNamedDeclaration')
246
- continue;
247
- const exportNode = node;
248
- const decl = exportNode.declaration;
249
- if (!decl) {
250
- // Re-export specifiers: export { X } from 'module' or export { X }
251
- for (const spec of exportNode.specifiers) {
252
- // ES2022 allows Literal export names (e.g. export { foo as "bar" }),
253
- // which have no .name — skip to avoid emitting `export const undefined = undefined`
254
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
255
- if (spec.exported.type !== 'Identifier')
256
- continue;
257
- names.push({ name: spec.exported.name, isFunction: false });
258
- }
259
- continue;
260
- }
261
- if (decl.type === 'FunctionDeclaration' && decl.id) {
262
- names.push({ name: decl.id.name, isFunction: true });
263
- }
264
- else if (decl.type === 'VariableDeclaration') {
265
- for (const declarator of decl.declarations) {
266
- if (declarator.id.type === 'Identifier') {
267
- const isFn = ((_a = declarator.init) === null || _a === void 0 ? void 0 : _a.type) === 'ArrowFunctionExpression' ||
268
- ((_b = declarator.init) === null || _b === void 0 ? void 0 : _b.type) === 'FunctionExpression';
269
- names.push({ name: declarator.id.name, isFunction: isFn });
265
+ // Named exports: export const x, export function x, export { x }
266
+ if (node.type === 'ExportNamedDeclaration') {
267
+ const exportNode = node;
268
+ const decl = exportNode.declaration;
269
+ if (!decl) {
270
+ // Re-export specifiers: export { X } from 'module' or export { X }
271
+ for (const spec of exportNode.specifiers) {
272
+ // ES2022 allows Literal export names (e.g. export { foo as "bar" }),
273
+ // which have no .name — skip to avoid emitting `export const undefined = undefined`
274
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
275
+ if (spec.exported.type !== 'Identifier')
276
+ continue;
277
+ // 'default' is a reserved word and cannot be used as a variable name in a stub
278
+ if (spec.exported.name === 'default')
279
+ continue;
280
+ names.push({ name: spec.exported.name, isFunction: false });
270
281
  }
271
- else {
272
- collectIdentifiersFromPattern(declarator.id, names);
282
+ continue;
283
+ }
284
+ if (decl.type === 'FunctionDeclaration' && decl.id) {
285
+ names.push({ name: decl.id.name, isFunction: true });
286
+ }
287
+ else if (decl.type === 'VariableDeclaration') {
288
+ for (const declarator of decl.declarations) {
289
+ if (declarator.id.type === 'Identifier') {
290
+ const isFn = ((_a = declarator.init) === null || _a === void 0 ? void 0 : _a.type) === 'ArrowFunctionExpression' ||
291
+ ((_b = declarator.init) === null || _b === void 0 ? void 0 : _b.type) === 'FunctionExpression';
292
+ names.push({ name: declarator.id.name, isFunction: isFn });
293
+ }
294
+ else {
295
+ collectIdentifiersFromPattern(declarator.id, names);
296
+ }
273
297
  }
274
298
  }
275
299
  }
300
+ // Default export: export default function Name() {} creates a named binding in scope
301
+ if (node.type === 'ExportDefaultDeclaration') {
302
+ const decl = node.declaration;
303
+ if ((decl.type === 'FunctionDeclaration' || decl.type === 'FunctionExpression') && decl.id) {
304
+ names.push({ name: decl.id.name, isFunction: true });
305
+ }
306
+ }
276
307
  }
277
308
  return names;
278
309
  }
@@ -350,34 +381,40 @@ function isArrayOfStringLiterals(estree) {
350
381
  export function remarkMdxRemoveJs() {
351
382
  return (tree) => {
352
383
  remove(tree, ['mdxTextExpression', 'mdxFlowExpression']);
353
- // Collect exported names before stripping ESM so we can inject stubs
354
- const exportedNames = [];
384
+ // Collect exported names before stripping ESM so we can inject stubs.
385
+ // Map keyed by name deduplicates naturally.
386
+ const stubbedNamesMap = new Map();
355
387
  visit(tree, (node) => {
356
388
  var _a;
357
389
  if (isMdxJsEsm(node) && ((_a = node.data) === null || _a === void 0 ? void 0 : _a.estree)) {
358
- exportedNames.push(...collectExportedNames(node.data.estree));
390
+ for (const entry of collectExportedNames(node.data.estree)) {
391
+ if (!stubbedNamesMap.has(entry.name))
392
+ stubbedNamesMap.set(entry.name, entry);
393
+ }
359
394
  }
360
395
  });
361
396
  remove(tree, (node) => isMdxJsEsm(node));
362
- // Inject stub declarations for stripped exports to prevent ReferenceErrors
363
- if (exportedNames.length > 0) {
364
- tree.children.unshift(buildStubEsmNode(exportedNames));
365
- }
397
+ // Sanitize JSX attributes. Any bare identifier that survives is added to stubbedNamesMap
398
+ // so it gets a stub even if its import was already stripped by a prior plugin.
366
399
  visit(tree, (node) => {
367
400
  if (!('attributes' in node))
368
401
  return CONTINUE;
369
402
  const newAttributes = node.attributes.map((attr) => {
370
- var _a, _b, _c, _d, _e, _f;
403
+ var _a, _b, _c, _d, _e, _f, _g;
371
404
  if (attr.type === 'mdxJsxAttribute' && !(attr.value instanceof Object))
372
405
  return attr;
373
406
  if (typeof attr.value === 'string' && isStringSafe(attr.value))
374
407
  return attr;
375
408
  if (attr.type === 'mdxJsxAttribute' && attr.value instanceof Object) {
376
- if (isStringSafe(attr.value.value))
409
+ if (isStringSafe(attr.value.value)) {
410
+ const ident = extractIdentifierRef((_a = attr.value.data) === null || _a === void 0 ? void 0 : _a.estree);
411
+ if (ident && !stubbedNamesMap.has(ident))
412
+ stubbedNamesMap.set(ident, { name: ident, isFunction: false });
377
413
  return attr;
378
- if (((_a = attr.value.data) === null || _a === void 0 ? void 0 : _a.estree) && isArrayOfStringLiterals(attr.value.data.estree))
414
+ }
415
+ if (((_b = attr.value.data) === null || _b === void 0 ? void 0 : _b.estree) && isArrayOfStringLiterals(attr.value.data.estree))
379
416
  return attr;
380
- if (attr.name === 'style' && ((_b = attr.value.data) === null || _b === void 0 ? void 0 : _b.estree)) {
417
+ if (attr.name === 'style' && ((_c = attr.value.data) === null || _c === void 0 ? void 0 : _c.estree)) {
381
418
  const filteredEstree = filterStyleProperties(attr.value.data.estree);
382
419
  if (filteredEstree) {
383
420
  const stmt = filteredEstree.body[0];
@@ -391,9 +428,9 @@ export function remarkMdxRemoveJs() {
391
428
  return undefined;
392
429
  }
393
430
  if (Object.keys(DEFAULT_PROP_EXPRESSIONS).includes(attr.name)) {
394
- attr.value.value = (_d = (_c = DEFAULT_PROP_EXPRESSIONS[attr.name]) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : '{}';
431
+ attr.value.value = (_e = (_d = DEFAULT_PROP_EXPRESSIONS[attr.name]) === null || _d === void 0 ? void 0 : _d.value) !== null && _e !== void 0 ? _e : '{}';
395
432
  attr.value.data = {
396
- estree: (_f = (_e = DEFAULT_PROP_EXPRESSIONS[attr.name]) === null || _e === void 0 ? void 0 : _e.estree) !== null && _f !== void 0 ? _f : objectEstree,
433
+ estree: structuredClone((_g = (_f = DEFAULT_PROP_EXPRESSIONS[attr.name]) === null || _f === void 0 ? void 0 : _f.estree) !== null && _g !== void 0 ? _g : objectEstree),
397
434
  };
398
435
  return attr;
399
436
  }
@@ -402,5 +439,9 @@ export function remarkMdxRemoveJs() {
402
439
  });
403
440
  node.attributes = newAttributes.filter((attr) => attr !== undefined);
404
441
  });
442
+ // Inject stubs after the attribute walk so identifiers collected from attributes are included
443
+ if (stubbedNamesMap.size > 0) {
444
+ tree.children.unshift(buildStubEsmNode([...stubbedNamesMap.values()]));
445
+ }
405
446
  };
406
447
  }