diff --git a/package-lock.json b/package-lock.json index b2a14c9ac..1a5457dfc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28397,6 +28397,7 @@ "dependencies": { "@mdx-js/mdx": "^3.0.0", "@types/unist": "^3.0.0", + "source-map": "^0.7.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" }, @@ -28478,6 +28479,7 @@ "license": "MIT", "dependencies": { "@mdx-js/mdx": "^3.0.0", + "source-map": "^0.7.0", "vfile": "^6.0.0" }, "devDependencies": {}, diff --git a/packages/esbuild/lib/index.js b/packages/esbuild/lib/index.js index c839203f6..1c26af65b 100644 --- a/packages/esbuild/lib/index.js +++ b/packages/esbuild/lib/index.js @@ -43,6 +43,7 @@ import fs from 'node:fs/promises' import path from 'node:path' import {createFormatAwareProcessors} from '@mdx-js/mdx/internal-create-format-aware-processors' import {extnamesToRegex} from '@mdx-js/mdx/internal-extnames-to-regex' +import {SourceMapGenerator} from 'source-map' import {VFile} from 'vfile' import {VFileMessage} from 'vfile-message' @@ -65,7 +66,10 @@ const name = '@mdx-js/esbuild' * Plugin. */ export function esbuild(options) { - const {extnames, process} = createFormatAwareProcessors(options || {}) + const {extnames, process} = createFormatAwareProcessors({ + ...options, + SourceMapGenerator + }) return {name, setup} @@ -96,7 +100,7 @@ export function esbuild(options) { /** @type {State} */ const state = {doc: document, name, path: data.path} let file = new VFile({path: data.path, value: document}) - /** @type {Value | undefined} */ + /** @type {string | undefined} */ let value /** @type {Array} */ let messages = [] @@ -107,7 +111,11 @@ export function esbuild(options) { try { file = await process(file) - value = file.value + value = + String(file.value) + + '\n//# sourceMappingURL=data:application/json;base64,' + + Buffer.from(JSON.stringify(file.map)).toString('base64') + + '\n' messages = file.messages } catch (error_) { const cause = /** @type {VFileMessage | Error} */ (error_) diff --git a/packages/esbuild/package.json b/packages/esbuild/package.json index 3853216ad..e1746928e 100644 --- a/packages/esbuild/package.json +++ b/packages/esbuild/package.json @@ -40,6 +40,7 @@ "dependencies": { "@mdx-js/mdx": "^3.0.0", "@types/unist": "^3.0.0", + "source-map": "^0.7.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" }, @@ -48,7 +49,7 @@ }, "scripts": { "test": "npm run test-coverage", - "test-api": "node --conditions development test/index.js", + "test-api": "node --conditions development --enable-source-maps test/index.js", "test-coverage": "c8 --100 --reporter lcov npm run test-api" }, "xo": { diff --git a/packages/esbuild/test/index.js b/packages/esbuild/test/index.js index 0769794d5..172f78ff6 100644 --- a/packages/esbuild/test/index.js +++ b/packages/esbuild/test/index.js @@ -539,6 +539,44 @@ test('@mdx-js/esbuild', async function (t) { await fs.rm(jsUrl) } ) + + await t.test('should support source maps', async () => { + const mdxUrl = new URL('crash.mdx', import.meta.url) + const jsUrl = new URL('crash.js', import.meta.url) + await fs.writeFile( + mdxUrl, + '\nexport function Throw() { throw new Error("Boom") }\n' + ) + + await esbuild.build({ + entryPoints: [fileURLToPath(mdxUrl)], + outfile: fileURLToPath(jsUrl), + plugins: [esbuildMdx()], + define: {'process.env.NODE_ENV': '"development"'}, + format: 'esm', + sourcemap: true, + bundle: true + }) + + /** @type {MDXModule} */ + const result = await import(jsUrl.href) + const Content = result.default + + assert.throws( + () => renderToStaticMarkup(React.createElement(Content)), + (error) => { + assert(error instanceof Error) + assert.equal(error.message, 'Boom') + // Source maps are off. + // The column should be 26, not 8. + assert(error.stack?.includes('crash.mdx:2:8)')) + return true + } + ) + + await fs.rm(mdxUrl) + await fs.rm(jsUrl) + }) }) /**