sass-loader 16.0.5 → 16.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -43
- package/dist/index.js +16 -16
- package/dist/options.json +7 -7
- package/dist/utils.js +138 -115
- package/package.json +75 -66
package/README.md
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
[![coverage][cover]][cover-url]
|
|
14
14
|
[![discussion][discussion]][discussion-url]
|
|
15
15
|
[![size][size]][size-url]
|
|
16
|
+
[![discord-invite][discord-invite]][discord-url]
|
|
16
17
|
|
|
17
18
|
# sass-loader
|
|
18
19
|
|
|
@@ -44,7 +45,7 @@ pnpm add -D sass-loader sass webpack
|
|
|
44
45
|
|
|
45
46
|
`sass-loader` requires you to install either [Dart Sass](https://github.com/sass/dart-sass), [Node Sass](https://github.com/sass/node-sass) on your own (more documentation can be found below) or [Sass Embedded](https://github.com/sass/embedded-host-node).
|
|
46
47
|
|
|
47
|
-
This allows you to control the versions of all your dependencies
|
|
48
|
+
This allows you to control the versions of all your dependencies and to choose which Sass implementation to use.
|
|
48
49
|
|
|
49
50
|
> [!NOTE]
|
|
50
51
|
>
|
|
@@ -54,7 +55,7 @@ This allows you to control the versions of all your dependencies, and to choose
|
|
|
54
55
|
>
|
|
55
56
|
> [Node Sass](https://github.com/sass/node-sass) does not work with [Yarn PnP](https://classic.yarnpkg.com/en/docs/pnp/) and doesn't support [@use rule](https://sass-lang.com/documentation/at-rules/use).
|
|
56
57
|
|
|
57
|
-
Chain the `sass-loader` with the [css-loader](https://github.com/webpack
|
|
58
|
+
Chain the `sass-loader` with the [css-loader](https://github.com/webpack/css-loader) and the [style-loader](https://github.com/webpack/style-loader) to immediately apply all styles to the DOM, or with the [mini-css-extract-plugin](https://github.com/webpack/mini-css-extract-plugin) to extract it into a separate file.
|
|
58
59
|
|
|
59
60
|
Then add the loader to your webpack configuration. For example:
|
|
60
61
|
|
|
@@ -96,7 +97,7 @@ module.exports = {
|
|
|
96
97
|
};
|
|
97
98
|
```
|
|
98
99
|
|
|
99
|
-
Finally run `webpack` via your preferred method.
|
|
100
|
+
Finally run `webpack` via your preferred method (e.g., via CLI or an npm script).
|
|
100
101
|
|
|
101
102
|
### The `style` (new API, by default since 16 version) and `outputStyle` (old API) options in `production` mode
|
|
102
103
|
|
|
@@ -106,13 +107,14 @@ For `production` mode, the `style` (new API, by default since 16 version) and `o
|
|
|
106
107
|
|
|
107
108
|
Webpack provides an [advanced mechanism to resolve files](https://webpack.js.org/concepts/module-resolution/).
|
|
108
109
|
|
|
109
|
-
The `sass-loader` uses Sass's custom importer feature to pass all queries to the webpack resolving engine enabling you to import your Sass modules from `node_modules`.
|
|
110
|
+
The `sass-loader` uses Sass's custom importer feature to pass all queries to the webpack resolving engine, enabling you to import your Sass modules from `node_modules`.
|
|
110
111
|
|
|
111
112
|
```scss
|
|
112
113
|
@import "bootstrap";
|
|
113
114
|
```
|
|
114
115
|
|
|
115
116
|
Using `~` is deprecated and should be removed from your code, but we still support it for historical reasons.
|
|
117
|
+
|
|
116
118
|
Why can you remove it? The loader will first try to resolve `@import` as a relative path. If it cannot be resolved, then the loader will try to resolve `@import` inside [`node_modules`](https://webpack.js.org/configuration/resolve/#resolvemodules).
|
|
117
119
|
|
|
118
120
|
Prepending module paths with a `~` tells webpack to search through [`node_modules`](https://webpack.js.org/configuration/resolve/#resolvemodules).
|
|
@@ -122,22 +124,25 @@ Prepending module paths with a `~` tells webpack to search through [`node_module
|
|
|
122
124
|
```
|
|
123
125
|
|
|
124
126
|
It's important to prepend the path with only `~`, because `~/` resolves to the home directory.
|
|
127
|
+
|
|
125
128
|
Webpack needs to distinguish between `bootstrap` and `~bootstrap` because CSS and Sass files have no special syntax for importing relative files.
|
|
129
|
+
|
|
126
130
|
Writing `@import "style.scss"` is the same as `@import "./style.scss";`
|
|
127
131
|
|
|
128
132
|
### Problems with `url(...)`
|
|
129
133
|
|
|
130
134
|
Since Sass implementations don't provide [url rewriting](https://github.com/sass/libsass/issues/532), all linked assets must be relative to the output.
|
|
131
135
|
|
|
132
|
-
- If you pass the generated CSS on to the `css-loader`, all
|
|
133
|
-
- If you're just generating CSS without passing it to the `css-loader`,
|
|
136
|
+
- If you pass the generated CSS on to the `css-loader`, all URLs must be relative to the entry-file (e.g. `main.scss`).
|
|
137
|
+
- If you're just generating CSS without passing it to the `css-loader`, URLs must be relative to your web root.
|
|
134
138
|
|
|
135
139
|
You might be surprised by this first issue, as it is natural to expect relative references to be resolved against the `.sass`/`.scss` file in which they are specified (like in regular `.css` files).
|
|
136
140
|
|
|
137
141
|
Thankfully there are two solutions to this problem:
|
|
138
142
|
|
|
139
|
-
- Add the missing
|
|
140
|
-
|
|
143
|
+
- Add the missing URL rewriting using the [resolve-url-loader](https://github.com/bholloway/resolve-url-loader). Place it before `sass-loader` in the loader chain.
|
|
144
|
+
|
|
145
|
+
- Library authors usually provide a variable to modify the asset path. [bootstrap-sass](https://github.com/twbs/bootstrap-sass) for example, has an `$icon-font-path`.
|
|
141
146
|
|
|
142
147
|
## Options
|
|
143
148
|
|
|
@@ -164,7 +169,7 @@ The special `implementation` option determines which implementation of Sass to u
|
|
|
164
169
|
By default, the loader resolves the implementation based on your dependencies.
|
|
165
170
|
Just add the desired implementation to your `package.json` (`sass`, `sass-embedded`, or `node-sass` package) and install dependencies.
|
|
166
171
|
|
|
167
|
-
Example where the `sass-loader`
|
|
172
|
+
Example where the `sass-loader` uses the `sass` (`dart-sass`) implementation:
|
|
168
173
|
|
|
169
174
|
**package.json**
|
|
170
175
|
|
|
@@ -177,7 +182,7 @@ Example where the `sass-loader` loader uses the `sass` (`dart-sass`) implementat
|
|
|
177
182
|
}
|
|
178
183
|
```
|
|
179
184
|
|
|
180
|
-
Example where the `sass-loader`
|
|
185
|
+
Example where the `sass-loader` uses the `node-sass` implementation:
|
|
181
186
|
|
|
182
187
|
**package.json**
|
|
183
188
|
|
|
@@ -190,7 +195,7 @@ Example where the `sass-loader` loader uses the `node-sass` implementation:
|
|
|
190
195
|
}
|
|
191
196
|
```
|
|
192
197
|
|
|
193
|
-
Example where the `sass-loader`
|
|
198
|
+
Example where the `sass-loader` uses the `sass-embedded` implementation:
|
|
194
199
|
|
|
195
200
|
**package.json**
|
|
196
201
|
|
|
@@ -208,8 +213,7 @@ Example where the `sass-loader` loader uses the `sass-embedded` implementation:
|
|
|
208
213
|
|
|
209
214
|
> [!NOTE]
|
|
210
215
|
>
|
|
211
|
-
> Using `optionalDependencies` means that `sass-loader` can fallback to `sass`
|
|
212
|
-
> when running on an operating system not supported by `sass-embedded`
|
|
216
|
+
> Using `optionalDependencies` means that `sass-loader` can fallback to `sass` when running on an operating system not supported by `sass-embedded`
|
|
213
217
|
|
|
214
218
|
Be aware of the order that `sass-loader` will resolve the implementation:
|
|
215
219
|
|
|
@@ -221,7 +225,7 @@ You can specify a specific implementation by using the `implementation` option,
|
|
|
221
225
|
|
|
222
226
|
#### `object`
|
|
223
227
|
|
|
224
|
-
For example, to always use Dart Sass
|
|
228
|
+
For example, to always use `Dart Sass`, you'd pass:
|
|
225
229
|
|
|
226
230
|
```js
|
|
227
231
|
module.exports = {
|
|
@@ -293,11 +297,11 @@ Options for [Dart Sass](http://sass-lang.com/dart-sass) or [Node Sass](https://g
|
|
|
293
297
|
|
|
294
298
|
> [!NOTE]
|
|
295
299
|
>
|
|
296
|
-
> The `charset` option is `true` by default for `dart-sass
|
|
300
|
+
> The `charset` option is `true` by default for `dart-sass`. We strongly discourage setting this to `false` because webpack doesn't support files other than `utf-8`.
|
|
297
301
|
|
|
298
302
|
> [!NOTE]
|
|
299
303
|
>
|
|
300
|
-
> The `syntax` (new API, by default since 16 version)
|
|
304
|
+
> The `syntax` (new API, by default since 16 version) and `indentedSyntax` (old API) option is `scss` for the `scss` extension, `indented` for the `sass` extension, and `css` for the `css` extension.
|
|
301
305
|
|
|
302
306
|
> [!NOTE]
|
|
303
307
|
>
|
|
@@ -336,7 +340,7 @@ module.exports = {
|
|
|
336
340
|
loader: "sass-loader",
|
|
337
341
|
options: {
|
|
338
342
|
sassOptions: {
|
|
339
|
-
style:
|
|
343
|
+
style: "compressed",
|
|
340
344
|
loadPaths: ["absolute/path/a", "absolute/path/b"],
|
|
341
345
|
},
|
|
342
346
|
},
|
|
@@ -398,7 +402,7 @@ type sourceMap = boolean;
|
|
|
398
402
|
|
|
399
403
|
Default: depends on the `compiler.devtool` value
|
|
400
404
|
|
|
401
|
-
Enables/
|
|
405
|
+
Enables/disables generation of source maps.
|
|
402
406
|
|
|
403
407
|
By default generation of source maps depends on the [`devtool`](https://webpack.js.org/configuration/devtool/) option.
|
|
404
408
|
All values enable source map generation except `eval` and `false`.
|
|
@@ -434,9 +438,9 @@ module.exports = {
|
|
|
434
438
|
};
|
|
435
439
|
```
|
|
436
440
|
|
|
437
|
-
> ℹ In some rare cases `node-sass` can output invalid source maps (
|
|
441
|
+
> ℹ In some rare cases `node-sass` can output invalid source maps (this is a `node-sass` bug).
|
|
438
442
|
>
|
|
439
|
-
> In order to avoid this, you can try to update `node-sass` to latest version, or you can try to set within `sassOptions` the `outputStyle` option to `compressed`.
|
|
443
|
+
> In order to avoid this, you can try to update `node-sass` to the latest version, or you can try to set within `sassOptions` the `outputStyle` option to `compressed`.
|
|
440
444
|
|
|
441
445
|
**webpack.config.js**
|
|
442
446
|
|
|
@@ -496,7 +500,7 @@ module.exports = {
|
|
|
496
500
|
{
|
|
497
501
|
loader: "sass-loader",
|
|
498
502
|
options: {
|
|
499
|
-
additionalData:
|
|
503
|
+
additionalData: `$env: ${process.env.NODE_ENV};`,
|
|
500
504
|
},
|
|
501
505
|
},
|
|
502
506
|
],
|
|
@@ -528,10 +532,10 @@ module.exports = {
|
|
|
528
532
|
const relativePath = path.relative(rootContext, resourcePath);
|
|
529
533
|
|
|
530
534
|
if (relativePath === "styles/foo.scss") {
|
|
531
|
-
return
|
|
535
|
+
return `$value: 100px;${content}`;
|
|
532
536
|
}
|
|
533
537
|
|
|
534
|
-
return
|
|
538
|
+
return `$value: 200px;${content}`;
|
|
535
539
|
},
|
|
536
540
|
},
|
|
537
541
|
},
|
|
@@ -562,10 +566,10 @@ module.exports = {
|
|
|
562
566
|
const relativePath = path.relative(rootContext, resourcePath);
|
|
563
567
|
|
|
564
568
|
if (relativePath === "styles/foo.scss") {
|
|
565
|
-
return
|
|
569
|
+
return `$value: 100px;${content}`;
|
|
566
570
|
}
|
|
567
571
|
|
|
568
|
-
return
|
|
572
|
+
return `$value: 200px;${content}`;
|
|
569
573
|
},
|
|
570
574
|
},
|
|
571
575
|
},
|
|
@@ -586,10 +590,10 @@ type webpackImporter = boolean;
|
|
|
586
590
|
|
|
587
591
|
Default: `true`
|
|
588
592
|
|
|
589
|
-
Enables/
|
|
593
|
+
Enables/disables the default webpack importer.
|
|
590
594
|
|
|
591
595
|
This can improve performance in some cases, though use it with caution because aliases and `@import` at-rules starting with `~` will not work.
|
|
592
|
-
You can pass your own `importer` to solve this (see [`importer docs
|
|
596
|
+
You can pass your own `importer` to solve this (see [`importer` docs](https://github.com/sass/node-sass#importer--v200---experimental)).
|
|
593
597
|
|
|
594
598
|
**webpack.config.js**
|
|
595
599
|
|
|
@@ -649,7 +653,7 @@ $known-prefixes: webkit, moz, ms, o;
|
|
|
649
653
|
}
|
|
650
654
|
```
|
|
651
655
|
|
|
652
|
-
The presented code will throw a webpack warning instead logging.
|
|
656
|
+
The presented code will throw a webpack warning instead of logging.
|
|
653
657
|
|
|
654
658
|
To ignore unnecessary warnings you can use the [ignoreWarnings](https://webpack.js.org/configuration/other-options/#ignorewarnings) option.
|
|
655
659
|
|
|
@@ -691,11 +695,11 @@ Allows you to switch between the `legacy` and `modern` APIs. You can find more i
|
|
|
691
695
|
|
|
692
696
|
> [!NOTE]
|
|
693
697
|
>
|
|
694
|
-
> Using `modern-compiler` and `sass-embedded` together significantly
|
|
698
|
+
> Using `modern-compiler` and `sass-embedded` together significantly improves performance and decreases build time. We strongly recommend their use. We will enable them by default in a future major release.
|
|
695
699
|
|
|
696
700
|
> [!WARNING]
|
|
697
701
|
>
|
|
698
|
-
> The
|
|
702
|
+
> The Sass options are different for the `legacy` and `modern` APIs. Please look at [docs](https://sass-lang.com/documentation/js-api) to learn how to migrate to the modern options.
|
|
699
703
|
|
|
700
704
|
**webpack.config.js**
|
|
701
705
|
|
|
@@ -726,7 +730,7 @@ module.exports = {
|
|
|
726
730
|
|
|
727
731
|
## How to enable `@debug` output
|
|
728
732
|
|
|
729
|
-
By default, the output of `@debug` messages
|
|
733
|
+
By default, the output of `@debug` messages is disabled.
|
|
730
734
|
Add the following to **webpack.config.js** to enable them:
|
|
731
735
|
|
|
732
736
|
```js
|
|
@@ -742,11 +746,11 @@ module.exports = {
|
|
|
742
746
|
|
|
743
747
|
### Extracts CSS into separate files
|
|
744
748
|
|
|
745
|
-
For production builds it's recommended to extract the CSS from your bundle to
|
|
749
|
+
For production builds, it's recommended to extract the CSS from your bundle to enable parallel loading of CSS/JS resources.
|
|
746
750
|
|
|
747
751
|
There are four recommended ways to extract a stylesheet from a bundle:
|
|
748
752
|
|
|
749
|
-
#### 1. [mini-css-extract-plugin](https://github.com/webpack
|
|
753
|
+
#### 1. [mini-css-extract-plugin](https://github.com/webpack/mini-css-extract-plugin)
|
|
750
754
|
|
|
751
755
|
**webpack.config.js**
|
|
752
756
|
|
|
@@ -785,8 +789,10 @@ module.exports = {
|
|
|
785
789
|
**webpack.config.js**
|
|
786
790
|
|
|
787
791
|
```js
|
|
792
|
+
const path = require("node:path");
|
|
793
|
+
|
|
788
794
|
module.exports = {
|
|
789
|
-
entry: [__dirname
|
|
795
|
+
entry: [path.resolve(__dirname, "./src/scss/app.scss")],
|
|
790
796
|
module: {
|
|
791
797
|
rules: [
|
|
792
798
|
{
|
|
@@ -815,8 +821,10 @@ module.exports = {
|
|
|
815
821
|
**webpack.config.js**
|
|
816
822
|
|
|
817
823
|
```js
|
|
824
|
+
const path = require("node:path");
|
|
825
|
+
|
|
818
826
|
module.exports = {
|
|
819
|
-
entry: [__dirname
|
|
827
|
+
entry: [path.resolve(__dirname, "./src/scss/app.scss")],
|
|
820
828
|
module: {
|
|
821
829
|
rules: [
|
|
822
830
|
{
|
|
@@ -844,9 +852,9 @@ module.exports = {
|
|
|
844
852
|
|
|
845
853
|
### Source maps
|
|
846
854
|
|
|
847
|
-
Enables/
|
|
855
|
+
Enables/disables generation of source maps.
|
|
848
856
|
|
|
849
|
-
To enable CSS source maps, you'll need to pass the `sourceMap` option to the `sass-loader` _and_ the `css-loader`.
|
|
857
|
+
To enable CSS source maps, you'll need to pass the `sourceMap` option to both the `sass-loader` _and_ the `css-loader`.
|
|
850
858
|
|
|
851
859
|
**webpack.config.js**
|
|
852
860
|
|
|
@@ -878,11 +886,13 @@ module.exports = {
|
|
|
878
886
|
};
|
|
879
887
|
```
|
|
880
888
|
|
|
881
|
-
If you want to edit the original Sass files inside Chrome, [there's a good blog post](https://medium.com/@toolmantim/getting-started-with-css-sourcemaps-and-in-browser-sass-editing-b4daab987fb0).
|
|
889
|
+
If you want to edit the original Sass files inside Chrome, [there's a good blog post](https://medium.com/@toolmantim/getting-started-with-css-sourcemaps-and-in-browser-sass-editing-b4daab987fb0).
|
|
890
|
+
Checkout [test/sourceMap](https://github.com/webpack/sass-loader/tree/main/test) for a working example.
|
|
882
891
|
|
|
883
892
|
## Contributing
|
|
884
893
|
|
|
885
|
-
|
|
894
|
+
We welcome all contributions!
|
|
895
|
+
If you're new here, please take a moment to review our contributing guidelines before submitting issues or pull requests.
|
|
886
896
|
|
|
887
897
|
[CONTRIBUTING](./.github/CONTRIBUTING.md)
|
|
888
898
|
|
|
@@ -894,11 +904,13 @@ Please take a moment to read our contributing guidelines if you haven't yet done
|
|
|
894
904
|
[npm-url]: https://npmjs.com/package/sass-loader
|
|
895
905
|
[node]: https://img.shields.io/node/v/sass-loader.svg
|
|
896
906
|
[node-url]: https://nodejs.org
|
|
897
|
-
[tests]: https://github.com/webpack
|
|
898
|
-
[tests-url]: https://github.com/webpack
|
|
899
|
-
[cover]: https://codecov.io/gh/webpack
|
|
900
|
-
[cover-url]: https://codecov.io/gh/webpack
|
|
907
|
+
[tests]: https://github.com/webpack/sass-loader/workflows/sass-loader/badge.svg
|
|
908
|
+
[tests-url]: https://github.com/webpack/sass-loader/actions
|
|
909
|
+
[cover]: https://codecov.io/gh/webpack/sass-loader/branch/main/graph/badge.svg
|
|
910
|
+
[cover-url]: https://codecov.io/gh/webpack/sass-loader
|
|
901
911
|
[discussion]: https://img.shields.io/github/discussions/webpack/webpack
|
|
902
912
|
[discussion-url]: https://github.com/webpack/webpack/discussions
|
|
903
913
|
[size]: https://packagephobia.now.sh/badge?p=sass-loader
|
|
904
914
|
[size-url]: https://packagephobia.now.sh/result?p=sass-loader
|
|
915
|
+
[discord-invite]: https://img.shields.io/discord/1180618526436888586?style=flat&logo=discord&logoColor=white&label=discord
|
|
916
|
+
[discord-url]: https://discord.gg/ARKBCXBu
|
package/dist/index.js
CHANGED
|
@@ -4,16 +4,16 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
-
var
|
|
8
|
-
var
|
|
7
|
+
var _nodePath = _interopRequireDefault(require("node:path"));
|
|
8
|
+
var _nodeUrl = _interopRequireDefault(require("node:url"));
|
|
9
9
|
var _options = _interopRequireDefault(require("./options.json"));
|
|
10
10
|
var _utils = require("./utils");
|
|
11
11
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
// eslint-disable-next-line jsdoc/no-restricted-syntax
|
|
12
13
|
/**
|
|
13
14
|
* The sass-loader makes node-sass and dart-sass available to webpack modules.
|
|
14
|
-
*
|
|
15
|
-
* @
|
|
16
|
-
* @param {string} content
|
|
15
|
+
* @this {LoaderContext<{ string: any }>}
|
|
16
|
+
* @param {string} content content
|
|
17
17
|
*/
|
|
18
18
|
async function loader(content) {
|
|
19
19
|
const options = this.getOptions(_options.default);
|
|
@@ -57,19 +57,19 @@ async function loader(content) {
|
|
|
57
57
|
// There are situations when the `file`/`span.url` property do not exist
|
|
58
58
|
// Modern API
|
|
59
59
|
if (error.span && typeof error.span.url !== "undefined") {
|
|
60
|
-
this.addDependency(
|
|
60
|
+
this.addDependency(_nodeUrl.default.fileURLToPath(error.span.url));
|
|
61
61
|
}
|
|
62
62
|
// Legacy API
|
|
63
63
|
else if (typeof error.file !== "undefined") {
|
|
64
64
|
// `node-sass` returns POSIX paths
|
|
65
|
-
this.addDependency(
|
|
65
|
+
this.addDependency(_nodePath.default.normalize(error.file));
|
|
66
66
|
}
|
|
67
67
|
callback((0, _utils.errorFactory)(error));
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
70
|
let map =
|
|
71
71
|
// Modern API, then legacy API
|
|
72
|
-
result.sourceMap
|
|
72
|
+
result.sourceMap || (result.map ? JSON.parse(result.map) : null);
|
|
73
73
|
|
|
74
74
|
// Modify source paths only for webpack, otherwise we do nothing
|
|
75
75
|
if (map && useSourceMap) {
|
|
@@ -78,25 +78,25 @@ async function loader(content) {
|
|
|
78
78
|
|
|
79
79
|
// Modern API
|
|
80
80
|
if (typeof result.loadedUrls !== "undefined") {
|
|
81
|
-
result.loadedUrls.filter(loadedUrl => loadedUrl.protocol === "file:")
|
|
82
|
-
const normalizedIncludedFile =
|
|
81
|
+
for (const includedFile of result.loadedUrls.filter(loadedUrl => loadedUrl.protocol === "file:")) {
|
|
82
|
+
const normalizedIncludedFile = _nodeUrl.default.fileURLToPath(includedFile);
|
|
83
83
|
|
|
84
84
|
// Custom `importer` can return only `contents` so includedFile will be relative
|
|
85
|
-
if (
|
|
85
|
+
if (_nodePath.default.isAbsolute(normalizedIncludedFile)) {
|
|
86
86
|
this.addDependency(normalizedIncludedFile);
|
|
87
87
|
}
|
|
88
|
-
}
|
|
88
|
+
}
|
|
89
89
|
}
|
|
90
90
|
// Legacy API
|
|
91
91
|
else if (typeof result.stats !== "undefined" && typeof result.stats.includedFiles !== "undefined") {
|
|
92
|
-
result.stats.includedFiles
|
|
93
|
-
const normalizedIncludedFile =
|
|
92
|
+
for (const includedFile of result.stats.includedFiles) {
|
|
93
|
+
const normalizedIncludedFile = _nodePath.default.normalize(includedFile);
|
|
94
94
|
|
|
95
95
|
// Custom `importer` can return only `contents` so includedFile will be relative
|
|
96
|
-
if (
|
|
96
|
+
if (_nodePath.default.isAbsolute(normalizedIncludedFile)) {
|
|
97
97
|
this.addDependency(normalizedIncludedFile);
|
|
98
98
|
}
|
|
99
|
-
}
|
|
99
|
+
}
|
|
100
100
|
}
|
|
101
101
|
callback(null, result.css.toString(), map);
|
|
102
102
|
}
|
package/dist/options.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"properties": {
|
|
5
5
|
"implementation": {
|
|
6
6
|
"description": "The implementation of the sass to be used.",
|
|
7
|
-
"link": "https://github.com/webpack
|
|
7
|
+
"link": "https://github.com/webpack/sass-loader#implementation",
|
|
8
8
|
"anyOf": [
|
|
9
9
|
{
|
|
10
10
|
"type": "string"
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
},
|
|
17
17
|
"api": {
|
|
18
18
|
"description": "Switch between old and modern API for `sass` (`Dart Sass`) and `Sass Embedded` implementations.",
|
|
19
|
-
"link": "https://github.com/webpack
|
|
19
|
+
"link": "https://github.com/webpack/sass-loader#sassoptions",
|
|
20
20
|
"enum": ["legacy", "modern", "modern-compiler"]
|
|
21
21
|
},
|
|
22
22
|
"sassOptions": {
|
|
23
23
|
"description": "Options for `node-sass` or `sass` (`Dart Sass`) implementation.",
|
|
24
|
-
"link": "https://github.com/webpack
|
|
24
|
+
"link": "https://github.com/webpack/sass-loader#sassoptions",
|
|
25
25
|
"anyOf": [
|
|
26
26
|
{
|
|
27
27
|
"type": "object",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"additionalData": {
|
|
36
36
|
"description": "Prepends/Appends `Sass`/`SCSS` code before the actual entry file.",
|
|
37
|
-
"link": "https://github.com/webpack
|
|
37
|
+
"link": "https://github.com/webpack/sass-loader#additionaldata",
|
|
38
38
|
"anyOf": [
|
|
39
39
|
{
|
|
40
40
|
"type": "string"
|
|
@@ -46,17 +46,17 @@
|
|
|
46
46
|
},
|
|
47
47
|
"sourceMap": {
|
|
48
48
|
"description": "Enables/Disables generation of source maps.",
|
|
49
|
-
"link": "https://github.com/webpack
|
|
49
|
+
"link": "https://github.com/webpack/sass-loader#sourcemap",
|
|
50
50
|
"type": "boolean"
|
|
51
51
|
},
|
|
52
52
|
"webpackImporter": {
|
|
53
53
|
"description": "Enables/Disables default `webpack` importer.",
|
|
54
|
-
"link": "https://github.com/webpack
|
|
54
|
+
"link": "https://github.com/webpack/sass-loader#webpackimporter",
|
|
55
55
|
"type": "boolean"
|
|
56
56
|
},
|
|
57
57
|
"warnRuleAsWarning": {
|
|
58
58
|
"description": "Treats the '@warn' rule as a webpack warning.",
|
|
59
|
-
"link": "https://github.com/webpack
|
|
59
|
+
"link": "https://github.com/webpack/sass-loader#warnruleaswarning",
|
|
60
60
|
"type": "boolean"
|
|
61
61
|
}
|
|
62
62
|
},
|
package/dist/utils.js
CHANGED
|
@@ -11,33 +11,47 @@ exports.getSassOptions = getSassOptions;
|
|
|
11
11
|
exports.getWebpackImporter = getWebpackImporter;
|
|
12
12
|
exports.getWebpackResolver = getWebpackResolver;
|
|
13
13
|
exports.normalizeSourceMap = normalizeSourceMap;
|
|
14
|
-
var
|
|
15
|
-
var
|
|
14
|
+
var _nodePath = _interopRequireDefault(require("node:path"));
|
|
15
|
+
var _nodeUrl = _interopRequireDefault(require("node:url"));
|
|
16
16
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
|
+
/** @typedef {import("sass")} Sass */
|
|
18
|
+
/** @typedef {import("sass").StringOptionsWithImporter} SassSassOptions */
|
|
19
|
+
/** @typedef {import("sass-embedded")} SassEmbedded */
|
|
20
|
+
/** @typedef {import("sass-embedded").StringOptionsWithImporter} SassEmbeddedOptions */
|
|
21
|
+
|
|
22
|
+
/** @typedef {Sass | SassEmbedded} SassImplementation */
|
|
23
|
+
/** @typedef {SassSassOptions | SassEmbeddedOptions} SassOptions */
|
|
24
|
+
// eslint-disable-next-line jsdoc/no-restricted-syntax
|
|
25
|
+
/** @typedef {Record<string, any>} LoaderOptions */
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @returns {Sass | SassEmbedded} sass implementation
|
|
29
|
+
*/
|
|
17
30
|
function getDefaultSassImplementation() {
|
|
18
31
|
let sassImplPkg = "sass";
|
|
19
32
|
try {
|
|
20
33
|
require.resolve("sass-embedded");
|
|
21
34
|
sassImplPkg = "sass-embedded";
|
|
22
|
-
} catch
|
|
35
|
+
} catch {
|
|
23
36
|
try {
|
|
24
37
|
require.resolve("sass");
|
|
25
|
-
} catch
|
|
38
|
+
} catch {
|
|
26
39
|
try {
|
|
27
40
|
require.resolve("node-sass");
|
|
28
41
|
sassImplPkg = "node-sass";
|
|
29
|
-
} catch
|
|
42
|
+
} catch {
|
|
30
43
|
sassImplPkg = "sass";
|
|
31
44
|
}
|
|
32
45
|
}
|
|
33
46
|
}
|
|
34
|
-
|
|
35
|
-
// eslint-disable-next-line import/no-dynamic-require, global-require
|
|
36
47
|
return require(sassImplPkg);
|
|
37
48
|
}
|
|
38
49
|
|
|
39
50
|
/**
|
|
40
51
|
* This function is not Webpack-specific and can be used by tools wishing to mimic `sass-loader`'s behaviour, so its signature should not be changed.
|
|
52
|
+
* @param {LoaderContext} loaderContext loader context
|
|
53
|
+
* @param {SassImplementation} implementation sass implementation
|
|
54
|
+
* @returns {SassImplementation} resolved sass implementation
|
|
41
55
|
*/
|
|
42
56
|
function getSassImplementation(loaderContext, implementation) {
|
|
43
57
|
let resolvedImplementation = implementation;
|
|
@@ -45,7 +59,6 @@ function getSassImplementation(loaderContext, implementation) {
|
|
|
45
59
|
resolvedImplementation = getDefaultSassImplementation();
|
|
46
60
|
}
|
|
47
61
|
if (typeof resolvedImplementation === "string") {
|
|
48
|
-
// eslint-disable-next-line import/no-dynamic-require, global-require
|
|
49
62
|
resolvedImplementation = require(resolvedImplementation);
|
|
50
63
|
}
|
|
51
64
|
const {
|
|
@@ -60,27 +73,30 @@ function getSassImplementation(loaderContext, implementation) {
|
|
|
60
73
|
}
|
|
61
74
|
const [implementationName] = infoParts;
|
|
62
75
|
if (implementationName === "dart-sass") {
|
|
63
|
-
// eslint-disable-next-line consistent-return
|
|
64
76
|
return resolvedImplementation;
|
|
65
77
|
} else if (implementationName === "node-sass") {
|
|
66
|
-
// eslint-disable-next-line consistent-return
|
|
67
78
|
return resolvedImplementation;
|
|
68
79
|
} else if (implementationName === "sass-embedded") {
|
|
69
|
-
// eslint-disable-next-line consistent-return
|
|
70
80
|
return resolvedImplementation;
|
|
71
81
|
}
|
|
72
82
|
throw new Error(`Unknown Sass implementation "${implementationName}".`);
|
|
73
83
|
}
|
|
74
84
|
|
|
75
85
|
/**
|
|
76
|
-
* @param {
|
|
77
|
-
* @returns {boolean}
|
|
86
|
+
* @param {LoaderContext} loaderContext loader context
|
|
87
|
+
* @returns {boolean} true when mode is production, otherwise false
|
|
78
88
|
*/
|
|
79
89
|
function isProductionLikeMode(loaderContext) {
|
|
80
90
|
return loaderContext.mode === "production" || !loaderContext.mode;
|
|
81
91
|
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @param {Importer[]} importers importers
|
|
95
|
+
* @param {LoaderContext} loaderContext loader context
|
|
96
|
+
* @returns {Importer[]} proxied importers
|
|
97
|
+
*/
|
|
82
98
|
function proxyCustomImporters(importers, loaderContext) {
|
|
83
|
-
return [].
|
|
99
|
+
return [importers].flat().map(importer => function proxyImporter(...args) {
|
|
84
100
|
const self = {
|
|
85
101
|
...this,
|
|
86
102
|
webpackLoaderContext: loaderContext
|
|
@@ -91,14 +107,13 @@ function proxyCustomImporters(importers, loaderContext) {
|
|
|
91
107
|
|
|
92
108
|
/**
|
|
93
109
|
* Derives the sass options from the loader context and normalizes its values with sane defaults.
|
|
94
|
-
*
|
|
95
|
-
* @param {
|
|
96
|
-
* @param {
|
|
97
|
-
* @param {
|
|
98
|
-
* @param {
|
|
99
|
-
* @param {
|
|
100
|
-
* @
|
|
101
|
-
* @returns {Object}
|
|
110
|
+
* @param {LoaderContext} loaderContext loader context
|
|
111
|
+
* @param {LoaderOptions} loaderOptions loader options
|
|
112
|
+
* @param {string} content content
|
|
113
|
+
* @param {SassImplementation} implementation sass implementation
|
|
114
|
+
* @param {boolean} useSourceMap true when need to generate source maps, otherwise false
|
|
115
|
+
* @param {"legacy" | "modern" | "modern-compiler"} apiType api type
|
|
116
|
+
* @returns {SassOptions} sass options
|
|
102
117
|
*/
|
|
103
118
|
async function getSassOptions(loaderContext, loaderOptions, content, implementation, useSourceMap, apiType) {
|
|
104
119
|
const options = loaderOptions.sassOptions ? typeof loaderOptions.sassOptions === "function" ? loaderOptions.sassOptions(loaderContext) || {} : loaderOptions.sassOptions : {};
|
|
@@ -151,7 +166,7 @@ async function getSassOptions(loaderContext, loaderOptions, content, implementat
|
|
|
151
166
|
resourcePath
|
|
152
167
|
} = loaderContext;
|
|
153
168
|
if (isModernAPI) {
|
|
154
|
-
sassOptions.url =
|
|
169
|
+
sassOptions.url = _nodeUrl.default.pathToFileURL(resourcePath);
|
|
155
170
|
|
|
156
171
|
// opt.outputStyle
|
|
157
172
|
if (!sassOptions.style && isProductionLikeMode(loaderContext)) {
|
|
@@ -164,7 +179,7 @@ async function getSassOptions(loaderContext, loaderOptions, content, implementat
|
|
|
164
179
|
|
|
165
180
|
// If we are compiling sass and indentedSyntax isn't set, automatically set it.
|
|
166
181
|
if (typeof sassOptions.syntax === "undefined") {
|
|
167
|
-
const ext =
|
|
182
|
+
const ext = _nodePath.default.extname(resourcePath);
|
|
168
183
|
if (ext && ext.toLowerCase() === ".scss") {
|
|
169
184
|
sassOptions.syntax = "scss";
|
|
170
185
|
} else if (ext && ext.toLowerCase() === ".sass") {
|
|
@@ -173,10 +188,10 @@ async function getSassOptions(loaderContext, loaderOptions, content, implementat
|
|
|
173
188
|
sassOptions.syntax = "css";
|
|
174
189
|
}
|
|
175
190
|
}
|
|
176
|
-
sassOptions.loadPaths = [
|
|
191
|
+
sassOptions.loadPaths = [
|
|
177
192
|
// We use `loadPaths` in context for resolver, so it should be always absolute
|
|
178
|
-
(sassOptions.loadPaths ? sassOptions.loadPaths
|
|
179
|
-
sassOptions.importers = sassOptions.importers ? Array.isArray(sassOptions.importers) ? sassOptions.importers
|
|
193
|
+
...(sassOptions.loadPaths ? [...sassOptions.loadPaths] : []).map(includePath => _nodePath.default.isAbsolute(includePath) ? includePath : _nodePath.default.join(process.cwd(), includePath)), ...(process.env.SASS_PATH ? process.env.SASS_PATH.split(process.platform === "win32" ? ";" : ":") : [])];
|
|
194
|
+
sassOptions.importers = sassOptions.importers ? Array.isArray(sassOptions.importers) ? [...sassOptions.importers] : [sassOptions.importers] : [];
|
|
180
195
|
} else {
|
|
181
196
|
sassOptions.file = resourcePath;
|
|
182
197
|
|
|
@@ -192,12 +207,12 @@ async function getSassOptions(loaderContext, loaderOptions, content, implementat
|
|
|
192
207
|
// all paths in sourceMap.sources will be relative to that path.
|
|
193
208
|
// Pretty complicated... :(
|
|
194
209
|
sassOptions.sourceMap = true;
|
|
195
|
-
sassOptions.outFile =
|
|
210
|
+
sassOptions.outFile = _nodePath.default.join(loaderContext.rootContext, "style.css.map");
|
|
196
211
|
sassOptions.sourceMapContents = true;
|
|
197
212
|
sassOptions.omitSourceMapUrl = true;
|
|
198
213
|
sassOptions.sourceMapEmbed = false;
|
|
199
214
|
}
|
|
200
|
-
const ext =
|
|
215
|
+
const ext = _nodePath.default.extname(resourcePath);
|
|
201
216
|
|
|
202
217
|
// If we are compiling sass and indentedSyntax isn't set, automatically set it.
|
|
203
218
|
if (ext && ext.toLowerCase() === ".sass" && typeof sassOptions.indentedSyntax === "undefined") {
|
|
@@ -207,16 +222,15 @@ async function getSassOptions(loaderContext, loaderOptions, content, implementat
|
|
|
207
222
|
}
|
|
208
223
|
|
|
209
224
|
// Allow passing custom importers to `sass`/`node-sass`. Accepts `Function` or an array of `Function`s.
|
|
210
|
-
sassOptions.importer = sassOptions.importer ? proxyCustomImporters(Array.isArray(sassOptions.importer) ? sassOptions.importer
|
|
225
|
+
sassOptions.importer = sassOptions.importer ? proxyCustomImporters(Array.isArray(sassOptions.importer) ? [...sassOptions.importer] : [sassOptions.importer], loaderContext) : [];
|
|
211
226
|
|
|
212
227
|
// Regression on the `sass-embedded` side
|
|
213
228
|
if (loaderOptions.webpackImporter === false && sassOptions.importer.length === 0) {
|
|
214
|
-
// eslint-disable-next-line no-undefined
|
|
215
229
|
sassOptions.importer = undefined;
|
|
216
230
|
}
|
|
217
|
-
sassOptions.includePaths = [
|
|
231
|
+
sassOptions.includePaths = [process.cwd(), ...
|
|
218
232
|
// We use `includePaths` in context for resolver, so it should be always absolute
|
|
219
|
-
(sassOptions.includePaths ? sassOptions.includePaths
|
|
233
|
+
(sassOptions.includePaths ? [...sassOptions.includePaths] : []).map(includePath => _nodePath.default.isAbsolute(includePath) ? includePath : _nodePath.default.join(process.cwd(), includePath)), ...(process.env.SASS_PATH ? process.env.SASS_PATH.split(process.platform === "win32" ? ";" : ":") : [])];
|
|
220
234
|
if (typeof sassOptions.charset === "undefined") {
|
|
221
235
|
sassOptions.charset = true;
|
|
222
236
|
}
|
|
@@ -243,15 +257,12 @@ const IS_PKG_SCHEME = /^pkg:/i;
|
|
|
243
257
|
*
|
|
244
258
|
* We don't need emulate `dart-sass` "It's not clear which file to import." errors (when "file.ext" and "_file.ext" files are present simultaneously in the same directory).
|
|
245
259
|
* This reduces performance and `dart-sass` always do it on own side.
|
|
246
|
-
*
|
|
247
|
-
* @param {
|
|
248
|
-
* @param {boolean}
|
|
249
|
-
* @
|
|
250
|
-
* @returns {Array<string>}
|
|
260
|
+
* @param {string} url url
|
|
261
|
+
* @param {boolean} forWebpackResolver true when for webpack resolver, otherwise false
|
|
262
|
+
* @param {boolean} fromImport true when from `@import`, otherwise false
|
|
263
|
+
* @returns {string[]} possible requests
|
|
251
264
|
*/
|
|
252
|
-
function getPossibleRequests(
|
|
253
|
-
// eslint-disable-next-line no-shadow
|
|
254
|
-
url, forWebpackResolver = false, fromImport = false) {
|
|
265
|
+
function getPossibleRequests(url, forWebpackResolver = false, fromImport = false) {
|
|
255
266
|
let request = url;
|
|
256
267
|
|
|
257
268
|
// In case there is module request, send this to webpack resolver
|
|
@@ -270,8 +281,8 @@ url, forWebpackResolver = false, fromImport = false) {
|
|
|
270
281
|
}
|
|
271
282
|
|
|
272
283
|
// Keep in mind: ext can also be something like '.datepicker' when the true extension is omitted and the filename contains a dot.
|
|
273
|
-
// @see https://github.com/webpack
|
|
274
|
-
const extension =
|
|
284
|
+
// @see https://github.com/webpack/sass/issues/167
|
|
285
|
+
const extension = _nodePath.default.extname(request).toLowerCase();
|
|
275
286
|
|
|
276
287
|
// 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.
|
|
277
288
|
// 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:
|
|
@@ -285,12 +296,17 @@ url, forWebpackResolver = false, fromImport = false) {
|
|
|
285
296
|
if (extension === ".css") {
|
|
286
297
|
return fromImport ? [] : [url];
|
|
287
298
|
}
|
|
288
|
-
const dirname =
|
|
299
|
+
const dirname = _nodePath.default.dirname(request);
|
|
289
300
|
const normalizedDirname = dirname === "." ? "" : `${dirname}/`;
|
|
290
|
-
const basename =
|
|
291
|
-
const basenameWithoutExtension =
|
|
292
|
-
return [...new Set([
|
|
301
|
+
const basename = _nodePath.default.basename(request);
|
|
302
|
+
const basenameWithoutExtension = _nodePath.default.basename(request, extension);
|
|
303
|
+
return [...new Set([...[fromImport ? [`${normalizedDirname}_${basenameWithoutExtension}.import${extension}`, `${normalizedDirname}${basenameWithoutExtension}.import${extension}`] : []].flat(), `${normalizedDirname}_${basename}`, `${normalizedDirname}${basename}`, ...(forWebpackResolver ? [url] : [])])];
|
|
293
304
|
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* @param {(context: string, request: string, callback: (error: Error | null, result: string) => void) => void} callbackResolve callback resolve
|
|
308
|
+
* @returns {(context: string, request: string) => Promise<string>} promise resolve
|
|
309
|
+
*/
|
|
294
310
|
function promiseResolve(callbackResolve) {
|
|
295
311
|
return (context, request) => new Promise((resolve, reject) => {
|
|
296
312
|
callbackResolve(context, request, (error, result) => {
|
|
@@ -302,15 +318,20 @@ function promiseResolve(callbackResolve) {
|
|
|
302
318
|
});
|
|
303
319
|
});
|
|
304
320
|
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* @param {ResolutionMap} resolutionMap resolution map
|
|
324
|
+
* @returns {Promise<string>} resolved value
|
|
325
|
+
*/
|
|
305
326
|
async function startResolving(resolutionMap) {
|
|
306
327
|
if (resolutionMap.length === 0) {
|
|
307
|
-
|
|
328
|
+
throw new Error("Next");
|
|
308
329
|
}
|
|
309
330
|
const [{
|
|
310
331
|
possibleRequests
|
|
311
332
|
}] = resolutionMap;
|
|
312
333
|
if (possibleRequests.length === 0) {
|
|
313
|
-
|
|
334
|
+
throw new Error("Next");
|
|
314
335
|
}
|
|
315
336
|
const [{
|
|
316
337
|
resolve,
|
|
@@ -318,14 +339,12 @@ async function startResolving(resolutionMap) {
|
|
|
318
339
|
}] = resolutionMap;
|
|
319
340
|
try {
|
|
320
341
|
return await resolve(context, possibleRequests[0]);
|
|
321
|
-
} catch
|
|
342
|
+
} catch {
|
|
322
343
|
const [, ...tailResult] = possibleRequests;
|
|
323
344
|
if (tailResult.length === 0) {
|
|
324
345
|
const [, ...tailResolutionMap] = resolutionMap;
|
|
325
346
|
return startResolving(tailResolutionMap);
|
|
326
347
|
}
|
|
327
|
-
|
|
328
|
-
// eslint-disable-next-line no-param-reassign
|
|
329
348
|
resolutionMap[0].possibleRequests = tailResult;
|
|
330
349
|
return startResolving(resolutionMap);
|
|
331
350
|
}
|
|
@@ -335,20 +354,15 @@ const IS_SPECIAL_MODULE_IMPORT = /^~[^/]+$/;
|
|
|
335
354
|
const IS_NATIVE_WIN32_PATH = /^[a-z]:[/\\]|^\\\\/i;
|
|
336
355
|
|
|
337
356
|
/**
|
|
338
|
-
* @public
|
|
339
357
|
* Create the resolve function used in the custom Sass importer.
|
|
340
|
-
*
|
|
341
358
|
* Can be used by external tools to mimic how `sass-loader` works, for example
|
|
342
359
|
* in a Jest transform. Such usages will want to wrap `resolve.create` from
|
|
343
360
|
* [`enhanced-resolve`]{@link https://github.com/webpack/enhanced-resolve} to
|
|
344
361
|
* pass as the `resolverFactory` argument.
|
|
345
|
-
*
|
|
346
|
-
* @param {
|
|
347
|
-
*
|
|
348
|
-
* @
|
|
349
|
-
* `sass` (Dart Sass) and `node-sass` are supported.
|
|
350
|
-
* @param {string[]} [includePaths] - The list of include paths passed to Sass.
|
|
351
|
-
*
|
|
362
|
+
* @param {ResolveFactory} resolverFactory a factory function for creating a Webpack resolver.
|
|
363
|
+
* @param {Sass} implementation the imported Sass implementation, both `sass` (Dart Sass) and `node-sass` are supported.
|
|
364
|
+
* @param {string[]=} includePaths the list of include paths passed to Sass.
|
|
365
|
+
* @returns {Resolver} webpack resolver
|
|
352
366
|
* @throws If a compatible Sass implementation cannot be found.
|
|
353
367
|
*/
|
|
354
368
|
function getWebpackResolver(resolverFactory, implementation, includePaths = []) {
|
|
@@ -409,17 +423,15 @@ function getWebpackResolver(resolverFactory, implementation, includePaths = [])
|
|
|
409
423
|
// See https://github.com/webpack/webpack/issues/12340
|
|
410
424
|
// Because `node-sass` calls our importer before `1. Filesystem imports relative to the base file.`
|
|
411
425
|
// custom importer may not return `{ file: '/path/to/name.ext' }` and therefore our `context` will be relative
|
|
412
|
-
if (!isModernSass && !
|
|
426
|
+
if (!isModernSass && !_nodePath.default.isAbsolute(context)) {
|
|
413
427
|
return Promise.reject();
|
|
414
428
|
}
|
|
415
429
|
const originalRequest = request;
|
|
416
430
|
const isFileScheme = originalRequest.slice(0, 5).toLowerCase() === "file:";
|
|
417
431
|
if (isFileScheme) {
|
|
418
432
|
try {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
} catch (ignoreError) {
|
|
422
|
-
// eslint-disable-next-line no-param-reassign
|
|
433
|
+
request = _nodeUrl.default.fileURLToPath(originalRequest);
|
|
434
|
+
} catch {
|
|
423
435
|
request = request.slice(7);
|
|
424
436
|
}
|
|
425
437
|
}
|
|
@@ -448,32 +460,35 @@ function getWebpackResolver(resolverFactory, implementation, includePaths = [])
|
|
|
448
460
|
|
|
449
461
|
// `node-sass` calls our importer before `1. Filesystem imports relative to the base file.`, so we need emulate this too
|
|
450
462
|
if (!isModernSass) {
|
|
451
|
-
resolutionMap = resolutionMap
|
|
463
|
+
resolutionMap = [...resolutionMap, {
|
|
452
464
|
resolve: fromImport ? sassImportResolve : sassModuleResolve,
|
|
453
|
-
context:
|
|
465
|
+
context: _nodePath.default.dirname(context),
|
|
454
466
|
possibleRequests: sassPossibleRequests
|
|
455
|
-
}
|
|
467
|
+
}];
|
|
456
468
|
}
|
|
457
|
-
resolutionMap = resolutionMap.
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
context,
|
|
463
|
-
possibleRequests: sassPossibleRequests
|
|
464
|
-
};
|
|
465
|
-
}));
|
|
469
|
+
resolutionMap = [...resolutionMap, ...includePaths.map(context => ({
|
|
470
|
+
resolve: fromImport ? sassImportResolve : sassModuleResolve,
|
|
471
|
+
context,
|
|
472
|
+
possibleRequests: sassPossibleRequests
|
|
473
|
+
}))];
|
|
466
474
|
}
|
|
467
475
|
const webpackPossibleRequests = getPossibleRequests(request, true, fromImport);
|
|
468
|
-
resolutionMap = resolutionMap
|
|
476
|
+
resolutionMap = [...resolutionMap, {
|
|
469
477
|
resolve: fromImport ? webpackImportResolve : webpackModuleResolve,
|
|
470
|
-
context:
|
|
478
|
+
context: _nodePath.default.dirname(context),
|
|
471
479
|
possibleRequests: webpackPossibleRequests
|
|
472
|
-
}
|
|
480
|
+
}];
|
|
473
481
|
return startResolving(resolutionMap);
|
|
474
482
|
};
|
|
475
483
|
}
|
|
476
484
|
const MATCH_CSS = /\.css$/i;
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* @param {LoaderContext} loaderContext loader context
|
|
488
|
+
* @param {SassImplementation} implementation sass implementation
|
|
489
|
+
* @param {string[]} loadPaths load paths
|
|
490
|
+
* @returns {Importer} the modern webpack importer
|
|
491
|
+
*/
|
|
477
492
|
function getModernWebpackImporter(loaderContext, implementation, loadPaths) {
|
|
478
493
|
const resolve = getWebpackResolver(loaderContext.getResolve, implementation, loadPaths);
|
|
479
494
|
return {
|
|
@@ -481,19 +496,19 @@ function getModernWebpackImporter(loaderContext, implementation, loadPaths) {
|
|
|
481
496
|
const {
|
|
482
497
|
fromImport
|
|
483
498
|
} = context;
|
|
484
|
-
const prev = context.containingUrl ?
|
|
499
|
+
const prev = context.containingUrl ? _nodeUrl.default.fileURLToPath(context.containingUrl.toString()) : loaderContext.resourcePath;
|
|
485
500
|
let result;
|
|
486
501
|
try {
|
|
487
502
|
result = await resolve(prev, originalUrl, fromImport);
|
|
488
|
-
} catch
|
|
503
|
+
} catch {
|
|
489
504
|
// If no stylesheets are found, the importer should return null.
|
|
490
505
|
return null;
|
|
491
506
|
}
|
|
492
|
-
loaderContext.addDependency(
|
|
493
|
-
return
|
|
507
|
+
loaderContext.addDependency(_nodePath.default.normalize(result));
|
|
508
|
+
return _nodeUrl.default.pathToFileURL(result);
|
|
494
509
|
},
|
|
495
510
|
async load(canonicalUrl) {
|
|
496
|
-
const ext =
|
|
511
|
+
const ext = _nodePath.default.extname(canonicalUrl.pathname);
|
|
497
512
|
let syntax;
|
|
498
513
|
if (ext && ext.toLowerCase() === ".scss") {
|
|
499
514
|
syntax = "scss";
|
|
@@ -506,17 +521,16 @@ function getModernWebpackImporter(loaderContext, implementation, loadPaths) {
|
|
|
506
521
|
syntax = "scss";
|
|
507
522
|
}
|
|
508
523
|
try {
|
|
509
|
-
// eslint-disable-next-line no-shadow
|
|
510
524
|
const contents = await new Promise((resolve, reject) => {
|
|
511
525
|
// Old version of `enhanced-resolve` supports only path as a string
|
|
512
526
|
// TODO simplify in the next major release and pass URL
|
|
513
|
-
const canonicalPath =
|
|
514
|
-
loaderContext.fs.readFile(canonicalPath,
|
|
527
|
+
const canonicalPath = _nodeUrl.default.fileURLToPath(canonicalUrl);
|
|
528
|
+
loaderContext.fs.readFile(canonicalPath, (err, content) => {
|
|
515
529
|
if (err) {
|
|
516
530
|
reject(err);
|
|
517
531
|
return;
|
|
518
532
|
}
|
|
519
|
-
resolve(content);
|
|
533
|
+
resolve(content.toString("utf8"));
|
|
520
534
|
});
|
|
521
535
|
});
|
|
522
536
|
return {
|
|
@@ -524,12 +538,19 @@ function getModernWebpackImporter(loaderContext, implementation, loadPaths) {
|
|
|
524
538
|
syntax,
|
|
525
539
|
sourceMapUrl: canonicalUrl
|
|
526
540
|
};
|
|
527
|
-
} catch
|
|
541
|
+
} catch {
|
|
528
542
|
return null;
|
|
529
543
|
}
|
|
530
544
|
}
|
|
531
545
|
};
|
|
532
546
|
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* @param {LoaderContext} loaderContext loader context
|
|
550
|
+
* @param {SassImplementation} implementation sass implementation
|
|
551
|
+
* @param {string[]} includePaths include paths
|
|
552
|
+
* @returns {Importer} the webpack importer
|
|
553
|
+
*/
|
|
533
554
|
function getWebpackImporter(loaderContext, implementation, includePaths) {
|
|
534
555
|
const resolve = getWebpackResolver(loaderContext.getResolve, implementation, includePaths);
|
|
535
556
|
return function importer(originalUrl, prev, done) {
|
|
@@ -542,7 +563,7 @@ function getWebpackImporter(loaderContext, implementation, includePaths) {
|
|
|
542
563
|
// Add the result as dependency.
|
|
543
564
|
// Although we're also using stats.includedFiles, this might come in handy when an error occurs.
|
|
544
565
|
// In this case, we don't get stats.includedFiles from node-sass/sass.
|
|
545
|
-
loaderContext.addDependency(
|
|
566
|
+
loaderContext.addDependency(_nodePath.default.normalize(result));
|
|
546
567
|
|
|
547
568
|
// By removing the CSS file extension, we trigger node-sass to include the CSS file instead of just linking it.
|
|
548
569
|
done({
|
|
@@ -562,11 +583,10 @@ const sassModernCompilers = new WeakMap();
|
|
|
562
583
|
|
|
563
584
|
/**
|
|
564
585
|
* Verifies that the implementation and version of Sass is supported by this loader.
|
|
565
|
-
*
|
|
566
|
-
* @param {
|
|
567
|
-
* @param {
|
|
568
|
-
* @
|
|
569
|
-
* @returns {Function}
|
|
586
|
+
* @param {LoaderContext} loaderContext loader context
|
|
587
|
+
* @param {SassImplementation} implementation sass implementation
|
|
588
|
+
* @param {"legacy" | "modern" | "modern-compiler"} apiType api type
|
|
589
|
+
* @returns {SassCompileFunction} compile function
|
|
570
590
|
*/
|
|
571
591
|
function getCompileFn(loaderContext, implementation, apiType) {
|
|
572
592
|
if (typeof implementation.compileStringAsync !== "undefined") {
|
|
@@ -581,7 +601,6 @@ function getCompileFn(loaderContext, implementation, apiType) {
|
|
|
581
601
|
}
|
|
582
602
|
if (apiType === "modern-compiler") {
|
|
583
603
|
return async sassOptions => {
|
|
584
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
585
604
|
const webpackCompiler = loaderContext._compiler;
|
|
586
605
|
const {
|
|
587
606
|
data,
|
|
@@ -631,8 +650,9 @@ function getCompileFn(loaderContext, implementation, apiType) {
|
|
|
631
650
|
// We need to use a job queue to make sure that one thread is always available to the UV lib
|
|
632
651
|
if (nodeSassJobQueue === null) {
|
|
633
652
|
const threadPoolSize = Number(process.env.UV_THREADPOOL_SIZE || 4);
|
|
653
|
+
|
|
634
654
|
// Only used for `node-sass`, so let's load it lazily
|
|
635
|
-
|
|
655
|
+
|
|
636
656
|
const async = require("neo-async");
|
|
637
657
|
nodeSassJobQueue = async.queue(implementation.render.bind(implementation), threadPoolSize - 1);
|
|
638
658
|
}
|
|
@@ -649,8 +669,8 @@ function getCompileFn(loaderContext, implementation, apiType) {
|
|
|
649
669
|
const ABSOLUTE_SCHEME = /^[A-Za-z0-9+\-.]+:/;
|
|
650
670
|
|
|
651
671
|
/**
|
|
652
|
-
* @param {string} source
|
|
653
|
-
* @returns {"absolute" | "scheme-relative" | "path-absolute" | "path-absolute"}
|
|
672
|
+
* @param {string} source source
|
|
673
|
+
* @returns {"absolute" | "scheme-relative" | "path-absolute" | "path-absolute"} a type of URL
|
|
654
674
|
*/
|
|
655
675
|
function getURLType(source) {
|
|
656
676
|
if (source[0] === "/") {
|
|
@@ -664,44 +684,47 @@ function getURLType(source) {
|
|
|
664
684
|
}
|
|
665
685
|
return ABSOLUTE_SCHEME.test(source) ? "absolute" : "path-relative";
|
|
666
686
|
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* @param {RawSourceMap} map source map
|
|
690
|
+
* @param {string} rootContext root context
|
|
691
|
+
* @returns {RawSourceMap} normalized source map
|
|
692
|
+
*/
|
|
667
693
|
function normalizeSourceMap(map, rootContext) {
|
|
668
694
|
const newMap = map;
|
|
669
695
|
|
|
670
696
|
// result.map.file is an optional property that provides the output filename.
|
|
671
697
|
// Since we don't know the final filename in the webpack build chain yet, it makes no sense to have it.
|
|
672
|
-
|
|
698
|
+
|
|
673
699
|
if (typeof newMap.file !== "undefined") {
|
|
674
700
|
delete newMap.file;
|
|
675
701
|
}
|
|
676
|
-
|
|
677
|
-
// eslint-disable-next-line no-param-reassign
|
|
678
702
|
newMap.sourceRoot = "";
|
|
679
703
|
|
|
680
704
|
// node-sass returns POSIX paths, that's why we need to transform them back to native paths.
|
|
681
705
|
// This fixes an error on windows where the source-map module cannot resolve the source maps.
|
|
682
|
-
// @see https://github.com/webpack
|
|
683
|
-
|
|
706
|
+
// @see https://github.com/webpack/sass-loader/issues/366#issuecomment-279460722
|
|
707
|
+
|
|
684
708
|
newMap.sources = newMap.sources.map(source => {
|
|
685
709
|
const sourceType = getURLType(source);
|
|
686
710
|
|
|
687
711
|
// Do no touch `scheme-relative`, `path-absolute` and `absolute` types (except `file:`)
|
|
688
712
|
if (sourceType === "absolute" && /^file:/i.test(source)) {
|
|
689
|
-
return
|
|
713
|
+
return _nodeUrl.default.fileURLToPath(source);
|
|
690
714
|
} else if (sourceType === "path-relative") {
|
|
691
|
-
return
|
|
715
|
+
return _nodePath.default.resolve(rootContext, _nodePath.default.normalize(source));
|
|
692
716
|
}
|
|
693
717
|
return source;
|
|
694
718
|
});
|
|
695
719
|
return newMap;
|
|
696
720
|
}
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* @param {Error | SassError} error the original sass error
|
|
724
|
+
* @returns {Error} a new error
|
|
725
|
+
*/
|
|
697
726
|
function errorFactory(error) {
|
|
698
|
-
|
|
699
|
-
if (error.formatted) {
|
|
700
|
-
message = error.formatted.replace(/^(.+)?Error: /, "");
|
|
701
|
-
} else {
|
|
702
|
-
// Keep original error if `sassError.formatted` is unavailable
|
|
703
|
-
message = (error.message || error.toString()).replace(/^(.+)?Error: /, "");
|
|
704
|
-
}
|
|
727
|
+
const message = error.formatted ? error.formatted.replace(/^(.+)?Error: /, "") : (error.message || error.toString()).replace(/^(.+)?Error: /, "");
|
|
705
728
|
const obj = new Error(message, {
|
|
706
729
|
cause: error
|
|
707
730
|
});
|
package/package.json
CHANGED
|
@@ -1,35 +1,41 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sass-loader",
|
|
3
|
-
"version": "16.0.
|
|
3
|
+
"version": "16.0.6",
|
|
4
4
|
"description": "Sass loader for webpack",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
"keywords": [
|
|
6
|
+
"sass",
|
|
7
|
+
"libsass",
|
|
8
|
+
"webpack",
|
|
9
|
+
"loader"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://github.com/webpack/sass-loader",
|
|
12
|
+
"bugs": "https://github.com/webpack/sass-loader/issues",
|
|
13
|
+
"repository": "webpack/sass-loader",
|
|
10
14
|
"funding": {
|
|
11
15
|
"type": "opencollective",
|
|
12
16
|
"url": "https://opencollective.com/webpack"
|
|
13
17
|
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": "J. Tangelder",
|
|
14
20
|
"main": "dist/cjs.js",
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
18
24
|
"scripts": {
|
|
19
25
|
"start": "npm run build -- -w",
|
|
20
26
|
"clean": "del-cli dist",
|
|
21
27
|
"prebuild": "npm run clean",
|
|
22
28
|
"build": "cross-env NODE_ENV=production babel src -d dist --copy-files",
|
|
23
|
-
"commitlint": "commitlint --from=
|
|
29
|
+
"commitlint": "commitlint --from=main",
|
|
24
30
|
"security": "npm audit --production",
|
|
25
31
|
"lint:prettier": "prettier --cache --list-different .",
|
|
26
|
-
"lint:
|
|
32
|
+
"lint:code": "eslint --cache .",
|
|
27
33
|
"lint:spelling": "cspell --cache --no-must-find-files --quiet \"**/*.*\"",
|
|
28
34
|
"lint": "npm-run-all -l -p \"lint:**\"",
|
|
29
35
|
"test:only": "cross-env NODE_ENV=test jest",
|
|
30
|
-
"fix:
|
|
36
|
+
"fix:code": "npm run lint:code -- --fix",
|
|
31
37
|
"fix:prettier": "npm run lint:prettier -- --write",
|
|
32
|
-
"fix": "npm-run-all -l fix:
|
|
38
|
+
"fix": "npm-run-all -l fix:code fix:prettier",
|
|
33
39
|
"test:watch": "npm run test:only -- --watch",
|
|
34
40
|
"test:manual": "npm run build && webpack-dev-server test/manual/src/index.js --open --config test/manual/webpack.config.js",
|
|
35
41
|
"test:coverage": "npm run test:only -- --collectCoverageFrom=\"src/**/*.js\" --coverage",
|
|
@@ -38,9 +44,59 @@
|
|
|
38
44
|
"prepare": "husky && npm run build",
|
|
39
45
|
"release": "standard-version"
|
|
40
46
|
},
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"neo-async": "^2.6.2"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@babel/cli": "^7.28.0",
|
|
52
|
+
"@babel/core": "^7.28.0",
|
|
53
|
+
"@babel/preset-env": "^7.28.0",
|
|
54
|
+
"@commitlint/cli": "^19.8.1",
|
|
55
|
+
"@commitlint/config-conventional": "^19.8.1",
|
|
56
|
+
"@eslint/js": "^9.32.0",
|
|
57
|
+
"@eslint/markdown": "^7.0.0",
|
|
58
|
+
"@stylistic/eslint-plugin": "^5.2.2",
|
|
59
|
+
"bootstrap-sass": "^3.4.1",
|
|
60
|
+
"bootstrap-v4": "npm:bootstrap@^4.5.3",
|
|
61
|
+
"bootstrap-v5": "npm:bootstrap@^5.3.7",
|
|
62
|
+
"cross-env": "^7.0.3",
|
|
63
|
+
"cspell": "^8.19.4",
|
|
64
|
+
"css-loader": "^6.9.0",
|
|
65
|
+
"del": "^6.1.1",
|
|
66
|
+
"del-cli": "^5.1.0",
|
|
67
|
+
"enhanced-resolve": "^5.18.2",
|
|
68
|
+
"eslint": "^9.32.0",
|
|
69
|
+
"eslint-config-prettier": "^10.1.8",
|
|
70
|
+
"eslint-config-webpack": "^4.5.1",
|
|
71
|
+
"eslint-plugin-import": "^2.32.0",
|
|
72
|
+
"eslint-plugin-jest": "^29.0.1",
|
|
73
|
+
"eslint-plugin-jsdoc": "^52.0.0",
|
|
74
|
+
"eslint-plugin-n": "^17.21.0",
|
|
75
|
+
"eslint-plugin-prettier": "^5.5.3",
|
|
76
|
+
"eslint-plugin-unicorn": "^60.0.0",
|
|
77
|
+
"file-loader": "^6.2.0",
|
|
78
|
+
"foundation-sites": "^6.7.5",
|
|
79
|
+
"globals": "^16.3.0",
|
|
80
|
+
"husky": "^9.1.3",
|
|
81
|
+
"jest": "^30.0.5",
|
|
82
|
+
"lint-staged": "^15.5.2",
|
|
83
|
+
"material-components-web": "^9.0.0",
|
|
84
|
+
"memfs": "^4.23.0",
|
|
85
|
+
"node-sass": "^9.0.0",
|
|
86
|
+
"node-sass-glob-importer": "^5.3.2",
|
|
87
|
+
"npm-run-all": "^4.1.5",
|
|
88
|
+
"prettier": "^3.6.2",
|
|
89
|
+
"sass": "^1.89.2",
|
|
90
|
+
"sass-embedded": "^1.89.2",
|
|
91
|
+
"semver": "^7.7.2",
|
|
92
|
+
"standard-version": "^9.3.1",
|
|
93
|
+
"style-loader": "^3.3.4",
|
|
94
|
+
"typescript": "^5.9.2",
|
|
95
|
+
"typescript-eslint": "^8.39.0",
|
|
96
|
+
"webpack": "^5.101.0",
|
|
97
|
+
"webpack-cli": "^6.0.1",
|
|
98
|
+
"webpack-dev-server": "^5.2.2"
|
|
99
|
+
},
|
|
44
100
|
"peerDependencies": {
|
|
45
101
|
"@rspack/core": "0.x || 1.x",
|
|
46
102
|
"node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
|
|
@@ -65,54 +121,7 @@
|
|
|
65
121
|
"optional": true
|
|
66
122
|
}
|
|
67
123
|
},
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
}
|
|
71
|
-
"devDependencies": {
|
|
72
|
-
"@babel/cli": "^7.23.4",
|
|
73
|
-
"@babel/core": "^7.24.0",
|
|
74
|
-
"@babel/preset-env": "^7.24.0",
|
|
75
|
-
"@commitlint/cli": "^19.3.0",
|
|
76
|
-
"@commitlint/config-conventional": "^19.2.2",
|
|
77
|
-
"@webpack-contrib/eslint-config-webpack": "^3.0.0",
|
|
78
|
-
"babel-jest": "^29.6.2",
|
|
79
|
-
"bootstrap-sass": "^3.4.1",
|
|
80
|
-
"bootstrap-v4": "npm:bootstrap@^4.5.3",
|
|
81
|
-
"bootstrap-v5": "npm:bootstrap@^5.0.1",
|
|
82
|
-
"cross-env": "^7.0.3",
|
|
83
|
-
"cspell": "^8.6.0",
|
|
84
|
-
"css-loader": "^6.9.0",
|
|
85
|
-
"del": "^6.1.1",
|
|
86
|
-
"del-cli": "^5.1.0",
|
|
87
|
-
"enhanced-resolve": "^5.15.1",
|
|
88
|
-
"eslint": "^8.57.0",
|
|
89
|
-
"eslint-config-prettier": "^9.1.0",
|
|
90
|
-
"eslint-plugin-import": "^2.28.0",
|
|
91
|
-
"file-loader": "^6.2.0",
|
|
92
|
-
"foundation-sites": "^6.7.5",
|
|
93
|
-
"husky": "^9.1.3",
|
|
94
|
-
"jest": "^29.6.2",
|
|
95
|
-
"jest-environment-node-single-context": "^29.1.0",
|
|
96
|
-
"lint-staged": "^15.2.0",
|
|
97
|
-
"material-components-web": "^9.0.0",
|
|
98
|
-
"memfs": "^4.7.7",
|
|
99
|
-
"node-sass": "^9.0.0",
|
|
100
|
-
"node-sass-glob-importer": "^5.3.2",
|
|
101
|
-
"npm-run-all": "^4.1.5",
|
|
102
|
-
"prettier": "^3.2.2",
|
|
103
|
-
"sass": "^1.71.1",
|
|
104
|
-
"sass-embedded": "^1.71.1",
|
|
105
|
-
"semver": "^7.5.4",
|
|
106
|
-
"standard-version": "^9.3.1",
|
|
107
|
-
"style-loader": "^3.3.4",
|
|
108
|
-
"webpack": "^5.93.0",
|
|
109
|
-
"webpack-cli": "^5.1.4",
|
|
110
|
-
"webpack-dev-server": "^5.0.4"
|
|
111
|
-
},
|
|
112
|
-
"keywords": [
|
|
113
|
-
"sass",
|
|
114
|
-
"libsass",
|
|
115
|
-
"webpack",
|
|
116
|
-
"loader"
|
|
117
|
-
]
|
|
124
|
+
"engines": {
|
|
125
|
+
"node": ">= 18.12.0"
|
|
126
|
+
}
|
|
118
127
|
}
|