├── .c8rc.json
├── .editorconfig
├── .eslintignore
├── .eslintrc.yaml
├── .github
└── workflows
│ └── ci.yaml
├── .gitignore
├── .prettierrc.yaml
├── .remarkignore
├── .remarkrc.yaml
├── LICENSE.md
├── README.md
├── fixtures
├── alt
│ ├── expected.jsx
│ └── input.md
├── custom-attributes
│ ├── expected.jsx
│ ├── input.md
│ └── options.json
├── duplicate
│ ├── expected.jsx
│ └── input.md
├── external-http
│ ├── expected.jsx
│ └── input.md
├── external-https
│ ├── expected.jsx
│ └── input.md
├── external-without-protocol
│ ├── expected.jsx
│ └── input.md
├── hash-preserve-both
│ ├── expected.jsx
│ ├── input.md
│ └── options.json
├── hash-preserve-import
│ ├── expected.jsx
│ └── input.md
├── hash-preserve-jsx
│ ├── expected.jsx
│ ├── input.md
│ └── options.json
├── hash-preserve-none
│ ├── expected.jsx
│ ├── input.md
│ └── options.json
├── html
│ ├── expected.jsx
│ └── input.md
├── inline
│ ├── expected.jsx
│ └── input.md
├── link
│ ├── expected.jsx
│ └── input.md
├── multiple
│ ├── expected.jsx
│ └── input.md
├── node-modules
│ ├── expected.jsx
│ ├── input.md
│ └── options.json
├── query-preserve-both
│ ├── expected.jsx
│ ├── input.md
│ └── options.json
├── query-preserve-import
│ ├── expected.jsx
│ └── input.md
├── query-preserve-jsx
│ ├── expected.jsx
│ ├── input.md
│ └── options.json
├── query-preserve-none
│ ├── expected.jsx
│ ├── input.md
│ └── options.json
├── relative-grandparent
│ ├── expected.jsx
│ └── input.md
├── relative-parent
│ ├── expected.jsx
│ └── input.md
├── relative-sibling
│ ├── expected.jsx
│ └── input.md
├── relative-simple
│ ├── expected.jsx
│ └── input.md
├── root
│ ├── expected.jsx
│ └── input.md
├── srcset
│ ├── expected.jsx
│ └── input.md
└── title
│ ├── expected.jsx
│ └── input.md
├── package-lock.json
├── package.json
├── src
├── rehype-mdx-import-media.test.ts
└── rehype-mdx-import-media.ts
└── tsconfig.json
/.c8rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "100": true,
3 | "reporter": ["html", "lcov", "text"]
4 | }
5 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | indent_size = 2
7 | indent_style = space
8 | insert_final_newline = true
9 | max_line_length = 100
10 | trim_trailing_whitespace = true
11 |
12 | [COMMIT_EDITMSG]
13 | max_line_length = 72
14 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | *.jsx
2 |
--------------------------------------------------------------------------------
/.eslintrc.yaml:
--------------------------------------------------------------------------------
1 | root: true
2 | extends:
3 | - remcohaszing
4 | rules:
5 | no-param-reassign: off
6 | import/no-extraneous-dependencies: off
7 | overrides:
8 | - files: ['*.md/*']
9 | rules:
10 | capitalized-comments: off
11 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yaml:
--------------------------------------------------------------------------------
1 | name: ci
2 |
3 | on:
4 | pull_request:
5 | push:
6 | branches: [main]
7 | tags: ['*']
8 |
9 | jobs:
10 | eslint:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v4
14 | - uses: actions/setup-node@v4
15 | with:
16 | node-version: 20
17 | - run: npm ci
18 | - run: npx eslint .
19 |
20 | pack:
21 | runs-on: ubuntu-latest
22 | steps:
23 | - uses: actions/checkout@v4
24 | - uses: actions/setup-node@v4
25 | with:
26 | node-version: 20
27 | - run: npm ci
28 | - run: npm pack
29 | - uses: actions/upload-artifact@v4
30 | with:
31 | name: package
32 | path: '*.tgz'
33 |
34 | test:
35 | runs-on: ubuntu-latest
36 | strategy:
37 | matrix:
38 | node-version:
39 | - 18
40 | - 20
41 | - 22
42 | steps:
43 | - uses: actions/checkout@v4
44 | - uses: actions/setup-node@v4
45 | with:
46 | node-version: ${{ matrix.node-version }}
47 | - run: npm ci
48 | - run: npm test
49 | - uses: codecov/codecov-action@v4
50 | if: ${{ matrix.node-version == 20 }}
51 |
52 | prettier:
53 | runs-on: ubuntu-latest
54 | steps:
55 | - uses: actions/checkout@v4
56 | - uses: actions/setup-node@v4
57 | with:
58 | node-version: 20
59 | - run: npm ci
60 | - run: npx prettier --check .
61 |
62 | release:
63 | runs-on: ubuntu-latest
64 | needs:
65 | - eslint
66 | - test
67 | - pack
68 | - prettier
69 | if: startsWith(github.ref, 'refs/tags/')
70 | permissions:
71 | id-token: write
72 | steps:
73 | - uses: actions/setup-node@v4
74 | with:
75 | node-version: 20
76 | registry-url: https://registry.npmjs.org
77 | - uses: actions/download-artifact@v4
78 | with: { name: package }
79 | - run: npm publish *.tgz --provenance
80 | env:
81 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
82 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | coverage/
2 | dist/
3 | node_modules/
4 | *.tsbuildinfo
5 | *.log
6 | *.tgz
7 |
--------------------------------------------------------------------------------
/.prettierrc.yaml:
--------------------------------------------------------------------------------
1 | proseWrap: always
2 | semi: false
3 | singleQuote: true
4 | trailingComma: none
5 |
--------------------------------------------------------------------------------
/.remarkignore:
--------------------------------------------------------------------------------
1 | fixtures/
2 |
--------------------------------------------------------------------------------
/.remarkrc.yaml:
--------------------------------------------------------------------------------
1 | plugins:
2 | - remark-preset-remcohaszing
3 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # MIT License
2 |
3 | Copyright © 2024 Remco Haszing
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6 | associated documentation files (the “Software”), to deal in the Software without restriction,
7 | including without limitation the rights to use, copy, modify, merge, publish, distribute,
8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all copies or substantial
12 | portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
17 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # rehype-mdx-import-media
2 |
3 | [](https://github.com/remcohaszing/rehype-mdx-import-media/actions/workflows/ci.yaml)
4 | [](https://codecov.io/gh/remcohaszing/rehype-mdx-import-media)
5 | [](https://www.npmjs.com/package/rehype-mdx-import-media)
6 | [](https://www.npmjs.com/package/rehype-mdx-import-media)
7 |
8 | An [MDX](https://mdxjs.com) [rehype](https://github.com/rehypejs/rehype) plugin for turning media
9 | paths into imports.
10 |
11 | ## Table of Contents
12 |
13 | - [Installation](#installation)
14 | - [When should I use this?](#when-should-i-use-this)
15 | - [Usage](#usage)
16 | - [Examples](#examples)
17 | - [Script](#script)
18 | - [Next.js](#nextjs)
19 | - [API](#api)
20 | - [Options](#options)
21 | - [Compatibility](#compatibility)
22 | - [License](#license)
23 |
24 | ## Installation
25 |
26 | ```sh
27 | npm install rehype-mdx-import-media
28 | ```
29 |
30 | ## When should I use this?
31 |
32 | You may want to author images in MDX using the markdown format, like so:
33 |
34 | ```markdown
35 | 
36 | ```
37 |
38 | You may use MDX with a bundler such as [webpack](https://webpack.js.org) or
39 | [Vite](http://vitejs.dev). By default bundlers don’t understand how to resolve those images. They
40 | only understand how to resolve imports. This plugin solves that problem.
41 |
42 | Also you may use MDX to load markdown files. If you reference other media in those markdown files
43 | using HTML tags, that media can be resolved by this plugin too.
44 |
45 | ## Usage
46 |
47 | This plugin takes HTML elements that refer to media content, and turns them into MDX expressions
48 | that use imports. This allows bundlers to resolve media you referenced from your code. Note that JSX
49 | elements are **not** HTML elements, so they are not processed. HTML elements can come from:
50 |
51 | - Markdown syntax in MDX files, such as images.
52 | - HTML in files parsed using the `md` [format](https://mdxjs.com/packages/mdx/#processoroptions)
53 | when using [`rehype-raw`](https://github.com/rehypejs/rehype-raw)
54 | - Custom remark / rehype plugins.
55 |
56 | If this plugin finds an attribute to process, it transforms the
57 | [hast](https://github.com/syntax-tree/hast) [`element`](https://github.com/syntax-tree/hast#element)
58 | nodes into an
59 | [`mdxJsxTextElement`](https://github.com/syntax-tree/mdast-util-mdx-jsx#mdxjsxtextelementhast) node.
60 | This may prevent other rehype plugins from further processing. To avoid this, put
61 | `rehype-mdx-import-media` after any other rehype plugins
62 |
63 | ## Examples
64 |
65 | ### Script
66 |
67 | Let’s say we have a file named `example.mdx` with the following contents:
68 |
69 | ```mdx
70 | 
71 | ```
72 |
73 | The following script:
74 |
75 | ```js
76 | import { compile } from '@mdx-js/mdx'
77 | import rehypeMdxImportMedia from 'rehype-mdx-import-media'
78 | import { read } from 'to-vfile'
79 |
80 | const { value } = await compile(await read('example.mdx'), {
81 | jsx: true,
82 | rehypePlugins: [rehypeMdxImportMedia]
83 | })
84 | console.log(value)
85 | ```
86 |
87 | Roughly yields:
88 |
89 | ```jsx
90 | import _rehypeMdxImportMedia0 from './image.png'
91 |
92 | export default function MDXContent() {
93 | return (
94 |
95 |
96 |
97 | )
98 | }
99 | ```
100 |
101 | ### Next.js
102 |
103 | If you use this with Next.js, you must combine it with
104 | [`next/image`](https://nextjs.org/docs/pages/api-reference/components/image).
105 |
106 | ```ts
107 | // next.config.ts
108 | import createMDX from '@next/mdx'
109 |
110 | const withMDX = createMDX({
111 | options: {
112 | rehypePlugins: [['rehype-mdx-import-media']]
113 | }
114 | })
115 |
116 | export default withMDX()
117 | ```
118 |
119 | ```ts
120 | // mdx-components.ts
121 | import Image from 'next/image'
122 |
123 | const components = {
124 | img: Image
125 | }
126 |
127 | declare global {
128 | type MDXProvidedComponents = typeof components
129 | }
130 |
131 | export function useMDXComponents(): MDXProvidedComponents {
132 | return components
133 | }
134 | ```
135 |
136 | ## API
137 |
138 | The default export is a [rehype](https://github.com/rehypejs/rehype) plugin.
139 |
140 | ### Options
141 |
142 | - `attributes` (`object`): HTML element attributes that should be processed. The key is the HTML
143 | element tag name. The value is a list of attribute names to process. The default attributes are:
144 | - [`audio[src]`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio#src)
145 | - [`embed[src]`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed#src)
146 | - [`img[src]`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#src)
147 | - [`img[srcset]`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#srcset)
148 | - [`object[data]`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object#data)
149 | - [`source[src]`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source#src)
150 | - [`source[srcset]`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source#srcset)
151 | - [`track[src]`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track#src)
152 | - [`video[poster]`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video#poster)
153 | - [`video[src]`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video#src)
154 | - `elementAttributeNameCase` (`'html' | 'react'`): The casing to use for attribute names. This
155 | should match the elementAttributeNameCase value passed to MDX. (Default: `'react'`)
156 | - `preserveHash` (`'both' | 'import' | 'jsx' | 'none'`): Where to keep URL hash. (Default:
157 | `'import'`)
158 | - `both`: Keep the URL hash on both the import source and the JSX prop.
159 | - `import`: Only keep the URL hash on the import source.
160 | - `jsx`: Only keep the URL hash on the JSX prop.
161 | - `none`: Remove the URL hash.
162 | - `preserveQuery` (`'both' | 'import' | 'jsx' | 'none'`): Where to keep query parameters. (Default:
163 | `'import'`)
164 | - `both`: Keep the query parameters on both the import source and the JSX prop.
165 | - `import`: Only keep the query parameters on the import source.
166 | - `jsx`: Only keep the query parameters on the JSX prop.
167 | - `none`: Remove the query parameters.
168 | - `resolve` (`boolean`): By default imports are resolved relative to the markdown file. This matches
169 | behaviour of places that render the markdown, such as GitHub. If this is set to false, this
170 | behaviour is removed and URLs are no longer processed. This allows to import images from
171 | `node_modules`. If this is disabled, local images can still be imported by prepending the path
172 | with `./.`. (Default: `true`).
173 |
174 | ## Compatibility
175 |
176 | This project is compatible with MDX 3 and Node.js 18 or greater.
177 |
178 | ## License
179 |
180 | [MIT](LICENSE.md) © [Remco Haszing](https://github.com/remcohaszing)
181 |
--------------------------------------------------------------------------------
/fixtures/alt/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png'
4 | function _createMdxContent(props) {
5 | const _components = {
6 | img: 'img',
7 | p: 'p',
8 | ...props.components
9 | }
10 | return (
11 | <_components.p>
12 | <_components.img src={_rehypeMdxImportMedia0} alt="Alt text" />
13 |
14 | )
15 | }
16 | export default function MDXContent(props = {}) {
17 | const { wrapper: MDXLayout } = props.components || {}
18 | return MDXLayout ? (
19 |
20 | <_createMdxContent {...props} />
21 |
22 | ) : (
23 | _createMdxContent(props)
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/fixtures/alt/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/fixtures/custom-attributes/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './script.js'
4 | function _createMdxContent(props) {
5 | const _components = {
6 | img: 'img',
7 | p: 'p',
8 | script: 'script',
9 | ...props.components
10 | }
11 | return (
12 | <>
13 | <_components.p>
14 | <_components.img src="./hello.png" alt="" />
15 |
16 | {'\n'}
17 | <_components.script src={_rehypeMdxImportMedia0} />
18 | >
19 | )
20 | }
21 | export default function MDXContent(props = {}) {
22 | const { wrapper: MDXLayout } = props.components || {}
23 | return MDXLayout ? (
24 |
25 | <_createMdxContent {...props} />
26 |
27 | ) : (
28 | _createMdxContent(props)
29 | )
30 | }
31 |
--------------------------------------------------------------------------------
/fixtures/custom-attributes/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 |
--------------------------------------------------------------------------------
/fixtures/custom-attributes/options.json:
--------------------------------------------------------------------------------
1 | {
2 | "attributes": {
3 | "script": "src"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/fixtures/duplicate/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png'
4 | import _rehypeMdxImportMedia1 from './image.jpg'
5 | function _createMdxContent(props) {
6 | const _components = {
7 | img: 'img',
8 | p: 'p',
9 | ...props.components
10 | }
11 | return (
12 | <>
13 | <_components.p>
14 | <_components.img src={_rehypeMdxImportMedia0} alt="" />
15 |
16 | {'\n'}
17 | <_components.p>
18 | <_components.img src={_rehypeMdxImportMedia0} alt="" />
19 |
20 | {'\n'}
21 | <_components.p>
22 | <_components.img src={_rehypeMdxImportMedia1} alt="" />
23 |
24 | {'\n'}
25 | <_components.p>
26 | <_components.img src={_rehypeMdxImportMedia1} alt="" />
27 |
28 | >
29 | )
30 | }
31 | export default function MDXContent(props = {}) {
32 | const { wrapper: MDXLayout } = props.components || {}
33 | return MDXLayout ? (
34 |
35 | <_createMdxContent {...props} />
36 |
37 | ) : (
38 | _createMdxContent(props)
39 | )
40 | }
41 |
--------------------------------------------------------------------------------
/fixtures/duplicate/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | 
4 |
5 | 
6 |
7 | 
8 |
--------------------------------------------------------------------------------
/fixtures/external-http/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | function _createMdxContent(props) {
4 | const _components = {
5 | img: 'img',
6 | p: 'p',
7 | ...props.components
8 | }
9 | return (
10 | <_components.p>
11 | <_components.img src="http://mdx-logo.now.sh" alt="" />
12 |
13 | )
14 | }
15 | export default function MDXContent(props = {}) {
16 | const { wrapper: MDXLayout } = props.components || {}
17 | return MDXLayout ? (
18 |
19 | <_createMdxContent {...props} />
20 |
21 | ) : (
22 | _createMdxContent(props)
23 | )
24 | }
25 |
--------------------------------------------------------------------------------
/fixtures/external-http/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/fixtures/external-https/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | function _createMdxContent(props) {
4 | const _components = {
5 | img: 'img',
6 | p: 'p',
7 | ...props.components
8 | }
9 | return (
10 | <_components.p>
11 | <_components.img src="https://mdx-logo.now.sh" alt="" />
12 |
13 | )
14 | }
15 | export default function MDXContent(props = {}) {
16 | const { wrapper: MDXLayout } = props.components || {}
17 | return MDXLayout ? (
18 |
19 | <_createMdxContent {...props} />
20 |
21 | ) : (
22 | _createMdxContent(props)
23 | )
24 | }
25 |
--------------------------------------------------------------------------------
/fixtures/external-https/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/fixtures/external-without-protocol/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | function _createMdxContent(props) {
4 | const _components = {
5 | img: 'img',
6 | p: 'p',
7 | ...props.components
8 | }
9 | return (
10 | <_components.p>
11 | <_components.img src="//mdx-logo.now.sh" alt="" />
12 |
13 | )
14 | }
15 | export default function MDXContent(props = {}) {
16 | const { wrapper: MDXLayout } = props.components || {}
17 | return MDXLayout ? (
18 |
19 | <_createMdxContent {...props} />
20 |
21 | ) : (
22 | _createMdxContent(props)
23 | )
24 | }
25 |
--------------------------------------------------------------------------------
/fixtures/external-without-protocol/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/fixtures/hash-preserve-both/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png#some-hash'
4 | import _rehypeMdxImportMedia1 from './image.png#some-hash2'
5 | function _createMdxContent(props) {
6 | const _components = {
7 | img: 'img',
8 | p: 'p',
9 | ...props.components
10 | }
11 | return (
12 | <>
13 | <_components.p>
14 | <_components.img src={`${_rehypeMdxImportMedia0}#some-hash`} alt="" />
15 |
16 | {'\n'}
17 | <_components.img
18 | srcSet={`${_rehypeMdxImportMedia0}#some-hash 2x,${_rehypeMdxImportMedia1}#some-hash2 4x`}
19 | />
20 | >
21 | )
22 | }
23 | export default function MDXContent(props = {}) {
24 | const { wrapper: MDXLayout } = props.components || {}
25 | return MDXLayout ? (
26 |
27 | <_createMdxContent {...props} />
28 |
29 | ) : (
30 | _createMdxContent(props)
31 | )
32 | }
33 |
--------------------------------------------------------------------------------
/fixtures/hash-preserve-both/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 |
--------------------------------------------------------------------------------
/fixtures/hash-preserve-both/options.json:
--------------------------------------------------------------------------------
1 | { "preserveHash": "both" }
2 |
--------------------------------------------------------------------------------
/fixtures/hash-preserve-import/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png#some-hash'
4 | import _rehypeMdxImportMedia1 from './image.png#some-hash2'
5 | function _createMdxContent(props) {
6 | const _components = {
7 | img: 'img',
8 | p: 'p',
9 | ...props.components
10 | }
11 | return (
12 | <>
13 | <_components.p>
14 | <_components.img src={_rehypeMdxImportMedia0} alt="" />
15 |
16 | {'\n'}
17 | <_components.img srcSet={`${_rehypeMdxImportMedia0} 2x,${_rehypeMdxImportMedia1} 4x`} />
18 | >
19 | )
20 | }
21 | export default function MDXContent(props = {}) {
22 | const { wrapper: MDXLayout } = props.components || {}
23 | return MDXLayout ? (
24 |
25 | <_createMdxContent {...props} />
26 |
27 | ) : (
28 | _createMdxContent(props)
29 | )
30 | }
31 |
--------------------------------------------------------------------------------
/fixtures/hash-preserve-import/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 |
--------------------------------------------------------------------------------
/fixtures/hash-preserve-jsx/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png'
4 | function _createMdxContent(props) {
5 | const _components = {
6 | img: 'img',
7 | p: 'p',
8 | ...props.components
9 | }
10 | return (
11 | <>
12 | <_components.p>
13 | <_components.img src={`${_rehypeMdxImportMedia0}#some-hash`} alt="" />
14 |
15 | {'\n'}
16 | <_components.img
17 | srcSet={`${_rehypeMdxImportMedia0}#some-hash 2x,${_rehypeMdxImportMedia0}#some-hash2 4x`}
18 | />
19 | >
20 | )
21 | }
22 | export default function MDXContent(props = {}) {
23 | const { wrapper: MDXLayout } = props.components || {}
24 | return MDXLayout ? (
25 |
26 | <_createMdxContent {...props} />
27 |
28 | ) : (
29 | _createMdxContent(props)
30 | )
31 | }
32 |
--------------------------------------------------------------------------------
/fixtures/hash-preserve-jsx/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 |
--------------------------------------------------------------------------------
/fixtures/hash-preserve-jsx/options.json:
--------------------------------------------------------------------------------
1 | { "preserveHash": "jsx" }
2 |
--------------------------------------------------------------------------------
/fixtures/hash-preserve-none/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png'
4 | function _createMdxContent(props) {
5 | const _components = {
6 | img: 'img',
7 | p: 'p',
8 | ...props.components
9 | }
10 | return (
11 | <>
12 | <_components.p>
13 | <_components.img src={_rehypeMdxImportMedia0} alt="" />
14 |
15 | {'\n'}
16 | <_components.img srcSet={`${_rehypeMdxImportMedia0} 2x,${_rehypeMdxImportMedia0} 4x`} />
17 | >
18 | )
19 | }
20 | export default function MDXContent(props = {}) {
21 | const { wrapper: MDXLayout } = props.components || {}
22 | return MDXLayout ? (
23 |
24 | <_createMdxContent {...props} />
25 |
26 | ) : (
27 | _createMdxContent(props)
28 | )
29 | }
30 |
--------------------------------------------------------------------------------
/fixtures/hash-preserve-none/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 |
--------------------------------------------------------------------------------
/fixtures/hash-preserve-none/options.json:
--------------------------------------------------------------------------------
1 | { "preserveHash": "none" }
2 |
--------------------------------------------------------------------------------
/fixtures/html/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png'
4 | import _rehypeMdxImportMedia1 from './other-image.png'
5 | function _createMdxContent(props) {
6 | const _components = {
7 | img: 'img',
8 | picture: 'picture',
9 | video: 'video',
10 | ...props.components
11 | }
12 | return (
13 | <>
14 | <_components.img
15 | srcSet={`${_rehypeMdxImportMedia0} 2x,${_rehypeMdxImportMedia0} 640w 480h,${_rehypeMdxImportMedia1}`}
16 | />
17 | {'\n'}
18 | <_components.picture>
19 | {'\n '}
20 | <_components.img
21 | srcSet={`${_rehypeMdxImportMedia0} 2x,${_rehypeMdxImportMedia0} 640w 480h,${_rehypeMdxImportMedia1}`}
22 | />
23 | {'\n'}
24 |
25 | {'\n'}
26 | <_components.video>{'\n'}
27 | >
28 | )
29 | }
30 | export default function MDXContent(props = {}) {
31 | const { wrapper: MDXLayout } = props.components || {}
32 | return MDXLayout ? (
33 |
34 | <_createMdxContent {...props} />
35 |
36 | ) : (
37 | _createMdxContent(props)
38 | )
39 | }
40 |
--------------------------------------------------------------------------------
/fixtures/html/input.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/fixtures/inline/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png'
4 | function _createMdxContent(props) {
5 | const _components = {
6 | img: 'img',
7 | p: 'p',
8 | ...props.components
9 | }
10 | return (
11 | <_components.p>
12 | {'This is an inline image: '}
13 | <_components.img src={_rehypeMdxImportMedia0} alt="" />
14 | {'. See?'}
15 |
16 | )
17 | }
18 | export default function MDXContent(props = {}) {
19 | const { wrapper: MDXLayout } = props.components || {}
20 | return MDXLayout ? (
21 |
22 | <_createMdxContent {...props} />
23 |
24 | ) : (
25 | _createMdxContent(props)
26 | )
27 | }
28 |
--------------------------------------------------------------------------------
/fixtures/inline/input.md:
--------------------------------------------------------------------------------
1 | This is an inline image: . See?
2 |
--------------------------------------------------------------------------------
/fixtures/link/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png'
4 | function _createMdxContent(props) {
5 | const _components = {
6 | a: 'a',
7 | img: 'img',
8 | p: 'p',
9 | ...props.components
10 | }
11 | return (
12 | <_components.p>
13 | <_components.a href="https://example.com">
14 | <_components.img src={_rehypeMdxImportMedia0} alt="" />
15 |
16 |
17 | )
18 | }
19 | export default function MDXContent(props = {}) {
20 | const { wrapper: MDXLayout } = props.components || {}
21 | return MDXLayout ? (
22 |
23 | <_createMdxContent {...props} />
24 |
25 | ) : (
26 | _createMdxContent(props)
27 | )
28 | }
29 |
--------------------------------------------------------------------------------
/fixtures/link/input.md:
--------------------------------------------------------------------------------
1 | [](https://example.com)
2 |
--------------------------------------------------------------------------------
/fixtures/multiple/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.gif'
4 | import _rehypeMdxImportMedia1 from './image.jpg'
5 | import _rehypeMdxImportMedia2 from './image.png'
6 | import _rehypeMdxImportMedia3 from './image.svg'
7 | function _createMdxContent(props) {
8 | const _components = {
9 | img: 'img',
10 | p: 'p',
11 | ...props.components
12 | }
13 | return (
14 | <>
15 | <_components.p>
16 | <_components.img src={_rehypeMdxImportMedia0} alt="" />
17 |
18 | {'\n'}
19 | <_components.p>
20 | <_components.img src={_rehypeMdxImportMedia1} alt="" />
21 |
22 | {'\n'}
23 | <_components.p>
24 | <_components.img src={_rehypeMdxImportMedia2} alt="" />
25 |
26 | {'\n'}
27 | <_components.p>
28 | <_components.img src={_rehypeMdxImportMedia3} alt="" />
29 |
30 | >
31 | )
32 | }
33 | export default function MDXContent(props = {}) {
34 | const { wrapper: MDXLayout } = props.components || {}
35 | return MDXLayout ? (
36 |
37 | <_createMdxContent {...props} />
38 |
39 | ) : (
40 | _createMdxContent(props)
41 | )
42 | }
43 |
--------------------------------------------------------------------------------
/fixtures/multiple/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | 
4 |
5 | 
6 |
7 | 
8 |
--------------------------------------------------------------------------------
/fixtures/node-modules/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from '@browser-logos/chrome/chrome.png'
4 | function _createMdxContent(props) {
5 | const _components = {
6 | img: 'img',
7 | p: 'p',
8 | ...props.components
9 | }
10 | return (
11 | <_components.p>
12 | <_components.img src={_rehypeMdxImportMedia0} alt="" />
13 |
14 | )
15 | }
16 | export default function MDXContent(props = {}) {
17 | const { wrapper: MDXLayout } = props.components || {}
18 | return MDXLayout ? (
19 |
20 | <_createMdxContent {...props} />
21 |
22 | ) : (
23 | _createMdxContent(props)
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/fixtures/node-modules/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/fixtures/node-modules/options.json:
--------------------------------------------------------------------------------
1 | {
2 | "resolve": false
3 | }
4 |
--------------------------------------------------------------------------------
/fixtures/query-preserve-both/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png?size=16'
4 | import _rehypeMdxImportMedia1 from './image.png?size=32'
5 | function _createMdxContent(props) {
6 | const _components = {
7 | img: 'img',
8 | p: 'p',
9 | ...props.components
10 | }
11 | return (
12 | <>
13 | <_components.p>
14 | <_components.img src={`${_rehypeMdxImportMedia0}?size=16`} alt="" />
15 |
16 | {'\n'}
17 | <_components.img
18 | srcSet={`${_rehypeMdxImportMedia0}?size=16 2x,${_rehypeMdxImportMedia1}?size=32 4x`}
19 | />
20 | >
21 | )
22 | }
23 | export default function MDXContent(props = {}) {
24 | const { wrapper: MDXLayout } = props.components || {}
25 | return MDXLayout ? (
26 |
27 | <_createMdxContent {...props} />
28 |
29 | ) : (
30 | _createMdxContent(props)
31 | )
32 | }
33 |
--------------------------------------------------------------------------------
/fixtures/query-preserve-both/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 |
--------------------------------------------------------------------------------
/fixtures/query-preserve-both/options.json:
--------------------------------------------------------------------------------
1 | { "preserveQuery": "both" }
2 |
--------------------------------------------------------------------------------
/fixtures/query-preserve-import/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png?size=16'
4 | import _rehypeMdxImportMedia1 from './image.png?size=32'
5 | function _createMdxContent(props) {
6 | const _components = {
7 | img: 'img',
8 | p: 'p',
9 | ...props.components
10 | }
11 | return (
12 | <>
13 | <_components.p>
14 | <_components.img src={_rehypeMdxImportMedia0} alt="" />
15 |
16 | {'\n'}
17 | <_components.img srcSet={`${_rehypeMdxImportMedia0} 2x,${_rehypeMdxImportMedia1} 4x`} />
18 | >
19 | )
20 | }
21 | export default function MDXContent(props = {}) {
22 | const { wrapper: MDXLayout } = props.components || {}
23 | return MDXLayout ? (
24 |
25 | <_createMdxContent {...props} />
26 |
27 | ) : (
28 | _createMdxContent(props)
29 | )
30 | }
31 |
--------------------------------------------------------------------------------
/fixtures/query-preserve-import/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 |
--------------------------------------------------------------------------------
/fixtures/query-preserve-jsx/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png'
4 | function _createMdxContent(props) {
5 | const _components = {
6 | img: 'img',
7 | p: 'p',
8 | ...props.components
9 | }
10 | return (
11 | <>
12 | <_components.p>
13 | <_components.img src={`${_rehypeMdxImportMedia0}?size=16`} alt="" />
14 |
15 | {'\n'}
16 | <_components.img
17 | srcSet={`${_rehypeMdxImportMedia0}?size=16 2x,${_rehypeMdxImportMedia0}?size=32 4x`}
18 | />
19 | >
20 | )
21 | }
22 | export default function MDXContent(props = {}) {
23 | const { wrapper: MDXLayout } = props.components || {}
24 | return MDXLayout ? (
25 |
26 | <_createMdxContent {...props} />
27 |
28 | ) : (
29 | _createMdxContent(props)
30 | )
31 | }
32 |
--------------------------------------------------------------------------------
/fixtures/query-preserve-jsx/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 |
--------------------------------------------------------------------------------
/fixtures/query-preserve-jsx/options.json:
--------------------------------------------------------------------------------
1 | { "preserveQuery": "jsx" }
2 |
--------------------------------------------------------------------------------
/fixtures/query-preserve-none/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png'
4 | function _createMdxContent(props) {
5 | const _components = {
6 | img: 'img',
7 | p: 'p',
8 | ...props.components
9 | }
10 | return (
11 | <>
12 | <_components.p>
13 | <_components.img src={_rehypeMdxImportMedia0} alt="" />
14 |
15 | {'\n'}
16 | <_components.img srcSet={`${_rehypeMdxImportMedia0} 2x,${_rehypeMdxImportMedia0} 4x`} />
17 | >
18 | )
19 | }
20 | export default function MDXContent(props = {}) {
21 | const { wrapper: MDXLayout } = props.components || {}
22 | return MDXLayout ? (
23 |
24 | <_createMdxContent {...props} />
25 |
26 | ) : (
27 | _createMdxContent(props)
28 | )
29 | }
30 |
--------------------------------------------------------------------------------
/fixtures/query-preserve-none/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 |
--------------------------------------------------------------------------------
/fixtures/query-preserve-none/options.json:
--------------------------------------------------------------------------------
1 | { "preserveQuery": "none" }
2 |
--------------------------------------------------------------------------------
/fixtures/relative-grandparent/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from '../../image.png'
4 | function _createMdxContent(props) {
5 | const _components = {
6 | img: 'img',
7 | p: 'p',
8 | ...props.components
9 | }
10 | return (
11 | <_components.p>
12 | <_components.img src={_rehypeMdxImportMedia0} alt="" />
13 |
14 | )
15 | }
16 | export default function MDXContent(props = {}) {
17 | const { wrapper: MDXLayout } = props.components || {}
18 | return MDXLayout ? (
19 |
20 | <_createMdxContent {...props} />
21 |
22 | ) : (
23 | _createMdxContent(props)
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/fixtures/relative-grandparent/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/fixtures/relative-parent/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from '../image.png'
4 | function _createMdxContent(props) {
5 | const _components = {
6 | img: 'img',
7 | p: 'p',
8 | ...props.components
9 | }
10 | return (
11 | <_components.p>
12 | <_components.img src={_rehypeMdxImportMedia0} alt="" />
13 |
14 | )
15 | }
16 | export default function MDXContent(props = {}) {
17 | const { wrapper: MDXLayout } = props.components || {}
18 | return MDXLayout ? (
19 |
20 | <_createMdxContent {...props} />
21 |
22 | ) : (
23 | _createMdxContent(props)
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/fixtures/relative-parent/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/fixtures/relative-sibling/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png'
4 | function _createMdxContent(props) {
5 | const _components = {
6 | img: 'img',
7 | p: 'p',
8 | ...props.components
9 | }
10 | return (
11 | <_components.p>
12 | <_components.img src={_rehypeMdxImportMedia0} alt="" />
13 |
14 | )
15 | }
16 | export default function MDXContent(props = {}) {
17 | const { wrapper: MDXLayout } = props.components || {}
18 | return MDXLayout ? (
19 |
20 | <_createMdxContent {...props} />
21 |
22 | ) : (
23 | _createMdxContent(props)
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/fixtures/relative-sibling/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/fixtures/relative-simple/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png'
4 | function _createMdxContent(props) {
5 | const _components = {
6 | img: 'img',
7 | p: 'p',
8 | ...props.components
9 | }
10 | return (
11 | <_components.p>
12 | <_components.img src={_rehypeMdxImportMedia0} alt="" />
13 |
14 | )
15 | }
16 | export default function MDXContent(props = {}) {
17 | const { wrapper: MDXLayout } = props.components || {}
18 | return MDXLayout ? (
19 |
20 | <_createMdxContent {...props} />
21 |
22 | ) : (
23 | _createMdxContent(props)
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/fixtures/relative-simple/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/fixtures/root/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | function _createMdxContent(props) {
4 | const _components = {
5 | img: 'img',
6 | p: 'p',
7 | ...props.components
8 | }
9 | return (
10 | <_components.p>
11 | <_components.img src="/image.png" alt="" />
12 |
13 | )
14 | }
15 | export default function MDXContent(props = {}) {
16 | const { wrapper: MDXLayout } = props.components || {}
17 | return MDXLayout ? (
18 |
19 | <_createMdxContent {...props} />
20 |
21 | ) : (
22 | _createMdxContent(props)
23 | )
24 | }
25 |
--------------------------------------------------------------------------------
/fixtures/root/input.md:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/fixtures/srcset/expected.jsx:
--------------------------------------------------------------------------------
1 | /*@jsxRuntime automatic*/
2 | /*@jsxImportSource react*/
3 | import _rehypeMdxImportMedia0 from './image.png'
4 | import _rehypeMdxImportMedia1 from './other-image.png'
5 | import _rehypeMdxImportMedia2 from './sound.mp3'
6 | import _rehypeMdxImportMedia3 from './video.mp4'
7 | import _rehypeMdxImportMedia4 from './image.jpg'
8 | import _rehypeMdxImportMedia5 from './video.webm'
9 | import _rehypeMdxImportMedia6 from './video.mpg'
10 | import _rehypeMdxImportMedia7 from './video.png'
11 | import _rehypeMdxImportMedia8 from './video.vtt'
12 | function _createMdxContent(props) {
13 | const _components = {
14 | audio: 'audio',
15 | embed: 'embed',
16 | img: 'img',
17 | object: 'object',
18 | p: 'p',
19 | picture: 'picture',
20 | source: 'source',
21 | track: 'track',
22 | video: 'video',
23 | ...props.components
24 | }
25 | return (
26 | <>
27 | <_components.img
28 | srcSet={`${_rehypeMdxImportMedia0} 2x,${_rehypeMdxImportMedia0} 640w 480h,${_rehypeMdxImportMedia1}`}
29 | />
30 | {'\n'}
31 | <_components.img
32 | srcSet={`${_rehypeMdxImportMedia0} 2x,${_rehypeMdxImportMedia0},${_rehypeMdxImportMedia1} 640w 480h`}
33 | />
34 | {'\n'}
35 | <_components.img srcSet="https://example.com/image.png" />
36 | {'\n'}
37 | <_components.p>
38 | <_components.audio src={_rehypeMdxImportMedia2} />
39 |
40 | {'\n'}
41 | <_components.p>
42 | <_components.embed src={_rehypeMdxImportMedia3} type="video/webm" />
43 |
44 | {'\n'}
45 | <_components.p>
46 | <_components.object src="video.pdf" type="application/pdf" />
47 |
48 | {'\n'}
49 | <_components.picture>
50 | {'\n '}
51 | <_components.source srcSet={`${_rehypeMdxImportMedia0}`} />
52 | {'\n '}
53 | <_components.source srcSet={`${_rehypeMdxImportMedia4}`} />
54 | {'\n '}
55 | <_components.img src={_rehypeMdxImportMedia4} />
56 | {'\n'}
57 |
58 | {'\n'}
59 | <_components.video>
60 | {'\n '}
61 | <_components.source src={_rehypeMdxImportMedia5} type="video/webm" />
62 | {'\n '}
63 | <_components.source src={_rehypeMdxImportMedia6} type="video/mp4" />
64 | {'\n'}
65 |
66 | {'\n'}
67 | <_components.video src={_rehypeMdxImportMedia5} poster={_rehypeMdxImportMedia7}>
68 | {'\n '}
69 | <_components.track kind="captions" srcLang="en" src={_rehypeMdxImportMedia8} />
70 | {'\n'}
71 |
72 | >
73 | )
74 | }
75 | export default function MDXContent(props = {}) {
76 | const { wrapper: MDXLayout } = props.components || {}
77 | return MDXLayout ? (
78 |
79 | <_createMdxContent {...props} />
80 |
81 | ) : (
82 | _createMdxContent(props)
83 | )
84 | }
85 |
--------------------------------------------------------------------------------
/fixtures/srcset/input.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |