@readme/markdown 12.1.0 → 12.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -93529,6 +93529,61 @@ function restoreCodeBlocks(content, protectedCode) {
93529
93529
  return protectedCode.codeBlocks[parseInt(idx, 10)];
93530
93530
  });
93531
93531
  }
93532
+ /**
93533
+ * Escapes unbalanced braces in content to prevent MDX expression parsing errors.
93534
+ * Handles: already-escaped braces, string literals inside expressions, nested balanced braces.
93535
+ */
93536
+ function escapeUnbalancedBraces(content) {
93537
+ const opens = [];
93538
+ const unbalanced = new Set();
93539
+ let strDelim = null;
93540
+ let strEscaped = false;
93541
+ for (let i = 0; i < content.length; i += 1) {
93542
+ const ch = content[i];
93543
+ // Track strings inside expressions to ignore braces within them
93544
+ if (opens.length > 0) {
93545
+ if (strDelim) {
93546
+ if (strEscaped)
93547
+ strEscaped = false;
93548
+ else if (ch === '\\')
93549
+ strEscaped = true;
93550
+ else if (ch === strDelim)
93551
+ strDelim = null;
93552
+ // eslint-disable-next-line no-continue
93553
+ continue;
93554
+ }
93555
+ if (ch === '"' || ch === "'" || ch === '`') {
93556
+ strDelim = ch;
93557
+ // eslint-disable-next-line no-continue
93558
+ continue;
93559
+ }
93560
+ }
93561
+ // Skip already-escaped braces (count preceding backslashes)
93562
+ if (ch === '{' || ch === '}') {
93563
+ let bs = 0;
93564
+ for (let j = i - 1; j >= 0 && content[j] === '\\'; j -= 1)
93565
+ bs += 1;
93566
+ if (bs % 2 === 1) {
93567
+ // eslint-disable-next-line no-continue
93568
+ continue;
93569
+ }
93570
+ }
93571
+ if (ch === '{')
93572
+ opens.push(i);
93573
+ else if (ch === '}') {
93574
+ if (opens.length > 0)
93575
+ opens.pop();
93576
+ else
93577
+ unbalanced.add(i);
93578
+ }
93579
+ }
93580
+ opens.forEach(pos => unbalanced.add(pos));
93581
+ if (unbalanced.size === 0)
93582
+ return content;
93583
+ return Array.from(content)
93584
+ .map((ch, i) => (unbalanced.has(i) ? `\\${ch}` : ch))
93585
+ .join('');
93586
+ }
93532
93587
  /**
93533
93588
  * Converts JSX attribute expressions (attribute={expression}) to HTML attributes (attribute="value").
93534
93589
  * Handles style objects (camelCase → kebab-case), className → class, and JSON stringifies objects.
@@ -93645,7 +93700,9 @@ function preprocessJSXExpressions(content, context = {}) {
93645
93700
  // For inline expressions, we use a library to parse the expression & evaluate it later
93646
93701
  // For attribute expressions, it was difficult to use a library to parse them, so do it manually
93647
93702
  processed = evaluateAttributeExpressions(processed, context, protectedCode);
93648
- // Step 4: Restore protected code blocks
93703
+ // Step 4: Escape unbalanced braces to prevent MDX expression parsing errors
93704
+ processed = escapeUnbalancedBraces(processed);
93705
+ // Step 5: Restore protected code blocks
93649
93706
  processed = restoreProtectedCodes(processed, protectedCode);
93650
93707
  return processed;
93651
93708
  }
@@ -95621,6 +95678,7 @@ const mdxishTags_tags = (doc) => {
95621
95678
 
95622
95679
 
95623
95680
 
95681
+
95624
95682
  /**
95625
95683
  * Removes Markdown and MDX comments.
95626
95684
  */
@@ -95628,6 +95686,7 @@ async function stripComments(doc, { mdx } = {}) {
95628
95686
  const { replaced, blocks } = extractMagicBlocks(doc);
95629
95687
  const processor = unified()
95630
95688
  .use(remarkParse)
95689
+ .use(normalize_malformed_md_syntax)
95631
95690
  .use(mdx ? remarkMdx : undefined)
95632
95691
  .use(stripCommentsTransformer)
95633
95692
  .use(remarkStringify, mdx
package/dist/main.node.js CHANGED
@@ -113733,6 +113733,61 @@ function restoreCodeBlocks(content, protectedCode) {
113733
113733
  return protectedCode.codeBlocks[parseInt(idx, 10)];
113734
113734
  });
113735
113735
  }
113736
+ /**
113737
+ * Escapes unbalanced braces in content to prevent MDX expression parsing errors.
113738
+ * Handles: already-escaped braces, string literals inside expressions, nested balanced braces.
113739
+ */
113740
+ function escapeUnbalancedBraces(content) {
113741
+ const opens = [];
113742
+ const unbalanced = new Set();
113743
+ let strDelim = null;
113744
+ let strEscaped = false;
113745
+ for (let i = 0; i < content.length; i += 1) {
113746
+ const ch = content[i];
113747
+ // Track strings inside expressions to ignore braces within them
113748
+ if (opens.length > 0) {
113749
+ if (strDelim) {
113750
+ if (strEscaped)
113751
+ strEscaped = false;
113752
+ else if (ch === '\\')
113753
+ strEscaped = true;
113754
+ else if (ch === strDelim)
113755
+ strDelim = null;
113756
+ // eslint-disable-next-line no-continue
113757
+ continue;
113758
+ }
113759
+ if (ch === '"' || ch === "'" || ch === '`') {
113760
+ strDelim = ch;
113761
+ // eslint-disable-next-line no-continue
113762
+ continue;
113763
+ }
113764
+ }
113765
+ // Skip already-escaped braces (count preceding backslashes)
113766
+ if (ch === '{' || ch === '}') {
113767
+ let bs = 0;
113768
+ for (let j = i - 1; j >= 0 && content[j] === '\\'; j -= 1)
113769
+ bs += 1;
113770
+ if (bs % 2 === 1) {
113771
+ // eslint-disable-next-line no-continue
113772
+ continue;
113773
+ }
113774
+ }
113775
+ if (ch === '{')
113776
+ opens.push(i);
113777
+ else if (ch === '}') {
113778
+ if (opens.length > 0)
113779
+ opens.pop();
113780
+ else
113781
+ unbalanced.add(i);
113782
+ }
113783
+ }
113784
+ opens.forEach(pos => unbalanced.add(pos));
113785
+ if (unbalanced.size === 0)
113786
+ return content;
113787
+ return Array.from(content)
113788
+ .map((ch, i) => (unbalanced.has(i) ? `\\${ch}` : ch))
113789
+ .join('');
113790
+ }
113736
113791
  /**
113737
113792
  * Converts JSX attribute expressions (attribute={expression}) to HTML attributes (attribute="value").
113738
113793
  * Handles style objects (camelCase → kebab-case), className → class, and JSON stringifies objects.
@@ -113849,7 +113904,9 @@ function preprocessJSXExpressions(content, context = {}) {
113849
113904
  // For inline expressions, we use a library to parse the expression & evaluate it later
113850
113905
  // For attribute expressions, it was difficult to use a library to parse them, so do it manually
113851
113906
  processed = evaluateAttributeExpressions(processed, context, protectedCode);
113852
- // Step 4: Restore protected code blocks
113907
+ // Step 4: Escape unbalanced braces to prevent MDX expression parsing errors
113908
+ processed = escapeUnbalancedBraces(processed);
113909
+ // Step 5: Restore protected code blocks
113853
113910
  processed = restoreProtectedCodes(processed, protectedCode);
113854
113911
  return processed;
113855
113912
  }
@@ -115825,6 +115882,7 @@ const mdxishTags_tags = (doc) => {
115825
115882
 
115826
115883
 
115827
115884
 
115885
+
115828
115886
  /**
115829
115887
  * Removes Markdown and MDX comments.
115830
115888
  */
@@ -115832,6 +115890,7 @@ async function stripComments(doc, { mdx } = {}) {
115832
115890
  const { replaced, blocks } = extractMagicBlocks(doc);
115833
115891
  const processor = unified()
115834
115892
  .use(remarkParse)
115893
+ .use(normalize_malformed_md_syntax)
115835
115894
  .use(mdx ? remarkMdx : undefined)
115836
115895
  .use(stripCommentsTransformer)
115837
115896
  .use(remarkStringify, mdx