wooorm / xdm

Just a *really* good MDX compiler. No runtime. With esbuild, Rollup, and webpack plugins
http://wooorm.com/xdm/
MIT License
595 stars 18 forks source link

Using JSX as props for a component #71

Closed alexanderson1993 closed 3 years ago

alexanderson1993 commented 3 years ago

Initial checklist

Affected packages and versions: xdm@1.12.1

Steps to reproduce

  1. Create some MDX that includes a React component. Include a prop that has JSX passed to it, with extra spaces between the JSX tags and the text content.
  2. Run that MDX through @mdx-js/mdx. The MDX should render without error. The text content inside the JSX should be rendered as if it were inline MDX, converting symbols like **bold** to <strong>bold</strong>.
  3. Run that MDX through xdm. An error is thrown: Error: Unexpected end of file in expression, expected a corresponding closing brace for \{``

Link to code example: https://codesandbox.io/s/mdx-jsmdx-vs-xdm-9357n?file=/src/index.js

Expected behavior

XDM should provide similar results to @mdx-js/mdx, properly parsing the MDX and converting MDX symbols inside the prop into HTML/JSX elements.

Actual behavior

An error is thrown, indicating that XDM can't parse the MDX content for some reason.

alexanderson1993 commented 3 years ago

I found this bug after converting a site from using @mdx-js/mdx to xdm, but found some of my pages weren't rendering at all. I'm not even sure where to start looking to fix it. I figured it was an actual bug when I saw @mdx-js/mdx is able to parse it just fine.

It would be awesome if XDM could parse MDX like I've described. Otherwise, any suggestions for how to work around this limitation would be great!

wooorm commented 3 years ago

Thanks for the repro Alex!

Hmm. Quite sure @mdx-js/mdx@next also doesn’t parse it, so this is a difference between the old and the newer parsers.

If you format it a bit different, it does work:

<Aside
  title="This is the title"
  extra={
    <div>
      Here is some **rich content** in the middle
    </div>
  }
>
  This is the child content.
</Aside>

This shows that you can now format JSX as you’d want, instead of having to resort to removing indentation and adding blank lines. Another change though is that you can’t enter markdown again inside braces. So the “rich content” wont be rich. That’s just JSX.

alexanderson1993 commented 3 years ago

Thanks for the info. This is super helpful.

I'm still digging into this. I'll let you know when I find the exact step in the process where it starts falling apart.

wooorm commented 3 years ago

To perhaps clarify, the most minimal working version is:

<Aside title="This is the title" extra={<div>

Here is some **rich content** in the middle

</div>}>
  This is the child content.
</Aside>

So, the way to nest changed. You have the opening tag, which is JS. Then you want to “enter markdown” again (a whitespace sensitive language, so they must be on their own lines). After it, you enter JSX again.

alexanderson1993 commented 3 years ago

It looks like the break is happening in /lib/plugin/remark-mdx.js, but I'm afraid I don't know enough about what's happening to dig in any further.

Since this isn't something supported by @mdx-js/mdx@next, I'll consider it unsafe, undocumented behavior and remove it from my app. No need for xdm to support it, unless you're feeling particularly ambitious.

Thanks again for your help!