Skip to content

Commit

Permalink
fix: resolution algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-akait committed Aug 15, 2019
1 parent 96f436f commit b59abe5
Show file tree
Hide file tree
Showing 103 changed files with 1,424 additions and 37 deletions.
51 changes: 37 additions & 14 deletions src/importsToResolve.js
Expand Up @@ -19,41 +19,64 @@ function importsToResolve(url) {
// @see https://github.com/webpack-contrib/sass-loader/issues/167
const ext = path.extname(request);

// In case there is module request, send this to webpack resolver
if (matchModuleImport.test(url)) {
return [request, url];
}

// libsass' import algorithm works like this:

// In case there is a file extension...
// - If the file is a CSS-file, do not include it all, but just link it via @import url().
// - The exact file name must match (no auto-resolving of '_'-modules).
// Because @import is also defined in CSS, Sass needs a way of compiling plain CSS @imports without trying to import the files at compile time.
// To accomplish this, and to ensure SCSS is as much of a superset of CSS as possible, Sass will compile any @imports with the following characteristics to plain CSS imports:
// - imports where the URL ends with .css.
// - imports where the URL begins http:// or https://.
// - imports where the URL is written as a url().
// - imports that have media queries.
//
// The `node-sass` package sends `@import` ending on `.css` to importer, it is bug, so we skip resolve
if (ext === '.css') {
return [];
}

const dirname = path.dirname(request);
const basename = path.basename(request);

// In case there is file extension:
//
// 1. Try to resolve `_` file.
// 2. Try to resolve file without `_`.
// 3. Send a original url to webpack resolver, maybe it is alias.
if (['.scss', '.sass'].includes(ext)) {
return [request, url];
return [`${dirname}/_${basename}`, `${dirname}/${basename}`, url];
}

// In case there is no file extension...
// - Prefer modules starting with '_'.
// - File extension precedence: .scss, .sass, .css.
const basename = path.basename(request);

// In case there is no file extension and filename starts with `_`:
//
// 1. Try to resolve files with `scss`, `sass` and `css` extensions.
// 2. Try to resolve directory with `_index` or `index` filename.
// 3. Send a original url to webpack resolver, maybe it is alias.
if (basename.charAt(0) === '_') {
return [`${request}.scss`, `${request}.sass`, `${request}.css`, url];
return [
`${request}.scss`,
`${request}.sass`,
`${request}.css`,
request,
url,
];
}

const dirname = path.dirname(request);

// In case there is no file extension and filename doesn't start with `_`:
//
// 1. Try to resolve file starts with `_` and with extensions
// 2. Try to resolve file with extensions
// 3. Try to resolve directory with `_index` or `index` filename.
// 4. Send a original url to webpack resolver, maybe it is alias.
return [
`${dirname}/_${basename}.scss`,
`${dirname}/_${basename}.sass`,
`${dirname}/_${basename}.css`,
`${request}.scss`,
`${request}.sass`,
`${request}.css`,
request,
url,
];
}
Expand Down
3 changes: 2 additions & 1 deletion src/index.js
Expand Up @@ -55,7 +55,8 @@ function loader(content) {
// Supported since v4.36.0
if (hasGetResolve(self)) {
resolve = this.getResolve({
mainFields: ['sass', 'style', '...'],
mainFields: ['sass', 'style', 'main', '...'],
mainFiles: ['_index', 'index', '...'],
extensions: ['.scss', '.sass', '.css', '...'],
});
}
Expand Down
144 changes: 136 additions & 8 deletions test/__snapshots__/loader.test.js.snap
Expand Up @@ -282,6 +282,22 @@ exports[`loader should work and ignore all css "@import" at-rules (node-sass) (s
exports[`loader should work and ignore all css "@import" at-rules (node-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "_index" file in package (dart-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "_index" file in package (dart-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work and use the "_index" file in package (dart-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work and use the "_index" file in package (dart-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "_index" file in package (node-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "_index" file in package (node-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work and use the "_index" file in package (node-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work and use the "_index" file in package (node-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "custom-sass" field (dart-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "custom-sass" field (dart-sass) (sass): warnings 1`] = `Array []`;
Expand All @@ -298,21 +314,53 @@ exports[`loader should work and use the "custom-sass" field (node-sass) (scss):
exports[`loader should work and use the "custom-sass" field (node-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" property in package (dart-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "index" file in package (dart-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "index" file in package (dart-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" file in package (dart-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work and use the "index" file in package (dart-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" file in package (node-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "index" file in package (node-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" file in package (node-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work and use the "index" file in package (node-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value already in the "mainFiles" resolve option (dart-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "index" property in package (dart-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value already in the "mainFiles" resolve option (dart-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" property in package (dart-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value already in the "mainFiles" resolve option (dart-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work and use the "index" property in package (dart-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value already in the "mainFiles" resolve option (dart-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" property in package (node-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value already in the "mainFiles" resolve option (node-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "index" property in package (node-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value already in the "mainFiles" resolve option (node-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" property in package (node-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value already in the "mainFiles" resolve option (node-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work and use the "index" property in package (node-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value already in the "mainFiles" resolve option (node-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value is not in the "mainFiles" resolve option (dart-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value is not in the "mainFiles" resolve option (dart-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value is not in the "mainFiles" resolve option (dart-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value is not in the "mainFiles" resolve option (dart-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value is not in the "mainFiles" resolve option (node-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value is not in the "mainFiles" resolve option (node-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value is not in the "mainFiles" resolve option (node-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work and use the "index" file in package when the "index" value is not in the "mainFiles" resolve option (node-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "main" field (dart-sass) (sass): errors 1`] = `Array []`;
Expand All @@ -330,6 +378,38 @@ exports[`loader should work and use the "main" field (node-sass) (scss): errors
exports[`loader should work and use the "main" field (node-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value already in the "mainFields" resolve option (dart-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value already in the "mainFields" resolve option (dart-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value already in the "mainFields" resolve option (dart-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value already in the "mainFields" resolve option (dart-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value already in the "mainFields" resolve option (node-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value already in the "mainFields" resolve option (node-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value already in the "mainFields" resolve option (node-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value already in the "mainFields" resolve option (node-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value is not in the "mainFields" resolve option (dart-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value is not in the "mainFields" resolve option (dart-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value is not in the "mainFields" resolve option (dart-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value is not in the "mainFields" resolve option (dart-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value is not in the "mainFields" resolve option (node-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value is not in the "mainFields" resolve option (node-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value is not in the "mainFields" resolve option (node-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work and use the "main" field when the "main" value is not in the "mainFields" resolve option (node-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work and use the "sass" field (dart-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work and use the "sass" field (dart-sass) (sass): warnings 1`] = `Array []`;
Expand Down Expand Up @@ -362,6 +442,54 @@ exports[`loader should work and use the "style" field (node-sass) (scss): errors
exports[`loader should work and use the "style" field (node-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work when "@import" at-rules starting with "_" (dart-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work when "@import" at-rules starting with "_" (dart-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work when "@import" at-rules starting with "_" (dart-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work when "@import" at-rules starting with "_" (dart-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work when "@import" at-rules starting with "_" (node-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work when "@import" at-rules starting with "_" (node-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work when "@import" at-rules starting with "_" (node-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work when "@import" at-rules starting with "_" (node-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work when "@import" at-rules with extensions (dart-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work when "@import" at-rules with extensions (dart-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work when "@import" at-rules with extensions (dart-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work when "@import" at-rules with extensions (dart-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work when "@import" at-rules with extensions (node-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work when "@import" at-rules with extensions (node-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work when "@import" at-rules with extensions (node-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work when "@import" at-rules with extensions (node-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work when "@import" at-rules without extensions and do not start with "_" (dart-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work when "@import" at-rules without extensions and do not start with "_" (dart-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work when "@import" at-rules without extensions and do not start with "_" (dart-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work when "@import" at-rules without extensions and do not start with "_" (dart-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work when "@import" at-rules without extensions and do not start with "_" (node-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work when "@import" at-rules without extensions and do not start with "_" (node-sass) (sass): warnings 1`] = `Array []`;
exports[`loader should work when "@import" at-rules without extensions and do not start with "_" (node-sass) (scss): errors 1`] = `Array []`;
exports[`loader should work when "@import" at-rules without extensions and do not start with "_" (node-sass) (scss): warnings 1`] = `Array []`;
exports[`loader should work when an "@import" at-rule from scoped npm packages (dart-sass) (sass): errors 1`] = `Array []`;
exports[`loader should work when an "@import" at-rule from scoped npm packages (dart-sass) (sass): warnings 1`] = `Array []`;
Expand Down

0 comments on commit b59abe5

Please sign in to comment.