@readme/markdown 15.9.2 → 15.9.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.
@@ -1,16 +1,20 @@
1
+ import type { Variables } from '../../../types';
1
2
  import type { Root } from 'hast';
2
3
  import type { Plugin } from 'unified';
4
+ interface Options {
5
+ variables?: Variables;
6
+ }
3
7
  /**
4
8
  * Resolve attribute expressions that `mdxJsxElementHandler` deferred.
5
9
  *
6
10
  * The handler stashed each attribute expression's source in `node.data.deferredExpressions`
7
11
  * (keyed by prop name) instead of evaluating eagerly, because an eager result can be a React
8
12
  * element or function that rehypeRaw's `structuredClone` passthrough rejects. Now that we're
9
- * past the clone, evaluate each source with a scope of `{ React, ...mdxishScope }` and write
13
+ * past the clone, evaluate each source with a scope of `{ user, React, ...mdxishScope }` and write
10
14
  * the real value into `properties` (e.g. an array of objects whose fields are React elements).
11
15
  *
12
16
  * Must run after `rehypeRaw` (past the clone) but before `normalizeMdxJsxNodes` rewrites these
13
17
  * `mdx-jsx` nodes into plain elements. Skipped in safeMode, which keeps expressions literal.
14
18
  */
15
- declare const resolveDeferredAttributeExpressionProps: Plugin<[], Root>;
19
+ declare const resolveDeferredAttributeExpressionProps: Plugin<[Options?], Root>;
16
20
  export default resolveDeferredAttributeExpressionProps;
@@ -19111,7 +19111,7 @@ module.exports = function () {
19111
19111
 
19112
19112
  /***/ },
19113
19113
 
19114
- /***/ 1186
19114
+ /***/ 7905
19115
19115
  (module, __webpack_exports__, __webpack_require__) {
19116
19116
 
19117
19117
  "use strict";
@@ -19358,6 +19358,8 @@ const TOKENIZER_MDX_COMPONENT_EXCLUDED_TAGS = new Set([
19358
19358
  * run after rehype (where hast `tagName` is normalized to lowercase).
19359
19359
  */
19360
19360
  const INLINE_COMPONENT_TAGS_LOWER = new Set([...INLINE_COMPONENT_TAGS].map(t => t.toLowerCase()));
19361
+ /** Raw markup props injected with `dangerouslySetInnerHTML` by HTMLBlock and Embed; never interpolate reader values. */
19362
+ const RAW_HTML_PROP_NAMES = new Set(['html']);
19361
19363
 
19362
19364
  ;// ./node_modules/github-slugger/regex.js
19363
19365
  // This module is generated by `script/`.
@@ -93264,6 +93266,26 @@ const mdxToHast = () => tree => {
93264
93266
  };
93265
93267
  /* harmony default export */ const mdx_to_hast = ((/* unused pure expression or super */ null && (mdxToHast)));
93266
93268
 
93269
+ ;// ./lib/mdast-util/mdx-expression/index.ts
93270
+
93271
+ const upstream = mdxExpressionFromMarkdown();
93272
+ /**
93273
+ * An image's alt is its label flattened to text, which drops an expression's braces. Keep the
93274
+ * `{...}` source there so `{user.*}` still resolves in alt at render time (RM-10865).
93275
+ */
93276
+ function exitTextExpression(token) {
93277
+ upstream.exit.mdxTextExpression.call(this, token);
93278
+ if (!this.stack.some(node => node.type === 'image'))
93279
+ return;
93280
+ const { children } = this.stack[this.stack.length - 1];
93281
+ const { position } = children[children.length - 1];
93282
+ children[children.length - 1] = { type: 'text', value: this.sliceSerialize(token), position };
93283
+ }
93284
+ /** Upstream `mdxExpressionFromMarkdown`, overriding only the text-expression exit to keep `{...}` source in image alt. */
93285
+ function mdxishExpressionFromMarkdown() {
93286
+ return { ...upstream, exit: { ...upstream.exit, mdxTextExpression: exitTextExpression } };
93287
+ }
93288
+
93267
93289
  ;// ./lib/mdast-util/empty-task-list-item/index.ts
93268
93290
  /**
93269
93291
  * Normalizes list items that are written as only `[ ]` or `[x]` into GFM task
@@ -93496,6 +93518,16 @@ function exitlegacyVariableValue(token) {
93496
93518
  function exitlegacyVariable(token) {
93497
93519
  const ctx = legacy_variable_contextMap.get(token);
93498
93520
  const serialized = this.sliceSerialize(token);
93521
+ // An escaped `\<<name>>` (or `\<<name\>>`) is literal text, as in the legacy parser.
93522
+ if (serialized.startsWith('\\')) {
93523
+ const literal = serialized.slice(1).replace('\\>>', '>>');
93524
+ // An image's alt is flattened to a string, so keep the escape for render-time resolution to honor.
93525
+ const inImageAlt = this.stack.some(node => node.type === 'image');
93526
+ this.enter({ type: 'text', value: inImageAlt ? `\\${literal}` : literal }, token);
93527
+ this.exit(token);
93528
+ legacy_variable_contextMap.delete(token);
93529
+ return;
93530
+ }
93499
93531
  const variableName = serialized.startsWith('<<') && serialized.endsWith('>>')
93500
93532
  ? serialized.slice(2, -2)
93501
93533
  : ctx?.value ?? '';
@@ -95089,9 +95121,16 @@ const legacyVariableConstruct = {
95089
95121
  function syntax_tokenize(effects, ok, nok) {
95090
95122
  let hasValue = false;
95091
95123
  const start = (code) => {
95124
+ effects.enter('legacyVariable');
95125
+ // Claim `\<<name>>` before CommonMark's character escape drops the backslash, as the legacy parser did.
95126
+ if (code !== codes.backslash)
95127
+ return open(code);
95128
+ effects.consume(code); // \
95129
+ return open;
95130
+ };
95131
+ const open = (code) => {
95092
95132
  if (code !== codes.lessThan)
95093
95133
  return nok(code);
95094
- effects.enter('legacyVariable');
95095
95134
  effects.enter('legacyVariableMarkerStart');
95096
95135
  effects.consume(code); // <
95097
95136
  return open2;
@@ -95131,7 +95170,7 @@ function syntax_tokenize(effects, ok, nok) {
95131
95170
  }
95132
95171
  function legacyVariable() {
95133
95172
  return {
95134
- text: { [codes.lessThan]: legacyVariableConstruct },
95173
+ text: { [codes.backslash]: legacyVariableConstruct, [codes.lessThan]: legacyVariableConstruct },
95135
95174
  };
95136
95175
  }
95137
95176
 
@@ -97455,12 +97494,12 @@ const REGISTRY = {
97455
97494
  magicBlock: { syntax: magicBlock, fromMarkdown: magicBlockFromMarkdown },
97456
97495
  // Two `{` tokenizers, never registered together: the document parser takes text
97457
97496
  // only, the component-body re-parser needs flow too for multi-line expressions.
97458
- mdxExpressionLenient: { syntax: mdxExpressionLenient, fromMarkdown: mdxExpressionFromMarkdown, expression: true },
97497
+ mdxExpressionLenient: { syntax: mdxExpressionLenient, fromMarkdown: mdxishExpressionFromMarkdown, expression: true },
97459
97498
  // `allowEmpty` is the package default; passed explicitly because `mdx-jsx`
97460
97499
  // registers the same tokenizer with it off for attribute expressions.
97461
97500
  mdxExpression: {
97462
97501
  syntax: () => mdxExpression({ allowEmpty: true }),
97463
- fromMarkdown: mdxExpressionFromMarkdown,
97502
+ fromMarkdown: mdxishExpressionFromMarkdown,
97464
97503
  expression: true,
97465
97504
  },
97466
97505
  mdxComponent: { syntax: mdxComponent, fromMarkdown: mdxComponentFromMarkdown },
@@ -101060,6 +101099,7 @@ const splitHtmlWithNestedTables = (node, source) => {
101060
101099
 
101061
101100
 
101062
101101
 
101102
+
101063
101103
 
101064
101104
 
101065
101105
  const isTableCell = (node) => isMDXElement(node) && ['th', 'td'].includes(node.name);
@@ -101080,9 +101120,13 @@ const buildTableNodeProcessor = (withMdx) => {
101080
101120
  const { micromarkExtensions, fromMarkdownExtensions } = mdxishExtensions(FEATURES.tableCell);
101081
101121
  // `mdxjs` goes first (= lowest priority): its `mdxJsx` also claims `text` + `<`,
101082
101122
  // and `legacyVariable` has to keep winning that race so `<<var>>` still parses.
101123
+ // `mdxishExpressionFromMarkdown` follows `mdxFromMarkdown` to override its expression exit.
101083
101124
  return unified()
101084
101125
  .data('micromarkExtensions', [...(withMdx ? [mdxjs()] : []), ...micromarkExtensions])
101085
- .data('fromMarkdownExtensions', [...(withMdx ? [mdxFromMarkdown()] : []), ...fromMarkdownExtensions])
101126
+ .data('fromMarkdownExtensions', [
101127
+ ...(withMdx ? [mdxFromMarkdown(), mdxishExpressionFromMarkdown()] : []),
101128
+ ...fromMarkdownExtensions,
101129
+ ])
101086
101130
  .use(remarkParse)
101087
101131
  .use(normalize_malformed_md_syntax)
101088
101132
  .use([[callouts, { isMdxish: true }], code_tabs])
@@ -127792,33 +127836,81 @@ function repairMistakenTableClosers(content) {
127792
127836
  return applyInserts(content, edits).value;
127793
127837
  }
127794
127838
 
127839
+ ;// ./lib/utils/mdxish/mdxish-variables.ts
127840
+
127841
+
127842
+ // The `$` guard skips template-literal interpolation: `${user.name}` embeds `{user.name}`, and
127843
+ // substituting it would leave a mangled `` `Hi $Name` `` behind. Those belong to an expression,
127844
+ // which either evaluated already or is meant to stay literal.
127845
+ const MDX_VARIABLE_REGEX = new RegExp(`(?<!\\$)${variable_dist.MDX_VARIABLE_REGEXP}`, 'gu');
127846
+ // A whole attribute expression that is one `user.*` reference, e.g. the `user.name` in `title={user.name}`.
127847
+ const BARE_VARIABLE_REGEX = new RegExp(`^${variable_dist.MDX_VARIABLE_REGEXP}$`, 'u');
127848
+ // Bracket notation names the same variable as dot notation, so normalize it before substituting.
127849
+ // Escaped and `$`-prefixed forms are left alone so a reference that stays literal keeps its source.
127850
+ // A closing escape needs no lookahead: requiring a literal `]}` already rules out `]\}`.
127851
+ const BRACKET_NOTATION_REGEX = /(?<![$\\])\{user\[['"](\w+)['"]\]\}/gu;
127852
+ const ALT_VARIABLE_REGEX = new RegExp(`${MDX_VARIABLE_REGEX.source}|${variable_dist.VARIABLE_REGEXP}`, 'gu');
127853
+ /**
127854
+ * Resolve `{user.*}` in a JSX attribute value against the same `user` binding the rmdx engine gets,
127855
+ * so both engines agree. Body text differs on empty values: `Variable` falls back to the default.
127856
+ *
127857
+ * Legacy `<<...>>` is valid inside a quoted attribute but deliberately left literal — attributes are
127858
+ * an MDX surface, and `{user.*}` is the syntax authors use there. Image alt is the exception, resolved
127859
+ * in the same pass so a substituted value is never rescanned (RM-10865).
127860
+ */
127861
+ function resolveAttributeVariables(value, user, isImageAlt = false) {
127862
+ if (!isImageAlt && !value.includes('{user'))
127863
+ return value;
127864
+ return value
127865
+ .replace(BRACKET_NOTATION_REGEX, '{user.$1}')
127866
+ .replace(isImageAlt ? ALT_VARIABLE_REGEX : MDX_VARIABLE_REGEX, (source, _prefix, name, _suffix, legacyName) => {
127867
+ // Variable names can't contain a backslash, so one marks an escaped reference.
127868
+ if (source.includes('\\'))
127869
+ return isImageAlt ? source.replaceAll('\\', '') : source;
127870
+ const key = (name ?? legacyName).trim();
127871
+ if (key.startsWith('glossary:'))
127872
+ return key.slice('glossary:'.length).trim();
127873
+ return stringifyVariableValue(user[key]);
127874
+ });
127875
+ }
127876
+ /** Whether an attribute expression's source is a bare `user.*` reference, left for render-time substitution. */
127877
+ const isBareVariableReference = (source) => BARE_VARIABLE_REGEX.test(`{${source.trim()}}`.replace(BRACKET_NOTATION_REGEX, '{user.$1}'));
127878
+
127795
127879
  ;// ./processor/transform/mdxish/resolve-deferred-attribute-expression-props.ts
127796
127880
 
127797
127881
 
127798
127882
 
127799
127883
 
127884
+
127885
+
127886
+
127800
127887
  /**
127801
127888
  * Resolve attribute expressions that `mdxJsxElementHandler` deferred.
127802
127889
  *
127803
127890
  * The handler stashed each attribute expression's source in `node.data.deferredExpressions`
127804
127891
  * (keyed by prop name) instead of evaluating eagerly, because an eager result can be a React
127805
127892
  * element or function that rehypeRaw's `structuredClone` passthrough rejects. Now that we're
127806
- * past the clone, evaluate each source with a scope of `{ React, ...mdxishScope }` and write
127893
+ * past the clone, evaluate each source with a scope of `{ user, React, ...mdxishScope }` and write
127807
127894
  * the real value into `properties` (e.g. an array of objects whose fields are React elements).
127808
127895
  *
127809
127896
  * Must run after `rehypeRaw` (past the clone) but before `normalizeMdxJsxNodes` rewrites these
127810
127897
  * `mdx-jsx` nodes into plain elements. Skipped in safeMode, which keeps expressions literal.
127811
127898
  */
127812
- const resolveDeferredAttributeExpressionProps = () => (tree, file) => {
127899
+ const resolveDeferredAttributeExpressionProps = ({ variables } = {}) => (tree, file) => {
127813
127900
  const scope = { ...file.data.mdxishScope, React: (external_react_default()) };
127901
+ // `user` only when variables were supplied, as in `evaluateExpressions`.
127902
+ const userScope = variables ? { user: user(variables), ...scope } : scope;
127814
127903
  visit(tree, 'mdx-jsx', (node) => {
127815
127904
  const deferredExpressions = node.data?.deferredExpressions;
127816
127905
  if (!deferredExpressions)
127817
127906
  return;
127818
127907
  const properties = node.properties;
127819
127908
  Object.entries(deferredExpressions).forEach(([name, source]) => {
127909
+ // Raw markup never gets `user`: a reader's values reaching `dangerouslySetInnerHTML` is an injection
127910
+ // vector. A bare `{user.x}` keeps render-time substitution, which stringifies structured values.
127911
+ const canReadUser = !RAW_HTML_PROP_NAMES.has(name) && !isBareVariableReference(source);
127820
127912
  try {
127821
- const result = evalExpression(source, scope);
127913
+ const result = evalExpression(source, canReadUser ? userScope : scope);
127822
127914
  // hast/HTML `style` is a plain CSS string; a `style={{...}}` expression evaluates to
127823
127915
  // a JS object, which must be serialized or it renders as the literal "[object Object]".
127824
127916
  properties[name] = name === 'style' && style_object_to_css_isPlainObject(result) ? styleObjectToCssText(result) : result;
@@ -128428,7 +128520,7 @@ function mdxish(mdContent, opts = {}) {
128428
128520
  .use(preserveBooleanProperties) // RehypeRaw converts boolean properties to empty strings
128429
128521
  .use(rehypeRaw, { passThrough: ['html-block', 'mdx-jsx'] }) // MDX JSX nodes bypass parse5's string-only HTML round-trip
128430
128522
  .use(restoreBooleanProperties)
128431
- .use(safeMode ? undefined : resolve_deferred_attribute_expression_props) // Evaluate deferred attribute expressions on mdx-jsx nodes (now past rehypeRaw's clone)
128523
+ .use(safeMode ? undefined : resolve_deferred_attribute_expression_props, { variables }) // Evaluate deferred attribute expressions on mdx-jsx nodes (now past rehypeRaw's clone)
128432
128524
  .use(normalize_mdx_jsx_nodes) // Rewrite `mdx-jsx` back to standard `element` nodes for downstream plugins
128433
128525
  .use(sanitize ? rehypeStripTags : undefined) // Strip STRIPPED_TAG_NAMES elements; this pipeline has no sanitization step
128434
128526
  .use(rehypeFlattenTableCellParagraphs) // Remove <p> wrappers inside table cells to prevent margin issues
@@ -128593,36 +128685,6 @@ const makeUseMDXComponents = (more = {}) => {
128593
128685
  };
128594
128686
  /* harmony default export */ const makeUseMdxComponents = (makeUseMDXComponents);
128595
128687
 
128596
- ;// ./lib/utils/mdxish/mdxish-variables.ts
128597
-
128598
-
128599
- // The `$` guard skips template-literal interpolation: `${user.name}` embeds `{user.name}`, and
128600
- // substituting it would leave a mangled `` `Hi $Name` `` behind. Those belong to an expression,
128601
- // which either evaluated already or is meant to stay literal.
128602
- const MDX_VARIABLE_REGEX = new RegExp(`(?<!\\$)${variable_dist.MDX_VARIABLE_REGEXP}`, 'gu');
128603
- // Bracket notation names the same variable as dot notation, so normalize it before substituting.
128604
- // Escaped and `$`-prefixed forms are left alone so a reference that stays literal keeps its source.
128605
- // A closing escape needs no lookahead: requiring a literal `]}` already rules out `]\}`.
128606
- const BRACKET_NOTATION_REGEX = /(?<![$\\])\{user\[['"](\w+)['"]\]\}/gu;
128607
- /**
128608
- * Resolve `{user.*}` in a JSX attribute value against the same `user` binding the rmdx engine gets,
128609
- * so both engines agree. Body text differs on empty values: `Variable` falls back to the default.
128610
- *
128611
- * Legacy `<<...>>` is valid inside a quoted attribute but deliberately left literal — attributes are
128612
- * an MDX surface, and `{user.*}` is the syntax authors use there.
128613
- */
128614
- function resolveAttributeVariables(value, user) {
128615
- if (!value.includes('{user'))
128616
- return value;
128617
- return value
128618
- .replace(BRACKET_NOTATION_REGEX, '{user.$1}')
128619
- .replace(MDX_VARIABLE_REGEX, (source, escapePrefix, name, escapeSuffix) => {
128620
- if (escapePrefix || escapeSuffix)
128621
- return source;
128622
- return stringifyVariableValue(user[name]);
128623
- });
128624
- }
128625
-
128626
128688
  ;// ./lib/utils/mdxish/mdxish-render-utils.tsx
128627
128689
 
128628
128690
 
@@ -128633,6 +128695,7 @@ function resolveAttributeVariables(value, user) {
128633
128695
 
128634
128696
 
128635
128697
 
128698
+
128636
128699
  /** Flatten CustomComponents into a component map for rehype-react */
128637
128700
  function exportComponentsForRehype(components) {
128638
128701
  const exported = Object.entries(components).reduce((memo, [tag, mod]) => {
@@ -128665,10 +128728,10 @@ function exportComponentsForRehype(components) {
128665
128728
  * deliberately leaves mermaid alone; resolving it again here would override that.
128666
128729
  */
128667
128730
  const CODE_TAG_NAMES = new Set(['code']);
128668
- /** Raw markup injected with `dangerouslySetInnerHTML` by HTMLBlock and Embed — never interpolate. */
128669
- const RAW_HTML_PROP_NAMES = new Set(['html']);
128731
+ const isImageAlt = (tagName, key) => tagName === 'img' && key === 'alt';
128670
128732
  /**
128671
- * Resolve `{user.*}` in string-valued props. Body text is handled by the `Variable` component, but
128733
+ * Resolve `{user.*}` in string-valued props, plus legacy `<<...>>` in img alt, where markdown flattens
128734
+ * body variables to text (RM-10865). Body text is handled by the `Variable` component, but
128672
128735
  * attributes are plain strings, so they are substituted here — at render time, so that a
128673
128736
  * server-parsed (user-agnostic) tree resolves against the current reader's variables.
128674
128737
  */
@@ -128678,7 +128741,7 @@ function resolveVariablesInProps(props, user, tagName) {
128678
128741
  const isDocumentContent = RAW_HTML_PROP_NAMES.has(key) || (isCodeTag && key === 'value');
128679
128742
  if (typeof value !== 'string' || isDocumentContent)
128680
128743
  return [key, value];
128681
- return [key, resolveAttributeVariables(value, user)];
128744
+ return [key, resolveAttributeVariables(value, user, isImageAlt(tagName, key))];
128682
128745
  });
128683
128746
  return Object.fromEntries(resolvedEntries);
128684
128747
  }
@@ -129513,7 +129576,7 @@ module.exports = /*#__PURE__*/JSON.parse('{"*":["about","acceptCharset","accessK
129513
129576
  /******/ // startup
129514
129577
  /******/ // Load entry module and return exports
129515
129578
  /******/ // This entry module used 'module' so it can't be inlined
129516
- /******/ let __webpack_exports__ = __webpack_require__(1186);
129579
+ /******/ let __webpack_exports__ = __webpack_require__(7905);
129517
129580
  /******/ module.exports = __webpack_exports__;
129518
129581
  /******/
129519
129582
  /******/ })()