MDX presents a new paradigm for people currently using remark (or other markdown rendering approaches). When using remark the most common option to get shortcodes, or other novel behavior, inside a markdown file is to do AST manipulation via remark plugins. This has led to an ecosystem of plugins that assume you're using remark and thus directly insert html blobs into the remark AST. This is an example of plugins assuming that they're going to be run in a specific environment with a specific use case.... but this post isn't really about assumptions people made before there was a different option, not panning out for that new option. That's a fact of life in engineering; Your assumptions today probably won't hold up to the future.
This post is about composition, it's about components, and it's about React.
Powerful tools that manipulate ASTs often require vast knowledge to apply consistently to generic situations. While this knowledge is both achievable and within reach of many people, we don't always have the time to upskill into a new skill set. The more we provide for the time-strapped "can I get this done in the next 30min before I leave work" engineer, the more people it will be accessible to generally.
Like I said earlier in this post: MDX allows us to change the way we render markdown and also the way we modify the content of markdown itself. Using the component model that has established itself over the last few years means we can enable more people to build more powerful interfaces while keeping the overhead for content editors to a minimum.
Markdown typically renders to HTML. A small markdown document such as:
With MDX, we can replace each of these elements with a React component:
This by itself isn't super powerful yet. We may attach some
styles to the heading, paragraph and other elements. What
is powerful is the way we can take control of the element
in npm packages like
which handle syntax highlighting and creating a code
playground that works inside your browser respectively. We
can pass the code string to these npm packages and get
interesting functionality almost for free.
We can also start replacing AST manipulation with React components. gatsby-remark-autolink-headers adds a generated id field to all of our headings... and we can do that in a React component.
This gives us more control over how the ids are generated
slugify takes options like
lower to lowercase
replace to replace spaces with a specific
character. You could even use your own or a different npm
package that offers this functionality as a function that
can be composed with other functions to build in interesting
functionality to your components.
hooks can be used to maintain interesting state. Here's on that simply tracks hover state.
We can expand this to even more interesting applications like rendering a markdown code block as a language-specific playgound that calls out to an API to run code and displays the result. Each language can be lazy-loaded on-demand for client-side rendering and rendered however we want on the server. go, Pony, and Babel have playgrounds/repls that could be used liked this.
So replacing components can get pretty awesome, but we still
have the problem of introducing novel new functionality to
the content of our markdown. Typically this is done via
custom shortcode syntax
that abuse the inline code syntax or introduce new meaning
to existing syntax like
. Instead of introducing custom
syntax for shortcodes, we can rely on an established,
common, syntax: JSX.
JSX is powerful enough to do everything we need from out shortcodes: basic declarations, attributes, and children. It even has additional super powers. In the near future, we could extend features like Gatsby's StaticQuery to be automatically handled through React Components and Babel manipulation. We could literally write:
and render a list of related posts to the current blog post that get fetched through Gatsby's GraphQL data layer at build time. The possibilities of replacing custom shortcode implementations with React components is interesting and useful.
In this post I've tried to convince you that remark and the AST manipulation it requires is a worse fit for the problems we are trying to solve than MDX and React components. That's not to say AST manipulation doesn't have it's uses, but they should be relegated to advanced integration use cases like optimizing the images referenced in your markdown at build time and shipping blur-up features for each of them. The future is components and that will require a mind shift from the world of remark and other markdown processing tools.