Skip to content
This repository was archived by the owner on Apr 27, 2026. It is now read-only.
This repository was archived by the owner on Apr 27, 2026. It is now read-only.

Support markdown content inside JSX container components (Steps, FileTree, etc.) #154

Description

@jp-knj

Problem

Several MDX files fall back to @mdx-js/mdx due to markdown-rs parse errors when JSX components contain markdown content:

Markdown parse error: 147:2: Unexpected closing slash `/` in tag, expected an open tag first

Affected patterns:

<Steps>
1. First step with **bold** text
2. Second step
</Steps>
<FileTree>
- folder/
  - nested file
</FileTree>

Affected files (~24 in withastro-docs):

  • concepts/islands.mdx (13 translations)
  • guides/cms/builderio.mdx (5 translations)
  • guides/media/mux.mdx (3 translations)
  • guides/cms/keystatic.mdx (2 files)

Root Cause

markdown-rs's JSX parser has strict rules. When it parses <Steps>, it enters "JSX flow content" mode and cannot recognize markdown syntax (like numbered lists) inside the tag body. When it encounters </Steps>, it fails because it lost track of the opening tag context.

Existing Preprocessing

Markflow already has preprocessing in jsx_normalize.rs that handles:

  • JSX near markdown (inserting blank lines)
  • Multiline wrapper tags (collapsing <p> wrappers)
  • Tab components in list contexts

The gap: These don't handle markdown inside JSX.

Proposed Solution: Extend Masking Pattern

The existing mask_raw_html_blocks function successfully masks <script> and <style> blocks before parsing. The same pattern can be extended for markdown-container components:

  1. Before parsing, mask <Steps>...</Steps>, <FileTree>...</FileTree>, etc. with placeholders
  2. Parse the remaining markdown normally
  3. Parse the masked content separately as markdown
  4. Restore the parsed HTML into the component slots

Implementation location: crates/core/src/renderer/mdast/mod.rs

Components to support:

  • Steps (wrap in <ol>)
  • FileTree (wrap in <ul>)
  • Box, Tabs, TabItem (pass through)

Estimated Effort

2-4 hours of Rust work:

  • ~150-200 lines in mod.rs
  • Test cases for masking/unmasking
  • No changes to JSX normalization, rendering, or codegen layers

Alternatives Considered

Approach Effort Risk Notes
Masking pattern (recommended) Low Low Reuses proven infrastructure
Container component registry Medium Medium More code changes across pipeline
Extend directive system Low Low Requires users to change syntax
Extract and reparse High High Complex state management

Current Workaround

The fallback to @mdx-js/mdx works correctly. These files represent ~0.5% of withastro-docs.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions