Mdx: RFC: Interleaving Markdown in JSX

Created on 11 Jul 2019  ·  53Comments  ·  Source: mdx-js/mdx

Summary

Interleaving Markdown and JSX in MDX has been asked for by a lot of folks and is something we should officially support. It's been on the roadmap, but we've decided to add it as a minor version after v1. Now is that time 😸

It's a common need to wrap a block of content to achieve things like image + captions, notifs, callouts, and custom background/text colors for given sections.

Basic (proposed) example

Inline JSX blocks are automatically interleaved and block-level JSX requires an blank lines to open back up Markdown parsing:

# Hello, <span>*world*</span>, from <>{props.name}</>!

<Note>

This *is* **markdown**!

</Note>
Output JSX
<MDXLayout
  {...layoutProps}
  {...props}
  components={components}
  mdxType="MDXLayout"
>
  <h1>
    {`Hello, `}
    <span>
      <em parentName="h1">{`world`}</em>
    </span>
    {`, from `}
    <>{props.name}</>
    {`!`}
  </h1>
  <Note mdxType="Note">
    <p>
      {`This `}
      <em parentName="p">{`is`}</em>
      {` `}
      <strong parentName="p">{`markdown`}</strong>
      {`!`}
    </p>
  </Note>
</MDXLayout>

Motivation

This approach is currently being used in the wild and in production. As @jxnblk mentioned previously this approach comes with the benefit that it's in the Commonmark Spec.

Detailed design

The majority of parsing is already implemented. However, there are a few things we need to be able to address.

Handling embedded expressions {props.foo}

There are two additional scenarios where we need to be able to handle embedded expressions, which all essentially boil down to inline JSX.

# Hello, from <>{props.name}</>

<Note>

Here's another expression: <>{props.thing}</>

</Note>

This can get a bit tricky because technically the following should also be handled:

# Hello, <>from {props.name}</>

Handling more complex JSX blocks

When there is indented JSX across two lines the parser currently misses it. Something that doesn't currently work, but should:

# Hello, world!

<div>
  <div>

# I should be an h1 inside two divs

  </div>
<div>

Drawbacks

This will likely make the last JSX block parsing issue _more_ difficult. The biggest remaining block issue is where we have empty lines in the JSX. This causes parsing breakages for render props and template strings.

Render props

# Hello, world

<SomeComponent>
  {prop => {
    const newValue = doStuff(prop)

    return <h1>{newValue}</h1>
  }}
</SomeComponent>

Template strings

# Hello, world!

<SomeComponent
  someProp={`
    Here's a template string

    with empty lines
  `}
/>

Alternatives

The other main alternative we've considered is an MDX component.

# Hello, <span><MDX>*world*</MDX></span>!

<Note>
  <MDX>
    This *is* **markdown**!
  </MDX>
</Note>

An additional alternative from PHP Markdown Extra is using a markdown attribute:

# Hello, <span markdown="1">*world*</span>!

<Note markdown="1">
  This *is* **markdown**!
</Note>

This comes with the benefit of being more explicit, but it is confusing for folks coming from traditional Markdown as they slowly adopt JSX. It also feels syntactically noisy.

I've toyed with different syntax in place of MDX like aliasing it to something terser: <_>. However, this isn't as approachable.

Adoption strategy

Considering this already _mostly_ works and is already being used (just not officially supported) the adoption strategy should be straightforward. We'd need to fix some parsing edge cases mentioned above and add documentation.

Related issues

  • #195
  • #241
  • #345
  • #556
  • ... and many more 😆

cc/ @wooorm @jxnblk @ChristopherBiscardi @timneutkens @ChristianMurphy @silvenon

⛵️ statureleased 💎 v2 💬 typdiscussion 🗄 areinterface 🦋 typenhancement 🧑 semvemajor

Most helpful comment

Heads up everyone: we’re working on rewriting the parser to solve amongst other things, this problem, in 2.0.0. Out relatively soon!

All 53 comments

It's probably worth mentioning at the beginning what the output of span/world should be as fragments are mentioned later for interpolation but not for interleaving

# Hello, <span>*world*</span>!

<Note>

This *is* **markdown**!

</Note>

What should happen in this case?

# Hello, <>from {props.name}</>

It feels to me that if this worked, this should work as well:

# Hello from {props.name}

These things are hard 😓

What should happen in this case?

# Hello, <>from {props.name}</>

Yeahhh, good point. I wonder if we should only allow embedded expressions to be the only "children" in a JSX block (whether inline or block - <>{props.name}</>)? That would make the parsing easier for the render props case, too. 🤔

Yeah, I think that would be a win-win because it wouldn't be syntactically misleading.

would my use case in this issue:

https://github.com/mdx-js/mdx/issues/474

...be solved by this kind of feature? I realized that I'm really wanting to wrap different lists in different styles, but still write the lists in markdown, but then include jsx in the markdown, like so:

<ListStyleOne>

  -  Thing
      -  Subthing and this word is <Red>Red</Red> right here.
      -  Another subthing with a <Blue>colorful</Blue> word again.

</ListStyleOne>

it seems like this is the case initially, but I just want to be sure that I'm understanding this proposal correctly XD

would my use case in this issue:

474

...be solved by this kind of feature? I realized that I'm really wanting to wrap different lists in different styles, but still write the lists in markdown, but then include jsx in the markdown

It would 😄

noice :-)

This looks good! I think it makes sense for users. But there’s still some parser problems. Here goes a few more questions and random thoughts.

  • block-level JSX requires an empty newline

    To make sure we’re on the same page: I think you mean a blank line, namely two newlines (\n\n), optionally with white space (as defined by CM: https://spec.commonmark.org/0.29/#blank-lines). A newline is a carriage return and/or line feed. And line feed / carriage return are the unix / windows characters!

  • The first example:

    # Hello, <span>*world*</span>, from <>{props.name</>!
    

    Turns into (zooming into world):

    <span>
      <em parentName="h1">{`world`}</em>
    </span>
    

    …is parentName indeed h1? 🤔
    P.S. props.name misses a closing curly brace

  • I don’t think # Hello from {props.name} should be supported (@silvenon). Users are already learning that < and > need to be there to be in JSX. However, implementing it everywhere is easier than only inside inline JSX.

  • I think <>from {props.name}</> shouldn’t be too tricky. We start out with Markdown. If </> or other JSX is found, either inline or block level JSX is entered. We add a new inline tokenizer to remark that only works “in” JSX. This means we need to match open and closing tags for inline JSX though, but that’s doable. As {} are not used in “normal” Markdown, we could just as well support it everywhere though.

Drawbacks

Interesting insights: MDX in JSX blocks in MDX is typically not indented, and needs two blank lines. I think that’s too fragile to depend on though. 🤔

Would it make the parsing more explicit if the JSX block included a markdown prop/attribute? There's prior art here from PHP Markdown Extra that is worth reviewing.

Thanks for the thoughts @wooorm! I've addressed a few things in edits to the original comment.

…is parentName indeed h1?

Yeah I think this is something we'll need to also address since, you're right, it isn't 😆.

Would it make the parsing more explicit if the JSX block included a markdown prop/attribute? There's prior art here from PHP Markdown Extra that is worth reviewing.

Thanks for pointing this out @rsexton404! I've added it as an alternative in the comment. It'd definitely make parsing easier due to it's explicitness, but it's also a bit noisy. I'll need to think on that one!

Re markdown attribute, could be mdx as well:

# Hello, <span markdown="1">*world*</span>!

<Note mdx={true}>
  This *is* **markdown**!
</Note>

This is becoming such a complex language with its own highly detailed rules that it seems like it might be best to take the full source to a simple JSX parser and simple Markdown parser, and try to surgically combine them into a single MDX parser. It might very well be quicker and easier than trying to go down this route.

Here's another potential idea @johno: What if MDX had everything inside {{}} be JS, kind of like a reverse of JSX? It'd be a similar concept to Mustache. Here's an example:

# This is a {{<b>}}*header*{{</b>}}

This is a paragraph.

{{<Button>}}
  This is a *Markdown* button
{{</Button>}}

- This is
- a list

{{
  // This is just plain JS
  const size = 123;
  import MyCanvas from './MyCanvas';
}}

{{<MyCanvas width={size} height={size} />}}

Or here's an idea using just one, which I originally thought would clash with plain text that uses {, but it could be escaped as \{

# This is a {<b>}*header*{</b>}

This is a paragraph.

{<Button>}
  This is a *Markdown* button
{</Button>}

- This is
- a list

{
  // This is just plain JS
  const size = 123;
  import MyCanvas from './MyCanvas';
}

{<MyCanvas width={size} height={size} />}

Thanks for the suggestions @sdegutis!

We explored curly braces a bit for handling JSX but ultimately found it to be too noisy. Pure, inlined JSX feels more elegant and is more pleasant to work with as an author. Though, of course, it does make parsing more difficult.

Currently MDX _does_ use a surgically combined parser. It enhances remark's Markdown parser by extending its tokenization to recognize JSX syntax and import/exports. Currently, import/export blocks are then parsed/transformed with babel to do anything node massaging needed for the MDXAST.

The proposed interleaving is already _partially_ supported, it's just a matter of officially defining the syntax and then parsing a handful of additional cases. This route is ultimately something that we need as authors of MDX for callouts, messages, and other decorations to MDX markup.

We're not far off from achieving this next level of syntax/functionality, it's mostly a matter of fully defining the syntax we want and then rolling up our sleeves.

@johno Thanks for the response. I should probably explain a little bit about where I'm coming from.

I found MDX about a year ago because my client has a use-case that MDX in its 0.x incarnation is somewhat close to suitable for, and the evolution of syntax ideas in these issues are really close to suitable for. But as I tried to integrate MDX into our system, there were too many rough edges, so I put that whole project on hold.

Coming back to that project this month, I looked into MDX again and found these issues, as well as the initial design proposal from 18 months ago. I know that 18 months in the software world is almost an eternity but I see this thread as essentially a continuation of that brainstorming, and figured I'd hop in with some ideas. But I kind of jumped into it too quickly last night with my Mustache-like proposal, because it was around 5pm and my laptop battery was almost dead, so that was too rushed. My apologies.

One of the main problems I see with the direction MDX is being taken in these issues is the extreme ambiguity, where new clashes and edge-cases are found often. This leads to two concrete problems:

  1. The language becomes unpredictable and surprising, because as difficult as it is to express the rules of the language to the parser, it's also that difficult to express them to users, and for users to memorize the rules of the language. (This is similar to the extreme flexibility in Ruby, which increases the learning curve time a lot and makes for a lot of headaches for many people.)

  2. The parser becomes more and more difficult to implement, and implementing and trying out specific designs often reveals more and more edge-cases because the syntax isn't very orthogonal. This leads to very slow development time and very long times between releases.

That's why I'm still looking into ways where either the future of MDX, or a fork of MDX, or something similar to MDX, can become something that has a syntax that's extremely predictable, very quick and easy for developers to grok (almost as easy as Markdown itself!), and is so clear that there are (almost) no edge-cases to wait for someone to stumble upon.

Another reason is that I'm really interested in getting this one particular client project to a usable stage since it's been shelved for 12 months, and MDX in its current form is not quite suitable, and it's not exactly clear when these syntax evolutions will be feasible to implement, because as you mentioned, many design quirks are still being worked out. Whereas, for the sake of getting my client project moving forward, I could probably justify spending a week or two of full time work on either MDX or something like MDX, and I wonder if during that time, I would be able to get to something immediately usable, assuming there was a design proposal that simplified and disambiguated the language.

So that's where my design proposal above was coming from. I thought perhaps if the community were open to design/syntax simplifications, we could perhaps get the ball rolling. And since it's not clear where all the discussion has been happening, and all I found was these issues, which didn't mention anything like this one, I figured I would suggest it. The idea was based on the simple rule that "everything outside curly braces is markdown and everything inside of it is interweaved JSX." It could even simplify the syntax further by adding the clause that "if the line starts with < then it doesn't need to be wrapped in curly braces," as another idea. It's not perfect of course, and has its own ambiguities, but it was something to put out there.

That said, even if that specific proposal isn't quite right, I do think it's worth considering some major simplifications, to get MDX back to the extreme simplicity that made Markdown so successful in the first place, while having the power of dynamic JavaScript.

Incidentally, this idea of simplicity came from looking at MDX's About page and finding Idyll, which has less flexibility but far more simplicity and predictability than MDX's proposals. In fact the main thing Idyll is missing is the ability to write raw JavaScript inline in Markdown. MDX allows that only in an "export" line, which kind of feels like a strange hack when the variables are meant to be local only and aren't going to be exported. So this was another reason I started looking into an idea like "everything inside curly braces that starts at the beginning of a line is just plain JavaScript" which would allow import, export, and plain const/let statements too.

Hi @sdegutis, that’s a great write up, thanks for taking the time to express your thoughts so thoroughly.

[...] very quick and easy for developers to grok (almost as easy as Markdown itself!)

What makes you think that Markdown is easy? I’m asking because I spent the last 5 years on Markdown parsers and I conclude that Markdown is messy.
Especially the part where you embed HTML, and maybe even JS in HTML in MD.
It’s one of the things that makes it great as well. And MDX plus this proposal are working on that.

I find Markdown very different from your proposal: Markdown is loose, it’s vague, it’s unpredictable.

that’s a great write up, thanks for taking the time to express your thoughts so thoroughly.

My apologies for writing such a long comment, but I didn't have time to make it shorter. 😄

What makes you think that Markdown is easy? I’m asking because I spent the last 5 years on Markdown parsers and I conclude that Markdown is messy.

@wooorm It's true that Markdown has some complexity (as seen by how long the CommonMark Spec is) in order to address Gruber's original ambiguities. But I can't help but think that if MDX embraces that complexity instead of fighting against it, it's going to multiply exponentially.

Or in other words, as I'm reading through the examples in this issue and the related issues that it links to, they're starting to get so confusing that I couldn't really explain what they should do or not do, why they should work or not work, etc. And to me that seems like a sign that it'll be just as confusing for users of my client's project to work with.

And I get the idea that these issues are meant to focus more on the more confusing and ambiguous edge-cases, rather than the easy and common-sense situations. But the more I try to internalize the language rules that this new evolution of MDX represents, the harder of a time I'm having understanding it, being able to put it into words, and using it to create sample documents.

Here's another evolution idea, inspired by Idyll.

If the MDX community isn't open to discussion about new syntax ideas, or this is the wrong place for that discussion, let me know. I'm posting this here because it's the closest place I can guess for this kind of discussion, based on the issue's title. Besides, interpreted more broadly, "interleaving markdown in JSX" is kind of the heart of MDX.

The idea is based on Idyll's super restrictions of their bracket-style version of JSX, where they only allow extremely restricted code to be present inside JSX expressions. At first I was highly skeptical of such an idea, because I often put arbitrary code inside JSX attributes, such as map literals, array literals, and arrow functions. But then I realized, all of those could be extracted into variables anyway.

So the idea is to limit "raw JavaScript" to one section of the document, and allow only very specific and restricted subsets of JSX expressions within the Markdown area, which would be interpreted with the same basic semantics that CommonMark interprets HTML. And using the same concept as front-matter, all JavaScript could go in the "front-matter area" of a document, and all Markdown at the end. This would also make a clear delineation representing "execution flow" since in this variant proposal, arbitrary executable JS would be allowed in the same document as the Markdown, and not just limited to an export statement like in current MDX.

For example:

// raw JS goes here
import Foo from './Foo';
const qux = 123;
// this is the front-matter delimiter between JS and Markdown:
---
# This is the *Markdown* body

<Foo bar={qux}/>

Restricting JSX syntax to only variables or a few types of literals would make implementation of this as simple as taking an existing Markdown parser and slightly adjusting its HTML parsing, rather than dealing with a full-fledged parser plugin system and ASTs.

Restricting JS to above the fold and MD to below would make it easy to just use two different parsers and not need to surgically combine them or weave them together with plugins.

I just figured out how to use Babel's parser to reliably figure out where a JavaScript expression ends (about 10 lines of code), which means a portion of my suggestion is unnecessary now, the part about restricting what kind of JS(X) can appear inside a JSX element's attribute.

That said, I think the concept of splitting the file into ${prelude}\n\n---\n\n${markup} makes a lot more sense than special-casing lines that start with /^(import|export)\s/. This allows full use of JS, including executing code as soon as the document is loaded, rather than restricting arbitrary JS to be subordinate to an export statement.

@sdegutis ideas around changing the syntax are welcome.
These ideas seem to be getting increasing off topic for Markdown-JSX interleaving.

I'm splitting this out into https://github.com/mdx-js/mdx/issues/732 to continue this discussion.

Would it be fair to say, that you don't think interleaving is needed in this form, and your syntax idea is an alternative?

@ChristianMurphy Honestly my earlier suggestions were not very well thought out, but my last comment from this morning does make sense to split out into another issue. Thanks.

@wooorm Re: your comment about the parentName prop, what's it used for? Is it necessary?

@sdegutis It’s available in mdx-js/mdx as it is, it was in the example above, but it seemed to be mistyped. I don’t know the historical reason for it existing but I’m sure it’s useful and that @johno could expand on that.

Re: your comment about the parentName prop, what's it used for? Is it necessary?

It's a prop that contains the element name of the parent node for all elements originating from Markdown. It's much nicer to have it passed as a prop rather than manipulating React.children directly so it's sort of a convenience/DX feature.

Folks typically use it to change the rendering of components based on their parent context.

Thanks for the explanation. My suggestion on how to deal with it won't help in that case.

Hi, may I ask what the status of this RFC is? I'm using gatsby-theme-docz 2.0.0-rc.35 with @mdx-js/mdx 1.1.0 and gatsby-plugin-mdx 1.0.13. I'm seeing behavior from the parser I do not understand.

For instance,

    <- this line has a space here
<Notice type={"tip"} title={"Side note"}>

does this `really` work?

</Notice>

works as advertised in this RFC. My custom Notice component receives the parsed JSX as it should.

When I remove the space before the <Notice >, or the entire line, then the body of the JSX is parsed as the string work? really does this which makes no sense.

Sorry for the intrusion, but should this work and if so, where do I report parser bugs to?

PS: I think that adding the space was spurious. For the second occurrence of <Notice> in my text, I can't figure out a way to get the parser to provide correct parsed MDX to my component. It's all garbled, which makes creating this text impossible.

PS. To follow up for anyone reading this. This RFC appears to be functional and deployed and working, but apparently this feature is not well-known to others. My issue stemmed from a post-processing tree visitor in remark-docz that mistakenly assumed that JSX nodes need both an opening and closing tag, which is no longer the case when MDX is embedded in JSX. See the referenced issue.

@godmar I think it is not fully functional yet. For example, using the playground, the following will not work: # Test <>{1 + 1}</>!

I'd also be interested in any kind of status / roadmap :)

@jonathanherdt your example seems to be about something else. This thread is about MDX inside JSX, which your example doesn't have. You have JSX inside MDX.

As for why your example doesn't parse - I believe it's because the JSX fragment has to start on a new line, but I'm not sure.

@godmar The first example in this thread explicitly mentions JSX inside MDX: # Hello, <span>*world*</span>, from <>{props.name}</>! My understanding is that both scenarios are covered here.

@jonathanherdt you're right about that. Upon rereading, the entire thread reads confusing. Even more so that issue #732 was split off and then closed.

To me, it seems to cut to the core of why anybody would use MDX if the interaction of JSX and MDX is not clearly defined. The references to the common mark standard address the case of MDX inside JSX.

The case of having MDX inside inline content - isn't this already addressed by the Common Mark specification? For instance,# is an ATX heading which is followed by inline content, which can include "raw HTML" and presumably JSX entities would count as that?

Given that arbitrary JS code can appear between fragment-wrapped curly braces like so:

# Hello, <span>*world*</span>, from <>{props.name}</>!

should this MDX code also be allowed?

# Hello <>{(() => (

## *world*

))()}</>!

Hi, I was hoping to find a starting point on where this issue stands in terms of technical implementation and outstanding problems. I consider MDX a very useful tool in a content authoring toolchain I'm writing, and even just being able to do away with the no-empty-lines-ever issue would be fantastic. I'd love to offer any support or PRs I can towards this purpose. Thanks!

Should jsx commments in "inline" jsx be considered?

https://github.com/mdx-js/eslint-mdx/issues/18#issuecomment-581137403

image

It's quite counterintuitive.

Hi, may I ask what the status of this RFC is? I'm using gatsby-theme-docz 2.0.0-rc.35 with @mdx-js/mdx 1.1.0 and gatsby-plugin-mdx 1.0.13. I'm seeing behavior from the parser I do not understand.

For instance,

    <- this line has a space here
<Notice type={"tip"} title={"Side note"}>

does this `really` work?

</Notice>

works as advertised in this RFC. My custom Notice component receives the parsed JSX as it should.

When I remove the space before the <Notice >, or the entire line, then the body of the JSX is parsed as the string work? really does this which makes no sense.

Sorry for the intrusion, but should this work and if so, where do I report parser bugs to?

_PS_: I think that adding the space was spurious. For the second occurrence of <Notice> in my text, I can't figure out a way to get the parser to provide correct parsed MDX to my component. It's all garbled, which makes creating this text impossible.

I am also using Docz and stumble upon exactly the same use case you're describing.

What approach did you end up taking?

For future googlers who find this, it seems the newlines are important

This does not work for me

<Note>
This *is* **markdown**!
</Note>

While this does

<Note>

This *is* **markdown**!

</Note>

I have made a prettier plugin that may help with this issue:

https://github.com/ncuillery/prettier-plugin-mdx-no-text-child

This discussion is quite long, could you sum up what if someone _intended_ to leave the first line as plain text?

@silvenon I've summarized what I have in mind here.

Heads up everyone: we’re working on rewriting the parser to solve amongst other things, this problem, in 2.0.0. Out relatively soon!

Hey, I'd like to use details/summary tags in a MDX file.

<details>

<summary>My `markdown` **title**</summary>

Some details

</details>

image

I tried things like that, line breaks help but this have unwanted side-effects as well.

<details>

<summary>

My `markdown` **title**

</summary>

Some details

</details>

image

Until we have a proper interleaving solution, do you know any workaround to solve this with markup-only?

I'm thinking about overriding <code> with a MDXProvider at the summary level.

@slorber I don’t think this has to do with MDX, but with with the underlying flavor of Markdown, CommonMark. And I don’t think you can work around this by overriding <code> as you suggested, because the MDXProvider doesn’t parse Markdown strings, it only defines the meaning of tags in Markdown that has already been parsed.

are there plans to support this / are there any workarounds available?

edit — i see its in the plan for v2

Is the <MDX> component mentioned above actually implemented? I'm using MDX v2, and it doesn't seem to be available. I also tried the markdown="1" and mdx={true} variants that were mentioned.

I'm trying to render MDX in a component attribute. Like this:

<MyComponent value={<>This *is* **markdown**</>} />

I also tried doing it by assigning the nested MDX to a variable:

export const mdx = <>This *is* **markdown**</>;

<MyComponent value={mdx} />

But neither of the above works. Any suggestions?

What do you want? As in, can you take a step back, and explain more of your situation?

I have a component that accepts a JSX component as a prop. For example, the following does work fine:

<MyComponent value={<>This <em>is</em> <strong>markdown</strong></>}/>

When I use this component in an MDX page, I'd like to be able to use MDX syntax to populate the prop. Ideally, one of these two syntaxes would work:

<MyComponent value={<>
  This *is* **markdown**
</>}/>
<MyComponent value={`
  This *is* **markdown**
`}/>

But it would also be acceptable to do it via some MDX-specific component, such as <MDX>:

<MyComponent value={<MDX>
  This *is* **markdown**
</MDX>}/>

Thanks for the clarification! mdx@next does not allow further MDX inside property values. Once you’re in JSX, you’re in JSX. Except in the case of content—so, between tags. Can you work around this by either doing the following?

<MyComponent>This *is* **markdown**</MyComponent>

Or:

<MyComponent value={<>This <em>is</em> <strong>JSX</strong></>}></MyComponent>

Thanks for the fast reply @wooorm. The first example you showed would work for a _single_ JSX slot, but my component actually allows an arbitrary number of slots:

<ProductCatalog products={[
    {
        productName: "Product A",
        description: <div>This *is* **markdown**</div>
    },
    {
        productName: "Product B",
        description: <div>This *is* **markdown**</div>
    },
    {
        productName: "Product C",
        description: <div>This *is* **markdown**</div>
    },
]}/>

The only workaround I can think of that still allows for Markdown content is to make each slot a child component:

<ProductCatalog>
  <Product name="Product A">
    <ProductDescription>
      <div>This *is* **markdown**</div>
    </ProductDescription>
  </Product>

  <Product name="Product B">
    <ProductDescription>
      <div>This *is* **markdown**</div>
    </ProductDescription>
  </Product>

  <Product name="Product C">
    <ProductDescription>
      <div>This *is* **markdown**</div>
    </ProductDescription>
  </Product>
]}/>

This works, and supports Markdown content (in MDX v2). 👍 It's just tedious and feels a lot more like writing XML than Markdown 😟

Great to hear that that works! Is this good enough for you? Or do you feel very strongly that more markdown should also be available in props?

I think that that would be technically very hard. Although, maybe the MDX component you showed before could be implemented in userland, if that also works?

I would expect _any_ JSX component in an MDX file to support Markdown content, regardless of where the component occurs. Examples include:

export const MyComponent = <div>This *is* **markdown**</div>

export const ArrayOfComponents = [
    <div>This *is* **markdown**</div>,
    <div>This *is* **markdown**</div>,
    <div>This *is* **markdown**</div>
];

<SomeComponent someProp={<div>This *is* **markdown**</div>} />

<ProductCatalog products={[
    {
        productName: "Product A",
        description: <div>This *is* **markdown**</div>
    },
    {
        productName: "Product B",
        description: <div>This *is* **markdown**</div>
    },
    {
        productName: "Product C",
        description: <div>This *is* **markdown**</div>
    },
]}/>

Let me emphasize that while I think it would be totally awesome to support all of the above examples, I realize this means you'd basically have to write a JavaScript parser. 😰 So, no, I don't feel strongly that this is a must-have feature. MDX is already friggin' awesome, crazy powerful, and incredibly useful.

Your last observation is indeed correct, to rephrase: we parse markdown and recognise the JSX inside it. Your expectation is the inverse: parse JavaScript and recognise markdown inside it. It sounds interesting, but to me it doesn’t align well with this project, or at least my ideas of how content should work, maybe others will have different opinions though!

And thanks, glad to hear MDX is generally working well for you! Also: do let us know more about your experience w/ mdx@next!

Hi y’all! I’m going to close this as it landed on the main, the (now default) branch we’re using to gear up to the MDX@2 release.

The reason is so that it’s more clear which issues still need to be solved already and don’t require further work.

Expect another next release soonish, which might include it, or maybe it’s already released as a beta!

For more info, see https://github.com/mdx-js/mdx/issues/1041.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

johno picture johno  ·  4Comments

MatthewCaseres picture MatthewCaseres  ·  4Comments

EddyVinck picture EddyVinck  ·  3Comments

francisfuzz picture francisfuzz  ·  4Comments

waterfoul picture waterfoul  ·  3Comments