@readme/markdown 13.1.1 → 13.1.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/dist/main.js
CHANGED
|
@@ -13007,8 +13007,7 @@ function color(d) {
|
|
|
13007
13007
|
|
|
13008
13008
|
;// ./node_modules/unist-util-visit-parents/lib/index.js
|
|
13009
13009
|
/**
|
|
13010
|
-
* @
|
|
13011
|
-
* @typedef {import('unist').Parent} UnistParent
|
|
13010
|
+
* @import {Node as UnistNode, Parent as UnistParent} from 'unist'
|
|
13012
13011
|
*/
|
|
13013
13012
|
|
|
13014
13013
|
/**
|
|
@@ -13056,8 +13055,10 @@ function color(d) {
|
|
|
13056
13055
|
|
|
13057
13056
|
/**
|
|
13058
13057
|
* @typedef {(
|
|
13059
|
-
* Check extends
|
|
13060
|
-
* ? MatchesOne<Value,
|
|
13058
|
+
* Check extends ReadonlyArray<infer T>
|
|
13059
|
+
* ? MatchesOne<Value, T>
|
|
13060
|
+
* : Check extends Array<infer T>
|
|
13061
|
+
* ? MatchesOne<Value, T>
|
|
13061
13062
|
* : MatchesOne<Value, Check>
|
|
13062
13063
|
* )} Matches
|
|
13063
13064
|
* Check whether a node matches a check in the type system.
|
|
@@ -13327,9 +13328,9 @@ function visitParents(tree, test, visitor, reverse) {
|
|
|
13327
13328
|
typeof value.tagName === 'string'
|
|
13328
13329
|
? value.tagName
|
|
13329
13330
|
: // `xast`
|
|
13330
|
-
|
|
13331
|
-
|
|
13332
|
-
|
|
13331
|
+
typeof value.name === 'string'
|
|
13332
|
+
? value.name
|
|
13333
|
+
: undefined
|
|
13333
13334
|
|
|
13334
13335
|
Object.defineProperty(visit, 'name', {
|
|
13335
13336
|
value:
|
|
@@ -71516,6 +71517,19 @@ const coerceJsxToMd = ({ components = {}, html = false } = {}) => (node, index,
|
|
|
71516
71517
|
};
|
|
71517
71518
|
parent.children[index] = mdNode;
|
|
71518
71519
|
}
|
|
71520
|
+
else if (node.name === 'Recipe' || node.name === 'TutorialTile') {
|
|
71521
|
+
const hProperties = getAttrs(node);
|
|
71522
|
+
const mdNode = {
|
|
71523
|
+
...hProperties,
|
|
71524
|
+
type: types[node.name],
|
|
71525
|
+
data: {
|
|
71526
|
+
hName: node.name,
|
|
71527
|
+
...(Object.keys(hProperties).length && { hProperties }),
|
|
71528
|
+
},
|
|
71529
|
+
position: node.position,
|
|
71530
|
+
};
|
|
71531
|
+
parent.children[index] = mdNode;
|
|
71532
|
+
}
|
|
71519
71533
|
else if (node.name in types) {
|
|
71520
71534
|
const hProperties = getAttrs(node);
|
|
71521
71535
|
const mdNode = {
|
|
@@ -93244,6 +93258,63 @@ function rehypeStringify(options) {
|
|
|
93244
93258
|
}
|
|
93245
93259
|
}
|
|
93246
93260
|
|
|
93261
|
+
;// ./node_modules/mdast-util-newline-to-break/lib/index.js
|
|
93262
|
+
/**
|
|
93263
|
+
* @typedef {import('mdast').Nodes} Nodes
|
|
93264
|
+
* @typedef {import('mdast-util-find-and-replace').ReplaceFunction} ReplaceFunction
|
|
93265
|
+
*/
|
|
93266
|
+
|
|
93267
|
+
|
|
93268
|
+
|
|
93269
|
+
/**
|
|
93270
|
+
* Turn normal line endings into hard breaks.
|
|
93271
|
+
*
|
|
93272
|
+
* @param {Nodes} tree
|
|
93273
|
+
* Tree to change.
|
|
93274
|
+
* @returns {undefined}
|
|
93275
|
+
* Nothing.
|
|
93276
|
+
*/
|
|
93277
|
+
function newlineToBreak(tree) {
|
|
93278
|
+
findAndReplace(tree, [/\r?\n|\r/g, lib_replace])
|
|
93279
|
+
}
|
|
93280
|
+
|
|
93281
|
+
/**
|
|
93282
|
+
* Replace line endings.
|
|
93283
|
+
*
|
|
93284
|
+
* @type {ReplaceFunction}
|
|
93285
|
+
*/
|
|
93286
|
+
function lib_replace() {
|
|
93287
|
+
return {type: 'break'}
|
|
93288
|
+
}
|
|
93289
|
+
|
|
93290
|
+
;// ./node_modules/remark-breaks/lib/index.js
|
|
93291
|
+
/**
|
|
93292
|
+
* @typedef {import('mdast').Root} Root
|
|
93293
|
+
*/
|
|
93294
|
+
|
|
93295
|
+
|
|
93296
|
+
|
|
93297
|
+
/**
|
|
93298
|
+
* Support hard breaks without needing spaces or escapes (turns enters into
|
|
93299
|
+
* `<br>`s).
|
|
93300
|
+
*
|
|
93301
|
+
* @returns
|
|
93302
|
+
* Transform.
|
|
93303
|
+
*/
|
|
93304
|
+
function remarkBreaks() {
|
|
93305
|
+
/**
|
|
93306
|
+
* Transform.
|
|
93307
|
+
*
|
|
93308
|
+
* @param {Root} tree
|
|
93309
|
+
* Tree.
|
|
93310
|
+
* @returns {undefined}
|
|
93311
|
+
* Nothing.
|
|
93312
|
+
*/
|
|
93313
|
+
return function (tree) {
|
|
93314
|
+
newlineToBreak(tree)
|
|
93315
|
+
}
|
|
93316
|
+
}
|
|
93317
|
+
|
|
93247
93318
|
;// ./lib/utils/mdxish/mdxish-get-component-name.ts
|
|
93248
93319
|
/** Convert a string to PascalCase */
|
|
93249
93320
|
function toPascalCase(str) {
|
|
@@ -93922,6 +93993,71 @@ const evaluateExpressions = ({ context = {} } = {}) => tree => {
|
|
|
93922
93993
|
};
|
|
93923
93994
|
/* harmony default export */ const evaluate_expressions = (evaluateExpressions);
|
|
93924
93995
|
|
|
93996
|
+
;// ./node_modules/rehype-parse/lib/index.js
|
|
93997
|
+
/**
|
|
93998
|
+
* @import {Root} from 'hast'
|
|
93999
|
+
* @import {Options as FromHtmlOptions} from 'hast-util-from-html'
|
|
94000
|
+
* @import {Parser, Processor} from 'unified'
|
|
94001
|
+
*/
|
|
94002
|
+
|
|
94003
|
+
/**
|
|
94004
|
+
* @typedef {Omit<FromHtmlOptions, 'onerror'> & RehypeParseFields} Options
|
|
94005
|
+
* Configuration.
|
|
94006
|
+
*
|
|
94007
|
+
* @typedef RehypeParseFields
|
|
94008
|
+
* Extra fields.
|
|
94009
|
+
* @property {boolean | null | undefined} [emitParseErrors=false]
|
|
94010
|
+
* Whether to emit parse errors while parsing (default: `false`).
|
|
94011
|
+
*
|
|
94012
|
+
* > 👉 **Note**: parse errors are currently being added to HTML.
|
|
94013
|
+
* > Not all errors emitted by parse5 (or us) are specced yet.
|
|
94014
|
+
* > Some documentation may still be missing.
|
|
94015
|
+
*/
|
|
94016
|
+
|
|
94017
|
+
|
|
94018
|
+
|
|
94019
|
+
/**
|
|
94020
|
+
* Plugin to add support for parsing from HTML.
|
|
94021
|
+
*
|
|
94022
|
+
* > 👉 **Note**: this is not an XML parser.
|
|
94023
|
+
* > It supports SVG as embedded in HTML.
|
|
94024
|
+
* > It does not support the features available in XML.
|
|
94025
|
+
* > Passing SVG files might break but fragments of modern SVG should be fine.
|
|
94026
|
+
* > Use [`xast-util-from-xml`][xast-util-from-xml] to parse XML.
|
|
94027
|
+
*
|
|
94028
|
+
* @param {Options | null | undefined} [options]
|
|
94029
|
+
* Configuration (optional).
|
|
94030
|
+
* @returns {undefined}
|
|
94031
|
+
* Nothing.
|
|
94032
|
+
*/
|
|
94033
|
+
function rehypeParse(options) {
|
|
94034
|
+
/** @type {Processor<Root>} */
|
|
94035
|
+
// @ts-expect-error: TS in JSDoc generates wrong types if `this` is typed regularly.
|
|
94036
|
+
const self = this
|
|
94037
|
+
const {emitParseErrors, ...settings} = {...self.data('settings'), ...options}
|
|
94038
|
+
|
|
94039
|
+
self.parser = parser
|
|
94040
|
+
|
|
94041
|
+
/**
|
|
94042
|
+
* @type {Parser<Root>}
|
|
94043
|
+
*/
|
|
94044
|
+
function parser(document, file) {
|
|
94045
|
+
return fromHtml(document, {
|
|
94046
|
+
...settings,
|
|
94047
|
+
onerror: emitParseErrors
|
|
94048
|
+
? function (message) {
|
|
94049
|
+
if (file.path) {
|
|
94050
|
+
message.name = file.path + ':' + message.name
|
|
94051
|
+
message.file = file.path
|
|
94052
|
+
}
|
|
94053
|
+
|
|
94054
|
+
file.messages.push(message)
|
|
94055
|
+
}
|
|
94056
|
+
: undefined
|
|
94057
|
+
})
|
|
94058
|
+
}
|
|
94059
|
+
}
|
|
94060
|
+
|
|
93925
94061
|
;// ./processor/transform/mdxish/normalize-malformed-md-syntax.ts
|
|
93926
94062
|
|
|
93927
94063
|
// Marker patterns for multi-node emphasis detection
|
|
@@ -94265,6 +94401,18 @@ const normalizeEmphasisAST = () => (tree) => {
|
|
|
94265
94401
|
};
|
|
94266
94402
|
/* harmony default export */ const normalize_malformed_md_syntax = (normalizeEmphasisAST);
|
|
94267
94403
|
|
|
94404
|
+
;// ./processor/transform/mdxish/magic-blocks/patterns.ts
|
|
94405
|
+
/** Matches HTML tags (open, close, self-closing) with optional attributes. */
|
|
94406
|
+
const HTML_TAG_RE = /<\/?([a-zA-Z][a-zA-Z0-9-]*)((?:[^>"']*(?:"[^"]*"|'[^']*'))*[^>"']*)>/g;
|
|
94407
|
+
/** Matches an HTML element from its opening tag to the matching closing tag. */
|
|
94408
|
+
const HTML_ELEMENT_BLOCK_RE = /<([a-zA-Z][a-zA-Z0-9-]*)[\s>][\s\S]*?<\/\1>/g;
|
|
94409
|
+
/** Matches a newline with surrounding horizontal whitespace. */
|
|
94410
|
+
const NEWLINE_WITH_WHITESPACE_RE = /[^\S\n]*\n[^\S\n]*/g;
|
|
94411
|
+
/** Matches a closing block-level tag followed by non-tag text or by a newline then non-blank content. */
|
|
94412
|
+
const CLOSE_BLOCK_TAG_BOUNDARY_RE = /<\/([a-zA-Z][a-zA-Z0-9-]*)>\s*(?:(?!<)(\S)|\n([^\n]))/g;
|
|
94413
|
+
/** Tests whether a string contains a complete HTML element (open + close tag). */
|
|
94414
|
+
const COMPLETE_HTML_ELEMENT_RE = /<[a-zA-Z][^>]*>[\s\S]*<\/[a-zA-Z]/;
|
|
94415
|
+
|
|
94268
94416
|
;// ./processor/transform/mdxish/magic-blocks/placeholder.ts
|
|
94269
94417
|
const EMPTY_IMAGE_PLACEHOLDER = {
|
|
94270
94418
|
type: 'image',
|
|
@@ -94318,6 +94466,14 @@ const EMPTY_CODE_PLACEHOLDER = {
|
|
|
94318
94466
|
|
|
94319
94467
|
|
|
94320
94468
|
|
|
94469
|
+
|
|
94470
|
+
|
|
94471
|
+
|
|
94472
|
+
|
|
94473
|
+
|
|
94474
|
+
|
|
94475
|
+
|
|
94476
|
+
|
|
94321
94477
|
/**
|
|
94322
94478
|
* Wraps a node in a "pinned" container if sidebar: true is set.
|
|
94323
94479
|
*/
|
|
@@ -94345,12 +94501,125 @@ const imgWidthBySize = new Proxy(imgSizeValues, {
|
|
|
94345
94501
|
});
|
|
94346
94502
|
const textToInline = (text) => [{ type: 'text', value: text }];
|
|
94347
94503
|
const textToBlock = (text) => [{ children: textToInline(text), type: 'paragraph' }];
|
|
94348
|
-
/**
|
|
94349
|
-
|
|
94504
|
+
/**
|
|
94505
|
+
* Converts leading newlines in magic block content to `<br>` tags.
|
|
94506
|
+
* Leading newlines are stripped by remark-parse before they become soft break nodes,
|
|
94507
|
+
* so remark-breaks cannot handle them. We convert them to HTML `<br>` tags instead.
|
|
94508
|
+
*/
|
|
94509
|
+
const ensureLeadingBreaks = (text) => text.replace(/^\n+/, match => '<br>'.repeat(match.length));
|
|
94510
|
+
/** Preprocesses magic block body content before parsing. */
|
|
94511
|
+
const preprocessBody = (text) => {
|
|
94512
|
+
return ensureLeadingBreaks(text);
|
|
94513
|
+
};
|
|
94514
|
+
/** Markdown parser */
|
|
94515
|
+
const contentParser = unified().use(remarkParse).use(remarkBreaks).use(remarkGfm).use(normalize_malformed_md_syntax);
|
|
94516
|
+
/** Markdown to HTML processor (mdast → hast → HTML string) */
|
|
94517
|
+
const markdownToHtml = unified()
|
|
94518
|
+
.use(remarkParse)
|
|
94519
|
+
.use(remarkGfm)
|
|
94520
|
+
.use(normalize_malformed_md_syntax)
|
|
94521
|
+
.use(remarkRehype)
|
|
94522
|
+
.use(rehypeStringify);
|
|
94523
|
+
/** HTML parser (HTML string → hast) */
|
|
94524
|
+
const htmlParser = unified().use(rehypeParse, { fragment: true });
|
|
94525
|
+
/** HTML stringifier (hast → HTML string) */
|
|
94526
|
+
const htmlStringifier = unified().use(rehypeStringify);
|
|
94527
|
+
/** Process \|, \<, \> backslash escapes. Only < is entity-escaped; > is left literal to avoid double-encoding by rehype. */
|
|
94528
|
+
const processBackslashEscapes = (text) => text.replace(/\\<([^>]*)>/g, '<$1>').replace(/\\([<>|])/g, (_, c) => (c === '<' ? '<' : c === '>' ? '>' : c));
|
|
94529
|
+
/** Block-level HTML tags that trigger CommonMark type 6 HTML blocks (condition 6). */
|
|
94530
|
+
const BLOCK_LEVEL_TAGS = new Set(htmlBlockNames);
|
|
94531
|
+
const escapeInvalidTags = (str) => str.replace(HTML_TAG_RE, (match, tag, rest) => {
|
|
94532
|
+
const tagName = tag.replace(/^\//, '');
|
|
94533
|
+
if (STANDARD_HTML_TAGS.has(tagName.toLowerCase()))
|
|
94534
|
+
return match;
|
|
94535
|
+
// Preserve PascalCase tags (custom components like <Glossary>) for the main pipeline
|
|
94536
|
+
if (/^[A-Z]/.test(tagName))
|
|
94537
|
+
return match;
|
|
94538
|
+
return `<${tag}${rest}>`;
|
|
94539
|
+
});
|
|
94540
|
+
/**
|
|
94541
|
+
* Process markdown within HTML string.
|
|
94542
|
+
* 1. Parse HTML to HAST
|
|
94543
|
+
* 2. Find text nodes, parse as markdown, convert to HAST
|
|
94544
|
+
* 3. Stringify back to HTML
|
|
94545
|
+
*
|
|
94546
|
+
* PascalCase component tags (e.g. `<Glossary>`) are temporarily replaced with
|
|
94547
|
+
* placeholders before HTML parsing so `rehype-parse` doesn't mangle them
|
|
94548
|
+
* (it treats unknown tags as void elements, stripping their children).
|
|
94549
|
+
*/
|
|
94550
|
+
const processMarkdownInHtmlString = (html) => {
|
|
94551
|
+
const placeholders = [];
|
|
94552
|
+
let counter = 0;
|
|
94553
|
+
const safened = escapeInvalidTags(html).replace(HTML_TAG_RE, match => {
|
|
94554
|
+
if (!/^<\/?[A-Z]/.test(match))
|
|
94555
|
+
return match;
|
|
94556
|
+
const id = `<!--PC${(counter += 1)}-->`;
|
|
94557
|
+
placeholders.push([id, match]);
|
|
94558
|
+
return id;
|
|
94559
|
+
});
|
|
94560
|
+
const hast = htmlParser.parse(safened);
|
|
94561
|
+
const textToHast = (text) => {
|
|
94562
|
+
if (!text.trim())
|
|
94563
|
+
return [{ type: 'text', value: text }];
|
|
94564
|
+
const parsed = markdownToHtml.runSync(markdownToHtml.parse(escapeInvalidTags(text)));
|
|
94565
|
+
const nodes = parsed.children.flatMap(n => n.type === 'element' && n.tagName === 'p' ? n.children : [n]);
|
|
94566
|
+
const leading = text.match(/^\s+/)?.[0];
|
|
94567
|
+
const trailing = text.match(/\s+$/)?.[0];
|
|
94568
|
+
if (leading)
|
|
94569
|
+
nodes.unshift({ type: 'text', value: leading });
|
|
94570
|
+
if (trailing)
|
|
94571
|
+
nodes.push({ type: 'text', value: trailing });
|
|
94572
|
+
return nodes;
|
|
94573
|
+
};
|
|
94574
|
+
const processChildren = (children) => children.flatMap(child => (child.type === 'text' ? textToHast(child.value) : [child]));
|
|
94575
|
+
hast.children = processChildren(hast.children);
|
|
94576
|
+
visit(hast, 'element', (node) => {
|
|
94577
|
+
node.children = processChildren(node.children);
|
|
94578
|
+
});
|
|
94579
|
+
return placeholders.reduce((res, [id, original]) => res.replace(id, original), htmlStringifier.stringify(hast));
|
|
94580
|
+
};
|
|
94581
|
+
/**
|
|
94582
|
+
* Separate a closing block-level tag from the content that follows it.
|
|
94583
|
+
*
|
|
94584
|
+
* Each \n in the original text becomes a <br> tag to preserve spacing, then a
|
|
94585
|
+
* blank line (\n\n) is appended so CommonMark ends the HTML block and parses
|
|
94586
|
+
* the following content as markdown.
|
|
94587
|
+
*/
|
|
94588
|
+
const separateBlockTagFromContent = (match, tag, inlineChar, nextLineChar) => {
|
|
94589
|
+
if (!BLOCK_LEVEL_TAGS.has(tag.toLowerCase()))
|
|
94590
|
+
return match;
|
|
94591
|
+
const newlineCount = (match.match(/\n/g) ?? []).length;
|
|
94592
|
+
const breaks = '<br>'.repeat(newlineCount);
|
|
94593
|
+
return `</${tag}>${breaks}\n\n${inlineChar || nextLineChar}`;
|
|
94594
|
+
};
|
|
94595
|
+
/**
|
|
94596
|
+
* CommonMark doesn't process markdown inside HTML blocks -
|
|
94597
|
+
* so `<ul><li>_text_</li></ul>` won't convert underscores to emphasis.
|
|
94598
|
+
* We parse first, then visit html nodes and process their text content.
|
|
94599
|
+
*/
|
|
94350
94600
|
const parseTableCell = (text) => {
|
|
94351
94601
|
if (!text.trim())
|
|
94352
94602
|
return [{ type: 'text', value: '' }];
|
|
94353
|
-
|
|
94603
|
+
// Convert \n (and surrounding whitespace) to <br> inside HTML blocks so
|
|
94604
|
+
// CommonMark doesn't split them on blank lines.
|
|
94605
|
+
// Then strip leading whitespace to prevent indented code blocks.
|
|
94606
|
+
const escaped = processBackslashEscapes(text);
|
|
94607
|
+
const normalized = escaped
|
|
94608
|
+
.replace(HTML_ELEMENT_BLOCK_RE, match => match.replace(NEWLINE_WITH_WHITESPACE_RE, '<br>'))
|
|
94609
|
+
.replace(CLOSE_BLOCK_TAG_BOUNDARY_RE, separateBlockTagFromContent);
|
|
94610
|
+
const trimmedLines = normalized.split('\n').map(line => line.trimStart());
|
|
94611
|
+
const processed = trimmedLines.join('\n');
|
|
94612
|
+
const tree = contentParser.runSync(contentParser.parse(processed));
|
|
94613
|
+
// Process markdown inside complete HTML elements (e.g. _emphasis_ within <li>).
|
|
94614
|
+
// Bare tags like "<i>" are left for rehypeRaw since rehype-parse would mangle them.
|
|
94615
|
+
visit(tree, 'html', (node) => {
|
|
94616
|
+
if (COMPLETE_HTML_ELEMENT_RE.test(node.value)) {
|
|
94617
|
+
node.value = processMarkdownInHtmlString(node.value);
|
|
94618
|
+
}
|
|
94619
|
+
else {
|
|
94620
|
+
node.value = escapeInvalidTags(node.value);
|
|
94621
|
+
}
|
|
94622
|
+
});
|
|
94354
94623
|
if (tree.children.length > 1) {
|
|
94355
94624
|
return tree.children;
|
|
94356
94625
|
}
|
|
@@ -94505,7 +94774,7 @@ function transformMagicBlock(blockType, data, rawValue, options = {}) {
|
|
|
94505
94774
|
});
|
|
94506
94775
|
}
|
|
94507
94776
|
if (hasBody) {
|
|
94508
|
-
const bodyBlocks = parseBlock(calloutJson.body || '');
|
|
94777
|
+
const bodyBlocks = parseBlock(preprocessBody(calloutJson.body || ''));
|
|
94509
94778
|
children.push(...bodyBlocks);
|
|
94510
94779
|
}
|
|
94511
94780
|
const calloutElement = {
|
|
@@ -94540,7 +94809,7 @@ function transformMagicBlock(blockType, data, rawValue, options = {}) {
|
|
|
94540
94809
|
const tokenizeCell = compatibilityMode ? textToBlock : parseTableCell;
|
|
94541
94810
|
const tableChildren = Array.from({ length: rows + 1 }, (_, y) => ({
|
|
94542
94811
|
children: Array.from({ length: cols }, (__, x) => ({
|
|
94543
|
-
children: sparseData[y]?.[x] ? tokenizeCell(sparseData[y][x]) : [{ type: 'text', value: '' }],
|
|
94812
|
+
children: sparseData[y]?.[x] ? tokenizeCell(preprocessBody(sparseData[y][x])) : [{ type: 'text', value: '' }],
|
|
94544
94813
|
type: y === 0 ? 'tableHead' : 'tableCell',
|
|
94545
94814
|
})),
|
|
94546
94815
|
type: 'tableRow',
|
|
@@ -94641,79 +94910,63 @@ const isBlockNode = (node) => blockTypes.includes(node.type);
|
|
|
94641
94910
|
*/
|
|
94642
94911
|
const magicBlockTransformer = (options = {}) => tree => {
|
|
94643
94912
|
const replacements = [];
|
|
94644
|
-
|
|
94645
|
-
|
|
94646
|
-
|
|
94913
|
+
visitParents(tree, 'magicBlock', (node, ancestors) => {
|
|
94914
|
+
const parent = ancestors[ancestors.length - 1]; // direct parent of the current node
|
|
94915
|
+
const index = parent.children.indexOf(node);
|
|
94916
|
+
if (index === -1)
|
|
94917
|
+
return;
|
|
94647
94918
|
const children = transformMagicBlock(node.blockType, node.data, node.value, options);
|
|
94648
94919
|
if (!children.length) {
|
|
94649
|
-
//
|
|
94920
|
+
// `visitParents` doesn't support [Action, Index] returns like `visit` does;
|
|
94921
|
+
// a bare return after splicing is sufficient since `visitParents` walks by
|
|
94922
|
+
// tree structure rather than index.
|
|
94650
94923
|
parent.children.splice(index, 1);
|
|
94651
|
-
return
|
|
94924
|
+
return;
|
|
94652
94925
|
}
|
|
94653
94926
|
// If parent is a paragraph and we're inserting block nodes (which must not be in paragraphs), lift them out
|
|
94654
94927
|
if (parent.type === 'paragraph' && children.some(child => isBlockNode(child))) {
|
|
94655
94928
|
const blockNodes = [];
|
|
94656
94929
|
const inlineNodes = [];
|
|
94657
|
-
// Separate block and inline nodes
|
|
94658
94930
|
children.forEach(child => {
|
|
94659
|
-
|
|
94660
|
-
blockNodes.push(child);
|
|
94661
|
-
}
|
|
94662
|
-
else {
|
|
94663
|
-
inlineNodes.push(child);
|
|
94664
|
-
}
|
|
94931
|
+
(isBlockNode(child) ? blockNodes : inlineNodes).push(child);
|
|
94665
94932
|
});
|
|
94666
|
-
const before = parent.children.slice(0, index);
|
|
94667
|
-
const after = parent.children.slice(index + 1);
|
|
94668
94933
|
replacements.push({
|
|
94934
|
+
container: ancestors[ancestors.length - 2] || tree, // grandparent of the current node
|
|
94669
94935
|
parent,
|
|
94670
94936
|
blockNodes,
|
|
94671
94937
|
inlineNodes,
|
|
94672
|
-
before,
|
|
94673
|
-
after,
|
|
94938
|
+
before: parent.children.slice(0, index),
|
|
94939
|
+
after: parent.children.slice(index + 1),
|
|
94674
94940
|
});
|
|
94675
94941
|
}
|
|
94676
94942
|
else {
|
|
94677
|
-
// Normal case: just replace the inlineCode with the children
|
|
94678
94943
|
parent.children.splice(index, 1, ...children);
|
|
94679
94944
|
}
|
|
94680
|
-
return undefined;
|
|
94681
94945
|
});
|
|
94682
94946
|
// Second pass: apply replacements that require lifting block nodes out of paragraphs
|
|
94683
94947
|
// Process in reverse order to maintain correct indices
|
|
94684
94948
|
for (let i = replacements.length - 1; i >= 0; i -= 1) {
|
|
94685
|
-
const { after, before, blockNodes, inlineNodes, parent } = replacements[i];
|
|
94686
|
-
|
|
94687
|
-
const
|
|
94688
|
-
const paraIndex = rootChildren.findIndex(child => child === parent);
|
|
94949
|
+
const { after, before, blockNodes, container, inlineNodes, parent } = replacements[i];
|
|
94950
|
+
const containerChildren = container.children;
|
|
94951
|
+
const paraIndex = containerChildren.indexOf(parent);
|
|
94689
94952
|
if (paraIndex === -1) {
|
|
94690
|
-
|
|
94691
|
-
// This shouldn't happen normally, but handle it gracefully
|
|
94692
|
-
// Reconstruct the original index from before.length
|
|
94693
|
-
const originalIndex = before.length;
|
|
94694
|
-
parent.children.splice(originalIndex, 1, ...blockNodes, ...inlineNodes);
|
|
94953
|
+
parent.children.splice(before.length, 1, ...blockNodes, ...inlineNodes);
|
|
94695
94954
|
// eslint-disable-next-line no-continue
|
|
94696
94955
|
continue;
|
|
94697
94956
|
}
|
|
94698
|
-
// Update or remove the paragraph
|
|
94699
94957
|
if (inlineNodes.length > 0) {
|
|
94700
|
-
// Keep paragraph with inline nodes
|
|
94701
94958
|
parent.children = [...before, ...inlineNodes, ...after];
|
|
94702
|
-
// Insert block nodes after the paragraph
|
|
94703
94959
|
if (blockNodes.length > 0) {
|
|
94704
|
-
|
|
94960
|
+
containerChildren.splice(paraIndex + 1, 0, ...blockNodes);
|
|
94705
94961
|
}
|
|
94706
94962
|
}
|
|
94707
94963
|
else if (before.length === 0 && after.length === 0) {
|
|
94708
|
-
|
|
94709
|
-
rootChildren.splice(paraIndex, 1, ...blockNodes);
|
|
94964
|
+
containerChildren.splice(paraIndex, 1, ...blockNodes);
|
|
94710
94965
|
}
|
|
94711
94966
|
else {
|
|
94712
|
-
// Keep paragraph with remaining content
|
|
94713
94967
|
parent.children = [...before, ...after];
|
|
94714
|
-
// Insert block nodes after the paragraph
|
|
94715
94968
|
if (blockNodes.length > 0) {
|
|
94716
|
-
|
|
94969
|
+
containerChildren.splice(paraIndex + 1, 0, ...blockNodes);
|
|
94717
94970
|
}
|
|
94718
94971
|
}
|
|
94719
94972
|
}
|
|
@@ -95548,6 +95801,45 @@ const restoreBooleanProperties = () => tree => {
|
|
|
95548
95801
|
};
|
|
95549
95802
|
|
|
95550
95803
|
|
|
95804
|
+
;// ./processor/transform/mdxish/terminate-html-flow-blocks.ts
|
|
95805
|
+
|
|
95806
|
+
const STANDALONE_HTML_LINE_REGEX = /^(<[a-z][^<>]*>|<\/[a-z][^<>]*>)+\s*$/;
|
|
95807
|
+
const HTML_LINE_WITH_CONTENT_REGEX = /^<[a-z][^<>]*>.*<\/[a-z][^<>]*>(?:[^<]*)$/;
|
|
95808
|
+
/**
|
|
95809
|
+
* Preprocessor to terminate HTML flow blocks.
|
|
95810
|
+
*
|
|
95811
|
+
* In CommonMark, HTML blocks (types 6 and 7) only terminate on a blank line.
|
|
95812
|
+
* Without one, any content on the next line is consumed as part of the HTML block
|
|
95813
|
+
* and never parsed as its own construct. For example, a `[block:callout]` immediately
|
|
95814
|
+
* following `<div><p></p></div>` gets swallowed into the HTML flow token.
|
|
95815
|
+
*
|
|
95816
|
+
* @link https://spec.commonmark.org/0.29/#html-blocks
|
|
95817
|
+
*
|
|
95818
|
+
* This preprocessor inserts a blank line after standalone HTML lines when the
|
|
95819
|
+
* next line is non-blank, ensuring micromark's HTML flow tokenizer terminates
|
|
95820
|
+
* and subsequent content is parsed independently.
|
|
95821
|
+
*
|
|
95822
|
+
* Only targets non-indented lines with lowercase tag names. Uppercase tags
|
|
95823
|
+
* (e.g., `<Table>`, `<MyComponent>`) are JSX custom components and don't
|
|
95824
|
+
* trigger CommonMark HTML blocks, so they are left untouched.
|
|
95825
|
+
*
|
|
95826
|
+
* Lines inside fenced code blocks are skipped entirely.
|
|
95827
|
+
*/
|
|
95828
|
+
function terminateHtmlFlowBlocks(content) {
|
|
95829
|
+
const { protectedContent, protectedCode } = protectCodeBlocks(content);
|
|
95830
|
+
const lines = protectedContent.split('\n');
|
|
95831
|
+
const result = [];
|
|
95832
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
95833
|
+
result.push(lines[i]);
|
|
95834
|
+
if (i < lines.length - 1 &&
|
|
95835
|
+
(STANDALONE_HTML_LINE_REGEX.test(lines[i]) || HTML_LINE_WITH_CONTENT_REGEX.test(lines[i])) &&
|
|
95836
|
+
lines[i + 1].trim().length > 0) {
|
|
95837
|
+
result.push('');
|
|
95838
|
+
}
|
|
95839
|
+
}
|
|
95840
|
+
return restoreCodeBlocks(result.join('\n'), protectedCode);
|
|
95841
|
+
}
|
|
95842
|
+
|
|
95551
95843
|
;// ./processor/transform/mdxish/variables-text.ts
|
|
95552
95844
|
|
|
95553
95845
|
|
|
@@ -96850,10 +97142,29 @@ function loadComponents() {
|
|
|
96850
97142
|
|
|
96851
97143
|
|
|
96852
97144
|
|
|
97145
|
+
|
|
97146
|
+
|
|
96853
97147
|
|
|
96854
97148
|
|
|
96855
97149
|
|
|
96856
97150
|
const defaultTransformers = [callouts, code_tabs, gemoji_, transform_embeds];
|
|
97151
|
+
/**
|
|
97152
|
+
* Preprocessing pipeline: applies string-level transformations to work around
|
|
97153
|
+
* CommonMark/remark limitations and reach parity with legacy (rdmd) rendering.
|
|
97154
|
+
*
|
|
97155
|
+
* Runs a series of string-level transformations before micromark/remark parsing:
|
|
97156
|
+
* 1. Normalize malformed table separator syntax (e.g., `|: ---` → `| :---`)
|
|
97157
|
+
* 2. Terminate HTML flow blocks so subsequent content isn't swallowed
|
|
97158
|
+
* 3. Evaluate JSX expressions in attributes (unless safeMode)
|
|
97159
|
+
* 4. Replace snake_case component names with parser-safe placeholders
|
|
97160
|
+
*/
|
|
97161
|
+
function preprocessContent(content, opts) {
|
|
97162
|
+
const { safeMode, jsxContext, knownComponents } = opts;
|
|
97163
|
+
let result = normalizeTableSeparator(content);
|
|
97164
|
+
result = terminateHtmlFlowBlocks(result);
|
|
97165
|
+
result = safeMode ? result : preprocessJSXExpressions(result, jsxContext);
|
|
97166
|
+
return processSnakeCaseComponent(result, { knownComponents });
|
|
97167
|
+
}
|
|
96857
97168
|
function mdxishAstProcessor(mdContent, opts = {}) {
|
|
96858
97169
|
const { components: userComponents = {}, jsxContext = {}, newEditorTypes = false, safeMode = false, useTailwind, } = opts;
|
|
96859
97170
|
const components = {
|
|
@@ -96862,15 +97173,11 @@ function mdxishAstProcessor(mdContent, opts = {}) {
|
|
|
96862
97173
|
};
|
|
96863
97174
|
// Build set of known component names for snake_case filtering
|
|
96864
97175
|
const knownComponents = new Set(Object.keys(components));
|
|
96865
|
-
|
|
96866
|
-
|
|
96867
|
-
|
|
96868
|
-
|
|
96869
|
-
|
|
96870
|
-
? contentAfterTableNormalization
|
|
96871
|
-
: preprocessJSXExpressions(contentAfterTableNormalization, jsxContext);
|
|
96872
|
-
// Step 3: Replace snake_case component names with parser-safe placeholders
|
|
96873
|
-
const { content: parserReadyContent, mapping: snakeCaseMapping } = processSnakeCaseComponent(contentAfterJSXEvaluation, { knownComponents });
|
|
97176
|
+
const { content: parserReadyContent, mapping: snakeCaseMapping } = preprocessContent(mdContent, {
|
|
97177
|
+
safeMode,
|
|
97178
|
+
jsxContext,
|
|
97179
|
+
knownComponents,
|
|
97180
|
+
});
|
|
96874
97181
|
// Create string map for tailwind transformer
|
|
96875
97182
|
const tempComponentsMap = Object.entries(components).reduce((acc, [key, value]) => {
|
|
96876
97183
|
acc[key] = String(value);
|
|
@@ -96938,6 +97245,7 @@ function mdxish(mdContent, opts = {}) {
|
|
|
96938
97245
|
};
|
|
96939
97246
|
const { processor, parserReadyContent } = mdxishAstProcessor(mdContent, opts);
|
|
96940
97247
|
processor
|
|
97248
|
+
.use(remarkBreaks)
|
|
96941
97249
|
.use(remarkRehype, { allowDangerousHtml: true, handlers: mdxComponentHandlers })
|
|
96942
97250
|
.use(preserveBooleanProperties) // RehypeRaw converts boolean properties to empty strings
|
|
96943
97251
|
.use(rehypeRaw, { passThrough: ['html-block'] })
|
|
@@ -97450,18 +97758,19 @@ const mdxishTags_tags = (doc) => {
|
|
|
97450
97758
|
* Removes Markdown and MDX comments.
|
|
97451
97759
|
*/
|
|
97452
97760
|
async function stripComments(doc, { mdx, mdxish } = {}) {
|
|
97453
|
-
const
|
|
97454
|
-
|
|
97455
|
-
.data('fromMarkdownExtensions', [magicBlockFromMarkdown()])
|
|
97456
|
-
.data('toMarkdownExtensions', [magicBlockToMarkdown()]);
|
|
97761
|
+
const micromarkExtensions = [magicBlock()];
|
|
97762
|
+
const fromMarkdownExtensions = [magicBlockFromMarkdown()];
|
|
97457
97763
|
// we still require these two extensions because:
|
|
97458
|
-
// 1. we
|
|
97764
|
+
// 1. we cant rely on remarkMdx to parse MDXish
|
|
97459
97765
|
// 2. we need to parse JSX comments into mdxTextExpression nodes so that the transformers can pick them up
|
|
97460
97766
|
if (mdxish) {
|
|
97461
|
-
|
|
97462
|
-
|
|
97463
|
-
.data('fromMarkdownExtensions', [mdxExpressionFromMarkdown()]);
|
|
97767
|
+
micromarkExtensions.push(mdxExpression({ allowEmpty: true }));
|
|
97768
|
+
fromMarkdownExtensions.push(mdxExpressionFromMarkdown());
|
|
97464
97769
|
}
|
|
97770
|
+
const processor = unified()
|
|
97771
|
+
.data('micromarkExtensions', micromarkExtensions)
|
|
97772
|
+
.data('fromMarkdownExtensions', fromMarkdownExtensions)
|
|
97773
|
+
.data('toMarkdownExtensions', [magicBlockToMarkdown()]);
|
|
97465
97774
|
processor
|
|
97466
97775
|
.use(remarkParse)
|
|
97467
97776
|
.use(normalize_malformed_md_syntax)
|