Skip to content

Commit 501abd0

Browse files
feat!: update dependency minimatch to v10 (#20246)
* chore: update dependency minimatch to v10 * add unit tests * update migration guide * v10 → v10.0.0 * update `@eslint/config-array` --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Francesco Trotta <github@fasttime.org>
1 parent ca4d3b4 commit 501abd0

3 files changed

Lines changed: 106 additions & 6 deletions

File tree

docs/src/use/migrate-to-10.0.0.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ The lists below are ordered roughly by the number of users each change is expect
2121
- [Old config format no longer supported](#remove-eslintrc)
2222
- [`eslint-env` comments are reported as errors](#eslint-env-comments)
2323
- [Jiti < v2.2.0 are no longer supported](#drop-old-jiti)
24+
- [POSIX character classes in glob patterns](#posix-character-classes)
2425
- [Deprecated options of the `radix` rule](#radix)
2526
- [`no-shadow-restricted-names` now reports `globalThis` by default](#no-shadow-restricted-names)
2627
- [`func-names` schema is stricter](#func-names)
@@ -36,13 +37,15 @@ The lists below are ordered roughly by the number of users each change is expect
3637
- [New requirements for `ScopeManager` implementations](#scope-manager)
3738
- [Removal of deprecated `context` members](#rule-context)
3839
- [Prohibiting `errors` or `output` of valid RuleTester test cases](#stricter-rule-tester)
40+
- [POSIX character classes in glob patterns](#posix-character-classes)
3941

4042
### Breaking changes for integration developers
4143

4244
- [Node.js < v20.19, v21, v23 are no longer supported](#drop-old-node)
4345
- [New configuration file lookup algorithm](#config-lookup-from-file)
4446
- [Old config format no longer supported](#remove-eslintrc)
4547
- [Removal of `nodeType` property in `LintMessage` objects](#lintmessage-nodetype-removed)
48+
- [POSIX character classes in glob patterns](#posix-character-classes)
4649

4750
---
4851

@@ -120,6 +123,22 @@ ESLint is officially dropping support for versions of `jiti` that are less than
120123

121124
**Related issue(s):** [#19765](https://github.com/eslint/eslint/issues/19765)
122125

126+
## <a name="posix-character-classes"></a> POSIX character classes in glob patterns
127+
128+
ESLint v10.0.0 uses the latest version of [minimatch](https://github.com/isaacs/minimatch), which supports [POSIX character classes](https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html) in bracket expressions. ESLint relies on minimatch to match file names against glob patterns, such as those defined in `files`, `ignores`, and `globalIgnores()` within a config, or passed via the CLI.
129+
130+
For example, to lint all `.js` files whose names begin with an uppercase letter, you can now run:
131+
132+
```shell
133+
npx eslint "**/[[:upper:]]*.js"
134+
```
135+
136+
Here, `[[:upper:]]` is a POSIX character class that matches uppercase letters in different alphabets.
137+
138+
**To address:** If any of the glob patterns in your configuration, CLI arguments, or Node.js API calls look like containing a POSIX character class, verify that they match files as intended.
139+
140+
**Related issue(s):** [eslint/rewrite#66](https://github.com/eslint/rewrite/issues/66)
141+
123142
## <a name="radix"></a> Deprecated options of the `radix` rule
124143

125144
As of ESLint v10.0.0, string options `"always"` and `"as-needed"` of the [`radix`](../rules/radix) rule are deprecated. Setting either of these options doesn't change the behavior of this rule, which now always enforces providing a radix, as it was the case when the `"always"` option (default) was specified. Since the default radix depends on the first argument of `parseInt()`, this rule assumes that the second argument (the radix) is always needed.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@
108108
"dependencies": {
109109
"@eslint-community/eslint-utils": "^4.8.0",
110110
"@eslint-community/regexpp": "^4.12.1",
111-
"@eslint/config-array": "^0.22.0",
111+
"@eslint/config-array": "^0.23.0",
112112
"@eslint/config-helpers": "^0.5.0",
113113
"@eslint/core": "^1.0.0",
114114
"@eslint/plugin-kit": "^0.5.0",
@@ -134,7 +134,7 @@
134134
"imurmurhash": "^0.1.4",
135135
"is-glob": "^4.0.0",
136136
"json-stable-stringify-without-jsonify": "^1.0.1",
137-
"minimatch": "^3.1.2",
137+
"minimatch": "^10.1.1",
138138
"natural-compare": "^1.4.0",
139139
"optionator": "^0.9.3"
140140
},

tests/lib/eslint/eslint.js

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2355,7 +2355,7 @@ describe("ESLint", () => {
23552355
});
23562356

23572357
// https://github.com/eslint/eslint/issues/16038
2358-
it("should allow files patterns with '..' inside", async () => {
2358+
it("should allow file patterns with '..' inside", async () => {
23592359
eslint = new ESLint({
23602360
ignore: false,
23612361
cwd: getFixturePath("dots-in-files"),
@@ -2371,6 +2371,23 @@ describe("ESLint", () => {
23712371
assert.strictEqual(results[0].suppressedMessages.length, 0);
23722372
});
23732373

2374+
it("should allow file patterns with POSIX character classes", async () => {
2375+
eslint = new ESLint({
2376+
cwd: getFixturePath(),
2377+
});
2378+
const results = await eslint.lintFiles([
2379+
"file[[:alnum:]]/[[:punct:]]*.js",
2380+
]);
2381+
2382+
assert.strictEqual(results.length, 1);
2383+
assert.strictEqual(results[0].messages.length, 0);
2384+
assert.strictEqual(
2385+
results[0].filePath,
2386+
getFixturePath("files/.bar.js"),
2387+
);
2388+
assert.strictEqual(results[0].suppressedMessages.length, 0);
2389+
});
2390+
23742391
// https://github.com/eslint/eslint/issues/16299
23752392
it("should only find files in the subdir1 directory when given a directory name", async () => {
23762393
eslint = new ESLint({
@@ -2389,7 +2406,7 @@ describe("ESLint", () => {
23892406
});
23902407

23912408
// https://github.com/eslint/eslint/issues/14742
2392-
it("should run", async () => {
2409+
it("should work when a directory name contains curly braces", async () => {
23932410
eslint = new ESLint({
23942411
cwd: getFixturePath("{curly-path}", "server"),
23952412
});
@@ -5628,7 +5645,7 @@ describe("ESLint", () => {
56285645

56295646
afterEach(() => cleanup());
56305647

5631-
it("should match '[ab].js' if existed.", async () => {
5648+
it("should match '[ab].js' if existing", async () => {
56325649
const teardown = createCustomTeardown({
56335650
cwd: root,
56345651
files: {
@@ -5650,7 +5667,7 @@ describe("ESLint", () => {
56505667
assert.deepStrictEqual(filenames, ["[ab].js"]);
56515668
});
56525669

5653-
it("should match 'a.js' and 'b.js' if '[ab].js' didn't existed.", async () => {
5670+
it("should match 'a.js' and 'b.js' if '[ab].js' doesn't exist", async () => {
56545671
const teardown = createCustomTeardown({
56555672
cwd: root,
56565673
files: {
@@ -5671,6 +5688,70 @@ describe("ESLint", () => {
56715688
});
56725689
});
56735690

5691+
describe("pattern [0[:alpha:]].js", () => {
5692+
if (os.platform() === "win32") {
5693+
return; // skip on Windows - ":" is not valid in Windows filenames
5694+
}
5695+
5696+
const root = getFixturePath("cli-engine/unmatched-glob");
5697+
5698+
let cleanup;
5699+
5700+
beforeEach(() => {
5701+
cleanup = () => {};
5702+
});
5703+
5704+
afterEach(() => cleanup());
5705+
5706+
it("should match '[0[:alpha:]].js' if existing", async () => {
5707+
const teardown = createCustomTeardown({
5708+
cwd: root,
5709+
files: {
5710+
"a.js": "",
5711+
"b.js": "",
5712+
"[0[:alpha:]].js": "",
5713+
},
5714+
});
5715+
5716+
await teardown.prepare();
5717+
cleanup = teardown.cleanup;
5718+
5719+
eslint = new ESLint({
5720+
cwd: teardown.getPath(),
5721+
overrideConfigFile: true,
5722+
});
5723+
const results = await eslint.lintFiles(["[0[:alpha:]].js"]);
5724+
const filenames = results.map(r => path.basename(r.filePath));
5725+
5726+
assert.deepStrictEqual(filenames, ["[0[:alpha:]].js"]);
5727+
});
5728+
5729+
it("should match '0.js', 'a.js' and 'b.js' if '[0[:alpha:]].js' doesn't exist", async () => {
5730+
const teardown = createCustomTeardown({
5731+
cwd: root,
5732+
files: {
5733+
"0.js": "",
5734+
"1.js": "",
5735+
"a.js": "",
5736+
"b.js": "",
5737+
"0a.js": "",
5738+
"[:alpha:].js": "",
5739+
},
5740+
});
5741+
5742+
await teardown.prepare();
5743+
cleanup = teardown.cleanup;
5744+
eslint = new ESLint({
5745+
cwd: teardown.getPath(),
5746+
overrideConfigFile: true,
5747+
});
5748+
const results = await eslint.lintFiles(["[0[:alpha:]].js"]);
5749+
const filenames = results.map(r => path.basename(r.filePath));
5750+
5751+
assert.deepStrictEqual(filenames, ["0.js", "a.js", "b.js"]);
5752+
});
5753+
});
5754+
56745755
describe("with 'noInlineConfig' setting", () => {
56755756
const root = getFixturePath("cli-engine/noInlineConfig");
56765757

0 commit comments

Comments
 (0)