Mdx: Less-than or greater-than sign in text

Created on 1 May 2018  路  7Comments  路  Source: mdx-js/mdx

It appears that you can't currently use < or > characters in text.

For example, this markdown:

# Hello, MDX

I <3 Markdown and JSX

Produces this JSX:

export default ({components}) => <MDXTag name="wrapper"><MDXTag name="h1" components={components}>Hello, MDX</MDXTag>
<MDXTag name="p" components={components}> I <3 Markdown and JSX</MDXTag></MDXTag>

Which fails to compile in babel.

MDXC compiles this the following way:

export default function({ factories={} }) {
  const {
    h1 = createFactory('h1'),
    p = createFactory('p'),
    wrapper = createFactory('div'),
  } = factories

  return wrapper({},
    h1({"id": "Hello-MDX"},
      "Hello, MDX",
    ),
    p({},
      "I <3 Markdown and JSX",
    )
  )
}
馃悰 typbug

Most helpful comment

I'm going to fix this once and for all in a bit 馃憤 We just need to turn text nodes into

{`CONTENT`}

And then escape backticks. Exactly the same as code/inlineCode works right now.

All 7 comments

Sounds like we have to escape them 馃槃

cc @johno

Added a failing test

Thanks for opening this issue!

Just opened a PR with an escaping fix. I wonder if going the factory route will be more resilient to these types of bugs? Though, JSX syntax only has a handful of gotchas so there prolly aren't too many escaping bugs that we need to flush out.

Thanks for fixing it!

I do think that factories are more resilient and have other advantages (e.g. smaller produced code size). Here's another one I just found where the produced code can't be compiled by babel:

# Hello, MDX

:-}

Produces:

export default ({components}) => <MDXTag name="wrapper"><MDXTag name="h1" components={components}>Hello, MDX</MDXTag>
<MDXTag name="p" components={components}> :-}</MDXTag></MDXTag>

Regarding curly braces, I feel like they should be automatically escaped when they're not inside a JSX block, so that {Hello} compiles to "{Hello}", but <span>{Hello}</span> compiles to React.createElement('span', null, Hello). My thinking here is that MDX may be used in publishing systems where the authors don't actually know JavaScript, and who will be confused when curly braces cause their document to crash their blogging/publishing tool.

I'm going to fix this once and for all in a bit 馃憤 We just need to turn text nodes into

{`CONTENT`}

And then escape backticks. Exactly the same as code/inlineCode works right now.

@jamesknelson so how mdx works:

Input:

import Foo from './foo'

# Hello world

<Foo />

  1. We transform MDX to MDXAST
  2. We apply remark plugins
  3. We transform MDXAST to MDXHAST
  4. We apply hast plugins
  5. We transform MDXHAST into a javascript file by traversing all nodes recursively

The output is a javascript file like:

import Foo from './foo'

export default ({components}) => {
  return <MDXTag name="root" components={components}>
    <MDXTag name="h1" components={components} parentName="root">Hello world</MDXTag>
    <Foo />
  </MDXTag>
}

So in short we turn HTML nodes into JSX nodes, JSX nodes are not touched, but instead just pasted into the output without any transformations, same for import and export, the only difference with import/export is that they're applied outside of the function scope (import/export) doesn't work otherwise. The "bug" here is that we need to treat all text nodes the same way, instead of having an exception for code/inlinecode.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pedronauck picture pedronauck  路  18Comments

kylegach picture kylegach  路  22Comments

ChristianMurphy picture ChristianMurphy  路  13Comments

Nkzn picture Nkzn  路  13Comments

AlmeroSteyn picture AlmeroSteyn  路  32Comments