sass-loader 7.3.1 → 8.0.0

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,31 @@
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
+ ## [8.0.0](https://github.com/webpack-contrib/sass-loader/compare/v7.3.1...v8.0.0) (2019-08-29)
6
+
7
+
8
+ ### ⚠ BREAKING CHANGES
9
+
10
+ * minimum required `webpack` version is `4.36.0`
11
+ * minimum required `node.js` version is `8.9.0`
12
+ * move all sass (`includePaths`, `importer`, `functions`) options to the `sassOptions` option. The `functions` option can't be used as `Function`, you should use `sassOption` as `Function` to achieve this.
13
+ * the `data` option was renamed to the `prependData` option
14
+ * default value of the `sourceMap` option depends on the `devtool` value (`eval`/`false` values don't enable source map generation)
15
+
16
+
17
+ ### Features
18
+
19
+ * automatically use the `fibers` package if it is possible ([#744](https://github.com/webpack-contrib/sass-loader/issues/744)) ([96184e1](https://github.com/webpack-contrib/sass-loader/commit/96184e1))
20
+ * source map generation depends on the `devtool` option ([#743](https://github.com/webpack-contrib/sass-loader/issues/743)) ([fcea88e](https://github.com/webpack-contrib/sass-loader/commit/fcea88e))
21
+ * validate loader options ([#737](https://github.com/webpack-contrib/sass-loader/issues/737)) ([7b543fc](https://github.com/webpack-contrib/sass-loader/commit/7b543fc))
22
+ * reworked error handling from `node-sass`/`sass`
23
+ * improve resolution for `@import` (including support `_index` and `index` files in a directory)
24
+
25
+ ### Bug Fixes
26
+
27
+ * compatibility with `pnp`
28
+
29
+
5
30
  ### [7.3.1](https://github.com/webpack-contrib/sass-loader/compare/v7.3.0...v7.3.1) (2019-08-20)
6
31
 
7
32
 
package/README.md CHANGED
@@ -107,19 +107,44 @@ Thankfully there are a two solutions to this problem:
107
107
 
108
108
  ## Options
109
109
 
110
- By default all options passed to loader also passed to to [Node Sass](https://github.com/sass/node-sass) or [Dart Sass](http://sass-lang.com/dart-sass)
110
+ ### `implementation`
111
111
 
112
- > ℹ️ The `indentedSyntax` option has `true` value for the `sass` extension.
113
- > ℹ️ Options such as `file` and `outFile` are unavailable.
114
- > ℹ️ Only the "expanded" and "compressed" values of outputStyle are supported for `dart-sass`.
115
- > ℹ We recommend don't use `sourceMapContents`, `sourceMapEmbed`, `sourceMapRoot` options because loader automatically setup this options.
112
+ The special `implementation` option determines which implementation of Sass to use.
116
113
 
117
- There is a slight difference between the `node-sass` and `sass` options. We recommend look documentation before used them:
114
+ By default the loader resolve the implementation based on your dependencies.
115
+ Just add required implementation to `package.json` (`node-sass` or `sass` package) and install dependencies.
118
116
 
119
- - [the Node Sass documentation](https://github.com/sass/node-sass/#options) for all available `node-sass` options.
120
- - [the Dart Sass documentation](https://github.com/sass/dart-sass#javascript-api) for all available `sass` options.
117
+ Example where the `sass-loader` loader uses the `sass` (`dart-sass`) implementation:
121
118
 
122
- **webpack.config.js**
119
+ **package.json**
120
+
121
+ ```json
122
+ {
123
+ "devDependencies": {
124
+ "sass-loader": "^7.2.0",
125
+ "sass": "^1.22.10"
126
+ }
127
+ }
128
+ ```
129
+
130
+ Example where the `sass-loader` loader uses the `node-sass` implementation:
131
+
132
+ **package.json**
133
+
134
+ ```json
135
+ {
136
+ "devDependencies": {
137
+ "sass-loader": "^7.2.0",
138
+ "node-sass": "^4.0.0"
139
+ }
140
+ }
141
+ ```
142
+
143
+ Beware the situation when `node-sass` and `sass` was installed, by default the `sass-loader` prefers `node-sass`, to avoid this situation use the `implementation` option.
144
+
145
+ It takes either `node-sass` or `sass` (`Dart Sass`) module.
146
+
147
+ For example, to use Dart Sass, you'd pass:
123
148
 
124
149
  ```js
125
150
  module.exports = {
@@ -133,8 +158,8 @@ module.exports = {
133
158
  {
134
159
  loader: 'sass-loader',
135
160
  options: {
136
- indentWidth: 4,
137
- includePaths: ['absolute/path/a', 'absolute/path/b'],
161
+ // Prefer `dart-sass`
162
+ implementation: require('sass'),
138
163
  },
139
164
  },
140
165
  ],
@@ -144,14 +169,10 @@ module.exports = {
144
169
  };
145
170
  ```
146
171
 
147
- ### `implementation`
148
-
149
- The special `implementation` option determines which implementation of Sass to use.
150
-
151
- By default the loader resolve the implementation based on your dependencies.
152
- Just add required implementation to `package.json` (`node-sass` or `sass` package) and install dependencies.
172
+ Note that when using `sass` (`Dart Sass`), **synchronous compilation is twice as fast as asynchronous compilation** by default, due to the overhead of asynchronous callbacks.
173
+ To avoid this overhead, you can use the [fibers](https://www.npmjs.com/package/fibers) package to call asynchronous importers from the synchronous code path.
153
174
 
154
- Example where the `sass-loader` loader uses the `sass` (`dart-sass`) implementation:
175
+ We automatically inject the [`fibers`](https://github.com/laverdet/node-fibers) package (setup `sassOptions.fiber`) if is possible (i.e. you need install the [`fibers`](https://github.com/laverdet/node-fibers) package).
155
176
 
156
177
  **package.json**
157
178
 
@@ -159,29 +180,44 @@ Example where the `sass-loader` loader uses the `sass` (`dart-sass`) implementat
159
180
  {
160
181
  "devDependencies": {
161
182
  "sass-loader": "^7.2.0",
162
- "sass": "^1.22.10"
183
+ "sass": "^1.22.10",
184
+ "fibers": "^4.0.1"
163
185
  }
164
186
  }
165
187
  ```
166
188
 
167
- Example where the `sass-loader` loader uses the `node-sass` implementation:
189
+ You can disable automatically inject the [`fibers`](https://github.com/laverdet/node-fibers) package pass the `false` value for the `sassOptions.fiber` option.
168
190
 
169
- **package.json**
191
+ **webpack.config.js**
170
192
 
171
- ```json
172
- {
173
- "devDependencies": {
174
- "sass-loader": "^7.2.0",
175
- "node-sass": "^4.0.0"
176
- }
177
- }
193
+ ```js
194
+ module.exports = {
195
+ module: {
196
+ rules: [
197
+ {
198
+ test: /\.s[ac]ss$/i,
199
+ use: [
200
+ 'style-loader',
201
+ 'css-loader',
202
+ {
203
+ loader: 'sass-loader',
204
+ options: {
205
+ implementation: require('sass'),
206
+ sassOptions: {
207
+ fiber: false,
208
+ },
209
+ },
210
+ },
211
+ ],
212
+ },
213
+ ],
214
+ },
215
+ };
178
216
  ```
179
217
 
180
- Beware the situation when `node-sass` and `sass` was installed, by default the `sass-loader` prefers `node-sass`, to avoid this situation use the `implementation` option.
218
+ Also you can pass own the `fiber` value using this code:
181
219
 
182
- It takes either `node-sass` or `sass` (`Dart Sass`) module.
183
-
184
- For example, to use Dart Sass, you'd pass:
220
+ **webpack.config.js**
185
221
 
186
222
  ```js
187
223
  module.exports = {
@@ -195,8 +231,10 @@ module.exports = {
195
231
  {
196
232
  loader: 'sass-loader',
197
233
  options: {
198
- // Prefer `dart-sass`
199
234
  implementation: require('sass'),
235
+ sassOptions: {
236
+ fiber: require('fibers'),
237
+ },
200
238
  },
201
239
  },
202
240
  ],
@@ -206,10 +244,27 @@ module.exports = {
206
244
  };
207
245
  ```
208
246
 
209
- Note that when using `sass` (`Dart Sass`), **synchronous compilation is twice as fast as asynchronous compilation** by default, due to the overhead of asynchronous callbacks.
210
- To avoid this overhead, you can use the [fibers](https://www.npmjs.com/package/fibers) package to call asynchronous importers from the synchronous code path.
247
+ ### `sassOptions`
248
+
249
+ Type: `Object|Function`
250
+
251
+ Options for [Node Sass](https://github.com/sass/node-sass) or [Dart Sass](http://sass-lang.com/dart-sass) implementation.
252
+
253
+ > ℹ️ The `indentedSyntax` option has `true` value for the `sass` extension.
254
+
255
+ > ℹ️ Options such as `file` and `outFile` are unavailable.
256
+
257
+ > ℹ We recommend don't use `sourceMapContents`, `sourceMapEmbed`, `sourceMapRoot` options because loader automatically setup this options.
258
+
259
+ There is a slight difference between the `node-sass` and `sass` (`Dart Sass`) options.
260
+ We recommend look documentation before used them:
261
+
262
+ - [the Node Sass documentation](https://github.com/sass/node-sass/#options) for all available `node-sass` options.
263
+ - [the Dart Sass documentation](https://github.com/sass/dart-sass#javascript-api) for all available `sass` options.
264
+
265
+ #### `Object`
211
266
 
212
- To enable this, pass the `Fiber` class to the `fiber` option:
267
+ Setups option as object for sass implementation.
213
268
 
214
269
  **webpack.config.js**
215
270
 
@@ -225,8 +280,10 @@ module.exports = {
225
280
  {
226
281
  loader: 'sass-loader',
227
282
  options: {
228
- implementation: require('sass'),
229
- fiber: require('fibers'),
283
+ sassOptions: {
284
+ indentWidth: 4,
285
+ includePaths: ['absolute/path/a', 'absolute/path/b'],
286
+ },
230
287
  },
231
288
  },
232
289
  ],
@@ -236,7 +293,47 @@ module.exports = {
236
293
  };
237
294
  ```
238
295
 
239
- ### `data`
296
+ #### `Function`
297
+
298
+ Allows setup difference options based on loader context.
299
+
300
+ ```js
301
+ module.exports = {
302
+ module: {
303
+ rules: [
304
+ {
305
+ test: /\.s[ac]ss$/i,
306
+ use: [
307
+ 'style-loader',
308
+ 'css-loader',
309
+ {
310
+ loader: 'sass-loader',
311
+ options: {
312
+ sassOptions: (loaderContext) => {
313
+ // More information about available properties https://webpack.js.org/api/loaders/
314
+ const { resourcePath, rootContext } = loaderContext;
315
+ const relativePath = path.relative(rootContext, resourcePath);
316
+
317
+ if (relativePath === 'styles/foo.scss') {
318
+ return {
319
+ includePaths: ['absolute/path/c', 'absolute/path/d'],
320
+ };
321
+ }
322
+
323
+ return {
324
+ includePaths: ['absolute/path/a', 'absolute/path/b'],
325
+ };
326
+ },
327
+ },
328
+ },
329
+ ],
330
+ },
331
+ ],
332
+ },
333
+ };
334
+ ```
335
+
336
+ ### `prependData`
240
337
 
241
338
  Type: `String|Function`
242
339
  Default: `undefined`
@@ -262,7 +359,7 @@ module.exports = {
262
359
  {
263
360
  loader: 'sass-loader',
264
361
  options: {
265
- data: '$env: ' + process.env.NODE_ENV + ';',
362
+ prependData: '$env: ' + process.env.NODE_ENV + ';',
266
363
  },
267
364
  },
268
365
  ],
@@ -286,8 +383,8 @@ module.exports = {
286
383
  {
287
384
  loader: 'sass-loader',
288
385
  options: {
289
- data: (loaderContext) => {
290
- // More information about avalaible options https://webpack.js.org/api/loaders/
386
+ prependData: (loaderContext) => {
387
+ // More information about available properties https://webpack.js.org/api/loaders/
291
388
  const { resourcePath, rootContext } = loaderContext;
292
389
  const relativePath = path.relative(rootContext, resourcePath);
293
390
 
@@ -309,11 +406,11 @@ module.exports = {
309
406
  ### `sourceMap`
310
407
 
311
408
  Type: `Boolean`
312
- Default: `false`
409
+ Default: depends on the `compiler.devtool` value
313
410
 
314
411
  Enables/Disables generation of source maps.
315
412
 
316
- They are not enabled by default because they expose a runtime overhead and increase in bundle size (JS source maps do not).
413
+ By default generation of source maps depends on the [`devtool`](https://webpack.js.org/configuration/devtool/) option, all values enable source map generation except `eval` and `false` value.
317
414
 
318
415
  **webpack.config.js**
319
416
 
@@ -351,7 +448,7 @@ module.exports = {
351
448
  Type: `Boolean`
352
449
  Default: `true`
353
450
 
354
- Allows to disable default `webpack` importer.
451
+ Enables/Disables default `webpack` importer.
355
452
 
356
453
  This can improve performance in some cases. Use it with caution because aliases and `@import` at-rules starts with `~` will not work, but you can pass own `importer` to solve this (see [`importer docs`](https://github.com/sass/node-sass#importer--v200---experimental)).
357
454
 
@@ -424,6 +521,8 @@ module.exports = {
424
521
 
425
522
  ### Source maps
426
523
 
524
+ Enables/Disables generation of source maps.
525
+
427
526
  To enable CSS source maps, you'll need to pass the `sourceMap` option to the sass-loader _and_ the css-loader.
428
527
 
429
528
  **webpack.config.js**
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ class SassError extends Error {
9
+ constructor(sassError, resourcePath) {
10
+ super();
11
+ this.name = 'SassError';
12
+ this.originalSassError = sassError;
13
+ this.loc = {
14
+ line: sassError.line,
15
+ column: sassError.column
16
+ }; // Keep original error if `sassError.formatted` is unavailable
17
+
18
+ this.message = `${this.name}: ${this.originalSassError.message}`;
19
+
20
+ if (this.originalSassError.formatted) {
21
+ this.message = `${this.name}: ${this.originalSassError.formatted.replace(/^Error: /, '').replace(/(\s*)stdin(\s*)/, `$1${resourcePath}$2`)}`; // Instruct webpack to hide the JS stack from the console.
22
+ // Usually you're only interested in the SASS stack in this case.
23
+ // eslint-disable-next-line no-param-reassign
24
+
25
+ this.hideStack = true;
26
+ Error.captureStackTrace(this, this.constructor);
27
+ }
28
+ }
29
+
30
+ }
31
+
32
+ var _default = SassError;
33
+ exports.default = _default;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ function getDefaultSassImplementation() {
9
+ let sassImplPkg = 'node-sass';
10
+
11
+ try {
12
+ require.resolve('node-sass');
13
+ } catch (error) {
14
+ try {
15
+ require.resolve('sass');
16
+
17
+ sassImplPkg = 'sass';
18
+ } catch (ignoreError) {
19
+ sassImplPkg = 'node-sass';
20
+ }
21
+ } // eslint-disable-next-line import/no-dynamic-require, global-require
22
+
23
+
24
+ return require(sassImplPkg);
25
+ }
26
+
27
+ var _default = getDefaultSassImplementation;
28
+ exports.default = _default;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _neoAsync = _interopRequireDefault(require("neo-async"));
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+
12
+ let nodeSassJobQueue = null;
13
+ /**
14
+ * Verifies that the implementation and version of Sass is supported by this loader.
15
+ *
16
+ * @param {Object} implementation
17
+ * @returns {Function}
18
+ */
19
+
20
+ function getRenderFunctionFromSassImplementation(implementation) {
21
+ const isDartSass = implementation.info.includes('dart-sass');
22
+
23
+ if (isDartSass) {
24
+ return implementation.render.bind(implementation);
25
+ } // There is an issue with node-sass when async custom importers are used
26
+ // See https://github.com/sass/node-sass/issues/857#issuecomment-93594360
27
+ // We need to use a job queue to make sure that one thread is always available to the UV lib
28
+
29
+
30
+ if (nodeSassJobQueue === null) {
31
+ const threadPoolSize = Number(process.env.UV_THREADPOOL_SIZE || 4);
32
+ nodeSassJobQueue = _neoAsync.default.queue(implementation.render.bind(implementation), threadPoolSize - 1);
33
+ }
34
+
35
+ return nodeSassJobQueue.push.bind(nodeSassJobQueue);
36
+ }
37
+
38
+ var _default = getRenderFunctionFromSassImplementation;
39
+ exports.default = _default;
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _semver = _interopRequireDefault(require("semver"));
9
+
10
+ var _getDefaultSassImplementation = _interopRequireDefault(require("./getDefaultSassImplementation"));
11
+
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
+
14
+ function getSassImplementation(implementation) {
15
+ let resolvedImplementation = implementation;
16
+
17
+ if (!resolvedImplementation) {
18
+ // eslint-disable-next-line no-param-reassign
19
+ resolvedImplementation = (0, _getDefaultSassImplementation.default)();
20
+ }
21
+
22
+ const {
23
+ info
24
+ } = resolvedImplementation;
25
+
26
+ if (!info) {
27
+ throw new Error('Unknown Sass implementation.');
28
+ }
29
+
30
+ const infoParts = info.split('\t');
31
+
32
+ if (infoParts.length < 2) {
33
+ throw new Error(`Unknown Sass implementation "${info}".`);
34
+ }
35
+
36
+ const [implementationName, version] = infoParts;
37
+
38
+ if (implementationName === 'dart-sass') {
39
+ if (!_semver.default.satisfies(version, '^1.3.0')) {
40
+ throw new Error(`Dart Sass version ${version} is incompatible with ^1.3.0.`);
41
+ }
42
+
43
+ return resolvedImplementation;
44
+ } else if (implementationName === 'node-sass') {
45
+ if (!_semver.default.satisfies(version, '^4.0.0')) {
46
+ throw new Error(`Node Sass version ${version} is incompatible with ^4.0.0.`);
47
+ }
48
+
49
+ return resolvedImplementation;
50
+ }
51
+
52
+ throw new Error(`Unknown Sass implementation "${implementationName}".`);
53
+ }
54
+
55
+ var _default = getSassImplementation;
56
+ exports.default = _default;
@@ -21,44 +21,53 @@ function isProductionLikeMode(loaderContext) {
21
21
  /**
22
22
  * Derives the sass options from the loader context and normalizes its values with sane defaults.
23
23
  *
24
- * Please note: If loaderContext.query is an options object, it will be re-used across multiple invocations.
25
- * That's why we must not modify the object directly.
26
- *
27
- * @param {LoaderContext} loaderContext
28
- * @param {string} loaderOptions
29
- * @param {object} content
24
+ * @param {object} loaderContext
25
+ * @param {object} loaderOptions
26
+ * @param {string} content
27
+ * @param {object} implementation
30
28
  * @returns {Object}
31
29
  */
32
30
 
33
31
 
34
- function getSassOptions(loaderContext, loaderOptions, content) {
35
- const options = (0, _cloneDeep.default)(loaderOptions);
36
- const {
37
- resourcePath
38
- } = loaderContext; // allow opt.functions to be configured WRT loaderContext
32
+ function getSassOptions(loaderContext, loaderOptions, content, implementation) {
33
+ const options = (0, _cloneDeep.default)(loaderOptions.sassOptions ? typeof loaderOptions.sassOptions === 'function' ? loaderOptions.sassOptions(loaderContext) || {} : loaderOptions.sassOptions : {});
34
+ const isDartSass = implementation.info.includes('dart-sass');
39
35
 
40
- if (typeof options.functions === 'function') {
41
- options.functions = options.functions(loaderContext);
42
- }
36
+ if (isDartSass) {
37
+ const shouldTryToResolveFibers = !options.fiber && options.fiber !== false;
43
38
 
44
- let {
45
- data
46
- } = options;
39
+ if (shouldTryToResolveFibers) {
40
+ let fibers;
47
41
 
48
- if (typeof options.data === 'function') {
49
- data = options.data(loaderContext);
42
+ try {
43
+ fibers = require.resolve('fibers');
44
+ } catch (_error) {// Nothing
45
+ }
46
+
47
+ if (fibers) {
48
+ // eslint-disable-next-line global-require, import/no-dynamic-require
49
+ options.fiber = require(fibers);
50
+ }
51
+ } else if (options.fiber === false) {
52
+ // Don't pass the `fiber` option for `sass` (`Dart Sass`)
53
+ delete options.fiber;
54
+ }
55
+ } else {
56
+ // Don't pass the `fiber` option for `node-sass`
57
+ delete options.fiber;
50
58
  }
51
59
 
52
- options.data = data ? data + _os.default.EOL + content : content; // opt.outputStyle
60
+ options.data = loaderOptions.prependData ? typeof loaderOptions.prependData === 'function' ? loaderOptions.prependData(loaderContext) + _os.default.EOL + content : loaderOptions.prependData + _os.default.EOL + content : content; // opt.outputStyle
53
61
 
54
62
  if (!options.outputStyle && isProductionLikeMode(loaderContext)) {
55
63
  options.outputStyle = 'compressed';
56
- } // opt.sourceMap
64
+ }
65
+
66
+ const useSourceMap = typeof loaderOptions.sourceMap === 'boolean' ? loaderOptions.sourceMap : loaderContext.sourceMap; // opt.sourceMap
57
67
  // Not using the `this.sourceMap` flag because css source maps are different
58
68
  // @see https://github.com/webpack/css-loader/pull/40
59
69
 
60
-
61
- if (options.sourceMap) {
70
+ if (useSourceMap) {
62
71
  // Deliberately overriding the sourceMap option here.
63
72
  // node-sass won't produce source maps if the data option is used and options.sourceMap is not a string.
64
73
  // In case it is a string, options.sourceMap should be a path where the source map is written.
@@ -82,8 +91,11 @@ function getSassOptions(loaderContext, loaderOptions, content) {
82
91
  // when exported by webpack-extract-text-plugin.
83
92
  options.sourceMapContents = true;
84
93
  }
85
- } // indentedSyntax is a boolean flag.
94
+ }
86
95
 
96
+ const {
97
+ resourcePath
98
+ } = loaderContext;
87
99
 
88
100
  const ext = _path.default.extname(resourcePath); // If we are compiling sass and indentedSyntax isn't set, automatically set it.
89
101
 
@@ -95,10 +107,8 @@ function getSassOptions(loaderContext, loaderOptions, content) {
95
107
  } // Allow passing custom importers to `node-sass`. Accepts `Function` or an array of `Function`s.
96
108
 
97
109
 
98
- options.importer = options.importer ? (0, _proxyCustomImporters.default)(options.importer, resourcePath) : []; // `node-sass` uses `includePaths` to resolve `@import` paths. Append the currently processed file.
99
-
100
- options.includePaths = options.includePaths || [];
101
- options.includePaths.push(_path.default.dirname(resourcePath));
110
+ options.importer = options.importer ? (0, _proxyCustomImporters.default)(options.importer, resourcePath) : [];
111
+ options.includePaths = (options.includePaths || []).concat(_path.default.dirname(resourcePath));
102
112
  return options;
103
113
  }
104
114
 
@@ -34,7 +34,7 @@ function importsToResolve(url) {
34
34
  // @see https://github.com/webpack-contrib/sass-loader/issues/167
35
35
 
36
36
 
37
- const ext = _path.default.extname(request); // In case there is module request, send this to webpack resolver
37
+ const ext = _path.default.extname(request).toLowerCase(); // In case there is module request, send this to webpack resolver
38
38
 
39
39
 
40
40
  if (matchModuleImport.test(url)) {
package/dist/index.js CHANGED
@@ -7,66 +7,53 @@ exports.default = void 0;
7
7
 
8
8
  var _path = _interopRequireDefault(require("path"));
9
9
 
10
- var _neoAsync = _interopRequireDefault(require("neo-async"));
10
+ var _schemaUtils = _interopRequireDefault(require("schema-utils"));
11
11
 
12
- var _pify = _interopRequireDefault(require("pify"));
12
+ var _loaderUtils = require("loader-utils");
13
13
 
14
- var _semver = _interopRequireDefault(require("semver"));
14
+ var _options = _interopRequireDefault(require("./options.json"));
15
15
 
16
- var _loaderUtils = require("loader-utils");
16
+ var _getSassImplementation = _interopRequireDefault(require("./getSassImplementation"));
17
17
 
18
- var _formatSassError = _interopRequireDefault(require("./formatSassError"));
18
+ var _getSassOptions = _interopRequireDefault(require("./getSassOptions"));
19
19
 
20
20
  var _webpackImporter = _interopRequireDefault(require("./webpackImporter"));
21
21
 
22
- var _getSassOptions = _interopRequireDefault(require("./getSassOptions"));
22
+ var _getRenderFunctionFromSassImplementation = _interopRequireDefault(require("./getRenderFunctionFromSassImplementation"));
23
23
 
24
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24
+ var _SassError = _interopRequireDefault(require("./SassError"));
25
25
 
26
- let nodeSassJobQueue = null; // Very hacky check
26
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
27
27
 
28
- function hasGetResolve(loaderContext) {
29
- return loaderContext.getResolve && // eslint-disable-next-line no-underscore-dangle
30
- loaderContext._compiler && // eslint-disable-next-line no-underscore-dangle
31
- loaderContext._compiler.resolverFactory && // eslint-disable-next-line no-underscore-dangle
32
- loaderContext._compiler.resolverFactory._create && /cachedCleverMerge/.test( // eslint-disable-next-line no-underscore-dangle
33
- loaderContext._compiler.resolverFactory._create.toString());
34
- }
35
28
  /**
36
29
  * The sass-loader makes node-sass and dart-sass available to webpack modules.
37
30
  *
38
- * @this {LoaderContext}
31
+ * @this {object}
39
32
  * @param {string} content
40
33
  */
41
-
42
-
43
34
  function loader(content) {
44
35
  const options = (0, _loaderUtils.getOptions)(this) || {};
36
+ (0, _schemaUtils.default)(_options.default, options, {
37
+ name: 'Sass Loader',
38
+ baseDataPath: 'options'
39
+ });
40
+ const implementation = (0, _getSassImplementation.default)(options.implementation);
45
41
  const callback = this.async();
46
42
 
47
43
  const addNormalizedDependency = file => {
48
44
  // node-sass returns POSIX paths
49
- this.dependency(_path.default.normalize(file));
45
+ this.addDependency(_path.default.normalize(file));
50
46
  };
51
47
 
52
- if (typeof callback !== 'function') {
53
- throw new Error('Synchronous compilation is not supported anymore. See https://github.com/webpack-contrib/sass-loader/issues/333');
54
- }
55
-
56
- let resolve = (0, _pify.default)(this.resolve); // Supported since v4.36.0
48
+ const sassOptions = (0, _getSassOptions.default)(this, options, content, implementation);
49
+ const shouldUseWebpackImporter = typeof options.webpackImporter === 'boolean' ? options.webpackImporter : true;
57
50
 
58
- if (hasGetResolve(this)) {
59
- resolve = this.getResolve({
51
+ if (shouldUseWebpackImporter) {
52
+ const resolve = this.getResolve({
60
53
  mainFields: ['sass', 'style', 'main', '...'],
61
54
  mainFiles: ['_index', 'index', '...'],
62
55
  extensions: ['.scss', '.sass', '.css', '...']
63
56
  });
64
- }
65
-
66
- const sassOptions = (0, _getSassOptions.default)(this, options, content);
67
- const shouldUseWebpackImporter = typeof options.webpackImporter === 'boolean' ? options.webpackImporter : true;
68
-
69
- if (shouldUseWebpackImporter) {
70
57
  sassOptions.importer.push((0, _webpackImporter.default)(this.resourcePath, resolve, addNormalizedDependency));
71
58
  } // Skip empty files, otherwise it will stop webpack, see issue #21
72
59
 
@@ -76,17 +63,14 @@ function loader(content) {
76
63
  return;
77
64
  }
78
65
 
79
- const render = getRenderFuncFromSassImpl( // eslint-disable-next-line import/no-extraneous-dependencies, global-require
80
- options.implementation || getDefaultSassImpl());
66
+ const render = (0, _getRenderFunctionFromSassImplementation.default)(implementation);
81
67
  render(sassOptions, (error, result) => {
82
68
  if (error) {
83
- (0, _formatSassError.default)(error, this.resourcePath);
84
-
85
69
  if (error.file) {
86
- this.dependency(error.file);
70
+ addNormalizedDependency(error.file);
87
71
  }
88
72
 
89
- callback(error);
73
+ callback(new _SassError.default(error, this.resourcePath));
90
74
  return;
91
75
  }
92
76
 
@@ -125,78 +109,6 @@ function loader(content) {
125
109
  callback(null, result.css.toString(), result.map);
126
110
  });
127
111
  }
128
- /**
129
- * Verifies that the implementation and version of Sass is supported by this loader.
130
- *
131
- * @param {Object} module
132
- * @returns {Function}
133
- */
134
-
135
-
136
- function getRenderFuncFromSassImpl(module) {
137
- const {
138
- info
139
- } = module;
140
-
141
- if (!info) {
142
- throw new Error('Unknown Sass implementation.');
143
- }
144
-
145
- const components = info.split('\t');
146
-
147
- if (components.length < 2) {
148
- throw new Error(`Unknown Sass implementation "${info}".`);
149
- }
150
-
151
- const [implementation, version] = components;
152
-
153
- if (!_semver.default.valid(version)) {
154
- throw new Error(`Invalid Sass version "${version}".`);
155
- }
156
-
157
- if (implementation === 'dart-sass') {
158
- if (!_semver.default.satisfies(version, '^1.3.0')) {
159
- throw new Error(`Dart Sass version ${version} is incompatible with ^1.3.0.`);
160
- }
161
-
162
- return module.render.bind(module);
163
- } else if (implementation === 'node-sass') {
164
- if (!_semver.default.satisfies(version, '^4.0.0')) {
165
- throw new Error(`Node Sass version ${version} is incompatible with ^4.0.0.`);
166
- } // There is an issue with node-sass when async custom importers are used
167
- // See https://github.com/sass/node-sass/issues/857#issuecomment-93594360
168
- // We need to use a job queue to make sure that one thread is always available to the UV lib
169
-
170
-
171
- if (nodeSassJobQueue === null) {
172
- const threadPoolSize = Number(process.env.UV_THREADPOOL_SIZE || 4);
173
- nodeSassJobQueue = _neoAsync.default.queue(module.render.bind(module), threadPoolSize - 1);
174
- }
175
-
176
- return nodeSassJobQueue.push.bind(nodeSassJobQueue);
177
- }
178
-
179
- throw new Error(`Unknown Sass implementation "${implementation}".`);
180
- }
181
-
182
- function getDefaultSassImpl() {
183
- let sassImplPkg = 'node-sass';
184
-
185
- try {
186
- require.resolve('node-sass');
187
- } catch (error) {
188
- try {
189
- require.resolve('sass');
190
-
191
- sassImplPkg = 'sass';
192
- } catch (ignoreError) {
193
- sassImplPkg = 'node-sass';
194
- }
195
- } // eslint-disable-next-line import/no-dynamic-require, global-require
196
-
197
-
198
- return require(sassImplPkg);
199
- }
200
112
 
201
113
  var _default = loader;
202
114
  exports.default = _default;
package/dist/options.json CHANGED
@@ -1,9 +1,41 @@
1
1
  {
2
2
  "type": "object",
3
3
  "properties": {
4
- "name": {
4
+ "implementation": {
5
+ "description": "The implementation of the sass to be used (https://github.com/webpack-contrib/sass-loader#implementation).",
6
+ "type": "object"
7
+ },
8
+ "sassOptions": {
9
+ "description": "Options for `node-sass` or `sass` (`Dart Sass`) implementation. (https://github.com/webpack-contrib/sass-loader#implementation).",
10
+ "anyOf": [
11
+ {
12
+ "type": "object",
13
+ "additionalProperties": true
14
+ },
15
+ {
16
+ "instanceof": "Function"
17
+ }
18
+ ]
19
+ },
20
+ "prependData": {
21
+ "description": "Prepends `Sass`/`SCSS` code before the actual entry file (https://github.com/webpack-contrib/sass-loader#prependdata).",
22
+ "anyOf": [
23
+ {
24
+ "type": "string"
25
+ },
26
+ {
27
+ "instanceof": "Function"
28
+ }
29
+ ]
30
+ },
31
+ "sourceMap": {
32
+ "description": "Enables/Disables generation of source maps (https://github.com/webpack-contrib/sass-loader#sourcemap).",
33
+ "type": "boolean"
34
+ },
35
+ "webpackImporter": {
36
+ "description": "Enables/Disables default `webpack` importer (https://github.com/webpack-contrib/sass-loader#webpackimporter).",
5
37
  "type": "boolean"
6
38
  }
7
39
  },
8
40
  "additionalProperties": false
9
- }
41
+ }
@@ -26,7 +26,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
26
26
  * @param {string} prev
27
27
  * @param {Function<Error, string>} done
28
28
  */
29
- const matchCss = /\.css$/;
29
+ const matchCss = /\.css$/i;
30
30
  /**
31
31
  * Returns an importer that uses webpack's resolving algorithm.
32
32
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sass-loader",
3
- "version": "7.3.1",
3
+ "version": "8.0.0",
4
4
  "description": "Sass loader for webpack",
5
5
  "license": "MIT",
6
6
  "repository": "webpack-contrib/sass-loader",
@@ -9,7 +9,7 @@
9
9
  "bugs": "https://github.com/webpack-contrib/sass-loader/issues",
10
10
  "main": "dist/cjs.js",
11
11
  "engines": {
12
- "node": ">= 6.9.0"
12
+ "node": ">= 8.9.0"
13
13
  },
14
14
  "scripts": {
15
15
  "start": "npm run build -- -w",
@@ -35,13 +35,27 @@
35
35
  "dist"
36
36
  ],
37
37
  "peerDependencies": {
38
- "webpack": "^3.0.0 || ^4.0.0"
38
+ "webpack": "^4.36.0",
39
+ "node-sass": "^4.0.0",
40
+ "sass": "^1.3.0",
41
+ "fibers": ">= 3.1.0"
42
+ },
43
+ "peerDependenciesMeta": {
44
+ "node-sass": {
45
+ "optional": true
46
+ },
47
+ "sass": {
48
+ "optional": true
49
+ },
50
+ "fibers": {
51
+ "optional": true
52
+ }
39
53
  },
40
54
  "dependencies": {
41
55
  "clone-deep": "^4.0.1",
42
- "loader-utils": "^1.0.1",
43
- "neo-async": "^2.5.0",
44
- "pify": "^4.0.1",
56
+ "loader-utils": "^1.2.3",
57
+ "neo-async": "^2.6.1",
58
+ "schema-utils": "^2.1.0",
45
59
  "semver": "^6.3.0"
46
60
  },
47
61
  "devDependencies": {
@@ -54,35 +68,33 @@
54
68
  "@webpack-contrib/eslint-config-webpack": "^3.0.0",
55
69
  "babel-jest": "^24.9.0",
56
70
  "bootstrap": "^4.3.1",
57
- "bootstrap-sass": "^3.3.5",
58
- "chokidar": "^2.1.6",
71
+ "bootstrap-sass": "^3.4.1",
59
72
  "commitlint-azure-pipelines-cli": "^1.0.2",
60
73
  "cross-env": "^5.2.0",
61
74
  "css-loader": "^3.2.0",
62
- "del": "^4.1.1",
63
- "del-cli": "^1.1.0",
64
- "eslint": "^6.1.0",
65
- "eslint-config-prettier": "^6.0.0",
66
- "eslint-plugin-import": "^2.14.0",
75
+ "del": "^5.1.0",
76
+ "del-cli": "^2.0.0",
77
+ "eslint": "^6.2.2",
78
+ "eslint-config-prettier": "^6.1.0",
79
+ "eslint-plugin-import": "^2.18.2",
80
+ "fibers": "^4.0.1",
67
81
  "file-loader": "^4.2.0",
68
- "husky": "^3.0.3",
82
+ "husky": "^3.0.4",
69
83
  "jest": "^24.9.0",
70
- "jest-junit": "^7.0.0",
84
+ "jest-junit": "^8.0.0",
71
85
  "jquery": "^3.4.1",
72
- "lint-staged": "^9.2.1",
86
+ "lint-staged": "^9.2.5",
73
87
  "memory-fs": "^0.4.1",
74
- "node-sass": "^4.5.0",
88
+ "node-sass": "^4.12.0",
75
89
  "npm-run-all": "^4.1.5",
76
- "nyc": "^14.1.1",
77
90
  "popper.js": "^1.15.0",
78
- "prettier": "^1.15.2",
79
- "raw-loader": "^3.1.0",
80
- "sass": "^1.3.0",
91
+ "prettier": "^1.18.2",
92
+ "sass": "^1.22.10",
81
93
  "standard-version": "^7.0.0",
82
94
  "style-loader": "^1.0.0",
83
- "webpack": "^4.5.0",
84
- "webpack-cli": "^3.1.0",
85
- "webpack-dev-server": "^3.1.4"
95
+ "webpack": "^4.39.3",
96
+ "webpack-cli": "^3.3.7",
97
+ "webpack-dev-server": "^3.8.0"
86
98
  },
87
99
  "keywords": [
88
100
  "sass",
@@ -1,82 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
-
8
- var _path = _interopRequireDefault(require("path"));
9
-
10
- var _os = _interopRequireDefault(require("os"));
11
-
12
- var _fs = _interopRequireDefault(require("fs"));
13
-
14
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
-
16
- // A typical sass error looks like this
17
- // const SassError = {
18
- // message: "invalid property name",
19
- // column: 14,
20
- // line: 1,
21
- // file: "stdin",
22
- // status: 1
23
- // };
24
-
25
- /**
26
- * Enhances the sass error with additional information about what actually went wrong.
27
- *
28
- * @param {SassError} error
29
- * @param {string} resourcePath
30
- */
31
- function formatSassError(error, resourcePath) {
32
- // Instruct webpack to hide the JS stack from the console
33
- // Usually you're only interested in the SASS stack in this case.
34
- // eslint-disable-next-line no-param-reassign
35
- error.hideStack = true; // The file property is missing in rare cases.
36
- // No improvement in the error is possible.
37
-
38
- if (!error.file) {
39
- return;
40
- }
41
-
42
- let msg = error.message;
43
-
44
- if (error.file === 'stdin') {
45
- // eslint-disable-next-line no-param-reassign
46
- error.file = resourcePath;
47
- } // node-sass returns UNIX-style paths
48
- // eslint-disable-next-line no-param-reassign
49
-
50
-
51
- error.file = _path.default.normalize(error.file); // The 'Current dir' hint of node-sass does not help us, we're providing
52
- // additional information by reading the err.file property
53
-
54
- msg = msg.replace(/\s*Current dir:\s*/, ''); // msg = msg.replace(/(\s*)(stdin)(\s*)/, `$1${err.file}$3`);
55
- // eslint-disable-next-line no-param-reassign
56
-
57
- error.message = `${getFileExcerptIfPossible(error) + msg.charAt(0).toUpperCase() + msg.slice(1) + _os.default.EOL} in ${error.file} (line ${error.line}, column ${error.column})`;
58
- }
59
- /**
60
- * Tries to get an excerpt of the file where the error happened.
61
- * Uses err.line and err.column.
62
- *
63
- * Returns an empty string if the excerpt could not be retrieved.
64
- *
65
- * @param {SassError} error
66
- * @returns {string}
67
- */
68
-
69
-
70
- function getFileExcerptIfPossible(error) {
71
- try {
72
- const content = _fs.default.readFileSync(error.file, 'utf8');
73
-
74
- return `${_os.default.EOL + content.split(/\r?\n/)[error.line - 1] + _os.default.EOL + new Array(error.column - 1).join(' ')}^${_os.default.EOL} `;
75
- } catch (ignoreError) {
76
- // If anything goes wrong here, we don't want any errors to be reported to the user
77
- return '';
78
- }
79
- }
80
-
81
- var _default = formatSassError;
82
- exports.default = _default;