@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.js
CHANGED
|
@@ -97322,6 +97322,19 @@ const compile_list_item_listItem = (node, parent, state, info) => {
|
|
|
97322
97322
|
const plain_plain = (node) => node.value;
|
|
97323
97323
|
/* harmony default export */ const compile_plain = (plain_plain);
|
|
97324
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
|
+
|
|
97325
97338
|
;// ./processor/compile/index.ts
|
|
97326
97339
|
|
|
97327
97340
|
|
|
@@ -97334,11 +97347,11 @@ const plain_plain = (node) => node.value;
|
|
|
97334
97347
|
|
|
97335
97348
|
|
|
97336
97349
|
|
|
97350
|
+
|
|
97337
97351
|
function compilers(mdxish = false) {
|
|
97338
97352
|
const data = this.data();
|
|
97339
97353
|
const toMarkdownExtensions = data.toMarkdownExtensions || (data.toMarkdownExtensions = []);
|
|
97340
97354
|
const handlers = {
|
|
97341
|
-
...(mdxish && { [NodeTypes.anchor]: compile_anchor }),
|
|
97342
97355
|
[NodeTypes.callout]: compile_callout,
|
|
97343
97356
|
[NodeTypes.codeTabs]: compile_code_tabs,
|
|
97344
97357
|
[NodeTypes.embedBlock]: compile_embed,
|
|
@@ -97346,15 +97359,18 @@ function compilers(mdxish = false) {
|
|
|
97346
97359
|
[NodeTypes.glossary]: compile_compatibility,
|
|
97347
97360
|
[NodeTypes.htmlBlock]: html_block,
|
|
97348
97361
|
[NodeTypes.reusableContent]: compile_compatibility,
|
|
97349
|
-
...(mdxish && { [NodeTypes.variable]: compile_variable }),
|
|
97350
97362
|
embed: compile_compatibility,
|
|
97351
97363
|
escape: compile_compatibility,
|
|
97352
97364
|
figure: compile_compatibility,
|
|
97353
97365
|
html: compile_compatibility,
|
|
97354
97366
|
i: compile_compatibility,
|
|
97355
|
-
...(mdxish && { listItem: list_item }),
|
|
97356
97367
|
plain: compile_plain,
|
|
97357
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 }),
|
|
97358
97374
|
};
|
|
97359
97375
|
toMarkdownExtensions.push({ extensions: [{ handlers }] });
|
|
97360
97376
|
}
|
|
@@ -102216,70 +102232,168 @@ const mdxishInlineMdxComponents = () => tree => {
|
|
|
102216
102232
|
};
|
|
102217
102233
|
/* harmony default export */ const inline_mdx_blocks = (mdxishInlineMdxComponents);
|
|
102218
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
|
+
|
|
102219
102332
|
;// ./processor/transform/mdxish/components/mdx-blocks.ts
|
|
102220
102333
|
|
|
102221
102334
|
|
|
102222
102335
|
|
|
102223
102336
|
|
|
102224
102337
|
|
|
102225
|
-
|
|
102338
|
+
|
|
102339
|
+
|
|
102340
|
+
// Matches a JSX attribute expression (e.g. `key={i}`) anywhere in a string. */
|
|
102226
102341
|
const NESTED_ATTR_EXPRESSION_RE = /[\w-]+\s*=\s*\{/;
|
|
102227
|
-
|
|
102228
|
-
|
|
102229
|
-
|
|
102230
|
-
|
|
102231
|
-
|
|
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).
|
|
102232
102354
|
*/
|
|
102233
102355
|
function safeDeindent(text) {
|
|
102234
102356
|
const lines = text.split('\n');
|
|
102235
102357
|
const nonEmptyLines = lines.filter(line => line.trim().length > 0);
|
|
102236
102358
|
if (nonEmptyLines.length === 0)
|
|
102237
102359
|
return text;
|
|
102238
|
-
|
|
102239
|
-
|
|
102240
|
-
|
|
102241
|
-
|
|
102242
|
-
|
|
102243
|
-
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;
|
|
102244
102366
|
if (stripAmount === 0)
|
|
102245
102367
|
return text;
|
|
102246
102368
|
return lines.map(line => line.slice(stripAmount)).join('\n');
|
|
102247
102369
|
}
|
|
102248
102370
|
/**
|
|
102249
|
-
* Parse markdown
|
|
102250
|
-
*
|
|
102251
|
-
*
|
|
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.
|
|
102252
102374
|
*/
|
|
102253
102375
|
const parseMdChildren = (value, safeMode) => {
|
|
102254
|
-
const parsed = getInlineMdProcessor({ safeMode }).parse(safeDeindent(value).trim());
|
|
102376
|
+
const parsed = getInlineMdProcessor({ safeMode }).parse(terminateHtmlFlowBlocks(safeDeindent(value).trim()));
|
|
102255
102377
|
return parsed.children || [];
|
|
102256
102378
|
};
|
|
102257
|
-
|
|
102258
|
-
|
|
102259
|
-
*/
|
|
102379
|
+
// Parses trailing content into sibling nodes and re-queues the parent so any
|
|
102380
|
+
// components among them get processed.
|
|
102260
102381
|
const parseSibling = (stack, parent, index, sibling, safeMode) => {
|
|
102261
102382
|
const siblingNodes = parseMdChildren(sibling, safeMode);
|
|
102262
|
-
// The new sibling nodes might contain new components to be processed
|
|
102263
102383
|
if (siblingNodes.length > 0) {
|
|
102264
102384
|
parent.children.splice(index + 1, 0, ...siblingNodes);
|
|
102265
102385
|
stack.push(parent);
|
|
102266
102386
|
}
|
|
102267
102387
|
};
|
|
102268
|
-
|
|
102269
|
-
|
|
102270
|
-
* component doesn't claim trailing content the tokenizer swallowed into one node.
|
|
102271
|
-
*/
|
|
102388
|
+
// Ends the position at `consumedLength` so the component doesn't claim trailing
|
|
102389
|
+
// content the tokenizer swallowed into the same html node.
|
|
102272
102390
|
const positionEndingAtConsumed = (nodePosition, value, consumedLength) => {
|
|
102273
102391
|
if (!nodePosition?.start)
|
|
102274
102392
|
return nodePosition;
|
|
102275
102393
|
return { start: nodePosition.start, end: pointAfter(nodePosition.start, value.slice(0, consumedLength)) };
|
|
102276
102394
|
};
|
|
102277
|
-
|
|
102278
|
-
|
|
102279
|
-
* this node's span in the original source. Used in the trailing-content path so
|
|
102280
|
-
* the offset is computed against the real source bytes (including blockquote/list
|
|
102281
|
-
* prefixes that were stripped from the html node's value).
|
|
102282
|
-
*/
|
|
102395
|
+
// Like `positionEndingAtConsumed`, but measures against the original source so
|
|
102396
|
+
// blockquote/list prefixes stripped from the html node's value are counted.
|
|
102283
102397
|
const positionEndingAtClosingTagInSource = (nodePosition, closingTag, source) => {
|
|
102284
102398
|
if (!nodePosition?.start || !nodePosition.end)
|
|
102285
102399
|
return nodePosition;
|
|
@@ -102290,9 +102404,6 @@ const positionEndingAtClosingTagInSource = (nodePosition, closingTag, source) =>
|
|
|
102290
102404
|
const consumed = nodeSource.slice(0, closingTagOffset + closingTag.length);
|
|
102291
102405
|
return { start: nodePosition.start, end: pointAfter(nodePosition.start, consumed) };
|
|
102292
102406
|
};
|
|
102293
|
-
/**
|
|
102294
|
-
* Create an MdxJsxFlowElement node from component data.
|
|
102295
|
-
*/
|
|
102296
102407
|
const createComponentNode = ({ tag, attributes, children, startPosition, endPosition }) => ({
|
|
102297
102408
|
type: 'mdxJsxFlowElement',
|
|
102298
102409
|
name: tag,
|
|
@@ -102345,8 +102456,7 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102345
102456
|
if ('children' in node && Array.isArray(node.children)) {
|
|
102346
102457
|
stack.push(node);
|
|
102347
102458
|
}
|
|
102348
|
-
// Only
|
|
102349
|
-
// which means a potential unparsed MDX component
|
|
102459
|
+
// Only html nodes can be an unparsed MDX component.
|
|
102350
102460
|
const value = node.value;
|
|
102351
102461
|
if (node.type !== 'html' || typeof value !== 'string')
|
|
102352
102462
|
return;
|
|
@@ -102355,32 +102465,25 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102355
102465
|
if (!parsed)
|
|
102356
102466
|
return;
|
|
102357
102467
|
const { tag, attributes, selfClosing, contentAfterTag = '' } = parsed;
|
|
102358
|
-
//
|
|
102359
|
-
// 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.
|
|
102360
102469
|
const leadingWhitespace = value.length - value.trimStart().length;
|
|
102361
|
-
// Index right after the opening tag's `>` within `trimmed`.
|
|
102362
102470
|
const openingTagEnd = trimmed.length - contentAfterTag.length;
|
|
102363
|
-
// Skip tags that have dedicated transformers
|
|
102364
102471
|
if (GENERIC_MDX_COMPONENT_EXCLUDED_TAGS.has(tag))
|
|
102365
|
-
return;
|
|
102472
|
+
return; // owned by dedicated transformers
|
|
102366
102473
|
const isPascal = isPascalCase(tag);
|
|
102367
|
-
// Lowercase inline tags
|
|
102368
|
-
//
|
|
102369
|
-
//
|
|
102370
|
-
// keep going through this transformer (they stay flow-level even when
|
|
102371
|
-
// 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).
|
|
102372
102477
|
if (!isPascal && parent.type === 'paragraph')
|
|
102373
102478
|
return;
|
|
102374
|
-
//
|
|
102375
|
-
//
|
|
102376
|
-
// JSX
|
|
102377
|
-
//
|
|
102378
|
-
// `style={{...}}`/`.map()` JSX inside it — as literal HTML text, which
|
|
102379
|
-
// rehype-raw's parse5 pass then garbles (it has no notion of JS expressions).
|
|
102380
|
-
// Plain HTML with no expressions anywhere stays as an html node so
|
|
102381
|
-
// 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.
|
|
102382
102483
|
const hasNestedExpressionAttr = !selfClosing && NESTED_ATTR_EXPRESSION_RE.test(contentAfterTag);
|
|
102383
|
-
|
|
102484
|
+
const isTableStructuralTag = tag === 'table' || tableTags.has(tag);
|
|
102485
|
+
const hasNestedComponentTag = !selfClosing && !isTableStructuralTag && hasNestedGenericComponentTag(contentAfterTag);
|
|
102486
|
+
if (!isPascal && !hasExpressionAttr(attributes) && !hasNestedExpressionAttr && !hasNestedComponentTag)
|
|
102384
102487
|
return;
|
|
102385
102488
|
const closingTagStr = `</${tag}>`;
|
|
102386
102489
|
// Case 1: Self-closing tag
|
|
@@ -102394,7 +102497,6 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102394
102497
|
endPosition: positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd),
|
|
102395
102498
|
});
|
|
102396
102499
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
102397
|
-
// Check and parse if there's relevant content after the current closing tag
|
|
102398
102500
|
const remainingContent = contentAfterTag.trim();
|
|
102399
102501
|
if (remainingContent) {
|
|
102400
102502
|
parseSibling(stack, parent, index, remainingContent, safeMode);
|
|
@@ -102403,17 +102505,14 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102403
102505
|
}
|
|
102404
102506
|
// Case 2: Self-contained block (closing tag in content)
|
|
102405
102507
|
if (contentAfterTag.includes(closingTagStr)) {
|
|
102406
|
-
// Find the first closing tag
|
|
102407
102508
|
const closingTagIndex = contentAfterTag.lastIndexOf(closingTagStr);
|
|
102408
|
-
//
|
|
102409
|
-
// normalize indentation before trimming
|
|
102509
|
+
// Untrimmed so parseMdChildren can dedent before trimming.
|
|
102410
102510
|
const componentInnerContent = contentAfterTag.substring(0, closingTagIndex);
|
|
102411
102511
|
const contentAfterClose = contentAfterTag.substring(closingTagIndex + closingTagStr.length).trim();
|
|
102412
102512
|
let parsedChildren = componentInnerContent.trim()
|
|
102413
102513
|
? parseMdChildren(componentInnerContent, safeMode)
|
|
102414
102514
|
: [];
|
|
102415
|
-
// Lowercase
|
|
102416
|
-
// 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
|
|
102417
102516
|
// phrasing content isn't spuriously block-wrapped.
|
|
102418
102517
|
if (!isPascal && parsedChildren.length === 1 && parsedChildren[0].type === 'paragraph') {
|
|
102419
102518
|
parsedChildren = parsedChildren[0].children;
|
|
@@ -102423,12 +102522,9 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102423
102522
|
attributes,
|
|
102424
102523
|
children: parsedChildren,
|
|
102425
102524
|
startPosition: node.position,
|
|
102426
|
-
//
|
|
102427
|
-
//
|
|
102428
|
-
//
|
|
102429
|
-
// node's value has '> '/space prefixes stripped for blockquotes/list items, so
|
|
102430
|
-
// positionEndingAtConsumed would undercount source offsets. When the entire node
|
|
102431
|
-
// 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.
|
|
102432
102528
|
endPosition: contentAfterClose
|
|
102433
102529
|
? source
|
|
102434
102530
|
? positionEndingAtClosingTagInSource(node.position, closingTagStr, source)
|
|
@@ -102436,17 +102532,16 @@ const mdxishMdxComponentBlocks = (opts = {}) => (tree, file) => {
|
|
|
102436
102532
|
: node.position,
|
|
102437
102533
|
});
|
|
102438
102534
|
substituteNodeWithMdxNode(parent, index, componentNode);
|
|
102439
|
-
//
|
|
102535
|
+
// Re-queue whichever side may hold further components.
|
|
102440
102536
|
if (contentAfterClose) {
|
|
102441
102537
|
parseSibling(stack, parent, index, contentAfterClose, safeMode);
|
|
102442
102538
|
}
|
|
102443
102539
|
else if (componentNode.children.length > 0) {
|
|
102444
|
-
// The content inside the component block might contain new components to be processed
|
|
102445
102540
|
stack.push(componentNode);
|
|
102446
102541
|
}
|
|
102447
102542
|
}
|
|
102448
102543
|
};
|
|
102449
|
-
//
|
|
102544
|
+
// Depth-first so nodes keep their source order.
|
|
102450
102545
|
while (stack.length) {
|
|
102451
102546
|
const parent = stack.pop();
|
|
102452
102547
|
if (parent?.children) {
|
|
@@ -105279,73 +105374,6 @@ function normalizeTableSeparator(content) {
|
|
|
105279
105374
|
}
|
|
105280
105375
|
/* harmony default export */ const normalize_table_separator = ((/* unused pure expression or super */ null && (normalizeTableSeparator)));
|
|
105281
105376
|
|
|
105282
|
-
;// ./processor/transform/mdxish/terminate-html-flow-blocks.ts
|
|
105283
|
-
|
|
105284
|
-
|
|
105285
|
-
|
|
105286
|
-
const STANDALONE_HTML_LINE_REGEX = /^(<[a-z][^<>]*>|<\/[a-z][^<>]*>)+\s*$/;
|
|
105287
|
-
const HTML_LINE_WITH_CONTENT_REGEX = /^<[a-z][^<>]*>.*<\/[a-z][^<>]*>(?:[^<]*)$/;
|
|
105288
|
-
// Tags whose contents must be preserved as is, inserting a blank line after the
|
|
105289
|
-
// opener corrupts the payload.
|
|
105290
|
-
// htmlRawNames here refer to <pre>, <textarea>, <script>, <style>
|
|
105291
|
-
const RAW_CONTENT_TAGS = [...htmlRawNames, ...HTML_TABLE_STRUCTURE_TAGS];
|
|
105292
|
-
// The `(?=[\s/>])` lookahead avoids false matches on lookalike names like `<script-foo>`.
|
|
105293
|
-
const RAW_CONTENT_TAG_MATCHERS = RAW_CONTENT_TAGS.map(tag => ({
|
|
105294
|
-
open: new RegExp(`<${tag}(?=[\\s/>])[^>]*?(?<!/)>`, 'gi'),
|
|
105295
|
-
close: new RegExp(`</${tag}(?=[\\s>])[^>]*>`, 'gi'),
|
|
105296
|
-
}));
|
|
105297
|
-
function isLineHtml(line) {
|
|
105298
|
-
return STANDALONE_HTML_LINE_REGEX.test(line) || HTML_LINE_WITH_CONTENT_REGEX.test(line);
|
|
105299
|
-
}
|
|
105300
|
-
// True if any RAW_CONTENT_TAGS opener on this line is not closed on the same line.
|
|
105301
|
-
function hasUnclosedRawContentOpener(line) {
|
|
105302
|
-
return RAW_CONTENT_TAG_MATCHERS.some(({ open, close }) => {
|
|
105303
|
-
const opens = (line.match(open) ?? []).length;
|
|
105304
|
-
const closes = (line.match(close) ?? []).length;
|
|
105305
|
-
return opens > closes;
|
|
105306
|
-
});
|
|
105307
|
-
}
|
|
105308
|
-
/**
|
|
105309
|
-
* Preprocessor to terminate HTML flow blocks.
|
|
105310
|
-
*
|
|
105311
|
-
* In CommonMark, HTML blocks (types 6 and 7) only terminate on a blank line.
|
|
105312
|
-
* Without one, any content on the next line is consumed as part of the HTML block
|
|
105313
|
-
* and never parsed as its own construct. For example, a `[block:callout]` immediately
|
|
105314
|
-
* following `<div><p></p></div>` gets swallowed into the HTML flow token.
|
|
105315
|
-
*
|
|
105316
|
-
* @link https://spec.commonmark.org/0.29/#html-blocks
|
|
105317
|
-
*
|
|
105318
|
-
* This preprocessor inserts a blank line after standalone HTML lines when the next
|
|
105319
|
-
* line is non-blank and not an HTML construct, ensuring micromark's HTML flow
|
|
105320
|
-
* tokenizer terminates and subsequent content is parsed independently.
|
|
105321
|
-
*
|
|
105322
|
-
* Conditions:
|
|
105323
|
-
* 1. Only non-indented lines with lowercase tag names are considered. Uppercase tags
|
|
105324
|
-
* (e.g. `<Table>`, `<MyComponent>`) are JSX custom components and don't trigger
|
|
105325
|
-
* CommonMark HTML blocks.
|
|
105326
|
-
* 2. Lines inside protected blocks (e.g. fenced code) are left untouched.
|
|
105327
|
-
* 3. Lines with an unclosed RAW_CONTENT_TAGS opener are exempted.
|
|
105328
|
-
*/
|
|
105329
|
-
function terminateHtmlFlowBlocks(content) {
|
|
105330
|
-
const { protectedContent, protectedCode } = protectCodeBlocks(content);
|
|
105331
|
-
const lines = protectedContent.split('\n');
|
|
105332
|
-
const result = [];
|
|
105333
|
-
for (let i = 0; i < lines.length; i += 1) {
|
|
105334
|
-
result.push(lines[i]);
|
|
105335
|
-
// Skip blank & indented lines
|
|
105336
|
-
if (i >= lines.length - 1 || lines[i + 1].trim().length === 0 || lines[i + 1].startsWith(' ') || lines[i + 1].startsWith('\t')) {
|
|
105337
|
-
// eslint-disable-next-line no-continue
|
|
105338
|
-
continue;
|
|
105339
|
-
}
|
|
105340
|
-
const isCurrentLineHtml = isLineHtml(lines[i]);
|
|
105341
|
-
const isNextLineHtml = isLineHtml(lines[i + 1]);
|
|
105342
|
-
if (isCurrentLineHtml && !isNextLineHtml && !hasUnclosedRawContentOpener(lines[i])) {
|
|
105343
|
-
result.push('');
|
|
105344
|
-
}
|
|
105345
|
-
}
|
|
105346
|
-
return restoreCodeBlocks(result.join('\n'), protectedCode);
|
|
105347
|
-
}
|
|
105348
|
-
|
|
105349
105377
|
;// ./processor/transform/mdxish/variables-code.ts
|
|
105350
105378
|
|
|
105351
105379
|
|
|
@@ -106213,6 +106241,12 @@ function mdxishMdastToMd(mdast) {
|
|
|
106213
106241
|
.use(remarkStringify, {
|
|
106214
106242
|
bullet: '-',
|
|
106215
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
|
+
],
|
|
106216
106250
|
});
|
|
106217
106251
|
return processor.stringify(processor.runSync(mdast));
|
|
106218
106252
|
}
|