@readme/markdown 15.0.2 → 15.1.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/components/Callout/style.scss +6 -6
- package/components/Cards/style.scss +2 -2
- package/components/Glossary/index.tsx +5 -0
- package/components/Glossary/style.scss +5 -3
- package/components/Image/style.scss +2 -2
- package/dist/main.css +2 -2
- package/dist/main.css.map +1 -1
- package/dist/main.js +103 -34
- package/dist/main.node.js +103 -34
- package/dist/main.node.js.map +1 -1
- package/dist/render-fixture.css +1 -1
- package/dist/render-fixture.css.map +1 -1
- package/dist/render-fixture.node.js +103 -34
- package/dist/render-fixture.node.js.map +1 -1
- package/package.json +1 -1
- package/styles/mixins/dark-mode.scss +13 -0
- package/styles/mixins/when-color-mode-dark.scss +48 -0
package/dist/main.node.js
CHANGED
|
@@ -24807,6 +24807,9 @@ const GlossaryContext = (0,external_react_.createContext)([]);
|
|
|
24807
24807
|
|
|
24808
24808
|
|
|
24809
24809
|
|
|
24810
|
+
/** Tippy portals to document.body by default, which would break the
|
|
24811
|
+
* `.rm-ReadMe[data-color-mode] …` descendant selectors in style.scss. */
|
|
24812
|
+
const appendToReadMeRoot = (ref) => ref.closest('.rm-ReadMe') ?? document.body;
|
|
24810
24813
|
const Glossary = ({ children, term: termProp, terms }) => {
|
|
24811
24814
|
const term = (Array.isArray(children) ? children[0] : children) || termProp;
|
|
24812
24815
|
if (!term)
|
|
@@ -24814,7 +24817,7 @@ const Glossary = ({ children, term: termProp, terms }) => {
|
|
|
24814
24817
|
const foundTerm = terms.find(i => term.toLowerCase() === i?.term?.toLowerCase());
|
|
24815
24818
|
if (!foundTerm)
|
|
24816
24819
|
return external_react_default().createElement("span", null, term);
|
|
24817
|
-
return (external_react_default().createElement(tippy_react_esm, { content: external_react_default().createElement("div", { className: "GlossaryItem-tooltip-content" },
|
|
24820
|
+
return (external_react_default().createElement(tippy_react_esm, { appendTo: appendToReadMeRoot, content: external_react_default().createElement("div", { className: "GlossaryItem-tooltip-content" },
|
|
24818
24821
|
external_react_default().createElement("strong", { className: "GlossaryItem-term" }, foundTerm.term),
|
|
24819
24822
|
" - ",
|
|
24820
24823
|
foundTerm.definition), offset: [-5, 5], placement: "bottom-start" },
|
|
@@ -97297,13 +97300,36 @@ const MARKER_PATTERNS = [
|
|
|
97297
97300
|
// Pattern for ** bold **
|
|
97298
97301
|
// Groups: 1=wordBefore, 2=marker, 3=contentWithSpaceAfter, 4=trailingSpace1, 5=contentWithSpaceBefore, 6=trailingSpace2, 7=afterChar
|
|
97299
97302
|
// trailingSpace1 is for "** text **" pattern, trailingSpace2 is for "**text **" pattern
|
|
97300
|
-
|
|
97303
|
+
//
|
|
97304
|
+
// The wordBefore and whitespace prefixes are deliberately bounded ({1,64} /
|
|
97305
|
+
// {0,8}) rather than unbounded (+ / *). An unbounded prefix makes matchAll
|
|
97306
|
+
// re-scan an arbitrarily long run from every character position, which turns
|
|
97307
|
+
// the pass O(n²) on text nodes containing huge unbroken tokens (pasted base64
|
|
97308
|
+
// payloads, minified code). Bounding the prefix caps the backtracking per
|
|
97309
|
+
// position; a prefix longer than the bound just starts the match later, and
|
|
97310
|
+
// the cut-off chars flow into the preceding text node instead — adjacent text
|
|
97311
|
+
// parts are merged before splicing, so the emitted AST is unchanged.
|
|
97312
|
+
//
|
|
97313
|
+
// The content quantifiers are bounded too ({1,500}). The underscore content
|
|
97314
|
+
// clauses can scan across `_` (needed for snake_case content), so without a
|
|
97315
|
+
// bound every `_` in a marker-dense token (base64url, snake_case identifiers)
|
|
97316
|
+
// re-scans to end-of-line looking for a closer — O(n²) again. Content already
|
|
97317
|
+
// can't cross a newline, and 500 chars covers any sentence-length emphasis
|
|
97318
|
+
// phrase; longer spans stay unnormalized rather than costing quadratic scans.
|
|
97319
|
+
const asteriskBoldRegex = /([^*\s]{1,64})?\s{0,8}(\*\*)(?:\s+((?:[^*\n]|\*(?!\*)){1,500}?)(\s*)\2|((?:[^*\n]|\*(?!\*)){1,500}?)(\s+)\2)(\S|$)?/g;
|
|
97301
97320
|
// Pattern for __ bold __
|
|
97302
|
-
const underscoreBoldRegex = /([^_\s]
|
|
97321
|
+
const underscoreBoldRegex = /([^_\s]{1,64})?\s{0,8}(__)(?:\s+((?:__(?! )|_(?!_)|[^_\n]){1,500}?)(\s*)\2|((?:__(?! )|_(?!_)|[^_\n]){1,500}?)(\s+)\2)(\S|$)?/g;
|
|
97303
97322
|
// Pattern for * italic *
|
|
97304
|
-
const asteriskItalicRegex = /([^*\s]
|
|
97323
|
+
const asteriskItalicRegex = /([^*\s]{1,64})?\s{0,8}(\*)(?!\*)(?:\s+([^*\n]{1,500}?)(\s*)\2|([^*\n]{1,500}?)(\s+)\2)(\S|$)?/g;
|
|
97305
97324
|
// Pattern for _ italic _
|
|
97306
|
-
const underscoreItalicRegex = /([^_\s]
|
|
97325
|
+
const underscoreItalicRegex = /([^_\s]{1,64})?\s{0,8}(_)(?!_)(?:\s+((?:[^_\n]|_(?! )){1,500}?)(\s*)\2|((?:[^_\n]|_(?! )){1,500}?)(\s+)\2)(\S|$)?/g;
|
|
97326
|
+
// Every loose alternation requires whitespace beside a marker — after the
|
|
97327
|
+
// opening (`** text**`) or before the closing (`**text **`) — so
|
|
97328
|
+
// marker-beside-whitespace is an exact gate for the loose families. A single
|
|
97329
|
+
// linear probe skips them entirely on marker-dense tokens whose markers are
|
|
97330
|
+
// all intraword (base64url payloads, snake_case identifiers).
|
|
97331
|
+
const asteriskBesideWhitespaceRegex = /\*\s|\s\*/;
|
|
97332
|
+
const underscoreBesideWhitespaceRegex = /_\s|\s_/;
|
|
97307
97333
|
// CommonMark ignores intraword underscores or asteriks, but we want to italicize/bold the inner part
|
|
97308
97334
|
// Pattern for intraword _word_ in words like hello_world_
|
|
97309
97335
|
const intrawordUnderscoreItalicRegex = /(\w)_(?!_)([a-zA-Z0-9]+)_(?![\w_])/g;
|
|
@@ -97313,6 +97339,23 @@ const intrawordUnderscoreBoldRegex = /(\w)__([a-zA-Z0-9]+)__(?![\w_])/g;
|
|
|
97313
97339
|
const intrawordAsteriskItalicRegex = /(\w)\*(?!\*)([a-zA-Z0-9]+)\*(?![\w*])/g;
|
|
97314
97340
|
// Pattern for intraword **word** in words like hello**world**
|
|
97315
97341
|
const intrawordAsteriskBoldRegex = /(\w)\*\*([a-zA-Z0-9]+)\*\*(?![\w*])/g;
|
|
97342
|
+
// All regex families, in match-precedence order: collected matches are
|
|
97343
|
+
// stable-sorted by match.index, so at an equal index the earlier row wins the
|
|
97344
|
+
// overlap filter — keep this order. `gate` names the per-node precondition
|
|
97345
|
+
// (see the gate record in the visitor) checked before the family's regex
|
|
97346
|
+
// runs, so a node that can't possibly match never pays for a full scan: the
|
|
97347
|
+
// intraword families need their marker character present, and the loose
|
|
97348
|
+
// families additionally need that marker beside whitespace.
|
|
97349
|
+
const REGEX_FAMILIES = [
|
|
97350
|
+
{ regex: asteriskBoldRegex, isBold: true, marker: '**', gate: 'asteriskLoose' },
|
|
97351
|
+
{ regex: underscoreBoldRegex, isBold: true, marker: '__', gate: 'underscoreLoose' },
|
|
97352
|
+
{ regex: asteriskItalicRegex, isBold: false, marker: '*', gate: 'asteriskLoose' },
|
|
97353
|
+
{ regex: underscoreItalicRegex, isBold: false, marker: '_', gate: 'underscoreLoose' },
|
|
97354
|
+
{ regex: intrawordUnderscoreItalicRegex, isBold: false, isIntraword: true, marker: '_', gate: 'underscore' },
|
|
97355
|
+
{ regex: intrawordUnderscoreBoldRegex, isBold: true, isIntraword: true, marker: '__', gate: 'underscore' },
|
|
97356
|
+
{ regex: intrawordAsteriskItalicRegex, isBold: false, isIntraword: true, marker: '*', gate: 'asterisk' },
|
|
97357
|
+
{ regex: intrawordAsteriskBoldRegex, isBold: true, isIntraword: true, marker: '**', gate: 'asterisk' },
|
|
97358
|
+
];
|
|
97316
97359
|
/**
|
|
97317
97360
|
* Finds opening emphasis marker in a text value.
|
|
97318
97361
|
* Returns marker info if found, null otherwise.
|
|
@@ -97504,6 +97547,21 @@ function isInsideInlineHtmlCode(index, parent) {
|
|
|
97504
97547
|
* malformed emphasis syntax. This plugin post-processes the AST to handle these cases.
|
|
97505
97548
|
*/
|
|
97506
97549
|
const normalizeEmphasisAST = () => (tree) => {
|
|
97550
|
+
// Back-scanning siblings for <code>…</code> html pairs costs O(children)
|
|
97551
|
+
// per text node — O(children²) per parent, which bites on marker-dense
|
|
97552
|
+
// paragraphs where micromark emits thousands of inline children. Most
|
|
97553
|
+
// parents have no html children at all, so cache that check per parent and
|
|
97554
|
+
// skip the back-scan entirely. The cached flag survives our splices: they
|
|
97555
|
+
// only ever swap text nodes for text/strong/emphasis, never html.
|
|
97556
|
+
const hasHtmlChild = new WeakMap();
|
|
97557
|
+
const mayBeInsideInlineHtmlCode = (index, parent) => {
|
|
97558
|
+
let flag = hasHtmlChild.get(parent);
|
|
97559
|
+
if (flag === undefined) {
|
|
97560
|
+
flag = parent.children.some(child => child.type === 'html');
|
|
97561
|
+
hasHtmlChild.set(parent, flag);
|
|
97562
|
+
}
|
|
97563
|
+
return flag && isInsideInlineHtmlCode(index, parent);
|
|
97564
|
+
};
|
|
97507
97565
|
visit(tree, 'text', function visitor(node, index, parent) {
|
|
97508
97566
|
if (index === undefined || !parent)
|
|
97509
97567
|
return undefined;
|
|
@@ -97515,41 +97573,39 @@ const normalizeEmphasisAST = () => (tree) => {
|
|
|
97515
97573
|
// raw HTML <code>...</code> inside table cells, which the table re-parser
|
|
97516
97574
|
// parses as MDX JSX (not as an mdast `inlineCode` node).
|
|
97517
97575
|
if ((parent.type === 'mdxJsxTextElement' || parent.type === 'mdxJsxFlowElement') &&
|
|
97518
|
-
'name' in parent &&
|
|
97576
|
+
'name' in parent &&
|
|
97577
|
+
parent.name === 'code') {
|
|
97519
97578
|
return undefined;
|
|
97520
97579
|
}
|
|
97580
|
+
const text = node.value;
|
|
97581
|
+
// The regexes below can't match without their marker character, but
|
|
97582
|
+
// running them anyway costs a scan of the whole node — ruinous on huge
|
|
97583
|
+
// pasted payloads (base64 attachments, minified code). Checked before the
|
|
97584
|
+
// html-sibling scan so marker-free text never pays for that either.
|
|
97585
|
+
const hasAsterisk = text.includes('*');
|
|
97586
|
+
const hasUnderscore = text.includes('_');
|
|
97587
|
+
if (!hasAsterisk && !hasUnderscore)
|
|
97588
|
+
return undefined;
|
|
97521
97589
|
// In GFM tables, inline <code>...</code> is represented as sibling `html`
|
|
97522
97590
|
// nodes rather than as an mdxJsxTextElement, so the check above doesn't
|
|
97523
97591
|
// apply. Scan backwards through siblings to see if we are enclosed by a
|
|
97524
97592
|
// <code>…</code> inline HTML pair.
|
|
97525
|
-
if (
|
|
97593
|
+
if (mayBeInsideInlineHtmlCode(index, parent)) {
|
|
97526
97594
|
return undefined;
|
|
97527
97595
|
}
|
|
97528
|
-
const
|
|
97596
|
+
const gates = {
|
|
97597
|
+
asterisk: hasAsterisk,
|
|
97598
|
+
asteriskLoose: hasAsterisk && asteriskBesideWhitespaceRegex.test(text),
|
|
97599
|
+
underscore: hasUnderscore,
|
|
97600
|
+
underscoreLoose: hasUnderscore && underscoreBesideWhitespaceRegex.test(text),
|
|
97601
|
+
};
|
|
97529
97602
|
const allMatches = [];
|
|
97530
|
-
|
|
97531
|
-
|
|
97532
|
-
|
|
97533
|
-
|
|
97534
|
-
|
|
97535
|
-
|
|
97536
|
-
[...text.matchAll(asteriskItalicRegex)].forEach(match => {
|
|
97537
|
-
allMatches.push({ isBold: false, marker: '*', match });
|
|
97538
|
-
});
|
|
97539
|
-
[...text.matchAll(underscoreItalicRegex)].forEach(match => {
|
|
97540
|
-
allMatches.push({ isBold: false, marker: '_', match });
|
|
97541
|
-
});
|
|
97542
|
-
[...text.matchAll(intrawordUnderscoreItalicRegex)].forEach(match => {
|
|
97543
|
-
allMatches.push({ isBold: false, isIntraword: true, marker: '_', match });
|
|
97544
|
-
});
|
|
97545
|
-
[...text.matchAll(intrawordUnderscoreBoldRegex)].forEach(match => {
|
|
97546
|
-
allMatches.push({ isBold: true, isIntraword: true, marker: '__', match });
|
|
97547
|
-
});
|
|
97548
|
-
[...text.matchAll(intrawordAsteriskItalicRegex)].forEach(match => {
|
|
97549
|
-
allMatches.push({ isBold: false, isIntraword: true, marker: '*', match });
|
|
97550
|
-
});
|
|
97551
|
-
[...text.matchAll(intrawordAsteriskBoldRegex)].forEach(match => {
|
|
97552
|
-
allMatches.push({ isBold: true, isIntraword: true, marker: '**', match });
|
|
97603
|
+
REGEX_FAMILIES.forEach(({ regex, gate, ...info }) => {
|
|
97604
|
+
if (!gates[gate])
|
|
97605
|
+
return;
|
|
97606
|
+
[...text.matchAll(regex)].forEach(match => {
|
|
97607
|
+
allMatches.push({ ...info, match });
|
|
97608
|
+
});
|
|
97553
97609
|
});
|
|
97554
97610
|
if (allMatches.length === 0)
|
|
97555
97611
|
return undefined;
|
|
@@ -97646,9 +97702,22 @@ const normalizeEmphasisAST = () => (tree) => {
|
|
|
97646
97702
|
parts.push({ type: 'text', value: remainingText });
|
|
97647
97703
|
}
|
|
97648
97704
|
}
|
|
97649
|
-
|
|
97650
|
-
|
|
97651
|
-
|
|
97705
|
+
// Merge adjacent text parts so the emitted AST doesn't depend on where a
|
|
97706
|
+
// match happened to start (the bounded prefixes above can shift a match
|
|
97707
|
+
// start rightward, splitting what used to be a single text node).
|
|
97708
|
+
const mergedParts = parts.reduce((acc, part) => {
|
|
97709
|
+
const prev = acc[acc.length - 1];
|
|
97710
|
+
if (part.type === 'text' && prev?.type === 'text') {
|
|
97711
|
+
prev.value += part.value;
|
|
97712
|
+
}
|
|
97713
|
+
else {
|
|
97714
|
+
acc.push(part);
|
|
97715
|
+
}
|
|
97716
|
+
return acc;
|
|
97717
|
+
}, []);
|
|
97718
|
+
if (mergedParts.length > 0) {
|
|
97719
|
+
parent.children.splice(index, 1, ...mergedParts);
|
|
97720
|
+
return [SKIP, index + mergedParts.length];
|
|
97652
97721
|
}
|
|
97653
97722
|
return undefined;
|
|
97654
97723
|
});
|