diff --git a/lint-staged.config.js b/lint-staged.config.js index 45fc4c0..9b355d0 100644 --- a/lint-staged.config.js +++ b/lint-staged.config.js @@ -1,4 +1,4 @@ module.exports = { - "*": ["prettier --write --ignore-unknown", "cspell"], + "*": ["prettier --write --ignore-unknown", "cspell --no-must-find-files"], "*.{js}": ["eslint --cache --fix"], }; diff --git a/src/LessError.js b/src/LessError.js deleted file mode 100644 index 59b7c3d..0000000 --- a/src/LessError.js +++ /dev/null @@ -1,39 +0,0 @@ -import path from "path"; - -class LessError extends Error { - constructor(error) { - super(); - - this.message = [ - "\n", - ...LessError.getFileExcerptIfPossible(error), - error.message.charAt(0).toUpperCase() + error.message.slice(1), - error.filename - ? ` Error in ${path.normalize(error.filename)} (line ${ - error.line - }, column ${error.column})` - : "", - ].join("\n"); - - this.hideStack = true; - } - - static getFileExcerptIfPossible(lessError) { - if (typeof lessError.extract === "undefined") { - return []; - } - - const excerpt = lessError.extract.slice(0, 2); - const column = Math.max(lessError.column - 1, 0); - - if (typeof excerpt[0] === "undefined") { - excerpt.shift(); - } - - excerpt.push(`${new Array(column).join(" ")}^`); - - return excerpt; - } -} - -export default LessError; diff --git a/src/index.js b/src/index.js index fa3c200..3b254bc 100644 --- a/src/index.js +++ b/src/index.js @@ -6,8 +6,8 @@ import { isUnsupportedUrl, normalizeSourceMap, getLessImplementation, + errorFactory, } from "./utils"; -import LessError from "./LessError"; async function lessLoader(source) { const options = this.getOptions(schema); @@ -78,7 +78,7 @@ async function lessLoader(source) { this.addDependency(path.normalize(error.filename)); } - callback(new LessError(error)); + callback(errorFactory(error)); return; } finally { diff --git a/src/utils.js b/src/utils.js index d742385..ed03364 100644 --- a/src/utils.js +++ b/src/utils.js @@ -240,9 +240,46 @@ function getLessImplementation(loaderContext, implementation) { return resolvedImplementation; } +function getFileExcerptIfPossible(error) { + if (typeof error.extract === "undefined") { + return []; + } + + const excerpt = error.extract.slice(0, 2); + const column = Math.max(error.column - 1, 0); + + if (typeof excerpt[0] === "undefined") { + excerpt.shift(); + } + + excerpt.push(`${new Array(column).join(" ")}^`); + + return excerpt; +} + +function errorFactory(error) { + const message = [ + "\n", + ...getFileExcerptIfPossible(error), + error.message.charAt(0).toUpperCase() + error.message.slice(1), + error.filename + ? ` Error in ${path.normalize(error.filename)} (line ${ + error.line + }, column ${error.column})` + : "", + ].join("\n"); + + const obj = new Error(message, { cause: error }); + + obj.stack = null; + + return obj; +} + export { getLessOptions, isUnsupportedUrl, normalizeSourceMap, getLessImplementation, + errorFactory, }; diff --git a/test/__snapshots__/loader.test.js.snap b/test/__snapshots__/loader.test.js.snap index e6ca568..bd9a3ec 100644 --- a/test/__snapshots__/loader.test.js.snap +++ b/test/__snapshots__/loader.test.js.snap @@ -431,6 +431,15 @@ exports[`loader should resolve unresolved url with alias: errors 1`] = `[]`; exports[`loader should resolve unresolved url with alias: warnings 1`] = `[]`; +exports[`loader should throw an error: errors 1`] = ` +[ + "ModuleBuildError: Module build failed (from \`replaced original path\`): +", +] +`; + +exports[`loader should throw an error: warnings 1`] = `[]`; + exports[`loader should transform urls: css 1`] = ` ".img4 { background: url(folder/img.jpg); diff --git a/test/fixtures/broken.less b/test/fixtures/broken.less new file mode 100644 index 0000000..53633c2 --- /dev/null +++ b/test/fixtures/broken.less @@ -0,0 +1 @@ +broken; diff --git a/test/loader.test.js b/test/loader.test.js index 2b6a71f..487cc54 100644 --- a/test/loader.test.js +++ b/test/loader.test.js @@ -991,4 +991,13 @@ describe("loader", () => { expect(getWarnings(stats)).toMatchSnapshot("warnings"); expect(getErrors(stats)).toMatchSnapshot("errors"); }); + + it("should throw an error", async () => { + const testId = "./broken.less"; + const compiler = getCompiler(testId); + const stats = await compile(compiler); + + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + }); });