@readme/markdown 14.7.2 → 14.8.1

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
@@ -19377,15 +19377,34 @@ __webpack_require__.d(util_types_namespaceObject, {
19377
19377
  // EXTERNAL MODULE: external "react"
19378
19378
  var external_react_ = __webpack_require__(4953);
19379
19379
  var external_react_default = /*#__PURE__*/__webpack_require__.n(external_react_);
19380
+ ;// ./components/Icon/index.tsx
19381
+
19382
+ /** @see https://docs-v5.fontawesome.com/web/reference-icons */
19383
+ const FA_PREFIXES = new Set(['fa', 'fab', 'fad', 'fal', 'far', 'fas', 'fast', 'fasl', 'fasr', 'fass', 'fat']);
19384
+ /**
19385
+ * Renders an icon element, either as a Font Awesome icon or an emoji.
19386
+ */
19387
+ const Icon = ({ className, icon, iconColor }) => {
19388
+ const hasFontAwesomePrefix = FA_PREFIXES.has(icon.split(' ')[0]);
19389
+ const isFontAwesome = hasFontAwesomePrefix || icon.startsWith('fa-');
19390
+ if (!isFontAwesome) {
19391
+ return external_react_default().createElement("span", { className: className }, icon);
19392
+ }
19393
+ const faClasses = hasFontAwesomePrefix ? icon : `fa-duotone fa-solid ${icon}`;
19394
+ return external_react_default().createElement("i", { className: `${className} ${faClasses}`, style: iconColor ? { color: iconColor } : undefined });
19395
+ };
19396
+ /* harmony default export */ const components_Icon = (Icon);
19397
+
19380
19398
  ;// ./components/Accordion/index.tsx
19381
19399
 
19382
19400
 
19401
+
19383
19402
  const Accordion = ({ children, icon, iconColor, title }) => {
19384
19403
  const [isOpen, setIsOpen] = (0,external_react_.useState)(false);
19385
19404
  return (external_react_default().createElement("details", { className: "Accordion", onToggle: () => setIsOpen(!isOpen) },
19386
19405
  external_react_default().createElement("summary", { className: "Accordion-title" },
19387
19406
  external_react_default().createElement("i", { className: `Accordion-toggleIcon${isOpen ? '_opened' : ''} fa fa-regular fa-chevron-right` }),
19388
- icon && external_react_default().createElement("i", { className: `Accordion-icon fa-duotone fa-solid ${icon}`, style: { color: `${iconColor}` } }),
19407
+ icon && external_react_default().createElement(components_Icon, { className: "Accordion-icon", icon: icon, iconColor: iconColor }),
19389
19408
  title),
19390
19409
  external_react_default().createElement("div", { className: "Accordion-content" }, children)));
19391
19410
  };
@@ -19507,10 +19526,11 @@ const Callout = (props) => {
19507
19526
  ;// ./components/Cards/index.tsx
19508
19527
 
19509
19528
 
19529
+
19510
19530
  const Card = ({ badge, children, href, kind = 'card', icon, iconColor, target, title }) => {
19511
19531
  const Tag = href ? 'a' : 'div';
19512
19532
  return (external_react_default().createElement(Tag, { className: `Card Card_${kind}`, href: href, target: target },
19513
- icon && external_react_default().createElement("i", { className: `Card-icon fa-duotone fa-solid ${icon}`, style: { '--Card-icon-color': iconColor } }),
19533
+ icon && external_react_default().createElement(components_Icon, { className: "Card-icon", icon: icon, iconColor: iconColor }),
19514
19534
  external_react_default().createElement("div", { className: "Card-content" },
19515
19535
  title && (external_react_default().createElement("div", { className: "Card-title" },
19516
19536
  title,
@@ -25129,10 +25149,18 @@ function useScrollHighlight(navRef) {
25129
25149
  return rect.top >= 0 && rect.top < window.innerHeight * VISIBLE_RATIO;
25130
25150
  }) || headings[0];
25131
25151
  activate(initialHeading.id);
25152
+ // Snap the active indicator to its initial position without animating, then
25153
+ // enable transitions so only subsequent scroll updates animate. The forced
25154
+ // reflow (reading layout) commits the snapped position as the transition
25155
+ // baseline — otherwise enabling the transition in the same style recalc would
25156
+ // animate it in from height 0 every time the TOC (re)mounts.
25157
+ nav.getBoundingClientRect();
25158
+ nav.dataset.tocReady = 'true';
25132
25159
  return () => {
25133
25160
  observer.disconnect();
25134
25161
  scrollTarget.removeEventListener('scroll', onScroll);
25135
25162
  nav.removeEventListener('click', onClick);
25163
+ delete nav.dataset.tocReady;
25136
25164
  };
25137
25165
  }, [navRef, tocKey]);
25138
25166
  }
@@ -25148,6 +25176,7 @@ function TableOfContents({ children }) {
25148
25176
  ;// ./components/Tabs/index.tsx
25149
25177
 
25150
25178
 
25179
+
25151
25180
  const Tab = ({ children }) => {
25152
25181
  return external_react_default().createElement("div", { className: "TabContent" }, children);
25153
25182
  };
@@ -25158,7 +25187,7 @@ const Tabs = ({ children }) => {
25158
25187
  return (external_react_default().createElement("div", { className: "TabGroup" },
25159
25188
  external_react_default().createElement("header", null,
25160
25189
  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) },
25161
- tab.props.icon && (external_react_default().createElement("i", { className: `TabGroup-icon fa-duotone fa-solid ${tab.props.icon}`, style: { color: `${tab.props.iconColor}` } })),
25190
+ tab.props.icon && (external_react_default().createElement(components_Icon, { className: "TabGroup-icon", icon: tab.props.icon, iconColor: tab.props.iconColor })),
25162
25191
  tab.props.title))))),
25163
25192
  external_react_default().createElement("section", null, tabs[activeTab])));
25164
25193
  };
@@ -118950,26 +118979,17 @@ const rehypeMdxishComponents = ({ components, processMarkdown }) => {
118950
118979
  ;// ./processor/plugin/mdxish-handlers.ts
118951
118980
 
118952
118981
 
118953
-
118954
118982
  // Convert MDX expressions to text nodes (evaluation happens earlier in pipeline)
118955
118983
  const mdxExpressionHandler = (_state, node) => ({
118956
118984
  type: 'text',
118957
118985
  value: node.value || '',
118958
118986
  });
118959
- function isStructuredCloneable(value) {
118960
- try {
118961
- structuredClone(value);
118962
- return true;
118963
- }
118964
- catch {
118965
- return false;
118966
- }
118967
- }
118968
118987
  // Convert MDX JSX elements to a custom mdx-jsx hast node that bypasses rehypeRaw's
118969
118988
  // HTML serialization round-trip; downstream normalization rewrites it to `element`.
118970
118989
  const mdxJsxElementHandler = (state, node) => {
118971
118990
  const { attributes = [], name } = node;
118972
118991
  const properties = {};
118992
+ const deferredExpressions = {};
118973
118993
  attributes.forEach(attribute => {
118974
118994
  if (attribute.type !== 'mdxJsxAttribute' || !attribute.name)
118975
118995
  return;
@@ -118980,30 +119000,20 @@ const mdxJsxElementHandler = (state, node) => {
118980
119000
  properties[attribute.name] = decode_decodeHTMLStrict(attribute.value);
118981
119001
  }
118982
119002
  else {
118983
- const expressionSource = attribute.value.value;
118984
- let evaluated;
118985
- try {
118986
- evaluated = evaluate(expressionSource);
118987
- }
118988
- catch {
118989
- evaluated = expressionSource;
118990
- }
118991
- // rehypeRaw's passThrough clones our mdx-jsx node with structuredClone, which
118992
- // rejects functions and other non-serializable values. Attribute expressions
118993
- // that evaluate to such values (`onClick={() => ...}`) would crash the pipeline,
118994
- // so if we have a non-serializable value, we fall back to the raw expression source
118995
- // and not support it for now.
118996
- if (!isStructuredCloneable(evaluated)) {
118997
- evaluated = expressionSource;
118998
- }
118999
- properties[attribute.name] = evaluated;
119003
+ // Defer every attribute-expression evaluation past rehypeRaw's `structuredClone`
119004
+ // passthrough: evaluating here can yield React elements or functions that the clone
119005
+ // rejects. The source is stashed in `node.data` (clone-safe) and
119006
+ // `resolveDeferredAttributeExpressionProps` evaluates it once past the clone.
119007
+ deferredExpressions[attribute.name] = attribute.value.value;
119000
119008
  }
119001
119009
  });
119010
+ const hasDeferredExpressions = Object.keys(deferredExpressions).length > 0;
119002
119011
  const jsxNode = {
119003
119012
  type: 'mdx-jsx',
119004
119013
  tagName: name || '',
119005
- properties,
119014
+ properties: properties,
119006
119015
  children: state.all(node),
119016
+ ...(hasDeferredExpressions && { data: { deferredExpressions } }),
119007
119017
  };
119008
119018
  return jsxNode;
119009
119019
  };
@@ -122285,27 +122295,56 @@ const evaluateExports = () => (tree, file) => {
122285
122295
 
122286
122296
  // EXTERNAL MODULE: ./node_modules/react-dom/server.node.js
122287
122297
  var server_node = __webpack_require__(4362);
122288
- ;// ./processor/transform/mdxish/evaluate-expressions.ts
122289
-
122298
+ ;// ./lib/utils/mdxish/mdxish-expression.ts
122290
122299
 
122291
122300
 
122292
122301
 
122293
-
122294
-
122295
- const HAS_JSX = /<[A-Za-z]|<>/;
122296
- /** The raw Function() can't parse JSX, so parse & convert it to a React element first so later we can get its HTML representation */
122297
- const evalJsxExpression = (expression, scope) => {
122298
- const program = jsxAcornParser.parse(expression, { ecmaVersion: 'latest', sourceType: 'module' });
122302
+ const parseExpression = (expression) => jsxAcornParser.parse(expression, { ecmaVersion: 'latest', sourceType: 'module' });
122303
+ /**
122304
+ * Recursively report whether an estree value contains any JSX element or fragment node.
122305
+ * estree stores children across named fields (not a `children` array), so this descends
122306
+ * through every nested object/array rather than using a unist-shaped walker.
122307
+ */
122308
+ const containsJsxNode = (value) => {
122309
+ if (Array.isArray(value))
122310
+ return value.some(containsJsxNode);
122311
+ if (value === null || typeof value !== 'object')
122312
+ return false;
122313
+ const { type } = value;
122314
+ if (type === 'JSXElement' || type === 'JSXFragment')
122315
+ return true;
122316
+ return Object.values(value).some(containsJsxNode);
122317
+ };
122318
+ /** Convert a program's JSX into `React.createElement` calls and evaluate it. `scope` must provide `React`. */
122319
+ const evalJsxProgram = (program, scope) => {
122299
122320
  buildJsx(program, { runtime: 'classic', pragma: 'React.createElement', pragmaFrag: 'React.Fragment' });
122300
122321
  const { value: source } = toJs(program);
122301
122322
  return evaluate(`(() => { return ${source.trim().replace(/;$/, '')}; })()`, scope);
122302
122323
  };
122303
- /** Evaluate an expression body, transforming JSX to `React.createElement` only when needed. */
122324
+ /**
122325
+ * Evaluate an expression body, transforming JSX to `React.createElement` only when the
122326
+ * parsed estree actually contains a JSX node. The raw `Function()` evaluator can't parse
122327
+ * JSX, so JSX-bearing expressions take the build-and-serialize path while everything else
122328
+ * evaluates directly. Input acorn can't parse falls back to the plain evaluator unchanged.
122329
+ */
122304
122330
  const evalExpression = (expression, scope) => {
122305
- if (HAS_JSX.test(expression))
122306
- return evalJsxExpression(expression, scope);
122307
- return evaluate(expression, scope);
122331
+ let program;
122332
+ try {
122333
+ program = parseExpression(expression);
122334
+ }
122335
+ catch {
122336
+ return evaluate(expression, scope);
122337
+ }
122338
+ if (!containsJsxNode(program))
122339
+ return evaluate(expression, scope);
122340
+ return evalJsxProgram(program, scope);
122308
122341
  };
122342
+
122343
+ ;// ./processor/transform/mdxish/evaluate-expressions.ts
122344
+
122345
+
122346
+
122347
+
122309
122348
  /** Given the type of the expression result, create the corresponding mdast node. */
122310
122349
  const createEvaluatedNode = (result, position) => {
122311
122350
  if (result === null || result === undefined) {
@@ -124363,6 +124402,45 @@ function preprocessJSXExpressions(content) {
124363
124402
  return processed;
124364
124403
  }
124365
124404
 
124405
+ ;// ./processor/transform/mdxish/resolve-deferred-attribute-expression-props.ts
124406
+
124407
+
124408
+
124409
+ /**
124410
+ * Resolve attribute expressions that `mdxJsxElementHandler` deferred.
124411
+ *
124412
+ * The handler stashed each attribute expression's source in `node.data.deferredExpressions`
124413
+ * (keyed by prop name) instead of evaluating eagerly, because an eager result can be a React
124414
+ * element or function that rehypeRaw's `structuredClone` passthrough rejects. Now that we're
124415
+ * past the clone, evaluate each source with a scope of `{ React, ...mdxishScope }` and write
124416
+ * the real value into `properties` (e.g. an array of objects whose fields are React elements).
124417
+ *
124418
+ * Must run after `rehypeRaw` (past the clone) but before `normalizeMdxJsxNodes` rewrites these
124419
+ * `mdx-jsx` nodes into plain elements. Skipped in safeMode, which keeps expressions literal.
124420
+ */
124421
+ const resolveDeferredAttributeExpressionProps = () => (tree, file) => {
124422
+ const scope = { ...file.data.mdxishScope, React: (external_react_default()) };
124423
+ visit(tree, 'mdx-jsx', (node) => {
124424
+ const deferredExpressions = node.data?.deferredExpressions;
124425
+ if (!deferredExpressions)
124426
+ return;
124427
+ const properties = node.properties;
124428
+ Object.entries(deferredExpressions).forEach(([name, source]) => {
124429
+ try {
124430
+ properties[name] = evalExpression(source, scope);
124431
+ }
124432
+ catch {
124433
+ // Evaluation failed — fall back to the raw expression source so the attribute
124434
+ // renders as readable text rather than disappearing.
124435
+ properties[name] = source;
124436
+ }
124437
+ });
124438
+ delete node.data.deferredExpressions;
124439
+ });
124440
+ return tree;
124441
+ };
124442
+ /* harmony default export */ const resolve_deferred_attribute_expression_props = (resolveDeferredAttributeExpressionProps);
124443
+
124366
124444
  ;// ./processor/transform/mdxish/restore-snake-case-component-name.ts
124367
124445
 
124368
124446
 
@@ -125392,6 +125470,7 @@ function loadComponents() {
125392
125470
 
125393
125471
 
125394
125472
 
125473
+
125395
125474
 
125396
125475
 
125397
125476
  const defaultTransformers = [
@@ -125551,6 +125630,7 @@ function mdxish(mdContent, opts = {}) {
125551
125630
  .use(preserveBooleanProperties) // RehypeRaw converts boolean properties to empty strings
125552
125631
  .use(rehypeRaw, { passThrough: ['html-block', 'mdx-jsx'] }) // MDX JSX nodes bypass parse5's string-only HTML round-trip
125553
125632
  .use(restoreBooleanProperties)
125633
+ .use(safeMode ? undefined : resolve_deferred_attribute_expression_props) // Evaluate deferred attribute expressions on mdx-jsx nodes (now past rehypeRaw's clone)
125554
125634
  .use(normalize_mdx_jsx_nodes) // Rewrite `mdx-jsx` back to standard `element` nodes for downstream plugins
125555
125635
  .use(rehypeFlattenTableCellParagraphs) // Remove <p> wrappers inside table cells to prevent margin issues
125556
125636
  .use(mdxish_mermaid) // Add mermaid-render className to pre wrappers