Skip to content

Conversation

@dannobytes
Copy link
Contributor

@dannobytes dannobytes commented Nov 26, 2025

PR App Fix CX-2543

🧰 Changes

Discovered through this ticket
that the TOC generated by the MDX renderer would become broken with
miscalculated nesting depths and exposing h3s or other heading depths that shouldn't be included.

This happened when a jsx element was embedded inside the MDX body and
the custom component name did not match the exported jsx elements.

For example:
image

I'm not entirely sure whether this is an edge-case we should be guarding
against from our custom component editor. Like, adding validation to
ensure that the component name matches what's being exported from it. My
gut tells me it'd be really hard to enforce that.

So, the fix here is to simply take this edge-case into account and add
protections for the cases where this happens.

When a component name doesn't match the jsx element name, it previously
was making its way into the plugin/toc flow. But b/c it has no
tagName, the getDepth() calculation would break and return a NaN
instead of a valid integer. This would break the nesting logic in
toctoHast() and cause all headers to render at the first level.

Fixed this by:

  1. filtering away these mismatched components that make it through
  2. additionally updating the getDepth() function to be more fail-proof
    and handle the case where tagName is undefined
before after
image image

🧬 QA & Testing

Tests should pass

Discovered through [this ticket](https://linear.app/readme-io/issue/CX-2543/tabapay-toc-does-not-respect-headers-nesting)
that the TOC generated by the MDX renderer would become broken with
miscalculated nesting depths.

This happened when a jsx element was embedded inside the MDX body and
the custom component name did not match the exported jsx elements.

For example:
image here

I'm not entirely sure whether this is an edge-case we should be guarding
against from our custom component editor. Like, adding validation to
ensure that the component name matches what's being exported from it. My
gut tells me it'd be really hard to enforce that.

So, the fix here is to simply take this edge-case into account and add
protections for the cases where this happens.

When a component name doesn't match the jsx element name, it previously
was making its way into the `plugin/toc` flow. But b/c it has no
`tagName`, the `getDepth()` calculation would break and return a `NaN`
instead of a valid integer. This would break the nesting logic in
`toctoHast()` and cause all headers to render at the first level.

Fixed this by:
1. filtering away these mismatched components that make it through
1. additionally updating the `getDepth()` function to be more fail-proof
   and handle the case where `tagName` is undefined

CX-2543
@dannobytes dannobytes requested a review from a team November 26, 2025 06:49
@dannobytes dannobytes changed the title fix(toc): prevent misnamed mdx components from breaking TOC nesting fix(toc): prevent misnamed mdx components from breaking TOC Nov 26, 2025
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.

2 participants