sass-loader 9.0.2 → 10.0.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/CHANGELOG.md CHANGED
@@ -2,6 +2,32 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [10.0.1](https://github.com/webpack-contrib/sass-loader/compare/v10.0.0...v10.0.1) (2020-08-25)
6
+
7
+ ### Chore
8
+
9
+ * update deps
10
+
11
+ ## [10.0.0](https://github.com/webpack-contrib/sass-loader/compare/v10.0.0-rc.0...v10.0.0) (2020-08-24)
12
+
13
+ ### Bug Fixes
14
+
15
+ * handle absolute windows path in source maps
16
+
17
+ ## [10.0.0-rc.0](https://github.com/webpack-contrib/sass-loader/compare/v9.0.3...v10.0.0-rc.0) (2020-08-24)
18
+
19
+
20
+ ### ⚠ BREAKING CHANGES
21
+
22
+ * loader generates absolute `sources` in source maps, also avoids modifying `sass` source maps if the `sourceMap` option is `false`
23
+
24
+ ### [9.0.3](https://github.com/webpack-contrib/sass-loader/compare/v9.0.2...v9.0.3) (2020-08-05)
25
+
26
+
27
+ ### Bug Fixes
28
+
29
+ * resolution algorithm ([#875](https://github.com/webpack-contrib/sass-loader/issues/875)) ([ea73cfa](https://github.com/webpack-contrib/sass-loader/commit/ea73cfab047c751e1055d0c2ec58ef503f7dbe36))
30
+
5
31
  ### [9.0.2](https://github.com/webpack-contrib/sass-loader/compare/v9.0.1...v9.0.2) (2020-07-07)
6
32
 
7
33
 
package/dist/index.js CHANGED
@@ -32,7 +32,8 @@ function loader(content) {
32
32
  baseDataPath: 'options'
33
33
  });
34
34
  const implementation = (0, _utils.getSassImplementation)(options.implementation);
35
- const sassOptions = (0, _utils.getSassOptions)(this, options, content, implementation);
35
+ const useSourceMap = typeof options.sourceMap === 'boolean' ? options.sourceMap : this.sourceMap;
36
+ const sassOptions = (0, _utils.getSassOptions)(this, options, content, implementation, useSourceMap);
36
37
  const shouldUseWebpackImporter = typeof options.webpackImporter === 'boolean' ? options.webpackImporter : true;
37
38
 
38
39
  if (shouldUseWebpackImporter) {
@@ -54,22 +55,23 @@ function loader(content) {
54
55
 
55
56
  callback(new _SassError.default(error));
56
57
  return;
57
- }
58
+ } // Modify source paths only for webpack, otherwise we do nothing
59
+
58
60
 
59
- if (result.map) {
61
+ if (result.map && useSourceMap) {
60
62
  // eslint-disable-next-line no-param-reassign
61
63
  result.map = JSON.parse(result.map); // result.map.file is an optional property that provides the output filename.
62
64
  // Since we don't know the final filename in the webpack build chain yet, it makes no sense to have it.
63
65
  // eslint-disable-next-line no-param-reassign
64
66
 
65
- delete result.map.file; // node-sass returns POSIX paths, that's why we need to transform them back to native paths.
67
+ delete result.map.file; // eslint-disable-next-line no-param-reassign
68
+
69
+ result.sourceRoot = ''; // node-sass returns POSIX paths, that's why we need to transform them back to native paths.
66
70
  // This fixes an error on windows where the source-map module cannot resolve the source maps.
67
71
  // @see https://github.com/webpack-contrib/sass-loader/issues/366#issuecomment-279460722
68
72
  // eslint-disable-next-line no-param-reassign
69
73
 
70
- result.map.sourceRoot = _path.default.normalize(result.map.sourceRoot); // eslint-disable-next-line no-param-reassign
71
-
72
- result.map.sources = result.map.sources.map(_path.default.normalize);
74
+ result.map.sources = result.map.sources.map(source => (0, _utils.absolutifySourceMapSource)(this.rootContext, source));
73
75
  }
74
76
 
75
77
  result.stats.includedFiles.forEach(includedFile => {
package/dist/utils.js CHANGED
@@ -3,11 +3,12 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = getPossibleRequests;
7
6
  exports.getSassImplementation = getSassImplementation;
8
7
  exports.getSassOptions = getSassOptions;
8
+ exports.getWebpackResolver = getWebpackResolver;
9
9
  exports.getWebpackImporter = getWebpackImporter;
10
10
  exports.getRenderFunctionFromSassImplementation = getRenderFunctionFromSassImplementation;
11
+ exports.absolutifySourceMapSource = absolutifySourceMapSource;
11
12
 
12
13
  var _url = _interopRequireDefault(require("url"));
13
14
 
@@ -15,7 +16,7 @@ var _path = _interopRequireDefault(require("path"));
15
16
 
16
17
  var _semver = _interopRequireDefault(require("semver"));
17
18
 
18
- var _klona = _interopRequireDefault(require("klona"));
19
+ var _full = require("klona/full");
19
20
 
20
21
  var _loaderUtils = require("loader-utils");
21
22
 
@@ -41,6 +42,12 @@ function getDefaultSassImplementation() {
41
42
 
42
43
  return require(sassImplPkg);
43
44
  }
45
+ /**
46
+ * @public
47
+ * This function is not Webpack-specific and can be used by tools wishing to
48
+ * mimic `sass-loader`'s behaviour, so its signature should not be changed.
49
+ */
50
+
44
51
 
45
52
  function getSassImplementation(implementation) {
46
53
  let resolvedImplementation = implementation;
@@ -102,12 +109,13 @@ function proxyCustomImporters(importers, loaderContext) {
102
109
  * @param {object} loaderOptions
103
110
  * @param {string} content
104
111
  * @param {object} implementation
112
+ * @param {boolean} useSourceMap
105
113
  * @returns {Object}
106
114
  */
107
115
 
108
116
 
109
- function getSassOptions(loaderContext, loaderOptions, content, implementation) {
110
- const options = (0, _klona.default)(loaderOptions.sassOptions ? typeof loaderOptions.sassOptions === 'function' ? loaderOptions.sassOptions(loaderContext) || {} : loaderOptions.sassOptions : {});
117
+ function getSassOptions(loaderContext, loaderOptions, content, implementation, useSourceMap) {
118
+ const options = (0, _full.klona)(loaderOptions.sassOptions ? typeof loaderOptions.sassOptions === 'function' ? loaderOptions.sassOptions(loaderContext) || {} : loaderOptions.sassOptions : {});
111
119
  const isDartSass = implementation.info.includes('dart-sass');
112
120
 
113
121
  if (isDartSass) {
@@ -141,8 +149,6 @@ function getSassOptions(loaderContext, loaderOptions, content, implementation) {
141
149
  options.outputStyle = 'compressed';
142
150
  }
143
151
 
144
- const useSourceMap = typeof loaderOptions.sourceMap === 'boolean' ? loaderOptions.sourceMap : loaderContext.sourceMap;
145
-
146
152
  if (useSourceMap) {
147
153
  // Deliberately overriding the sourceMap option here.
148
154
  // node-sass won't produce source maps if the data option is used and options.sourceMap is not a string.
@@ -150,8 +156,9 @@ function getSassOptions(loaderContext, loaderOptions, content, implementation) {
150
156
  // But since we're using the data option, the source map will not actually be written, but
151
157
  // all paths in sourceMap.sources will be relative to that path.
152
158
  // Pretty complicated... :(
153
- options.sourceMap = _path.default.join(process.cwd(), '/sass.css.map');
154
- options.sourceMapRoot = process.cwd();
159
+ options.sourceMap = true;
160
+ options.outFile = _path.default.join(loaderContext.rootContext, 'style.css.map'); // options.sourceMapRoot = process.cwd();
161
+
155
162
  options.sourceMapContents = true;
156
163
  options.omitSourceMapUrl = true;
157
164
  options.sourceMapEmbed = false;
@@ -195,15 +202,14 @@ const isModuleImport = /^~([^/]+|[^/]+\/|@[^/]+[/][^/]+|@[^/]+\/?|@[^/]+[/][^/]+
195
202
  *
196
203
  * @param {string} url
197
204
  * @param {boolean} forWebpackResolver
198
- * @param {Object} loaderContext
205
+ * @param {string} rootContext
199
206
  * @returns {Array<string>}
200
207
  */
201
208
 
202
- function getPossibleRequests(loaderContext, // eslint-disable-next-line no-shadow
203
- url, forWebpackResolver = false) {
209
+ function getPossibleRequests( // eslint-disable-next-line no-shadow
210
+ url, forWebpackResolver = false, rootContext = false) {
204
211
  const request = (0, _loaderUtils.urlToRequest)(url, // Maybe it is server-relative URLs
205
- forWebpackResolver && url.charAt(0) === '/' ? loaderContext.rootContext : // eslint-disable-next-line no-undefined
206
- undefined); // In case there is module request, send this to webpack resolver
212
+ forWebpackResolver && rootContext); // In case there is module request, send this to webpack resolver
207
213
 
208
214
  if (forWebpackResolver && isModuleImport.test(url)) {
209
215
  return [...new Set([request, url])];
@@ -229,16 +235,45 @@ url, forWebpackResolver = false) {
229
235
 
230
236
  const basename = _path.default.basename(request);
231
237
 
232
- return [...new Set([`${dirname}/_${basename}`, request].concat(forWebpackResolver ? [url] : []))];
238
+ return [...new Set([`${dirname}/_${basename}`, request].concat(forWebpackResolver ? [`${_path.default.dirname(url)}/_${basename}`, url] : []))];
233
239
  }
234
240
 
235
- const matchCss = /\.css$/i;
236
- const isSpecialModuleImport = /^~[^/]+$/; // `[drive_letter]:\` + `\\[server]\[sharename]\`
241
+ function promiseResolve(callbackResolve) {
242
+ return (context, request) => new Promise((resolve, reject) => {
243
+ callbackResolve(context, request, (error, result) => {
244
+ if (error) {
245
+ reject(error);
246
+ } else {
247
+ resolve(result);
248
+ }
249
+ });
250
+ });
251
+ }
237
252
 
238
- const isNativeWin32Path = /^[a-zA-Z]:[/\\]|^\\\\/i;
253
+ const IS_SPECIAL_MODULE_IMPORT = /^~[^/]+$/; // `[drive_letter]:\` + `\\[server]\[sharename]\`
239
254
 
240
- function getWebpackImporter(loaderContext, implementation, includePaths) {
241
- function startResolving(resolutionMap) {
255
+ const IS_NATIVE_WIN32_PATH = /^[a-z]:[/\\]|^\\\\/i;
256
+ /**
257
+ * @public
258
+ * Create the resolve function used in the custom Sass importer.
259
+ *
260
+ * Can be used by external tools to mimic how `sass-loader` works, for example
261
+ * in a Jest transform. Such usages will want to wrap `resolve.create` from
262
+ * [`enhanced-resolve`]{@link https://github.com/webpack/enhanced-resolve} to
263
+ * pass as the `resolverFactory` argument.
264
+ *
265
+ * @param {Function} resolverFactory - A factory function for creating a Webpack
266
+ * resolver.
267
+ * @param {Object} implementation - The imported Sass implementation, both
268
+ * `sass` (Dart Sass) and `node-sass` are supported.
269
+ * @param {string[]} [includePaths] - The list of include paths passed to Sass.
270
+ * @param {boolean} [rootContext] - The configured Webpack root context.
271
+ *
272
+ * @throws If a compatible Sass implementation cannot be found.
273
+ */
274
+
275
+ function getWebpackResolver(resolverFactory, implementation, includePaths = [], rootContext = false) {
276
+ async function startResolving(resolutionMap) {
242
277
  if (resolutionMap.length === 0) {
243
278
  return Promise.reject();
244
279
  }
@@ -248,16 +283,10 @@ function getWebpackImporter(loaderContext, implementation, includePaths) {
248
283
  context,
249
284
  possibleRequests
250
285
  }] = resolutionMap;
251
- return resolve(context, possibleRequests[0]).then(result => {
252
- // Add the result as dependency.
253
- // Although we're also using stats.includedFiles, this might come in handy when an error occurs.
254
- // In this case, we don't get stats.includedFiles from node-sass/sass.
255
- 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.
256
286
 
257
- return {
258
- file: result.replace(matchCss, '')
259
- };
260
- }).catch(() => {
287
+ try {
288
+ return await resolve(context, possibleRequests[0]);
289
+ } catch (_ignoreError) {
261
290
  const [, ...tailResult] = possibleRequests;
262
291
 
263
292
  if (tailResult.length === 0) {
@@ -268,10 +297,11 @@ function getWebpackImporter(loaderContext, implementation, includePaths) {
268
297
 
269
298
  resolutionMap[0].possibleRequests = tailResult;
270
299
  return startResolving(resolutionMap);
271
- });
300
+ }
272
301
  }
273
302
 
274
- const sassResolve = loaderContext.getResolve({
303
+ const isDartSass = implementation.info.includes('dart-sass');
304
+ const sassResolve = promiseResolve(resolverFactory({
275
305
  alias: [],
276
306
  aliasFields: [],
277
307
  conditionNames: [],
@@ -282,34 +312,35 @@ function getWebpackImporter(loaderContext, implementation, includePaths) {
282
312
  mainFiles: ['_index', 'index'],
283
313
  modules: [],
284
314
  restrictions: [/\.((sa|sc|c)ss)$/i]
285
- });
286
- const webpackResolve = loaderContext.getResolve({
315
+ }));
316
+ const webpackResolve = promiseResolve(resolverFactory({
287
317
  conditionNames: ['sass', 'style'],
288
318
  mainFields: ['sass', 'style', 'main', '...'],
289
319
  mainFiles: ['_index', 'index', '...'],
290
320
  extensions: ['.sass', '.scss', '.css'],
291
321
  restrictions: [/\.((sa|sc|c)ss)$/i]
292
- });
293
- return (originalUrl, prev, done) => {
294
- let request = originalUrl;
295
- const isFileScheme = originalUrl.slice(0, 5).toLowerCase() === 'file:';
322
+ }));
323
+ return (context, request) => {
324
+ const originalRequest = request;
325
+ const isFileScheme = originalRequest.slice(0, 5).toLowerCase() === 'file:';
296
326
 
297
327
  if (isFileScheme) {
298
328
  try {
299
329
  // eslint-disable-next-line no-param-reassign
300
- request = _url.default.fileURLToPath(originalUrl);
330
+ request = _url.default.fileURLToPath(originalRequest);
301
331
  } catch (ignoreError) {
332
+ // eslint-disable-next-line no-param-reassign
302
333
  request = request.slice(7);
303
334
  }
304
335
  }
305
336
 
306
337
  let resolutionMap = [];
307
338
  const needEmulateSassResolver = // `sass` doesn't support module import
308
- !isSpecialModuleImport.test(request) && // We need improve absolute paths handling.
339
+ !IS_SPECIAL_MODULE_IMPORT.test(request) && // We need improve absolute paths handling.
309
340
  // Absolute paths should be resolved:
310
341
  // - Server-relative URLs - `<context>/path/to/file.ext` (where `<context>` is root context)
311
342
  // - Absolute path - `/full/path/to/file.ext` or `C:\\full\path\to\file.ext`
312
- !isFileScheme && !originalUrl.startsWith('/') && !isNativeWin32Path.test(originalUrl);
343
+ !isFileScheme && !originalRequest.startsWith('/') && !IS_NATIVE_WIN32_PATH.test(originalRequest);
313
344
 
314
345
  if (includePaths.length > 0 && needEmulateSassResolver) {
315
346
  // The order of import precedence is as follows:
@@ -321,34 +352,54 @@ function getWebpackImporter(loaderContext, implementation, includePaths) {
321
352
  // 5. Filesystem imports relative to a `SASS_PATH` path.
322
353
  //
323
354
  // Because `sass`/`node-sass` run custom importers before `3`, `4` and `5` points, we need to emulate this behavior to avoid wrong resolution.
324
- const sassPossibleRequests = getPossibleRequests(loaderContext, request);
325
- const isDartSass = implementation.info.includes('dart-sass'); // `node-sass` calls our importer before `1. Filesystem imports relative to the base file.`, so we need emulate this too
355
+ const sassPossibleRequests = getPossibleRequests(request); // `node-sass` calls our importer before `1. Filesystem imports relative to the base file.`, so we need emulate this too
326
356
 
327
357
  if (!isDartSass) {
328
358
  resolutionMap = resolutionMap.concat({
329
359
  resolve: sassResolve,
330
- context: _path.default.dirname(prev),
360
+ context: _path.default.dirname(context),
331
361
  possibleRequests: sassPossibleRequests
332
362
  });
333
363
  }
334
364
 
335
- resolutionMap = resolutionMap.concat(includePaths.map(context => ({
365
+ resolutionMap = resolutionMap.concat( // eslint-disable-next-line no-shadow
366
+ includePaths.map(context => ({
336
367
  resolve: sassResolve,
337
368
  context,
338
369
  possibleRequests: sassPossibleRequests
339
370
  })));
340
371
  }
341
372
 
342
- const webpackPossibleRequests = getPossibleRequests(loaderContext, request, true);
373
+ const webpackPossibleRequests = getPossibleRequests(request, true, rootContext);
343
374
  resolutionMap = resolutionMap.concat({
344
375
  resolve: webpackResolve,
345
- context: _path.default.dirname(prev),
376
+ context: _path.default.dirname(context),
346
377
  possibleRequests: webpackPossibleRequests
347
378
  });
348
- startResolving(resolutionMap) // Catch all resolving errors, return the original file and pass responsibility back to other custom importers
349
- .catch(() => ({
350
- file: originalUrl
351
- })).then(done);
379
+ return startResolving(resolutionMap);
380
+ };
381
+ }
382
+
383
+ const matchCss = /\.css$/i;
384
+
385
+ function getWebpackImporter(loaderContext, implementation, includePaths) {
386
+ const resolve = getWebpackResolver(loaderContext.getResolve, implementation, includePaths, loaderContext.rootContext);
387
+ return (originalUrl, prev, done) => {
388
+ resolve(prev, originalUrl).then(result => {
389
+ // Add the result as dependency.
390
+ // Although we're also using stats.includedFiles, this might come in handy when an error occurs.
391
+ // In this case, we don't get stats.includedFiles from node-sass/sass.
392
+ 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.
393
+
394
+ done({
395
+ file: result.replace(matchCss, '')
396
+ });
397
+ }) // Catch all resolving errors, return the original file and pass responsibility back to other custom importers
398
+ .catch(() => {
399
+ done({
400
+ file: originalUrl
401
+ });
402
+ });
352
403
  };
353
404
  }
354
405
 
@@ -376,4 +427,32 @@ function getRenderFunctionFromSassImplementation(implementation) {
376
427
  }
377
428
 
378
429
  return nodeSassJobQueue.push.bind(nodeSassJobQueue);
430
+ }
431
+
432
+ const ABSOLUTE_SCHEME = /^[A-Za-z0-9+\-.]+:/;
433
+
434
+ function getURLType(source) {
435
+ if (source[0] === '/') {
436
+ if (source[1] === '/') {
437
+ return 'scheme-relative';
438
+ }
439
+
440
+ return 'path-absolute';
441
+ }
442
+
443
+ if (IS_NATIVE_WIN32_PATH.test(source)) {
444
+ return 'path-absolute';
445
+ }
446
+
447
+ return ABSOLUTE_SCHEME.test(source) ? 'absolute' : 'path-relative';
448
+ }
449
+
450
+ function absolutifySourceMapSource(sourceRoot, source) {
451
+ const sourceType = getURLType(source); // Do no touch `scheme-relative`, `path-absolute` and `absolute` types
452
+
453
+ if (sourceType === 'path-relative') {
454
+ return _path.default.resolve(sourceRoot, _path.default.normalize(source));
455
+ }
456
+
457
+ return source;
379
458
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sass-loader",
3
- "version": "9.0.2",
3
+ "version": "10.0.1",
4
4
  "description": "Sass loader for webpack",
5
5
  "license": "MIT",
6
6
  "repository": "webpack-contrib/sass-loader",
@@ -56,45 +56,46 @@
56
56
  }
57
57
  },
58
58
  "dependencies": {
59
- "klona": "^1.1.1",
59
+ "klona": "^2.0.3",
60
60
  "loader-utils": "^2.0.0",
61
- "neo-async": "^2.6.1",
61
+ "neo-async": "^2.6.2",
62
62
  "schema-utils": "^2.7.0",
63
63
  "semver": "^7.3.2"
64
64
  },
65
65
  "devDependencies": {
66
- "@babel/cli": "^7.10.3",
67
- "@babel/core": "^7.10.3",
68
- "@babel/preset-env": "^7.10.3",
69
- "@commitlint/cli": "^9.0.1",
70
- "@commitlint/config-conventional": "^9.0.1",
66
+ "@babel/cli": "^7.10.5",
67
+ "@babel/core": "^7.11.4",
68
+ "@babel/preset-env": "^7.11.0",
69
+ "@commitlint/cli": "^10.0.0",
70
+ "@commitlint/config-conventional": "^10.0.0",
71
71
  "@webpack-contrib/defaults": "^6.3.0",
72
72
  "@webpack-contrib/eslint-config-webpack": "^3.0.0",
73
- "babel-jest": "^26.0.1",
74
- "bootstrap": "^4.5.0",
73
+ "babel-jest": "^26.3.0",
74
+ "bootstrap": "^4.5.2",
75
75
  "bootstrap-sass": "^3.4.1",
76
76
  "cross-env": "^7.0.2",
77
- "css-loader": "^3.6.0",
77
+ "css-loader": "^4.2.2",
78
78
  "del": "^5.1.0",
79
79
  "del-cli": "^3.0.1",
80
- "eslint": "^7.3.0",
80
+ "enhanced-resolve": "^4.3.0",
81
+ "eslint": "^7.7.0",
81
82
  "eslint-config-prettier": "^6.11.0",
82
83
  "eslint-plugin-import": "^2.21.2",
83
84
  "fibers": "^5.0.0",
84
85
  "file-loader": "^6.0.0",
85
86
  "foundation-sites": "^6.6.3",
86
87
  "husky": "^4.2.5",
87
- "jest": "^26.0.1",
88
- "lint-staged": "^10.2.11",
88
+ "jest": "^26.4.2",
89
+ "lint-staged": "^10.2.12",
89
90
  "material-components-web": "^7.0.0",
90
91
  "memfs": "^3.2.0",
91
92
  "node-sass": "^4.14.1",
92
93
  "npm-run-all": "^4.1.5",
93
- "prettier": "^2.0.5",
94
- "sass": "^1.26.8",
95
- "standard-version": "^8.0.0",
94
+ "prettier": "^2.1.0",
95
+ "sass": "^1.26.10",
96
+ "standard-version": "^9.0.0",
96
97
  "style-loader": "^1.2.1",
97
- "webpack": "^4.43.0"
98
+ "webpack": "^4.44.1"
98
99
  },
99
100
  "keywords": [
100
101
  "sass",