@readme/markdown 13.8.1 → 13.8.3

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
@@ -12090,6 +12090,21 @@ function buildLinkMap(nav) {
12090
12090
  const VISIBLE_RATIO = 0.4;
12091
12091
  /** Tolerance for subpixel rounding when checking if scrolled to the bottom. */
12092
12092
  const SCROLL_BOTTOM_TOLERANCE = 1;
12093
+ /**
12094
+ * Walk up the DOM to find the nearest scrollable ancestor.
12095
+ * Falls back to `window` when the page itself scrolls.
12096
+ */
12097
+ function getScrollParent(el) {
12098
+ let parent = el.parentElement;
12099
+ while (parent) {
12100
+ const { overflow, overflowY } = getComputedStyle(parent);
12101
+ if (/(auto|scroll)/.test(overflow + overflowY) && parent.scrollHeight > parent.clientHeight) {
12102
+ return parent;
12103
+ }
12104
+ parent = parent.parentElement;
12105
+ }
12106
+ return window;
12107
+ }
12093
12108
  /**
12094
12109
  * Watches headings in the viewport and toggles `active` on the
12095
12110
  * corresponding TOC links so the reader always knows where they are.
@@ -12118,7 +12133,13 @@ function useScrollHighlight(navRef) {
12118
12133
  let activeId = null;
12119
12134
  let clickLocked = false;
12120
12135
  const visible = new Set();
12121
- const isAtBottom = () => window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - SCROLL_BOTTOM_TOLERANCE;
12136
+ const scrollParent = getScrollParent(headings[0]);
12137
+ const isAtBottom = () => {
12138
+ if (scrollParent instanceof Window) {
12139
+ return window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - SCROLL_BOTTOM_TOLERANCE;
12140
+ }
12141
+ return scrollParent.scrollTop + scrollParent.clientHeight >= scrollParent.scrollHeight - SCROLL_BOTTOM_TOLERANCE;
12142
+ };
12122
12143
  const activate = (id) => {
12123
12144
  if (id === activeId)
12124
12145
  return;
@@ -12158,38 +12179,54 @@ function useScrollHighlight(navRef) {
12158
12179
  });
12159
12180
  updateActive();
12160
12181
  }, { rootMargin: `0px 0px -${(1 - VISIBLE_RATIO) * 100}% 0px`, threshold: 0 });
12161
- // Also check on scroll so bottom-of-page detection works even when
12182
+ // Check on scroll so bottom-of-page detection works even when
12162
12183
  // no headings are crossing the intersection boundary.
12184
+ const scrollTarget = scrollParent instanceof Window ? window : scrollParent;
12163
12185
  const onScroll = () => { updateActive(); };
12164
12186
  // Click a ToC link → immediately activate it, suppress the observer
12165
12187
  // until the smooth scroll finishes, then hand control back.
12166
12188
  const onClick = (e) => {
12167
- const anchor = e.target.closest?.('a[href^="#"]');
12168
- if (!anchor)
12189
+ if (!(e.target instanceof Element))
12190
+ return;
12191
+ const anchor = e.target.closest('a[href^="#"]');
12192
+ if (!(anchor instanceof HTMLAnchorElement))
12169
12193
  return;
12170
- const id = decodeURIComponent(anchor.getAttribute('href').slice(1));
12194
+ const id = decodeURIComponent(anchor.hash.slice(1));
12171
12195
  if (!linkMap.has(id))
12172
12196
  return;
12173
- e.preventDefault();
12197
+ if (window.location.hash !== anchor.hash) {
12198
+ window.location.hash = anchor.hash;
12199
+ }
12174
12200
  activate(id);
12175
12201
  clickLocked = true;
12176
- const unlock = () => { clickLocked = false; };
12177
- window.addEventListener('scrollend', unlock, { once: true });
12178
- document.getElementById(id)?.scrollIntoView({ behavior: 'smooth' });
12202
+ let unlockTimer = null;
12203
+ const unlock = () => {
12204
+ clickLocked = false;
12205
+ scrollTarget.removeEventListener('scrollend', unlock);
12206
+ window.removeEventListener('hashchange', unlock);
12207
+ if (unlockTimer !== null) {
12208
+ window.clearTimeout(unlockTimer);
12209
+ unlockTimer = null;
12210
+ }
12211
+ };
12212
+ scrollTarget.addEventListener('scrollend', unlock, { once: true });
12213
+ window.addEventListener('hashchange', unlock, { once: true });
12214
+ // Fallback in case scrollend and hashchange don't fire
12215
+ unlockTimer = window.setTimeout(unlock, 500);
12179
12216
  };
12180
12217
  headings.forEach(el => { observer.observe(el); });
12181
- window.addEventListener('scroll', onScroll, { passive: true });
12218
+ scrollTarget.addEventListener('scroll', onScroll, { passive: true });
12182
12219
  nav.addEventListener('click', onClick);
12183
- // Set initial active state for the first heading visible in the viewport
12220
+ // Set initial active state for the first heading visible in the viewport,
12221
+ // falling back to the first heading if none is in the observation zone yet.
12184
12222
  const initialHeading = headings.find(el => {
12185
12223
  const rect = el.getBoundingClientRect();
12186
12224
  return rect.top >= 0 && rect.top < window.innerHeight * VISIBLE_RATIO;
12187
- });
12188
- if (initialHeading)
12189
- activate(initialHeading.id);
12225
+ }) || headings[0];
12226
+ activate(initialHeading.id);
12190
12227
  return () => {
12191
12228
  observer.disconnect();
12192
- window.removeEventListener('scroll', onScroll);
12229
+ scrollTarget.removeEventListener('scroll', onScroll);
12193
12230
  nav.removeEventListener('click', onClick);
12194
12231
  };
12195
12232
  }, [navRef, linkCount]);
@@ -96434,10 +96471,10 @@ const parseTableCell = (text) => {
96434
96471
  node.value = escapeInvalidTags(node.value);
96435
96472
  }
96436
96473
  });
96437
- if (tree.children.length > 1) {
96438
- return tree.children;
96439
- }
96440
- return tree.children.flatMap(n => n.type === 'paragraph' && 'children' in n ? n.children : [n]);
96474
+ const result = tree.children.length > 1
96475
+ ? tree.children
96476
+ : tree.children.flatMap(n => n.type === 'paragraph' && 'children' in n ? n.children : [n]);
96477
+ return result;
96441
96478
  };
96442
96479
  const parseBlock = (text) => {
96443
96480
  if (!text.trim())
@@ -96649,7 +96686,9 @@ function transformMagicBlock(blockType, data, rawValue, options = {}) {
96649
96686
  mapped[rowIndex][colIndex] = v;
96650
96687
  return mapped;
96651
96688
  }, []);
96652
- const tokenizeCell = compatibilityMode ? textToBlock : parseTableCell;
96689
+ const tokenizeCell = compatibilityMode
96690
+ ? textToBlock
96691
+ : parseTableCell;
96653
96692
  const tableChildren = Array.from({ length: rows + 1 }, (_, y) => ({
96654
96693
  children: Array.from({ length: cols }, (__, x) => ({
96655
96694
  children: sparseData[y]?.[x] ? tokenizeCell(preprocessBody(sparseData[y][x])) : [{ type: 'text', value: '' }],
@@ -98342,6 +98381,7 @@ function restoreSnakeCase(placeholderName, mapping) {
98342
98381
  ;// ./processor/transform/mdxish/mdxish-tables-to-jsx.ts
98343
98382
 
98344
98383
 
98384
+
98345
98385
  const SELF_CLOSING_JSX_REGEX = /^\s*<[A-Z][^>]*\/>\s*$/;
98346
98386
  const mdxish_tables_to_jsx_alignToStyle = (align) => {
98347
98387
  if (!align || align === 'left')
@@ -98371,22 +98411,27 @@ const mdxishTablesToJsx = () => tree => {
98371
98411
  visit(table, mdxish_tables_to_jsx_isTableCell, (cell) => {
98372
98412
  if (hasFlowContent || cell.children.length === 0)
98373
98413
  return;
98374
- const content = cell.children.length === 1 && cell.children[0].type === 'paragraph'
98375
- ? cell.children[0].children[0]
98376
- : cell.children[0];
98377
- if (!content)
98378
- return;
98379
98414
  visit(cell, 'break', (_, breakIndex, breakParent) => {
98380
98415
  breakParent.children.splice(breakIndex, 1, { type: 'text', value: '\n' });
98381
98416
  });
98382
- if (!(phrasing(content) || content.type === 'plain') && content.type !== 'escape') {
98383
- // Plain HTML (e.g. <div>Hello</div>) is skipped here — it stays in GFM cells fine.
98384
- // But self-closing JSX components (e.g. <Image src="..." caption="..." />) serialize
98385
- // with newlines that break GFM cells, so they must trigger JSX <Table> serialization.
98386
- const isPlainHtml = content.type === 'html' && !SELF_CLOSING_JSX_REGEX.test(content.value);
98387
- if (!isPlainHtml) {
98388
- hasFlowContent = true;
98417
+ // Check if any child is "flow" content (block-level) that requires JSX <Table>
98418
+ // serialization instead of GFM. `phrasing()` from mdast-util-phrasing returns
98419
+ // true for inline node types (text, emphasis, strong, link, etc.) which are
98420
+ // safe to keep in GFM cells.
98421
+ const hasFlowChild = cell.children.some(child => {
98422
+ if (child.type === 'paragraph' || child.type === 'plain' || child.type === 'escape')
98423
+ return false;
98424
+ if (child.type === NodeTypes.variable)
98425
+ return false;
98426
+ if (phrasing(child))
98427
+ return false;
98428
+ if (child.type === 'html') {
98429
+ return SELF_CLOSING_JSX_REGEX.test(child.value);
98389
98430
  }
98431
+ return true;
98432
+ });
98433
+ if (hasFlowChild) {
98434
+ hasFlowContent = true;
98390
98435
  }
98391
98436
  if (!hasFlowContent) {
98392
98437
  visit(cell, mdxish_tables_to_jsx_isLiteral, (node) => {
@@ -98763,25 +98808,31 @@ function makeVariableNode(varName, rawValue) {
98763
98808
  }
98764
98809
  /**
98765
98810
  * A remark plugin that parses {user.<field>} patterns from text nodes and
98766
- * mdxTextExpression nodes, creating Variable nodes for runtime resolution.
98811
+ * mdx expression nodes, creating Variable nodes for runtime resolution.
98767
98812
  *
98768
- * Handles both:
98813
+ * Handles:
98769
98814
  * - `text` nodes: when safeMode is true or after expression evaluation
98770
98815
  * - `mdxTextExpression` nodes: when mdxExpression has parsed {user.*} before evaluation
98816
+ * - `mdxFlowExpression` nodes: when {user.*} appears on its own line (e.g. inside JSX table cells)
98771
98817
  *
98772
98818
  * Supports any user field: name, email, email_verified, exp, iat, etc.
98773
98819
  */
98820
+ function visitExpressionNode(node, index, parent) {
98821
+ if (index === undefined || !parent)
98822
+ return;
98823
+ const wrapped = `{${(node.value ?? '').trim()}}`;
98824
+ const matches = [...wrapped.matchAll(USER_VAR_REGEX)];
98825
+ if (matches.length !== 1)
98826
+ return;
98827
+ const varName = matches[0][1] || matches[0][2];
98828
+ parent.children.splice(index, 1, makeVariableNode(varName, wrapped));
98829
+ }
98774
98830
  const variablesTextTransformer = () => tree => {
98775
- // Handle mdxTextExpression nodes (e.g. {user.name} parsed by mdxExpression)
98776
98831
  visit(tree, 'mdxTextExpression', (node, index, parent) => {
98777
- if (index === undefined || !parent)
98778
- return;
98779
- const wrapped = `{${(node.value ?? '').trim()}}`; // Wrap the expression value in {} to match the USER_VAR_REGEX pattern
98780
- const matches = [...wrapped.matchAll(USER_VAR_REGEX)];
98781
- if (matches.length !== 1)
98782
- return;
98783
- const varName = matches[0][1] || matches[0][2];
98784
- parent.children.splice(index, 1, makeVariableNode(varName, wrapped));
98832
+ visitExpressionNode(node, index, parent);
98833
+ });
98834
+ visit(tree, 'mdxFlowExpression', (node, index, parent) => {
98835
+ visitExpressionNode(node, index, parent);
98785
98836
  });
98786
98837
  visit(tree, 'text', (node, index, parent) => {
98787
98838
  if (index === undefined || !parent)
package/dist/main.node.js CHANGED
@@ -19670,14 +19670,14 @@ function getWindowScrollBarX(element) {
19670
19670
  }
19671
19671
  ;// ./node_modules/@popperjs/core/lib/dom-utils/getComputedStyle.js
19672
19672
 
19673
- function getComputedStyle(element) {
19673
+ function getComputedStyle_getComputedStyle(element) {
19674
19674
  return getWindow(element).getComputedStyle(element);
19675
19675
  }
19676
19676
  ;// ./node_modules/@popperjs/core/lib/dom-utils/isScrollParent.js
19677
19677
 
19678
19678
  function isScrollParent(element) {
19679
19679
  // Firefox wants us to check `-x` and `-y` variations as well
19680
- var _getComputedStyle = getComputedStyle(element),
19680
+ var _getComputedStyle = getComputedStyle_getComputedStyle(element),
19681
19681
  overflow = _getComputedStyle.overflow,
19682
19682
  overflowX = _getComputedStyle.overflowX,
19683
19683
  overflowY = _getComputedStyle.overflowY;
@@ -19849,7 +19849,7 @@ function isTableElement(element) {
19849
19849
 
19850
19850
  function getTrueOffsetParent(element) {
19851
19851
  if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837
19852
- getComputedStyle(element).position === 'fixed') {
19852
+ getComputedStyle_getComputedStyle(element).position === 'fixed') {
19853
19853
  return null;
19854
19854
  }
19855
19855
 
@@ -19864,7 +19864,7 @@ function getContainingBlock(element) {
19864
19864
 
19865
19865
  if (isIE && isHTMLElement(element)) {
19866
19866
  // In IE 9, 10 and 11 fixed elements containing block is always established by the viewport
19867
- var elementCss = getComputedStyle(element);
19867
+ var elementCss = getComputedStyle_getComputedStyle(element);
19868
19868
 
19869
19869
  if (elementCss.position === 'fixed') {
19870
19870
  return null;
@@ -19878,7 +19878,7 @@ function getContainingBlock(element) {
19878
19878
  }
19879
19879
 
19880
19880
  while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {
19881
- var css = getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that
19881
+ var css = getComputedStyle_getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that
19882
19882
  // create a containing block.
19883
19883
  // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
19884
19884
 
@@ -19898,11 +19898,11 @@ function getOffsetParent(element) {
19898
19898
  var window = getWindow(element);
19899
19899
  var offsetParent = getTrueOffsetParent(element);
19900
19900
 
19901
- while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {
19901
+ while (offsetParent && isTableElement(offsetParent) && getComputedStyle_getComputedStyle(offsetParent).position === 'static') {
19902
19902
  offsetParent = getTrueOffsetParent(offsetParent);
19903
19903
  }
19904
19904
 
19905
- if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static')) {
19905
+ if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle_getComputedStyle(offsetParent).position === 'static')) {
19906
19906
  return window;
19907
19907
  }
19908
19908
 
@@ -20447,7 +20447,7 @@ function mapToStyles(_ref2) {
20447
20447
  if (offsetParent === getWindow(popper)) {
20448
20448
  offsetParent = getDocumentElement(popper);
20449
20449
 
20450
- if (getComputedStyle(offsetParent).position !== 'static' && position === 'absolute') {
20450
+ if (getComputedStyle_getComputedStyle(offsetParent).position !== 'static' && position === 'absolute') {
20451
20451
  heightProp = 'scrollHeight';
20452
20452
  widthProp = 'scrollWidth';
20453
20453
  }
@@ -20759,7 +20759,7 @@ function getDocumentRect(element) {
20759
20759
  var x = -winScroll.scrollLeft + getWindowScrollBarX(element);
20760
20760
  var y = -winScroll.scrollTop;
20761
20761
 
20762
- if (getComputedStyle(body || html).direction === 'rtl') {
20762
+ if (getComputedStyle_getComputedStyle(body || html).direction === 'rtl') {
20763
20763
  x += math_max(html.clientWidth, body ? body.clientWidth : 0) - width;
20764
20764
  }
20765
20765
 
@@ -20841,7 +20841,7 @@ function getClientRectFromMixedType(element, clippingParent, strategy) {
20841
20841
 
20842
20842
  function getClippingParents(element) {
20843
20843
  var clippingParents = listScrollParents(getParentNode(element));
20844
- var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle(element).position) >= 0;
20844
+ var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle_getComputedStyle(element).position) >= 0;
20845
20845
  var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;
20846
20846
 
20847
20847
  if (!isElement(clipperElement)) {
@@ -24686,6 +24686,21 @@ function buildLinkMap(nav) {
24686
24686
  const VISIBLE_RATIO = 0.4;
24687
24687
  /** Tolerance for subpixel rounding when checking if scrolled to the bottom. */
24688
24688
  const SCROLL_BOTTOM_TOLERANCE = 1;
24689
+ /**
24690
+ * Walk up the DOM to find the nearest scrollable ancestor.
24691
+ * Falls back to `window` when the page itself scrolls.
24692
+ */
24693
+ function TableOfContents_getScrollParent(el) {
24694
+ let parent = el.parentElement;
24695
+ while (parent) {
24696
+ const { overflow, overflowY } = getComputedStyle(parent);
24697
+ if (/(auto|scroll)/.test(overflow + overflowY) && parent.scrollHeight > parent.clientHeight) {
24698
+ return parent;
24699
+ }
24700
+ parent = parent.parentElement;
24701
+ }
24702
+ return window;
24703
+ }
24689
24704
  /**
24690
24705
  * Watches headings in the viewport and toggles `active` on the
24691
24706
  * corresponding TOC links so the reader always knows where they are.
@@ -24714,7 +24729,13 @@ function useScrollHighlight(navRef) {
24714
24729
  let activeId = null;
24715
24730
  let clickLocked = false;
24716
24731
  const visible = new Set();
24717
- const isAtBottom = () => window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - SCROLL_BOTTOM_TOLERANCE;
24732
+ const scrollParent = TableOfContents_getScrollParent(headings[0]);
24733
+ const isAtBottom = () => {
24734
+ if (scrollParent instanceof Window) {
24735
+ return window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - SCROLL_BOTTOM_TOLERANCE;
24736
+ }
24737
+ return scrollParent.scrollTop + scrollParent.clientHeight >= scrollParent.scrollHeight - SCROLL_BOTTOM_TOLERANCE;
24738
+ };
24718
24739
  const activate = (id) => {
24719
24740
  if (id === activeId)
24720
24741
  return;
@@ -24754,38 +24775,54 @@ function useScrollHighlight(navRef) {
24754
24775
  });
24755
24776
  updateActive();
24756
24777
  }, { rootMargin: `0px 0px -${(1 - VISIBLE_RATIO) * 100}% 0px`, threshold: 0 });
24757
- // Also check on scroll so bottom-of-page detection works even when
24778
+ // Check on scroll so bottom-of-page detection works even when
24758
24779
  // no headings are crossing the intersection boundary.
24780
+ const scrollTarget = scrollParent instanceof Window ? window : scrollParent;
24759
24781
  const onScroll = () => { updateActive(); };
24760
24782
  // Click a ToC link → immediately activate it, suppress the observer
24761
24783
  // until the smooth scroll finishes, then hand control back.
24762
24784
  const onClick = (e) => {
24763
- const anchor = e.target.closest?.('a[href^="#"]');
24764
- if (!anchor)
24785
+ if (!(e.target instanceof Element))
24765
24786
  return;
24766
- const id = decodeURIComponent(anchor.getAttribute('href').slice(1));
24787
+ const anchor = e.target.closest('a[href^="#"]');
24788
+ if (!(anchor instanceof HTMLAnchorElement))
24789
+ return;
24790
+ const id = decodeURIComponent(anchor.hash.slice(1));
24767
24791
  if (!linkMap.has(id))
24768
24792
  return;
24769
- e.preventDefault();
24793
+ if (window.location.hash !== anchor.hash) {
24794
+ window.location.hash = anchor.hash;
24795
+ }
24770
24796
  activate(id);
24771
24797
  clickLocked = true;
24772
- const unlock = () => { clickLocked = false; };
24773
- window.addEventListener('scrollend', unlock, { once: true });
24774
- document.getElementById(id)?.scrollIntoView({ behavior: 'smooth' });
24798
+ let unlockTimer = null;
24799
+ const unlock = () => {
24800
+ clickLocked = false;
24801
+ scrollTarget.removeEventListener('scrollend', unlock);
24802
+ window.removeEventListener('hashchange', unlock);
24803
+ if (unlockTimer !== null) {
24804
+ window.clearTimeout(unlockTimer);
24805
+ unlockTimer = null;
24806
+ }
24807
+ };
24808
+ scrollTarget.addEventListener('scrollend', unlock, { once: true });
24809
+ window.addEventListener('hashchange', unlock, { once: true });
24810
+ // Fallback in case scrollend and hashchange don't fire
24811
+ unlockTimer = window.setTimeout(unlock, 500);
24775
24812
  };
24776
24813
  headings.forEach(el => { observer.observe(el); });
24777
- window.addEventListener('scroll', onScroll, { passive: true });
24814
+ scrollTarget.addEventListener('scroll', onScroll, { passive: true });
24778
24815
  nav.addEventListener('click', onClick);
24779
- // Set initial active state for the first heading visible in the viewport
24816
+ // Set initial active state for the first heading visible in the viewport,
24817
+ // falling back to the first heading if none is in the observation zone yet.
24780
24818
  const initialHeading = headings.find(el => {
24781
24819
  const rect = el.getBoundingClientRect();
24782
24820
  return rect.top >= 0 && rect.top < window.innerHeight * VISIBLE_RATIO;
24783
- });
24784
- if (initialHeading)
24785
- activate(initialHeading.id);
24821
+ }) || headings[0];
24822
+ activate(initialHeading.id);
24786
24823
  return () => {
24787
24824
  observer.disconnect();
24788
- window.removeEventListener('scroll', onScroll);
24825
+ scrollTarget.removeEventListener('scroll', onScroll);
24789
24826
  nav.removeEventListener('click', onClick);
24790
24827
  };
24791
24828
  }, [navRef, linkCount]);
@@ -116628,10 +116665,10 @@ const parseTableCell = (text) => {
116628
116665
  node.value = escapeInvalidTags(node.value);
116629
116666
  }
116630
116667
  });
116631
- if (tree.children.length > 1) {
116632
- return tree.children;
116633
- }
116634
- return tree.children.flatMap(n => n.type === 'paragraph' && 'children' in n ? n.children : [n]);
116668
+ const result = tree.children.length > 1
116669
+ ? tree.children
116670
+ : tree.children.flatMap(n => n.type === 'paragraph' && 'children' in n ? n.children : [n]);
116671
+ return result;
116635
116672
  };
116636
116673
  const parseBlock = (text) => {
116637
116674
  if (!text.trim())
@@ -116843,7 +116880,9 @@ function transformMagicBlock(blockType, data, rawValue, options = {}) {
116843
116880
  mapped[rowIndex][colIndex] = v;
116844
116881
  return mapped;
116845
116882
  }, []);
116846
- const tokenizeCell = compatibilityMode ? textToBlock : parseTableCell;
116883
+ const tokenizeCell = compatibilityMode
116884
+ ? textToBlock
116885
+ : parseTableCell;
116847
116886
  const tableChildren = Array.from({ length: rows + 1 }, (_, y) => ({
116848
116887
  children: Array.from({ length: cols }, (__, x) => ({
116849
116888
  children: sparseData[y]?.[x] ? tokenizeCell(preprocessBody(sparseData[y][x])) : [{ type: 'text', value: '' }],
@@ -118536,6 +118575,7 @@ function restoreSnakeCase(placeholderName, mapping) {
118536
118575
  ;// ./processor/transform/mdxish/mdxish-tables-to-jsx.ts
118537
118576
 
118538
118577
 
118578
+
118539
118579
  const SELF_CLOSING_JSX_REGEX = /^\s*<[A-Z][^>]*\/>\s*$/;
118540
118580
  const mdxish_tables_to_jsx_alignToStyle = (align) => {
118541
118581
  if (!align || align === 'left')
@@ -118565,22 +118605,27 @@ const mdxishTablesToJsx = () => tree => {
118565
118605
  visit(table, mdxish_tables_to_jsx_isTableCell, (cell) => {
118566
118606
  if (hasFlowContent || cell.children.length === 0)
118567
118607
  return;
118568
- const content = cell.children.length === 1 && cell.children[0].type === 'paragraph'
118569
- ? cell.children[0].children[0]
118570
- : cell.children[0];
118571
- if (!content)
118572
- return;
118573
118608
  visit(cell, 'break', (_, breakIndex, breakParent) => {
118574
118609
  breakParent.children.splice(breakIndex, 1, { type: 'text', value: '\n' });
118575
118610
  });
118576
- if (!(phrasing(content) || content.type === 'plain') && content.type !== 'escape') {
118577
- // Plain HTML (e.g. <div>Hello</div>) is skipped here — it stays in GFM cells fine.
118578
- // But self-closing JSX components (e.g. <Image src="..." caption="..." />) serialize
118579
- // with newlines that break GFM cells, so they must trigger JSX <Table> serialization.
118580
- const isPlainHtml = content.type === 'html' && !SELF_CLOSING_JSX_REGEX.test(content.value);
118581
- if (!isPlainHtml) {
118582
- hasFlowContent = true;
118611
+ // Check if any child is "flow" content (block-level) that requires JSX <Table>
118612
+ // serialization instead of GFM. `phrasing()` from mdast-util-phrasing returns
118613
+ // true for inline node types (text, emphasis, strong, link, etc.) which are
118614
+ // safe to keep in GFM cells.
118615
+ const hasFlowChild = cell.children.some(child => {
118616
+ if (child.type === 'paragraph' || child.type === 'plain' || child.type === 'escape')
118617
+ return false;
118618
+ if (child.type === NodeTypes.variable)
118619
+ return false;
118620
+ if (phrasing(child))
118621
+ return false;
118622
+ if (child.type === 'html') {
118623
+ return SELF_CLOSING_JSX_REGEX.test(child.value);
118583
118624
  }
118625
+ return true;
118626
+ });
118627
+ if (hasFlowChild) {
118628
+ hasFlowContent = true;
118584
118629
  }
118585
118630
  if (!hasFlowContent) {
118586
118631
  visit(cell, mdxish_tables_to_jsx_isLiteral, (node) => {
@@ -118957,25 +119002,31 @@ function makeVariableNode(varName, rawValue) {
118957
119002
  }
118958
119003
  /**
118959
119004
  * A remark plugin that parses {user.<field>} patterns from text nodes and
118960
- * mdxTextExpression nodes, creating Variable nodes for runtime resolution.
119005
+ * mdx expression nodes, creating Variable nodes for runtime resolution.
118961
119006
  *
118962
- * Handles both:
119007
+ * Handles:
118963
119008
  * - `text` nodes: when safeMode is true or after expression evaluation
118964
119009
  * - `mdxTextExpression` nodes: when mdxExpression has parsed {user.*} before evaluation
119010
+ * - `mdxFlowExpression` nodes: when {user.*} appears on its own line (e.g. inside JSX table cells)
118965
119011
  *
118966
119012
  * Supports any user field: name, email, email_verified, exp, iat, etc.
118967
119013
  */
119014
+ function visitExpressionNode(node, index, parent) {
119015
+ if (index === undefined || !parent)
119016
+ return;
119017
+ const wrapped = `{${(node.value ?? '').trim()}}`;
119018
+ const matches = [...wrapped.matchAll(USER_VAR_REGEX)];
119019
+ if (matches.length !== 1)
119020
+ return;
119021
+ const varName = matches[0][1] || matches[0][2];
119022
+ parent.children.splice(index, 1, makeVariableNode(varName, wrapped));
119023
+ }
118968
119024
  const variablesTextTransformer = () => tree => {
118969
- // Handle mdxTextExpression nodes (e.g. {user.name} parsed by mdxExpression)
118970
119025
  visit(tree, 'mdxTextExpression', (node, index, parent) => {
118971
- if (index === undefined || !parent)
118972
- return;
118973
- const wrapped = `{${(node.value ?? '').trim()}}`; // Wrap the expression value in {} to match the USER_VAR_REGEX pattern
118974
- const matches = [...wrapped.matchAll(USER_VAR_REGEX)];
118975
- if (matches.length !== 1)
118976
- return;
118977
- const varName = matches[0][1] || matches[0][2];
118978
- parent.children.splice(index, 1, makeVariableNode(varName, wrapped));
119026
+ visitExpressionNode(node, index, parent);
119027
+ });
119028
+ visit(tree, 'mdxFlowExpression', (node, index, parent) => {
119029
+ visitExpressionNode(node, index, parent);
118979
119030
  });
118980
119031
  visit(tree, 'text', (node, index, parent) => {
118981
119032
  if (index === undefined || !parent)