diff --git a/.changeset/curly-badgers-boil.md b/.changeset/curly-badgers-boil.md new file mode 100644 index 000000000000..f7fc51ecb9c9 --- /dev/null +++ b/.changeset/curly-badgers-boil.md @@ -0,0 +1,16 @@ +--- +"@astrojs/mdx": patch +--- + +Fixes an issue where images in MDX required a relative specifier (e.g. `./`) + +Now, you can use the standard `![](img.png)` syntax in MDX files for images colocated in the same folder: no relative specifier required! + +There is no need to update your project; your existing images will still continue to work. However, you may wish to remove any relative specifiers from these MDX images as they are no longer necessary: + +```diff +- ![A cute dog](./dog.jpg) ++ ![A cute dog](dog.jpg) + +``` + diff --git a/packages/integrations/mdx/src/index.ts b/packages/integrations/mdx/src/index.ts index bdf1c90627f2..db7f6413451f 100644 --- a/packages/integrations/mdx/src/index.ts +++ b/packages/integrations/mdx/src/index.ts @@ -106,6 +106,13 @@ export default function mdx(partialMdxOptions: Partial = {}): AstroI } } }, + async resolveId(source, importer, options) { + if (importer?.endsWith('.mdx') && source[0] !== '/') { + let resolved = await this.resolve(source, importer, options); + if (!resolved) resolved = await this.resolve('./' + source, importer, options); + return resolved; + } + }, // Override transform to alter code before MDX compilation // ex. inject layouts async transform(_, id) { diff --git a/packages/integrations/mdx/src/remark-images-to-component.ts b/packages/integrations/mdx/src/remark-images-to-component.ts index 4ab6a0422e90..46d04d443341 100644 --- a/packages/integrations/mdx/src/remark-images-to-component.ts +++ b/packages/integrations/mdx/src/remark-images-to-component.ts @@ -24,7 +24,6 @@ export function remarkImageToComponent() { // If we haven't already imported this image, add an import statement if (!importName) { importName = `__${importedImages.size}_${node.url.replace(/\W/g, '_')}__`; - importsStatements.push({ type: 'mdxjsEsm', value: '', @@ -35,7 +34,11 @@ export function remarkImageToComponent() { body: [ { type: 'ImportDeclaration', - source: { type: 'Literal', value: node.url, raw: JSON.stringify(node.url) }, + source: { + type: 'Literal', + value: node.url, + raw: JSON.stringify(node.url), + }, specifiers: [ { type: 'ImportDefaultSpecifier', diff --git a/packages/integrations/mdx/test/fixtures/mdx-images/src/pages/houston.png b/packages/integrations/mdx/test/fixtures/mdx-images/src/pages/houston.png new file mode 100644 index 000000000000..345ed0e9de1e Binary files /dev/null and b/packages/integrations/mdx/test/fixtures/mdx-images/src/pages/houston.png differ diff --git a/packages/integrations/mdx/test/fixtures/mdx-images/src/pages/index.mdx b/packages/integrations/mdx/test/fixtures/mdx-images/src/pages/index.mdx index b34d50b7ce37..de126a6a0fa0 100644 --- a/packages/integrations/mdx/test/fixtures/mdx-images/src/pages/index.mdx +++ b/packages/integrations/mdx/test/fixtures/mdx-images/src/pages/index.mdx @@ -9,3 +9,9 @@ Image with a title: Image with spaces in the path: ![Houston](<~/assets/houston in space.webp>) + +Image using a relative path with no slashes: +![Houston](houston.png) + +Image using a relative path with nested directory: +![Houston](relative/houston.png) diff --git a/packages/integrations/mdx/test/fixtures/mdx-images/src/pages/relative/houston.png b/packages/integrations/mdx/test/fixtures/mdx-images/src/pages/relative/houston.png new file mode 100644 index 000000000000..345ed0e9de1e Binary files /dev/null and b/packages/integrations/mdx/test/fixtures/mdx-images/src/pages/relative/houston.png differ diff --git a/packages/integrations/mdx/test/mdx-images.test.js b/packages/integrations/mdx/test/mdx-images.test.js index d4af271ec55f..3d544f855950 100644 --- a/packages/integrations/mdx/test/mdx-images.test.js +++ b/packages/integrations/mdx/test/mdx-images.test.js @@ -29,7 +29,7 @@ describe('MDX Page', () => { const { document } = parseHTML(html); const imgs = document.getElementsByTagName('img'); - assert.equal(imgs.length, 4); + assert.equal(imgs.length, 6); // Image using a relative path assert.equal(imgs.item(0).src.startsWith('/_image'), true); // Image using an aliased path @@ -38,6 +38,10 @@ describe('MDX Page', () => { assert.equal(imgs.item(2).title, 'Houston title'); // Image with spaces in the path assert.equal(imgs.item(3).src.startsWith('/_image'), true); + // Image using a relative path with no slashes + assert.equal(imgs.item(4).src.startsWith('/_image'), true); + // Image using a relative path with nested directory + assert.equal(imgs.item(5).src.startsWith('/_image'), true); }); for (const route of imageTestRoutes) {