From f648f2d873b7b06daec07fb4fe516573ffd3bbe3 Mon Sep 17 00:00:00 2001 From: Remco Haszing Date: Tue, 12 Mar 2024 14:54:02 +0100 Subject: [PATCH 1/4] Support source maps in the node loader This allows people to debug MDX files when using the Node.js loader. --- packages/node-loader/lib/index.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/node-loader/lib/index.js b/packages/node-loader/lib/index.js index 890450004..657eca05c 100644 --- a/packages/node-loader/lib/index.js +++ b/packages/node-loader/lib/index.js @@ -61,8 +61,17 @@ export function createLoader(options) { if (url.protocol === 'file:' && regex.test(url.pathname)) { const value = await fs.readFile(url) const file = await process(new VFile({value, path: url})) + let source = String(file) + /* c8 ignore start -- not sure how to test this. */ + if (file.map) { + source += + '\n//# sourceMappingURL=data:application/json;base64,' + + Buffer.from(JSON.stringify(file.map)).toString('base64') + + '\n' + } + /* c8 ignore stop */ - return {format: 'module', shortCircuit: true, source: String(file)} + return {format: 'module', shortCircuit: true, source} } return nextLoad(href, context) From 85c53fb2e73183c010504f58438cfd87844402be Mon Sep 17 00:00:00 2001 From: Remco Haszing Date: Thu, 4 Apr 2024 14:21:46 +0200 Subject: [PATCH 2/4] Always use source maps in @mdx-js/node-loader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There’s not really a reason not to. --- packages/node-loader/lib/index.js | 4 ++- packages/node-loader/package.json | 3 +- packages/node-loader/test/index.js | 44 ++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/packages/node-loader/lib/index.js b/packages/node-loader/lib/index.js index 657eca05c..6bcca33d6 100644 --- a/packages/node-loader/lib/index.js +++ b/packages/node-loader/lib/index.js @@ -21,6 +21,7 @@ import fs from 'node:fs/promises' 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 {development as defaultDevelopment} from '#condition' @@ -36,7 +37,8 @@ export function createLoader(options) { const options_ = options || {} const {extnames, process} = createFormatAwareProcessors({ development: defaultDevelopment, - ...options_ + ...options_, + SourceMapGenerator }) const regex = extnamesToRegex(extnames) diff --git a/packages/node-loader/package.json b/packages/node-loader/package.json index ba29129aa..38e2e2bf6 100644 --- a/packages/node-loader/package.json +++ b/packages/node-loader/package.json @@ -44,12 +44,13 @@ ], "dependencies": { "@mdx-js/mdx": "^3.0.0", + "source-map": "^0.7.0", "vfile": "^6.0.0" }, "devDependencies": {}, "scripts": { "test": "npm run test-coverage", - "test-api": "node --conditions development --loader=@mdx-js/node-loader test/index.js", + "test-api": "node --conditions development --enable-source-maps --loader=@mdx-js/node-loader test/index.js", "test-coverage": "c8 --100 --reporter lcov npm run test-api" }, "xo": { diff --git a/packages/node-loader/test/index.js b/packages/node-loader/test/index.js index fa09d75ce..e160f0a30 100644 --- a/packages/node-loader/test/index.js +++ b/packages/node-loader/test/index.js @@ -52,4 +52,48 @@ test('@mdx-js/node-loader', async function (t) { await fs.rm(mdxUrl) }) + + await t.test('supports source maps work', async function () { + const mdxUrl = new URL('crash.mdx', import.meta.url) + + await fs.writeFile( + mdxUrl, + '\nexport function Throw() { throw new Error("Boom") }\n' + ) + + /** @type {MDXModule} */ + let result + + try { + result = await import(mdxUrl.href) + } catch (error) { + const exception = /** @type {NodeJS.ErrnoException} */ (error) + + if (exception.code === 'ERR_UNKNOWN_FILE_EXTENSION') { + await fs.rm(mdxUrl) + + throw new Error( + 'Please run Node with `--loader=@mdx-js/node-loader` to test the ESM loader' + ) + } + + throw error + } + + 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) + }) }) From f6c9317cef71f235bdb5ac8f067b0b767b1fd748 Mon Sep 17 00:00:00 2001 From: Remco Haszing Date: Thu, 4 Apr 2024 16:08:42 +0200 Subject: [PATCH 3/4] Fix test failure on Windows --- packages/node-loader/test/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/node-loader/test/index.js b/packages/node-loader/test/index.js index e160f0a30..9c68167e1 100644 --- a/packages/node-loader/test/index.js +++ b/packages/node-loader/test/index.js @@ -89,7 +89,7 @@ test('@mdx-js/node-loader', async function (t) { assert.equal(error.message, 'Boom') // Source maps are off. // The column should be 26, not 8. - assert(error.stack?.includes('/crash.mdx:2:8)')) + assert(error.stack?.includes('crash.mdx:2:8)')) return true } ) From 08acc226ff49e8d77185ee1a90e2885c08204ded Mon Sep 17 00:00:00 2001 From: Remco Haszing Date: Thu, 4 Apr 2024 16:14:49 +0200 Subject: [PATCH 4/4] Assume source maps exist in node-loader --- packages/node-loader/lib/index.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/node-loader/lib/index.js b/packages/node-loader/lib/index.js index 6bcca33d6..4acd3dfbd 100644 --- a/packages/node-loader/lib/index.js +++ b/packages/node-loader/lib/index.js @@ -63,17 +63,16 @@ export function createLoader(options) { if (url.protocol === 'file:' && regex.test(url.pathname)) { const value = await fs.readFile(url) const file = await process(new VFile({value, path: url})) - let source = String(file) - /* c8 ignore start -- not sure how to test this. */ - if (file.map) { - source += + + return { + format: 'module', + shortCircuit: true, + source: + String(file) + '\n//# sourceMappingURL=data:application/json;base64,' + Buffer.from(JSON.stringify(file.map)).toString('base64') + '\n' } - /* c8 ignore stop */ - - return {format: 'module', shortCircuit: true, source} } return nextLoad(href, context)