@readme/markdown 15.6.0 → 15.7.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.
@@ -96172,31 +96172,11 @@ const HTML_VOID_ELEMENTS = new Set([
96172
96172
 
96173
96173
 
96174
96174
  /**
96175
- * Partial constructs the `mdxComponent` tokenizer runs via `effects.check` to
96176
- * decide whether the next line continues the block. They live here (not in
96177
- * `syntax.ts`) because they hold none of `createTokenize`'s closure state — each
96175
+ * Partial construct the `mdxComponent` tokenizer runs via `effects.check` to
96176
+ * decide whether the next line continues the block. It lives here (not in
96177
+ * `syntax.ts`) because it holds none of `createTokenize`'s closure state — it
96178
96178
  * is a self-contained, single-line lookahead.
96179
96179
  */
96180
- function continuation_checks_tokenizeNonLazyContinuationStart(effects, ok, nok) {
96181
- // eslint-disable-next-line @typescript-eslint/no-this-alias
96182
- const self = this;
96183
- return start;
96184
- function start(code) {
96185
- if (markdownLineEnding(code)) {
96186
- effects.enter(types_types.lineEnding);
96187
- effects.consume(code);
96188
- effects.exit(types_types.lineEnding);
96189
- return after;
96190
- }
96191
- return nok(code);
96192
- }
96193
- function after(code) {
96194
- if (self.parser.lazy[self.now().line]) {
96195
- return nok(code);
96196
- }
96197
- return ok(code);
96198
- }
96199
- }
96200
96180
  // A markup-only line opens with a tag (`<x`/`</x`) and ends (ignoring trailing
96201
96181
  // spaces) at a `>`. That distinguishes a structural continuation like
96202
96182
  // `<span>b</span></div>` from a paragraph like `<b>Note:</b> read *this*`.
@@ -96237,12 +96217,6 @@ function tokenizeMarkupOnlyContinuation(effects, ok, nok) {
96237
96217
  return scanToLineEnd;
96238
96218
  }
96239
96219
  }
96240
- // A line ending whose next line isn't a lazy paragraph continuation. Checked so a
96241
- // component body's blank/continuation lines aren't stolen by an interrupted paragraph.
96242
- const continuation_checks_nonLazyContinuationStart = {
96243
- tokenize: continuation_checks_tokenizeNonLazyContinuationStart,
96244
- partial: true,
96245
- };
96246
96220
  // Lookahead for `plainClaimLineStart`: is this line markup-only, or a paragraph
96247
96221
  // that merely starts with a tag? Run via `effects.check` so it never consumes.
96248
96222
  const markupOnlyContinuation = {
@@ -96658,14 +96632,7 @@ function syntax_createTokenize(mode) {
96658
96632
  }
96659
96633
  // Continuation for multi-line opening tags
96660
96634
  function openTagContinuationStart(code) {
96661
- return effects.check(continuation_checks_nonLazyContinuationStart, openTagContinuationNonLazy, continuationAfter)(code);
96662
- }
96663
- function openTagContinuationNonLazy(code) {
96664
- sawLineEnding = true;
96665
- effects.enter(types_types.lineEnding);
96666
- effects.consume(code);
96667
- effects.exit(types_types.lineEnding);
96668
- return openTagContinuationBefore;
96635
+ return continueOnNextLine(code, openTagContinuationBefore);
96669
96636
  }
96670
96637
  function openTagContinuationBefore(code) {
96671
96638
  if (code === null || markdownLineEnding(code)) {
@@ -96783,14 +96750,7 @@ function syntax_createTokenize(mode) {
96783
96750
  return inFencedCode;
96784
96751
  }
96785
96752
  function fencedCodeContinuationStart(code) {
96786
- return effects.check(continuation_checks_nonLazyContinuationStart, fencedCodeContinuationNonLazy, continuationAfter)(code);
96787
- }
96788
- function fencedCodeContinuationNonLazy(code) {
96789
- sawLineEnding = true;
96790
- effects.enter(types_types.lineEnding);
96791
- effects.consume(code);
96792
- effects.exit(types_types.lineEnding);
96793
- return fencedCodeContinuationBefore;
96753
+ return continueOnNextLine(code, fencedCodeContinuationBefore);
96794
96754
  }
96795
96755
  function fencedCodeContinuationBefore(code) {
96796
96756
  if (code === null || markdownLineEnding(code)) {
@@ -97007,14 +96967,7 @@ function syntax_createTokenize(mode) {
97007
96967
  }
97008
96968
  // ── Body continuation (line endings) ───────────────────────────────────
97009
96969
  function bodyContinuationStart(code) {
97010
- return effects.check(continuation_checks_nonLazyContinuationStart, bodyContinuationNonLazy, continuationAfter)(code);
97011
- }
97012
- function bodyContinuationNonLazy(code) {
97013
- sawLineEnding = true;
97014
- effects.enter(types_types.lineEnding);
97015
- effects.consume(code);
97016
- effects.exit(types_types.lineEnding);
97017
- return bodyContinuationBefore;
96970
+ return continueOnNextLine(code, bodyContinuationBefore);
97018
96971
  }
97019
96972
  function bodyContinuationBefore(code) {
97020
96973
  if (code === null || markdownLineEnding(code)) {
@@ -97083,13 +97036,18 @@ function syntax_createTokenize(mode) {
97083
97036
  pendingBlankLine = false;
97084
97037
  return bodyLineStart(code);
97085
97038
  }
97086
- // ── Shared lazy continuation failure ───────────────────────────────────
97087
- function continuationAfter(code) {
97088
- if (code === null) {
97039
+ // ── Shared line-ending continuation ────────────────────────────────────
97040
+ // Consumes one line ending and resumes at `nextLine`. Lazy lines (under-indented
97041
+ // under a list item or blockquote) continue too: a claim only ends at its closing
97042
+ // tag, and an unclosed one fails whole at EOF instead of leaving a truncated opener (CX-3940).
97043
+ function continueOnNextLine(code, nextLine) {
97044
+ if (!markdownLineEnding(code))
97089
97045
  return nok(code);
97090
- }
97091
- effects.exit('mdxComponent');
97092
- return ok(code);
97046
+ sawLineEnding = true;
97047
+ effects.enter(types_types.lineEnding);
97048
+ effects.consume(code);
97049
+ effects.exit(types_types.lineEnding);
97050
+ return nextLine;
97093
97051
  }
97094
97052
  };
97095
97053
  }
@@ -101217,6 +101175,8 @@ const processTableNode = (node, index, parent, documentPosition) => {
101217
101175
  type: 'table',
101218
101176
  position,
101219
101177
  children,
101178
+ // Remember the author's spelling so the serializer can write `<table>` back instead of `<Table>`
101179
+ ...(node.name === 'table' && { data: { lowercaseTable: true } }),
101220
101180
  };
101221
101181
  parent.children[index] = mdNode;
101222
101182
  };
@@ -116819,7 +116779,7 @@ const rehypeToc = ({ components = {} }) => {
116819
116779
  });
116820
116780
  };
116821
116781
  };
116822
- const MAX_DEPTH = 2;
116782
+ const MAX_DEPTH = 3;
116823
116783
  /**
116824
116784
  * Get the depth of a heading element based on its tag name.
116825
116785
  *
@@ -123344,7 +123304,7 @@ const parseMdChildren = (value, safeMode) => {
123344
123304
  // Promote nested wrappers bottom-up so an outer wrapper sees markdown buried in a
123345
123305
  // child claimed whole (e.g. `<li>` in `<ol>`) before its containsMarkdownConstruct check (RM-17560).
123346
123306
  // eslint-disable-next-line @typescript-eslint/no-use-before-define -- mutually recursive; hoisted decl, safe at runtime
123347
- promoteComponentBlocks(parsed, safeMode, null);
123307
+ promoteComponentBlocks(parsed, safeMode, reparseSource);
123348
123308
  const children = parsed.children || [];
123349
123309
  // These children root a new coordinate space: their offsets index into `reparseSource`.
123350
123310
  stampReparseSource(children, reparseSource);
@@ -123363,23 +123323,26 @@ const parseSibling = (parent, index, sibling, safeMode, promoted) => {
123363
123323
  }
123364
123324
  };
123365
123325
  // Ends the position at `consumedLength` so the component doesn't claim trailing
123366
- // content the tokenizer swallowed into the same html node.
123367
- const positionEndingAtConsumed = (nodePosition, value, consumedLength) => {
123326
+ // content the tokenizer swallowed into the same html node. Measured against the source
123327
+ // when available: each value line is its source line minus the container prefix
123328
+ // (list indent, `> `) micromark stripped, so those prefixes are counted back in.
123329
+ const positionEndingAtConsumed = (nodePosition, value, consumedLength, source) => {
123368
123330
  if (!nodePosition?.start)
123369
123331
  return nodePosition;
123370
- return { start: nodePosition.start, end: pointAfter(nodePosition.start, value.slice(0, consumedLength)) };
123371
- };
123372
- // Like `positionEndingAtConsumed`, but measures against the original source so
123373
- // blockquote/list prefixes stripped from the html node's value are counted.
123374
- const positionEndingAtClosingTagInSource = (nodePosition, closingTag, source) => {
123375
- if (!nodePosition?.start || !nodePosition.end)
123376
- return nodePosition;
123377
- const nodeSource = source.slice(nodePosition.start.offset, nodePosition.end.offset);
123378
- const closingTagOffset = nodeSource.lastIndexOf(closingTag);
123379
- if (closingTagOffset === -1)
123380
- return nodePosition;
123381
- const consumed = nodeSource.slice(0, closingTagOffset + closingTag.length);
123382
- return { start: nodePosition.start, end: pointAfter(nodePosition.start, consumed) };
123332
+ const consumedValue = value.slice(0, consumedLength);
123333
+ const sourceLines = source?.slice(nodePosition.start.offset, nodePosition.end?.offset).split('\n');
123334
+ const valueLines = value.split('\n');
123335
+ if (!sourceLines || sourceLines.length !== valueLines.length) {
123336
+ return { start: nodePosition.start, end: pointAfter(nodePosition.start, consumedValue) };
123337
+ }
123338
+ const consumedLines = consumedValue.split('\n');
123339
+ const lastLineIndex = consumedLines.length - 1;
123340
+ const prefixWidth = sourceLines[lastLineIndex].length - valueLines[lastLineIndex].length;
123341
+ const consumedSource = [
123342
+ ...sourceLines.slice(0, lastLineIndex),
123343
+ sourceLines[lastLineIndex].slice(0, prefixWidth + consumedLines[lastLineIndex].length),
123344
+ ].join('\n');
123345
+ return { start: nodePosition.start, end: pointAfter(nodePosition.start, consumedSource) };
123383
123346
  };
123384
123347
  const createComponentNode = ({ tag, attributes, children, startPosition, endPosition, }) => ({
123385
123348
  type: 'mdxJsxFlowElement',
@@ -123486,16 +123449,18 @@ function promoteComponentBlocks(tree, safeMode, source) {
123486
123449
  const closingTagStr = `</${tag}>`;
123487
123450
  // Case 1: Self-closing tag
123488
123451
  if (selfClosing) {
123452
+ const remainingContent = contentAfterTag.trim();
123489
123453
  const componentNode = createComponentNode({
123490
123454
  tag,
123491
123455
  attributes,
123492
123456
  children: [],
123493
123457
  startPosition: node.position,
123494
- // End at the self-closing tag, not at any trailing content.
123495
- endPosition: positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd),
123458
+ // Without trailing content the whole node position is correct; with it, end at the tag.
123459
+ endPosition: remainingContent
123460
+ ? positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd, source)
123461
+ : node.position,
123496
123462
  });
123497
123463
  substituteNodeWithMdxNode(parent, index, componentNode);
123498
- const remainingContent = contentAfterTag.trim();
123499
123464
  if (remainingContent) {
123500
123465
  parseSibling(parent, index, remainingContent, safeMode, promoted);
123501
123466
  }
@@ -123534,14 +123499,10 @@ function promoteComponentBlocks(tree, safeMode, source) {
123534
123499
  stampReparseSource(parsedChildren, soleParagraph.data.reparseSource);
123535
123500
  unwrappedSoleParagraph = true;
123536
123501
  }
123537
- // Without trailing content the whole node position is correct. With it, end
123538
- // precisely at the closing tag — preferring source offsets when available (the
123539
- // node's value strips blockquote/list prefixes), else the consumed span.
123502
+ // Without trailing content the whole node position is correct; with it, end at the closing tag.
123540
123503
  let endPosition = node.position;
123541
123504
  if (contentAfterClose) {
123542
- endPosition = source
123543
- ? positionEndingAtClosingTagInSource(node.position, closingTagStr, source)
123544
- : positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd + closingTagIndex + closingTagStr.length);
123505
+ endPosition = positionEndingAtConsumed(node.position, value, leadingWhitespace + openingTagEnd + closingTagIndex + closingTagStr.length, source);
123545
123506
  }
123546
123507
  const componentNode = createComponentNode({
123547
123508
  tag,
@@ -127590,13 +127551,22 @@ const mdxishTablesToJsx = () => tree => {
127590
127551
  gfmCells.push([cell, normalized]);
127591
127552
  return undefined;
127592
127553
  });
127593
- if (!requiresJsxTable) {
127554
+ const stayLowercase = table.data?.lowercaseTable === true;
127555
+ // We transform to GFM tables if:
127556
+ // 1. If it doesn't contain complex elements that the syntax can't represent
127557
+ // 2. The original table is not lowercase HTML <table>, because we want to
127558
+ // preserve original tables as much as possible
127559
+ if (!requiresJsxTable && !stayLowercase) {
127594
127560
  gfmCells.forEach(([cell, children]) => {
127595
127561
  cell.children = children;
127596
127562
  });
127597
127563
  table.type = 'table';
127598
127564
  return;
127599
127565
  }
127566
+ // Nothing to build a JSX table from; leave the empty node to the GFM stringifier.
127567
+ const [headerRow, ...bodyRows] = table.children;
127568
+ if (!headerRow)
127569
+ return;
127600
127570
  mdxish_tables_to_jsx_visit(table, mdxish_tables_to_jsx_isTableCell, flattenBreaksToNewlines);
127601
127571
  const styles = table.align.map(mdxish_tables_to_jsx_alignToStyle);
127602
127572
  const head = {
@@ -127608,7 +127578,7 @@ const mdxishTablesToJsx = () => tree => {
127608
127578
  attributes: [],
127609
127579
  type: 'mdxJsxFlowElement',
127610
127580
  name: 'tr',
127611
- children: table.children[0].children.map((cell, cellIndex) => {
127581
+ children: headerRow.children.map((cell, cellIndex) => {
127612
127582
  return {
127613
127583
  attributes: [],
127614
127584
  type: 'mdxJsxFlowElement',
@@ -127624,7 +127594,7 @@ const mdxishTablesToJsx = () => tree => {
127624
127594
  attributes: [],
127625
127595
  type: 'mdxJsxFlowElement',
127626
127596
  name: 'tbody',
127627
- children: table.children.splice(1).map(row => {
127597
+ children: bodyRows.map(row => {
127628
127598
  return {
127629
127599
  attributes: [],
127630
127600
  type: 'mdxJsxFlowElement',
@@ -127652,8 +127622,8 @@ const mdxishTablesToJsx = () => tree => {
127652
127622
  ];
127653
127623
  const jsx = {
127654
127624
  type: 'mdxJsxFlowElement',
127655
- name: 'Table',
127656
- attributes: table.align.find(a => a) ? attributes : [],
127625
+ name: stayLowercase ? 'table' : 'Table',
127626
+ attributes: !stayLowercase && table.align.find(a => a) ? attributes : [],
127657
127627
  children: [head, body],
127658
127628
  };
127659
127629
  parent.children[index] = jsx;