diff --git a/README.md b/README.md index b7786a9..2e91e3f 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ And run `webpack` via your preferred method. - **[`sourceMap`](#sourcemap)** - **[`webpackImporter`](#webpackimporter)** - **[`implementation`](#implementation)** +- **[`lessLogAsWarnAndErr`](#lesslogaswarnanderr)** ### `lessOptions` @@ -411,6 +412,52 @@ module.exports = { }; ``` +### `lessLogAsWarnOrErr` + +Type: + +```ts +type lessLogAsWarnOrErr = boolean; +``` + +Default: `false` + +`Less` warnings and errors will be webpack warnings and errors, not just logs. + +**warning.less** + +```less +div { + &:extend(.body1); +} +``` + +If `lessLogAsWarnOrErr` is set to `false` it will be just a log and webpack will compile successfully, but if you set this option to `true` webpack will compile fail with a warning. + +**webpack.config.js** + +```js +module.exports = { + module: { + rules: [ + { + test: /\.less$/i, + use: [ + "style-loader", + "css-loader", + { + loader: "less-loader", + options: { + lessLogAsWarnOrErr: true, + }, + }, + ], + }, + ], + }, +}; +``` + ## Examples ### Normal usage diff --git a/src/index.js b/src/index.js index f8f975e..b6f0431 100644 --- a/src/index.js +++ b/src/index.js @@ -52,12 +52,23 @@ async function lessLoader(source) { } const logger = this.getLogger("less-loader"); + const loaderContext = this; const loggerListener = { error(message) { - logger.error(message); + // TODO enable by default in the next major release + if (options.lessLogAsWarnOrErr) { + loaderContext.emitError(new Error(message)); + } else { + logger.error(message); + } }, warn(message) { - logger.warn(message); + // TODO enable by default in the next major release + if (options.lessLogAsWarnOrErr) { + loaderContext.emitWarning(new Error(message)); + } else { + logger.warn(message); + } }, info(message) { logger.log(message); diff --git a/src/options.json b/src/options.json index a21fdf7..36f18a9 100644 --- a/src/options.json +++ b/src/options.json @@ -48,6 +48,11 @@ "type": "object" } ] + }, + "lessLogAsWarnOrErr": { + "description": "Less warnings and errors will be webpack warnings or errors.", + "link": "https://github.com/webpack-contrib/less-loader#lesslogaswarnorerr", + "type": "boolean" } }, "additionalProperties": false diff --git a/test/__snapshots__/loader.test.js.snap b/test/__snapshots__/loader.test.js.snap index 74823d3..a385427 100644 --- a/test/__snapshots__/loader.test.js.snap +++ b/test/__snapshots__/loader.test.js.snap @@ -84,6 +84,17 @@ exports[`loader should emit an error: errors 1`] = ` exports[`loader should emit an error: warnings 1`] = `[]`; +exports[`loader should emit less warning as webpack warning: css 1`] = `""`; + +exports[`loader should emit less warning as webpack warning: errors 1`] = `[]`; + +exports[`loader should emit less warning as webpack warning: warnings 1`] = ` +[ + "ModuleWarning: Module Warning (from \`replaced original path\`): +extend ' .body1' has no matches", +] +`; + exports[`loader should get absolute path relative rootContext: css 1`] = ` ".box { color: #fe33ac; diff --git a/test/__snapshots__/validate-options.test.js.snap b/test/__snapshots__/validate-options.test.js.snap index fd57455..57ac7c0 100644 --- a/test/__snapshots__/validate-options.test.js.snap +++ b/test/__snapshots__/validate-options.test.js.snap @@ -114,6 +114,13 @@ exports[`validate options should throw an error on the "implementation" option w object { … }" `; +exports[`validate options should throw an error on the "lessLogAsWarnOrErr" option with "string" value 1`] = ` +"Invalid options object. Less Loader has been initialized using an options object that does not match the API schema. + - options.lessLogAsWarnOrErr should be a boolean. + -> Less warnings and errors will be webpack warnings or errors. + -> Read more at https://github.com/webpack-contrib/less-loader#lesslogaswarnorerr" +`; + exports[`validate options should throw an error on the "lessOptions" option with "[]" value 1`] = ` "Invalid options object. Less Loader has been initialized using an options object that does not match the API schema. - options.lessOptions should be one of these: @@ -184,49 +191,49 @@ exports[`validate options should throw an error on the "sourceMap" option with " exports[`validate options should throw an error on the "unknown" option with "/test/" value 1`] = ` "Invalid options object. Less Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation? }" + object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation?, lessLogAsWarnOrErr? }" `; exports[`validate options should throw an error on the "unknown" option with "[]" value 1`] = ` "Invalid options object. Less Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation? }" + object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation?, lessLogAsWarnOrErr? }" `; exports[`validate options should throw an error on the "unknown" option with "{"foo":"bar"}" value 1`] = ` "Invalid options object. Less Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation? }" + object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation?, lessLogAsWarnOrErr? }" `; exports[`validate options should throw an error on the "unknown" option with "{}" value 1`] = ` "Invalid options object. Less Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation? }" + object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation?, lessLogAsWarnOrErr? }" `; exports[`validate options should throw an error on the "unknown" option with "1" value 1`] = ` "Invalid options object. Less Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation? }" + object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation?, lessLogAsWarnOrErr? }" `; exports[`validate options should throw an error on the "unknown" option with "false" value 1`] = ` "Invalid options object. Less Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation? }" + object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation?, lessLogAsWarnOrErr? }" `; exports[`validate options should throw an error on the "unknown" option with "test" value 1`] = ` "Invalid options object. Less Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation? }" + object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation?, lessLogAsWarnOrErr? }" `; exports[`validate options should throw an error on the "unknown" option with "true" value 1`] = ` "Invalid options object. Less Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation? }" + object { lessOptions?, additionalData?, sourceMap?, webpackImporter?, implementation?, lessLogAsWarnOrErr? }" `; exports[`validate options should throw an error on the "webpackImporter" option with "string" value 1`] = ` diff --git a/test/fixtures/err.less b/test/fixtures/err.less new file mode 100644 index 0000000..3decd45 --- /dev/null +++ b/test/fixtures/err.less @@ -0,0 +1,6 @@ +div { + .m(@x) when (default()) {} + .m(@x) when not(default()) {} + + .m(1); // Error +} diff --git a/test/fixtures/warn.less b/test/fixtures/warn.less new file mode 100644 index 0000000..3381e77 --- /dev/null +++ b/test/fixtures/warn.less @@ -0,0 +1,3 @@ +div { + &:extend(.body1); +} diff --git a/test/loader.test.js b/test/loader.test.js index c57d5cf..55abed3 100644 --- a/test/loader.test.js +++ b/test/loader.test.js @@ -1047,4 +1047,17 @@ describe("loader", () => { expect(getWarnings(stats)).toMatchSnapshot("warnings"); expect(getErrors(stats)).toMatchSnapshot("errors"); }); + + it("should emit less warning as webpack warning", async () => { + const testId = "./warn.less"; + const compiler = getCompiler(testId, { + lessLogAsWarnOrErr: true, + }); + const stats = await compile(compiler); + const codeFromBundle = getCodeFromBundle(stats, compiler); + + expect(codeFromBundle.css).toMatchSnapshot("css"); + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + }); }); diff --git a/test/validate-options.test.js b/test/validate-options.test.js index a760dd2..c49be48 100644 --- a/test/validate-options.test.js +++ b/test/validate-options.test.js @@ -30,6 +30,10 @@ describe("validate options", () => { success: [require("less"), "less"], failure: [true, false, () => {}, []], }, + lessLogAsWarnOrErr: { + success: [true, false], + failure: ["string"], + }, unknown: { success: [], failure: [1, true, false, "test", /test/, [], {}, { foo: "bar" }],