@readme/markdown 14.10.0 → 14.10.2
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/lib/render-diff/differ.d.ts +49 -0
- package/dist/lib/render-diff/index.d.ts +2 -0
- package/dist/lib/render-diff/types.d.ts +119 -0
- package/dist/lib/render-fixture/index.d.ts +19 -0
- package/dist/lib/render-fixture/loadFixture.d.ts +21 -0
- package/dist/lib/render-fixture/renderFixture.d.ts +17 -0
- package/dist/main.js +119 -7
- package/dist/main.node.js +119 -7
- package/dist/main.node.js.map +1 -1
- package/dist/render-diff.node.js +3568 -0
- package/dist/render-diff.node.js.map +1 -0
- package/dist/render-fixture.css +6 -0
- package/dist/render-fixture.css.map +1 -0
- package/dist/render-fixture.node.js +126418 -0
- package/dist/render-fixture.node.js.map +1 -0
- package/package.json +30 -2
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,43 @@ 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
|
+
};
|
|
121977
|
+
/**
|
|
121978
|
+
* Build a position ending right after the last occurrence of `closingTag` within
|
|
121979
|
+
* this node's span in the original source. Used in the trailing-content path so
|
|
121980
|
+
* the offset is computed against the real source bytes (including blockquote/list
|
|
121981
|
+
* prefixes that were stripped from the html node's value).
|
|
121982
|
+
*/
|
|
121983
|
+
const positionEndingAtClosingTagInSource = (nodePosition, closingTag, source) => {
|
|
121984
|
+
if (!nodePosition?.start || !nodePosition.end)
|
|
121985
|
+
return nodePosition;
|
|
121986
|
+
const nodeSource = source.slice(nodePosition.start.offset, nodePosition.end.offset);
|
|
121987
|
+
const closingTagOffset = nodeSource.lastIndexOf(closingTag);
|
|
121988
|
+
if (closingTagOffset === -1)
|
|
121989
|
+
return nodePosition;
|
|
121990
|
+
const consumed = nodeSource.slice(0, closingTagOffset + closingTag.length);
|
|
121991
|
+
return { start: nodePosition.start, end: pointAfter(nodePosition.start, consumed) };
|
|
121992
|
+
};
|
|
121946
121993
|
/**
|
|
121947
121994
|
* Create an MdxJsxFlowElement node from component data.
|
|
121948
121995
|
*/
|
|
@@ -121986,9 +122033,10 @@ const substituteNodeWithMdxNode = (parent, index, mdxNode) => {
|
|
|
121986
122033
|
* The opening tag, content, and closing tag are all captured in one HTML node
|
|
121987
122034
|
* (guaranteed by the mdx-component tokenizer).
|
|
121988
122035
|
*/
|
|
121989
|
-
const mdxishMdxComponentBlocks = (opts = {}) => tree => {
|
|
122036
|
+
const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
121990
122037
|
const stack = [tree];
|
|
121991
122038
|
const safeMode = !!opts.safeMode;
|
|
122039
|
+
const source = file?.value ? String(file.value) : null;
|
|
121992
122040
|
const parseOpts = { preserveExpressionsAsText: safeMode };
|
|
121993
122041
|
const processChildNode = (parent, index) => {
|
|
121994
122042
|
const node = parent.children[index];
|
|
@@ -122002,10 +122050,16 @@ const mdxishMdxComponentBlocks = (opts = {}) => tree => {
|
|
|
122002
122050
|
const value = node.value;
|
|
122003
122051
|
if (node.type !== 'html' || typeof value !== 'string')
|
|
122004
122052
|
return;
|
|
122005
|
-
const
|
|
122053
|
+
const trimmed = value.trim();
|
|
122054
|
+
const parsed = parseTag(trimmed, parseOpts);
|
|
122006
122055
|
if (!parsed)
|
|
122007
122056
|
return;
|
|
122008
122057
|
const { tag, attributes, selfClosing, contentAfterTag = '' } = parsed;
|
|
122058
|
+
// Offset of `trimmed` within the (possibly whitespace-padded) html node value,
|
|
122059
|
+
// so consumed-length math maps back onto the node's real source offsets.
|
|
122060
|
+
const leadingWhitespace = value.length - value.trimStart().length;
|
|
122061
|
+
// Index right after the opening tag's `>` within `trimmed`.
|
|
122062
|
+
const openingTagEnd = trimmed.length - contentAfterTag.length;
|
|
122009
122063
|
// Skip tags that have dedicated transformers
|
|
122010
122064
|
if (GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(tag))
|
|
122011
122065
|
return;
|
|
@@ -122030,6 +122084,8 @@ const mdxishMdxComponentBlocks = (opts = {}) => tree => {
|
|
|
122030
122084
|
attributes,
|
|
122031
122085
|
children: [],
|
|
122032
122086
|
startPosition: node.position,
|
|
122087
|
+
// End at the self-closing tag, not at any trailing content.
|
|
122088
|
+
endPosition: positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd),
|
|
122033
122089
|
});
|
|
122034
122090
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
122035
122091
|
// Check and parse if there's relevant content after the current closing tag
|
|
@@ -122061,6 +122117,17 @@ const mdxishMdxComponentBlocks = (opts = {}) => tree => {
|
|
|
122061
122117
|
attributes,
|
|
122062
122118
|
children: parsedChildren,
|
|
122063
122119
|
startPosition: node.position,
|
|
122120
|
+
// When trailing content follows the closing tag, compute the end position precisely
|
|
122121
|
+
// within the html node's value so the component doesn't claim that content.
|
|
122122
|
+
// Prefer source-based positioning when the original source is available: the html
|
|
122123
|
+
// node's value has '> '/space prefixes stripped for blockquotes/list items, so
|
|
122124
|
+
// positionEndingAtConsumed would undercount source offsets. When the entire node
|
|
122125
|
+
// is consumed, use the original node position directly.
|
|
122126
|
+
endPosition: contentAfterClose
|
|
122127
|
+
? source
|
|
122128
|
+
? positionEndingAtClosingTagInSource(node.position, closingTagStr, source)
|
|
122129
|
+
: positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd + closingTagIndex + closingTagStr.length)
|
|
122130
|
+
: node.position,
|
|
122064
122131
|
});
|
|
122065
122132
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
122066
122133
|
// After the closing tag, there might be more content to be processed
|
|
@@ -124331,6 +124398,24 @@ function restoreHTMLElements(content, htmlElements) {
|
|
|
124331
124398
|
return content;
|
|
124332
124399
|
return content.replace(HTML_ELEM_PLACEHOLDER, (_m, idx) => htmlElements[parseInt(idx, 10)]);
|
|
124333
124400
|
}
|
|
124401
|
+
const ESM_DECLARATION_START = /^(?:export|import)\b/;
|
|
124402
|
+
/**
|
|
124403
|
+
* Whether a line begins a top-level `export`/`import` declaration. Its braces
|
|
124404
|
+
* are valid JS owned by the mdxjsEsm tokenizer (which tolerates blank lines),
|
|
124405
|
+
* so escaping them would corrupt the source and break acorn parsing.
|
|
124406
|
+
*/
|
|
124407
|
+
function startsEsmDeclaration(chars, lineStart) {
|
|
124408
|
+
return ESM_DECLARATION_START.test(chars.slice(lineStart, lineStart + 7).join(''));
|
|
124409
|
+
}
|
|
124410
|
+
function isBlankLine(chars, lineStart) {
|
|
124411
|
+
for (let i = lineStart; i < chars.length; i += 1) {
|
|
124412
|
+
if (chars[i] === '\n')
|
|
124413
|
+
return true;
|
|
124414
|
+
if (chars[i] !== ' ' && chars[i] !== '\t')
|
|
124415
|
+
return false;
|
|
124416
|
+
}
|
|
124417
|
+
return true;
|
|
124418
|
+
}
|
|
124334
124419
|
/**
|
|
124335
124420
|
* Escapes unbalanced and paragraph-spanning braces so MDX doesn't trip on them.
|
|
124336
124421
|
*/
|
|
@@ -124346,8 +124431,18 @@ function escapeProblematicBraces(content) {
|
|
|
124346
124431
|
// Convert to array of Unicode code points so that emojis and multi-byte characters are correctly tracked
|
|
124347
124432
|
const chars = Array.from(protectedContent);
|
|
124348
124433
|
const openStack = [];
|
|
124434
|
+
// Whether the current top-level statement is an `export`/`import` declaration.
|
|
124435
|
+
let insideEsmDeclaration = false;
|
|
124349
124436
|
for (let i = 0; i < chars.length; i += 1) {
|
|
124350
124437
|
const ch = chars[i];
|
|
124438
|
+
// At a top-level (brace depth 0) line start, decide whether we're inside an
|
|
124439
|
+
// ESM declaration. The flag persists across the declaration's own lines.
|
|
124440
|
+
if (openStack.length === 0 && (i === 0 || chars[i - 1] === '\n')) {
|
|
124441
|
+
if (startsEsmDeclaration(chars, i))
|
|
124442
|
+
insideEsmDeclaration = true;
|
|
124443
|
+
else if (isBlankLine(chars, i))
|
|
124444
|
+
insideEsmDeclaration = false;
|
|
124445
|
+
}
|
|
124351
124446
|
// Track string delimiters inside expressions to ignore braces within them
|
|
124352
124447
|
if (openStack.length > 0) {
|
|
124353
124448
|
if (strDelim) {
|
|
@@ -124405,19 +124500,22 @@ function escapeProblematicBraces(content) {
|
|
|
124405
124500
|
if (!isAttrExpr && openStack.length > 0 && openStack[openStack.length - 1].isAttrExpr) {
|
|
124406
124501
|
isAttrExpr = true;
|
|
124407
124502
|
}
|
|
124408
|
-
openStack.push({ pos: i, hasBlankLine: false, isAttrExpr });
|
|
124503
|
+
openStack.push({ pos: i, hasBlankLine: false, isAttrExpr, isEsmDeclaration: insideEsmDeclaration });
|
|
124409
124504
|
lastNewlinePos = -2;
|
|
124410
124505
|
}
|
|
124411
124506
|
else if (ch === '}') {
|
|
124412
124507
|
if (openStack.length > 0) {
|
|
124413
124508
|
const entry = openStack.pop();
|
|
124509
|
+
// The declaration's braces are closed; later top-level braces are not ESM.
|
|
124510
|
+
if (openStack.length === 0)
|
|
124511
|
+
insideEsmDeclaration = false;
|
|
124414
124512
|
// Pure `{/* ... */}` comments are handled downstream by the jsxComment
|
|
124415
124513
|
// tokenizer — escaping their braces would prevent it from running.
|
|
124416
124514
|
const isPureJsxComment = chars[entry.pos + 1] === '/' &&
|
|
124417
124515
|
chars[entry.pos + 2] === '*' &&
|
|
124418
124516
|
chars[i - 1] === '/' &&
|
|
124419
124517
|
chars[i - 2] === '*';
|
|
124420
|
-
if (entry.hasBlankLine && !isPureJsxComment && !entry.isAttrExpr) {
|
|
124518
|
+
if (entry.hasBlankLine && !isPureJsxComment && !entry.isAttrExpr && !entry.isEsmDeclaration) {
|
|
124421
124519
|
toEscape.add(entry.pos);
|
|
124422
124520
|
toEscape.add(i);
|
|
124423
124521
|
}
|
|
@@ -124426,9 +124524,16 @@ function escapeProblematicBraces(content) {
|
|
|
124426
124524
|
toEscape.add(i);
|
|
124427
124525
|
}
|
|
124428
124526
|
}
|
|
124527
|
+
else if (ch === ';' && openStack.length === 0) {
|
|
124528
|
+
// A top-level `;` ends the current statement, ESM or otherwise.
|
|
124529
|
+
insideEsmDeclaration = false;
|
|
124530
|
+
}
|
|
124429
124531
|
}
|
|
124430
124532
|
// Anything still open is unbalanced.
|
|
124431
|
-
openStack.forEach(entry =>
|
|
124533
|
+
openStack.forEach(entry => {
|
|
124534
|
+
if (!entry.isEsmDeclaration)
|
|
124535
|
+
toEscape.add(entry.pos);
|
|
124536
|
+
});
|
|
124432
124537
|
// Reconstruct the content with the escaped braces.
|
|
124433
124538
|
const escapedContent = toEscape.size === 0 ? protectedContent : chars.map((ch, i) => (toEscape.has(i) ? `\\${ch}` : ch)).join('');
|
|
124434
124539
|
return restoreHTMLElements(escapedContent, htmlElements);
|
|
@@ -125927,11 +126032,18 @@ function exportComponentsForRehype(components) {
|
|
|
125927
126032
|
* semantics). That breaks any component prop that is genuinely an array. With
|
|
125928
126033
|
* `passNode: true` we get the original hast node in `props.node` for components
|
|
125929
126034
|
* and can read the raw properties directly.
|
|
126035
|
+
*
|
|
126036
|
+
* Only arrays win over `rest`, overwriting other shapes would undo correct
|
|
126037
|
+
* React conversions like `style="color:red"` → `{ color: 'red' }`.
|
|
125930
126038
|
*/
|
|
125931
126039
|
function createElementPreservingHastProps(type, props, ...children) {
|
|
125932
126040
|
if (props?.node?.properties) {
|
|
125933
126041
|
const { node, ...rest } = props;
|
|
125934
|
-
const mergedProps = { ...rest
|
|
126042
|
+
const mergedProps = { ...rest };
|
|
126043
|
+
Object.entries(node.properties).forEach(([key, value]) => {
|
|
126044
|
+
if (Array.isArray(value))
|
|
126045
|
+
mergedProps[key] = value;
|
|
126046
|
+
});
|
|
125935
126047
|
// Strip undefined so positional args don't shadow node.properties.children
|
|
125936
126048
|
const definedChildren = children.filter(c => c !== undefined);
|
|
125937
126049
|
return external_react_default().createElement(type, mergedProps, ...definedChildren);
|