Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/curvy-schools-cover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"sass-loader": minor
---

Added types.
201 changes: 115 additions & 86 deletions package-lock.json

Large diffs are not rendered by default.

16 changes: 11 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"type": "module",
"exports": {
".": {
"types": "./types/index.d.ts",
"import": "./dist/esm/index.js",
"require": "./dist/cjs/index.js",
"default": "./dist/esm/index.js"
Expand All @@ -28,19 +29,23 @@
},
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"types": "./types/index.d.ts",
"files": [
"dist"
"dist",
"types"
],
"scripts": {
"clean": "del-cli dist",
"clean": "del-cli dist types",
"prebuild": "npm run clean",
"build:esm": "babel src -d dist/esm --env-name esm --copy-files --no-copy-ignored",
"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')\"",
"build:types": "tsc && prettier \"types/**/*.ts\" --write",
"build": "npm-run-all -p \"build:*\"",
"security": "npm audit --production",
"lint": "npm-run-all -l -p \"lint:**\" && npm run fmt:check",
"lint:code": "eslint --cache .",
"lint:spelling": "cspell --cache --no-must-find-files --quiet \"**/*.*\"",
"lint:types": "tsc --pretty --noEmit",
"fmt": "npm run fmt:check -- --write",
"fmt:check": "prettier --list-different --cache --ignore-unknown .",
"fix": "npm run fix:code && npm run fmt",
Expand All @@ -60,6 +65,7 @@
"@babel/preset-env": "^7.28.6",
"@changesets/cli": "^2.30.0",
"@changesets/get-github-info": "^0.8.0",
"@types/node": "^22.3.0",
"bootstrap-sass": "^3.4.1",
"bootstrap-v4": "npm:bootstrap@^4.5.3",
"bootstrap-v5": "npm:bootstrap@^5.3.7",
Expand All @@ -78,10 +84,10 @@
"memfs": "^4.57.2",
"npm-run-all": "^4.1.5",
"prettier": "^3.8.3",
"sass": "^1.89.2",
"sass-embedded": "^1.89.2",
"sass": "^1.99.0",
"sass-embedded": "^1.99.0",
"style-loader": "^3.3.4",
"typescript": "^5.9.2",
"typescript": "^6.0.3",
"webpack": "^5.106.2"
},
"peerDependencies": {
Expand Down
39 changes: 21 additions & 18 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,39 @@ import {
normalizeSourceMap,
} from "./utils.js";

// eslint-disable-next-line jsdoc/reject-any-type
/** @typedef {any} EXPECTED_ANY */
/** @typedef {import("webpack").LoaderContext<LoaderOptions>} LoaderContext */
/** @typedef {import("schema-utils/declarations/validate").Schema} Schema */
/** @typedef {import("./utils.js").LoaderOptions} LoaderOptions */
/** @typedef {import("./utils.js").SassError} SassError */

/**
* The sass-loader makes dart-sass and sass-embedded available to webpack modules.
* @this {LoaderContext<{ string: EXPECTED_ANY }>}
* @this {LoaderContext}
* @param {string} content content
* @returns {Promise<void>} loader result
*/
async function loader(content) {
const options = this.getOptions(schema);
const options = this.getOptions(/** @type {Schema} */ (schema));
const callback = this.async();

let implementation;

try {
implementation = await getSassImplementation(this, options.implementation);
implementation = await getSassImplementation(options.implementation);
} catch (error) {
callback(error);
callback(/** @type {Error} */ (error));

return;
}

const useSourceMap =
typeof options.sourceMap === "boolean" ? options.sourceMap : this.sourceMap;
typeof options.sourceMap === "boolean"
? options.sourceMap
: this.sourceMap === true;
const sassOptions = await getSassOptions(
this,
options,
content,
implementation,
useSourceMap,
);

Expand All @@ -49,18 +53,15 @@ async function loader(content) {
: true;

if (shouldUseWebpackImporter) {
sassOptions.importers.push(
// No need to pass `loadPaths`, because modern API handle them itself
getModernWebpackImporter(this, implementation, []),
);
sassOptions.importers.push(getModernWebpackImporter(this));
}

let compile;

try {
compile = getCompileFn(this, implementation, options.api);
} catch (error) {
callback(error);
callback(/** @type {Error} */ (error));
return;
}

Expand All @@ -69,17 +70,19 @@ async function loader(content) {
try {
result = await compile(sassOptions);
} catch (error) {
const sassError = /** @type {SassError} */ (error);

// There are situations when the `span.url` property does not exist
if (error.span && typeof error.span.url !== "undefined") {
this.addDependency(url.fileURLToPath(error.span.url));
if (sassError.span && typeof sassError.span.url !== "undefined") {
this.addDependency(url.fileURLToPath(sassError.span.url));
}

callback(errorFactory(error));
callback(errorFactory(sassError));

return;
}

let map = result.sourceMap || null;
let map = result.sourceMap || undefined;

// Modify source paths only for webpack, otherwise we do nothing
if (map && useSourceMap) {
Expand All @@ -99,7 +102,7 @@ async function loader(content) {
}
}

callback(null, result.css.toString(), map);
callback(null, result.css.toString(), map || undefined);
}

export default loader;
Loading
Loading