Skip to content

Commit

Permalink
Fix support for baseUrl rewriting import.meta.url
Browse files Browse the repository at this point in the history
MDX can compile *and* run code, at the same time (called
“evaluation”).
To evaluate imports and exports in that code, it has to know *from
where* to do that, which is a location on the users computer that is
not the folder that contains `@mdx-js/mdx` in `node_modules`.
That’s what the `baseUrl` option is used for.

Previously though, the URL given as `baseUrl` was not used to replace
`import.meta.url` in MDX code, which crashed.
As they are equivalent, this commit introduces that behavior.

Closes GH-2021.
  • Loading branch information
wooorm authored Apr 23, 2022
1 parent 109f9c1 commit f77c33f
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 3 deletions.
26 changes: 25 additions & 1 deletion packages/mdx/lib/plugin/recma-document.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
* Whether to keep `import` (and `export … from`) statements or compile them
* to dynamic `import()` instead.
* @property {string} [baseUrl]
* Resolve relative `import` (and `export … from`) relative to this URL.
* Resolve `import`s (and `export … from`, and `import.meta.url`) relative to
* this URL.
* @property {string} [pragma='React.createElement']
* Pragma for JSX (used in classic runtime).
* @property {string} [pragmaFrag='React.Fragment']
Expand All @@ -42,6 +43,7 @@
import {analyze} from 'periscopic'
import {stringifyPosition} from 'unist-util-stringify-position'
import {positionFromEstree} from 'unist-util-position-from-estree'
import {walk} from 'estree-walker'
import {create} from '../util/estree-util-create.js'
import {specifiersToDeclarations} from '../util/estree-util-specifiers-to-declarations.js'
import {declarationToExpression} from '../util/estree-util-declaration-to-expression.js'
Expand Down Expand Up @@ -296,6 +298,28 @@ export function recmaDocument(options = {}) {

tree.body = replacement

if (baseUrl) {
walk(tree, {
enter(_node) {
const node = /** @type {Node} */ (_node)

if (
node.type === 'MemberExpression' &&
'object' in node &&
node.object.type === 'MetaProperty' &&
node.property.type === 'Identifier' &&
node.object.meta.name === 'import' &&
node.object.property.name === 'meta' &&
node.property.name === 'url'
) {
/** @type {SimpleLiteral} */
const replacement = {type: 'Literal', value: baseUrl}
this.replace(replacement)
}
}
})
}

/**
* @param {ExportNamedDeclaration|ExportAllDeclaration} node
* @returns {void}
Expand Down
4 changes: 2 additions & 2 deletions packages/mdx/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,8 @@ return {no, default: MDXContent}

###### `options.baseUrl`

Resolve relative `import` (and `export … from`) from this URL (`string?`,
example: `import.meta.url`).
Resolve `import`s (and `export … from`, and `import.meta.url`) from this URL
(`string?`, example: `import.meta.url`).

Relative specifiers are non-absolute URLs that start with `/`, `./`, or `../`.
For example: `/index.js`, `./folder/file.js`, or `../main.js`.
Expand Down
2 changes: 2 additions & 0 deletions packages/mdx/test/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ test('compile', async () => {
)
}

console.log('\nnote: the following warning is expected!\n')
assert.equal(
renderToStaticMarkup(
React.createElement(
Expand All @@ -545,6 +546,7 @@ test('compile', async () => {
'<a></a>',
'should render if a used member is defined locally (JSX in a function)'
)
console.log('\nnote: the preceding warning is expected!\n')

try {
renderToStaticMarkup(
Expand Down
11 changes: 11 additions & 0 deletions packages/mdx/test/evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,17 @@ test('evaluate', async () => {
'should support an `export all from`, but prefer explicit exports, w/ `useDynamicImport`'
)

assert.equal(
(
await evaluate(
'export const x = new URL("example.png", import.meta.url).href',
{baseUrl: 'https://example.com', ...runtime}
)
).x,
'https://example.com/example.png',
'should support rewriting `import.meta.url` w/ `baseUrl`'
)

assert.throws(
() => {
evaluateSync('export * from "a"', runtime)
Expand Down

1 comment on commit f77c33f

@vercel
Copy link

@vercel vercel bot commented on f77c33f Apr 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

mdx – ./

v2.mdxjs.com
mdxjs.com
mdx-mdx.vercel.app
mdx-git-main-mdx.vercel.app

Please sign in to comment.