@readme/markdown 12.1.0 → 12.2.0

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.
@@ -1,8 +1,9 @@
1
1
  interface Opts {
2
2
  mdx?: boolean;
3
+ mdxish?: boolean;
3
4
  }
4
5
  /**
5
6
  * Removes Markdown and MDX comments.
6
7
  */
7
- declare function stripComments(doc: string, { mdx }?: Opts): Promise<string>;
8
+ declare function stripComments(doc: string, { mdx, mdxish }?: Opts): Promise<string>;
8
9
  export default stripComments;
package/dist/main.js CHANGED
@@ -52923,6 +52923,37 @@ const stripCommentsTransformer = () => {
52923
52923
 
52924
52924
 
52925
52925
  const STRIP_TAGS = ['script', 'style'];
52926
+ /**
52927
+ * Extract variable key from MDX expression AST (e.g., {user.name} → 'name')
52928
+ * Uses ESTree AST inspection, matching the approach in processor/transform/variables.ts
52929
+ *
52930
+ * @see https://github.com/syntax-tree/mdast-util-mdx-expression - MdxTextExpressionHast type
52931
+ * @see https://github.com/estree/estree/blob/master/es5.md - ESTree spec for expression types
52932
+ */
52933
+ function extractMdxVariableKey(node) {
52934
+ const estree = node.data?.estree;
52935
+ if (!estree || estree.type !== 'Program' || estree.body.length === 0)
52936
+ return undefined;
52937
+ const statement = estree.body[0];
52938
+ if (statement.type !== 'ExpressionStatement')
52939
+ return undefined;
52940
+ const expr = statement.expression;
52941
+ if (expr.type !== 'MemberExpression')
52942
+ return undefined;
52943
+ const memberExpr = expr;
52944
+ const obj = memberExpr.object;
52945
+ if (obj.type !== 'Identifier' || obj.name !== 'user')
52946
+ return undefined;
52947
+ const prop = memberExpr.property;
52948
+ if (prop.type === 'Identifier') {
52949
+ return prop.name;
52950
+ }
52951
+ if (prop.type === 'Literal') {
52952
+ const val = prop.value;
52953
+ return typeof val === 'string' ? val : undefined;
52954
+ }
52955
+ return undefined;
52956
+ }
52926
52957
  function plain_one(node, opts) {
52927
52958
  if (node.type === 'comment')
52928
52959
  return '';
@@ -52946,6 +52977,8 @@ function plain_one(node, opts) {
52946
52977
  const body = children ? plain_all({ type: 'root', children }, opts) : '';
52947
52978
  return [icon, ' ', title, title && body && ': ', body].filter(Boolean).join('');
52948
52979
  }
52980
+ // 'variable' (lowercase) comes from mdxish() after rehypeRaw normalizes HTML tag names
52981
+ case 'variable':
52949
52982
  case 'Variable': {
52950
52983
  const key = node.properties.name.toString();
52951
52984
  const val = 'variables' in opts && opts.variables[key];
@@ -52967,6 +53000,13 @@ function plain_one(node, opts) {
52967
53000
  break;
52968
53001
  }
52969
53002
  }
53003
+ // Handle MDX expressions like {user.name}
53004
+ if (node.type === 'mdxTextExpression') {
53005
+ const key = extractMdxVariableKey(node);
53006
+ if (key) {
53007
+ return ('variables' in opts && opts.variables[key]) || key;
53008
+ }
53009
+ }
52970
53010
  if ('value' in node) {
52971
53011
  return node.value;
52972
53012
  }
@@ -86628,11 +86668,27 @@ const getDepth = (el) => {
86628
86668
  return Infinity;
86629
86669
  return parseInt(el.tagName?.match(/^h(\d)/)[1], 10);
86630
86670
  };
86671
+ /**
86672
+ * Flatten Variables into a simple key-value map for static resolution.
86673
+ * Merges user values with defaults (user values take precedence).
86674
+ */
86675
+ const flattenVariables = (variables) => {
86676
+ if (!variables)
86677
+ return {};
86678
+ return {
86679
+ ...variables.user,
86680
+ ...Object.fromEntries((variables.defaults || []).filter(d => !(d.name in variables.user)).map(d => [d.name, d.default])),
86681
+ };
86682
+ };
86631
86683
  /*
86632
86684
  * `tocToHast` consumes the list generated by `rehypeToc` and produces a hast
86633
86685
  * of nested lists to be rendered as a table of contents.
86686
+ *
86687
+ * @param headings - The list of heading elements to render
86688
+ * @param variables - Optional user variables for resolving Variable nodes in headings
86634
86689
  */
86635
- const tocToHast = (headings = []) => {
86690
+ const tocToHast = (headings = [], variables) => {
86691
+ const flatVars = flattenVariables(variables);
86636
86692
  const headingDepths = headings.map(getDepth);
86637
86693
  const min = Math.min(...headingDepths);
86638
86694
  const ast = hastscript_lib_h('ul');
@@ -86650,7 +86706,7 @@ const tocToHast = (headings = []) => {
86650
86706
  stack.pop();
86651
86707
  }
86652
86708
  if (heading.properties) {
86653
- const content = lib_plain({ type: 'root', children: heading.children });
86709
+ const content = lib_plain({ type: 'root', children: heading.children }, { variables: flatVars });
86654
86710
  stack[stack.length - 1].children.push(hastscript_lib_h('li', null, hastscript_lib_h('a', { href: `#${heading.properties.id}` }, content)));
86655
86711
  }
86656
86712
  });
@@ -86660,8 +86716,12 @@ const tocToHast = (headings = []) => {
86660
86716
  * `tocHastToMdx` is a utility for combining `TocList`s of a root document and
86661
86717
  * any child components it may have. Once combined it will generate a markdown
86662
86718
  * doc representing a table of contents.
86719
+ *
86720
+ * @param toc - The list of TOC elements
86721
+ * @param components - Custom components that may contain headings
86722
+ * @param variables - Optional user variables for resolving Variable nodes in headings
86663
86723
  */
86664
- const tocHastToMdx = (toc, components) => {
86724
+ const tocHastToMdx = (toc, components, variables) => {
86665
86725
  if (typeof toc === 'undefined')
86666
86726
  return '';
86667
86727
  const injected = toc.flatMap(node => {
@@ -86670,7 +86730,7 @@ const tocHastToMdx = (toc, components) => {
86670
86730
  }
86671
86731
  return node;
86672
86732
  });
86673
- const tocHast = tocToHast(injected);
86733
+ const tocHast = tocToHast(injected, variables);
86674
86734
  return lib_mdx({ type: 'root', children: [tocHast] }, { hast: true });
86675
86735
  };
86676
86736
 
@@ -93529,6 +93589,61 @@ function restoreCodeBlocks(content, protectedCode) {
93529
93589
  return protectedCode.codeBlocks[parseInt(idx, 10)];
93530
93590
  });
93531
93591
  }
93592
+ /**
93593
+ * Escapes unbalanced braces in content to prevent MDX expression parsing errors.
93594
+ * Handles: already-escaped braces, string literals inside expressions, nested balanced braces.
93595
+ */
93596
+ function escapeUnbalancedBraces(content) {
93597
+ const opens = [];
93598
+ const unbalanced = new Set();
93599
+ let strDelim = null;
93600
+ let strEscaped = false;
93601
+ for (let i = 0; i < content.length; i += 1) {
93602
+ const ch = content[i];
93603
+ // Track strings inside expressions to ignore braces within them
93604
+ if (opens.length > 0) {
93605
+ if (strDelim) {
93606
+ if (strEscaped)
93607
+ strEscaped = false;
93608
+ else if (ch === '\\')
93609
+ strEscaped = true;
93610
+ else if (ch === strDelim)
93611
+ strDelim = null;
93612
+ // eslint-disable-next-line no-continue
93613
+ continue;
93614
+ }
93615
+ if (ch === '"' || ch === "'" || ch === '`') {
93616
+ strDelim = ch;
93617
+ // eslint-disable-next-line no-continue
93618
+ continue;
93619
+ }
93620
+ }
93621
+ // Skip already-escaped braces (count preceding backslashes)
93622
+ if (ch === '{' || ch === '}') {
93623
+ let bs = 0;
93624
+ for (let j = i - 1; j >= 0 && content[j] === '\\'; j -= 1)
93625
+ bs += 1;
93626
+ if (bs % 2 === 1) {
93627
+ // eslint-disable-next-line no-continue
93628
+ continue;
93629
+ }
93630
+ }
93631
+ if (ch === '{')
93632
+ opens.push(i);
93633
+ else if (ch === '}') {
93634
+ if (opens.length > 0)
93635
+ opens.pop();
93636
+ else
93637
+ unbalanced.add(i);
93638
+ }
93639
+ }
93640
+ opens.forEach(pos => unbalanced.add(pos));
93641
+ if (unbalanced.size === 0)
93642
+ return content;
93643
+ return Array.from(content)
93644
+ .map((ch, i) => (unbalanced.has(i) ? `\\${ch}` : ch))
93645
+ .join('');
93646
+ }
93532
93647
  /**
93533
93648
  * Converts JSX attribute expressions (attribute={expression}) to HTML attributes (attribute="value").
93534
93649
  * Handles style objects (camelCase → kebab-case), className → class, and JSON stringifies objects.
@@ -93645,7 +93760,9 @@ function preprocessJSXExpressions(content, context = {}) {
93645
93760
  // For inline expressions, we use a library to parse the expression & evaluate it later
93646
93761
  // For attribute expressions, it was difficult to use a library to parse them, so do it manually
93647
93762
  processed = evaluateAttributeExpressions(processed, context, protectedCode);
93648
- // Step 4: Restore protected code blocks
93763
+ // Step 4: Escape unbalanced braces to prevent MDX expression parsing errors
93764
+ processed = escapeUnbalancedBraces(processed);
93765
+ // Step 5: Restore protected code blocks
93649
93766
  processed = restoreProtectedCodes(processed, protectedCode);
93650
93767
  return processed;
93651
93768
  }
@@ -95440,7 +95557,7 @@ function buildRMDXModule(content, headings, tocHast, opts) {
95440
95557
  * @see {@link https://github.com/readmeio/rmdx/blob/main/docs/mdxish-flow.md}
95441
95558
  */
95442
95559
  const renderMdxish = (tree, opts = {}) => {
95443
- const { components: userComponents = {}, ...contextOpts } = opts;
95560
+ const { components: userComponents = {}, variables, ...contextOpts } = opts;
95444
95561
  const components = {
95445
95562
  ...loadComponents(),
95446
95563
  ...userComponents,
@@ -95449,8 +95566,8 @@ const renderMdxish = (tree, opts = {}) => {
95449
95566
  const componentsForRehype = exportComponentsForRehype(components);
95450
95567
  const processor = createRehypeReactProcessor(componentsForRehype);
95451
95568
  const content = processor.stringify(tree);
95452
- const tocHast = headings.length > 0 ? tocToHast(headings) : null;
95453
- return buildRMDXModule(content, headings, tocHast, contextOpts);
95569
+ const tocHast = headings.length > 0 ? tocToHast(headings, variables) : null;
95570
+ return buildRMDXModule(content, headings, tocHast, { ...contextOpts, variables });
95454
95571
  };
95455
95572
  /* harmony default export */ const lib_renderMdxish = (renderMdxish);
95456
95573
 
@@ -95560,7 +95677,7 @@ const run_run = (string, _opts = {}) => {
95560
95677
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
95561
95678
  const { Toc: _Toc, toc, default: Content, stylesheet, ...exports } = exec(string);
95562
95679
  let Toc;
95563
- const tocMdx = tocHastToMdx(toc, tocsByTag);
95680
+ const tocMdx = tocHastToMdx(toc, tocsByTag, variables);
95564
95681
  if (tocMdx) {
95565
95682
  const compiledToc = lib_compile(tocMdx);
95566
95683
  const tocModule = exec(compiledToc, { useMDXComponents: () => ({ p: Fragment }) });
@@ -95621,13 +95738,26 @@ const mdxishTags_tags = (doc) => {
95621
95738
 
95622
95739
 
95623
95740
 
95741
+
95742
+
95743
+
95624
95744
  /**
95625
95745
  * Removes Markdown and MDX comments.
95626
95746
  */
95627
- async function stripComments(doc, { mdx } = {}) {
95747
+ async function stripComments(doc, { mdx, mdxish } = {}) {
95628
95748
  const { replaced, blocks } = extractMagicBlocks(doc);
95629
- const processor = unified()
95749
+ const processor = unified();
95750
+ // we still require these two extensions because:
95751
+ // 1. we can rely on remarkMdx to parse MDXish
95752
+ // 2. we need to parse JSX comments into mdxTextExpression nodes so that the transformers can pick them up
95753
+ if (mdxish) {
95754
+ processor
95755
+ .data('micromarkExtensions', [mdxExpression({ allowEmpty: true })])
95756
+ .data('fromMarkdownExtensions', [mdxExpressionFromMarkdown()]);
95757
+ }
95758
+ processor
95630
95759
  .use(remarkParse)
95760
+ .use(normalize_malformed_md_syntax)
95631
95761
  .use(mdx ? remarkMdx : undefined)
95632
95762
  .use(stripCommentsTransformer)
95633
95763
  .use(remarkStringify, mdx
@@ -95647,8 +95777,14 @@ async function stripComments(doc, { mdx } = {}) {
95647
95777
  // Preserve tight sibling code blocks without adding extra newlines between them.
95648
95778
  // Our markdown renderer uses this to group these code blocks into a tabbed interface.
95649
95779
  (left, right) => {
95650
- // 0 = no newline between blocks
95651
- return left.type === 'code' && right.type === 'code' ? 0 : undefined;
95780
+ if (left.type === 'code' && right.type === 'code') {
95781
+ const isTight = left.position &&
95782
+ right.position &&
95783
+ right.position.start.line - left.position.end.line === 1; // Are the blocks on adjacent lines?
95784
+ // 0 = no newline between blocks
95785
+ return isTight ? 0 : undefined;
95786
+ }
95787
+ return undefined;
95652
95788
  },
95653
95789
  ],
95654
95790
  });
package/dist/main.node.js CHANGED
@@ -73127,6 +73127,37 @@ const stripCommentsTransformer = () => {
73127
73127
 
73128
73128
 
73129
73129
  const STRIP_TAGS = ['script', 'style'];
73130
+ /**
73131
+ * Extract variable key from MDX expression AST (e.g., {user.name} → 'name')
73132
+ * Uses ESTree AST inspection, matching the approach in processor/transform/variables.ts
73133
+ *
73134
+ * @see https://github.com/syntax-tree/mdast-util-mdx-expression - MdxTextExpressionHast type
73135
+ * @see https://github.com/estree/estree/blob/master/es5.md - ESTree spec for expression types
73136
+ */
73137
+ function extractMdxVariableKey(node) {
73138
+ const estree = node.data?.estree;
73139
+ if (!estree || estree.type !== 'Program' || estree.body.length === 0)
73140
+ return undefined;
73141
+ const statement = estree.body[0];
73142
+ if (statement.type !== 'ExpressionStatement')
73143
+ return undefined;
73144
+ const expr = statement.expression;
73145
+ if (expr.type !== 'MemberExpression')
73146
+ return undefined;
73147
+ const memberExpr = expr;
73148
+ const obj = memberExpr.object;
73149
+ if (obj.type !== 'Identifier' || obj.name !== 'user')
73150
+ return undefined;
73151
+ const prop = memberExpr.property;
73152
+ if (prop.type === 'Identifier') {
73153
+ return prop.name;
73154
+ }
73155
+ if (prop.type === 'Literal') {
73156
+ const val = prop.value;
73157
+ return typeof val === 'string' ? val : undefined;
73158
+ }
73159
+ return undefined;
73160
+ }
73130
73161
  function plain_one(node, opts) {
73131
73162
  if (node.type === 'comment')
73132
73163
  return '';
@@ -73150,6 +73181,8 @@ function plain_one(node, opts) {
73150
73181
  const body = children ? plain_all({ type: 'root', children }, opts) : '';
73151
73182
  return [icon, ' ', title, title && body && ': ', body].filter(Boolean).join('');
73152
73183
  }
73184
+ // 'variable' (lowercase) comes from mdxish() after rehypeRaw normalizes HTML tag names
73185
+ case 'variable':
73153
73186
  case 'Variable': {
73154
73187
  const key = node.properties.name.toString();
73155
73188
  const val = 'variables' in opts && opts.variables[key];
@@ -73171,6 +73204,13 @@ function plain_one(node, opts) {
73171
73204
  break;
73172
73205
  }
73173
73206
  }
73207
+ // Handle MDX expressions like {user.name}
73208
+ if (node.type === 'mdxTextExpression') {
73209
+ const key = extractMdxVariableKey(node);
73210
+ if (key) {
73211
+ return ('variables' in opts && opts.variables[key]) || key;
73212
+ }
73213
+ }
73174
73214
  if ('value' in node) {
73175
73215
  return node.value;
73176
73216
  }
@@ -106832,11 +106872,27 @@ const getDepth = (el) => {
106832
106872
  return Infinity;
106833
106873
  return parseInt(el.tagName?.match(/^h(\d)/)[1], 10);
106834
106874
  };
106875
+ /**
106876
+ * Flatten Variables into a simple key-value map for static resolution.
106877
+ * Merges user values with defaults (user values take precedence).
106878
+ */
106879
+ const flattenVariables = (variables) => {
106880
+ if (!variables)
106881
+ return {};
106882
+ return {
106883
+ ...variables.user,
106884
+ ...Object.fromEntries((variables.defaults || []).filter(d => !(d.name in variables.user)).map(d => [d.name, d.default])),
106885
+ };
106886
+ };
106835
106887
  /*
106836
106888
  * `tocToHast` consumes the list generated by `rehypeToc` and produces a hast
106837
106889
  * of nested lists to be rendered as a table of contents.
106890
+ *
106891
+ * @param headings - The list of heading elements to render
106892
+ * @param variables - Optional user variables for resolving Variable nodes in headings
106838
106893
  */
106839
- const tocToHast = (headings = []) => {
106894
+ const tocToHast = (headings = [], variables) => {
106895
+ const flatVars = flattenVariables(variables);
106840
106896
  const headingDepths = headings.map(getDepth);
106841
106897
  const min = Math.min(...headingDepths);
106842
106898
  const ast = hastscript_lib_h('ul');
@@ -106854,7 +106910,7 @@ const tocToHast = (headings = []) => {
106854
106910
  stack.pop();
106855
106911
  }
106856
106912
  if (heading.properties) {
106857
- const content = lib_plain({ type: 'root', children: heading.children });
106913
+ const content = lib_plain({ type: 'root', children: heading.children }, { variables: flatVars });
106858
106914
  stack[stack.length - 1].children.push(hastscript_lib_h('li', null, hastscript_lib_h('a', { href: `#${heading.properties.id}` }, content)));
106859
106915
  }
106860
106916
  });
@@ -106864,8 +106920,12 @@ const tocToHast = (headings = []) => {
106864
106920
  * `tocHastToMdx` is a utility for combining `TocList`s of a root document and
106865
106921
  * any child components it may have. Once combined it will generate a markdown
106866
106922
  * doc representing a table of contents.
106923
+ *
106924
+ * @param toc - The list of TOC elements
106925
+ * @param components - Custom components that may contain headings
106926
+ * @param variables - Optional user variables for resolving Variable nodes in headings
106867
106927
  */
106868
- const tocHastToMdx = (toc, components) => {
106928
+ const tocHastToMdx = (toc, components, variables) => {
106869
106929
  if (typeof toc === 'undefined')
106870
106930
  return '';
106871
106931
  const injected = toc.flatMap(node => {
@@ -106874,7 +106934,7 @@ const tocHastToMdx = (toc, components) => {
106874
106934
  }
106875
106935
  return node;
106876
106936
  });
106877
- const tocHast = tocToHast(injected);
106937
+ const tocHast = tocToHast(injected, variables);
106878
106938
  return lib_mdx({ type: 'root', children: [tocHast] }, { hast: true });
106879
106939
  };
106880
106940
 
@@ -113733,6 +113793,61 @@ function restoreCodeBlocks(content, protectedCode) {
113733
113793
  return protectedCode.codeBlocks[parseInt(idx, 10)];
113734
113794
  });
113735
113795
  }
113796
+ /**
113797
+ * Escapes unbalanced braces in content to prevent MDX expression parsing errors.
113798
+ * Handles: already-escaped braces, string literals inside expressions, nested balanced braces.
113799
+ */
113800
+ function escapeUnbalancedBraces(content) {
113801
+ const opens = [];
113802
+ const unbalanced = new Set();
113803
+ let strDelim = null;
113804
+ let strEscaped = false;
113805
+ for (let i = 0; i < content.length; i += 1) {
113806
+ const ch = content[i];
113807
+ // Track strings inside expressions to ignore braces within them
113808
+ if (opens.length > 0) {
113809
+ if (strDelim) {
113810
+ if (strEscaped)
113811
+ strEscaped = false;
113812
+ else if (ch === '\\')
113813
+ strEscaped = true;
113814
+ else if (ch === strDelim)
113815
+ strDelim = null;
113816
+ // eslint-disable-next-line no-continue
113817
+ continue;
113818
+ }
113819
+ if (ch === '"' || ch === "'" || ch === '`') {
113820
+ strDelim = ch;
113821
+ // eslint-disable-next-line no-continue
113822
+ continue;
113823
+ }
113824
+ }
113825
+ // Skip already-escaped braces (count preceding backslashes)
113826
+ if (ch === '{' || ch === '}') {
113827
+ let bs = 0;
113828
+ for (let j = i - 1; j >= 0 && content[j] === '\\'; j -= 1)
113829
+ bs += 1;
113830
+ if (bs % 2 === 1) {
113831
+ // eslint-disable-next-line no-continue
113832
+ continue;
113833
+ }
113834
+ }
113835
+ if (ch === '{')
113836
+ opens.push(i);
113837
+ else if (ch === '}') {
113838
+ if (opens.length > 0)
113839
+ opens.pop();
113840
+ else
113841
+ unbalanced.add(i);
113842
+ }
113843
+ }
113844
+ opens.forEach(pos => unbalanced.add(pos));
113845
+ if (unbalanced.size === 0)
113846
+ return content;
113847
+ return Array.from(content)
113848
+ .map((ch, i) => (unbalanced.has(i) ? `\\${ch}` : ch))
113849
+ .join('');
113850
+ }
113736
113851
  /**
113737
113852
  * Converts JSX attribute expressions (attribute={expression}) to HTML attributes (attribute="value").
113738
113853
  * Handles style objects (camelCase → kebab-case), className → class, and JSON stringifies objects.
@@ -113849,7 +113964,9 @@ function preprocessJSXExpressions(content, context = {}) {
113849
113964
  // For inline expressions, we use a library to parse the expression & evaluate it later
113850
113965
  // For attribute expressions, it was difficult to use a library to parse them, so do it manually
113851
113966
  processed = evaluateAttributeExpressions(processed, context, protectedCode);
113852
- // Step 4: Restore protected code blocks
113967
+ // Step 4: Escape unbalanced braces to prevent MDX expression parsing errors
113968
+ processed = escapeUnbalancedBraces(processed);
113969
+ // Step 5: Restore protected code blocks
113853
113970
  processed = restoreProtectedCodes(processed, protectedCode);
113854
113971
  return processed;
113855
113972
  }
@@ -115644,7 +115761,7 @@ function buildRMDXModule(content, headings, tocHast, opts) {
115644
115761
  * @see {@link https://github.com/readmeio/rmdx/blob/main/docs/mdxish-flow.md}
115645
115762
  */
115646
115763
  const renderMdxish = (tree, opts = {}) => {
115647
- const { components: userComponents = {}, ...contextOpts } = opts;
115764
+ const { components: userComponents = {}, variables, ...contextOpts } = opts;
115648
115765
  const components = {
115649
115766
  ...loadComponents(),
115650
115767
  ...userComponents,
@@ -115653,8 +115770,8 @@ const renderMdxish = (tree, opts = {}) => {
115653
115770
  const componentsForRehype = exportComponentsForRehype(components);
115654
115771
  const processor = createRehypeReactProcessor(componentsForRehype);
115655
115772
  const content = processor.stringify(tree);
115656
- const tocHast = headings.length > 0 ? tocToHast(headings) : null;
115657
- return buildRMDXModule(content, headings, tocHast, contextOpts);
115773
+ const tocHast = headings.length > 0 ? tocToHast(headings, variables) : null;
115774
+ return buildRMDXModule(content, headings, tocHast, { ...contextOpts, variables });
115658
115775
  };
115659
115776
  /* harmony default export */ const lib_renderMdxish = (renderMdxish);
115660
115777
 
@@ -115764,7 +115881,7 @@ const run_run = (string, _opts = {}) => {
115764
115881
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
115765
115882
  const { Toc: _Toc, toc, default: Content, stylesheet, ...exports } = exec(string);
115766
115883
  let Toc;
115767
- const tocMdx = tocHastToMdx(toc, tocsByTag);
115884
+ const tocMdx = tocHastToMdx(toc, tocsByTag, variables);
115768
115885
  if (tocMdx) {
115769
115886
  const compiledToc = lib_compile(tocMdx);
115770
115887
  const tocModule = exec(compiledToc, { useMDXComponents: () => ({ p: Fragment }) });
@@ -115825,13 +115942,26 @@ const mdxishTags_tags = (doc) => {
115825
115942
 
115826
115943
 
115827
115944
 
115945
+
115946
+
115947
+
115828
115948
  /**
115829
115949
  * Removes Markdown and MDX comments.
115830
115950
  */
115831
- async function stripComments(doc, { mdx } = {}) {
115951
+ async function stripComments(doc, { mdx, mdxish } = {}) {
115832
115952
  const { replaced, blocks } = extractMagicBlocks(doc);
115833
- const processor = unified()
115953
+ const processor = unified();
115954
+ // we still require these two extensions because:
115955
+ // 1. we can rely on remarkMdx to parse MDXish
115956
+ // 2. we need to parse JSX comments into mdxTextExpression nodes so that the transformers can pick them up
115957
+ if (mdxish) {
115958
+ processor
115959
+ .data('micromarkExtensions', [mdxExpression({ allowEmpty: true })])
115960
+ .data('fromMarkdownExtensions', [mdxExpressionFromMarkdown()]);
115961
+ }
115962
+ processor
115834
115963
  .use(remarkParse)
115964
+ .use(normalize_malformed_md_syntax)
115835
115965
  .use(mdx ? remarkMdx : undefined)
115836
115966
  .use(stripCommentsTransformer)
115837
115967
  .use(remarkStringify, mdx
@@ -115851,8 +115981,14 @@ async function stripComments(doc, { mdx } = {}) {
115851
115981
  // Preserve tight sibling code blocks without adding extra newlines between them.
115852
115982
  // Our markdown renderer uses this to group these code blocks into a tabbed interface.
115853
115983
  (left, right) => {
115854
- // 0 = no newline between blocks
115855
- return left.type === 'code' && right.type === 'code' ? 0 : undefined;
115984
+ if (left.type === 'code' && right.type === 'code') {
115985
+ const isTight = left.position &&
115986
+ right.position &&
115987
+ right.position.start.line - left.position.end.line === 1; // Are the blocks on adjacent lines?
115988
+ // 0 = no newline between blocks
115989
+ return isTight ? 0 : undefined;
115990
+ }
115991
+ return undefined;
115856
115992
  },
115857
115993
  ],
115858
115994
  });