@readme/markdown 13.6.2 → 13.7.0

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
@@ -1,13 +1,13 @@
1
1
  (function webpackUniversalModuleDefinition(root, factory) {
2
2
  if(typeof exports === 'object' && typeof module === 'object')
3
- module.exports = factory(require("@readme/syntax-highlighter"), require("@readme/variable"), require("@tippyjs/react"), require("acorn"), require("mermaid"), require("react"));
3
+ module.exports = factory(require("@readme/syntax-highlighter"), require("@readme/variable"), require("@tippyjs/react"), require("acorn"), require("mermaid"), require("react"), require("react-dom"));
4
4
  else if(typeof define === 'function' && define.amd)
5
- define(["@readme/syntax-highlighter", "@readme/variable", "@tippyjs/react", "acorn", "mermaid", "react"], factory);
5
+ define(["@readme/syntax-highlighter", "@readme/variable", "@tippyjs/react", "acorn", "mermaid", "react", "react-dom"], factory);
6
6
  else {
7
- var a = typeof exports === 'object' ? factory(require("@readme/syntax-highlighter"), require("@readme/variable"), require("@tippyjs/react"), require("acorn"), require("mermaid"), require("react")) : factory(root["@readme/syntax-highlighter"], root["@readme/variable"], root["@tippyjs/react"], root["acorn"], root["mermaid"], root["React"]);
7
+ var a = typeof exports === 'object' ? factory(require("@readme/syntax-highlighter"), require("@readme/variable"), require("@tippyjs/react"), require("acorn"), require("mermaid"), require("react"), require("react-dom")) : factory(root["@readme/syntax-highlighter"], root["@readme/variable"], root["@tippyjs/react"], root["acorn"], root["mermaid"], root["React"], root["ReactDOM"]);
8
8
  for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
9
9
  }
10
- })(self, (__WEBPACK_EXTERNAL_MODULE__3966__, __WEBPACK_EXTERNAL_MODULE__8167__, __WEBPACK_EXTERNAL_MODULE__4189__, __WEBPACK_EXTERNAL_MODULE__6473__, __WEBPACK_EXTERNAL_MODULE__1387__, __WEBPACK_EXTERNAL_MODULE__1307__) => {
10
+ })(self, (__WEBPACK_EXTERNAL_MODULE__3966__, __WEBPACK_EXTERNAL_MODULE__8167__, __WEBPACK_EXTERNAL_MODULE__4189__, __WEBPACK_EXTERNAL_MODULE__6473__, __WEBPACK_EXTERNAL_MODULE__1387__, __WEBPACK_EXTERNAL_MODULE__1307__, __WEBPACK_EXTERNAL_MODULE__8759__) => {
11
11
  return /******/ (() => { // webpackBootstrap
12
12
  /******/ var __webpack_modules__ = ({
13
13
 
@@ -11149,6 +11149,14 @@ module.exports = __WEBPACK_EXTERNAL_MODULE__1307__;
11149
11149
 
11150
11150
  /***/ }),
11151
11151
 
11152
+ /***/ 8759:
11153
+ /***/ ((module) => {
11154
+
11155
+ "use strict";
11156
+ module.exports = __WEBPACK_EXTERNAL_MODULE__8759__;
11157
+
11158
+ /***/ }),
11159
+
11152
11160
  /***/ 9746:
11153
11161
  /***/ (() => {
11154
11162
 
@@ -11906,8 +11914,20 @@ const CreateHeading = (depth) => {
11906
11914
  };
11907
11915
  /* harmony default export */ const components_Heading = (CreateHeading);
11908
11916
 
11917
+ // EXTERNAL MODULE: external {"amd":"react-dom","commonjs2":"react-dom","commonjs":"react-dom","root":"ReactDOM","umd":"react-dom"}
11918
+ var external_amd_react_dom_commonjs2_react_dom_commonjs_react_dom_root_ReactDOM_umd_react_dom_ = __webpack_require__(8759);
11909
11919
  ;// ./components/Image/index.tsx
11910
11920
 
11921
+
11922
+ /**
11923
+ * Renders lightbox overlay via a React portal to document.body so it escapes
11924
+ * any intermediate CSS stacking contexts and reliably covers all UI chrome.
11925
+ */
11926
+ const LightboxPortal = ({ children }) => {
11927
+ if (typeof document === 'undefined')
11928
+ return null;
11929
+ return (0,external_amd_react_dom_commonjs2_react_dom_commonjs_react_dom_root_ReactDOM_umd_react_dom_.createPortal)(children, document.body);
11930
+ };
11911
11931
  const Image = (Props) => {
11912
11932
  const { align = '', alt = '', border: borderProp = false, caption, className = '', height = 'auto', src, title = '', width = 'auto', lazy = true, children, } = Props;
11913
11933
  // Normalize border: MDXish passes {false} as the string "false", not a boolean
@@ -11940,20 +11960,27 @@ const Image = (Props) => {
11940
11960
  return;
11941
11961
  setLightbox(!lightbox);
11942
11962
  };
11963
+ const imgElement = (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("img", { alt: alt, className: `img ${caption || children ? 'img-align-center' : align ? `img-align-${align}` : ''} ${border ? 'border' : ''}`, height: height, loading: lazy ? 'lazy' : 'eager', src: src, title: title, width: width }));
11964
+ const lightboxOverlay = lightbox ? (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement(LightboxPortal, null,
11965
+ external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("div", { className: "markdown-body" },
11966
+ external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("span", { "aria-label": alt || 'Collapse image', className: "img lightbox open", onClick: toggle, onKeyDown: handleKeyDown, role: 'button', tabIndex: 0 },
11967
+ external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("span", { className: "lightbox-inner" },
11968
+ imgElement,
11969
+ (children || caption) && external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("figcaption", null, children || caption))),
11970
+ external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("button", { "aria-label": "Minimize image", className: "lightbox-close", onClick: toggle, type: "button" },
11971
+ external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("i", { "aria-hidden": "true", className: "fa-solid fa-xmark" }))))) : null;
11943
11972
  if (children || caption) {
11944
11973
  return (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("figure", null,
11945
- external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("span", { "aria-label": alt, className: `img lightbox ${lightbox ? 'open' : 'closed'}`, onClick: toggle, onKeyDown: handleKeyDown, role: 'button', tabIndex: 0 },
11974
+ external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("span", { "aria-label": alt, className: "img lightbox closed", onClick: toggle, onKeyDown: handleKeyDown, role: 'button', tabIndex: 0 },
11946
11975
  external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("span", { className: "lightbox-inner" },
11947
- external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("img", { alt: alt, className: `img img-align-center ${border ? 'border' : ''}`, height: height, loading: lazy ? 'lazy' : 'eager', src: src, title: title, width: width }),
11976
+ imgElement,
11948
11977
  external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("figcaption", null, children || caption))),
11949
- lightbox && (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("button", { "aria-label": "Minimize image", className: "lightbox-close", type: "button" },
11950
- external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("i", { "aria-hidden": "true", className: "fa-solid fa-xmark" })))));
11951
- }
11952
- return (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("span", { "aria-label": `${lightbox ? 'Collapse image' : 'Expand image'}`, className: `img lightbox ${lightbox ? 'open' : 'closed'}`, onClick: toggle, onKeyDown: handleKeyDown, role: 'button', tabIndex: 0 },
11953
- external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("span", { className: "lightbox-inner" },
11954
- external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("img", { alt: alt, className: `img ${align ? `img-align-${align}` : ''} ${border ? 'border' : ''}`, height: height, loading: lazy ? 'lazy' : 'eager', src: src, title: title, width: width })),
11955
- lightbox && (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("button", { "aria-label": "Minimize image", className: "lightbox-close", type: "button" },
11956
- external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("i", { "aria-hidden": "true", className: "fa-solid fa-xmark" })))));
11978
+ lightboxOverlay));
11979
+ }
11980
+ return (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement(external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.Fragment, null,
11981
+ external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("span", { "aria-label": "Expand image", className: "img lightbox closed", onClick: toggle, onKeyDown: handleKeyDown, role: 'button', tabIndex: 0 },
11982
+ external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createElement("span", { className: "lightbox-inner" }, imgElement)),
11983
+ lightboxOverlay));
11957
11984
  };
11958
11985
  /* harmony default export */ const components_Image = (Image);
11959
11986
 
@@ -32830,13 +32857,9 @@ function listItemWithTaskListItem(node, parent, state, info) {
32830
32857
 
32831
32858
  ;// ./node_modules/mdast-util-gfm/lib/index.js
32832
32859
  /**
32833
- * @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension
32834
- * @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension
32835
- */
32836
-
32837
- /**
32838
- * @typedef {import('mdast-util-gfm-table').Options} Options
32839
- * Configuration.
32860
+ * @import {Extension as FromMarkdownExtension} from 'mdast-util-from-markdown'
32861
+ * @import {Options} from 'mdast-util-gfm'
32862
+ * @import {Options as ToMarkdownExtension} from 'mdast-util-to-markdown'
32840
32863
  */
32841
32864
 
32842
32865
 
@@ -32868,7 +32891,7 @@ function gfmFromMarkdown() {
32868
32891
  * literals, footnotes, strikethrough, tables, tasklists).
32869
32892
  *
32870
32893
  * @param {Options | null | undefined} [options]
32871
- * Configuration.
32894
+ * Configuration (optional).
32872
32895
  * @returns {ToMarkdownExtension}
32873
32896
  * Extension for `mdast-util-to-markdown` to enable GFM (autolink literals,
32874
32897
  * footnotes, strikethrough, tables, tasklists).
@@ -32877,7 +32900,7 @@ function gfmToMarkdown(options) {
32877
32900
  return {
32878
32901
  extensions: [
32879
32902
  gfmAutolinkLiteralToMarkdown(),
32880
- gfmFootnoteToMarkdown(),
32903
+ gfmFootnoteToMarkdown(options),
32881
32904
  gfmStrikethroughToMarkdown(),
32882
32905
  gfmTableToMarkdown(options),
32883
32906
  gfmTaskListItemToMarkdown()
@@ -53081,7 +53104,7 @@ const titleParser = unified().use(remarkParse).use(remarkGfm);
53081
53104
  // The title paragraph may contain custom AST nodes that `toMarkdown` doesn't
53082
53105
  // natively understand
53083
53106
  const toMarkdownExtensions = [
53084
- gfmStrikethroughToMarkdown(),
53107
+ gfmToMarkdown(),
53085
53108
  // For mdx variable syntaxes (e.g., {user.name})
53086
53109
  mdxExpressionToMarkdown(),
53087
53110
  // Important: This is required and would crash the parser if there's no variable node handler
@@ -53173,7 +53196,7 @@ const removeIconPrefix = (paragraph, prefixLength) => {
53173
53196
  firstTextNode.value = firstTextNode.value.slice(prefixLength);
53174
53197
  }
53175
53198
  };
53176
- const processBlockquote = (node, index, parent) => {
53199
+ const processBlockquote = (node, index, parent, isMdxish = false) => {
53177
53200
  if (!isCalloutStructure(node)) {
53178
53201
  // Only stringify empty blockquotes (no extractable text content)
53179
53202
  // Preserve blockquotes with actual content (e.g., headings, lists, etc.)
@@ -53221,7 +53244,11 @@ const processBlockquote = (node, index, parent) => {
53221
53244
  node.children[0].position.start.offset += match.length;
53222
53245
  node.children[0].position.start.column += match.length;
53223
53246
  }
53224
- else {
53247
+ else if (isMdxish) {
53248
+ // Block-level title re-parsing is only needed for MDXish where HTML stays
53249
+ // as raw nodes. In MDX, remarkMdx has already converted HTML to JSX AST
53250
+ // nodes which toMarkdown can't serialize — and MDX doesn't need this
53251
+ // block-level title handling anyway.
53225
53252
  const headingText = toMarkdown({ type: 'root', children: [firstParagraph] }, {
53226
53253
  extensions: toMarkdownExtensions,
53227
53254
  })
@@ -53247,6 +53274,11 @@ const processBlockquote = (node, index, parent) => {
53247
53274
  node.children[0].position.start.column += match.length;
53248
53275
  }
53249
53276
  }
53277
+ else {
53278
+ node.children[0] = wrapHeading(node);
53279
+ node.children[0].position.start.offset += match.length;
53280
+ node.children[0].position.start.column += match.length;
53281
+ }
53250
53282
  }
53251
53283
  // Insert body content as a separate paragraph after the heading
53252
53284
  if (bodyChildren) {
@@ -53277,10 +53309,10 @@ const processBlockquote = (node, index, parent) => {
53277
53309
  });
53278
53310
  }
53279
53311
  };
53280
- const calloutTransformer = () => {
53312
+ const calloutTransformer = ({ isMdxish = false } = {}) => {
53281
53313
  const processNode = (root) => {
53282
53314
  visit(root, 'blockquote', (node, index, parent) => {
53283
- processBlockquote(node, index, parent);
53315
+ processBlockquote(node, index, parent, isMdxish);
53284
53316
  if (node.type === NodeTypes.callout) {
53285
53317
  // SKIP prevents re-processing synthetic blockquotes in parsed title content
53286
53318
  // (e.g., blockquotes from "> Quote" titles). Recursively process body children
@@ -71273,7 +71305,7 @@ const tableNodeProcessor = unified()
71273
71305
  .use(remarkParse)
71274
71306
  .use(remarkMdx)
71275
71307
  .use(normalize_malformed_md_syntax)
71276
- .use([callouts, gemoji_, code_tabs])
71308
+ .use([[callouts, { isMdxish: true }], gemoji_, code_tabs])
71277
71309
  .use(remarkGfm);
71278
71310
  /**
71279
71311
  * Check if children are only text nodes that might contain markdown
@@ -72142,7 +72174,12 @@ const defaultTransforms = {
72142
72174
  imageTransformer: transform_images,
72143
72175
  gemojiTransformer: gemoji_,
72144
72176
  };
72145
- const mdxishTransformers = [callouts, code_tabs, transform_images, gemoji_];
72177
+ const mdxishTransformers = [
72178
+ [callouts, { isMdxish: true }],
72179
+ code_tabs,
72180
+ transform_images,
72181
+ gemoji_,
72182
+ ];
72146
72183
  /* harmony default export */ const transform = (Object.values(defaultTransforms));
72147
72184
 
72148
72185
  ;// ./lib/ast-processor.ts
@@ -95451,7 +95488,7 @@ function transformMagicBlock(blockType, data, rawValue, options = {}) {
95451
95488
  data: {
95452
95489
  hProperties: {
95453
95490
  ...(imgData.align && { align: imgData.align }),
95454
- ...(imgData.border && { border: imgData.border.toString() }),
95491
+ ...(imgData.border !== undefined && { border: String(imgData.border) !== 'false' }),
95455
95492
  ...(imgData.sizing && { width: imgWidthBySize[imgData.sizing] }),
95456
95493
  },
95457
95494
  },
@@ -95730,7 +95767,7 @@ const constants_INLINE_COMPONENT_TAGS = new Set(['Anchor']);
95730
95767
 
95731
95768
 
95732
95769
 
95733
- const pascalCaseTagPattern = /^<([A-Z][A-Za-z0-9_]*)([^>]*?)(\/?)>([\s\S]*)?$/;
95770
+ const pascalCaseTagPattern = /^<([A-Z][A-Za-z0-9_]*)((?:[^>"']|"[^"]*"|'[^']*')*?)(\/?)>([\s\S]*)?$/;
95734
95771
  const tagAttributePattern = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*("[^"]*"|'[^']*'|[^\s"'>]+))?/g;
95735
95772
  /**
95736
95773
  * Maximum number of siblings to scan forward when looking for a closing tag
@@ -96454,6 +96491,30 @@ const mdxishInlineComponents = () => tree => {
96454
96491
 
96455
96492
 
96456
96493
 
96494
+ function toImageAlign(value) {
96495
+ if (value === 'left' || value === 'center' || value === 'right') {
96496
+ return value;
96497
+ }
96498
+ return undefined;
96499
+ }
96500
+ function toBool(value) {
96501
+ if (value === undefined)
96502
+ return undefined;
96503
+ if (typeof value === 'boolean')
96504
+ return value;
96505
+ return value !== '' && value !== 'false';
96506
+ }
96507
+ function mdxish_jsx_to_mdast_extractText(nodes) {
96508
+ return nodes
96509
+ .map(n => {
96510
+ if ('value' in n && typeof n.value === 'string')
96511
+ return n.value;
96512
+ if ('children' in n)
96513
+ return mdxish_jsx_to_mdast_extractText(n.children);
96514
+ return '';
96515
+ })
96516
+ .join('');
96517
+ }
96457
96518
  const transformAnchor = (jsx) => {
96458
96519
  const attrs = getAttrs(jsx);
96459
96520
  const { href = '', label, target, title } = attrs;
@@ -96475,31 +96536,35 @@ const transformAnchor = (jsx) => {
96475
96536
  const transformImage = (jsx) => {
96476
96537
  const attrs = getAttrs(jsx);
96477
96538
  const { align, alt = '', border, caption, className, height, lazy, src = '', title = '', width } = attrs;
96539
+ const validAlign = toImageAlign(align);
96540
+ const sizing = width !== undefined ? String(width) : undefined;
96478
96541
  const hProperties = {
96479
96542
  alt,
96480
96543
  src,
96481
96544
  title,
96482
- ...(align && { align }),
96483
- ...(border !== undefined && { border: String(border) }),
96545
+ ...(validAlign && { align: validAlign }),
96546
+ ...(border !== undefined && { border: toBool(border) }),
96484
96547
  ...(caption && { caption }),
96485
96548
  ...(className && { className }),
96486
96549
  ...(height !== undefined && { height: String(height) }),
96487
- ...(lazy !== undefined && { lazy }),
96488
- ...(width !== undefined && { width: String(width) }),
96550
+ ...(lazy !== undefined && { lazy: toBool(lazy) }),
96551
+ ...(sizing && { sizing }),
96552
+ ...(sizing && { width: sizing }),
96489
96553
  };
96490
96554
  return {
96491
96555
  type: NodeTypes.imageBlock,
96492
- align,
96556
+ align: validAlign,
96493
96557
  alt,
96494
- border: border !== undefined ? String(border) : undefined,
96558
+ border: toBool(border),
96495
96559
  caption,
96496
96560
  children: caption ? lib_mdast(caption).children : [],
96497
96561
  className,
96498
96562
  height: height !== undefined ? String(height) : undefined,
96499
- lazy,
96563
+ lazy: toBool(lazy),
96564
+ sizing,
96500
96565
  src,
96501
96566
  title,
96502
- width: width !== undefined ? String(width) : undefined,
96567
+ width: sizing,
96503
96568
  data: {
96504
96569
  hName: 'img',
96505
96570
  hProperties,
@@ -96526,7 +96591,7 @@ const transformCallout = (jsx) => {
96526
96591
  };
96527
96592
  const transformEmbed = (jsx) => {
96528
96593
  const attrs = getAttrs(jsx);
96529
- const { favicon, height, html, iframe, image, providerName, providerUrl, title = '', typeOfEmbed, url = '', width } = attrs;
96594
+ const { favicon, height, html, iframe, image, providerName, providerUrl, title = '', typeOfEmbed, url = '', width, } = attrs;
96530
96595
  return {
96531
96596
  type: NodeTypes.embedBlock,
96532
96597
  title,
@@ -96572,22 +96637,26 @@ const transformMagicBlockImage = (node) => {
96572
96637
  const { alt = '', data, position, title = '', url = '' } = node;
96573
96638
  const hProps = data?.hProperties || {};
96574
96639
  const { align, border, width } = hProps;
96640
+ const validAlign = toImageAlign(align);
96641
+ const sizing = width || undefined;
96575
96642
  const hProperties = {
96576
96643
  alt,
96577
96644
  src: url,
96578
96645
  title,
96579
- ...(align && { align }),
96580
- ...(border && { border }),
96581
- ...(width && { width }),
96646
+ ...(validAlign && { align: validAlign }),
96647
+ ...(border !== undefined && { border: toBool(border) }),
96648
+ ...(sizing && { sizing }),
96649
+ ...(sizing && { width: sizing }),
96582
96650
  };
96583
96651
  return {
96584
96652
  type: NodeTypes.imageBlock,
96585
- align,
96653
+ align: validAlign,
96586
96654
  alt,
96587
- border,
96655
+ border: toBool(border),
96656
+ sizing,
96588
96657
  src: url,
96589
96658
  title,
96590
- width,
96659
+ width: sizing,
96591
96660
  data: {
96592
96661
  hName: 'img',
96593
96662
  hProperties,
@@ -96635,7 +96704,8 @@ const COMPONENT_MAP = {
96635
96704
  * - JSX component elements (Image, Callout, Embed, Recipe) into their corresponding MDAST types
96636
96705
  * - Magic block image nodes (type: 'image') into image-block
96637
96706
  * - Magic block embed nodes (type: 'embed') into embed-block
96638
- * - Figure nodes containing images (from magic blocks with captions) - transforms the inner image
96707
+ * - Figure nodes (magic blocks with captions) into flat image-block with caption string
96708
+ * - Normalizes all image-block attrs (border, align, sizing, caption) to a consistent shape
96639
96709
  *
96640
96710
  * This is controlled by the `newEditorTypes` flag to maintain backwards compatibility.
96641
96711
  */
@@ -96661,12 +96731,10 @@ const mdxishJsxToMdast = () => tree => {
96661
96731
  }
96662
96732
  });
96663
96733
  // Transform magic block images (type: 'image') to image-block
96664
- // Note: Standard markdown images are wrapped in paragraphs and handled by imageTransformer
96665
- // Magic block images are direct children of root, so we handle them here
96734
+ // Images inside paragraphs are standard markdown handled by imageTransformer, normalized below
96666
96735
  visit(tree, 'image', (node, index, parent) => {
96667
96736
  if (!parent || index === undefined)
96668
96737
  return SKIP;
96669
- // Skip images inside paragraphs (those are standard markdown images handled by imageTransformer)
96670
96738
  if (parent.type === 'paragraph')
96671
96739
  return SKIP;
96672
96740
  const newNode = transformMagicBlockImage(node);
@@ -96681,16 +96749,74 @@ const mdxishJsxToMdast = () => tree => {
96681
96749
  parent.children[index] = newNode;
96682
96750
  return SKIP;
96683
96751
  });
96684
- // Transform images inside figure nodes (magic blocks with captions)
96752
+ // Flatten figure nodes (magic blocks with captions) into image-block nodes
96685
96753
  const isFigure = (node) => node.type === 'figure';
96686
- visit(tree, isFigure, node => {
96687
- // Find and transform the image child
96688
- node.children = node.children.map(child => {
96689
- if (child.type === 'image') {
96690
- return transformMagicBlockImage(child);
96691
- }
96692
- return child;
96693
- });
96754
+ visit(tree, isFigure, (node, index, parent) => {
96755
+ if (!parent || index === undefined)
96756
+ return;
96757
+ const imageChild = node.children.find(child => child.type === 'image' || child.type === NodeTypes.imageBlock);
96758
+ if (!imageChild)
96759
+ return;
96760
+ const figcaptionChild = node.children.find(child => child.type === 'figcaption');
96761
+ // If the image was already transformed to image-block by the earlier visitor, use it directly
96762
+ const imageBlock = imageChild.type === NodeTypes.imageBlock
96763
+ ? imageChild
96764
+ : transformMagicBlockImage(imageChild);
96765
+ if (figcaptionChild?.children) {
96766
+ const caption = mdxish_jsx_to_mdast_extractText(figcaptionChild.children);
96767
+ if (caption) {
96768
+ imageBlock.caption = caption;
96769
+ imageBlock.data.hProperties.caption = caption;
96770
+ }
96771
+ }
96772
+ parent.children[index] = imageBlock;
96773
+ });
96774
+ // Final normalization pass across all image-block nodes
96775
+ // Ensures consistent types (border→boolean, align→ImageAlign, width→sizing) and cleans up artifacts
96776
+ const isImageBlock = (node) => node.type === NodeTypes.imageBlock;
96777
+ visit(tree, isImageBlock, _node => {
96778
+ const node = _node;
96779
+ const hProps = (node.data?.hProperties || {});
96780
+ // Normalize boolean attrs
96781
+ if (hProps.border !== undefined) {
96782
+ const val = toBool(hProps.border);
96783
+ node.border = val;
96784
+ hProps.border = val;
96785
+ }
96786
+ else if (node.border !== undefined) {
96787
+ node.border = toBool(node.border);
96788
+ }
96789
+ // Validate align
96790
+ const validAlign = toImageAlign(hProps.align) || toImageAlign(node.align);
96791
+ node.align = validAlign;
96792
+ if (validAlign) {
96793
+ hProps.align = validAlign;
96794
+ }
96795
+ else {
96796
+ delete hProps.align;
96797
+ }
96798
+ // Map width → sizing
96799
+ const width = hProps.width || node.width;
96800
+ if (width) {
96801
+ node.sizing = width;
96802
+ node.width = width;
96803
+ hProps.sizing = width;
96804
+ hProps.width = width;
96805
+ }
96806
+ // Normalize caption
96807
+ const caption = hProps.caption || node.caption;
96808
+ if (caption) {
96809
+ node.caption = caption;
96810
+ hProps.caption = caption;
96811
+ }
96812
+ // Normalize src (url → src)
96813
+ node.src = hProps.src || node.src;
96814
+ hProps.src = node.src;
96815
+ // Remove stray children array from imageTransformer, but preserve caption children
96816
+ if (!caption) {
96817
+ delete node.children;
96818
+ }
96819
+ delete hProps.children;
96694
96820
  });
96695
96821
  return tree;
96696
96822
  };
@@ -98974,7 +99100,12 @@ function loadComponents() {
98974
99100
 
98975
99101
 
98976
99102
 
98977
- const defaultTransformers = [callouts, code_tabs, gemoji_, transform_embeds];
99103
+ const defaultTransformers = [
99104
+ [callouts, { isMdxish: true }],
99105
+ code_tabs,
99106
+ gemoji_,
99107
+ transform_embeds,
99108
+ ];
98978
99109
  /**
98979
99110
  * Preprocessing pipeline: applies string-level transformations to work around
98980
99111
  * CommonMark/remark limitations and reach parity with legacy (rdmd) rendering.
@@ -99021,8 +99152,21 @@ function mdxishAstProcessor(mdContent, opts = {}) {
99021
99152
  ? [jsxTable(), magicBlock(), legacyVariable(), looseHtmlEntity()]
99022
99153
  : [jsxTable(), magicBlock(), mdxExprTextOnly, legacyVariable(), looseHtmlEntity()])
99023
99154
  .data('fromMarkdownExtensions', safeMode
99024
- ? [jsxTableFromMarkdown(), magicBlockFromMarkdown(), legacyVariableFromMarkdown(), emptyTaskListItemFromMarkdown(), looseHtmlEntityFromMarkdown()]
99025
- : [jsxTableFromMarkdown(), magicBlockFromMarkdown(), mdxExpressionFromMarkdown(), legacyVariableFromMarkdown(), emptyTaskListItemFromMarkdown(), looseHtmlEntityFromMarkdown()])
99155
+ ? [
99156
+ jsxTableFromMarkdown(),
99157
+ magicBlockFromMarkdown(),
99158
+ legacyVariableFromMarkdown(),
99159
+ emptyTaskListItemFromMarkdown(),
99160
+ looseHtmlEntityFromMarkdown(),
99161
+ ]
99162
+ : [
99163
+ jsxTableFromMarkdown(),
99164
+ magicBlockFromMarkdown(),
99165
+ mdxExpressionFromMarkdown(),
99166
+ legacyVariableFromMarkdown(),
99167
+ emptyTaskListItemFromMarkdown(),
99168
+ looseHtmlEntityFromMarkdown(),
99169
+ ])
99026
99170
  .use(remarkParse)
99027
99171
  .use(remarkFrontmatter)
99028
99172
  .use(normalize_malformed_md_syntax)
@@ -99035,7 +99179,6 @@ function mdxishAstProcessor(mdContent, opts = {}) {
99035
99179
  .use(mdxish_html_blocks)
99036
99180
  .use(newEditorTypes ? mdxish_inline_components : undefined) // Merge inline html components (e.g. <Anchor>) into MDAST nodes
99037
99181
  .use(newEditorTypes ? mdxish_jsx_to_mdast : undefined) // Convert block JSX elements to MDAST types
99038
- .use(safeMode ? undefined : evaluate_expressions, { context: jsxContext }) // Evaluate MDX expressions using jsxContext
99039
99182
  .use(variables_text) // Parse {user.*} patterns from text nodes
99040
99183
  .use(useTailwind ? transform_tailwind : undefined, { components: tempComponentsMap })
99041
99184
  .use(remarkGfm);