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 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, and to choose which Sass implementation to use.
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-contrib/css-loader) and the [style-loader](https://github.com/webpack-contrib/style-loader) to immediately apply all styles to the DOM or the [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) to extract it into a separate file.
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 urls must be relative to the entry-file (e.g. `main.scss`).
133
- - If you're just generating CSS without passing it to the `css-loader`, it must be relative to your web root.
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 url rewriting using the [resolve-url-loader](https://github.com/bholloway/resolve-url-loader). Place it before `sass-loader` in the loader chain.
140
- - 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`.
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` loader uses the `sass` (`dart-sass`) implementation:
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` loader uses the `node-sass` implementation:
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` loader uses the `sass-embedded` implementation:
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, you'd pass:
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`, we strongly discourage setting this to `false`, because webpack doesn't support files other than `utf-8`.
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)`and`indentedSyntax`(old API) option is`scss`for the`scss`extension,`indented`for the`sass`extension and`css`for the`css` extension.
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: `compressed`,
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/Disables generation of source maps.
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 (it is a `node-sass` bug).
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: "$env: " + process.env.NODE_ENV + ";",
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 "$value: 100px;" + content;
535
+ return `$value: 100px;${content}`;
532
536
  }
533
537
 
534
- return "$value: 200px;" + content;
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 "$value: 100px;" + content;
569
+ return `$value: 100px;${content}`;
566
570
  }
567
571
 
568
- return "$value: 200px;" + content;
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/Disables the default webpack importer.
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`](https://github.com/sass/node-sass#importer--v200---experimental)).
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 improve performance and decrease built time. We strongly recommend their use. We will enable them by default in a future major release.
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 sass options are different for the `legacy` and `modern` APIs. Please look at [docs](https://sass-lang.com/documentation/js-api) how to migrate to the modern options.
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 are disabled.
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 be able to use parallel loading of CSS/JS resources later on.
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-contrib/mini-css-extract-plugin)
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 + "/src/scss/app.scss"],
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 + "/src/scss/app.scss"],
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/Disables generation of source maps.
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). Checkout [test/sourceMap](https://github.com/webpack-contrib/sass-loader/tree/master/test) for a running example.
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
- Please take a moment to read our contributing guidelines if you haven't yet done so.
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-contrib/sass-loader/workflows/sass-loader/badge.svg
898
- [tests-url]: https://github.com/webpack-contrib/sass-loader/actions
899
- [cover]: https://codecov.io/gh/webpack-contrib/sass-loader/branch/master/graph/badge.svg
900
- [cover-url]: https://codecov.io/gh/webpack-contrib/sass-loader
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 _url = _interopRequireDefault(require("url"));
8
- var _path = _interopRequireDefault(require("path"));
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
- * @this {object}
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(_url.default.fileURLToPath(error.span.url));
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(_path.default.normalize(error.file));
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 ? result.sourceMap : result.map ? JSON.parse(result.map) : null;
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:").forEach(includedFile => {
82
- const normalizedIncludedFile = _url.default.fileURLToPath(includedFile);
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 (_path.default.isAbsolute(normalizedIncludedFile)) {
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.forEach(includedFile => {
93
- const normalizedIncludedFile = _path.default.normalize(includedFile);
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 (_path.default.isAbsolute(normalizedIncludedFile)) {
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-contrib/sass-loader#implementation",
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-contrib/sass-loader#sassoptions",
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-contrib/sass-loader#sassoptions",
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-contrib/sass-loader#additionaldata",
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-contrib/sass-loader#sourcemap",
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-contrib/sass-loader#webpackimporter",
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-contrib/sass-loader#warnruleaswarning",
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 _url = _interopRequireDefault(require("url"));
15
- var _path = _interopRequireDefault(require("path"));
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 (ignoreError) {
35
+ } catch {
23
36
  try {
24
37
  require.resolve("sass");
25
- } catch (_ignoreError) {
38
+ } catch {
26
39
  try {
27
40
  require.resolve("node-sass");
28
41
  sassImplPkg = "node-sass";
29
- } catch (__ignoreError) {
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 {any} loaderContext
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 [].concat(importers).map(importer => function proxyImporter(...args) {
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 {object} loaderContext
96
- * @param {object} loaderOptions
97
- * @param {string} content
98
- * @param {object} implementation
99
- * @param {boolean} useSourceMap
100
- * @param {"legacy" | "modern" | "modern-compiler"} apiType
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 = _url.default.pathToFileURL(resourcePath);
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 = _path.default.extname(resourcePath);
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 = [].concat(
191
+ sassOptions.loadPaths = [
177
192
  // We use `loadPaths` in context for resolver, so it should be always absolute
178
- (sassOptions.loadPaths ? sassOptions.loadPaths.slice() : []).map(includePath => _path.default.isAbsolute(includePath) ? includePath : _path.default.join(process.cwd(), includePath))).concat(process.env.SASS_PATH ? process.env.SASS_PATH.split(process.platform === "win32" ? ";" : ":") : []);
179
- sassOptions.importers = sassOptions.importers ? Array.isArray(sassOptions.importers) ? sassOptions.importers.slice() : [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 = _path.default.join(loaderContext.rootContext, "style.css.map");
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 = _path.default.extname(resourcePath);
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.slice() : [sassOptions.importer], loaderContext) : [];
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 = [].concat(process.cwd()).concat(
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.slice() : []).map(includePath => _path.default.isAbsolute(includePath) ? includePath : _path.default.join(process.cwd(), includePath))).concat(process.env.SASS_PATH ? process.env.SASS_PATH.split(process.platform === "win32" ? ";" : ":") : []);
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 {string} url
248
- * @param {boolean} forWebpackResolver
249
- * @param {boolean} fromImport
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-contrib/sass-loader/issues/167
274
- const extension = _path.default.extname(request).toLowerCase();
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 = _path.default.dirname(request);
299
+ const dirname = _nodePath.default.dirname(request);
289
300
  const normalizedDirname = dirname === "." ? "" : `${dirname}/`;
290
- const basename = _path.default.basename(request);
291
- const basenameWithoutExtension = _path.default.basename(request, extension);
292
- return [...new Set([].concat(fromImport ? [`${normalizedDirname}_${basenameWithoutExtension}.import${extension}`, `${normalizedDirname}${basenameWithoutExtension}.import${extension}`] : []).concat([`${normalizedDirname}_${basename}`, `${normalizedDirname}${basename}`]).concat(forWebpackResolver ? [url] : []))];
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
- return Promise.reject();
328
+ throw new Error("Next");
308
329
  }
309
330
  const [{
310
331
  possibleRequests
311
332
  }] = resolutionMap;
312
333
  if (possibleRequests.length === 0) {
313
- return Promise.reject();
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 (_ignoreError) {
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 {Function} resolverFactory - A factory function for creating a Webpack
347
- * resolver.
348
- * @param {Object} implementation - The imported Sass implementation, both
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 && !_path.default.isAbsolute(context)) {
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
- // eslint-disable-next-line no-param-reassign
420
- request = _url.default.fileURLToPath(originalRequest);
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.concat({
463
+ resolutionMap = [...resolutionMap, {
452
464
  resolve: fromImport ? sassImportResolve : sassModuleResolve,
453
- context: _path.default.dirname(context),
465
+ context: _nodePath.default.dirname(context),
454
466
  possibleRequests: sassPossibleRequests
455
- });
467
+ }];
456
468
  }
457
- resolutionMap = resolutionMap.concat(
458
- // eslint-disable-next-line no-shadow
459
- includePaths.map(context => {
460
- return {
461
- resolve: fromImport ? sassImportResolve : sassModuleResolve,
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.concat({
476
+ resolutionMap = [...resolutionMap, {
469
477
  resolve: fromImport ? webpackImportResolve : webpackModuleResolve,
470
- context: _path.default.dirname(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 ? _url.default.fileURLToPath(context.containingUrl.toString()) : loaderContext.resourcePath;
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 (err) {
503
+ } catch {
489
504
  // If no stylesheets are found, the importer should return null.
490
505
  return null;
491
506
  }
492
- loaderContext.addDependency(_path.default.normalize(result));
493
- return _url.default.pathToFileURL(result);
507
+ loaderContext.addDependency(_nodePath.default.normalize(result));
508
+ return _nodeUrl.default.pathToFileURL(result);
494
509
  },
495
510
  async load(canonicalUrl) {
496
- const ext = _path.default.extname(canonicalUrl.pathname);
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 = _url.default.fileURLToPath(canonicalUrl);
514
- loaderContext.fs.readFile(canonicalPath, "utf8", (err, content) => {
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 (err) {
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(_path.default.normalize(result));
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 {Object} loaderContext
567
- * @param {Object} implementation
568
- * @param {"legacy" | "modern" | "modern-compiler"} apiType
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
- // eslint-disable-next-line global-require
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
- // eslint-disable-next-line no-param-reassign
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-contrib/sass-loader/issues/366#issuecomment-279460722
683
- // eslint-disable-next-line no-param-reassign
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 _url.default.fileURLToPath(source);
713
+ return _nodeUrl.default.fileURLToPath(source);
690
714
  } else if (sourceType === "path-relative") {
691
- return _path.default.resolve(rootContext, _path.default.normalize(source));
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
- let message;
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.5",
3
+ "version": "16.0.6",
4
4
  "description": "Sass loader for webpack",
5
- "license": "MIT",
6
- "repository": "webpack-contrib/sass-loader",
7
- "author": "J. Tangelder",
8
- "homepage": "https://github.com/webpack-contrib/sass-loader",
9
- "bugs": "https://github.com/webpack-contrib/sass-loader/issues",
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
- "engines": {
16
- "node": ">= 18.12.0"
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=master",
29
+ "commitlint": "commitlint --from=main",
24
30
  "security": "npm audit --production",
25
31
  "lint:prettier": "prettier --cache --list-different .",
26
- "lint:js": "eslint --cache .",
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:js": "npm run lint:js -- --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:js fix:prettier",
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
- "files": [
42
- "dist"
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
- "dependencies": {
69
- "neo-async": "^2.6.2"
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
  }