sass-loader 13.2.0 → 13.2.1

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/dist/SassError.js CHANGED
@@ -4,32 +4,28 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  class SassError extends Error {
9
8
  constructor(sassError) {
10
9
  super();
11
- this.name = "SassError"; // Instruct webpack to hide the JS stack from the console.
12
- // Usually you're only interested in the SASS error in this case.
10
+ this.name = "SassError";
13
11
 
12
+ // Instruct webpack to hide the JS stack from the console.
13
+ // Usually you're only interested in the SASS error in this case.
14
14
  this.hideStack = true;
15
15
  Error.captureStackTrace(this, this.constructor);
16
-
17
16
  if (typeof sassError.line !== "undefined" || typeof sassError.column !== "undefined") {
18
17
  this.loc = {
19
18
  line: sassError.line,
20
19
  column: sassError.column
21
20
  };
22
- } // Keep original error if `sassError.formatted` is unavailable
23
-
21
+ }
24
22
 
23
+ // Keep original error if `sassError.formatted` is unavailable
25
24
  this.message = `${this.name}: ${typeof sassError.message !== "undefined" ? sassError.message : sassError}`;
26
-
27
25
  if (sassError.formatted) {
28
26
  this.message = `${this.name}: ${sassError.formatted.replace(/^Error: /, "")}`;
29
27
  }
30
28
  }
31
-
32
29
  }
33
-
34
30
  var _default = SassError;
35
31
  exports.default = _default;
@@ -4,13 +4,11 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  class SassWarning extends Error {
9
8
  constructor(warning, options) {
10
9
  super(warning);
11
10
  this.name = "SassWarning";
12
11
  this.hideStack = true;
13
-
14
12
  if (options.span) {
15
13
  this.loc = {
16
14
  line: options.span.start.line,
@@ -18,8 +16,6 @@ class SassWarning extends Error {
18
16
  };
19
17
  }
20
18
  }
21
-
22
19
  }
23
-
24
20
  var _default = SassWarning;
25
21
  exports.default = _default;
package/dist/cjs.js CHANGED
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
2
 
3
3
  const loader = require("./index");
4
-
5
4
  module.exports = loader.default;
package/dist/index.js CHANGED
@@ -4,19 +4,12 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var _url = _interopRequireDefault(require("url"));
9
-
10
8
  var _path = _interopRequireDefault(require("path"));
11
-
12
9
  var _options = _interopRequireDefault(require("./options.json"));
13
-
14
10
  var _utils = require("./utils");
15
-
16
11
  var _SassError = _interopRequireDefault(require("./SassError"));
17
-
18
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
-
20
13
  /**
21
14
  * The sass-loader makes node-sass and dart-sass available to webpack modules.
22
15
  *
@@ -27,19 +20,15 @@ async function loader(content) {
27
20
  const options = this.getOptions(_options.default);
28
21
  const callback = this.async();
29
22
  const implementation = (0, _utils.getSassImplementation)(this, options.implementation);
30
-
31
23
  if (!implementation) {
32
24
  callback();
33
25
  return;
34
26
  }
35
-
36
27
  const useSourceMap = typeof options.sourceMap === "boolean" ? options.sourceMap : this.sourceMap;
37
28
  const sassOptions = await (0, _utils.getSassOptions)(this, options, content, implementation, useSourceMap);
38
29
  const shouldUseWebpackImporter = typeof options.webpackImporter === "boolean" ? options.webpackImporter : true;
39
-
40
30
  if (shouldUseWebpackImporter) {
41
31
  const isModernAPI = options.api === "modern";
42
-
43
32
  if (!isModernAPI) {
44
33
  const {
45
34
  includePaths
@@ -49,10 +38,8 @@ async function loader(content) {
49
38
  sassOptions.importers.push((0, _utils.getModernWebpackImporter)(this, implementation));
50
39
  }
51
40
  }
52
-
53
41
  const compile = (0, _utils.getCompileFn)(implementation, options);
54
42
  let result;
55
-
56
43
  try {
57
44
  result = await compile(sassOptions, options);
58
45
  } catch (error) {
@@ -60,47 +47,47 @@ async function loader(content) {
60
47
  // Modern API
61
48
  if (error.span && typeof error.span.url !== "undefined") {
62
49
  this.addDependency(_url.default.fileURLToPath(error.span.url));
63
- } // Legacy API
50
+ }
51
+ // Legacy API
64
52
  else if (typeof error.file !== "undefined") {
65
53
  // `node-sass` returns POSIX paths
66
54
  this.addDependency(_path.default.normalize(error.file));
67
55
  }
68
-
69
56
  callback(new _SassError.default(error));
70
57
  return;
71
58
  }
59
+ let map =
60
+ // Modern API, then legacy API
61
+ result.sourceMap ? result.sourceMap : result.map ? JSON.parse(result.map) : null;
72
62
 
73
- let map = // Modern API, then legacy API
74
- result.sourceMap ? result.sourceMap : result.map ? JSON.parse(result.map) : null; // Modify source paths only for webpack, otherwise we do nothing
75
-
63
+ // Modify source paths only for webpack, otherwise we do nothing
76
64
  if (map && useSourceMap) {
77
65
  map = (0, _utils.normalizeSourceMap)(map, this.rootContext);
78
- } // Modern API
79
-
66
+ }
80
67
 
68
+ // Modern API
81
69
  if (typeof result.loadedUrls !== "undefined") {
82
- result.loadedUrls.forEach(includedFile => {
83
- const normalizedIncludedFile = _url.default.fileURLToPath(includedFile); // Custom `importer` can return only `contents` so includedFile will be relative
84
-
70
+ result.loadedUrls.filter(url => url.protocol === "file").forEach(includedFile => {
71
+ const normalizedIncludedFile = _url.default.fileURLToPath(includedFile);
85
72
 
73
+ // Custom `importer` can return only `contents` so includedFile will be relative
86
74
  if (_path.default.isAbsolute(normalizedIncludedFile)) {
87
75
  this.addDependency(normalizedIncludedFile);
88
76
  }
89
77
  });
90
- } // Legacy API
78
+ }
79
+ // Legacy API
91
80
  else if (typeof result.stats !== "undefined" && typeof result.stats.includedFiles !== "undefined") {
92
81
  result.stats.includedFiles.forEach(includedFile => {
93
- const normalizedIncludedFile = _path.default.normalize(includedFile); // Custom `importer` can return only `contents` so includedFile will be relative
94
-
82
+ const normalizedIncludedFile = _path.default.normalize(includedFile);
95
83
 
84
+ // Custom `importer` can return only `contents` so includedFile will be relative
96
85
  if (_path.default.isAbsolute(normalizedIncludedFile)) {
97
86
  this.addDependency(normalizedIncludedFile);
98
87
  }
99
88
  });
100
89
  }
101
-
102
90
  callback(null, result.css.toString(), map);
103
91
  }
104
-
105
92
  var _default = loader;
106
93
  exports.default = _default;
package/dist/utils.js CHANGED
@@ -11,51 +11,39 @@ exports.getWebpackImporter = getWebpackImporter;
11
11
  exports.getWebpackResolver = getWebpackResolver;
12
12
  exports.isSupportedFibers = isSupportedFibers;
13
13
  exports.normalizeSourceMap = normalizeSourceMap;
14
-
15
14
  var _url = _interopRequireDefault(require("url"));
16
-
17
15
  var _path = _interopRequireDefault(require("path"));
18
-
19
16
  var _full = require("klona/full");
20
-
21
17
  var _neoAsync = _interopRequireDefault(require("neo-async"));
22
-
23
18
  var _SassWarning = _interopRequireDefault(require("./SassWarning"));
24
-
25
19
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
26
-
27
20
  function getDefaultSassImplementation() {
28
21
  let sassImplPkg = "sass";
29
-
30
22
  try {
31
23
  require.resolve("sass");
32
24
  } catch (ignoreError) {
33
25
  try {
34
26
  require.resolve("node-sass");
35
-
36
27
  sassImplPkg = "node-sass";
37
28
  } catch (_ignoreError) {
38
29
  try {
39
30
  require.resolve("sass-embedded");
40
-
41
31
  sassImplPkg = "sass-embedded";
42
32
  } catch (__ignoreError) {
43
33
  sassImplPkg = "sass";
44
34
  }
45
35
  }
46
- } // eslint-disable-next-line import/no-dynamic-require, global-require
47
-
36
+ }
48
37
 
38
+ // eslint-disable-next-line import/no-dynamic-require, global-require
49
39
  return require(sassImplPkg);
50
40
  }
41
+
51
42
  /**
52
43
  * 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.
53
44
  */
54
-
55
-
56
45
  function getSassImplementation(loaderContext, implementation) {
57
46
  let resolvedImplementation = implementation;
58
-
59
47
  if (!resolvedImplementation) {
60
48
  try {
61
49
  resolvedImplementation = getDefaultSassImplementation();
@@ -64,36 +52,30 @@ function getSassImplementation(loaderContext, implementation) {
64
52
  return;
65
53
  }
66
54
  }
67
-
68
55
  if (typeof resolvedImplementation === "string") {
69
56
  try {
70
57
  // eslint-disable-next-line import/no-dynamic-require, global-require
71
58
  resolvedImplementation = require(resolvedImplementation);
72
59
  } catch (error) {
73
- loaderContext.emitError(error); // eslint-disable-next-line consistent-return
60
+ loaderContext.emitError(error);
74
61
 
62
+ // eslint-disable-next-line consistent-return
75
63
  return;
76
64
  }
77
65
  }
78
-
79
66
  const {
80
67
  info
81
68
  } = resolvedImplementation;
82
-
83
69
  if (!info) {
84
70
  loaderContext.emitError(new Error("Unknown Sass implementation."));
85
71
  return;
86
72
  }
87
-
88
73
  const infoParts = info.split("\t");
89
-
90
74
  if (infoParts.length < 2) {
91
75
  loaderContext.emitError(new Error(`Unknown Sass implementation "${info}".`));
92
76
  return;
93
77
  }
94
-
95
78
  const [implementationName] = infoParts;
96
-
97
79
  if (implementationName === "dart-sass") {
98
80
  // eslint-disable-next-line consistent-return
99
81
  return resolvedImplementation;
@@ -104,32 +86,30 @@ function getSassImplementation(loaderContext, implementation) {
104
86
  // eslint-disable-next-line consistent-return
105
87
  return resolvedImplementation;
106
88
  }
107
-
108
89
  loaderContext.emitError(new Error(`Unknown Sass implementation "${implementationName}".`));
109
90
  }
91
+
110
92
  /**
111
93
  * @param {any} loaderContext
112
94
  * @returns {boolean}
113
95
  */
114
-
115
-
116
96
  function isProductionLikeMode(loaderContext) {
117
97
  return loaderContext.mode === "production" || !loaderContext.mode;
118
98
  }
119
-
120
99
  function proxyCustomImporters(importers, loaderContext) {
121
100
  return [].concat(importers).map(importer => function proxyImporter(...args) {
122
- const self = { ...this,
101
+ const self = {
102
+ ...this,
123
103
  webpackLoaderContext: loaderContext
124
104
  };
125
105
  return importer.apply(self, args);
126
106
  });
127
107
  }
128
-
129
108
  function isSupportedFibers() {
130
109
  const [nodeVersion] = process.versions.node.split(".");
131
110
  return Number(nodeVersion) < 16;
132
111
  }
112
+
133
113
  /**
134
114
  * Derives the sass options from the loader context and normalizes its values with sane defaults.
135
115
  *
@@ -140,80 +120,62 @@ function isSupportedFibers() {
140
120
  * @param {boolean} useSourceMap
141
121
  * @returns {Object}
142
122
  */
143
-
144
-
145
123
  async function getSassOptions(loaderContext, loaderOptions, content, implementation, useSourceMap) {
146
124
  const options = (0, _full.klona)(loaderOptions.sassOptions ? typeof loaderOptions.sassOptions === "function" ? loaderOptions.sassOptions(loaderContext) || {} : loaderOptions.sassOptions : {});
147
125
  const isDartSass = implementation.info.includes("dart-sass");
148
126
  const isModernAPI = loaderOptions.api === "modern";
149
127
  options.data = loaderOptions.additionalData ? typeof loaderOptions.additionalData === "function" ? await loaderOptions.additionalData(content, loaderContext) : `${loaderOptions.additionalData}\n${content}` : content;
150
-
151
128
  if (!options.logger) {
152
129
  const needEmitWarning = loaderOptions.warnRuleAsWarning !== false;
153
130
  const logger = loaderContext.getLogger("sass-loader");
154
-
155
131
  const formatSpan = span => `${span.url || "-"}:${span.start.line}:${span.start.column}: `;
156
-
157
132
  const formatDebugSpan = span => `[debug:${span.start.line}:${span.start.column}] `;
158
-
159
133
  options.logger = {
160
134
  debug(message, loggerOptions) {
161
135
  let builtMessage = "";
162
-
163
136
  if (loggerOptions.span) {
164
137
  builtMessage = formatDebugSpan(loggerOptions.span);
165
138
  }
166
-
167
139
  builtMessage += message;
168
140
  logger.debug(builtMessage);
169
141
  },
170
-
171
142
  warn(message, loggerOptions) {
172
143
  let builtMessage = "";
173
-
174
144
  if (loggerOptions.deprecation) {
175
145
  builtMessage += "Deprecation ";
176
146
  }
177
-
178
147
  if (loggerOptions.span && !loggerOptions.stack) {
179
148
  builtMessage = formatSpan(loggerOptions.span);
180
149
  }
181
-
182
150
  builtMessage += message;
183
-
184
151
  if (loggerOptions.stack) {
185
152
  builtMessage += `\n\n${loggerOptions.stack}`;
186
153
  }
187
-
188
154
  if (needEmitWarning) {
189
155
  loaderContext.emitWarning(new _SassWarning.default(builtMessage, loggerOptions));
190
156
  } else {
191
157
  logger.warn(builtMessage);
192
158
  }
193
159
  }
194
-
195
160
  };
196
161
  }
197
-
198
162
  const {
199
163
  resourcePath
200
164
  } = loaderContext;
201
-
202
165
  if (isModernAPI) {
203
- options.url = _url.default.pathToFileURL(resourcePath); // opt.outputStyle
166
+ options.url = _url.default.pathToFileURL(resourcePath);
204
167
 
168
+ // opt.outputStyle
205
169
  if (!options.style && isProductionLikeMode(loaderContext)) {
206
170
  options.style = "compressed";
207
171
  }
208
-
209
172
  if (useSourceMap) {
210
173
  options.sourceMap = true;
211
- } // If we are compiling sass and indentedSyntax isn't set, automatically set it.
212
-
174
+ }
213
175
 
176
+ // If we are compiling sass and indentedSyntax isn't set, automatically set it.
214
177
  if (typeof options.syntax === "undefined") {
215
178
  const ext = _path.default.extname(resourcePath);
216
-
217
179
  if (ext && ext.toLowerCase() === ".scss") {
218
180
  options.syntax = "scss";
219
181
  } else if (ext && ext.toLowerCase() === ".sass") {
@@ -222,22 +184,18 @@ async function getSassOptions(loaderContext, loaderOptions, content, implementat
222
184
  options.syntax = "css";
223
185
  }
224
186
  }
225
-
226
187
  options.importers = options.importers ? Array.isArray(options.importers) ? options.importers : [options.importers] : [];
227
188
  } else {
228
189
  options.file = resourcePath;
229
-
230
190
  if (isDartSass && isSupportedFibers()) {
231
191
  const shouldTryToResolveFibers = !options.fiber && options.fiber !== false;
232
-
233
192
  if (shouldTryToResolveFibers) {
234
193
  let fibers;
235
-
236
194
  try {
237
195
  fibers = require.resolve("fibers");
238
- } catch (_error) {// Nothing
196
+ } catch (_error) {
197
+ // Nothing
239
198
  }
240
-
241
199
  if (fibers) {
242
200
  // eslint-disable-next-line global-require, import/no-dynamic-require
243
201
  options.fiber = require(fibers);
@@ -249,13 +207,12 @@ async function getSassOptions(loaderContext, loaderOptions, content, implementat
249
207
  } else {
250
208
  // Don't pass the `fiber` option for `node-sass`
251
209
  delete options.fiber;
252
- } // opt.outputStyle
253
-
210
+ }
254
211
 
212
+ // opt.outputStyle
255
213
  if (!options.outputStyle && isProductionLikeMode(loaderContext)) {
256
214
  options.outputStyle = "compressed";
257
215
  }
258
-
259
216
  if (useSourceMap) {
260
217
  // Deliberately overriding the sourceMap option here.
261
218
  // node-sass won't produce source maps if the data option is used and options.sourceMap is not a string.
@@ -269,38 +226,37 @@ async function getSassOptions(loaderContext, loaderOptions, content, implementat
269
226
  options.omitSourceMapUrl = true;
270
227
  options.sourceMapEmbed = false;
271
228
  }
229
+ const ext = _path.default.extname(resourcePath);
272
230
 
273
- const ext = _path.default.extname(resourcePath); // If we are compiling sass and indentedSyntax isn't set, automatically set it.
274
-
275
-
231
+ // If we are compiling sass and indentedSyntax isn't set, automatically set it.
276
232
  if (ext && ext.toLowerCase() === ".sass" && typeof options.indentedSyntax === "undefined") {
277
233
  options.indentedSyntax = true;
278
234
  } else {
279
235
  options.indentedSyntax = Boolean(options.indentedSyntax);
280
- } // Allow passing custom importers to `sass`/`node-sass`. Accepts `Function` or an array of `Function`s.
281
-
236
+ }
282
237
 
238
+ // Allow passing custom importers to `sass`/`node-sass`. Accepts `Function` or an array of `Function`s.
283
239
  options.importer = options.importer ? proxyCustomImporters(Array.isArray(options.importer) ? options.importer : [options.importer], loaderContext) : [];
284
- options.includePaths = [].concat(process.cwd()).concat( // We use `includePaths` in context for resolver, so it should be always absolute
240
+ options.includePaths = [].concat(process.cwd()).concat(
241
+ // We use `includePaths` in context for resolver, so it should be always absolute
285
242
  (options.includePaths || []).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" ? ";" : ":") : []);
286
-
287
243
  if (typeof options.charset === "undefined") {
288
244
  options.charset = true;
289
245
  }
290
246
  }
291
-
292
247
  return options;
293
248
  }
249
+ const MODULE_REQUEST_REGEX = /^[^?]*~/;
294
250
 
295
- const MODULE_REQUEST_REGEX = /^[^?]*~/; // Examples:
251
+ // Examples:
296
252
  // - ~package
297
253
  // - ~package/
298
254
  // - ~@org
299
255
  // - ~@org/
300
256
  // - ~@org/package
301
257
  // - ~@org/package/
302
-
303
258
  const IS_MODULE_IMPORT = /^~([^/]+|[^/]+\/|@[^/]+[/][^/]+|@[^/]+\/?|@[^/]+[/][^/]+\/)$/;
259
+
304
260
  /**
305
261
  * When `sass`/`node-sass` tries to resolve an import, it uses a special algorithm.
306
262
  * Since the `sass-loader` uses webpack to resolve the modules, we need to simulate that algorithm.
@@ -315,25 +271,27 @@ const IS_MODULE_IMPORT = /^~([^/]+|[^/]+\/|@[^/]+[/][^/]+|@[^/]+\/?|@[^/]+[/][^/
315
271
  * @param {boolean} fromImport
316
272
  * @returns {Array<string>}
317
273
  */
318
-
319
- function getPossibleRequests( // eslint-disable-next-line no-shadow
274
+ function getPossibleRequests(
275
+ // eslint-disable-next-line no-shadow
320
276
  url, forWebpackResolver = false, fromImport = false) {
321
- let request = url; // In case there is module request, send this to webpack resolver
277
+ let request = url;
322
278
 
279
+ // In case there is module request, send this to webpack resolver
323
280
  if (forWebpackResolver) {
324
281
  if (MODULE_REQUEST_REGEX.test(url)) {
325
282
  request = request.replace(MODULE_REQUEST_REGEX, "");
326
283
  }
327
-
328
284
  if (IS_MODULE_IMPORT.test(url)) {
329
285
  request = request[request.length - 1] === "/" ? request : `${request}/`;
330
286
  return [...new Set([request, url])];
331
287
  }
332
- } // Keep in mind: ext can also be something like '.datepicker' when the true extension is omitted and the filename contains a dot.
333
- // @see https://github.com/webpack-contrib/sass-loader/issues/167
288
+ }
334
289
 
290
+ // Keep in mind: ext can also be something like '.datepicker' when the true extension is omitted and the filename contains a dot.
291
+ // @see https://github.com/webpack-contrib/sass-loader/issues/167
292
+ const extension = _path.default.extname(request).toLowerCase();
335
293
 
336
- const extension = _path.default.extname(request).toLowerCase(); // 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.
294
+ // 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.
337
295
  // 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:
338
296
  // - imports where the URL ends with .css.
339
297
  // - imports where the URL begins http:// or https://.
@@ -341,23 +299,15 @@ url, forWebpackResolver = false, fromImport = false) {
341
299
  // - imports that have media queries.
342
300
  //
343
301
  // The `node-sass` package sends `@import` ending on `.css` to importer, it is bug, so we skip resolve
344
-
345
-
346
302
  if (extension === ".css") {
347
303
  return [];
348
304
  }
349
-
350
305
  const dirname = _path.default.dirname(request);
351
-
352
306
  const normalizedDirname = dirname === "." ? "" : `${dirname}/`;
353
-
354
307
  const basename = _path.default.basename(request);
355
-
356
308
  const basenameWithoutExtension = _path.default.basename(request, extension);
357
-
358
309
  return [...new Set([].concat(fromImport ? [`${normalizedDirname}_${basenameWithoutExtension}.import${extension}`, `${normalizedDirname}${basenameWithoutExtension}.import${extension}`] : []).concat([`${normalizedDirname}_${basename}`, `${normalizedDirname}${basename}`]).concat(forWebpackResolver ? [url] : []))];
359
310
  }
360
-
361
311
  function promiseResolve(callbackResolve) {
362
312
  return (context, request) => new Promise((resolve, reject) => {
363
313
  callbackResolve(context, request, (error, result) => {
@@ -369,44 +319,38 @@ function promiseResolve(callbackResolve) {
369
319
  });
370
320
  });
371
321
  }
372
-
373
322
  async function startResolving(resolutionMap) {
374
323
  if (resolutionMap.length === 0) {
375
324
  return Promise.reject();
376
325
  }
377
-
378
326
  const [{
379
327
  possibleRequests
380
328
  }] = resolutionMap;
381
-
382
329
  if (possibleRequests.length === 0) {
383
330
  return Promise.reject();
384
331
  }
385
-
386
332
  const [{
387
333
  resolve,
388
334
  context
389
335
  }] = resolutionMap;
390
-
391
336
  try {
392
337
  return await resolve(context, possibleRequests[0]);
393
338
  } catch (_ignoreError) {
394
339
  const [, ...tailResult] = possibleRequests;
395
-
396
340
  if (tailResult.length === 0) {
397
341
  const [, ...tailResolutionMap] = resolutionMap;
398
342
  return startResolving(tailResolutionMap);
399
- } // eslint-disable-next-line no-param-reassign
400
-
343
+ }
401
344
 
345
+ // eslint-disable-next-line no-param-reassign
402
346
  resolutionMap[0].possibleRequests = tailResult;
403
347
  return startResolving(resolutionMap);
404
348
  }
405
349
  }
406
-
407
- const IS_SPECIAL_MODULE_IMPORT = /^~[^/]+$/; // `[drive_letter]:\` + `\\[server]\[sharename]\`
408
-
350
+ const IS_SPECIAL_MODULE_IMPORT = /^~[^/]+$/;
351
+ // `[drive_letter]:\` + `\\[server]\[sharename]\`
409
352
  const IS_NATIVE_WIN32_PATH = /^[a-z]:[/\\]|^\\\\/i;
353
+
410
354
  /**
411
355
  * @public
412
356
  * Create the resolve function used in the custom Sass importer.
@@ -424,9 +368,9 @@ const IS_NATIVE_WIN32_PATH = /^[a-z]:[/\\]|^\\\\/i;
424
368
  *
425
369
  * @throws If a compatible Sass implementation cannot be found.
426
370
  */
427
-
428
371
  function getWebpackResolver(resolverFactory, implementation, includePaths = []) {
429
- const isDartSass = implementation && implementation.info.includes("dart-sass"); // We only have one difference with the built-in sass resolution logic and out resolution logic:
372
+ const isDartSass = implementation && implementation.info.includes("dart-sass");
373
+ // We only have one difference with the built-in sass resolution logic and out resolution logic:
430
374
  // First, we look at the files starting with `_`, then without `_` (i.e. `_name.sass`, `_name.scss`, `_name.css`, `name.sass`, `name.scss`, `name.css`),
431
375
  // although `sass` look together by extensions (i.e. `_name.sass`/`name.sass`/`_name.scss`/`name.scss`/`_name.css`/`name.css`).
432
376
  // It shouldn't be a problem because `sass` throw errors:
@@ -434,7 +378,6 @@ function getWebpackResolver(resolverFactory, implementation, includePaths = [])
434
378
  // - on having `_name.sass` and `_name.scss` in the same directory
435
379
  //
436
380
  // Also `sass` prefer `sass`/`scss` over `css`.
437
-
438
381
  const sassModuleResolve = promiseResolve(resolverFactory({
439
382
  alias: [],
440
383
  aliasFields: [],
@@ -486,10 +429,8 @@ function getWebpackResolver(resolverFactory, implementation, includePaths = [])
486
429
  if (!isDartSass && !_path.default.isAbsolute(context)) {
487
430
  return Promise.reject();
488
431
  }
489
-
490
432
  const originalRequest = request;
491
433
  const isFileScheme = originalRequest.slice(0, 5).toLowerCase() === "file:";
492
-
493
434
  if (isFileScheme) {
494
435
  try {
495
436
  // eslint-disable-next-line no-param-reassign
@@ -499,15 +440,15 @@ function getWebpackResolver(resolverFactory, implementation, includePaths = [])
499
440
  request = request.slice(7);
500
441
  }
501
442
  }
502
-
503
443
  let resolutionMap = [];
504
- const needEmulateSassResolver = // `sass` doesn't support module import
505
- !IS_SPECIAL_MODULE_IMPORT.test(request) && // We need improve absolute paths handling.
444
+ const needEmulateSassResolver =
445
+ // `sass` doesn't support module import
446
+ !IS_SPECIAL_MODULE_IMPORT.test(request) &&
447
+ // We need improve absolute paths handling.
506
448
  // Absolute paths should be resolved:
507
449
  // - Server-relative URLs - `<context>/path/to/file.ext` (where `<context>` is root context)
508
450
  // - Absolute path - `/full/path/to/file.ext` or `C:\\full\path\to\file.ext`
509
451
  !isFileScheme && !originalRequest.startsWith("/") && !IS_NATIVE_WIN32_PATH.test(originalRequest);
510
-
511
452
  if (includePaths.length > 0 && needEmulateSassResolver) {
512
453
  // The order of import precedence is as follows:
513
454
  //
@@ -518,8 +459,9 @@ function getWebpackResolver(resolverFactory, implementation, includePaths = [])
518
459
  // 5. Filesystem imports relative to a `SASS_PATH` path.
519
460
  //
520
461
  // `sass` run custom importers before `3`, `4` and `5` points, we need to emulate this behavior to avoid wrong resolution.
521
- const sassPossibleRequests = getPossibleRequests(request, false, fromImport); // `node-sass` calls our importer before `1. Filesystem imports relative to the base file.`, so we need emulate this too
462
+ const sassPossibleRequests = getPossibleRequests(request, false, fromImport);
522
463
 
464
+ // `node-sass` calls our importer before `1. Filesystem imports relative to the base file.`, so we need emulate this too
523
465
  if (!isDartSass) {
524
466
  resolutionMap = resolutionMap.concat({
525
467
  resolve: fromImport ? sassImportResolve : sassModuleResolve,
@@ -527,8 +469,8 @@ function getWebpackResolver(resolverFactory, implementation, includePaths = [])
527
469
  possibleRequests: sassPossibleRequests
528
470
  });
529
471
  }
530
-
531
- resolutionMap = resolutionMap.concat( // eslint-disable-next-line no-shadow
472
+ resolutionMap = resolutionMap.concat(
473
+ // eslint-disable-next-line no-shadow
532
474
  includePaths.map(context => {
533
475
  return {
534
476
  resolve: fromImport ? sassImportResolve : sassModuleResolve,
@@ -537,7 +479,6 @@ function getWebpackResolver(resolverFactory, implementation, includePaths = [])
537
479
  };
538
480
  }));
539
481
  }
540
-
541
482
  const webpackPossibleRequests = getPossibleRequests(request, true, fromImport);
542
483
  resolutionMap = resolutionMap.concat({
543
484
  resolve: fromImport ? webpackImportResolve : webpackModuleResolve,
@@ -547,21 +488,17 @@ function getWebpackResolver(resolverFactory, implementation, includePaths = [])
547
488
  return startResolving(resolutionMap);
548
489
  };
549
490
  }
550
-
551
491
  const MATCH_CSS = /\.css$/i;
552
-
553
492
  function getModernWebpackImporter() {
554
493
  return {
555
494
  async canonicalize() {
556
495
  return null;
557
496
  },
558
-
559
- load() {// TODO implement
497
+ load() {
498
+ // TODO implement
560
499
  }
561
-
562
500
  };
563
501
  }
564
-
565
502
  function getWebpackImporter(loaderContext, implementation, includePaths) {
566
503
  const resolve = getWebpackResolver(loaderContext.getResolve, implementation, includePaths);
567
504
  return function importer(originalUrl, prev, done) {
@@ -572,12 +509,14 @@ function getWebpackImporter(loaderContext, implementation, includePaths) {
572
509
  // Add the result as dependency.
573
510
  // Although we're also using stats.includedFiles, this might come in handy when an error occurs.
574
511
  // In this case, we don't get stats.includedFiles from node-sass/sass.
575
- loaderContext.addDependency(_path.default.normalize(result)); // By removing the CSS file extension, we trigger node-sass to include the CSS file instead of just linking it.
512
+ loaderContext.addDependency(_path.default.normalize(result));
576
513
 
514
+ // By removing the CSS file extension, we trigger node-sass to include the CSS file instead of just linking it.
577
515
  done({
578
516
  file: result.replace(MATCH_CSS, "")
579
517
  });
580
- }) // Catch all resolving errors, return the original file and pass responsibility back to other custom importers
518
+ })
519
+ // Catch all resolving errors, return the original file and pass responsibility back to other custom importers
581
520
  .catch(() => {
582
521
  done({
583
522
  file: originalUrl
@@ -585,8 +524,8 @@ function getWebpackImporter(loaderContext, implementation, includePaths) {
585
524
  });
586
525
  };
587
526
  }
588
-
589
527
  let nodeSassJobQueue = null;
528
+
590
529
  /**
591
530
  * Verifies that the implementation and version of Sass is supported by this loader.
592
531
  *
@@ -594,10 +533,8 @@ let nodeSassJobQueue = null;
594
533
  * @param {Object} options
595
534
  * @returns {Function}
596
535
  */
597
-
598
536
  function getCompileFn(implementation, options) {
599
537
  const isNewSass = implementation.info.includes("dart-sass") || implementation.info.includes("sass-embedded");
600
-
601
538
  if (isNewSass) {
602
539
  if (options.api === "modern") {
603
540
  return sassOptions => {
@@ -608,89 +545,81 @@ function getCompileFn(implementation, options) {
608
545
  return implementation.compileStringAsync(data, rest);
609
546
  };
610
547
  }
611
-
612
548
  return sassOptions => new Promise((resolve, reject) => {
613
549
  implementation.render(sassOptions, (error, result) => {
614
550
  if (error) {
615
551
  reject(error);
616
552
  return;
617
553
  }
618
-
619
554
  resolve(result);
620
555
  });
621
556
  });
622
557
  }
623
-
624
558
  if (options.api === "modern") {
625
559
  throw new Error("Modern API is not supported for 'node-sass'");
626
- } // There is an issue with node-sass when async custom importers are used
560
+ }
561
+
562
+ // There is an issue with node-sass when async custom importers are used
627
563
  // See https://github.com/sass/node-sass/issues/857#issuecomment-93594360
628
564
  // We need to use a job queue to make sure that one thread is always available to the UV lib
629
-
630
-
631
565
  if (nodeSassJobQueue === null) {
632
566
  const threadPoolSize = Number(process.env.UV_THREADPOOL_SIZE || 4);
633
567
  nodeSassJobQueue = _neoAsync.default.queue(implementation.render.bind(implementation), threadPoolSize - 1);
634
568
  }
635
-
636
569
  return sassOptions => new Promise((resolve, reject) => {
637
570
  nodeSassJobQueue.push.bind(nodeSassJobQueue)(sassOptions, (error, result) => {
638
571
  if (error) {
639
572
  reject(error);
640
573
  return;
641
574
  }
642
-
643
575
  resolve(result);
644
576
  });
645
577
  });
646
578
  }
647
-
648
579
  const ABSOLUTE_SCHEME = /^[A-Za-z0-9+\-.]+:/;
580
+
649
581
  /**
650
582
  * @param {string} source
651
583
  * @returns {"absolute" | "scheme-relative" | "path-absolute" | "path-absolute"}
652
584
  */
653
-
654
585
  function getURLType(source) {
655
586
  if (source[0] === "/") {
656
587
  if (source[1] === "/") {
657
588
  return "scheme-relative";
658
589
  }
659
-
660
590
  return "path-absolute";
661
591
  }
662
-
663
592
  if (IS_NATIVE_WIN32_PATH.test(source)) {
664
593
  return "path-absolute";
665
594
  }
666
-
667
595
  return ABSOLUTE_SCHEME.test(source) ? "absolute" : "path-relative";
668
596
  }
669
-
670
597
  function normalizeSourceMap(map, rootContext) {
671
- const newMap = map; // result.map.file is an optional property that provides the output filename.
598
+ const newMap = map;
599
+
600
+ // result.map.file is an optional property that provides the output filename.
672
601
  // Since we don't know the final filename in the webpack build chain yet, it makes no sense to have it.
673
602
  // eslint-disable-next-line no-param-reassign
674
-
675
603
  if (typeof newMap.file !== "undefined") {
676
604
  delete newMap.file;
677
- } // eslint-disable-next-line no-param-reassign
605
+ }
678
606
 
607
+ // eslint-disable-next-line no-param-reassign
608
+ newMap.sourceRoot = "";
679
609
 
680
- newMap.sourceRoot = ""; // node-sass returns POSIX paths, that's why we need to transform them back to native paths.
610
+ // node-sass returns POSIX paths, that's why we need to transform them back to native paths.
681
611
  // This fixes an error on windows where the source-map module cannot resolve the source maps.
682
612
  // @see https://github.com/webpack-contrib/sass-loader/issues/366#issuecomment-279460722
683
613
  // eslint-disable-next-line no-param-reassign
684
-
685
614
  newMap.sources = newMap.sources.map(source => {
686
- const sourceType = getURLType(source); // Do no touch `scheme-relative`, `path-absolute` and `absolute` types (except `file:`)
615
+ const sourceType = getURLType(source);
687
616
 
617
+ // Do no touch `scheme-relative`, `path-absolute` and `absolute` types (except `file:`)
688
618
  if (sourceType === "absolute" && /^file:/i.test(source)) {
689
619
  return _url.default.fileURLToPath(source);
690
620
  } else if (sourceType === "path-relative") {
691
621
  return _path.default.resolve(rootContext, _path.default.normalize(source));
692
622
  }
693
-
694
623
  return source;
695
624
  });
696
625
  return newMap;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sass-loader",
3
- "version": "13.2.0",
3
+ "version": "13.2.1",
4
4
  "description": "Sass loader for webpack",
5
5
  "license": "MIT",
6
6
  "repository": "webpack-contrib/sass-loader",
@@ -26,6 +26,7 @@
26
26
  "lint:js": "eslint --cache .",
27
27
  "lint": "npm-run-all -l -p \"lint:**\"",
28
28
  "test:only": "cross-env NODE_ENV=test jest",
29
+ "lint:spelling": "cspell \"**/*.*\"",
29
30
  "test:watch": "npm run test:only -- --watch",
30
31
  "test:manual": "npm run build && webpack-dev-server test/manual/src/index.js --open --config test/manual/webpack.config.js",
31
32
  "test:coverage": "npm run test:only -- --collectCoverageFrom=\"src/**/*.js\" --coverage",
@@ -59,47 +60,48 @@
59
60
  }
60
61
  },
61
62
  "dependencies": {
62
- "klona": "^2.0.4",
63
+ "klona": "^2.0.6",
63
64
  "neo-async": "^2.6.2"
64
65
  },
65
66
  "devDependencies": {
66
- "@babel/cli": "^7.19.3",
67
- "@babel/core": "^7.19.6",
68
- "@babel/preset-env": "^7.19.4",
69
- "@commitlint/cli": "^17.2.0",
70
- "@commitlint/config-conventional": "^17.2.0",
67
+ "@babel/cli": "^7.20.7",
68
+ "@babel/core": "^7.20.12",
69
+ "@babel/preset-env": "^7.20.2",
70
+ "@commitlint/cli": "^17.4.2",
71
+ "@commitlint/config-conventional": "^17.4.2",
71
72
  "@webpack-contrib/eslint-config-webpack": "^3.0.0",
72
- "babel-jest": "^29.2.2",
73
+ "babel-jest": "^29.4.1",
73
74
  "bootstrap-sass": "^3.4.1",
74
75
  "bootstrap-v4": "npm:bootstrap@^4.5.3",
75
76
  "bootstrap-v5": "npm:bootstrap@^5.0.1",
76
77
  "cross-env": "^7.0.3",
77
- "css-loader": "^6.6.0",
78
+ "cspell": "^6.20.1",
79
+ "css-loader": "^6.7.3",
78
80
  "del": "^6.1.1",
79
81
  "del-cli": "^4.0.1",
80
- "enhanced-resolve": "^5.10.0",
81
- "eslint": "^8.26.0",
82
- "eslint-config-prettier": "^8.3.0",
83
- "eslint-plugin-import": "^2.25.4",
82
+ "enhanced-resolve": "^5.12.0",
83
+ "eslint": "^8.33.0",
84
+ "eslint-config-prettier": "^8.6.0",
85
+ "eslint-plugin-import": "^2.27.5",
84
86
  "fibers": "^5.0.3",
85
87
  "file-loader": "^6.2.0",
86
88
  "foundation-sites": "^6.7.5",
87
- "husky": "^8.0.1",
88
- "jest": "^29.2.2",
89
+ "husky": "^8.0.3",
90
+ "jest": "^29.4.1",
89
91
  "jest-environment-node-single-context": "^29.0.0",
90
92
  "lint-staged": "^12.5.0",
91
93
  "material-components-web": "^8.0.0",
92
- "memfs": "^3.4.9",
94
+ "memfs": "^3.4.13",
93
95
  "node-sass": "^8.0.0",
94
96
  "node-sass-glob-importer": "^5.3.2",
95
97
  "npm-run-all": "^4.1.5",
96
- "prettier": "^2.7.1",
97
- "sass": "^1.55.0",
98
- "sass-embedded": "^1.55.0",
98
+ "prettier": "^2.8.3",
99
+ "sass": "^1.58.0",
100
+ "sass-embedded": "^1.57.1",
99
101
  "semver": "^7.3.8",
100
102
  "standard-version": "^9.3.1",
101
103
  "style-loader": "^3.2.1",
102
- "webpack": "^5.74.0"
104
+ "webpack": "^5.75.0"
103
105
  },
104
106
  "keywords": [
105
107
  "sass",