@readme/markdown 14.11.2 → 14.11.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
@@ -25257,10 +25257,10 @@ const Tabs = ({ children }) => {
25257
25257
  const tabs = external_react_default().Children.toArray(children);
25258
25258
  return (external_react_default().createElement("div", { className: "TabGroup" },
25259
25259
  external_react_default().createElement("header", null,
25260
- external_react_default().createElement("nav", { className: "TabGroup-nav" }, tabs.map((tab, index) => (external_react_default().createElement("button", { key: tab.props.title, className: `TabGroup-tab${activeTab === index ? '_active' : ''}`, onClick: () => setActiveTab(index) },
25260
+ external_react_default().createElement("nav", { className: "TabGroup-nav" }, tabs.map((tab, index) => (external_react_default().createElement("button", { key: tab.key, className: `TabGroup-tab${activeTab === index ? '_active' : ''}`, onClick: () => setActiveTab(index) },
25261
25261
  tab.props.icon && (external_react_default().createElement(components_Icon, { className: "TabGroup-icon", icon: tab.props.icon, iconColor: tab.props.iconColor })),
25262
25262
  tab.props.title))))),
25263
- external_react_default().createElement("section", null, tabs[activeTab])));
25263
+ external_react_default().createElement("section", null, tabs.map((tab, index) => (external_react_default().createElement("div", { key: tab.key, hidden: index !== activeTab }, tab))))));
25264
25264
  };
25265
25265
  /* harmony default export */ const components_Tabs = (Tabs);
25266
25266
 
@@ -74751,6 +74751,21 @@ function evaluate(source, scope = {}) {
74751
74751
  // eslint-disable-next-line no-new-func
74752
74752
  return new Function(...names, `return (${source})`)(...values);
74753
74753
  }
74754
+ /**
74755
+ * Advance a `Point` by the `consumed` substring that follows it, returning the
74756
+ * point at the consumed string's end. Lets split-out sub-nodes carry accurate
74757
+ * document positions so downstream offset shifting stays correct.
74758
+ */
74759
+ const pointAfter = (start, consumed) => {
74760
+ const newlineIndex = consumed.lastIndexOf('\n');
74761
+ const newlineCount = newlineIndex === -1 ? 0 : consumed.split('\n').length - 1;
74762
+ return {
74763
+ line: start.line + newlineCount,
74764
+ // Same line → advance the base column; a later line → column is the run since its newline.
74765
+ column: newlineCount === 0 ? start.column + consumed.length : consumed.length - newlineIndex,
74766
+ offset: (start.offset ?? 0) + consumed.length,
74767
+ };
74768
+ };
74754
74769
  /**
74755
74770
  * Formats the hProperties of a node as a string, so they can be compiled back into JSX/MDX.
74756
74771
  * This currently sets all the values to a string since we process/compile the MDX on the fly
@@ -96019,6 +96034,134 @@ const applyInserts = (html, inserts) => {
96019
96034
  return { value: out + html.slice(cursor), inserts: sorted };
96020
96035
  };
96021
96036
 
96037
+ ;// ./processor/transform/mdxish/tables/escape-crossing-emphasis.ts
96038
+
96039
+
96040
+
96041
+ // Maximal run of a single emphasis delimiter (`_`, `*`, `**`, `***`, …).
96042
+ const EMPHASIS_RUN_RE = /([*_])\1*/g;
96043
+ // String bounds (undefined) count as whitespace, not punctuation, per the
96044
+ // CommonMark flanking definition.
96045
+ const escape_crossing_emphasis_isWhitespace = (ch) => ch === undefined || unicodeWhitespace(ch.charCodeAt(0));
96046
+ const isPunctuation = (ch) => ch !== undefined && unicodePunctuation(ch.charCodeAt(0));
96047
+ /**
96048
+ * Whether a delimiter run can open and/or close emphasis, per CommonMark's
96049
+ * left/right-flanking rules. The extra `_` conditions forbid intraword
96050
+ * emphasis, which keeps `snake_case` from being treated as a delimiter.
96051
+ */
96052
+ const analyzeFlanking = (source, char, start, end) => {
96053
+ const before = source[start - 1];
96054
+ const after = source[end];
96055
+ const leftFlanking = !escape_crossing_emphasis_isWhitespace(after) && (!isPunctuation(after) || escape_crossing_emphasis_isWhitespace(before) || isPunctuation(before));
96056
+ const rightFlanking = !escape_crossing_emphasis_isWhitespace(before) && (!isPunctuation(before) || escape_crossing_emphasis_isWhitespace(after) || isPunctuation(after));
96057
+ if (char === '_') {
96058
+ return {
96059
+ canOpen: leftFlanking && (!rightFlanking || isPunctuation(before)),
96060
+ canClose: rightFlanking && (!leftFlanking || isPunctuation(after)),
96061
+ };
96062
+ }
96063
+ return { canOpen: leftFlanking, canClose: rightFlanking };
96064
+ };
96065
+ /**
96066
+ * Collect HTML tag boundaries (via htmlparser2) and emphasis delimiter runs
96067
+ * (via regex over the masked source, so code spans and escaped `<` are skipped)
96068
+ * into one list ordered by position. At a shared offset a tag opener sorts
96069
+ * before a closer, so a self-closing tag brackets rather than swallows a run.
96070
+ */
96071
+ const collectEvents = (html) => {
96072
+ const masked = maskNonTagRegions(html);
96073
+ const events = [];
96074
+ walkTags(html, {
96075
+ onOpen: ({ start }) => events.push({ kind: 'tagOpen', offset: start }),
96076
+ onClose: ({ start }) => events.push({ kind: 'tagClose', offset: start }),
96077
+ });
96078
+ EMPHASIS_RUN_RE.lastIndex = 0;
96079
+ let match;
96080
+ while ((match = EMPHASIS_RUN_RE.exec(masked)) !== null) {
96081
+ const [run, char] = match;
96082
+ const start = match.index;
96083
+ // eslint-disable-next-line no-continue
96084
+ if (html[start - 1] === '\\')
96085
+ continue; // already escaped
96086
+ events.push({ kind: 'emphasis', offset: start, char, length: run.length, flanking: analyzeFlanking(html, char, start, start + run.length) });
96087
+ }
96088
+ return events.sort((a, b) => a.offset - b.offset || (a.kind === 'tagClose' ? 1 : 0) - (b.kind === 'tagClose' ? 1 : 0));
96089
+ };
96090
+ /**
96091
+ * mdxjs rejects a table when a markdown emphasis run opens at one HTML
96092
+ * tag-nesting depth and closes at another — e.g. `_<ul><li>text_</li></ul>`,
96093
+ * where the `_` opens outside the list but closes inside a `<li>`. It throws
96094
+ * "Expected a closing tag for `<li>` before the end of `emphasis`" and the
96095
+ * whole `<Table>` fails to parse.
96096
+ *
96097
+ * We walk tags and emphasis together, tracking tag depth and a stack of open
96098
+ * emphasis. A delimiter only closes an opener at the same depth; any emphasis
96099
+ * still open when its enclosing tag closes (or at end of input), and any closer
96100
+ * with no same-depth opener, is escaped so mdxjs treats it as literal text.
96101
+ * Scoped to the malformed-retry path.
96102
+ */
96103
+ const escapeCrossingEmphasis = (html) => {
96104
+ const open = [];
96105
+ const orphans = [];
96106
+ let depth = 0;
96107
+ collectEvents(html).forEach(event => {
96108
+ if (event.kind === 'tagOpen') {
96109
+ depth += 1;
96110
+ return;
96111
+ }
96112
+ if (event.kind === 'tagClose') {
96113
+ depth -= 1;
96114
+ // Emphasis opened deeper than the surviving depth was inside the tag that
96115
+ // just closed, so it crosses the boundary.
96116
+ while (open.length > 0 && open[open.length - 1].depth > depth) {
96117
+ const crossed = open.pop();
96118
+ if (crossed)
96119
+ orphans.push(crossed);
96120
+ }
96121
+ return;
96122
+ }
96123
+ const top = open[open.length - 1];
96124
+ if (event.flanking.canClose && top?.char === event.char && top.depth === depth) {
96125
+ open.pop();
96126
+ }
96127
+ else if (event.flanking.canOpen) {
96128
+ open.push({ char: event.char, depth, offset: event.offset, length: event.length });
96129
+ }
96130
+ else if (event.flanking.canClose) {
96131
+ orphans.push({ offset: event.offset, length: event.length });
96132
+ }
96133
+ });
96134
+ orphans.push(...open); // anything still open never closed
96135
+ const inserts = orphans.flatMap(({ offset, length }) => Array.from({ length }, (_unused, i) => ({ offset: offset + i, text: '\\' })));
96136
+ return applyInserts(html, inserts);
96137
+ };
96138
+
96139
+ ;// ./processor/transform/mdxish/tables/escape-stray-less-than.ts
96140
+
96141
+
96142
+ // A `<` only starts a JSX/HTML construct when followed by a tag-name start
96143
+ // (letter, `_`, `$`), a closer `/`, a fragment `>`, or a comment/declaration
96144
+ // `!`. Anything else (whitespace, EOL, a digit, …) is a literal `<` that acorn
96145
+ // rejects with "before name, expected a character that can start a name".
96146
+ const STRAY_LESS_THAN_RE = /<(?![a-zA-Z_$/>!])/g;
96147
+ /**
96148
+ * Escapes stray `<` characters that don't begin a valid tag so the strict mdxjs
96149
+ * parse treats them as literal text instead of throwing (`word <`, `a <1>`).
96150
+ *
96151
+ * Runs against the masked source so `<` inside code spans, legacy `<<var>>`
96152
+ * syntax, or already-escaped `\<` are left untouched.
96153
+ */
96154
+ const escapeStrayLessThan = (html) => {
96155
+ const masked = maskNonTagRegions(html);
96156
+ const inserts = [];
96157
+ STRAY_LESS_THAN_RE.lastIndex = 0;
96158
+ let match;
96159
+ while ((match = STRAY_LESS_THAN_RE.exec(masked)) !== null) {
96160
+ inserts.push({ offset: match.index, text: '\\' });
96161
+ }
96162
+ return applyInserts(html, inserts);
96163
+ };
96164
+
96022
96165
  ;// ./processor/transform/mdxish/tables/normalize-tag-spacing.ts
96023
96166
 
96024
96167
 
@@ -96145,6 +96288,21 @@ const buildOffsetMapper = (inserts) => {
96145
96288
  return repaired - shift;
96146
96289
  };
96147
96290
  };
96291
+ /**
96292
+ * Compose the per-repair offset mappers into one that maps an offset in the
96293
+ * fully-repaired string back to the original. `layers` are in application
96294
+ * order; each maps its own output space to its input space, so we apply them
96295
+ * last-repair-first to peel every edit back to the original coordinates.
96296
+ */
96297
+ const composeOffsetMapper = (layers) => {
96298
+ const mappers = layers.map(buildOffsetMapper);
96299
+ return (repaired) => {
96300
+ let offset = repaired;
96301
+ for (let i = mappers.length - 1; i >= 0; i -= 1)
96302
+ offset = mappers[i](offset);
96303
+ return offset;
96304
+ };
96305
+ };
96148
96306
  /**
96149
96307
  * Map an offset in `source` to its 1-based `{ line, column }`. `lineStarts`
96150
96308
  * is the precomputed array of offsets where each line begins.
@@ -96172,14 +96330,11 @@ const computeLineStarts = (source) => {
96172
96330
  };
96173
96331
  /**
96174
96332
  * Walk `tree`, translating every node's position from the repaired source's
96175
- * coordinate space back to the original source. Offsets are remapped via the
96176
- * insert list; line/column are recomputed from the original source so they
96177
- * remain accurate even if repairs introduced newlines.
96333
+ * coordinate space back to the original source via `mapOffset`. Line/column
96334
+ * are recomputed from the original source so they remain accurate even if
96335
+ * repairs introduced newlines.
96178
96336
  */
96179
- const remapPositionsToOriginal = (tree, originalSource, inserts) => {
96180
- if (inserts.length === 0)
96181
- return;
96182
- const mapOffset = buildOffsetMapper(inserts);
96337
+ const remapWithMapper = (tree, originalSource, mapOffset) => {
96183
96338
  const lineStarts = computeLineStarts(originalSource);
96184
96339
  visit(tree, child => {
96185
96340
  if (child.position?.start) {
@@ -96198,6 +96353,15 @@ const remapPositionsToOriginal = (tree, originalSource, inserts) => {
96198
96353
  }
96199
96354
  });
96200
96355
  };
96356
+ /**
96357
+ * Remap positions produced after a chain of repairs (each applied to the prior
96358
+ * one's output) back to the original source coordinates.
96359
+ */
96360
+ const remapPositionsThroughLayers = (tree, originalSource, layers) => {
96361
+ if (layers.length === 0)
96362
+ return;
96363
+ remapWithMapper(tree, originalSource, composeOffsetMapper(layers));
96364
+ };
96201
96365
 
96202
96366
  ;// ./processor/transform/mdxish/tables/repair-expression-escapes.ts
96203
96367
 
@@ -96497,6 +96661,83 @@ const repairUnclosedTags = (html) => {
96497
96661
  return applyInserts(html, inserts);
96498
96662
  };
96499
96663
 
96664
+ ;// ./processor/transform/mdxish/tables/split-nested-tables.ts
96665
+
96666
+
96667
+ const TOP_LEVEL_TABLE_TAG_RE = /^<(?:table|Table)(?=[\s/>])/;
96668
+ /**
96669
+ * Find every balanced, depth-matched `<table>…</table>` range in an html string.
96670
+ * Uses `walkTags` so `<table>`s inside code spans / fenced blocks (masked away)
96671
+ * are never matched.
96672
+ *
96673
+ * Note: An implicitly-closed table (no `</table>`, so htmlparser2 synthesizes the
96674
+ * close at a later tag) is skipped: splitting there would swallow whatever
96675
+ * followed the table into the fragment and drop it, so we leave such a node
96676
+ * whole for downstream raw-HTML handling instead.
96677
+ */
96678
+ const findTableRanges = (html) => {
96679
+ const ranges = [];
96680
+ let depth = 0;
96681
+ let start = 0;
96682
+ walkTags(html, {
96683
+ onOpen: ({ name, start: openStart, isStrayCloser }) => {
96684
+ if (name.toLowerCase() !== 'table' || isStrayCloser)
96685
+ return;
96686
+ if (depth === 0)
96687
+ start = openStart;
96688
+ depth += 1;
96689
+ },
96690
+ onClose: ({ name, end, implicit }) => {
96691
+ if (implicit || name.toLowerCase() !== 'table' || depth === 0)
96692
+ return;
96693
+ depth -= 1;
96694
+ if (depth === 0)
96695
+ ranges.push({ start, end });
96696
+ },
96697
+ });
96698
+ return ranges;
96699
+ };
96700
+ /**
96701
+ * Given an HTML node that might contain table sequences inside it, split
96702
+ * the node based on the table boundaries so they become a top level node.
96703
+ *
96704
+ * The surrounding raw HTML (the wrapper's open/close tags) would be re-nested
96705
+ * around the parsed tables by rehype-raw.
96706
+ *
96707
+ * Returns null when there is no wrapped table to extract.
96708
+ */
96709
+ const splitHtmlWithNestedTables = (node) => {
96710
+ const { value } = node;
96711
+ // This is a top-level table, so we don't need to split it
96712
+ if (TOP_LEVEL_TABLE_TAG_RE.test(value))
96713
+ return null;
96714
+ // No table text anywhere in the value → skip the htmlparser2 walk entirely.
96715
+ if (!/<\/?table/i.test(value))
96716
+ return null;
96717
+ const ranges = findTableRanges(value);
96718
+ if (ranges.length === 0)
96719
+ return null;
96720
+ const base = node.position?.start;
96721
+ const sliceToHtml = (from, to) => ({
96722
+ type: 'html',
96723
+ value: value.slice(from, to),
96724
+ ...(base && {
96725
+ position: { start: pointAfter(base, value.slice(0, from)), end: pointAfter(base, value.slice(0, to)) },
96726
+ }),
96727
+ });
96728
+ const parts = [];
96729
+ let cursor = 0;
96730
+ ranges.forEach(({ start, end }) => {
96731
+ if (start > cursor)
96732
+ parts.push(sliceToHtml(cursor, start));
96733
+ parts.push(sliceToHtml(start, end)); // starts with `<table` → picked up by the main pass
96734
+ cursor = end;
96735
+ });
96736
+ if (cursor < value.length)
96737
+ parts.push(sliceToHtml(cursor, value.length));
96738
+ return parts;
96739
+ };
96740
+
96500
96741
  ;// ./processor/transform/mdxish/tables/mdxish-tables.ts
96501
96742
 
96502
96743
 
@@ -96516,6 +96757,9 @@ const repairUnclosedTags = (html) => {
96516
96757
 
96517
96758
 
96518
96759
 
96760
+
96761
+
96762
+
96519
96763
 
96520
96764
 
96521
96765
 
@@ -96546,6 +96790,21 @@ const buildTableNodeProcessor = (withMdx) => unified()
96546
96790
  .use(remarkGfm);
96547
96791
  const tableNodeProcessor = buildTableNodeProcessor(true);
96548
96792
  const fallbackTableNodeProcessor = buildTableNodeProcessor(false);
96793
+ // Targeted repairs for tables mdxjs rejects, tried cumulatively (each runs on
96794
+ // the prior's output) since one table can carry independent per-cell defects.
96795
+ // Each was added after seeing real customer content fail to parse:
96796
+ // - repairUnclosedTags: unclosed/orphan HTML tags
96797
+ // - normalizeTagSpacing: a line mixing text and an opening tag
96798
+ // - repairExpressionEscapes: backslash escapes inside a `{…}` expression
96799
+ // - escapeStrayLessThan: a `<` that doesn't begin a valid tag (`word <`)
96800
+ // - escapeCrossingEmphasis: emphasis opening/closing at different tag depths
96801
+ const tableRepairs = [
96802
+ repairUnclosedTags,
96803
+ normalizeTagSpacing,
96804
+ repairExpressionEscapes,
96805
+ escapeStrayLessThan,
96806
+ escapeCrossingEmphasis,
96807
+ ];
96549
96808
  /**
96550
96809
  * Parse the HTML node that contains the full table substring
96551
96810
  * into the table parts (headers, rows, cells).
@@ -96561,10 +96820,10 @@ const parseTableNode = (processor, node, repair) => {
96561
96820
  return undefined;
96562
96821
  }
96563
96822
  // If `node.value` was repaired before parsing, first remap positions back to
96564
- // the original (unrepaired) coordinates via the insert list — otherwise the
96823
+ // the original (unrepaired) coordinates via the insert layers — otherwise the
96565
96824
  // shift would land on synthetic characters and be inaccurate
96566
96825
  if (repair) {
96567
- remapPositionsToOriginal(parsed, repair.originalSource, repair.inserts);
96826
+ remapPositionsThroughLayers(parsed, repair.originalSource, repair.layers);
96568
96827
  }
96569
96828
  // The subparser produces positions relative to `node.value`; shift them by
96570
96829
  // the outer node's offset/line so consumers can slice the full source.
@@ -96661,9 +96920,7 @@ const processTableNode = (node, index, parent, documentPosition) => {
96661
96920
  visit(node, isMDXElement, (child) => {
96662
96921
  if (child.name === 'thead')
96663
96922
  hasThead = true;
96664
- if (tableTags.has(child.name) &&
96665
- Array.isArray(child.attributes) &&
96666
- child.attributes.length > 0) {
96923
+ if (tableTags.has(child.name) && Array.isArray(child.attributes) && child.attributes.length > 0) {
96667
96924
  hasStructuralAttributes = true;
96668
96925
  }
96669
96926
  });
@@ -96774,6 +97031,26 @@ const processTableNode = (node, index, parent, documentPosition) => {
96774
97031
  };
96775
97032
  parent.children[index] = mdNode;
96776
97033
  };
97034
+ /**
97035
+ * Apply `tableRepairs` cumulatively, re-parsing after every change and stopping
97036
+ * once the accumulated result parses. Each layer's inserts are relative to the
97037
+ * string that repair received, so they stay ordered for position remapping.
97038
+ */
97039
+ const repairAndReparse = (node) => {
97040
+ let repairedValue = node.value;
97041
+ const layers = [];
97042
+ let parsed;
97043
+ tableRepairs.some(repair => {
97044
+ const { value, inserts } = repair(repairedValue);
97045
+ if (value === repairedValue)
97046
+ return false;
97047
+ repairedValue = value;
97048
+ layers.push(inserts);
97049
+ parsed = parseTableNode(tableNodeProcessor, { ...node, value: repairedValue }, { layers, originalSource: node.value });
97050
+ return Boolean(parsed);
97051
+ });
97052
+ return parsed;
97053
+ };
96777
97054
  /**
96778
97055
  * Converts JSX Table elements to markdown table nodes and re-parses markdown in cells.
96779
97056
  *
@@ -96786,39 +97063,30 @@ const processTableNode = (node, index, parent, documentPosition) => {
96786
97063
  * is kept as a JSX <Table> element so that remarkRehype can properly handle the flow content.
96787
97064
  */
96788
97065
  const mdxishTables = () => tree => {
97066
+ // Pre-pass: lift `<table>`s wrapped in a raw HTML block out into their own
97067
+ // html nodes so the main pass below treats them like top-level tables.
97068
+ visit(tree, 'html', (_node, index, parent) => {
97069
+ const node = _node;
97070
+ if (typeof index !== 'number' || !parent || !('children' in parent))
97071
+ return;
97072
+ const parts = splitHtmlWithNestedTables(node);
97073
+ if (!parts)
97074
+ return;
97075
+ // The inserted parts can't re-trigger a split (table parts start with
97076
+ // `<table`; the wrapper slices hold no table), so plain in-place splicing
97077
+ // visits each once without looping.
97078
+ parent.children.splice(index, 1, ...parts);
97079
+ });
96789
97080
  visit(tree, 'html', (_node, index, parent) => {
96790
97081
  const node = _node;
96791
97082
  if (typeof index !== 'number' || !parent || !('children' in parent))
96792
97083
  return;
96793
97084
  if (!node.value.startsWith('<Table') && !node.value.startsWith('<table'))
96794
97085
  return;
96795
- // Main logic to transform table node to its parts
96796
97086
  // Because the processor uses remarkMdx, it is stricter in what it accepts
96797
- // and only accepts valid MDX syntax. in the table node.
96798
- // To get around that, we have some fallback logics after trying to repair the table content.
96799
- let parsed = parseTableNode(tableNodeProcessor, node);
96800
- if (!parsed) {
96801
- // Try a sequence of targeted repairs and re-parse
96802
- // after each, stopping at the first that yields a parseable tree:
96803
- // - repairUnclosedTags: unclosed/orphan HTML tags
96804
- // - normalizeTagSpacing: a line mixing text and an opening tag
96805
- // (e.g. `text <div> \n <div> text`)
96806
- // - repairExpressionEscapes: backslash escapes inside a `{…}` expression
96807
- // These repairs are created after seeing real customer content that has failed to parse
96808
- const repairs = [
96809
- repairUnclosedTags,
96810
- normalizeTagSpacing,
96811
- repairExpressionEscapes,
96812
- ];
96813
- // Stops at the first repair that yields a parseable tree
96814
- repairs.some(repair => {
96815
- const { value, inserts } = repair(node.value);
96816
- if (value !== node.value) {
96817
- parsed = parseTableNode(tableNodeProcessor, { ...node, value }, { inserts, originalSource: node.value });
96818
- }
96819
- return Boolean(parsed);
96820
- });
96821
- }
97087
+ // and only accepts valid MDX syntax in the table node. To get around that,
97088
+ // fall back to the cumulative repairs when the first parse fails.
97089
+ const parsed = parseTableNode(tableNodeProcessor, node) ?? repairAndReparse(node);
96822
97090
  if (parsed) {
96823
97091
  // If the table is parsed successfully, we can now process it further
96824
97092
  // to build on the markdown / JSX table
@@ -118967,6 +119235,21 @@ function isActualHtmlTag(tagName, originalExcerpt) {
118967
119235
  return true;
118968
119236
  return false;
118969
119237
  }
119238
+ /**
119239
+ * Re-parsing a component's text child treats it as a standalone document, so
119240
+ * content that happens to start with the literal word `export`/`import`
119241
+ * (e.g. link text like "export Lorem Ipsum") sits at true column 1 and
119242
+ * gets mistaken for an MDX ESM statement, which then fails to parse as JS.
119243
+ * Fall back to `undefined` rather than letting one such child crash the page.
119244
+ */
119245
+ function tryProcessMarkdown(processMarkdown, content) {
119246
+ try {
119247
+ return processMarkdown(content);
119248
+ }
119249
+ catch {
119250
+ return undefined;
119251
+ }
119252
+ }
118970
119253
  /** Parse and replace text children with processed markdown */
118971
119254
  function parseTextChildren(node, processMarkdown, components) {
118972
119255
  if (!node.children?.length)
@@ -118981,7 +119264,9 @@ function parseTextChildren(node, processMarkdown, components) {
118981
119264
  node.properties = { ...node.properties, children: child.value };
118982
119265
  return [];
118983
119266
  }
118984
- const hast = processMarkdown(child.value.trim());
119267
+ const hast = tryProcessMarkdown(processMarkdown, child.value.trim());
119268
+ if (!hast)
119269
+ return [child];
118985
119270
  const children = (hast.children ?? []).filter(isElementContentNode);
118986
119271
  // For inline components, preserve plain text instead of wrapping in <p>
118987
119272
  if (INLINE_COMPONENT_TAGS_LOWER.has(node.tagName.toLowerCase()) && isSingleParagraphTextNode(children)) {
@@ -119055,8 +119340,9 @@ const rehypeMdxishComponents = ({ components, processMarkdown }) => {
119055
119340
  // rehypeRaw strips children from <img> (void element), so we must
119056
119341
  // re-process the caption here, after rehypeRaw.
119057
119342
  if (node.tagName === 'img' && typeof node.properties?.caption === 'string' && !node.children?.length) {
119058
- const captionHast = processMarkdown(node.properties.caption);
119059
- node.children = (captionHast.children ?? []).filter(isElementContentNode);
119343
+ const caption = node.properties.caption;
119344
+ const captionHast = tryProcessMarkdown(processMarkdown, caption);
119345
+ node.children = captionHast ? (captionHast.children ?? []).filter(isElementContentNode) : [{ type: 'text', value: caption }];
119060
119346
  }
119061
119347
  // Skip runtime components and standard HTML tags
119062
119348
  if (RUNTIME_COMPONENT_TAGS.has(node.tagName))
@@ -119089,11 +119375,10 @@ const rehypeMdxishComponents = ({ components, processMarkdown }) => {
119089
119375
  ;// ./processor/plugin/mdxish-handlers.ts
119090
119376
 
119091
119377
 
119092
- // Convert MDX expressions to text nodes (evaluation happens earlier in pipeline)
119093
- const mdxExpressionHandler = (_state, node) => ({
119094
- type: 'text',
119095
- value: node.value || '',
119096
- });
119378
+ // If hChildren is populated, it means the node holds a renderable value (e.g. React)
119379
+ // See evaluate-expressions.ts for more details
119380
+ // Otherwise, it's a simple value and we fall back to text
119381
+ const mdxExpressionHandler = (_state, node) => node.data?.hChildren ?? { type: 'text', value: node.value || '' };
119097
119382
  // Convert MDX JSX elements to a custom mdx-jsx hast node that bypasses rehypeRaw's
119098
119383
  // HTML serialization round-trip; downstream normalization rewrites it to `element`.
119099
119384
  const mdxJsxElementHandler = (state, node) => {
@@ -122160,6 +122445,7 @@ const mdxishInlineMdxComponents = () => tree => {
122160
122445
 
122161
122446
 
122162
122447
 
122448
+
122163
122449
  /** Matches a JSX attribute expression (e.g. `key={i}`) anywhere in a string. */
122164
122450
  const NESTED_ATTR_EXPRESSION_RE = /[\w-]+\s*=\s*\{/;
122165
122451
  /**
@@ -122203,18 +122489,6 @@ const parseSibling = (stack, parent, index, sibling, safeMode) => {
122203
122489
  stack.push(parent);
122204
122490
  }
122205
122491
  };
122206
- /**
122207
- * Advance a point by the substring of source consumed from it.
122208
- */
122209
- const pointAfter = (start, consumed) => {
122210
- const newlineIndex = consumed.lastIndexOf('\n');
122211
- const newlineCount = newlineIndex === -1 ? 0 : consumed.split('\n').length - 1;
122212
- return {
122213
- line: start.line + newlineCount,
122214
- column: newlineCount === 0 ? start.column + consumed.length : consumed.length - newlineIndex,
122215
- offset: start.offset + consumed.length,
122216
- };
122217
- };
122218
122492
  /**
122219
122493
  * Build a position ending at `consumedLength` into the html node's value, so the
122220
122494
  * component doesn't claim trailing content the tokenizer swallowed into one node.
@@ -122717,8 +122991,6 @@ const evaluateExports = () => (tree, file) => {
122717
122991
  };
122718
122992
  /* harmony default export */ const evaluate_exports = (evaluateExports);
122719
122993
 
122720
- // EXTERNAL MODULE: ./node_modules/react-dom/server.node.js
122721
- var server_node = __webpack_require__(4362);
122722
122994
  ;// ./lib/utils/mdxish/mdxish-expression.ts
122723
122995
 
122724
122996
 
@@ -122764,26 +123036,185 @@ const evalExpression = (expression, scope) => {
122764
123036
  return evalJsxProgram(program, scope);
122765
123037
  };
122766
123038
 
122767
- ;// ./processor/transform/mdxish/evaluate-expressions.ts
123039
+ // EXTERNAL MODULE: ./node_modules/react-dom/server.node.js
123040
+ var server_node = __webpack_require__(4362);
123041
+ ;// ./processor/transform/mdxish/style-object-to-css.ts
123042
+
123043
+ /**
123044
+ * CSS properties React treats as unitless — a bare number stays as-is instead of
123045
+ * getting `px` appended. Mirrors React DOM's `isUnitlessNumber` whitelist.
123046
+ * @see https://github.com/facebook/react/blob/main/packages/react-dom-bindings/src/shared/CSSProperty.js
123047
+ */
123048
+ const UNITLESS_CSS_PROPERTIES = new Set([
123049
+ 'animationIterationCount',
123050
+ 'aspectRatio',
123051
+ 'borderImageOutset',
123052
+ 'borderImageSlice',
123053
+ 'borderImageWidth',
123054
+ 'boxFlex',
123055
+ 'boxFlexGroup',
123056
+ 'boxOrdinalGroup',
123057
+ 'columnCount',
123058
+ 'columns',
123059
+ 'flex',
123060
+ 'flexGrow',
123061
+ 'flexPositive',
123062
+ 'flexShrink',
123063
+ 'flexNegative',
123064
+ 'flexOrder',
123065
+ 'gridArea',
123066
+ 'gridRow',
123067
+ 'gridRowEnd',
123068
+ 'gridRowSpan',
123069
+ 'gridRowStart',
123070
+ 'gridColumn',
123071
+ 'gridColumnEnd',
123072
+ 'gridColumnSpan',
123073
+ 'gridColumnStart',
123074
+ 'fontWeight',
123075
+ 'lineClamp',
123076
+ 'lineHeight',
123077
+ 'opacity',
123078
+ 'order',
123079
+ 'orphans',
123080
+ 'tabSize',
123081
+ 'widows',
123082
+ 'zIndex',
123083
+ 'zoom',
123084
+ 'fillOpacity',
123085
+ 'floodOpacity',
123086
+ 'stopOpacity',
123087
+ 'strokeDasharray',
123088
+ 'strokeDashoffset',
123089
+ 'strokeMiterlimit',
123090
+ 'strokeOpacity',
123091
+ 'strokeWidth',
123092
+ ]);
123093
+ /** Convert a camelCase (or CSS custom property) key into its kebab-case CSS name. */
123094
+ const cssPropertyName = (key) => (key.startsWith('--') ? key : key.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`));
123095
+ /** React appends `px` to non-zero numeric values, except unitless and custom properties. */
123096
+ const cssPropertyValue = (key, value) => typeof value === 'number' && value !== 0 && !key.startsWith('--') && !UNITLESS_CSS_PROPERTIES.has(key)
123097
+ ? `${value}px`
123098
+ : `${value}`;
123099
+ /**
123100
+ * True for a value that should be serialized as a style object rather than passed through
123101
+ * as an already-CSS string. React elements are excluded since they're valid objects too.
123102
+ */
123103
+ const style_object_to_css_isPlainObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value) && !external_react_default().isValidElement(value);
123104
+ /**
123105
+ * Serialize a React-style inline style object (`{ color: "red", fontSize: 12 }`) into a
123106
+ * CSS declaration string (`color:red;font-size:12px`), the shape hast/HTML expects for a
123107
+ * `style` attribute. Empty (`undefined`/`null`/`''`) entries are dropped.
123108
+ */
123109
+ const styleObjectToCssText = (style) => Object.entries(style)
123110
+ .filter(([, value]) => value !== undefined && value !== null && value !== '')
123111
+ .map(([key, value]) => `${cssPropertyName(key)}:${cssPropertyValue(key, value)}`)
123112
+ .join(';');
122768
123113
 
123114
+ ;// ./processor/transform/mdxish/react-element-to-hast.ts
122769
123115
 
122770
123116
 
122771
123117
 
122772
- /** True for an array containing at least one React element, e.g. the result of `.map()` returning JSX. */
122773
- const isRenderableElementArray = (value) => Array.isArray(value) && value.some((external_react_default()).isValidElement);
122774
- /** Given the type of the expression result, create the corresponding mdast node. */
122775
- const createEvaluatedNode = (result, position) => {
122776
- if (result === null || result === undefined) {
122777
- return { type: 'text', value: '', position };
123118
+ // React props that never map to an HTML/hast attribute.
123119
+ const RESERVED_PROPS = new Set(['children', 'key', 'ref']);
123120
+ /**
123121
+ * Translate React props into hast `properties`: reserved and function props (event handlers)
123122
+ * are dropped (known gap), `style` objects flatten to CSS text. Names stay as authored (`className`); the
123123
+ * hast HTML boundary maps them to `class`/`for` downstream.
123124
+ */
123125
+ function propsToHastProperties(props) {
123126
+ const properties = {};
123127
+ Object.entries(props).forEach(([key, value]) => {
123128
+ if (RESERVED_PROPS.has(key) || typeof value === 'function' || value === undefined)
123129
+ return;
123130
+ properties[key] = key === 'style' && style_object_to_css_isPlainObject(value) ? styleObjectToCssText(value) : value;
123131
+ });
123132
+ // Values are resolved React props, wider than hast's HTML-attribute `PropertyValue` union.
123133
+ return properties;
123134
+ }
123135
+ /**
123136
+ * Render an element with React's own renderer as a last resort, wrapped as a hast `raw` node —
123137
+ * the same node type markdown's literal HTML blocks produce, so it re-enters rehypeRaw's
123138
+ * parse5 pass normally. Used for element types this converter can't resolve on its own (wrapped
123139
+ * component types, or a function component that throws when called outside React, e.g. one
123140
+ * using hooks). It's not immune to the invalid-HTML-nesting this module otherwise avoids, but
123141
+ * that's a fair trade against silently dropping the content.
123142
+ */
123143
+ function renderFallbackHtml(element) {
123144
+ try {
123145
+ const rawNode = { type: 'raw', value: (0,server_node/* renderToStaticMarkup */.qV)(element) };
123146
+ return [rawNode];
122778
123147
  }
122779
- else if (external_react_default().isValidElement(result) || isRenderableElementArray(result)) {
122780
- // Convert react elements (or arrays of them, e.g. `.map()` returning JSX) to their HTML
122781
- // representation. This must come before the object check as both are a subset of it.
122782
- return { type: 'html', value: (0,server_node/* renderToStaticMarkup */.qV)(external_react_default().createElement((external_react_default()).Fragment, null, result)), position };
123148
+ catch {
123149
+ return [];
122783
123150
  }
122784
- else if (typeof result === 'object') {
122785
- return { type: 'text', value: JSON.stringify(result), position };
123151
+ }
123152
+ /**
123153
+ * Convert a React element tree into hast. Emitting `mdx-jsx` nodes (rehypeRaw passthrough, later normalized to `element`)
123154
+ * preserves nesting that is valid JSX but not valid HTML, which parse5 would otherwise
123155
+ * restructure — e.g. an `<a>` wrapping another `<a>`.
123156
+ * Recursively converts the tree into an array of hast nodes, dealing with arrays and null/undefined/boolean values.
123157
+ */
123158
+ function reactElementToHast(node) {
123159
+ if (Array.isArray(node))
123160
+ return node.flatMap(reactElementToHast);
123161
+ if (node === null || node === undefined || typeof node === 'boolean')
123162
+ return [];
123163
+ if (typeof node === 'string' || typeof node === 'number') {
123164
+ const textNode = { type: 'text', value: String(node) };
123165
+ return [textNode];
122786
123166
  }
123167
+ if (!external_react_default().isValidElement(node))
123168
+ return [];
123169
+ const { type, props } = node;
123170
+ // Fragments contribute their children with no wrapper element.
123171
+ if (type === (external_react_default()).Fragment)
123172
+ return reactElementToHast(props.children);
123173
+ // Resolve function components to their rendered output so the tree is plain intrinsic
123174
+ // elements. If invoking it directly throws (e.g. it uses hooks, which need React's own
123175
+ // render context), fall back to React's renderer for just this subtree.
123176
+ if (typeof type === 'function') {
123177
+ try {
123178
+ return reactElementToHast(type(props));
123179
+ }
123180
+ catch {
123181
+ return renderFallbackHtml(node);
123182
+ }
123183
+ }
123184
+ // Non-intrinsic, non-callable element types — `React.memo`, `React.forwardRef`,
123185
+ // `Context.Provider`/`Consumer`, `React.lazy` — have no `type` we can resolve ourselves.
123186
+ if (typeof type !== 'string')
123187
+ return renderFallbackHtml(node);
123188
+ const mdxJsxNode = {
123189
+ type: 'mdx-jsx',
123190
+ tagName: type,
123191
+ properties: propsToHastProperties(props),
123192
+ children: reactElementToHast(props.children),
123193
+ };
123194
+ return [mdxJsxNode];
123195
+ }
123196
+
123197
+ ;// ./processor/transform/mdxish/evaluate-expressions.ts
123198
+
123199
+
123200
+
123201
+
123202
+ /**
123203
+ * We divide the result of an expression into two categories:
123204
+ * 1. Renderable values: HTML, JSX, e.g. .map() returning JSX
123205
+ * 2. Non-renderable values: a string, number, or object, regular JS values
123206
+ */
123207
+ const isRenderable = (value) => {
123208
+ if (external_react_default().isValidElement(value))
123209
+ return true;
123210
+ return Array.isArray(value) && value.some(isRenderable);
123211
+ };
123212
+ /** Turn a non-renderable evaluation result into a text node. */
123213
+ const createTextNode = (result, position) => {
123214
+ if (result === null || result === undefined)
123215
+ return { type: 'text', value: '', position };
123216
+ if (typeof result === 'object')
123217
+ return { type: 'text', value: JSON.stringify(result), position };
122787
123218
  return { type: 'text', value: String(result), position };
122788
123219
  };
122789
123220
  /**
@@ -122799,13 +123230,23 @@ const evaluateExpressions = () => (tree, file) => {
122799
123230
  visit(tree, ['mdxFlowExpression', 'mdxTextExpression'], (node, index, parent) => {
122800
123231
  if (!parent || index === null || index === undefined)
122801
123232
  return;
122802
- const { value, position } = node;
123233
+ const expressionNode = node;
123234
+ const { value, position } = expressionNode;
122803
123235
  const expression = value?.trim();
122804
123236
  if (!expression)
122805
123237
  return;
122806
123238
  try {
122807
123239
  const result = evalExpression(expression, scope);
122808
- parent.children.splice(index, 1, createEvaluatedNode(result, position));
123240
+ if (isRenderable(result)) {
123241
+ // Stash hast built straight from the React tree; `mdxExpressionHandler` emits it and it
123242
+ // passes through rehypeRaw/parse5 step later in the pipeline. This ensures that the
123243
+ // expression result is not parsed by parse5 and fragmenting the nesting that is valid JSX
123244
+ // but invalid HTML — e.g. an `<a>` wrapping `<a>`.
123245
+ expressionNode.data = { ...expressionNode.data, hChildren: reactElementToHast(result) };
123246
+ }
123247
+ else {
123248
+ parent.children.splice(index, 1, createTextNode(result, position));
123249
+ }
122809
123250
  }
122810
123251
  catch (_error) {
122811
123252
  // Evaluation failed — fall back to literal `{...}` text. The expression
@@ -124716,79 +125157,6 @@ function removeJSXComments(content) {
124716
125157
  return content.replace(JSX_COMMENT_REGEX, '');
124717
125158
  }
124718
125159
 
124719
- ;// ./processor/transform/mdxish/style-object-to-css.ts
124720
-
124721
- /**
124722
- * CSS properties React treats as unitless — a bare number stays as-is instead of
124723
- * getting `px` appended. Mirrors React DOM's `isUnitlessNumber` whitelist.
124724
- * @see https://github.com/facebook/react/blob/main/packages/react-dom-bindings/src/shared/CSSProperty.js
124725
- */
124726
- const UNITLESS_CSS_PROPERTIES = new Set([
124727
- 'animationIterationCount',
124728
- 'aspectRatio',
124729
- 'borderImageOutset',
124730
- 'borderImageSlice',
124731
- 'borderImageWidth',
124732
- 'boxFlex',
124733
- 'boxFlexGroup',
124734
- 'boxOrdinalGroup',
124735
- 'columnCount',
124736
- 'columns',
124737
- 'flex',
124738
- 'flexGrow',
124739
- 'flexPositive',
124740
- 'flexShrink',
124741
- 'flexNegative',
124742
- 'flexOrder',
124743
- 'gridArea',
124744
- 'gridRow',
124745
- 'gridRowEnd',
124746
- 'gridRowSpan',
124747
- 'gridRowStart',
124748
- 'gridColumn',
124749
- 'gridColumnEnd',
124750
- 'gridColumnSpan',
124751
- 'gridColumnStart',
124752
- 'fontWeight',
124753
- 'lineClamp',
124754
- 'lineHeight',
124755
- 'opacity',
124756
- 'order',
124757
- 'orphans',
124758
- 'tabSize',
124759
- 'widows',
124760
- 'zIndex',
124761
- 'zoom',
124762
- 'fillOpacity',
124763
- 'floodOpacity',
124764
- 'stopOpacity',
124765
- 'strokeDasharray',
124766
- 'strokeDashoffset',
124767
- 'strokeMiterlimit',
124768
- 'strokeOpacity',
124769
- 'strokeWidth',
124770
- ]);
124771
- /** Convert a camelCase (or CSS custom property) key into its kebab-case CSS name. */
124772
- const cssPropertyName = (key) => (key.startsWith('--') ? key : key.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`));
124773
- /** React appends `px` to non-zero numeric values, except unitless and custom properties. */
124774
- const cssPropertyValue = (key, value) => typeof value === 'number' && value !== 0 && !key.startsWith('--') && !UNITLESS_CSS_PROPERTIES.has(key)
124775
- ? `${value}px`
124776
- : `${value}`;
124777
- /**
124778
- * True for a value that should be serialized as a style object rather than passed through
124779
- * as an already-CSS string. React elements are excluded since they're valid objects too.
124780
- */
124781
- const style_object_to_css_isPlainObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value) && !external_react_default().isValidElement(value);
124782
- /**
124783
- * Serialize a React-style inline style object (`{ color: "red", fontSize: 12 }`) into a
124784
- * CSS declaration string (`color:red;font-size:12px`), the shape hast/HTML expects for a
124785
- * `style` attribute. Empty (`undefined`/`null`/`''`) entries are dropped.
124786
- */
124787
- const styleObjectToCssText = (style) => Object.entries(style)
124788
- .filter(([, value]) => value !== undefined && value !== null && value !== '')
124789
- .map(([key, value]) => `${cssPropertyName(key)}:${cssPropertyValue(key, value)}`)
124790
- .join(';');
124791
-
124792
125160
  ;// ./processor/transform/mdxish/resolve-deferred-attribute-expression-props.ts
124793
125161
 
124794
125162
 
@@ -126607,6 +126975,332 @@ const mdxishTags_tags = (doc) => {
126607
126975
  };
126608
126976
  /* harmony default export */ const mdxishTags = (mdxishTags_tags);
126609
126977
 
126978
+ ;// ./lib/mdast-util/html-block-component/index.ts
126979
+ const html_block_component_contextMap = new WeakMap();
126980
+ function findHtmlBlockComponentToken() {
126981
+ const events = this.tokenStack;
126982
+ for (let i = events.length - 1; i >= 0; i -= 1) {
126983
+ if (events[i][0].type === 'htmlBlockComponent')
126984
+ return events[i][0];
126985
+ }
126986
+ return undefined;
126987
+ }
126988
+ function enterHtmlBlockComponent(token) {
126989
+ html_block_component_contextMap.set(token, { chunks: [], lastEndLine: token.start.line });
126990
+ this.enter({ type: 'html', value: '' }, token);
126991
+ }
126992
+ function exitHtmlBlockComponentData(token) {
126993
+ const componentToken = findHtmlBlockComponentToken.call(this);
126994
+ if (!componentToken)
126995
+ return;
126996
+ const ctx = html_block_component_contextMap.get(componentToken);
126997
+ if (ctx) {
126998
+ const gap = token.start.line - ctx.lastEndLine;
126999
+ if (ctx.chunks.length > 0 && gap > 0) {
127000
+ ctx.chunks.push('\n'.repeat(gap));
127001
+ }
127002
+ ctx.chunks.push(this.sliceSerialize(token));
127003
+ ctx.lastEndLine = token.end.line;
127004
+ }
127005
+ }
127006
+ function exitHtmlBlockComponent(token) {
127007
+ const ctx = html_block_component_contextMap.get(token);
127008
+ const node = this.stack[this.stack.length - 1];
127009
+ if (ctx) {
127010
+ node.value = ctx.chunks.join('');
127011
+ html_block_component_contextMap.delete(token);
127012
+ }
127013
+ this.exit(token);
127014
+ }
127015
+ function htmlBlockComponentFromMarkdown() {
127016
+ return {
127017
+ enter: {
127018
+ htmlBlockComponent: enterHtmlBlockComponent,
127019
+ },
127020
+ exit: {
127021
+ htmlBlockComponentData: exitHtmlBlockComponentData,
127022
+ htmlBlockComponent: exitHtmlBlockComponent,
127023
+ },
127024
+ };
127025
+ }
127026
+
127027
+ ;// ./lib/micromark/html-block-component/syntax.ts
127028
+
127029
+
127030
+ const TAG_SUFFIX = [
127031
+ codes.uppercaseT,
127032
+ codes.uppercaseM,
127033
+ codes.uppercaseL,
127034
+ codes.uppercaseB,
127035
+ codes.lowercaseL,
127036
+ codes.lowercaseO,
127037
+ codes.lowercaseC,
127038
+ codes.lowercaseK,
127039
+ ];
127040
+ // ---------------------------------------------------------------------------
127041
+ // Shared tokenizer factory
127042
+ // ---------------------------------------------------------------------------
127043
+ /**
127044
+ * Creates a tokenize function for `<HTMLBlock>...</HTMLBlock>`.
127045
+ *
127046
+ * - **flow** (block-level): supports multiline content via line continuations,
127047
+ * consumes trailing whitespace after the closing tag.
127048
+ * - **text** (inline): single-line only, exits immediately after the closing tag.
127049
+ */
127050
+ function syntax_createTokenize(mode) {
127051
+ return function tokenize(effects, ok, nok) {
127052
+ let depth = 1;
127053
+ function matchChars(chars, onMatch, onFail) {
127054
+ if (chars.length === 0)
127055
+ return onMatch;
127056
+ const next = (code) => {
127057
+ if (code === chars[0]) {
127058
+ effects.consume(code);
127059
+ return matchChars(chars.slice(1), onMatch, onFail);
127060
+ }
127061
+ return onFail(code);
127062
+ };
127063
+ return next;
127064
+ }
127065
+ function matchTagName(onMatch, onFail) {
127066
+ const next = (code) => {
127067
+ if (code === codes.uppercaseH) {
127068
+ effects.consume(code);
127069
+ return matchChars(TAG_SUFFIX, onMatch, onFail);
127070
+ }
127071
+ return onFail(code);
127072
+ };
127073
+ return next;
127074
+ }
127075
+ return start;
127076
+ function start(code) {
127077
+ if (code !== codes.lessThan)
127078
+ return nok(code);
127079
+ effects.enter('htmlBlockComponent');
127080
+ effects.enter('htmlBlockComponentData');
127081
+ effects.consume(code);
127082
+ return matchTagName(afterTagName, nok);
127083
+ }
127084
+ function afterTagName(code) {
127085
+ if (code === codes.greaterThan) {
127086
+ effects.consume(code);
127087
+ return body;
127088
+ }
127089
+ if (code === codes.space || code === codes.horizontalTab) {
127090
+ effects.consume(code);
127091
+ return inAttributes;
127092
+ }
127093
+ if (mode === 'flow' && markdownLineEnding(code)) {
127094
+ effects.exit('htmlBlockComponentData');
127095
+ return attributeContinuationStart(code);
127096
+ }
127097
+ if (code === codes.slash) {
127098
+ effects.consume(code);
127099
+ return selfClose;
127100
+ }
127101
+ return nok(code);
127102
+ }
127103
+ function inAttributes(code) {
127104
+ if (code === codes.greaterThan) {
127105
+ effects.consume(code);
127106
+ return body;
127107
+ }
127108
+ if (code === null) {
127109
+ return nok(code);
127110
+ }
127111
+ if (markdownLineEnding(code)) {
127112
+ if (mode === 'text')
127113
+ return nok(code);
127114
+ effects.exit('htmlBlockComponentData');
127115
+ return attributeContinuationStart(code);
127116
+ }
127117
+ effects.consume(code);
127118
+ return inAttributes;
127119
+ }
127120
+ function attributeContinuationStart(code) {
127121
+ return effects.check(html_block_component_syntax_nonLazyContinuationStart, attributeContinuationNonLazy, continuationAfter)(code);
127122
+ }
127123
+ function attributeContinuationNonLazy(code) {
127124
+ effects.enter(types_types.lineEnding);
127125
+ effects.consume(code);
127126
+ effects.exit(types_types.lineEnding);
127127
+ return attributeContinuationBefore;
127128
+ }
127129
+ function attributeContinuationBefore(code) {
127130
+ if (code === null || markdownLineEnding(code)) {
127131
+ return attributeContinuationStart(code);
127132
+ }
127133
+ effects.enter('htmlBlockComponentData');
127134
+ return inAttributes(code);
127135
+ }
127136
+ function selfClose(code) {
127137
+ if (code === codes.greaterThan) {
127138
+ effects.consume(code);
127139
+ return mode === 'flow' ? afterClose : done(code);
127140
+ }
127141
+ return nok(code);
127142
+ }
127143
+ function body(code) {
127144
+ if (code === null)
127145
+ return nok(code);
127146
+ if (markdownLineEnding(code)) {
127147
+ if (mode === 'text') {
127148
+ // Text constructs operate on paragraph content which spans lines
127149
+ effects.consume(code);
127150
+ return body;
127151
+ }
127152
+ effects.exit('htmlBlockComponentData');
127153
+ return continuationStart(code);
127154
+ }
127155
+ if (code === codes.lessThan) {
127156
+ effects.consume(code);
127157
+ return closeSlash;
127158
+ }
127159
+ effects.consume(code);
127160
+ return body;
127161
+ }
127162
+ function closeSlash(code) {
127163
+ if (code === codes.slash) {
127164
+ effects.consume(code);
127165
+ return matchTagName(closeGt, body);
127166
+ }
127167
+ return matchTagName(openAfterTagName, body)(code);
127168
+ }
127169
+ function openAfterTagName(code) {
127170
+ if (code === codes.greaterThan || code === codes.space || code === codes.horizontalTab) {
127171
+ depth += 1;
127172
+ effects.consume(code);
127173
+ return body;
127174
+ }
127175
+ return body(code);
127176
+ }
127177
+ function closeGt(code) {
127178
+ if (code === codes.greaterThan) {
127179
+ depth -= 1;
127180
+ effects.consume(code);
127181
+ if (depth === 0) {
127182
+ return mode === 'flow' ? afterClose : done(code);
127183
+ }
127184
+ return body;
127185
+ }
127186
+ return body(code);
127187
+ }
127188
+ // -- flow-only states ---------------------------------------------------
127189
+ function afterClose(code) {
127190
+ if (code === null || markdownLineEnding(code)) {
127191
+ return done(code);
127192
+ }
127193
+ if (code === codes.space || code === codes.horizontalTab) {
127194
+ effects.consume(code);
127195
+ return afterClose;
127196
+ }
127197
+ // Reject so the block re-parses as a paragraph, deferring to the
127198
+ // text tokenizer which preserves trailing content in the same line.
127199
+ return nok(code);
127200
+ }
127201
+ // -- flow-only: line continuation ---------------------------------------
127202
+ function continuationStart(code) {
127203
+ return effects.check(html_block_component_syntax_nonLazyContinuationStart, continuationStartNonLazy, continuationAfter)(code);
127204
+ }
127205
+ function continuationStartNonLazy(code) {
127206
+ effects.enter(types_types.lineEnding);
127207
+ effects.consume(code);
127208
+ effects.exit(types_types.lineEnding);
127209
+ return continuationBefore;
127210
+ }
127211
+ function continuationBefore(code) {
127212
+ if (code === null || markdownLineEnding(code)) {
127213
+ return continuationStart(code);
127214
+ }
127215
+ effects.enter('htmlBlockComponentData');
127216
+ return body(code);
127217
+ }
127218
+ function continuationAfter(code) {
127219
+ if (code === null)
127220
+ return nok(code);
127221
+ effects.exit('htmlBlockComponent');
127222
+ return ok(code);
127223
+ }
127224
+ // -- shared exit --------------------------------------------------------
127225
+ function done(_code) {
127226
+ effects.exit('htmlBlockComponentData');
127227
+ effects.exit('htmlBlockComponent');
127228
+ return ok(_code);
127229
+ }
127230
+ };
127231
+ }
127232
+ // ---------------------------------------------------------------------------
127233
+ // Flow construct (block-level)
127234
+ // ---------------------------------------------------------------------------
127235
+ const html_block_component_syntax_nonLazyContinuationStart = {
127236
+ tokenize: html_block_component_syntax_tokenizeNonLazyContinuationStart,
127237
+ partial: true,
127238
+ };
127239
+ function resolveToHtmlBlockComponent(events) {
127240
+ let index = events.length;
127241
+ while (index > 0) {
127242
+ index -= 1;
127243
+ if (events[index][0] === 'enter' && events[index][1].type === 'htmlBlockComponent') {
127244
+ break;
127245
+ }
127246
+ }
127247
+ if (index > 1 && events[index - 2][1].type === types_types.linePrefix) {
127248
+ events[index][1].start = events[index - 2][1].start;
127249
+ events[index + 1][1].start = events[index - 2][1].start;
127250
+ events.splice(index - 2, 2);
127251
+ }
127252
+ return events;
127253
+ }
127254
+ const htmlBlockComponentFlowConstruct = {
127255
+ name: 'htmlBlockComponent',
127256
+ tokenize: syntax_createTokenize('flow'),
127257
+ resolveTo: resolveToHtmlBlockComponent,
127258
+ concrete: true,
127259
+ };
127260
+ function html_block_component_syntax_tokenizeNonLazyContinuationStart(effects, ok, nok) {
127261
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
127262
+ const self = this;
127263
+ return start;
127264
+ function start(code) {
127265
+ if (markdownLineEnding(code)) {
127266
+ effects.enter(types_types.lineEnding);
127267
+ effects.consume(code);
127268
+ effects.exit(types_types.lineEnding);
127269
+ return after;
127270
+ }
127271
+ return nok(code);
127272
+ }
127273
+ function after(code) {
127274
+ if (self.parser.lazy[self.now().line]) {
127275
+ return nok(code);
127276
+ }
127277
+ return ok(code);
127278
+ }
127279
+ }
127280
+ // ---------------------------------------------------------------------------
127281
+ // Text construct (inline)
127282
+ // ---------------------------------------------------------------------------
127283
+ const htmlBlockComponentTextConstruct = {
127284
+ name: 'htmlBlockComponent',
127285
+ tokenize: syntax_createTokenize('text'),
127286
+ };
127287
+ // ---------------------------------------------------------------------------
127288
+ // Extension
127289
+ // ---------------------------------------------------------------------------
127290
+ function htmlBlockComponent() {
127291
+ return {
127292
+ flow: {
127293
+ [codes.lessThan]: [htmlBlockComponentFlowConstruct],
127294
+ },
127295
+ text: {
127296
+ [codes.lessThan]: [htmlBlockComponentTextConstruct],
127297
+ },
127298
+ };
127299
+ }
127300
+
127301
+ ;// ./lib/micromark/html-block-component/index.ts
127302
+
127303
+
126610
127304
  ;// ./lib/utils/extractMagicBlocks.ts
126611
127305
  /**
126612
127306
  * The content matching in this regex captures everything between `[block:TYPE]`
@@ -126673,19 +127367,22 @@ function restoreMagicBlocks(replaced, blocks) {
126673
127367
 
126674
127368
 
126675
127369
 
127370
+
127371
+
126676
127372
  /**
126677
127373
  * Removes Markdown and MDX comments.
126678
127374
  */
126679
127375
  async function stripComments(doc, { mdx, mdxish } = {}) {
126680
127376
  const { replaced, blocks } = extractMagicBlocks(doc);
126681
127377
  const processor = unified();
126682
- // we still require these two extensions because:
127378
+ // we still require these extensions because:
126683
127379
  // 1. we can rely on remarkMdx to parse MDXish
126684
127380
  // 2. we need to parse JSX comments into mdxTextExpression nodes so that the transformers can pick them up
127381
+ // 3. we need to claim <HTMLBlock> before htmlFlow intercepts its inner HTML tags
126685
127382
  if (mdxish) {
126686
127383
  processor
126687
- .data('micromarkExtensions', [jsxTable(), mdxExpression({ allowEmpty: true })])
126688
- .data('fromMarkdownExtensions', [jsxTableFromMarkdown(), mdxExpressionFromMarkdown()])
127384
+ .data('micromarkExtensions', [htmlBlockComponent(), jsxTable(), mdxExpression({ allowEmpty: true })])
127385
+ .data('fromMarkdownExtensions', [htmlBlockComponentFromMarkdown(), jsxTableFromMarkdown(), mdxExpressionFromMarkdown()])
126689
127386
  .data('toMarkdownExtensions', [mdxExpressionToMarkdown()]);
126690
127387
  }
126691
127388
  processor