@mintlify/common 1.0.1144 → 1.0.1145

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.
@@ -14,17 +14,18 @@ export const findExportedNodes = (tree, ...type) => {
14
14
  continue;
15
15
  if (((_a = bodyChild.declaration) === null || _a === void 0 ? void 0 : _a.type) !== 'VariableDeclaration')
16
16
  continue;
17
- const declaration = bodyChild.declaration.declarations[0];
18
- if (declaration == undefined)
19
- continue;
20
- const init = declaration.init;
21
- if (init == null)
22
- continue;
23
- if (!type.includes(init.type))
24
- continue;
25
- if (declaration.id.type !== 'Identifier')
26
- continue;
27
- exports.push(declaration.id.name);
17
+ for (const declaration of bodyChild.declaration.declarations) {
18
+ if (declaration == undefined)
19
+ continue;
20
+ const init = declaration.init;
21
+ if (init == null)
22
+ continue;
23
+ if (!type.includes(init.type))
24
+ continue;
25
+ if (declaration.id.type !== 'Identifier')
26
+ continue;
27
+ exports.push(declaration.id.name);
28
+ }
28
29
  }
29
30
  }
30
31
  });
@@ -534,8 +534,62 @@ function buildStubEsmNode(names) {
534
534
  },
535
535
  };
536
536
  }
537
+ function collectStringConstants(tree) {
538
+ const constants = new Map();
539
+ visit(tree, (node) => {
540
+ var _a;
541
+ if (!isMdxJsEsm(node) || !((_a = node.data) === null || _a === void 0 ? void 0 : _a.estree))
542
+ return;
543
+ for (const stmt of node.data.estree.body) {
544
+ if (stmt.type !== 'ExportNamedDeclaration')
545
+ continue;
546
+ const exportNode = stmt;
547
+ const decl = exportNode.declaration;
548
+ if (!decl || decl.type !== 'VariableDeclaration' || decl.kind !== 'const')
549
+ continue;
550
+ for (const declarator of decl.declarations) {
551
+ if (declarator.id.type !== 'Identifier' || !declarator.init)
552
+ continue;
553
+ if (declarator.init.type === 'Literal' && typeof declarator.init.value === 'string') {
554
+ constants.set(declarator.id.name, declarator.init.value);
555
+ }
556
+ }
557
+ }
558
+ });
559
+ return constants;
560
+ }
561
+ function tryResolveAsString(estree, constants) {
562
+ if (!estree)
563
+ return null;
564
+ const stmt = estree.body[0];
565
+ if ((stmt === null || stmt === void 0 ? void 0 : stmt.type) !== 'ExpressionStatement')
566
+ return null;
567
+ const expr = stmt.expression;
568
+ if (expr.type !== 'Identifier')
569
+ return null;
570
+ const val = constants.get(expr.name);
571
+ return val !== undefined ? val : null;
572
+ }
537
573
  export function remarkMdxRemoveJs() {
538
574
  return (tree) => {
575
+ const constantStrings = collectStringConstants(tree);
576
+ if (constantStrings.size > 0) {
577
+ visit(tree, (node, index, parent) => {
578
+ var _a;
579
+ if (!parent || index == null)
580
+ return CONTINUE;
581
+ if (node.type !== 'mdxTextExpression' && node.type !== 'mdxFlowExpression')
582
+ return CONTINUE;
583
+ const exprNode = node;
584
+ const substitution = tryResolveAsString((_a = exprNode.data) === null || _a === void 0 ? void 0 : _a.estree, constantStrings);
585
+ if (substitution === null)
586
+ return CONTINUE;
587
+ const replacement = node.type === 'mdxTextExpression'
588
+ ? { type: 'text', value: substitution }
589
+ : { type: 'paragraph', children: [{ type: 'text', value: substitution }] };
590
+ parent.children[index] = replacement;
591
+ });
592
+ }
539
593
  remove(tree, ['mdxTextExpression', 'mdxFlowExpression']);
540
594
  // Collect exported names before stripping ESM so we can inject stubs.
541
595
  // Map keyed by name deduplicates naturally.
@@ -0,0 +1,120 @@
1
+ import { fromMarkdown } from 'mdast-util-from-markdown';
2
+ import { gfmFromMarkdown } from 'mdast-util-gfm';
3
+ import { mdxFromMarkdown } from 'mdast-util-mdx';
4
+ import { gfm } from 'micromark-extension-gfm';
5
+ import { mdxjs } from 'micromark-extension-mdxjs';
6
+ import { describe, expect, it } from 'vitest';
7
+ import { remarkMdxRemoveJs } from './remarkMdxRemoveJs.js';
8
+ function parse(mdx) {
9
+ return fromMarkdown(mdx, {
10
+ extensions: [gfm(), mdxjs()],
11
+ mdastExtensions: [gfmFromMarkdown(), mdxFromMarkdown()],
12
+ });
13
+ }
14
+ function extractText(node) {
15
+ if (node.type === 'text' && typeof node.value === 'string') {
16
+ return node.value;
17
+ }
18
+ if ('children' in node && Array.isArray(node.children)) {
19
+ return node.children
20
+ .map((child) => extractText(child))
21
+ .join('');
22
+ }
23
+ return '';
24
+ }
25
+ function applyPlugin(mdx) {
26
+ const tree = parse(mdx);
27
+ remarkMdxRemoveJs()(tree);
28
+ return tree;
29
+ }
30
+ describe('remarkMdxRemoveJs', () => {
31
+ describe('expression removal (existing behaviour)', () => {
32
+ it('removes arbitrary binary expressions', () => {
33
+ const tree = applyPlugin('Sum is {1 + 1} here.');
34
+ const text = extractText(tree);
35
+ expect(text).not.toContain('1 + 1');
36
+ expect(text).not.toContain('2');
37
+ expect(text).toContain('Sum is');
38
+ expect(text).toContain('here.');
39
+ });
40
+ it('removes function call expressions', () => {
41
+ const tree = applyPlugin('Items: {["a","b"].map(x => x)} end.');
42
+ const text = extractText(tree);
43
+ expect(text).not.toContain('map');
44
+ expect(text).toContain('Items:');
45
+ expect(text).toContain('end.');
46
+ });
47
+ it('removes template literals', () => {
48
+ const tree = applyPlugin('Val {`tpl-${1 + 1}`} end.');
49
+ const text = extractText(tree);
50
+ expect(text).not.toContain('tpl');
51
+ expect(text).toContain('Val');
52
+ expect(text).toContain('end.');
53
+ });
54
+ });
55
+ describe('string constant substitution (new behaviour)', () => {
56
+ it('substitutes a bare identifier that maps to an exported string constant', () => {
57
+ const mdx = `export const versions = "v1.2.3 and later";
58
+
59
+ On {versions}, this feature requires opt-in.`;
60
+ const tree = applyPlugin(mdx);
61
+ const text = extractText(tree);
62
+ expect(text).toContain('v1.2.3 and later');
63
+ expect(text).toContain('On v1.2.3 and later, this feature requires opt-in.');
64
+ });
65
+ it('substitutes a page-level export const used inline', () => {
66
+ const mdx = `export const ver = "v5.5.5-CONSTVAL";
67
+
68
+ Version {ver} here.`;
69
+ const tree = applyPlugin(mdx);
70
+ expect(extractText(tree)).toContain('Version v5.5.5-CONSTVAL here.');
71
+ });
72
+ it('substitutes multiple constants from separate export statements', () => {
73
+ const mdx = `export const a = "AAA";
74
+ export const b = "BBB";
75
+
76
+ {a} and {b}.`;
77
+ const tree = applyPlugin(mdx);
78
+ const text = extractText(tree);
79
+ expect(text).toContain('AAA');
80
+ expect(text).toContain('BBB');
81
+ });
82
+ it('substitutes all declarators in a multi-declarator const', () => {
83
+ const mdx = `export const a = "AAA", b = "BBB";
84
+
85
+ {a} and {b}.`;
86
+ const tree = applyPlugin(mdx);
87
+ const text = extractText(tree);
88
+ expect(text).toContain('AAA');
89
+ expect(text).toContain('BBB');
90
+ });
91
+ it('does not substitute non-string (number) constants', () => {
92
+ const mdx = `export const count = 42;
93
+
94
+ Value {count} here.`;
95
+ const tree = applyPlugin(mdx);
96
+ const text = extractText(tree);
97
+ expect(text).not.toContain('42');
98
+ expect(text).toContain('Value');
99
+ expect(text).toContain('here.');
100
+ });
101
+ it('does not substitute identifiers with no matching export', () => {
102
+ const tree = applyPlugin('Value {unknown} here.');
103
+ const text = extractText(tree);
104
+ expect(text).not.toContain('unknown');
105
+ expect(text).toContain('Value');
106
+ expect(text).toContain('here.');
107
+ });
108
+ it('substitutes the constant but still removes unresolvable expressions in the same page', () => {
109
+ const mdx = `export const x = "hello";
110
+
111
+ Result {1 + 1} and {x} here.`;
112
+ const tree = applyPlugin(mdx);
113
+ const text = extractText(tree);
114
+ expect(text).toContain('hello');
115
+ expect(text).not.toContain('1 + 1');
116
+ expect(text).toContain('Result');
117
+ expect(text).toContain('and hello here.');
118
+ });
119
+ });
120
+ });