From 24021cdb9dc0496fcebd6966516ff66584525cf3 Mon Sep 17 00:00:00 2001 From: Alexey Lavinsky Date: Fri, 17 Apr 2020 19:38:40 +0300 Subject: [PATCH] fix: import alias without tilde (#335) --- package-lock.json | 47 +++++++++++++++++-- package.json | 1 + src/createWebpackLessPlugin.js | 37 +++++++++++++-- test/__snapshots__/index.test.js.snap | 12 +++-- .../fixtures/less/import-webpack-aliases.less | 11 +++++ test/helpers/createSpec.js | 2 + test/helpers/getErrors.js | 5 ++ test/helpers/normalizeErrors.js | 24 ++++++++++ test/index.test.js | 9 ++-- 9 files changed, 133 insertions(+), 15 deletions(-) create mode 100644 test/fixtures/less/import-webpack-aliases.less create mode 100644 test/helpers/getErrors.js create mode 100644 test/helpers/normalizeErrors.js diff --git a/package-lock.json b/package-lock.json index 0414f9d3..6da50fb3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2694,6 +2694,17 @@ "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } } }, "js-tokens": { @@ -3456,6 +3467,17 @@ "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } } } } @@ -9860,6 +9882,15 @@ "chalk": "^1.0.0" } }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -12723,12 +12754,20 @@ "dev": true }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + } } }, "strip-bom": { diff --git a/package.json b/package.json index 6e08a927..ea7504f8 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "npm-run-all": "^4.1.5", "prettier": "^2.0.4", "standard-version": "^7.0.1", + "strip-ansi": "^6.0.0", "webpack": "^4.42.1" }, "keywords": [ diff --git a/src/createWebpackLessPlugin.js b/src/createWebpackLessPlugin.js index 643d8b58..11393307 100644 --- a/src/createWebpackLessPlugin.js +++ b/src/createWebpackLessPlugin.js @@ -31,7 +31,7 @@ function createWebpackLessPlugin(loaderContext) { const resolve = loaderContext.getResolve({ mainFields: ['less', 'style', 'main', '...'], mainFiles: ['_index', 'index', '...'], - extensions: ['.less', '.css', '...'], + extensions: ['.less', '.css'], }); class WebpackFileManager extends less.FileManager { @@ -61,7 +61,27 @@ function createWebpackLessPlugin(loaderContext) { return filename; } - async loadFile(filename, currentDirectory, options) { + resolveRequests(context, possibleRequests) { + if (possibleRequests.length === 0) { + return Promise.reject(); + } + + return resolve(context, possibleRequests[0]) + .then((result) => { + return result; + }) + .catch((error) => { + const [, ...tailPossibleRequests] = possibleRequests; + + if (tailPossibleRequests.length === 0) { + throw error; + } + + return this.resolveRequests(context, tailPossibleRequests); + }); + } + + async loadFile(filename, currentDirectory, options, ...args) { const url = this.getUrl(filename, options); const moduleRequest = urlToRequest( @@ -71,7 +91,18 @@ function createWebpackLessPlugin(loaderContext) { // Less is giving us trailing slashes, but the context should have no trailing slash const context = currentDirectory.replace(trailingSlash, ''); - const resolvedFilename = await resolve(context, moduleRequest); + let resolvedFilename; + + try { + resolvedFilename = await this.resolveRequests(context, [ + moduleRequest, + url, + ]); + } catch (error) { + loaderContext.emitError(error); + + return super.loadFile(filename, currentDirectory, options, ...args); + } loaderContext.addDependency(resolvedFilename); diff --git a/test/__snapshots__/index.test.js.snap b/test/__snapshots__/index.test.js.snap index 61deef45..15c02572 100644 --- a/test/__snapshots__/index.test.js.snap +++ b/test/__snapshots__/index.test.js.snap @@ -11,14 +11,18 @@ exports[`should fail if a file is tried to be loaded from include paths and with in /test/fixtures/less/error-mixed-resolvers.less (line 3, column 0)" `; -exports[`should provide a useful error message if the import could not be found 1`] = ` -"Module build failed (from ./src/cjs.js): +exports[`should provide a useful error message if the import could not be found: errors 1`] = ` +Array [ + "ModuleBuildError: Module build failed (from \`replaced original path\`): @import \\"not-existing\\"; ^ -Can't resolve './not-existing.less' in '/test/fixtures/less' - in /test/fixtures/less/error-import-not-existing.less (line 1, column 0)" +'not-existing' wasn't found. Tried - /test/fixtures/less/not-existing.less,npm://not-existing,npm://not-existing.less,not-existing.less + in /test/fixtures/less/error-import-not-existing.less (line 1, column 0)", + "ModuleError: Module Error (from \`replaced original path\`): +Can't resolve 'not-existing.less' in '/test/fixtures/less'", +] `; exports[`should provide a useful error message if there was a syntax error 1`] = ` diff --git a/test/fixtures/less/import-webpack-aliases.less b/test/fixtures/less/import-webpack-aliases.less new file mode 100644 index 00000000..0703da01 --- /dev/null +++ b/test/fixtures/less/import-webpack-aliases.less @@ -0,0 +1,11 @@ +@import "~fileAlias"; +@import "~assets/folder/url-path.less"; +@import "assets/folder/url-path.less"; + +body { + background: url(assets/resources/circle.svg); +} + +.abs { + background: url(~assets/resources/circle.svg); +} diff --git a/test/helpers/createSpec.js b/test/helpers/createSpec.js index 62454fd4..79022af9 100644 --- a/test/helpers/createSpec.js +++ b/test/helpers/createSpec.js @@ -21,6 +21,8 @@ const ignore = [ ]; const lessReplacements = [ [/~some\//g, '../node_modules/some/'], + [/(~)?assets\//g, '../less/'], + [/~fileAlias/g, '../less/img.less'], [/~(aliased-)?some"/g, '../node_modules/some/module.less"'], ]; const cssReplacements = [[/\.\.\/node_modules\/some\//g, '~some/']]; diff --git a/test/helpers/getErrors.js b/test/helpers/getErrors.js new file mode 100644 index 00000000..085bae5b --- /dev/null +++ b/test/helpers/getErrors.js @@ -0,0 +1,5 @@ +import normalizeErrors from './normalizeErrors'; + +export default (stats) => { + return normalizeErrors(stats.compilation.errors).sort(); +}; diff --git a/test/helpers/normalizeErrors.js b/test/helpers/normalizeErrors.js new file mode 100644 index 00000000..36020766 --- /dev/null +++ b/test/helpers/normalizeErrors.js @@ -0,0 +1,24 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import stripAnsi from 'strip-ansi'; + +function removeCWD(str) { + const isWin = process.platform === 'win32'; + let cwd = process.cwd(); + + if (isWin) { + // eslint-disable-next-line no-param-reassign + str = str.replace(/\\/g, '/'); + // eslint-disable-next-line no-param-reassign + cwd = cwd.replace(/\\/g, '/'); + } + + return stripAnsi(str) + .replace(/\(from .*?\)/, '(from `replaced original path`)') + .replace(new RegExp(cwd, 'g'), ''); +} + +export default (errors) => { + return errors.map((error) => + removeCWD(error.toString().split('\n').slice(0, 12).join('\n')) + ); +}; diff --git a/test/index.test.js b/test/index.test.js index d2b0d455..2708f3bc 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -4,6 +4,7 @@ import compile from './helpers/compile'; import moduleRules from './helpers/moduleRules'; import { readCssFixture, readSourceMap } from './helpers/readFixture'; import compareErrorMessage from './helpers/compareErrorMessage'; +import getErrors from './helpers/getErrors'; const nodeModulesPath = path.resolve(__dirname, 'fixtures', 'node_modules'); @@ -88,10 +89,12 @@ test('should add all resolved imports as dependencies, including node_modules', ); }); -test('should resolve aliases as configured', async () => { +test('should resolve aliases in diffrent variants', async () => { await compileAndCompare('import-webpack-alias', { resolveAlias: { 'aliased-some': 'some', + fileAlias: path.resolve(__dirname, 'fixtures', 'less', 'img.less'), + assets: path.resolve(__dirname, 'fixtures', 'less'), }, }); }); @@ -300,9 +303,7 @@ test('should provide a useful error message if the import could not be found', a moduleRules.basic() ).catch((e) => e); - expect(err).toBeInstanceOf(Error); - - compareErrorMessage(err.message); + expect(getErrors(err.stats)).toMatchSnapshot('errors'); }); test('should provide a useful error message if there was a syntax error', async () => {