@readme/markdown 13.1.3 → 13.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.
package/dist/main.js
CHANGED
|
@@ -70954,13 +70954,15 @@ const scanForClosingTag = (parent, startIndex, tag) => {
|
|
|
70954
70954
|
if (isClosingTag(siblingValue, tag)) {
|
|
70955
70955
|
return { closingIndex: i, extraClosingChildren: [] };
|
|
70956
70956
|
}
|
|
70957
|
-
// Embedded closing tag (closing tag
|
|
70957
|
+
// Embedded closing tag (closing tag within HTML block content)
|
|
70958
70958
|
if (siblingValue.includes(closingTagStr)) {
|
|
70959
|
-
const
|
|
70959
|
+
const closeTagPos = siblingValue.indexOf(closingTagStr);
|
|
70960
|
+
const contentBeforeClose = siblingValue.substring(0, closeTagPos).trim();
|
|
70961
|
+
const contentAfterClose = siblingValue.substring(closeTagPos + closingTagStr.length).trim();
|
|
70960
70962
|
const extraChildren = contentBeforeClose
|
|
70961
70963
|
? parseMdChildren(contentBeforeClose)
|
|
70962
70964
|
: [];
|
|
70963
|
-
return { closingIndex: i, extraClosingChildren: extraChildren };
|
|
70965
|
+
return { closingIndex: i, extraClosingChildren: extraChildren, contentAfterClose: contentAfterClose || undefined };
|
|
70964
70966
|
}
|
|
70965
70967
|
}
|
|
70966
70968
|
// Check paragraph siblings
|
|
@@ -71105,7 +71107,7 @@ const mdxishComponentBlocks = () => tree => {
|
|
|
71105
71107
|
const scanResult = scanForClosingTag(parent, index, tag);
|
|
71106
71108
|
if (!scanResult)
|
|
71107
71109
|
return;
|
|
71108
|
-
const { closingIndex, extraClosingChildren, strippedParagraph } = scanResult;
|
|
71110
|
+
const { closingIndex, extraClosingChildren, strippedParagraph, contentAfterClose: remainingAfterClose } = scanResult;
|
|
71109
71111
|
const extraChildren = contentAfterTag ? parseMdChildren(contentAfterTag.trimStart()) : [];
|
|
71110
71112
|
// Collect all intermediate siblings between opening tag and closing tag
|
|
71111
71113
|
const intermediateChildren = parent.children.slice(index + 1, closingIndex);
|
|
@@ -71128,6 +71130,11 @@ const mdxishComponentBlocks = () => tree => {
|
|
|
71128
71130
|
if (componentNode.children.length > 0) {
|
|
71129
71131
|
stack.push(componentNode);
|
|
71130
71132
|
}
|
|
71133
|
+
// If the closing tag sibling had content after it (e.g., another component opening tag),
|
|
71134
|
+
// re-insert it as a sibling so it can be processed in subsequent iterations
|
|
71135
|
+
if (remainingAfterClose) {
|
|
71136
|
+
parseSibling(stack, parent, index, remainingAfterClose);
|
|
71137
|
+
}
|
|
71131
71138
|
};
|
|
71132
71139
|
// Process the nodes with the components depth-first to maintain the correct order of the nodes
|
|
71133
71140
|
while (stack.length) {
|
|
@@ -93444,7 +93451,7 @@ function isActualHtmlTag(tagName, originalExcerpt) {
|
|
|
93444
93451
|
return false;
|
|
93445
93452
|
}
|
|
93446
93453
|
/** Parse and replace text children with processed markdown */
|
|
93447
|
-
function parseTextChildren(node, processMarkdown) {
|
|
93454
|
+
function parseTextChildren(node, processMarkdown, components) {
|
|
93448
93455
|
if (!node.children?.length)
|
|
93449
93456
|
return;
|
|
93450
93457
|
// First pass: Recursively process text children as they may contain stringified markdown / mdx content
|
|
@@ -93459,6 +93466,27 @@ function parseTextChildren(node, processMarkdown) {
|
|
|
93459
93466
|
}
|
|
93460
93467
|
return children;
|
|
93461
93468
|
});
|
|
93469
|
+
// Unwrap <p> elements whose meaningful children are ALL components.
|
|
93470
|
+
// The markdown parser wraps inline content in <p> tags, but when that content
|
|
93471
|
+
// is actually component children (e.g., <Tab> inside <Tabs>), the wrapper
|
|
93472
|
+
// should be removed so components appear as direct children.
|
|
93473
|
+
// Only unwrap when every non-whitespace, non-br child is a known component
|
|
93474
|
+
// to avoid breaking paragraphs with mixed content (text + inline HTML like <code>).
|
|
93475
|
+
node.children = node.children.flatMap(child => {
|
|
93476
|
+
if (child.type !== 'element' || child.tagName !== 'p')
|
|
93477
|
+
return [child];
|
|
93478
|
+
const meaningfulChildren = child.children.filter(gc => {
|
|
93479
|
+
if (gc.type === 'text' && !gc.value.trim())
|
|
93480
|
+
return false;
|
|
93481
|
+
if (gc.type === 'element' && gc.tagName === 'br')
|
|
93482
|
+
return false;
|
|
93483
|
+
return true;
|
|
93484
|
+
});
|
|
93485
|
+
const allComponents = meaningfulChildren.length > 0 && meaningfulChildren.every(gc => gc.type === 'element' && getComponentName(gc.tagName, components));
|
|
93486
|
+
if (!allComponents)
|
|
93487
|
+
return [child];
|
|
93488
|
+
return meaningfulChildren;
|
|
93489
|
+
});
|
|
93462
93490
|
// Post-processing: remove whitespace-only text nodes if all siblings are components
|
|
93463
93491
|
// This prevents whitespace between component children from being counted as extra children
|
|
93464
93492
|
if (areAllChildrenComponents(node.children)) {
|
|
@@ -93513,7 +93541,7 @@ const rehypeMdxishComponents = ({ components, processMarkdown }) => {
|
|
|
93513
93541
|
}
|
|
93514
93542
|
node.tagName = componentName;
|
|
93515
93543
|
normalizeProperties(node);
|
|
93516
|
-
parseTextChildren(node, processMarkdown);
|
|
93544
|
+
parseTextChildren(node, processMarkdown, components);
|
|
93517
93545
|
});
|
|
93518
93546
|
// Remove unknown components in reverse order to preserve indices
|
|
93519
93547
|
for (let i = nodesToRemove.length - 1; i >= 0; i -= 1) {
|
|
@@ -93814,8 +93842,10 @@ function escapeUnbalancedBraces(content) {
|
|
|
93814
93842
|
const unbalanced = new Set();
|
|
93815
93843
|
let strDelim = null;
|
|
93816
93844
|
let strEscaped = false;
|
|
93817
|
-
|
|
93818
|
-
|
|
93845
|
+
// Convert to array of Unicode code points to handle emojis and multi-byte characters correctly
|
|
93846
|
+
const chars = Array.from(content);
|
|
93847
|
+
for (let i = 0; i < chars.length; i += 1) {
|
|
93848
|
+
const ch = chars[i];
|
|
93819
93849
|
// Track strings inside expressions to ignore braces within them
|
|
93820
93850
|
if (opens.length > 0) {
|
|
93821
93851
|
if (strDelim) {
|
|
@@ -93837,7 +93867,7 @@ function escapeUnbalancedBraces(content) {
|
|
|
93837
93867
|
// Skip already-escaped braces (count preceding backslashes)
|
|
93838
93868
|
if (ch === '{' || ch === '}') {
|
|
93839
93869
|
let bs = 0;
|
|
93840
|
-
for (let j = i - 1; j >= 0 &&
|
|
93870
|
+
for (let j = i - 1; j >= 0 && chars[j] === '\\'; j -= 1)
|
|
93841
93871
|
bs += 1;
|
|
93842
93872
|
if (bs % 2 === 1) {
|
|
93843
93873
|
// eslint-disable-next-line no-continue
|
|
@@ -93856,7 +93886,7 @@ function escapeUnbalancedBraces(content) {
|
|
|
93856
93886
|
opens.forEach(pos => unbalanced.add(pos));
|
|
93857
93887
|
if (unbalanced.size === 0)
|
|
93858
93888
|
return content;
|
|
93859
|
-
return
|
|
93889
|
+
return chars
|
|
93860
93890
|
.map((ch, i) => (unbalanced.has(i) ? `\\${ch}` : ch))
|
|
93861
93891
|
.join('');
|
|
93862
93892
|
}
|
|
@@ -94001,9 +94031,12 @@ const evaluateExpressions = ({ context = {} } = {}) => tree => {
|
|
|
94001
94031
|
}
|
|
94002
94032
|
catch (_error) {
|
|
94003
94033
|
// If evaluation fails, leave the expression as-is (fallback to text)
|
|
94034
|
+
// we still need to manually escape escaped characters because the expression
|
|
94035
|
+
// parser treats the contents as code instead of text, skipping the backslash escapes
|
|
94036
|
+
const processed = expression.replace(/\\([!-/:-@[-`{-~])/g, '$1');
|
|
94004
94037
|
parent.children.splice(index, 1, {
|
|
94005
94038
|
type: 'text',
|
|
94006
|
-
value: `{${
|
|
94039
|
+
value: `{${processed}}`,
|
|
94007
94040
|
position: node.position,
|
|
94008
94041
|
});
|
|
94009
94042
|
}
|
|
@@ -94096,11 +94129,11 @@ const MARKER_PATTERNS = [
|
|
|
94096
94129
|
// trailingSpace1 is for "** text **" pattern, trailingSpace2 is for "**text **" pattern
|
|
94097
94130
|
const asteriskBoldRegex = /([^*\s]+)?\s*(\*\*)(?:\s+((?:[^*\n]|\*(?!\*))+?)(\s*)\2|((?:[^*\n]|\*(?!\*))+?)(\s+)\2)(\S|$)?/g;
|
|
94098
94131
|
// Pattern for __ bold __
|
|
94099
|
-
const underscoreBoldRegex = /([^_\s]+)?\s*(__)(?:\s+((?:[^_\n]
|
|
94132
|
+
const underscoreBoldRegex = /([^_\s]+)?\s*(__)(?:\s+((?:__(?! )|_(?!_)|[^_\n])+?)(\s*)\2|((?:__(?! )|_(?!_)|[^_\n])+?)(\s+)\2)(\S|$)?/g;
|
|
94100
94133
|
// Pattern for * italic *
|
|
94101
94134
|
const asteriskItalicRegex = /([^*\s]+)?\s*(\*)(?!\*)(?:\s+([^*\n]+?)(\s*)\2|([^*\n]+?)(\s+)\2)(\S|$)?/g;
|
|
94102
94135
|
// Pattern for _ italic _
|
|
94103
|
-
const underscoreItalicRegex = /([^_\s]+)?\s*(_)(?!_)(?:\s+([^_\n]+?)(\s*)\2|([^_\n]+?)(\s+)\2)(\S|$)?/g;
|
|
94136
|
+
const underscoreItalicRegex = /([^_\s]+)?\s*(_)(?!_)(?:\s+((?:[^_\n]|_(?! ))+?)(\s*)\2|((?:[^_\n]|_(?! ))+?)(\s+)\2)(\S|$)?/g;
|
|
94104
94137
|
// CommonMark ignores intraword underscores or asteriks, but we want to italicize/bold the inner part
|
|
94105
94138
|
// Pattern for intraword _word_ in words like hello_world_
|
|
94106
94139
|
const intrawordUnderscoreItalicRegex = /(\w)_(?!_)([a-zA-Z0-9]+)_(?![\w_])/g;
|
|
@@ -95824,6 +95857,9 @@ const restoreBooleanProperties = () => tree => {
|
|
|
95824
95857
|
|
|
95825
95858
|
const STANDALONE_HTML_LINE_REGEX = /^(<[a-z][^<>]*>|<\/[a-z][^<>]*>)+\s*$/;
|
|
95826
95859
|
const HTML_LINE_WITH_CONTENT_REGEX = /^<[a-z][^<>]*>.*<\/[a-z][^<>]*>(?:[^<]*)$/;
|
|
95860
|
+
function isLineHtml(line) {
|
|
95861
|
+
return STANDALONE_HTML_LINE_REGEX.test(line) || HTML_LINE_WITH_CONTENT_REGEX.test(line);
|
|
95862
|
+
}
|
|
95827
95863
|
/**
|
|
95828
95864
|
* Preprocessor to terminate HTML flow blocks.
|
|
95829
95865
|
*
|
|
@@ -95835,14 +95871,14 @@ const HTML_LINE_WITH_CONTENT_REGEX = /^<[a-z][^<>]*>.*<\/[a-z][^<>]*>(?:[^<]*)$/
|
|
|
95835
95871
|
* @link https://spec.commonmark.org/0.29/#html-blocks
|
|
95836
95872
|
*
|
|
95837
95873
|
* This preprocessor inserts a blank line after standalone HTML lines when the
|
|
95838
|
-
* next line is non-blank
|
|
95839
|
-
* and subsequent content is parsed independently.
|
|
95874
|
+
* next line is non-blank and not an HTML construct (because they still might be part of the HTML flow),
|
|
95875
|
+
* ensuring micromark's HTML flow tokenizer terminates and subsequent content is parsed independently.
|
|
95840
95876
|
*
|
|
95841
|
-
*
|
|
95877
|
+
* Conditions:
|
|
95878
|
+
* 1. Only targets non-indented lines with lowercase tag names. Uppercase tags
|
|
95842
95879
|
* (e.g., `<Table>`, `<MyComponent>`) are JSX custom components and don't
|
|
95843
95880
|
* trigger CommonMark HTML blocks, so they are left untouched.
|
|
95844
|
-
*
|
|
95845
|
-
* Lines inside fenced code blocks are skipped entirely.
|
|
95881
|
+
* 2. Lines inside protected blocks (e.g., code blocks) should be left untouched.
|
|
95846
95882
|
*/
|
|
95847
95883
|
function terminateHtmlFlowBlocks(content) {
|
|
95848
95884
|
const { protectedContent, protectedCode } = protectCodeBlocks(content);
|
|
@@ -95850,9 +95886,14 @@ function terminateHtmlFlowBlocks(content) {
|
|
|
95850
95886
|
const result = [];
|
|
95851
95887
|
for (let i = 0; i < lines.length; i += 1) {
|
|
95852
95888
|
result.push(lines[i]);
|
|
95853
|
-
|
|
95854
|
-
|
|
95855
|
-
|
|
95889
|
+
// Skip blank & indented lines
|
|
95890
|
+
if (i >= lines.length - 1 || lines[i + 1].trim().length === 0 || lines[i + 1].startsWith(' ') || lines[i + 1].startsWith('\t')) {
|
|
95891
|
+
// eslint-disable-next-line no-continue
|
|
95892
|
+
continue;
|
|
95893
|
+
}
|
|
95894
|
+
const isCurrentLineHtml = isLineHtml(lines[i]);
|
|
95895
|
+
const isNextLineHtml = isLineHtml(lines[i + 1]);
|
|
95896
|
+
if (isCurrentLineHtml && !isNextLineHtml) {
|
|
95856
95897
|
result.push('');
|
|
95857
95898
|
}
|
|
95858
95899
|
}
|
|
@@ -97836,7 +97877,8 @@ async function stripComments(doc, { mdx, mdxish } = {}) {
|
|
|
97836
97877
|
if (mdxish) {
|
|
97837
97878
|
processor
|
|
97838
97879
|
.data('micromarkExtensions', [mdxExpression({ allowEmpty: true })])
|
|
97839
|
-
.data('fromMarkdownExtensions', [mdxExpressionFromMarkdown()])
|
|
97880
|
+
.data('fromMarkdownExtensions', [mdxExpressionFromMarkdown()])
|
|
97881
|
+
.data('toMarkdownExtensions', [mdxExpressionToMarkdown()]);
|
|
97840
97882
|
}
|
|
97841
97883
|
processor
|
|
97842
97884
|
.use(remarkParse)
|
|
@@ -97861,9 +97903,7 @@ async function stripComments(doc, { mdx, mdxish } = {}) {
|
|
|
97861
97903
|
// Our markdown renderer uses this to group these code blocks into a tabbed interface.
|
|
97862
97904
|
(left, right) => {
|
|
97863
97905
|
if (left.type === 'code' && right.type === 'code') {
|
|
97864
|
-
const isTight = left.position &&
|
|
97865
|
-
right.position &&
|
|
97866
|
-
right.position.start.line - left.position.end.line === 1; // Are the blocks on adjacent lines?
|
|
97906
|
+
const isTight = left.position && right.position && right.position.start.line - left.position.end.line === 1; // Are the blocks on adjacent lines?
|
|
97867
97907
|
// 0 = no newline between blocks
|
|
97868
97908
|
return isTight ? 0 : undefined;
|
|
97869
97909
|
}
|
package/dist/main.node.js
CHANGED
|
@@ -91158,13 +91158,15 @@ const scanForClosingTag = (parent, startIndex, tag) => {
|
|
|
91158
91158
|
if (isClosingTag(siblingValue, tag)) {
|
|
91159
91159
|
return { closingIndex: i, extraClosingChildren: [] };
|
|
91160
91160
|
}
|
|
91161
|
-
// Embedded closing tag (closing tag
|
|
91161
|
+
// Embedded closing tag (closing tag within HTML block content)
|
|
91162
91162
|
if (siblingValue.includes(closingTagStr)) {
|
|
91163
|
-
const
|
|
91163
|
+
const closeTagPos = siblingValue.indexOf(closingTagStr);
|
|
91164
|
+
const contentBeforeClose = siblingValue.substring(0, closeTagPos).trim();
|
|
91165
|
+
const contentAfterClose = siblingValue.substring(closeTagPos + closingTagStr.length).trim();
|
|
91164
91166
|
const extraChildren = contentBeforeClose
|
|
91165
91167
|
? parseMdChildren(contentBeforeClose)
|
|
91166
91168
|
: [];
|
|
91167
|
-
return { closingIndex: i, extraClosingChildren: extraChildren };
|
|
91169
|
+
return { closingIndex: i, extraClosingChildren: extraChildren, contentAfterClose: contentAfterClose || undefined };
|
|
91168
91170
|
}
|
|
91169
91171
|
}
|
|
91170
91172
|
// Check paragraph siblings
|
|
@@ -91309,7 +91311,7 @@ const mdxishComponentBlocks = () => tree => {
|
|
|
91309
91311
|
const scanResult = scanForClosingTag(parent, index, tag);
|
|
91310
91312
|
if (!scanResult)
|
|
91311
91313
|
return;
|
|
91312
|
-
const { closingIndex, extraClosingChildren, strippedParagraph } = scanResult;
|
|
91314
|
+
const { closingIndex, extraClosingChildren, strippedParagraph, contentAfterClose: remainingAfterClose } = scanResult;
|
|
91313
91315
|
const extraChildren = contentAfterTag ? parseMdChildren(contentAfterTag.trimStart()) : [];
|
|
91314
91316
|
// Collect all intermediate siblings between opening tag and closing tag
|
|
91315
91317
|
const intermediateChildren = parent.children.slice(index + 1, closingIndex);
|
|
@@ -91332,6 +91334,11 @@ const mdxishComponentBlocks = () => tree => {
|
|
|
91332
91334
|
if (componentNode.children.length > 0) {
|
|
91333
91335
|
stack.push(componentNode);
|
|
91334
91336
|
}
|
|
91337
|
+
// If the closing tag sibling had content after it (e.g., another component opening tag),
|
|
91338
|
+
// re-insert it as a sibling so it can be processed in subsequent iterations
|
|
91339
|
+
if (remainingAfterClose) {
|
|
91340
|
+
parseSibling(stack, parent, index, remainingAfterClose);
|
|
91341
|
+
}
|
|
91335
91342
|
};
|
|
91336
91343
|
// Process the nodes with the components depth-first to maintain the correct order of the nodes
|
|
91337
91344
|
while (stack.length) {
|
|
@@ -113648,7 +113655,7 @@ function isActualHtmlTag(tagName, originalExcerpt) {
|
|
|
113648
113655
|
return false;
|
|
113649
113656
|
}
|
|
113650
113657
|
/** Parse and replace text children with processed markdown */
|
|
113651
|
-
function parseTextChildren(node, processMarkdown) {
|
|
113658
|
+
function parseTextChildren(node, processMarkdown, components) {
|
|
113652
113659
|
if (!node.children?.length)
|
|
113653
113660
|
return;
|
|
113654
113661
|
// First pass: Recursively process text children as they may contain stringified markdown / mdx content
|
|
@@ -113663,6 +113670,27 @@ function parseTextChildren(node, processMarkdown) {
|
|
|
113663
113670
|
}
|
|
113664
113671
|
return children;
|
|
113665
113672
|
});
|
|
113673
|
+
// Unwrap <p> elements whose meaningful children are ALL components.
|
|
113674
|
+
// The markdown parser wraps inline content in <p> tags, but when that content
|
|
113675
|
+
// is actually component children (e.g., <Tab> inside <Tabs>), the wrapper
|
|
113676
|
+
// should be removed so components appear as direct children.
|
|
113677
|
+
// Only unwrap when every non-whitespace, non-br child is a known component
|
|
113678
|
+
// to avoid breaking paragraphs with mixed content (text + inline HTML like <code>).
|
|
113679
|
+
node.children = node.children.flatMap(child => {
|
|
113680
|
+
if (child.type !== 'element' || child.tagName !== 'p')
|
|
113681
|
+
return [child];
|
|
113682
|
+
const meaningfulChildren = child.children.filter(gc => {
|
|
113683
|
+
if (gc.type === 'text' && !gc.value.trim())
|
|
113684
|
+
return false;
|
|
113685
|
+
if (gc.type === 'element' && gc.tagName === 'br')
|
|
113686
|
+
return false;
|
|
113687
|
+
return true;
|
|
113688
|
+
});
|
|
113689
|
+
const allComponents = meaningfulChildren.length > 0 && meaningfulChildren.every(gc => gc.type === 'element' && getComponentName(gc.tagName, components));
|
|
113690
|
+
if (!allComponents)
|
|
113691
|
+
return [child];
|
|
113692
|
+
return meaningfulChildren;
|
|
113693
|
+
});
|
|
113666
113694
|
// Post-processing: remove whitespace-only text nodes if all siblings are components
|
|
113667
113695
|
// This prevents whitespace between component children from being counted as extra children
|
|
113668
113696
|
if (areAllChildrenComponents(node.children)) {
|
|
@@ -113717,7 +113745,7 @@ const rehypeMdxishComponents = ({ components, processMarkdown }) => {
|
|
|
113717
113745
|
}
|
|
113718
113746
|
node.tagName = componentName;
|
|
113719
113747
|
normalizeProperties(node);
|
|
113720
|
-
parseTextChildren(node, processMarkdown);
|
|
113748
|
+
parseTextChildren(node, processMarkdown, components);
|
|
113721
113749
|
});
|
|
113722
113750
|
// Remove unknown components in reverse order to preserve indices
|
|
113723
113751
|
for (let i = nodesToRemove.length - 1; i >= 0; i -= 1) {
|
|
@@ -114018,8 +114046,10 @@ function escapeUnbalancedBraces(content) {
|
|
|
114018
114046
|
const unbalanced = new Set();
|
|
114019
114047
|
let strDelim = null;
|
|
114020
114048
|
let strEscaped = false;
|
|
114021
|
-
|
|
114022
|
-
|
|
114049
|
+
// Convert to array of Unicode code points to handle emojis and multi-byte characters correctly
|
|
114050
|
+
const chars = Array.from(content);
|
|
114051
|
+
for (let i = 0; i < chars.length; i += 1) {
|
|
114052
|
+
const ch = chars[i];
|
|
114023
114053
|
// Track strings inside expressions to ignore braces within them
|
|
114024
114054
|
if (opens.length > 0) {
|
|
114025
114055
|
if (strDelim) {
|
|
@@ -114041,7 +114071,7 @@ function escapeUnbalancedBraces(content) {
|
|
|
114041
114071
|
// Skip already-escaped braces (count preceding backslashes)
|
|
114042
114072
|
if (ch === '{' || ch === '}') {
|
|
114043
114073
|
let bs = 0;
|
|
114044
|
-
for (let j = i - 1; j >= 0 &&
|
|
114074
|
+
for (let j = i - 1; j >= 0 && chars[j] === '\\'; j -= 1)
|
|
114045
114075
|
bs += 1;
|
|
114046
114076
|
if (bs % 2 === 1) {
|
|
114047
114077
|
// eslint-disable-next-line no-continue
|
|
@@ -114060,7 +114090,7 @@ function escapeUnbalancedBraces(content) {
|
|
|
114060
114090
|
opens.forEach(pos => unbalanced.add(pos));
|
|
114061
114091
|
if (unbalanced.size === 0)
|
|
114062
114092
|
return content;
|
|
114063
|
-
return
|
|
114093
|
+
return chars
|
|
114064
114094
|
.map((ch, i) => (unbalanced.has(i) ? `\\${ch}` : ch))
|
|
114065
114095
|
.join('');
|
|
114066
114096
|
}
|
|
@@ -114205,9 +114235,12 @@ const evaluateExpressions = ({ context = {} } = {}) => tree => {
|
|
|
114205
114235
|
}
|
|
114206
114236
|
catch (_error) {
|
|
114207
114237
|
// If evaluation fails, leave the expression as-is (fallback to text)
|
|
114238
|
+
// we still need to manually escape escaped characters because the expression
|
|
114239
|
+
// parser treats the contents as code instead of text, skipping the backslash escapes
|
|
114240
|
+
const processed = expression.replace(/\\([!-/:-@[-`{-~])/g, '$1');
|
|
114208
114241
|
parent.children.splice(index, 1, {
|
|
114209
114242
|
type: 'text',
|
|
114210
|
-
value: `{${
|
|
114243
|
+
value: `{${processed}}`,
|
|
114211
114244
|
position: node.position,
|
|
114212
114245
|
});
|
|
114213
114246
|
}
|
|
@@ -114300,11 +114333,11 @@ const MARKER_PATTERNS = [
|
|
|
114300
114333
|
// trailingSpace1 is for "** text **" pattern, trailingSpace2 is for "**text **" pattern
|
|
114301
114334
|
const asteriskBoldRegex = /([^*\s]+)?\s*(\*\*)(?:\s+((?:[^*\n]|\*(?!\*))+?)(\s*)\2|((?:[^*\n]|\*(?!\*))+?)(\s+)\2)(\S|$)?/g;
|
|
114302
114335
|
// Pattern for __ bold __
|
|
114303
|
-
const underscoreBoldRegex = /([^_\s]+)?\s*(__)(?:\s+((?:[^_\n]
|
|
114336
|
+
const underscoreBoldRegex = /([^_\s]+)?\s*(__)(?:\s+((?:__(?! )|_(?!_)|[^_\n])+?)(\s*)\2|((?:__(?! )|_(?!_)|[^_\n])+?)(\s+)\2)(\S|$)?/g;
|
|
114304
114337
|
// Pattern for * italic *
|
|
114305
114338
|
const asteriskItalicRegex = /([^*\s]+)?\s*(\*)(?!\*)(?:\s+([^*\n]+?)(\s*)\2|([^*\n]+?)(\s+)\2)(\S|$)?/g;
|
|
114306
114339
|
// Pattern for _ italic _
|
|
114307
|
-
const underscoreItalicRegex = /([^_\s]+)?\s*(_)(?!_)(?:\s+([^_\n]+?)(\s*)\2|([^_\n]+?)(\s+)\2)(\S|$)?/g;
|
|
114340
|
+
const underscoreItalicRegex = /([^_\s]+)?\s*(_)(?!_)(?:\s+((?:[^_\n]|_(?! ))+?)(\s*)\2|((?:[^_\n]|_(?! ))+?)(\s+)\2)(\S|$)?/g;
|
|
114308
114341
|
// CommonMark ignores intraword underscores or asteriks, but we want to italicize/bold the inner part
|
|
114309
114342
|
// Pattern for intraword _word_ in words like hello_world_
|
|
114310
114343
|
const intrawordUnderscoreItalicRegex = /(\w)_(?!_)([a-zA-Z0-9]+)_(?![\w_])/g;
|
|
@@ -116028,6 +116061,9 @@ const restoreBooleanProperties = () => tree => {
|
|
|
116028
116061
|
|
|
116029
116062
|
const STANDALONE_HTML_LINE_REGEX = /^(<[a-z][^<>]*>|<\/[a-z][^<>]*>)+\s*$/;
|
|
116030
116063
|
const HTML_LINE_WITH_CONTENT_REGEX = /^<[a-z][^<>]*>.*<\/[a-z][^<>]*>(?:[^<]*)$/;
|
|
116064
|
+
function isLineHtml(line) {
|
|
116065
|
+
return STANDALONE_HTML_LINE_REGEX.test(line) || HTML_LINE_WITH_CONTENT_REGEX.test(line);
|
|
116066
|
+
}
|
|
116031
116067
|
/**
|
|
116032
116068
|
* Preprocessor to terminate HTML flow blocks.
|
|
116033
116069
|
*
|
|
@@ -116039,14 +116075,14 @@ const HTML_LINE_WITH_CONTENT_REGEX = /^<[a-z][^<>]*>.*<\/[a-z][^<>]*>(?:[^<]*)$/
|
|
|
116039
116075
|
* @link https://spec.commonmark.org/0.29/#html-blocks
|
|
116040
116076
|
*
|
|
116041
116077
|
* This preprocessor inserts a blank line after standalone HTML lines when the
|
|
116042
|
-
* next line is non-blank
|
|
116043
|
-
* and subsequent content is parsed independently.
|
|
116078
|
+
* next line is non-blank and not an HTML construct (because they still might be part of the HTML flow),
|
|
116079
|
+
* ensuring micromark's HTML flow tokenizer terminates and subsequent content is parsed independently.
|
|
116044
116080
|
*
|
|
116045
|
-
*
|
|
116081
|
+
* Conditions:
|
|
116082
|
+
* 1. Only targets non-indented lines with lowercase tag names. Uppercase tags
|
|
116046
116083
|
* (e.g., `<Table>`, `<MyComponent>`) are JSX custom components and don't
|
|
116047
116084
|
* trigger CommonMark HTML blocks, so they are left untouched.
|
|
116048
|
-
*
|
|
116049
|
-
* Lines inside fenced code blocks are skipped entirely.
|
|
116085
|
+
* 2. Lines inside protected blocks (e.g., code blocks) should be left untouched.
|
|
116050
116086
|
*/
|
|
116051
116087
|
function terminateHtmlFlowBlocks(content) {
|
|
116052
116088
|
const { protectedContent, protectedCode } = protectCodeBlocks(content);
|
|
@@ -116054,9 +116090,14 @@ function terminateHtmlFlowBlocks(content) {
|
|
|
116054
116090
|
const result = [];
|
|
116055
116091
|
for (let i = 0; i < lines.length; i += 1) {
|
|
116056
116092
|
result.push(lines[i]);
|
|
116057
|
-
|
|
116058
|
-
|
|
116059
|
-
|
|
116093
|
+
// Skip blank & indented lines
|
|
116094
|
+
if (i >= lines.length - 1 || lines[i + 1].trim().length === 0 || lines[i + 1].startsWith(' ') || lines[i + 1].startsWith('\t')) {
|
|
116095
|
+
// eslint-disable-next-line no-continue
|
|
116096
|
+
continue;
|
|
116097
|
+
}
|
|
116098
|
+
const isCurrentLineHtml = isLineHtml(lines[i]);
|
|
116099
|
+
const isNextLineHtml = isLineHtml(lines[i + 1]);
|
|
116100
|
+
if (isCurrentLineHtml && !isNextLineHtml) {
|
|
116060
116101
|
result.push('');
|
|
116061
116102
|
}
|
|
116062
116103
|
}
|
|
@@ -118040,7 +118081,8 @@ async function stripComments(doc, { mdx, mdxish } = {}) {
|
|
|
118040
118081
|
if (mdxish) {
|
|
118041
118082
|
processor
|
|
118042
118083
|
.data('micromarkExtensions', [mdxExpression({ allowEmpty: true })])
|
|
118043
|
-
.data('fromMarkdownExtensions', [mdxExpressionFromMarkdown()])
|
|
118084
|
+
.data('fromMarkdownExtensions', [mdxExpressionFromMarkdown()])
|
|
118085
|
+
.data('toMarkdownExtensions', [mdxExpressionToMarkdown()]);
|
|
118044
118086
|
}
|
|
118045
118087
|
processor
|
|
118046
118088
|
.use(remarkParse)
|
|
@@ -118065,9 +118107,7 @@ async function stripComments(doc, { mdx, mdxish } = {}) {
|
|
|
118065
118107
|
// Our markdown renderer uses this to group these code blocks into a tabbed interface.
|
|
118066
118108
|
(left, right) => {
|
|
118067
118109
|
if (left.type === 'code' && right.type === 'code') {
|
|
118068
|
-
const isTight = left.position &&
|
|
118069
|
-
right.position &&
|
|
118070
|
-
right.position.start.line - left.position.end.line === 1; // Are the blocks on adjacent lines?
|
|
118110
|
+
const isTight = left.position && right.position && right.position.start.line - left.position.end.line === 1; // Are the blocks on adjacent lines?
|
|
118071
118111
|
// 0 = no newline between blocks
|
|
118072
118112
|
return isTight ? 0 : undefined;
|
|
118073
118113
|
}
|