@readme/markdown 13.7.3 → 13.7.4

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
@@ -24471,6 +24471,8 @@ const GlossaryContext = (0,external_react_.createContext)([]);
24471
24471
 
24472
24472
  const Glossary = ({ children, term: termProp, terms }) => {
24473
24473
  const term = (Array.isArray(children) ? children[0] : children) || termProp;
24474
+ if (!term)
24475
+ return null;
24474
24476
  const foundTerm = terms.find(i => term.toLowerCase() === i?.term?.toLowerCase());
24475
24477
  if (!foundTerm)
24476
24478
  return external_react_default().createElement("span", null, term);
@@ -24938,19 +24940,10 @@ const TailwindStyle = ({ children, darkModeDataAttribute }) => {
24938
24940
  records.forEach(record => {
24939
24941
  if (record.type === 'childList') {
24940
24942
  record.addedNodes.forEach(node => {
24941
- if (!(node instanceof HTMLElement))
24943
+ if (!(node instanceof HTMLElement) || !node.classList.contains(tailwindPrefix))
24942
24944
  return;
24943
- // Check the added node itself
24944
- if (node.classList.contains(tailwindPrefix)) {
24945
- traverse(node, addClasses);
24946
- shouldUpdate = true;
24947
- }
24948
- // Also check descendants — React may insert a parent node
24949
- // whose children contain TailwindRoot elements
24950
- node.querySelectorAll(`.${tailwindPrefix}`).forEach(child => {
24951
- traverse(child, addClasses);
24952
- shouldUpdate = true;
24953
- });
24945
+ traverse(node, addClasses);
24946
+ shouldUpdate = true;
24954
24947
  });
24955
24948
  }
24956
24949
  else if (record.type === 'attributes') {
@@ -73183,6 +73176,10 @@ const plain = (node, opts = {}) => {
73183
73176
  };
73184
73177
  /* harmony default export */ const lib_plain = (plain);
73185
73178
 
73179
+ ;// ./processor/compile/gemoji.ts
73180
+ const gemoji = (node) => `:${node.name}:`;
73181
+ /* harmony default export */ const compile_gemoji = (gemoji);
73182
+
73186
73183
  ;// ./processor/compile/variable.ts
73187
73184
  const variable = (node) => `{user.${node.data?.hProperties?.name || ''}}`;
73188
73185
  /* harmony default export */ const compile_variable = (variable);
@@ -73233,6 +73230,7 @@ const extractText = (node) => {
73233
73230
 
73234
73231
 
73235
73232
 
73233
+
73236
73234
  const titleParser = unified().use(remarkParse).use(remarkGfm);
73237
73235
  // The title paragraph may contain custom AST nodes that `toMarkdown` doesn't
73238
73236
  // natively understand
@@ -73240,8 +73238,8 @@ const toMarkdownExtensions = [
73240
73238
  gfmToMarkdown(),
73241
73239
  // For mdx variable syntaxes (e.g., {user.name})
73242
73240
  mdxExpressionToMarkdown(),
73243
- // Important: This is required and would crash the parser if there's no variable node handler
73244
- { handlers: { [NodeTypes.variable]: compile_variable } },
73241
+ // Important: This is required and would crash the parser if there's no variable and gemoji node handler
73242
+ { handlers: { [NodeTypes.variable]: compile_variable, [NodeTypes.emoji]: compile_gemoji } },
73245
73243
  ];
73246
73244
  const callouts_regex = `^(${emoji_regex().source}|⚠)(\\s+|$)`;
73247
73245
  const findFirst = (node) => {
@@ -73636,7 +73634,7 @@ const embedTransformer = () => {
73636
73634
  *
73637
73635
  * @type {Array<Gemoji>}
73638
73636
  */
73639
- const gemoji = [
73637
+ const gemoji_gemoji = [
73640
73638
  {
73641
73639
  emoji: '😀',
73642
73640
  names: ['grinning'],
@@ -90579,7 +90577,7 @@ class Owlmoji {
90579
90577
  return null;
90580
90578
  };
90581
90579
  static nameToEmoji = nameToEmoji;
90582
- static owlmoji = gemoji.concat(owlmoji);
90580
+ static owlmoji = gemoji_gemoji.concat(owlmoji);
90583
90581
  }
90584
90582
 
90585
90583
  ;// ./processor/transform/gemoji+.ts
@@ -91489,6 +91487,316 @@ const mdxToHast = () => tree => {
91489
91487
  };
91490
91488
  /* harmony default export */ const mdx_to_hast = (mdxToHast);
91491
91489
 
91490
+ ;// ./lib/mdast-util/gemoji/index.ts
91491
+
91492
+
91493
+ function exitGemoji(token) {
91494
+ const name = this.sliceSerialize(token).slice(1, -1); // strip surrounding colons
91495
+ switch (Owlmoji.kind(name)) {
91496
+ case 'gemoji': {
91497
+ this.enter({ type: NodeTypes.emoji, value: Owlmoji.nameToEmoji[name], name }, token);
91498
+ this.exit(token);
91499
+ break;
91500
+ }
91501
+ case 'fontawesome': {
91502
+ this.enter({
91503
+ type: NodeTypes.i,
91504
+ value: name,
91505
+ data: { hName: 'i', hProperties: { className: ['fa-regular', name] } },
91506
+ }, token);
91507
+ this.exit(token);
91508
+ break;
91509
+ }
91510
+ case 'owlmoji': {
91511
+ this.enter({
91512
+ type: NodeTypes.emoji,
91513
+ value: `:${name}:`,
91514
+ name,
91515
+ data: {
91516
+ hName: 'img',
91517
+ hProperties: {
91518
+ src: `/public/img/emojis/${name}.png`,
91519
+ alt: `:${name}:`,
91520
+ title: `:${name}:`,
91521
+ className: 'emoji',
91522
+ align: 'absmiddle',
91523
+ height: '20',
91524
+ width: '20',
91525
+ },
91526
+ },
91527
+ }, token);
91528
+ this.exit(token);
91529
+ break;
91530
+ }
91531
+ default: {
91532
+ // Unknown shortcode, emit as literal text `:name:`
91533
+ this.enter({ type: 'text', value: `:${name}:` }, token);
91534
+ this.exit(token);
91535
+ break;
91536
+ }
91537
+ }
91538
+ }
91539
+ function gemojiFromMarkdown() {
91540
+ return {
91541
+ exit: {
91542
+ gemoji: exitGemoji,
91543
+ },
91544
+ };
91545
+ }
91546
+
91547
+ ;// ./node_modules/micromark-util-symbol/lib/codes.js
91548
+ /**
91549
+ * Character codes.
91550
+ *
91551
+ * This module is compiled away!
91552
+ *
91553
+ * micromark works based on character codes.
91554
+ * This module contains constants for the ASCII block and the replacement
91555
+ * character.
91556
+ * A couple of them are handled in a special way, such as the line endings
91557
+ * (CR, LF, and CR+LF, commonly known as end-of-line: EOLs), the tab (horizontal
91558
+ * tab) and its expansion based on what column it’s at (virtual space),
91559
+ * and the end-of-file (eof) character.
91560
+ * As values are preprocessed before handling them, the actual characters LF,
91561
+ * CR, HT, and NUL (which is present as the replacement character), are
91562
+ * guaranteed to not exist.
91563
+ *
91564
+ * Unicode basic latin block.
91565
+ */
91566
+ const codes = /** @type {const} */ ({
91567
+ carriageReturn: -5,
91568
+ lineFeed: -4,
91569
+ carriageReturnLineFeed: -3,
91570
+ horizontalTab: -2,
91571
+ virtualSpace: -1,
91572
+ eof: null,
91573
+ nul: 0,
91574
+ soh: 1,
91575
+ stx: 2,
91576
+ etx: 3,
91577
+ eot: 4,
91578
+ enq: 5,
91579
+ ack: 6,
91580
+ bel: 7,
91581
+ bs: 8,
91582
+ ht: 9, // `\t`
91583
+ lf: 10, // `\n`
91584
+ vt: 11, // `\v`
91585
+ ff: 12, // `\f`
91586
+ cr: 13, // `\r`
91587
+ so: 14,
91588
+ si: 15,
91589
+ dle: 16,
91590
+ dc1: 17,
91591
+ dc2: 18,
91592
+ dc3: 19,
91593
+ dc4: 20,
91594
+ nak: 21,
91595
+ syn: 22,
91596
+ etb: 23,
91597
+ can: 24,
91598
+ em: 25,
91599
+ sub: 26,
91600
+ esc: 27,
91601
+ fs: 28,
91602
+ gs: 29,
91603
+ rs: 30,
91604
+ us: 31,
91605
+ space: 32,
91606
+ exclamationMark: 33, // `!`
91607
+ quotationMark: 34, // `"`
91608
+ numberSign: 35, // `#`
91609
+ dollarSign: 36, // `$`
91610
+ percentSign: 37, // `%`
91611
+ ampersand: 38, // `&`
91612
+ apostrophe: 39, // `'`
91613
+ leftParenthesis: 40, // `(`
91614
+ rightParenthesis: 41, // `)`
91615
+ asterisk: 42, // `*`
91616
+ plusSign: 43, // `+`
91617
+ comma: 44, // `,`
91618
+ dash: 45, // `-`
91619
+ dot: 46, // `.`
91620
+ slash: 47, // `/`
91621
+ digit0: 48, // `0`
91622
+ digit1: 49, // `1`
91623
+ digit2: 50, // `2`
91624
+ digit3: 51, // `3`
91625
+ digit4: 52, // `4`
91626
+ digit5: 53, // `5`
91627
+ digit6: 54, // `6`
91628
+ digit7: 55, // `7`
91629
+ digit8: 56, // `8`
91630
+ digit9: 57, // `9`
91631
+ colon: 58, // `:`
91632
+ semicolon: 59, // `;`
91633
+ lessThan: 60, // `<`
91634
+ equalsTo: 61, // `=`
91635
+ greaterThan: 62, // `>`
91636
+ questionMark: 63, // `?`
91637
+ atSign: 64, // `@`
91638
+ uppercaseA: 65, // `A`
91639
+ uppercaseB: 66, // `B`
91640
+ uppercaseC: 67, // `C`
91641
+ uppercaseD: 68, // `D`
91642
+ uppercaseE: 69, // `E`
91643
+ uppercaseF: 70, // `F`
91644
+ uppercaseG: 71, // `G`
91645
+ uppercaseH: 72, // `H`
91646
+ uppercaseI: 73, // `I`
91647
+ uppercaseJ: 74, // `J`
91648
+ uppercaseK: 75, // `K`
91649
+ uppercaseL: 76, // `L`
91650
+ uppercaseM: 77, // `M`
91651
+ uppercaseN: 78, // `N`
91652
+ uppercaseO: 79, // `O`
91653
+ uppercaseP: 80, // `P`
91654
+ uppercaseQ: 81, // `Q`
91655
+ uppercaseR: 82, // `R`
91656
+ uppercaseS: 83, // `S`
91657
+ uppercaseT: 84, // `T`
91658
+ uppercaseU: 85, // `U`
91659
+ uppercaseV: 86, // `V`
91660
+ uppercaseW: 87, // `W`
91661
+ uppercaseX: 88, // `X`
91662
+ uppercaseY: 89, // `Y`
91663
+ uppercaseZ: 90, // `Z`
91664
+ leftSquareBracket: 91, // `[`
91665
+ backslash: 92, // `\`
91666
+ rightSquareBracket: 93, // `]`
91667
+ caret: 94, // `^`
91668
+ underscore: 95, // `_`
91669
+ graveAccent: 96, // `` ` ``
91670
+ lowercaseA: 97, // `a`
91671
+ lowercaseB: 98, // `b`
91672
+ lowercaseC: 99, // `c`
91673
+ lowercaseD: 100, // `d`
91674
+ lowercaseE: 101, // `e`
91675
+ lowercaseF: 102, // `f`
91676
+ lowercaseG: 103, // `g`
91677
+ lowercaseH: 104, // `h`
91678
+ lowercaseI: 105, // `i`
91679
+ lowercaseJ: 106, // `j`
91680
+ lowercaseK: 107, // `k`
91681
+ lowercaseL: 108, // `l`
91682
+ lowercaseM: 109, // `m`
91683
+ lowercaseN: 110, // `n`
91684
+ lowercaseO: 111, // `o`
91685
+ lowercaseP: 112, // `p`
91686
+ lowercaseQ: 113, // `q`
91687
+ lowercaseR: 114, // `r`
91688
+ lowercaseS: 115, // `s`
91689
+ lowercaseT: 116, // `t`
91690
+ lowercaseU: 117, // `u`
91691
+ lowercaseV: 118, // `v`
91692
+ lowercaseW: 119, // `w`
91693
+ lowercaseX: 120, // `x`
91694
+ lowercaseY: 121, // `y`
91695
+ lowercaseZ: 122, // `z`
91696
+ leftCurlyBrace: 123, // `{`
91697
+ verticalBar: 124, // `|`
91698
+ rightCurlyBrace: 125, // `}`
91699
+ tilde: 126, // `~`
91700
+ del: 127,
91701
+ // Unicode Specials block.
91702
+ byteOrderMarker: 65_279,
91703
+ // Unicode Specials block.
91704
+ replacementCharacter: 65_533 // `�`
91705
+ })
91706
+
91707
+ ;// ./lib/micromark/gemoji/syntax.ts
91708
+
91709
+ // Matches the name pattern from the original regex: \+1 or [-\w]+
91710
+ // see https://github.com/readmeio/markdown/blob/489a71e19b34f640595ce81e988dad631045186f/processor/transform/gemoji%2B.ts#L9
91711
+ function isNameChar(code) {
91712
+ if (code === null)
91713
+ return false;
91714
+ return ((code >= codes.lowercaseA && code <= codes.lowercaseZ) ||
91715
+ (code >= codes.uppercaseA && code <= codes.uppercaseZ) ||
91716
+ (code >= codes.digit0 && code <= codes.digit9) ||
91717
+ code === codes.dash ||
91718
+ code === codes.underscore);
91719
+ }
91720
+ const gemojiConstruct = {
91721
+ name: 'gemoji',
91722
+ tokenize,
91723
+ };
91724
+ function tokenize(effects, ok, nok) {
91725
+ let hasName = false;
91726
+ // Entry point — expect opening `:`
91727
+ const start = (code) => {
91728
+ if (code !== codes.colon)
91729
+ return nok(code);
91730
+ effects.enter('gemoji');
91731
+ effects.enter('gemojiMarker');
91732
+ effects.consume(code); // :
91733
+ effects.exit('gemojiMarker');
91734
+ effects.enter('gemojiName');
91735
+ return nameStart;
91736
+ };
91737
+ // First char after `:`, branch on `+` for :+1:, otherwise start normal name
91738
+ const nameStart = (code) => {
91739
+ if (code === codes.plusSign) {
91740
+ effects.consume(code); // +
91741
+ return plusOne;
91742
+ }
91743
+ if (isNameChar(code)) {
91744
+ hasName = true;
91745
+ effects.consume(code);
91746
+ return name;
91747
+ }
91748
+ // Not a valid shortcode start (e.g. `::`, `: `, `:<`)
91749
+ return nok(code);
91750
+ };
91751
+ // After `+`, only `1` is valid (for :+1:), anything else rejects
91752
+ // this is a special case for :+1: 👍 since + isnt a normal name character
91753
+ const plusOne = (code) => {
91754
+ if (code === codes.digit1) {
91755
+ hasName = true;
91756
+ effects.consume(code); // 1
91757
+ return nameEnd;
91758
+ }
91759
+ return nok(code);
91760
+ };
91761
+ // Consume name characters until we hit closing `:` or an invalid char
91762
+ const name = (code) => {
91763
+ if (code === codes.colon) {
91764
+ if (!hasName)
91765
+ return nok(code);
91766
+ return nameEnd(code);
91767
+ }
91768
+ if (isNameChar(code)) {
91769
+ effects.consume(code);
91770
+ return name;
91771
+ }
91772
+ // Invalid character in name (space, newline, special char) — reject
91773
+ return nok(code);
91774
+ };
91775
+ // Expect closing `:`
91776
+ const nameEnd = (code) => {
91777
+ if (code !== codes.colon)
91778
+ return nok(code);
91779
+ effects.exit('gemojiName');
91780
+ effects.enter('gemojiMarker');
91781
+ effects.consume(code); // :
91782
+ effects.exit('gemojiMarker');
91783
+ effects.exit('gemoji');
91784
+ return ok;
91785
+ };
91786
+ return start;
91787
+ }
91788
+ function syntax_gemoji() {
91789
+ return {
91790
+ text: { [codes.colon]: gemojiConstruct },
91791
+ };
91792
+ }
91793
+
91794
+ ;// ./lib/micromark/gemoji/index.ts
91795
+ /**
91796
+ * Micromark extension for :emoji: inline syntax.
91797
+ */
91798
+
91799
+
91492
91800
  ;// ./processor/transform/mdxish/normalize-malformed-md-syntax.ts
91493
91801
 
91494
91802
  // Marker patterns for multi-node emphasis detection
@@ -91845,6 +92153,7 @@ const normalizeEmphasisAST = () => (tree) => {
91845
92153
 
91846
92154
 
91847
92155
 
92156
+
91848
92157
  const isTableCell = (node) => isMDXElement(node) && ['th', 'td'].includes(node.name);
91849
92158
  const tableTypes = {
91850
92159
  tr: 'tableRow',
@@ -91852,10 +92161,12 @@ const tableTypes = {
91852
92161
  td: 'tableCell',
91853
92162
  };
91854
92163
  const tableNodeProcessor = unified()
92164
+ .data('micromarkExtensions', [syntax_gemoji()])
92165
+ .data('fromMarkdownExtensions', [gemojiFromMarkdown()])
91855
92166
  .use(remarkParse)
91856
92167
  .use(remarkMdx)
91857
92168
  .use(normalize_malformed_md_syntax)
91858
- .use([[callouts, { isMdxish: true }], gemoji_, code_tabs])
92169
+ .use([[callouts, { isMdxish: true }], code_tabs])
91859
92170
  .use(remarkGfm);
91860
92171
  /**
91861
92172
  * Check if children are only text nodes that might contain markdown
@@ -92728,7 +93039,6 @@ const mdxishTransformers = [
92728
93039
  [callouts, { isMdxish: true }],
92729
93040
  code_tabs,
92730
93041
  transform_images,
92731
- gemoji_,
92732
93042
  ];
92733
93043
  /* harmony default export */ const transform = (Object.values(defaultTransforms));
92734
93044
 
@@ -112510,10 +112820,6 @@ const embed_embed = (node) => {
112510
112820
  };
112511
112821
  /* harmony default export */ const compile_embed = (embed_embed);
112512
112822
 
112513
- ;// ./processor/compile/gemoji.ts
112514
- const gemoji_gemoji = (node) => `:${node.name}:`;
112515
- /* harmony default export */ const compile_gemoji = (gemoji_gemoji);
112516
-
112517
112823
  ;// ./processor/compile/html-block.ts
112518
112824
 
112519
112825
  const htmlBlock = (node) => {
@@ -114496,6 +114802,86 @@ const mdxComponentHandlers = {
114496
114802
  [NodeTypes.htmlBlock]: htmlBlockHandler,
114497
114803
  };
114498
114804
 
114805
+ ;// ./processor/transform/mdxish/close-self-closing-html-tags.ts
114806
+
114807
+ /**
114808
+ * HTML void elements that are legitimately self-closing per the HTML spec.
114809
+ * These should NOT be transformed.
114810
+ *
114811
+ * @see https://html.spec.whatwg.org/multipage/syntax.html#void-elements
114812
+ */
114813
+ const HTML_VOID_ELEMENTS = new Set([
114814
+ 'area',
114815
+ 'base',
114816
+ 'br',
114817
+ 'col',
114818
+ 'embed',
114819
+ 'hr',
114820
+ 'img',
114821
+ 'input',
114822
+ 'link',
114823
+ 'meta',
114824
+ 'param',
114825
+ 'source',
114826
+ 'track',
114827
+ 'wbr',
114828
+ ]);
114829
+ /**
114830
+ * Matches self-closing HTML tags: `<tagname/>` or `<tagname attr="val" />`
114831
+ *
114832
+ * Captures:
114833
+ * 1 - tag name (lowercase letters, digits, hyphens)
114834
+ * 2 - attributes (everything between tag name and `/>`)
114835
+ *
114836
+ * The attribute portion skips over quoted strings (`"..."` and `'...'`) so that
114837
+ * a `/>` inside an attribute value (e.g. `title="use /> here"`) does not cause
114838
+ * a premature match.
114839
+ *
114840
+ * Only matches lowercase tag names to avoid interfering with PascalCase
114841
+ * JSX custom components (e.g. `<MyComponent />`), which are handled
114842
+ * separately by mdxish-component-blocks.
114843
+ */
114844
+ const SELF_CLOSING_TAG_RE = /<([a-z][a-z0-9-]*)((?:\s+(?:[^>"']*(?:"[^"]*"|'[^']*'))*[^>"']*)?)?\s*\/>/g;
114845
+ /**
114846
+ * String-level preprocessor that converts self-closing non-void HTML tags
114847
+ * into explicitly closed tags.
114848
+ *
114849
+ * Problem: `rehype-raw` (via parse5) follows the HTML spec where the `/` in
114850
+ * `<i />` is ignored for non-void elements. This causes `<i />` to be parsed
114851
+ * as an opening `<i>` tag, which then wraps all subsequent content.
114852
+ *
114853
+ * Solution: Transform `<i />` → `<i></i>` before parsing, so rehype-raw
114854
+ * sees a properly closed element.
114855
+ *
114856
+ * This preprocessor:
114857
+ * - Skips void elements (`<br />`, `<hr />`, `<img />`, etc.)
114858
+ * - Skips PascalCase tags (custom components handled elsewhere)
114859
+ * - Protects code blocks from transformation
114860
+ *
114861
+ * @example
114862
+ * closeSelfClosingHtmlTags('<i/> text') // '<i></i> text'
114863
+ * closeSelfClosingHtmlTags('<br />') // '<br />' (void, untouched)
114864
+ * closeSelfClosingHtmlTags('<MyComp />') // '<MyComp />' (PascalCase, untouched)
114865
+ * closeSelfClosingHtmlTags('<i class="icon" />') // '<i class="icon"></i>'
114866
+ */
114867
+ function closeSelfClosingHtmlTags(content) {
114868
+ const { protectedContent, protectedCode } = protectCodeBlocks(content);
114869
+ const result = protectedContent.replace(SELF_CLOSING_TAG_RE, (match, tagName, attrs) => {
114870
+ // Skip void elements (legitimately self-closing)
114871
+ if (HTML_VOID_ELEMENTS.has(tagName)) {
114872
+ return match;
114873
+ }
114874
+ // Skip tags with hyphens — these are custom elements (web components)
114875
+ // and should not be rewritten (e.g. <my-component />)
114876
+ if (tagName.includes('-')) {
114877
+ return match;
114878
+ }
114879
+ const attributes = attrs?.trim() ? ` ${attrs.trim()}` : '';
114880
+ return `<${tagName}${attributes}></${tagName}>`;
114881
+ });
114882
+ return restoreCodeBlocks(result, protectedCode);
114883
+ }
114884
+
114499
114885
  ;// ./processor/transform/mdxish/evaluate-expressions.ts
114500
114886
 
114501
114887
 
@@ -114785,166 +115171,6 @@ function legacyVariableFromMarkdown() {
114785
115171
  };
114786
115172
  }
114787
115173
 
114788
- ;// ./node_modules/micromark-util-symbol/lib/codes.js
114789
- /**
114790
- * Character codes.
114791
- *
114792
- * This module is compiled away!
114793
- *
114794
- * micromark works based on character codes.
114795
- * This module contains constants for the ASCII block and the replacement
114796
- * character.
114797
- * A couple of them are handled in a special way, such as the line endings
114798
- * (CR, LF, and CR+LF, commonly known as end-of-line: EOLs), the tab (horizontal
114799
- * tab) and its expansion based on what column it’s at (virtual space),
114800
- * and the end-of-file (eof) character.
114801
- * As values are preprocessed before handling them, the actual characters LF,
114802
- * CR, HT, and NUL (which is present as the replacement character), are
114803
- * guaranteed to not exist.
114804
- *
114805
- * Unicode basic latin block.
114806
- */
114807
- const codes = /** @type {const} */ ({
114808
- carriageReturn: -5,
114809
- lineFeed: -4,
114810
- carriageReturnLineFeed: -3,
114811
- horizontalTab: -2,
114812
- virtualSpace: -1,
114813
- eof: null,
114814
- nul: 0,
114815
- soh: 1,
114816
- stx: 2,
114817
- etx: 3,
114818
- eot: 4,
114819
- enq: 5,
114820
- ack: 6,
114821
- bel: 7,
114822
- bs: 8,
114823
- ht: 9, // `\t`
114824
- lf: 10, // `\n`
114825
- vt: 11, // `\v`
114826
- ff: 12, // `\f`
114827
- cr: 13, // `\r`
114828
- so: 14,
114829
- si: 15,
114830
- dle: 16,
114831
- dc1: 17,
114832
- dc2: 18,
114833
- dc3: 19,
114834
- dc4: 20,
114835
- nak: 21,
114836
- syn: 22,
114837
- etb: 23,
114838
- can: 24,
114839
- em: 25,
114840
- sub: 26,
114841
- esc: 27,
114842
- fs: 28,
114843
- gs: 29,
114844
- rs: 30,
114845
- us: 31,
114846
- space: 32,
114847
- exclamationMark: 33, // `!`
114848
- quotationMark: 34, // `"`
114849
- numberSign: 35, // `#`
114850
- dollarSign: 36, // `$`
114851
- percentSign: 37, // `%`
114852
- ampersand: 38, // `&`
114853
- apostrophe: 39, // `'`
114854
- leftParenthesis: 40, // `(`
114855
- rightParenthesis: 41, // `)`
114856
- asterisk: 42, // `*`
114857
- plusSign: 43, // `+`
114858
- comma: 44, // `,`
114859
- dash: 45, // `-`
114860
- dot: 46, // `.`
114861
- slash: 47, // `/`
114862
- digit0: 48, // `0`
114863
- digit1: 49, // `1`
114864
- digit2: 50, // `2`
114865
- digit3: 51, // `3`
114866
- digit4: 52, // `4`
114867
- digit5: 53, // `5`
114868
- digit6: 54, // `6`
114869
- digit7: 55, // `7`
114870
- digit8: 56, // `8`
114871
- digit9: 57, // `9`
114872
- colon: 58, // `:`
114873
- semicolon: 59, // `;`
114874
- lessThan: 60, // `<`
114875
- equalsTo: 61, // `=`
114876
- greaterThan: 62, // `>`
114877
- questionMark: 63, // `?`
114878
- atSign: 64, // `@`
114879
- uppercaseA: 65, // `A`
114880
- uppercaseB: 66, // `B`
114881
- uppercaseC: 67, // `C`
114882
- uppercaseD: 68, // `D`
114883
- uppercaseE: 69, // `E`
114884
- uppercaseF: 70, // `F`
114885
- uppercaseG: 71, // `G`
114886
- uppercaseH: 72, // `H`
114887
- uppercaseI: 73, // `I`
114888
- uppercaseJ: 74, // `J`
114889
- uppercaseK: 75, // `K`
114890
- uppercaseL: 76, // `L`
114891
- uppercaseM: 77, // `M`
114892
- uppercaseN: 78, // `N`
114893
- uppercaseO: 79, // `O`
114894
- uppercaseP: 80, // `P`
114895
- uppercaseQ: 81, // `Q`
114896
- uppercaseR: 82, // `R`
114897
- uppercaseS: 83, // `S`
114898
- uppercaseT: 84, // `T`
114899
- uppercaseU: 85, // `U`
114900
- uppercaseV: 86, // `V`
114901
- uppercaseW: 87, // `W`
114902
- uppercaseX: 88, // `X`
114903
- uppercaseY: 89, // `Y`
114904
- uppercaseZ: 90, // `Z`
114905
- leftSquareBracket: 91, // `[`
114906
- backslash: 92, // `\`
114907
- rightSquareBracket: 93, // `]`
114908
- caret: 94, // `^`
114909
- underscore: 95, // `_`
114910
- graveAccent: 96, // `` ` ``
114911
- lowercaseA: 97, // `a`
114912
- lowercaseB: 98, // `b`
114913
- lowercaseC: 99, // `c`
114914
- lowercaseD: 100, // `d`
114915
- lowercaseE: 101, // `e`
114916
- lowercaseF: 102, // `f`
114917
- lowercaseG: 103, // `g`
114918
- lowercaseH: 104, // `h`
114919
- lowercaseI: 105, // `i`
114920
- lowercaseJ: 106, // `j`
114921
- lowercaseK: 107, // `k`
114922
- lowercaseL: 108, // `l`
114923
- lowercaseM: 109, // `m`
114924
- lowercaseN: 110, // `n`
114925
- lowercaseO: 111, // `o`
114926
- lowercaseP: 112, // `p`
114927
- lowercaseQ: 113, // `q`
114928
- lowercaseR: 114, // `r`
114929
- lowercaseS: 115, // `s`
114930
- lowercaseT: 116, // `t`
114931
- lowercaseU: 117, // `u`
114932
- lowercaseV: 118, // `v`
114933
- lowercaseW: 119, // `w`
114934
- lowercaseX: 120, // `x`
114935
- lowercaseY: 121, // `y`
114936
- lowercaseZ: 122, // `z`
114937
- leftCurlyBrace: 123, // `{`
114938
- verticalBar: 124, // `|`
114939
- rightCurlyBrace: 125, // `}`
114940
- tilde: 126, // `~`
114941
- del: 127,
114942
- // Unicode Specials block.
114943
- byteOrderMarker: 65_279,
114944
- // Unicode Specials block.
114945
- replacementCharacter: 65_533 // `�`
114946
- })
114947
-
114948
115174
  ;// ./lib/micromark/legacy-variable/syntax.ts
114949
115175
 
114950
115176
 
@@ -114956,9 +115182,9 @@ function isAllowedValueChar(code) {
114956
115182
  }
114957
115183
  const legacyVariableConstruct = {
114958
115184
  name: 'legacyVariable',
114959
- tokenize,
115185
+ tokenize: syntax_tokenize,
114960
115186
  };
114961
- function tokenize(effects, ok, nok) {
115187
+ function syntax_tokenize(effects, ok, nok) {
114962
115188
  let hasValue = false;
114963
115189
  const start = (code) => {
114964
115190
  if (code !== codes.lessThan)
@@ -116097,6 +116323,8 @@ const EMPTY_CODE_PLACEHOLDER = {
116097
116323
 
116098
116324
 
116099
116325
 
116326
+
116327
+
116100
116328
 
116101
116329
 
116102
116330
 
@@ -116139,8 +116367,8 @@ const preprocessBody = (text) => {
116139
116367
  };
116140
116368
  /** Markdown parser */
116141
116369
  const contentParser = unified()
116142
- .data('micromarkExtensions', [legacyVariable(), looseHtmlEntity()])
116143
- .data('fromMarkdownExtensions', [legacyVariableFromMarkdown(), emptyTaskListItemFromMarkdown(), looseHtmlEntityFromMarkdown()])
116370
+ .data('micromarkExtensions', [syntax_gemoji(), legacyVariable(), looseHtmlEntity()])
116371
+ .data('fromMarkdownExtensions', [gemojiFromMarkdown(), legacyVariableFromMarkdown(), emptyTaskListItemFromMarkdown(), looseHtmlEntityFromMarkdown()])
116144
116372
  .use(remarkParse)
116145
116373
  .use(remarkBreaks)
116146
116374
  .use(remarkGfm)
@@ -116153,8 +116381,8 @@ const contentParser = unified()
116153
116381
  * such as `<ul><li>https://a</li>\n</ul>` due to subtokenizing recursion for URLs
116154
116382
  */
116155
116383
  const markdownToHtml = unified()
116156
- .data('micromarkExtensions', [gfmStrikethrough(), legacyVariable(), looseHtmlEntity()])
116157
- .data('fromMarkdownExtensions', [gfmStrikethroughFromMarkdown(), legacyVariableFromMarkdown(), emptyTaskListItemFromMarkdown(), looseHtmlEntityFromMarkdown()])
116384
+ .data('micromarkExtensions', [gfmStrikethrough(), syntax_gemoji(), legacyVariable(), looseHtmlEntity()])
116385
+ .data('fromMarkdownExtensions', [gfmStrikethroughFromMarkdown(), gemojiFromMarkdown(), legacyVariableFromMarkdown(), emptyTaskListItemFromMarkdown(), looseHtmlEntityFromMarkdown()])
116158
116386
  .use(remarkParse)
116159
116387
  .use(normalize_malformed_md_syntax)
116160
116388
  .use(remarkRehype)
@@ -116295,6 +116523,7 @@ const parseBlock = (text) => {
116295
116523
  */
116296
116524
  const apiHeaderTitleParser = unified()
116297
116525
  .data('micromarkExtensions', [
116526
+ syntax_gemoji(),
116298
116527
  legacyVariable(),
116299
116528
  looseHtmlEntity(),
116300
116529
  {
@@ -116308,7 +116537,7 @@ const apiHeaderTitleParser = unified()
116308
116537
  },
116309
116538
  },
116310
116539
  ])
116311
- .data('fromMarkdownExtensions', [legacyVariableFromMarkdown(), looseHtmlEntityFromMarkdown()])
116540
+ .data('fromMarkdownExtensions', [gemojiFromMarkdown(), legacyVariableFromMarkdown(), looseHtmlEntityFromMarkdown()])
116312
116541
  .use(remarkParse)
116313
116542
  .use(remarkGfm);
116314
116543
  const parseApiHeaderTitle = (text) => {
@@ -117422,6 +117651,179 @@ function mdxish_jsx_to_mdast_extractText(nodes) {
117422
117651
  })
117423
117652
  .join('');
117424
117653
  }
117654
+ const FIGURE_OPEN_REGEX = /^<figure(\s[^>]*)?>$/;
117655
+ const FIGURE_CLOSE_REGEX = /^\s*<\/figure>\s*$/;
117656
+ const FIGURE_COMPLETE_REGEX = /^<figure(\s[^>]*)?>[\s\S]*<\/figure>\s*$/;
117657
+ const FIGCAPTION_REGEX = /<figcaption>(.*?)<\/figcaption>/s;
117658
+ const FIGCAPTION_OPEN_REGEX = /^<figcaption>$/;
117659
+ const FIGCAPTION_CLOSE_REGEX = /^<\/figcaption>$/;
117660
+ /**
117661
+ * Extracts an image or image-block from a node. If the node itself is an image/image-block,
117662
+ * it is returned directly. If the node is a paragraph, its children are searched for one.
117663
+ * This is needed because standalone markdown images (`![](url)`) may be wrapped in a
117664
+ * paragraph node by the parser, or already transformed to image-block by imageTransformer.
117665
+ */
117666
+ function findImageInNode(node) {
117667
+ if (node.type === 'image' || node.type === NodeTypes.imageBlock)
117668
+ return node;
117669
+ if (node.type === 'paragraph') {
117670
+ return node.children.find(child => child.type === 'image' || child.type === NodeTypes.imageBlock);
117671
+ }
117672
+ return undefined;
117673
+ }
117674
+ /**
117675
+ * Parses a complete `<figure>` HTML string into image URL, alt text, and optional caption.
117676
+ * Returns undefined if the HTML doesn't contain a recognizable image.
117677
+ */
117678
+ function parseCompleteFigure(html) {
117679
+ const imageMatch = /!\[([^\]]*)\]\(([^)]+)\)/.exec(html);
117680
+ if (!imageMatch)
117681
+ return undefined;
117682
+ const captionMatch = FIGCAPTION_REGEX.exec(html);
117683
+ return {
117684
+ alt: imageMatch[1],
117685
+ caption: captionMatch?.[1],
117686
+ url: imageMatch[2],
117687
+ };
117688
+ }
117689
+ /**
117690
+ * Builds a FigureNode containing an image and optional figcaption from parsed figure data.
117691
+ */
117692
+ function buildFigureNode(imageNode, captionText, position) {
117693
+ const figureChildren = [imageNode];
117694
+ if (captionText) {
117695
+ figureChildren.push({
117696
+ children: [{ type: 'text', value: captionText }],
117697
+ data: { hName: 'figcaption' },
117698
+ type: 'figcaption',
117699
+ });
117700
+ }
117701
+ return {
117702
+ children: figureChildren,
117703
+ data: { hName: 'figure' },
117704
+ position,
117705
+ type: 'figure',
117706
+ };
117707
+ }
117708
+ /**
117709
+ * Scans siblings starting at `startIndex` within a parent's children looking for the
117710
+ * figcaption text and </figure> closing tag. Handles three fragmentation patterns:
117711
+ *
117712
+ * 1. Combined: `<figcaption>Hello</figcaption>\n</figure>` in one html node
117713
+ * 2. Separate: `<figcaption>Hello</figcaption>` then `</figure>` as sibling html nodes
117714
+ * 3. Split (table cells): `<figcaption>` + text(Hello) + `</figcaption>` + `</figure>` as siblings
117715
+ */
117716
+ function scanForFigcaptionAndClose(children, startIndex) {
117717
+ let captionText;
117718
+ let endIndex = startIndex - 1;
117719
+ let foundClose = false;
117720
+ for (let j = startIndex; j < children.length; j += 1) {
117721
+ const sibling = children[j];
117722
+ const htmlValue = sibling.type === 'html' ? sibling.value : undefined;
117723
+ if (htmlValue === undefined && sibling.type !== 'text')
117724
+ break;
117725
+ // Standalone </figure>
117726
+ if (htmlValue && FIGURE_CLOSE_REGEX.test(htmlValue)) {
117727
+ endIndex = j;
117728
+ foundClose = true;
117729
+ break;
117730
+ }
117731
+ // Combined <figcaption>...</figcaption> in one node (possibly with </figure>)
117732
+ if (htmlValue) {
117733
+ const figcaptionMatch = FIGCAPTION_REGEX.exec(htmlValue);
117734
+ if (figcaptionMatch) {
117735
+ captionText = figcaptionMatch[1];
117736
+ if (FIGURE_CLOSE_REGEX.test(htmlValue.replace(FIGCAPTION_REGEX, ''))) {
117737
+ endIndex = j;
117738
+ foundClose = true;
117739
+ break;
117740
+ }
117741
+ const nextSibling = children[j + 1];
117742
+ if (nextSibling?.type === 'html' && FIGURE_CLOSE_REGEX.test(nextSibling.value)) {
117743
+ endIndex = j + 1;
117744
+ foundClose = true;
117745
+ break;
117746
+ }
117747
+ }
117748
+ }
117749
+ // Split figcaption: <figcaption> + text + </figcaption> as separate nodes (table cells)
117750
+ if (htmlValue && FIGCAPTION_OPEN_REGEX.test(htmlValue)) {
117751
+ const textNode = children[j + 1];
117752
+ const closeCaption = children[j + 2];
117753
+ if (textNode?.type === 'text' &&
117754
+ closeCaption?.type === 'html' &&
117755
+ FIGCAPTION_CLOSE_REGEX.test(closeCaption.value)) {
117756
+ captionText = textNode.value;
117757
+ const closeFigure = children[j + 3];
117758
+ if (closeFigure?.type === 'html' && FIGURE_CLOSE_REGEX.test(closeFigure.value)) {
117759
+ endIndex = j + 3;
117760
+ foundClose = true;
117761
+ break;
117762
+ }
117763
+ }
117764
+ }
117765
+ }
117766
+ return { captionText, endIndex, foundClose };
117767
+ }
117768
+ /**
117769
+ * Reconstruct fragmented or complete HTML <figure> elements into figure MDAST nodes.
117770
+ *
117771
+ * Handles three html-based cases (the JSX case is handled by transformFigure in COMPONENT_MAP):
117772
+ * 1. Complete: A single html node containing the full `<figure>...<figcaption>...</figure>` block
117773
+ * (e.g. inside callouts where blockquote parsing keeps it together).
117774
+ * 2. Fragmented siblings: `terminateHtmlFlowBlocks` splits `<figure>` into separate sibling
117775
+ * nodes (open tag, image, figcaption, close tag).
117776
+ * 3. Split tags (GFM table cells): Each tag becomes its own html node with text nodes between them.
117777
+ *
117778
+ * Runs on all parent nodes so it works inside callouts, tables, and at root level.
117779
+ */
117780
+ function reassembleHtmlFigures(tree) {
117781
+ // Case 1: Handle complete <figure> blocks in a single html node (e.g. inside callouts)
117782
+ visit(tree, 'html', (node, index, parent) => {
117783
+ if (!parent || index === undefined)
117784
+ return;
117785
+ if (!FIGURE_COMPLETE_REGEX.test(node.value.trim()))
117786
+ return;
117787
+ const parsed = parseCompleteFigure(node.value);
117788
+ if (!parsed)
117789
+ return;
117790
+ const imageNode = {
117791
+ type: 'image',
117792
+ url: parsed.url,
117793
+ alt: parsed.alt,
117794
+ };
117795
+ const figureNode = buildFigureNode(imageNode, parsed.caption, node.position);
117796
+ parent.children.splice(index, 1, figureNode);
117797
+ });
117798
+ // Case 2 & 3: Handle fragmented <figure> blocks split across sibling nodes
117799
+ const processChildren = (parent) => {
117800
+ const children = parent.children;
117801
+ let i = 0;
117802
+ while (i < children.length) {
117803
+ const node = children[i];
117804
+ const nextNode = children[i + 1];
117805
+ const imageNode = nextNode ? findImageInNode(nextNode) : undefined;
117806
+ if (node.type === 'html' &&
117807
+ FIGURE_OPEN_REGEX.test(node.value.trim()) &&
117808
+ imageNode) {
117809
+ const { captionText, endIndex, foundClose } = scanForFigcaptionAndClose(children, i + 2);
117810
+ if (foundClose) {
117811
+ const figureNode = buildFigureNode(imageNode, captionText, node.position);
117812
+ parent.children.splice(i, endIndex - i + 1, figureNode);
117813
+ }
117814
+ }
117815
+ i += 1;
117816
+ }
117817
+ };
117818
+ // Process all parent nodes (root, callouts, blockquotes, table cells, list items)
117819
+ visit(tree, (node) => {
117820
+ if ('children' in node)
117821
+ processChildren(node);
117822
+ });
117823
+ }
117824
+ /**
117825
+ * Transforms an inline `<Anchor>` JSX element into a readme-anchor MDAST node.
117826
+ */
117425
117827
  const transformAnchor = (jsx) => {
117426
117828
  const attrs = getAttrs(jsx);
117427
117829
  const { href = '', label, target, title } = attrs;
@@ -117440,6 +117842,10 @@ const transformAnchor = (jsx) => {
117440
117842
  position: jsx.position,
117441
117843
  };
117442
117844
  };
117845
+ /**
117846
+ * Transforms an `<Image />` JSX element into an image-block MDAST node.
117847
+ * Normalizes attributes (align, border, width→sizing) and parses caption markdown into children.
117848
+ */
117443
117849
  const transformImage = (jsx) => {
117444
117850
  const attrs = getAttrs(jsx);
117445
117851
  const { align, alt = '', border, caption, className, height, lazy, src = '', title = '', width } = attrs;
@@ -117479,6 +117885,9 @@ const transformImage = (jsx) => {
117479
117885
  position: jsx.position,
117480
117886
  };
117481
117887
  };
117888
+ /**
117889
+ * Transforms a `<Callout>` JSX element into an rdme-callout MDAST node.
117890
+ */
117482
117891
  const transformCallout = (jsx) => {
117483
117892
  const attrs = getAttrs(jsx);
117484
117893
  const { empty = false, icon = '', theme = '' } = attrs;
@@ -117496,6 +117905,9 @@ const transformCallout = (jsx) => {
117496
117905
  position: jsx.position,
117497
117906
  };
117498
117907
  };
117908
+ /**
117909
+ * Transforms an `<Embed />` JSX element into an embed-block MDAST node.
117910
+ */
117499
117911
  const transformEmbed = (jsx) => {
117500
117912
  const attrs = getAttrs(jsx);
117501
117913
  const { favicon, height, href, html, iframe, image, providerName, providerUrl, provider, title = '', typeOfEmbed, url = '', width, } = attrs;
@@ -117524,6 +117936,9 @@ const transformEmbed = (jsx) => {
117524
117936
  position: jsx.position,
117525
117937
  };
117526
117938
  };
117939
+ /**
117940
+ * Transforms a `<Recipe />` JSX element into a recipe MDAST node.
117941
+ */
117527
117942
  const transformRecipe = (jsx) => {
117528
117943
  const attrs = getAttrs(jsx);
117529
117944
  const { backgroundColor = '', emoji = '', id = '', link = '', slug = '', title = '' } = attrs;
@@ -117660,21 +118075,44 @@ const transformTable = (jsx) => {
117660
118075
  children: rows,
117661
118076
  };
117662
118077
  };
118078
+ /**
118079
+ * Transforms a `<figure>` JSX element into a FigureNode.
118080
+ * Inside JSX tables with blank lines, the parser treats `<figure>` as an mdxJsxFlowElement
118081
+ * containing a paragraph with the image and a `<figcaption>` mdxJsxTextElement as children.
118082
+ */
118083
+ const transformFigure = (jsx) => {
118084
+ let imageNode;
118085
+ let captionText;
118086
+ visit(jsx, (child) => {
118087
+ if (!imageNode && (child.type === 'image' || child.type === NodeTypes.imageBlock)) {
118088
+ imageNode = child;
118089
+ }
118090
+ if (!captionText && child.type === 'mdxJsxTextElement' && child.name === 'figcaption') {
118091
+ captionText = mdxish_jsx_to_mdast_extractText(child.children);
118092
+ }
118093
+ });
118094
+ if (!imageNode)
118095
+ return null;
118096
+ return buildFigureNode(imageNode, captionText, jsx.position);
118097
+ };
117663
118098
  const COMPONENT_MAP = {
117664
118099
  Callout: transformCallout,
117665
118100
  Embed: transformEmbed,
117666
118101
  Image: transformImage,
118102
+ figure: transformFigure,
117667
118103
  Recipe: transformRecipe,
117668
118104
  Table: transformTable,
117669
118105
  };
117670
118106
  /**
117671
- * Transform mdxJsxFlowElement nodes and magic block nodes into proper MDAST node types.
118107
+ * Transform mdxJsxFlowElement nodes, magic block nodes, and HTML figure elements
118108
+ * into proper MDAST node types.
117672
118109
  *
117673
118110
  * This transformer runs after mdxishComponentBlocks and converts:
117674
- * - JSX component elements (Image, Callout, Embed, Recipe) into their corresponding MDAST types
118111
+ * - JSX component elements (Image, Callout, Embed, Recipe, figure) into their corresponding MDAST types
117675
118112
  * - Magic block image nodes (type: 'image') into image-block
117676
118113
  * - Magic block embed nodes (type: 'embed') into embed-block
117677
- * - Figure nodes (magic blocks with captions) into flat image-block with caption string
118114
+ * - Fragmented HTML <figure> blocks (from terminateHtmlFlowBlocks) back into figure nodes
118115
+ * - Figure nodes (from magic blocks, HTML, or JSX) into flat image-block with caption string
117678
118116
  * - Normalizes all image-block attrs (border, align, sizing, caption) to a consistent shape
117679
118117
  *
117680
118118
  * This is controlled by the `newEditorTypes` flag to maintain backwards compatibility.
@@ -117721,6 +118159,9 @@ const mdxishJsxToMdast = () => tree => {
117721
118159
  parent.children[index] = newNode;
117722
118160
  return SKIP;
117723
118161
  });
118162
+ // Reassembling fragmented HTML <figure> blocks into proper figure/figcaption nodes
118163
+ // this will then later be transformed into image-block nodes by imageTransformer
118164
+ reassembleHtmlFigures(tree);
117724
118165
  // Flatten figure nodes (magic blocks with captions) into image-block nodes
117725
118166
  const isFigure = (node) => node.type === 'figure';
117726
118167
  visit(tree, isFigure, (node, index, parent) => {
@@ -117973,6 +118414,7 @@ function restoreSnakeCase(placeholderName, mapping) {
117973
118414
  ;// ./processor/transform/mdxish/mdxish-tables-to-jsx.ts
117974
118415
 
117975
118416
 
118417
+ const SELF_CLOSING_JSX_REGEX = /^\s*<[A-Z][^>]*\/>\s*$/;
117976
118418
  const mdxish_tables_to_jsx_alignToStyle = (align) => {
117977
118419
  if (!align || align === 'left')
117978
118420
  return null;
@@ -117999,7 +118441,7 @@ const mdxishTablesToJsx = () => tree => {
117999
118441
  visit(tree, (node) => ['table', 'tableau'].includes(node.type), (table, index, parent) => {
118000
118442
  let hasFlowContent = false;
118001
118443
  visit(table, mdxish_tables_to_jsx_isTableCell, (cell) => {
118002
- if (cell.children.length === 0)
118444
+ if (hasFlowContent || cell.children.length === 0)
118003
118445
  return;
118004
118446
  const content = cell.children.length === 1 && cell.children[0].type === 'paragraph'
118005
118447
  ? cell.children[0].children[0]
@@ -118010,17 +118452,21 @@ const mdxishTablesToJsx = () => tree => {
118010
118452
  breakParent.children.splice(breakIndex, 1, { type: 'text', value: '\n' });
118011
118453
  });
118012
118454
  if (!(phrasing(content) || content.type === 'plain') && content.type !== 'escape') {
118013
- if (content.type === 'html')
118014
- return;
118015
- hasFlowContent = true;
118016
- return EXIT;
118017
- }
118018
- visit(cell, mdxish_tables_to_jsx_isLiteral, (node) => {
118019
- if (node.value.match(/\n/)) {
118455
+ // Plain HTML (e.g. <div>Hello</div>) is skipped here — it stays in GFM cells fine.
118456
+ // But self-closing JSX components (e.g. <Image src="..." caption="..." />) serialize
118457
+ // with newlines that break GFM cells, so they must trigger JSX <Table> serialization.
118458
+ const isPlainHtml = content.type === 'html' && !SELF_CLOSING_JSX_REGEX.test(content.value);
118459
+ if (!isPlainHtml) {
118020
118460
  hasFlowContent = true;
118021
- return EXIT;
118022
118461
  }
118023
- });
118462
+ }
118463
+ if (!hasFlowContent) {
118464
+ visit(cell, mdxish_tables_to_jsx_isLiteral, (node) => {
118465
+ if (node.value.match(/\n/)) {
118466
+ hasFlowContent = true;
118467
+ }
118468
+ });
118469
+ }
118024
118470
  });
118025
118471
  if (!hasFlowContent) {
118026
118472
  table.type = 'table';
@@ -120260,13 +120706,14 @@ function loadComponents() {
120260
120706
 
120261
120707
 
120262
120708
 
120709
+
120710
+
120263
120711
 
120264
120712
 
120265
120713
 
120266
120714
  const defaultTransformers = [
120267
120715
  [callouts, { isMdxish: true }],
120268
120716
  code_tabs,
120269
- gemoji_,
120270
120717
  transform_embeds,
120271
120718
  ];
120272
120719
  /**
@@ -120276,13 +120723,15 @@ const defaultTransformers = [
120276
120723
  * Runs a series of string-level transformations before micromark/remark parsing:
120277
120724
  * 1. Normalize malformed table separator syntax (e.g., `|: ---` → `| :---`)
120278
120725
  * 2. Terminate HTML flow blocks so subsequent content isn't swallowed
120279
- * 3. Evaluate JSX expressions in attributes (unless safeMode)
120280
- * 4. Replace snake_case component names with parser-safe placeholders
120726
+ * 3. Close invalid "self-closing" HTML tags (e.g., `<i />` → `<i></i>`)
120727
+ * 4. Evaluate JSX expressions in attributes (unless safeMode)
120728
+ * 5. Replace snake_case component names with parser-safe placeholders
120281
120729
  */
120282
120730
  function preprocessContent(content, opts) {
120283
120731
  const { safeMode, jsxContext, knownComponents } = opts;
120284
120732
  let result = normalizeTableSeparator(content);
120285
120733
  result = terminateHtmlFlowBlocks(result);
120734
+ result = closeSelfClosingHtmlTags(result);
120286
120735
  result = safeMode ? result : preprocessJSXExpressions(result, jsxContext);
120287
120736
  return processSnakeCaseComponent(result, { knownComponents });
120288
120737
  }
@@ -120312,12 +120761,13 @@ function mdxishAstProcessor(mdContent, opts = {}) {
120312
120761
  };
120313
120762
  const processor = unified()
120314
120763
  .data('micromarkExtensions', safeMode
120315
- ? [jsxTable(), magicBlock(), legacyVariable(), looseHtmlEntity()]
120316
- : [jsxTable(), magicBlock(), mdxExprTextOnly, legacyVariable(), looseHtmlEntity()])
120764
+ ? [jsxTable(), magicBlock(), syntax_gemoji(), legacyVariable(), looseHtmlEntity()]
120765
+ : [jsxTable(), magicBlock(), syntax_gemoji(), mdxExprTextOnly, legacyVariable(), looseHtmlEntity()])
120317
120766
  .data('fromMarkdownExtensions', safeMode
120318
120767
  ? [
120319
120768
  jsxTableFromMarkdown(),
120320
120769
  magicBlockFromMarkdown(),
120770
+ gemojiFromMarkdown(),
120321
120771
  legacyVariableFromMarkdown(),
120322
120772
  emptyTaskListItemFromMarkdown(),
120323
120773
  looseHtmlEntityFromMarkdown(),
@@ -120325,6 +120775,7 @@ function mdxishAstProcessor(mdContent, opts = {}) {
120325
120775
  : [
120326
120776
  jsxTableFromMarkdown(),
120327
120777
  magicBlockFromMarkdown(),
120778
+ gemojiFromMarkdown(),
120328
120779
  mdxExpressionFromMarkdown(),
120329
120780
  legacyVariableFromMarkdown(),
120330
120781
  emptyTaskListItemFromMarkdown(),