@readme/markdown 14.11.4 → 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/dist/main.js +173 -139
- package/dist/main.node.js +173 -139
- package/dist/main.node.js.map +1 -1
- package/dist/processor/compile/text.d.ts +4 -0
- package/dist/processor/transform/mdxish/terminate-html-flow-blocks.d.ts +3 -17
- package/dist/render-fixture.node.js +173 -139
- package/dist/render-fixture.node.js.map +1 -1
- package/package.json +1 -1
package/dist/main.node.js
CHANGED
|
@@ -117546,6 +117546,19 @@ const compile_list_item_listItem = (node, parent, state, info) => {
|
|
|
117546
117546
|
const plain_plain = (node) => node.value;
|
|
117547
117547
|
/* harmony default export */ const compile_plain = (plain_plain);
|
|
117548
117548
|
|
|
117549
|
+
;// ./processor/compile/text.ts
|
|
117550
|
+
|
|
117551
|
+
// A `_` flanked by word characters can never open or close emphasis under
|
|
117552
|
+
// CommonMark's flanking rules, so the escape mdast-util-to-markdown adds to
|
|
117553
|
+
// intraword underscores is unnecessary and only produces noisy `\_` diffs.
|
|
117554
|
+
// Uses Unicode letter/number classes so non-ASCII words (e.g. `é_pay`) match.
|
|
117555
|
+
const INTRAWORD_UNDERSCORE_ESCAPE = /(?<=[\p{L}\p{N}_])\\_(?=[\p{L}\p{N}_]|\\_)/gu;
|
|
117556
|
+
const compile_text_text = (node, parent, state, info) => {
|
|
117557
|
+
const serialized = handle.text(node, parent, state, info);
|
|
117558
|
+
return serialized.replace(INTRAWORD_UNDERSCORE_ESCAPE, '_');
|
|
117559
|
+
};
|
|
117560
|
+
/* harmony default export */ const compile_text = (compile_text_text);
|
|
117561
|
+
|
|
117549
117562
|
;// ./processor/compile/index.ts
|
|
117550
117563
|
|
|
117551
117564
|
|
|
@@ -117558,11 +117571,11 @@ const plain_plain = (node) => node.value;
|
|
|
117558
117571
|
|
|
117559
117572
|
|
|
117560
117573
|
|
|
117574
|
+
|
|
117561
117575
|
function compilers(mdxish = false) {
|
|
117562
117576
|
const data = this.data();
|
|
117563
117577
|
const toMarkdownExtensions = data.toMarkdownExtensions || (data.toMarkdownExtensions = []);
|
|
117564
117578
|
const handlers = {
|
|
117565
|
-
...(mdxish && { [NodeTypes.anchor]: compile_anchor }),
|
|
117566
117579
|
[NodeTypes.callout]: compile_callout,
|
|
117567
117580
|
[NodeTypes.codeTabs]: compile_code_tabs,
|
|
117568
117581
|
[NodeTypes.embedBlock]: compile_embed,
|
|
@@ -117570,15 +117583,18 @@ function compilers(mdxish = false) {
|
|
|
117570
117583
|
[NodeTypes.glossary]: compile_compatibility,
|
|
117571
117584
|
[NodeTypes.htmlBlock]: html_block,
|
|
117572
117585
|
[NodeTypes.reusableContent]: compile_compatibility,
|
|
117573
|
-
...(mdxish && { [NodeTypes.variable]: compile_variable }),
|
|
117574
117586
|
embed: compile_compatibility,
|
|
117575
117587
|
escape: compile_compatibility,
|
|
117576
117588
|
figure: compile_compatibility,
|
|
117577
117589
|
html: compile_compatibility,
|
|
117578
117590
|
i: compile_compatibility,
|
|
117579
|
-
...(mdxish && { listItem: list_item }),
|
|
117580
117591
|
plain: compile_plain,
|
|
117581
117592
|
yaml: compile_compatibility,
|
|
117593
|
+
// needed only for mdxish
|
|
117594
|
+
...(mdxish && { [NodeTypes.anchor]: compile_anchor }),
|
|
117595
|
+
...(mdxish && { listItem: list_item }),
|
|
117596
|
+
...(mdxish && { text: compile_text }),
|
|
117597
|
+
...(mdxish && { [NodeTypes.variable]: compile_variable }),
|
|
117582
117598
|
};
|
|
117583
117599
|
toMarkdownExtensions.push({ extensions: [{ handlers }] });
|
|
117584
117600
|
}
|
|
@@ -122440,70 +122456,168 @@ const mdxishInlineMdxComponents = () => tree => {
|
|
|
122440
122456
|
};
|
|
122441
122457
|
/* harmony default export */ const inline_mdx_blocks = (mdxishInlineMdxComponents);
|
|
122442
122458
|
|
|
122459
|
+
;// ./processor/transform/mdxish/terminate-html-flow-blocks.ts
|
|
122460
|
+
|
|
122461
|
+
|
|
122462
|
+
|
|
122463
|
+
const STANDALONE_HTML_LINE_REGEX = /^(<[a-z][^<>]*>|<\/[a-z][^<>]*>)+\s*$/;
|
|
122464
|
+
const HTML_LINE_WITH_CONTENT_REGEX = /^<[a-z][^<>]*>.*<\/[a-z][^<>]*>(?:[^<]*)$/;
|
|
122465
|
+
// A line that is exactly one lowercase opening (or self-closing) tag — the shape
|
|
122466
|
+
// that opens a CommonMark type-6/7 HTML block and swallows the lines below it.
|
|
122467
|
+
const SINGLE_OPENING_TAG_REGEX = /^<[a-z][^<>]*>$/;
|
|
122468
|
+
// Tags whose contents must be preserved as is, inserting a blank line after the
|
|
122469
|
+
// opener corrupts the payload.
|
|
122470
|
+
// htmlRawNames here refer to <pre>, <textarea>, <script>, <style>
|
|
122471
|
+
const RAW_CONTENT_TAGS = [...htmlRawNames, ...HTML_TABLE_STRUCTURE_TAGS];
|
|
122472
|
+
// The `(?=[\s/>])` lookahead avoids false matches on lookalike names like `<script-foo>`.
|
|
122473
|
+
const RAW_CONTENT_TAG_MATCHERS = RAW_CONTENT_TAGS.map(tag => ({
|
|
122474
|
+
open: new RegExp(`<${tag}(?=[\\s/>])[^>]*?(?<!/)>`, 'gi'),
|
|
122475
|
+
close: new RegExp(`</${tag}(?=[\\s>])[^>]*>`, 'gi'),
|
|
122476
|
+
}));
|
|
122477
|
+
function isLineHtml(line) {
|
|
122478
|
+
return STANDALONE_HTML_LINE_REGEX.test(line) || HTML_LINE_WITH_CONTENT_REGEX.test(line);
|
|
122479
|
+
}
|
|
122480
|
+
// Per-tag {opens, closes} counts of RAW_CONTENT_TAGS on one line — feeds both the
|
|
122481
|
+
// per-line net-open check and the cumulative still-open depth tracking.
|
|
122482
|
+
function countRawContentTags(line) {
|
|
122483
|
+
return RAW_CONTENT_TAG_MATCHERS.map(({ open, close }) => ({
|
|
122484
|
+
opens: (line.match(open) ?? []).length,
|
|
122485
|
+
closes: (line.match(close) ?? []).length,
|
|
122486
|
+
}));
|
|
122487
|
+
}
|
|
122488
|
+
// Indentation width in columns, counting a tab as 4 per CommonMark.
|
|
122489
|
+
function indentWidth(line) {
|
|
122490
|
+
const leading = line.match(/^[ \t]*/)?.[0] ?? '';
|
|
122491
|
+
return leading.replace(/\t/g, ' ').length;
|
|
122492
|
+
}
|
|
122493
|
+
/**
|
|
122494
|
+
* Decides whether a blank line belongs between `line` and `next` so the HTML
|
|
122495
|
+
* flow block opened on `line` terminates and `next` parses as markdown.
|
|
122496
|
+
*/
|
|
122497
|
+
function shouldTerminateBetween(line, next, { insideRawContent, lineLeavesRawOpen }) {
|
|
122498
|
+
if (next.trim().length === 0)
|
|
122499
|
+
return false;
|
|
122500
|
+
const currentIndent = indentWidth(line);
|
|
122501
|
+
const nextIndent = indentWidth(next);
|
|
122502
|
+
// 4+ columns is CommonMark indented-code territory: an inserted blank line
|
|
122503
|
+
// would turn the next line into a code block instead of freeing it (#1344).
|
|
122504
|
+
if (currentIndent > 3 || nextIndent > 3)
|
|
122505
|
+
return false;
|
|
122506
|
+
const currentTrimmed = line.trim();
|
|
122507
|
+
const nextTrimmed = next.trim();
|
|
122508
|
+
if (!isLineHtml(currentTrimmed) || isLineHtml(nextTrimmed) || lineLeavesRawOpen) {
|
|
122509
|
+
return false;
|
|
122510
|
+
}
|
|
122511
|
+
// Column-0 pairs keep the original (pre-relaxation) rule, deliberately ignoring
|
|
122512
|
+
// `insideRawContent`: one unclosed <pre>/<table> typo would otherwise suppress
|
|
122513
|
+
// termination for the whole rest of the document.
|
|
122514
|
+
if (currentIndent === 0 && nextIndent === 0)
|
|
122515
|
+
return true;
|
|
122516
|
+
// Indented shapes (either line at 1–3 columns) are stricter: only a lone opening
|
|
122517
|
+
// tag followed by markdown. A next line opening a tag or expression must stay
|
|
122518
|
+
// glued for the mdxComponent tokenizer; raw-content payloads stay byte-exact.
|
|
122519
|
+
return (!insideRawContent &&
|
|
122520
|
+
SINGLE_OPENING_TAG_REGEX.test(currentTrimmed) &&
|
|
122521
|
+
!nextTrimmed.startsWith('<') &&
|
|
122522
|
+
!nextTrimmed.startsWith('{'));
|
|
122523
|
+
}
|
|
122524
|
+
/**
|
|
122525
|
+
* CommonMark HTML blocks (types 6/7) end only at a blank line, so markdown on the
|
|
122526
|
+
* next line is swallowed as HTML (`## heading` after `<div>` renders as literal text).
|
|
122527
|
+
* Inserts the missing blank line; the gating rules live in `shouldTerminateBetween`.
|
|
122528
|
+
*
|
|
122529
|
+
* @link https://spec.commonmark.org/0.29/#html-blocks
|
|
122530
|
+
*/
|
|
122531
|
+
function terminateHtmlFlowBlocks(content) {
|
|
122532
|
+
const { protectedContent, protectedCode } = protectCodeBlocks(content);
|
|
122533
|
+
const lines = protectedContent.split('\n');
|
|
122534
|
+
const result = [];
|
|
122535
|
+
// Per-tag count of still-open raw-content elements at the current boundary.
|
|
122536
|
+
const rawContentDepths = RAW_CONTENT_TAG_MATCHERS.map(() => 0);
|
|
122537
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
122538
|
+
const line = lines[i];
|
|
122539
|
+
result.push(line);
|
|
122540
|
+
const tagCounts = countRawContentTags(line);
|
|
122541
|
+
tagCounts.forEach(({ opens, closes }, tagIndex) => {
|
|
122542
|
+
rawContentDepths[tagIndex] = Math.max(0, rawContentDepths[tagIndex] + opens - closes);
|
|
122543
|
+
});
|
|
122544
|
+
const next = lines[i + 1];
|
|
122545
|
+
const rawContentFacts = {
|
|
122546
|
+
insideRawContent: rawContentDepths.some(depth => depth > 0),
|
|
122547
|
+
lineLeavesRawOpen: tagCounts.some(({ opens, closes }) => opens > closes),
|
|
122548
|
+
};
|
|
122549
|
+
if (next !== undefined && shouldTerminateBetween(line, next, rawContentFacts)) {
|
|
122550
|
+
result.push('');
|
|
122551
|
+
}
|
|
122552
|
+
}
|
|
122553
|
+
return restoreCodeBlocks(result.join('\n'), protectedCode);
|
|
122554
|
+
}
|
|
122555
|
+
|
|
122443
122556
|
;// ./processor/transform/mdxish/components/mdx-blocks.ts
|
|
122444
122557
|
|
|
122445
122558
|
|
|
122446
122559
|
|
|
122447
122560
|
|
|
122448
122561
|
|
|
122449
|
-
|
|
122562
|
+
|
|
122563
|
+
|
|
122564
|
+
// Matches a JSX attribute expression (e.g. `key={i}`) anywhere in a string. */
|
|
122450
122565
|
const NESTED_ATTR_EXPRESSION_RE = /[\w-]+\s*=\s*\{/;
|
|
122451
|
-
|
|
122452
|
-
|
|
122453
|
-
|
|
122454
|
-
|
|
122455
|
-
|
|
122566
|
+
// Name shape mirrors `componentTagPattern`; the lookbehind skips the inner tag
|
|
122567
|
+
// of a legacy `<<VARIABLE>>`.
|
|
122568
|
+
const NESTED_COMPONENT_TAG_RE = /(?<!<)<([A-Z][A-Za-z0-9_]*)[\s/>]/g;
|
|
122569
|
+
// Excludes tags with dedicated transformers (`Table`, `HTMLBlock`, inline
|
|
122570
|
+
// components), which expect their wrapper to stay raw.
|
|
122571
|
+
const hasNestedGenericComponentTag = (content) => [...content.matchAll(NESTED_COMPONENT_TAG_RE)].some(match => !GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(match[1]));
|
|
122572
|
+
/**
|
|
122573
|
+
* Strip the shared leading indentation from a component body so readability indentation
|
|
122574
|
+
* isn't parsed as indented code (4+ spaces), e.g. ` <p>` / ` text` -> `<p>` / ` text`.
|
|
122575
|
+
* Relative indentation is kept, so content genuinely 4+ columns deeper stays code. We
|
|
122576
|
+
* only strip when a line actually reaches 4 columns; otherwise the body is left as-is so
|
|
122577
|
+
* its leading whitespace survives as text nodes (mixed component + HTML content needs it).
|
|
122456
122578
|
*/
|
|
122457
122579
|
function safeDeindent(text) {
|
|
122458
122580
|
const lines = text.split('\n');
|
|
122459
122581
|
const nonEmptyLines = lines.filter(line => line.trim().length > 0);
|
|
122460
122582
|
if (nonEmptyLines.length === 0)
|
|
122461
122583
|
return text;
|
|
122462
|
-
|
|
122463
|
-
|
|
122464
|
-
|
|
122465
|
-
|
|
122466
|
-
|
|
122467
|
-
const stripAmount =
|
|
122584
|
+
// Indent counts characters (tab = 1), unlike indentWidth's CommonMark columns
|
|
122585
|
+
// (tab = 4) in terminate-html-flow-blocks.
|
|
122586
|
+
const indents = nonEmptyLines.map(line => line.match(/^(\s*)/)?.[1].length ?? 0);
|
|
122587
|
+
const minIndent = Math.min(...indents);
|
|
122588
|
+
const maxIndent = Math.max(...indents);
|
|
122589
|
+
const stripAmount = maxIndent > 3 ? minIndent : 0;
|
|
122468
122590
|
if (stripAmount === 0)
|
|
122469
122591
|
return text;
|
|
122470
122592
|
return lines.map(line => line.slice(stripAmount)).join('\n');
|
|
122471
122593
|
}
|
|
122472
122594
|
/**
|
|
122473
|
-
* Parse markdown
|
|
122474
|
-
*
|
|
122475
|
-
*
|
|
122595
|
+
* Parse component-body markdown into mdast children. Dedenting shifts columns and
|
|
122596
|
+
* stales the top-level `terminateHtmlFlowBlocks` decisions, so that one preprocessor
|
|
122597
|
+
* re-runs here; other column-anchored fixups (compact headings, tables) do not.
|
|
122476
122598
|
*/
|
|
122477
122599
|
const parseMdChildren = (value, safeMode) => {
|
|
122478
|
-
const parsed = getInlineMdProcessor({ safeMode }).parse(safeDeindent(value).trim());
|
|
122600
|
+
const parsed = getInlineMdProcessor({ safeMode }).parse(terminateHtmlFlowBlocks(safeDeindent(value).trim()));
|
|
122479
122601
|
return parsed.children || [];
|
|
122480
122602
|
};
|
|
122481
|
-
|
|
122482
|
-
|
|
122483
|
-
*/
|
|
122603
|
+
// Parses trailing content into sibling nodes and re-queues the parent so any
|
|
122604
|
+
// components among them get processed.
|
|
122484
122605
|
const parseSibling = (stack, parent, index, sibling, safeMode) => {
|
|
122485
122606
|
const siblingNodes = parseMdChildren(sibling, safeMode);
|
|
122486
|
-
// The new sibling nodes might contain new components to be processed
|
|
122487
122607
|
if (siblingNodes.length > 0) {
|
|
122488
122608
|
parent.children.splice(index + 1, 0, ...siblingNodes);
|
|
122489
122609
|
stack.push(parent);
|
|
122490
122610
|
}
|
|
122491
122611
|
};
|
|
122492
|
-
|
|
122493
|
-
|
|
122494
|
-
* component doesn't claim trailing content the tokenizer swallowed into one node.
|
|
122495
|
-
*/
|
|
122612
|
+
// Ends the position at `consumedLength` so the component doesn't claim trailing
|
|
122613
|
+
// content the tokenizer swallowed into the same html node.
|
|
122496
122614
|
const positionEndingAtConsumed = (nodePosition, value, consumedLength) => {
|
|
122497
122615
|
if (!nodePosition?.start)
|
|
122498
122616
|
return nodePosition;
|
|
122499
122617
|
return { start: nodePosition.start, end: pointAfter(nodePosition.start, value.slice(0, consumedLength)) };
|
|
122500
122618
|
};
|
|
122501
|
-
|
|
122502
|
-
|
|
122503
|
-
* this node's span in the original source. Used in the trailing-content path so
|
|
122504
|
-
* the offset is computed against the real source bytes (including blockquote/list
|
|
122505
|
-
* prefixes that were stripped from the html node's value).
|
|
122506
|
-
*/
|
|
122619
|
+
// Like `positionEndingAtConsumed`, but measures against the original source so
|
|
122620
|
+
// blockquote/list prefixes stripped from the html node's value are counted.
|
|
122507
122621
|
const positionEndingAtClosingTagInSource = (nodePosition, closingTag, source) => {
|
|
122508
122622
|
if (!nodePosition?.start || !nodePosition.end)
|
|
122509
122623
|
return nodePosition;
|
|
@@ -122514,9 +122628,6 @@ const positionEndingAtClosingTagInSource = (nodePosition, closingTag, source) =>
|
|
|
122514
122628
|
const consumed = nodeSource.slice(0, closingTagOffset + closingTag.length);
|
|
122515
122629
|
return { start: nodePosition.start, end: pointAfter(nodePosition.start, consumed) };
|
|
122516
122630
|
};
|
|
122517
|
-
/**
|
|
122518
|
-
* Create an MdxJsxFlowElement node from component data.
|
|
122519
|
-
*/
|
|
122520
122631
|
const createComponentNode = ({ tag, attributes, children, startPosition, endPosition }) => ({
|
|
122521
122632
|
type: 'mdxJsxFlowElement',
|
|
122522
122633
|
name: tag,
|
|
@@ -122569,8 +122680,7 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
122569
122680
|
if ('children' in node && Array.isArray(node.children)) {
|
|
122570
122681
|
stack.push(node);
|
|
122571
122682
|
}
|
|
122572
|
-
// Only
|
|
122573
|
-
// which means a potential unparsed MDX component
|
|
122683
|
+
// Only html nodes can be an unparsed MDX component.
|
|
122574
122684
|
const value = node.value;
|
|
122575
122685
|
if (node.type !== 'html' || typeof value !== 'string')
|
|
122576
122686
|
return;
|
|
@@ -122579,32 +122689,25 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
122579
122689
|
if (!parsed)
|
|
122580
122690
|
return;
|
|
122581
122691
|
const { tag, attributes, selfClosing, contentAfterTag = '' } = parsed;
|
|
122582
|
-
//
|
|
122583
|
-
// so consumed-length math maps back onto the node's real source offsets.
|
|
122692
|
+
// Offsets so consumed-length math maps back onto the node's real source.
|
|
122584
122693
|
const leadingWhitespace = value.length - value.trimStart().length;
|
|
122585
|
-
// Index right after the opening tag's `>` within `trimmed`.
|
|
122586
122694
|
const openingTagEnd = trimmed.length - contentAfterTag.length;
|
|
122587
|
-
// Skip tags that have dedicated transformers
|
|
122588
122695
|
if (GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(tag))
|
|
122589
|
-
return;
|
|
122696
|
+
return; // owned by dedicated transformers
|
|
122590
122697
|
const isPascal = isPascalCase(tag);
|
|
122591
|
-
// Lowercase inline tags
|
|
122592
|
-
//
|
|
122593
|
-
//
|
|
122594
|
-
// keep going through this transformer (they stay flow-level even when
|
|
122595
|
-
// inline, which is how ReadMe's custom components are modeled).
|
|
122698
|
+
// Lowercase inline tags with `{…}` attributes belong to
|
|
122699
|
+
// mdxishInlineComponentBlocks; leave them as html for that pass. PascalCase
|
|
122700
|
+
// components stay flow-level even when inline (ReadMe's component model).
|
|
122596
122701
|
if (!isPascal && parent.type === 'paragraph')
|
|
122597
122702
|
return;
|
|
122598
|
-
//
|
|
122599
|
-
//
|
|
122600
|
-
// JSX
|
|
122601
|
-
//
|
|
122602
|
-
// `style={{...}}`/`.map()` JSX inside it — as literal HTML text, which
|
|
122603
|
-
// rehype-raw's parse5 pass then garbles (it has no notion of JS expressions).
|
|
122604
|
-
// Plain HTML with no expressions anywhere stays as an html node so
|
|
122605
|
-
// rehype-raw handles it as normal.
|
|
122703
|
+
// A lowercase wrapper is only promoted when it (or a descendant) carries a
|
|
122704
|
+
// JSX expression or nests a component; otherwise it would swallow that inner
|
|
122705
|
+
// JSX/component as literal text that rehype-raw's parse5 pass can't handle.
|
|
122706
|
+
// Table-structural wrappers are excluded — `mdxishTables` re-parses those.
|
|
122606
122707
|
const hasNestedExpressionAttr = !selfClosing && NESTED_ATTR_EXPRESSION_RE.test(contentAfterTag);
|
|
122607
|
-
|
|
122708
|
+
const isTableStructuralTag = tag === 'table' || tableTags.has(tag);
|
|
122709
|
+
const hasNestedComponentTag = !selfClosing && !isTableStructuralTag && hasNestedGenericComponentTag(contentAfterTag);
|
|
122710
|
+
if (!isPascal && !hasExpressionAttr(attributes) && !hasNestedExpressionAttr && !hasNestedComponentTag)
|
|
122608
122711
|
return;
|
|
122609
122712
|
const closingTagStr = `</${tag}>`;
|
|
122610
122713
|
// Case 1: Self-closing tag
|
|
@@ -122618,7 +122721,6 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
122618
122721
|
endPosition: positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd),
|
|
122619
122722
|
});
|
|
122620
122723
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
122621
|
-
// Check and parse if there's relevant content after the current closing tag
|
|
122622
122724
|
const remainingContent = contentAfterTag.trim();
|
|
122623
122725
|
if (remainingContent) {
|
|
122624
122726
|
parseSibling(stack, parent, index, remainingContent, safeMode);
|
|
@@ -122627,17 +122729,14 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
122627
122729
|
}
|
|
122628
122730
|
// Case 2: Self-contained block (closing tag in content)
|
|
122629
122731
|
if (contentAfterTag.includes(closingTagStr)) {
|
|
122630
|
-
// Find the first closing tag
|
|
122631
122732
|
const closingTagIndex = contentAfterTag.lastIndexOf(closingTagStr);
|
|
122632
|
-
//
|
|
122633
|
-
// normalize indentation before trimming
|
|
122733
|
+
// Untrimmed so parseMdChildren can dedent before trimming.
|
|
122634
122734
|
const componentInnerContent = contentAfterTag.substring(0, closingTagIndex);
|
|
122635
122735
|
const contentAfterClose = contentAfterTag.substring(closingTagIndex + closingTagStr.length).trim();
|
|
122636
122736
|
let parsedChildren = componentInnerContent.trim()
|
|
122637
122737
|
? parseMdChildren(componentInnerContent, safeMode)
|
|
122638
122738
|
: [];
|
|
122639
|
-
// Lowercase
|
|
122640
|
-
// bare text in a paragraph; unwrap when there's exactly one paragraph so
|
|
122739
|
+
// Lowercase tags are usually inline; unwrap a sole paragraph so their
|
|
122641
122740
|
// phrasing content isn't spuriously block-wrapped.
|
|
122642
122741
|
if (!isPascal && parsedChildren.length === 1 && parsedChildren[0].type === 'paragraph') {
|
|
122643
122742
|
parsedChildren = parsedChildren[0].children;
|
|
@@ -122647,12 +122746,9 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
122647
122746
|
attributes,
|
|
122648
122747
|
children: parsedChildren,
|
|
122649
122748
|
startPosition: node.position,
|
|
122650
|
-
//
|
|
122651
|
-
//
|
|
122652
|
-
//
|
|
122653
|
-
// node's value has '> '/space prefixes stripped for blockquotes/list items, so
|
|
122654
|
-
// positionEndingAtConsumed would undercount source offsets. When the entire node
|
|
122655
|
-
// is consumed, use the original node position directly.
|
|
122749
|
+
// With trailing content, end precisely at the closing tag. Prefer source
|
|
122750
|
+
// offsets when available (the node's value strips blockquote/list
|
|
122751
|
+
// prefixes); otherwise fall back to the whole node position.
|
|
122656
122752
|
endPosition: contentAfterClose
|
|
122657
122753
|
? source
|
|
122658
122754
|
? positionEndingAtClosingTagInSource(node.position, closingTagStr, source)
|
|
@@ -122660,17 +122756,16 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
122660
122756
|
: node.position,
|
|
122661
122757
|
});
|
|
122662
122758
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
122663
|
-
//
|
|
122759
|
+
// Re-queue whichever side may hold further components.
|
|
122664
122760
|
if (contentAfterClose) {
|
|
122665
122761
|
parseSibling(stack, parent, index, contentAfterClose, safeMode);
|
|
122666
122762
|
}
|
|
122667
122763
|
else if (componentNode.children.length > 0) {
|
|
122668
|
-
// The content inside the component block might contain new components to be processed
|
|
122669
122764
|
stack.push(componentNode);
|
|
122670
122765
|
}
|
|
122671
122766
|
}
|
|
122672
122767
|
};
|
|
122673
|
-
//
|
|
122768
|
+
// Depth-first so nodes keep their source order.
|
|
122674
122769
|
while (stack.length) {
|
|
122675
122770
|
const parent = stack.pop();
|
|
122676
122771
|
if (parent?.children) {
|
|
@@ -125503,73 +125598,6 @@ function normalizeTableSeparator(content) {
|
|
|
125503
125598
|
}
|
|
125504
125599
|
/* harmony default export */ const normalize_table_separator = ((/* unused pure expression or super */ null && (normalizeTableSeparator)));
|
|
125505
125600
|
|
|
125506
|
-
;// ./processor/transform/mdxish/terminate-html-flow-blocks.ts
|
|
125507
|
-
|
|
125508
|
-
|
|
125509
|
-
|
|
125510
|
-
const STANDALONE_HTML_LINE_REGEX = /^(<[a-z][^<>]*>|<\/[a-z][^<>]*>)+\s*$/;
|
|
125511
|
-
const HTML_LINE_WITH_CONTENT_REGEX = /^<[a-z][^<>]*>.*<\/[a-z][^<>]*>(?:[^<]*)$/;
|
|
125512
|
-
// Tags whose contents must be preserved as is, inserting a blank line after the
|
|
125513
|
-
// opener corrupts the payload.
|
|
125514
|
-
// htmlRawNames here refer to <pre>, <textarea>, <script>, <style>
|
|
125515
|
-
const RAW_CONTENT_TAGS = [...htmlRawNames, ...HTML_TABLE_STRUCTURE_TAGS];
|
|
125516
|
-
// The `(?=[\s/>])` lookahead avoids false matches on lookalike names like `<script-foo>`.
|
|
125517
|
-
const RAW_CONTENT_TAG_MATCHERS = RAW_CONTENT_TAGS.map(tag => ({
|
|
125518
|
-
open: new RegExp(`<${tag}(?=[\\s/>])[^>]*?(?<!/)>`, 'gi'),
|
|
125519
|
-
close: new RegExp(`</${tag}(?=[\\s>])[^>]*>`, 'gi'),
|
|
125520
|
-
}));
|
|
125521
|
-
function isLineHtml(line) {
|
|
125522
|
-
return STANDALONE_HTML_LINE_REGEX.test(line) || HTML_LINE_WITH_CONTENT_REGEX.test(line);
|
|
125523
|
-
}
|
|
125524
|
-
// True if any RAW_CONTENT_TAGS opener on this line is not closed on the same line.
|
|
125525
|
-
function hasUnclosedRawContentOpener(line) {
|
|
125526
|
-
return RAW_CONTENT_TAG_MATCHERS.some(({ open, close }) => {
|
|
125527
|
-
const opens = (line.match(open) ?? []).length;
|
|
125528
|
-
const closes = (line.match(close) ?? []).length;
|
|
125529
|
-
return opens > closes;
|
|
125530
|
-
});
|
|
125531
|
-
}
|
|
125532
|
-
/**
|
|
125533
|
-
* Preprocessor to terminate HTML flow blocks.
|
|
125534
|
-
*
|
|
125535
|
-
* In CommonMark, HTML blocks (types 6 and 7) only terminate on a blank line.
|
|
125536
|
-
* Without one, any content on the next line is consumed as part of the HTML block
|
|
125537
|
-
* and never parsed as its own construct. For example, a `[block:callout]` immediately
|
|
125538
|
-
* following `<div><p></p></div>` gets swallowed into the HTML flow token.
|
|
125539
|
-
*
|
|
125540
|
-
* @link https://spec.commonmark.org/0.29/#html-blocks
|
|
125541
|
-
*
|
|
125542
|
-
* This preprocessor inserts a blank line after standalone HTML lines when the next
|
|
125543
|
-
* line is non-blank and not an HTML construct, ensuring micromark's HTML flow
|
|
125544
|
-
* tokenizer terminates and subsequent content is parsed independently.
|
|
125545
|
-
*
|
|
125546
|
-
* Conditions:
|
|
125547
|
-
* 1. Only non-indented lines with lowercase tag names are considered. Uppercase tags
|
|
125548
|
-
* (e.g. `<Table>`, `<MyComponent>`) are JSX custom components and don't trigger
|
|
125549
|
-
* CommonMark HTML blocks.
|
|
125550
|
-
* 2. Lines inside protected blocks (e.g. fenced code) are left untouched.
|
|
125551
|
-
* 3. Lines with an unclosed RAW_CONTENT_TAGS opener are exempted.
|
|
125552
|
-
*/
|
|
125553
|
-
function terminateHtmlFlowBlocks(content) {
|
|
125554
|
-
const { protectedContent, protectedCode } = protectCodeBlocks(content);
|
|
125555
|
-
const lines = protectedContent.split('\n');
|
|
125556
|
-
const result = [];
|
|
125557
|
-
for (let i = 0; i < lines.length; i += 1) {
|
|
125558
|
-
result.push(lines[i]);
|
|
125559
|
-
// Skip blank & indented lines
|
|
125560
|
-
if (i >= lines.length - 1 || lines[i + 1].trim().length === 0 || lines[i + 1].startsWith(' ') || lines[i + 1].startsWith('\t')) {
|
|
125561
|
-
// eslint-disable-next-line no-continue
|
|
125562
|
-
continue;
|
|
125563
|
-
}
|
|
125564
|
-
const isCurrentLineHtml = isLineHtml(lines[i]);
|
|
125565
|
-
const isNextLineHtml = isLineHtml(lines[i + 1]);
|
|
125566
|
-
if (isCurrentLineHtml && !isNextLineHtml && !hasUnclosedRawContentOpener(lines[i])) {
|
|
125567
|
-
result.push('');
|
|
125568
|
-
}
|
|
125569
|
-
}
|
|
125570
|
-
return restoreCodeBlocks(result.join('\n'), protectedCode);
|
|
125571
|
-
}
|
|
125572
|
-
|
|
125573
125601
|
;// ./processor/transform/mdxish/variables-code.ts
|
|
125574
125602
|
|
|
125575
125603
|
|
|
@@ -126437,6 +126465,12 @@ function mdxishMdastToMd(mdast) {
|
|
|
126437
126465
|
.use(remarkStringify, {
|
|
126438
126466
|
bullet: '-',
|
|
126439
126467
|
emphasis: '_',
|
|
126468
|
+
// Escape literal braces in text so they don't parse as (often
|
|
126469
|
+
// unterminated) MDX expressions on the next round trip.
|
|
126470
|
+
unsafe: [
|
|
126471
|
+
{ character: '{', inConstruct: 'phrasing' },
|
|
126472
|
+
{ character: '}', inConstruct: 'phrasing' },
|
|
126473
|
+
],
|
|
126440
126474
|
});
|
|
126441
126475
|
return processor.stringify(processor.runSync(mdast));
|
|
126442
126476
|
}
|