sass-loader 7.0.1 → 7.2.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,57 @@
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
+ <a name="7.2.0"></a>
6
+ # [7.2.0](https://github.com/webpack-contrib/sass-loader/compare/v7.1.0...v7.2.0) (2019-08-08)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * better handle stdin in sources ([#681](https://github.com/webpack-contrib/sass-loader/issues/681)) ([e279f2a](https://github.com/webpack-contrib/sass-loader/commit/e279f2a))
12
+ * prefer `sass`/`scss`/`css` extensions ([#711](https://github.com/webpack-contrib/sass-loader/issues/711)) ([6fc9d4e](https://github.com/webpack-contrib/sass-loader/commit/6fc9d4e))
13
+ * relax node engine ([#708](https://github.com/webpack-contrib/sass-loader/issues/708)) ([2a51502](https://github.com/webpack-contrib/sass-loader/commit/2a51502))
14
+
15
+
16
+ ### Features
17
+
18
+ * allow passing `functions` option as function ([#651](https://github.com/webpack-contrib/sass-loader/issues/651)) ([6c9654d](https://github.com/webpack-contrib/sass-loader/commit/6c9654d))
19
+ * support `data` as `Function` ([#648](https://github.com/webpack-contrib/sass-loader/issues/648)) ([aa64e1b](https://github.com/webpack-contrib/sass-loader/commit/aa64e1b))
20
+ * support `sass` and `style` fields in `package.json` ([#647](https://github.com/webpack-contrib/sass-loader/issues/647)) ([a8709c9](https://github.com/webpack-contrib/sass-loader/commit/a8709c9))
21
+ * support auto resolving `dart-sass` ([ff90dd6](https://github.com/webpack-contrib/sass-loader/commit/ff90dd6))
22
+
23
+
24
+
25
+ <a name="7.1.0"></a>
26
+ # [7.1.0](https://github.com/webpack-contrib/sass-loader/compare/v7.0.3...v7.1.0) (2018-08-01)
27
+
28
+
29
+ ### Features
30
+
31
+ * Make this package implementation-agnostic (#573) ([bed9fb5](https://github.com/webpack-contrib/sass-loader/commit/bed9fb5)), closes [#435](https://github.com/webpack-contrib/sass-loader/issues/435)
32
+
33
+
34
+
35
+ <a name="7.0.3"></a>
36
+ ## [7.0.3](https://github.com/webpack-contrib/sass-loader/compare/v7.0.2...v7.0.3) (2018-06-05)
37
+
38
+
39
+ ### Bug Fixes
40
+
41
+ * Bare imports not working sometimes (#579) ([c348281](https://github.com/webpack-contrib/sass-loader/commit/c348281)), closes [#566](https://github.com/webpack-contrib/sass-loader/issues/566)
42
+
43
+
44
+
45
+ <a name="7.0.2"></a>
46
+ ## [7.0.2](https://github.com/webpack-contrib/sass-loader/compare/v7.0.1...v7.0.2) (2018-06-02)
47
+
48
+
49
+ ### Bug Fixes
50
+
51
+ * Errors being swallowed when trying to load node-sass (#576) ([6dfb274](https://github.com/webpack-contrib/sass-loader/commit/6dfb274)), closes [#563](https://github.com/webpack-contrib/sass-loader/issues/563)
52
+ * Report error to user for problems loading node-sass (#562) ([2529c07](https://github.com/webpack-contrib/sass-loader/commit/2529c07))
53
+
54
+
55
+
5
56
  <a name="7.0.1"></a>
6
57
  ## [7.0.1](https://github.com/webpack-contrib/sass-loader/compare/v7.0.0...v7.0.1) (2018-04-13)
7
58
 
package/README.md CHANGED
@@ -18,7 +18,7 @@
18
18
  <p>Loads a Sass/SCSS file and compiles it to CSS.</p>
19
19
  </div>
20
20
 
21
- Use the [css-loader](https://github.com/webpack-contrib/css-loader) or the [raw-loader](https://github.com/webpack-contrib/raw-loader) to turn it into a JS module and the [ExtractTextPlugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) to extract it into a separate file.
21
+ Use the [css-loader](https://github.com/webpack-contrib/css-loader) or the [raw-loader](https://github.com/webpack-contrib/raw-loader) to turn it into a JS module and the [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) to extract it into a separate file.
22
22
  Looking for the webpack 1 loader? Check out the [archive/webpack-1 branch](https://github.com/webpack-contrib/sass-loader/tree/archive/webpack-1).
23
23
 
24
24
  <h2 align="center">Install</h2>
@@ -27,8 +27,14 @@ Looking for the webpack 1 loader? Check out the [archive/webpack-1 branch](https
27
27
  npm install sass-loader node-sass webpack --save-dev
28
28
  ```
29
29
 
30
- The sass-loader requires [node-sass](https://github.com/sass/node-sass) and [webpack](https://github.com/webpack)
31
- as [`peerDependency`](https://docs.npmjs.com/files/package.json#peerdependencies). Thus you are able to control the versions accurately.
30
+ The sass-loader requires [webpack](https://github.com/webpack) as a
31
+ [`peerDependency`](https://docs.npmjs.com/files/package.json#peerdependencies)
32
+ and it requires you to install either [Node Sass](https://github.com/sass/node-sass) or [Dart Sass](https://github.com/sass/dart-sass) on your
33
+ own. This allows you to control the versions of all your dependencies, and to
34
+ choose which Sass implementation to use.
35
+
36
+ [Node Sass]: https://github.com/sass/node-sass
37
+ [Dart Sass]: http://sass-lang.com/dart-sass
32
38
 
33
39
  <h2 align="center">Examples</h2>
34
40
 
@@ -38,6 +44,25 @@ Chain the sass-loader with the [css-loader](https://github.com/webpack-contrib/c
38
44
  npm install style-loader css-loader --save-dev
39
45
  ```
40
46
 
47
+ ```js
48
+ // webpack.config.js
49
+ module.exports = {
50
+ ...
51
+ module: {
52
+ rules: [{
53
+ test: /\.scss$/,
54
+ use: [
55
+ "style-loader", // creates style nodes from JS strings
56
+ "css-loader", // translates CSS into CommonJS
57
+ "sass-loader" // compiles Sass to CSS, using Node Sass by default
58
+ ]
59
+ }]
60
+ }
61
+ };
62
+ ```
63
+
64
+ You can also pass options directly to [Node Sass][] or [Dart Sass][]:
65
+
41
66
  ```js
42
67
  // webpack.config.js
43
68
  module.exports = {
@@ -46,21 +71,82 @@ module.exports = {
46
71
  rules: [{
47
72
  test: /\.scss$/,
48
73
  use: [{
49
- loader: "style-loader" // creates style nodes from JS strings
74
+ loader: "style-loader"
50
75
  }, {
51
- loader: "css-loader" // translates CSS into CommonJS
76
+ loader: "css-loader"
52
77
  }, {
53
- loader: "sass-loader" // compiles Sass to CSS
78
+ loader: "sass-loader",
79
+ options: {
80
+ includePaths: ["absolute/path/a", "absolute/path/b"]
81
+ }
54
82
  }]
55
83
  }]
56
84
  }
57
85
  };
58
86
  ```
59
87
 
60
- You can also pass options directly to [node-sass](https://github.com/andrew/node-sass) by specifying an `options` property like this:
88
+ See [the Node Sass documentation](https://github.com/sass/node-sass/blob/master/README.md#options) for all available Sass options.
89
+
90
+ By default the loader resolve the implementation based on your dependencies.
91
+ Just add required implementation to `package.json`
92
+ (`node-sass` or `sass` package) and install dependencies.
93
+
94
+ Example where the `sass-loader` loader uses the `sass` (`dart-sass`) implementation:
95
+
96
+ **package.json**
97
+
98
+ ```json
99
+ {
100
+ "devDependencies": {
101
+ "sass-loader": "*",
102
+ "sass": "*"
103
+ }
104
+ }
105
+ ```
106
+
107
+ Example where the `sass-loader` loader uses the `node-sass` implementation:
108
+
109
+ **package.json**
110
+
111
+ ```json
112
+ {
113
+ "devDependencies": {
114
+ "sass-loader": "*",
115
+ "node-sass": "*"
116
+ }
117
+ }
118
+ ```
119
+
120
+ Beware the situation
121
+ when `node-sass` and `sass` was installed, by default the `sass-loader`
122
+ prefers `node-sass`, to avoid this situation use the `implementation` option.
123
+
124
+ The special `implementation` option determines which implementation of Sass to
125
+ use. It takes either a [Node Sass][] or a [Dart Sass][] module. For example, to
126
+ use Dart Sass, you'd pass:
127
+
128
+ ```js
129
+ // ...
130
+ {
131
+ loader: "sass-loader",
132
+ options: {
133
+ implementation: require("sass")
134
+ }
135
+ }
136
+ // ...
137
+ ```
138
+
139
+ Note that when using Dart Sass, **synchronous compilation is twice as fast as
140
+ asynchronous compilation** by default, due to the overhead of asynchronous
141
+ callbacks. To avoid this overhead, you can use the
142
+ [`fibers`](https://www.npmjs.com/package/fibers) package to call asynchronous
143
+ importers from the synchronous code path. To enable this, pass the `Fiber` class
144
+ to the `fiber` option:
61
145
 
62
146
  ```js
63
147
  // webpack.config.js
148
+ const Fiber = require('fibers');
149
+
64
150
  module.exports = {
65
151
  ...
66
152
  module: {
@@ -73,7 +159,8 @@ module.exports = {
73
159
  }, {
74
160
  loader: "sass-loader",
75
161
  options: {
76
- includePaths: ["absolute/path/a", "absolute/path/b"]
162
+ implementation: require("sass"),
163
+ fiber: Fiber
77
164
  }
78
165
  }]
79
166
  }]
@@ -81,38 +168,33 @@ module.exports = {
81
168
  };
82
169
  ```
83
170
 
84
- See [node-sass](https://github.com/andrew/node-sass) for all available Sass options.
85
-
86
171
  ### In production
87
172
 
88
- Usually, it's recommended to extract the style sheets into a dedicated file in production using the [ExtractTextPlugin](https://github.com/webpack-contrib/extract-text-webpack-plugin). This way your styles are not dependent on JavaScript:
173
+ Usually, it's recommended to extract the style sheets into a dedicated file in production using the [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin). This way your styles are not dependent on JavaScript:
89
174
 
90
175
  ```js
91
- const ExtractTextPlugin = require("extract-text-webpack-plugin");
92
-
93
- const extractSass = new ExtractTextPlugin({
94
- filename: "[name].[contenthash].css",
95
- disable: process.env.NODE_ENV === "development"
96
- });
176
+ const MiniCssExtractPlugin = require("mini-css-extract-plugin");
97
177
 
98
178
  module.exports = {
99
179
  ...
100
180
  module: {
101
181
  rules: [{
102
182
  test: /\.scss$/,
103
- use: extractSass.extract({
104
- use: [{
105
- loader: "css-loader"
106
- }, {
107
- loader: "sass-loader"
108
- }],
109
- // use style-loader in development
110
- fallback: "style-loader"
111
- })
183
+ use: [
184
+ // fallback to style-loader in development
185
+ process.env.NODE_ENV !== 'production' ? 'style-loader' : MiniCssExtractPlugin.loader,
186
+ "css-loader",
187
+ "sass-loader"
188
+ ]
112
189
  }]
113
190
  },
114
191
  plugins: [
115
- extractSass
192
+ new MiniCssExtractPlugin({
193
+ // Options similar to the same options in webpackOptions.output
194
+ // both options are optional
195
+ filename: "[name].css",
196
+ chunkFilename: "[id].css"
197
+ })
116
198
  ]
117
199
  };
118
200
  ```
@@ -121,7 +203,7 @@ module.exports = {
121
203
 
122
204
  ### Imports
123
205
 
124
- webpack provides an [advanced mechanism to resolve files](https://webpack.js.org/concepts/module-resolution/). The sass-loader uses node-sass' custom importer feature to pass all queries to the webpack resolving engine. Thus you can import your Sass modules from `node_modules`. Just prepend them with a `~` to tell webpack that this is not a relative import:
206
+ webpack provides an [advanced mechanism to resolve files](https://webpack.js.org/concepts/module-resolution/). The sass-loader uses Sass's custom importer feature to pass all queries to the webpack resolving engine. Thus you can import your Sass modules from `node_modules`. Just prepend them with a `~` to tell webpack that this is not a relative import:
125
207
 
126
208
  ```css
127
209
  @import "~bootstrap/dist/css/bootstrap";
@@ -148,7 +230,7 @@ Bundling CSS with webpack has some nice advantages like referencing images and f
148
230
  There are two possibilities to extract a style sheet from the bundle:
149
231
 
150
232
  - [extract-loader](https://github.com/peerigon/extract-loader) (simpler, but specialized on the css-loader's output)
151
- - [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) (more complex, but works in all use-cases)
233
+ - [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) (use this, when using webpack 4 configuration. Works in all use-cases)
152
234
 
153
235
  ### Source maps
154
236
 
@@ -162,7 +244,9 @@ module.exports = {
162
244
  rules: [{
163
245
  test: /\.scss$/,
164
246
  use: [{
165
- loader: "style-loader"
247
+ loader: "style-loader", options: {
248
+ sourceMap: true
249
+ }
166
250
  }, {
167
251
  loader: "css-loader", options: {
168
252
  sourceMap: true
@@ -192,6 +276,27 @@ If you want to prepend Sass code before the actual entry file, you can set the `
192
276
  }
193
277
  ```
194
278
 
279
+ The `data` option supports `Function` notation:
280
+
281
+ ```javascript
282
+ {
283
+ loader: "sass-loader",
284
+ options: {
285
+ data: (loaderContext) => {
286
+ // More information about avalaible options https://webpack.js.org/api/loaders/
287
+ const { resourcePath, rootContext } = loaderContext;
288
+ const relativePath = path.relative(rootContext,resourcePath);
289
+
290
+ if (relativePath === "styles/foo.scss") {
291
+ return "$value: 100px;"
292
+ }
293
+
294
+ return "$value: 200px;"
295
+ }
296
+ }
297
+ }
298
+ ```
299
+
195
300
  **Please note:** Since you're injecting code, this will break the source mappings in your entry file. Often there's a simpler solution than this, like multiple Sass entry files.
196
301
 
197
302
  <h2 align="center">Maintainers</h2>
@@ -1,17 +1,17 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
- const path = require("path");
4
- const os = require("os");
5
- const fs = require("fs");
3
+ const path = require('path');
4
+ const os = require('os');
5
+ const fs = require('fs');
6
6
 
7
7
  // A typical sass error looks like this
8
- const SassError = { // eslint-disable-line no-unused-vars
9
- message: "invalid property name",
10
- column: 14,
11
- line: 1,
12
- file: "stdin",
13
- status: 1
14
- };
8
+ // const SassError = {
9
+ // message: "invalid property name",
10
+ // column: 14,
11
+ // line: 1,
12
+ // file: "stdin",
13
+ // status: 1
14
+ // };
15
15
 
16
16
  /**
17
17
  * Enhances the sass error with additional information about what actually went wrong.
@@ -20,31 +20,37 @@ const SassError = { // eslint-disable-line no-unused-vars
20
20
  * @param {string} resourcePath
21
21
  */
22
22
  function formatSassError(err, resourcePath) {
23
- // Instruct webpack to hide the JS stack from the console
24
- // Usually you're only interested in the SASS stack in this case.
25
- err.hideStack = true;
23
+ // Instruct webpack to hide the JS stack from the console
24
+ // Usually you're only interested in the SASS stack in this case.
25
+ // eslint-disable-next-line no-param-reassign
26
+ err.hideStack = true;
26
27
 
27
- // The file property is missing in rare cases.
28
- // No improvement in the error is possible.
29
- if (!err.file) {
30
- return;
31
- }
28
+ // The file property is missing in rare cases.
29
+ // No improvement in the error is possible.
30
+ if (!err.file) {
31
+ return;
32
+ }
32
33
 
33
- let msg = err.message;
34
+ let msg = err.message;
34
35
 
35
- if (err.file === "stdin") {
36
- err.file = resourcePath;
37
- }
38
- // node-sass returns UNIX-style paths
39
- err.file = path.normalize(err.file);
36
+ if (err.file === 'stdin') {
37
+ // eslint-disable-next-line no-param-reassign
38
+ err.file = resourcePath;
39
+ }
40
40
 
41
- // The 'Current dir' hint of node-sass does not help us, we're providing
42
- // additional information by reading the err.file property
43
- msg = msg.replace(/\s*Current dir:\s*/, "");
41
+ // node-sass returns UNIX-style paths
42
+ // eslint-disable-next-line no-param-reassign
43
+ err.file = path.normalize(err.file);
44
44
 
45
- err.message = getFileExcerptIfPossible(err) +
46
- msg.charAt(0).toUpperCase() + msg.slice(1) + os.EOL +
47
- " in " + err.file + " (line " + err.line + ", column " + err.column + ")";
45
+ // The 'Current dir' hint of node-sass does not help us, we're providing
46
+ // additional information by reading the err.file property
47
+ msg = msg.replace(/\s*Current dir:\s*/, '');
48
+
49
+ // eslint-disable-next-line no-param-reassign
50
+ err.message = `${getFileExcerptIfPossible(err) +
51
+ msg.charAt(0).toUpperCase() +
52
+ msg.slice(1) +
53
+ os.EOL} in ${err.file} (line ${err.line}, column ${err.column})`;
48
54
  }
49
55
 
50
56
  /**
@@ -57,17 +63,17 @@ function formatSassError(err, resourcePath) {
57
63
  * @returns {string}
58
64
  */
59
65
  function getFileExcerptIfPossible(err) {
60
- try {
61
- const content = fs.readFileSync(err.file, "utf8");
66
+ try {
67
+ const content = fs.readFileSync(err.file, 'utf8');
62
68
 
63
- return os.EOL +
64
- content.split(os.EOL)[err.line - 1] + os.EOL +
65
- new Array(err.column - 1).join(" ") + "^" + os.EOL +
66
- " ";
67
- } catch (err) {
68
- // If anything goes wrong here, we don't want any errors to be reported to the user
69
- return "";
70
- }
69
+ return `${os.EOL +
70
+ content.split(os.EOL)[err.line - 1] +
71
+ os.EOL +
72
+ new Array(err.column - 1).join(' ')}^${os.EOL} `;
73
+ } catch (ignoreErr) {
74
+ // If anything goes wrong here, we don't want any errors to be reported to the user
75
+ return '';
76
+ }
71
77
  }
72
78
 
73
79
  module.exports = formatSassError;
@@ -1,9 +1,10 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
- const path = require("path");
4
- const utils = require("loader-utils");
3
+ const path = require('path');
5
4
 
6
- const matchModuleImport = /^~([^\/]+|@[^\/]+[\/][^\/]+)$/g;
5
+ const utils = require('loader-utils');
6
+
7
+ const matchModuleImport = /^~([^/]+|@[^/]+[/][^/]+)$/;
7
8
 
8
9
  /**
9
10
  * When libsass tries to resolve an import, it uses a special algorithm.
@@ -15,46 +16,47 @@ const matchModuleImport = /^~([^\/]+|@[^\/]+[\/][^\/]+)$/g;
15
16
  * @returns {Array<string>}
16
17
  */
17
18
  function importsToResolve(url) {
18
- const request = utils.urlToRequest(url);
19
- // Keep in mind: ext can also be something like '.datepicker' when the true extension is omitted and the filename contains a dot.
20
- // @see https://github.com/webpack-contrib/sass-loader/issues/167
21
- const ext = path.extname(request);
22
-
23
- if (matchModuleImport.test(url)) {
24
- return [request, url];
25
- }
26
-
27
- // libsass' import algorithm works like this:
28
-
29
- // In case there is a file extension...
30
- // - If the file is a CSS-file, do not include it all, but just link it via @import url().
31
- // - The exact file name must match (no auto-resolving of '_'-modules).
32
- if (ext === ".css") {
33
- return [];
34
- }
35
- if (ext === ".scss" || ext === ".sass") {
36
- return [request, url];
37
- }
38
-
39
- // In case there is no file extension...
40
- // - Prefer modules starting with '_'.
41
- // - File extension precedence: .scss, .sass, .css.
42
- const basename = path.basename(request);
43
-
44
- if (basename.charAt(0) === "_") {
45
- return [
46
- `${ request }.scss`, `${ request }.sass`, `${ request }.css`,
47
- url
48
- ];
49
- }
50
-
51
- const dirname = path.dirname(request);
52
-
53
- return [
54
- `${ dirname }/_${ basename }.scss`, `${ dirname }/_${ basename }.sass`, `${ dirname }/_${ basename }.css`,
55
- `${ request }.scss`, `${ request }.sass`, `${ request }.css`,
56
- url
57
- ];
19
+ const request = utils.urlToRequest(url);
20
+ // Keep in mind: ext can also be something like '.datepicker' when the true extension is omitted and the filename contains a dot.
21
+ // @see https://github.com/webpack-contrib/sass-loader/issues/167
22
+ const ext = path.extname(request);
23
+
24
+ if (matchModuleImport.test(url)) {
25
+ return [request, url];
26
+ }
27
+
28
+ // libsass' import algorithm works like this:
29
+
30
+ // In case there is a file extension...
31
+ // - If the file is a CSS-file, do not include it all, but just link it via @import url().
32
+ // - The exact file name must match (no auto-resolving of '_'-modules).
33
+ if (ext === '.css') {
34
+ return [];
35
+ }
36
+ if (ext === '.scss' || ext === '.sass') {
37
+ return [request, url];
38
+ }
39
+
40
+ // In case there is no file extension...
41
+ // - Prefer modules starting with '_'.
42
+ // - File extension precedence: .scss, .sass, .css.
43
+ const basename = path.basename(request);
44
+
45
+ if (basename.charAt(0) === '_') {
46
+ return [`${request}.scss`, `${request}.sass`, `${request}.css`, url];
47
+ }
48
+
49
+ const dirname = path.dirname(request);
50
+
51
+ return [
52
+ `${dirname}/_${basename}.scss`,
53
+ `${dirname}/_${basename}.sass`,
54
+ `${dirname}/_${basename}.css`,
55
+ `${request}.scss`,
56
+ `${request}.sass`,
57
+ `${request}.css`,
58
+ url,
59
+ ];
58
60
  }
59
61
 
60
62
  module.exports = importsToResolve;
package/lib/loader.js CHANGED
@@ -1,104 +1,206 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
- const path = require("path");
4
- const async = require("neo-async");
5
- const formatSassError = require("./formatSassError");
6
- const webpackImporter = require("./webpackImporter");
7
- const normalizeOptions = require("./normalizeOptions");
8
- const pify = require("pify");
3
+ const path = require('path');
9
4
 
10
- // This queue makes sure node-sass leaves one thread available for executing
11
- // fs tasks when running the custom importer code.
12
- // This can be removed as soon as node-sass implements a fix for this.
13
- const threadPoolSize = process.env.UV_THREADPOOL_SIZE || 4;
14
- let asyncSassJobQueue = null;
5
+ const async = require('neo-async');
6
+ const pify = require('pify');
7
+ const semver = require('semver');
8
+
9
+ const formatSassError = require('./formatSassError');
10
+ const webpackImporter = require('./webpackImporter');
11
+ const normalizeOptions = require('./normalizeOptions');
12
+
13
+ let nodeSassJobQueue = null;
14
+
15
+ // Very hacky check
16
+ function hasGetResolve(loaderContext) {
17
+ return (
18
+ loaderContext.getResolve &&
19
+ // eslint-disable-next-line no-underscore-dangle
20
+ loaderContext._compiler &&
21
+ // eslint-disable-next-line no-underscore-dangle
22
+ loaderContext._compiler.resolverFactory &&
23
+ // eslint-disable-next-line no-underscore-dangle
24
+ loaderContext._compiler.resolverFactory._create &&
25
+ /cachedCleverMerge/.test(
26
+ // eslint-disable-next-line no-underscore-dangle
27
+ loaderContext._compiler.resolverFactory._create.toString()
28
+ )
29
+ );
30
+ }
15
31
 
16
32
  /**
17
- * The sass-loader makes node-sass available to webpack modules.
33
+ * The sass-loader makes node-sass and dart-sass available to webpack modules.
18
34
  *
19
35
  * @this {LoaderContext}
20
36
  * @param {string} content
21
37
  */
22
38
  function sassLoader(content) {
23
- if (asyncSassJobQueue === null) {
24
- let sass;
25
- let sassVersion;
26
-
27
- try {
28
- sass = require("node-sass");
29
- sassVersion = /^(\d+)/.exec(require("node-sass/package.json").version).pop();
30
- } catch (e) {
31
- throw new Error(
32
- "`sass-loader` requires `node-sass` >=4. Please install a compatible version."
33
- );
34
- }
35
-
36
- if (Number(sassVersion) < 4) {
37
- throw new Error(
38
- "The installed version of `node-sass` is not compatible (expected: >= 4, actual: " + sassVersion + ")."
39
- );
40
- }
41
-
42
- asyncSassJobQueue = async.queue(sass.render, threadPoolSize - 1);
39
+ const callback = this.async();
40
+ const isSync = typeof callback !== 'function';
41
+ const self = this;
42
+ const { resourcePath } = this;
43
+
44
+ function addNormalizedDependency(file) {
45
+ // node-sass returns POSIX paths
46
+ self.dependency(path.normalize(file));
47
+ }
48
+
49
+ if (isSync) {
50
+ throw new Error(
51
+ 'Synchronous compilation is not supported anymore. See https://github.com/webpack-contrib/sass-loader/issues/333'
52
+ );
53
+ }
54
+
55
+ let resolve = pify(this.resolve);
56
+
57
+ // Supported since v4.36.0
58
+ if (hasGetResolve(self)) {
59
+ resolve = this.getResolve({
60
+ mainFields: ['sass', 'style', '...'],
61
+ extensions: ['.scss', '.sass', '.css', '...'],
62
+ });
63
+ }
64
+
65
+ const options = normalizeOptions(
66
+ this,
67
+ content,
68
+ webpackImporter(resourcePath, resolve, addNormalizedDependency)
69
+ );
70
+
71
+ // Skip empty files, otherwise it will stop webpack, see issue #21
72
+ if (options.data.trim() === '') {
73
+ callback(null, '');
74
+ return;
75
+ }
76
+
77
+ const render = getRenderFuncFromSassImpl(
78
+ // eslint-disable-next-line import/no-extraneous-dependencies, global-require
79
+ options.implementation || getDefaultSassImpl()
80
+ );
81
+
82
+ render(options, (err, result) => {
83
+ if (err) {
84
+ formatSassError(err, this.resourcePath);
85
+
86
+ if (err.file) {
87
+ this.dependency(err.file);
88
+ }
89
+
90
+ callback(err);
91
+ return;
92
+ }
93
+
94
+ if (result.map && result.map !== '{}') {
95
+ // eslint-disable-next-line no-param-reassign
96
+ result.map = JSON.parse(result.map);
97
+ // result.map.file is an optional property that provides the output filename.
98
+ // Since we don't know the final filename in the webpack build chain yet, it makes no sense to have it.
99
+ // eslint-disable-next-line no-param-reassign
100
+ delete result.map.file;
101
+ // One of the sources is 'stdin' according to dart-sass/node-sass because we've used the data input.
102
+ // Now let's override that value with the correct relative path.
103
+ // Since we specified options.sourceMap = path.join(process.cwd(), "/sass.map"); in normalizeOptions,
104
+ // we know that this path is relative to process.cwd(). This is how node-sass works.
105
+ // eslint-disable-next-line no-param-reassign
106
+ const stdinIndex = result.map.sources.findIndex(
107
+ (source) => source.indexOf('stdin') !== -1
108
+ );
109
+
110
+ if (stdinIndex !== -1) {
111
+ // eslint-disable-next-line no-param-reassign
112
+ result.map.sources[stdinIndex] = path.relative(
113
+ process.cwd(),
114
+ resourcePath
115
+ );
116
+ }
117
+ // node-sass returns POSIX paths, that's why we need to transform them back to native paths.
118
+ // This fixes an error on windows where the source-map module cannot resolve the source maps.
119
+ // @see https://github.com/webpack-contrib/sass-loader/issues/366#issuecomment-279460722
120
+ // eslint-disable-next-line no-param-reassign
121
+ result.map.sourceRoot = path.normalize(result.map.sourceRoot);
122
+ // eslint-disable-next-line no-param-reassign
123
+ result.map.sources = result.map.sources.map(path.normalize);
124
+ } else {
125
+ // eslint-disable-next-line no-param-reassign
126
+ result.map = null;
43
127
  }
44
128
 
45
- const callback = this.async();
46
- const isSync = typeof callback !== "function";
47
- const self = this;
48
- const resourcePath = this.resourcePath;
129
+ result.stats.includedFiles.forEach(addNormalizedDependency);
130
+
131
+ callback(null, result.css.toString(), result.map);
132
+ });
133
+ }
134
+
135
+ /**
136
+ * Verifies that the implementation and version of Sass is supported by this loader.
137
+ *
138
+ * @param {Object} module
139
+ * @returns {Function}
140
+ */
141
+ function getRenderFuncFromSassImpl(module) {
142
+ const { info } = module;
143
+ const components = info.split('\t');
144
+
145
+ if (components.length < 2) {
146
+ throw new Error(`Unknown Sass implementation "${info}".`);
147
+ }
148
+
149
+ const [implementation, version] = components;
49
150
 
50
- function addNormalizedDependency(file) {
51
- // node-sass returns POSIX paths
52
- self.dependency(path.normalize(file));
151
+ if (!semver.valid(version)) {
152
+ throw new Error(`Invalid Sass version "${version}".`);
153
+ }
154
+
155
+ if (implementation === 'dart-sass') {
156
+ if (!semver.satisfies(version, '^1.3.0')) {
157
+ throw new Error(
158
+ `Dart Sass version ${version} is incompatible with ^1.3.0.`
159
+ );
53
160
  }
54
161
 
55
- if (isSync) {
56
- throw new Error("Synchronous compilation is not supported anymore. See https://github.com/webpack-contrib/sass-loader/issues/333");
162
+ return module.render.bind(module);
163
+ } else if (implementation === 'node-sass') {
164
+ if (!semver.satisfies(version, '^4.0.0')) {
165
+ throw new Error(
166
+ `Node Sass version ${version} is incompatible with ^4.0.0.`
167
+ );
57
168
  }
58
169
 
59
- const options = normalizeOptions(this, content, webpackImporter(
60
- resourcePath,
61
- pify(this.resolve.bind(this)),
62
- addNormalizedDependency
63
- ));
170
+ // There is an issue with node-sass when async custom importers are used
171
+ // See https://github.com/sass/node-sass/issues/857#issuecomment-93594360
172
+ // We need to use a job queue to make sure that one thread is always available to the UV lib
173
+ if (nodeSassJobQueue === null) {
174
+ const threadPoolSize = Number(process.env.UV_THREADPOOL_SIZE || 4);
64
175
 
65
- // Skip empty files, otherwise it will stop webpack, see issue #21
66
- if (options.data.trim() === "") {
67
- callback(null, "");
68
- return;
176
+ nodeSassJobQueue = async.queue(
177
+ module.render.bind(module),
178
+ threadPoolSize - 1
179
+ );
69
180
  }
70
181
 
71
- // start the actual rendering
72
- asyncSassJobQueue.push(options, (err, result) => {
73
- if (err) {
74
- formatSassError(err, this.resourcePath);
75
- err.file && this.dependency(err.file);
76
- callback(err);
77
- return;
78
- }
79
-
80
- if (result.map && result.map !== "{}") {
81
- result.map = JSON.parse(result.map);
82
- // result.map.file is an optional property that provides the output filename.
83
- // Since we don't know the final filename in the webpack build chain yet, it makes no sense to have it.
84
- delete result.map.file;
85
- // The first source is 'stdin' according to node-sass because we've used the data input.
86
- // Now let's override that value with the correct relative path.
87
- // Since we specified options.sourceMap = path.join(process.cwd(), "/sass.map"); in normalizeOptions,
88
- // we know that this path is relative to process.cwd(). This is how node-sass works.
89
- result.map.sources[0] = path.relative(process.cwd(), resourcePath);
90
- // node-sass returns POSIX paths, that's why we need to transform them back to native paths.
91
- // This fixes an error on windows where the source-map module cannot resolve the source maps.
92
- // @see https://github.com/webpack-contrib/sass-loader/issues/366#issuecomment-279460722
93
- result.map.sourceRoot = path.normalize(result.map.sourceRoot);
94
- result.map.sources = result.map.sources.map(path.normalize);
95
- } else {
96
- result.map = null;
97
- }
98
-
99
- result.stats.includedFiles.forEach(addNormalizedDependency);
100
- callback(null, result.css.toString(), result.map);
101
- });
182
+ return nodeSassJobQueue.push.bind(nodeSassJobQueue);
183
+ }
184
+
185
+ throw new Error(`Unknown Sass implementation "${implementation}".`);
186
+ }
187
+
188
+ function getDefaultSassImpl() {
189
+ let sassImplPkg = 'node-sass';
190
+
191
+ try {
192
+ require.resolve('node-sass');
193
+ } catch (error) {
194
+ try {
195
+ require.resolve('sass');
196
+ sassImplPkg = 'sass';
197
+ } catch (ignoreError) {
198
+ sassImplPkg = 'node-sass';
199
+ }
200
+ }
201
+
202
+ // eslint-disable-next-line import/no-dynamic-require, global-require
203
+ return require(sassImplPkg);
102
204
  }
103
205
 
104
206
  module.exports = sassLoader;
@@ -1,10 +1,12 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
- const os = require("os");
4
- const utils = require("loader-utils");
5
- const cloneDeep = require("clone-deep");
6
- const path = require("path");
7
- const proxyCustomImporters = require("./proxyCustomImporters");
3
+ const os = require('os');
4
+ const path = require('path');
5
+
6
+ const utils = require('loader-utils');
7
+ const cloneDeep = require('clone-deep');
8
+
9
+ const proxyCustomImporters = require('./proxyCustomImporters');
8
10
 
9
11
  /**
10
12
  * Derives the sass options from the loader context and normalizes its values with sane defaults.
@@ -18,61 +20,78 @@ const proxyCustomImporters = require("./proxyCustomImporters");
18
20
  * @returns {Object}
19
21
  */
20
22
  function normalizeOptions(loaderContext, content, webpackImporter) {
21
- const options = cloneDeep(utils.getOptions(loaderContext)) || {};
22
- const resourcePath = loaderContext.resourcePath;
23
+ const options = cloneDeep(utils.getOptions(loaderContext)) || {};
24
+ const { resourcePath } = loaderContext;
23
25
 
24
- options.data = options.data ? (options.data + os.EOL + content) : content;
26
+ // allow opt.functions to be configured WRT loaderContext
27
+ if (typeof options.functions === 'function') {
28
+ options.functions = options.functions(loaderContext);
29
+ }
25
30
 
26
- // opt.outputStyle
27
- if (!options.outputStyle && loaderContext.minimize) {
28
- options.outputStyle = "compressed";
29
- }
31
+ let { data } = options;
30
32
 
31
- // opt.sourceMap
32
- // Not using the `this.sourceMap` flag because css source maps are different
33
- // @see https://github.com/webpack/css-loader/pull/40
34
- if (options.sourceMap) {
35
- // Deliberately overriding the sourceMap option here.
36
- // node-sass won't produce source maps if the data option is used and options.sourceMap is not a string.
37
- // In case it is a string, options.sourceMap should be a path where the source map is written.
38
- // But since we're using the data option, the source map will not actually be written, but
39
- // all paths in sourceMap.sources will be relative to that path.
40
- // Pretty complicated... :(
41
- options.sourceMap = path.join(process.cwd(), "/sass.map");
42
- if ("sourceMapRoot" in options === false) {
43
- options.sourceMapRoot = process.cwd();
44
- }
45
- if ("omitSourceMapUrl" in options === false) {
46
- // The source map url doesn't make sense because we don't know the output path
47
- // The css-loader will handle that for us
48
- options.omitSourceMapUrl = true;
49
- }
50
- if ("sourceMapContents" in options === false) {
51
- // If sourceMapContents option is not set, set it to true otherwise maps will be empty/null
52
- // when exported by webpack-extract-text-plugin.
53
- options.sourceMapContents = true;
54
- }
55
- }
33
+ if (typeof options.data === 'function') {
34
+ data = options.data(loaderContext);
35
+ }
36
+
37
+ options.data = data ? data + os.EOL + content : content;
56
38
 
57
- // indentedSyntax is a boolean flag.
58
- const ext = path.extname(resourcePath);
39
+ // opt.outputStyle
40
+ if (!options.outputStyle && loaderContext.minimize) {
41
+ options.outputStyle = 'compressed';
42
+ }
59
43
 
60
- // If we are compiling sass and indentedSyntax isn't set, automatically set it.
61
- if (ext && ext.toLowerCase() === ".sass" && "indentedSyntax" in options === false) {
62
- options.indentedSyntax = true;
63
- } else {
64
- options.indentedSyntax = Boolean(options.indentedSyntax);
44
+ // opt.sourceMap
45
+ // Not using the `this.sourceMap` flag because css source maps are different
46
+ // @see https://github.com/webpack/css-loader/pull/40
47
+ if (options.sourceMap) {
48
+ // Deliberately overriding the sourceMap option here.
49
+ // node-sass won't produce source maps if the data option is used and options.sourceMap is not a string.
50
+ // In case it is a string, options.sourceMap should be a path where the source map is written.
51
+ // But since we're using the data option, the source map will not actually be written, but
52
+ // all paths in sourceMap.sources will be relative to that path.
53
+ // Pretty complicated... :(
54
+ options.sourceMap = path.join(process.cwd(), '/sass.map');
55
+ if ('sourceMapRoot' in options === false) {
56
+ options.sourceMapRoot = process.cwd();
65
57
  }
58
+ if ('omitSourceMapUrl' in options === false) {
59
+ // The source map url doesn't make sense because we don't know the output path
60
+ // The css-loader will handle that for us
61
+ options.omitSourceMapUrl = true;
62
+ }
63
+ if ('sourceMapContents' in options === false) {
64
+ // If sourceMapContents option is not set, set it to true otherwise maps will be empty/null
65
+ // when exported by webpack-extract-text-plugin.
66
+ options.sourceMapContents = true;
67
+ }
68
+ }
69
+
70
+ // indentedSyntax is a boolean flag.
71
+ const ext = path.extname(resourcePath);
72
+
73
+ // If we are compiling sass and indentedSyntax isn't set, automatically set it.
74
+ if (
75
+ ext &&
76
+ ext.toLowerCase() === '.sass' &&
77
+ 'indentedSyntax' in options === false
78
+ ) {
79
+ options.indentedSyntax = true;
80
+ } else {
81
+ options.indentedSyntax = Boolean(options.indentedSyntax);
82
+ }
66
83
 
67
- // Allow passing custom importers to `node-sass`. Accepts `Function` or an array of `Function`s.
68
- options.importer = options.importer ? proxyCustomImporters(options.importer, resourcePath) : [];
69
- options.importer.push(webpackImporter);
84
+ // Allow passing custom importers to `node-sass`. Accepts `Function` or an array of `Function`s.
85
+ options.importer = options.importer
86
+ ? proxyCustomImporters(options.importer, resourcePath)
87
+ : [];
88
+ options.importer.push(webpackImporter);
70
89
 
71
- // `node-sass` uses `includePaths` to resolve `@import` paths. Append the currently processed file.
72
- options.includePaths = options.includePaths || [];
73
- options.includePaths.push(path.dirname(resourcePath));
90
+ // `node-sass` uses `includePaths` to resolve `@import` paths. Append the currently processed file.
91
+ options.includePaths = options.includePaths || [];
92
+ options.includePaths.push(path.dirname(resourcePath));
74
93
 
75
- return options;
94
+ return options;
76
95
  }
77
96
 
78
97
  module.exports = normalizeOptions;
@@ -1,4 +1,4 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
3
  /**
4
4
  * Creates new custom importers that use the given `resourcePath` if libsass calls the custom importer with `prev`
@@ -10,20 +10,24 @@
10
10
  *
11
11
  * We have to fix this behavior in order to provide a consistent experience to the webpack user.
12
12
  *
13
- * @param {function|Array<function>} importer
13
+ * @param {Function|Array<Function>} importer
14
14
  * @param {string} resourcePath
15
- * @returns {Array<function>}
15
+ * @returns {Array<Function>}
16
16
  */
17
17
  function proxyCustomImporters(importer, resourcePath) {
18
- return [].concat(importer).map((importer) => {
19
- return function (url, prev, done) {
20
- return importer.apply(
21
- this, // eslint-disable-line no-invalid-this
22
- Array.from(arguments)
23
- .map((arg, i) => i === 1 && arg === "stdin" ? resourcePath : arg)
24
- );
25
- };
26
- });
18
+ return [].concat(importer).map(
19
+ // eslint-disable-next-line no-shadow
20
+ (importer) =>
21
+ function customImporter() {
22
+ return importer.apply(
23
+ this,
24
+ // eslint-disable-next-line prefer-rest-params
25
+ Array.from(arguments).map((arg, i) =>
26
+ i === 1 && arg === 'stdin' ? resourcePath : arg
27
+ )
28
+ );
29
+ }
30
+ );
27
31
  }
28
32
 
29
33
  module.exports = proxyCustomImporters;
@@ -1,4 +1,4 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
3
  /**
4
4
  * @name PromisedResolve
@@ -16,9 +16,9 @@
16
16
  * @param {Function<Error, string>} done
17
17
  */
18
18
 
19
- const path = require("path");
20
- const tail = require("lodash.tail");
21
- const importsToResolve = require("./importsToResolve");
19
+ const path = require('path');
20
+
21
+ const importsToResolve = require('./importsToResolve');
22
22
 
23
23
  const matchCss = /\.css$/;
24
24
 
@@ -34,39 +34,45 @@ const matchCss = /\.css$/;
34
34
  * @returns {Importer}
35
35
  */
36
36
  function webpackImporter(resourcePath, resolve, addNormalizedDependency) {
37
- function dirContextFrom(fileContext) {
38
- return path.dirname(
39
- // The first file is 'stdin' when we're using the data option
40
- fileContext === "stdin" ? resourcePath : fileContext
41
- );
42
- }
37
+ function dirContextFrom(fileContext) {
38
+ return path.dirname(
39
+ // The first file is 'stdin' when we're using the data option
40
+ fileContext === 'stdin' ? resourcePath : fileContext
41
+ );
42
+ }
43
43
 
44
- function startResolving(dir, importsToResolve) {
45
- return importsToResolve.length === 0 ?
46
- Promise.reject() :
47
- resolve(dir, importsToResolve[0])
48
- .then(resolvedFile => {
49
- // Add the resolvedFilename as dependency. Although we're also using stats.includedFiles, this might come
50
- // in handy when an error occurs. In this case, we don't get stats.includedFiles from node-sass.
51
- addNormalizedDependency(resolvedFile);
52
- return {
53
- // By removing the CSS file extension, we trigger node-sass to include the CSS file instead of just linking it.
54
- file: resolvedFile.replace(matchCss, "")
55
- };
56
- }, () => startResolving(
57
- dir,
58
- tail(importsToResolve)
59
- ));
60
- }
44
+ // eslint-disable-next-line no-shadow
45
+ function startResolving(dir, importsToResolve) {
46
+ return importsToResolve.length === 0
47
+ ? Promise.reject()
48
+ : resolve(dir, importsToResolve[0]).then(
49
+ (resolvedFile) => {
50
+ // Add the resolvedFilename as dependency. Although we're also using stats.includedFiles, this might come
51
+ // in handy when an error occurs. In this case, we don't get stats.includedFiles from node-sass.
52
+ addNormalizedDependency(resolvedFile);
53
+ return {
54
+ // By removing the CSS file extension, we trigger node-sass to include the CSS file instead of just linking it.
55
+ file: resolvedFile.replace(matchCss, ''),
56
+ };
57
+ },
58
+ () => {
59
+ const [, ...tailResult] = importsToResolve;
60
+
61
+ return startResolving(dir, tailResult);
62
+ }
63
+ );
64
+ }
61
65
 
62
- return (url, prev, done) => {
63
- startResolving(
64
- dirContextFrom(prev),
65
- importsToResolve(url)
66
- ) // Catch all resolving errors, return the original file and pass responsibility back to other custom importers
67
- .catch(() => ({ file: url }))
68
- .then(done);
69
- };
66
+ return (url, prev, done) => {
67
+ startResolving(dirContextFrom(prev), importsToResolve(url))
68
+ // Catch all resolving errors, return the original file and pass responsibility back to other custom importers
69
+ .catch(() => {
70
+ return {
71
+ file: url,
72
+ };
73
+ })
74
+ .then(done);
75
+ };
70
76
  }
71
77
 
72
78
  module.exports = webpackImporter;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sass-loader",
3
- "version": "7.0.1",
3
+ "version": "7.2.0",
4
4
  "description": "Sass loader for webpack",
5
5
  "author": "J. Tangelder",
6
6
  "license": "MIT",
@@ -12,13 +12,14 @@
12
12
  "appveyor:test": "npm test",
13
13
  "create-spec": "node test/tools/runCreateSpec.js",
14
14
  "lint": "eslint lib test",
15
- "test": "nyc --all mocha -R spec -t 10000",
15
+ "test": "nyc mocha -R spec -t 10000",
16
16
  "test-bootstrap-sass": "webpack-dev-server --config test/bootstrapSass/webpack.config.js --content-base ./test/bootstrapSass",
17
17
  "test-source-map": "webpack-dev-server --config test/sourceMap/webpack.config.js --content-base ./test/sourceMap --inline",
18
18
  "test-watch": "webpack --config test/watch/webpack.config.js",
19
19
  "test-extract-text": "webpack --config test/extractText/webpack.config.js",
20
20
  "test-hmr": "webpack-dev-server --config test/hmr/webpack.config.js --content-base ./test/hmr --hot --inline",
21
- "travis:lint": "npm run lint",
21
+ "travis:lint:commits": "commitlint --from=${TRAVIS_BRANCH} --to=${TRAVIS_COMMIT}",
22
+ "travis:lint": "npm run lint && npm run travis:lint:commits",
22
23
  "travis:test": "npm run test",
23
24
  "travis:coverage": "npm run test",
24
25
  "pretest": "npm run create-spec",
@@ -26,33 +27,43 @@
26
27
  "release": "standard-version"
27
28
  },
28
29
  "dependencies": {
29
- "clone-deep": "^2.0.1",
30
+ "clone-deep": "^4.0.1",
30
31
  "loader-utils": "^1.0.1",
31
- "lodash.tail": "^4.1.1",
32
32
  "neo-async": "^2.5.0",
33
- "pify": "^3.0.0"
33
+ "pify": "^4.0.1",
34
+ "semver": "^5.5.0"
34
35
  },
35
36
  "devDependencies": {
37
+ "@commitlint/cli": "^7.2.1",
38
+ "@commitlint/config-conventional": "^7.1.2",
39
+ "@webpack-contrib/eslint-config-webpack": "^3.0.0",
36
40
  "bootstrap-sass": "^3.3.5",
37
- "css-loader": "^0.28.4",
38
- "eslint": "^3.16.0",
39
- "eslint-config-peerigon": "^9.0.0",
40
- "eslint-plugin-jsdoc": "^2.4.0",
41
- "file-loader": "^0.11.2",
42
- "mocha": "^3.0.2",
41
+ "css-loader": "^2.0.0",
42
+ "eslint": "^5.10.0",
43
+ "eslint-plugin-import": "^2.14.0",
44
+ "eslint-plugin-jsdoc": "^4.4.3",
45
+ "eslint-plugin-prettier": "^3.0.0",
46
+ "file-loader": "^3.0.1",
47
+ "husky": "^1.2.0",
48
+ "lint-staged": "^8.1.0",
49
+ "mocha": "^6.0.2",
43
50
  "mock-require": "^3.0.1",
44
51
  "node-sass": "^4.5.0",
45
- "nyc": "^11.0.2",
46
- "raw-loader": "^0.5.1",
47
- "should": "^11.2.0",
48
- "standard-version": "^4.2.0",
49
- "style-loader": "^0.18.2",
52
+ "nyc": "^13.1.0",
53
+ "raw-loader": "^1.0.0",
54
+ "prettier": "^1.15.2",
55
+ "sass": "^1.3.0",
56
+ "should": "^13.2.3",
57
+ "standard-version": "^5.0.2",
58
+ "style-loader": "^0.23.1",
50
59
  "webpack": "^4.5.0",
51
- "webpack-dev-server": "^2.4.1",
52
- "webpack-merge": "^4.0.0"
60
+ "webpack-cli": "^3.1.0",
61
+ "webpack-dev-server": "^3.1.4",
62
+ "webpack-merge": "^4.0.0",
63
+ "chokidar": "^2.1.6"
53
64
  },
54
65
  "engines": {
55
- "node": ">= 6.9.0 || >= 8.9.0"
66
+ "node": ">= 6.9.0"
56
67
  },
57
68
  "peerDependencies": {
58
69
  "webpack": "^3.0.0 || ^4.0.0"
@@ -65,5 +76,21 @@
65
76
  ],
66
77
  "repository": "https://github.com/webpack-contrib/sass-loader.git",
67
78
  "bugs": "https://github.com/webpack-contrib/sass-loader/issues",
68
- "homepage": "https://github.com/webpack-contrib/sass-loader"
79
+ "homepage": "https://github.com/webpack-contrib/sass-loader",
80
+ "husky": {
81
+ "hooks": {
82
+ "pre-commit": "lint-staged"
83
+ }
84
+ },
85
+ "lint-staged": {
86
+ "*.js": [
87
+ "eslint --fix",
88
+ "git add"
89
+ ]
90
+ },
91
+ "commitlint": {
92
+ "extends": [
93
+ "@commitlint/config-conventional"
94
+ ]
95
+ }
69
96
  }