.mdx proposal
February 9, 2018 at 5:43pm.mdx proposal
February 9, 2018 at 5:43pmFor a while now at ZEIT we've been using
markdown-in-js
as a pre-processor with Babel, so that we can write static documents more practically.In practice, our pages end up looking something like this:
import * as components from './components/text'import Video from ./components/video'export markdown(components)`# hello there\`\`\`My code snippet ${<Image />}\`\`\``
In addition to letting us quickly write markdown, it has some really powerful benefits:
- It's still JS, which means we can do imports, define helpers, assert that it's valid via a linter, etc.
- We can embed JSX components inside Markdown. This is a must for us, because we like writing blog posts (https://zeit.co/blog) that have diverse content inside.
However, in my opinion, a lot of the benefits of "writing markdown" are lost. For example, as you see above, escaping code blocks becomes cumbersome.
As a result, I've been playing with an idea in my mind for a potential custom webpack loader and a new format called
mdx
, which brings the "best of both worlds" of JSX and Markdown.Imagine
my-blog-post.mdx
:import Video from '../components/video'# My blog post```my code!```And here's a video:<Video width={300} src="video.mp4" />
This looks great IMO, however, some important problems remain:
- How do we lint? It should be impossible to include
<Vid>
because it's not imported, but<Video>
should work. Can we extendeslint
to understand.mdx
? - How do we defined the default set of components? One option would be to pass them to the webpack loader configuration
- How do we override one component? Let's say we want to use a custom paragraph renderer. An idea here would be to standarize on a series of names, so that you can just do
import P from '../components/paragraph'
- How do we prettify it? Another issue we have with our markdown pages is that the markdown inside ends up looking really ugly, unless you painstakingly format it by hand. Can we extend prettier to understand
.mdx
?
If someone in the community wants to start playing around with a prototype, please share!
February 9, 2018 at 8:56pm
I prefer the original proposal. It's tempting to want to use fenced code blocks, but they add viewing and editing overhead beyond what markdown already has, with its inline HTML support. I think the popularity of next and styled-components despite needing editor plugins (also jsx in the early days) shows that iterating on the language is feasible. My only suggestion is adding a jsx tag for import so it's `<import Video="../components/video" />` or something.
Wow, https://github.com/jamesknelson/mdxc is quite similar to this proposal! Even the import syntax is the same.
February 10, 2018 at 12:16pm
February 12, 2018 at 9:11pm
Spent some time this weekend messing around with this mdx proposal and implementing it in c8r/markdown. So it's really a reimplementation of mdxc (project is so awesome) using remark.
This got me thinking that to really solve this problem and add support for linters, syntax highlighters, and code formatters like prettier we likely need a full-fledged abstract syntax tree. Also, parsing gets quite tricky with complex JSX containing maps, template strings and other JavaScript features. To me only partial JSX support, when inlined into markdown files would be confusing. Thus a full blown parser and AST could be quite useful.
I whipped up a quick MDXAST definition based on MDAST and HAST (copy pasta with a couple new node types): https://github.com/c8r/markdown/blob/master/MDXAST_SPECIFICATION.md
And tried to formally define .mdx since it kinda goes along with the notion of MDXAST:
Definitely interested about whether you fine folks have any other thoughts on this <3.
February 13, 2018 at 9:32am
February 14, 2018 at 2:49am
September 28, 2018 at 10:05am
September 28, 2018 at 7:31pm
June 24, 2019 at 2:24pm
I have a feeling this is not the best place for this question.. 🤔