MDXMDX updateshttps://mdxjs.com/Fri, 07 Mar 2025 11:21:23 GMT2025-03-07T11:21:23.104Zenen© 2025 MDX contributors© 2025 MDX contributorsmdxmarkdownjsxossreactMDX 3Titus Wormerhttps://mdxjs.com/blog/v3/https://mdxjs.com/blog/v3/Tue, 24 Oct 2023 00:00:00 GMT2023-10-24T00:00:00.000Z2025-01-27T00:00:00.000Z<div><div><p><strong>Note</strong>: Info on how to migrate is available in our <a href="/migrating/v3/">Version 3 migration guide</a>.</p></div><h2 id="mdx-3"><a href="#mdx-3" class="" aria-label="Link to this section"></a>MDX 3</h2><p>Version 3 already! This major version contains a couple small changes. For most folks, updating Node.js and plugins is all that’s needed!</p><h3 id="contents"><a href="#contents" class="" aria-label="Link to this section"></a>Contents</h3><ul><li><a href="#breaking-changes">Breaking changes</a></li><li><a href="#improvements-to-the-mdx-format">Improvements to the MDX format</a><ul><li><a href="#adjacent-block-jsx-and-expressions-in-mdx">Adjacent block JSX and expressions in MDX</a></li><li><a href="#await-in-mdx">Await in MDX</a></li><li><a href="#es2024-in-mdx">ES2024 in MDX</a></li></ul></li><li><a href="#miscellaneous">Miscellaneous</a></li><li><a href="#thanks">Thanks</a></li></ul><h3 id="breaking-changes"><a href="#breaking-changes" class="" aria-label="Link to this section"></a>Breaking changes</h3><p>The main breaking change is that Node.js 16 is now the minimum supported version.</p><p>Across the ecosystem there were several small internal breaking changes. Everything’s released already. You can update all plugins now. If you ran into problems before, it should work now.</p><p>We also removed some infrequently used deprecated APIs. You’re likely fine but gloss over the <a href="/migrating/v3/">v3 migration guide</a> if you get errors.</p><p>Important to note when you use your lesser-known but powerful <code>evaluate</code>, <code>run</code>, or <code>outputFormat: 'function-body'</code> APIs, please pass the <code>baseUrl</code> option. That makes sure <code>import.meta.url</code>, <code>import</code>, and <code>export</code> work. You’ll get a runtime error when those features are used otherwise.</p><h3 id="improvements-to-the-mdx-format"><a href="#improvements-to-the-mdx-format" class="" aria-label="Link to this section"></a>Improvements to the MDX format</h3><p>There’s also a few small improvements to the MDX format, some of which technically breaking.</p><h4 id="adjacent-block-jsx-and-expressions-in-mdx"><a href="#adjacent-block-jsx-and-expressions-in-mdx" class="" aria-label="Link to this section"></a>Adjacent block JSX and expressions in MDX</h4><p>We now accept block expressions right next to block JSX tags:</p><pre><code class="language-mdx">&#x3C;<span>style</span>><span>{<span>`</span></span> h1 <span>{</span> <span>color</span>: <span>blue</span>; } `}&#x3C;/<span>style</span>> </code></pre><p>Previously, there was a syntax error, and you had to add a newline between the angle brackets and the braces.</p><h4 id="await-in-mdx"><a href="#await-in-mdx" class="" aria-label="Link to this section"></a>Await in MDX</h4><p>We now accept <code>await</code> syntax:</p><div><div><span>MDX</span></div><pre><code class="language-mdx"><span>{</span><span>await</span> <span>Promise</span>.<span>resolve</span>(<span>42</span>)<span>}</span> </code></pre></div><p>Most frameworks don’t support promises. Whether this works depends on that.</p><p>Previously, there was a runtime error that <code>await</code> was used in a context where it wasn’t allowed.</p><h4 id="es2024-in-mdx"><a href="#es2024-in-mdx" class="" aria-label="Link to this section"></a>ES2024 in MDX</h4><p>You can now use modern JavaScript syntax in MDX. Acorn, used internally, is now instructed to use ES2024.</p><h3 id="miscellaneous"><a href="#miscellaneous" class="" aria-label="Link to this section"></a>Miscellaneous</h3><p>I refactored all the docs. Updating every use example where needed. I also wrote a guide on how to inject components from anywhere: <a href="/guides/injecting-components/">§ Injecting components</a>.</p><p>The site is a lot faster. There’s a nice improved playground too: <a href="/playground/">try it out! »</a>. We also have proper syntax highlighting here, thanks to <a href="//github.com/wooorm/markdown-tm-language"><code>wooorm/markdown-tm-language</code></a> and <a href="//github.com/wooorm/starry-night"><code>wooorm/starry-night</code></a>.</p><p>The generated JS code is a little cleaner (the JSX pragma comment is removed and objects are sorted where needed), it also uses spreads instead of <code>Object.assign</code>, there’s a <code>'use strict'</code> added when needed, and the <code>MDXContent</code> is exported immediately.</p><h3 id="thanks"><a href="#thanks" class="" aria-label="Link to this section"></a>Thanks</h3><p>We’d like to say thanks to all our contributors and our happy users. Special thanks to 北雁云依 (<a href="//github.com/BeiyanYunyi"><strong>@BeiyanYunyi</strong></a>), Christian Murphy (<a href="//github.com/ChristianMurphy"><strong>@ChristianMurphy</strong></a>), JokcyLou (<a href="//github.com/Jokcy"><strong>@Jokcy</strong></a>), Maël Nison (<a href="//github.com/arcanis"><strong>@arcanis</strong></a>), Andreas Deininger (<a href="//github.com/deining"><strong>@deining</strong></a>), Remco Haszing (<a href="//github.com/remcohaszing"><strong>@remcohaszing</strong></a>), Sébastien Lorber (<a href="//github.com/slorber"><strong>@slorber</strong></a>), Víctor Fernández (<a href="//github.com/victor23k"><strong>@victor23k</strong></a>), Titus Wormer (<a href="//github.com/wooorm"><strong>@wooorm</strong></a>), and anyone we may have forgotten.</p></div>MDX 2Titus Wormerhttps://mdxjs.com/blog/v2/https://mdxjs.com/blog/v2/Tue, 01 Feb 2022 00:00:00 GMT2022-02-01T00:00:00.000Z2025-01-27T00:00:00.000Z<div><div><p><strong>Note</strong>: This is an old blog post. The below is kept as is for historical purposes.</p></div><div><p><strong>Note</strong>: Info on how to migrate is available in our <a href="/migrating/v2/">Version 2 migration guide</a>.</p></div><h2 id="mdx-2"><a href="#mdx-2" class="" aria-label="Link to this section"></a>MDX 2</h2><p>Version 2 of MDX was released after years of hard work, and has many improvements. Here are the highlights:</p><div><ul><li>📝 <strong>Improved syntax</strong> makes it easier to use markdown in JSX</li><li>🧑‍💻 <strong>JavaScript expressions</strong> turn <code>{2 * Math.PI}</code> into 6.283185307179586</li><li>🔌 New <strong>esbuild</strong>, <strong>Rollup</strong>, and <strong>Node.js</strong> integrations</li><li>⚛️ <strong>Any JSX runtime</strong>: React, Preact, Vue, Emotion, you name it, they’re all supported</li><li>🌳 <strong>Improved AST</strong> exposes more info in greater detail</li><li>🏃‍♀️ Compiles at least <strong>25% faster</strong></li><li>🚴 Generated code runs twice as fast (<strong>100% faster</strong>)</li><li>🚄 Bundle size of <code>@mdx-js/mdx</code> is more than three times as small (<strong>250% smaller</strong>)</li><li>🧵 …and much, so much more</li></ul></div><p>It’s been 4 years since this project was announced. 2½ since we released our stable version 1. <strong>We’re proud to finally release v2!</strong> Let’s dive in!</p><h3 id="contents"><a href="#contents" class="" aria-label="Link to this section"></a>Contents</h3><ul><li><a href="#improvements-to-the-mdx-format">Improvements to the MDX format</a></li><li><a href="#rollup-esbuild-and-other-integrations">Rollup, esbuild, and other integrations</a></li><li><a href="#architectural-improvements">Architectural improvements</a></li><li><a href="#typescript">TypeScript</a></li><li><a href="#docs--site">Docs &#x26; site</a></li><li><a href="#breaking-changes">Breaking changes</a></li><li><a href="#thanks">Thanks</a></li></ul><h3 id="improvements-to-the-mdx-format"><a href="#improvements-to-the-mdx-format" class="" aria-label="Link to this section"></a>Improvements to the MDX format</h3><p>We’ve spent a lot of time thinking and trying out different ways to improve the format. Originally, the format was very close to how markdown, and HTML in markdown, works. We found that the old behavior often yielded unexpected results. In version 2, we shift the format a little bit closer to how JS(X) works.</p><p>Take for example this MDX file:</p><pre><code class="language-mdx">&#x3C;<span>div</span>><span>*</span>hi<span>*</span>?&#x3C;/<span>div</span>> &#x3C;<span>div</span>> <span> # <span>hi?</span></span> &#x3C;/<span>div</span>> &#x3C;<span>main</span>> &#x3C;<span>div</span>> <span> # <span>hi?</span></span> &#x3C;/<span>div</span>> &#x3C;/<span>main</span>> </code></pre><div><div><p>In version 1, that was equivalent to the following JSX:</p><pre><code class="">&#x3C;> &#x3C;<span>div</span>>*hi*?&#x3C;/<span>div</span>> &#x3C;<span>div</span>> # hi? &#x3C;/<span>div</span>> &#x3C;<span>main</span>> &#x3C;<span>div</span>> &#x3C;<span>pre</span>>&#x3C;<span>code</span>># hi?&#x3C;/<span>code</span>>&#x3C;/<span>pre</span>> &#x3C;/<span>div</span>> &#x3C;/<span>main</span>> &#x3C;/> </code></pre></div><div><p>In version 2, it’s equivalent to the following JSX:</p><pre><code class="">&#x3C;> &#x3C;<span>div</span>>&#x3C;<span>em</span>>hi&#x3C;/<span>em</span>>?&#x3C;/<span>div</span>> &#x3C;<span>div</span>> &#x3C;<span>h1</span>>hi?&#x3C;/<span>h1</span>> &#x3C;/<span>div</span>> &#x3C;<span>main</span>> &#x3C;<span>div</span>> &#x3C;<span>h1</span>>hi?&#x3C;/<span>h1</span>> &#x3C;/<span>div</span>> &#x3C;/<span>main</span>> &#x3C;/> </code></pre></div></div><p>We believe it’s more intuitive that markdown “inlines” such as emphasis can form between tags on the same line (first <code>&#x3C;div></code>), “blocks” such as headings can form if they’re on their own line (second <code>&#x3C;div></code>), and indentation is allowed rather than forming code (third <code>&#x3C;div></code>).</p><p>We also added support for JavaScript expressions, take for example:</p><div><div><div><div><span>expressions.mdx</span></div><pre><code class="language-mdx"><span>export</span> <span>const</span> <span>authors</span> <span>=</span> [ {name: <span><span>'</span>Jane<span>'</span></span>, email: <span><span>'</span>[email protected]<span>'</span></span>}, {name: <span><span>'</span>John<span>'</span></span>, github: <span><span>'</span>@johno<span>'</span></span>} ] <span>export</span> <span>const</span> <span>published</span> <span>=</span> <span>new</span> <span>Date</span>(<span><span>'</span>2022-02-01<span>'</span></span>) Written by: <span>{</span><span>new</span> <span>Intl</span>.<span>ListFormat</span>(<span><span>'</span>en<span>'</span></span>).<span>format</span>(<span>authors</span>.<span>map</span>(<span>d</span> <span>=></span> <span>d</span>.<span>name</span>))<span>}</span>. Published on: <span>{</span><span>new</span> <span>Intl</span>.<span>DateTimeFormat</span>(<span><span>'</span>en<span>'</span></span>, {dateStyle: <span><span>'</span>long<span>'</span></span>}).<span>format</span>(<span>published</span>)<span>}</span>. </code></pre></div></div><div><div><div><span>equivalent.jsx</span></div><pre><code class="">&#x3C;> &#x3C;<span>p</span>>Written by: Jane and John.&#x3C;/<span>p</span>> &#x3C;<span>p</span>>Published on: February 1, 2022.&#x3C;/<span>p</span>> &#x3C;/> </code></pre></div></div></div><p>As the format moves a little further from markdown towards JSX, we’ve added support for loading “normal” markdown without our syntax extensions. If you’re using our bundler integration <code>@mdx-js/loader</code> (or <code>@mdx-js/rollup</code>, <code>@mdx-js/esbuild</code>, or <code>@mdx-js/node-loader</code>, see next section), then that’ll just work: import <code>readme.mdx</code> and it’s seen as the MDX format, import <code>readme.md</code> and it’s seen as markdown, based on their extensions.</p><p>The MDX format is described in <a href="/docs/what-is-mdx/">§ What is MDX?</a></p><h3 id="rollup-esbuild-and-other-integrations"><a href="#rollup-esbuild-and-other-integrations" class="" aria-label="Link to this section"></a>Rollup, esbuild, and other integrations</h3><p>When we started out, Babel, webpack, and React were ubiquitous in the JavaScript ecosystem and we built MDX on them. For version 2, we worked hard to make them optional. They’re no longer required and MDX can more easily be used with other tools.</p><p>On the bundler side, we’ve added new integrations: <code>@mdx-js/esbuild</code> for esbuild (an extremely fast bundler) and <code>@mdx-js/rollup</code> for Rollup (a bundler that’s also used in Vite and WMR). You can even import MDX files directly in Node.js with our new <code>@mdx-js/node-loader</code>.</p><p>On the runtime side, we can now compile JSX away to normal JavaScript and no longer need framework-specific code to glue them together with MDX. Now any JSX runtime, whether <a href="//reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html">classic or automatic</a>, is supported. This means MDX can be used with React, Preact, Vue, Emotion, Theme UI, Ink, you name it, plus anything that’s yet to be invented!</p><p>See <a href="/docs/getting-started/">§ Getting started</a> for a quick start but also in-depth info on how to integrate MDX with many different tools.</p><h3 id="architectural-improvements"><a href="#architectural-improvements" class="" aria-label="Link to this section"></a>Architectural improvements</h3><p>To make the syntax of the MDX format better and to allow new integrations and arbitrary JSX runtimes, we’ve rewritten almost everything. Part of that effort was <a href="//github.com/micromark/micromark">micromark</a>, which is another story, but it means we’re fully CommonMark (and optionally GFM) compliant, while also understanding more about MDX files.</p><p>Now we can throw an early error when there’s a typo and point to exactly where it happened, instead of a later bundler like webpack complaining about an error in an intermediate, unrecognizable, and broken string of JavaScript. It also means that we have a new AST which describes the MDX syntax in more detail — we even expose the embedded JavaScript. This detailed AST allows plugins to enhance MDX in powerful new ways. It also helped solve edge cases where MDX would previously crash. And it let us drop Babel.</p><p>This new architecture results in <strong>25% faster</strong> compilation, generated code that runs twice as fast (<strong>100% faster</strong>), and that the bundle size of <code>@mdx-js/mdx</code> is more than three times as small (<strong>250% smaller</strong>).</p><p>See <a href="/packages/mdx/#architecture">¶ Architecture in <code>@mdx-js/mdx</code></a> for more on how our compiler works. See <a href="/docs/extending-mdx/">§ Extending MDX</a> for several plugins that use the new tree to enhance MDX, how to use them and other plugins, and how to create plugins.</p><h3 id="typescript"><a href="#typescript" class="" aria-label="Link to this section"></a>TypeScript</h3><p>All <a href="/packages/"><code>@mdx-js/*</code> packages</a> are now fully typed with <a href="//www.typescriptlang.org">TypeScript</a> through JSDoc comments. That means our APIs are exposed as TypeScript types but also that our projects are type safe internally.</p><p>We’ve published <a href="//github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/mdx"><code>@types/mdx</code></a>, a types-only package that can be used with any (community) integration. You can use it, if you’re importing MDX files, to type those imported components.</p><p>See <a href="/docs/getting-started/#types">¶ TypeScript in § Getting started</a> for more on how to use configure TypeScript.</p><h3 id="docs--site"><a href="#docs--site" class="" aria-label="Link to this section"></a>Docs &#x26; site</h3><p>MDX is used and liked a lot. Before version 1 we had amassed a total of <strong>2.5m downloads</strong>. Now we hit that number every week. Our core compiler <code>@mdx-js/mdx</code> is used in <strong>61k projects</strong>. Our GitHub repo has <strong>11.6k stars</strong>.</p><p>Many people help, often with docs. 85 contributors committed to our repo since version 1. We’re grateful for these contributions and all those individual insights, but over the years it did result in some inconsistencies and duplicated content.</p><p>For version 2, we rewrote our docs from beginning to end to tell a consistent story for new users, folks that do complex AST and compiler stuff, and anyone in between.</p><p>We also made a new website. It’s built on MDX of course, <a href="//unifiedjs.com">unified</a> itself, and <a href="//reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html">React Server Components (RSC)</a>. While we dogfood the former two as they’re projects we maintain, and the latter is extremely experimental, we think compiling things ahead of time and betting on hybrid models, compared to completely server-side sites or completely client-side apps, is the smart choice for us and the web’s future.</p><p>Our new site is heavily optimized and fast, gorgeous (subjective but hey), has rich metadata, and scores very well in performance and accessibility review tools such as Lighthouse and axe.</p><p>See <a href="/community/contribute/">§ Contribute</a> for more on how to help.</p><h3 id="breaking-changes"><a href="#breaking-changes" class="" aria-label="Link to this section"></a>Breaking changes</h3><p>When you’re ready to migrate, please see the <a href="/migrating/v2/">Version 2 migration guide</a>.</p><h3 id="thanks"><a href="#thanks" class="" aria-label="Link to this section"></a>Thanks</h3><p>We’d like to say thanks to all our contributors and our happy users. Special thanks to John Otander (<a href="//github.com/johno"><strong>@johno</strong></a>), Christian Murphy (<a href="//github.com/ChristianMurphy"><strong>@ChristianMurphy</strong></a>), JounQin (<a href="//github.com/JounQin"><strong>@JounQin</strong></a>), Jack Bates (<a href="//github.com/jablko"><strong>@jablko</strong></a>), Sam Chen (<a href="//github.com/chenxsan"><strong>@chenxsan</strong></a>), Sam Robbins (<a href="//github.com/samrobbins85"><strong>@samrobbins85</strong></a>), Remco Haszing (<a href="//github.com/remcohaszing"><strong>@remcohaszing</strong></a>), LB (<a href="//github.com/laurieontech"><strong>@laurieontech</strong></a>), Gabriel Kirkley (<a href="//github.com/gdgkirkley"><strong>@gdgkirkley</strong></a>>), Hung-I Wang (<a href="//github.com/Gowee"><strong>@Gowee</strong></a>), Ilham Wahabi (<a href="//github.com/iwgx"><strong>@iwgx</strong></a>), Kaito Sugimoto (<a href="//github.com/HelloRusk"><strong>@HelloRusk</strong></a>), Karl Horky (<a href="//github.com/karlhorky"><strong>@karlhorky</strong></a>), Katie Hughes (<a href="//github.com/glitteringkatie"><strong>@glitteringkatie</strong></a>), Lachlan Campbell (<a href="//github.com/lachlanjc"><strong>@lachlanjc</strong></a>), Marcy Sutton (<a href="//github.com/marcysutton"><strong>@marcysutton</strong></a>), Marius Gundersen (<a href="//github.com/mariusGundersen"><strong>@mariusGundersen</strong></a>), Marius-Remus Mate, Mark Skelton (<a href="//github.com/mskelton"><strong>@mskelton</strong></a>), Martin V (<a href="//github.com/ndresx"><strong>@ndresx</strong></a>), Matija Marohnić (<a href="//github.com/silvenon"><strong>@silvenon</strong></a>), Michael Oliver (<a href="//github.com/michaeloliverx"><strong>@michaeloliverx</strong></a>), Michaël De Boey (<a href="//github.com/MichaelDeBoey"><strong>@MichaelDeBoey</strong></a>), Muescha (<a href="//github.com/muescha"><strong>@muescha</strong></a>), Norviah (<a href="//github.com/Norviah"><strong>@Norviah</strong></a>), Paul Scanlon (<a href="//github.com/PaulieScanlon"><strong>@PaulieScanlon</strong></a>), Peter Mouland (<a href="//github.com/peter-mouland"><strong>@peter-mouland</strong></a>), Prince Wilson (<a href="//github.com/maxcell"><strong>@maxcell</strong></a>), Rafael Almeida (<a href="//github.com/rafaelalmeidatk"><strong>@rafaelalmeidatk</strong></a>), Rodrez (<a href="//github.com/rodrez"><strong>@rodrez</strong></a>), Rongjian Zhang (<a href="//github.com/pd4d10"><strong>@pd4d10</strong></a>), Taeheon Kim (<a href="//github.com/lonyele"><strong>@lonyele</strong></a>), Tom Parker-Shemilt (<a href="//github.com/palfrey"><strong>@palfrey</strong></a>), Try Ajitiono (<a href="//github.com/imballinst"><strong>@imballinst</strong></a>), Yamagishi Kazutoshi (<a href="//github.com/ykzts"><strong>@ykzts</strong></a>), Yoav Kadosh (<a href="//github.com/ykadosh"><strong>@ykadosh</strong></a>), Yordis Prieto (<a href="//github.com/Yordis"><strong>@Yordis</strong></a>), Adrian Foong (<a href="//github.com/adrfoong"><strong>@adrfoong</strong></a>), Dan Abramov (<a href="//github.com/gaearon"><strong>@gaearon</strong></a>), <a href="//github.com/ihupoo"><strong>@ihupoo</strong></a>, <a href="//github.com/nikhog"><strong>@nikhog</strong></a>, <a href="//github.com/redallen"><strong>@redallen</strong></a>, Akshay Kadam (<a href="//github.com/deadcoder0904"><strong>@deadcoder0904</strong></a>), я котик пур-пур (<a href="//github.com/mvasilkov"><strong>@mvasilkov</strong></a>), Anders D. Johnson (<a href="//github.com/AndersDJohnson"><strong>@AndersDJohnson</strong></a>), Andrew Aylett (<a href="//github.com/andrewaylett"><strong>@andrewaylett</strong></a>), Ankeet Maini (<a href="//github.com/ankeetmaini"><strong>@ankeetmaini</strong></a>), Biswas Nandamuri (<a href="//github.com/Biswas-N"><strong>@Biswas-N</strong></a>), Bret (<a href="//github.com/bcomnes"><strong>@bcomnes</strong></a>), Chris Chinchilla (<a href="//github.com/ChrisChinchilla"><strong>@ChrisChinchilla</strong></a>), Christopher Biscardi (<a href="//github.com/ChristopherBiscardi"><strong>@ChristopherBiscardi</strong></a>), Dan Overton (<a href="//github.com/dan-overton"><strong>@dan-overton</strong></a>), Domitrius (<a href="//github.com/domitriusclark"><strong>@domitriusclark</strong></a>), Dovi Winberger (<a href="//github.com/dowi"><strong>@dowi</strong></a>), Emmie Päivärinta (<a href="//github.com/emmiep"><strong>@emmiep</strong></a>), Eugene Ghanizadeh (<a href="//github.com/loreanvictor"><strong>@loreanvictor</strong></a>), and anyone we may have forgotten.</p></div>MDXConfJohn Otanderhttps://mdxjs.com/blog/conf/https://mdxjs.com/blog/conf/Fri, 31 Jul 2020 00:00:00 GMT2020-07-31T00:00:00.000Z2025-01-27T00:00:00.000Z<div><div><p><strong>Note</strong>: This is an old blog post. The below is kept as is for historical purposes.</p></div><h2 id="mdxconf"><a href="#mdxconf" class="" aria-label="Link to this section"></a>MDXConf</h2><p>MDXConf is a free and online conference for the MDX community. Whether you’re just learning about MDX or an expert, there’ll be something for you!</p><p>August 24th, 2020 at 8am PDT/3pm UST<br>Online • Free</p><h3 id="watch"><a href="#watch" class="" aria-label="Link to this section"></a>Watch</h3><p>The conference is now over, but you can still watch the recordings!</p><p><a href="//egghead.io/playlists/mdx-conf-3fc2">Watch the talks →</a></p><h3 id="about"><a href="#about" class="" aria-label="Link to this section"></a>About</h3><p>Join us for the first MDX conference! We’ll stream it directly to you, for free.</p><p>MDX has grown rapidly since the <a href="//github.com/mdx-js/mdx/commit/dee47dc20b08d534132e3b966cdccf3b88c7bca5">first commit</a> two and a half years ago. We’d like to celebrate our accomplishments so far, and talk about what lies ahead. We’ve got lots of plans.</p><p>Learn how MDX increases developer productivity, improves educational content authoring, and even peek behind the curtains to see how MDX works.</p><h3 id="speakers"><a href="#speakers" class="" aria-label="Link to this section"></a>Speakers</h3><h4 id="chris-biscardi"><a href="#chris-biscardi" class="" aria-label="Link to this section"></a>Chris Biscardi</h4><p><img alt="" src="//github.com/ChristopherBiscardi.png?size=200">]</p><p>Keynote: The past, present, and future of MDX</p><h4 id="monica-powell"><a href="#monica-powell" class="" aria-label="Link to this section"></a>Monica Powell</h4><p><img alt="" src="//github.com/M0nica.png?size=200"></p><p>Migrating to MDX</p><h4 id="laurie-barth"><a href="#laurie-barth" class="" aria-label="Link to this section"></a>Laurie Barth</h4><p><img alt="" src="//github.com/laurieontech.png?size=200"></p><p>MDX v2 syntax</p><h4 id="cole-bemis"><a href="#cole-bemis" class="" aria-label="Link to this section"></a>Cole Bemis</h4><p><img alt="" src="//github.com/colebemis.png?size=200"></p><p>Demystifying MDX</p><h4 id="prince-wilson"><a href="#prince-wilson" class="" aria-label="Link to this section"></a>Prince Wilson</h4><p><img alt="" src="//github.com/maxcell.png?size=200"></p><p>Personal site playgrounds</p><h4 id="kathleen-mcmahon"><a href="#kathleen-mcmahon" class="" aria-label="Link to this section"></a>Kathleen McMahon</h4><p><img alt="" src="//github.com/resource11.png?size=200"></p><p>Digital gardening with MDX magic</p><h4 id="rodrigo-pombo"><a href="#rodrigo-pombo" class="" aria-label="Link to this section"></a>Rodrigo Pombo</h4><p><img alt="" src="//github.com/pomber.png?size=200"></p><p>The X in MDX</p><h4 id="jonathan-bakebwa"><a href="#jonathan-bakebwa" class="" aria-label="Link to this section"></a>Jonathan Bakebwa</h4><p><img alt="" src="//github.com/codebender828.png?size=200"></p><p>MDX and Vue/Nuxt</p><h3 id="sign-up"><a href="#sign-up" class="" aria-label="Link to this section"></a>Sign up</h3><div><p><strong>Note</strong>: Sign up is closed.</p></div><h3 id="faq"><a href="#faq" class="" aria-label="Link to this section"></a>FAQ</h3><h4 id="what-if-i-cant-make-it-on-august-24th"><a href="#what-if-i-cant-make-it-on-august-24th" class="" aria-label="Link to this section"></a>What if I can’t make it on August 24th?</h4><p>We’ll miss you, but you won’t miss out! All talks will be recorded and released the day of the conference. You can catch up with the talks, or rewatch them, whenever convenient.</p><h4 id="will-the-talks-be-transcribed"><a href="#will-the-talks-be-transcribed" class="" aria-label="Link to this section"></a>Will the talks be transcribed?</h4><p>Yes.</p><h4 id="is-there-a-code-of-conduct"><a href="#is-there-a-code-of-conduct" class="" aria-label="Link to this section"></a>Is there a code of conduct?</h4><p>Absolutely. We’re dedicated to providing a harassment-free experience for everyone. We will not tolerate harassment of participants in any form. We’ve adopted the <a href="//github.com/partycorgi/partycorgi/blob/corgi/CODE_OF_CONDUCT.md">Party Corgi Network’s Code of Conduct</a>. We will have moderators to ensure that the code of conduct is followed.</p><h4 id="do-you-have-a-different-question"><a href="#do-you-have-a-different-question" class="" aria-label="Link to this section"></a>Do you have a different question?</h4><p>Reach out to us.</p></div>ShortcodesJohn Otanderhttps://mdxjs.com/blog/shortcodes/https://mdxjs.com/blog/shortcodes/Tue, 14 May 2019 00:00:00 GMT2019-05-14T00:00:00.000Z2021-11-01T00:00:00.000Z<div><div><p><strong>Note</strong>: This is an old blog post. The features described in it are currently documented at <a href="/docs/using-mdx/#mdx-provider">§ MDX provider</a>. The below is kept as is for historical purposes.</p></div><h2 id="shortcodes"><a href="#shortcodes" class="" aria-label="Link to this section"></a>Shortcodes</h2><p>An exciting new feature in MDX v1 is global shortcodes. This allows you to expose components to all of your documents in your app or website. This is a useful feature for common components like YouTube embeds, Twitter cards, or anything else frequently used in your documents.</p><p>If you have an application wrapper for your MDX documents you can add in components with the <code>MDXProvider</code>:</p><div><div><span>src/App.js</span></div><pre><code class=""><span>import</span> <span>React</span> <span>from</span> <span><span>'</span>react<span>'</span></span> <span>import</span> {<span>MDXProvider</span>} <span>from</span> <span><span>'</span>@mdx-js/react<span>'</span></span> <span>import</span> {<span>TomatoBox</span>, <span>Twitter</span>, <span>YouTube</span>} <span>from</span> <span><span>'</span>./ui<span>'</span></span> <span>const</span> <span>shortcodes</span> <span>=</span> {<span>TomatoBox</span>, <span>Twitter</span>, <span>YouTube</span>} <span>export</span> <span>default</span> ({<span>children</span>}) <span>=></span> ( &#x3C;<span>MDXProvider</span> <span>components</span><span>=</span><span>{</span><span>shortcodes</span><span>}</span>><span>{</span><span>children</span><span>}</span>&#x3C;/<span>MDXProvider</span>> ) </code></pre></div><p>Then, any MDX document that’s wrapped in <code>App</code> has access to <code>YouTube</code>, <code>Twitter</code>, and <code>TomatoBox</code>. Shortcodes are nothing more than components, so you can reference them anywhere in an MDX document with JSX.</p><div><div><span>example.mdx</span></div><pre><code class="language-mdx"><span># <span>Hello world!</span></span> Here’s a YouTube shortcode: &#x3C;<span>YouTube</span> <span>tweetId</span><span>=</span><span><span>"</span>1234<span>"</span></span> /> Here’s a YouTube shortcode wrapped in TomatoBox: &#x3C;<span>TomatoBox</span>> &#x3C;<span>YouTube</span> <span>videoId</span><span>=</span><span><span>"</span>1234<span>"</span></span> /> &#x3C;/<span>TomatoBox</span>> </code></pre></div><p>That’s it. 🎉 🚀</p><p>Huge thanks to <a href="//christopherbiscardi.com">Chris Biscardi</a> for building out most of this functionality.</p></div>MDX goes stableJohn Otanderhttps://mdxjs.com/blog/v1/https://mdxjs.com/blog/v1/Thu, 11 Apr 2019 00:00:00 GMT2019-04-11T00:00:00.000Z2025-01-27T00:00:00.000Z<div><div><p><strong>Note</strong>: This is an old blog post. <a href="//rauchg.com/2020/vercel">ZEIT is now Vercel</a>. An “<code>@mdx</code> pragma” is no longer needed. The below is kept as is for historical purposes.</p></div><h2 id="mdx-goes-stable"><a href="#mdx-goes-stable" class="" aria-label="Link to this section"></a>MDX goes stable</h2><p>It’s been a year and a half since the first MDX commit and a year since MDX was first announced at ZEIT Day. MDX is a radical paradigm shift in how to write immersive content using components. It’s an open, <a href="//johno.com/authorable-format">authorable format</a> that makes it <em>fun</em> to write again.</p><p>Since announcing MDX we’ve been working on numerous bug fixes, new features, better parsing, and integration tests. Now, we think it’s ready. <strong>We’re happy to finally release v1!</strong></p><h3 id="-whats-new"><a href="#-whats-new" class="" aria-label="Link to this section"></a>🎉 What’s new?</h3><p>Here’s a rough breakdown on what we’ve been working on:</p><h4 id="parsing"><a href="#parsing" class="" aria-label="Link to this section"></a>Parsing</h4><p>MDX document parsing is significantly improved. We won’t get into the nitty gritty here, but we’ve seen how MDX is used in real-world projects, integrated the edge cases we came across into our test suite, and now handle JSX, imports, and exports much more intuitively. Please open an issue if you find a case we haven’t covered!😸</p><h4 id="remark-mdx"><a href="#remark-mdx" class="" aria-label="Link to this section"></a>remark-mdx</h4><p><code>remark-mdx</code> is the syntactic extension for MDX in remark. It provides the parsing functionality for MDX as a <em><a href="//github.com/remarkjs/remark">remark</a> plugin</em>. That sounds a bit meta. What it means is that before we had the syntax parsing bits <em>in</em> the library (unusable from the outside), and now it’s externalized (usable from the outside). This is useful if you want to inspect or transform MDX documents. For example, it allows tools like prettier to use the exact same parser used by MDX core. Or you could use <code>remark-mdx</code> in combination with <a href="//github.com/remarkjs/remark-lint">remark-lint</a> to check your MDX.</p><h4 id="custom-pragma"><a href="#custom-pragma" class="" aria-label="Link to this section"></a>Custom pragma</h4><p>With v1 we’ve moved away from using <code>MDXTag</code> and are using a custom pragma which wraps <code>React.createElement</code>. We decided to update this approach so the JSX output is more legible, lighterweight, and more customizable. <strong>This means MDX can be used with any React, Vue, Preact, or any other library with JSX support</strong>.</p><p>Special thanks to <a href="//github.com/christopherbiscardi">@christopherbiscardi</a> for implementing this feature.</p><p><a href="../custom-pragma/">Read the blog post</a></p><h4 id="-documentation"><a href="#-documentation" class="" aria-label="Link to this section"></a>📚 Documentation</h4><p><strong>Good libraries need great docs</strong>, so we’ve been working on adding content and improving the overall documentation website experience.</p><ul><li>Search (thanks Algolia)</li><li><a href="/guides/">Guides</a></li><li><a href="//zeit.co">Automatic deployment via ZEIT</a></li><li><a href="//gatsbyjs.org">Custom Gatsby theme</a></li><li>Reorganization of docs for intuitiveness</li><li>Full page rewrites to improve clarity</li></ul><p>Special thanks to <a href="//github.com/jxnblks">@jxnblk</a> and <a href="//github.com/wooorm">@wooorm</a> for their help improving the docs and updating the build tooling.</p><h3 id="breaking-changes"><a href="#breaking-changes" class="" aria-label="Link to this section"></a>Breaking changes</h3><p>In order to make some improvements we were forced to introduce a few breaking changes. <strong>These were the result of real-world production testing and feedback</strong>. The community has evolved and we’ve come up with newer, better ideas over the last year. We have made sure the impact is small and have written a full migration guide.</p><ul><li>🚨<code>@mdx-js/tag</code> is replaced by <code>@mdx-js/react</code> and an <code>@mdx</code> pragma — <a href="/migrating/v1#pragma">migration guide</a></li><li>MDXProvider now merges component contexts when nested — <a href="/migrating/v1#mdxprovider">migration guide</a></li><li>React support now requires <code>>= 16.8</code> in <code>@mdx-js/react</code> — <a href="/migrating/v1#react">migration guide</a></li></ul><p><a href="/migrating/v1">Read the full v1 migration guide</a></p><h4 id="deprecations"><a href="#deprecations" class="" aria-label="Link to this section"></a>Deprecations</h4><p>We only needed to introduce one deprecation. The <code>mdPlugins</code> and <code>hastPlugins</code> options have been renamed <code>remarkPlugins</code> and <code>rehypePlugins</code> respectively. For the time being we will issue a warning when the old options are used. In v2, the old options will be removed.</p><h3 id="-growth"><a href="#-growth" class="" aria-label="Link to this section"></a>📈 Growth</h3><p>A major release is always a good time to take a step back and reflect on what’s been happening in terms of growth and the greater community. The ecosystem surrounding MDX has already grown larger than we ever dreamed. We’ve also seen projects/products/application we never even imagined.</p><h4 id="numbers"><a href="#numbers" class="" aria-label="Link to this section"></a>Numbers</h4><ul><li><strong>Downloads</strong>: 125,000/week, 2.4M total</li><li><strong>Stars</strong>: 6,200</li><li><strong>Contributors</strong>: 50</li><li><strong>Pull requests</strong>: 281</li><li><strong>Commits</strong>: 670</li></ul><p>The contributor growth is one of the most important aspects here as we have numerous community members that are familiar with MDX internals. This allows us to continually improve the project and spread the workload against an ever growing team of contributors.</p><p><a href="//github.com/mdx-js/mdx/graphs/contributors?from=2017-12-17&#x26;to=2019-04-11&#x26;type=c">See the contributor graph</a></p><h4 id="ecosystem"><a href="#ecosystem" class="" aria-label="Link to this section"></a>Ecosystem</h4><ul><li><a href="//prettier.io">Prettier</a></li><li><a href="//docz.site">Docz</a></li><li><a href="//github.com/jxnblk/mdx-deck">MDX Deck</a></li><li><a href="//nextjs.org">Next.js</a></li><li><a href="//gatsbyjs.org">Gatsby</a></li><li><a href="//astexplorer.net">AST Explorer</a></li><li><a href="/docs/getting-started/#vue">Vue support (alpha)</a></li><li><a href="//frontarm.com/demoboard/">Demoboard</a></li><li><a href="/docs/getting-started/#editor">Editors</a></li></ul><h3 id="-roadmap"><a href="#-roadmap" class="" aria-label="Link to this section"></a>🛣 Roadmap</h3><p>With v1 released we have a roadmap in place that we’ll continue working towards over the next 6 months or so in addition to bug fixes and parsing issues we might encounter.</p><ul><li>MDXs: <a href="//github.com/mdx-js/mdx/issues/454">#454</a></li><li>Interleaving: <a href="//github.com/mdx-js/mdx/issues/195">#195</a></li><li>Global shortcodes: <a href="//github.com/mdx-js/mdx/pull/508">#508</a></li><li>Stable Vue support: <a href="//github.com/mdx-js/mdx/issues/238">#238</a></li><li>Blocks: MDX WYSIWYG: <a href="//github.com/blocks/blocks">blocks/blocks</a></li><li>MDX playground inspired by AST Explorer: <a href="//github.com/mdx-js/mdx/issues/220">#220</a></li><li>New splash page: <a href="//github.com/mdx-js/mdx/issues/444">#444</a></li><li>Showcase page: <a href="//github.com/mdx-js/mdx/issues/414">#414</a></li></ul><h4 id="vue-support"><a href="#vue-support" class="" aria-label="Link to this section"></a>Vue support</h4><p>Supporting Vue is an important goal for MDX and is one of the primary reasons we’ve rearchitected MDX to use custom pragma. We’re delighted that <strong>we now have an alpha version for Vue working</strong>. We’d love it if anyone from the Vue community wants to give it a try and provide feedback.</p><p><a href="//github.com/mdx-js/mdx/tree/36cb41b/examples/vue">See the Vue example</a></p><h4 id="blocks-project"><a href="#blocks-project" class="" aria-label="Link to this section"></a>Blocks project</h4><p>One of the key missing aspects of authoring MDX documents is the editing experience. Currently, there isn’t an approachable way to write MDX unless you enjoy working in a text editor and writing raw Markdown/code. We’d like to solve that and have begun work on an MDX “blocks editor” that’s a <strong>content-focused WYSIWYG</strong>. Not to mention, we’ll be doing all that we can to make sure the editor is as accessible as it can be from the beginning.</p><p>When we have a beta ready we will be open sourcing it and announcing, so stay tuned.</p><p><a href="//github.com/blocks/blocks">Check out the Blocks project</a></p><h3 id="unified-collective"><a href="#unified-collective" class="" aria-label="Link to this section"></a>unified collective</h3><p>MDX is part of the unified collective, which is an open source ecosystem for dealing with many sources of content. unified projects are used all over the web, and it would never be possible without financial support from our fine sponsors.</p><ul><li><a href="//zeit.co">ZEIT</a> 🥇</li><li><a href="//gatsbyjs.org">Gatsby</a> 🥇</li><li><a href="//www.holloway.com">Holloway</a> 🥉</li><li><a href="//opencollective.com/unified#budget">Backers</a> 🏆</li><li><a href="//opencollective.com/unified">You?</a>👤</li></ul><h3 id="-thanks"><a href="#-thanks" class="" aria-label="Link to this section"></a>🙏 Thanks</h3><p>We’d like to say thanks to all our contributors and our happy users. Special thanks to <a href="//github.com/wooorm">@wooorm</a>, <a href="//github.com/silvenon">@silvenon</a>, <a href="//github.com/timneutkens">@timneutkens</a>, <a href="//github.com/christopherbiscardi">@ChristopherBiscardi</a>, <a href="//github.com/jxnblk">@jxnblk</a>, <a href="//github.com/alexandernanberg">@alexandernanberg</a>, <a href="//github.com/jescalan">@jescalan</a>, <a href="//github.com/Jarred-Sumner">@Jarred-Sumner</a>, <a href="//github.com/leimonio">@leimonio</a>, <a href="//github.com/ticky">@ticky</a>, <a href="//github.com/jamesknelson">@jamesknelson</a>, <a href="//github.com/pshrmn">@pshrmn</a>, <a href="//github.com/rauchg">@rauchg</a>, <a href="//github.com/joelhooks">@joelhooks</a>, <a href="//github.com/jlengstorf">@jlengstorf</a>, <a href="//github.com/johnlindquist">@johnlindquist</a>, <a href="//github.com/kyleamathews">@kyleamathews</a>, <a href="//github.com/kentcdodds">@kentcdodds</a>, <a href="//github.com/wesbos">@wesbos</a>, <a href="//github.com/rosew">@rosew</a>, <a href="//github.com/pedronauck">@pedronauck</a>, <a href="//github.com/tayiorbeii">@tayiorbeii</a>, <a href="//github.com/nickbender">@nickbender</a>, <a href="//github.com/ntaylor89">@ntaylor89</a>, <a href="//github.com/mxstbr">@mxstbr</a>, <a href="//github.com/manovotny">@manovotny</a>, <a href="//github.com/xyc">@xyc</a>, <a href="//github.com/filoxo">@filoxo</a>, <a href="//github.com/millette">@millette</a>, <a href="//github.com/hugmanrique">@hugmanrique</a>, <a href="//github.com/johnsherrard">@johnsherrard</a>, <a href="//github.com/sw-yx">@sw-yx</a>, and anyone we may have forgotten.</p></div>Custom pragmaChris Biscardihttps://mdxjs.com/blog/custom-pragma/https://mdxjs.com/blog/custom-pragma/Mon, 11 Mar 2019 00:00:00 GMT2019-03-11T00:00:00.000Z2021-11-01T00:00:00.000Z<div><div><p><strong>Note</strong>: This is an old blog post. The steps described in it are no longer performed by MDX. It now uses an JavaScript AST first rather than generating a string of JSX. It is also no longer required for extra glue code, that combines MDX with a specific framework, to be used on the client. See <a href="/docs/using-mdx/#how-mdx-works">§ How MDX works</a> and <a href="/packages/mdx/#architecture">¶ Architecture</a> for more info. The below is kept as is for historical purposes.</p></div><h2 id="custom-pragma"><a href="#custom-pragma" class="" aria-label="Link to this section"></a>Custom pragma</h2><p><code>MDXTag</code>, for those that aren’t aware, is a critical piece in the way MDX replaces HTML primitives like <code>&#x3C;pre></code> and <code>&#x3C;h1></code> with custom React Components. <a href="//www.christopherbiscardi.com/post/codeblocks-mdx-and-mdx-utils">I’ve previously written</a> about the way <code>MDXTag</code> works when trying to replace the <code>&#x3C;pre></code> tag with a custom code component. <a href="//github.com/ChristopherBiscardi/gatsby-mdx/blob/00769a1b72455f40843cd2f09ee34fd63b009fb2/packages/mdx-utils/index.js">mdx-utils</a> contains the methodology for pulling the props around appropriately through the <code>MDXTag</code> elements that are inbetween <code>pre</code> and <code>code</code>.</p><div><div><span>TypeScript</span></div><pre><code class=""><span>exports</span>.<span>preToCodeBlock</span> <span>=</span> <span>preProps</span> <span>=></span> { <span>if</span> ( <span>// children is MDXTag</span> <span>preProps</span>.<span>children</span> <span>&#x26;&#x26;</span> <span>// MDXTag props</span> <span>preProps</span>.<span>children</span>.<span>props</span> <span>&#x26;&#x26;</span> <span>// if MDXTag is going to render a &#x3C;code></span> <span>preProps</span>.<span>children</span>.<span>props</span>.<span>name</span> <span>===</span> <span><span>'</span>code<span>'</span></span> ) { <span>// we have a &#x3C;pre>&#x3C;code> situation</span> <span>const</span> { <span>children</span>: <span>codeString</span>, <span>props</span>: {<span>className</span>, <span>...</span><span>props</span>} } <span>=</span> <span>preProps</span>.<span>children</span>.<span>props</span> <span>return</span> { codeString: <span>codeString</span>.<span>trim</span>(), language: <span>className</span> <span>&#x26;&#x26;</span> <span>className</span>.<span>split</span>(<span><span>'</span>-<span>'</span></span>)[<span>1</span>], <span>...</span><span>props</span> } } <span>return</span> <span>undefined</span> } </code></pre></div><p>So <code>MDXTag</code> is a real Component in the middle of all of the other MDX rendered elements. All of the code is included here for reference.</p><div><div><span>TypeScript</span></div><pre><code class=""><span>import</span> <span>React</span>, {<span>Component</span>} <span>from</span> <span><span>'</span>react<span>'</span></span> <span>import</span> {<span>withMDXComponents</span>} <span>from</span> <span><span>'</span>./mdx-provider<span>'</span></span> <span>const</span> <span>defaults</span> <span>=</span> { inlineCode: <span><span>'</span>code<span>'</span></span>, wrapper: <span><span>'</span>div<span>'</span></span> } <span>class</span> <span>MDXTag</span> <span>extends</span> <span>Component</span> { <span>render</span>() { <span>const</span> { <span>name</span>, <span>parentName</span>, <span>props</span>: <span>childProps</span> <span>=</span> {}, <span>children</span>, <span>components</span> <span>=</span> {}, <span>Layout</span>, <span>layoutProps</span> } <span>=</span> <span>this</span>.<span>props</span> <span>const</span> <span>Component</span> <span>=</span> <span>components</span>[<span><span>`</span>${<span>parentName</span>}.${<span>name</span>}<span>`</span></span>] <span>||</span> <span>components</span>[<span>name</span>] <span>||</span> <span>defaults</span>[<span>name</span>] <span>||</span> <span>name</span> <span>if</span> (<span>Layout</span>) { <span>return</span> ( &#x3C;<span>Layout</span> <span>components</span><span>=</span><span>{</span><span>components</span><span>}</span> <span>{</span><span>...</span><span>layoutProps</span><span>}</span>> &#x3C;<span>Component</span> <span>{</span><span>...</span><span>childProps</span><span>}</span>><span>{</span><span>children</span><span>}</span>&#x3C;/<span>Component</span>> &#x3C;/<span>Layout</span>> ) } <span>return</span> &#x3C;<span>Component</span> <span>{</span><span>...</span><span>childProps</span><span>}</span>><span>{</span><span>children</span><span>}</span>&#x3C;/<span>Component</span>> } } <span>export</span> <span>default</span> <span>withMDXComponents</span>(<span>MDXTag</span>) </code></pre></div><p><code>MDXTag</code> is used in the hast to estree conversion, which is the final step in the MDX AST pipeline. Every renderable element is wrapped in an <code>MDXTag</code>, and <code>MDXTag</code> handles rendering the element later.</p><div><div><span>TypeScript</span></div><pre><code class=""><span>return</span> <span><span>`</span>&#x3C;MDXTag name="${<span>node</span>.<span>tagName</span>}" components={components}${</span> <span> <span>parentNode</span>.<span>tagName</span> <span>?</span> <span>`</span> parentName="${<span>parentNode</span>.<span>tagName</span>}"<span>`</span> <span>:</span> <span>''</span></span> <span>}${<span>props</span> <span>?</span> <span>`</span> props={${<span>props</span>}}<span>`</span> <span>:</span> <span>''</span>}>${<span>children</span>}&#x3C;/MDXTag><span>`</span></span> </code></pre></div><h3 id="a-concrete-example"><a href="#a-concrete-example" class="" aria-label="Link to this section"></a>A concrete example</h3><p>The following MDX</p><div><div><span>MDX</span></div><pre><code class="language-mdx"><span># <span>a title</span></span> and such testing </code></pre></div><p>turns into the following React code</p><div><div><span>TypeScript</span></div><pre><code class=""><span>export</span> <span>default</span> ({<span>components</span>, <span>...</span><span>props</span>}) <span>=></span> ( &#x3C;<span>MDXTag</span> <span>name</span><span>=</span><span><span>"</span>wrapper<span>"</span></span> <span>components</span><span>=</span><span>{</span><span>components</span><span>}</span>> &#x3C;<span>MDXTag</span> <span>name</span><span>=</span><span><span>"</span>h1<span>"</span></span> <span>components</span><span>=</span><span>{</span><span>components</span><span>}</span>><span>{</span><span><span>`</span>a title<span>`</span></span><span>}</span>&#x3C;/<span>MDXTag</span>><span>{</span><span><span>'</span> <span>'</span></span><span>}</span> &#x3C;<span>MDXTag</span> <span>name</span><span>=</span><span><span>"</span>pre<span>"</span></span> <span>components</span><span>=</span><span>{</span><span>components</span><span>}</span>> &#x3C;<span>MDXTag</span> <span>name</span><span>=</span><span><span>"</span>code<span>"</span></span> <span>components</span><span>=</span><span>{</span><span>components</span><span>}</span> <span>parentName</span><span>=</span><span><span>"</span>pre<span>"</span></span> <span>props</span><span>=</span><span>{</span>{metaString: <span>null</span>}<span>}</span> ><span>{</span><span><span>`</span>and such <span>`</span></span><span>}</span>&#x3C;/<span>MDXTag</span>> &#x3C;/<span>MDXTag</span>><span>{</span><span><span>'</span> <span>'</span></span><span>}</span> &#x3C;<span>MDXTag</span> <span>name</span><span>=</span><span><span>"</span>p<span>"</span></span> <span>components</span><span>=</span><span>{</span><span>components</span><span>}</span>><span>{</span><span><span>`</span>testing<span>`</span></span><span>}</span>&#x3C;/<span>MDXTag</span>> &#x3C;/<span>MDXTag</span>> ) </code></pre></div><p>resulting in the following HTML</p><div><div><span>HTML</span></div><pre><code class="language-html">&#x3C;<span>div</span>> &#x3C;<span>h1</span>>a title&#x3C;/<span>h1</span>> &#x3C;<span>pre</span>> &#x3C;<span>code</span>>and such&#x3C;/<span>code</span>> &#x3C;/<span>pre</span>> &#x3C;<span>p</span>>testing&#x3C;/<span>p</span>> &#x3C;/<span>div</span>> </code></pre></div><h3 id="createelement"><a href="#createelement" class="" aria-label="Link to this section"></a>createElement</h3><p>With the new approach, the above MDX transforms into this new React code</p><div><div><span>TypeScript</span></div><pre><code class=""><span>const</span> <span>layoutProps</span> <span>=</span> {} <span>export</span> <span>default</span> <span>function</span> <span>MDXContent</span>({<span>components</span>, <span>...</span><span>props</span>}) { <span>return</span> ( &#x3C;<span>MDXLayout</span> <span>{</span><span>...</span><span>layoutProps</span><span>}</span> <span>{</span><span>...</span><span>props</span><span>}</span> <span>components</span><span>=</span><span>{</span><span>components</span><span>}</span> <span>mdxType</span><span>=</span><span><span>"</span>MDXLayout<span>"</span></span> > &#x3C;<span>h1</span>><span>{</span><span><span>`</span>a title<span>`</span></span><span>}</span>&#x3C;/<span>h1</span>> &#x3C;<span>pre</span>> &#x3C;<span>code</span> <span>parentName</span><span>=</span><span><span>"</span>pre<span>"</span></span> <span>{</span><span>...</span>{}<span>}</span>><span>{</span><span><span>`</span>and such</span> <span><span>`</span></span><span>}</span>&#x3C;/<span>code</span>> &#x3C;/<span>pre</span>> &#x3C;<span>p</span>><span>{</span><span><span>`</span>testing<span>`</span></span><span>}</span>&#x3C;/<span>p</span>> &#x3C;/<span>MDXLayout</span>> ) } <span>MDXContent</span>.<span>isMDXComponent</span> <span>=</span> <span>true</span> </code></pre></div><p>Notice how now the React elements are plainly readable without wrapping <code>MDXTag</code>.</p><p>Now that we’ve cleaned up the intermediary representation, we need to make sure that we have the same functionality as the old <code>MDXTag</code>. This is done through a custom <code>createElement</code> implementation. Typically when using React, we use <code>React.createElement</code> to render the elements on screen. This is even true if you’re using JSX because JSX tags such as <code>&#x3C;div></code> compile to <code>createElement</code> calls. So this time instead of using <code>React.createElement</code> we’ll be using our own.</p><p>Reproduced here is our <code>createElement</code> function and the logic for how we decide whether or not MDX should take over the rendering of the <code>createElement</code> call.</p><div><div><span>TypeScript</span></div><pre><code class=""><span>export</span> <span>default</span> <span>function</span> (<span>type</span>, <span>props</span>) { <span>const</span> <span>args</span> <span>=</span> <span>arguments</span> <span>const</span> <span>mdxType</span> <span>=</span> <span>props</span> <span>&#x26;&#x26;</span> <span>props</span>.<span>mdxType</span> <span>if</span> (<span>typeof</span> <span>type</span> <span>===</span> <span><span>'</span>string<span>'</span></span> <span>||</span> <span>mdxType</span>) { <span>const</span> <span>argsLength</span> <span>=</span> <span>args</span>.<span>length</span> <span>const</span> <span>createElementArgArray</span> <span>=</span> <span>new</span> <span>Array</span>(<span>argsLength</span>) <span>createElementArgArray</span>[<span>0</span>] <span>=</span> <span>MDXCreateElement</span> <span>const</span> <span>newProps</span> <span>=</span> {} <span>for</span> (<span>let</span> <span>key</span> <span>in</span> <span>props</span>) { <span>if</span> (<span>hasOwnProperty</span>.<span>call</span>(<span>props</span>, <span>key</span>)) { <span>newProps</span>[<span>key</span>] <span>=</span> <span>props</span>[<span>key</span>] } } <span>newProps</span>.<span>originalType</span> <span>=</span> <span>type</span> <span>newProps</span>[<span>TYPE_PROP_NAME</span>] <span>=</span> <span>typeof</span> <span>type</span> <span>===</span> <span><span>'</span>string<span>'</span></span> <span>?</span> <span>type</span> <span>:</span> <span>mdxType</span> <span>createElementArgArray</span>[<span>1</span>] <span>=</span> <span>newProps</span> <span>for</span> (<span>let</span> <span>i</span> <span>=</span> <span>2</span>; <span>i</span> <span>&#x3C;</span> <span>argsLength</span>; <span>i</span><span>++</span>) { <span>createElementArgArray</span>[<span>i</span>] <span>=</span> <span>args</span>[<span>i</span>] } <span>return</span> <span>React</span>.<span>createElement</span>.<span>apply</span>(<span>null</span>, <span>createElementArgArray</span>) } <span>return</span> <span>React</span>.<span>createElement</span>.<span>apply</span>(<span>null</span>, <span>args</span>) } </code></pre></div><h3 id="vue"><a href="#vue" class="" aria-label="Link to this section"></a>Vue</h3><p>One really cool application of the new output format using a custom <code>createElement</code> is that we can now write versions of it for Vue and other frameworks. Since the pragma insertion is the responsibility of the webpack (or other bundlers) loader, swapping the pragma can be an option in mdx-loader as long as we have a Vue <code>createElement</code> to point to.</p></div>