sass-loader 12.4.0 → 12.5.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/README.md +115 -22
- package/dist/SassError.js +9 -5
- package/dist/index.js +50 -21
- package/dist/options.json +5 -0
- package/dist/utils.js +194 -111
- package/package.json +23 -17
package/README.md
CHANGED
|
@@ -27,7 +27,19 @@ To begin, you'll need to install `sass-loader`:
|
|
|
27
27
|
npm install sass-loader sass webpack --save-dev
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
or
|
|
31
|
+
|
|
32
|
+
```console
|
|
33
|
+
yarn add -D sass-loader sass webpack
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
or
|
|
37
|
+
|
|
38
|
+
```console
|
|
39
|
+
pnpm add -D sass-loader sass webpack
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`sass-loader` requires you to install either [Dart Sass](https://github.com/sass/dart-sass), [Node Sass](https://github.com/sass/node-sass) on your own (more documentation can be found below) or [Sass Embedded](https://github.com/sass/embedded-host-node).
|
|
31
43
|
|
|
32
44
|
This allows you to control the versions of all your dependencies, and to choose which Sass implementation to use.
|
|
33
45
|
|
|
@@ -35,6 +47,8 @@ This allows you to control the versions of all your dependencies, and to choose
|
|
|
35
47
|
|
|
36
48
|
> ⚠ [Node Sass](https://github.com/sass/node-sass) does not work with [Yarn PnP](https://classic.yarnpkg.com/en/docs/pnp/) feature and doesn't support [@use rule](https://sass-lang.com/documentation/at-rules/use).
|
|
37
49
|
|
|
50
|
+
> ⚠ [Sass Embedded](https://github.com/sass/embedded-host-node) is experimental and in `beta`, therefore some features may not work
|
|
51
|
+
|
|
38
52
|
Chain the `sass-loader` with the [css-loader](https://github.com/webpack-contrib/css-loader) and the [style-loader](https://github.com/webpack-contrib/style-loader) to immediately apply all styles to the DOM or the [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) to extract it into a separate file.
|
|
39
53
|
|
|
40
54
|
Then add the loader to your Webpack configuration. For example:
|
|
@@ -119,18 +133,21 @@ Thankfully there are a two solutions to this problem:
|
|
|
119
133
|
|
|
120
134
|
## Options
|
|
121
135
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
| **[`webpackImporter`](#webpackimporter)** | `{Boolean}` | `true` | Enables/Disables the default Webpack importer. |
|
|
129
|
-
| **[`warnRuleAsWarning`](#warnruleaswarning)** | `{Boolean}` | `false` | Treats the `@warn` rule as a webpack warning. |
|
|
136
|
+
- **[`implementation`](#implementation)**
|
|
137
|
+
- **[`sassOptions`](#sassoptions)**
|
|
138
|
+
- **[`sourceMap`](#sourcemap)**
|
|
139
|
+
- **[`additionalData`](#additionaldata)**
|
|
140
|
+
- **[`webpackImporter`](#webpackimporter)**
|
|
141
|
+
- **[`warnRuleAsWarning`](#warnruleaswarning)**
|
|
130
142
|
|
|
131
143
|
### `implementation`
|
|
132
144
|
|
|
133
|
-
Type:
|
|
145
|
+
Type:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
type implementation = object | string;
|
|
149
|
+
```
|
|
150
|
+
|
|
134
151
|
Default: `sass`
|
|
135
152
|
|
|
136
153
|
The special `implementation` option determines which implementation of Sass to use.
|
|
@@ -169,7 +186,7 @@ In order to avoid this situation you can use the `implementation` option.
|
|
|
169
186
|
|
|
170
187
|
The `implementation` options either accepts `sass` (`Dart Sass`) or `node-sass` as a module.
|
|
171
188
|
|
|
172
|
-
####
|
|
189
|
+
#### `object`
|
|
173
190
|
|
|
174
191
|
For example, to use Dart Sass, you'd pass:
|
|
175
192
|
|
|
@@ -196,7 +213,7 @@ module.exports = {
|
|
|
196
213
|
};
|
|
197
214
|
```
|
|
198
215
|
|
|
199
|
-
####
|
|
216
|
+
#### `string`
|
|
200
217
|
|
|
201
218
|
For example, to use Dart Sass, you'd pass:
|
|
202
219
|
|
|
@@ -302,7 +319,18 @@ module.exports = {
|
|
|
302
319
|
|
|
303
320
|
### `sassOptions`
|
|
304
321
|
|
|
305
|
-
Type:
|
|
322
|
+
Type:
|
|
323
|
+
|
|
324
|
+
```ts
|
|
325
|
+
type sassOptions =
|
|
326
|
+
| import("sass").LegacyOptions<"async">
|
|
327
|
+
| ((
|
|
328
|
+
content: string | Buffer,
|
|
329
|
+
loaderContext: LoaderContext,
|
|
330
|
+
meta: any
|
|
331
|
+
) => import("sass").LegacyOptions<"async">);
|
|
332
|
+
```
|
|
333
|
+
|
|
306
334
|
Default: defaults values for Sass implementation
|
|
307
335
|
|
|
308
336
|
Options for [Dart Sass](http://sass-lang.com/dart-sass) or [Node Sass](https://github.com/sass/node-sass) implementation.
|
|
@@ -324,9 +352,9 @@ Please consult documentation before using them:
|
|
|
324
352
|
- [Dart Sass documentation](https://github.com/sass/dart-sass#javascript-api) for all available `sass` options.
|
|
325
353
|
- [Node Sass documentation](https://github.com/sass/node-sass/#options) for all available `node-sass` options.
|
|
326
354
|
|
|
327
|
-
#### `
|
|
355
|
+
#### `object`
|
|
328
356
|
|
|
329
|
-
Use
|
|
357
|
+
Use an object for the Sass implementation setup.
|
|
330
358
|
|
|
331
359
|
**webpack.config.js**
|
|
332
360
|
|
|
@@ -355,7 +383,7 @@ module.exports = {
|
|
|
355
383
|
};
|
|
356
384
|
```
|
|
357
385
|
|
|
358
|
-
#### `
|
|
386
|
+
#### `function`
|
|
359
387
|
|
|
360
388
|
Allows to setup the Sass implementation by setting different options based on the loader context.
|
|
361
389
|
|
|
@@ -397,7 +425,12 @@ module.exports = {
|
|
|
397
425
|
|
|
398
426
|
### `sourceMap`
|
|
399
427
|
|
|
400
|
-
Type:
|
|
428
|
+
Type:
|
|
429
|
+
|
|
430
|
+
```ts
|
|
431
|
+
type sourceMap = boolean;
|
|
432
|
+
```
|
|
433
|
+
|
|
401
434
|
Default: depends on the `compiler.devtool` value
|
|
402
435
|
|
|
403
436
|
Enables/Disables generation of source maps.
|
|
@@ -469,7 +502,14 @@ module.exports = {
|
|
|
469
502
|
|
|
470
503
|
### `additionalData`
|
|
471
504
|
|
|
472
|
-
Type:
|
|
505
|
+
Type:
|
|
506
|
+
|
|
507
|
+
```ts
|
|
508
|
+
type additionalData =
|
|
509
|
+
| string
|
|
510
|
+
| ((content: string | Buffer, loaderContext: LoaderContext) => string);
|
|
511
|
+
```
|
|
512
|
+
|
|
473
513
|
Default: `undefined`
|
|
474
514
|
|
|
475
515
|
Prepends `Sass`/`SCSS` code before the actual entry file.
|
|
@@ -477,7 +517,7 @@ In this case, the `sass-loader` will not override the `data` option but just **p
|
|
|
477
517
|
|
|
478
518
|
This is especially useful when some of your Sass variables depend on the environment:
|
|
479
519
|
|
|
480
|
-
#### `
|
|
520
|
+
#### `string`
|
|
481
521
|
|
|
482
522
|
```js
|
|
483
523
|
module.exports = {
|
|
@@ -501,7 +541,7 @@ module.exports = {
|
|
|
501
541
|
};
|
|
502
542
|
```
|
|
503
543
|
|
|
504
|
-
#### `
|
|
544
|
+
#### `function`
|
|
505
545
|
|
|
506
546
|
##### Sync
|
|
507
547
|
|
|
@@ -573,7 +613,12 @@ module.exports = {
|
|
|
573
613
|
|
|
574
614
|
### `webpackImporter`
|
|
575
615
|
|
|
576
|
-
Type:
|
|
616
|
+
Type:
|
|
617
|
+
|
|
618
|
+
```ts
|
|
619
|
+
type webpackImporter = boolean;
|
|
620
|
+
```
|
|
621
|
+
|
|
577
622
|
Default: `true`
|
|
578
623
|
|
|
579
624
|
Enables/Disables the default Webpack importer.
|
|
@@ -607,7 +652,12 @@ module.exports = {
|
|
|
607
652
|
|
|
608
653
|
### `warnRuleAsWarning`
|
|
609
654
|
|
|
610
|
-
Type:
|
|
655
|
+
Type:
|
|
656
|
+
|
|
657
|
+
```ts
|
|
658
|
+
type warnRuleAsWarning = boolean;
|
|
659
|
+
```
|
|
660
|
+
|
|
611
661
|
Default: `false`
|
|
612
662
|
|
|
613
663
|
Treats the `@warn` rule as a webpack warning.
|
|
@@ -664,6 +714,49 @@ module.exports = {
|
|
|
664
714
|
};
|
|
665
715
|
```
|
|
666
716
|
|
|
717
|
+
### `api`
|
|
718
|
+
|
|
719
|
+
Type:
|
|
720
|
+
|
|
721
|
+
```ts
|
|
722
|
+
type api = "legacy" | "modern";
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
Default: `"legacy"`
|
|
726
|
+
|
|
727
|
+
Allows you to switch between `legacy` and `modern` API. You can find more information [here](https://sass-lang.com/documentation/js-api).
|
|
728
|
+
|
|
729
|
+
> ⚠ "modern" API is experimental, so some features may not work (known: built-in `importer` is not working and files with errors is not watching on initial run), you can follow this [here](https://github.com/webpack-contrib/sass-loader/issues/774).
|
|
730
|
+
|
|
731
|
+
> ⚠ The sass options are different for `modern` and `old` APIs. Please look at [docs](https://sass-lang.com/documentation/js-api) how to migrate on new options.
|
|
732
|
+
|
|
733
|
+
**webpack.config.js**
|
|
734
|
+
|
|
735
|
+
```js
|
|
736
|
+
module.exports = {
|
|
737
|
+
module: {
|
|
738
|
+
rules: [
|
|
739
|
+
{
|
|
740
|
+
test: /\.s[ac]ss$/i,
|
|
741
|
+
use: [
|
|
742
|
+
"style-loader",
|
|
743
|
+
"css-loader",
|
|
744
|
+
{
|
|
745
|
+
loader: "sass-loader",
|
|
746
|
+
options: {
|
|
747
|
+
api: "modern",
|
|
748
|
+
sassOptions: {
|
|
749
|
+
// Your sass options
|
|
750
|
+
},
|
|
751
|
+
},
|
|
752
|
+
},
|
|
753
|
+
],
|
|
754
|
+
},
|
|
755
|
+
],
|
|
756
|
+
},
|
|
757
|
+
};
|
|
758
|
+
```
|
|
759
|
+
|
|
667
760
|
## Examples
|
|
668
761
|
|
|
669
762
|
### Extracts CSS into separate files
|
package/dist/SassError.js
CHANGED
|
@@ -11,12 +11,16 @@ class SassError extends Error {
|
|
|
11
11
|
this.name = "SassError"; // TODO remove me in the next major release
|
|
12
12
|
|
|
13
13
|
this.originalSassError = sassError;
|
|
14
|
-
this.loc = {
|
|
15
|
-
line: sassError.line,
|
|
16
|
-
column: sassError.column
|
|
17
|
-
}; // Keep original error if `sassError.formatted` is unavailable
|
|
18
14
|
|
|
19
|
-
|
|
15
|
+
if (typeof sassError.line !== "undefined" || typeof sassError.column !== "undefined") {
|
|
16
|
+
this.loc = {
|
|
17
|
+
line: sassError.line,
|
|
18
|
+
column: sassError.column
|
|
19
|
+
};
|
|
20
|
+
} // Keep original error if `sassError.formatted` is unavailable
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
this.message = `${this.name}: ${typeof this.originalSassError.message !== "undefined" ? this.originalSassError.message : this.originalSassError}`;
|
|
20
24
|
|
|
21
25
|
if (this.originalSassError.formatted) {
|
|
22
26
|
this.message = `${this.name}: ${this.originalSassError.formatted.replace(/^Error: /, "")}`; // Instruct webpack to hide the JS stack from the console.
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
+
var _url = _interopRequireDefault(require("url"));
|
|
9
|
+
|
|
8
10
|
var _path = _interopRequireDefault(require("path"));
|
|
9
11
|
|
|
10
12
|
var _options = _interopRequireDefault(require("./options.json"));
|
|
@@ -36,31 +38,57 @@ async function loader(content) {
|
|
|
36
38
|
const shouldUseWebpackImporter = typeof options.webpackImporter === "boolean" ? options.webpackImporter : true;
|
|
37
39
|
|
|
38
40
|
if (shouldUseWebpackImporter) {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
const isModernAPI = options.api === "modern";
|
|
42
|
+
|
|
43
|
+
if (!isModernAPI) {
|
|
44
|
+
const {
|
|
45
|
+
includePaths
|
|
46
|
+
} = sassOptions;
|
|
47
|
+
sassOptions.importer.push((0, _utils.getWebpackImporter)(this, implementation, includePaths));
|
|
48
|
+
} else {
|
|
49
|
+
sassOptions.importers.push((0, _utils.getModernWebpackImporter)(this, implementation));
|
|
50
|
+
}
|
|
43
51
|
}
|
|
44
52
|
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
const compile = (0, _utils.getCompileFn)(implementation, options);
|
|
54
|
+
let result;
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
result = await compile(sassOptions, options);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
// There are situations when the `file`/`span.url` property do not exist
|
|
60
|
+
// Modern API
|
|
61
|
+
if (error.span && typeof error.span.url !== "undefined") {
|
|
62
|
+
this.addDependency(_url.default.fileURLToPath(error.span.url));
|
|
63
|
+
} // Legacy API
|
|
64
|
+
else if (typeof error.file !== "undefined") {
|
|
65
|
+
// `node-sass` returns POSIX paths
|
|
66
|
+
this.addDependency(_path.default.normalize(error.file));
|
|
56
67
|
}
|
|
57
68
|
|
|
58
|
-
|
|
69
|
+
callback(new _SassError.default(error));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let map = // Modern API, then legacy API
|
|
74
|
+
result.sourceMap ? result.sourceMap : result.map ? JSON.parse(result.map) : null; // Modify source paths only for webpack, otherwise we do nothing
|
|
75
|
+
|
|
76
|
+
if (map && useSourceMap) {
|
|
77
|
+
map = (0, _utils.normalizeSourceMap)(map, this.rootContext);
|
|
78
|
+
} // Modern API
|
|
59
79
|
|
|
60
|
-
if (map && useSourceMap) {
|
|
61
|
-
map = (0, _utils.normalizeSourceMap)(map, this.rootContext);
|
|
62
|
-
}
|
|
63
80
|
|
|
81
|
+
if (typeof result.loadedUrls !== "undefined") {
|
|
82
|
+
result.loadedUrls.forEach(includedFile => {
|
|
83
|
+
const normalizedIncludedFile = _url.default.fileURLToPath(includedFile); // Custom `importer` can return only `contents` so includedFile will be relative
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
if (_path.default.isAbsolute(normalizedIncludedFile)) {
|
|
87
|
+
this.addDependency(normalizedIncludedFile);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
} // Legacy API
|
|
91
|
+
else if (typeof result.stats !== "undefined" && typeof result.stats.includedFiles !== "undefined") {
|
|
64
92
|
result.stats.includedFiles.forEach(includedFile => {
|
|
65
93
|
const normalizedIncludedFile = _path.default.normalize(includedFile); // Custom `importer` can return only `contents` so includedFile will be relative
|
|
66
94
|
|
|
@@ -69,8 +97,9 @@ async function loader(content) {
|
|
|
69
97
|
this.addDependency(normalizedIncludedFile);
|
|
70
98
|
}
|
|
71
99
|
});
|
|
72
|
-
|
|
73
|
-
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
callback(null, result.css.toString(), map);
|
|
74
103
|
}
|
|
75
104
|
|
|
76
105
|
var _default = loader;
|
package/dist/options.json
CHANGED
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
}
|
|
15
15
|
]
|
|
16
16
|
},
|
|
17
|
+
"api": {
|
|
18
|
+
"description": "Switch between old and modern API for `sass` (`Dart Sass`) and `Sass Embedded` implementations.",
|
|
19
|
+
"link": "https://github.com/webpack-contrib/sass-loader#sassoptions",
|
|
20
|
+
"enum": ["legacy", "modern"]
|
|
21
|
+
},
|
|
17
22
|
"sassOptions": {
|
|
18
23
|
"description": "Options for `node-sass` or `sass` (`Dart Sass`) implementation.",
|
|
19
24
|
"link": "https://github.com/webpack-contrib/sass-loader#sassoptions",
|
package/dist/utils.js
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
6
|
+
exports.getCompileFn = getCompileFn;
|
|
7
|
+
exports.getModernWebpackImporter = getModernWebpackImporter;
|
|
7
8
|
exports.getSassImplementation = getSassImplementation;
|
|
8
9
|
exports.getSassOptions = getSassOptions;
|
|
9
10
|
exports.getWebpackImporter = getWebpackImporter;
|
|
@@ -93,6 +94,9 @@ function getSassImplementation(loaderContext, implementation) {
|
|
|
93
94
|
} else if (implementationName === "node-sass") {
|
|
94
95
|
// eslint-disable-next-line consistent-return
|
|
95
96
|
return resolvedImplementation;
|
|
97
|
+
} else if (implementationName === "sass-embedded") {
|
|
98
|
+
// eslint-disable-next-line consistent-return
|
|
99
|
+
return resolvedImplementation;
|
|
96
100
|
}
|
|
97
101
|
|
|
98
102
|
loaderContext.emitError(new Error(`Unknown Sass implementation "${implementationName}".`));
|
|
@@ -135,73 +139,8 @@ function isSupportedFibers() {
|
|
|
135
139
|
async function getSassOptions(loaderContext, loaderOptions, content, implementation, useSourceMap) {
|
|
136
140
|
const options = (0, _full.klona)(loaderOptions.sassOptions ? typeof loaderOptions.sassOptions === "function" ? loaderOptions.sassOptions(loaderContext) || {} : loaderOptions.sassOptions : {});
|
|
137
141
|
const isDartSass = implementation.info.includes("dart-sass");
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const shouldTryToResolveFibers = !options.fiber && options.fiber !== false;
|
|
141
|
-
|
|
142
|
-
if (shouldTryToResolveFibers) {
|
|
143
|
-
let fibers;
|
|
144
|
-
|
|
145
|
-
try {
|
|
146
|
-
fibers = require.resolve("fibers");
|
|
147
|
-
} catch (_error) {// Nothing
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (fibers) {
|
|
151
|
-
// eslint-disable-next-line global-require, import/no-dynamic-require
|
|
152
|
-
options.fiber = require(fibers);
|
|
153
|
-
}
|
|
154
|
-
} else if (options.fiber === false) {
|
|
155
|
-
// Don't pass the `fiber` option for `sass` (`Dart Sass`)
|
|
156
|
-
delete options.fiber;
|
|
157
|
-
}
|
|
158
|
-
} else {
|
|
159
|
-
// Don't pass the `fiber` option for `node-sass`
|
|
160
|
-
delete options.fiber;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
options.file = loaderContext.resourcePath;
|
|
164
|
-
options.data = loaderOptions.additionalData ? typeof loaderOptions.additionalData === "function" ? await loaderOptions.additionalData(content, loaderContext) : `${loaderOptions.additionalData}\n${content}` : content; // opt.outputStyle
|
|
165
|
-
|
|
166
|
-
if (!options.outputStyle && isProductionLikeMode(loaderContext)) {
|
|
167
|
-
options.outputStyle = "compressed";
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (useSourceMap) {
|
|
171
|
-
// Deliberately overriding the sourceMap option here.
|
|
172
|
-
// node-sass won't produce source maps if the data option is used and options.sourceMap is not a string.
|
|
173
|
-
// In case it is a string, options.sourceMap should be a path where the source map is written.
|
|
174
|
-
// But since we're using the data option, the source map will not actually be written, but
|
|
175
|
-
// all paths in sourceMap.sources will be relative to that path.
|
|
176
|
-
// Pretty complicated... :(
|
|
177
|
-
options.sourceMap = true;
|
|
178
|
-
options.outFile = _path.default.join(loaderContext.rootContext, "style.css.map");
|
|
179
|
-
options.sourceMapContents = true;
|
|
180
|
-
options.omitSourceMapUrl = true;
|
|
181
|
-
options.sourceMapEmbed = false;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const {
|
|
185
|
-
resourcePath
|
|
186
|
-
} = loaderContext;
|
|
187
|
-
|
|
188
|
-
const ext = _path.default.extname(resourcePath); // If we are compiling sass and indentedSyntax isn't set, automatically set it.
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
if (ext && ext.toLowerCase() === ".sass" && typeof options.indentedSyntax === "undefined") {
|
|
192
|
-
options.indentedSyntax = true;
|
|
193
|
-
} else {
|
|
194
|
-
options.indentedSyntax = Boolean(options.indentedSyntax);
|
|
195
|
-
} // Allow passing custom importers to `sass`/`node-sass`. Accepts `Function` or an array of `Function`s.
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
options.importer = options.importer ? proxyCustomImporters(Array.isArray(options.importer) ? options.importer : [options.importer], loaderContext) : [];
|
|
199
|
-
options.includePaths = [].concat(process.cwd()).concat( // We use `includePaths` in context for resolver, so it should be always absolute
|
|
200
|
-
(options.includePaths || []).map(includePath => _path.default.isAbsolute(includePath) ? includePath : _path.default.join(process.cwd(), includePath))).concat(process.env.SASS_PATH ? process.env.SASS_PATH.split(process.platform === "win32" ? ";" : ":") : []);
|
|
201
|
-
|
|
202
|
-
if (typeof options.charset === "undefined") {
|
|
203
|
-
options.charset = true;
|
|
204
|
-
}
|
|
142
|
+
const isModernAPI = loaderOptions.api === "modern";
|
|
143
|
+
options.data = loaderOptions.additionalData ? typeof loaderOptions.additionalData === "function" ? await loaderOptions.additionalData(content, loaderContext) : `${loaderOptions.additionalData}\n${content}` : content;
|
|
205
144
|
|
|
206
145
|
if (!options.logger) {
|
|
207
146
|
// TODO set me to `true` by default in the next major release
|
|
@@ -249,6 +188,100 @@ async function getSassOptions(loaderContext, loaderOptions, content, implementat
|
|
|
249
188
|
};
|
|
250
189
|
}
|
|
251
190
|
|
|
191
|
+
const {
|
|
192
|
+
resourcePath
|
|
193
|
+
} = loaderContext;
|
|
194
|
+
|
|
195
|
+
if (isModernAPI) {
|
|
196
|
+
options.url = _url.default.pathToFileURL(resourcePath); // opt.outputStyle
|
|
197
|
+
|
|
198
|
+
if (!options.style && isProductionLikeMode(loaderContext)) {
|
|
199
|
+
options.style = "compressed";
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (useSourceMap) {
|
|
203
|
+
options.sourceMap = true;
|
|
204
|
+
} // If we are compiling sass and indentedSyntax isn't set, automatically set it.
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
if (typeof options.syntax === "undefined") {
|
|
208
|
+
const ext = _path.default.extname(resourcePath);
|
|
209
|
+
|
|
210
|
+
if (ext && ext.toLowerCase() === ".scss") {
|
|
211
|
+
options.syntax = "scss";
|
|
212
|
+
} else if (ext && ext.toLowerCase() === ".sass") {
|
|
213
|
+
options.syntax = "indented";
|
|
214
|
+
} else if (ext && ext.toLowerCase() === ".css") {
|
|
215
|
+
options.syntax = "css";
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
options.importers = options.importers ? proxyCustomImporters(Array.isArray(options.importers) ? options.importers : [options.importers], loaderContext) : [];
|
|
220
|
+
} else {
|
|
221
|
+
options.file = resourcePath;
|
|
222
|
+
|
|
223
|
+
if (isDartSass && isSupportedFibers()) {
|
|
224
|
+
const shouldTryToResolveFibers = !options.fiber && options.fiber !== false;
|
|
225
|
+
|
|
226
|
+
if (shouldTryToResolveFibers) {
|
|
227
|
+
let fibers;
|
|
228
|
+
|
|
229
|
+
try {
|
|
230
|
+
fibers = require.resolve("fibers");
|
|
231
|
+
} catch (_error) {// Nothing
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (fibers) {
|
|
235
|
+
// eslint-disable-next-line global-require, import/no-dynamic-require
|
|
236
|
+
options.fiber = require(fibers);
|
|
237
|
+
}
|
|
238
|
+
} else if (options.fiber === false) {
|
|
239
|
+
// Don't pass the `fiber` option for `sass` (`Dart Sass`)
|
|
240
|
+
delete options.fiber;
|
|
241
|
+
}
|
|
242
|
+
} else {
|
|
243
|
+
// Don't pass the `fiber` option for `node-sass`
|
|
244
|
+
delete options.fiber;
|
|
245
|
+
} // opt.outputStyle
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
if (!options.outputStyle && isProductionLikeMode(loaderContext)) {
|
|
249
|
+
options.outputStyle = "compressed";
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (useSourceMap) {
|
|
253
|
+
// Deliberately overriding the sourceMap option here.
|
|
254
|
+
// node-sass won't produce source maps if the data option is used and options.sourceMap is not a string.
|
|
255
|
+
// In case it is a string, options.sourceMap should be a path where the source map is written.
|
|
256
|
+
// But since we're using the data option, the source map will not actually be written, but
|
|
257
|
+
// all paths in sourceMap.sources will be relative to that path.
|
|
258
|
+
// Pretty complicated... :(
|
|
259
|
+
options.sourceMap = true;
|
|
260
|
+
options.outFile = _path.default.join(loaderContext.rootContext, "style.css.map");
|
|
261
|
+
options.sourceMapContents = true;
|
|
262
|
+
options.omitSourceMapUrl = true;
|
|
263
|
+
options.sourceMapEmbed = false;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const ext = _path.default.extname(resourcePath); // If we are compiling sass and indentedSyntax isn't set, automatically set it.
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
if (ext && ext.toLowerCase() === ".sass" && typeof options.indentedSyntax === "undefined") {
|
|
270
|
+
options.indentedSyntax = true;
|
|
271
|
+
} else {
|
|
272
|
+
options.indentedSyntax = Boolean(options.indentedSyntax);
|
|
273
|
+
} // Allow passing custom importers to `sass`/`node-sass`. Accepts `Function` or an array of `Function`s.
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
options.importer = options.importer ? proxyCustomImporters(Array.isArray(options.importer) ? options.importer : [options.importer], loaderContext) : [];
|
|
277
|
+
options.includePaths = [].concat(process.cwd()).concat( // We use `includePaths` in context for resolver, so it should be always absolute
|
|
278
|
+
(options.includePaths || []).map(includePath => _path.default.isAbsolute(includePath) ? includePath : _path.default.join(process.cwd(), includePath))).concat(process.env.SASS_PATH ? process.env.SASS_PATH.split(process.platform === "win32" ? ";" : ":") : []);
|
|
279
|
+
|
|
280
|
+
if (typeof options.charset === "undefined") {
|
|
281
|
+
options.charset = true;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
252
285
|
return options;
|
|
253
286
|
}
|
|
254
287
|
|
|
@@ -330,6 +363,40 @@ function promiseResolve(callbackResolve) {
|
|
|
330
363
|
});
|
|
331
364
|
}
|
|
332
365
|
|
|
366
|
+
async function startResolving(resolutionMap) {
|
|
367
|
+
if (resolutionMap.length === 0) {
|
|
368
|
+
return Promise.reject();
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const [{
|
|
372
|
+
possibleRequests
|
|
373
|
+
}] = resolutionMap;
|
|
374
|
+
|
|
375
|
+
if (possibleRequests.length === 0) {
|
|
376
|
+
return Promise.reject();
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const [{
|
|
380
|
+
resolve,
|
|
381
|
+
context
|
|
382
|
+
}] = resolutionMap;
|
|
383
|
+
|
|
384
|
+
try {
|
|
385
|
+
return await resolve(context, possibleRequests[0]);
|
|
386
|
+
} catch (_ignoreError) {
|
|
387
|
+
const [, ...tailResult] = possibleRequests;
|
|
388
|
+
|
|
389
|
+
if (tailResult.length === 0) {
|
|
390
|
+
const [, ...tailResolutionMap] = resolutionMap;
|
|
391
|
+
return startResolving(tailResolutionMap);
|
|
392
|
+
} // eslint-disable-next-line no-param-reassign
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
resolutionMap[0].possibleRequests = tailResult;
|
|
396
|
+
return startResolving(resolutionMap);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
333
400
|
const IS_SPECIAL_MODULE_IMPORT = /^~[^/]+$/; // `[drive_letter]:\` + `\\[server]\[sharename]\`
|
|
334
401
|
|
|
335
402
|
const IS_NATIVE_WIN32_PATH = /^[a-z]:[/\\]|^\\\\/i;
|
|
@@ -352,41 +419,7 @@ const IS_NATIVE_WIN32_PATH = /^[a-z]:[/\\]|^\\\\/i;
|
|
|
352
419
|
*/
|
|
353
420
|
|
|
354
421
|
function getWebpackResolver(resolverFactory, implementation, includePaths = []) {
|
|
355
|
-
|
|
356
|
-
if (resolutionMap.length === 0) {
|
|
357
|
-
return Promise.reject();
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
const [{
|
|
361
|
-
possibleRequests
|
|
362
|
-
}] = resolutionMap;
|
|
363
|
-
|
|
364
|
-
if (possibleRequests.length === 0) {
|
|
365
|
-
return Promise.reject();
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
const [{
|
|
369
|
-
resolve,
|
|
370
|
-
context
|
|
371
|
-
}] = resolutionMap;
|
|
372
|
-
|
|
373
|
-
try {
|
|
374
|
-
return await resolve(context, possibleRequests[0]);
|
|
375
|
-
} catch (_ignoreError) {
|
|
376
|
-
const [, ...tailResult] = possibleRequests;
|
|
377
|
-
|
|
378
|
-
if (tailResult.length === 0) {
|
|
379
|
-
const [, ...tailResolutionMap] = resolutionMap;
|
|
380
|
-
return startResolving(tailResolutionMap);
|
|
381
|
-
} // eslint-disable-next-line no-param-reassign
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
resolutionMap[0].possibleRequests = tailResult;
|
|
385
|
-
return startResolving(resolutionMap);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
const isDartSass = implementation.info.includes("dart-sass"); // We only have one difference with the built-in sass resolution logic and out resolution logic:
|
|
422
|
+
const isDartSass = implementation && implementation.info.includes("dart-sass"); // We only have one difference with the built-in sass resolution logic and out resolution logic:
|
|
390
423
|
// First, we look at the files starting with `_`, then without `_` (i.e. `_name.sass`, `_name.scss`, `_name.css`, `name.sass`, `name.scss`, `name.css`),
|
|
391
424
|
// although `sass` look together by extensions (i.e. `_name.sass`/`name.sass`/`_name.scss`/`name.scss`/`_name.css`/`name.css`).
|
|
392
425
|
// It shouldn't be a problem because `sass` throw errors:
|
|
@@ -510,6 +543,18 @@ function getWebpackResolver(resolverFactory, implementation, includePaths = [])
|
|
|
510
543
|
|
|
511
544
|
const MATCH_CSS = /\.css$/i;
|
|
512
545
|
|
|
546
|
+
function getModernWebpackImporter() {
|
|
547
|
+
return {
|
|
548
|
+
async canonicalize() {
|
|
549
|
+
return null;
|
|
550
|
+
},
|
|
551
|
+
|
|
552
|
+
load() {// TODO implement
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
|
|
513
558
|
function getWebpackImporter(loaderContext, implementation, includePaths) {
|
|
514
559
|
const resolve = getWebpackResolver(loaderContext.getResolve, implementation, includePaths);
|
|
515
560
|
return function importer(originalUrl, prev, done) {
|
|
@@ -539,14 +584,38 @@ let nodeSassJobQueue = null;
|
|
|
539
584
|
* Verifies that the implementation and version of Sass is supported by this loader.
|
|
540
585
|
*
|
|
541
586
|
* @param {Object} implementation
|
|
587
|
+
* @param {Object} options
|
|
542
588
|
* @returns {Function}
|
|
543
589
|
*/
|
|
544
590
|
|
|
545
|
-
function
|
|
546
|
-
const
|
|
591
|
+
function getCompileFn(implementation, options) {
|
|
592
|
+
const isNewSass = implementation.info.includes("dart-sass") || implementation.info.includes("sass-embedded");
|
|
593
|
+
|
|
594
|
+
if (isNewSass) {
|
|
595
|
+
if (options.api === "modern") {
|
|
596
|
+
return sassOptions => {
|
|
597
|
+
const {
|
|
598
|
+
data,
|
|
599
|
+
...rest
|
|
600
|
+
} = sassOptions;
|
|
601
|
+
return implementation.compileStringAsync(data, rest);
|
|
602
|
+
};
|
|
603
|
+
}
|
|
547
604
|
|
|
548
|
-
|
|
549
|
-
|
|
605
|
+
return sassOptions => new Promise((resolve, reject) => {
|
|
606
|
+
implementation.render(sassOptions, (error, result) => {
|
|
607
|
+
if (error) {
|
|
608
|
+
reject(error);
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
resolve(result);
|
|
613
|
+
});
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
if (options.api === "modern") {
|
|
618
|
+
throw new Error("Modern API is not supported for 'node-sass'");
|
|
550
619
|
} // There is an issue with node-sass when async custom importers are used
|
|
551
620
|
// See https://github.com/sass/node-sass/issues/857#issuecomment-93594360
|
|
552
621
|
// We need to use a job queue to make sure that one thread is always available to the UV lib
|
|
@@ -557,7 +626,16 @@ function getRenderFunctionFromSassImplementation(implementation) {
|
|
|
557
626
|
nodeSassJobQueue = _neoAsync.default.queue(implementation.render.bind(implementation), threadPoolSize - 1);
|
|
558
627
|
}
|
|
559
628
|
|
|
560
|
-
return
|
|
629
|
+
return sassOptions => new Promise((resolve, reject) => {
|
|
630
|
+
nodeSassJobQueue.push.bind(nodeSassJobQueue)(sassOptions, (error, result) => {
|
|
631
|
+
if (error) {
|
|
632
|
+
reject(error);
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
resolve(result);
|
|
637
|
+
});
|
|
638
|
+
});
|
|
561
639
|
}
|
|
562
640
|
|
|
563
641
|
const ABSOLUTE_SCHEME = /^[A-Za-z0-9+\-.]+:/;
|
|
@@ -587,7 +665,10 @@ function normalizeSourceMap(map, rootContext) {
|
|
|
587
665
|
// Since we don't know the final filename in the webpack build chain yet, it makes no sense to have it.
|
|
588
666
|
// eslint-disable-next-line no-param-reassign
|
|
589
667
|
|
|
590
|
-
|
|
668
|
+
if (typeof newMap.file !== "undefined") {
|
|
669
|
+
delete newMap.file;
|
|
670
|
+
} // eslint-disable-next-line no-param-reassign
|
|
671
|
+
|
|
591
672
|
|
|
592
673
|
newMap.sourceRoot = ""; // node-sass returns POSIX paths, that's why we need to transform them back to native paths.
|
|
593
674
|
// This fixes an error on windows where the source-map module cannot resolve the source maps.
|
|
@@ -595,9 +676,11 @@ function normalizeSourceMap(map, rootContext) {
|
|
|
595
676
|
// eslint-disable-next-line no-param-reassign
|
|
596
677
|
|
|
597
678
|
newMap.sources = newMap.sources.map(source => {
|
|
598
|
-
const sourceType = getURLType(source); // Do no touch `scheme-relative`, `path-absolute` and `absolute` types
|
|
679
|
+
const sourceType = getURLType(source); // Do no touch `scheme-relative`, `path-absolute` and `absolute` types (except `file:`)
|
|
599
680
|
|
|
600
|
-
if (sourceType === "
|
|
681
|
+
if (sourceType === "absolute" && /^file:/i.test(source)) {
|
|
682
|
+
return _url.default.fileURLToPath(source);
|
|
683
|
+
} else if (sourceType === "path-relative") {
|
|
601
684
|
return _path.default.resolve(rootContext, _path.default.normalize(source));
|
|
602
685
|
}
|
|
603
686
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sass-loader",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.5.0",
|
|
4
4
|
"description": "Sass loader for webpack",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "webpack-contrib/sass-loader",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"fibers": ">= 3.1.0",
|
|
42
42
|
"node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0",
|
|
43
43
|
"sass": "^1.3.0",
|
|
44
|
+
"sass-embedded": "*",
|
|
44
45
|
"webpack": "^5.0.0"
|
|
45
46
|
},
|
|
46
47
|
"peerDependenciesMeta": {
|
|
@@ -50,6 +51,9 @@
|
|
|
50
51
|
"sass": {
|
|
51
52
|
"optional": true
|
|
52
53
|
},
|
|
54
|
+
"sass-embedded": {
|
|
55
|
+
"optional": true
|
|
56
|
+
},
|
|
53
57
|
"fibers": {
|
|
54
58
|
"optional": true
|
|
55
59
|
}
|
|
@@ -59,41 +63,43 @@
|
|
|
59
63
|
"neo-async": "^2.6.2"
|
|
60
64
|
},
|
|
61
65
|
"devDependencies": {
|
|
62
|
-
"@babel/cli": "^7.
|
|
63
|
-
"@babel/core": "^7.
|
|
64
|
-
"@babel/preset-env": "^7.
|
|
65
|
-
"@commitlint/cli": "^
|
|
66
|
-
"@commitlint/config-conventional": "^
|
|
66
|
+
"@babel/cli": "^7.17.0",
|
|
67
|
+
"@babel/core": "^7.17.0",
|
|
68
|
+
"@babel/preset-env": "^7.16.11",
|
|
69
|
+
"@commitlint/cli": "^16.2.1",
|
|
70
|
+
"@commitlint/config-conventional": "^16.2.1",
|
|
67
71
|
"@webpack-contrib/eslint-config-webpack": "^3.0.0",
|
|
68
|
-
"babel-jest": "^27.0
|
|
72
|
+
"babel-jest": "^27.5.0",
|
|
69
73
|
"bootstrap-sass": "^3.4.1",
|
|
70
74
|
"bootstrap-v4": "npm:bootstrap@^4.5.3",
|
|
71
75
|
"bootstrap-v5": "npm:bootstrap@^5.0.1",
|
|
72
76
|
"cross-env": "^7.0.3",
|
|
73
|
-
"css-loader": "^6.
|
|
77
|
+
"css-loader": "^6.6.0",
|
|
74
78
|
"del": "^6.0.0",
|
|
75
79
|
"del-cli": "^4.0.1",
|
|
76
80
|
"enhanced-resolve": "^5.8.2",
|
|
77
|
-
"eslint": "^8.
|
|
81
|
+
"eslint": "^8.8.0",
|
|
78
82
|
"eslint-config-prettier": "^8.3.0",
|
|
79
|
-
"eslint-plugin-import": "^2.
|
|
80
|
-
"fibers": "^5.0.
|
|
83
|
+
"eslint-plugin-import": "^2.25.4",
|
|
84
|
+
"fibers": "^5.0.1",
|
|
81
85
|
"file-loader": "^6.2.0",
|
|
82
86
|
"foundation-sites": "^6.6.3",
|
|
83
87
|
"husky": "^7.0.1",
|
|
84
|
-
"jest": "^27.0
|
|
85
|
-
"
|
|
88
|
+
"jest": "^27.5.0",
|
|
89
|
+
"jest-environment-node-single-context": "^27.2.0",
|
|
90
|
+
"lint-staged": "^12.3.3",
|
|
86
91
|
"material-components-web": "^8.0.0",
|
|
87
|
-
"memfs": "^3.
|
|
88
|
-
"node-sass": "^7.0.
|
|
92
|
+
"memfs": "^3.4.1",
|
|
93
|
+
"node-sass": "^7.0.1",
|
|
89
94
|
"node-sass-glob-importer": "^5.3.2",
|
|
90
95
|
"npm-run-all": "^4.1.5",
|
|
91
96
|
"prettier": "^2.3.2",
|
|
92
|
-
"sass": "^1.
|
|
97
|
+
"sass": "^1.49.7",
|
|
98
|
+
"sass-embedded": "^1.49.7",
|
|
93
99
|
"semver": "^7.3.5",
|
|
94
100
|
"standard-version": "^9.3.1",
|
|
95
101
|
"style-loader": "^3.2.1",
|
|
96
|
-
"webpack": "^5.
|
|
102
|
+
"webpack": "^5.68.0"
|
|
97
103
|
},
|
|
98
104
|
"keywords": [
|
|
99
105
|
"sass",
|