Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: resolution algorithm #720

Merged
merged 1 commit into from Aug 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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