Skip to content

Conversation

@maximilianfalco
Copy link
Contributor

@maximilianfalco maximilianfalco commented Dec 12, 2025

PR App Fix RM-14615

🧰 Changes

We were seeing cases where magic blocks that uses the code cases was wrapped in paragraph nodes which caused invalid HTML and values like props not being passed down correctly which resulting in errors and causing the page to not be renderable.

CodeTabs were also being split into two components like this:

Before After
Screenshot 2025-12-12 at 11 15 57 Screenshot 2025-12-12 at 11 55 19

This PR fixes this by detecting when code-tabs nodes are inserted into paragraphs and lifting them out to the root level, preventing the paragraph wrapper and ensuring props are passed correctly.

Note

The fix only affects code tabs, so other block-level elements (like tables) are unchanged.

🧬 QA & Testing

Use the attached md file in the linear ticket. Paste it into raw mode and make sure no errors are thrown. Or use this raw md to test all magic block types in one go

[block:callout]
{"type":"info","body":"Hello"}
[/block]

[block:image]
{
  "images": [
    {
      "image": [
        "https://files.readme.io/fd21f977cfbb9f55b3a13ab0b827525e94ee1576f21bbe82945cdc22cc966d82-Screenshot_2024-09-12_at_3.47.05_PM.png",
        "",
        "Data Plane Setup"
      ],
      "align": "center",
      "caption": "Data Plane Setup",
      "border": true
    }
  ]
}
[/block]

[block:html]
{
  "html": "<h1>Hoo ha</h1>"
}
[/block]

[block:api-header]
{
  "title": "About CFO Control Control Tower"
}
[/block]

[block:parameters]
{
  "data": {
    "h-0": "Response",
    "0-0": "{'Message': 'There are **validation errors**', 'Errors': ['ConsumerDetails: <div>The ExternalId or CustomerID</div> must have a value.']}"
  },
  "cols": 2,
  "rows": 1,
  "align": [null, null]
}
[/block]

[block:embed]
{
  "url": "https://www.youtube.com/watch?v=FVikHLyW500&list=RD3-9V38W00CM&index=4",
  "provider": "youtube.com",
  "href": "https://www.youtube.com/watch?v=FVikHLyW500&list=RD3-9V38W00CM&index=4",
  "typeOfEmbed": "youtube"
}
[/block]

[block:code]
{
  "sidebar": true,
  "codes": [
    {
      "code": "const sidebar = 'deprecated'",
      "language": "javascript"
    }
  ]
}
[/block]

[block:code]
{
  "codes": [
    {
      "code": "hello",
      "language": "text",
      "name": "Pre-Modification Certificate"
    }
  ]
}
[/block]

paragraphParent = pParent as Parent;
return false;
// If parent is a paragraph and we're inserting block nodes (which must not be in paragraphs), lift them out
if (parent.type === 'paragraph' && children.some(child => isBlockNode(child))) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Will this not affect other magic blocks behaviour?

Copy link
Contributor Author

@maximilianfalco maximilianfalco Jan 14, 2026

Choose a reason for hiding this comment

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

testing using the attached testing block in the description and the results are looking fine

Screenshot 2026-01-14 at 16 01 23

Copy link
Contributor

@kevinports kevinports left a comment

Choose a reason for hiding this comment

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

I linked this branch locally and QA'd with the snippet you provided in the PR description, and I'm seeing one of the code blocks getting dropped when rendering:

Screen.Cast.2026-01-16.at.10.23.56.AM.mp4

Copy link
Contributor

Choose a reason for hiding this comment

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

Not blocking! Just a general question about this transformer for my understanding because I wasn't really involved in the initial setup of the mdxish engine.

Why didn't we re-use the magic block parser from the legacy rdmd engine instead of writing this new transformer plus the extraction/replacement stuff?
See this code from the v6 branch: https://github.com/readmeio/markdown/blob/v6/processor/parse/magic-block-parser.js

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes actually that transformer is based off from the legacy magic block parser! It's just we had to do quite a lot of adjustments such as providing types (since the legacy was in js) and because data processing flow is a bit different from legacy

@maximilianfalco
Copy link
Contributor Author

@kevinports ah sorry about that, turns out there was a sidebar prop for magic blocks that we didnt knew about and it was causing some rendering issues. should all be fixed in ef99b8e

Screenshot 2026-01-19 at 15 13 46

Copy link
Contributor

@kevinports kevinports left a comment

Choose a reason for hiding this comment

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

Now working when I tested it. Just had a few more comments.

@maximilianfalco maximilianfalco merged commit ea6e7bb into readmeio:next Jan 21, 2026
9 of 10 checks passed
rafegoldberg pushed a commit that referenced this pull request Jan 21, 2026
## Version 12.0.0
### ⚠ BREAKING CHANGES

* **mdxish:** the component tree.

**3. HTML Entity Decoding**
Because we introduced the double quotes, I needed to encode & decode
some special characters in the attributes so it doesn't split the
attributes nodes

**Before**
<img width="854" height="349" alt="Screenshot 2026-01-16 at 9 18 19 pm"
src="https://github.com/user-attachments/assets/a948297d-6d88-410c-8c38-6324dda1d260"
/>

**After**

https://github.com/user-attachments/assets/3973a605-eb30-4312-9029-5aa1f5aa9cb6

## 🧬 QA & Testing

- [Broken on production][prod].
- [Working in this PR app][demo].

1. In an mdxish project, create a custom component with some props
2. In a document, use the component while passing in template literal
prop. For example:
```
<MyComponent title={`Hello world`} />
```

[demo]: https://markdown-pr-PR_NUMBER.herokuapp.com
[prod]: https://SUBDOMAIN.readme.io
[icn]:
https://user-images.githubusercontent.com/886627/160426047-1bee9488-305a-4145-bb2b-09d8b757d38a.svg

### 🛠 Fixes & Updates

* allow parsing empty callouts like `>` without breaking ([#1260](#1260)) ([98a8c65](98a8c65))
* **mdxish:** fix rendering issues with `Code` magic blocks ([#1259](#1259)) ([ea6e7bb](ea6e7bb))
* **mdxish:** process jsx attributes on custom components ([#1298](#1298)) ([7f21a5e](7f21a5e))
* **mdxish:** remove unused whitespace nodes when rehyping components ([#1297](#1297)) ([33e868a](33e868a))

<!--SKIP CI-->
@rafegoldberg
Copy link
Contributor

This PR was released!

🚀 Changes included in v12.0.0

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants