@readme/markdown 15.9.2 → 15.9.3

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.
@@ -56,3 +56,5 @@ export declare const TOKENIZER_MDX_COMPONENT_EXCLUDED_TAGS: Set<string>;
56
56
  * run after rehype (where hast `tagName` is normalized to lowercase).
57
57
  */
58
58
  export declare const INLINE_COMPONENT_TAGS_LOWER: Set<string>;
59
+ /** Raw markup props injected with `dangerouslySetInnerHTML` by HTMLBlock and Embed; never interpolate reader values. */
60
+ export declare const RAW_HTML_PROP_NAMES: Set<string>;
@@ -6,3 +6,5 @@
6
6
  * an MDX surface, and `{user.*}` is the syntax authors use there.
7
7
  */
8
8
  export declare function resolveAttributeVariables(value: string, user: Record<string, unknown>): string;
9
+ /** Whether an attribute expression's source is a bare `user.*` reference, left for render-time substitution. */
10
+ export declare const isBareVariableReference: (source: string) => boolean;
package/dist/main.js CHANGED
@@ -13191,6 +13191,8 @@ const TOKENIZER_MDX_COMPONENT_EXCLUDED_TAGS = new Set([
13191
13191
  * run after rehype (where hast `tagName` is normalized to lowercase).
13192
13192
  */
13193
13193
  const INLINE_COMPONENT_TAGS_LOWER = new Set([...INLINE_COMPONENT_TAGS].map(t => t.toLowerCase()));
13194
+ /** Raw markup props injected with `dangerouslySetInnerHTML` by HTMLBlock and Embed; never interpolate reader values. */
13195
+ const RAW_HTML_PROP_NAMES = new Set(['html']);
13194
13196
 
13195
13197
  ;// ./node_modules/github-slugger/regex.js
13196
13198
  // This module is generated by `script/`.
@@ -107775,33 +107777,75 @@ function repairMistakenTableClosers(content) {
107775
107777
  return applyInserts(content, edits).value;
107776
107778
  }
107777
107779
 
107780
+ ;// ./lib/utils/mdxish/mdxish-variables.ts
107781
+
107782
+
107783
+ // The `$` guard skips template-literal interpolation: `${user.name}` embeds `{user.name}`, and
107784
+ // substituting it would leave a mangled `` `Hi $Name` `` behind. Those belong to an expression,
107785
+ // which either evaluated already or is meant to stay literal.
107786
+ const MDX_VARIABLE_REGEX = new RegExp(`(?<!\\$)${variable_.MDX_VARIABLE_REGEXP}`, 'gu');
107787
+ // A whole attribute expression that is one `user.*` reference, e.g. the `user.name` in `title={user.name}`.
107788
+ const BARE_VARIABLE_REGEX = new RegExp(`^${variable_.MDX_VARIABLE_REGEXP}$`, 'u');
107789
+ // Bracket notation names the same variable as dot notation, so normalize it before substituting.
107790
+ // Escaped and `$`-prefixed forms are left alone so a reference that stays literal keeps its source.
107791
+ // A closing escape needs no lookahead: requiring a literal `]}` already rules out `]\}`.
107792
+ const BRACKET_NOTATION_REGEX = /(?<![$\\])\{user\[['"](\w+)['"]\]\}/gu;
107793
+ /**
107794
+ * Resolve `{user.*}` in a JSX attribute value against the same `user` binding the rmdx engine gets,
107795
+ * so both engines agree. Body text differs on empty values: `Variable` falls back to the default.
107796
+ *
107797
+ * Legacy `<<...>>` is valid inside a quoted attribute but deliberately left literal — attributes are
107798
+ * an MDX surface, and `{user.*}` is the syntax authors use there.
107799
+ */
107800
+ function resolveAttributeVariables(value, user) {
107801
+ if (!value.includes('{user'))
107802
+ return value;
107803
+ return value
107804
+ .replace(BRACKET_NOTATION_REGEX, '{user.$1}')
107805
+ .replace(MDX_VARIABLE_REGEX, (source, escapePrefix, name, escapeSuffix) => {
107806
+ if (escapePrefix || escapeSuffix)
107807
+ return source;
107808
+ return stringifyVariableValue(user[name]);
107809
+ });
107810
+ }
107811
+ /** Whether an attribute expression's source is a bare `user.*` reference, left for render-time substitution. */
107812
+ const isBareVariableReference = (source) => BARE_VARIABLE_REGEX.test(`{${source.trim()}}`.replace(BRACKET_NOTATION_REGEX, '{user.$1}'));
107813
+
107778
107814
  ;// ./processor/transform/mdxish/resolve-deferred-attribute-expression-props.ts
107779
107815
 
107780
107816
 
107781
107817
 
107782
107818
 
107819
+
107820
+
107821
+
107783
107822
  /**
107784
107823
  * Resolve attribute expressions that `mdxJsxElementHandler` deferred.
107785
107824
  *
107786
107825
  * The handler stashed each attribute expression's source in `node.data.deferredExpressions`
107787
107826
  * (keyed by prop name) instead of evaluating eagerly, because an eager result can be a React
107788
107827
  * element or function that rehypeRaw's `structuredClone` passthrough rejects. Now that we're
107789
- * past the clone, evaluate each source with a scope of `{ React, ...mdxishScope }` and write
107828
+ * past the clone, evaluate each source with a scope of `{ user, React, ...mdxishScope }` and write
107790
107829
  * the real value into `properties` (e.g. an array of objects whose fields are React elements).
107791
107830
  *
107792
107831
  * Must run after `rehypeRaw` (past the clone) but before `normalizeMdxJsxNodes` rewrites these
107793
107832
  * `mdx-jsx` nodes into plain elements. Skipped in safeMode, which keeps expressions literal.
107794
107833
  */
107795
- const resolveDeferredAttributeExpressionProps = () => (tree, file) => {
107834
+ const resolveDeferredAttributeExpressionProps = ({ variables } = {}) => (tree, file) => {
107796
107835
  const scope = { ...file.data.mdxishScope, React: (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default()) };
107836
+ // `user` only when variables were supplied, as in `evaluateExpressions`.
107837
+ const userScope = variables ? { user: user(variables), ...scope } : scope;
107797
107838
  visit(tree, 'mdx-jsx', (node) => {
107798
107839
  const deferredExpressions = node.data?.deferredExpressions;
107799
107840
  if (!deferredExpressions)
107800
107841
  return;
107801
107842
  const properties = node.properties;
107802
107843
  Object.entries(deferredExpressions).forEach(([name, source]) => {
107844
+ // Raw markup never gets `user`: a reader's values reaching `dangerouslySetInnerHTML` is an injection
107845
+ // vector. A bare `{user.x}` keeps render-time substitution, which stringifies structured values.
107846
+ const canReadUser = !RAW_HTML_PROP_NAMES.has(name) && !isBareVariableReference(source);
107803
107847
  try {
107804
- const result = evalExpression(source, scope);
107848
+ const result = evalExpression(source, canReadUser ? userScope : scope);
107805
107849
  // hast/HTML `style` is a plain CSS string; a `style={{...}}` expression evaluates to
107806
107850
  // a JS object, which must be serialized or it renders as the literal "[object Object]".
107807
107851
  properties[name] = name === 'style' && style_object_to_css_isPlainObject(result) ? styleObjectToCssText(result) : result;
@@ -108465,7 +108509,7 @@ function mdxish(mdContent, opts = {}) {
108465
108509
  .use(preserveBooleanProperties) // RehypeRaw converts boolean properties to empty strings
108466
108510
  .use(rehypeRaw, { passThrough: ['html-block', 'mdx-jsx'] }) // MDX JSX nodes bypass parse5's string-only HTML round-trip
108467
108511
  .use(restoreBooleanProperties)
108468
- .use(safeMode ? undefined : resolve_deferred_attribute_expression_props) // Evaluate deferred attribute expressions on mdx-jsx nodes (now past rehypeRaw's clone)
108512
+ .use(safeMode ? undefined : resolve_deferred_attribute_expression_props, { variables }) // Evaluate deferred attribute expressions on mdx-jsx nodes (now past rehypeRaw's clone)
108469
108513
  .use(normalize_mdx_jsx_nodes) // Rewrite `mdx-jsx` back to standard `element` nodes for downstream plugins
108470
108514
  .use(sanitize ? rehypeStripTags : undefined) // Strip STRIPPED_TAG_NAMES elements; this pipeline has no sanitization step
108471
108515
  .use(rehypeFlattenTableCellParagraphs) // Remove <p> wrappers inside table cells to prevent margin issues
@@ -108671,36 +108715,6 @@ const makeUseMDXComponents = (more = {}) => {
108671
108715
  };
108672
108716
  /* harmony default export */ const makeUseMdxComponents = (makeUseMDXComponents);
108673
108717
 
108674
- ;// ./lib/utils/mdxish/mdxish-variables.ts
108675
-
108676
-
108677
- // The `$` guard skips template-literal interpolation: `${user.name}` embeds `{user.name}`, and
108678
- // substituting it would leave a mangled `` `Hi $Name` `` behind. Those belong to an expression,
108679
- // which either evaluated already or is meant to stay literal.
108680
- const MDX_VARIABLE_REGEX = new RegExp(`(?<!\\$)${variable_.MDX_VARIABLE_REGEXP}`, 'gu');
108681
- // Bracket notation names the same variable as dot notation, so normalize it before substituting.
108682
- // Escaped and `$`-prefixed forms are left alone so a reference that stays literal keeps its source.
108683
- // A closing escape needs no lookahead: requiring a literal `]}` already rules out `]\}`.
108684
- const BRACKET_NOTATION_REGEX = /(?<![$\\])\{user\[['"](\w+)['"]\]\}/gu;
108685
- /**
108686
- * Resolve `{user.*}` in a JSX attribute value against the same `user` binding the rmdx engine gets,
108687
- * so both engines agree. Body text differs on empty values: `Variable` falls back to the default.
108688
- *
108689
- * Legacy `<<...>>` is valid inside a quoted attribute but deliberately left literal — attributes are
108690
- * an MDX surface, and `{user.*}` is the syntax authors use there.
108691
- */
108692
- function resolveAttributeVariables(value, user) {
108693
- if (!value.includes('{user'))
108694
- return value;
108695
- return value
108696
- .replace(BRACKET_NOTATION_REGEX, '{user.$1}')
108697
- .replace(MDX_VARIABLE_REGEX, (source, escapePrefix, name, escapeSuffix) => {
108698
- if (escapePrefix || escapeSuffix)
108699
- return source;
108700
- return stringifyVariableValue(user[name]);
108701
- });
108702
- }
108703
-
108704
108718
  ;// ./lib/utils/mdxish/mdxish-render-utils.tsx
108705
108719
 
108706
108720
 
@@ -108711,6 +108725,7 @@ function resolveAttributeVariables(value, user) {
108711
108725
 
108712
108726
 
108713
108727
 
108728
+
108714
108729
  /** Flatten CustomComponents into a component map for rehype-react */
108715
108730
  function exportComponentsForRehype(components) {
108716
108731
  const exported = Object.entries(components).reduce((memo, [tag, mod]) => {
@@ -108743,8 +108758,6 @@ function exportComponentsForRehype(components) {
108743
108758
  * deliberately leaves mermaid alone; resolving it again here would override that.
108744
108759
  */
108745
108760
  const CODE_TAG_NAMES = new Set(['code']);
108746
- /** Raw markup injected with `dangerouslySetInnerHTML` by HTMLBlock and Embed — never interpolate. */
108747
- const RAW_HTML_PROP_NAMES = new Set(['html']);
108748
108761
  /**
108749
108762
  * Resolve `{user.*}` in string-valued props. Body text is handled by the `Variable` component, but
108750
108763
  * attributes are plain strings, so they are substituted here — at render time, so that a
package/dist/main.node.js CHANGED
@@ -25789,6 +25789,8 @@ const TOKENIZER_MDX_COMPONENT_EXCLUDED_TAGS = new Set([
25789
25789
  * run after rehype (where hast `tagName` is normalized to lowercase).
25790
25790
  */
25791
25791
  const INLINE_COMPONENT_TAGS_LOWER = new Set([...INLINE_COMPONENT_TAGS].map(t => t.toLowerCase()));
25792
+ /** Raw markup props injected with `dangerouslySetInnerHTML` by HTMLBlock and Embed; never interpolate reader values. */
25793
+ const RAW_HTML_PROP_NAMES = new Set(['html']);
25792
25794
 
25793
25795
  ;// ./node_modules/github-slugger/regex.js
25794
25796
  // This module is generated by `script/`.
@@ -128024,33 +128026,75 @@ function repairMistakenTableClosers(content) {
128024
128026
  return applyInserts(content, edits).value;
128025
128027
  }
128026
128028
 
128029
+ ;// ./lib/utils/mdxish/mdxish-variables.ts
128030
+
128031
+
128032
+ // The `$` guard skips template-literal interpolation: `${user.name}` embeds `{user.name}`, and
128033
+ // substituting it would leave a mangled `` `Hi $Name` `` behind. Those belong to an expression,
128034
+ // which either evaluated already or is meant to stay literal.
128035
+ const MDX_VARIABLE_REGEX = new RegExp(`(?<!\\$)${variable_dist.MDX_VARIABLE_REGEXP}`, 'gu');
128036
+ // A whole attribute expression that is one `user.*` reference, e.g. the `user.name` in `title={user.name}`.
128037
+ const BARE_VARIABLE_REGEX = new RegExp(`^${variable_dist.MDX_VARIABLE_REGEXP}$`, 'u');
128038
+ // Bracket notation names the same variable as dot notation, so normalize it before substituting.
128039
+ // Escaped and `$`-prefixed forms are left alone so a reference that stays literal keeps its source.
128040
+ // A closing escape needs no lookahead: requiring a literal `]}` already rules out `]\}`.
128041
+ const BRACKET_NOTATION_REGEX = /(?<![$\\])\{user\[['"](\w+)['"]\]\}/gu;
128042
+ /**
128043
+ * Resolve `{user.*}` in a JSX attribute value against the same `user` binding the rmdx engine gets,
128044
+ * so both engines agree. Body text differs on empty values: `Variable` falls back to the default.
128045
+ *
128046
+ * Legacy `<<...>>` is valid inside a quoted attribute but deliberately left literal — attributes are
128047
+ * an MDX surface, and `{user.*}` is the syntax authors use there.
128048
+ */
128049
+ function resolveAttributeVariables(value, user) {
128050
+ if (!value.includes('{user'))
128051
+ return value;
128052
+ return value
128053
+ .replace(BRACKET_NOTATION_REGEX, '{user.$1}')
128054
+ .replace(MDX_VARIABLE_REGEX, (source, escapePrefix, name, escapeSuffix) => {
128055
+ if (escapePrefix || escapeSuffix)
128056
+ return source;
128057
+ return stringifyVariableValue(user[name]);
128058
+ });
128059
+ }
128060
+ /** Whether an attribute expression's source is a bare `user.*` reference, left for render-time substitution. */
128061
+ const isBareVariableReference = (source) => BARE_VARIABLE_REGEX.test(`{${source.trim()}}`.replace(BRACKET_NOTATION_REGEX, '{user.$1}'));
128062
+
128027
128063
  ;// ./processor/transform/mdxish/resolve-deferred-attribute-expression-props.ts
128028
128064
 
128029
128065
 
128030
128066
 
128031
128067
 
128068
+
128069
+
128070
+
128032
128071
  /**
128033
128072
  * Resolve attribute expressions that `mdxJsxElementHandler` deferred.
128034
128073
  *
128035
128074
  * The handler stashed each attribute expression's source in `node.data.deferredExpressions`
128036
128075
  * (keyed by prop name) instead of evaluating eagerly, because an eager result can be a React
128037
128076
  * element or function that rehypeRaw's `structuredClone` passthrough rejects. Now that we're
128038
- * past the clone, evaluate each source with a scope of `{ React, ...mdxishScope }` and write
128077
+ * past the clone, evaluate each source with a scope of `{ user, React, ...mdxishScope }` and write
128039
128078
  * the real value into `properties` (e.g. an array of objects whose fields are React elements).
128040
128079
  *
128041
128080
  * Must run after `rehypeRaw` (past the clone) but before `normalizeMdxJsxNodes` rewrites these
128042
128081
  * `mdx-jsx` nodes into plain elements. Skipped in safeMode, which keeps expressions literal.
128043
128082
  */
128044
- const resolveDeferredAttributeExpressionProps = () => (tree, file) => {
128083
+ const resolveDeferredAttributeExpressionProps = ({ variables } = {}) => (tree, file) => {
128045
128084
  const scope = { ...file.data.mdxishScope, React: (external_react_default()) };
128085
+ // `user` only when variables were supplied, as in `evaluateExpressions`.
128086
+ const userScope = variables ? { user: user(variables), ...scope } : scope;
128046
128087
  visit(tree, 'mdx-jsx', (node) => {
128047
128088
  const deferredExpressions = node.data?.deferredExpressions;
128048
128089
  if (!deferredExpressions)
128049
128090
  return;
128050
128091
  const properties = node.properties;
128051
128092
  Object.entries(deferredExpressions).forEach(([name, source]) => {
128093
+ // Raw markup never gets `user`: a reader's values reaching `dangerouslySetInnerHTML` is an injection
128094
+ // vector. A bare `{user.x}` keeps render-time substitution, which stringifies structured values.
128095
+ const canReadUser = !RAW_HTML_PROP_NAMES.has(name) && !isBareVariableReference(source);
128052
128096
  try {
128053
- const result = evalExpression(source, scope);
128097
+ const result = evalExpression(source, canReadUser ? userScope : scope);
128054
128098
  // hast/HTML `style` is a plain CSS string; a `style={{...}}` expression evaluates to
128055
128099
  // a JS object, which must be serialized or it renders as the literal "[object Object]".
128056
128100
  properties[name] = name === 'style' && style_object_to_css_isPlainObject(result) ? styleObjectToCssText(result) : result;
@@ -128714,7 +128758,7 @@ function mdxish(mdContent, opts = {}) {
128714
128758
  .use(preserveBooleanProperties) // RehypeRaw converts boolean properties to empty strings
128715
128759
  .use(rehypeRaw, { passThrough: ['html-block', 'mdx-jsx'] }) // MDX JSX nodes bypass parse5's string-only HTML round-trip
128716
128760
  .use(restoreBooleanProperties)
128717
- .use(safeMode ? undefined : resolve_deferred_attribute_expression_props) // Evaluate deferred attribute expressions on mdx-jsx nodes (now past rehypeRaw's clone)
128761
+ .use(safeMode ? undefined : resolve_deferred_attribute_expression_props, { variables }) // Evaluate deferred attribute expressions on mdx-jsx nodes (now past rehypeRaw's clone)
128718
128762
  .use(normalize_mdx_jsx_nodes) // Rewrite `mdx-jsx` back to standard `element` nodes for downstream plugins
128719
128763
  .use(sanitize ? rehypeStripTags : undefined) // Strip STRIPPED_TAG_NAMES elements; this pipeline has no sanitization step
128720
128764
  .use(rehypeFlattenTableCellParagraphs) // Remove <p> wrappers inside table cells to prevent margin issues
@@ -128920,36 +128964,6 @@ const makeUseMDXComponents = (more = {}) => {
128920
128964
  };
128921
128965
  /* harmony default export */ const makeUseMdxComponents = (makeUseMDXComponents);
128922
128966
 
128923
- ;// ./lib/utils/mdxish/mdxish-variables.ts
128924
-
128925
-
128926
- // The `$` guard skips template-literal interpolation: `${user.name}` embeds `{user.name}`, and
128927
- // substituting it would leave a mangled `` `Hi $Name` `` behind. Those belong to an expression,
128928
- // which either evaluated already or is meant to stay literal.
128929
- const MDX_VARIABLE_REGEX = new RegExp(`(?<!\\$)${variable_dist.MDX_VARIABLE_REGEXP}`, 'gu');
128930
- // Bracket notation names the same variable as dot notation, so normalize it before substituting.
128931
- // Escaped and `$`-prefixed forms are left alone so a reference that stays literal keeps its source.
128932
- // A closing escape needs no lookahead: requiring a literal `]}` already rules out `]\}`.
128933
- const BRACKET_NOTATION_REGEX = /(?<![$\\])\{user\[['"](\w+)['"]\]\}/gu;
128934
- /**
128935
- * Resolve `{user.*}` in a JSX attribute value against the same `user` binding the rmdx engine gets,
128936
- * so both engines agree. Body text differs on empty values: `Variable` falls back to the default.
128937
- *
128938
- * Legacy `<<...>>` is valid inside a quoted attribute but deliberately left literal — attributes are
128939
- * an MDX surface, and `{user.*}` is the syntax authors use there.
128940
- */
128941
- function resolveAttributeVariables(value, user) {
128942
- if (!value.includes('{user'))
128943
- return value;
128944
- return value
128945
- .replace(BRACKET_NOTATION_REGEX, '{user.$1}')
128946
- .replace(MDX_VARIABLE_REGEX, (source, escapePrefix, name, escapeSuffix) => {
128947
- if (escapePrefix || escapeSuffix)
128948
- return source;
128949
- return stringifyVariableValue(user[name]);
128950
- });
128951
- }
128952
-
128953
128967
  ;// ./lib/utils/mdxish/mdxish-render-utils.tsx
128954
128968
 
128955
128969
 
@@ -128960,6 +128974,7 @@ function resolveAttributeVariables(value, user) {
128960
128974
 
128961
128975
 
128962
128976
 
128977
+
128963
128978
  /** Flatten CustomComponents into a component map for rehype-react */
128964
128979
  function exportComponentsForRehype(components) {
128965
128980
  const exported = Object.entries(components).reduce((memo, [tag, mod]) => {
@@ -128992,8 +129007,6 @@ function exportComponentsForRehype(components) {
128992
129007
  * deliberately leaves mermaid alone; resolving it again here would override that.
128993
129008
  */
128994
129009
  const CODE_TAG_NAMES = new Set(['code']);
128995
- /** Raw markup injected with `dangerouslySetInnerHTML` by HTMLBlock and Embed — never interpolate. */
128996
- const RAW_HTML_PROP_NAMES = new Set(['html']);
128997
129010
  /**
128998
129011
  * Resolve `{user.*}` in string-valued props. Body text is handled by the `Variable` component, but
128999
129012
  * attributes are plain strings, so they are substituted here — at render time, so that a