@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
|
@@ -1,22 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Without one, any content on the next line is consumed as part of the HTML block
|
|
6
|
-
* and never parsed as its own construct. For example, a `[block:callout]` immediately
|
|
7
|
-
* following `<div><p></p></div>` gets swallowed into the HTML flow token.
|
|
2
|
+
* CommonMark HTML blocks (types 6/7) end only at a blank line, so markdown on the
|
|
3
|
+
* next line is swallowed as HTML (`## heading` after `<div>` renders as literal text).
|
|
4
|
+
* Inserts the missing blank line; the gating rules live in `shouldTerminateBetween`.
|
|
8
5
|
*
|
|
9
6
|
* @link https://spec.commonmark.org/0.29/#html-blocks
|
|
10
|
-
*
|
|
11
|
-
* This preprocessor inserts a blank line after standalone HTML lines when the next
|
|
12
|
-
* line is non-blank and not an HTML construct, ensuring micromark's HTML flow
|
|
13
|
-
* tokenizer terminates and subsequent content is parsed independently.
|
|
14
|
-
*
|
|
15
|
-
* Conditions:
|
|
16
|
-
* 1. Only non-indented lines with lowercase tag names are considered. Uppercase tags
|
|
17
|
-
* (e.g. `<Table>`, `<MyComponent>`) are JSX custom components and don't trigger
|
|
18
|
-
* CommonMark HTML blocks.
|
|
19
|
-
* 2. Lines inside protected blocks (e.g. fenced code) are left untouched.
|
|
20
|
-
* 3. Lines with an unclosed RAW_CONTENT_TAGS opener are exempted.
|
|
21
7
|
*/
|
|
22
8
|
export declare function terminateHtmlFlowBlocks(content: string): string;
|
|
@@ -117497,6 +117497,19 @@ const compile_list_item_listItem = (node, parent, state, info) => {
|
|
|
117497
117497
|
const plain_plain = (node) => node.value;
|
|
117498
117498
|
/* harmony default export */ const compile_plain = (plain_plain);
|
|
117499
117499
|
|
|
117500
|
+
;// ./processor/compile/text.ts
|
|
117501
|
+
|
|
117502
|
+
// A `_` flanked by word characters can never open or close emphasis under
|
|
117503
|
+
// CommonMark's flanking rules, so the escape mdast-util-to-markdown adds to
|
|
117504
|
+
// intraword underscores is unnecessary and only produces noisy `\_` diffs.
|
|
117505
|
+
// Uses Unicode letter/number classes so non-ASCII words (e.g. `é_pay`) match.
|
|
117506
|
+
const INTRAWORD_UNDERSCORE_ESCAPE = /(?<=[\p{L}\p{N}_])\\_(?=[\p{L}\p{N}_]|\\_)/gu;
|
|
117507
|
+
const compile_text_text = (node, parent, state, info) => {
|
|
117508
|
+
const serialized = handle.text(node, parent, state, info);
|
|
117509
|
+
return serialized.replace(INTRAWORD_UNDERSCORE_ESCAPE, '_');
|
|
117510
|
+
};
|
|
117511
|
+
/* harmony default export */ const compile_text = (compile_text_text);
|
|
117512
|
+
|
|
117500
117513
|
;// ./processor/compile/index.ts
|
|
117501
117514
|
|
|
117502
117515
|
|
|
@@ -117509,11 +117522,11 @@ const plain_plain = (node) => node.value;
|
|
|
117509
117522
|
|
|
117510
117523
|
|
|
117511
117524
|
|
|
117525
|
+
|
|
117512
117526
|
function compilers(mdxish = false) {
|
|
117513
117527
|
const data = this.data();
|
|
117514
117528
|
const toMarkdownExtensions = data.toMarkdownExtensions || (data.toMarkdownExtensions = []);
|
|
117515
117529
|
const handlers = {
|
|
117516
|
-
...(mdxish && { [enums_NodeTypes.anchor]: compile_anchor }),
|
|
117517
117530
|
[enums_NodeTypes.callout]: compile_callout,
|
|
117518
117531
|
[enums_NodeTypes.codeTabs]: compile_code_tabs,
|
|
117519
117532
|
[enums_NodeTypes.embedBlock]: compile_embed,
|
|
@@ -117521,15 +117534,18 @@ function compilers(mdxish = false) {
|
|
|
117521
117534
|
[enums_NodeTypes.glossary]: compile_compatibility,
|
|
117522
117535
|
[enums_NodeTypes.htmlBlock]: html_block,
|
|
117523
117536
|
[enums_NodeTypes.reusableContent]: compile_compatibility,
|
|
117524
|
-
...(mdxish && { [enums_NodeTypes.variable]: compile_variable }),
|
|
117525
117537
|
embed: compile_compatibility,
|
|
117526
117538
|
escape: compile_compatibility,
|
|
117527
117539
|
figure: compile_compatibility,
|
|
117528
117540
|
html: compile_compatibility,
|
|
117529
117541
|
i: compile_compatibility,
|
|
117530
|
-
...(mdxish && { listItem: list_item }),
|
|
117531
117542
|
plain: compile_plain,
|
|
117532
117543
|
yaml: compile_compatibility,
|
|
117544
|
+
// needed only for mdxish
|
|
117545
|
+
...(mdxish && { [enums_NodeTypes.anchor]: compile_anchor }),
|
|
117546
|
+
...(mdxish && { listItem: list_item }),
|
|
117547
|
+
...(mdxish && { text: compile_text }),
|
|
117548
|
+
...(mdxish && { [enums_NodeTypes.variable]: compile_variable }),
|
|
117533
117549
|
};
|
|
117534
117550
|
toMarkdownExtensions.push({ extensions: [{ handlers }] });
|
|
117535
117551
|
}
|
|
@@ -120971,70 +120987,168 @@ const mdxishInlineMdxComponents = () => tree => {
|
|
|
120971
120987
|
};
|
|
120972
120988
|
/* harmony default export */ const inline_mdx_blocks = (mdxishInlineMdxComponents);
|
|
120973
120989
|
|
|
120990
|
+
;// ./processor/transform/mdxish/terminate-html-flow-blocks.ts
|
|
120991
|
+
|
|
120992
|
+
|
|
120993
|
+
|
|
120994
|
+
const STANDALONE_HTML_LINE_REGEX = /^(<[a-z][^<>]*>|<\/[a-z][^<>]*>)+\s*$/;
|
|
120995
|
+
const HTML_LINE_WITH_CONTENT_REGEX = /^<[a-z][^<>]*>.*<\/[a-z][^<>]*>(?:[^<]*)$/;
|
|
120996
|
+
// A line that is exactly one lowercase opening (or self-closing) tag — the shape
|
|
120997
|
+
// that opens a CommonMark type-6/7 HTML block and swallows the lines below it.
|
|
120998
|
+
const SINGLE_OPENING_TAG_REGEX = /^<[a-z][^<>]*>$/;
|
|
120999
|
+
// Tags whose contents must be preserved as is, inserting a blank line after the
|
|
121000
|
+
// opener corrupts the payload.
|
|
121001
|
+
// htmlRawNames here refer to <pre>, <textarea>, <script>, <style>
|
|
121002
|
+
const RAW_CONTENT_TAGS = [...htmlRawNames, ...HTML_TABLE_STRUCTURE_TAGS];
|
|
121003
|
+
// The `(?=[\s/>])` lookahead avoids false matches on lookalike names like `<script-foo>`.
|
|
121004
|
+
const RAW_CONTENT_TAG_MATCHERS = RAW_CONTENT_TAGS.map(tag => ({
|
|
121005
|
+
open: new RegExp(`<${tag}(?=[\\s/>])[^>]*?(?<!/)>`, 'gi'),
|
|
121006
|
+
close: new RegExp(`</${tag}(?=[\\s>])[^>]*>`, 'gi'),
|
|
121007
|
+
}));
|
|
121008
|
+
function isLineHtml(line) {
|
|
121009
|
+
return STANDALONE_HTML_LINE_REGEX.test(line) || HTML_LINE_WITH_CONTENT_REGEX.test(line);
|
|
121010
|
+
}
|
|
121011
|
+
// Per-tag {opens, closes} counts of RAW_CONTENT_TAGS on one line — feeds both the
|
|
121012
|
+
// per-line net-open check and the cumulative still-open depth tracking.
|
|
121013
|
+
function countRawContentTags(line) {
|
|
121014
|
+
return RAW_CONTENT_TAG_MATCHERS.map(({ open, close }) => ({
|
|
121015
|
+
opens: (line.match(open) ?? []).length,
|
|
121016
|
+
closes: (line.match(close) ?? []).length,
|
|
121017
|
+
}));
|
|
121018
|
+
}
|
|
121019
|
+
// Indentation width in columns, counting a tab as 4 per CommonMark.
|
|
121020
|
+
function indentWidth(line) {
|
|
121021
|
+
const leading = line.match(/^[ \t]*/)?.[0] ?? '';
|
|
121022
|
+
return leading.replace(/\t/g, ' ').length;
|
|
121023
|
+
}
|
|
121024
|
+
/**
|
|
121025
|
+
* Decides whether a blank line belongs between `line` and `next` so the HTML
|
|
121026
|
+
* flow block opened on `line` terminates and `next` parses as markdown.
|
|
121027
|
+
*/
|
|
121028
|
+
function shouldTerminateBetween(line, next, { insideRawContent, lineLeavesRawOpen }) {
|
|
121029
|
+
if (next.trim().length === 0)
|
|
121030
|
+
return false;
|
|
121031
|
+
const currentIndent = indentWidth(line);
|
|
121032
|
+
const nextIndent = indentWidth(next);
|
|
121033
|
+
// 4+ columns is CommonMark indented-code territory: an inserted blank line
|
|
121034
|
+
// would turn the next line into a code block instead of freeing it (#1344).
|
|
121035
|
+
if (currentIndent > 3 || nextIndent > 3)
|
|
121036
|
+
return false;
|
|
121037
|
+
const currentTrimmed = line.trim();
|
|
121038
|
+
const nextTrimmed = next.trim();
|
|
121039
|
+
if (!isLineHtml(currentTrimmed) || isLineHtml(nextTrimmed) || lineLeavesRawOpen) {
|
|
121040
|
+
return false;
|
|
121041
|
+
}
|
|
121042
|
+
// Column-0 pairs keep the original (pre-relaxation) rule, deliberately ignoring
|
|
121043
|
+
// `insideRawContent`: one unclosed <pre>/<table> typo would otherwise suppress
|
|
121044
|
+
// termination for the whole rest of the document.
|
|
121045
|
+
if (currentIndent === 0 && nextIndent === 0)
|
|
121046
|
+
return true;
|
|
121047
|
+
// Indented shapes (either line at 1–3 columns) are stricter: only a lone opening
|
|
121048
|
+
// tag followed by markdown. A next line opening a tag or expression must stay
|
|
121049
|
+
// glued for the mdxComponent tokenizer; raw-content payloads stay byte-exact.
|
|
121050
|
+
return (!insideRawContent &&
|
|
121051
|
+
SINGLE_OPENING_TAG_REGEX.test(currentTrimmed) &&
|
|
121052
|
+
!nextTrimmed.startsWith('<') &&
|
|
121053
|
+
!nextTrimmed.startsWith('{'));
|
|
121054
|
+
}
|
|
121055
|
+
/**
|
|
121056
|
+
* CommonMark HTML blocks (types 6/7) end only at a blank line, so markdown on the
|
|
121057
|
+
* next line is swallowed as HTML (`## heading` after `<div>` renders as literal text).
|
|
121058
|
+
* Inserts the missing blank line; the gating rules live in `shouldTerminateBetween`.
|
|
121059
|
+
*
|
|
121060
|
+
* @link https://spec.commonmark.org/0.29/#html-blocks
|
|
121061
|
+
*/
|
|
121062
|
+
function terminateHtmlFlowBlocks(content) {
|
|
121063
|
+
const { protectedContent, protectedCode } = protectCodeBlocks(content);
|
|
121064
|
+
const lines = protectedContent.split('\n');
|
|
121065
|
+
const result = [];
|
|
121066
|
+
// Per-tag count of still-open raw-content elements at the current boundary.
|
|
121067
|
+
const rawContentDepths = RAW_CONTENT_TAG_MATCHERS.map(() => 0);
|
|
121068
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
121069
|
+
const line = lines[i];
|
|
121070
|
+
result.push(line);
|
|
121071
|
+
const tagCounts = countRawContentTags(line);
|
|
121072
|
+
tagCounts.forEach(({ opens, closes }, tagIndex) => {
|
|
121073
|
+
rawContentDepths[tagIndex] = Math.max(0, rawContentDepths[tagIndex] + opens - closes);
|
|
121074
|
+
});
|
|
121075
|
+
const next = lines[i + 1];
|
|
121076
|
+
const rawContentFacts = {
|
|
121077
|
+
insideRawContent: rawContentDepths.some(depth => depth > 0),
|
|
121078
|
+
lineLeavesRawOpen: tagCounts.some(({ opens, closes }) => opens > closes),
|
|
121079
|
+
};
|
|
121080
|
+
if (next !== undefined && shouldTerminateBetween(line, next, rawContentFacts)) {
|
|
121081
|
+
result.push('');
|
|
121082
|
+
}
|
|
121083
|
+
}
|
|
121084
|
+
return restoreCodeBlocks(result.join('\n'), protectedCode);
|
|
121085
|
+
}
|
|
121086
|
+
|
|
120974
121087
|
;// ./processor/transform/mdxish/components/mdx-blocks.ts
|
|
120975
121088
|
|
|
120976
121089
|
|
|
120977
121090
|
|
|
120978
121091
|
|
|
120979
121092
|
|
|
120980
|
-
|
|
121093
|
+
|
|
121094
|
+
|
|
121095
|
+
// Matches a JSX attribute expression (e.g. `key={i}`) anywhere in a string. */
|
|
120981
121096
|
const NESTED_ATTR_EXPRESSION_RE = /[\w-]+\s*=\s*\{/;
|
|
120982
|
-
|
|
120983
|
-
|
|
120984
|
-
|
|
120985
|
-
|
|
120986
|
-
|
|
121097
|
+
// Name shape mirrors `componentTagPattern`; the lookbehind skips the inner tag
|
|
121098
|
+
// of a legacy `<<VARIABLE>>`.
|
|
121099
|
+
const NESTED_COMPONENT_TAG_RE = /(?<!<)<([A-Z][A-Za-z0-9_]*)[\s/>]/g;
|
|
121100
|
+
// Excludes tags with dedicated transformers (`Table`, `HTMLBlock`, inline
|
|
121101
|
+
// components), which expect their wrapper to stay raw.
|
|
121102
|
+
const hasNestedGenericComponentTag = (content) => [...content.matchAll(NESTED_COMPONENT_TAG_RE)].some(match => !GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(match[1]));
|
|
121103
|
+
/**
|
|
121104
|
+
* Strip the shared leading indentation from a component body so readability indentation
|
|
121105
|
+
* isn't parsed as indented code (4+ spaces), e.g. ` <p>` / ` text` -> `<p>` / ` text`.
|
|
121106
|
+
* Relative indentation is kept, so content genuinely 4+ columns deeper stays code. We
|
|
121107
|
+
* only strip when a line actually reaches 4 columns; otherwise the body is left as-is so
|
|
121108
|
+
* its leading whitespace survives as text nodes (mixed component + HTML content needs it).
|
|
120987
121109
|
*/
|
|
120988
121110
|
function safeDeindent(text) {
|
|
120989
121111
|
const lines = text.split('\n');
|
|
120990
121112
|
const nonEmptyLines = lines.filter(line => line.trim().length > 0);
|
|
120991
121113
|
if (nonEmptyLines.length === 0)
|
|
120992
121114
|
return text;
|
|
120993
|
-
|
|
120994
|
-
|
|
120995
|
-
|
|
120996
|
-
|
|
120997
|
-
|
|
120998
|
-
const stripAmount =
|
|
121115
|
+
// Indent counts characters (tab = 1), unlike indentWidth's CommonMark columns
|
|
121116
|
+
// (tab = 4) in terminate-html-flow-blocks.
|
|
121117
|
+
const indents = nonEmptyLines.map(line => line.match(/^(\s*)/)?.[1].length ?? 0);
|
|
121118
|
+
const minIndent = Math.min(...indents);
|
|
121119
|
+
const maxIndent = Math.max(...indents);
|
|
121120
|
+
const stripAmount = maxIndent > 3 ? minIndent : 0;
|
|
120999
121121
|
if (stripAmount === 0)
|
|
121000
121122
|
return text;
|
|
121001
121123
|
return lines.map(line => line.slice(stripAmount)).join('\n');
|
|
121002
121124
|
}
|
|
121003
121125
|
/**
|
|
121004
|
-
* Parse markdown
|
|
121005
|
-
*
|
|
121006
|
-
*
|
|
121126
|
+
* Parse component-body markdown into mdast children. Dedenting shifts columns and
|
|
121127
|
+
* stales the top-level `terminateHtmlFlowBlocks` decisions, so that one preprocessor
|
|
121128
|
+
* re-runs here; other column-anchored fixups (compact headings, tables) do not.
|
|
121007
121129
|
*/
|
|
121008
121130
|
const parseMdChildren = (value, safeMode) => {
|
|
121009
|
-
const parsed = getInlineMdProcessor({ safeMode }).parse(safeDeindent(value).trim());
|
|
121131
|
+
const parsed = getInlineMdProcessor({ safeMode }).parse(terminateHtmlFlowBlocks(safeDeindent(value).trim()));
|
|
121010
121132
|
return parsed.children || [];
|
|
121011
121133
|
};
|
|
121012
|
-
|
|
121013
|
-
|
|
121014
|
-
*/
|
|
121134
|
+
// Parses trailing content into sibling nodes and re-queues the parent so any
|
|
121135
|
+
// components among them get processed.
|
|
121015
121136
|
const parseSibling = (stack, parent, index, sibling, safeMode) => {
|
|
121016
121137
|
const siblingNodes = parseMdChildren(sibling, safeMode);
|
|
121017
|
-
// The new sibling nodes might contain new components to be processed
|
|
121018
121138
|
if (siblingNodes.length > 0) {
|
|
121019
121139
|
parent.children.splice(index + 1, 0, ...siblingNodes);
|
|
121020
121140
|
stack.push(parent);
|
|
121021
121141
|
}
|
|
121022
121142
|
};
|
|
121023
|
-
|
|
121024
|
-
|
|
121025
|
-
* component doesn't claim trailing content the tokenizer swallowed into one node.
|
|
121026
|
-
*/
|
|
121143
|
+
// Ends the position at `consumedLength` so the component doesn't claim trailing
|
|
121144
|
+
// content the tokenizer swallowed into the same html node.
|
|
121027
121145
|
const positionEndingAtConsumed = (nodePosition, value, consumedLength) => {
|
|
121028
121146
|
if (!nodePosition?.start)
|
|
121029
121147
|
return nodePosition;
|
|
121030
121148
|
return { start: nodePosition.start, end: pointAfter(nodePosition.start, value.slice(0, consumedLength)) };
|
|
121031
121149
|
};
|
|
121032
|
-
|
|
121033
|
-
|
|
121034
|
-
* this node's span in the original source. Used in the trailing-content path so
|
|
121035
|
-
* the offset is computed against the real source bytes (including blockquote/list
|
|
121036
|
-
* prefixes that were stripped from the html node's value).
|
|
121037
|
-
*/
|
|
121150
|
+
// Like `positionEndingAtConsumed`, but measures against the original source so
|
|
121151
|
+
// blockquote/list prefixes stripped from the html node's value are counted.
|
|
121038
121152
|
const positionEndingAtClosingTagInSource = (nodePosition, closingTag, source) => {
|
|
121039
121153
|
if (!nodePosition?.start || !nodePosition.end)
|
|
121040
121154
|
return nodePosition;
|
|
@@ -121045,9 +121159,6 @@ const positionEndingAtClosingTagInSource = (nodePosition, closingTag, source) =>
|
|
|
121045
121159
|
const consumed = nodeSource.slice(0, closingTagOffset + closingTag.length);
|
|
121046
121160
|
return { start: nodePosition.start, end: pointAfter(nodePosition.start, consumed) };
|
|
121047
121161
|
};
|
|
121048
|
-
/**
|
|
121049
|
-
* Create an MdxJsxFlowElement node from component data.
|
|
121050
|
-
*/
|
|
121051
121162
|
const createComponentNode = ({ tag, attributes, children, startPosition, endPosition }) => ({
|
|
121052
121163
|
type: 'mdxJsxFlowElement',
|
|
121053
121164
|
name: tag,
|
|
@@ -121100,8 +121211,7 @@ const mdx_blocks_mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
121100
121211
|
if ('children' in node && Array.isArray(node.children)) {
|
|
121101
121212
|
stack.push(node);
|
|
121102
121213
|
}
|
|
121103
|
-
// Only
|
|
121104
|
-
// which means a potential unparsed MDX component
|
|
121214
|
+
// Only html nodes can be an unparsed MDX component.
|
|
121105
121215
|
const value = node.value;
|
|
121106
121216
|
if (node.type !== 'html' || typeof value !== 'string')
|
|
121107
121217
|
return;
|
|
@@ -121110,32 +121220,25 @@ const mdx_blocks_mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
121110
121220
|
if (!parsed)
|
|
121111
121221
|
return;
|
|
121112
121222
|
const { tag, attributes, selfClosing, contentAfterTag = '' } = parsed;
|
|
121113
|
-
//
|
|
121114
|
-
// so consumed-length math maps back onto the node's real source offsets.
|
|
121223
|
+
// Offsets so consumed-length math maps back onto the node's real source.
|
|
121115
121224
|
const leadingWhitespace = value.length - value.trimStart().length;
|
|
121116
|
-
// Index right after the opening tag's `>` within `trimmed`.
|
|
121117
121225
|
const openingTagEnd = trimmed.length - contentAfterTag.length;
|
|
121118
|
-
// Skip tags that have dedicated transformers
|
|
121119
121226
|
if (GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(tag))
|
|
121120
|
-
return;
|
|
121227
|
+
return; // owned by dedicated transformers
|
|
121121
121228
|
const isPascal = isPascalCase(tag);
|
|
121122
|
-
// Lowercase inline tags
|
|
121123
|
-
//
|
|
121124
|
-
//
|
|
121125
|
-
// keep going through this transformer (they stay flow-level even when
|
|
121126
|
-
// inline, which is how ReadMe's custom components are modeled).
|
|
121229
|
+
// Lowercase inline tags with `{…}` attributes belong to
|
|
121230
|
+
// mdxishInlineComponentBlocks; leave them as html for that pass. PascalCase
|
|
121231
|
+
// components stay flow-level even when inline (ReadMe's component model).
|
|
121127
121232
|
if (!isPascal && parent.type === 'paragraph')
|
|
121128
121233
|
return;
|
|
121129
|
-
//
|
|
121130
|
-
//
|
|
121131
|
-
// JSX
|
|
121132
|
-
//
|
|
121133
|
-
// `style={{...}}`/`.map()` JSX inside it — as literal HTML text, which
|
|
121134
|
-
// rehype-raw's parse5 pass then garbles (it has no notion of JS expressions).
|
|
121135
|
-
// Plain HTML with no expressions anywhere stays as an html node so
|
|
121136
|
-
// rehype-raw handles it as normal.
|
|
121234
|
+
// A lowercase wrapper is only promoted when it (or a descendant) carries a
|
|
121235
|
+
// JSX expression or nests a component; otherwise it would swallow that inner
|
|
121236
|
+
// JSX/component as literal text that rehype-raw's parse5 pass can't handle.
|
|
121237
|
+
// Table-structural wrappers are excluded — `mdxishTables` re-parses those.
|
|
121137
121238
|
const hasNestedExpressionAttr = !selfClosing && NESTED_ATTR_EXPRESSION_RE.test(contentAfterTag);
|
|
121138
|
-
|
|
121239
|
+
const isTableStructuralTag = tag === 'table' || tableTags.has(tag);
|
|
121240
|
+
const hasNestedComponentTag = !selfClosing && !isTableStructuralTag && hasNestedGenericComponentTag(contentAfterTag);
|
|
121241
|
+
if (!isPascal && !hasExpressionAttr(attributes) && !hasNestedExpressionAttr && !hasNestedComponentTag)
|
|
121139
121242
|
return;
|
|
121140
121243
|
const closingTagStr = `</${tag}>`;
|
|
121141
121244
|
// Case 1: Self-closing tag
|
|
@@ -121149,7 +121252,6 @@ const mdx_blocks_mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
121149
121252
|
endPosition: positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd),
|
|
121150
121253
|
});
|
|
121151
121254
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
121152
|
-
// Check and parse if there's relevant content after the current closing tag
|
|
121153
121255
|
const remainingContent = contentAfterTag.trim();
|
|
121154
121256
|
if (remainingContent) {
|
|
121155
121257
|
parseSibling(stack, parent, index, remainingContent, safeMode);
|
|
@@ -121158,17 +121260,14 @@ const mdx_blocks_mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
121158
121260
|
}
|
|
121159
121261
|
// Case 2: Self-contained block (closing tag in content)
|
|
121160
121262
|
if (contentAfterTag.includes(closingTagStr)) {
|
|
121161
|
-
// Find the first closing tag
|
|
121162
121263
|
const closingTagIndex = contentAfterTag.lastIndexOf(closingTagStr);
|
|
121163
|
-
//
|
|
121164
|
-
// normalize indentation before trimming
|
|
121264
|
+
// Untrimmed so parseMdChildren can dedent before trimming.
|
|
121165
121265
|
const componentInnerContent = contentAfterTag.substring(0, closingTagIndex);
|
|
121166
121266
|
const contentAfterClose = contentAfterTag.substring(closingTagIndex + closingTagStr.length).trim();
|
|
121167
121267
|
let parsedChildren = componentInnerContent.trim()
|
|
121168
121268
|
? parseMdChildren(componentInnerContent, safeMode)
|
|
121169
121269
|
: [];
|
|
121170
|
-
// Lowercase
|
|
121171
|
-
// bare text in a paragraph; unwrap when there's exactly one paragraph so
|
|
121270
|
+
// Lowercase tags are usually inline; unwrap a sole paragraph so their
|
|
121172
121271
|
// phrasing content isn't spuriously block-wrapped.
|
|
121173
121272
|
if (!isPascal && parsedChildren.length === 1 && parsedChildren[0].type === 'paragraph') {
|
|
121174
121273
|
parsedChildren = parsedChildren[0].children;
|
|
@@ -121178,12 +121277,9 @@ const mdx_blocks_mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
121178
121277
|
attributes,
|
|
121179
121278
|
children: parsedChildren,
|
|
121180
121279
|
startPosition: node.position,
|
|
121181
|
-
//
|
|
121182
|
-
//
|
|
121183
|
-
//
|
|
121184
|
-
// node's value has '> '/space prefixes stripped for blockquotes/list items, so
|
|
121185
|
-
// positionEndingAtConsumed would undercount source offsets. When the entire node
|
|
121186
|
-
// is consumed, use the original node position directly.
|
|
121280
|
+
// With trailing content, end precisely at the closing tag. Prefer source
|
|
121281
|
+
// offsets when available (the node's value strips blockquote/list
|
|
121282
|
+
// prefixes); otherwise fall back to the whole node position.
|
|
121187
121283
|
endPosition: contentAfterClose
|
|
121188
121284
|
? source
|
|
121189
121285
|
? positionEndingAtClosingTagInSource(node.position, closingTagStr, source)
|
|
@@ -121191,17 +121287,16 @@ const mdx_blocks_mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
121191
121287
|
: node.position,
|
|
121192
121288
|
});
|
|
121193
121289
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
121194
|
-
//
|
|
121290
|
+
// Re-queue whichever side may hold further components.
|
|
121195
121291
|
if (contentAfterClose) {
|
|
121196
121292
|
parseSibling(stack, parent, index, contentAfterClose, safeMode);
|
|
121197
121293
|
}
|
|
121198
121294
|
else if (componentNode.children.length > 0) {
|
|
121199
|
-
// The content inside the component block might contain new components to be processed
|
|
121200
121295
|
stack.push(componentNode);
|
|
121201
121296
|
}
|
|
121202
121297
|
}
|
|
121203
121298
|
};
|
|
121204
|
-
//
|
|
121299
|
+
// Depth-first so nodes keep their source order.
|
|
121205
121300
|
while (stack.length) {
|
|
121206
121301
|
const parent = stack.pop();
|
|
121207
121302
|
if (parent?.children) {
|
|
@@ -125452,73 +125547,6 @@ function normalizeTableSeparator(content) {
|
|
|
125452
125547
|
}
|
|
125453
125548
|
/* harmony default export */ const normalize_table_separator = ((/* unused pure expression or super */ null && (normalizeTableSeparator)));
|
|
125454
125549
|
|
|
125455
|
-
;// ./processor/transform/mdxish/terminate-html-flow-blocks.ts
|
|
125456
|
-
|
|
125457
|
-
|
|
125458
|
-
|
|
125459
|
-
const STANDALONE_HTML_LINE_REGEX = /^(<[a-z][^<>]*>|<\/[a-z][^<>]*>)+\s*$/;
|
|
125460
|
-
const HTML_LINE_WITH_CONTENT_REGEX = /^<[a-z][^<>]*>.*<\/[a-z][^<>]*>(?:[^<]*)$/;
|
|
125461
|
-
// Tags whose contents must be preserved as is, inserting a blank line after the
|
|
125462
|
-
// opener corrupts the payload.
|
|
125463
|
-
// htmlRawNames here refer to <pre>, <textarea>, <script>, <style>
|
|
125464
|
-
const RAW_CONTENT_TAGS = [...htmlRawNames, ...HTML_TABLE_STRUCTURE_TAGS];
|
|
125465
|
-
// The `(?=[\s/>])` lookahead avoids false matches on lookalike names like `<script-foo>`.
|
|
125466
|
-
const RAW_CONTENT_TAG_MATCHERS = RAW_CONTENT_TAGS.map(tag => ({
|
|
125467
|
-
open: new RegExp(`<${tag}(?=[\\s/>])[^>]*?(?<!/)>`, 'gi'),
|
|
125468
|
-
close: new RegExp(`</${tag}(?=[\\s>])[^>]*>`, 'gi'),
|
|
125469
|
-
}));
|
|
125470
|
-
function isLineHtml(line) {
|
|
125471
|
-
return STANDALONE_HTML_LINE_REGEX.test(line) || HTML_LINE_WITH_CONTENT_REGEX.test(line);
|
|
125472
|
-
}
|
|
125473
|
-
// True if any RAW_CONTENT_TAGS opener on this line is not closed on the same line.
|
|
125474
|
-
function hasUnclosedRawContentOpener(line) {
|
|
125475
|
-
return RAW_CONTENT_TAG_MATCHERS.some(({ open, close }) => {
|
|
125476
|
-
const opens = (line.match(open) ?? []).length;
|
|
125477
|
-
const closes = (line.match(close) ?? []).length;
|
|
125478
|
-
return opens > closes;
|
|
125479
|
-
});
|
|
125480
|
-
}
|
|
125481
|
-
/**
|
|
125482
|
-
* Preprocessor to terminate HTML flow blocks.
|
|
125483
|
-
*
|
|
125484
|
-
* In CommonMark, HTML blocks (types 6 and 7) only terminate on a blank line.
|
|
125485
|
-
* Without one, any content on the next line is consumed as part of the HTML block
|
|
125486
|
-
* and never parsed as its own construct. For example, a `[block:callout]` immediately
|
|
125487
|
-
* following `<div><p></p></div>` gets swallowed into the HTML flow token.
|
|
125488
|
-
*
|
|
125489
|
-
* @link https://spec.commonmark.org/0.29/#html-blocks
|
|
125490
|
-
*
|
|
125491
|
-
* This preprocessor inserts a blank line after standalone HTML lines when the next
|
|
125492
|
-
* line is non-blank and not an HTML construct, ensuring micromark's HTML flow
|
|
125493
|
-
* tokenizer terminates and subsequent content is parsed independently.
|
|
125494
|
-
*
|
|
125495
|
-
* Conditions:
|
|
125496
|
-
* 1. Only non-indented lines with lowercase tag names are considered. Uppercase tags
|
|
125497
|
-
* (e.g. `<Table>`, `<MyComponent>`) are JSX custom components and don't trigger
|
|
125498
|
-
* CommonMark HTML blocks.
|
|
125499
|
-
* 2. Lines inside protected blocks (e.g. fenced code) are left untouched.
|
|
125500
|
-
* 3. Lines with an unclosed RAW_CONTENT_TAGS opener are exempted.
|
|
125501
|
-
*/
|
|
125502
|
-
function terminateHtmlFlowBlocks(content) {
|
|
125503
|
-
const { protectedContent, protectedCode } = protectCodeBlocks(content);
|
|
125504
|
-
const lines = protectedContent.split('\n');
|
|
125505
|
-
const result = [];
|
|
125506
|
-
for (let i = 0; i < lines.length; i += 1) {
|
|
125507
|
-
result.push(lines[i]);
|
|
125508
|
-
// Skip blank & indented lines
|
|
125509
|
-
if (i >= lines.length - 1 || lines[i + 1].trim().length === 0 || lines[i + 1].startsWith(' ') || lines[i + 1].startsWith('\t')) {
|
|
125510
|
-
// eslint-disable-next-line no-continue
|
|
125511
|
-
continue;
|
|
125512
|
-
}
|
|
125513
|
-
const isCurrentLineHtml = isLineHtml(lines[i]);
|
|
125514
|
-
const isNextLineHtml = isLineHtml(lines[i + 1]);
|
|
125515
|
-
if (isCurrentLineHtml && !isNextLineHtml && !hasUnclosedRawContentOpener(lines[i])) {
|
|
125516
|
-
result.push('');
|
|
125517
|
-
}
|
|
125518
|
-
}
|
|
125519
|
-
return restoreCodeBlocks(result.join('\n'), protectedCode);
|
|
125520
|
-
}
|
|
125521
|
-
|
|
125522
125550
|
;// ./processor/transform/mdxish/variables-code.ts
|
|
125523
125551
|
|
|
125524
125552
|
|
|
@@ -126386,6 +126414,12 @@ function mdxishMdastToMd(mdast) {
|
|
|
126386
126414
|
.use(remarkStringify, {
|
|
126387
126415
|
bullet: '-',
|
|
126388
126416
|
emphasis: '_',
|
|
126417
|
+
// Escape literal braces in text so they don't parse as (often
|
|
126418
|
+
// unterminated) MDX expressions on the next round trip.
|
|
126419
|
+
unsafe: [
|
|
126420
|
+
{ character: '{', inConstruct: 'phrasing' },
|
|
126421
|
+
{ character: '}', inConstruct: 'phrasing' },
|
|
126422
|
+
],
|
|
126389
126423
|
});
|
|
126390
126424
|
return processor.stringify(processor.runSync(mdast));
|
|
126391
126425
|
}
|