diff --git a/packages/loader/lib/index.js b/packages/loader/lib/index.js index ba961f215..86bbb7a43 100644 --- a/packages/loader/lib/index.js +++ b/packages/loader/lib/index.js @@ -1,6 +1,7 @@ /** * @typedef {import('vfile').VFileCompatible} VFileCompatible * @typedef {import('vfile').VFile} VFile + * @typedef {import('vfile-message').VFileMessage} VFileMessage * @typedef {import('@mdx-js/mdx').CompileOptions} CompileOptions * @typedef {Pick} Defaults * @typedef {Omit} Options @@ -10,6 +11,7 @@ */ import {createHash} from 'node:crypto' +import path from 'node:path'; import {SourceMapGenerator} from 'source-map' import {createFormatAwareProcessors} from '@mdx-js/mdx/lib/util/create-format-aware-processors.js' @@ -62,10 +64,16 @@ export function loader(value, callback) { map.set(hash, process) } - process({value, path: this.resourcePath}).then((file) => { - callback(null, file.value, file.map) - return file - }, callback) + process({value, path: this.resourcePath}).then( + (file) => { + callback(null, file.value, file.map) + }, + (/** @type VFileMessage */ e) => { + const fpath = path.relative(this.context, this.resourcePath); + e.message = `${fpath}:${e.name}: ${e.message}`; + callback(e); + } + ) } /** diff --git a/packages/loader/test/index.test.js b/packages/loader/test/index.test.js index 21a26b11e..a44b77b78 100644 --- a/packages/loader/test/index.test.js +++ b/packages/loader/test/index.test.js @@ -22,13 +22,49 @@ test('@mdx-js/loader', async () => { // Setup. const base = new URL('.', import.meta.url) + await fs.writeFile( + new URL('webpack.mdx', base), + '# Hello, {' + ) + + // Errors. + const failedResult = await promisify(webpack)({ + // @ts-expect-error To do: webpack types miss support for `context`. + context: fileURLToPath(base), + entry: './webpack.mdx', + mode: 'none', + module: { + rules: [ + { + test: /\.mdx$/, + use: [fileURLToPath(new URL('../index.cjs', import.meta.url))] + } + ] + }, + output: { + path: fileURLToPath(base), + filename: 'react.cjs', + libraryTarget: 'commonjs' + } + }) + + const error = failedResult?.toJson()?.errors?.[0] + + assert.ok(error); + assert.equal( + error.message, + `Module build failed (from ../index.cjs): +webpack.mdx:1:22: Unexpected end of file in expression, expected a corresponding closing brace for \`{\``, + 'received expected error message' + ) + await fs.writeFile( new URL('webpack.mdx', base), 'export const Message = () => <>World!\n\n# Hello, ' ) // React. - await promisify(webpack)({ + const reactBuild = await promisify(webpack)({ // @ts-expect-error To do: webpack types miss support for `context`. context: fileURLToPath(base), entry: './webpack.mdx', @@ -48,6 +84,8 @@ test('@mdx-js/loader', async () => { } }) + assert.not.ok(reactBuild?.hasErrors()) + // One for ESM loading CJS, one for webpack. const modReact = /** @type {{default: {default: MDXContent}}} */ ( // @ts-expect-error file is dynamically generated @@ -63,7 +101,7 @@ test('@mdx-js/loader', async () => { await fs.unlink(new URL('react.cjs', base)) // Preact and source maps - await promisify(webpack)({ + const preactBuild = await promisify(webpack)({ // @ts-expect-error To do: webpack types miss support for `context`. context: fileURLToPath(base), entry: './webpack.mdx', @@ -89,6 +127,9 @@ test('@mdx-js/loader', async () => { } }) + assert.not.ok(preactBuild?.hasErrors()) + + // One for ESM loading CJS, one for webpack. const modPreact = /** @type {{default: {default: PreactComponent}}} */ ( // @ts-expect-error file is dynamically generated. @@ -110,7 +151,7 @@ test('@mdx-js/loader', async () => { await fs.unlink(new URL('preact.cjs', base)) // Vue. - await promisify(webpack)({ + const vueBuild = await promisify(webpack)({ // @ts-expect-error To do: webpack types miss support for `context`. context: fileURLToPath(base), entry: './webpack.mdx', @@ -140,6 +181,8 @@ test('@mdx-js/loader', async () => { } }) + assert.not.ok(vueBuild?.hasErrors()) + // One for ESM loading CJS, one for webpack. const modVue = /** @type {{default: {default: VueComponent}}} */ ( // @ts-expect-error file is dynamically generated