40 | )
41 | }
42 |
--------------------------------------------------------------------------------
/docs/_component/sort.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {Data} from 'vfile'
3 | */
4 |
5 | /**
6 | * @typedef Item
7 | * Item.
8 | * @property {string} name
9 | * Name.
10 | * @property {Readonly} data
11 | * Data.
12 | * @property {Array} children
13 | * Children.
14 | */
15 |
16 | import dlv from 'dlv'
17 |
18 | const collator = new Intl.Collator('en').compare
19 |
20 | /**
21 | * @param {ReadonlyArray} items
22 | * Items.
23 | * @param {string | undefined} [sortString]
24 | * Fields to sort on (default: `'navSortSelf,meta.title'`).
25 | * @returns {ReadonlyArray}
26 | * Items.
27 | */
28 | export function sortItems(items, sortString = 'navSortSelf,meta.title') {
29 | /** @type {ReadonlyArray<[string, 'asc' | 'desc']>} */
30 | const fields = sortString.split(',').map(function (d) {
31 | const [field, order = 'asc'] = d.split(':')
32 |
33 | if (order !== 'asc' && order !== 'desc') {
34 | throw new Error('Cannot order as `' + order + '`')
35 | }
36 |
37 | return [field, order]
38 | })
39 |
40 | return [...items].sort(function (left, right) {
41 | let index = -1
42 |
43 | while (++index < fields.length) {
44 | const [field, order] = fields[index]
45 | /** @type {unknown} */
46 | let a = dlv(left.data, field)
47 | /** @type {unknown} */
48 | let b = dlv(right.data, field)
49 |
50 | // Dates.
51 | if (a && typeof a === 'object' && 'valueOf' in a) a = a.valueOf()
52 | if (b && typeof b === 'object' && 'valueOf' in b) b = b.valueOf()
53 |
54 | const score =
55 | typeof a === 'string' && typeof b === 'string'
56 | ? collator(a, b)
57 | : typeof a === 'number' && typeof b === 'number'
58 | ? a - b
59 | : (a === null || a === undefined) && (b === null || b === undefined)
60 | ? 0
61 | : a === null || a === undefined
62 | ? 1
63 | : b === null || b === undefined
64 | ? -1
65 | : 0
66 |
67 | if (score) return order === 'asc' ? score : -score
68 | }
69 |
70 | return 0
71 | })
72 | }
73 |
--------------------------------------------------------------------------------
/docs/_config.js:
--------------------------------------------------------------------------------
1 | const site = new URL('https://mdxjs.com')
2 | const git = new URL('../', import.meta.url)
3 | const gh = new URL('https://github.com/mdx-js/mdx/')
4 |
5 | export const config = {
6 | author: 'MDX contributors',
7 | color: '#010409',
8 | gh,
9 | ghBlob: new URL('blob/main/', gh),
10 | ghTree: new URL('tree/main/', gh),
11 | git,
12 | input: new URL('docs/', git),
13 | oc: new URL('https://opencollective.com/unified'),
14 | output: new URL('public/', git),
15 | site,
16 | tags: ['mdx', 'markdown', 'jsx', 'oss', 'react'],
17 | title: 'MDX'
18 | }
19 |
20 | /** @type {Record} */
21 | export const redirect = {
22 | '/about/index.html': '/community/about/',
23 | '/advanced/index.html': '/guides/',
24 | '/advanced/api/index.html': '/packages/mdx/#api',
25 | '/advanced/ast/index.html': '/packages/remark-mdx/#syntax-tree',
26 | '/advanced/components/index.html': '/docs/using-mdx/',
27 | '/advanced/contributing/index.html': '/community/contribute/',
28 | '/advanced/custom-loader/index.html': '/guides/frontmatter/',
29 | '/advanced/retext-plugins/index.html': '/docs/extending-mdx/#using-plugins',
30 | '/advanced/plugins/index.html': '/docs/extending-mdx/',
31 | '/advanced/runtime/index.html': '/packages/mdx/#evaluatefile-options',
32 | '/advanced/specification/index.html': '/packages/remark-mdx/#syntax-tree',
33 | '/advanced/sync-api/index.html': '/packages/mdx/#api',
34 | '/advanced/transform-content/index.html': '/packages/remark-mdx/',
35 | '/advanced/typescript/index.html': '/docs/getting-started/#types',
36 | '/advanced/writing-a-plugin/index.html': '/guides/frontmatter/',
37 | '/contributing/index.html': '/community/contribute/',
38 | '/editor-plugins/index.html': '/docs/getting-started/#editor',
39 | '/editors/index.html': '/docs/getting-started/#editor',
40 | '/getting-started/create-react-app/index.html': '/docs/getting-started/#vite',
41 | '/getting-started/gatsby/index.html': '/docs/getting-started/#gatsby',
42 | '/getting-started/next/index.html': '/docs/getting-started/#nextjs',
43 | '/getting-started/parcel/index.html': '/docs/getting-started/#parcel',
44 | '/getting-started/react-static/index.html': '/docs/getting-started/#vite',
45 | '/getting-started/table-of-components/index.html': '/table-of-components/',
46 | '/getting-started/typescript/index.html': '/docs/getting-started/#types',
47 | '/getting-started/webpack/index.html': '/docs/getting-started/#webpack',
48 | '/getting-started/index.html': '/docs/getting-started/',
49 | '/guides/custom-loader/index.html': '/guides/frontmatter/',
50 | '/guides/live-code/index.html':
51 | '/guides/syntax-highlighting/#syntax-highlighting-with-the-meta-field',
52 | '/guides/markdown-in-components/index.html': '/docs/what-is-mdx/',
53 | '/guides/math-blocks/index.html': '/guides/math/',
54 | '/guides/mdx-embed/index.html': '/guides/embed/#embeds-at-run-time',
55 | '/guides/table-of-contents/index.html': '/docs/extending-mdx/',
56 | '/guides/terminal/index.html': '/docs/getting-started/#ink',
57 | '/guides/vue/index.html': '/docs/getting-started/#vue',
58 | '/guides/wrapper-customization/index.html': '/docs/using-mdx/#layout',
59 | '/guides/writing-a-plugin/index.html':
60 | '/docs/extending-mdx/#creating-plugins',
61 | '/mdx/index.html': '/docs/what-is-mdx/',
62 | '/plugins/index.html': '/docs/extending-mdx/#using-plugins',
63 | '/projects/index.html': '/community/projects/',
64 | '/support/index.html': '/community/support/',
65 | '/syntax/index.html': '/docs/getting-started/#syntax',
66 | '/vue/index.html': '/docs/getting-started/#vue'
67 | }
68 |
--------------------------------------------------------------------------------
/docs/_static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mdx-js/mdx/b3351fadcb6f78833a72757b7135dcfb8ab646fe/docs/_static/favicon.ico
--------------------------------------------------------------------------------
/docs/_static/icon.svg:
--------------------------------------------------------------------------------
1 |
25 |
--------------------------------------------------------------------------------
/docs/_static/og-v2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mdx-js/mdx/b3351fadcb6f78833a72757b7135dcfb8ab646fe/docs/_static/og-v2.png
--------------------------------------------------------------------------------
/docs/_static/og.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mdx-js/mdx/b3351fadcb6f78833a72757b7135dcfb8ab646fe/docs/_static/og.png
--------------------------------------------------------------------------------
/docs/blog/conf.mdx:
--------------------------------------------------------------------------------
1 | import {Note} from '../_component/note.jsx'
2 |
3 | export const info = {
4 | author: [
5 | {github: 'johno', name: 'John Otander'}
6 | ],
7 | modified: new Date('2025-01-27'),
8 | published: new Date('2020-07-31')
9 | }
10 |
11 |
12 | **Note**: This is an old blog post.
13 | The below is kept as is for historical purposes.
14 |
15 |
16 | # MDXConf
17 |
18 | MDXConf is a free and online conference for the MDX community.
19 | Whether you’re just learning about MDX or an expert, there’ll be something for
20 | you! {/* more */}
21 |
22 | August 24th, 2020 at 8am PDT/3pm UST Online • Free
23 |
24 | ## Watch
25 |
26 | The conference is now over, but you can still watch the recordings!
27 |
28 | [Watch the talks →](https://egghead.io/playlists/mdx-conf-3fc2)
29 |
30 | ## About
31 |
32 | Join us for the first MDX conference!
33 | We’ll stream it directly to you, for free.
34 |
35 | MDX has grown rapidly since the [first commit][] two and a half years ago.
36 | We’d like to celebrate our accomplishments so far, and talk about what lies
37 | ahead.
38 | We’ve got lots of plans.
39 |
40 | Learn how MDX increases developer productivity, improves educational
41 | content authoring, and even peek behind the curtains to see how MDX works.
42 |
43 | ## Speakers
44 |
45 | ### Chris Biscardi
46 |
47 | ]
48 |
49 | Keynote: The past, present, and future of MDX
50 |
51 | ### Monica Powell
52 |
53 | 
54 |
55 | Migrating to MDX
56 |
57 | ### Laurie Barth
58 |
59 | 
60 |
61 | MDX v2 syntax
62 |
63 | ### Cole Bemis
64 |
65 | 
66 |
67 | Demystifying MDX
68 |
69 | ### Prince Wilson
70 |
71 | 
72 |
73 | Personal site playgrounds
74 |
75 | ### Kathleen McMahon
76 |
77 | 
78 |
79 | Digital gardening with MDX magic
80 |
81 | ### Rodrigo Pombo
82 |
83 | 
84 |
85 | The X in MDX
86 |
87 | ### Jonathan Bakebwa
88 |
89 | 
90 |
91 | MDX and Vue/Nuxt
92 |
93 | ## Sign up
94 |
95 |
96 | **Note**: Sign up is closed.
97 |
98 |
99 | ## FAQ
100 |
101 | ### What if I can’t make it on August 24th?
102 |
103 | We’ll miss you, but you won’t miss out!
104 | All talks will be recorded and released the day of the conference.
105 | You can catch up with the talks, or rewatch them, whenever convenient.
106 |
107 | ### Will the talks be transcribed?
108 |
109 | Yes.
110 |
111 | ### Is there a code of conduct?
112 |
113 | Absolutely.
114 | We’re dedicated to providing a harassment-free experience for everyone.
115 | We will not tolerate harassment of participants in any form.
116 | We’ve adopted the [Party Corgi Network’s Code of Conduct][coc].
117 | We will have moderators to ensure that the code of conduct is followed.
118 |
119 | ### Do you have a different question?
120 |
121 | Reach out to us.
122 |
123 | [coc]: https://github.com/partycorgi/partycorgi/blob/corgi/CODE_OF_CONDUCT.md
124 |
125 | [first commit]: https://github.com/mdx-js/mdx/commit/dee47dc20b08d534132e3b966cdccf3b88c7bca5
126 |
--------------------------------------------------------------------------------
/docs/blog/index.mdx:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * @import {Item} from '../_component/sort.js'
4 | */
5 |
6 | /**
7 | * @typedef Props
8 | * @property {Item} navigationTree
9 | */
10 | }
11 |
12 | import assert from 'node:assert/strict'
13 | import {BlogGroup} from '../_component/blog.jsx'
14 |
15 | export const info = {
16 | author: [{name: 'MDX Contributors'}],
17 | modified: new Date('2024-07-04'),
18 | published: new Date('2021-11-01')
19 | }
20 | export const navExcludeGroup = true
21 | export const navigationSortItems = 'navSortSelf,meta.published:desc'
22 | export const navSortSelf = 7
23 |
24 | # Blog
25 |
26 | The latest news about MDX.
27 |
28 | {
29 | (function () {
30 | const navigationTree = props.navigationTree
31 | const category = navigationTree.children.find(function (item) {
32 | return item.name === '/blog/'
33 | })
34 | assert(category)
35 |
36 | return (
37 |
40 | )
41 | })()
42 | }
43 |
--------------------------------------------------------------------------------
/docs/blog/shortcodes.mdx:
--------------------------------------------------------------------------------
1 | import {Note} from '../_component/note.jsx'
2 |
3 | export const info = {
4 | author: [
5 | {github: 'johno', name: 'John Otander'}
6 | ],
7 | modified: new Date('2021-11-01'),
8 | published: new Date('2019-05-14')
9 | }
10 |
11 |
12 | **Note**: This is an old blog post.
13 | The features described in it are currently documented at
14 | [§ MDX provider](/docs/using-mdx/#mdx-provider).
15 | The below is kept as is for historical purposes.
16 |
17 |
18 | # Shortcodes
19 |
20 | An exciting new feature in MDX v1 is global shortcodes.
21 | This allows you to expose components to all of your documents in your app or
22 | website.
23 | This is a useful feature for common components like YouTube embeds, Twitter
24 | cards, or anything else frequently used in your documents.
25 |
26 | {/* more */}
27 |
28 | If you have an application wrapper for your MDX documents
29 | you can add in components with the `MDXProvider`:
30 |
31 | ```tsx path="src/App.js"
32 | import React from 'react'
33 | import {MDXProvider} from '@mdx-js/react'
34 | import {TomatoBox, Twitter, YouTube} from './ui'
35 |
36 | const shortcodes = {TomatoBox, Twitter, YouTube}
37 |
38 | export default ({children}) => (
39 | {children}
40 | )
41 | ```
42 |
43 | Then, any MDX document that’s wrapped in `App` has access to `YouTube`,
44 | `Twitter`, and `TomatoBox`.
45 | Shortcodes are nothing more than components, so you can reference them anywhere
46 | in an MDX document with JSX.
47 |
48 | ```mdx path="example.mdx"
49 | # Hello world!
50 |
51 | Here’s a YouTube shortcode:
52 |
53 |
54 |
55 | Here’s a YouTube shortcode wrapped in TomatoBox:
56 |
57 |
58 |
59 |
60 | ```
61 |
62 | That’s it.
63 | 🎉 🚀
64 |
65 | Huge thanks to [Chris Biscardi](https://christopherbiscardi.com)
66 | for building out most of this functionality.
67 |
--------------------------------------------------------------------------------
/docs/blog/v3.mdx:
--------------------------------------------------------------------------------
1 | import {Note} from '../_component/note.jsx'
2 | export const info = {
3 | author: [
4 | {github: 'wooorm', name: 'Titus Wormer'}
5 | ],
6 | modified: new Date('2025-01-27'),
7 | published: new Date('2023-10-24')
8 | }
9 |
10 |
11 | **Note**: Info on how to migrate is available in our
12 | [Version 3 migration guide][migrating].
13 |
14 |
15 | # MDX 3
16 |
17 | Version 3 already!
18 | This major version contains a couple small changes.
19 | For most folks, updating Node.js and plugins is all that’s needed!
20 |
21 | {/* more */}
22 |
23 | ## Contents
24 |
25 | * [Breaking changes](#breaking-changes)
26 | * [Improvements to the MDX format](#improvements-to-the-mdx-format)
27 | * [Adjacent block JSX and expressions in MDX](#adjacent-block-jsx-and-expressions-in-mdx)
28 | * [Await in MDX](#await-in-mdx)
29 | * [ES2024 in MDX](#es2024-in-mdx)
30 | * [Miscellaneous](#miscellaneous)
31 | * [Thanks](#thanks)
32 |
33 | ## Breaking changes
34 |
35 | The main breaking change is that Node.js 16 is now the minimum supported
36 | version.
37 |
38 | Across the ecosystem there were several small internal breaking changes.
39 | Everything’s released already.
40 | You can update all plugins now.
41 | If you ran into problems before, it should work now.
42 |
43 | We also removed some infrequently used deprecated APIs.
44 | You’re likely fine but gloss over the [v3 migration guide][migrating] if you
45 | get errors.
46 |
47 | Important to note when you use your lesser-known but powerful `evaluate`, `run`,
48 | or `outputFormat: 'function-body'` APIs, please pass the `baseUrl` option.
49 | That makes sure `import.meta.url`, `import`, and `export` work.
50 | You’ll get a runtime error when those features are used otherwise.
51 |
52 | ## Improvements to the MDX format
53 |
54 | There’s also a few small improvements to the MDX format, some of which
55 | technically breaking.
56 |
57 | ### Adjacent block JSX and expressions in MDX
58 |
59 | We now accept block expressions right next to block JSX tags:
60 |
61 | ```mdx chrome=no
62 |
69 | ```
70 |
71 | Previously, there was a syntax error, and you had to add a newline between the
72 | angle brackets and the braces.
73 |
74 | ### Await in MDX
75 |
76 | We now accept `await` syntax:
77 |
78 | ```mdx
79 | {await Promise.resolve(42)}
80 | ```
81 |
82 | Most frameworks don’t support promises.
83 | Whether this works depends on that.
84 |
85 | Previously, there was a runtime error that `await` was used in a context where
86 | it wasn’t allowed.
87 |
88 | ### ES2024 in MDX
89 |
90 | You can now use modern JavaScript syntax in MDX.
91 | Acorn, used internally, is now instructed to use ES2024.
92 |
93 | ## Miscellaneous
94 |
95 | I refactored all the docs.
96 | Updating every use example where needed.
97 | I also wrote a guide on how to inject components from anywhere:
98 | [§ Injecting components][injecting-components].
99 |
100 | The site is a lot faster.
101 | There’s a nice improved playground too: [try it out! »][playground].
102 | We also have proper syntax highlighting here, thanks to
103 | [`wooorm/markdown-tm-language`][markdown-tm-language]
104 | and [`wooorm/starry-night`][starry-night].
105 |
106 | The generated JS code is a little cleaner (the JSX pragma comment is removed
107 | and objects are sorted where needed), it also uses spreads instead of
108 | `Object.assign`, there’s a `'use strict'` added when needed, and the
109 | `MDXContent` is exported immediately.
110 |
111 | ## Thanks
112 |
113 | We’d like to say thanks to all our contributors and our happy users.
114 | Special thanks to
115 | 北雁云依 ([**@BeiyanYunyi**](https://github.com/BeiyanYunyi)),
116 | Christian Murphy ([**@ChristianMurphy**](https://github.com/ChristianMurphy)),
117 | JokcyLou ([**@Jokcy**](https://github.com/Jokcy)),
118 | Maël Nison ([**@arcanis**](https://github.com/arcanis)),
119 | Andreas Deininger ([**@deining**](https://github.com/deining)),
120 | Remco Haszing ([**@remcohaszing**](https://github.com/remcohaszing)),
121 | Sébastien Lorber ([**@slorber**](https://github.com/slorber)),
122 | Víctor Fernández ([**@victor23k**](https://github.com/victor23k)),
123 | Titus Wormer ([**@wooorm**](https://github.com/wooorm)),
124 | and anyone we may have forgotten.
125 |
126 | [injecting-components]: /guides/injecting-components/
127 |
128 | [markdown-tm-language]: https://github.com/wooorm/markdown-tm-language
129 |
130 | [migrating]: /migrating/v3/
131 |
132 | [playground]: /playground/
133 |
134 | [starry-night]: https://github.com/wooorm/starry-night
135 |
--------------------------------------------------------------------------------
/docs/community/contribute.mdx:
--------------------------------------------------------------------------------
1 | import {Note} from '../_component/note.jsx'
2 |
3 | export const info = {
4 | author: [
5 | {github: 'wooorm', name: 'Titus Wormer'}
6 | ],
7 | modified: new Date('2025-01-27'),
8 | published: new Date('2018-11-04')
9 | }
10 | export const navSortSelf = 2
11 |
12 | # Contribute
13 |
14 | This article explains how to contribute to MDX.
15 | Please read through the following guidelines.
16 |
17 | {/* more */}
18 |
19 |
20 | **Important**: before participating in our community, please read our
21 | [code of conduct][coc].
22 | By interacting with this repository, organization, or community you agree to
23 | abide by its terms.
24 |
25 |
26 | ## Contributions
27 |
28 | There’s several ways to contribute, not just by writing code.
29 | If you have questions, see [§ Support][support].
30 | If you can provide financial support, see [§ Sponsor][sponsor].
31 |
32 | ### Improve docs
33 |
34 | As a user you’re perfect for helping us improve our docs.
35 | Typo corrections, error fixes, better explanations, new examples, etcetera.
36 | All MDX docs live in `docs/`.
37 |
38 | You can run the docs locally, see [¶ Site][site] below.
39 |
40 | ### Improve issues
41 |
42 | Some issues lack information, aren’t reproducible, or are just incorrect.
43 | You can help by trying to make them easier to resolve.
44 | Existing issues might benefit from your unique experience or opinions.
45 |
46 | ### Write code
47 |
48 | Code contributions are very welcome.
49 | It’s probably a good idea to first post a question or open an issue to report a
50 | bug or suggest a new feature before creating a pull request.
51 |
52 | ## Submitting an issue
53 |
54 | * The issue tracker is for issues.
55 | Use discussions for support
56 | * Search the issue tracker (including closed issues) before opening a new
57 | issue
58 | * Ensure you’re using the latest version of our packages
59 | * Use a clear and descriptive title
60 | * Include as much information as possible: steps to reproduce the issue,
61 | error message, version, operating system, etcetera
62 | * The more time you put into an issue, the better we will be able to help you
63 | * The best issue report is a failing test proving it
64 |
65 | ## Submitting a pull request
66 |
67 | * See [¶ Project][project] below for info on how the project is structured,
68 | how to test, and how to build the site
69 | * Non-trivial changes are often best discussed in an issue first, to prevent
70 | you from doing unnecessary work
71 | * For ambitious tasks, you should try to get your work in front of the
72 | community for feedback as soon as possible
73 | * New features should be accompanied by tests and documentation
74 | * Don’t include unrelated changes
75 | * Test before submitting code by running `npm test`
76 | * Write a convincing description of why we should land your pull request:
77 | it’s your job to convince us
78 |
79 | ## Project
80 |
81 | ### Structure
82 |
83 | MDX is a monorepo.
84 | All packages are in `packages/`.
85 | Documentation is in `docs/`.
86 |
87 | ### Tests
88 |
89 | To run the tests, first do `npm install`, then do `npm test`.
90 | This ensures everything is okay, from code style to unit tests to types.
91 |
92 | ### Site
93 |
94 | To build the site, first do `npm install`, then do `npm run docs`.
95 | This produces the website in `public/`.
96 |
97 | ### Release
98 |
99 | To release a new version, do:
100 |
101 | 1. update `version`s of packages with a patch, minor, or major (make sure to
102 | update dependency ranges on monorepo packages when needed):
103 | ```sh
104 | npm version minor --workspaces --no-git-tag-version
105 | ```
106 | 2. commit and tag using the version (without `v`) as the message:
107 | ```sh
108 | git commit --all --message 1.2.3 && git tag 1.2.3 && git push && git push --tags
109 | ```
110 | 3. release to the npm registry:
111 | ```sh
112 | npm publish --workspaces
113 | ```
114 | 4. add a changelog entry for the release on GitHub:
115 | ```sh
116 | open https://github.com/mdx-js/mdx/releases
117 | ```
118 |
119 | ## Resources
120 |
121 | * [Good first issues in the MDX repository](https://github.com/mdx-js/mdx/labels/good%20first%20issue%20👋)
122 | * [How to contribute to open source](https://opensource.guide/how-to-contribute/)
123 | * [Making your first contribution](https://medium.com/@vadimdemedes/making-your-first-contribution-de6576ddb190)
124 | * [Using pull requests](https://help.github.com/articles/about-pull-requests/)
125 | * [GitHub help](https://help.github.com)
126 |
127 | [coc]: https://github.com/mdx-js/.github/blob/main/code-of-conduct.md
128 |
129 | [project]: #project
130 |
131 | [site]: #site
132 |
133 | [sponsor]: /community/sponsor/
134 |
135 | [support]: /community/support/
136 |
--------------------------------------------------------------------------------
/docs/community/index.mdx:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * @import {Item} from '../_component/sort.js'
4 | */
5 |
6 | /**
7 | * @typedef Props
8 | * @property {Item} navigationTree
9 | */
10 | }
11 |
12 | import assert from 'node:assert/strict'
13 | import {NavigationGroup} from '../_component/nav.jsx'
14 |
15 | export const info = {
16 | author: [{name: 'MDX Contributors'}],
17 | modified: new Date('2024-07-04'),
18 | published: new Date('2021-11-01')
19 | }
20 | export const navSortSelf = 6
21 |
22 | # Community
23 |
24 | These pages explain how to contribute, get help, sponsor us, share your work,
25 | and some background information.
26 |
27 | {
28 | (function () {
29 | const navigationTree = props.navigationTree
30 | const category = navigationTree.children.find(function (item) {
31 | return item.name === '/community/'
32 | })
33 | assert(category)
34 |
35 | return (
36 |
39 | )
40 | })()
41 | }
42 |
--------------------------------------------------------------------------------
/docs/community/projects.mdx:
--------------------------------------------------------------------------------
1 | import {Note} from '../_component/note.jsx'
2 |
3 | export const info = {
4 | author: [
5 | {github: 'johno', name: 'John Otander'}
6 | ],
7 | modified: new Date('2021-11-01'),
8 | published: new Date('2018-08-11')
9 | }
10 | export const navSortSelf = 5
11 |
12 | # Projects
13 |
14 |
15 | **Note**: have another project built with MDX?
16 | Please send a PR to add it here!
17 |
18 |
19 | This page lists community projects using MDX.
20 |
21 | {/* more */}
22 |
23 | ## Apps
24 |
25 | * [demoboard][]: The simplest editor alive
26 |
27 | ## Libraries
28 |
29 | * [ok-mdx][]: Browser-based MDX editor
30 | * [docz][]: Documentation framework
31 | * [mdx-deck][]: MDX-based presentation decks
32 | * [mdx-docs][]: Next-based documentation framework
33 | * [mdx-paper][]: MDX-based research articles
34 | * [spectacle-boilerplate-mdx][]: Boilerplate that facilitates using MDX with
35 | Spectacle
36 | * [Charge][]: An opinionated, zero-config static site generator
37 | * [MDNEXT][]: An ecosystem of tools to get your NextJS + MDX projects blasting
38 | off
39 |
40 | ## Sites
41 |
42 | * This website!
43 | * [Prisma][]
44 | * [Max Stoiber’s Blog][mxstbr]
45 |
46 | ## Other related links
47 |
48 | * [awesome-mdx][]
49 | * [MDX: content for kings and princesses][mdx-fairy-tale]
50 |
51 | [awesome-mdx]: https://github.com/transitive-bullshit/awesome-mdx
52 |
53 | [charge]: https://charge.js.org
54 |
55 | [demoboard]: https://frontarm.com/demoboard
56 |
57 | [docz]: https://www.docz.site/
58 |
59 | [mdnext]: https://github.com/domitriusclark/mdnext
60 |
61 | [mdx-deck]: https://github.com/jxnblk/mdx-deck
62 |
63 | [mdx-docs]: https://github.com/jxnblk/mdx-docs
64 |
65 | [mdx-fairy-tale]: https://github.com/DeveloperMode/mdx-fairy-tale
66 |
67 | [mdx-paper]: https://github.com/hubgit/mdx-paper
68 |
69 | [mxstbr]: https://mxstbr.com
70 |
71 | [ok-mdx]: https://github.com/jxnblk/ok-mdx
72 |
73 | [prisma]: https://www.prisma.io/docs
74 |
75 | [spectacle-boilerplate-mdx]: https://github.com/FormidableLabs/spectacle-boilerplate-mdx
76 |
--------------------------------------------------------------------------------
/docs/community/support.mdx:
--------------------------------------------------------------------------------
1 | import {Note} from '../_component/note.jsx'
2 |
3 | export const info = {
4 | author: [
5 | {github: 'wooorm', name: 'Titus Wormer'}
6 | ],
7 | modified: new Date('2025-01-27'),
8 | published: new Date('2019-07-03')
9 | }
10 | export const navSortSelf = 1
11 |
12 | # Support
13 |
14 | This article explains where to get help with MDX.
15 | Please read through the following guidelines.
16 |
17 | {/* more */}
18 |
19 |
20 | **Important**: before participating in our community, please read our
21 | [code of conduct][coc].
22 | By interacting with this repository, organization, or community you agree to
23 | abide by its terms.
24 |
25 |
26 | ## Asking quality questions
27 |
28 | Questions can go to [GitHub Discussions][chat].
29 |
30 | Help us help you!
31 | Spend time framing questions and add links and resources.
32 | Spending the extra time up front can help save everyone time in the long run.
33 | Here are some tips:
34 |
35 | * Read through [§ Getting started][getting-started]
36 | * [Talk to a duck!][rubberduck]
37 | * Don’t fall for the [XY problem][xy]
38 | * Search to find out if a similar question has been asked
39 | * Try to define what you need help with:
40 | * Is there something in particular you want?
41 | * What problem are you encountering and what steps have you taken to try
42 | and fix it?
43 | * Is there a concept you don’t understand?
44 | * Provide sample code, such as a [CodeSandbox][cs] or video, if possible
45 | * Screenshots can help, but if there’s important text such as code or error
46 | messages in them, please also provide those as text
47 | * The more time you put into asking your question, the better we can help you
48 |
49 | [chat]: https://github.com/mdx-js/mdx/discussions
50 |
51 | [coc]: https://github.com/mdx-js/.github/blob/main/code-of-conduct.md
52 |
53 | [cs]: https://codesandbox.io
54 |
55 | [getting-started]: /docs/getting-started/
56 |
57 | [rubberduck]: https://rubberduckdebugging.com
58 |
59 | [xy]: https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem/66378#66378
60 |
--------------------------------------------------------------------------------
/docs/docs/index.mdx:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * @import {Item} from '../_component/sort.js'
4 | */
5 |
6 | /**
7 | * @typedef Props
8 | * @property {Item} navigationTree
9 | */
10 | }
11 |
12 | import assert from 'node:assert/strict'
13 | import {NavigationGroup} from '../_component/nav.jsx'
14 |
15 | export const info = {
16 | author: [{name: 'MDX Contributors'}],
17 | modified: new Date('2024-07-04'),
18 | published: new Date('2021-11-01')
19 | }
20 | export const navSortSelf = 1
21 |
22 | # Docs
23 |
24 | These docs explain the core concepts of MDX.
25 | How the format works, how to add it to your site, how to use MDX files, and how
26 | to extend them.
27 | Reading through these should give you a good understanding of MDX.
28 |
29 | {
30 | (function () {
31 | const navigationTree = props.navigationTree
32 | const category = navigationTree.children.find(function (item) {
33 | return item.name === '/docs/'
34 | })
35 | assert(category)
36 |
37 | return (
38 |
41 | )
42 | })()
43 | }
44 |
--------------------------------------------------------------------------------
/docs/guides/embed.mdx:
--------------------------------------------------------------------------------
1 | export const info = {
2 | author: [
3 | {github: 'wooorm', name: 'Titus Wormer'}
4 | ],
5 | modified: new Date('2025-01-27'),
6 | published: new Date('2021-10-06')
7 | }
8 | export const navSortSelf = 5
9 |
10 | # Embed
11 |
12 | This guide explores how to embed things like tweets, gists or codepens in
13 | markdown. {/* more */}
14 | MDX supports standard markdown syntax ([CommonMark][]).
15 | It does not support embeds by default.
16 |
17 | There are two ways to accomplish embeds: at compile time or at runtime.
18 | Doing it at compile time means the effort is spent upfront so that readers will
19 | have a fast experience as no requests have to be made on the client.
20 | Doing it at runtime gives more flexibility by moving the work to the client.
21 | This can result in a slow experience for readers though.
22 | It also depends on what framework you use (as in it’s specific to React, Preact,
23 | Vue, etc.)
24 |
25 | ## Embeds at compile time
26 |
27 | You can use [`@remark-embedder/core`][remark-embedder] by doing something like
28 | this:
29 |
30 | ```js path="example.js"
31 | import {compile} from '@mdx-js/mdx'
32 | // Note: `@remark-embedder` is currently using faux-esm.
33 | import fauxRemarkEmbedder from '@remark-embedder/core'
34 | import fauxOembedTransformer from '@remark-embedder/transformer-oembed'
35 |
36 | const remarkEmbedder = fauxRemarkEmbedder.default
37 | const oembedTransformer = fauxOembedTransformer.default
38 |
39 | const code = `
40 | Check out this video:
41 |
42 | https://www.youtube.com/watch?v=dQw4w9WgXcQ
43 | `
44 |
45 | console.log(
46 | String(
47 | await compile(code, {
48 | remarkPlugins: [
49 | [
50 | // @ts-expect-error: `remarkEmbedder` types are wrong.
51 | remarkEmbedder,
52 | {transformers: [oembedTransformer]}
53 | ]
54 | ]
55 | })
56 | )
57 | )
58 | ```
59 |
60 |
61 | Expand equivalent JSX
62 |
63 | ```jsx path="output.jsx"
64 | <>
65 |
Check out this video:
66 |
75 | >
76 | ```
77 |
78 |
79 | ## Embeds at run time
80 |
81 | You can use the React-specific [MDX Embed][mdx-embed] to embed things in MDX.
82 | Here is an example MDX file that uses a specific embed without `@mdx-js/react`:
83 |
84 | ```mdx path="example.mdx"
85 | import {CodePen} from 'mdx-embed'
86 |
87 | Here’s a codepen, and some other blog post text.
88 |
89 |
90 | ```
91 |
92 |
93 | Expand equivalent JSX
94 |
95 | ```jsx path="output.jsx"
96 | <>
97 |
Here’s a codepen, and some other blog post text.
98 |
99 | >
100 | ```
101 |
102 |
103 | If you don’t want to use explicit imports in MDX files:
104 |
105 | ```mdx path="example.mdx"
106 | Here’s a codepen, and some other blog post text.
107 |
108 |
109 | ```
110 |
111 | Then you can either pass all components:
112 |
113 | ```jsx path="example.jsx"
114 | import * as embeds from 'mdx-embed'
115 | import Example from './example.mdx' // Assumes an integration is used to compile MDX -> JS.
116 |
117 | console.log()
118 | ```
119 |
120 | Or, if you’ve installed and configured [`@mdx-js/react`][mdx-react], you can
121 | also use `MDXEmbedProvider`:
122 |
123 | ```jsx path="example.jsx"
124 | import {MDXEmbedProvider} from 'mdx-embed'
125 | import Example from './example.mdx' // Assumes an integration is used to compile MDX -> JS.
126 |
127 | console.log(
128 |
129 |
130 |
131 | )
132 | ```
133 |
134 | [commonmark]: https://spec.commonmark.org/current/
135 |
136 | [mdx-embed]: https://mdx-embed.netlify.app/
137 |
138 | [mdx-react]: /packages/react/
139 |
140 | [remark-embedder]: https://github.com/remark-embedder/core
141 |
--------------------------------------------------------------------------------
/docs/guides/frontmatter.mdx:
--------------------------------------------------------------------------------
1 | export const info = {
2 | author: [
3 | {github: 'wooorm', name: 'Titus Wormer'}
4 | ],
5 | modified: new Date('2025-01-27'),
6 | published: new Date('2021-10-06')
7 | }
8 | export const navSortSelf = 2
9 |
10 | # Frontmatter
11 |
12 | This guide explores how to support YAML frontmatter in MDX. {/* more */}
13 | MDX supports standard markdown syntax ([CommonMark][]).
14 | That means frontmatter is not supported by default.
15 |
16 | MDX comes with a powerful and dynamic alternative to frontmatter, namely ESM
17 | (`import`/`export`).
18 | These exports:
19 |
20 | ```mdx path="example.mdx"
21 | export const name = 'World'
22 | export const title = 'Hi, ' + name + '!'
23 |
24 | # {title}
25 | ```
26 |
27 | Can be used like so:
28 |
29 | ```js twoslash path="example.js"
30 | // @filename: types.d.ts
31 | declare module '*.mdx' {
32 | export {MDXContent as default} from 'mdx/types'
33 | export const name: string
34 | export const title: string
35 | }
36 | // @filename: example.js
37 | ///
38 | // ---cut---
39 | import * as Post from './example.mdx' // Assumes an integration is used to compile MDX -> JS.
40 |
41 | console.log(Post.title) // Prints 'Hi, World!'
42 | ```
43 |
44 | You might prefer frontmatter though, as it lets you define data that can be
45 | extracted from the file system *before* compiling.
46 | Say our MDX with frontmatter looked like this:
47 |
48 | ```mdx path="example.mdx"
49 | ---
50 | title: Hi, World!
51 | ---
52 |
53 | # Hi, World!
54 | ```
55 |
56 | Then without compiling or evaluating the metadata can be accessed like so:
57 |
58 | ```js twoslash path="example.js"
59 | ///
60 | // ---cut---
61 | import {read} from 'to-vfile'
62 | import {matter} from 'vfile-matter'
63 |
64 | const file = await read('example.mdx')
65 | matter(file)
66 |
67 | console.log(file.data.matter)
68 | ```
69 |
70 | Our compiler, `@mdx-js/mdx`, doesn’t understand YAML frontmatter by default but
71 | it can be enabled by using a remark plugin,
72 | [`remark-frontmatter`][remark-frontmatter]:
73 |
74 | ```js twoslash path="example.js"
75 | // @filename: example.js
76 | ///
77 | // ---cut---
78 | import fs from 'node:fs/promises'
79 | import {compile} from '@mdx-js/mdx'
80 | import remarkFrontmatter from 'remark-frontmatter'
81 |
82 | const file = await compile(await fs.readFile('example.mdx'), {
83 | remarkPlugins: [remarkFrontmatter]
84 | })
85 |
86 | console.log(file)
87 | ```
88 |
89 | Now it “works”.
90 | The frontmatter is not rendered as if it was markdown.
91 | But the data embedded in the frontmatter isn’t available from *inside* the MDX.
92 | What if we wanted that too?
93 | Like so:
94 |
95 | ```mdx path="example.mdx"
96 | ---
97 | title: Hi, World!
98 | ---
99 |
100 | # {title}
101 | ```
102 |
103 | That’s exactly what the remark plugin
104 | [`remark-mdx-frontmatter`][remark-mdx-frontmatter] does.
105 |
106 | That plugin, like all remark plugins, can be passed as
107 | [`remarkPlugins` in `ProcessorOptions`][processor-options].
108 | More info on plugins is available in [§ Extending MDX][extend]
109 |
110 | [commonmark]: https://spec.commonmark.org/current/
111 |
112 | [extend]: /docs/extending-mdx/
113 |
114 | [processor-options]: /packages/mdx/#processoroptions
115 |
116 | [remark-frontmatter]: https://github.com/remarkjs/remark-frontmatter
117 |
118 | [remark-mdx-frontmatter]: https://github.com/remcohaszing/remark-mdx-frontmatter
119 |
--------------------------------------------------------------------------------
/docs/guides/gfm.mdx:
--------------------------------------------------------------------------------
1 | export const info = {
2 | author: [
3 | {github: 'wooorm', name: 'Titus Wormer'}
4 | ],
5 | modified: new Date('2025-01-27'),
6 | published: new Date('2021-10-06')
7 | }
8 | export const navSortSelf = 1
9 |
10 | # GitHub flavored markdown (GFM)
11 |
12 | This guide explores how to support GFM features such as autolink literals,
13 | footnotes, strikethrough, tables, and task lists. {/* more */}
14 | MDX supports standard markdown syntax ([CommonMark][]).
15 | That means [GitHub flavored markdown (GFM)][gfm] extensions are not supported by
16 | default.
17 | They can be enabled by using a remark plugin: [`remark-gfm`][remark-gfm].
18 | That plugin, like all remark plugins, can be passed in [`remarkPlugins` in
19 | `ProcessorOptions`][processor-options].
20 | More info on plugins is available in [§ Extending MDX][extend]
21 |
22 | Say we have an MDX file like this:
23 |
24 | ```mdx path="example.mdx"
25 | # GFM
26 |
27 | ## Autolink literals
28 |
29 | www.example.com, https://example.com, and contact@example.com.
30 |
31 | ## Footnote
32 |
33 | A note[^1]
34 |
35 | [^1]: Big note.
36 |
37 | ## Strikethrough
38 |
39 | ~one~ or ~~two~~ tildes.
40 |
41 | ## Table
42 |
43 | | a | b | c | d |
44 | | - | :- | -: | :-: |
45 |
46 | ## Tasklist
47 |
48 | * [ ] to do
49 | * [x] done
50 | ```
51 |
52 | The above MDX with GFM can be transformed with the following module:
53 |
54 | ```js twoslash path="example.js"
55 | // @filename: example.js
56 | ///
57 | // ---cut---
58 | import fs from 'node:fs/promises'
59 | import {compile} from '@mdx-js/mdx'
60 | import remarkGfm from 'remark-gfm'
61 |
62 | console.log(
63 | String(
64 | await compile(await fs.readFile('example.mdx'), {remarkPlugins: [remarkGfm]})
65 | )
66 | )
67 | ```
68 |
69 |
70 | Expand equivalent JSX
71 |
72 | ```jsx path="output.jsx"
73 | <>
74 |
138 |
139 |
140 | >
141 | ```
142 |
143 |
144 | [commonmark]: https://spec.commonmark.org/current/
145 |
146 | [extend]: /docs/extending-mdx/
147 |
148 | [gfm]: https://github.github.com/gfm/
149 |
150 | [processor-options]: /packages/mdx/#processoroptions
151 |
152 | [remark-gfm]: https://github.com/remarkjs/remark-gfm
153 |
--------------------------------------------------------------------------------
/docs/guides/index.mdx:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * @import {Item} from '../_component/sort.js'
4 | */
5 |
6 | /**
7 | * @typedef Props
8 | * @property {Item} navigationTree
9 | */
10 | }
11 |
12 | import assert from 'node:assert/strict'
13 | import {NavigationGroup} from '../_component/nav.jsx'
14 |
15 | export const info = {
16 | author: [{name: 'MDX Contributors'}],
17 | modified: new Date('2024-07-04'),
18 | published: new Date('2021-11-01')
19 | }
20 | export const navSortSelf = 2
21 |
22 | # Guides
23 |
24 | These guides explain how to accomplish several common use cases and patterns
25 | around MDX.
26 |
27 | {
28 | (function () {
29 | const navigationTree = props.navigationTree
30 | const category = navigationTree.children.find(function (item) {
31 | return item.name === '/guides/'
32 | })
33 | assert(category)
34 |
35 | return (
36 |
39 | )
40 | })()
41 | }
42 |
--------------------------------------------------------------------------------
/docs/guides/injecting-components.mdx:
--------------------------------------------------------------------------------
1 | export const info = {
2 | author: [
3 | {github: 'wooorm', name: 'Titus Wormer'}
4 | ],
5 | modified: new Date('2024-07-04'),
6 | published: new Date('2023-10-24')
7 | }
8 | export const navSortSelf = 7
9 |
10 | # Injecting components
11 |
12 | This guide shows how to inject arbitrary components into MDX when it
13 | runs. {/* more */}
14 | It shows how the underlying features used by our providers (`@mdx-js/react`,
15 | `@mdx-js/preact`) and the [`mdx-components.tsx`][next-mdx-components] file
16 | supported by Next.js work,
17 | and how you can take advantage of that functionality yourself.
18 |
19 | In many cases you do not need this,
20 | as you can pass components to MDX:
21 |
22 | ```mdx path="example.mdx"
23 | # Hello **
24 | ```
25 |
26 | You can pass `Planet` and say a component used instead of the `h1`:
27 |
28 | ```jsx twoslash path="example.jsx"
29 | // @filename: types.d.ts
30 | import type {} from 'mdx'
31 | // @filename: example.jsx
32 | ///
33 | /* @jsxImportSource react */
34 | // ---cut---
35 | import Example from './example.mdx' // Assumes an integration is used to compile MDX -> JS.
36 |
37 | console.log(
38 |
45 | }
46 | }}
47 | />
48 | )
49 | ```
50 |
51 | When you find yourself passing that `components` prop around a lot,
52 | you might want to look at an alternative.
53 | You might reach for our context based providers (`@mdx-js/react`,
54 | `@mdx-js/preact`),
55 | but context has performance downsides and context doesn’t always work (such as
56 | in RSC).
57 |
58 | But first,
59 | how does component passing work?
60 | That can be illustrated by looking at the code generated by MDX for the above
61 | `example.mdx`.
62 | Here is a diff that shows what the example normally compiles to and what
63 | changes when `providerImportSource: 'xxx'` is passed:
64 |
65 | ```diff
66 | @@ -1,7 +1,13 @@
67 | import {jsx as _jsx, jsxs as _jsxs} from 'react/jsx-runtime'
68 | +import {useMDXComponents as _provideComponents} from 'xxx'
69 |
70 | function _createMdxContent(props) {
71 | - const _components = {em: 'em', h1: 'h1', ...props.components}
72 | + const _components = {
73 | + em: 'em',
74 | + h1: 'h1',
75 | + ..._provideComponents(),
76 | + ...props.components
77 | + }
78 | const {Planet} = _components
79 | if (!Planet) _missingMdxReference('Planet', true)
80 | return _jsxs(_components.h1, {
81 | @@ -10,7 +16,7 @@ function _createMdxContent(props) {
82 | }
83 |
84 | export default function MDXContent(props = {}) {
85 | - const {wrapper: MDXLayout} = props.components || {}
86 | + const {wrapper: MDXLayout} = {..._provideComponents(), ...props.components}
87 | return MDXLayout
88 | ? _jsx(MDXLayout, {...props, children: _jsx(_createMdxContent, {...props})})
89 | : _createMdxContent(props)
90 | ```
91 |
92 | Observe that components have defaults (such as that `h1` will use `'h1'`) and
93 | that components are taken from `props.components`.
94 | What changes is an added call to `_provideComponents`,
95 | which refers to an `useMDXComponents` export from the module we specified
96 | (`xxx`).
97 |
98 | We can use this interface to inject components from a file.
99 | In that file,
100 | we need a `useMDXComponents` function that returns our components.
101 |
102 | ```jsx twoslash path="mdx-components.js"
103 | // @filename: mdx-components.jsx
104 | /* @jsxImportSource react */
105 | // ---cut---
106 | /**
107 | * @import {MDXComponents} from 'mdx/types.js'
108 | */
109 |
110 | /** @returns {MDXComponents} */
111 | export function useMDXComponents() {
112 | return {
113 | Planet() {
114 | return 'Pluto'
115 | },
116 | h1(properties) {
117 | return
118 | }
119 | }
120 | }
121 | ```
122 |
123 | And now passing a file path or URL to that file as `providerImportSource`,
124 | such as with `import.meta.resolve('./mdx-components.js')`:
125 |
126 | ```diff
127 | @@ -1,5 +1,5 @@
128 | import {jsx as _jsx, jsxs as _jsxs} from 'react/jsx-runtime'
129 | -import {useMDXComponents as _provideComponents} from 'xxx'
130 | +import {useMDXComponents as _provideComponents} from 'file:///Users/tilde/…/mdx-components.js'
131 | ```
132 |
133 | Now our locally defined components will be used in all MDX files!
134 |
135 | [next-mdx-components]: https://nextjs.org/docs/pages/building-your-application/configuring/mdx
136 |
--------------------------------------------------------------------------------
/docs/guides/math.mdx:
--------------------------------------------------------------------------------
1 | import {Note} from '../_component/note.jsx'
2 |
3 | export const info = {
4 | author: [
5 | {github: 'wooorm', name: 'Titus Wormer'}
6 | ],
7 | modified: new Date('2025-01-27'),
8 | published: new Date('2021-10-06')
9 | }
10 | export const navSortSelf = 3
11 |
12 | # Math
13 |
14 | This guide explores how to support math (LaTeX) in MDX. {/* more */}
15 | MDX supports standard markdown syntax ([CommonMark][]).
16 | That means math is not supported by default.
17 | Math can be enabled by using a remark plugin: [`remark-math`][remark-math],
18 | combined with a rehype plugin: either
19 | [`rehype-katex`][rehype-katex] (KaTeX) or [`rehype-mathjax`][rehype-mathjax]
20 | (MathJax).
21 | Like other remark and rehype plugins, they can be passed in [`remarkPlugins`
22 | and `rehypePlugins`, respectively, in `ProcessorOptions`][processor-options].
23 | More info on plugins is available in [§ Extending MDX][extend]
24 |
25 | Say we have an MDX file like this:
26 |
27 | ```mdx path="example.mdx"
28 | # $$\sqrt{a^2 + b^2}$$
29 | ```
30 |
31 | The above MDX with math can be transformed with the following module:
32 |
33 | ```js twoslash path="example.js"
34 | // @filename: example.js
35 | ///
36 | // ---cut---
37 | import fs from 'node:fs/promises'
38 | import {compile} from '@mdx-js/mdx'
39 | import rehypeKatex from 'rehype-katex'
40 | import remarkMath from 'remark-math'
41 |
42 | console.log(
43 | String(
44 | await compile(await fs.readFile('example.mdx'), {
45 | rehypePlugins: [rehypeKatex],
46 | remarkPlugins: [remarkMath]
47 | })
48 | )
49 | )
50 | ```
51 |
52 |
53 | Expand equivalent JSX
54 |
55 | ```jsx path="output.jsx"
56 | <>
57 |
58 |
59 |
60 |
61 |
62 |
63 | …
64 |
65 |
66 |
67 | >
68 | ```
69 |
70 |
71 |
72 | **Important**: if you chose `rehype-katex`, you should also use `katex.css`
73 | somewhere on the page to style math properly.
74 | At the time of writing, the last version is:
75 |
76 | ```html
77 |
78 |
79 | ```
80 |
81 | To get the latest link to the stylesheet, go to [`katex docs`][katex-browser].
82 |
83 | {/* to do: once in a while, get the latest. */}
84 |
85 |
86 |
87 | **Note:** see also
88 | [`remark-mdx-math-enhanced`](https://github.com/goodproblems/remark-mdx-math-enhanced),
89 | which you can use to support JavaScript expressions inside of math (such as to
90 | access properties or to make calculations)
91 |
92 |
93 | [commonmark]: https://spec.commonmark.org/current/
94 |
95 | [extend]: /docs/extending-mdx/
96 |
97 | [katex-browser]: https://katex.org/docs/browser#loading-as-global
98 |
99 | [processor-options]: /packages/mdx/#processoroptions
100 |
101 | [rehype-katex]: https://github.com/remarkjs/remark-math/tree/main/packages/rehype-katex
102 |
103 | [rehype-mathjax]: https://github.com/remarkjs/remark-math/tree/main/packages/rehype-mathjax
104 |
105 | [remark-math]: https://github.com/remarkjs/remark-math/tree/main/packages/remark-math
106 |
--------------------------------------------------------------------------------
/docs/guides/mdx-on-demand.mdx:
--------------------------------------------------------------------------------
1 | import {Note} from '../_component/note.jsx'
2 |
3 | export const info = {
4 | author: [
5 | {github: 'wooorm', name: 'Titus Wormer'}
6 | ],
7 | modified: new Date('2025-01-27'),
8 | published: new Date('2021-11-13')
9 | }
10 | export const navSortSelf = 6
11 |
12 | # MDX on demand
13 |
14 | This guide shows how to use `@mdx-js/mdx` to compile MDX on the server and run
15 | the result on clients. {/* more */}
16 | Some frameworks, such as Next.js and Remix, make it easy to split work between
17 | servers and clients.
18 | Using that it’s possible to for example do most of the work on demand on the
19 | server instead of at build time, then pass the resulting data to clients, where
20 | they finally use it.
21 |
22 | This is similar to what people sometimes use [`mdx-bundler`][mdx-bundler] or
23 | [`next-mdx-remote`][next-mdx-remote] for, but MDX also supports it.
24 |
25 | ## Quick example
26 |
27 | On the server:
28 |
29 | ```js twoslash path="server.js"
30 | import {compile} from '@mdx-js/mdx'
31 |
32 | const code = String(await compile('# hi', {
33 | outputFormat: 'function-body',
34 | /* …otherOptions */
35 | }))
36 | // To do: send `code` to the client somehow.
37 | ```
38 |
39 | On the client:
40 |
41 | ```js twoslash path="client.js"
42 | import {run} from '@mdx-js/mdx'
43 | import * as runtime from 'react/jsx-runtime'
44 |
45 | const code = '' // To do: get `code` from server somehow.
46 |
47 | const {default: Content} = await run(code, {...runtime, baseUrl: import.meta.url})
48 | ```
49 |
50 | `Content` is now an `MDXContent` component that you can use like normal in your
51 | framework (see [§ Using MDX][use]).
52 |
53 | More information is available in the API docs of `@mdx-js/mdx` for
54 | [`compile`][compile] and [`run`][run].
55 | For other use cases, you can also use [`evaluate`][eval], which both compiles
56 | and runs in one.
57 |
58 |
59 | **Note**: MDX is not a bundler (esbuild, webpack, and Rollup are bundlers):
60 | you can’t import other code from the server within the string of MDX and get a
61 | nicely minified bundle out or so.
62 |
63 |
64 | ## Next.js example
65 |
66 | Some frameworks let you write the server and client code in one file, such as
67 | Next.
68 |
69 | ```js twoslash path="pages/hello.js"
70 | /**
71 | * @import {MDXModule} from 'mdx/types.js'
72 | * @import {Dispatch, ReactElement, SetStateAction} from 'react'
73 | */
74 |
75 | import {compile, run} from '@mdx-js/mdx'
76 | import {Fragment, useEffect, useState} from 'react'
77 | import * as runtime from 'react/jsx-runtime'
78 |
79 | /**
80 | * @param {{code: string}} props
81 | * @returns {ReactElement}
82 | */
83 | export default function Page({code}) {
84 | /** @type {[MDXModule | undefined, Dispatch>]} */
85 | const [mdxModule, setMdxModule] = useState()
86 | const Content = mdxModule ? mdxModule.default : Fragment
87 |
88 | useEffect(
89 | function () {
90 | ;(async function () {
91 | setMdxModule(await run(code, {...runtime, baseUrl: import.meta.url}))
92 | })()
93 | },
94 | [code]
95 | )
96 |
97 | return
98 | }
99 |
100 | export async function getStaticProps() {
101 | const code = String(
102 | await compile('# hi', {
103 | outputFormat: 'function-body'
104 | /* …otherOptions */
105 | })
106 | )
107 | return {props: {code}}
108 | }
109 | ```
110 |
111 | [compile]: /packages/mdx/#compilefile-options
112 |
113 | [eval]: /packages/mdx/#evaluatefile-options
114 |
115 | [mdx-bundler]: https://github.com/kentcdodds/mdx-bundler
116 |
117 | [next-mdx-remote]: https://github.com/hashicorp/next-mdx-remote
118 |
119 | [run]: /packages/mdx/#runcode-options
120 |
121 | [use]: /docs/using-mdx/
122 |
--------------------------------------------------------------------------------
/docs/index.mdx:
--------------------------------------------------------------------------------
1 | import {Chart} from './_component/snowfall.jsx'
2 |
3 | export {Home as default} from './_component/home.jsx'
4 | export const info = {
5 | author: [
6 | {github: 'johno', name: 'John Otander'},
7 | {github: 'wooorm', name: 'Titus Wormer'}
8 | ],
9 | modified: new Date('2025-01-27'),
10 | published: new Date('2017-12-23'),
11 | schemaOrg: {
12 | "@context": "https://schema.org",
13 | "@type": "SoftwareApplication",
14 | "additionalType": "ComputerLanguage",
15 | "applicationCategory": "DeveloperApplication",
16 | "description": "an authorable format for writing JSX in markdown documents",
17 | "name": "MDX",
18 | "offers": {
19 | "@type": "Offer",
20 | "price": "0.00",
21 | "priceCurrency": "USD"
22 | },
23 | "operatingSystem": "Windows, MacOS, Linux",
24 | "sameAs": [
25 | "https://www.wikidata.org/wiki/Q95971592",
26 | "https://www.wikidata.org/wiki/Q27966906",
27 | "https://www.wikidata.org/wiki/Q95961071",
28 | "https://en.wikipedia.org/wiki/MDX_(markup_language)",
29 | "https://github.com/mdx-js/mdx"
30 | ],
31 | "url": "https://mdxjs.com"
32 | }
33 | }
34 | export const year = 2023
35 |
36 | {/* lint disable heading-style */}
37 |
38 | Markdown for the\
39 | **component era**
40 | =================
41 |
42 | MDX lets you use JSX in your markdown content.
43 | You can import components, such as interactive charts or alerts, and embed them
44 | within your content.
45 | This makes writing long-form content with components a blast. {/* more */}
46 | 🚀
47 | [Continue reading »][what]
48 |
49 |
50 | ## New: MDX 3!
51 |
52 | A small major this time, nothing big, which is also nice sometimes!
53 | This mainly drops support for old Node (use 16 or later), adds modern ES2024
54 | support in MDX, supports `await` in MDX (if your framework does too), and
55 | removes several deprecated options.
56 |
57 | [Continue reading »][v3]
58 |
59 |
60 | ## What does MDX do?
61 |
62 |
63 |
64 | You write markdown with embedded components through JSX:
65 |
66 | ```mdx path="example.mdx"
67 | import {Chart} from './snowfall.js'
68 | export const year = 2023
69 |
70 | # Last year’s snowfall
71 |
72 | In {year}, the snowfall was above average.
73 | It was followed by a warm spring which caused
74 | flood conditions in many of the nearby rivers.
75 |
76 |
77 | ```
78 |
79 |
80 |
81 | It gets compiled to JavaScript that you can use in any framework that
82 | supports JSX:
83 |
84 | {/* lint disable no-multiple-toplevel-headings */}
85 |
86 |
87 | # Last year’s snowfall
88 |
89 | In {year}, the snowfall was above average.
90 | It was followed by a warm spring which caused flood conditions in many of
91 | the nearby rivers.
92 |
93 |
94 |
99 |
100 | We made an interactive playground where you can try MDX out and see what it
101 | turns into.
102 | [Play »][playground]
103 |
104 | ## Get started
105 |
106 | There are integrations for most bundlers, frameworks, and editors.
107 | Whether you build with Docusaurus, Next.js, or Vite.
108 | You prefer Rollup, esbuild, or webpack.
109 | You’re using React, Preact, or Vue.
110 | [Get started »][getting-started]
111 |
112 | ## MDX in short
113 |
114 |
115 | * ❤️ **Powerful**: MDX blends markdown and JSX syntax to fit perfectly in
116 | JSX-based projects
117 | * 💻 **Everything is a component**: Use existing components in your
118 | MDX and import other MDX files as components
119 | * 🔧 **Customizable**: Decide which component is rendered for each markdown
120 | construct (`{h1: MyHeading}`)
121 | * 📚 **Markdown-based**: The simplicity and elegance of markdown remains,
122 | you use JSX only when you want to
123 | * 🔥 **Blazingly blazing fast**: MDX has no runtime, all compilation occurs
124 | during the build stage
125 |
126 |
127 | > lol mdx is so good
128 | >
129 | > — **@dan\_abramov**
130 |
131 | [getting-started]: /docs/getting-started/
132 |
133 | [playground]: /playground/
134 |
135 | [v3]: /blog/v3/
136 |
137 | [what]: /docs/what-is-mdx/
138 |
--------------------------------------------------------------------------------
/docs/migrating/v1.mdx:
--------------------------------------------------------------------------------
1 | import {Note} from '../_component/note.jsx'
2 |
3 | export const info = {
4 | author: [
5 | {github: 'johno', name: 'John Otander'}
6 | ],
7 | modified: new Date('2025-01-27'),
8 | published: new Date('2019-04-04')
9 | }
10 | export const navExclude = true
11 |
12 |
13 | **Note**: This is an old migration guide.
14 | See [§ Migrating from v1 to v2](/migrating/v2/).
15 | The below is kept as is for historical purposes.
16 |
17 |
18 | # Migrating from v0 to v1
19 |
20 | Unfortunately, we’ve had to introduce a few breaking changes, so we’ve written a
21 | migration guide.
22 | In order to ensure as seamless of an upgrade as possible we plan on supporting
23 | v0 for the next 12 months so there’s not a huge rush to update (though we’d
24 | love for you to ASAP) 📆.
25 |
26 | ## ⚠️ Breaking changes
27 |
28 | * [🚨 `@mdx-js/tag` is replaced by `@mdx-js/react` and an `mdx`
29 | pragma](#pragma) 🚨
30 | * [MDXProvider now merges component contexts when nested](#mdxprovider)
31 | * [React support now requires `>= 16.8` in `@mdx-js/react`](#react)
32 |
33 | ## Pragma
34 |
35 | For v1 you need to remove `@mdx-js/tag` and replace it with `@mdx-js/react`:
36 |
37 | ```sh
38 | yarn remove @mdx-js/tag
39 | yarn add @mdx-js/react
40 | ```
41 |
42 | ### What’s different?
43 |
44 | The MDXTag implementation has been removed with a custom pragma implementation
45 | inspired by
46 | [Emotion](https://emotion.sh/docs/css-prop#jsx-pragma).
47 | This ensures that transpiled JSX is more readable and that JSX blocks use the
48 | same component as its markdown counterpart.
49 | It also allows MDXProvider to provide global component scope like a `Youtube`
50 | component.
51 |
52 | The pragma implementation will also cause JSX HTML elements to be rendered with
53 | the component mapping passed to MDXProvider.
54 | So, the following will result in two identically rendered `h1`s:
55 |
56 | ```mdx
57 | # Hello, world!
58 |
59 |
Hello, world!
60 | ```
61 |
62 | [See the blog post for further reading](/blog/custom-pragma/)
63 |
64 | ## MDXProvider
65 |
66 | This shouldn’t affect most usecases, however if you’re nesting component
67 | contexts and rely on them not being merged you will have to use the functional
68 | form which allows you to customize the merge.
69 | By ignoring outer context components and returning a new component mapping, you
70 | will restore the old behavior:
71 |
72 | ```tsx
73 |
74 | newComponents}>
75 | {children}
76 |
77 |
78 | ```
79 |
80 | ## React
81 |
82 | Before upgrading to `@mdx-js/mdx@1`, update your website/application to
83 | `react@16.8 react-dom@16.8` and ensure it works as expected.
84 | Then upgrade to v1.
85 |
--------------------------------------------------------------------------------
/docs/migrating/v3.mdx:
--------------------------------------------------------------------------------
1 | export const info = {
2 | author: [
3 | {github: 'wooorm', name: 'Titus Wormer'}
4 | ],
5 | modified: new Date('2023-10-24'),
6 | published: new Date('2023-10-24')
7 | }
8 | export const navExclude = true
9 |
10 | # Migrating from v2 to v3
11 |
12 | A couple small changes this time around.
13 | For most folks, updating Node.js and plugins is all that’s needed!
14 |
15 | ## Contents
16 |
17 | * [Update Node.js](#update-nodejs)
18 | * [Update plugins](#update-plugins)
19 | * [Pass `baseUrl` to `evaluate`, `run`](#pass-baseurl-to-evaluate-run)
20 | * [Use the automatic JSX runtime](#use-the-automatic-jsx-runtime)
21 | * [Replace `MDXContext`, `withMDXComponents` with `useMDXComponents`](#replace-mdxcontext-withmdxcomponents-with-usemdxcomponents)
22 | * [Replace `@mdx-js/register` with `@mdx-js/node-loader`](#replace-mdx-jsregister-with-mdx-jsnode-loader)
23 |
24 | ## Update Node.js
25 |
26 | If you’re still on old Node, it’s time to update.
27 | Use at least Node 16.
28 |
29 | ## Update plugins
30 |
31 | If you use rehype and remark plugins: update.
32 |
33 | Most of them remain working between versions.
34 | Particularly if you use TypeScript, there was a breaking internal change in the
35 | types, which is now supported here.
36 | There were also some small internal changes in how the parser works, which
37 | affect `remark-gfm` and `remark-math`.
38 |
39 | ## Pass `baseUrl` to `evaluate`, `run`
40 |
41 | If you use `evaluate` or `run` (or `outputFormat: 'function-body'`), you should
42 | pass the `baseUrl` option.
43 | Likely set to `import.meta.url`.
44 |
45 | If MDX content uses `export` statements, `import` expressions/statements,
46 | or `import.meta.url`, we compile to code that works, but it needs to know
47 | where the code runs: you need to pass where you are.
48 |
49 | You will get a runtime error if these features are used in MDX without
50 | `baseUrl`.
51 |
52 | If you passed the `useDynamicImport` option before, remove it, the behavior
53 | is now the default.
54 |
55 | ```tsx
56 | import * as runtime from 'react/jsx-runtime'
57 |
58 | const result = await run('# hi', {...runtime, baseUrl: import.meta.url})
59 | ```
60 |
61 | ## Use the automatic JSX runtime
62 |
63 | If you use the classic runtime, switch to the automatic runtime.
64 | Classic is still supported but you will now see a warning if you use the
65 | classic JSX runtime.
66 |
67 | The classic runtime can still be nice in other places, but it causes potential
68 | problems in MDX.
69 | If you specify `jsxRuntime: 'classic'` (and `pragma`, `pragmaFrag`,
70 | `pragmaImportSource`), consider switching to `automatic`.
71 | All major frameworks support the automatic runtime.
72 | Support for the classic runtime will likely be removed next major.
73 |
74 | ## Replace `MDXContext`, `withMDXComponents` with `useMDXComponents`
75 |
76 | If you use the deprecated symbols `MDXContext` and `withMDXComponents`, use
77 | `useMDXComponents` instead.
78 |
79 | Reminder: you probably don’t need the context based `@mdx-js/react` or
80 | `@mdx-js/preact` packages.
81 |
82 | ## Replace `@mdx-js/register` with `@mdx-js/node-loader`
83 |
84 | If you use the deprecated package `@mdx-js/register`, use `@mdx-js/node-loader` instead.
85 |
--------------------------------------------------------------------------------
/docs/packages/esbuild.md:
--------------------------------------------------------------------------------
1 | ../../packages/esbuild/readme.md
--------------------------------------------------------------------------------
/docs/packages/index.mdx:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * @import {Item} from '../_component/sort.js'
4 | */
5 |
6 | /**
7 | * @typedef Props
8 | * @property {Item} navigationTree
9 | */
10 | }
11 |
12 | import assert from 'node:assert/strict'
13 | import {NavigationGroup} from '../_component/nav.jsx'
14 |
15 | export const info = {
16 | author: [{name: 'MDX Contributors'}],
17 | modified: new Date('2024-07-04'),
18 | published: new Date('2021-11-01')
19 | }
20 | export const navSortSelf = 3
21 |
22 | # Packages
23 |
24 | This index lists the packages that are maintained in our monorepo.
25 | They include `@mdx-js/mdx`, which is our core compiler; `remark-mdx`, which is
26 | the remark plugin to support the MDX syntax; and several integrations with
27 | bundlers and frontend frameworks.
28 |
29 | {
30 | (function () {
31 | const navigationTree = props.navigationTree
32 | const category = navigationTree.children.find(function (item) {
33 | return item.name === '/packages/'
34 | })
35 | assert(category)
36 |
37 | return (
38 |
41 | )
42 | })()
43 | }
44 |
--------------------------------------------------------------------------------
/docs/packages/loader.md:
--------------------------------------------------------------------------------
1 | ../../packages/loader/readme.md
--------------------------------------------------------------------------------
/docs/packages/mdx.md:
--------------------------------------------------------------------------------
1 | ../../packages/mdx/readme.md
--------------------------------------------------------------------------------
/docs/packages/node-loader.md:
--------------------------------------------------------------------------------
1 | ../../packages/node-loader/readme.md
--------------------------------------------------------------------------------
/docs/packages/preact.md:
--------------------------------------------------------------------------------
1 | ../../packages/preact/readme.md
--------------------------------------------------------------------------------
/docs/packages/react.md:
--------------------------------------------------------------------------------
1 | ../../packages/react/readme.md
--------------------------------------------------------------------------------
/docs/packages/remark-mdx.md:
--------------------------------------------------------------------------------
1 | ../../packages/remark-mdx/readme.md
--------------------------------------------------------------------------------
/docs/packages/rollup.md:
--------------------------------------------------------------------------------
1 | ../../packages/rollup/readme.md
--------------------------------------------------------------------------------
/docs/packages/vue.md:
--------------------------------------------------------------------------------
1 | ../../packages/vue/readme.md
--------------------------------------------------------------------------------
/docs/playground.mdx:
--------------------------------------------------------------------------------
1 | export const info = {
2 | author: [
3 | {github: 'johno', name: 'John Otander'},
4 | {github: 'wooorm', name: 'Titus Wormer'}
5 | ],
6 | modified: new Date('2023-12-24'),
7 | published: new Date('2021-09-13')
8 | }
9 | export const navSortSelf = 5
10 |
11 | # Playground
12 |
13 | Here you can play with the MDX format.
14 | Write some MDX to find out what it turns into. {/* more */}
15 | You can see the rendered result, the generated code, and the intermediary
16 | ASTs.
17 | This can be helpful for debugging or exploring.
18 | To read about how the MDX format works, we recommend that you start with
19 | [§ What is MDX][what].
20 |
21 |
` (so it has no knowledge of “HTML”).
12 | *
13 | * It also marks JSX as being explicitly JSX, so when a user passes a `h1`
14 | * component, it is used for `# heading` but not for `
heading
`.
15 | *
16 | * @returns
17 | * Transform.
18 | */
19 | export function remarkMarkAndUnravel() {
20 | /**
21 | * @param {Root} tree
22 | * Tree.
23 | * @returns {undefined}
24 | * Nothing.
25 | */
26 | return function (tree) {
27 | visit(tree, function (node, index, parent) {
28 | let offset = -1
29 | let all = true
30 | let oneOrMore = false
31 |
32 | if (parent && typeof index === 'number' && node.type === 'paragraph') {
33 | const children = node.children
34 |
35 | while (++offset < children.length) {
36 | const child = children[offset]
37 |
38 | if (
39 | child.type === 'mdxJsxTextElement' ||
40 | child.type === 'mdxTextExpression'
41 | ) {
42 | oneOrMore = true
43 | } else if (
44 | child.type === 'text' &&
45 | collapseWhiteSpace(child.value, {style: 'html', trim: true}) === ''
46 | ) {
47 | // Empty.
48 | } else {
49 | all = false
50 | break
51 | }
52 | }
53 |
54 | if (all && oneOrMore) {
55 | offset = -1
56 |
57 | /** @type {Array} */
58 | const newChildren = []
59 |
60 | while (++offset < children.length) {
61 | const child = children[offset]
62 |
63 | if (child.type === 'mdxJsxTextElement') {
64 | // @ts-expect-error: mutate because it is faster; content model is fine.
65 | child.type = 'mdxJsxFlowElement'
66 | }
67 |
68 | if (child.type === 'mdxTextExpression') {
69 | // @ts-expect-error: mutate because it is faster; content model is fine.
70 | child.type = 'mdxFlowExpression'
71 | }
72 |
73 | if (
74 | child.type === 'text' &&
75 | /^[\t\r\n ]+$/.test(String(child.value))
76 | ) {
77 | // Empty.
78 | } else {
79 | newChildren.push(child)
80 | }
81 | }
82 |
83 | parent.children.splice(index, 1, ...newChildren)
84 | return index
85 | }
86 | }
87 |
88 | if (
89 | node.type === 'mdxJsxFlowElement' ||
90 | node.type === 'mdxJsxTextElement'
91 | ) {
92 | const data = node.data || (node.data = {})
93 | data._mdxExplicitJsx = true
94 | }
95 |
96 | if (
97 | (node.type === 'mdxFlowExpression' ||
98 | node.type === 'mdxTextExpression' ||
99 | node.type === 'mdxjsEsm') &&
100 | node.data &&
101 | node.data.estree
102 | ) {
103 | walk(node.data.estree, {
104 | enter(node) {
105 | if (node.type === 'JSXElement') {
106 | const data = node.data || (node.data = {})
107 | data._mdxExplicitJsx = true
108 | }
109 | }
110 | })
111 | }
112 | })
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/packages/mdx/lib/run.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {MDXModule} from 'mdx/types.js'
3 | * @import {RunOptions} from './util/resolve-evaluate-options.js'
4 | */
5 |
6 | /** @type {new (code: string, ...args: Array) => Function} **/
7 | const AsyncFunction = Object.getPrototypeOf(run).constructor
8 |
9 | /**
10 | * Run code compiled with `outputFormat: 'function-body'`.
11 | *
12 | * > ☢️ **Danger**: this `eval`s JavaScript.
13 | *
14 | * @param {{toString(): string}} code
15 | * JavaScript function body to run.
16 | * @param {RunOptions} options
17 | * Configuration (**required**).
18 | * @return {Promise}
19 | * Promise to a module;
20 | * the result is an object with a `default` field set to the component;
21 | * anything else that was exported is available too.
22 | */
23 | export async function run(code, options) {
24 | return new AsyncFunction(String(code))(options)
25 | }
26 |
27 | /**
28 | * Run code, synchronously.
29 | *
30 | * When possible please use the async `run`.
31 | *
32 | * > ☢️ **Danger**: this `eval`s JavaScript.
33 | *
34 | * @param {{toString(): string}} code
35 | * JavaScript function body to run.
36 | * @param {RunOptions} options
37 | * Configuration (**required**).
38 | * @return {MDXModule}
39 | * Module.
40 | */
41 | export function runSync(code, options) {
42 | // eslint-disable-next-line no-new-func
43 | return new Function(String(code))(options)
44 | }
45 |
--------------------------------------------------------------------------------
/packages/mdx/lib/types.d.ts:
--------------------------------------------------------------------------------
1 | import type {Program as EstreeProgram} from 'estree'
2 | import type {Data as UnistData} from 'unist'
3 |
4 | interface EsastData extends UnistData {
5 | /**
6 | * Whether a node was authored as explicit JSX (`
`) or as implicitly
7 | * turned into JSX (`# hi`).
8 | *
9 | * Registered by `@mdx-js/mdx/lib/types.d.ts`.
10 | */
11 | _mdxExplicitJsx?: boolean | null | undefined
12 | }
13 |
14 | interface EsastCommentData extends EsastData {
15 | /**
16 | * Whether a node (only used on comments) was generated by us to include the
17 | * JSX pragmas, so that when we compile JSX away, we can remove it.
18 | *
19 | * Registered by `@mdx-js/mdx/lib/types.d.ts`.
20 | */
21 | _mdxIsPragmaComment?: boolean | null | undefined
22 | }
23 |
24 | // Register data on `estree`.
25 | declare module 'estree' {
26 | interface BaseNode {
27 | /**
28 | * Extra unist data passed through from mdast through hast to esast.
29 | *
30 | * Registered by `@mdx-js/mdx/lib/types.d.ts`.
31 | */
32 | data?: EsastData | undefined
33 | }
34 |
35 | interface Comment {
36 | /**
37 | * Extra unist data added by `recma-document`.
38 | *
39 | * Registered by `@mdx-js/mdx/lib/types.d.ts`.
40 | */
41 | data?: EsastCommentData | undefined
42 | }
43 | }
44 |
45 | // Register data on `mdast`.
46 | declare module 'mdast-util-mdx-jsx' {
47 | interface MdxJsxFlowElementData {
48 | /**
49 | * Whether a node was authored as explicit JSX (`
`) or as implicitly
50 | * turned into JSX (`# hi`).
51 | *
52 | * Registered by `@mdx-js/mdx/lib/types.d.ts`.
53 | */
54 | _mdxExplicitJsx?: boolean | null | undefined
55 | }
56 |
57 | interface MdxJsxTextElementData {
58 | /**
59 | * Whether a node was authored as explicit JSX (`
`) or as implicitly
60 | * turned into JSX (`# hi`).
61 | *
62 | * Registered by `@mdx-js/mdx/lib/types.d.ts`.
63 | */
64 | _mdxExplicitJsx?: boolean | null | undefined
65 | }
66 | }
67 |
68 | declare module 'unified' {
69 | interface CompileResultMap {
70 | EstreeProgram: EstreeProgram
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/packages/mdx/lib/util/create-format-aware-processors.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {Program} from 'estree-jsx'
3 | * @import {Root} from 'mdast'
4 | * @import {Processor} from 'unified'
5 | * @import {Compatible, VFile} from 'vfile'
6 | * @import {CompileOptions} from '../compile.js'
7 | */
8 |
9 | /**
10 | * @typedef FormatAwareProcessors
11 | * Result.
12 | * @property {ReadonlyArray} extnames
13 | * Extensions to use.
14 | * @property {Process} process
15 | * Smart processor, async.
16 | *
17 | * @callback Process
18 | * Smart processor.
19 | * @param {Compatible} vfileCompatible
20 | * MDX or markdown document.
21 | * @return {Promise}
22 | * File.
23 | */
24 |
25 | import {createProcessor} from '../core.js'
26 | import {md, mdx} from './extnames.js'
27 | import {resolveFileAndOptions} from './resolve-file-and-options.js'
28 |
29 | /**
30 | * Create smart processors to handle different formats.
31 | *
32 | * @param {Readonly | null | undefined} [compileOptions]
33 | * Configuration (optional).
34 | * @return {FormatAwareProcessors}
35 | * Smart processor.
36 | */
37 | export function createFormatAwareProcessors(compileOptions) {
38 | const compileOptions_ = compileOptions || {}
39 | const mdExtensions = compileOptions_.mdExtensions || md
40 | const mdxExtensions = compileOptions_.mdxExtensions || mdx
41 | /** @type {Processor} */
42 | let cachedMarkdown
43 | /** @type {Processor} */
44 | let cachedMdx
45 |
46 | return {
47 | extnames:
48 | compileOptions_.format === 'md'
49 | ? mdExtensions
50 | : compileOptions_.format === 'mdx'
51 | ? mdxExtensions
52 | : [...mdExtensions, ...mdxExtensions],
53 | process
54 | }
55 |
56 | /**
57 | * Smart processor.
58 | *
59 | * @type {Process}
60 | */
61 | function process(vfileCompatible) {
62 | const {file, processor} = split(vfileCompatible)
63 | return processor.process(file)
64 | }
65 |
66 | /**
67 | * Make a full vfile from what’s given, and figure out which processor
68 | * should be used for it.
69 | * This caches processors (one for markdown and one for MDX) so that they do
70 | * not have to be reconstructed for each file.
71 | *
72 | * @param {Compatible} vfileCompatible
73 | * MDX or markdown document.
74 | * @return {{file: VFile, processor: Processor}}
75 | * File and corresponding processor.
76 | */
77 | function split(vfileCompatible) {
78 | const {file, options} = resolveFileAndOptions(
79 | vfileCompatible,
80 | compileOptions_
81 | )
82 | const processor =
83 | options.format === 'md'
84 | ? cachedMarkdown || (cachedMarkdown = createProcessor(options))
85 | : cachedMdx || (cachedMdx = createProcessor(options))
86 | return {file, processor}
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/packages/mdx/lib/util/estree-util-create.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {Node} from 'estree-jsx'
3 | */
4 |
5 | // Fix to show references to above types in VS Code.
6 | ''
7 |
8 | /**
9 | * @param {Readonly} from
10 | * Node to take from.
11 | * @param {Node} to
12 | * Node to add to.
13 | * @returns {undefined}
14 | * Nothing.
15 | */
16 | export function create(from, to) {
17 | /** @type {Array} */
18 | const fields = ['start', 'end', 'loc', 'range']
19 | let index = -1
20 |
21 | while (++index < fields.length) {
22 | const field = fields[index]
23 |
24 | if (field in from) {
25 | // @ts-expect-error: assume they’re settable.
26 | to[field] = from[field]
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/packages/mdx/lib/util/estree-util-declaration-to-expression.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {
3 | Declaration,
4 | Expression,
5 | MaybeNamedClassDeclaration,
6 | MaybeNamedFunctionDeclaration
7 | * } from 'estree-jsx'
8 | */
9 |
10 | import {ok as assert} from 'devlop'
11 |
12 | /**
13 | * Turn a declaration into an expression.
14 | *
15 | * Doesn’t work for variable declarations, but that’s fine for our use case
16 | * because currently we’re using this utility for export default declarations,
17 | * which can’t contain variable declarations.
18 | *
19 | * @param {Readonly} declaration
20 | * Declaration.
21 | * @returns {Expression}
22 | * Expression.
23 | */
24 | export function declarationToExpression(declaration) {
25 | if (declaration.type === 'FunctionDeclaration') {
26 | return {...declaration, type: 'FunctionExpression'}
27 | }
28 |
29 | // This is currently an internal utility so the next shouldn’t happen or a
30 | // maintainer is making a mistake.
31 | assert(declaration.type === 'ClassDeclaration', 'unexpected node type')
32 | return {...declaration, type: 'ClassExpression'}
33 | }
34 |
--------------------------------------------------------------------------------
/packages/mdx/lib/util/estree-util-is-declaration.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {
3 | Declaration,
4 | MaybeNamedClassDeclaration,
5 | MaybeNamedFunctionDeclaration,
6 | Node
7 | * } from 'estree-jsx'
8 | */
9 |
10 | // Fix to show references to above types in VS Code.
11 | ''
12 |
13 | /**
14 | * Check if `node` is a declaration.
15 | *
16 | * @param {Readonly} node
17 | * Node to check.
18 | * @returns {node is Declaration | MaybeNamedClassDeclaration | MaybeNamedFunctionDeclaration}
19 | * Whether `node` is a declaration.
20 | */
21 | export function isDeclaration(node) {
22 | return Boolean(
23 | node.type === 'FunctionDeclaration' ||
24 | node.type === 'ClassDeclaration' ||
25 | node.type === 'VariableDeclaration'
26 | )
27 | }
28 |
--------------------------------------------------------------------------------
/packages/mdx/lib/util/estree-util-specifiers-to-declarations.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {
3 | AssignmentProperty,
4 | ExportSpecifier,
5 | Expression,
6 | Identifier,
7 | ImportDefaultSpecifier,
8 | ImportNamespaceSpecifier,
9 | ImportSpecifier,
10 | Literal,
11 | VariableDeclarator
12 | * } from 'estree-jsx'
13 | */
14 |
15 | import {ok as assert} from 'devlop'
16 | import {create} from './estree-util-create.js'
17 |
18 | /**
19 | * @param {ReadonlyArray | Readonly | Readonly | Readonly>} specifiers
20 | * Specifiers.
21 | * @param {Readonly} init
22 | * Initializer.
23 | * @returns {Array}
24 | * Declarations.
25 | */
26 | export function specifiersToDeclarations(specifiers, init) {
27 | let index = -1
28 | /** @type {Array} */
29 | const declarations = []
30 | /** @type {Array} */
31 | const otherSpecifiers = []
32 | // Can only be one according to JS syntax.
33 | /** @type {ImportNamespaceSpecifier | undefined} */
34 | let importNamespaceSpecifier
35 |
36 | while (++index < specifiers.length) {
37 | const specifier = specifiers[index]
38 |
39 | if (specifier.type === 'ImportNamespaceSpecifier') {
40 | importNamespaceSpecifier = specifier
41 | } else {
42 | otherSpecifiers.push(specifier)
43 | }
44 | }
45 |
46 | if (importNamespaceSpecifier) {
47 | /** @type {VariableDeclarator} */
48 | const declarator = {
49 | type: 'VariableDeclarator',
50 | id: importNamespaceSpecifier.local,
51 | init
52 | }
53 | create(importNamespaceSpecifier, declarator)
54 | declarations.push(declarator)
55 | }
56 |
57 | declarations.push({
58 | type: 'VariableDeclarator',
59 | id: {
60 | type: 'ObjectPattern',
61 | properties: otherSpecifiers.map(function (specifier) {
62 | /** @type {Identifier | Literal} */
63 | let key =
64 | specifier.type === 'ImportSpecifier'
65 | ? specifier.imported
66 | : specifier.type === 'ExportSpecifier'
67 | ? specifier.exported
68 | : {type: 'Identifier', name: 'default'}
69 | let value = specifier.local
70 |
71 | // Switch them around if we’re exporting.
72 | if (specifier.type === 'ExportSpecifier') {
73 | value = key
74 | key = specifier.local
75 | }
76 |
77 | // To do: what to do about literals?
78 | // `const { a: 'b' } = c()` does not work?
79 | assert(value.type === 'Identifier')
80 |
81 | /** @type {AssignmentProperty} */
82 | const property = {
83 | type: 'Property',
84 | kind: 'init',
85 | shorthand:
86 | key.type === 'Identifier' &&
87 | value.type === 'Identifier' &&
88 | key.name === value.name,
89 | method: false,
90 | computed: false,
91 | key,
92 | value
93 | }
94 | create(specifier, property)
95 | return property
96 | })
97 | },
98 | init: importNamespaceSpecifier
99 | ? {type: 'Identifier', name: importNamespaceSpecifier.local.name}
100 | : init
101 | })
102 |
103 | return declarations
104 | }
105 |
--------------------------------------------------------------------------------
/packages/mdx/lib/util/estree-util-to-binary-addition.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {Expression} from 'estree-jsx'
3 | */
4 |
5 | import {ok as assert} from 'devlop'
6 |
7 | /**
8 | * @param {ReadonlyArray} expressions
9 | * Expressions.
10 | * @returns {Expression}
11 | * Addition.
12 | */
13 | export function toBinaryAddition(expressions) {
14 | let index = -1
15 | /** @type {Expression | undefined} */
16 | let left
17 |
18 | while (++index < expressions.length) {
19 | const right = expressions[index]
20 | left = left ? {type: 'BinaryExpression', left, operator: '+', right} : right
21 | }
22 |
23 | assert(left, 'expected non-empty `expressions` to be passed')
24 | return left
25 | }
26 |
--------------------------------------------------------------------------------
/packages/mdx/lib/util/estree-util-to-id-or-member-expression.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {
3 | Identifier,
4 | JSXIdentifier,
5 | JSXMemberExpression,
6 | Literal,
7 | MemberExpression
8 | * } from 'estree-jsx'
9 | */
10 |
11 | import {ok as assert} from 'devlop'
12 | import {name as isIdentifierName} from 'estree-util-is-identifier-name'
13 |
14 | /**
15 | * @param {ReadonlyArray} ids
16 | * Identifiers (example: `['list', 0]).
17 | * @returns {Identifier | MemberExpression}
18 | * Identifier or member expression.
19 | */
20 | export function toIdOrMemberExpression(ids) {
21 | let index = -1
22 | /** @type {Identifier | Literal | MemberExpression | undefined} */
23 | let object
24 |
25 | while (++index < ids.length) {
26 | const name = ids[index]
27 | /** @type {Identifier | Literal} */
28 | const id =
29 | typeof name === 'string' && isIdentifierName(name)
30 | ? {type: 'Identifier', name}
31 | : {type: 'Literal', value: name}
32 | object = object
33 | ? {
34 | type: 'MemberExpression',
35 | object,
36 | property: id,
37 | computed: id.type === 'Literal',
38 | optional: false
39 | }
40 | : id
41 | }
42 |
43 | assert(object, 'expected non-empty `ids` to be passed')
44 | assert(object.type !== 'Literal', 'expected identifier as left-most value')
45 | return object
46 | }
47 |
48 | /**
49 | * @param {ReadonlyArray} ids
50 | * Identifiers (example: `['list', 0]).
51 | * @returns {JSXIdentifier | JSXMemberExpression}
52 | * Identifier or member expression.
53 | */
54 | export function toJsxIdOrMemberExpression(ids) {
55 | let index = -1
56 | /** @type {JSXIdentifier | JSXMemberExpression | undefined} */
57 | let object
58 |
59 | while (++index < ids.length) {
60 | const name = ids[index]
61 | assert(
62 | typeof name === 'string' && isIdentifierName(name, {jsx: true}),
63 | 'expected valid jsx identifier, not `' + name + '`'
64 | )
65 |
66 | /** @type {JSXIdentifier} */
67 | const id = {type: 'JSXIdentifier', name}
68 | object = object ? {type: 'JSXMemberExpression', object, property: id} : id
69 | }
70 |
71 | assert(object, 'expected non-empty `ids` to be passed')
72 | return object
73 | }
74 |
--------------------------------------------------------------------------------
/packages/mdx/lib/util/extnames-to-regex.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Turn a list of extnames (*with* dots) into an expression.
3 | *
4 | * @param {ReadonlyArray} extnames
5 | * List of extnames.
6 | * @returns {RegExp}
7 | * Regex matching them.
8 | */
9 | export function extnamesToRegex(extnames) {
10 | return new RegExp(
11 | '\\.(' +
12 | extnames
13 | .map(function (d) {
14 | return d.slice(1)
15 | })
16 | .join('|') +
17 | ')([?#]|$)'
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/packages/mdx/lib/util/extnames.js:
--------------------------------------------------------------------------------
1 | import markdownExtensions from 'markdown-extensions'
2 |
3 | export const md = markdownExtensions.map(function (d) {
4 | return '.' + d
5 | })
6 | export const mdx = ['.mdx']
7 |
--------------------------------------------------------------------------------
/packages/mdx/lib/util/resolve-evaluate-options.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {Fragment, Jsx, JsxDev} from 'hast-util-to-jsx-runtime'
3 | * @import {MDXComponents} from 'mdx/types.js'
4 | * @import {CompileOptions} from '../compile.js'
5 | */
6 |
7 | /**
8 | * @typedef {EvaluateProcessorOptions & RunOptions} EvaluateOptions
9 | * Configuration for `evaluate`.
10 | *
11 | * @typedef {Omit } EvaluateProcessorOptions
12 | * Compile configuration without JSX options for evaluation.
13 | *
14 | * @typedef RunOptions
15 | * Configuration to run compiled code.
16 | *
17 | * `Fragment`, `jsx`, and `jsxs` are used when the code is compiled in
18 | * production mode (`development: false`).
19 | * `Fragment` and `jsxDEV` are used when compiled in development mode
20 | * (`development: true`).
21 | * `useMDXComponents` is used when the code is compiled with
22 | * `providerImportSource: '#'` (the exact value of this compile option
23 | * doesn’t matter).
24 | * @property {URL | string | null | undefined} [baseUrl]
25 | * Use this URL as `import.meta.url` and resolve `import` and `export … from`
26 | * relative to it (optional, example: `import.meta.url`);
27 | * this option can also be given at compile time in `CompileOptions`;
28 | * you should pass this (likely at runtime), as you might get runtime errors
29 | * when using `import.meta.url` / `import` / `export … from ` otherwise.
30 | * @property {Fragment} Fragment
31 | * Symbol to use for fragments (**required**).
32 | * @property {Jsx | null | undefined} [jsx]
33 | * Function to generate an element with static children in production mode.
34 | * @property {JsxDev | null | undefined} [jsxDEV]
35 | * Function to generate an element in development mode.
36 | * @property {Jsx | null | undefined} [jsxs]
37 | * Function to generate an element with dynamic children in production mode.
38 | * @property {UseMdxComponents | null | undefined} [useMDXComponents]
39 | * Function to get components from context.
40 | *
41 | * @callback UseMdxComponents
42 | * Get components from context.
43 | * @returns {MDXComponents}
44 | * Current components.
45 | */
46 |
47 | // Fix to show references to above types in VS Code.
48 | ''
49 |
50 | /**
51 | * Split compiletime options from runtime options.
52 | *
53 | * @param {Readonly | null | undefined} options
54 | * Configuration.
55 | * @returns {{compiletime: CompileOptions, runtime: RunOptions}}
56 | * Split options.
57 | */
58 | export function resolveEvaluateOptions(options) {
59 | const {
60 | Fragment,
61 | baseUrl,
62 | development,
63 | jsx,
64 | jsxDEV,
65 | jsxs,
66 | useMDXComponents,
67 | ...rest
68 | } = options || {}
69 |
70 | if (!Fragment) throw new Error('Expected `Fragment` given to `evaluate`')
71 | if (development) {
72 | if (!jsxDEV) throw new Error('Expected `jsxDEV` given to `evaluate`')
73 | } else {
74 | if (!jsx) throw new Error('Expected `jsx` given to `evaluate`')
75 | if (!jsxs) throw new Error('Expected `jsxs` given to `evaluate`')
76 | }
77 |
78 | return {
79 | compiletime: {
80 | ...rest,
81 | development,
82 | outputFormat: 'function-body',
83 | providerImportSource: useMDXComponents ? '#' : undefined
84 | },
85 | runtime: {Fragment, baseUrl, jsx, jsxDEV, jsxs, useMDXComponents}
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/packages/mdx/lib/util/resolve-file-and-options.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {Compatible} from 'vfile'
3 | * @import {CompileOptions} from '../compile.js'
4 | * @import {ProcessorOptions} from '../core.js'
5 | */
6 |
7 | import {VFile} from 'vfile'
8 | import {md} from './extnames.js'
9 |
10 | /**
11 | * Create a file and options from a given `vfileCompatible` and options that
12 | * might contain `format: 'detect'`.
13 | *
14 | * @param {Readonly} vfileCompatible
15 | * File.
16 | * @param {Readonly | null | undefined} [options]
17 | * Configuration (optional).
18 | * @returns {{file: VFile, options: ProcessorOptions}}
19 | * File and options.
20 | */
21 | export function resolveFileAndOptions(vfileCompatible, options) {
22 | const file = looksLikeAVFile(vfileCompatible)
23 | ? vfileCompatible
24 | : new VFile(vfileCompatible)
25 | const {format, ...rest} = options || {}
26 | return {
27 | file,
28 | options: {
29 | format:
30 | format === 'md' || format === 'mdx'
31 | ? format
32 | : file.extname && (rest.mdExtensions || md).includes(file.extname)
33 | ? 'md'
34 | : 'mdx',
35 | ...rest
36 | }
37 | }
38 | }
39 |
40 | /**
41 | * @param {Readonly | null | undefined} [value]
42 | * Thing.
43 | * @returns {value is VFile}
44 | * Check.
45 | */
46 | function looksLikeAVFile(value) {
47 | return Boolean(
48 | value &&
49 | typeof value === 'object' &&
50 | 'message' in value &&
51 | 'messages' in value
52 | )
53 | }
54 |
--------------------------------------------------------------------------------
/packages/mdx/license:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 Compositor, Inc. and Vercel, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/mdx/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@mdx-js/mdx",
3 | "version": "3.1.0",
4 | "description": "MDX compiler",
5 | "license": "MIT",
6 | "keywords": [
7 | "jsx",
8 | "markdown",
9 | "mdx",
10 | "remark"
11 | ],
12 | "homepage": "https://mdxjs.com",
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/mdx-js/mdx",
16 | "directory": "packages/mdx/"
17 | },
18 | "bugs": "https://github.com/mdx-js/mdx/issues",
19 | "funding": {
20 | "type": "opencollective",
21 | "url": "https://opencollective.com/unified"
22 | },
23 | "author": "John Otander (https://johno.com)",
24 | "contributors": [
25 | "John Otander (https://johno.com)",
26 | "Tim Neutkens ",
27 | "Matija Marohnić ",
28 | "Titus Wormer (https://wooorm.com)",
29 | "JounQin (https://www.1stg.me)",
30 | "Christian Murphy "
31 | ],
32 | "type": "module",
33 | "sideEffects": false,
34 | "exports": {
35 | ".": "./index.js",
36 | "./internal-create-format-aware-processors": "./lib/util/create-format-aware-processors.js",
37 | "./internal-extnames-to-regex": "./lib/util/extnames-to-regex.js"
38 | },
39 | "files": [
40 | "lib/",
41 | "index.d.ts.map",
42 | "index.d.ts",
43 | "index.js"
44 | ],
45 | "dependencies": {
46 | "@types/estree": "^1.0.0",
47 | "@types/estree-jsx": "^1.0.0",
48 | "@types/hast": "^3.0.0",
49 | "@types/mdx": "^2.0.0",
50 | "collapse-white-space": "^2.0.0",
51 | "devlop": "^1.0.0",
52 | "estree-util-is-identifier-name": "^3.0.0",
53 | "estree-util-scope": "^1.0.0",
54 | "estree-walker": "^3.0.0",
55 | "hast-util-to-jsx-runtime": "^2.0.0",
56 | "markdown-extensions": "^2.0.0",
57 | "recma-build-jsx": "^1.0.0",
58 | "recma-jsx": "^1.0.0",
59 | "recma-stringify": "^1.0.0",
60 | "rehype-recma": "^1.0.0",
61 | "remark-mdx": "^3.0.0",
62 | "remark-parse": "^11.0.0",
63 | "remark-rehype": "^11.0.0",
64 | "source-map": "^0.7.0",
65 | "unified": "^11.0.0",
66 | "unist-util-position-from-estree": "^2.0.0",
67 | "unist-util-stringify-position": "^4.0.0",
68 | "unist-util-visit": "^5.0.0",
69 | "vfile": "^6.0.0"
70 | },
71 | "scripts": {
72 | "test": "npm run test-coverage",
73 | "test-api": "node --conditions development --enable-source-maps test/index.js",
74 | "test-coverage": "c8 --100 --reporter lcov npm run test-api"
75 | },
76 | "xo": {
77 | "overrides": [
78 | {
79 | "files": [
80 | "test/**/*.js"
81 | ],
82 | "rules": {
83 | "no-restricted-globals": "off"
84 | }
85 | },
86 | {
87 | "files": [
88 | "**/*.ts"
89 | ],
90 | "rules": {
91 | "@typescript-eslint/array-type": "off",
92 | "@typescript-eslint/ban-types": "off",
93 | "@typescript-eslint/consistent-type-definitions": "off"
94 | }
95 | }
96 | ],
97 | "prettier": true,
98 | "rules": {
99 | "complexity": "off",
100 | "logical-assignment-operators": "off",
101 | "max-depth": "off",
102 | "n/file-extension-in-import": "off",
103 | "unicorn/prefer-at": "off",
104 | "unicorn/prefer-code-point": "off"
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/packages/mdx/test/context/components.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {ComponentProps} from 'react'
3 | */
4 |
5 | import React from 'react'
6 |
7 | /**
8 | * @param {Readonly>} properties
9 | * Properties.
10 | * @returns
11 | * `span` element.
12 | */
13 | export function Pill(properties) {
14 | return React.createElement('span', {...properties, style: {color: 'red'}})
15 | }
16 |
17 | /**
18 | * @param {Readonly>} properties
19 | * Properties.
20 | * @returns
21 | * `div` element.
22 | */
23 | export function Layout(properties) {
24 | return React.createElement('div', {...properties, style: {color: 'red'}})
25 | }
26 |
27 | export default Layout
28 |
--------------------------------------------------------------------------------
/packages/mdx/test/context/data.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Number.
3 | */
4 | export const number = 3.14
5 |
6 | /**
7 | * Object.
8 | */
9 | export const object = {a: 1, b: 2}
10 |
11 | /**
12 | * Array.
13 | */
14 | export const array = [1, 2]
15 |
16 | /**
17 | * Number.
18 | */
19 | export default 2 * number
20 |
--------------------------------------------------------------------------------
/packages/mdx/test/context/run.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {MDXContent, MDXModule} from 'mdx/types.js'
3 | * @import {Compatible} from 'vfile'
4 | */
5 |
6 | import fs from 'node:fs/promises'
7 |
8 | /**
9 | * @param {Readonly} input
10 | * MDX document.
11 | * @return {Promise}
12 | * MDX content.
13 | */
14 | export async function run(input) {
15 | const result = await runWhole(input)
16 | return result.default
17 | }
18 |
19 | /**
20 | *
21 | * @param {Readonly} input
22 | * MDX document.
23 | * @return {Promise}
24 | * MDX module.
25 | */
26 | export async function runWhole(input) {
27 | const fileName = 'fixture-' + Math.random() + '.js'
28 | const fileUrl = new URL(fileName, import.meta.url)
29 | const document = String(input)
30 |
31 | await fs.writeFile(fileUrl, document)
32 |
33 | try {
34 | /** @type {MDXModule} */
35 | return await import(fileUrl.href)
36 | } finally {
37 | // This is not a bug: the `finally` runs after the whole `try` block, but
38 | // before the `return`.
39 | await fs.rm(fileUrl)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/packages/mdx/test/core.js:
--------------------------------------------------------------------------------
1 | import assert from 'node:assert/strict'
2 | import {test} from 'node:test'
3 |
4 | test('@mdx-js/mdx: core', async function (t) {
5 | await t.test('should expose the public api', async function () {
6 | assert.deepEqual(Object.keys(await import('@mdx-js/mdx')).sort(), [
7 | 'compile',
8 | 'compileSync',
9 | 'createProcessor',
10 | 'evaluate',
11 | 'evaluateSync',
12 | 'nodeTypes',
13 | 'run',
14 | 'runSync'
15 | ])
16 | })
17 | })
18 |
--------------------------------------------------------------------------------
/packages/mdx/test/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/no-unassigned-import */
2 | import './compile.js'
3 | import './core.js'
4 | import './evaluate.js'
5 | import './syntax.js'
6 |
--------------------------------------------------------------------------------
/packages/mdx/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/packages/node-loader/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @typedef {import('./lib/index.js').Options} Options
3 | */
4 |
5 | import {createLoader} from './lib/index.js'
6 |
7 | const defaultLoader = createLoader()
8 |
9 | export {createLoader} from './lib/index.js'
10 |
11 | /**
12 | * Pass options to the loader.
13 | */
14 | export const initialize = defaultLoader.initialize
15 |
16 | /**
17 | * Load `file:` URLs to MD(X) files.
18 | */
19 | export const load = defaultLoader.load
20 |
--------------------------------------------------------------------------------
/packages/node-loader/lib/condition.default.js:
--------------------------------------------------------------------------------
1 | export const development = false
2 |
--------------------------------------------------------------------------------
/packages/node-loader/lib/condition.development.js:
--------------------------------------------------------------------------------
1 | export const development = true
2 |
--------------------------------------------------------------------------------
/packages/node-loader/lib/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {LoadFnOutput, LoadHook, LoadHookContext} from 'node:module'
3 | * @import {Process} from '@mdx-js/mdx/internal-create-format-aware-processors'
4 | * @import {CompileOptions} from '@mdx-js/mdx'
5 | */
6 |
7 | /**
8 | * @typedef {Parameters[2]} NextLoad
9 | * Next.
10 | *
11 | * @typedef {Omit} Options
12 | * Configuration.
13 | *
14 | * Options are the same as `compile` from `@mdx-js/mdx` with the
15 | * exception that the `development` option is supported based on
16 | * whether you run Node with `--conditions development`.
17 | * You cannot pass it manually.
18 | *
19 | * @typedef {[regex: RegExp, process: Process]} Settings
20 | */
21 |
22 | import fs from 'node:fs/promises'
23 | import {createFormatAwareProcessors} from '@mdx-js/mdx/internal-create-format-aware-processors'
24 | import {extnamesToRegex} from '@mdx-js/mdx/internal-extnames-to-regex'
25 | import {SourceMapGenerator} from 'source-map'
26 | import {reporter} from 'vfile-reporter'
27 | import {VFile} from 'vfile'
28 | import {development as defaultDevelopment} from '#condition'
29 |
30 | /**
31 | * Create Node.js hooks to handle markdown and MDX.
32 | *
33 | * @param {Readonly | null | undefined} [loaderOptions]
34 | * Configuration (optional).
35 | * @returns
36 | * Node.js hooks.
37 | */
38 | export function createLoader(loaderOptions) {
39 | /** @type {Settings} */
40 | let settings = configure(loaderOptions || {})
41 |
42 | return {initialize, load}
43 |
44 | /**
45 | *
46 | * @param {Readonly | null | undefined} options
47 | */
48 | async function initialize(options) {
49 | settings = configure({...loaderOptions, ...options})
50 | }
51 |
52 | /**
53 | * Load `file:` URLs to MD(X) files.
54 | *
55 | * @param {string} href
56 | * URL.
57 | * @param {LoadHookContext} context
58 | * Context.
59 | * @param {NextLoad} nextLoad
60 | * Next or default `load` function.
61 | * @returns {Promise}
62 | * Result.
63 | * @satisfies {LoadHook}
64 | */
65 | async function load(href, context, nextLoad) {
66 | const url = new URL(href)
67 | const [regex, process] = settings
68 |
69 | if (url.protocol === 'file:' && regex.test(url.pathname)) {
70 | const value = await fs.readFile(url)
71 | const file = await process(new VFile({value, path: url}))
72 |
73 | /* c8 ignore next 3 -- hard to test. */
74 | if (file.messages.length > 0) {
75 | console.error(reporter(file))
76 | }
77 |
78 | return {
79 | format: 'module',
80 | shortCircuit: true,
81 | source:
82 | String(file) +
83 | '\n//# sourceMappingURL=data:application/json;base64,' +
84 | Buffer.from(JSON.stringify(file.map)).toString('base64') +
85 | '\n'
86 | }
87 | }
88 |
89 | return nextLoad(href, context)
90 | }
91 | }
92 |
93 | /**
94 | * @param {Readonly} options
95 | * @returns {Settings}
96 | */
97 | function configure(options) {
98 | const {extnames, process} = createFormatAwareProcessors({
99 | development: defaultDevelopment,
100 | ...options,
101 | SourceMapGenerator
102 | })
103 | const regex = extnamesToRegex(extnames)
104 |
105 | return [regex, process]
106 | }
107 |
--------------------------------------------------------------------------------
/packages/node-loader/license:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2021 Titus Wormer
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/node-loader/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@mdx-js/node-loader",
3 | "version": "3.1.0",
4 | "description": "Node.js loader for MDX",
5 | "license": "MIT",
6 | "keywords": [
7 | "jsx",
8 | "loader",
9 | "markdown",
10 | "mdx",
11 | "node",
12 | "react",
13 | "remark"
14 | ],
15 | "homepage": "https://mdxjs.com",
16 | "repository": {
17 | "type": "git",
18 | "url": "https://github.com/mdx-js/mdx",
19 | "directory": "packages/node-loader/"
20 | },
21 | "bugs": "https://github.com/mdx-js/mdx/issues",
22 | "funding": {
23 | "type": "opencollective",
24 | "url": "https://opencollective.com/unified"
25 | },
26 | "author": "John Otander (https://johno.com)",
27 | "contributors": [
28 | "Titus Wormer (https://wooorm.com)"
29 | ],
30 | "type": "module",
31 | "sideEffects": false,
32 | "exports": "./index.js",
33 | "imports": {
34 | "#condition": {
35 | "development": "./lib/condition.development.js",
36 | "default": "./lib/condition.default.js"
37 | }
38 | },
39 | "files": [
40 | "lib/",
41 | "index.d.ts.map",
42 | "index.d.ts",
43 | "index.js"
44 | ],
45 | "dependencies": {
46 | "@mdx-js/mdx": "^3.0.0",
47 | "source-map": "^0.7.0",
48 | "vfile-reporter": "^8.0.0",
49 | "vfile": "^6.0.0"
50 | },
51 | "devDependencies": {},
52 | "scripts": {
53 | "test": "npm run test-coverage",
54 | "test-api": "node --conditions development --enable-source-maps --loader=@mdx-js/node-loader test/index.js",
55 | "test-coverage": "c8 --100 --reporter lcov npm run test-api"
56 | },
57 | "xo": {
58 | "prettier": true,
59 | "rules": {
60 | "n/file-extension-in-import": "off"
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/packages/node-loader/test/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {MDXModule} from 'mdx/types.js'
3 | */
4 |
5 | import assert from 'node:assert/strict'
6 | import fs from 'node:fs/promises'
7 | import {test} from 'node:test'
8 | import React from 'react'
9 | import {renderToStaticMarkup} from 'react-dom/server'
10 |
11 | test('@mdx-js/node-loader', async function (t) {
12 | await t.test('should expose the public api', async function () {
13 | assert.deepEqual(Object.keys(await import('@mdx-js/node-loader')).sort(), [
14 | 'createLoader',
15 | 'initialize',
16 | 'load'
17 | ])
18 | })
19 |
20 | await t.test('should work', async function () {
21 | const mdxUrl = new URL('node-loader.mdx', import.meta.url)
22 |
23 | await fs.writeFile(
24 | mdxUrl,
25 | 'export function Message() { return <>World!> }\n\n# Hello, '
26 | )
27 |
28 | /** @type {MDXModule} */
29 | let result
30 |
31 | try {
32 | result = await import(mdxUrl.href)
33 | } catch (error) {
34 | const exception = /** @type {NodeJS.ErrnoException} */ (error)
35 |
36 | if (exception.code === 'ERR_UNKNOWN_FILE_EXTENSION') {
37 | await fs.rm(mdxUrl)
38 |
39 | throw new Error(
40 | 'Please run Node with `--loader=@mdx-js/node-loader` to test the ESM loader'
41 | )
42 | }
43 |
44 | throw error
45 | }
46 |
47 | const Content = result.default
48 |
49 | assert.equal(
50 | renderToStaticMarkup(React.createElement(Content)),
51 | '
Hello, World!
'
52 | )
53 |
54 | await fs.rm(mdxUrl)
55 | })
56 |
57 | await t.test('supports source maps work', async function () {
58 | const mdxUrl = new URL('crash.mdx', import.meta.url)
59 |
60 | await fs.writeFile(
61 | mdxUrl,
62 | '\nexport function Throw() { throw new Error("Boom") }\n'
63 | )
64 |
65 | /** @type {MDXModule} */
66 | let result
67 |
68 | try {
69 | result = await import(mdxUrl.href)
70 | } catch (error) {
71 | const exception = /** @type {NodeJS.ErrnoException} */ (error)
72 |
73 | if (exception.code === 'ERR_UNKNOWN_FILE_EXTENSION') {
74 | await fs.rm(mdxUrl)
75 |
76 | throw new Error(
77 | 'Please run Node with `--loader=@mdx-js/node-loader` to test the ESM loader'
78 | )
79 | }
80 |
81 | throw error
82 | }
83 |
84 | const Content = result.default
85 |
86 | assert.throws(
87 | () => renderToStaticMarkup(React.createElement(Content)),
88 | (error) => {
89 | assert(error instanceof Error)
90 | assert.equal(error.message, 'Boom')
91 | // Source maps are off.
92 | // The column should be 26, not 8.
93 | assert(error.stack?.includes('crash.mdx:2:8)'))
94 | return true
95 | }
96 | )
97 |
98 | await fs.rm(mdxUrl)
99 | })
100 | })
101 |
--------------------------------------------------------------------------------
/packages/node-loader/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/packages/preact/index.js:
--------------------------------------------------------------------------------
1 | export {MDXProvider, useMDXComponents} from './lib/index.js'
2 |
--------------------------------------------------------------------------------
/packages/preact/lib/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {MDXComponents} from 'mdx/types.js'
3 | * @import {Component, ComponentChildren, VNode} from 'preact'
4 | */
5 |
6 | /**
7 | * @callback MergeComponents
8 | * Custom merge function.
9 | * @param {Readonly} currentComponents
10 | * Current components from the context.
11 | * @returns {MDXComponents}
12 | * Additional components.
13 | *
14 | * @typedef Props
15 | * Configuration for `MDXProvider`.
16 | * @property {ComponentChildren} [children]
17 | * Children (optional).
18 | * @property {Readonly | MergeComponents | null | undefined} [components]
19 | * Additional components to use or a function that creates them (optional).
20 | * @property {boolean | null | undefined} [disableParentContext=false]
21 | * Turn off outer component context (default: `false`).
22 | */
23 |
24 | import {createContext, h} from 'preact'
25 | import {useContext} from 'preact/hooks'
26 |
27 | /** @type {Readonly} */
28 | const emptyComponents = {}
29 |
30 | const MDXContext = createContext(emptyComponents)
31 |
32 | /**
33 | * Get current components from the MDX Context.
34 | *
35 | * @param {Readonly | MergeComponents | null | undefined} [components]
36 | * Additional components to use or a function that creates them (optional).
37 | * @returns {MDXComponents}
38 | * Current components.
39 | */
40 | export function useMDXComponents(components) {
41 | const contextComponents = useContext(MDXContext)
42 |
43 | // Custom merge via a function prop
44 | if (typeof components === 'function') {
45 | return components(contextComponents)
46 | }
47 |
48 | return {...contextComponents, ...components}
49 | }
50 |
51 | /**
52 | * Provider for MDX context.
53 | *
54 | * @param {Readonly} properties
55 | * Properties.
56 | * @returns {VNode}
57 | * Element.
58 | * @satisfies {Component}
59 | */
60 | export function MDXProvider(properties) {
61 | /** @type {Readonly} */
62 | let allComponents
63 |
64 | if (properties.disableParentContext) {
65 | allComponents =
66 | typeof properties.components === 'function'
67 | ? properties.components(emptyComponents)
68 | : properties.components || emptyComponents
69 | } else {
70 | allComponents = useMDXComponents(properties.components)
71 | }
72 |
73 | return h(
74 | MDXContext.Provider,
75 | {children: undefined, value: allComponents},
76 | properties.children
77 | )
78 | }
79 |
--------------------------------------------------------------------------------
/packages/preact/license:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 Compositor and Vercel, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/preact/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@mdx-js/preact",
3 | "version": "3.1.0",
4 | "description": "Preact context for MDX",
5 | "license": "MIT",
6 | "keywords": [
7 | "jsx",
8 | "markdown",
9 | "mdx",
10 | "preact",
11 | "remark"
12 | ],
13 | "homepage": "https://mdxjs.com",
14 | "repository": {
15 | "type": "git",
16 | "url": "https://github.com/mdx-js/mdx",
17 | "directory": "packages/preact/"
18 | },
19 | "bugs": "https://github.com/mdx-js/mdx/issues",
20 | "funding": {
21 | "type": "opencollective",
22 | "url": "https://opencollective.com/unified"
23 | },
24 | "author": "John Otander (https://johno.com)",
25 | "contributors": [
26 | "John Otander (https://johno.com)",
27 | "Tim Neutkens ",
28 | "Matija Marohnić ",
29 | "Titus Wormer (https://wooorm.com)",
30 | "JounQin (https://www.1stg.me)",
31 | "Chris Biscardi (https://www.christopherbiscardi.com)",
32 | "Christian Murphy "
33 | ],
34 | "type": "module",
35 | "sideEffects": false,
36 | "exports": "./index.js",
37 | "files": [
38 | "lib/",
39 | "index.d.ts.map",
40 | "index.d.ts",
41 | "index.js"
42 | ],
43 | "dependencies": {
44 | "@types/mdx": "^2.0.0"
45 | },
46 | "peerDependencies": {
47 | "preact": ">=10.0.0"
48 | },
49 | "devDependencies": {},
50 | "scripts": {
51 | "test": "npm run test-coverage",
52 | "test-api": "node --conditions development --loader=../../script/jsx-loader.js test/index.jsx",
53 | "test-coverage": "c8 --100 --reporter lcov npm run test-api"
54 | },
55 | "xo": {
56 | "overrides": [
57 | {
58 | "extends": "xo-react",
59 | "files": [
60 | "**/*.jsx"
61 | ],
62 | "rules": {
63 | "react/jsx-no-bind": "off",
64 | "react/react-in-jsx-scope": "off"
65 | }
66 | }
67 | ],
68 | "prettier": true,
69 | "rules": {
70 | "n/file-extension-in-import": "off"
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/packages/preact/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/packages/react/index.js:
--------------------------------------------------------------------------------
1 | export {MDXProvider, useMDXComponents} from './lib/index.js'
2 |
--------------------------------------------------------------------------------
/packages/react/lib/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {MDXComponents} from 'mdx/types.js'
3 | * @import {Component, ReactElement, ReactNode} from 'react'
4 | */
5 |
6 | /**
7 | * @callback MergeComponents
8 | * Custom merge function.
9 | * @param {Readonly} currentComponents
10 | * Current components from the context.
11 | * @returns {MDXComponents}
12 | * Additional components.
13 | *
14 | * @typedef Props
15 | * Configuration for `MDXProvider`.
16 | * @property {ReactNode | null | undefined} [children]
17 | * Children (optional).
18 | * @property {Readonly | MergeComponents | null | undefined} [components]
19 | * Additional components to use or a function that creates them (optional).
20 | * @property {boolean | null | undefined} [disableParentContext=false]
21 | * Turn off outer component context (default: `false`).
22 | */
23 |
24 | import React from 'react'
25 |
26 | /** @type {Readonly} */
27 | const emptyComponents = {}
28 |
29 | const MDXContext = React.createContext(emptyComponents)
30 |
31 | /**
32 | * Get current components from the MDX Context.
33 | *
34 | * @param {Readonly | MergeComponents | null | undefined} [components]
35 | * Additional components to use or a function that creates them (optional).
36 | * @returns {MDXComponents}
37 | * Current components.
38 | */
39 | export function useMDXComponents(components) {
40 | const contextComponents = React.useContext(MDXContext)
41 |
42 | // Memoize to avoid unnecessary top-level context changes
43 | return React.useMemo(
44 | function () {
45 | // Custom merge via a function prop
46 | if (typeof components === 'function') {
47 | return components(contextComponents)
48 | }
49 |
50 | return {...contextComponents, ...components}
51 | },
52 | [contextComponents, components]
53 | )
54 | }
55 |
56 | /**
57 | * Provider for MDX context.
58 | *
59 | * @param {Readonly} properties
60 | * Properties.
61 | * @returns {ReactElement}
62 | * Element.
63 | * @satisfies {Component}
64 | */
65 | export function MDXProvider(properties) {
66 | /** @type {Readonly} */
67 | let allComponents
68 |
69 | if (properties.disableParentContext) {
70 | allComponents =
71 | typeof properties.components === 'function'
72 | ? properties.components(emptyComponents)
73 | : properties.components || emptyComponents
74 | } else {
75 | allComponents = useMDXComponents(properties.components)
76 | }
77 |
78 | return React.createElement(
79 | MDXContext.Provider,
80 | {value: allComponents},
81 | properties.children
82 | )
83 | }
84 |
--------------------------------------------------------------------------------
/packages/react/license:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 Compositor and Vercel, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@mdx-js/react",
3 | "version": "3.1.0",
4 | "description": "React context for MDX",
5 | "license": "MIT",
6 | "keywords": [
7 | "jsx",
8 | "markdown",
9 | "mdx",
10 | "react",
11 | "remark"
12 | ],
13 | "homepage": "https://mdxjs.com",
14 | "repository": {
15 | "type": "git",
16 | "url": "https://github.com/mdx-js/mdx",
17 | "directory": "packages/react/"
18 | },
19 | "bugs": "https://github.com/mdx-js/mdx/issues",
20 | "funding": {
21 | "type": "opencollective",
22 | "url": "https://opencollective.com/unified"
23 | },
24 | "author": "John Otander (https://johno.com)",
25 | "contributors": [
26 | "John Otander (https://johno.com)",
27 | "Tim Neutkens ",
28 | "Matija Marohnić ",
29 | "Titus Wormer (https://wooorm.com)",
30 | "JounQin (https://www.1stg.me)",
31 | "Christian Murphy "
32 | ],
33 | "type": "module",
34 | "sideEffects": false,
35 | "exports": "./index.js",
36 | "files": [
37 | "lib/",
38 | "index.d.ts.map",
39 | "index.d.ts",
40 | "index.js"
41 | ],
42 | "dependencies": {
43 | "@types/mdx": "^2.0.0"
44 | },
45 | "peerDependencies": {
46 | "@types/react": ">=16",
47 | "react": ">=16"
48 | },
49 | "devDependencies": {},
50 | "scripts": {
51 | "test": "npm run test-coverage",
52 | "test-api": "node --conditions development --loader=../../script/jsx-loader.js test/index.jsx",
53 | "test-coverage": "c8 --100 --reporter lcov npm run test-api"
54 | },
55 | "xo": {
56 | "overrides": [
57 | {
58 | "extends": "xo-react",
59 | "files": [
60 | "**/*.jsx"
61 | ],
62 | "rules": {
63 | "react/jsx-no-bind": "off",
64 | "react/react-in-jsx-scope": "off"
65 | }
66 | }
67 | ],
68 | "prettier": true,
69 | "rules": {
70 | "n/file-extension-in-import": "off"
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/packages/react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/packages/remark-mdx/index.js:
--------------------------------------------------------------------------------
1 | // Augment node types:
2 | ///
3 |
4 | /**
5 | * @typedef {import('./lib/index.js').Options} Options
6 | */
7 |
8 | export {default} from './lib/index.js'
9 |
--------------------------------------------------------------------------------
/packages/remark-mdx/lib/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {ToMarkdownOptions} from 'mdast-util-mdx'
3 | * @import {Options as MicromarkOptions} from 'micromark-extension-mdxjs'
4 | * @import {Processor} from 'unified'
5 | */
6 |
7 | /**
8 | * @typedef {MicromarkOptions & ToMarkdownOptions} Options
9 | * Configuration.
10 | */
11 |
12 | import {mdxFromMarkdown, mdxToMarkdown} from 'mdast-util-mdx'
13 | import {mdxjs} from 'micromark-extension-mdxjs'
14 |
15 | /** @type {Readonly} */
16 | const emptyOptions = {}
17 |
18 | /**
19 | * Add support for MDX (JSX: ``, export/imports: `export {x}
20 | * from 'y'`; and expressions: `{1 + 1}`).
21 | *
22 | * @this {Processor}
23 | * Processor.
24 | * @param {Readonly | null | undefined} [options]
25 | * Configuration (optional).
26 | * @returns {undefined}
27 | * Nothing.
28 | */
29 | export default function remarkMdx(options) {
30 | const self = this
31 | const settings = options || emptyOptions
32 | const data = self.data()
33 |
34 | const micromarkExtensions =
35 | data.micromarkExtensions || (data.micromarkExtensions = [])
36 | const fromMarkdownExtensions =
37 | data.fromMarkdownExtensions || (data.fromMarkdownExtensions = [])
38 | const toMarkdownExtensions =
39 | data.toMarkdownExtensions || (data.toMarkdownExtensions = [])
40 |
41 | micromarkExtensions.push(mdxjs(settings))
42 | fromMarkdownExtensions.push(mdxFromMarkdown())
43 | toMarkdownExtensions.push(mdxToMarkdown(settings))
44 | }
45 |
--------------------------------------------------------------------------------
/packages/remark-mdx/license:
--------------------------------------------------------------------------------
1 | (The MIT License)
2 |
3 | Copyright (c) 2020 Titus Wormer
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/remark-mdx/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "remark-mdx",
3 | "version": "3.1.0",
4 | "description": "remark plugin to support MDX syntax",
5 | "license": "MIT",
6 | "keywords": [
7 | "javascript",
8 | "jsx",
9 | "markdown",
10 | "mdast",
11 | "mdx",
12 | "plugin",
13 | "remark",
14 | "remark-plugin",
15 | "unified",
16 | "xml"
17 | ],
18 | "homepage": "https://mdxjs.com",
19 | "repository": {
20 | "type": "git",
21 | "url": "https://github.com/mdx-js/mdx",
22 | "directory": "packages/remark-mdx/"
23 | },
24 | "bugs": "https://github.com/mdx-js/mdx/issues",
25 | "funding": {
26 | "type": "opencollective",
27 | "url": "https://opencollective.com/unified"
28 | },
29 | "author": "Titus Wormer (https://wooorm.com)",
30 | "contributors": [
31 | "Titus Wormer (https://wooorm.com)",
32 | "Christian Murphy "
33 | ],
34 | "type": "module",
35 | "sideEffects": false,
36 | "exports": "./index.js",
37 | "files": [
38 | "lib/",
39 | "index.d.ts.map",
40 | "index.d.ts",
41 | "index.js"
42 | ],
43 | "dependencies": {
44 | "mdast-util-mdx": "^3.0.0",
45 | "micromark-extension-mdxjs": "^3.0.0"
46 | },
47 | "devDependencies": {},
48 | "scripts": {
49 | "test": "npm run test-coverage",
50 | "test-api": "node --conditions development test/index.js",
51 | "test-coverage": "c8 --100 --reporter lcov npm run test-api"
52 | },
53 | "xo": {
54 | "prettier": true,
55 | "rules": {
56 | "logical-assignment-operators": "off",
57 | "n/file-extension-in-import": "off",
58 | "unicorn/no-this-assignment": "off"
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/packages/remark-mdx/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/packages/rollup/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @typedef {import('./lib/index.js').Options} Options
3 | */
4 |
5 | export {rollup as default} from './lib/index.js'
6 |
--------------------------------------------------------------------------------
/packages/rollup/lib/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {FormatAwareProcessors} from '@mdx-js/mdx/internal-create-format-aware-processors'
3 | * @import {CompileOptions} from '@mdx-js/mdx'
4 | * @import {FilterPattern} from '@rollup/pluginutils'
5 | * @import {SourceDescription} from 'rollup'
6 | */
7 |
8 | /**
9 | * @typedef {Omit} ApplicableOptions
10 | * Applicable compile configuration.
11 | *
12 | * @typedef ExtraOptions
13 | * Extra configuration.
14 | * @property {FilterPattern | null | undefined} [exclude]
15 | * Picomatch patterns to exclude (optional).
16 | * @property {FilterPattern | null | undefined} [include]
17 | * Picomatch patterns to include (optional).
18 | *
19 | * @typedef {ApplicableOptions & ExtraOptions} Options
20 | * Configuration.
21 | *
22 | * @typedef Plugin
23 | * Plugin that is compatible with both Rollup and Vite.
24 | * @property {string} name
25 | * The name of the plugin
26 | * @property {ViteConfig} config
27 | * Function used by Vite to set additional configuration options.
28 | * @property {Transform} transform
29 | * Function to transform the source content.
30 | *
31 | * @callback Transform
32 | * Callback called by Rollup and Vite to transform.
33 | * @param {string} value
34 | * File contents.
35 | * @param {string} path
36 | * File path.
37 | * @returns {Promise}
38 | * Result.
39 | *
40 | * @callback ViteConfig
41 | * Callback called by Vite to set additional configuration options.
42 | * @param {unknown} config
43 | * Configuration object (unused).
44 | * @param {ViteEnv} env
45 | * Environment variables.
46 | * @returns {undefined}
47 | * Nothing.
48 | *
49 | * @typedef ViteEnv
50 | * Environment variables used by Vite.
51 | * @property {string} mode
52 | * Mode.
53 | */
54 |
55 | import {createFormatAwareProcessors} from '@mdx-js/mdx/internal-create-format-aware-processors'
56 | import {createFilter} from '@rollup/pluginutils'
57 | import {SourceMapGenerator} from 'source-map'
58 | import {VFile} from 'vfile'
59 |
60 | /**
61 | * Plugin to compile MDX w/ rollup.
62 | *
63 | * @param {Readonly | null | undefined} [options]
64 | * Configuration (optional).
65 | * @return {Plugin}
66 | * Rollup plugin.
67 | */
68 | export function rollup(options) {
69 | const {exclude, include, ...rest} = options || {}
70 | /** @type {FormatAwareProcessors} */
71 | let formatAwareProcessors
72 | const filter = createFilter(include, exclude)
73 |
74 | return {
75 | name: '@mdx-js/rollup',
76 | config(config, env) {
77 | formatAwareProcessors = createFormatAwareProcessors({
78 | SourceMapGenerator,
79 | development: env.mode === 'development',
80 | ...rest
81 | })
82 | },
83 | async transform(value, path) {
84 | if (!formatAwareProcessors) {
85 | formatAwareProcessors = createFormatAwareProcessors({
86 | SourceMapGenerator,
87 | ...rest
88 | })
89 | }
90 |
91 | const file = new VFile({path, value})
92 |
93 | if (
94 | file.extname &&
95 | filter(file.path) &&
96 | formatAwareProcessors.extnames.includes(file.extname)
97 | ) {
98 | const compiled = await formatAwareProcessors.process(file)
99 | const code = String(compiled.value)
100 | /** @type {SourceDescription} */
101 | const result = {
102 | code,
103 | // @ts-expect-error: `rollup` is not compiled with `exactOptionalPropertyTypes`,
104 | // so it does not allow `sourceRoot` in `file.map` to be `undefined` here.
105 | map: compiled.map
106 | }
107 | return result
108 | }
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/packages/rollup/license:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2021 Titus Wormer
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/rollup/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@mdx-js/rollup",
3 | "version": "3.1.0",
4 | "description": "Rollup plugin for MDX",
5 | "license": "MIT",
6 | "keywords": [
7 | "jsx",
8 | "markdown",
9 | "mdx",
10 | "preact",
11 | "react",
12 | "remark",
13 | "rollup",
14 | "vue"
15 | ],
16 | "homepage": "https://mdxjs.com",
17 | "repository": {
18 | "type": "git",
19 | "url": "https://github.com/mdx-js/mdx",
20 | "directory": "packages/rollup/"
21 | },
22 | "bugs": "https://github.com/mdx-js/mdx/issues",
23 | "funding": {
24 | "type": "opencollective",
25 | "url": "https://opencollective.com/unified"
26 | },
27 | "author": "John Otander (https://johno.com)",
28 | "contributors": [
29 | "Titus Wormer (https://wooorm.com)"
30 | ],
31 | "type": "module",
32 | "sideEffects": false,
33 | "exports": "./index.js",
34 | "files": [
35 | "lib/",
36 | "index.d.ts.map",
37 | "index.d.ts",
38 | "index.js"
39 | ],
40 | "dependencies": {
41 | "@mdx-js/mdx": "^3.0.0",
42 | "@rollup/pluginutils": "^5.0.0",
43 | "source-map": "^0.7.0",
44 | "vfile": "^6.0.0"
45 | },
46 | "peerDependencies": {
47 | "rollup": ">=2"
48 | },
49 | "devDependencies": {},
50 | "scripts": {
51 | "test": "npm run test-coverage",
52 | "test-api": "node --conditions development test/index.js",
53 | "test-coverage": "c8 --100 --reporter lcov npm run test-api"
54 | },
55 | "xo": {
56 | "prettier": true,
57 | "rules": {
58 | "logical-assignment-operators": "off",
59 | "n/file-extension-in-import": "off"
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/packages/rollup/test/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {MDXModule} from 'mdx/types.js'
3 | * @import {RollupOutput} from 'rollup'
4 | */
5 |
6 | import assert from 'node:assert/strict'
7 | import fs from 'node:fs/promises'
8 | import {test} from 'node:test'
9 | import {fileURLToPath} from 'node:url'
10 | import rollupMdx from '@mdx-js/rollup'
11 | import React from 'react'
12 | import {renderToStaticMarkup} from 'react-dom/server'
13 | import {rollup} from 'rollup'
14 | import {build} from 'vite'
15 |
16 | test('@mdx-js/rollup', async function (t) {
17 | await t.test('should expose the public api', async function () {
18 | assert.deepEqual(Object.keys(await import('@mdx-js/rollup')).sort(), [
19 | 'default'
20 | ])
21 | })
22 |
23 | await t.test('should work', async function () {
24 | const mdxUrl = new URL('rollup.mdx', import.meta.url)
25 | const jsUrl = new URL('rollup.js', import.meta.url)
26 |
27 | await fs.writeFile(
28 | mdxUrl,
29 | 'export function Message() { return <>World!> }\n\n# Hello, '
30 | )
31 |
32 | const build = await rollup({
33 | external: ['react/jsx-runtime'],
34 | input: fileURLToPath(mdxUrl),
35 | plugins: [rollupMdx()]
36 | })
37 |
38 | const {output} = await build.generate({format: 'es', sourcemap: true})
39 | const chunk = output[0]
40 |
41 | // Source map.
42 | assert.equal(
43 | chunk.map?.mappings,
44 | ';;AAAO,SAAA,OAAA,GAAA;;AAA8B,IAAA,QAAA,EAAA;;;;;;;;;AAEnC,IAAA,QAAA,EAAA,CAAA,SAAA,EAAAA,GAAA,CAAA,OAAA,EAAA,EAAA,CAAA;;;;;;;;;;;;;;;'
45 | )
46 |
47 | await fs.writeFile(jsUrl, chunk.code)
48 |
49 | /** @type {MDXModule} */
50 | const result = await import(jsUrl.href)
51 | const Content = result.default
52 |
53 | assert.equal(
54 | renderToStaticMarkup(React.createElement(Content)),
55 | '
Hello, World!
'
56 | )
57 |
58 | await fs.rm(mdxUrl)
59 | await fs.rm(jsUrl)
60 | })
61 |
62 | await t.test('should infer production mode in vite', async () => {
63 | const result = /** @type {Array} */ (
64 | await build({
65 | build: {
66 | lib: {
67 | entry: fileURLToPath(new URL('vite-entry.mdx', import.meta.url)),
68 | name: 'production'
69 | },
70 | write: false
71 | },
72 | logLevel: 'silent',
73 | plugins: [rollupMdx()]
74 | })
75 | )
76 |
77 | const code = result[0].output[0].code
78 |
79 | assert.match(code, /jsxs?\(/)
80 | assert.doesNotMatch(code, /jsxDEV\(/)
81 | })
82 |
83 | await t.test('should infer development mode in vite', async () => {
84 | const result = /** @type {Array} */ (
85 | await build({
86 | build: {
87 | lib: {
88 | entry: fileURLToPath(new URL('vite-entry.mdx', import.meta.url)),
89 | name: 'production'
90 | },
91 | write: false
92 | },
93 | logLevel: 'silent',
94 | mode: 'development',
95 | plugins: [rollupMdx()]
96 | })
97 | )
98 |
99 | const code = result[0].output[0].code
100 |
101 | assert.doesNotMatch(code, /jsxs?\(/)
102 | assert.match(code, /jsxDEV\(/)
103 | })
104 | })
105 |
--------------------------------------------------------------------------------
/packages/rollup/test/vite-entry.mdx:
--------------------------------------------------------------------------------
1 | # Hello Vite
2 |
--------------------------------------------------------------------------------
/packages/rollup/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/packages/vue/index.js:
--------------------------------------------------------------------------------
1 | export {MDXProvider, useMDXComponents} from './lib/index.js'
2 |
--------------------------------------------------------------------------------
/packages/vue/lib/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {MDXComponents} from 'mdx/types.js'
3 | * @import {Component, ComponentPublicInstance} from 'vue'
4 | */
5 |
6 | /**
7 | * @typedef Props
8 | * Configuration for `MDXProvider`.
9 | * @property {MDXComponents | null | undefined} [components]
10 | * Additional components to use (optional).
11 | */
12 |
13 | import {Fragment, createVNode, inject, provide} from 'vue'
14 |
15 | /**
16 | * Provider for MDX context.
17 | *
18 | * @type {Component}
19 | * Provider.
20 | */
21 | export const MDXProvider = {
22 | name: 'MDXProvider',
23 | props: {
24 | components: {
25 | default() {
26 | return {}
27 | },
28 | type: Object
29 | }
30 | },
31 | setup(properties) {
32 | provide('$mdxComponents', properties.components)
33 | },
34 | /**
35 | * @this {ComponentPublicInstance}
36 | * Context.
37 | * @returns
38 | * Element.
39 | */
40 | render() {
41 | return createVNode(
42 | Fragment,
43 | undefined,
44 | this.$slots.default ? this.$slots.default() : []
45 | )
46 | }
47 | }
48 |
49 | /**
50 | * Get current components from the MDX Context.
51 | *
52 | * @returns {MDXComponents}
53 | * Current components.
54 | */
55 | export function useMDXComponents() {
56 | return inject('$mdxComponents', {})
57 | }
58 |
--------------------------------------------------------------------------------
/packages/vue/license:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 Compositor, Inc. and Vercel, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/vue/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@mdx-js/vue",
3 | "version": "3.1.0",
4 | "description": "Vue provider for MDX",
5 | "license": "MIT",
6 | "keywords": [
7 | "jsx",
8 | "markdown",
9 | "mdx",
10 | "remark",
11 | "vue"
12 | ],
13 | "homepage": "https://mdxjs.com",
14 | "repository": {
15 | "type": "git",
16 | "url": "https://github.com/mdx-js/mdx",
17 | "directory": "packages/vue/"
18 | },
19 | "bugs": "https://github.com/mdx-js/mdx/issues",
20 | "funding": {
21 | "type": "opencollective",
22 | "url": "https://opencollective.com/unified"
23 | },
24 | "author": "Jonathan Bakebwa (https://jbakebwa.dev)",
25 | "contributors": [
26 | "Jonathan Bakebwa (https://jbakebwa.dev)",
27 | "Christian Murphy "
28 | ],
29 | "type": "module",
30 | "sideEffects": false,
31 | "exports": "./index.js",
32 | "files": [
33 | "lib/",
34 | "index.d.ts.map",
35 | "index.d.ts",
36 | "index.js"
37 | ],
38 | "dependencies": {
39 | "@types/mdx": "^2.0.0"
40 | },
41 | "peerDependencies": {
42 | "vue": ">=3.0.0"
43 | },
44 | "devDependencies": {},
45 | "scripts": {
46 | "test": "npm run test-coverage",
47 | "test-api": "node --conditions development test/index.js",
48 | "test-coverage": "c8 --100 --reporter lcov npm run test-api"
49 | },
50 | "xo": {
51 | "prettier": true,
52 | "rules": {
53 | "n/file-extension-in-import": "off"
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/packages/vue/test/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @import {MDXModule} from 'mdx/types.js'
3 | * @import {Component} from 'vue'
4 | */
5 |
6 | import assert from 'node:assert/strict'
7 | import test from 'node:test'
8 | import {compile, run} from '@mdx-js/mdx'
9 | import {MDXProvider, useMDXComponents} from '@mdx-js/vue'
10 | import serverRenderer from '@vue/server-renderer'
11 | import * as runtime from 'vue/jsx-runtime'
12 | import * as vue from 'vue'
13 |
14 | test('@mdx-js/vue', async function (t) {
15 | await t.test('should expose the public api', async function () {
16 | assert.deepEqual(Object.keys(await import('@mdx-js/vue')).sort(), [
17 | 'MDXProvider',
18 | 'useMDXComponents'
19 | ])
20 | })
21 |
22 | await t.test('should evaluate MDX code', async function () {
23 | const {default: Content} = await evaluate('# hi')
24 |
25 | assert.equal(await vueToString(Content), '