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
4 changes: 2 additions & 2 deletions .changeset/add-jsdoc-types.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
"less-loader": patch
"less-loader": minor
---

Add JSDoc type annotations to `src/index.js` and `src/utils.js` so editors and downstream consumers get IntelliSense without a TypeScript toolchain.
Added types.
2 changes: 1 addition & 1 deletion .changeset/track-sync-loaded-dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
"less-loader": patch
---

Track files loaded synchronously by Less (e.g. `data-uri()` and custom functions installed via `@plugin`) as webpack file dependencies. Previously these reads were delegated to Less's default file manager and never registered with webpack, so persistent caching could keep a stale build when only the sync-loaded file changed. See [#492](https://github.com/webpack/less-loader/issues/492).
Track files loaded synchronously by Less (e.g. `data-uri()` and custom functions installed via `@plugin`) as webpack file dependencies. See [#492](https://github.com/webpack/less-loader/issues/492).
6 changes: 6 additions & 0 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ jobs:
- name: Security audit
run: npm run security

- name: Build types
run: npm run build:types

- name: Check types
run: if [ -n "$(git status types --porcelain)" ]; then echo "Missing types. Update types by running 'npm run build:types'"; exit 1; else echo "All types are valid"; fi

test:
name: Test - ${{ matrix.os }} - Node v${{ matrix.node-version }}, Webpack ${{ matrix.webpack-version }}

Expand Down
26 changes: 18 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,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 @@ -31,20 +32,24 @@
},
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"types": "./types/index.d.ts",
"files": [
"dist"
"dist",
"types"
],
"scripts": {
"start": "npm run build -- -w",
"clean": "del-cli dist",
"prebuild": "npm run clean",
"build:esm": "babel src -d dist/esm --env-name esm --copy-files --no-copy-ignored && node -e \"require('fs').writeFileSync('dist/esm/package.json','{\\\"type\\\":\\\"module\\\"}\\n')\"",
"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 @@ -57,12 +62,16 @@
"version": "changeset version",
"release": "npm run build && changeset publish"
},
"dependencies": {
"@types/less": "^3.0.8"
},
"devDependencies": {
"@babel/cli": "^7.24.7",
"@babel/core": "^7.24.7",
"@babel/preset-env": "^7.29.5",
"@changesets/cli": "^2.30.0",
"@changesets/get-github-info": "^0.8.0",
"@types/node": "^22.13.4",
"cspell": "^10.0.0",
"del": "^8.0.1",
"del-cli": "^7.0.0",
Expand All @@ -75,6 +84,7 @@
"memfs": "^4.57.2",
"npm-run-all": "^4.1.5",
"prettier": "^3.8.3",
"typescript": "^6.0.3",
"webpack": "^5.107.0"
},
"peerDependencies": {
Expand Down
29 changes: 17 additions & 12 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ import {
normalizeSourceMap,
} from "./utils.js";

/** @typedef {import("webpack").LoaderContext<import("./utils.js").LessLoaderOptions>} LoaderContext */
/** @typedef {import("./utils.js").LessLoaderOptions} LessLoaderOptions */
/** @typedef {import("webpack").LoaderContext<LoaderOptions>} LoaderContext */
/** @typedef {import("schema-utils/declarations/validate").Schema} Schema */
/** @typedef {import("./utils.js").LoaderOptions} LoaderOptions */
/** @typedef {import("./utils.js").LessError} LessError */
/** @typedef {import("./utils.js").SourceMap} SourceMap */

/**
* Webpack loader that compiles Less to CSS.
*
* @this {LoaderContext}
* @param {string} source
* @returns {Promise<void>}
* @param {string} content content
* @returns {Promise<void>} loader result
*/
async function lessLoader(source) {
const options = /** @type {LessLoaderOptions} */ (this.getOptions(schema));
async function lessLoader(content) {
const options = this.getOptions(/** @type {Schema} */ (schema));
const callback = this.async();
let implementation;

Expand Down Expand Up @@ -56,11 +56,12 @@ async function lessLoader(source) {
lessOptions.sourceMap = {
sourceMapBasepath: "",
outputSourceFiles: true,
// @ts-expect-error bad types
disableSourcemapAnnotation: true,
};
}

let data = source;
let data = content;

if (typeof options.additionalData !== "undefined") {
data =
Expand All @@ -72,7 +73,7 @@ async function lessLoader(source) {
const logger = this.getLogger("less-loader");
const loaderContext = this;
const loggerListener = {
/** @param {string} message */
/** @param {string} message message */
error(message) {
// TODO enable by default in the next major release
if (options.lessLogAsWarnOrErr) {
Expand All @@ -81,7 +82,7 @@ async function lessLoader(source) {
logger.error(message);
}
},
/** @param {string} message */
/** @param {string} message message */
warn(message) {
// TODO enable by default in the next major release
if (options.lessLogAsWarnOrErr) {
Expand All @@ -90,16 +91,17 @@ async function lessLoader(source) {
logger.warn(message);
}
},
/** @param {string} message */
/** @param {string} message message */
info(message) {
logger.log(message);
},
/** @param {string} message */
/** @param {string} message message */
debug(message) {
logger.debug(message);
},
};

// @ts-expect-error bad types
implementation.logger.addListener(loggerListener);

let result;
Expand All @@ -124,9 +126,12 @@ async function lessLoader(source) {
return;
} finally {
// Fix memory leaks in `less`
// @ts-expect-error bad types
implementation.logger.removeListener(loggerListener);

// @ts-expect-error we need it to reset loader context
delete lessOptions.pluginManager.webpackLoaderContext;
// @ts-expect-error we need it to reset loader context
delete lessOptions.pluginManager;
}

Expand Down
Loading
Loading