Skip to content

Conversation

@HugoHSun
Copy link
Contributor

@HugoHSun HugoHSun commented Jan 14, 2026

PR App Fix CX-2621

🧰 Changes

Variables like {user.name} in headings were not resolving in the Table of Contents, showing blank or the raw expression instead of the value.

Changes:

  • Add ESTree AST inspection in plain.ts to resolve MDX expressions (matches approach in processor/transform/variables.ts)
  • Handle lowercase 'variable' tagName for MDXish (rehypeRaw normalizes custom element names to lowercase)
  • Flatten variables in tocToHast() to use user values or default

The fix ensures both rendering paths resolve variables:

  • MDX: mdxTextExpression nodes → ESTree AST inspection
  • MDXish: elements → tagName switch case

🧬 QA & Testing

Adds tests for variable resolution in TOC headings for both MDX and MDXish rendering paths.

Superhub (MDX) MDXISH Legacy
image image image
image image image

lib/plain.ts Outdated
variables?: Record<string, string>;
}

interface MdxExpressionNode {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this structure from a library? If so I wonder if we can just import it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are full types available from mdast-util-mdx-expression (MdxTextExpressionHast) and estree-jsx (MemberExpression, Identifier, etc.), but using them requires more verbose type narrowing since ESTree types are unions that can represent any JS expression, not just user.name. This interface would document exactly the shape we expect and avoids multiple type assertions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How much verbose it would be? I'm just worried we'll accidentally access some attribute that we didn't account for, or the type from the library changed unknowingly and we would have to update this. Could you explain how we get this type, or provide a link to the type from the library this is based on?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The node structure comes from two libraries:

  1. mdast-util-mdx-expression - defines MdxTextExpressionHast for the node wrapper
    npm | types source

  2. estree-jsx (ESTree spec) - defines the Program, MemberExpression, Identifier structure inside data.estree
    npm | ESTree spec

But yea it would be more maintainable using library types, have refactored it!

@HugoHSun HugoHSun marked this pull request as ready for review January 15, 2026 05:56
Variables like {user.name} in headings were not resolving in the Table
of Contents, showing blank or the raw expression instead of the value.

Changes:
- Add ESTree AST inspection in plain.ts to resolve MDX expressions
  (matches approach in processor/transform/variables.ts)
- Handle lowercase 'variable' tagName for MDXish (rehypeRaw normalizes
  custom element names to lowercase)
- Flatten variables in tocToHast() to use user values or default

The fix ensures both rendering paths resolve variables:
- MDX: mdxTextExpression nodes → ESTree AST inspection
- MDXish: <variable> elements → tagName switch case

Adds tests for variable resolution in TOC headings for both MDX and
MDXish rendering paths.
Replace custom MdxExpressionNode interface with proper types from
mdast-util-mdx-expression and estree for better type safety and
maintainability.
@HugoHSun HugoHSun force-pushed the hugo/cx-2621-variables-inside-headings-do-not-resolve-in-refactored branch from cfd37a3 to f3430f9 Compare January 21, 2026 05:44
@HugoHSun HugoHSun requested a review from erunion January 21, 2026 06:06
@erunion erunion removed their request for review January 21, 2026 18:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants