@readme/markdown 14.8.0 → 14.9.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.
@@ -99,6 +99,8 @@ function useScrollHighlight(navRef: React.RefObject<HTMLElement | null>) {
99
99
  const linkRect = link.getBoundingClientRect();
100
100
  nav.style.setProperty('--ToC-border-active-height', `${linkRect.height}px`);
101
101
  nav.style.setProperty('--ToC-border-active-top', `${linkRect.top - navRect.top}px`);
102
+
103
+ link.scrollIntoView?.({ block: 'nearest', behavior: 'smooth' });
102
104
  }
103
105
  }
104
106
  };
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ declare const utils: {
6
6
  getHref: typeof getHref;
7
7
  calloutIcons: {};
8
8
  };
9
- export { compile, exports, FLOW_TYPES, hast, INLINE_ONLY_PARENT_TYPES, run, mdast, mdastV6, mdx, mdxish, mdxishAstProcessor, mdxishMdastToMd, mdxishTags, migrate, mix, plain, renderMdxish, remarkPlugins, stripComments, tags, } from './lib';
9
+ export { compile, exports, FLOW_TYPES, hast, INLINE_ONLY_PARENT_TYPES, run, mdast, mdastV6, mdx, mdxish, mdxishAstProcessor, mdxishMdastToMd, mdxishTags, extractToc, migrate, mix, plain, renderMdxish, remarkPlugins, stripComments, tags, } from './lib';
10
10
  export { default as Owlmoji } from './lib/owlmoji';
11
11
  export { Components, utils };
12
12
  export { tailwindCompiler } from './utils/tailwind-compiler';
@@ -0,0 +1,2 @@
1
+ import { extractToc } from '../processor/plugin/toc';
2
+ export default extractToc;
@@ -10,6 +10,7 @@ export { default as mdx } from './mdx';
10
10
  export { default as mix } from './mix';
11
11
  export { default as mdxish, mdxishAstProcessor, mdxishMdastToMd } from './mdxish';
12
12
  export type { MdxishOpts } from './mdxish';
13
+ export { default as extractToc } from './extractToc';
13
14
  export { default as migrate } from './migrate';
14
15
  export { default as plain } from './plain';
15
16
  export { default as renderMdxish } from './renderMdxish';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Evaluate an expression body, transforming JSX to `React.createElement` only when the
3
+ * parsed estree actually contains a JSX node. The raw `Function()` evaluator can't parse
4
+ * JSX, so JSX-bearing expressions take the build-and-serialize path while everything else
5
+ * evaluates directly. Input acorn can't parse falls back to the plain evaluator unchanged.
6
+ */
7
+ export declare const evalExpression: (expression: string, scope: Record<string, unknown>) => any;
package/dist/main.js CHANGED
@@ -11599,6 +11599,7 @@ __webpack_require__.d(__webpack_exports__, {
11599
11599
  Owlmoji: () => (/* reexport */ Owlmoji),
11600
11600
  compile: () => (/* reexport */ lib_compile),
11601
11601
  exports: () => (/* reexport */ lib_exports),
11602
+ extractToc: () => (/* reexport */ lib_extractToc),
11602
11603
  gemojiRegex: () => (/* reexport */ gemoji_regex),
11603
11604
  hast: () => (/* reexport */ lib_hast),
11604
11605
  mdast: () => (/* reexport */ lib_mdast),
@@ -12458,6 +12459,7 @@ function useScrollHighlight(navRef) {
12458
12459
  const linkRect = link.getBoundingClientRect();
12459
12460
  nav.style.setProperty('--ToC-border-active-height', `${linkRect.height}px`);
12460
12461
  nav.style.setProperty('--ToC-border-active-top', `${linkRect.top - navRect.top}px`);
12462
+ link.scrollIntoView?.({ block: 'nearest', behavior: 'smooth' });
12461
12463
  }
12462
12464
  }
12463
12465
  };
@@ -98755,26 +98757,17 @@ const rehypeMdxishComponents = ({ components, processMarkdown }) => {
98755
98757
  ;// ./processor/plugin/mdxish-handlers.ts
98756
98758
 
98757
98759
 
98758
-
98759
98760
  // Convert MDX expressions to text nodes (evaluation happens earlier in pipeline)
98760
98761
  const mdxExpressionHandler = (_state, node) => ({
98761
98762
  type: 'text',
98762
98763
  value: node.value || '',
98763
98764
  });
98764
- function isStructuredCloneable(value) {
98765
- try {
98766
- structuredClone(value);
98767
- return true;
98768
- }
98769
- catch {
98770
- return false;
98771
- }
98772
- }
98773
98765
  // Convert MDX JSX elements to a custom mdx-jsx hast node that bypasses rehypeRaw's
98774
98766
  // HTML serialization round-trip; downstream normalization rewrites it to `element`.
98775
98767
  const mdxJsxElementHandler = (state, node) => {
98776
98768
  const { attributes = [], name } = node;
98777
98769
  const properties = {};
98770
+ const deferredExpressions = {};
98778
98771
  attributes.forEach(attribute => {
98779
98772
  if (attribute.type !== 'mdxJsxAttribute' || !attribute.name)
98780
98773
  return;
@@ -98785,30 +98778,20 @@ const mdxJsxElementHandler = (state, node) => {
98785
98778
  properties[attribute.name] = decode_decodeHTMLStrict(attribute.value);
98786
98779
  }
98787
98780
  else {
98788
- const expressionSource = attribute.value.value;
98789
- let evaluated;
98790
- try {
98791
- evaluated = evaluate(expressionSource);
98792
- }
98793
- catch {
98794
- evaluated = expressionSource;
98795
- }
98796
- // rehypeRaw's passThrough clones our mdx-jsx node with structuredClone, which
98797
- // rejects functions and other non-serializable values. Attribute expressions
98798
- // that evaluate to such values (`onClick={() => ...}`) would crash the pipeline,
98799
- // so if we have a non-serializable value, we fall back to the raw expression source
98800
- // and not support it for now.
98801
- if (!isStructuredCloneable(evaluated)) {
98802
- evaluated = expressionSource;
98803
- }
98804
- properties[attribute.name] = evaluated;
98781
+ // Defer every attribute-expression evaluation past rehypeRaw's `structuredClone`
98782
+ // passthrough: evaluating here can yield React elements or functions that the clone
98783
+ // rejects. The source is stashed in `node.data` (clone-safe) and
98784
+ // `resolveDeferredAttributeExpressionProps` evaluates it once past the clone.
98785
+ deferredExpressions[attribute.name] = attribute.value.value;
98805
98786
  }
98806
98787
  });
98788
+ const hasDeferredExpressions = Object.keys(deferredExpressions).length > 0;
98807
98789
  const jsxNode = {
98808
98790
  type: 'mdx-jsx',
98809
98791
  tagName: name || '',
98810
- properties,
98792
+ properties: properties,
98811
98793
  children: state.all(node),
98794
+ ...(hasDeferredExpressions && { data: { deferredExpressions } }),
98812
98795
  };
98813
98796
  return jsxNode;
98814
98797
  };
@@ -102090,27 +102073,56 @@ const evaluateExports = () => (tree, file) => {
102090
102073
 
102091
102074
  // EXTERNAL MODULE: ./node_modules/react-dom/server.browser.js
102092
102075
  var server_browser = __webpack_require__(5848);
102093
- ;// ./processor/transform/mdxish/evaluate-expressions.ts
102094
-
102076
+ ;// ./lib/utils/mdxish/mdxish-expression.ts
102095
102077
 
102096
102078
 
102097
102079
 
102098
-
102099
-
102100
- const HAS_JSX = /<[A-Za-z]|<>/;
102101
- /** The raw Function() can't parse JSX, so parse & convert it to a React element first so later we can get its HTML representation */
102102
- const evalJsxExpression = (expression, scope) => {
102103
- const program = jsxAcornParser.parse(expression, { ecmaVersion: 'latest', sourceType: 'module' });
102080
+ const parseExpression = (expression) => jsxAcornParser.parse(expression, { ecmaVersion: 'latest', sourceType: 'module' });
102081
+ /**
102082
+ * Recursively report whether an estree value contains any JSX element or fragment node.
102083
+ * estree stores children across named fields (not a `children` array), so this descends
102084
+ * through every nested object/array rather than using a unist-shaped walker.
102085
+ */
102086
+ const containsJsxNode = (value) => {
102087
+ if (Array.isArray(value))
102088
+ return value.some(containsJsxNode);
102089
+ if (value === null || typeof value !== 'object')
102090
+ return false;
102091
+ const { type } = value;
102092
+ if (type === 'JSXElement' || type === 'JSXFragment')
102093
+ return true;
102094
+ return Object.values(value).some(containsJsxNode);
102095
+ };
102096
+ /** Convert a program's JSX into `React.createElement` calls and evaluate it. `scope` must provide `React`. */
102097
+ const evalJsxProgram = (program, scope) => {
102104
102098
  buildJsx(program, { runtime: 'classic', pragma: 'React.createElement', pragmaFrag: 'React.Fragment' });
102105
102099
  const { value: source } = toJs(program);
102106
102100
  return evaluate(`(() => { return ${source.trim().replace(/;$/, '')}; })()`, scope);
102107
102101
  };
102108
- /** Evaluate an expression body, transforming JSX to `React.createElement` only when needed. */
102102
+ /**
102103
+ * Evaluate an expression body, transforming JSX to `React.createElement` only when the
102104
+ * parsed estree actually contains a JSX node. The raw `Function()` evaluator can't parse
102105
+ * JSX, so JSX-bearing expressions take the build-and-serialize path while everything else
102106
+ * evaluates directly. Input acorn can't parse falls back to the plain evaluator unchanged.
102107
+ */
102109
102108
  const evalExpression = (expression, scope) => {
102110
- if (HAS_JSX.test(expression))
102111
- return evalJsxExpression(expression, scope);
102112
- return evaluate(expression, scope);
102109
+ let program;
102110
+ try {
102111
+ program = parseExpression(expression);
102112
+ }
102113
+ catch {
102114
+ return evaluate(expression, scope);
102115
+ }
102116
+ if (!containsJsxNode(program))
102117
+ return evaluate(expression, scope);
102118
+ return evalJsxProgram(program, scope);
102113
102119
  };
102120
+
102121
+ ;// ./processor/transform/mdxish/evaluate-expressions.ts
102122
+
102123
+
102124
+
102125
+
102114
102126
  /** Given the type of the expression result, create the corresponding mdast node. */
102115
102127
  const createEvaluatedNode = (result, position) => {
102116
102128
  if (result === null || result === undefined) {
@@ -102624,6 +102636,8 @@ const separateBlockTagFromContent = (match, tag, inlineChar, nextLineChar) => {
102624
102636
  const breaks = '<br>'.repeat(newlineCount);
102625
102637
  return `</${tag}>${breaks}\n\n${inlineChar || nextLineChar}`;
102626
102638
  };
102639
+ /** Escape leading `-`/`*`/`+` (followed by space/EOL) so cells don't become bullet lists. */
102640
+ const escapeLeadingListMarkers = (text) => text.replace(/^([-*+])(?=[ \t]|$)/gm, '\\$1');
102627
102641
  /**
102628
102642
  * CommonMark doesn't process markdown inside HTML blocks -
102629
102643
  * so `<ul><li>_text_</li></ul>` won't convert underscores to emphasis.
@@ -102640,7 +102654,7 @@ const parseTableCell = (text) => {
102640
102654
  .replace(HTML_ELEMENT_BLOCK_RE, match => match.replace(NEWLINE_WITH_WHITESPACE_RE, '<br>'))
102641
102655
  .replace(CLOSE_BLOCK_TAG_BOUNDARY_RE, separateBlockTagFromContent);
102642
102656
  const trimmedLines = normalized.split('\n').map(line => line.trimStart());
102643
- const processed = trimmedLines.join('\n');
102657
+ const processed = escapeLeadingListMarkers(trimmedLines.join('\n'));
102644
102658
  const tree = contentParser.runSync(contentParser.parse(processed));
102645
102659
  // Process markdown inside HTML blocks that have non-tag inner text (e.g. `<div>**x**`
102646
102660
  // or `<ul><li>_x_</li></ul>`). Pure bare tags like "<i>" or "<br>" are left for rehypeRaw
@@ -104168,6 +104182,45 @@ function preprocessJSXExpressions(content) {
104168
104182
  return processed;
104169
104183
  }
104170
104184
 
104185
+ ;// ./processor/transform/mdxish/resolve-deferred-attribute-expression-props.ts
104186
+
104187
+
104188
+
104189
+ /**
104190
+ * Resolve attribute expressions that `mdxJsxElementHandler` deferred.
104191
+ *
104192
+ * The handler stashed each attribute expression's source in `node.data.deferredExpressions`
104193
+ * (keyed by prop name) instead of evaluating eagerly, because an eager result can be a React
104194
+ * element or function that rehypeRaw's `structuredClone` passthrough rejects. Now that we're
104195
+ * past the clone, evaluate each source with a scope of `{ React, ...mdxishScope }` and write
104196
+ * the real value into `properties` (e.g. an array of objects whose fields are React elements).
104197
+ *
104198
+ * Must run after `rehypeRaw` (past the clone) but before `normalizeMdxJsxNodes` rewrites these
104199
+ * `mdx-jsx` nodes into plain elements. Skipped in safeMode, which keeps expressions literal.
104200
+ */
104201
+ const resolveDeferredAttributeExpressionProps = () => (tree, file) => {
104202
+ const scope = { ...file.data.mdxishScope, React: (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default()) };
104203
+ visit(tree, 'mdx-jsx', (node) => {
104204
+ const deferredExpressions = node.data?.deferredExpressions;
104205
+ if (!deferredExpressions)
104206
+ return;
104207
+ const properties = node.properties;
104208
+ Object.entries(deferredExpressions).forEach(([name, source]) => {
104209
+ try {
104210
+ properties[name] = evalExpression(source, scope);
104211
+ }
104212
+ catch {
104213
+ // Evaluation failed — fall back to the raw expression source so the attribute
104214
+ // renders as readable text rather than disappearing.
104215
+ properties[name] = source;
104216
+ }
104217
+ });
104218
+ delete node.data.deferredExpressions;
104219
+ });
104220
+ return tree;
104221
+ };
104222
+ /* harmony default export */ const resolve_deferred_attribute_expression_props = (resolveDeferredAttributeExpressionProps);
104223
+
104171
104224
  ;// ./processor/transform/mdxish/restore-snake-case-component-name.ts
104172
104225
 
104173
104226
 
@@ -105197,6 +105250,7 @@ function loadComponents() {
105197
105250
 
105198
105251
 
105199
105252
 
105253
+
105200
105254
 
105201
105255
 
105202
105256
  const defaultTransformers = [
@@ -105356,6 +105410,7 @@ function mdxish(mdContent, opts = {}) {
105356
105410
  .use(preserveBooleanProperties) // RehypeRaw converts boolean properties to empty strings
105357
105411
  .use(rehypeRaw, { passThrough: ['html-block', 'mdx-jsx'] }) // MDX JSX nodes bypass parse5's string-only HTML round-trip
105358
105412
  .use(restoreBooleanProperties)
105413
+ .use(safeMode ? undefined : resolve_deferred_attribute_expression_props) // Evaluate deferred attribute expressions on mdx-jsx nodes (now past rehypeRaw's clone)
105359
105414
  .use(normalize_mdx_jsx_nodes) // Rewrite `mdx-jsx` back to standard `element` nodes for downstream plugins
105360
105415
  .use(rehypeFlattenTableCellParagraphs) // Remove <p> wrappers inside table cells to prevent margin issues
105361
105416
  .use(mdxish_mermaid) // Add mermaid-render className to pre wrappers
@@ -105391,6 +105446,10 @@ const mix = (text, opts = {}) => {
105391
105446
  };
105392
105447
  /* harmony default export */ const lib_mix = (mix);
105393
105448
 
105449
+ ;// ./lib/extractToc.ts
105450
+
105451
+ /* harmony default export */ const lib_extractToc = (extractToc);
105452
+
105394
105453
  ;// ./processor/transform/migrate-callouts.ts
105395
105454
 
105396
105455
 
@@ -105832,12 +105891,16 @@ const tags = (doc) => {
105832
105891
 
105833
105892
 
105834
105893
 
105894
+
105895
+
105896
+
105835
105897
  const mdxishTags_tags = (doc) => {
105836
105898
  const set = new Set();
105837
105899
  const processor = remark()
105838
- .data('micromarkExtensions', [magicBlock(), mdxComponent()])
105839
- .data('fromMarkdownExtensions', [magicBlockFromMarkdown(), mdxComponentFromMarkdown()])
105840
- .use(mdx_blocks);
105900
+ .data('micromarkExtensions', [jsxTable(), magicBlock(), mdxComponent()])
105901
+ .data('fromMarkdownExtensions', [jsxTableFromMarkdown(), magicBlockFromMarkdown(), mdxComponentFromMarkdown()])
105902
+ .use(mdx_blocks)
105903
+ .use(mdxish_tables);
105841
105904
  const tree = processor.parse(doc);
105842
105905
  visit(processor.runSync(tree), isMDXElement, (node) => {
105843
105906
  if (node.name?.match(/^[A-Z]/)) {
@@ -105987,6 +106050,7 @@ async function stripComments(doc, { mdx, mdxish } = {}) {
105987
106050
 
105988
106051
 
105989
106052
 
106053
+
105990
106054
  ;// ./index.tsx
105991
106055
 
105992
106056
 
package/dist/main.node.js CHANGED
@@ -19283,6 +19283,7 @@ __webpack_require__.d(__webpack_exports__, {
19283
19283
  Owlmoji: () => (/* reexport */ Owlmoji),
19284
19284
  compile: () => (/* reexport */ lib_compile),
19285
19285
  exports: () => (/* reexport */ lib_exports),
19286
+ extractToc: () => (/* reexport */ lib_extractToc),
19286
19287
  gemojiRegex: () => (/* reexport */ gemoji_regex),
19287
19288
  hast: () => (/* reexport */ lib_hast),
19288
19289
  mdast: () => (/* reexport */ lib_mdast),
@@ -25084,6 +25085,7 @@ function useScrollHighlight(navRef) {
25084
25085
  const linkRect = link.getBoundingClientRect();
25085
25086
  nav.style.setProperty('--ToC-border-active-height', `${linkRect.height}px`);
25086
25087
  nav.style.setProperty('--ToC-border-active-top', `${linkRect.top - navRect.top}px`);
25088
+ link.scrollIntoView?.({ block: 'nearest', behavior: 'smooth' });
25087
25089
  }
25088
25090
  }
25089
25091
  };
@@ -118979,26 +118981,17 @@ const rehypeMdxishComponents = ({ components, processMarkdown }) => {
118979
118981
  ;// ./processor/plugin/mdxish-handlers.ts
118980
118982
 
118981
118983
 
118982
-
118983
118984
  // Convert MDX expressions to text nodes (evaluation happens earlier in pipeline)
118984
118985
  const mdxExpressionHandler = (_state, node) => ({
118985
118986
  type: 'text',
118986
118987
  value: node.value || '',
118987
118988
  });
118988
- function isStructuredCloneable(value) {
118989
- try {
118990
- structuredClone(value);
118991
- return true;
118992
- }
118993
- catch {
118994
- return false;
118995
- }
118996
- }
118997
118989
  // Convert MDX JSX elements to a custom mdx-jsx hast node that bypasses rehypeRaw's
118998
118990
  // HTML serialization round-trip; downstream normalization rewrites it to `element`.
118999
118991
  const mdxJsxElementHandler = (state, node) => {
119000
118992
  const { attributes = [], name } = node;
119001
118993
  const properties = {};
118994
+ const deferredExpressions = {};
119002
118995
  attributes.forEach(attribute => {
119003
118996
  if (attribute.type !== 'mdxJsxAttribute' || !attribute.name)
119004
118997
  return;
@@ -119009,30 +119002,20 @@ const mdxJsxElementHandler = (state, node) => {
119009
119002
  properties[attribute.name] = decode_decodeHTMLStrict(attribute.value);
119010
119003
  }
119011
119004
  else {
119012
- const expressionSource = attribute.value.value;
119013
- let evaluated;
119014
- try {
119015
- evaluated = evaluate(expressionSource);
119016
- }
119017
- catch {
119018
- evaluated = expressionSource;
119019
- }
119020
- // rehypeRaw's passThrough clones our mdx-jsx node with structuredClone, which
119021
- // rejects functions and other non-serializable values. Attribute expressions
119022
- // that evaluate to such values (`onClick={() => ...}`) would crash the pipeline,
119023
- // so if we have a non-serializable value, we fall back to the raw expression source
119024
- // and not support it for now.
119025
- if (!isStructuredCloneable(evaluated)) {
119026
- evaluated = expressionSource;
119027
- }
119028
- properties[attribute.name] = evaluated;
119005
+ // Defer every attribute-expression evaluation past rehypeRaw's `structuredClone`
119006
+ // passthrough: evaluating here can yield React elements or functions that the clone
119007
+ // rejects. The source is stashed in `node.data` (clone-safe) and
119008
+ // `resolveDeferredAttributeExpressionProps` evaluates it once past the clone.
119009
+ deferredExpressions[attribute.name] = attribute.value.value;
119029
119010
  }
119030
119011
  });
119012
+ const hasDeferredExpressions = Object.keys(deferredExpressions).length > 0;
119031
119013
  const jsxNode = {
119032
119014
  type: 'mdx-jsx',
119033
119015
  tagName: name || '',
119034
- properties,
119016
+ properties: properties,
119035
119017
  children: state.all(node),
119018
+ ...(hasDeferredExpressions && { data: { deferredExpressions } }),
119036
119019
  };
119037
119020
  return jsxNode;
119038
119021
  };
@@ -122314,27 +122297,56 @@ const evaluateExports = () => (tree, file) => {
122314
122297
 
122315
122298
  // EXTERNAL MODULE: ./node_modules/react-dom/server.node.js
122316
122299
  var server_node = __webpack_require__(4362);
122317
- ;// ./processor/transform/mdxish/evaluate-expressions.ts
122318
-
122300
+ ;// ./lib/utils/mdxish/mdxish-expression.ts
122319
122301
 
122320
122302
 
122321
122303
 
122322
-
122323
-
122324
- const HAS_JSX = /<[A-Za-z]|<>/;
122325
- /** The raw Function() can't parse JSX, so parse & convert it to a React element first so later we can get its HTML representation */
122326
- const evalJsxExpression = (expression, scope) => {
122327
- const program = jsxAcornParser.parse(expression, { ecmaVersion: 'latest', sourceType: 'module' });
122304
+ const parseExpression = (expression) => jsxAcornParser.parse(expression, { ecmaVersion: 'latest', sourceType: 'module' });
122305
+ /**
122306
+ * Recursively report whether an estree value contains any JSX element or fragment node.
122307
+ * estree stores children across named fields (not a `children` array), so this descends
122308
+ * through every nested object/array rather than using a unist-shaped walker.
122309
+ */
122310
+ const containsJsxNode = (value) => {
122311
+ if (Array.isArray(value))
122312
+ return value.some(containsJsxNode);
122313
+ if (value === null || typeof value !== 'object')
122314
+ return false;
122315
+ const { type } = value;
122316
+ if (type === 'JSXElement' || type === 'JSXFragment')
122317
+ return true;
122318
+ return Object.values(value).some(containsJsxNode);
122319
+ };
122320
+ /** Convert a program's JSX into `React.createElement` calls and evaluate it. `scope` must provide `React`. */
122321
+ const evalJsxProgram = (program, scope) => {
122328
122322
  buildJsx(program, { runtime: 'classic', pragma: 'React.createElement', pragmaFrag: 'React.Fragment' });
122329
122323
  const { value: source } = toJs(program);
122330
122324
  return evaluate(`(() => { return ${source.trim().replace(/;$/, '')}; })()`, scope);
122331
122325
  };
122332
- /** Evaluate an expression body, transforming JSX to `React.createElement` only when needed. */
122326
+ /**
122327
+ * Evaluate an expression body, transforming JSX to `React.createElement` only when the
122328
+ * parsed estree actually contains a JSX node. The raw `Function()` evaluator can't parse
122329
+ * JSX, so JSX-bearing expressions take the build-and-serialize path while everything else
122330
+ * evaluates directly. Input acorn can't parse falls back to the plain evaluator unchanged.
122331
+ */
122333
122332
  const evalExpression = (expression, scope) => {
122334
- if (HAS_JSX.test(expression))
122335
- return evalJsxExpression(expression, scope);
122336
- return evaluate(expression, scope);
122333
+ let program;
122334
+ try {
122335
+ program = parseExpression(expression);
122336
+ }
122337
+ catch {
122338
+ return evaluate(expression, scope);
122339
+ }
122340
+ if (!containsJsxNode(program))
122341
+ return evaluate(expression, scope);
122342
+ return evalJsxProgram(program, scope);
122337
122343
  };
122344
+
122345
+ ;// ./processor/transform/mdxish/evaluate-expressions.ts
122346
+
122347
+
122348
+
122349
+
122338
122350
  /** Given the type of the expression result, create the corresponding mdast node. */
122339
122351
  const createEvaluatedNode = (result, position) => {
122340
122352
  if (result === null || result === undefined) {
@@ -122848,6 +122860,8 @@ const separateBlockTagFromContent = (match, tag, inlineChar, nextLineChar) => {
122848
122860
  const breaks = '<br>'.repeat(newlineCount);
122849
122861
  return `</${tag}>${breaks}\n\n${inlineChar || nextLineChar}`;
122850
122862
  };
122863
+ /** Escape leading `-`/`*`/`+` (followed by space/EOL) so cells don't become bullet lists. */
122864
+ const escapeLeadingListMarkers = (text) => text.replace(/^([-*+])(?=[ \t]|$)/gm, '\\$1');
122851
122865
  /**
122852
122866
  * CommonMark doesn't process markdown inside HTML blocks -
122853
122867
  * so `<ul><li>_text_</li></ul>` won't convert underscores to emphasis.
@@ -122864,7 +122878,7 @@ const parseTableCell = (text) => {
122864
122878
  .replace(HTML_ELEMENT_BLOCK_RE, match => match.replace(NEWLINE_WITH_WHITESPACE_RE, '<br>'))
122865
122879
  .replace(CLOSE_BLOCK_TAG_BOUNDARY_RE, separateBlockTagFromContent);
122866
122880
  const trimmedLines = normalized.split('\n').map(line => line.trimStart());
122867
- const processed = trimmedLines.join('\n');
122881
+ const processed = escapeLeadingListMarkers(trimmedLines.join('\n'));
122868
122882
  const tree = contentParser.runSync(contentParser.parse(processed));
122869
122883
  // Process markdown inside HTML blocks that have non-tag inner text (e.g. `<div>**x**`
122870
122884
  // or `<ul><li>_x_</li></ul>`). Pure bare tags like "<i>" or "<br>" are left for rehypeRaw
@@ -124392,6 +124406,45 @@ function preprocessJSXExpressions(content) {
124392
124406
  return processed;
124393
124407
  }
124394
124408
 
124409
+ ;// ./processor/transform/mdxish/resolve-deferred-attribute-expression-props.ts
124410
+
124411
+
124412
+
124413
+ /**
124414
+ * Resolve attribute expressions that `mdxJsxElementHandler` deferred.
124415
+ *
124416
+ * The handler stashed each attribute expression's source in `node.data.deferredExpressions`
124417
+ * (keyed by prop name) instead of evaluating eagerly, because an eager result can be a React
124418
+ * element or function that rehypeRaw's `structuredClone` passthrough rejects. Now that we're
124419
+ * past the clone, evaluate each source with a scope of `{ React, ...mdxishScope }` and write
124420
+ * the real value into `properties` (e.g. an array of objects whose fields are React elements).
124421
+ *
124422
+ * Must run after `rehypeRaw` (past the clone) but before `normalizeMdxJsxNodes` rewrites these
124423
+ * `mdx-jsx` nodes into plain elements. Skipped in safeMode, which keeps expressions literal.
124424
+ */
124425
+ const resolveDeferredAttributeExpressionProps = () => (tree, file) => {
124426
+ const scope = { ...file.data.mdxishScope, React: (external_react_default()) };
124427
+ visit(tree, 'mdx-jsx', (node) => {
124428
+ const deferredExpressions = node.data?.deferredExpressions;
124429
+ if (!deferredExpressions)
124430
+ return;
124431
+ const properties = node.properties;
124432
+ Object.entries(deferredExpressions).forEach(([name, source]) => {
124433
+ try {
124434
+ properties[name] = evalExpression(source, scope);
124435
+ }
124436
+ catch {
124437
+ // Evaluation failed — fall back to the raw expression source so the attribute
124438
+ // renders as readable text rather than disappearing.
124439
+ properties[name] = source;
124440
+ }
124441
+ });
124442
+ delete node.data.deferredExpressions;
124443
+ });
124444
+ return tree;
124445
+ };
124446
+ /* harmony default export */ const resolve_deferred_attribute_expression_props = (resolveDeferredAttributeExpressionProps);
124447
+
124395
124448
  ;// ./processor/transform/mdxish/restore-snake-case-component-name.ts
124396
124449
 
124397
124450
 
@@ -125421,6 +125474,7 @@ function loadComponents() {
125421
125474
 
125422
125475
 
125423
125476
 
125477
+
125424
125478
 
125425
125479
 
125426
125480
  const defaultTransformers = [
@@ -125580,6 +125634,7 @@ function mdxish(mdContent, opts = {}) {
125580
125634
  .use(preserveBooleanProperties) // RehypeRaw converts boolean properties to empty strings
125581
125635
  .use(rehypeRaw, { passThrough: ['html-block', 'mdx-jsx'] }) // MDX JSX nodes bypass parse5's string-only HTML round-trip
125582
125636
  .use(restoreBooleanProperties)
125637
+ .use(safeMode ? undefined : resolve_deferred_attribute_expression_props) // Evaluate deferred attribute expressions on mdx-jsx nodes (now past rehypeRaw's clone)
125583
125638
  .use(normalize_mdx_jsx_nodes) // Rewrite `mdx-jsx` back to standard `element` nodes for downstream plugins
125584
125639
  .use(rehypeFlattenTableCellParagraphs) // Remove <p> wrappers inside table cells to prevent margin issues
125585
125640
  .use(mdxish_mermaid) // Add mermaid-render className to pre wrappers
@@ -125615,6 +125670,10 @@ const mix = (text, opts = {}) => {
125615
125670
  };
125616
125671
  /* harmony default export */ const lib_mix = (mix);
125617
125672
 
125673
+ ;// ./lib/extractToc.ts
125674
+
125675
+ /* harmony default export */ const lib_extractToc = (extractToc);
125676
+
125618
125677
  ;// ./processor/transform/migrate-callouts.ts
125619
125678
 
125620
125679
 
@@ -126056,12 +126115,16 @@ const tags = (doc) => {
126056
126115
 
126057
126116
 
126058
126117
 
126118
+
126119
+
126120
+
126059
126121
  const mdxishTags_tags = (doc) => {
126060
126122
  const set = new Set();
126061
126123
  const processor = remark()
126062
- .data('micromarkExtensions', [magicBlock(), mdxComponent()])
126063
- .data('fromMarkdownExtensions', [magicBlockFromMarkdown(), mdxComponentFromMarkdown()])
126064
- .use(mdx_blocks);
126124
+ .data('micromarkExtensions', [jsxTable(), magicBlock(), mdxComponent()])
126125
+ .data('fromMarkdownExtensions', [jsxTableFromMarkdown(), magicBlockFromMarkdown(), mdxComponentFromMarkdown()])
126126
+ .use(mdx_blocks)
126127
+ .use(mdxish_tables);
126065
126128
  const tree = processor.parse(doc);
126066
126129
  visit(processor.runSync(tree), isMDXElement, (node) => {
126067
126130
  if (node.name?.match(/^[A-Z]/)) {
@@ -126211,6 +126274,7 @@ async function stripComments(doc, { mdx, mdxish } = {}) {
126211
126274
 
126212
126275
 
126213
126276
 
126277
+
126214
126278
  ;// ./index.tsx
126215
126279
 
126216
126280