@readme/markdown 14.10.0 → 14.10.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 +92 -6
- package/dist/main.node.js +92 -6
- package/dist/main.node.js.map +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -76783,6 +76783,7 @@ const readmeComponents = (opts) => () => tree => {
|
|
|
76783
76783
|
|
|
76784
76784
|
|
|
76785
76785
|
|
|
76786
|
+
|
|
76786
76787
|
const imageAttrs = ['align', 'alt', 'caption', 'border', 'height', 'src', 'title', 'width', 'lazy', 'className'];
|
|
76787
76788
|
const readmeToMdx = () => tree => {
|
|
76788
76789
|
// Unwrap pinned nodes, replace rdme-pin with its child node
|
|
@@ -76873,7 +76874,11 @@ const readmeToMdx = () => tree => {
|
|
|
76873
76874
|
}
|
|
76874
76875
|
});
|
|
76875
76876
|
visit(tree, NodeTypes.imageBlock, (image, index, parent) => {
|
|
76876
|
-
|
|
76877
|
+
// Special case for caption: Captions are parsed as children of the image node, so we need to extract them explicitly
|
|
76878
|
+
const captionChildren = Array.isArray(image.children) ? image.children : [];
|
|
76879
|
+
// We want to add it back to the attributes, so re-serialize it to string
|
|
76880
|
+
const caption = captionChildren.length ? toMarkdown({ type: 'root', children: captionChildren }).trim() : '';
|
|
76881
|
+
const attributes = toAttributes({ ...image, ...image.data.hProperties, ...(caption && { caption }) }, imageAttrs);
|
|
76877
76882
|
if (hasExtra(attributes)) {
|
|
76878
76883
|
parent.children.splice(index, 1, {
|
|
76879
76884
|
type: 'mdxJsxFlowElement',
|
|
@@ -98611,6 +98616,11 @@ function smartCamelCase(str) {
|
|
|
98611
98616
|
if (str.includes('-')) {
|
|
98612
98617
|
return str.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
98613
98618
|
}
|
|
98619
|
+
// Keys that already carry casing (e.g. `cardWidth`) are correct as-is; running
|
|
98620
|
+
// boundary matching over them mangles inner matches (e.g. `id` inside `Width`).
|
|
98621
|
+
if (/[A-Z]/.test(str)) {
|
|
98622
|
+
return str;
|
|
98623
|
+
}
|
|
98614
98624
|
const allBoundaries = [...REACT_HTML_PROP_BOUNDARIES, ...CSS_STYLE_PROP_BOUNDARIES, ...CUSTOM_PROP_BOUNDARIES];
|
|
98615
98625
|
// Return as-is if already a boundary word to avoid incorrect splitting
|
|
98616
98626
|
if (allBoundaries.includes(str.toLowerCase())) {
|
|
@@ -101719,6 +101729,27 @@ const parseSibling = (stack, parent, index, sibling, safeMode) => {
|
|
|
101719
101729
|
stack.push(parent);
|
|
101720
101730
|
}
|
|
101721
101731
|
};
|
|
101732
|
+
/**
|
|
101733
|
+
* Advance a point by the substring of source consumed from it.
|
|
101734
|
+
*/
|
|
101735
|
+
const pointAfter = (start, consumed) => {
|
|
101736
|
+
const newlineIndex = consumed.lastIndexOf('\n');
|
|
101737
|
+
const newlineCount = newlineIndex === -1 ? 0 : consumed.split('\n').length - 1;
|
|
101738
|
+
return {
|
|
101739
|
+
line: start.line + newlineCount,
|
|
101740
|
+
column: newlineCount === 0 ? start.column + consumed.length : consumed.length - newlineIndex,
|
|
101741
|
+
offset: start.offset + consumed.length,
|
|
101742
|
+
};
|
|
101743
|
+
};
|
|
101744
|
+
/**
|
|
101745
|
+
* Build a position ending at `consumedLength` into the html node's value, so the
|
|
101746
|
+
* component doesn't claim trailing content the tokenizer swallowed into one node.
|
|
101747
|
+
*/
|
|
101748
|
+
const positionEndingAtConsumed = (nodePosition, value, consumedLength) => {
|
|
101749
|
+
if (!nodePosition?.start)
|
|
101750
|
+
return nodePosition;
|
|
101751
|
+
return { start: nodePosition.start, end: pointAfter(nodePosition.start, value.slice(0, consumedLength)) };
|
|
101752
|
+
};
|
|
101722
101753
|
/**
|
|
101723
101754
|
* Create an MdxJsxFlowElement node from component data.
|
|
101724
101755
|
*/
|
|
@@ -101778,10 +101809,16 @@ const mdxishMdxComponentBlocks = (opts = {}) => tree => {
|
|
|
101778
101809
|
const value = node.value;
|
|
101779
101810
|
if (node.type !== 'html' || typeof value !== 'string')
|
|
101780
101811
|
return;
|
|
101781
|
-
const
|
|
101812
|
+
const trimmed = value.trim();
|
|
101813
|
+
const parsed = parseTag(trimmed, parseOpts);
|
|
101782
101814
|
if (!parsed)
|
|
101783
101815
|
return;
|
|
101784
101816
|
const { tag, attributes, selfClosing, contentAfterTag = '' } = parsed;
|
|
101817
|
+
// Offset of `trimmed` within the (possibly whitespace-padded) html node value,
|
|
101818
|
+
// so consumed-length math maps back onto the node's real source offsets.
|
|
101819
|
+
const leadingWhitespace = value.length - value.trimStart().length;
|
|
101820
|
+
// Index right after the opening tag's `>` within `trimmed`.
|
|
101821
|
+
const openingTagEnd = trimmed.length - contentAfterTag.length;
|
|
101785
101822
|
// Skip tags that have dedicated transformers
|
|
101786
101823
|
if (GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(tag))
|
|
101787
101824
|
return;
|
|
@@ -101806,6 +101843,8 @@ const mdxishMdxComponentBlocks = (opts = {}) => tree => {
|
|
|
101806
101843
|
attributes,
|
|
101807
101844
|
children: [],
|
|
101808
101845
|
startPosition: node.position,
|
|
101846
|
+
// End at the self-closing tag, not at any trailing content.
|
|
101847
|
+
endPosition: positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd),
|
|
101809
101848
|
});
|
|
101810
101849
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
101811
101850
|
// Check and parse if there's relevant content after the current closing tag
|
|
@@ -101837,6 +101876,8 @@ const mdxishMdxComponentBlocks = (opts = {}) => tree => {
|
|
|
101837
101876
|
attributes,
|
|
101838
101877
|
children: parsedChildren,
|
|
101839
101878
|
startPosition: node.position,
|
|
101879
|
+
// End at the closing tag, not at trailing content re-parsed as siblings below.
|
|
101880
|
+
endPosition: positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd + closingTagIndex + closingTagStr.length),
|
|
101840
101881
|
});
|
|
101841
101882
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
101842
101883
|
// After the closing tag, there might be more content to be processed
|
|
@@ -104107,6 +104148,24 @@ function restoreHTMLElements(content, htmlElements) {
|
|
|
104107
104148
|
return content;
|
|
104108
104149
|
return content.replace(HTML_ELEM_PLACEHOLDER, (_m, idx) => htmlElements[parseInt(idx, 10)]);
|
|
104109
104150
|
}
|
|
104151
|
+
const ESM_DECLARATION_START = /^(?:export|import)\b/;
|
|
104152
|
+
/**
|
|
104153
|
+
* Whether a line begins a top-level `export`/`import` declaration. Its braces
|
|
104154
|
+
* are valid JS owned by the mdxjsEsm tokenizer (which tolerates blank lines),
|
|
104155
|
+
* so escaping them would corrupt the source and break acorn parsing.
|
|
104156
|
+
*/
|
|
104157
|
+
function startsEsmDeclaration(chars, lineStart) {
|
|
104158
|
+
return ESM_DECLARATION_START.test(chars.slice(lineStart, lineStart + 7).join(''));
|
|
104159
|
+
}
|
|
104160
|
+
function isBlankLine(chars, lineStart) {
|
|
104161
|
+
for (let i = lineStart; i < chars.length; i += 1) {
|
|
104162
|
+
if (chars[i] === '\n')
|
|
104163
|
+
return true;
|
|
104164
|
+
if (chars[i] !== ' ' && chars[i] !== '\t')
|
|
104165
|
+
return false;
|
|
104166
|
+
}
|
|
104167
|
+
return true;
|
|
104168
|
+
}
|
|
104110
104169
|
/**
|
|
104111
104170
|
* Escapes unbalanced and paragraph-spanning braces so MDX doesn't trip on them.
|
|
104112
104171
|
*/
|
|
@@ -104122,8 +104181,18 @@ function escapeProblematicBraces(content) {
|
|
|
104122
104181
|
// Convert to array of Unicode code points so that emojis and multi-byte characters are correctly tracked
|
|
104123
104182
|
const chars = Array.from(protectedContent);
|
|
104124
104183
|
const openStack = [];
|
|
104184
|
+
// Whether the current top-level statement is an `export`/`import` declaration.
|
|
104185
|
+
let insideEsmDeclaration = false;
|
|
104125
104186
|
for (let i = 0; i < chars.length; i += 1) {
|
|
104126
104187
|
const ch = chars[i];
|
|
104188
|
+
// At a top-level (brace depth 0) line start, decide whether we're inside an
|
|
104189
|
+
// ESM declaration. The flag persists across the declaration's own lines.
|
|
104190
|
+
if (openStack.length === 0 && (i === 0 || chars[i - 1] === '\n')) {
|
|
104191
|
+
if (startsEsmDeclaration(chars, i))
|
|
104192
|
+
insideEsmDeclaration = true;
|
|
104193
|
+
else if (isBlankLine(chars, i))
|
|
104194
|
+
insideEsmDeclaration = false;
|
|
104195
|
+
}
|
|
104127
104196
|
// Track string delimiters inside expressions to ignore braces within them
|
|
104128
104197
|
if (openStack.length > 0) {
|
|
104129
104198
|
if (strDelim) {
|
|
@@ -104181,19 +104250,22 @@ function escapeProblematicBraces(content) {
|
|
|
104181
104250
|
if (!isAttrExpr && openStack.length > 0 && openStack[openStack.length - 1].isAttrExpr) {
|
|
104182
104251
|
isAttrExpr = true;
|
|
104183
104252
|
}
|
|
104184
|
-
openStack.push({ pos: i, hasBlankLine: false, isAttrExpr });
|
|
104253
|
+
openStack.push({ pos: i, hasBlankLine: false, isAttrExpr, isEsmDeclaration: insideEsmDeclaration });
|
|
104185
104254
|
lastNewlinePos = -2;
|
|
104186
104255
|
}
|
|
104187
104256
|
else if (ch === '}') {
|
|
104188
104257
|
if (openStack.length > 0) {
|
|
104189
104258
|
const entry = openStack.pop();
|
|
104259
|
+
// The declaration's braces are closed; later top-level braces are not ESM.
|
|
104260
|
+
if (openStack.length === 0)
|
|
104261
|
+
insideEsmDeclaration = false;
|
|
104190
104262
|
// Pure `{/* ... */}` comments are handled downstream by the jsxComment
|
|
104191
104263
|
// tokenizer — escaping their braces would prevent it from running.
|
|
104192
104264
|
const isPureJsxComment = chars[entry.pos + 1] === '/' &&
|
|
104193
104265
|
chars[entry.pos + 2] === '*' &&
|
|
104194
104266
|
chars[i - 1] === '/' &&
|
|
104195
104267
|
chars[i - 2] === '*';
|
|
104196
|
-
if (entry.hasBlankLine && !isPureJsxComment && !entry.isAttrExpr) {
|
|
104268
|
+
if (entry.hasBlankLine && !isPureJsxComment && !entry.isAttrExpr && !entry.isEsmDeclaration) {
|
|
104197
104269
|
toEscape.add(entry.pos);
|
|
104198
104270
|
toEscape.add(i);
|
|
104199
104271
|
}
|
|
@@ -104202,9 +104274,16 @@ function escapeProblematicBraces(content) {
|
|
|
104202
104274
|
toEscape.add(i);
|
|
104203
104275
|
}
|
|
104204
104276
|
}
|
|
104277
|
+
else if (ch === ';' && openStack.length === 0) {
|
|
104278
|
+
// A top-level `;` ends the current statement, ESM or otherwise.
|
|
104279
|
+
insideEsmDeclaration = false;
|
|
104280
|
+
}
|
|
104205
104281
|
}
|
|
104206
104282
|
// Anything still open is unbalanced.
|
|
104207
|
-
openStack.forEach(entry =>
|
|
104283
|
+
openStack.forEach(entry => {
|
|
104284
|
+
if (!entry.isEsmDeclaration)
|
|
104285
|
+
toEscape.add(entry.pos);
|
|
104286
|
+
});
|
|
104208
104287
|
// Reconstruct the content with the escaped braces.
|
|
104209
104288
|
const escapedContent = toEscape.size === 0 ? protectedContent : chars.map((ch, i) => (toEscape.has(i) ? `\\${ch}` : ch)).join('');
|
|
104210
104289
|
return restoreHTMLElements(escapedContent, htmlElements);
|
|
@@ -105703,11 +105782,18 @@ function exportComponentsForRehype(components) {
|
|
|
105703
105782
|
* semantics). That breaks any component prop that is genuinely an array. With
|
|
105704
105783
|
* `passNode: true` we get the original hast node in `props.node` for components
|
|
105705
105784
|
* and can read the raw properties directly.
|
|
105785
|
+
*
|
|
105786
|
+
* Only arrays win over `rest`, overwriting other shapes would undo correct
|
|
105787
|
+
* React conversions like `style="color:red"` → `{ color: 'red' }`.
|
|
105706
105788
|
*/
|
|
105707
105789
|
function createElementPreservingHastProps(type, props, ...children) {
|
|
105708
105790
|
if (props?.node?.properties) {
|
|
105709
105791
|
const { node, ...rest } = props;
|
|
105710
|
-
const mergedProps = { ...rest
|
|
105792
|
+
const mergedProps = { ...rest };
|
|
105793
|
+
Object.entries(node.properties).forEach(([key, value]) => {
|
|
105794
|
+
if (Array.isArray(value))
|
|
105795
|
+
mergedProps[key] = value;
|
|
105796
|
+
});
|
|
105711
105797
|
// Strip undefined so positional args don't shadow node.properties.children
|
|
105712
105798
|
const definedChildren = children.filter(c => c !== undefined);
|
|
105713
105799
|
return external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement(type, mergedProps, ...definedChildren);
|
package/dist/main.node.js
CHANGED
|
@@ -97007,6 +97007,7 @@ const readmeComponents = (opts) => () => tree => {
|
|
|
97007
97007
|
|
|
97008
97008
|
|
|
97009
97009
|
|
|
97010
|
+
|
|
97010
97011
|
const imageAttrs = ['align', 'alt', 'caption', 'border', 'height', 'src', 'title', 'width', 'lazy', 'className'];
|
|
97011
97012
|
const readmeToMdx = () => tree => {
|
|
97012
97013
|
// Unwrap pinned nodes, replace rdme-pin with its child node
|
|
@@ -97097,7 +97098,11 @@ const readmeToMdx = () => tree => {
|
|
|
97097
97098
|
}
|
|
97098
97099
|
});
|
|
97099
97100
|
visit(tree, NodeTypes.imageBlock, (image, index, parent) => {
|
|
97100
|
-
|
|
97101
|
+
// Special case for caption: Captions are parsed as children of the image node, so we need to extract them explicitly
|
|
97102
|
+
const captionChildren = Array.isArray(image.children) ? image.children : [];
|
|
97103
|
+
// We want to add it back to the attributes, so re-serialize it to string
|
|
97104
|
+
const caption = captionChildren.length ? toMarkdown({ type: 'root', children: captionChildren }).trim() : '';
|
|
97105
|
+
const attributes = toAttributes({ ...image, ...image.data.hProperties, ...(caption && { caption }) }, imageAttrs);
|
|
97101
97106
|
if (hasExtra(attributes)) {
|
|
97102
97107
|
parent.children.splice(index, 1, {
|
|
97103
97108
|
type: 'mdxJsxFlowElement',
|
|
@@ -118835,6 +118840,11 @@ function smartCamelCase(str) {
|
|
|
118835
118840
|
if (str.includes('-')) {
|
|
118836
118841
|
return str.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
118837
118842
|
}
|
|
118843
|
+
// Keys that already carry casing (e.g. `cardWidth`) are correct as-is; running
|
|
118844
|
+
// boundary matching over them mangles inner matches (e.g. `id` inside `Width`).
|
|
118845
|
+
if (/[A-Z]/.test(str)) {
|
|
118846
|
+
return str;
|
|
118847
|
+
}
|
|
118838
118848
|
const allBoundaries = [...REACT_HTML_PROP_BOUNDARIES, ...CSS_STYLE_PROP_BOUNDARIES, ...CUSTOM_PROP_BOUNDARIES];
|
|
118839
118849
|
// Return as-is if already a boundary word to avoid incorrect splitting
|
|
118840
118850
|
if (allBoundaries.includes(str.toLowerCase())) {
|
|
@@ -121943,6 +121953,27 @@ const parseSibling = (stack, parent, index, sibling, safeMode) => {
|
|
|
121943
121953
|
stack.push(parent);
|
|
121944
121954
|
}
|
|
121945
121955
|
};
|
|
121956
|
+
/**
|
|
121957
|
+
* Advance a point by the substring of source consumed from it.
|
|
121958
|
+
*/
|
|
121959
|
+
const pointAfter = (start, consumed) => {
|
|
121960
|
+
const newlineIndex = consumed.lastIndexOf('\n');
|
|
121961
|
+
const newlineCount = newlineIndex === -1 ? 0 : consumed.split('\n').length - 1;
|
|
121962
|
+
return {
|
|
121963
|
+
line: start.line + newlineCount,
|
|
121964
|
+
column: newlineCount === 0 ? start.column + consumed.length : consumed.length - newlineIndex,
|
|
121965
|
+
offset: start.offset + consumed.length,
|
|
121966
|
+
};
|
|
121967
|
+
};
|
|
121968
|
+
/**
|
|
121969
|
+
* Build a position ending at `consumedLength` into the html node's value, so the
|
|
121970
|
+
* component doesn't claim trailing content the tokenizer swallowed into one node.
|
|
121971
|
+
*/
|
|
121972
|
+
const positionEndingAtConsumed = (nodePosition, value, consumedLength) => {
|
|
121973
|
+
if (!nodePosition?.start)
|
|
121974
|
+
return nodePosition;
|
|
121975
|
+
return { start: nodePosition.start, end: pointAfter(nodePosition.start, value.slice(0, consumedLength)) };
|
|
121976
|
+
};
|
|
121946
121977
|
/**
|
|
121947
121978
|
* Create an MdxJsxFlowElement node from component data.
|
|
121948
121979
|
*/
|
|
@@ -122002,10 +122033,16 @@ const mdxishMdxComponentBlocks = (opts = {}) => tree => {
|
|
|
122002
122033
|
const value = node.value;
|
|
122003
122034
|
if (node.type !== 'html' || typeof value !== 'string')
|
|
122004
122035
|
return;
|
|
122005
|
-
const
|
|
122036
|
+
const trimmed = value.trim();
|
|
122037
|
+
const parsed = parseTag(trimmed, parseOpts);
|
|
122006
122038
|
if (!parsed)
|
|
122007
122039
|
return;
|
|
122008
122040
|
const { tag, attributes, selfClosing, contentAfterTag = '' } = parsed;
|
|
122041
|
+
// Offset of `trimmed` within the (possibly whitespace-padded) html node value,
|
|
122042
|
+
// so consumed-length math maps back onto the node's real source offsets.
|
|
122043
|
+
const leadingWhitespace = value.length - value.trimStart().length;
|
|
122044
|
+
// Index right after the opening tag's `>` within `trimmed`.
|
|
122045
|
+
const openingTagEnd = trimmed.length - contentAfterTag.length;
|
|
122009
122046
|
// Skip tags that have dedicated transformers
|
|
122010
122047
|
if (GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(tag))
|
|
122011
122048
|
return;
|
|
@@ -122030,6 +122067,8 @@ const mdxishMdxComponentBlocks = (opts = {}) => tree => {
|
|
|
122030
122067
|
attributes,
|
|
122031
122068
|
children: [],
|
|
122032
122069
|
startPosition: node.position,
|
|
122070
|
+
// End at the self-closing tag, not at any trailing content.
|
|
122071
|
+
endPosition: positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd),
|
|
122033
122072
|
});
|
|
122034
122073
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
122035
122074
|
// Check and parse if there's relevant content after the current closing tag
|
|
@@ -122061,6 +122100,8 @@ const mdxishMdxComponentBlocks = (opts = {}) => tree => {
|
|
|
122061
122100
|
attributes,
|
|
122062
122101
|
children: parsedChildren,
|
|
122063
122102
|
startPosition: node.position,
|
|
122103
|
+
// End at the closing tag, not at trailing content re-parsed as siblings below.
|
|
122104
|
+
endPosition: positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd + closingTagIndex + closingTagStr.length),
|
|
122064
122105
|
});
|
|
122065
122106
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
122066
122107
|
// After the closing tag, there might be more content to be processed
|
|
@@ -124331,6 +124372,24 @@ function restoreHTMLElements(content, htmlElements) {
|
|
|
124331
124372
|
return content;
|
|
124332
124373
|
return content.replace(HTML_ELEM_PLACEHOLDER, (_m, idx) => htmlElements[parseInt(idx, 10)]);
|
|
124333
124374
|
}
|
|
124375
|
+
const ESM_DECLARATION_START = /^(?:export|import)\b/;
|
|
124376
|
+
/**
|
|
124377
|
+
* Whether a line begins a top-level `export`/`import` declaration. Its braces
|
|
124378
|
+
* are valid JS owned by the mdxjsEsm tokenizer (which tolerates blank lines),
|
|
124379
|
+
* so escaping them would corrupt the source and break acorn parsing.
|
|
124380
|
+
*/
|
|
124381
|
+
function startsEsmDeclaration(chars, lineStart) {
|
|
124382
|
+
return ESM_DECLARATION_START.test(chars.slice(lineStart, lineStart + 7).join(''));
|
|
124383
|
+
}
|
|
124384
|
+
function isBlankLine(chars, lineStart) {
|
|
124385
|
+
for (let i = lineStart; i < chars.length; i += 1) {
|
|
124386
|
+
if (chars[i] === '\n')
|
|
124387
|
+
return true;
|
|
124388
|
+
if (chars[i] !== ' ' && chars[i] !== '\t')
|
|
124389
|
+
return false;
|
|
124390
|
+
}
|
|
124391
|
+
return true;
|
|
124392
|
+
}
|
|
124334
124393
|
/**
|
|
124335
124394
|
* Escapes unbalanced and paragraph-spanning braces so MDX doesn't trip on them.
|
|
124336
124395
|
*/
|
|
@@ -124346,8 +124405,18 @@ function escapeProblematicBraces(content) {
|
|
|
124346
124405
|
// Convert to array of Unicode code points so that emojis and multi-byte characters are correctly tracked
|
|
124347
124406
|
const chars = Array.from(protectedContent);
|
|
124348
124407
|
const openStack = [];
|
|
124408
|
+
// Whether the current top-level statement is an `export`/`import` declaration.
|
|
124409
|
+
let insideEsmDeclaration = false;
|
|
124349
124410
|
for (let i = 0; i < chars.length; i += 1) {
|
|
124350
124411
|
const ch = chars[i];
|
|
124412
|
+
// At a top-level (brace depth 0) line start, decide whether we're inside an
|
|
124413
|
+
// ESM declaration. The flag persists across the declaration's own lines.
|
|
124414
|
+
if (openStack.length === 0 && (i === 0 || chars[i - 1] === '\n')) {
|
|
124415
|
+
if (startsEsmDeclaration(chars, i))
|
|
124416
|
+
insideEsmDeclaration = true;
|
|
124417
|
+
else if (isBlankLine(chars, i))
|
|
124418
|
+
insideEsmDeclaration = false;
|
|
124419
|
+
}
|
|
124351
124420
|
// Track string delimiters inside expressions to ignore braces within them
|
|
124352
124421
|
if (openStack.length > 0) {
|
|
124353
124422
|
if (strDelim) {
|
|
@@ -124405,19 +124474,22 @@ function escapeProblematicBraces(content) {
|
|
|
124405
124474
|
if (!isAttrExpr && openStack.length > 0 && openStack[openStack.length - 1].isAttrExpr) {
|
|
124406
124475
|
isAttrExpr = true;
|
|
124407
124476
|
}
|
|
124408
|
-
openStack.push({ pos: i, hasBlankLine: false, isAttrExpr });
|
|
124477
|
+
openStack.push({ pos: i, hasBlankLine: false, isAttrExpr, isEsmDeclaration: insideEsmDeclaration });
|
|
124409
124478
|
lastNewlinePos = -2;
|
|
124410
124479
|
}
|
|
124411
124480
|
else if (ch === '}') {
|
|
124412
124481
|
if (openStack.length > 0) {
|
|
124413
124482
|
const entry = openStack.pop();
|
|
124483
|
+
// The declaration's braces are closed; later top-level braces are not ESM.
|
|
124484
|
+
if (openStack.length === 0)
|
|
124485
|
+
insideEsmDeclaration = false;
|
|
124414
124486
|
// Pure `{/* ... */}` comments are handled downstream by the jsxComment
|
|
124415
124487
|
// tokenizer — escaping their braces would prevent it from running.
|
|
124416
124488
|
const isPureJsxComment = chars[entry.pos + 1] === '/' &&
|
|
124417
124489
|
chars[entry.pos + 2] === '*' &&
|
|
124418
124490
|
chars[i - 1] === '/' &&
|
|
124419
124491
|
chars[i - 2] === '*';
|
|
124420
|
-
if (entry.hasBlankLine && !isPureJsxComment && !entry.isAttrExpr) {
|
|
124492
|
+
if (entry.hasBlankLine && !isPureJsxComment && !entry.isAttrExpr && !entry.isEsmDeclaration) {
|
|
124421
124493
|
toEscape.add(entry.pos);
|
|
124422
124494
|
toEscape.add(i);
|
|
124423
124495
|
}
|
|
@@ -124426,9 +124498,16 @@ function escapeProblematicBraces(content) {
|
|
|
124426
124498
|
toEscape.add(i);
|
|
124427
124499
|
}
|
|
124428
124500
|
}
|
|
124501
|
+
else if (ch === ';' && openStack.length === 0) {
|
|
124502
|
+
// A top-level `;` ends the current statement, ESM or otherwise.
|
|
124503
|
+
insideEsmDeclaration = false;
|
|
124504
|
+
}
|
|
124429
124505
|
}
|
|
124430
124506
|
// Anything still open is unbalanced.
|
|
124431
|
-
openStack.forEach(entry =>
|
|
124507
|
+
openStack.forEach(entry => {
|
|
124508
|
+
if (!entry.isEsmDeclaration)
|
|
124509
|
+
toEscape.add(entry.pos);
|
|
124510
|
+
});
|
|
124432
124511
|
// Reconstruct the content with the escaped braces.
|
|
124433
124512
|
const escapedContent = toEscape.size === 0 ? protectedContent : chars.map((ch, i) => (toEscape.has(i) ? `\\${ch}` : ch)).join('');
|
|
124434
124513
|
return restoreHTMLElements(escapedContent, htmlElements);
|
|
@@ -125927,11 +126006,18 @@ function exportComponentsForRehype(components) {
|
|
|
125927
126006
|
* semantics). That breaks any component prop that is genuinely an array. With
|
|
125928
126007
|
* `passNode: true` we get the original hast node in `props.node` for components
|
|
125929
126008
|
* and can read the raw properties directly.
|
|
126009
|
+
*
|
|
126010
|
+
* Only arrays win over `rest`, overwriting other shapes would undo correct
|
|
126011
|
+
* React conversions like `style="color:red"` → `{ color: 'red' }`.
|
|
125930
126012
|
*/
|
|
125931
126013
|
function createElementPreservingHastProps(type, props, ...children) {
|
|
125932
126014
|
if (props?.node?.properties) {
|
|
125933
126015
|
const { node, ...rest } = props;
|
|
125934
|
-
const mergedProps = { ...rest
|
|
126016
|
+
const mergedProps = { ...rest };
|
|
126017
|
+
Object.entries(node.properties).forEach(([key, value]) => {
|
|
126018
|
+
if (Array.isArray(value))
|
|
126019
|
+
mergedProps[key] = value;
|
|
126020
|
+
});
|
|
125935
126021
|
// Strip undefined so positional args don't shadow node.properties.children
|
|
125936
126022
|
const definedChildren = children.filter(c => c !== undefined);
|
|
125937
126023
|
return external_react_default().createElement(type, mergedProps, ...definedChildren);
|