diff --git a/.changeset/replace-glob-dependencies.md b/.changeset/replace-glob-dependencies.md new file mode 100644 index 0000000..98b8ea3 --- /dev/null +++ b/.changeset/replace-glob-dependencies.md @@ -0,0 +1,5 @@ +--- +"diagnostics-webpack-plugin": patch +--- + +Replace `globby`, `micromatch` and `normalize-path` with `tinyglobby` and `picomatch`, and compile the file matchers once per check rather than on every module. diff --git a/package-lock.json b/package-lock.json index c6cc788..24609a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,20 +1,19 @@ { - "name": "lint-webpack-plugin", - "version": "6.0.0", + "name": "diagnostics-webpack-plugin", + "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "lint-webpack-plugin", - "version": "6.0.0", + "name": "diagnostics-webpack-plugin", + "version": "0.0.0", "license": "MIT", "dependencies": { "@types/eslint": "^9.6.1", - "globby": "^11.1.0", "jest-worker": "^30.5.1", - "micromatch": "^4.0.8", - "normalize-path": "^3.0.0", - "schema-utils": "^4.3.3" + "picomatch": "^4.0.4", + "schema-utils": "^4.3.3", + "tinyglobby": "^0.2.17" }, "devDependencies": { "@babel/cli": "^7.29.7", @@ -26,7 +25,7 @@ "@commitlint/config-conventional": "^21.2.2", "@types/micromatch": "^4.0.10", "@types/node": "^26.4.1", - "@types/normalize-path": "^3.0.2", + "@types/picomatch": "^4.0.3", "babel-plugin-transform-import-meta": "^2.3.3", "chokidar": "^5.0.0", "cross-env": "^10.1.0", @@ -5053,6 +5052,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -5066,6 +5066,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -5075,6 +5076,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -5731,10 +5733,10 @@ "undici-types": "~8.3.0" } }, - "node_modules/@types/normalize-path": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/normalize-path/-/normalize-path-3.0.2.tgz", - "integrity": "sha512-DO++toKYPaFn0Z8hQ7Tx+3iT9t77IJo/nDiqTXilgEP+kPNIYdpS9kh3fXuc53ugqwp9pxC1PVjCpV1tQDyqMA==", + "node_modules/@types/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-iG0T6+nYJ9FAPmx9SsUlnwcq1ZVRuCXcVEvWnntoPlrOpwtSTKNDC9uVAxTsC3PUvJ+99n4RpAcNgBbHX3JSnQ==", "dev": true, "license": "MIT" }, @@ -6566,15 +6568,6 @@ "dev": true, "license": "MIT" }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/array.prototype.findlast": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", @@ -7028,6 +7021,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -8355,18 +8349,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -10040,6 +10022,7 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -10056,6 +10039,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -10135,6 +10119,7 @@ "version": "1.20.3", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.3.tgz", "integrity": "sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==", + "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -10170,7 +10155,6 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12.0.0" @@ -10272,6 +10256,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -10757,35 +10742,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/globjoin": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", @@ -11037,6 +10993,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 4" @@ -11374,6 +11331,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11431,6 +11389,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -11469,6 +11428,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -14285,6 +14245,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -14922,6 +14883,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -14935,6 +14897,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -15264,6 +15227,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -15803,15 +15767,6 @@ "node": "20 || >=22" } }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -16219,6 +16174,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, "funding": [ { "type": "github", @@ -16501,6 +16457,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -16511,6 +16468,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, "funding": [ { "type": "github", @@ -17924,7 +17882,6 @@ "version": "0.2.17", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", - "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", @@ -17941,6 +17898,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" diff --git a/package.json b/package.json index 9d980e9..e268464 100644 --- a/package.json +++ b/package.json @@ -65,11 +65,10 @@ }, "dependencies": { "@types/eslint": "^9.6.1", - "globby": "^11.1.0", "jest-worker": "^30.5.1", - "micromatch": "^4.0.8", - "normalize-path": "^3.0.0", - "schema-utils": "^4.3.3" + "picomatch": "^4.0.4", + "schema-utils": "^4.3.3", + "tinyglobby": "^0.2.17" }, "devDependencies": { "@babel/cli": "^7.29.7", @@ -81,7 +80,7 @@ "@commitlint/config-conventional": "^21.2.2", "@types/micromatch": "^4.0.10", "@types/node": "^26.4.1", - "@types/normalize-path": "^3.0.2", + "@types/picomatch": "^4.0.3", "babel-plugin-transform-import-meta": "^2.3.3", "chokidar": "^5.0.0", "cross-env": "^10.1.0", diff --git a/src/index.js b/src/index.js index c9d6029..722b6f2 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ import { isAbsolute, join } from "node:path"; -import globby from "globby"; -import micromatch from "micromatch"; +import picomatch from "picomatch"; +import { globSync } from "tinyglobby"; import createCheckRunner from "./check.js"; import { getOptions, validateOptions } from "./options.js"; @@ -12,9 +12,6 @@ import { writeOutputFile, } from "./utils.js"; -// `micromatch` is CommonJS, whose named exports ESM cannot always see -const { isMatch } = micromatch; - /** @typedef {import("webpack").Compilation} Compilation */ /** @typedef {import("webpack").Compiler} Compiler */ /** @typedef {import("webpack").Module} Module */ @@ -32,6 +29,8 @@ const { isMatch } = micromatch; * @property {CheckOptions} options options resolved for this check * @property {string[]} wanted the globs of the files to lint * @property {string[]} exclude the globs of the files not to lint + * @property {(file: string) => boolean} isWanted whether a path is one to lint + * @property {(file: string) => boolean} isExcluded whether a path is left out */ const LINT_PLUGIN = "DiagnosticsWebpackPlugin"; @@ -40,19 +39,16 @@ let compilerId = 0; /** * @param {Compiler} compiler compiler - * @param {string[]} wanted the globs of the files to lint - * @param {string[]} exclude the globs of the files not to lint + * @param {ResolvedCheck} check the check to collect the files of * @returns {string[]} the files on disk to lint */ -function collectFromFileSystem(compiler, wanted, exclude) { +function collectFromFileSystem(compiler, { wanted, exclude, ...check }) { if (!compiler.modifiedFiles) { - return globby.sync(wanted, { dot: true, ignore: exclude }); + return globSync(wanted, { absolute: true, dot: true, ignore: exclude }); } return [...compiler.modifiedFiles].filter( - (file) => - isMatch(file, wanted, { dot: true }) && - !isMatch(file, exclude, { dot: true }), + (file) => check.isWanted(file) && !check.isExcluded(file), ); } @@ -149,15 +145,24 @@ class DiagnosticsWebpackPlugin { ), }; + const wanted = parseFoldersToGlobs( + /** @type {string[]} */ (resolved.files), + resolved.extensions, + ); + const exclude = parseFoldersToGlobs( + /** @type {string[]} */ (resolved.exclude), + ); + return { name, adapter, options: resolved, - wanted: parseFoldersToGlobs( - /** @type {string[]} */ (resolved.files), - resolved.extensions, - ), - exclude: parseFoldersToGlobs(/** @type {string[]} */ (resolved.exclude)), + wanted, + exclude, + // Compiled here rather than per call: the two run on every module of + // every build, and matching by pattern recompiles them each time. + isWanted: picomatch(wanted, { dot: true }), + isExcluded: picomatch(exclude, { dot: true }), }; } @@ -206,11 +211,11 @@ class DiagnosticsWebpackPlugin { if (!file) return; - for (const { files, wanted, exclude, options } of fromModules) { + for (const check of fromModules) { + const { files, options } = check; const isFileNotListed = !files.includes(file); const isFileWanted = - isMatch(file, wanted, { dot: true }) && - !isMatch(file, exclude, { dot: true }); + check.isWanted(file) && !check.isExcluded(file); const isQueryNotExclude = /** @type {RegExp[]} */ ( options.resourceQueryExclude ).every((reg) => !reg.test(query)); @@ -231,11 +236,12 @@ class DiagnosticsWebpackPlugin { // Lint all files added compilation.hooks.finishModules.tap(this.key, () => { - for (const { adapter, files, wanted, exclude, runner } of runners) { + for (const check of runners) { + const { adapter, files, runner } = check; const filesToLint = adapter.filesSource === "modules" ? files - : collectFromFileSystem(compiler, wanted, exclude); + : collectFromFileSystem(compiler, check); if (filesToLint.length > 0) runner.lint(filesToLint); } diff --git a/src/utils.js b/src/utils.js index 3526c0f..509d46a 100644 --- a/src/utils.js +++ b/src/utils.js @@ -7,8 +7,6 @@ import { dirname, isAbsolute, resolve } from "node:path"; import { pathToFileURL } from "node:url"; -import normalizePath from "normalize-path"; - const nodeRequire = createRequire(import.meta.url); /** @typedef {import("webpack").Compiler} Compiler */ @@ -73,6 +71,15 @@ async function importFrom(specifier) { } } +/** + * Globs only know the forward slash, so a path is compared and matched as one. + * @param {string} file a path + * @returns {string} the path with its separators turned into forward slashes + */ +function toPosixPath(file) { + return file.replaceAll("\\", "/"); +} + /** * @param {string | string[]} files files * @param {string} context context @@ -80,7 +87,7 @@ async function importFrom(specifier) { */ function parseFiles(files, context) { return arrify(files).map((/** @type {string} */ file) => - normalizePath(resolve(context, file)), + toPosixPath(resolve(context, file)), ); } @@ -193,5 +200,6 @@ export { omitPluginOptions, parseFiles, parseFoldersToGlobs, + toPosixPath, writeOutputFile, }; diff --git a/test/stylelint/threads.test.js b/test/stylelint/threads.test.js index 89eba16..a369b18 100644 --- a/test/stylelint/threads.test.js +++ b/test/stylelint/threads.test.js @@ -3,11 +3,9 @@ import { createRequire } from "node:module"; import { join } from "node:path"; import { describe, it } from "node:test"; -// @ts-expect-error no types -import normalizePath from "normalize-path"; - import { lintFiles, setup } from "../../src/checks/stylelint-worker.js"; import { getLoadedStylelint } from "../../src/checks/stylelint.js"; +import { toPosixPath } from "../../src/utils.js"; import pack from "./utils/pack.js"; @@ -40,10 +38,10 @@ describe("Threading", () => { try { const [good, bad] = await Promise.all([ threaded.lintFiles( - normalizePath(join(import.meta.dirname, "fixtures/good/test.scss")), + toPosixPath(join(import.meta.dirname, "fixtures/good/test.scss")), ), threaded.lintFiles( - normalizePath(join(import.meta.dirname, "fixtures/error/test.scss")), + toPosixPath(join(import.meta.dirname, "fixtures/error/test.scss")), ), ]); assert.strictEqual(good[0].errored, false); diff --git a/test/utils.test.js b/test/utils.test.js index 00c7a1b..25f2af9 100644 --- a/test/utils.test.js +++ b/test/utils.test.js @@ -2,13 +2,28 @@ import assert from "node:assert/strict"; import { join } from "node:path"; import { describe, it } from "node:test"; -import { parseFiles, parseFoldersToGlobs } from "../src/utils.js"; +import { parseFiles, parseFoldersToGlobs, toPosixPath } from "../src/utils.js"; // `parseFoldersToGlobs` stats what it is given, so the fixtures have to exist. const directory = join(import.meta.dirname, "fixtures"); const file = join(import.meta.dirname, "fixtures", "good.js"); describe("utils", () => { + it("toPosixPath should turn every separator into a forward slash", () => { + assert.strictEqual(toPosixPath("/home/user/a.css"), "/home/user/a.css"); + assert.strictEqual( + toPosixPath(String.raw`C:\Users\me\a.css`), + "C:/Users/me/a.css", + ); + // A UNC share and a drive root keep their shape, which is what a path + // walked back to `\\server` or `C:` would no longer name. + assert.strictEqual( + toPosixPath(String.raw`\\server\share\a.css`), + "//server/share/a.css", + ); + assert.strictEqual(toPosixPath("C:\\"), "C:/"); + }); + it("parseFiles should return relative files from context", () => { const [all, packageA, packageB] = parseFiles( ["**/*", "../package-a/src/**/", "../package-b/src/**/"], diff --git a/types/index.d.ts b/types/index.d.ts index f211917..d9bb2c6 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -29,6 +29,14 @@ export type ResolvedCheck = { * the globs of the files not to lint */ exclude: string[]; + /** + * whether a path is one to lint + */ + isWanted: (file: string) => boolean; + /** + * whether a path is left out + */ + isExcluded: (file: string) => boolean; }; declare class DiagnosticsWebpackPlugin { /** diff --git a/types/utils.d.ts b/types/utils.d.ts index 3cbddf1..ea6e284 100644 --- a/types/utils.d.ts +++ b/types/utils.d.ts @@ -79,6 +79,12 @@ export function parseFoldersToGlobs( patterns: string | string[], extensions?: string | string[], ): string[]; +/** + * Globs only know the forward slash, so a path is compared and matched as one. + * @param {string} file a path + * @returns {string} the path with its separators turned into forward slashes + */ +export function toPosixPath(file: string): string; /** * @param {Compiler} compiler compiler * @param {string} name absolute file name