question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

RFC: Interleaving Markdown in JSX

See original GitHub issue

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


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

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:67
  • Comments:53 (23 by maintainers)

github_iconTop GitHub Comments

29reactions
wooormcommented, Apr 23, 2020

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

7reactions
skylarmbcommented, Feb 11, 2020

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>
Read more comments on GitHub >

github_iconTop Results From Across the Web

What is MDX?
It shows how markdown, JSX, JavaScript expressions, and import and export statements in ESM can be used inside MDX.
Read more >
Media Types - Internet Assigned Numbers Authority
Per Section 3.1 of [RFC6838], Standards Tree requests made through IETF documents will be reviewed and approved by the IESG, while requests made ......
Read more >
This Week In React #92: Remix, MDX 2, Lifetime Analysis ...
Official launch for MDX 2.0. This technology permits to interleave Markdown and JSX quite easily, very convenient to create interactive content ...
Read more >
react-markdown - npm
This package is a React component that can be given a string of markdown that it'll safely render to React elements. You can...
Read more >
draft-ietf-httpbis-semantics-13 - HTTP Semantics - IETF Datatracker
Editorial Note This note is to be removed before publishing as an RFC. ... However, multiple trailer sections interleaved with payload data have...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found