@readme/markdown 14.11.3 → 14.11.5
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/Tabs/index.tsx +9 -2
- package/dist/339.node.js +2 -2
- package/dist/486.node.js +4 -4
- package/dist/main.js +643 -289
- package/dist/main.node.js +643 -289
- package/dist/main.node.js.map +1 -1
- package/dist/processor/compile/text.d.ts +4 -0
- package/dist/processor/transform/mdxish/react-element-to-hast.d.ts +8 -0
- package/dist/processor/transform/mdxish/tables/escape-crossing-emphasis.d.ts +15 -0
- package/dist/processor/transform/mdxish/tables/remap-positions.d.ts +3 -5
- package/dist/processor/transform/mdxish/tables/split-nested-tables.d.ts +11 -0
- package/dist/processor/transform/mdxish/terminate-html-flow-blocks.d.ts +3 -17
- package/dist/processor/utils.d.ts +7 -0
- package/dist/render-fixture.node.js +641 -287
- package/dist/render-fixture.node.js.map +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -12631,10 +12631,10 @@ const Tabs = ({ children }) => {
|
|
|
12631
12631
|
const tabs = external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().Children.toArray(children);
|
|
12632
12632
|
return (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("div", { className: "TabGroup" },
|
|
12633
12633
|
external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("header", null,
|
|
12634
|
-
external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("nav", { className: "TabGroup-nav" }, tabs.map((tab, index) => (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("button", { key: tab.
|
|
12634
|
+
external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("nav", { className: "TabGroup-nav" }, tabs.map((tab, index) => (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("button", { key: tab.key, className: `TabGroup-tab${activeTab === index ? '_active' : ''}`, onClick: () => setActiveTab(index) },
|
|
12635
12635
|
tab.props.icon && (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement(components_Icon, { className: "TabGroup-icon", icon: tab.props.icon, iconColor: tab.props.iconColor })),
|
|
12636
12636
|
tab.props.title))))),
|
|
12637
|
-
external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("section", null, tabs
|
|
12637
|
+
external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("section", null, tabs.map((tab, index) => (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("div", { key: tab.key, hidden: index !== activeTab }, tab))))));
|
|
12638
12638
|
};
|
|
12639
12639
|
/* harmony default export */ const components_Tabs = (Tabs);
|
|
12640
12640
|
|
|
@@ -54527,6 +54527,21 @@ function evaluate(source, scope = {}) {
|
|
|
54527
54527
|
// eslint-disable-next-line no-new-func
|
|
54528
54528
|
return new Function(...names, `return (${source})`)(...values);
|
|
54529
54529
|
}
|
|
54530
|
+
/**
|
|
54531
|
+
* Advance a `Point` by the `consumed` substring that follows it, returning the
|
|
54532
|
+
* point at the consumed string's end. Lets split-out sub-nodes carry accurate
|
|
54533
|
+
* document positions so downstream offset shifting stays correct.
|
|
54534
|
+
*/
|
|
54535
|
+
const pointAfter = (start, consumed) => {
|
|
54536
|
+
const newlineIndex = consumed.lastIndexOf('\n');
|
|
54537
|
+
const newlineCount = newlineIndex === -1 ? 0 : consumed.split('\n').length - 1;
|
|
54538
|
+
return {
|
|
54539
|
+
line: start.line + newlineCount,
|
|
54540
|
+
// Same line → advance the base column; a later line → column is the run since its newline.
|
|
54541
|
+
column: newlineCount === 0 ? start.column + consumed.length : consumed.length - newlineIndex,
|
|
54542
|
+
offset: (start.offset ?? 0) + consumed.length,
|
|
54543
|
+
};
|
|
54544
|
+
};
|
|
54530
54545
|
/**
|
|
54531
54546
|
* Formats the hProperties of a node as a string, so they can be compiled back into JSX/MDX.
|
|
54532
54547
|
* This currently sets all the values to a string since we process/compile the MDX on the fly
|
|
@@ -75795,6 +75810,108 @@ const applyInserts = (html, inserts) => {
|
|
|
75795
75810
|
return { value: out + html.slice(cursor), inserts: sorted };
|
|
75796
75811
|
};
|
|
75797
75812
|
|
|
75813
|
+
;// ./processor/transform/mdxish/tables/escape-crossing-emphasis.ts
|
|
75814
|
+
|
|
75815
|
+
|
|
75816
|
+
|
|
75817
|
+
// Maximal run of a single emphasis delimiter (`_`, `*`, `**`, `***`, …).
|
|
75818
|
+
const EMPHASIS_RUN_RE = /([*_])\1*/g;
|
|
75819
|
+
// String bounds (undefined) count as whitespace, not punctuation, per the
|
|
75820
|
+
// CommonMark flanking definition.
|
|
75821
|
+
const escape_crossing_emphasis_isWhitespace = (ch) => ch === undefined || unicodeWhitespace(ch.charCodeAt(0));
|
|
75822
|
+
const isPunctuation = (ch) => ch !== undefined && unicodePunctuation(ch.charCodeAt(0));
|
|
75823
|
+
/**
|
|
75824
|
+
* Whether a delimiter run can open and/or close emphasis, per CommonMark's
|
|
75825
|
+
* left/right-flanking rules. The extra `_` conditions forbid intraword
|
|
75826
|
+
* emphasis, which keeps `snake_case` from being treated as a delimiter.
|
|
75827
|
+
*/
|
|
75828
|
+
const analyzeFlanking = (source, char, start, end) => {
|
|
75829
|
+
const before = source[start - 1];
|
|
75830
|
+
const after = source[end];
|
|
75831
|
+
const leftFlanking = !escape_crossing_emphasis_isWhitespace(after) && (!isPunctuation(after) || escape_crossing_emphasis_isWhitespace(before) || isPunctuation(before));
|
|
75832
|
+
const rightFlanking = !escape_crossing_emphasis_isWhitespace(before) && (!isPunctuation(before) || escape_crossing_emphasis_isWhitespace(after) || isPunctuation(after));
|
|
75833
|
+
if (char === '_') {
|
|
75834
|
+
return {
|
|
75835
|
+
canOpen: leftFlanking && (!rightFlanking || isPunctuation(before)),
|
|
75836
|
+
canClose: rightFlanking && (!leftFlanking || isPunctuation(after)),
|
|
75837
|
+
};
|
|
75838
|
+
}
|
|
75839
|
+
return { canOpen: leftFlanking, canClose: rightFlanking };
|
|
75840
|
+
};
|
|
75841
|
+
/**
|
|
75842
|
+
* Collect HTML tag boundaries (via htmlparser2) and emphasis delimiter runs
|
|
75843
|
+
* (via regex over the masked source, so code spans and escaped `<` are skipped)
|
|
75844
|
+
* into one list ordered by position. At a shared offset a tag opener sorts
|
|
75845
|
+
* before a closer, so a self-closing tag brackets rather than swallows a run.
|
|
75846
|
+
*/
|
|
75847
|
+
const collectEvents = (html) => {
|
|
75848
|
+
const masked = maskNonTagRegions(html);
|
|
75849
|
+
const events = [];
|
|
75850
|
+
walkTags(html, {
|
|
75851
|
+
onOpen: ({ start }) => events.push({ kind: 'tagOpen', offset: start }),
|
|
75852
|
+
onClose: ({ start }) => events.push({ kind: 'tagClose', offset: start }),
|
|
75853
|
+
});
|
|
75854
|
+
EMPHASIS_RUN_RE.lastIndex = 0;
|
|
75855
|
+
let match;
|
|
75856
|
+
while ((match = EMPHASIS_RUN_RE.exec(masked)) !== null) {
|
|
75857
|
+
const [run, char] = match;
|
|
75858
|
+
const start = match.index;
|
|
75859
|
+
// eslint-disable-next-line no-continue
|
|
75860
|
+
if (html[start - 1] === '\\')
|
|
75861
|
+
continue; // already escaped
|
|
75862
|
+
events.push({ kind: 'emphasis', offset: start, char, length: run.length, flanking: analyzeFlanking(html, char, start, start + run.length) });
|
|
75863
|
+
}
|
|
75864
|
+
return events.sort((a, b) => a.offset - b.offset || (a.kind === 'tagClose' ? 1 : 0) - (b.kind === 'tagClose' ? 1 : 0));
|
|
75865
|
+
};
|
|
75866
|
+
/**
|
|
75867
|
+
* mdxjs rejects a table when a markdown emphasis run opens at one HTML
|
|
75868
|
+
* tag-nesting depth and closes at another — e.g. `_<ul><li>text_</li></ul>`,
|
|
75869
|
+
* where the `_` opens outside the list but closes inside a `<li>`. It throws
|
|
75870
|
+
* "Expected a closing tag for `<li>` before the end of `emphasis`" and the
|
|
75871
|
+
* whole `<Table>` fails to parse.
|
|
75872
|
+
*
|
|
75873
|
+
* We walk tags and emphasis together, tracking tag depth and a stack of open
|
|
75874
|
+
* emphasis. A delimiter only closes an opener at the same depth; any emphasis
|
|
75875
|
+
* still open when its enclosing tag closes (or at end of input), and any closer
|
|
75876
|
+
* with no same-depth opener, is escaped so mdxjs treats it as literal text.
|
|
75877
|
+
* Scoped to the malformed-retry path.
|
|
75878
|
+
*/
|
|
75879
|
+
const escapeCrossingEmphasis = (html) => {
|
|
75880
|
+
const open = [];
|
|
75881
|
+
const orphans = [];
|
|
75882
|
+
let depth = 0;
|
|
75883
|
+
collectEvents(html).forEach(event => {
|
|
75884
|
+
if (event.kind === 'tagOpen') {
|
|
75885
|
+
depth += 1;
|
|
75886
|
+
return;
|
|
75887
|
+
}
|
|
75888
|
+
if (event.kind === 'tagClose') {
|
|
75889
|
+
depth -= 1;
|
|
75890
|
+
// Emphasis opened deeper than the surviving depth was inside the tag that
|
|
75891
|
+
// just closed, so it crosses the boundary.
|
|
75892
|
+
while (open.length > 0 && open[open.length - 1].depth > depth) {
|
|
75893
|
+
const crossed = open.pop();
|
|
75894
|
+
if (crossed)
|
|
75895
|
+
orphans.push(crossed);
|
|
75896
|
+
}
|
|
75897
|
+
return;
|
|
75898
|
+
}
|
|
75899
|
+
const top = open[open.length - 1];
|
|
75900
|
+
if (event.flanking.canClose && top?.char === event.char && top.depth === depth) {
|
|
75901
|
+
open.pop();
|
|
75902
|
+
}
|
|
75903
|
+
else if (event.flanking.canOpen) {
|
|
75904
|
+
open.push({ char: event.char, depth, offset: event.offset, length: event.length });
|
|
75905
|
+
}
|
|
75906
|
+
else if (event.flanking.canClose) {
|
|
75907
|
+
orphans.push({ offset: event.offset, length: event.length });
|
|
75908
|
+
}
|
|
75909
|
+
});
|
|
75910
|
+
orphans.push(...open); // anything still open never closed
|
|
75911
|
+
const inserts = orphans.flatMap(({ offset, length }) => Array.from({ length }, (_unused, i) => ({ offset: offset + i, text: '\\' })));
|
|
75912
|
+
return applyInserts(html, inserts);
|
|
75913
|
+
};
|
|
75914
|
+
|
|
75798
75915
|
;// ./processor/transform/mdxish/tables/escape-stray-less-than.ts
|
|
75799
75916
|
|
|
75800
75917
|
|
|
@@ -75947,6 +76064,21 @@ const buildOffsetMapper = (inserts) => {
|
|
|
75947
76064
|
return repaired - shift;
|
|
75948
76065
|
};
|
|
75949
76066
|
};
|
|
76067
|
+
/**
|
|
76068
|
+
* Compose the per-repair offset mappers into one that maps an offset in the
|
|
76069
|
+
* fully-repaired string back to the original. `layers` are in application
|
|
76070
|
+
* order; each maps its own output space to its input space, so we apply them
|
|
76071
|
+
* last-repair-first to peel every edit back to the original coordinates.
|
|
76072
|
+
*/
|
|
76073
|
+
const composeOffsetMapper = (layers) => {
|
|
76074
|
+
const mappers = layers.map(buildOffsetMapper);
|
|
76075
|
+
return (repaired) => {
|
|
76076
|
+
let offset = repaired;
|
|
76077
|
+
for (let i = mappers.length - 1; i >= 0; i -= 1)
|
|
76078
|
+
offset = mappers[i](offset);
|
|
76079
|
+
return offset;
|
|
76080
|
+
};
|
|
76081
|
+
};
|
|
75950
76082
|
/**
|
|
75951
76083
|
* Map an offset in `source` to its 1-based `{ line, column }`. `lineStarts`
|
|
75952
76084
|
* is the precomputed array of offsets where each line begins.
|
|
@@ -75974,14 +76106,11 @@ const computeLineStarts = (source) => {
|
|
|
75974
76106
|
};
|
|
75975
76107
|
/**
|
|
75976
76108
|
* Walk `tree`, translating every node's position from the repaired source's
|
|
75977
|
-
* coordinate space back to the original source
|
|
75978
|
-
*
|
|
75979
|
-
*
|
|
76109
|
+
* coordinate space back to the original source via `mapOffset`. Line/column
|
|
76110
|
+
* are recomputed from the original source so they remain accurate even if
|
|
76111
|
+
* repairs introduced newlines.
|
|
75980
76112
|
*/
|
|
75981
|
-
const
|
|
75982
|
-
if (inserts.length === 0)
|
|
75983
|
-
return;
|
|
75984
|
-
const mapOffset = buildOffsetMapper(inserts);
|
|
76113
|
+
const remapWithMapper = (tree, originalSource, mapOffset) => {
|
|
75985
76114
|
const lineStarts = computeLineStarts(originalSource);
|
|
75986
76115
|
visit(tree, child => {
|
|
75987
76116
|
if (child.position?.start) {
|
|
@@ -76000,6 +76129,15 @@ const remapPositionsToOriginal = (tree, originalSource, inserts) => {
|
|
|
76000
76129
|
}
|
|
76001
76130
|
});
|
|
76002
76131
|
};
|
|
76132
|
+
/**
|
|
76133
|
+
* Remap positions produced after a chain of repairs (each applied to the prior
|
|
76134
|
+
* one's output) back to the original source coordinates.
|
|
76135
|
+
*/
|
|
76136
|
+
const remapPositionsThroughLayers = (tree, originalSource, layers) => {
|
|
76137
|
+
if (layers.length === 0)
|
|
76138
|
+
return;
|
|
76139
|
+
remapWithMapper(tree, originalSource, composeOffsetMapper(layers));
|
|
76140
|
+
};
|
|
76003
76141
|
|
|
76004
76142
|
;// ./processor/transform/mdxish/tables/repair-expression-escapes.ts
|
|
76005
76143
|
|
|
@@ -76299,6 +76437,83 @@ const repairUnclosedTags = (html) => {
|
|
|
76299
76437
|
return applyInserts(html, inserts);
|
|
76300
76438
|
};
|
|
76301
76439
|
|
|
76440
|
+
;// ./processor/transform/mdxish/tables/split-nested-tables.ts
|
|
76441
|
+
|
|
76442
|
+
|
|
76443
|
+
const TOP_LEVEL_TABLE_TAG_RE = /^<(?:table|Table)(?=[\s/>])/;
|
|
76444
|
+
/**
|
|
76445
|
+
* Find every balanced, depth-matched `<table>…</table>` range in an html string.
|
|
76446
|
+
* Uses `walkTags` so `<table>`s inside code spans / fenced blocks (masked away)
|
|
76447
|
+
* are never matched.
|
|
76448
|
+
*
|
|
76449
|
+
* Note: An implicitly-closed table (no `</table>`, so htmlparser2 synthesizes the
|
|
76450
|
+
* close at a later tag) is skipped: splitting there would swallow whatever
|
|
76451
|
+
* followed the table into the fragment and drop it, so we leave such a node
|
|
76452
|
+
* whole for downstream raw-HTML handling instead.
|
|
76453
|
+
*/
|
|
76454
|
+
const findTableRanges = (html) => {
|
|
76455
|
+
const ranges = [];
|
|
76456
|
+
let depth = 0;
|
|
76457
|
+
let start = 0;
|
|
76458
|
+
walkTags(html, {
|
|
76459
|
+
onOpen: ({ name, start: openStart, isStrayCloser }) => {
|
|
76460
|
+
if (name.toLowerCase() !== 'table' || isStrayCloser)
|
|
76461
|
+
return;
|
|
76462
|
+
if (depth === 0)
|
|
76463
|
+
start = openStart;
|
|
76464
|
+
depth += 1;
|
|
76465
|
+
},
|
|
76466
|
+
onClose: ({ name, end, implicit }) => {
|
|
76467
|
+
if (implicit || name.toLowerCase() !== 'table' || depth === 0)
|
|
76468
|
+
return;
|
|
76469
|
+
depth -= 1;
|
|
76470
|
+
if (depth === 0)
|
|
76471
|
+
ranges.push({ start, end });
|
|
76472
|
+
},
|
|
76473
|
+
});
|
|
76474
|
+
return ranges;
|
|
76475
|
+
};
|
|
76476
|
+
/**
|
|
76477
|
+
* Given an HTML node that might contain table sequences inside it, split
|
|
76478
|
+
* the node based on the table boundaries so they become a top level node.
|
|
76479
|
+
*
|
|
76480
|
+
* The surrounding raw HTML (the wrapper's open/close tags) would be re-nested
|
|
76481
|
+
* around the parsed tables by rehype-raw.
|
|
76482
|
+
*
|
|
76483
|
+
* Returns null when there is no wrapped table to extract.
|
|
76484
|
+
*/
|
|
76485
|
+
const splitHtmlWithNestedTables = (node) => {
|
|
76486
|
+
const { value } = node;
|
|
76487
|
+
// This is a top-level table, so we don't need to split it
|
|
76488
|
+
if (TOP_LEVEL_TABLE_TAG_RE.test(value))
|
|
76489
|
+
return null;
|
|
76490
|
+
// No table text anywhere in the value → skip the htmlparser2 walk entirely.
|
|
76491
|
+
if (!/<\/?table/i.test(value))
|
|
76492
|
+
return null;
|
|
76493
|
+
const ranges = findTableRanges(value);
|
|
76494
|
+
if (ranges.length === 0)
|
|
76495
|
+
return null;
|
|
76496
|
+
const base = node.position?.start;
|
|
76497
|
+
const sliceToHtml = (from, to) => ({
|
|
76498
|
+
type: 'html',
|
|
76499
|
+
value: value.slice(from, to),
|
|
76500
|
+
...(base && {
|
|
76501
|
+
position: { start: pointAfter(base, value.slice(0, from)), end: pointAfter(base, value.slice(0, to)) },
|
|
76502
|
+
}),
|
|
76503
|
+
});
|
|
76504
|
+
const parts = [];
|
|
76505
|
+
let cursor = 0;
|
|
76506
|
+
ranges.forEach(({ start, end }) => {
|
|
76507
|
+
if (start > cursor)
|
|
76508
|
+
parts.push(sliceToHtml(cursor, start));
|
|
76509
|
+
parts.push(sliceToHtml(start, end)); // starts with `<table` → picked up by the main pass
|
|
76510
|
+
cursor = end;
|
|
76511
|
+
});
|
|
76512
|
+
if (cursor < value.length)
|
|
76513
|
+
parts.push(sliceToHtml(cursor, value.length));
|
|
76514
|
+
return parts;
|
|
76515
|
+
};
|
|
76516
|
+
|
|
76302
76517
|
;// ./processor/transform/mdxish/tables/mdxish-tables.ts
|
|
76303
76518
|
|
|
76304
76519
|
|
|
@@ -76320,6 +76535,8 @@ const repairUnclosedTags = (html) => {
|
|
|
76320
76535
|
|
|
76321
76536
|
|
|
76322
76537
|
|
|
76538
|
+
|
|
76539
|
+
|
|
76323
76540
|
|
|
76324
76541
|
|
|
76325
76542
|
|
|
@@ -76349,6 +76566,21 @@ const buildTableNodeProcessor = (withMdx) => unified()
|
|
|
76349
76566
|
.use(remarkGfm);
|
|
76350
76567
|
const tableNodeProcessor = buildTableNodeProcessor(true);
|
|
76351
76568
|
const fallbackTableNodeProcessor = buildTableNodeProcessor(false);
|
|
76569
|
+
// Targeted repairs for tables mdxjs rejects, tried cumulatively (each runs on
|
|
76570
|
+
// the prior's output) since one table can carry independent per-cell defects.
|
|
76571
|
+
// Each was added after seeing real customer content fail to parse:
|
|
76572
|
+
// - repairUnclosedTags: unclosed/orphan HTML tags
|
|
76573
|
+
// - normalizeTagSpacing: a line mixing text and an opening tag
|
|
76574
|
+
// - repairExpressionEscapes: backslash escapes inside a `{…}` expression
|
|
76575
|
+
// - escapeStrayLessThan: a `<` that doesn't begin a valid tag (`word <`)
|
|
76576
|
+
// - escapeCrossingEmphasis: emphasis opening/closing at different tag depths
|
|
76577
|
+
const tableRepairs = [
|
|
76578
|
+
repairUnclosedTags,
|
|
76579
|
+
normalizeTagSpacing,
|
|
76580
|
+
repairExpressionEscapes,
|
|
76581
|
+
escapeStrayLessThan,
|
|
76582
|
+
escapeCrossingEmphasis,
|
|
76583
|
+
];
|
|
76352
76584
|
/**
|
|
76353
76585
|
* Parse the HTML node that contains the full table substring
|
|
76354
76586
|
* into the table parts (headers, rows, cells).
|
|
@@ -76364,10 +76596,10 @@ const parseTableNode = (processor, node, repair) => {
|
|
|
76364
76596
|
return undefined;
|
|
76365
76597
|
}
|
|
76366
76598
|
// If `node.value` was repaired before parsing, first remap positions back to
|
|
76367
|
-
// the original (unrepaired) coordinates via the insert
|
|
76599
|
+
// the original (unrepaired) coordinates via the insert layers — otherwise the
|
|
76368
76600
|
// shift would land on synthetic characters and be inaccurate
|
|
76369
76601
|
if (repair) {
|
|
76370
|
-
|
|
76602
|
+
remapPositionsThroughLayers(parsed, repair.originalSource, repair.layers);
|
|
76371
76603
|
}
|
|
76372
76604
|
// The subparser produces positions relative to `node.value`; shift them by
|
|
76373
76605
|
// the outer node's offset/line so consumers can slice the full source.
|
|
@@ -76464,9 +76696,7 @@ const processTableNode = (node, index, parent, documentPosition) => {
|
|
|
76464
76696
|
visit(node, isMDXElement, (child) => {
|
|
76465
76697
|
if (child.name === 'thead')
|
|
76466
76698
|
hasThead = true;
|
|
76467
|
-
if (tableTags.has(child.name) &&
|
|
76468
|
-
Array.isArray(child.attributes) &&
|
|
76469
|
-
child.attributes.length > 0) {
|
|
76699
|
+
if (tableTags.has(child.name) && Array.isArray(child.attributes) && child.attributes.length > 0) {
|
|
76470
76700
|
hasStructuralAttributes = true;
|
|
76471
76701
|
}
|
|
76472
76702
|
});
|
|
@@ -76577,6 +76807,26 @@ const processTableNode = (node, index, parent, documentPosition) => {
|
|
|
76577
76807
|
};
|
|
76578
76808
|
parent.children[index] = mdNode;
|
|
76579
76809
|
};
|
|
76810
|
+
/**
|
|
76811
|
+
* Apply `tableRepairs` cumulatively, re-parsing after every change and stopping
|
|
76812
|
+
* once the accumulated result parses. Each layer's inserts are relative to the
|
|
76813
|
+
* string that repair received, so they stay ordered for position remapping.
|
|
76814
|
+
*/
|
|
76815
|
+
const repairAndReparse = (node) => {
|
|
76816
|
+
let repairedValue = node.value;
|
|
76817
|
+
const layers = [];
|
|
76818
|
+
let parsed;
|
|
76819
|
+
tableRepairs.some(repair => {
|
|
76820
|
+
const { value, inserts } = repair(repairedValue);
|
|
76821
|
+
if (value === repairedValue)
|
|
76822
|
+
return false;
|
|
76823
|
+
repairedValue = value;
|
|
76824
|
+
layers.push(inserts);
|
|
76825
|
+
parsed = parseTableNode(tableNodeProcessor, { ...node, value: repairedValue }, { layers, originalSource: node.value });
|
|
76826
|
+
return Boolean(parsed);
|
|
76827
|
+
});
|
|
76828
|
+
return parsed;
|
|
76829
|
+
};
|
|
76580
76830
|
/**
|
|
76581
76831
|
* Converts JSX Table elements to markdown table nodes and re-parses markdown in cells.
|
|
76582
76832
|
*
|
|
@@ -76589,42 +76839,30 @@ const processTableNode = (node, index, parent, documentPosition) => {
|
|
|
76589
76839
|
* is kept as a JSX <Table> element so that remarkRehype can properly handle the flow content.
|
|
76590
76840
|
*/
|
|
76591
76841
|
const mdxishTables = () => tree => {
|
|
76842
|
+
// Pre-pass: lift `<table>`s wrapped in a raw HTML block out into their own
|
|
76843
|
+
// html nodes so the main pass below treats them like top-level tables.
|
|
76844
|
+
visit(tree, 'html', (_node, index, parent) => {
|
|
76845
|
+
const node = _node;
|
|
76846
|
+
if (typeof index !== 'number' || !parent || !('children' in parent))
|
|
76847
|
+
return;
|
|
76848
|
+
const parts = splitHtmlWithNestedTables(node);
|
|
76849
|
+
if (!parts)
|
|
76850
|
+
return;
|
|
76851
|
+
// The inserted parts can't re-trigger a split (table parts start with
|
|
76852
|
+
// `<table`; the wrapper slices hold no table), so plain in-place splicing
|
|
76853
|
+
// visits each once without looping.
|
|
76854
|
+
parent.children.splice(index, 1, ...parts);
|
|
76855
|
+
});
|
|
76592
76856
|
visit(tree, 'html', (_node, index, parent) => {
|
|
76593
76857
|
const node = _node;
|
|
76594
76858
|
if (typeof index !== 'number' || !parent || !('children' in parent))
|
|
76595
76859
|
return;
|
|
76596
76860
|
if (!node.value.startsWith('<Table') && !node.value.startsWith('<table'))
|
|
76597
76861
|
return;
|
|
76598
|
-
// Main logic to transform table node to its parts
|
|
76599
76862
|
// Because the processor uses remarkMdx, it is stricter in what it accepts
|
|
76600
|
-
// and only accepts valid MDX syntax
|
|
76601
|
-
//
|
|
76602
|
-
|
|
76603
|
-
if (!parsed) {
|
|
76604
|
-
// Try a sequence of targeted repairs and re-parse
|
|
76605
|
-
// after each, stopping at the first that yields a parseable tree:
|
|
76606
|
-
// - repairUnclosedTags: unclosed/orphan HTML tags
|
|
76607
|
-
// - normalizeTagSpacing: a line mixing text and an opening tag
|
|
76608
|
-
// (e.g. `text <div> \n <div> text`)
|
|
76609
|
-
// - repairExpressionEscapes: backslash escapes inside a `{…}` expression
|
|
76610
|
-
// - escapeStrayLessThan: a `<` that doesn't begin a valid tag
|
|
76611
|
-
// (e.g. `word <`, `a <1>`)
|
|
76612
|
-
// These repairs are created after seeing real customer content that has failed to parse
|
|
76613
|
-
const repairs = [
|
|
76614
|
-
repairUnclosedTags,
|
|
76615
|
-
normalizeTagSpacing,
|
|
76616
|
-
repairExpressionEscapes,
|
|
76617
|
-
escapeStrayLessThan,
|
|
76618
|
-
];
|
|
76619
|
-
// Stops at the first repair that yields a parseable tree
|
|
76620
|
-
repairs.some(repair => {
|
|
76621
|
-
const { value, inserts } = repair(node.value);
|
|
76622
|
-
if (value !== node.value) {
|
|
76623
|
-
parsed = parseTableNode(tableNodeProcessor, { ...node, value }, { inserts, originalSource: node.value });
|
|
76624
|
-
}
|
|
76625
|
-
return Boolean(parsed);
|
|
76626
|
-
});
|
|
76627
|
-
}
|
|
76863
|
+
// and only accepts valid MDX syntax in the table node. To get around that,
|
|
76864
|
+
// fall back to the cumulative repairs when the first parse fails.
|
|
76865
|
+
const parsed = parseTableNode(tableNodeProcessor, node) ?? repairAndReparse(node);
|
|
76628
76866
|
if (parsed) {
|
|
76629
76867
|
// If the table is parsed successfully, we can now process it further
|
|
76630
76868
|
// to build on the markdown / JSX table
|
|
@@ -97084,6 +97322,19 @@ const compile_list_item_listItem = (node, parent, state, info) => {
|
|
|
97084
97322
|
const plain_plain = (node) => node.value;
|
|
97085
97323
|
/* harmony default export */ const compile_plain = (plain_plain);
|
|
97086
97324
|
|
|
97325
|
+
;// ./processor/compile/text.ts
|
|
97326
|
+
|
|
97327
|
+
// A `_` flanked by word characters can never open or close emphasis under
|
|
97328
|
+
// CommonMark's flanking rules, so the escape mdast-util-to-markdown adds to
|
|
97329
|
+
// intraword underscores is unnecessary and only produces noisy `\_` diffs.
|
|
97330
|
+
// Uses Unicode letter/number classes so non-ASCII words (e.g. `é_pay`) match.
|
|
97331
|
+
const INTRAWORD_UNDERSCORE_ESCAPE = /(?<=[\p{L}\p{N}_])\\_(?=[\p{L}\p{N}_]|\\_)/gu;
|
|
97332
|
+
const compile_text_text = (node, parent, state, info) => {
|
|
97333
|
+
const serialized = handle.text(node, parent, state, info);
|
|
97334
|
+
return serialized.replace(INTRAWORD_UNDERSCORE_ESCAPE, '_');
|
|
97335
|
+
};
|
|
97336
|
+
/* harmony default export */ const compile_text = (compile_text_text);
|
|
97337
|
+
|
|
97087
97338
|
;// ./processor/compile/index.ts
|
|
97088
97339
|
|
|
97089
97340
|
|
|
@@ -97096,11 +97347,11 @@ const plain_plain = (node) => node.value;
|
|
|
97096
97347
|
|
|
97097
97348
|
|
|
97098
97349
|
|
|
97350
|
+
|
|
97099
97351
|
function compilers(mdxish = false) {
|
|
97100
97352
|
const data = this.data();
|
|
97101
97353
|
const toMarkdownExtensions = data.toMarkdownExtensions || (data.toMarkdownExtensions = []);
|
|
97102
97354
|
const handlers = {
|
|
97103
|
-
...(mdxish && { [NodeTypes.anchor]: compile_anchor }),
|
|
97104
97355
|
[NodeTypes.callout]: compile_callout,
|
|
97105
97356
|
[NodeTypes.codeTabs]: compile_code_tabs,
|
|
97106
97357
|
[NodeTypes.embedBlock]: compile_embed,
|
|
@@ -97108,15 +97359,18 @@ function compilers(mdxish = false) {
|
|
|
97108
97359
|
[NodeTypes.glossary]: compile_compatibility,
|
|
97109
97360
|
[NodeTypes.htmlBlock]: html_block,
|
|
97110
97361
|
[NodeTypes.reusableContent]: compile_compatibility,
|
|
97111
|
-
...(mdxish && { [NodeTypes.variable]: compile_variable }),
|
|
97112
97362
|
embed: compile_compatibility,
|
|
97113
97363
|
escape: compile_compatibility,
|
|
97114
97364
|
figure: compile_compatibility,
|
|
97115
97365
|
html: compile_compatibility,
|
|
97116
97366
|
i: compile_compatibility,
|
|
97117
|
-
...(mdxish && { listItem: list_item }),
|
|
97118
97367
|
plain: compile_plain,
|
|
97119
97368
|
yaml: compile_compatibility,
|
|
97369
|
+
// needed only for mdxish
|
|
97370
|
+
...(mdxish && { [NodeTypes.anchor]: compile_anchor }),
|
|
97371
|
+
...(mdxish && { listItem: list_item }),
|
|
97372
|
+
...(mdxish && { text: compile_text }),
|
|
97373
|
+
...(mdxish && { [NodeTypes.variable]: compile_variable }),
|
|
97120
97374
|
};
|
|
97121
97375
|
toMarkdownExtensions.push({ extensions: [{ handlers }] });
|
|
97122
97376
|
}
|
|
@@ -98913,11 +99167,10 @@ const rehypeMdxishComponents = ({ components, processMarkdown }) => {
|
|
|
98913
99167
|
;// ./processor/plugin/mdxish-handlers.ts
|
|
98914
99168
|
|
|
98915
99169
|
|
|
98916
|
-
//
|
|
98917
|
-
|
|
98918
|
-
|
|
98919
|
-
|
|
98920
|
-
});
|
|
99170
|
+
// If hChildren is populated, it means the node holds a renderable value (e.g. React)
|
|
99171
|
+
// See evaluate-expressions.ts for more details
|
|
99172
|
+
// Otherwise, it's a simple value and we fall back to text
|
|
99173
|
+
const mdxExpressionHandler = (_state, node) => node.data?.hChildren ?? { type: 'text', value: node.value || '' };
|
|
98921
99174
|
// Convert MDX JSX elements to a custom mdx-jsx hast node that bypasses rehypeRaw's
|
|
98922
99175
|
// HTML serialization round-trip; downstream normalization rewrites it to `element`.
|
|
98923
99176
|
const mdxJsxElementHandler = (state, node) => {
|
|
@@ -101979,81 +102232,168 @@ const mdxishInlineMdxComponents = () => tree => {
|
|
|
101979
102232
|
};
|
|
101980
102233
|
/* harmony default export */ const inline_mdx_blocks = (mdxishInlineMdxComponents);
|
|
101981
102234
|
|
|
102235
|
+
;// ./processor/transform/mdxish/terminate-html-flow-blocks.ts
|
|
102236
|
+
|
|
102237
|
+
|
|
102238
|
+
|
|
102239
|
+
const STANDALONE_HTML_LINE_REGEX = /^(<[a-z][^<>]*>|<\/[a-z][^<>]*>)+\s*$/;
|
|
102240
|
+
const HTML_LINE_WITH_CONTENT_REGEX = /^<[a-z][^<>]*>.*<\/[a-z][^<>]*>(?:[^<]*)$/;
|
|
102241
|
+
// A line that is exactly one lowercase opening (or self-closing) tag — the shape
|
|
102242
|
+
// that opens a CommonMark type-6/7 HTML block and swallows the lines below it.
|
|
102243
|
+
const SINGLE_OPENING_TAG_REGEX = /^<[a-z][^<>]*>$/;
|
|
102244
|
+
// Tags whose contents must be preserved as is, inserting a blank line after the
|
|
102245
|
+
// opener corrupts the payload.
|
|
102246
|
+
// htmlRawNames here refer to <pre>, <textarea>, <script>, <style>
|
|
102247
|
+
const RAW_CONTENT_TAGS = [...htmlRawNames, ...HTML_TABLE_STRUCTURE_TAGS];
|
|
102248
|
+
// The `(?=[\s/>])` lookahead avoids false matches on lookalike names like `<script-foo>`.
|
|
102249
|
+
const RAW_CONTENT_TAG_MATCHERS = RAW_CONTENT_TAGS.map(tag => ({
|
|
102250
|
+
open: new RegExp(`<${tag}(?=[\\s/>])[^>]*?(?<!/)>`, 'gi'),
|
|
102251
|
+
close: new RegExp(`</${tag}(?=[\\s>])[^>]*>`, 'gi'),
|
|
102252
|
+
}));
|
|
102253
|
+
function isLineHtml(line) {
|
|
102254
|
+
return STANDALONE_HTML_LINE_REGEX.test(line) || HTML_LINE_WITH_CONTENT_REGEX.test(line);
|
|
102255
|
+
}
|
|
102256
|
+
// Per-tag {opens, closes} counts of RAW_CONTENT_TAGS on one line — feeds both the
|
|
102257
|
+
// per-line net-open check and the cumulative still-open depth tracking.
|
|
102258
|
+
function countRawContentTags(line) {
|
|
102259
|
+
return RAW_CONTENT_TAG_MATCHERS.map(({ open, close }) => ({
|
|
102260
|
+
opens: (line.match(open) ?? []).length,
|
|
102261
|
+
closes: (line.match(close) ?? []).length,
|
|
102262
|
+
}));
|
|
102263
|
+
}
|
|
102264
|
+
// Indentation width in columns, counting a tab as 4 per CommonMark.
|
|
102265
|
+
function indentWidth(line) {
|
|
102266
|
+
const leading = line.match(/^[ \t]*/)?.[0] ?? '';
|
|
102267
|
+
return leading.replace(/\t/g, ' ').length;
|
|
102268
|
+
}
|
|
102269
|
+
/**
|
|
102270
|
+
* Decides whether a blank line belongs between `line` and `next` so the HTML
|
|
102271
|
+
* flow block opened on `line` terminates and `next` parses as markdown.
|
|
102272
|
+
*/
|
|
102273
|
+
function shouldTerminateBetween(line, next, { insideRawContent, lineLeavesRawOpen }) {
|
|
102274
|
+
if (next.trim().length === 0)
|
|
102275
|
+
return false;
|
|
102276
|
+
const currentIndent = indentWidth(line);
|
|
102277
|
+
const nextIndent = indentWidth(next);
|
|
102278
|
+
// 4+ columns is CommonMark indented-code territory: an inserted blank line
|
|
102279
|
+
// would turn the next line into a code block instead of freeing it (#1344).
|
|
102280
|
+
if (currentIndent > 3 || nextIndent > 3)
|
|
102281
|
+
return false;
|
|
102282
|
+
const currentTrimmed = line.trim();
|
|
102283
|
+
const nextTrimmed = next.trim();
|
|
102284
|
+
if (!isLineHtml(currentTrimmed) || isLineHtml(nextTrimmed) || lineLeavesRawOpen) {
|
|
102285
|
+
return false;
|
|
102286
|
+
}
|
|
102287
|
+
// Column-0 pairs keep the original (pre-relaxation) rule, deliberately ignoring
|
|
102288
|
+
// `insideRawContent`: one unclosed <pre>/<table> typo would otherwise suppress
|
|
102289
|
+
// termination for the whole rest of the document.
|
|
102290
|
+
if (currentIndent === 0 && nextIndent === 0)
|
|
102291
|
+
return true;
|
|
102292
|
+
// Indented shapes (either line at 1–3 columns) are stricter: only a lone opening
|
|
102293
|
+
// tag followed by markdown. A next line opening a tag or expression must stay
|
|
102294
|
+
// glued for the mdxComponent tokenizer; raw-content payloads stay byte-exact.
|
|
102295
|
+
return (!insideRawContent &&
|
|
102296
|
+
SINGLE_OPENING_TAG_REGEX.test(currentTrimmed) &&
|
|
102297
|
+
!nextTrimmed.startsWith('<') &&
|
|
102298
|
+
!nextTrimmed.startsWith('{'));
|
|
102299
|
+
}
|
|
102300
|
+
/**
|
|
102301
|
+
* CommonMark HTML blocks (types 6/7) end only at a blank line, so markdown on the
|
|
102302
|
+
* next line is swallowed as HTML (`## heading` after `<div>` renders as literal text).
|
|
102303
|
+
* Inserts the missing blank line; the gating rules live in `shouldTerminateBetween`.
|
|
102304
|
+
*
|
|
102305
|
+
* @link https://spec.commonmark.org/0.29/#html-blocks
|
|
102306
|
+
*/
|
|
102307
|
+
function terminateHtmlFlowBlocks(content) {
|
|
102308
|
+
const { protectedContent, protectedCode } = protectCodeBlocks(content);
|
|
102309
|
+
const lines = protectedContent.split('\n');
|
|
102310
|
+
const result = [];
|
|
102311
|
+
// Per-tag count of still-open raw-content elements at the current boundary.
|
|
102312
|
+
const rawContentDepths = RAW_CONTENT_TAG_MATCHERS.map(() => 0);
|
|
102313
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
102314
|
+
const line = lines[i];
|
|
102315
|
+
result.push(line);
|
|
102316
|
+
const tagCounts = countRawContentTags(line);
|
|
102317
|
+
tagCounts.forEach(({ opens, closes }, tagIndex) => {
|
|
102318
|
+
rawContentDepths[tagIndex] = Math.max(0, rawContentDepths[tagIndex] + opens - closes);
|
|
102319
|
+
});
|
|
102320
|
+
const next = lines[i + 1];
|
|
102321
|
+
const rawContentFacts = {
|
|
102322
|
+
insideRawContent: rawContentDepths.some(depth => depth > 0),
|
|
102323
|
+
lineLeavesRawOpen: tagCounts.some(({ opens, closes }) => opens > closes),
|
|
102324
|
+
};
|
|
102325
|
+
if (next !== undefined && shouldTerminateBetween(line, next, rawContentFacts)) {
|
|
102326
|
+
result.push('');
|
|
102327
|
+
}
|
|
102328
|
+
}
|
|
102329
|
+
return restoreCodeBlocks(result.join('\n'), protectedCode);
|
|
102330
|
+
}
|
|
102331
|
+
|
|
101982
102332
|
;// ./processor/transform/mdxish/components/mdx-blocks.ts
|
|
101983
102333
|
|
|
101984
102334
|
|
|
101985
102335
|
|
|
101986
102336
|
|
|
101987
|
-
|
|
102337
|
+
|
|
102338
|
+
|
|
102339
|
+
|
|
102340
|
+
// Matches a JSX attribute expression (e.g. `key={i}`) anywhere in a string. */
|
|
101988
102341
|
const NESTED_ATTR_EXPRESSION_RE = /[\w-]+\s*=\s*\{/;
|
|
101989
|
-
|
|
101990
|
-
|
|
101991
|
-
|
|
101992
|
-
|
|
101993
|
-
|
|
102342
|
+
// Name shape mirrors `componentTagPattern`; the lookbehind skips the inner tag
|
|
102343
|
+
// of a legacy `<<VARIABLE>>`.
|
|
102344
|
+
const NESTED_COMPONENT_TAG_RE = /(?<!<)<([A-Z][A-Za-z0-9_]*)[\s/>]/g;
|
|
102345
|
+
// Excludes tags with dedicated transformers (`Table`, `HTMLBlock`, inline
|
|
102346
|
+
// components), which expect their wrapper to stay raw.
|
|
102347
|
+
const hasNestedGenericComponentTag = (content) => [...content.matchAll(NESTED_COMPONENT_TAG_RE)].some(match => !GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(match[1]));
|
|
102348
|
+
/**
|
|
102349
|
+
* Strip the shared leading indentation from a component body so readability indentation
|
|
102350
|
+
* isn't parsed as indented code (4+ spaces), e.g. ` <p>` / ` text` -> `<p>` / ` text`.
|
|
102351
|
+
* Relative indentation is kept, so content genuinely 4+ columns deeper stays code. We
|
|
102352
|
+
* only strip when a line actually reaches 4 columns; otherwise the body is left as-is so
|
|
102353
|
+
* its leading whitespace survives as text nodes (mixed component + HTML content needs it).
|
|
101994
102354
|
*/
|
|
101995
102355
|
function safeDeindent(text) {
|
|
101996
102356
|
const lines = text.split('\n');
|
|
101997
102357
|
const nonEmptyLines = lines.filter(line => line.trim().length > 0);
|
|
101998
102358
|
if (nonEmptyLines.length === 0)
|
|
101999
102359
|
return text;
|
|
102000
|
-
|
|
102001
|
-
|
|
102002
|
-
|
|
102003
|
-
|
|
102004
|
-
|
|
102005
|
-
const stripAmount =
|
|
102360
|
+
// Indent counts characters (tab = 1), unlike indentWidth's CommonMark columns
|
|
102361
|
+
// (tab = 4) in terminate-html-flow-blocks.
|
|
102362
|
+
const indents = nonEmptyLines.map(line => line.match(/^(\s*)/)?.[1].length ?? 0);
|
|
102363
|
+
const minIndent = Math.min(...indents);
|
|
102364
|
+
const maxIndent = Math.max(...indents);
|
|
102365
|
+
const stripAmount = maxIndent > 3 ? minIndent : 0;
|
|
102006
102366
|
if (stripAmount === 0)
|
|
102007
102367
|
return text;
|
|
102008
102368
|
return lines.map(line => line.slice(stripAmount)).join('\n');
|
|
102009
102369
|
}
|
|
102010
102370
|
/**
|
|
102011
|
-
* Parse markdown
|
|
102012
|
-
*
|
|
102013
|
-
*
|
|
102371
|
+
* Parse component-body markdown into mdast children. Dedenting shifts columns and
|
|
102372
|
+
* stales the top-level `terminateHtmlFlowBlocks` decisions, so that one preprocessor
|
|
102373
|
+
* re-runs here; other column-anchored fixups (compact headings, tables) do not.
|
|
102014
102374
|
*/
|
|
102015
102375
|
const parseMdChildren = (value, safeMode) => {
|
|
102016
|
-
const parsed = getInlineMdProcessor({ safeMode }).parse(safeDeindent(value).trim());
|
|
102376
|
+
const parsed = getInlineMdProcessor({ safeMode }).parse(terminateHtmlFlowBlocks(safeDeindent(value).trim()));
|
|
102017
102377
|
return parsed.children || [];
|
|
102018
102378
|
};
|
|
102019
|
-
|
|
102020
|
-
|
|
102021
|
-
*/
|
|
102379
|
+
// Parses trailing content into sibling nodes and re-queues the parent so any
|
|
102380
|
+
// components among them get processed.
|
|
102022
102381
|
const parseSibling = (stack, parent, index, sibling, safeMode) => {
|
|
102023
102382
|
const siblingNodes = parseMdChildren(sibling, safeMode);
|
|
102024
|
-
// The new sibling nodes might contain new components to be processed
|
|
102025
102383
|
if (siblingNodes.length > 0) {
|
|
102026
102384
|
parent.children.splice(index + 1, 0, ...siblingNodes);
|
|
102027
102385
|
stack.push(parent);
|
|
102028
102386
|
}
|
|
102029
102387
|
};
|
|
102030
|
-
|
|
102031
|
-
|
|
102032
|
-
*/
|
|
102033
|
-
const pointAfter = (start, consumed) => {
|
|
102034
|
-
const newlineIndex = consumed.lastIndexOf('\n');
|
|
102035
|
-
const newlineCount = newlineIndex === -1 ? 0 : consumed.split('\n').length - 1;
|
|
102036
|
-
return {
|
|
102037
|
-
line: start.line + newlineCount,
|
|
102038
|
-
column: newlineCount === 0 ? start.column + consumed.length : consumed.length - newlineIndex,
|
|
102039
|
-
offset: start.offset + consumed.length,
|
|
102040
|
-
};
|
|
102041
|
-
};
|
|
102042
|
-
/**
|
|
102043
|
-
* Build a position ending at `consumedLength` into the html node's value, so the
|
|
102044
|
-
* component doesn't claim trailing content the tokenizer swallowed into one node.
|
|
102045
|
-
*/
|
|
102388
|
+
// Ends the position at `consumedLength` so the component doesn't claim trailing
|
|
102389
|
+
// content the tokenizer swallowed into the same html node.
|
|
102046
102390
|
const positionEndingAtConsumed = (nodePosition, value, consumedLength) => {
|
|
102047
102391
|
if (!nodePosition?.start)
|
|
102048
102392
|
return nodePosition;
|
|
102049
102393
|
return { start: nodePosition.start, end: pointAfter(nodePosition.start, value.slice(0, consumedLength)) };
|
|
102050
102394
|
};
|
|
102051
|
-
|
|
102052
|
-
|
|
102053
|
-
* this node's span in the original source. Used in the trailing-content path so
|
|
102054
|
-
* the offset is computed against the real source bytes (including blockquote/list
|
|
102055
|
-
* prefixes that were stripped from the html node's value).
|
|
102056
|
-
*/
|
|
102395
|
+
// Like `positionEndingAtConsumed`, but measures against the original source so
|
|
102396
|
+
// blockquote/list prefixes stripped from the html node's value are counted.
|
|
102057
102397
|
const positionEndingAtClosingTagInSource = (nodePosition, closingTag, source) => {
|
|
102058
102398
|
if (!nodePosition?.start || !nodePosition.end)
|
|
102059
102399
|
return nodePosition;
|
|
@@ -102064,9 +102404,6 @@ const positionEndingAtClosingTagInSource = (nodePosition, closingTag, source) =>
|
|
|
102064
102404
|
const consumed = nodeSource.slice(0, closingTagOffset + closingTag.length);
|
|
102065
102405
|
return { start: nodePosition.start, end: pointAfter(nodePosition.start, consumed) };
|
|
102066
102406
|
};
|
|
102067
|
-
/**
|
|
102068
|
-
* Create an MdxJsxFlowElement node from component data.
|
|
102069
|
-
*/
|
|
102070
102407
|
const createComponentNode = ({ tag, attributes, children, startPosition, endPosition }) => ({
|
|
102071
102408
|
type: 'mdxJsxFlowElement',
|
|
102072
102409
|
name: tag,
|
|
@@ -102119,8 +102456,7 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102119
102456
|
if ('children' in node && Array.isArray(node.children)) {
|
|
102120
102457
|
stack.push(node);
|
|
102121
102458
|
}
|
|
102122
|
-
// Only
|
|
102123
|
-
// which means a potential unparsed MDX component
|
|
102459
|
+
// Only html nodes can be an unparsed MDX component.
|
|
102124
102460
|
const value = node.value;
|
|
102125
102461
|
if (node.type !== 'html' || typeof value !== 'string')
|
|
102126
102462
|
return;
|
|
@@ -102129,32 +102465,25 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102129
102465
|
if (!parsed)
|
|
102130
102466
|
return;
|
|
102131
102467
|
const { tag, attributes, selfClosing, contentAfterTag = '' } = parsed;
|
|
102132
|
-
//
|
|
102133
|
-
// so consumed-length math maps back onto the node's real source offsets.
|
|
102468
|
+
// Offsets so consumed-length math maps back onto the node's real source.
|
|
102134
102469
|
const leadingWhitespace = value.length - value.trimStart().length;
|
|
102135
|
-
// Index right after the opening tag's `>` within `trimmed`.
|
|
102136
102470
|
const openingTagEnd = trimmed.length - contentAfterTag.length;
|
|
102137
|
-
// Skip tags that have dedicated transformers
|
|
102138
102471
|
if (GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(tag))
|
|
102139
|
-
return;
|
|
102472
|
+
return; // owned by dedicated transformers
|
|
102140
102473
|
const isPascal = isPascalCase(tag);
|
|
102141
|
-
// Lowercase inline tags
|
|
102142
|
-
//
|
|
102143
|
-
//
|
|
102144
|
-
// keep going through this transformer (they stay flow-level even when
|
|
102145
|
-
// inline, which is how ReadMe's custom components are modeled).
|
|
102474
|
+
// Lowercase inline tags with `{…}` attributes belong to
|
|
102475
|
+
// mdxishInlineComponentBlocks; leave them as html for that pass. PascalCase
|
|
102476
|
+
// components stay flow-level even when inline (ReadMe's component model).
|
|
102146
102477
|
if (!isPascal && parent.type === 'paragraph')
|
|
102147
102478
|
return;
|
|
102148
|
-
//
|
|
102149
|
-
//
|
|
102150
|
-
// JSX
|
|
102151
|
-
//
|
|
102152
|
-
// `style={{...}}`/`.map()` JSX inside it — as literal HTML text, which
|
|
102153
|
-
// rehype-raw's parse5 pass then garbles (it has no notion of JS expressions).
|
|
102154
|
-
// Plain HTML with no expressions anywhere stays as an html node so
|
|
102155
|
-
// rehype-raw handles it as normal.
|
|
102479
|
+
// A lowercase wrapper is only promoted when it (or a descendant) carries a
|
|
102480
|
+
// JSX expression or nests a component; otherwise it would swallow that inner
|
|
102481
|
+
// JSX/component as literal text that rehype-raw's parse5 pass can't handle.
|
|
102482
|
+
// Table-structural wrappers are excluded — `mdxishTables` re-parses those.
|
|
102156
102483
|
const hasNestedExpressionAttr = !selfClosing && NESTED_ATTR_EXPRESSION_RE.test(contentAfterTag);
|
|
102157
|
-
|
|
102484
|
+
const isTableStructuralTag = tag === 'table' || tableTags.has(tag);
|
|
102485
|
+
const hasNestedComponentTag = !selfClosing && !isTableStructuralTag && hasNestedGenericComponentTag(contentAfterTag);
|
|
102486
|
+
if (!isPascal && !hasExpressionAttr(attributes) && !hasNestedExpressionAttr && !hasNestedComponentTag)
|
|
102158
102487
|
return;
|
|
102159
102488
|
const closingTagStr = `</${tag}>`;
|
|
102160
102489
|
// Case 1: Self-closing tag
|
|
@@ -102168,7 +102497,6 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102168
102497
|
endPosition: positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd),
|
|
102169
102498
|
});
|
|
102170
102499
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
102171
|
-
// Check and parse if there's relevant content after the current closing tag
|
|
102172
102500
|
const remainingContent = contentAfterTag.trim();
|
|
102173
102501
|
if (remainingContent) {
|
|
102174
102502
|
parseSibling(stack, parent, index, remainingContent, safeMode);
|
|
@@ -102177,17 +102505,14 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102177
102505
|
}
|
|
102178
102506
|
// Case 2: Self-contained block (closing tag in content)
|
|
102179
102507
|
if (contentAfterTag.includes(closingTagStr)) {
|
|
102180
|
-
// Find the first closing tag
|
|
102181
102508
|
const closingTagIndex = contentAfterTag.lastIndexOf(closingTagStr);
|
|
102182
|
-
//
|
|
102183
|
-
// normalize indentation before trimming
|
|
102509
|
+
// Untrimmed so parseMdChildren can dedent before trimming.
|
|
102184
102510
|
const componentInnerContent = contentAfterTag.substring(0, closingTagIndex);
|
|
102185
102511
|
const contentAfterClose = contentAfterTag.substring(closingTagIndex + closingTagStr.length).trim();
|
|
102186
102512
|
let parsedChildren = componentInnerContent.trim()
|
|
102187
102513
|
? parseMdChildren(componentInnerContent, safeMode)
|
|
102188
102514
|
: [];
|
|
102189
|
-
// Lowercase
|
|
102190
|
-
// bare text in a paragraph; unwrap when there's exactly one paragraph so
|
|
102515
|
+
// Lowercase tags are usually inline; unwrap a sole paragraph so their
|
|
102191
102516
|
// phrasing content isn't spuriously block-wrapped.
|
|
102192
102517
|
if (!isPascal && parsedChildren.length === 1 && parsedChildren[0].type === 'paragraph') {
|
|
102193
102518
|
parsedChildren = parsedChildren[0].children;
|
|
@@ -102197,12 +102522,9 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102197
102522
|
attributes,
|
|
102198
102523
|
children: parsedChildren,
|
|
102199
102524
|
startPosition: node.position,
|
|
102200
|
-
//
|
|
102201
|
-
//
|
|
102202
|
-
//
|
|
102203
|
-
// node's value has '> '/space prefixes stripped for blockquotes/list items, so
|
|
102204
|
-
// positionEndingAtConsumed would undercount source offsets. When the entire node
|
|
102205
|
-
// is consumed, use the original node position directly.
|
|
102525
|
+
// With trailing content, end precisely at the closing tag. Prefer source
|
|
102526
|
+
// offsets when available (the node's value strips blockquote/list
|
|
102527
|
+
// prefixes); otherwise fall back to the whole node position.
|
|
102206
102528
|
endPosition: contentAfterClose
|
|
102207
102529
|
? source
|
|
102208
102530
|
? positionEndingAtClosingTagInSource(node.position, closingTagStr, source)
|
|
@@ -102210,17 +102532,16 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102210
102532
|
: node.position,
|
|
102211
102533
|
});
|
|
102212
102534
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
102213
|
-
//
|
|
102535
|
+
// Re-queue whichever side may hold further components.
|
|
102214
102536
|
if (contentAfterClose) {
|
|
102215
102537
|
parseSibling(stack, parent, index, contentAfterClose, safeMode);
|
|
102216
102538
|
}
|
|
102217
102539
|
else if (componentNode.children.length > 0) {
|
|
102218
|
-
// The content inside the component block might contain new components to be processed
|
|
102219
102540
|
stack.push(componentNode);
|
|
102220
102541
|
}
|
|
102221
102542
|
}
|
|
102222
102543
|
};
|
|
102223
|
-
//
|
|
102544
|
+
// Depth-first so nodes keep their source order.
|
|
102224
102545
|
while (stack.length) {
|
|
102225
102546
|
const parent = stack.pop();
|
|
102226
102547
|
if (parent?.children) {
|
|
@@ -102541,8 +102862,6 @@ const evaluateExports = () => (tree, file) => {
|
|
|
102541
102862
|
};
|
|
102542
102863
|
/* harmony default export */ const evaluate_exports = (evaluateExports);
|
|
102543
102864
|
|
|
102544
|
-
// EXTERNAL MODULE: ./node_modules/react-dom/server.browser.js
|
|
102545
|
-
var server_browser = __webpack_require__(5848);
|
|
102546
102865
|
;// ./lib/utils/mdxish/mdxish-expression.ts
|
|
102547
102866
|
|
|
102548
102867
|
|
|
@@ -102588,26 +102907,185 @@ const evalExpression = (expression, scope) => {
|
|
|
102588
102907
|
return evalJsxProgram(program, scope);
|
|
102589
102908
|
};
|
|
102590
102909
|
|
|
102591
|
-
|
|
102910
|
+
// EXTERNAL MODULE: ./node_modules/react-dom/server.browser.js
|
|
102911
|
+
var server_browser = __webpack_require__(5848);
|
|
102912
|
+
;// ./processor/transform/mdxish/style-object-to-css.ts
|
|
102913
|
+
|
|
102914
|
+
/**
|
|
102915
|
+
* CSS properties React treats as unitless — a bare number stays as-is instead of
|
|
102916
|
+
* getting `px` appended. Mirrors React DOM's `isUnitlessNumber` whitelist.
|
|
102917
|
+
* @see https://github.com/facebook/react/blob/main/packages/react-dom-bindings/src/shared/CSSProperty.js
|
|
102918
|
+
*/
|
|
102919
|
+
const UNITLESS_CSS_PROPERTIES = new Set([
|
|
102920
|
+
'animationIterationCount',
|
|
102921
|
+
'aspectRatio',
|
|
102922
|
+
'borderImageOutset',
|
|
102923
|
+
'borderImageSlice',
|
|
102924
|
+
'borderImageWidth',
|
|
102925
|
+
'boxFlex',
|
|
102926
|
+
'boxFlexGroup',
|
|
102927
|
+
'boxOrdinalGroup',
|
|
102928
|
+
'columnCount',
|
|
102929
|
+
'columns',
|
|
102930
|
+
'flex',
|
|
102931
|
+
'flexGrow',
|
|
102932
|
+
'flexPositive',
|
|
102933
|
+
'flexShrink',
|
|
102934
|
+
'flexNegative',
|
|
102935
|
+
'flexOrder',
|
|
102936
|
+
'gridArea',
|
|
102937
|
+
'gridRow',
|
|
102938
|
+
'gridRowEnd',
|
|
102939
|
+
'gridRowSpan',
|
|
102940
|
+
'gridRowStart',
|
|
102941
|
+
'gridColumn',
|
|
102942
|
+
'gridColumnEnd',
|
|
102943
|
+
'gridColumnSpan',
|
|
102944
|
+
'gridColumnStart',
|
|
102945
|
+
'fontWeight',
|
|
102946
|
+
'lineClamp',
|
|
102947
|
+
'lineHeight',
|
|
102948
|
+
'opacity',
|
|
102949
|
+
'order',
|
|
102950
|
+
'orphans',
|
|
102951
|
+
'tabSize',
|
|
102952
|
+
'widows',
|
|
102953
|
+
'zIndex',
|
|
102954
|
+
'zoom',
|
|
102955
|
+
'fillOpacity',
|
|
102956
|
+
'floodOpacity',
|
|
102957
|
+
'stopOpacity',
|
|
102958
|
+
'strokeDasharray',
|
|
102959
|
+
'strokeDashoffset',
|
|
102960
|
+
'strokeMiterlimit',
|
|
102961
|
+
'strokeOpacity',
|
|
102962
|
+
'strokeWidth',
|
|
102963
|
+
]);
|
|
102964
|
+
/** Convert a camelCase (or CSS custom property) key into its kebab-case CSS name. */
|
|
102965
|
+
const cssPropertyName = (key) => (key.startsWith('--') ? key : key.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`));
|
|
102966
|
+
/** React appends `px` to non-zero numeric values, except unitless and custom properties. */
|
|
102967
|
+
const cssPropertyValue = (key, value) => typeof value === 'number' && value !== 0 && !key.startsWith('--') && !UNITLESS_CSS_PROPERTIES.has(key)
|
|
102968
|
+
? `${value}px`
|
|
102969
|
+
: `${value}`;
|
|
102970
|
+
/**
|
|
102971
|
+
* True for a value that should be serialized as a style object rather than passed through
|
|
102972
|
+
* as an already-CSS string. React elements are excluded since they're valid objects too.
|
|
102973
|
+
*/
|
|
102974
|
+
const style_object_to_css_isPlainObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value) && !external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().isValidElement(value);
|
|
102975
|
+
/**
|
|
102976
|
+
* Serialize a React-style inline style object (`{ color: "red", fontSize: 12 }`) into a
|
|
102977
|
+
* CSS declaration string (`color:red;font-size:12px`), the shape hast/HTML expects for a
|
|
102978
|
+
* `style` attribute. Empty (`undefined`/`null`/`''`) entries are dropped.
|
|
102979
|
+
*/
|
|
102980
|
+
const styleObjectToCssText = (style) => Object.entries(style)
|
|
102981
|
+
.filter(([, value]) => value !== undefined && value !== null && value !== '')
|
|
102982
|
+
.map(([key, value]) => `${cssPropertyName(key)}:${cssPropertyValue(key, value)}`)
|
|
102983
|
+
.join(';');
|
|
102592
102984
|
|
|
102985
|
+
;// ./processor/transform/mdxish/react-element-to-hast.ts
|
|
102593
102986
|
|
|
102594
102987
|
|
|
102595
102988
|
|
|
102596
|
-
|
|
102597
|
-
const
|
|
102598
|
-
/**
|
|
102599
|
-
|
|
102600
|
-
|
|
102601
|
-
|
|
102989
|
+
// React props that never map to an HTML/hast attribute.
|
|
102990
|
+
const RESERVED_PROPS = new Set(['children', 'key', 'ref']);
|
|
102991
|
+
/**
|
|
102992
|
+
* Translate React props into hast `properties`: reserved and function props (event handlers)
|
|
102993
|
+
* are dropped (known gap), `style` objects flatten to CSS text. Names stay as authored (`className`); the
|
|
102994
|
+
* hast → HTML boundary maps them to `class`/`for` downstream.
|
|
102995
|
+
*/
|
|
102996
|
+
function propsToHastProperties(props) {
|
|
102997
|
+
const properties = {};
|
|
102998
|
+
Object.entries(props).forEach(([key, value]) => {
|
|
102999
|
+
if (RESERVED_PROPS.has(key) || typeof value === 'function' || value === undefined)
|
|
103000
|
+
return;
|
|
103001
|
+
properties[key] = key === 'style' && style_object_to_css_isPlainObject(value) ? styleObjectToCssText(value) : value;
|
|
103002
|
+
});
|
|
103003
|
+
// Values are resolved React props, wider than hast's HTML-attribute `PropertyValue` union.
|
|
103004
|
+
return properties;
|
|
103005
|
+
}
|
|
103006
|
+
/**
|
|
103007
|
+
* Render an element with React's own renderer as a last resort, wrapped as a hast `raw` node —
|
|
103008
|
+
* the same node type markdown's literal HTML blocks produce, so it re-enters rehypeRaw's
|
|
103009
|
+
* parse5 pass normally. Used for element types this converter can't resolve on its own (wrapped
|
|
103010
|
+
* component types, or a function component that throws when called outside React, e.g. one
|
|
103011
|
+
* using hooks). It's not immune to the invalid-HTML-nesting this module otherwise avoids, but
|
|
103012
|
+
* that's a fair trade against silently dropping the content.
|
|
103013
|
+
*/
|
|
103014
|
+
function renderFallbackHtml(element) {
|
|
103015
|
+
try {
|
|
103016
|
+
const rawNode = { type: 'raw', value: (0,server_browser/* renderToStaticMarkup */.qV)(element) };
|
|
103017
|
+
return [rawNode];
|
|
102602
103018
|
}
|
|
102603
|
-
|
|
102604
|
-
|
|
102605
|
-
// representation. This must come before the object check as both are a subset of it.
|
|
102606
|
-
return { type: 'html', value: (0,server_browser/* renderToStaticMarkup */.qV)(external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement((external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default()).Fragment, null, result)), position };
|
|
103019
|
+
catch {
|
|
103020
|
+
return [];
|
|
102607
103021
|
}
|
|
102608
|
-
|
|
102609
|
-
|
|
103022
|
+
}
|
|
103023
|
+
/**
|
|
103024
|
+
* Convert a React element tree into hast. Emitting `mdx-jsx` nodes (rehypeRaw passthrough, later normalized to `element`)
|
|
103025
|
+
* preserves nesting that is valid JSX but not valid HTML, which parse5 would otherwise
|
|
103026
|
+
* restructure — e.g. an `<a>` wrapping another `<a>`.
|
|
103027
|
+
* Recursively converts the tree into an array of hast nodes, dealing with arrays and null/undefined/boolean values.
|
|
103028
|
+
*/
|
|
103029
|
+
function reactElementToHast(node) {
|
|
103030
|
+
if (Array.isArray(node))
|
|
103031
|
+
return node.flatMap(reactElementToHast);
|
|
103032
|
+
if (node === null || node === undefined || typeof node === 'boolean')
|
|
103033
|
+
return [];
|
|
103034
|
+
if (typeof node === 'string' || typeof node === 'number') {
|
|
103035
|
+
const textNode = { type: 'text', value: String(node) };
|
|
103036
|
+
return [textNode];
|
|
102610
103037
|
}
|
|
103038
|
+
if (!external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().isValidElement(node))
|
|
103039
|
+
return [];
|
|
103040
|
+
const { type, props } = node;
|
|
103041
|
+
// Fragments contribute their children with no wrapper element.
|
|
103042
|
+
if (type === (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default()).Fragment)
|
|
103043
|
+
return reactElementToHast(props.children);
|
|
103044
|
+
// Resolve function components to their rendered output so the tree is plain intrinsic
|
|
103045
|
+
// elements. If invoking it directly throws (e.g. it uses hooks, which need React's own
|
|
103046
|
+
// render context), fall back to React's renderer for just this subtree.
|
|
103047
|
+
if (typeof type === 'function') {
|
|
103048
|
+
try {
|
|
103049
|
+
return reactElementToHast(type(props));
|
|
103050
|
+
}
|
|
103051
|
+
catch {
|
|
103052
|
+
return renderFallbackHtml(node);
|
|
103053
|
+
}
|
|
103054
|
+
}
|
|
103055
|
+
// Non-intrinsic, non-callable element types — `React.memo`, `React.forwardRef`,
|
|
103056
|
+
// `Context.Provider`/`Consumer`, `React.lazy` — have no `type` we can resolve ourselves.
|
|
103057
|
+
if (typeof type !== 'string')
|
|
103058
|
+
return renderFallbackHtml(node);
|
|
103059
|
+
const mdxJsxNode = {
|
|
103060
|
+
type: 'mdx-jsx',
|
|
103061
|
+
tagName: type,
|
|
103062
|
+
properties: propsToHastProperties(props),
|
|
103063
|
+
children: reactElementToHast(props.children),
|
|
103064
|
+
};
|
|
103065
|
+
return [mdxJsxNode];
|
|
103066
|
+
}
|
|
103067
|
+
|
|
103068
|
+
;// ./processor/transform/mdxish/evaluate-expressions.ts
|
|
103069
|
+
|
|
103070
|
+
|
|
103071
|
+
|
|
103072
|
+
|
|
103073
|
+
/**
|
|
103074
|
+
* We divide the result of an expression into two categories:
|
|
103075
|
+
* 1. Renderable values: HTML, JSX, e.g. .map() returning JSX
|
|
103076
|
+
* 2. Non-renderable values: a string, number, or object, regular JS values
|
|
103077
|
+
*/
|
|
103078
|
+
const isRenderable = (value) => {
|
|
103079
|
+
if (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().isValidElement(value))
|
|
103080
|
+
return true;
|
|
103081
|
+
return Array.isArray(value) && value.some(isRenderable);
|
|
103082
|
+
};
|
|
103083
|
+
/** Turn a non-renderable evaluation result into a text node. */
|
|
103084
|
+
const createTextNode = (result, position) => {
|
|
103085
|
+
if (result === null || result === undefined)
|
|
103086
|
+
return { type: 'text', value: '', position };
|
|
103087
|
+
if (typeof result === 'object')
|
|
103088
|
+
return { type: 'text', value: JSON.stringify(result), position };
|
|
102611
103089
|
return { type: 'text', value: String(result), position };
|
|
102612
103090
|
};
|
|
102613
103091
|
/**
|
|
@@ -102623,13 +103101,23 @@ const evaluateExpressions = () => (tree, file) => {
|
|
|
102623
103101
|
visit(tree, ['mdxFlowExpression', 'mdxTextExpression'], (node, index, parent) => {
|
|
102624
103102
|
if (!parent || index === null || index === undefined)
|
|
102625
103103
|
return;
|
|
102626
|
-
const
|
|
103104
|
+
const expressionNode = node;
|
|
103105
|
+
const { value, position } = expressionNode;
|
|
102627
103106
|
const expression = value?.trim();
|
|
102628
103107
|
if (!expression)
|
|
102629
103108
|
return;
|
|
102630
103109
|
try {
|
|
102631
103110
|
const result = evalExpression(expression, scope);
|
|
102632
|
-
|
|
103111
|
+
if (isRenderable(result)) {
|
|
103112
|
+
// Stash hast built straight from the React tree; `mdxExpressionHandler` emits it and it
|
|
103113
|
+
// passes through rehypeRaw/parse5 step later in the pipeline. This ensures that the
|
|
103114
|
+
// expression result is not parsed by parse5 and fragmenting the nesting that is valid JSX
|
|
103115
|
+
// but invalid HTML — e.g. an `<a>` wrapping `<a>`.
|
|
103116
|
+
expressionNode.data = { ...expressionNode.data, hChildren: reactElementToHast(result) };
|
|
103117
|
+
}
|
|
103118
|
+
else {
|
|
103119
|
+
parent.children.splice(index, 1, createTextNode(result, position));
|
|
103120
|
+
}
|
|
102633
103121
|
}
|
|
102634
103122
|
catch (_error) {
|
|
102635
103123
|
// Evaluation failed — fall back to literal `{...}` text. The expression
|
|
@@ -104540,79 +105028,6 @@ function removeJSXComments(content) {
|
|
|
104540
105028
|
return content.replace(JSX_COMMENT_REGEX, '');
|
|
104541
105029
|
}
|
|
104542
105030
|
|
|
104543
|
-
;// ./processor/transform/mdxish/style-object-to-css.ts
|
|
104544
|
-
|
|
104545
|
-
/**
|
|
104546
|
-
* CSS properties React treats as unitless — a bare number stays as-is instead of
|
|
104547
|
-
* getting `px` appended. Mirrors React DOM's `isUnitlessNumber` whitelist.
|
|
104548
|
-
* @see https://github.com/facebook/react/blob/main/packages/react-dom-bindings/src/shared/CSSProperty.js
|
|
104549
|
-
*/
|
|
104550
|
-
const UNITLESS_CSS_PROPERTIES = new Set([
|
|
104551
|
-
'animationIterationCount',
|
|
104552
|
-
'aspectRatio',
|
|
104553
|
-
'borderImageOutset',
|
|
104554
|
-
'borderImageSlice',
|
|
104555
|
-
'borderImageWidth',
|
|
104556
|
-
'boxFlex',
|
|
104557
|
-
'boxFlexGroup',
|
|
104558
|
-
'boxOrdinalGroup',
|
|
104559
|
-
'columnCount',
|
|
104560
|
-
'columns',
|
|
104561
|
-
'flex',
|
|
104562
|
-
'flexGrow',
|
|
104563
|
-
'flexPositive',
|
|
104564
|
-
'flexShrink',
|
|
104565
|
-
'flexNegative',
|
|
104566
|
-
'flexOrder',
|
|
104567
|
-
'gridArea',
|
|
104568
|
-
'gridRow',
|
|
104569
|
-
'gridRowEnd',
|
|
104570
|
-
'gridRowSpan',
|
|
104571
|
-
'gridRowStart',
|
|
104572
|
-
'gridColumn',
|
|
104573
|
-
'gridColumnEnd',
|
|
104574
|
-
'gridColumnSpan',
|
|
104575
|
-
'gridColumnStart',
|
|
104576
|
-
'fontWeight',
|
|
104577
|
-
'lineClamp',
|
|
104578
|
-
'lineHeight',
|
|
104579
|
-
'opacity',
|
|
104580
|
-
'order',
|
|
104581
|
-
'orphans',
|
|
104582
|
-
'tabSize',
|
|
104583
|
-
'widows',
|
|
104584
|
-
'zIndex',
|
|
104585
|
-
'zoom',
|
|
104586
|
-
'fillOpacity',
|
|
104587
|
-
'floodOpacity',
|
|
104588
|
-
'stopOpacity',
|
|
104589
|
-
'strokeDasharray',
|
|
104590
|
-
'strokeDashoffset',
|
|
104591
|
-
'strokeMiterlimit',
|
|
104592
|
-
'strokeOpacity',
|
|
104593
|
-
'strokeWidth',
|
|
104594
|
-
]);
|
|
104595
|
-
/** Convert a camelCase (or CSS custom property) key into its kebab-case CSS name. */
|
|
104596
|
-
const cssPropertyName = (key) => (key.startsWith('--') ? key : key.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`));
|
|
104597
|
-
/** React appends `px` to non-zero numeric values, except unitless and custom properties. */
|
|
104598
|
-
const cssPropertyValue = (key, value) => typeof value === 'number' && value !== 0 && !key.startsWith('--') && !UNITLESS_CSS_PROPERTIES.has(key)
|
|
104599
|
-
? `${value}px`
|
|
104600
|
-
: `${value}`;
|
|
104601
|
-
/**
|
|
104602
|
-
* True for a value that should be serialized as a style object rather than passed through
|
|
104603
|
-
* as an already-CSS string. React elements are excluded since they're valid objects too.
|
|
104604
|
-
*/
|
|
104605
|
-
const style_object_to_css_isPlainObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value) && !external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().isValidElement(value);
|
|
104606
|
-
/**
|
|
104607
|
-
* Serialize a React-style inline style object (`{ color: "red", fontSize: 12 }`) into a
|
|
104608
|
-
* CSS declaration string (`color:red;font-size:12px`), the shape hast/HTML expects for a
|
|
104609
|
-
* `style` attribute. Empty (`undefined`/`null`/`''`) entries are dropped.
|
|
104610
|
-
*/
|
|
104611
|
-
const styleObjectToCssText = (style) => Object.entries(style)
|
|
104612
|
-
.filter(([, value]) => value !== undefined && value !== null && value !== '')
|
|
104613
|
-
.map(([key, value]) => `${cssPropertyName(key)}:${cssPropertyValue(key, value)}`)
|
|
104614
|
-
.join(';');
|
|
104615
|
-
|
|
104616
105031
|
;// ./processor/transform/mdxish/resolve-deferred-attribute-expression-props.ts
|
|
104617
105032
|
|
|
104618
105033
|
|
|
@@ -104959,73 +105374,6 @@ function normalizeTableSeparator(content) {
|
|
|
104959
105374
|
}
|
|
104960
105375
|
/* harmony default export */ const normalize_table_separator = ((/* unused pure expression or super */ null && (normalizeTableSeparator)));
|
|
104961
105376
|
|
|
104962
|
-
;// ./processor/transform/mdxish/terminate-html-flow-blocks.ts
|
|
104963
|
-
|
|
104964
|
-
|
|
104965
|
-
|
|
104966
|
-
const STANDALONE_HTML_LINE_REGEX = /^(<[a-z][^<>]*>|<\/[a-z][^<>]*>)+\s*$/;
|
|
104967
|
-
const HTML_LINE_WITH_CONTENT_REGEX = /^<[a-z][^<>]*>.*<\/[a-z][^<>]*>(?:[^<]*)$/;
|
|
104968
|
-
// Tags whose contents must be preserved as is, inserting a blank line after the
|
|
104969
|
-
// opener corrupts the payload.
|
|
104970
|
-
// htmlRawNames here refer to <pre>, <textarea>, <script>, <style>
|
|
104971
|
-
const RAW_CONTENT_TAGS = [...htmlRawNames, ...HTML_TABLE_STRUCTURE_TAGS];
|
|
104972
|
-
// The `(?=[\s/>])` lookahead avoids false matches on lookalike names like `<script-foo>`.
|
|
104973
|
-
const RAW_CONTENT_TAG_MATCHERS = RAW_CONTENT_TAGS.map(tag => ({
|
|
104974
|
-
open: new RegExp(`<${tag}(?=[\\s/>])[^>]*?(?<!/)>`, 'gi'),
|
|
104975
|
-
close: new RegExp(`</${tag}(?=[\\s>])[^>]*>`, 'gi'),
|
|
104976
|
-
}));
|
|
104977
|
-
function isLineHtml(line) {
|
|
104978
|
-
return STANDALONE_HTML_LINE_REGEX.test(line) || HTML_LINE_WITH_CONTENT_REGEX.test(line);
|
|
104979
|
-
}
|
|
104980
|
-
// True if any RAW_CONTENT_TAGS opener on this line is not closed on the same line.
|
|
104981
|
-
function hasUnclosedRawContentOpener(line) {
|
|
104982
|
-
return RAW_CONTENT_TAG_MATCHERS.some(({ open, close }) => {
|
|
104983
|
-
const opens = (line.match(open) ?? []).length;
|
|
104984
|
-
const closes = (line.match(close) ?? []).length;
|
|
104985
|
-
return opens > closes;
|
|
104986
|
-
});
|
|
104987
|
-
}
|
|
104988
|
-
/**
|
|
104989
|
-
* Preprocessor to terminate HTML flow blocks.
|
|
104990
|
-
*
|
|
104991
|
-
* In CommonMark, HTML blocks (types 6 and 7) only terminate on a blank line.
|
|
104992
|
-
* Without one, any content on the next line is consumed as part of the HTML block
|
|
104993
|
-
* and never parsed as its own construct. For example, a `[block:callout]` immediately
|
|
104994
|
-
* following `<div><p></p></div>` gets swallowed into the HTML flow token.
|
|
104995
|
-
*
|
|
104996
|
-
* @link https://spec.commonmark.org/0.29/#html-blocks
|
|
104997
|
-
*
|
|
104998
|
-
* This preprocessor inserts a blank line after standalone HTML lines when the next
|
|
104999
|
-
* line is non-blank and not an HTML construct, ensuring micromark's HTML flow
|
|
105000
|
-
* tokenizer terminates and subsequent content is parsed independently.
|
|
105001
|
-
*
|
|
105002
|
-
* Conditions:
|
|
105003
|
-
* 1. Only non-indented lines with lowercase tag names are considered. Uppercase tags
|
|
105004
|
-
* (e.g. `<Table>`, `<MyComponent>`) are JSX custom components and don't trigger
|
|
105005
|
-
* CommonMark HTML blocks.
|
|
105006
|
-
* 2. Lines inside protected blocks (e.g. fenced code) are left untouched.
|
|
105007
|
-
* 3. Lines with an unclosed RAW_CONTENT_TAGS opener are exempted.
|
|
105008
|
-
*/
|
|
105009
|
-
function terminateHtmlFlowBlocks(content) {
|
|
105010
|
-
const { protectedContent, protectedCode } = protectCodeBlocks(content);
|
|
105011
|
-
const lines = protectedContent.split('\n');
|
|
105012
|
-
const result = [];
|
|
105013
|
-
for (let i = 0; i < lines.length; i += 1) {
|
|
105014
|
-
result.push(lines[i]);
|
|
105015
|
-
// Skip blank & indented lines
|
|
105016
|
-
if (i >= lines.length - 1 || lines[i + 1].trim().length === 0 || lines[i + 1].startsWith(' ') || lines[i + 1].startsWith('\t')) {
|
|
105017
|
-
// eslint-disable-next-line no-continue
|
|
105018
|
-
continue;
|
|
105019
|
-
}
|
|
105020
|
-
const isCurrentLineHtml = isLineHtml(lines[i]);
|
|
105021
|
-
const isNextLineHtml = isLineHtml(lines[i + 1]);
|
|
105022
|
-
if (isCurrentLineHtml && !isNextLineHtml && !hasUnclosedRawContentOpener(lines[i])) {
|
|
105023
|
-
result.push('');
|
|
105024
|
-
}
|
|
105025
|
-
}
|
|
105026
|
-
return restoreCodeBlocks(result.join('\n'), protectedCode);
|
|
105027
|
-
}
|
|
105028
|
-
|
|
105029
105377
|
;// ./processor/transform/mdxish/variables-code.ts
|
|
105030
105378
|
|
|
105031
105379
|
|
|
@@ -105893,6 +106241,12 @@ function mdxishMdastToMd(mdast) {
|
|
|
105893
106241
|
.use(remarkStringify, {
|
|
105894
106242
|
bullet: '-',
|
|
105895
106243
|
emphasis: '_',
|
|
106244
|
+
// Escape literal braces in text so they don't parse as (often
|
|
106245
|
+
// unterminated) MDX expressions on the next round trip.
|
|
106246
|
+
unsafe: [
|
|
106247
|
+
{ character: '{', inConstruct: 'phrasing' },
|
|
106248
|
+
{ character: '}', inConstruct: 'phrasing' },
|
|
106249
|
+
],
|
|
105896
106250
|
});
|
|
105897
106251
|
return processor.stringify(processor.runSync(mdast));
|
|
105898
106252
|
}
|