@readme/markdown 14.1.4 → 14.2.1

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
@@ -53325,9 +53325,16 @@ function formatHtmlForMdxish(html) {
53325
53325
  }
53326
53326
  // Removes the leading/trailing newlines
53327
53327
  let cleaned = processed.replace(/^\s*\n|\n\s*$/g, '');
53328
- // Convert literal \n sequences to actual newlines BEFORE processing backticks
53329
- // This prevents the backtick unescaping regex from incorrectly matching \n sequences
53330
- cleaned = cleaned.replace(/\\n/g, '\n');
53328
+ // Convert literal \n sequences to actual newlines only inside <pre> and <code>.
53329
+ // Because <pre> needs to respect the newline visual and
53330
+ // escape characters should be processed in the <code> tag.
53331
+ //
53332
+ // We don't want to unescape every \n because it might break the HTML & cause errors
53333
+ // Example: <script>console.log("\n");</script>
53334
+ // Would get turned into: <script>console.log("
53335
+ // ");</script>
53336
+ // which is invalid javascript and will cause error
53337
+ cleaned = cleaned.replace(/(<(pre|code)\b[^>]*>)([\s\S]*?)(<\/\2>)/gi, (_m, open, _tag, inner, close) => open + inner.replace(/\\n/g, '\n') + close);
53331
53338
  // Unescape backticks: \` -> ` (users escape backticks in template literals)
53332
53339
  // Handle both cases: \` (adjacent) and \ followed by ` (split by markdown parser)
53333
53340
  cleaned = cleaned.replace(/\\`/g, '`');
@@ -71223,6 +71230,87 @@ function gemojiFromMarkdown() {
71223
71230
  };
71224
71231
  }
71225
71232
 
71233
+ ;// ./lib/mdast-util/legacy-variable/index.ts
71234
+
71235
+ const contextMap = new WeakMap();
71236
+ function findlegacyVariableToken() {
71237
+ // tokenStack is micromark's current open token ancestry; find the nearest legacyVariable token.
71238
+ const events = this.tokenStack;
71239
+ for (let i = events.length - 1; i >= 0; i -= 1) {
71240
+ const token = events[i][0];
71241
+ if (token.type === 'legacyVariable')
71242
+ return token;
71243
+ }
71244
+ return undefined;
71245
+ }
71246
+ function enterlegacyVariable(token) {
71247
+ contextMap.set(token, { value: '' });
71248
+ }
71249
+ function exitlegacyVariableValue(token) {
71250
+ const variableToken = findlegacyVariableToken.call(this);
71251
+ if (!variableToken)
71252
+ return;
71253
+ const ctx = contextMap.get(variableToken);
71254
+ // Build up the variable characters
71255
+ if (ctx)
71256
+ ctx.value += this.sliceSerialize(token);
71257
+ }
71258
+ function exitlegacyVariable(token) {
71259
+ const ctx = contextMap.get(token);
71260
+ const serialized = this.sliceSerialize(token);
71261
+ const variableName = serialized.startsWith('<<') && serialized.endsWith('>>')
71262
+ ? serialized.slice(2, -2)
71263
+ : ctx?.value ?? '';
71264
+ const nodePosition = {
71265
+ start: {
71266
+ offset: token.start.offset,
71267
+ line: token.start.line,
71268
+ column: token.start.column,
71269
+ },
71270
+ end: {
71271
+ offset: token.end.offset,
71272
+ line: token.end.line,
71273
+ column: token.end.column,
71274
+ },
71275
+ };
71276
+ if (variableName.startsWith('glossary:')) {
71277
+ const term = variableName.slice('glossary:'.length).trim();
71278
+ this.enter({
71279
+ type: NodeTypes.glossary,
71280
+ data: {
71281
+ hName: 'Glossary',
71282
+ hProperties: { term },
71283
+ },
71284
+ children: [{ type: 'text', value: term }],
71285
+ position: nodePosition,
71286
+ }, token);
71287
+ this.exit(token);
71288
+ contextMap.delete(token);
71289
+ return;
71290
+ }
71291
+ this.enter({
71292
+ type: NodeTypes.variable,
71293
+ data: {
71294
+ hName: 'Variable',
71295
+ hProperties: { name: variableName.trim(), isLegacy: true },
71296
+ },
71297
+ value: `<<${variableName}>>`,
71298
+ }, token);
71299
+ this.exit(token);
71300
+ contextMap.delete(token);
71301
+ }
71302
+ function legacyVariableFromMarkdown() {
71303
+ return {
71304
+ enter: {
71305
+ legacyVariable: enterlegacyVariable,
71306
+ },
71307
+ exit: {
71308
+ legacyVariableValue: exitlegacyVariableValue,
71309
+ legacyVariable: exitlegacyVariable,
71310
+ },
71311
+ };
71312
+ }
71313
+
71226
71314
  ;// ./node_modules/micromark-util-symbol/lib/codes.js
71227
71315
  /**
71228
71316
  * Character codes.
@@ -71476,6 +71564,74 @@ function syntax_gemoji() {
71476
71564
  */
71477
71565
 
71478
71566
 
71567
+ ;// ./lib/micromark/legacy-variable/syntax.ts
71568
+
71569
+
71570
+ function isAllowedValueChar(code) {
71571
+ return (code !== null &&
71572
+ code !== codes.lessThan &&
71573
+ code !== codes.greaterThan &&
71574
+ !markdownLineEnding(code));
71575
+ }
71576
+ const legacyVariableConstruct = {
71577
+ name: 'legacyVariable',
71578
+ tokenize: syntax_tokenize,
71579
+ };
71580
+ function syntax_tokenize(effects, ok, nok) {
71581
+ let hasValue = false;
71582
+ const start = (code) => {
71583
+ if (code !== codes.lessThan)
71584
+ return nok(code);
71585
+ effects.enter('legacyVariable');
71586
+ effects.enter('legacyVariableMarkerStart');
71587
+ effects.consume(code); // <
71588
+ return open2;
71589
+ };
71590
+ const open2 = (code) => {
71591
+ if (code !== codes.lessThan)
71592
+ return nok(code);
71593
+ effects.consume(code); // <<
71594
+ effects.exit('legacyVariableMarkerStart');
71595
+ effects.enter('legacyVariableValue');
71596
+ return value;
71597
+ };
71598
+ const value = (code) => {
71599
+ if (code === codes.greaterThan) {
71600
+ if (!hasValue)
71601
+ return nok(code);
71602
+ effects.exit('legacyVariableValue');
71603
+ effects.enter('legacyVariableMarkerEnd');
71604
+ effects.consume(code); // >
71605
+ return close2;
71606
+ }
71607
+ if (!isAllowedValueChar(code))
71608
+ return nok(code);
71609
+ hasValue = true;
71610
+ effects.consume(code);
71611
+ return value;
71612
+ };
71613
+ const close2 = (code) => {
71614
+ if (code !== codes.greaterThan)
71615
+ return nok(code);
71616
+ effects.consume(code); // >>
71617
+ effects.exit('legacyVariableMarkerEnd');
71618
+ effects.exit('legacyVariable');
71619
+ return ok;
71620
+ };
71621
+ return start;
71622
+ }
71623
+ function legacyVariable() {
71624
+ return {
71625
+ text: { [codes.lessThan]: legacyVariableConstruct },
71626
+ };
71627
+ }
71628
+
71629
+ ;// ./lib/micromark/legacy-variable/index.ts
71630
+ /**
71631
+ * Micromark extension for <<variable>> / <<glossary:term>> inline syntax.
71632
+ */
71633
+
71634
+
71479
71635
  ;// ./processor/transform/mdxish/normalize-malformed-md-syntax.ts
71480
71636
 
71481
71637
  // Marker patterns for multi-node emphasis detection
@@ -71854,20 +72010,59 @@ const unwrapSoleParagraph = (children) => {
71854
72010
 
71855
72011
 
71856
72012
 
72013
+
72014
+
72015
+
71857
72016
  const isTableCell = (node) => isMDXElement(node) && ['th', 'td'].includes(node.name);
71858
72017
  const tableTypes = {
71859
72018
  tr: 'tableRow',
71860
72019
  th: 'tableCell',
71861
72020
  td: 'tableCell',
71862
72021
  };
71863
- const tableNodeProcessor = unified()
71864
- .data('micromarkExtensions', [syntax_gemoji()])
71865
- .data('fromMarkdownExtensions', [gemojiFromMarkdown()])
72022
+ // `mdxjs` + `mdxFromMarkdown` is what `remarkMdx` registers internally; we
72023
+ // register them manually so we control ordering against our other tokenizers.
72024
+ // The fallback omits these so blank-line-separated markdown inside cells still
72025
+ // parses when mdxjs throws on malformed JSX.
72026
+ const buildTableNodeProcessor = (withMdx) => unified()
72027
+ .data('micromarkExtensions', [...(withMdx ? [mdxjs()] : []), syntax_gemoji(), legacyVariable()])
72028
+ .data('fromMarkdownExtensions', [
72029
+ ...(withMdx ? [mdxFromMarkdown()] : []),
72030
+ gemojiFromMarkdown(),
72031
+ legacyVariableFromMarkdown(),
72032
+ ])
71866
72033
  .use(remarkParse)
71867
- .use(remarkMdx)
71868
72034
  .use(normalize_malformed_md_syntax)
71869
72035
  .use([[callouts, { isMdxish: true }], code_tabs])
71870
72036
  .use(remarkGfm);
72037
+ const tableNodeProcessor = buildTableNodeProcessor(true);
72038
+ const fallbackTableNodeProcessor = buildTableNodeProcessor(false);
72039
+ // Since we use a subparser in `tableNodeProcessor` to parse `node.value`,
72040
+ // positions are relative to that substring. Shifting them by the base
72041
+ // offset and line number makes them valid in the outer source coordinate space.
72042
+ // Otherwise, consumers who directly slice based on position would read and grab the
72043
+ // wrong content
72044
+ const parseTableNode = (processor, node) => {
72045
+ let parsed;
72046
+ try {
72047
+ parsed = processor.runSync(processor.parse(node.value));
72048
+ }
72049
+ catch {
72050
+ return undefined;
72051
+ }
72052
+ const baseOffset = node.position?.start?.offset ?? 0;
72053
+ const baseLine = (node.position?.start?.line ?? 1) - 1;
72054
+ visit(parsed, child => {
72055
+ if (child.position?.start) {
72056
+ child.position.start.offset = (child.position.start.offset ?? 0) + baseOffset;
72057
+ child.position.start.line += baseLine;
72058
+ }
72059
+ if (child.position?.end) {
72060
+ child.position.end.offset = (child.position.end.offset ?? 0) + baseOffset;
72061
+ child.position.end.line += baseLine;
72062
+ }
72063
+ });
72064
+ return parsed;
72065
+ };
71871
72066
  /**
71872
72067
  * Check if children are only text nodes that might contain markdown
71873
72068
  */
@@ -71970,27 +72165,54 @@ const processTableNode = (node, index, parent, documentPosition) => {
71970
72165
  }
71971
72166
  // All cells are phrasing-only — convert to markdown table
71972
72167
  const children = [];
72168
+ // Collect `<td>`/`<th>` cells under any container (a `<tr>`, or a section
72169
+ // when cells are bare).
72170
+ const collectCells = (container) => {
72171
+ const cells = [];
72172
+ visit(container, isTableCell, ({ name, children: cellChildren, position: cellPosition }) => {
72173
+ cells.push({
72174
+ type: tableTypes[name],
72175
+ children: unwrapSoleParagraph(cellChildren),
72176
+ position: cellPosition,
72177
+ });
72178
+ });
72179
+ return cells;
72180
+ };
72181
+ // remarkMdx wraps inline `<tr>`s in a paragraph; unwrap one level so the
72182
+ // hasRow check below sees them.
72183
+ const flattenSectionChildren = (nodes) => nodes.flatMap(n => n.type === 'paragraph' && 'children' in n && Array.isArray(n.children) ? n.children : [n]);
71973
72184
  visit(node, isMDXElement, (child) => {
71974
- if (child.name === 'thead' || child.name === 'tbody') {
72185
+ if (child.name !== 'thead' && child.name !== 'tbody')
72186
+ return;
72187
+ const sectionChildren = flattenSectionChildren(child.children);
72188
+ const hasRow = sectionChildren.some(c => isMDXElement(c) && c.name === 'tr');
72189
+ if (hasRow) {
71975
72190
  visit(child, isMDXElement, (row) => {
71976
72191
  if (row.name !== 'tr')
71977
72192
  return;
71978
- const rowChildren = [];
71979
- visit(row, isTableCell, ({ name, children: cellChildren, position: cellPosition }) => {
71980
- const parsedChildren = unwrapSoleParagraph(cellChildren);
71981
- rowChildren.push({
71982
- type: tableTypes[name],
71983
- children: parsedChildren,
71984
- position: cellPosition,
71985
- });
71986
- });
71987
72193
  children.push({
71988
72194
  type: 'tableRow',
71989
- children: rowChildren,
72195
+ children: collectCells(row),
71990
72196
  position: row.position,
71991
72197
  });
71992
72198
  });
71993
72199
  }
72200
+ else {
72201
+ // No `<tr>`, chunk bare cells into rows using the prior row's column
72202
+ // count (e.g. from `<thead>`), so 4 bare `<td>`s under a 2-col header
72203
+ // become 2 rows of 2.
72204
+ const cells = collectCells(child);
72205
+ if (cells.length === 0)
72206
+ return;
72207
+ const cols = children[0]?.children?.length || cells.length;
72208
+ for (let i = 0; i < cells.length; i += cols) {
72209
+ children.push({
72210
+ type: 'tableRow',
72211
+ children: cells.slice(i, i + cols),
72212
+ position: child.position,
72213
+ });
72214
+ }
72215
+ }
71994
72216
  });
71995
72217
  const firstRow = children[0];
71996
72218
  const columnCount = firstRow?.children?.length || 0;
@@ -72023,35 +72245,22 @@ const mdxishTables = () => tree => {
72023
72245
  return;
72024
72246
  if (!node.value.startsWith('<Table') && !node.value.startsWith('<table'))
72025
72247
  return;
72026
- try {
72027
- const parsed = tableNodeProcessor.runSync(tableNodeProcessor.parse(node.value));
72028
- // since we use a subparser in `tableNodeProcessor` to parse `node.value`,
72029
- // positions are relative to that substring. shifting them by the base
72030
- // offset and line number makes them valid in the outer source coordinate space.
72031
- // otherwise, consumers who directly slice based on position would read and grab the
72032
- // wrong content
72033
- const baseOffset = node.position?.start?.offset ?? 0;
72034
- const baseLine = (node.position?.start?.line ?? 1) - 1;
72035
- visit(parsed, child => {
72036
- if (child.position?.start) {
72037
- child.position.start.offset = (child.position.start.offset ?? 0) + baseOffset;
72038
- child.position.start.line += baseLine;
72039
- }
72040
- if (child.position?.end) {
72041
- child.position.end.offset = (child.position.end.offset ?? 0) + baseOffset;
72042
- child.position.end.line += baseLine;
72043
- }
72044
- });
72248
+ const parsed = parseTableNode(tableNodeProcessor, node);
72249
+ if (parsed) {
72045
72250
  visit(parsed, isMDXElement, (tableNode) => {
72046
72251
  if (tableNode.name !== 'Table' && tableNode.name !== 'table')
72047
72252
  return undefined;
72048
72253
  processTableNode(tableNode, index, parent, node.position);
72049
72254
  return EXIT;
72050
72255
  });
72256
+ return;
72051
72257
  }
72052
- catch {
72053
- // If parsing fails, leave the node as-is
72054
- }
72258
+ // MDX parse failed (usually unbalanced JSX). Re-parse without MDX so
72259
+ // markdown between `<td>` and `</td>` still renders; tags stay as raw HTML.
72260
+ const fallback = parseTableNode(fallbackTableNodeProcessor, node);
72261
+ if (!fallback || fallback.children.length <= 1)
72262
+ return;
72263
+ parent.children.splice(index, 1, ...fallback.children);
72055
72264
  });
72056
72265
  return tree;
72057
72266
  };
@@ -84802,6 +85011,63 @@ function rehypeSanitize(options) {
84802
85011
  }
84803
85012
  }
84804
85013
 
85014
+ ;// ./node_modules/mdast-util-newline-to-break/lib/index.js
85015
+ /**
85016
+ * @typedef {import('mdast').Nodes} Nodes
85017
+ * @typedef {import('mdast-util-find-and-replace').ReplaceFunction} ReplaceFunction
85018
+ */
85019
+
85020
+
85021
+
85022
+ /**
85023
+ * Turn normal line endings into hard breaks.
85024
+ *
85025
+ * @param {Nodes} tree
85026
+ * Tree to change.
85027
+ * @returns {undefined}
85028
+ * Nothing.
85029
+ */
85030
+ function newlineToBreak(tree) {
85031
+ findAndReplace(tree, [/\r?\n|\r/g, lib_replace])
85032
+ }
85033
+
85034
+ /**
85035
+ * Replace line endings.
85036
+ *
85037
+ * @type {ReplaceFunction}
85038
+ */
85039
+ function lib_replace() {
85040
+ return {type: 'break'}
85041
+ }
85042
+
85043
+ ;// ./node_modules/remark-breaks/lib/index.js
85044
+ /**
85045
+ * @typedef {import('mdast').Root} Root
85046
+ */
85047
+
85048
+
85049
+
85050
+ /**
85051
+ * Support hard breaks without needing spaces or escapes (turns enters into
85052
+ * `<br>`s).
85053
+ *
85054
+ * @returns
85055
+ * Transform.
85056
+ */
85057
+ function remarkBreaks() {
85058
+ /**
85059
+ * Transform.
85060
+ *
85061
+ * @param {Root} tree
85062
+ * Tree.
85063
+ * @returns {undefined}
85064
+ * Nothing.
85065
+ */
85066
+ return function (tree) {
85067
+ newlineToBreak(tree)
85068
+ }
85069
+ }
85070
+
84805
85071
  ;// ./errors/mdx-syntax-error.ts
84806
85072
  class MdxSyntaxError extends SyntaxError {
84807
85073
  original = null;
@@ -87607,6 +87873,7 @@ const tocHastToMdx = (toc, components, variables) => {
87607
87873
 
87608
87874
 
87609
87875
 
87876
+
87610
87877
  const sanitizeSchema = cjs_default()(defaultSchema, {
87611
87878
  attributes: {
87612
87879
  a: ['target'],
@@ -87615,12 +87882,13 @@ const sanitizeSchema = cjs_default()(defaultSchema, {
87615
87882
  href: ['doc', 'ref', 'blog', 'changelog', 'page'],
87616
87883
  },
87617
87884
  });
87618
- const compile_compile = (text, { components = {}, missingComponents, copyButtons, useTailwind, ...opts } = {}) => {
87885
+ const compile_compile = (text, { components = {}, missingComponents, copyButtons, useTailwind, hardBreaks, ...opts } = {}) => {
87619
87886
  // Destructure at runtime to avoid circular dependency issues
87620
87887
  const { codeTabsTransformer, ...transforms } = defaultTransforms;
87621
87888
  const remarkPlugins = [
87622
87889
  remarkFrontmatter,
87623
87890
  remarkGfm,
87891
+ ...(hardBreaks ? [remarkBreaks] : []),
87624
87892
  ...Object.values(transforms),
87625
87893
  [codeTabsTransformer, { copyButtons }],
87626
87894
  [
@@ -94026,63 +94294,6 @@ function rehypeStringify(options) {
94026
94294
  }
94027
94295
  }
94028
94296
 
94029
- ;// ./node_modules/mdast-util-newline-to-break/lib/index.js
94030
- /**
94031
- * @typedef {import('mdast').Nodes} Nodes
94032
- * @typedef {import('mdast-util-find-and-replace').ReplaceFunction} ReplaceFunction
94033
- */
94034
-
94035
-
94036
-
94037
- /**
94038
- * Turn normal line endings into hard breaks.
94039
- *
94040
- * @param {Nodes} tree
94041
- * Tree to change.
94042
- * @returns {undefined}
94043
- * Nothing.
94044
- */
94045
- function newlineToBreak(tree) {
94046
- findAndReplace(tree, [/\r?\n|\r/g, lib_replace])
94047
- }
94048
-
94049
- /**
94050
- * Replace line endings.
94051
- *
94052
- * @type {ReplaceFunction}
94053
- */
94054
- function lib_replace() {
94055
- return {type: 'break'}
94056
- }
94057
-
94058
- ;// ./node_modules/remark-breaks/lib/index.js
94059
- /**
94060
- * @typedef {import('mdast').Root} Root
94061
- */
94062
-
94063
-
94064
-
94065
- /**
94066
- * Support hard breaks without needing spaces or escapes (turns enters into
94067
- * `<br>`s).
94068
- *
94069
- * @returns
94070
- * Transform.
94071
- */
94072
- function remarkBreaks() {
94073
- /**
94074
- * Transform.
94075
- *
94076
- * @param {Root} tree
94077
- * Tree.
94078
- * @returns {undefined}
94079
- * Nothing.
94080
- */
94081
- return function (tree) {
94082
- newlineToBreak(tree)
94083
- }
94084
- }
94085
-
94086
94297
  ;// ./processor/plugin/flatten-table-cell-paragraphs.ts
94087
94298
 
94088
94299
  /** List elements that cause margin issues when adjacent to paragraphs */
@@ -94862,87 +95073,6 @@ function emptyTaskListItemFromMarkdown() {
94862
95073
  };
94863
95074
  }
94864
95075
 
94865
- ;// ./lib/mdast-util/legacy-variable/index.ts
94866
-
94867
- const contextMap = new WeakMap();
94868
- function findlegacyVariableToken() {
94869
- // tokenStack is micromark's current open token ancestry; find the nearest legacyVariable token.
94870
- const events = this.tokenStack;
94871
- for (let i = events.length - 1; i >= 0; i -= 1) {
94872
- const token = events[i][0];
94873
- if (token.type === 'legacyVariable')
94874
- return token;
94875
- }
94876
- return undefined;
94877
- }
94878
- function enterlegacyVariable(token) {
94879
- contextMap.set(token, { value: '' });
94880
- }
94881
- function exitlegacyVariableValue(token) {
94882
- const variableToken = findlegacyVariableToken.call(this);
94883
- if (!variableToken)
94884
- return;
94885
- const ctx = contextMap.get(variableToken);
94886
- // Build up the variable characters
94887
- if (ctx)
94888
- ctx.value += this.sliceSerialize(token);
94889
- }
94890
- function exitlegacyVariable(token) {
94891
- const ctx = contextMap.get(token);
94892
- const serialized = this.sliceSerialize(token);
94893
- const variableName = serialized.startsWith('<<') && serialized.endsWith('>>')
94894
- ? serialized.slice(2, -2)
94895
- : ctx?.value ?? '';
94896
- const nodePosition = {
94897
- start: {
94898
- offset: token.start.offset,
94899
- line: token.start.line,
94900
- column: token.start.column,
94901
- },
94902
- end: {
94903
- offset: token.end.offset,
94904
- line: token.end.line,
94905
- column: token.end.column,
94906
- },
94907
- };
94908
- if (variableName.startsWith('glossary:')) {
94909
- const term = variableName.slice('glossary:'.length).trim();
94910
- this.enter({
94911
- type: NodeTypes.glossary,
94912
- data: {
94913
- hName: 'Glossary',
94914
- hProperties: { term },
94915
- },
94916
- children: [{ type: 'text', value: term }],
94917
- position: nodePosition,
94918
- }, token);
94919
- this.exit(token);
94920
- contextMap.delete(token);
94921
- return;
94922
- }
94923
- this.enter({
94924
- type: NodeTypes.variable,
94925
- data: {
94926
- hName: 'Variable',
94927
- hProperties: { name: variableName.trim(), isLegacy: true },
94928
- },
94929
- value: `<<${variableName}>>`,
94930
- }, token);
94931
- this.exit(token);
94932
- contextMap.delete(token);
94933
- }
94934
- function legacyVariableFromMarkdown() {
94935
- return {
94936
- enter: {
94937
- legacyVariable: enterlegacyVariable,
94938
- },
94939
- exit: {
94940
- legacyVariableValue: exitlegacyVariableValue,
94941
- legacyVariable: exitlegacyVariable,
94942
- },
94943
- };
94944
- }
94945
-
94946
95076
  ;// ./lib/mdast-util/magic-block/index.ts
94947
95077
  const magic_block_contextMap = new WeakMap();
94948
95078
  /**
@@ -95132,74 +95262,6 @@ function mdxComponentFromMarkdown() {
95132
95262
  };
95133
95263
  }
95134
95264
 
95135
- ;// ./lib/micromark/legacy-variable/syntax.ts
95136
-
95137
-
95138
- function isAllowedValueChar(code) {
95139
- return (code !== null &&
95140
- code !== codes.lessThan &&
95141
- code !== codes.greaterThan &&
95142
- !markdownLineEnding(code));
95143
- }
95144
- const legacyVariableConstruct = {
95145
- name: 'legacyVariable',
95146
- tokenize: syntax_tokenize,
95147
- };
95148
- function syntax_tokenize(effects, ok, nok) {
95149
- let hasValue = false;
95150
- const start = (code) => {
95151
- if (code !== codes.lessThan)
95152
- return nok(code);
95153
- effects.enter('legacyVariable');
95154
- effects.enter('legacyVariableMarkerStart');
95155
- effects.consume(code); // <
95156
- return open2;
95157
- };
95158
- const open2 = (code) => {
95159
- if (code !== codes.lessThan)
95160
- return nok(code);
95161
- effects.consume(code); // <<
95162
- effects.exit('legacyVariableMarkerStart');
95163
- effects.enter('legacyVariableValue');
95164
- return value;
95165
- };
95166
- const value = (code) => {
95167
- if (code === codes.greaterThan) {
95168
- if (!hasValue)
95169
- return nok(code);
95170
- effects.exit('legacyVariableValue');
95171
- effects.enter('legacyVariableMarkerEnd');
95172
- effects.consume(code); // >
95173
- return close2;
95174
- }
95175
- if (!isAllowedValueChar(code))
95176
- return nok(code);
95177
- hasValue = true;
95178
- effects.consume(code);
95179
- return value;
95180
- };
95181
- const close2 = (code) => {
95182
- if (code !== codes.greaterThan)
95183
- return nok(code);
95184
- effects.consume(code); // >>
95185
- effects.exit('legacyVariableMarkerEnd');
95186
- effects.exit('legacyVariable');
95187
- return ok;
95188
- };
95189
- return start;
95190
- }
95191
- function legacyVariable() {
95192
- return {
95193
- text: { [codes.lessThan]: legacyVariableConstruct },
95194
- };
95195
- }
95196
-
95197
- ;// ./lib/micromark/legacy-variable/index.ts
95198
- /**
95199
- * Micromark extension for <<variable>> / <<glossary:term>> inline syntax.
95200
- */
95201
-
95202
-
95203
95265
  ;// ./lib/micromark/magic-block/syntax.ts
95204
95266
 
95205
95267
 
@@ -100518,11 +100580,43 @@ const transformMagicBlockEmbed = (node) => {
100518
100580
  };
100519
100581
  };
100520
100582
  const mdxish_jsx_to_mdast_isTableCell = (node) => isMDXElement(node) && ['th', 'td'].includes(node.name);
100583
+ /**
100584
+ * Wraps bare `<td>`/`<th>` cells directly inside `<thead>`/`<tbody>` with an
100585
+ * implicit `<tr>`. remarkMdx may wrap inline JSX elements in paragraph nodes,
100586
+ * so unwrap those first.
100587
+ */
100588
+ const wrapBareCellsInRow = (node) => {
100589
+ visit(node, isMDXElement, (section) => {
100590
+ if (section.name !== 'thead' && section.name !== 'tbody')
100591
+ return;
100592
+ const children = section.children;
100593
+ const hasRow = children.some(c => isMDXElement(c) && c.name === 'tr');
100594
+ if (hasRow)
100595
+ return;
100596
+ const unwrapped = children.flatMap(c => {
100597
+ if (c.type === 'paragraph' && 'children' in c && Array.isArray(c.children)) {
100598
+ return c.children;
100599
+ }
100600
+ return [c];
100601
+ });
100602
+ const cells = unwrapped.filter(c => mdxish_jsx_to_mdast_isTableCell(c));
100603
+ if (cells.length === 0)
100604
+ return;
100605
+ const tr = {
100606
+ type: 'mdxJsxFlowElement',
100607
+ name: 'tr',
100608
+ attributes: [],
100609
+ children: cells,
100610
+ };
100611
+ section.children = [tr];
100612
+ });
100613
+ };
100521
100614
  /**
100522
100615
  * Converts a JSX <Table> element to an MDAST table node with alignment.
100523
100616
  * Returns null for header-less tables since MDAST always promotes the first row to <thead>.
100524
100617
  */
100525
100618
  const transformTable = (jsx) => {
100619
+ wrapBareCellsInRow(jsx);
100526
100620
  let hasThead = false;
100527
100621
  visit(jsx, isMDXElement, (child) => {
100528
100622
  if (child.name === 'thead')