|
1 | 1 | "use strict";
|
2 | 2 |
|
3 | 3 | const path = require("path");
|
| 4 | +const utils = require("loader-utils"); |
4 | 5 |
|
5 |
| -// libsass uses this precedence when importing files without extension |
6 |
| -const extPrecedence = [".scss", ".sass", ".css"]; |
| 6 | +const matchModuleImport = /^~([^\/]+|@[^\/]+[\/][^\/]+)$/g; |
7 | 7 |
|
8 | 8 | /**
|
9 | 9 | * When libsass tries to resolve an import, it uses a special algorithm.
|
10 | 10 | * Since the sass-loader uses webpack to resolve the modules, we need to simulate that algorithm. This function
|
11 |
| - * returns an array of import paths to try. |
| 11 | + * returns an array of import paths to try. The first entry in the array is always the original url |
| 12 | + * to enable straight-forward webpack.config aliases. |
12 | 13 | *
|
13 |
| - * @param {string} request |
| 14 | + * @param {string} url |
14 | 15 | * @returns {Array<string>}
|
15 | 16 | */
|
16 |
| -function importsToResolve(request) { |
| 17 | +function importsToResolve(url) { |
| 18 | + const request = utils.urlToRequest(url); |
| 19 | + // Keep in mind: ext can also be something like '.datepicker' when the true extension is omitted and the filename contains a dot. |
| 20 | + // @see https://github.com/webpack-contrib/sass-loader/issues/167 |
| 21 | + const ext = path.extname(request); |
| 22 | + |
| 23 | + if (matchModuleImport.test(url)) { |
| 24 | + return [url, request]; |
| 25 | + } |
| 26 | + |
17 | 27 | // libsass' import algorithm works like this:
|
18 |
| - // In case there is no file extension... |
19 |
| - // - Prefer modules starting with '_'. |
20 |
| - // - File extension precedence: .scss, .sass, .css. |
| 28 | + |
21 | 29 | // In case there is a file extension...
|
22 | 30 | // - If the file is a CSS-file, do not include it all, but just link it via @import url().
|
23 | 31 | // - The exact file name must match (no auto-resolving of '_'-modules).
|
| 32 | + if (ext === ".css") { |
| 33 | + return []; |
| 34 | + } |
| 35 | + if (ext === ".scss" || ext === ".sass") { |
| 36 | + return [url, request]; |
| 37 | + } |
24 | 38 |
|
25 |
| - // Keep in mind: ext can also be something like '.datepicker' when the true extension is omitted and the filename contains a dot. |
26 |
| - // @see https://github.com/webpack-contrib/sass-loader/issues/167 |
27 |
| - const ext = path.extname(request); |
| 39 | + // In case there is no file extension... |
| 40 | + // - Prefer modules starting with '_'. |
| 41 | + // - File extension precedence: .scss, .sass, .css. |
28 | 42 | const basename = path.basename(request);
|
29 |
| - const dirname = path.dirname(request); |
30 |
| - const startsWithUnderscore = basename.charAt(0) === "_"; |
31 |
| - const hasCssExt = ext === ".css"; |
32 |
| - const hasSassExt = ext === ".scss" || ext === ".sass"; |
33 |
| - |
34 |
| - // a module import is an identifier like 'bootstrap-sass' |
35 |
| - // We also need to check for dirname since it might also be a deep import like 'bootstrap-sass/something' |
36 |
| - let isModuleImport = request.charAt(0) !== "." && dirname === "."; |
37 |
| - |
38 |
| - if (dirname.charAt(0) === "@") { |
39 |
| - // Check whether it is a deep import from scoped npm package |
40 |
| - // (i.e. @pkg/foo/file), if so, process import as file import; |
41 |
| - // otherwise, if we import from root npm scoped package (i.e. @pkg/foo) |
42 |
| - // process import as a module import. |
43 |
| - isModuleImport = !(dirname.indexOf("/") > -1); |
| 43 | + |
| 44 | + if (basename.charAt(0) === "_") { |
| 45 | + return [ |
| 46 | + url, |
| 47 | + `${ request }.scss`, `${ request }.sass`, `${ request }.css` |
| 48 | + ]; |
44 | 49 | }
|
45 | 50 |
|
46 |
| - return (isModuleImport && [request]) || // Do not modify module imports |
47 |
| - (hasCssExt && []) || // Do not import css files |
48 |
| - (hasSassExt && [request]) || // Do not modify imports with explicit extensions |
49 |
| - (startsWithUnderscore ? [] : extPrecedence) // Do not add underscore imports if there is already an underscore |
50 |
| - .map(ext => "_" + basename + ext) |
51 |
| - .concat( |
52 |
| - extPrecedence.map(ext => basename + ext) |
53 |
| - ).map( |
54 |
| - file => dirname + "/" + file // No path.sep required here, because imports inside SASS are usually with / |
55 |
| - ); |
| 51 | + const dirname = path.dirname(request); |
| 52 | + |
| 53 | + return [ |
| 54 | + url, |
| 55 | + `${ dirname }/_${ basename }.scss`, `${ dirname }/_${ basename }.sass`, `${ dirname }/_${ basename }.css`, |
| 56 | + `${ request }.scss`, `${ request }.sass`, `${ request }.css` |
| 57 | + ]; |
56 | 58 | }
|
57 | 59 |
|
58 | 60 | module.exports = importsToResolve;
|
0 commit comments