sass-loader 16.0.8 → 17.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sass-loader",
3
- "version": "16.0.8",
3
+ "version": "17.0.0",
4
4
  "description": "Sass loader for webpack",
5
5
  "keywords": [
6
6
  "sass",
@@ -17,89 +17,81 @@
17
17
  },
18
18
  "license": "MIT",
19
19
  "author": "J. Tangelder",
20
- "main": "dist/cjs.js",
20
+ "type": "module",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./types/index.d.ts",
24
+ "import": "./dist/esm/index.js",
25
+ "require": "./dist/cjs/index.js",
26
+ "default": "./dist/esm/index.js"
27
+ },
28
+ "./package.json": "./package.json"
29
+ },
30
+ "main": "./dist/cjs/index.js",
31
+ "module": "./dist/esm/index.js",
32
+ "types": "./types/index.d.ts",
21
33
  "files": [
22
- "dist"
34
+ "dist",
35
+ "types"
23
36
  ],
24
37
  "scripts": {
25
- "start": "npm run build -- -w",
26
- "clean": "del-cli dist",
38
+ "clean": "del-cli dist types",
27
39
  "prebuild": "npm run clean",
28
- "build": "cross-env NODE_ENV=production babel src -d dist --copy-files",
29
- "commitlint": "commitlint --from=main",
40
+ "build:esm": "babel src -d dist/esm --env-name esm --copy-files --no-copy-ignored",
41
+ "build:cjs": "babel src -d dist/cjs --env-name cjs --copy-files --no-copy-ignored && node -e \"const fs=require('fs');fs.writeFileSync('dist/cjs/package.json','{\\\"type\\\":\\\"commonjs\\\"}\\n');fs.appendFileSync('dist/cjs/index.js','module.exports = exports.default;\\nmodule.exports.default = exports.default;\\n')\"",
42
+ "build:types": "tsc && prettier \"types/**/*.ts\" --write",
43
+ "build": "npm-run-all -p \"build:*\"",
30
44
  "security": "npm audit --production",
31
- "lint:prettier": "prettier --cache --list-different .",
45
+ "lint": "npm-run-all -l -p \"lint:**\" && npm run fmt:check",
32
46
  "lint:code": "eslint --cache .",
33
47
  "lint:spelling": "cspell --cache --no-must-find-files --quiet \"**/*.*\"",
34
- "lint": "npm-run-all -l -p \"lint:**\"",
35
- "test:only": "cross-env NODE_ENV=test jest",
48
+ "lint:types": "tsc --pretty --noEmit",
49
+ "fmt": "npm run fmt:check -- --write",
50
+ "fmt:check": "prettier --list-different --cache --ignore-unknown .",
51
+ "fix": "npm run fix:code && npm run fmt",
36
52
  "fix:code": "npm run lint:code -- --fix",
37
- "fix:prettier": "npm run lint:prettier -- --write",
38
- "fix": "npm-run-all -l fix:code fix:prettier",
39
- "test:watch": "npm run test:only -- --watch",
40
- "test:manual": "npm run build && webpack-dev-server test/manual/src/index.js --open --config test/manual/webpack.config.js",
41
- "test:coverage": "npm run test:only -- --collectCoverageFrom=\"src/**/*.js\" --coverage",
42
53
  "pretest": "npm run lint",
43
- "test": "npm run test:coverage",
54
+ "test": "npm run test:base",
55
+ "test:base": "node --import ./test/setup-snapshots.js --test --test-force-exit --test-reporter=dot --test-reporter-destination=stdout --experimental-test-module-mocks",
56
+ "test:coverage": "npm run test:base -- --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=coverage.lcov --test-coverage-include=\"src/**/*.js\"",
44
57
  "prepare": "husky && npm run build",
45
- "release": "standard-version"
46
- },
47
- "dependencies": {
48
- "neo-async": "^2.6.2"
58
+ "version": "changeset version",
59
+ "release": "npm run build && changeset publish"
49
60
  },
61
+ "dependencies": {},
50
62
  "devDependencies": {
51
- "@babel/cli": "^7.28.0",
52
- "@babel/core": "^7.28.0",
53
- "@babel/preset-env": "^7.28.0",
54
- "@commitlint/cli": "^19.8.1",
55
- "@commitlint/config-conventional": "^19.8.1",
56
- "@eslint/js": "^9.32.0",
57
- "@eslint/markdown": "^7.0.0",
58
- "@stylistic/eslint-plugin": "^5.2.2",
63
+ "@babel/cli": "^7.28.6",
64
+ "@babel/core": "^7.28.6",
65
+ "@babel/preset-env": "^7.28.6",
66
+ "@changesets/cli": "^2.30.0",
67
+ "@changesets/get-github-info": "^0.8.0",
68
+ "@types/node": "^22.13.4",
59
69
  "bootstrap-sass": "^3.4.1",
60
70
  "bootstrap-v4": "npm:bootstrap@^4.5.3",
61
- "bootstrap-v5": "npm:bootstrap@^5.3.7",
62
- "cross-env": "^7.0.3",
63
- "cspell": "^8.19.4",
64
- "css-loader": "^6.9.0",
65
- "del": "^6.1.1",
66
- "del-cli": "^5.1.0",
67
- "enhanced-resolve": "^5.18.2",
68
- "eslint": "^9.32.0",
69
- "eslint-config-prettier": "^10.1.8",
70
- "eslint-config-webpack": "^4.5.1",
71
- "eslint-plugin-import": "^2.32.0",
72
- "eslint-plugin-jest": "^29.0.1",
73
- "eslint-plugin-jsdoc": "^52.0.0",
74
- "eslint-plugin-n": "^17.21.0",
75
- "eslint-plugin-prettier": "^5.5.3",
76
- "eslint-plugin-unicorn": "^60.0.0",
71
+ "bootstrap-v5": "npm:bootstrap@^5.3.8",
72
+ "cspell": "^10.0.0",
73
+ "css-loader": "^7.1.4",
74
+ "del": "^8.0.1",
75
+ "del-cli": "^7.0.0",
76
+ "enhanced-resolve": "^5.21.5",
77
+ "eslint": "^9.38.0",
78
+ "eslint-config-webpack": "^4.9.6",
77
79
  "file-loader": "^6.2.0",
78
80
  "foundation-sites": "^6.7.5",
79
- "globals": "^16.3.0",
80
81
  "husky": "^9.1.3",
81
- "jest": "^30.0.5",
82
- "lint-staged": "^15.5.2",
82
+ "lint-staged": "^17.0.5",
83
83
  "material-components-web": "^9.0.0",
84
- "memfs": "^4.23.0",
85
- "node-sass": "^9.0.0",
86
- "node-sass-glob-importer": "^5.3.2",
84
+ "memfs": "^4.57.2",
87
85
  "npm-run-all": "^4.1.5",
88
- "prettier": "^3.6.2",
89
- "sass": "^1.89.2",
90
- "sass-embedded": "^1.89.2",
91
- "semver": "^7.7.2",
92
- "standard-version": "^9.3.1",
93
- "style-loader": "^3.3.4",
94
- "typescript": "^5.9.2",
95
- "typescript-eslint": "^8.39.0",
96
- "webpack": "^5.101.0",
97
- "webpack-cli": "^6.0.1",
98
- "webpack-dev-server": "^5.2.2"
86
+ "prettier": "^3.8.3",
87
+ "sass": "^1.99.0",
88
+ "sass-embedded": "^1.99.0",
89
+ "style-loader": "^4.0.0",
90
+ "typescript": "^6.0.3",
91
+ "webpack": "^5.106.2"
99
92
  },
100
93
  "peerDependencies": {
101
94
  "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0",
102
- "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
103
95
  "sass": "^1.3.0",
104
96
  "sass-embedded": "*",
105
97
  "webpack": "^5.0.0"
@@ -108,9 +100,6 @@
108
100
  "@rspack/core": {
109
101
  "optional": true
110
102
  },
111
- "node-sass": {
112
- "optional": true
113
- },
114
103
  "sass": {
115
104
  "optional": true
116
105
  },
@@ -122,6 +111,6 @@
122
111
  }
123
112
  },
124
113
  "engines": {
125
- "node": ">= 18.12.0"
114
+ "node": ">= 22.11.0"
126
115
  }
127
116
  }
@@ -0,0 +1,19 @@
1
+ export default loader;
2
+ export type LoaderContext = import("webpack").LoaderContext<LoaderOptions>;
3
+ export type Schema = import("schema-utils/declarations/validate").Schema;
4
+ export type LoaderOptions = import("./utils.js").LoaderOptions;
5
+ export type SassError = import("./utils.js").SassError;
6
+ /** @typedef {import("webpack").LoaderContext<LoaderOptions>} LoaderContext */
7
+ /** @typedef {import("schema-utils/declarations/validate").Schema} Schema */
8
+ /** @typedef {import("./utils.js").LoaderOptions} LoaderOptions */
9
+ /** @typedef {import("./utils.js").SassError} SassError */
10
+ /**
11
+ * The sass-loader makes dart-sass and sass-embedded available to webpack modules.
12
+ * @this {LoaderContext}
13
+ * @param {string} content content
14
+ * @returns {Promise<void>} loader result
15
+ */
16
+ declare function loader(
17
+ this: import("webpack").LoaderContext<import("./utils.js").LoaderOptions>,
18
+ content: string,
19
+ ): Promise<void>;
@@ -0,0 +1,294 @@
1
+ export type EXPECTED_ANY = any;
2
+ export type SourceLocation = {
3
+ /**
4
+ * line number
5
+ */
6
+ line: number;
7
+ /**
8
+ * column number
9
+ */
10
+ column: number;
11
+ /**
12
+ * character offset
13
+ */
14
+ offset: number;
15
+ };
16
+ export type SourceSpan = {
17
+ /**
18
+ * start location
19
+ */
20
+ start: SourceLocation;
21
+ /**
22
+ * end location
23
+ */
24
+ end: SourceLocation;
25
+ /**
26
+ * canonical URL of the file
27
+ */
28
+ url?: URL | undefined;
29
+ /**
30
+ * covered text
31
+ */
32
+ text: string;
33
+ /**
34
+ * surrounding context
35
+ */
36
+ context?: string | undefined;
37
+ };
38
+ export type LoggerWarnOptions = {
39
+ deprecation?: boolean;
40
+ span?: SourceSpan;
41
+ stack?: string;
42
+ };
43
+ export type Logger = {
44
+ /**
45
+ * warn handler
46
+ */
47
+ warn?: ((message: string, options: LoggerWarnOptions) => void) | undefined;
48
+ /**
49
+ * debug handler
50
+ */
51
+ debug?:
52
+ | ((
53
+ message: string,
54
+ options: {
55
+ span: SourceSpan;
56
+ },
57
+ ) => void)
58
+ | undefined;
59
+ };
60
+ export type CompileResult = {
61
+ /**
62
+ * css output
63
+ */
64
+ css: Buffer | string;
65
+ /**
66
+ * source map
67
+ */
68
+ sourceMap?: RawSourceMap | undefined;
69
+ /**
70
+ * loaded URLs
71
+ */
72
+ loadedUrls: URL[];
73
+ };
74
+ export type Importer = {
75
+ /**
76
+ * canonicalize
77
+ */
78
+ canonicalize: (
79
+ originalUrl: string,
80
+ context: {
81
+ containingUrl: URL | null;
82
+ fromImport: boolean;
83
+ },
84
+ ) => Promise<URL | null>;
85
+ /**
86
+ * load
87
+ */
88
+ load: (canonicalUrl: URL) => Promise<{
89
+ contents: string;
90
+ syntax: "scss" | "indented" | "css";
91
+ sourceMapUrl?: URL;
92
+ } | null>;
93
+ };
94
+ export type OutputStyle = "expanded" | "compressed";
95
+ export type KnownSassOptions = {
96
+ /**
97
+ * syntax
98
+ */
99
+ syntax?: ("scss" | "indented" | "css") | undefined;
100
+ /**
101
+ * url
102
+ */
103
+ url?: URL | undefined;
104
+ /**
105
+ * style
106
+ */
107
+ style?: ("expanded" | "compressed") | undefined;
108
+ /**
109
+ * load paths
110
+ */
111
+ loadPaths?: string[] | undefined;
112
+ /**
113
+ * source map
114
+ */
115
+ sourceMap?: boolean | undefined;
116
+ /**
117
+ * source map include sources
118
+ */
119
+ sourceMapIncludeSources?: boolean | undefined;
120
+ /**
121
+ * importers
122
+ */
123
+ importers?: Importer[] | undefined;
124
+ /**
125
+ * logger
126
+ */
127
+ logger?: Logger | undefined;
128
+ };
129
+ export type SassOptions = KnownSassOptions & Record<string, EXPECTED_ANY>;
130
+ export type AsyncCompiler = {
131
+ /**
132
+ * compile a string
133
+ */
134
+ compileStringAsync: (
135
+ source: string,
136
+ options?: SassOptions,
137
+ ) => Promise<CompileResult>;
138
+ /**
139
+ * dispose the compiler
140
+ */
141
+ dispose: () => Promise<void>;
142
+ };
143
+ export type SassImplementation = {
144
+ info: string;
145
+ compileStringAsync(
146
+ source: string,
147
+ options?: SassOptions,
148
+ ): Promise<CompileResult>;
149
+ initAsyncCompiler?(): Promise<AsyncCompiler>;
150
+ };
151
+ export type ApiType = "auto" | "modern" | "modern-compiler";
152
+ export type LoaderContext = import("webpack").LoaderContext<LoaderOptions>;
153
+ export type LoaderOptions = {
154
+ /**
155
+ * SaSS implementation
156
+ */
157
+ implementation?: SassImplementation | undefined;
158
+ /**
159
+ * SaSS options
160
+ */
161
+ sassOptions?:
162
+ | (SassOptions | ((loaderContext: LoaderContext) => SassOptions))
163
+ | undefined;
164
+ /**
165
+ * true if source map is enabled, otherwise false
166
+ */
167
+ sourceMap?: boolean | undefined;
168
+ /**
169
+ * prepends Sass/SCSS code before the actual entry file
170
+ */
171
+ additionalData?:
172
+ | (string | ((content: string, loaderContext: LoaderContext) => string))
173
+ | undefined;
174
+ /**
175
+ * true if webpack importer is enabled, otherwise false
176
+ */
177
+ webpackImporter?: boolean | undefined;
178
+ /**
179
+ * API type
180
+ */
181
+ api?: ApiType | undefined;
182
+ /**
183
+ * true if treats the `@warn` rule as a webpack warning, otherwise false
184
+ */
185
+ warnRuleAsWarning?: boolean | undefined;
186
+ };
187
+ export type Resolver = (
188
+ context: string,
189
+ request: string,
190
+ fromImport?: boolean,
191
+ ) => Promise<string>;
192
+ export type ResolutionMap = {
193
+ resolve: (context: string, request: string) => Promise<string>;
194
+ context: string;
195
+ possibleRequests: string[];
196
+ }[];
197
+ export type RawSourceMap = {
198
+ version: number;
199
+ sources: string[];
200
+ names: string[];
201
+ sourceRoot?: string;
202
+ sourcesContent?: string[];
203
+ mappings: string;
204
+ file: string;
205
+ debugId?: string;
206
+ ignoreList?: number[];
207
+ };
208
+ export type SassError = Error & {
209
+ formatted?: string;
210
+ span?: {
211
+ url?: URL;
212
+ start: {
213
+ line: number;
214
+ column: number;
215
+ };
216
+ context?: string;
217
+ };
218
+ };
219
+ /**
220
+ * @param {Error | SassError} error the original sass error
221
+ * @returns {Error} a new error
222
+ */
223
+ export function errorFactory(error: Error | SassError): Error;
224
+ /**
225
+ * Verifies that the implementation and version of Sass is supported by this loader.
226
+ * @template {SassImplementation} T
227
+ * @param {LoaderContext} loaderContext loader context
228
+ * @param {T} implementation sass implementation
229
+ * @param {ApiType=} apiType api type
230
+ * @returns {(sassOptions: SassOptions & { data: string }) => Promise<CompileResult>} compile function
231
+ */
232
+ export function getCompileFn<T extends SassImplementation>(
233
+ loaderContext: LoaderContext,
234
+ implementation: T,
235
+ apiType?: ApiType | undefined,
236
+ ): (
237
+ sassOptions: SassOptions & {
238
+ data: string;
239
+ },
240
+ ) => Promise<CompileResult>;
241
+ /**
242
+ * @param {LoaderContext} loaderContext loader context
243
+ * @returns {Importer} the modern webpack importer
244
+ */
245
+ export function getModernWebpackImporter(
246
+ loaderContext: LoaderContext,
247
+ ): Importer;
248
+ /**
249
+ * This function is not Webpack-specific and can be used by tools wishing to mimic `sass-loader`'s behaviour, so its signature should not be changed.
250
+ * @param {SassImplementation | string | undefined} implementation sass implementation
251
+ * @returns {Promise<SassImplementation>} resolved sass implementation
252
+ */
253
+ export function getSassImplementation(
254
+ implementation: SassImplementation | string | undefined,
255
+ ): Promise<SassImplementation>;
256
+ /**
257
+ * Derives the sass options from the loader context and normalizes its values with sane defaults.
258
+ * @param {LoaderContext} loaderContext loader context
259
+ * @param {LoaderOptions} loaderOptions loader options
260
+ * @param {string} content content
261
+ * @param {boolean} useSourceMap true when need to generate source maps, otherwise false
262
+ * @returns {Promise<Required<KnownSassOptions> & { data: string }>} sass options
263
+ */
264
+ export function getSassOptions(
265
+ loaderContext: LoaderContext,
266
+ loaderOptions: LoaderOptions,
267
+ content: string,
268
+ useSourceMap: boolean,
269
+ ): Promise<
270
+ Required<KnownSassOptions> & {
271
+ data: string;
272
+ }
273
+ >;
274
+ /**
275
+ * Create the resolve function used in the custom Sass importer.
276
+ * Can be used by external tools to mimic how `sass-loader` works, for example
277
+ * in a Jest transform. Such usages will want to wrap `resolve.create` from
278
+ * [`enhanced-resolve`]{@link https://github.com/webpack/enhanced-resolve} to
279
+ * pass as the `resolverFactory` argument.
280
+ * @param {LoaderContext["getResolve"]} resolverFactory a factory function for creating a Webpack resolver.
281
+ * @returns {Resolver} webpack resolver
282
+ */
283
+ export function getWebpackResolver(
284
+ resolverFactory: LoaderContext["getResolve"],
285
+ ): Resolver;
286
+ /**
287
+ * @param {RawSourceMap} map source map
288
+ * @param {string} rootContext root context
289
+ * @returns {RawSourceMap} normalized source map
290
+ */
291
+ export function normalizeSourceMap(
292
+ map: RawSourceMap,
293
+ rootContext: string,
294
+ ): RawSourceMap;
package/dist/cjs.js DELETED
@@ -1,4 +0,0 @@
1
- "use strict";
2
-
3
- const loader = require("./index");
4
- module.exports = loader.default;
package/dist/index.js DELETED
@@ -1,103 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- var _nodePath = _interopRequireDefault(require("node:path"));
8
- var _nodeUrl = _interopRequireDefault(require("node:url"));
9
- var _options = _interopRequireDefault(require("./options.json"));
10
- var _utils = require("./utils");
11
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
- // eslint-disable-next-line jsdoc/no-restricted-syntax
13
- /**
14
- * The sass-loader makes node-sass and dart-sass available to webpack modules.
15
- * @this {LoaderContext<{ string: any }>}
16
- * @param {string} content content
17
- */
18
- async function loader(content) {
19
- const options = this.getOptions(_options.default);
20
- const callback = this.async();
21
- let implementation;
22
- try {
23
- implementation = (0, _utils.getSassImplementation)(this, options.implementation);
24
- } catch (error) {
25
- callback(error);
26
- return;
27
- }
28
- const useSourceMap = typeof options.sourceMap === "boolean" ? options.sourceMap : this.sourceMap;
29
- // Use `legacy` for `node-sass` and `modern` for `dart-sass` and `sass-embedded`
30
- const apiType = typeof implementation.compileStringAsync === "undefined" ? "legacy" : typeof options.api === "undefined" ? "modern" : options.api;
31
- const sassOptions = await (0, _utils.getSassOptions)(this, options, content, implementation, useSourceMap, apiType);
32
- const shouldUseWebpackImporter = typeof options.webpackImporter === "boolean" ? options.webpackImporter : true;
33
- if (shouldUseWebpackImporter) {
34
- const isModernAPI = apiType === "modern" || apiType === "modern-compiler";
35
- if (!isModernAPI) {
36
- const {
37
- includePaths
38
- } = sassOptions;
39
- sassOptions.importer.push((0, _utils.getWebpackImporter)(this, implementation, includePaths));
40
- } else {
41
- sassOptions.importers.push(
42
- // No need to pass `loadPaths`, because modern API handle them itself
43
- (0, _utils.getModernWebpackImporter)(this, implementation, []));
44
- }
45
- }
46
- let compile;
47
- try {
48
- compile = (0, _utils.getCompileFn)(this, implementation, apiType);
49
- } catch (error) {
50
- callback(error);
51
- return;
52
- }
53
- let result;
54
- try {
55
- result = await compile(sassOptions);
56
- } catch (error) {
57
- // There are situations when the `file`/`span.url` property do not exist
58
- // Modern API
59
- if (error.span && typeof error.span.url !== "undefined") {
60
- this.addDependency(_nodeUrl.default.fileURLToPath(error.span.url));
61
- }
62
- // Legacy API
63
- else if (typeof error.file !== "undefined") {
64
- // `node-sass` returns POSIX paths
65
- this.addDependency(_nodePath.default.normalize(error.file));
66
- }
67
- callback((0, _utils.errorFactory)(error));
68
- return;
69
- }
70
- let map =
71
- // Modern API, then legacy API
72
- result.sourceMap || (result.map ? JSON.parse(result.map) : null);
73
-
74
- // Modify source paths only for webpack, otherwise we do nothing
75
- if (map && useSourceMap) {
76
- map = (0, _utils.normalizeSourceMap)(map, this.rootContext);
77
- }
78
-
79
- // Modern API
80
- if (typeof result.loadedUrls !== "undefined") {
81
- for (const includedFile of result.loadedUrls.filter(loadedUrl => loadedUrl.protocol === "file:")) {
82
- const normalizedIncludedFile = _nodeUrl.default.fileURLToPath(includedFile);
83
-
84
- // Custom `importer` can return only `contents` so includedFile will be relative
85
- if (_nodePath.default.isAbsolute(normalizedIncludedFile)) {
86
- this.addDependency(normalizedIncludedFile);
87
- }
88
- }
89
- }
90
- // Legacy API
91
- else if (typeof result.stats !== "undefined" && typeof result.stats.includedFiles !== "undefined") {
92
- for (const includedFile of result.stats.includedFiles) {
93
- const normalizedIncludedFile = _nodePath.default.normalize(includedFile);
94
-
95
- // Custom `importer` can return only `contents` so includedFile will be relative
96
- if (_nodePath.default.isAbsolute(normalizedIncludedFile)) {
97
- this.addDependency(normalizedIncludedFile);
98
- }
99
- }
100
- }
101
- callback(null, result.css.toString(), map);
102
- }
103
- var _default = exports.default = loader;