@readme/markdown 13.1.0 → 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.node.js CHANGED
@@ -25560,8 +25560,7 @@ function color(d) {
25560
25560
 
25561
25561
  ;// ./node_modules/unist-util-visit-parents/lib/index.js
25562
25562
  /**
25563
- * @typedef {import('unist').Node} UnistNode
25564
- * @typedef {import('unist').Parent} UnistParent
25563
+ * @import {Node as UnistNode, Parent as UnistParent} from 'unist'
25565
25564
  */
25566
25565
 
25567
25566
  /**
@@ -25609,8 +25608,10 @@ function color(d) {
25609
25608
 
25610
25609
  /**
25611
25610
  * @typedef {(
25612
- * Check extends Array<any>
25613
- * ? MatchesOne<Value, Check[keyof Check]>
25611
+ * Check extends ReadonlyArray<infer T>
25612
+ * ? MatchesOne<Value, T>
25613
+ * : Check extends Array<infer T>
25614
+ * ? MatchesOne<Value, T>
25614
25615
  * : MatchesOne<Value, Check>
25615
25616
  * )} Matches
25616
25617
  * Check whether a node matches a check in the type system.
@@ -25880,9 +25881,9 @@ function visitParents(tree, test, visitor, reverse) {
25880
25881
  typeof value.tagName === 'string'
25881
25882
  ? value.tagName
25882
25883
  : // `xast`
25883
- typeof value.name === 'string'
25884
- ? value.name
25885
- : undefined
25884
+ typeof value.name === 'string'
25885
+ ? value.name
25886
+ : undefined
25886
25887
 
25887
25888
  Object.defineProperty(visit, 'name', {
25888
25889
  value:
@@ -91720,6 +91721,19 @@ const coerceJsxToMd = ({ components = {}, html = false } = {}) => (node, index,
91720
91721
  };
91721
91722
  parent.children[index] = mdNode;
91722
91723
  }
91724
+ else if (node.name === 'Recipe' || node.name === 'TutorialTile') {
91725
+ const hProperties = getAttrs(node);
91726
+ const mdNode = {
91727
+ ...hProperties,
91728
+ type: readme_components_types[node.name],
91729
+ data: {
91730
+ hName: node.name,
91731
+ ...(Object.keys(hProperties).length && { hProperties }),
91732
+ },
91733
+ position: node.position,
91734
+ };
91735
+ parent.children[index] = mdNode;
91736
+ }
91723
91737
  else if (node.name in readme_components_types) {
91724
91738
  const hProperties = getAttrs(node);
91725
91739
  const mdNode = {
@@ -113448,6 +113462,63 @@ function rehypeStringify(options) {
113448
113462
  }
113449
113463
  }
113450
113464
 
113465
+ ;// ./node_modules/mdast-util-newline-to-break/lib/index.js
113466
+ /**
113467
+ * @typedef {import('mdast').Nodes} Nodes
113468
+ * @typedef {import('mdast-util-find-and-replace').ReplaceFunction} ReplaceFunction
113469
+ */
113470
+
113471
+
113472
+
113473
+ /**
113474
+ * Turn normal line endings into hard breaks.
113475
+ *
113476
+ * @param {Nodes} tree
113477
+ * Tree to change.
113478
+ * @returns {undefined}
113479
+ * Nothing.
113480
+ */
113481
+ function newlineToBreak(tree) {
113482
+ findAndReplace(tree, [/\r?\n|\r/g, lib_replace])
113483
+ }
113484
+
113485
+ /**
113486
+ * Replace line endings.
113487
+ *
113488
+ * @type {ReplaceFunction}
113489
+ */
113490
+ function lib_replace() {
113491
+ return {type: 'break'}
113492
+ }
113493
+
113494
+ ;// ./node_modules/remark-breaks/lib/index.js
113495
+ /**
113496
+ * @typedef {import('mdast').Root} Root
113497
+ */
113498
+
113499
+
113500
+
113501
+ /**
113502
+ * Support hard breaks without needing spaces or escapes (turns enters into
113503
+ * `<br>`s).
113504
+ *
113505
+ * @returns
113506
+ * Transform.
113507
+ */
113508
+ function remarkBreaks() {
113509
+ /**
113510
+ * Transform.
113511
+ *
113512
+ * @param {Root} tree
113513
+ * Tree.
113514
+ * @returns {undefined}
113515
+ * Nothing.
113516
+ */
113517
+ return function (tree) {
113518
+ newlineToBreak(tree)
113519
+ }
113520
+ }
113521
+
113451
113522
  ;// ./lib/utils/mdxish/mdxish-get-component-name.ts
113452
113523
  /** Convert a string to PascalCase */
113453
113524
  function toPascalCase(str) {
@@ -114126,6 +114197,71 @@ const evaluateExpressions = ({ context = {} } = {}) => tree => {
114126
114197
  };
114127
114198
  /* harmony default export */ const evaluate_expressions = (evaluateExpressions);
114128
114199
 
114200
+ ;// ./node_modules/rehype-parse/lib/index.js
114201
+ /**
114202
+ * @import {Root} from 'hast'
114203
+ * @import {Options as FromHtmlOptions} from 'hast-util-from-html'
114204
+ * @import {Parser, Processor} from 'unified'
114205
+ */
114206
+
114207
+ /**
114208
+ * @typedef {Omit<FromHtmlOptions, 'onerror'> & RehypeParseFields} Options
114209
+ * Configuration.
114210
+ *
114211
+ * @typedef RehypeParseFields
114212
+ * Extra fields.
114213
+ * @property {boolean | null | undefined} [emitParseErrors=false]
114214
+ * Whether to emit parse errors while parsing (default: `false`).
114215
+ *
114216
+ * > 👉 **Note**: parse errors are currently being added to HTML.
114217
+ * > Not all errors emitted by parse5 (or us) are specced yet.
114218
+ * > Some documentation may still be missing.
114219
+ */
114220
+
114221
+
114222
+
114223
+ /**
114224
+ * Plugin to add support for parsing from HTML.
114225
+ *
114226
+ * > 👉 **Note**: this is not an XML parser.
114227
+ * > It supports SVG as embedded in HTML.
114228
+ * > It does not support the features available in XML.
114229
+ * > Passing SVG files might break but fragments of modern SVG should be fine.
114230
+ * > Use [`xast-util-from-xml`][xast-util-from-xml] to parse XML.
114231
+ *
114232
+ * @param {Options | null | undefined} [options]
114233
+ * Configuration (optional).
114234
+ * @returns {undefined}
114235
+ * Nothing.
114236
+ */
114237
+ function rehypeParse(options) {
114238
+ /** @type {Processor<Root>} */
114239
+ // @ts-expect-error: TS in JSDoc generates wrong types if `this` is typed regularly.
114240
+ const self = this
114241
+ const {emitParseErrors, ...settings} = {...self.data('settings'), ...options}
114242
+
114243
+ self.parser = parser
114244
+
114245
+ /**
114246
+ * @type {Parser<Root>}
114247
+ */
114248
+ function parser(document, file) {
114249
+ return fromHtml(document, {
114250
+ ...settings,
114251
+ onerror: emitParseErrors
114252
+ ? function (message) {
114253
+ if (file.path) {
114254
+ message.name = file.path + ':' + message.name
114255
+ message.file = file.path
114256
+ }
114257
+
114258
+ file.messages.push(message)
114259
+ }
114260
+ : undefined
114261
+ })
114262
+ }
114263
+ }
114264
+
114129
114265
  ;// ./processor/transform/mdxish/normalize-malformed-md-syntax.ts
114130
114266
 
114131
114267
  // Marker patterns for multi-node emphasis detection
@@ -114469,6 +114605,18 @@ const normalizeEmphasisAST = () => (tree) => {
114469
114605
  };
114470
114606
  /* harmony default export */ const normalize_malformed_md_syntax = (normalizeEmphasisAST);
114471
114607
 
114608
+ ;// ./processor/transform/mdxish/magic-blocks/patterns.ts
114609
+ /** Matches HTML tags (open, close, self-closing) with optional attributes. */
114610
+ const HTML_TAG_RE = /<\/?([a-zA-Z][a-zA-Z0-9-]*)((?:[^>"']*(?:"[^"]*"|'[^']*'))*[^>"']*)>/g;
114611
+ /** Matches an HTML element from its opening tag to the matching closing tag. */
114612
+ const HTML_ELEMENT_BLOCK_RE = /<([a-zA-Z][a-zA-Z0-9-]*)[\s>][\s\S]*?<\/\1>/g;
114613
+ /** Matches a newline with surrounding horizontal whitespace. */
114614
+ const NEWLINE_WITH_WHITESPACE_RE = /[^\S\n]*\n[^\S\n]*/g;
114615
+ /** Matches a closing block-level tag followed by non-tag text or by a newline then non-blank content. */
114616
+ const CLOSE_BLOCK_TAG_BOUNDARY_RE = /<\/([a-zA-Z][a-zA-Z0-9-]*)>\s*(?:(?!<)(\S)|\n([^\n]))/g;
114617
+ /** Tests whether a string contains a complete HTML element (open + close tag). */
114618
+ const COMPLETE_HTML_ELEMENT_RE = /<[a-zA-Z][^>]*>[\s\S]*<\/[a-zA-Z]/;
114619
+
114472
114620
  ;// ./processor/transform/mdxish/magic-blocks/placeholder.ts
114473
114621
  const EMPTY_IMAGE_PLACEHOLDER = {
114474
114622
  type: 'image',
@@ -114522,6 +114670,14 @@ const EMPTY_CODE_PLACEHOLDER = {
114522
114670
 
114523
114671
 
114524
114672
 
114673
+
114674
+
114675
+
114676
+
114677
+
114678
+
114679
+
114680
+
114525
114681
  /**
114526
114682
  * Wraps a node in a "pinned" container if sidebar: true is set.
114527
114683
  */
@@ -114549,12 +114705,125 @@ const imgWidthBySize = new Proxy(imgSizeValues, {
114549
114705
  });
114550
114706
  const textToInline = (text) => [{ type: 'text', value: text }];
114551
114707
  const textToBlock = (text) => [{ children: textToInline(text), type: 'paragraph' }];
114552
- /** Parses markdown and html to markdown nodes */
114553
- const contentParser = unified().use(remarkParse).use(remarkGfm).use(normalize_malformed_md_syntax);
114708
+ /**
114709
+ * Converts leading newlines in magic block content to `<br>` tags.
114710
+ * Leading newlines are stripped by remark-parse before they become soft break nodes,
114711
+ * so remark-breaks cannot handle them. We convert them to HTML `<br>` tags instead.
114712
+ */
114713
+ const ensureLeadingBreaks = (text) => text.replace(/^\n+/, match => '<br>'.repeat(match.length));
114714
+ /** Preprocesses magic block body content before parsing. */
114715
+ const preprocessBody = (text) => {
114716
+ return ensureLeadingBreaks(text);
114717
+ };
114718
+ /** Markdown parser */
114719
+ const contentParser = unified().use(remarkParse).use(remarkBreaks).use(remarkGfm).use(normalize_malformed_md_syntax);
114720
+ /** Markdown to HTML processor (mdast → hast → HTML string) */
114721
+ const markdownToHtml = unified()
114722
+ .use(remarkParse)
114723
+ .use(remarkGfm)
114724
+ .use(normalize_malformed_md_syntax)
114725
+ .use(remarkRehype)
114726
+ .use(rehypeStringify);
114727
+ /** HTML parser (HTML string → hast) */
114728
+ const htmlParser = unified().use(rehypeParse, { fragment: true });
114729
+ /** HTML stringifier (hast → HTML string) */
114730
+ const htmlStringifier = unified().use(rehypeStringify);
114731
+ /** Process \|, \<, \> backslash escapes. Only < is entity-escaped; > is left literal to avoid double-encoding by rehype. */
114732
+ const processBackslashEscapes = (text) => text.replace(/\\<([^>]*)>/g, '&lt;$1>').replace(/\\([<>|])/g, (_, c) => (c === '<' ? '&lt;' : c === '>' ? '>' : c));
114733
+ /** Block-level HTML tags that trigger CommonMark type 6 HTML blocks (condition 6). */
114734
+ const BLOCK_LEVEL_TAGS = new Set(htmlBlockNames);
114735
+ const escapeInvalidTags = (str) => str.replace(HTML_TAG_RE, (match, tag, rest) => {
114736
+ const tagName = tag.replace(/^\//, '');
114737
+ if (STANDARD_HTML_TAGS.has(tagName.toLowerCase()))
114738
+ return match;
114739
+ // Preserve PascalCase tags (custom components like <Glossary>) for the main pipeline
114740
+ if (/^[A-Z]/.test(tagName))
114741
+ return match;
114742
+ return `&lt;${tag}${rest}&gt;`;
114743
+ });
114744
+ /**
114745
+ * Process markdown within HTML string.
114746
+ * 1. Parse HTML to HAST
114747
+ * 2. Find text nodes, parse as markdown, convert to HAST
114748
+ * 3. Stringify back to HTML
114749
+ *
114750
+ * PascalCase component tags (e.g. `<Glossary>`) are temporarily replaced with
114751
+ * placeholders before HTML parsing so `rehype-parse` doesn't mangle them
114752
+ * (it treats unknown tags as void elements, stripping their children).
114753
+ */
114754
+ const processMarkdownInHtmlString = (html) => {
114755
+ const placeholders = [];
114756
+ let counter = 0;
114757
+ const safened = escapeInvalidTags(html).replace(HTML_TAG_RE, match => {
114758
+ if (!/^<\/?[A-Z]/.test(match))
114759
+ return match;
114760
+ const id = `<!--PC${(counter += 1)}-->`;
114761
+ placeholders.push([id, match]);
114762
+ return id;
114763
+ });
114764
+ const hast = htmlParser.parse(safened);
114765
+ const textToHast = (text) => {
114766
+ if (!text.trim())
114767
+ return [{ type: 'text', value: text }];
114768
+ const parsed = markdownToHtml.runSync(markdownToHtml.parse(escapeInvalidTags(text)));
114769
+ const nodes = parsed.children.flatMap(n => n.type === 'element' && n.tagName === 'p' ? n.children : [n]);
114770
+ const leading = text.match(/^\s+/)?.[0];
114771
+ const trailing = text.match(/\s+$/)?.[0];
114772
+ if (leading)
114773
+ nodes.unshift({ type: 'text', value: leading });
114774
+ if (trailing)
114775
+ nodes.push({ type: 'text', value: trailing });
114776
+ return nodes;
114777
+ };
114778
+ const processChildren = (children) => children.flatMap(child => (child.type === 'text' ? textToHast(child.value) : [child]));
114779
+ hast.children = processChildren(hast.children);
114780
+ visit(hast, 'element', (node) => {
114781
+ node.children = processChildren(node.children);
114782
+ });
114783
+ return placeholders.reduce((res, [id, original]) => res.replace(id, original), htmlStringifier.stringify(hast));
114784
+ };
114785
+ /**
114786
+ * Separate a closing block-level tag from the content that follows it.
114787
+ *
114788
+ * Each \n in the original text becomes a <br> tag to preserve spacing, then a
114789
+ * blank line (\n\n) is appended so CommonMark ends the HTML block and parses
114790
+ * the following content as markdown.
114791
+ */
114792
+ const separateBlockTagFromContent = (match, tag, inlineChar, nextLineChar) => {
114793
+ if (!BLOCK_LEVEL_TAGS.has(tag.toLowerCase()))
114794
+ return match;
114795
+ const newlineCount = (match.match(/\n/g) ?? []).length;
114796
+ const breaks = '<br>'.repeat(newlineCount);
114797
+ return `</${tag}>${breaks}\n\n${inlineChar || nextLineChar}`;
114798
+ };
114799
+ /**
114800
+ * CommonMark doesn't process markdown inside HTML blocks -
114801
+ * so `<ul><li>_text_</li></ul>` won't convert underscores to emphasis.
114802
+ * We parse first, then visit html nodes and process their text content.
114803
+ */
114554
114804
  const parseTableCell = (text) => {
114555
114805
  if (!text.trim())
114556
114806
  return [{ type: 'text', value: '' }];
114557
- const tree = contentParser.runSync(contentParser.parse(text));
114807
+ // Convert \n (and surrounding whitespace) to <br> inside HTML blocks so
114808
+ // CommonMark doesn't split them on blank lines.
114809
+ // Then strip leading whitespace to prevent indented code blocks.
114810
+ const escaped = processBackslashEscapes(text);
114811
+ const normalized = escaped
114812
+ .replace(HTML_ELEMENT_BLOCK_RE, match => match.replace(NEWLINE_WITH_WHITESPACE_RE, '<br>'))
114813
+ .replace(CLOSE_BLOCK_TAG_BOUNDARY_RE, separateBlockTagFromContent);
114814
+ const trimmedLines = normalized.split('\n').map(line => line.trimStart());
114815
+ const processed = trimmedLines.join('\n');
114816
+ const tree = contentParser.runSync(contentParser.parse(processed));
114817
+ // Process markdown inside complete HTML elements (e.g. _emphasis_ within <li>).
114818
+ // Bare tags like "<i>" are left for rehypeRaw since rehype-parse would mangle them.
114819
+ visit(tree, 'html', (node) => {
114820
+ if (COMPLETE_HTML_ELEMENT_RE.test(node.value)) {
114821
+ node.value = processMarkdownInHtmlString(node.value);
114822
+ }
114823
+ else {
114824
+ node.value = escapeInvalidTags(node.value);
114825
+ }
114826
+ });
114558
114827
  if (tree.children.length > 1) {
114559
114828
  return tree.children;
114560
114829
  }
@@ -114709,7 +114978,7 @@ function transformMagicBlock(blockType, data, rawValue, options = {}) {
114709
114978
  });
114710
114979
  }
114711
114980
  if (hasBody) {
114712
- const bodyBlocks = parseBlock(calloutJson.body || '');
114981
+ const bodyBlocks = parseBlock(preprocessBody(calloutJson.body || ''));
114713
114982
  children.push(...bodyBlocks);
114714
114983
  }
114715
114984
  const calloutElement = {
@@ -114744,7 +115013,7 @@ function transformMagicBlock(blockType, data, rawValue, options = {}) {
114744
115013
  const tokenizeCell = compatibilityMode ? textToBlock : parseTableCell;
114745
115014
  const tableChildren = Array.from({ length: rows + 1 }, (_, y) => ({
114746
115015
  children: Array.from({ length: cols }, (__, x) => ({
114747
- children: sparseData[y]?.[x] ? tokenizeCell(sparseData[y][x]) : [{ type: 'text', value: '' }],
115016
+ children: sparseData[y]?.[x] ? tokenizeCell(preprocessBody(sparseData[y][x])) : [{ type: 'text', value: '' }],
114748
115017
  type: y === 0 ? 'tableHead' : 'tableCell',
114749
115018
  })),
114750
115019
  type: 'tableRow',
@@ -114845,79 +115114,63 @@ const isBlockNode = (node) => blockTypes.includes(node.type);
114845
115114
  */
114846
115115
  const magicBlockTransformer = (options = {}) => tree => {
114847
115116
  const replacements = [];
114848
- visit(tree, 'magicBlock', (node, index, parent) => {
114849
- if (!parent || index === undefined)
114850
- return undefined;
115117
+ visitParents(tree, 'magicBlock', (node, ancestors) => {
115118
+ const parent = ancestors[ancestors.length - 1]; // direct parent of the current node
115119
+ const index = parent.children.indexOf(node);
115120
+ if (index === -1)
115121
+ return;
114851
115122
  const children = transformMagicBlock(node.blockType, node.data, node.value, options);
114852
115123
  if (!children.length) {
114853
- // Remove the node if transformation returns nothing
115124
+ // `visitParents` doesn't support [Action, Index] returns like `visit` does;
115125
+ // a bare return after splicing is sufficient since `visitParents` walks by
115126
+ // tree structure rather than index.
114854
115127
  parent.children.splice(index, 1);
114855
- return [SKIP, index];
115128
+ return;
114856
115129
  }
114857
115130
  // If parent is a paragraph and we're inserting block nodes (which must not be in paragraphs), lift them out
114858
115131
  if (parent.type === 'paragraph' && children.some(child => isBlockNode(child))) {
114859
115132
  const blockNodes = [];
114860
115133
  const inlineNodes = [];
114861
- // Separate block and inline nodes
114862
115134
  children.forEach(child => {
114863
- if (isBlockNode(child)) {
114864
- blockNodes.push(child);
114865
- }
114866
- else {
114867
- inlineNodes.push(child);
114868
- }
115135
+ (isBlockNode(child) ? blockNodes : inlineNodes).push(child);
114869
115136
  });
114870
- const before = parent.children.slice(0, index);
114871
- const after = parent.children.slice(index + 1);
114872
115137
  replacements.push({
115138
+ container: ancestors[ancestors.length - 2] || tree, // grandparent of the current node
114873
115139
  parent,
114874
115140
  blockNodes,
114875
115141
  inlineNodes,
114876
- before,
114877
- after,
115142
+ before: parent.children.slice(0, index),
115143
+ after: parent.children.slice(index + 1),
114878
115144
  });
114879
115145
  }
114880
115146
  else {
114881
- // Normal case: just replace the inlineCode with the children
114882
115147
  parent.children.splice(index, 1, ...children);
114883
115148
  }
114884
- return undefined;
114885
115149
  });
114886
115150
  // Second pass: apply replacements that require lifting block nodes out of paragraphs
114887
115151
  // Process in reverse order to maintain correct indices
114888
115152
  for (let i = replacements.length - 1; i >= 0; i -= 1) {
114889
- const { after, before, blockNodes, inlineNodes, parent } = replacements[i];
114890
- // Find the paragraph's position in the root
114891
- const rootChildren = tree.children;
114892
- const paraIndex = rootChildren.findIndex(child => child === parent);
115153
+ const { after, before, blockNodes, container, inlineNodes, parent } = replacements[i];
115154
+ const containerChildren = container.children;
115155
+ const paraIndex = containerChildren.indexOf(parent);
114893
115156
  if (paraIndex === -1) {
114894
- // Paragraph not found in root - fall back to normal replacement
114895
- // This shouldn't happen normally, but handle it gracefully
114896
- // Reconstruct the original index from before.length
114897
- const originalIndex = before.length;
114898
- parent.children.splice(originalIndex, 1, ...blockNodes, ...inlineNodes);
115157
+ parent.children.splice(before.length, 1, ...blockNodes, ...inlineNodes);
114899
115158
  // eslint-disable-next-line no-continue
114900
115159
  continue;
114901
115160
  }
114902
- // Update or remove the paragraph
114903
115161
  if (inlineNodes.length > 0) {
114904
- // Keep paragraph with inline nodes
114905
115162
  parent.children = [...before, ...inlineNodes, ...after];
114906
- // Insert block nodes after the paragraph
114907
115163
  if (blockNodes.length > 0) {
114908
- rootChildren.splice(paraIndex + 1, 0, ...blockNodes);
115164
+ containerChildren.splice(paraIndex + 1, 0, ...blockNodes);
114909
115165
  }
114910
115166
  }
114911
115167
  else if (before.length === 0 && after.length === 0) {
114912
- // Remove empty paragraph and replace with block nodes
114913
- rootChildren.splice(paraIndex, 1, ...blockNodes);
115168
+ containerChildren.splice(paraIndex, 1, ...blockNodes);
114914
115169
  }
114915
115170
  else {
114916
- // Keep paragraph with remaining content
114917
115171
  parent.children = [...before, ...after];
114918
- // Insert block nodes after the paragraph
114919
115172
  if (blockNodes.length > 0) {
114920
- rootChildren.splice(paraIndex + 1, 0, ...blockNodes);
115173
+ containerChildren.splice(paraIndex + 1, 0, ...blockNodes);
114921
115174
  }
114922
115175
  }
114923
115176
  }
@@ -115752,6 +116005,45 @@ const restoreBooleanProperties = () => tree => {
115752
116005
  };
115753
116006
 
115754
116007
 
116008
+ ;// ./processor/transform/mdxish/terminate-html-flow-blocks.ts
116009
+
116010
+ const STANDALONE_HTML_LINE_REGEX = /^(<[a-z][^<>]*>|<\/[a-z][^<>]*>)+\s*$/;
116011
+ const HTML_LINE_WITH_CONTENT_REGEX = /^<[a-z][^<>]*>.*<\/[a-z][^<>]*>(?:[^<]*)$/;
116012
+ /**
116013
+ * Preprocessor to terminate HTML flow blocks.
116014
+ *
116015
+ * In CommonMark, HTML blocks (types 6 and 7) only terminate on a blank line.
116016
+ * Without one, any content on the next line is consumed as part of the HTML block
116017
+ * and never parsed as its own construct. For example, a `[block:callout]` immediately
116018
+ * following `<div><p></p></div>` gets swallowed into the HTML flow token.
116019
+ *
116020
+ * @link https://spec.commonmark.org/0.29/#html-blocks
116021
+ *
116022
+ * This preprocessor inserts a blank line after standalone HTML lines when the
116023
+ * next line is non-blank, ensuring micromark's HTML flow tokenizer terminates
116024
+ * and subsequent content is parsed independently.
116025
+ *
116026
+ * Only targets non-indented lines with lowercase tag names. Uppercase tags
116027
+ * (e.g., `<Table>`, `<MyComponent>`) are JSX custom components and don't
116028
+ * trigger CommonMark HTML blocks, so they are left untouched.
116029
+ *
116030
+ * Lines inside fenced code blocks are skipped entirely.
116031
+ */
116032
+ function terminateHtmlFlowBlocks(content) {
116033
+ const { protectedContent, protectedCode } = protectCodeBlocks(content);
116034
+ const lines = protectedContent.split('\n');
116035
+ const result = [];
116036
+ for (let i = 0; i < lines.length; i += 1) {
116037
+ result.push(lines[i]);
116038
+ if (i < lines.length - 1 &&
116039
+ (STANDALONE_HTML_LINE_REGEX.test(lines[i]) || HTML_LINE_WITH_CONTENT_REGEX.test(lines[i])) &&
116040
+ lines[i + 1].trim().length > 0) {
116041
+ result.push('');
116042
+ }
116043
+ }
116044
+ return restoreCodeBlocks(result.join('\n'), protectedCode);
116045
+ }
116046
+
115755
116047
  ;// ./processor/transform/mdxish/variables-text.ts
115756
116048
 
115757
116049
 
@@ -117054,10 +117346,29 @@ function loadComponents() {
117054
117346
 
117055
117347
 
117056
117348
 
117349
+
117350
+
117057
117351
 
117058
117352
 
117059
117353
 
117060
117354
  const defaultTransformers = [callouts, code_tabs, gemoji_, transform_embeds];
117355
+ /**
117356
+ * Preprocessing pipeline: applies string-level transformations to work around
117357
+ * CommonMark/remark limitations and reach parity with legacy (rdmd) rendering.
117358
+ *
117359
+ * Runs a series of string-level transformations before micromark/remark parsing:
117360
+ * 1. Normalize malformed table separator syntax (e.g., `|: ---` → `| :---`)
117361
+ * 2. Terminate HTML flow blocks so subsequent content isn't swallowed
117362
+ * 3. Evaluate JSX expressions in attributes (unless safeMode)
117363
+ * 4. Replace snake_case component names with parser-safe placeholders
117364
+ */
117365
+ function preprocessContent(content, opts) {
117366
+ const { safeMode, jsxContext, knownComponents } = opts;
117367
+ let result = normalizeTableSeparator(content);
117368
+ result = terminateHtmlFlowBlocks(result);
117369
+ result = safeMode ? result : preprocessJSXExpressions(result, jsxContext);
117370
+ return processSnakeCaseComponent(result, { knownComponents });
117371
+ }
117061
117372
  function mdxishAstProcessor(mdContent, opts = {}) {
117062
117373
  const { components: userComponents = {}, jsxContext = {}, newEditorTypes = false, safeMode = false, useTailwind, } = opts;
117063
117374
  const components = {
@@ -117066,15 +117377,11 @@ function mdxishAstProcessor(mdContent, opts = {}) {
117066
117377
  };
117067
117378
  // Build set of known component names for snake_case filtering
117068
117379
  const knownComponents = new Set(Object.keys(components));
117069
- // Preprocessing pipeline: Transform content to be parser-ready
117070
- // Step 1: Normalize malformed table separator syntax (e.g., `|: ---` → `| :---`)
117071
- const contentAfterTableNormalization = normalizeTableSeparator(mdContent);
117072
- // Step 2: Evaluate JSX expressions in attributes
117073
- const contentAfterJSXEvaluation = safeMode
117074
- ? contentAfterTableNormalization
117075
- : preprocessJSXExpressions(contentAfterTableNormalization, jsxContext);
117076
- // Step 3: Replace snake_case component names with parser-safe placeholders
117077
- const { content: parserReadyContent, mapping: snakeCaseMapping } = processSnakeCaseComponent(contentAfterJSXEvaluation, { knownComponents });
117380
+ const { content: parserReadyContent, mapping: snakeCaseMapping } = preprocessContent(mdContent, {
117381
+ safeMode,
117382
+ jsxContext,
117383
+ knownComponents,
117384
+ });
117078
117385
  // Create string map for tailwind transformer
117079
117386
  const tempComponentsMap = Object.entries(components).reduce((acc, [key, value]) => {
117080
117387
  acc[key] = String(value);
@@ -117142,6 +117449,7 @@ function mdxish(mdContent, opts = {}) {
117142
117449
  };
117143
117450
  const { processor, parserReadyContent } = mdxishAstProcessor(mdContent, opts);
117144
117451
  processor
117452
+ .use(remarkBreaks)
117145
117453
  .use(remarkRehype, { allowDangerousHtml: true, handlers: mdxComponentHandlers })
117146
117454
  .use(preserveBooleanProperties) // RehypeRaw converts boolean properties to empty strings
117147
117455
  .use(rehypeRaw, { passThrough: ['html-block'] })
@@ -117654,18 +117962,19 @@ const mdxishTags_tags = (doc) => {
117654
117962
  * Removes Markdown and MDX comments.
117655
117963
  */
117656
117964
  async function stripComments(doc, { mdx, mdxish } = {}) {
117657
- const processor = unified()
117658
- .data('micromarkExtensions', [magicBlock()])
117659
- .data('fromMarkdownExtensions', [magicBlockFromMarkdown()])
117660
- .data('toMarkdownExtensions', [magicBlockToMarkdown()]);
117965
+ const micromarkExtensions = [magicBlock()];
117966
+ const fromMarkdownExtensions = [magicBlockFromMarkdown()];
117661
117967
  // we still require these two extensions because:
117662
- // 1. we can rely on remarkMdx to parse MDXish
117968
+ // 1. we cant rely on remarkMdx to parse MDXish
117663
117969
  // 2. we need to parse JSX comments into mdxTextExpression nodes so that the transformers can pick them up
117664
117970
  if (mdxish) {
117665
- processor
117666
- .data('micromarkExtensions', [mdxExpression({ allowEmpty: true })])
117667
- .data('fromMarkdownExtensions', [mdxExpressionFromMarkdown()]);
117971
+ micromarkExtensions.push(mdxExpression({ allowEmpty: true }));
117972
+ fromMarkdownExtensions.push(mdxExpressionFromMarkdown());
117668
117973
  }
117974
+ const processor = unified()
117975
+ .data('micromarkExtensions', micromarkExtensions)
117976
+ .data('fromMarkdownExtensions', fromMarkdownExtensions)
117977
+ .data('toMarkdownExtensions', [magicBlockToMarkdown()]);
117669
117978
  processor
117670
117979
  .use(remarkParse)
117671
117980
  .use(normalize_malformed_md_syntax)
@@ -117722,6 +118031,7 @@ async function stripComments(doc, { mdx, mdxish } = {}) {
117722
118031
 
117723
118032
 
117724
118033
 
118034
+
117725
118035
  ;// ./index.tsx
117726
118036
 
117727
118037