@readme/markdown 14.13.0 → 14.13.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/components/Accordion/style.scss +4 -0
- package/components/TailwindRoot/index.tsx +4 -0
- package/dist/example/components.d.ts +2 -0
- package/dist/lib/mdxish.d.ts +1 -1
- package/dist/lib/micromark/mdx-component/continuation-checks.d.ts +3 -0
- package/dist/lib/renderMdxish.d.ts +1 -1
- package/dist/main.css +2 -2
- package/dist/main.css.map +1 -1
- package/dist/main.js +243 -116
- package/dist/main.node.js +243 -116
- package/dist/main.node.js.map +1 -1
- package/dist/processor/plugin/mdxish-components.d.ts +1 -1
- package/dist/processor/transform/mdxish/components/mdx-blocks.d.ts +0 -31
- package/dist/render-fixture.css +1 -1
- package/dist/render-fixture.css.map +1 -1
- package/dist/render-fixture.node.js +243 -116
- package/dist/render-fixture.node.js.map +1 -1
- package/dist/utils/common-html-words.d.ts +9 -0
- package/package.json +1 -1
- package/styles/gfm.scss +15 -1
package/dist/main.node.js
CHANGED
|
@@ -25271,6 +25271,10 @@ const tailwindPrefix = 'readme-tailwind';
|
|
|
25271
25271
|
|
|
25272
25272
|
|
|
25273
25273
|
const TailwindRoot = ({ children, flow }) => {
|
|
25274
|
+
// `styles/gfm.scss` spaces the wrapped block children through this element and
|
|
25275
|
+
// relies on their margins collapsing through it. Keep it a plain block — no
|
|
25276
|
+
// border, padding, or block formatting context (overflow, display: flow-root/
|
|
25277
|
+
// flex/grid) — or the spacing breaks.
|
|
25274
25278
|
const Tag = flow ? 'div' : 'span';
|
|
25275
25279
|
return external_react_default().createElement(Tag, { className: tailwindPrefix }, children);
|
|
25276
25280
|
};
|
|
@@ -96525,6 +96529,15 @@ const HTML_TABLE_STRUCTURE_TAGS = new Set([
|
|
|
96525
96529
|
'caption',
|
|
96526
96530
|
'colgroup',
|
|
96527
96531
|
]);
|
|
96532
|
+
/**
|
|
96533
|
+
* Tags whose bodies a later mdxish transform keeps raw and never re-parses as
|
|
96534
|
+
* markdown. Both layers depend on this property, not on the tags being figures:
|
|
96535
|
+
* the transformer treats them as non-promotable, and the tokenizer must not claim
|
|
96536
|
+
* markdown islands inside them (a claimed island would never be re-parsed and would
|
|
96537
|
+
* leak as literal text). Currently just the figure tags, whose bodies are owned by
|
|
96538
|
+
* the figure reassembly transform (`mdxishJsxToMdast`).
|
|
96539
|
+
*/
|
|
96540
|
+
const NON_REPARSED_BODY_TAGS = new Set(['figure', 'figcaption']);
|
|
96528
96541
|
/**
|
|
96529
96542
|
* The two HTML "foreign content" namespaces: SVG and MathML. Their descendants
|
|
96530
96543
|
* (`<path>`, `<mrow>`, …) are namespaced XML, not HTML tags or components. A closed
|
|
@@ -119322,7 +119335,7 @@ function normalizeProperties(node) {
|
|
|
119322
119335
|
* Identifies custom MDX components and recursively parses markdown children.
|
|
119323
119336
|
* Replaces tagName with PascalCase component name for React component resolution.
|
|
119324
119337
|
*
|
|
119325
|
-
* @see
|
|
119338
|
+
* @see .claude/context/MDXish/Processor Overview.md
|
|
119326
119339
|
* @param {Options} options - Configuration options
|
|
119327
119340
|
* @param {CustomComponents} options.components - Available custom components
|
|
119328
119341
|
* @param {Function} options.processMarkdown - Function to process markdown content
|
|
@@ -121722,12 +121735,95 @@ function tokenizeMagicBlockText(effects, ok, nok) {
|
|
|
121722
121735
|
*/
|
|
121723
121736
|
|
|
121724
121737
|
|
|
121738
|
+
;// ./lib/micromark/mdx-component/continuation-checks.ts
|
|
121739
|
+
|
|
121740
|
+
|
|
121741
|
+
/**
|
|
121742
|
+
* Partial constructs the `mdxComponent` tokenizer runs via `effects.check` to
|
|
121743
|
+
* decide whether the next line continues the block. They live here (not in
|
|
121744
|
+
* `syntax.ts`) because they hold none of `createTokenize`'s closure state — each
|
|
121745
|
+
* is a self-contained, single-line lookahead.
|
|
121746
|
+
*/
|
|
121747
|
+
function continuation_checks_tokenizeNonLazyContinuationStart(effects, ok, nok) {
|
|
121748
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
121749
|
+
const self = this;
|
|
121750
|
+
return start;
|
|
121751
|
+
function start(code) {
|
|
121752
|
+
if (markdownLineEnding(code)) {
|
|
121753
|
+
effects.enter(types_types.lineEnding);
|
|
121754
|
+
effects.consume(code);
|
|
121755
|
+
effects.exit(types_types.lineEnding);
|
|
121756
|
+
return after;
|
|
121757
|
+
}
|
|
121758
|
+
return nok(code);
|
|
121759
|
+
}
|
|
121760
|
+
function after(code) {
|
|
121761
|
+
if (self.parser.lazy[self.now().line]) {
|
|
121762
|
+
return nok(code);
|
|
121763
|
+
}
|
|
121764
|
+
return ok(code);
|
|
121765
|
+
}
|
|
121766
|
+
}
|
|
121767
|
+
// A markup-only line opens with a tag (`<x`/`</x`) and ends (ignoring trailing
|
|
121768
|
+
// spaces) at a `>`. That distinguishes a structural continuation like
|
|
121769
|
+
// `<span>b</span></div>` from a paragraph like `<b>Note:</b> read *this*`.
|
|
121770
|
+
function tokenizeMarkupOnlyContinuation(effects, ok, nok) {
|
|
121771
|
+
let lastNonSpace = null;
|
|
121772
|
+
return start;
|
|
121773
|
+
function start(code) {
|
|
121774
|
+
// Caller guarantees we are at `<` at the (already de-indented) line start.
|
|
121775
|
+
effects.enter(types_types.data);
|
|
121776
|
+
effects.consume(code);
|
|
121777
|
+
return afterLessThan;
|
|
121778
|
+
}
|
|
121779
|
+
function afterLessThan(code) {
|
|
121780
|
+
if (code === codes.slash) {
|
|
121781
|
+
effects.consume(code);
|
|
121782
|
+
return afterSlash;
|
|
121783
|
+
}
|
|
121784
|
+
return afterSlash(code);
|
|
121785
|
+
}
|
|
121786
|
+
// The `<` (or `</`) must introduce a real tag, not a stray `<` in prose.
|
|
121787
|
+
function afterSlash(code) {
|
|
121788
|
+
if (asciiAlpha(code)) {
|
|
121789
|
+
lastNonSpace = code;
|
|
121790
|
+
effects.consume(code);
|
|
121791
|
+
return scanToLineEnd;
|
|
121792
|
+
}
|
|
121793
|
+
effects.exit(types_types.data);
|
|
121794
|
+
return nok(code);
|
|
121795
|
+
}
|
|
121796
|
+
function scanToLineEnd(code) {
|
|
121797
|
+
if (code === null || markdownLineEnding(code)) {
|
|
121798
|
+
effects.exit(types_types.data);
|
|
121799
|
+
return lastNonSpace === codes.greaterThan ? ok(code) : nok(code);
|
|
121800
|
+
}
|
|
121801
|
+
if (!markdownSpace(code))
|
|
121802
|
+
lastNonSpace = code;
|
|
121803
|
+
effects.consume(code);
|
|
121804
|
+
return scanToLineEnd;
|
|
121805
|
+
}
|
|
121806
|
+
}
|
|
121807
|
+
// A line ending whose next line isn't a lazy paragraph continuation. Checked so a
|
|
121808
|
+
// component body's blank/continuation lines aren't stolen by an interrupted paragraph.
|
|
121809
|
+
const continuation_checks_nonLazyContinuationStart = {
|
|
121810
|
+
tokenize: continuation_checks_tokenizeNonLazyContinuationStart,
|
|
121811
|
+
partial: true,
|
|
121812
|
+
};
|
|
121813
|
+
// Lookahead for `plainClaimLineStart`: is this line markup-only, or a paragraph
|
|
121814
|
+
// that merely starts with a tag? Run via `effects.check` so it never consumes.
|
|
121815
|
+
const markupOnlyContinuation = {
|
|
121816
|
+
tokenize: tokenizeMarkupOnlyContinuation,
|
|
121817
|
+
partial: true,
|
|
121818
|
+
};
|
|
121819
|
+
|
|
121725
121820
|
;// ./lib/micromark/mdx-component/syntax.ts
|
|
121726
121821
|
|
|
121727
121822
|
|
|
121728
121823
|
|
|
121729
121824
|
|
|
121730
121825
|
|
|
121826
|
+
|
|
121731
121827
|
// Raw tags (type-1: pre/script/style/textarea) and block tags (type-6: div,
|
|
121732
121828
|
// section, …) always start a block, so they stay flow even with trailing
|
|
121733
121829
|
// content. Other lowercase tags (i, span, …) follow the type-7 rule and only
|
|
@@ -121737,16 +121833,19 @@ const htmlFlowTagNames = new Set([...htmlRawNames, ...htmlBlockNames]);
|
|
|
121737
121833
|
// blank lines between nested JSX siblings don't fragment the block. Excludes table
|
|
121738
121834
|
// tags (mdxishTables owns their blank lines) and voids (never close).
|
|
121739
121835
|
const plainBlockClaimTagNames = new Set([...htmlBlockNames].filter(tag => !HTML_TABLE_STRUCTURE_TAGS.has(tag) && !HTML_VOID_ELEMENTS.has(tag)));
|
|
121740
|
-
const
|
|
121741
|
-
|
|
121742
|
-
|
|
121743
|
-
|
|
121744
|
-
//
|
|
121745
|
-
//
|
|
121746
|
-
const
|
|
121747
|
-
|
|
121748
|
-
|
|
121749
|
-
|
|
121836
|
+
const foreignContentTags = new Set(FOREIGN_CONTENT_TAGS);
|
|
121837
|
+
// Type-7 lowercase tags (a, span, button, and unknown names): CommonMark ends their
|
|
121838
|
+
// block at a blank line, fragmenting 4+ column children into indented code. Claimable
|
|
121839
|
+
// only in block-wrapper shape (see `blockWrapperOpenerRest`); lookalike openers
|
|
121840
|
+
// (`<https://…>`) never find a closer, so their claim retreats cleanly to CommonMark.
|
|
121841
|
+
// Voids never close and raw/foreign-content bodies have dedicated owners.
|
|
121842
|
+
const isBlockWrapperClaimTagName = (tag) => !htmlFlowTagNames.has(tag) && !HTML_VOID_ELEMENTS.has(tag) && !foreignContentTags.has(tag);
|
|
121843
|
+
// Both are 4 columns per CommonMark, but they mean different things: a tab advances
|
|
121844
|
+
// to the next multiple of TAB_STOP_WIDTH, and INDENTED_CODE_MIN_COLUMNS is the depth
|
|
121845
|
+
// at which a line would fragment into indented code. Named separately so the two
|
|
121846
|
+
// concepts don't read as one incidental literal.
|
|
121847
|
+
const TAB_STOP_WIDTH = 4;
|
|
121848
|
+
const INDENTED_CODE_MIN_COLUMNS = 4;
|
|
121750
121849
|
function resolveToMdxComponent(events) {
|
|
121751
121850
|
let index = events.length;
|
|
121752
121851
|
while (index > 0) {
|
|
@@ -121805,6 +121904,23 @@ function createTokenize(mode) {
|
|
|
121805
121904
|
// `plainClaimLineStart`: after a blank line it may only continue on a tag line.
|
|
121806
121905
|
let isPlainBlockClaim = false;
|
|
121807
121906
|
let pendingBlankLine = false;
|
|
121907
|
+
// Type-7 tag claimed pending the block-wrapper (opener alone on its line) check.
|
|
121908
|
+
let pendingBlockWrapperClaim = false;
|
|
121909
|
+
// True once a block-wrapper claim is confirmed; relaxes the top-of-body island gate
|
|
121910
|
+
// below (type-7 fallback is the fragmentation bug, not intentional indented code).
|
|
121911
|
+
let isBlockWrapperClaim = false;
|
|
121912
|
+
// Leading indent columns of the current plain-claim line, reset per line; ≥4 is
|
|
121913
|
+
// where CommonMark would fragment the island as indented code. Tabs advance to the
|
|
121914
|
+
// next 4-column stop — the same rule `expandIndentToColumns`
|
|
121915
|
+
// (processor/transform/mdxish/indentation.ts) applies, kept in sync by hand since
|
|
121916
|
+
// this side works on a `Code` stream, not a string. NB: do NOT swap this for
|
|
121917
|
+
// `self.now().column`; micromark bumps the point column by 1 per `horizontalTab`
|
|
121918
|
+
// code (the trailing `virtualSpace` codes don't move it), so it measures a tab as
|
|
121919
|
+
// 1 column, reviving the tab-under-measurement bug this math exists to avoid.
|
|
121920
|
+
let plainClaimIndentColumns = 0;
|
|
121921
|
+
// True once a non-blank line follows the opener: a deep island below it is nested
|
|
121922
|
+
// (cosmetic indent), not top-of-body indented code.
|
|
121923
|
+
let sawPlainBlockBodyContent = false;
|
|
121808
121924
|
// Code span tracking
|
|
121809
121925
|
let codeSpanOpenSize = 0;
|
|
121810
121926
|
let codeSpanCloseSize = 0;
|
|
@@ -122038,16 +122154,11 @@ function createTokenize(mode) {
|
|
|
122038
122154
|
}
|
|
122039
122155
|
// End of opening tag
|
|
122040
122156
|
if (code === codes.greaterThan) {
|
|
122041
|
-
if (requiresBraceAttr && !sawBraceAttr)
|
|
122042
|
-
|
|
122043
|
-
// `plainClaimLineStart`; everything else falls through to CommonMark.
|
|
122044
|
-
if (!isFlow || !plainBlockClaimTagNames.has(tagName))
|
|
122045
|
-
return nok(code);
|
|
122046
|
-
isPlainBlockClaim = true;
|
|
122047
|
-
}
|
|
122157
|
+
if (requiresBraceAttr && !sawBraceAttr && !claimBraceLessTag())
|
|
122158
|
+
return nok(code);
|
|
122048
122159
|
effects.consume(code);
|
|
122049
122160
|
onOpenerLine = isFlow;
|
|
122050
|
-
return body;
|
|
122161
|
+
return pendingBlockWrapperClaim ? blockWrapperOpenerRest : body;
|
|
122051
122162
|
}
|
|
122052
122163
|
// Quoted attribute value
|
|
122053
122164
|
if (code === codes.quotationMark || code === codes.apostrophe) {
|
|
@@ -122102,9 +122213,38 @@ function createTokenize(mode) {
|
|
|
122102
122213
|
// `/ ` without `>` is just part of the attribute area
|
|
122103
122214
|
return afterOpenTagName(code);
|
|
122104
122215
|
}
|
|
122216
|
+
// Whether a brace-less lowercase flow tag is claimable: type-6 tags immediately,
|
|
122217
|
+
// type-7 tags pending the block-wrapper check; anything else is CommonMark's.
|
|
122218
|
+
function claimBraceLessTag() {
|
|
122219
|
+
if (!isFlow)
|
|
122220
|
+
return false;
|
|
122221
|
+
if (plainBlockClaimTagNames.has(tagName)) {
|
|
122222
|
+
isPlainBlockClaim = true;
|
|
122223
|
+
return true;
|
|
122224
|
+
}
|
|
122225
|
+
if (isBlockWrapperClaimTagName(tagName)) {
|
|
122226
|
+
pendingBlockWrapperClaim = true;
|
|
122227
|
+
return true;
|
|
122228
|
+
}
|
|
122229
|
+
return false;
|
|
122230
|
+
}
|
|
122231
|
+
// A type-7 tag is claimed only as a block wrapper: opener alone on its line
|
|
122232
|
+
// (trailing spaces ok). Inline content after the opener bails to CommonMark.
|
|
122233
|
+
function blockWrapperOpenerRest(code) {
|
|
122234
|
+
if (markdownSpace(code)) {
|
|
122235
|
+
effects.consume(code);
|
|
122236
|
+
return blockWrapperOpenerRest;
|
|
122237
|
+
}
|
|
122238
|
+
if (!markdownLineEnding(code))
|
|
122239
|
+
return nok(code);
|
|
122240
|
+
pendingBlockWrapperClaim = false;
|
|
122241
|
+
isPlainBlockClaim = true;
|
|
122242
|
+
isBlockWrapperClaim = true;
|
|
122243
|
+
return body(code);
|
|
122244
|
+
}
|
|
122105
122245
|
// Continuation for multi-line opening tags
|
|
122106
122246
|
function openTagContinuationStart(code) {
|
|
122107
|
-
return effects.check(
|
|
122247
|
+
return effects.check(continuation_checks_nonLazyContinuationStart, openTagContinuationNonLazy, continuationAfter)(code);
|
|
122108
122248
|
}
|
|
122109
122249
|
function openTagContinuationNonLazy(code) {
|
|
122110
122250
|
sawLineEnding = true;
|
|
@@ -122149,6 +122289,9 @@ function createTokenize(mode) {
|
|
|
122149
122289
|
}
|
|
122150
122290
|
if (code !== codes.space && code !== codes.horizontalTab) {
|
|
122151
122291
|
openerLineHasContent = true;
|
|
122292
|
+
// Continuation content marks a later deep island as nested, not indented code.
|
|
122293
|
+
if (!onOpenerLine)
|
|
122294
|
+
sawPlainBlockBodyContent = true;
|
|
122152
122295
|
}
|
|
122153
122296
|
if (code === codes.backslash) {
|
|
122154
122297
|
effects.consume(code);
|
|
@@ -122229,7 +122372,7 @@ function createTokenize(mode) {
|
|
|
122229
122372
|
return inFencedCode;
|
|
122230
122373
|
}
|
|
122231
122374
|
function fencedCodeContinuationStart(code) {
|
|
122232
|
-
return effects.check(
|
|
122375
|
+
return effects.check(continuation_checks_nonLazyContinuationStart, fencedCodeContinuationNonLazy, continuationAfter)(code);
|
|
122233
122376
|
}
|
|
122234
122377
|
function fencedCodeContinuationNonLazy(code) {
|
|
122235
122378
|
sawLineEnding = true;
|
|
@@ -122437,7 +122580,7 @@ function createTokenize(mode) {
|
|
|
122437
122580
|
}
|
|
122438
122581
|
// ── Body continuation (line endings) ───────────────────────────────────
|
|
122439
122582
|
function bodyContinuationStart(code) {
|
|
122440
|
-
return effects.check(
|
|
122583
|
+
return effects.check(continuation_checks_nonLazyContinuationStart, bodyContinuationNonLazy, continuationAfter)(code);
|
|
122441
122584
|
}
|
|
122442
122585
|
function bodyContinuationNonLazy(code) {
|
|
122443
122586
|
sawLineEnding = true;
|
|
@@ -122463,8 +122606,10 @@ function createTokenize(mode) {
|
|
|
122463
122606
|
return inBodyBraceString(code);
|
|
122464
122607
|
return inBodyBraceExpr(code);
|
|
122465
122608
|
}
|
|
122466
|
-
if (isPlainBlockClaim)
|
|
122609
|
+
if (isPlainBlockClaim) {
|
|
122610
|
+
plainClaimIndentColumns = 0;
|
|
122467
122611
|
return plainClaimLineStart(code);
|
|
122612
|
+
}
|
|
122468
122613
|
return bodyLineStart(code);
|
|
122469
122614
|
}
|
|
122470
122615
|
// Dispatch a non-blank continuation line: fenced code at line start, else body.
|
|
@@ -122492,8 +122637,16 @@ function createTokenize(mode) {
|
|
|
122492
122637
|
// continue on a tag line (`<…`); any markdown island (`**bold**`, `[block:…]`, a
|
|
122493
122638
|
// fence) refuses so CommonMark html-flow reparses it exactly as it does today.
|
|
122494
122639
|
function plainClaimLineStart(code) {
|
|
122495
|
-
// Leading whitespace only → treat as a blank line, matching CommonMark.
|
|
122496
|
-
|
|
122640
|
+
// Leading whitespace only → treat as a blank line, matching CommonMark. A tab
|
|
122641
|
+
// advances to the next stop; its trailing `virtualSpace` fillers add nothing
|
|
122642
|
+
// but must still be consumed or they'd read as line content below.
|
|
122643
|
+
if (markdownSpace(code)) {
|
|
122644
|
+
if (code === codes.horizontalTab) {
|
|
122645
|
+
plainClaimIndentColumns += TAB_STOP_WIDTH - (plainClaimIndentColumns % TAB_STOP_WIDTH);
|
|
122646
|
+
}
|
|
122647
|
+
else if (code === codes.space) {
|
|
122648
|
+
plainClaimIndentColumns += 1;
|
|
122649
|
+
}
|
|
122497
122650
|
effects.consume(code);
|
|
122498
122651
|
return plainClaimLineStart;
|
|
122499
122652
|
}
|
|
@@ -122502,10 +122655,19 @@ function createTokenize(mode) {
|
|
|
122502
122655
|
effects.exit('mdxComponentData');
|
|
122503
122656
|
return bodyContinuationStart(code);
|
|
122504
122657
|
}
|
|
122505
|
-
// Across a blank line the block only continues onto a markup-only line; a
|
|
122506
|
-
// paragraph that merely starts with a tag must fall back so its markdown
|
|
122507
|
-
// parses and rehype-raw re-nests it into the wrapper.
|
|
122508
122658
|
if (pendingBlankLine) {
|
|
122659
|
+
// A 4+ col island nested under other tags is cosmetic nesting indent, not code:
|
|
122660
|
+
// keep claiming so promotion dedents + re-parses it as markdown (RM-17560).
|
|
122661
|
+
// Block-wrapper claims extend this to top-of-body islands — their CommonMark
|
|
122662
|
+
// fallback is the fragmentation bug, not intentional indented code. Tags whose
|
|
122663
|
+
// bodies stay raw are excluded: a claimed island there would leak as literal text.
|
|
122664
|
+
if (plainClaimIndentColumns >= INDENTED_CODE_MIN_COLUMNS &&
|
|
122665
|
+
(sawPlainBlockBodyContent || isBlockWrapperClaim) &&
|
|
122666
|
+
!NON_REPARSED_BODY_TAGS.has(tagName)) {
|
|
122667
|
+
return plainClaimContinue(code);
|
|
122668
|
+
}
|
|
122669
|
+
// Otherwise only a markup-only tag line continues; markdown/prose falls back to
|
|
122670
|
+
// CommonMark so it parses and rehype-raw re-nests it into the wrapper.
|
|
122509
122671
|
if (code !== codes.lessThan)
|
|
122510
122672
|
return nok(code);
|
|
122511
122673
|
return effects.check(markupOnlyContinuation, plainClaimContinue, nok)(code);
|
|
@@ -122526,66 +122688,6 @@ function createTokenize(mode) {
|
|
|
122526
122688
|
}
|
|
122527
122689
|
};
|
|
122528
122690
|
}
|
|
122529
|
-
function mdx_component_syntax_tokenizeNonLazyContinuationStart(effects, ok, nok) {
|
|
122530
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
122531
|
-
const self = this;
|
|
122532
|
-
return start;
|
|
122533
|
-
function start(code) {
|
|
122534
|
-
if (markdownLineEnding(code)) {
|
|
122535
|
-
effects.enter(types_types.lineEnding);
|
|
122536
|
-
effects.consume(code);
|
|
122537
|
-
effects.exit(types_types.lineEnding);
|
|
122538
|
-
return after;
|
|
122539
|
-
}
|
|
122540
|
-
return nok(code);
|
|
122541
|
-
}
|
|
122542
|
-
function after(code) {
|
|
122543
|
-
if (self.parser.lazy[self.now().line]) {
|
|
122544
|
-
return nok(code);
|
|
122545
|
-
}
|
|
122546
|
-
return ok(code);
|
|
122547
|
-
}
|
|
122548
|
-
}
|
|
122549
|
-
// A markup-only line opens with a tag (`<x`/`</x`) and ends (ignoring trailing
|
|
122550
|
-
// spaces) at a `>`. That distinguishes a structural continuation like
|
|
122551
|
-
// `<span>b</span></div>` from a paragraph like `<b>Note:</b> read *this*`.
|
|
122552
|
-
function tokenizeMarkupOnlyContinuation(effects, ok, nok) {
|
|
122553
|
-
let lastNonSpace = null;
|
|
122554
|
-
return start;
|
|
122555
|
-
function start(code) {
|
|
122556
|
-
// Caller guarantees we are at `<` at the (already de-indented) line start.
|
|
122557
|
-
effects.enter(types_types.data);
|
|
122558
|
-
effects.consume(code);
|
|
122559
|
-
return afterLessThan;
|
|
122560
|
-
}
|
|
122561
|
-
function afterLessThan(code) {
|
|
122562
|
-
if (code === codes.slash) {
|
|
122563
|
-
effects.consume(code);
|
|
122564
|
-
return afterSlash;
|
|
122565
|
-
}
|
|
122566
|
-
return afterSlash(code);
|
|
122567
|
-
}
|
|
122568
|
-
// The `<` (or `</`) must introduce a real tag, not a stray `<` in prose.
|
|
122569
|
-
function afterSlash(code) {
|
|
122570
|
-
if (asciiAlpha(code)) {
|
|
122571
|
-
lastNonSpace = code;
|
|
122572
|
-
effects.consume(code);
|
|
122573
|
-
return scanToLineEnd;
|
|
122574
|
-
}
|
|
122575
|
-
effects.exit(types_types.data);
|
|
122576
|
-
return nok(code);
|
|
122577
|
-
}
|
|
122578
|
-
function scanToLineEnd(code) {
|
|
122579
|
-
if (code === null || markdownLineEnding(code)) {
|
|
122580
|
-
effects.exit(types_types.data);
|
|
122581
|
-
return lastNonSpace === codes.greaterThan ? ok(code) : nok(code);
|
|
122582
|
-
}
|
|
122583
|
-
if (!markdownSpace(code))
|
|
122584
|
-
lastNonSpace = code;
|
|
122585
|
-
effects.consume(code);
|
|
122586
|
-
return scanToLineEnd;
|
|
122587
|
-
}
|
|
122588
|
-
}
|
|
122589
122691
|
/**
|
|
122590
122692
|
* Micromark extension that tokenizes MDX-like components.
|
|
122591
122693
|
*
|
|
@@ -122639,6 +122741,7 @@ function mdxComponent() {
|
|
|
122639
122741
|
|
|
122640
122742
|
|
|
122641
122743
|
|
|
122744
|
+
|
|
122642
122745
|
|
|
122643
122746
|
const buildInlineMdProcessor = (safeMode) => {
|
|
122644
122747
|
// `jsxTable` must be present so a `<Table>`/`<table>` nested in a component
|
|
@@ -122710,7 +122813,7 @@ const toMdxJsxTextElement = (name, attributes, children, position) => ({
|
|
|
122710
122813
|
// Raw-body tags (pre/script/style/textarea) must stay byte-exact; table
|
|
122711
122814
|
// structure (`table` + `tableTags`) is owned by `mdxishTables` and figures by
|
|
122712
122815
|
// `mdxishJsxToMdast`, both of which run later on raw html nodes.
|
|
122713
|
-
const NON_PROMOTABLE_PLAIN_TAGS = new Set([...htmlRawNames, ...tableTags, 'table',
|
|
122816
|
+
const NON_PROMOTABLE_PLAIN_TAGS = new Set([...htmlRawNames, ...tableTags, 'table', ...NON_REPARSED_BODY_TAGS]);
|
|
122714
122817
|
const NESTED_TABLE_RE = /<table[\s>]/i;
|
|
122715
122818
|
const isMarkdownPromotableHtmlTag = (tag) => !NON_PROMOTABLE_PLAIN_TAGS.has(tag);
|
|
122716
122819
|
// Expression nodes count as plain so `<div>{1+1}</div>` keeps its current
|
|
@@ -123069,15 +123172,22 @@ function safeDeindent(text) {
|
|
|
123069
123172
|
*/
|
|
123070
123173
|
const parseMdChildren = (value, safeMode) => {
|
|
123071
123174
|
const parsed = getInlineMdProcessor({ safeMode }).parse(terminateHtmlFlowBlocks(safeDeindent(value).trim()));
|
|
123175
|
+
// Promote nested wrappers bottom-up so an outer wrapper sees markdown buried in a
|
|
123176
|
+
// child claimed whole (e.g. `<li>` in `<ol>`) before its containsMarkdownConstruct check (RM-17560).
|
|
123177
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define -- mutually recursive; hoisted decl, safe at runtime
|
|
123178
|
+
promoteComponentBlocks(parsed, safeMode, null);
|
|
123072
123179
|
return parsed.children || [];
|
|
123073
123180
|
};
|
|
123074
|
-
//
|
|
123075
|
-
// components among them
|
|
123076
|
-
|
|
123181
|
+
// Splices trailing content in as sibling nodes. parseMdChildren has already
|
|
123182
|
+
// promoted any components nested among them (bottom-up); the main loop's
|
|
123183
|
+
// index-based walk then reaches these spliced siblings and the original children
|
|
123184
|
+
// they shift down, so no parent re-queue is needed. Each spliced subtree is marked
|
|
123185
|
+
// `promoted` so the walk doesn't redundantly re-descend into it (its html is gone).
|
|
123186
|
+
const parseSibling = (parent, index, sibling, safeMode, promoted) => {
|
|
123077
123187
|
const siblingNodes = parseMdChildren(sibling, safeMode);
|
|
123078
123188
|
if (siblingNodes.length > 0) {
|
|
123079
123189
|
parent.children.splice(index + 1, 0, ...siblingNodes);
|
|
123080
|
-
|
|
123190
|
+
siblingNodes.forEach(siblingNode => promoted.add(siblingNode));
|
|
123081
123191
|
}
|
|
123082
123192
|
};
|
|
123083
123193
|
// Ends the position at `consumedLength` so the component doesn't claim trailing
|
|
@@ -123143,16 +123253,19 @@ const substituteNodeWithMdxNode = (parent, index, mdxNode) => {
|
|
|
123143
123253
|
* The opening tag, content, and closing tag are all captured in one HTML node
|
|
123144
123254
|
* (guaranteed by the mdx-component tokenizer).
|
|
123145
123255
|
*/
|
|
123146
|
-
|
|
123256
|
+
function promoteComponentBlocks(tree, safeMode, source) {
|
|
123147
123257
|
const stack = [tree];
|
|
123148
|
-
const safeMode = !!opts.safeMode;
|
|
123149
|
-
const source = file?.value ? String(file.value) : null;
|
|
123150
123258
|
const parseOpts = { preserveExpressionsAsText: safeMode };
|
|
123259
|
+
// Subtrees a nested parseMdChildren already promoted wholesale (spliced siblings):
|
|
123260
|
+
// re-descending them finds no html to promote, so skip them.
|
|
123261
|
+
const promoted = new WeakSet();
|
|
123151
123262
|
const processChildNode = (parent, index) => {
|
|
123152
123263
|
const node = parent.children[index];
|
|
123153
123264
|
if (!node)
|
|
123154
123265
|
return;
|
|
123155
|
-
|
|
123266
|
+
// Descend into container nodes (lists, blockquotes, …) so their html children
|
|
123267
|
+
// are reached — unless the subtree was already promoted upstream.
|
|
123268
|
+
if ('children' in node && Array.isArray(node.children) && !promoted.has(node)) {
|
|
123156
123269
|
stack.push(node);
|
|
123157
123270
|
}
|
|
123158
123271
|
// Only html nodes can be an unparsed MDX component.
|
|
@@ -123207,7 +123320,7 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
123207
123320
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
123208
123321
|
const remainingContent = contentAfterTag.trim();
|
|
123209
123322
|
if (remainingContent) {
|
|
123210
|
-
parseSibling(
|
|
123323
|
+
parseSibling(parent, index, remainingContent, safeMode, promoted);
|
|
123211
123324
|
}
|
|
123212
123325
|
return;
|
|
123213
123326
|
}
|
|
@@ -123234,43 +123347,57 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
123234
123347
|
return;
|
|
123235
123348
|
// Lowercase tags are usually inline; unwrap a sole paragraph so their
|
|
123236
123349
|
// phrasing content isn't spuriously block-wrapped.
|
|
123350
|
+
let unwrappedSoleParagraph = false;
|
|
123237
123351
|
if (!isPascal && parsedChildren.length === 1 && parsedChildren[0].type === 'paragraph') {
|
|
123238
123352
|
parsedChildren = parsedChildren[0].children;
|
|
123353
|
+
unwrappedSoleParagraph = true;
|
|
123354
|
+
}
|
|
123355
|
+
// Without trailing content the whole node position is correct. With it, end
|
|
123356
|
+
// precisely at the closing tag — preferring source offsets when available (the
|
|
123357
|
+
// node's value strips blockquote/list prefixes), else the consumed span.
|
|
123358
|
+
let endPosition = node.position;
|
|
123359
|
+
if (contentAfterClose) {
|
|
123360
|
+
endPosition = source
|
|
123361
|
+
? positionEndingAtClosingTagInSource(node.position, closingTagStr, source)
|
|
123362
|
+
: positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd + closingTagIndex + closingTagStr.length);
|
|
123239
123363
|
}
|
|
123240
123364
|
const componentNode = createComponentNode({
|
|
123241
123365
|
tag,
|
|
123242
123366
|
attributes,
|
|
123243
123367
|
children: parsedChildren,
|
|
123244
123368
|
startPosition: node.position,
|
|
123245
|
-
|
|
123246
|
-
// offsets when available (the node's value strips blockquote/list
|
|
123247
|
-
// prefixes); otherwise fall back to the whole node position.
|
|
123248
|
-
endPosition: contentAfterClose
|
|
123249
|
-
? source
|
|
123250
|
-
? positionEndingAtClosingTagInSource(node.position, closingTagStr, source)
|
|
123251
|
-
: positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd + closingTagIndex + closingTagStr.length)
|
|
123252
|
-
: node.position,
|
|
123369
|
+
endPosition,
|
|
123253
123370
|
});
|
|
123254
123371
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
123255
|
-
//
|
|
123256
|
-
|
|
123257
|
-
|
|
123258
|
-
}
|
|
123259
|
-
else if (componentNode.children.length > 0) {
|
|
123372
|
+
// The unwrap reparented the children out of their paragraph, so re-walk them
|
|
123373
|
+
// since the children HTML may contain promotable syntax (e.g. `{…}`-attr tags)
|
|
123374
|
+
if (unwrappedSoleParagraph) {
|
|
123260
123375
|
stack.push(componentNode);
|
|
123261
123376
|
}
|
|
123377
|
+
// Trailing content after the close becomes siblings; parseMdChildren has
|
|
123378
|
+
// already promoted any components nested inside both sides, so the promoted
|
|
123379
|
+
// subtree itself needs no re-queue.
|
|
123380
|
+
if (contentAfterClose) {
|
|
123381
|
+
parseSibling(parent, index, contentAfterClose, safeMode, promoted);
|
|
123382
|
+
}
|
|
123262
123383
|
}
|
|
123263
123384
|
};
|
|
123264
|
-
// Depth-first so nodes keep their source order.
|
|
123385
|
+
// Depth-first so nodes keep their source order. Index-based (not forEach) and
|
|
123386
|
+
// re-reading length each step: parseSibling splices siblings in mid-iteration, and
|
|
123387
|
+
// those — plus the original children they shift down — must all stay eligible.
|
|
123265
123388
|
while (stack.length) {
|
|
123266
123389
|
const parent = stack.pop();
|
|
123267
123390
|
if (parent?.children) {
|
|
123268
|
-
parent.children.
|
|
123391
|
+
for (let index = 0; index < parent.children.length; index += 1) {
|
|
123269
123392
|
processChildNode(parent, index);
|
|
123270
|
-
}
|
|
123393
|
+
}
|
|
123271
123394
|
}
|
|
123272
123395
|
}
|
|
123273
123396
|
return tree;
|
|
123397
|
+
}
|
|
123398
|
+
const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
123399
|
+
const source = file?.value ? String(file.value) : null;
|
|
123400
|
+
return promoteComponentBlocks(tree, !!opts.safeMode, source);
|
|
123274
123401
|
};
|
|
123275
123402
|
/* harmony default export */ const mdx_blocks = (mdxishMdxComponentBlocks);
|
|
123276
123403
|
|
|
@@ -127024,7 +127151,7 @@ function mdxishMdastToMd(mdast) {
|
|
|
127024
127151
|
* Processes markdown content with MDX syntax support and returns a HAST.
|
|
127025
127152
|
* Detects and renders custom component tags from the components hash.
|
|
127026
127153
|
*
|
|
127027
|
-
* @see
|
|
127154
|
+
* @see .claude/context/MDXish/Processor Overview.md
|
|
127028
127155
|
*/
|
|
127029
127156
|
function mdxish(mdContent, opts = {}) {
|
|
127030
127157
|
const { components: userComponents = {}, safeMode = false, variables } = opts;
|
|
@@ -127364,7 +127491,7 @@ function buildRMDXModule(content, headings, tocHast, opts) {
|
|
|
127364
127491
|
* @param opts - The options for the render
|
|
127365
127492
|
* @returns The React component
|
|
127366
127493
|
*
|
|
127367
|
-
* @see
|
|
127494
|
+
* @see .claude/context/MDXish/Processor Overview.md
|
|
127368
127495
|
*/
|
|
127369
127496
|
const renderMdxish = (tree, opts = {}) => {
|
|
127370
127497
|
const { components: userComponents = {}, variables, ...contextOpts } = opts;
|