@readme/markdown 12.0.1 → 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
@@ -52879,14 +52879,57 @@ function visualizeCharacterCode(charCode) {
52879
52879
  return '0x' + charCode.toString(16).toUpperCase()
52880
52880
  }
52881
52881
 
52882
+ ;// ./processor/transform/stripComments.ts
52883
+
52884
+ const HTML_COMMENT_REGEX = /<!--[\s\S]*?-->/g;
52885
+ const MDX_COMMENT_REGEX = /\/\*(?:(?!\*\/)[\s\S])*\*\//g;
52886
+ /**
52887
+ * A remark plugin to remove comments from Markdown and MDX.
52888
+ */
52889
+ const stripCommentsTransformer = () => {
52890
+ return (tree) => {
52891
+ visit(tree, ['html', 'mdxFlowExpression', 'mdxTextExpression'], (node, index, parent) => {
52892
+ if (parent && typeof index === 'number') {
52893
+ // Remove HTML comments
52894
+ if (node.type === 'html' && HTML_COMMENT_REGEX.test(node.value)) {
52895
+ const newValue = node.value.replace(HTML_COMMENT_REGEX, '').trim();
52896
+ if (newValue) {
52897
+ node.value = newValue;
52898
+ }
52899
+ else {
52900
+ parent.children.splice(index, 1);
52901
+ return [SKIP, index];
52902
+ }
52903
+ }
52904
+ // Remove MDX comments
52905
+ if ((node.type === 'mdxFlowExpression' || node.type === 'mdxTextExpression') &&
52906
+ MDX_COMMENT_REGEX.test(node.value)) {
52907
+ const newValue = node.value.replace(MDX_COMMENT_REGEX, '').trim();
52908
+ if (newValue) {
52909
+ node.value = newValue;
52910
+ }
52911
+ else {
52912
+ parent.children.splice(index, 1);
52913
+ return [SKIP, index];
52914
+ }
52915
+ }
52916
+ }
52917
+ return undefined;
52918
+ });
52919
+ };
52920
+ };
52921
+
52882
52922
  ;// ./lib/plain.ts
52883
52923
 
52924
+
52884
52925
  const STRIP_TAGS = ['script', 'style'];
52885
52926
  function plain_one(node, opts) {
52886
52927
  if (node.type === 'comment')
52887
52928
  return '';
52888
52929
  if ('type' in node && node.type === 'text') {
52889
- return node.value;
52930
+ // Remove all MDX comments from text nodes. We need this here because we
52931
+ // don't control whether comments are parsed into comment vs text nodes.
52932
+ return node.value.replace(MDX_COMMENT_REGEX, '');
52890
52933
  }
52891
52934
  if ('tagName' in node) {
52892
52935
  if (STRIP_TAGS.includes(node.tagName))
@@ -93486,6 +93529,61 @@ function restoreCodeBlocks(content, protectedCode) {
93486
93529
  return protectedCode.codeBlocks[parseInt(idx, 10)];
93487
93530
  });
93488
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
+ }
93489
93587
  /**
93490
93588
  * Converts JSX attribute expressions (attribute={expression}) to HTML attributes (attribute="value").
93491
93589
  * Handles style objects (camelCase → kebab-case), className → class, and JSON stringifies objects.
@@ -93602,7 +93700,9 @@ function preprocessJSXExpressions(content, context = {}) {
93602
93700
  // For inline expressions, we use a library to parse the expression & evaluate it later
93603
93701
  // For attribute expressions, it was difficult to use a library to parse them, so do it manually
93604
93702
  processed = evaluateAttributeExpressions(processed, context, protectedCode);
93605
- // 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
93606
93706
  processed = restoreProtectedCodes(processed, protectedCode);
93607
93707
  return processed;
93608
93708
  }
@@ -95570,46 +95670,6 @@ const mdxishTags_tags = (doc) => {
95570
95670
  };
95571
95671
  /* harmony default export */ const mdxishTags = (mdxishTags_tags);
95572
95672
 
95573
- ;// ./processor/transform/stripComments.ts
95574
-
95575
- const HTML_COMMENT_REGEX = /<!--[\s\S]*?-->/g;
95576
- const MDX_COMMENT_REGEX = /\/\*[\s\S]*?\*\//g;
95577
- /**
95578
- * A remark plugin to remove comments from Markdown and MDX.
95579
- */
95580
- const stripCommentsTransformer = () => {
95581
- return (tree) => {
95582
- visit(tree, ['html', 'mdxFlowExpression', 'mdxTextExpression'], (node, index, parent) => {
95583
- if (parent && typeof index === 'number') {
95584
- // Remove HTML comments
95585
- if (node.type === 'html' && HTML_COMMENT_REGEX.test(node.value)) {
95586
- const newValue = node.value.replace(HTML_COMMENT_REGEX, '').trim();
95587
- if (newValue) {
95588
- node.value = newValue;
95589
- }
95590
- else {
95591
- parent.children.splice(index, 1);
95592
- return [SKIP, index];
95593
- }
95594
- }
95595
- // Remove MDX comments
95596
- if ((node.type === 'mdxFlowExpression' || node.type === 'mdxTextExpression') &&
95597
- MDX_COMMENT_REGEX.test(node.value)) {
95598
- const newValue = node.value.replace(MDX_COMMENT_REGEX, '').trim();
95599
- if (newValue) {
95600
- node.value = newValue;
95601
- }
95602
- else {
95603
- parent.children.splice(index, 1);
95604
- return [SKIP, index];
95605
- }
95606
- }
95607
- }
95608
- return undefined;
95609
- });
95610
- };
95611
- };
95612
-
95613
95673
  ;// ./lib/stripComments.ts
95614
95674
 
95615
95675
 
@@ -95618,6 +95678,7 @@ const stripCommentsTransformer = () => {
95618
95678
 
95619
95679
 
95620
95680
 
95681
+
95621
95682
  /**
95622
95683
  * Removes Markdown and MDX comments.
95623
95684
  */
@@ -95625,6 +95686,7 @@ async function stripComments(doc, { mdx } = {}) {
95625
95686
  const { replaced, blocks } = extractMagicBlocks(doc);
95626
95687
  const processor = unified()
95627
95688
  .use(remarkParse)
95689
+ .use(normalize_malformed_md_syntax)
95628
95690
  .use(mdx ? remarkMdx : undefined)
95629
95691
  .use(stripCommentsTransformer)
95630
95692
  .use(remarkStringify, mdx
package/dist/main.node.js CHANGED
@@ -73083,14 +73083,57 @@ function visualizeCharacterCode(charCode) {
73083
73083
  return '0x' + charCode.toString(16).toUpperCase()
73084
73084
  }
73085
73085
 
73086
+ ;// ./processor/transform/stripComments.ts
73087
+
73088
+ const HTML_COMMENT_REGEX = /<!--[\s\S]*?-->/g;
73089
+ const MDX_COMMENT_REGEX = /\/\*(?:(?!\*\/)[\s\S])*\*\//g;
73090
+ /**
73091
+ * A remark plugin to remove comments from Markdown and MDX.
73092
+ */
73093
+ const stripCommentsTransformer = () => {
73094
+ return (tree) => {
73095
+ visit(tree, ['html', 'mdxFlowExpression', 'mdxTextExpression'], (node, index, parent) => {
73096
+ if (parent && typeof index === 'number') {
73097
+ // Remove HTML comments
73098
+ if (node.type === 'html' && HTML_COMMENT_REGEX.test(node.value)) {
73099
+ const newValue = node.value.replace(HTML_COMMENT_REGEX, '').trim();
73100
+ if (newValue) {
73101
+ node.value = newValue;
73102
+ }
73103
+ else {
73104
+ parent.children.splice(index, 1);
73105
+ return [SKIP, index];
73106
+ }
73107
+ }
73108
+ // Remove MDX comments
73109
+ if ((node.type === 'mdxFlowExpression' || node.type === 'mdxTextExpression') &&
73110
+ MDX_COMMENT_REGEX.test(node.value)) {
73111
+ const newValue = node.value.replace(MDX_COMMENT_REGEX, '').trim();
73112
+ if (newValue) {
73113
+ node.value = newValue;
73114
+ }
73115
+ else {
73116
+ parent.children.splice(index, 1);
73117
+ return [SKIP, index];
73118
+ }
73119
+ }
73120
+ }
73121
+ return undefined;
73122
+ });
73123
+ };
73124
+ };
73125
+
73086
73126
  ;// ./lib/plain.ts
73087
73127
 
73128
+
73088
73129
  const STRIP_TAGS = ['script', 'style'];
73089
73130
  function plain_one(node, opts) {
73090
73131
  if (node.type === 'comment')
73091
73132
  return '';
73092
73133
  if ('type' in node && node.type === 'text') {
73093
- return node.value;
73134
+ // Remove all MDX comments from text nodes. We need this here because we
73135
+ // don't control whether comments are parsed into comment vs text nodes.
73136
+ return node.value.replace(MDX_COMMENT_REGEX, '');
73094
73137
  }
73095
73138
  if ('tagName' in node) {
73096
73139
  if (STRIP_TAGS.includes(node.tagName))
@@ -113690,6 +113733,61 @@ function restoreCodeBlocks(content, protectedCode) {
113690
113733
  return protectedCode.codeBlocks[parseInt(idx, 10)];
113691
113734
  });
113692
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
+ }
113693
113791
  /**
113694
113792
  * Converts JSX attribute expressions (attribute={expression}) to HTML attributes (attribute="value").
113695
113793
  * Handles style objects (camelCase → kebab-case), className → class, and JSON stringifies objects.
@@ -113806,7 +113904,9 @@ function preprocessJSXExpressions(content, context = {}) {
113806
113904
  // For inline expressions, we use a library to parse the expression & evaluate it later
113807
113905
  // For attribute expressions, it was difficult to use a library to parse them, so do it manually
113808
113906
  processed = evaluateAttributeExpressions(processed, context, protectedCode);
113809
- // 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
113810
113910
  processed = restoreProtectedCodes(processed, protectedCode);
113811
113911
  return processed;
113812
113912
  }
@@ -115774,46 +115874,6 @@ const mdxishTags_tags = (doc) => {
115774
115874
  };
115775
115875
  /* harmony default export */ const mdxishTags = (mdxishTags_tags);
115776
115876
 
115777
- ;// ./processor/transform/stripComments.ts
115778
-
115779
- const HTML_COMMENT_REGEX = /<!--[\s\S]*?-->/g;
115780
- const MDX_COMMENT_REGEX = /\/\*[\s\S]*?\*\//g;
115781
- /**
115782
- * A remark plugin to remove comments from Markdown and MDX.
115783
- */
115784
- const stripCommentsTransformer = () => {
115785
- return (tree) => {
115786
- visit(tree, ['html', 'mdxFlowExpression', 'mdxTextExpression'], (node, index, parent) => {
115787
- if (parent && typeof index === 'number') {
115788
- // Remove HTML comments
115789
- if (node.type === 'html' && HTML_COMMENT_REGEX.test(node.value)) {
115790
- const newValue = node.value.replace(HTML_COMMENT_REGEX, '').trim();
115791
- if (newValue) {
115792
- node.value = newValue;
115793
- }
115794
- else {
115795
- parent.children.splice(index, 1);
115796
- return [SKIP, index];
115797
- }
115798
- }
115799
- // Remove MDX comments
115800
- if ((node.type === 'mdxFlowExpression' || node.type === 'mdxTextExpression') &&
115801
- MDX_COMMENT_REGEX.test(node.value)) {
115802
- const newValue = node.value.replace(MDX_COMMENT_REGEX, '').trim();
115803
- if (newValue) {
115804
- node.value = newValue;
115805
- }
115806
- else {
115807
- parent.children.splice(index, 1);
115808
- return [SKIP, index];
115809
- }
115810
- }
115811
- }
115812
- return undefined;
115813
- });
115814
- };
115815
- };
115816
-
115817
115877
  ;// ./lib/stripComments.ts
115818
115878
 
115819
115879
 
@@ -115822,6 +115882,7 @@ const stripCommentsTransformer = () => {
115822
115882
 
115823
115883
 
115824
115884
 
115885
+
115825
115886
  /**
115826
115887
  * Removes Markdown and MDX comments.
115827
115888
  */
@@ -115829,6 +115890,7 @@ async function stripComments(doc, { mdx } = {}) {
115829
115890
  const { replaced, blocks } = extractMagicBlocks(doc);
115830
115891
  const processor = unified()
115831
115892
  .use(remarkParse)
115893
+ .use(normalize_malformed_md_syntax)
115832
115894
  .use(mdx ? remarkMdx : undefined)
115833
115895
  .use(stripCommentsTransformer)
115834
115896
  .use(remarkStringify, mdx