eslint 9.1.1 → 9.3.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/README.md +2 -7
- package/bin/eslint.js +1 -1
- package/lib/cli-engine/cli-engine.js +2 -2
- package/lib/cli-engine/file-enumerator.js +2 -2
- package/lib/cli-engine/lint-result-cache.js +2 -2
- package/lib/cli-engine/load-rules.js +2 -2
- package/lib/cli.js +3 -3
- package/lib/eslint/eslint-helpers.js +2 -2
- package/lib/eslint/eslint.js +5 -5
- package/lib/eslint/legacy-eslint.js +3 -3
- package/lib/linter/code-path-analysis/code-path-analyzer.js +1 -1
- package/lib/linter/code-path-analysis/fork-context.js +1 -1
- package/lib/linter/linter.js +2 -2
- package/lib/linter/report-translator.js +1 -1
- package/lib/rule-tester/rule-tester.js +3 -3
- package/lib/rules/capitalized-comments.js +10 -7
- package/lib/rules/func-style.js +42 -4
- package/lib/rules/line-comment-position.js +3 -0
- package/lib/rules/multiline-comment-style.js +3 -1
- package/lib/rules/no-case-declarations.js +13 -1
- package/lib/rules/no-constant-binary-expression.js +1 -1
- package/lib/rules/no-extra-boolean-cast.js +79 -27
- package/lib/rules/no-misleading-character-class.js +111 -30
- package/lib/rules/no-restricted-exports.js +13 -2
- package/lib/rules/object-shorthand.js +21 -20
- package/lib/shared/runtime-info.js +2 -2
- package/lib/source-code/source-code.js +1 -1
- package/lib/source-code/token-store/index.js +1 -1
- package/messages/config-file-missing.js +16 -0
- package/messages/eslintrc-incompat.js +22 -1
- package/package.json +9 -9
- package/lib/rules/utils/patterns/letters.js +0 -36
package/README.md
CHANGED
@@ -253,11 +253,6 @@ Nitin Kumar
|
|
253
253
|
The people who review and fix bugs and help triage issues.
|
254
254
|
|
255
255
|
<table><tbody><tr><td align="center" valign="top" width="11%">
|
256
|
-
<a href="https://github.com/bmish">
|
257
|
-
<img src="https://github.com/bmish.png?s=75" width="75" height="75" alt="Bryan Mishkin's Avatar"><br />
|
258
|
-
Bryan Mishkin
|
259
|
-
</a>
|
260
|
-
</td><td align="center" valign="top" width="11%">
|
261
256
|
<a href="https://github.com/JoshuaKGoldberg">
|
262
257
|
<img src="https://github.com/JoshuaKGoldberg.png?s=75" width="75" height="75" alt="Josh Goldberg ✨'s Avatar"><br />
|
263
258
|
Josh Goldberg ✨
|
@@ -301,8 +296,8 @@ The following companies, organizations, and individuals support ESLint's ongoing
|
|
301
296
|
<h3>Platinum Sponsors</h3>
|
302
297
|
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="undefined"></a></p><h3>Gold Sponsors</h3>
|
303
298
|
<p><a href="https://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a></p><h3>Silver Sponsors</h3>
|
304
|
-
<p><a href="https://www.jetbrains.com/"><img src="https://images.opencollective.com/jetbrains/
|
305
|
-
<p><a href="https://www.notion.so"><img src="https://images.opencollective.com/notion/bf3b117/logo.png" alt="notion" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://
|
299
|
+
<p><a href="https://www.jetbrains.com/"><img src="https://images.opencollective.com/jetbrains/fe76f99/logo.png" alt="JetBrains" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="64"></a> <a href="https://www.workleap.com"><img src="https://avatars.githubusercontent.com/u/53535748?u=d1e55d7661d724bf2281c1bfd33cb8f99fe2465f&v=4" alt="Workleap" height="64"></a></p><h3>Bronze Sponsors</h3>
|
300
|
+
<p><a href="https://www.notion.so"><img src="https://images.opencollective.com/notion/bf3b117/logo.png" alt="notion" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Ignition" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104?v=4" alt="Nx" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a> <a href="https://usenextbase.com"><img src="https://avatars.githubusercontent.com/u/145838380?v=4" alt="Nextbase Starter Kit" height="32"></a></p>
|
306
301
|
<!--sponsorsend-->
|
307
302
|
|
308
303
|
## Technology Sponsors
|
package/bin/eslint.js
CHANGED
@@ -64,7 +64,7 @@ function readStdin() {
|
|
64
64
|
function getErrorMessage(error) {
|
65
65
|
|
66
66
|
// Lazy loading because this is used only if an error happened.
|
67
|
-
const util = require("util");
|
67
|
+
const util = require("node:util");
|
68
68
|
|
69
69
|
// Foolproof -- third-party module might throw non-object.
|
70
70
|
if (typeof error !== "object" || error === null) {
|
@@ -15,8 +15,8 @@
|
|
15
15
|
// Requirements
|
16
16
|
//------------------------------------------------------------------------------
|
17
17
|
|
18
|
-
const fs = require("fs");
|
19
|
-
const path = require("path");
|
18
|
+
const fs = require("node:fs");
|
19
|
+
const path = require("node:path");
|
20
20
|
const defaultOptions = require("../../conf/default-cli-options");
|
21
21
|
const pkg = require("../../package.json");
|
22
22
|
|
@@ -34,8 +34,8 @@
|
|
34
34
|
// Requirements
|
35
35
|
//------------------------------------------------------------------------------
|
36
36
|
|
37
|
-
const fs = require("fs");
|
38
|
-
const path = require("path");
|
37
|
+
const fs = require("node:fs");
|
38
|
+
const path = require("node:path");
|
39
39
|
const getGlobParent = require("glob-parent");
|
40
40
|
const isGlob = require("is-glob");
|
41
41
|
const escapeRegExp = require("escape-string-regexp");
|
@@ -8,8 +8,8 @@
|
|
8
8
|
// Requirements
|
9
9
|
//-----------------------------------------------------------------------------
|
10
10
|
|
11
|
-
const assert = require("assert");
|
12
|
-
const fs = require("fs");
|
11
|
+
const assert = require("node:assert");
|
12
|
+
const fs = require("node:fs");
|
13
13
|
const fileEntryCache = require("file-entry-cache");
|
14
14
|
const stringify = require("json-stable-stringify-without-jsonify");
|
15
15
|
const pkg = require("../../package.json");
|
@@ -9,8 +9,8 @@
|
|
9
9
|
// Requirements
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
const fs = require("fs"),
|
13
|
-
path = require("path");
|
12
|
+
const fs = require("node:fs"),
|
13
|
+
path = require("node:path");
|
14
14
|
|
15
15
|
const rulesDirCache = {};
|
16
16
|
|
package/lib/cli.js
CHANGED
@@ -15,9 +15,9 @@
|
|
15
15
|
// Requirements
|
16
16
|
//------------------------------------------------------------------------------
|
17
17
|
|
18
|
-
const fs = require("fs"),
|
19
|
-
path = require("path"),
|
20
|
-
{ promisify } = require("util"),
|
18
|
+
const fs = require("node:fs"),
|
19
|
+
path = require("node:path"),
|
20
|
+
{ promisify } = require("node:util"),
|
21
21
|
{ LegacyESLint } = require("./eslint"),
|
22
22
|
{ ESLint, shouldUseFlatConfig, locateConfigFileToUse } = require("./eslint/eslint"),
|
23
23
|
createCLIOptions = require("./options"),
|
@@ -9,8 +9,8 @@
|
|
9
9
|
// Requirements
|
10
10
|
//-----------------------------------------------------------------------------
|
11
11
|
|
12
|
-
const path = require("path");
|
13
|
-
const fs = require("fs");
|
12
|
+
const path = require("node:path");
|
13
|
+
const fs = require("node:fs");
|
14
14
|
const fsp = fs.promises;
|
15
15
|
const isGlob = require("is-glob");
|
16
16
|
const hash = require("../cli-engine/hash");
|
package/lib/eslint/eslint.js
CHANGED
@@ -9,10 +9,9 @@
|
|
9
9
|
// Requirements
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
|
13
|
-
const
|
14
|
-
const
|
15
|
-
const path = require("path");
|
12
|
+
const fs = require("node:fs/promises");
|
13
|
+
const { existsSync } = require("node:fs");
|
14
|
+
const path = require("node:path");
|
16
15
|
const findUp = require("find-up");
|
17
16
|
const { version } = require("../../package.json");
|
18
17
|
const { Linter } = require("../linter");
|
@@ -39,7 +38,7 @@ const {
|
|
39
38
|
|
40
39
|
processOptions
|
41
40
|
} = require("./eslint-helpers");
|
42
|
-
const { pathToFileURL } = require("url");
|
41
|
+
const { pathToFileURL } = require("node:url");
|
43
42
|
const { FlatConfigArray } = require("../config/flat-config-array");
|
44
43
|
const LintResultCache = require("../cli-engine/lint-result-cache");
|
45
44
|
const { Retrier } = require("@humanwhocodes/retry");
|
@@ -348,6 +347,7 @@ async function locateConfigFileToUse({ configFile, cwd }) {
|
|
348
347
|
basePath = path.resolve(path.dirname(configFilePath));
|
349
348
|
} else {
|
350
349
|
error = new Error("Could not find config file.");
|
350
|
+
error.messageTemplate = "config-file-missing";
|
351
351
|
}
|
352
352
|
|
353
353
|
}
|
@@ -10,9 +10,9 @@
|
|
10
10
|
// Requirements
|
11
11
|
//------------------------------------------------------------------------------
|
12
12
|
|
13
|
-
const path = require("path");
|
14
|
-
const fs = require("fs");
|
15
|
-
const { promisify } = require("util");
|
13
|
+
const path = require("node:path");
|
14
|
+
const fs = require("node:fs");
|
15
|
+
const { promisify } = require("node:util");
|
16
16
|
const { CLIEngine, getCLIEngineInternalSlots } = require("../cli-engine/cli-engine");
|
17
17
|
const BuiltinRules = require("../rules");
|
18
18
|
const {
|
@@ -9,7 +9,7 @@
|
|
9
9
|
// Requirements
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
const assert = require("assert"),
|
12
|
+
const assert = require("node:assert"),
|
13
13
|
{ breakableTypePattern } = require("../../shared/ast-utils"),
|
14
14
|
CodePath = require("./code-path"),
|
15
15
|
CodePathSegment = require("./code-path-segment"),
|
@@ -13,7 +13,7 @@
|
|
13
13
|
// Requirements
|
14
14
|
//------------------------------------------------------------------------------
|
15
15
|
|
16
|
-
const assert = require("assert"),
|
16
|
+
const assert = require("node:assert"),
|
17
17
|
CodePathSegment = require("./code-path-segment");
|
18
18
|
|
19
19
|
//------------------------------------------------------------------------------
|
package/lib/linter/linter.js
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
//------------------------------------------------------------------------------
|
12
12
|
|
13
13
|
const
|
14
|
-
path = require("path"),
|
14
|
+
path = require("node:path"),
|
15
15
|
eslintScope = require("eslint-scope"),
|
16
16
|
evk = require("eslint-visitor-keys"),
|
17
17
|
espree = require("espree"),
|
@@ -775,7 +775,7 @@ function createLanguageOptions({ globals: configuredGlobals, parser, parserOptio
|
|
775
775
|
*/
|
776
776
|
function resolveGlobals(providedGlobals, enabledEnvironments) {
|
777
777
|
return Object.assign(
|
778
|
-
|
778
|
+
Object.create(null),
|
779
779
|
...enabledEnvironments.filter(env => env.globals).map(env => env.globals),
|
780
780
|
providedGlobals
|
781
781
|
);
|
@@ -9,7 +9,7 @@
|
|
9
9
|
// Requirements
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
const assert = require("assert");
|
12
|
+
const assert = require("node:assert");
|
13
13
|
const ruleFixer = require("./rule-fixer");
|
14
14
|
const { interpolate } = require("./interpolate");
|
15
15
|
|
@@ -11,9 +11,9 @@
|
|
11
11
|
//------------------------------------------------------------------------------
|
12
12
|
|
13
13
|
const
|
14
|
-
assert = require("assert"),
|
15
|
-
util = require("util"),
|
16
|
-
path = require("path"),
|
14
|
+
assert = require("node:assert"),
|
15
|
+
util = require("node:util"),
|
16
|
+
path = require("node:path"),
|
17
17
|
equal = require("fast-deep-equal"),
|
18
18
|
Traverser = require("../shared/traverser"),
|
19
19
|
{ getRuleOptionsSchema } = require("../config/flat-config-helpers"),
|
@@ -8,7 +8,6 @@
|
|
8
8
|
// Requirements
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
|
-
const LETTER_PATTERN = require("./utils/patterns/letters");
|
12
11
|
const astUtils = require("./utils/ast-utils");
|
13
12
|
|
14
13
|
//------------------------------------------------------------------------------
|
@@ -17,7 +16,8 @@ const astUtils = require("./utils/ast-utils");
|
|
17
16
|
|
18
17
|
const DEFAULT_IGNORE_PATTERN = astUtils.COMMENTS_IGNORE_PATTERN,
|
19
18
|
WHITESPACE = /\s/gu,
|
20
|
-
MAYBE_URL = /^\s*[^:/?#\s]+:\/\/[^?#]/u
|
19
|
+
MAYBE_URL = /^\s*[^:/?#\s]+:\/\/[^?#]/u, // TODO: Combine w/ max-len pattern?
|
20
|
+
LETTER_PATTERN = /\p{L}/u;
|
21
21
|
|
22
22
|
/*
|
23
23
|
* Base schema body for defining the basic capitalization rule, ignorePattern,
|
@@ -233,7 +233,8 @@ module.exports = {
|
|
233
233
|
return true;
|
234
234
|
}
|
235
235
|
|
236
|
-
|
236
|
+
// Get the first Unicode character (1 or 2 code units).
|
237
|
+
const [firstWordChar] = commentWordCharsOnly;
|
237
238
|
|
238
239
|
if (!LETTER_PATTERN.test(firstWordChar)) {
|
239
240
|
return true;
|
@@ -273,12 +274,14 @@ module.exports = {
|
|
273
274
|
messageId,
|
274
275
|
fix(fixer) {
|
275
276
|
const match = comment.value.match(LETTER_PATTERN);
|
277
|
+
const char = match[0];
|
276
278
|
|
277
|
-
|
279
|
+
// Offset match.index by 2 to account for the first 2 characters that start the comment (// or /*)
|
280
|
+
const charIndex = comment.range[0] + match.index + 2;
|
278
281
|
|
279
|
-
|
280
|
-
[
|
281
|
-
capitalize === "always" ?
|
282
|
+
return fixer.replaceTextRange(
|
283
|
+
[charIndex, charIndex + char.length],
|
284
|
+
capitalize === "always" ? char.toLocaleUpperCase() : char.toLocaleLowerCase()
|
282
285
|
);
|
283
286
|
}
|
284
287
|
});
|
package/lib/rules/func-style.js
CHANGED
@@ -29,6 +29,15 @@ module.exports = {
|
|
29
29
|
allowArrowFunctions: {
|
30
30
|
type: "boolean",
|
31
31
|
default: false
|
32
|
+
},
|
33
|
+
overrides: {
|
34
|
+
type: "object",
|
35
|
+
properties: {
|
36
|
+
namedExports: {
|
37
|
+
enum: ["declaration", "expression", "ignore"]
|
38
|
+
}
|
39
|
+
},
|
40
|
+
additionalProperties: false
|
32
41
|
}
|
33
42
|
},
|
34
43
|
additionalProperties: false
|
@@ -46,13 +55,22 @@ module.exports = {
|
|
46
55
|
const style = context.options[0],
|
47
56
|
allowArrowFunctions = context.options[1] && context.options[1].allowArrowFunctions,
|
48
57
|
enforceDeclarations = (style === "declaration"),
|
58
|
+
exportFunctionStyle = context.options[1] && context.options[1].overrides && context.options[1].overrides.namedExports,
|
49
59
|
stack = [];
|
50
60
|
|
51
61
|
const nodesToCheck = {
|
52
62
|
FunctionDeclaration(node) {
|
53
63
|
stack.push(false);
|
54
64
|
|
55
|
-
if (
|
65
|
+
if (
|
66
|
+
!enforceDeclarations &&
|
67
|
+
node.parent.type !== "ExportDefaultDeclaration" &&
|
68
|
+
(typeof exportFunctionStyle === "undefined" || node.parent.type !== "ExportNamedDeclaration")
|
69
|
+
) {
|
70
|
+
context.report({ node, messageId: "expression" });
|
71
|
+
}
|
72
|
+
|
73
|
+
if (node.parent.type === "ExportNamedDeclaration" && exportFunctionStyle === "expression") {
|
56
74
|
context.report({ node, messageId: "expression" });
|
57
75
|
}
|
58
76
|
},
|
@@ -63,7 +81,18 @@ module.exports = {
|
|
63
81
|
FunctionExpression(node) {
|
64
82
|
stack.push(false);
|
65
83
|
|
66
|
-
if (
|
84
|
+
if (
|
85
|
+
enforceDeclarations &&
|
86
|
+
node.parent.type === "VariableDeclarator" &&
|
87
|
+
(typeof exportFunctionStyle === "undefined" || node.parent.parent.parent.type !== "ExportNamedDeclaration")
|
88
|
+
) {
|
89
|
+
context.report({ node: node.parent, messageId: "declaration" });
|
90
|
+
}
|
91
|
+
|
92
|
+
if (
|
93
|
+
node.parent.type === "VariableDeclarator" && node.parent.parent.parent.type === "ExportNamedDeclaration" &&
|
94
|
+
exportFunctionStyle === "declaration"
|
95
|
+
) {
|
67
96
|
context.report({ node: node.parent, messageId: "declaration" });
|
68
97
|
}
|
69
98
|
},
|
@@ -86,8 +115,17 @@ module.exports = {
|
|
86
115
|
nodesToCheck["ArrowFunctionExpression:exit"] = function(node) {
|
87
116
|
const hasThisExpr = stack.pop();
|
88
117
|
|
89
|
-
if (
|
90
|
-
|
118
|
+
if (!hasThisExpr && node.parent.type === "VariableDeclarator") {
|
119
|
+
if (
|
120
|
+
enforceDeclarations &&
|
121
|
+
(typeof exportFunctionStyle === "undefined" || node.parent.parent.parent.type !== "ExportNamedDeclaration")
|
122
|
+
) {
|
123
|
+
context.report({ node: node.parent, messageId: "declaration" });
|
124
|
+
}
|
125
|
+
|
126
|
+
if (node.parent.parent.parent.type === "ExportNamedDeclaration" && exportFunctionStyle === "declaration") {
|
127
|
+
context.report({ node: node.parent, messageId: "declaration" });
|
128
|
+
}
|
91
129
|
}
|
92
130
|
};
|
93
131
|
}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* @fileoverview Rule to enforce the position of line comments
|
3
3
|
* @author Alberto Rodríguez
|
4
|
+
* @deprecated in ESLint v9.3.0
|
4
5
|
*/
|
5
6
|
"use strict";
|
6
7
|
|
@@ -13,6 +14,8 @@ const astUtils = require("./utils/ast-utils");
|
|
13
14
|
/** @type {import('../shared/types').Rule} */
|
14
15
|
module.exports = {
|
15
16
|
meta: {
|
17
|
+
deprecated: true,
|
18
|
+
replacedBy: [],
|
16
19
|
type: "layout",
|
17
20
|
|
18
21
|
docs: {
|
@@ -1,6 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* @fileoverview enforce a particular style for multiline comments
|
3
3
|
* @author Teddy Katz
|
4
|
+
* @deprecated in ESLint v9.3.0
|
4
5
|
*/
|
5
6
|
"use strict";
|
6
7
|
|
@@ -13,8 +14,9 @@ const astUtils = require("./utils/ast-utils");
|
|
13
14
|
/** @type {import('../shared/types').Rule} */
|
14
15
|
module.exports = {
|
15
16
|
meta: {
|
17
|
+
deprecated: true,
|
18
|
+
replacedBy: [],
|
16
19
|
type: "suggestion",
|
17
|
-
|
18
20
|
docs: {
|
19
21
|
description: "Enforce a particular style for multiline comments",
|
20
22
|
recommended: false,
|
@@ -19,9 +19,12 @@ module.exports = {
|
|
19
19
|
url: "https://eslint.org/docs/latest/rules/no-case-declarations"
|
20
20
|
},
|
21
21
|
|
22
|
+
hasSuggestions: true,
|
23
|
+
|
22
24
|
schema: [],
|
23
25
|
|
24
26
|
messages: {
|
27
|
+
addBrackets: "Add {} brackets around the case block.",
|
25
28
|
unexpected: "Unexpected lexical declaration in case block."
|
26
29
|
}
|
27
30
|
},
|
@@ -53,7 +56,16 @@ module.exports = {
|
|
53
56
|
if (isLexicalDeclaration(statement)) {
|
54
57
|
context.report({
|
55
58
|
node: statement,
|
56
|
-
messageId: "unexpected"
|
59
|
+
messageId: "unexpected",
|
60
|
+
suggest: [
|
61
|
+
{
|
62
|
+
messageId: "addBrackets",
|
63
|
+
fix: fixer => [
|
64
|
+
fixer.insertTextBefore(node.consequent[0], "{ "),
|
65
|
+
fixer.insertTextAfter(node.consequent.at(-1), " }")
|
66
|
+
]
|
67
|
+
}
|
68
|
+
]
|
57
69
|
});
|
58
70
|
}
|
59
71
|
}
|
@@ -148,7 +148,7 @@ function isStaticBoolean(scope, node) {
|
|
148
148
|
* truthiness.
|
149
149
|
* https://262.ecma-international.org/5.1/#sec-11.9.3
|
150
150
|
*
|
151
|
-
*
|
151
|
+
* JavaScript `==` operator works by converting the boolean to `1` (true) or
|
152
152
|
* `+0` (false) and then checks the values `==` equality to that number.
|
153
153
|
* @param {Scope} scope The scope in which node was found.
|
154
154
|
* @param {ASTNode} node The node to test.
|
@@ -30,14 +30,28 @@ module.exports = {
|
|
30
30
|
},
|
31
31
|
|
32
32
|
schema: [{
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
anyOf: [
|
34
|
+
{
|
35
|
+
type: "object",
|
36
|
+
properties: {
|
37
|
+
enforceForInnerExpressions: {
|
38
|
+
type: "boolean"
|
39
|
+
}
|
40
|
+
},
|
41
|
+
additionalProperties: false
|
42
|
+
},
|
43
|
+
|
44
|
+
// deprecated
|
45
|
+
{
|
46
|
+
type: "object",
|
47
|
+
properties: {
|
48
|
+
enforceForLogicalOperands: {
|
49
|
+
type: "boolean"
|
50
|
+
}
|
51
|
+
},
|
52
|
+
additionalProperties: false
|
38
53
|
}
|
39
|
-
|
40
|
-
additionalProperties: false
|
54
|
+
]
|
41
55
|
}],
|
42
56
|
fixable: "code",
|
43
57
|
|
@@ -49,6 +63,9 @@ module.exports = {
|
|
49
63
|
|
50
64
|
create(context) {
|
51
65
|
const sourceCode = context.sourceCode;
|
66
|
+
const enforceForLogicalOperands = context.options[0]?.enforceForLogicalOperands === true;
|
67
|
+
const enforceForInnerExpressions = context.options[0]?.enforceForInnerExpressions === true;
|
68
|
+
|
52
69
|
|
53
70
|
// Node types which have a test which will coerce values to booleans.
|
54
71
|
const BOOLEAN_NODE_TYPES = new Set([
|
@@ -72,19 +89,6 @@ module.exports = {
|
|
72
89
|
node.callee.name === "Boolean";
|
73
90
|
}
|
74
91
|
|
75
|
-
/**
|
76
|
-
* Checks whether the node is a logical expression and that the option is enabled
|
77
|
-
* @param {ASTNode} node the node
|
78
|
-
* @returns {boolean} if the node is a logical expression and option is enabled
|
79
|
-
*/
|
80
|
-
function isLogicalContext(node) {
|
81
|
-
return node.type === "LogicalExpression" &&
|
82
|
-
(node.operator === "||" || node.operator === "&&") &&
|
83
|
-
(context.options.length && context.options[0].enforceForLogicalOperands === true);
|
84
|
-
|
85
|
-
}
|
86
|
-
|
87
|
-
|
88
92
|
/**
|
89
93
|
* Check if a node is in a context where its value would be coerced to a boolean at runtime.
|
90
94
|
* @param {ASTNode} node The node
|
@@ -115,12 +119,51 @@ module.exports = {
|
|
115
119
|
return isInFlaggedContext(node.parent);
|
116
120
|
}
|
117
121
|
|
118
|
-
|
119
|
-
|
122
|
+
/*
|
123
|
+
* legacy behavior - enforceForLogicalOperands will only recurse on
|
124
|
+
* logical expressions, not on other contexts.
|
125
|
+
* enforceForInnerExpressions will recurse on logical expressions
|
126
|
+
* as well as the other recursive syntaxes.
|
127
|
+
*/
|
128
|
+
|
129
|
+
if (enforceForLogicalOperands || enforceForInnerExpressions) {
|
130
|
+
if (node.parent.type === "LogicalExpression") {
|
131
|
+
if (node.parent.operator === "||" || node.parent.operator === "&&") {
|
132
|
+
return isInFlaggedContext(node.parent);
|
133
|
+
}
|
120
134
|
|
121
|
-
|
122
|
-
|
123
|
-
|
135
|
+
// Check the right hand side of a `??` operator.
|
136
|
+
if (enforceForInnerExpressions &&
|
137
|
+
node.parent.operator === "??" &&
|
138
|
+
node.parent.right === node
|
139
|
+
) {
|
140
|
+
return isInFlaggedContext(node.parent);
|
141
|
+
}
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
if (enforceForInnerExpressions) {
|
146
|
+
if (
|
147
|
+
node.parent.type === "ConditionalExpression" &&
|
148
|
+
(node.parent.consequent === node || node.parent.alternate === node)
|
149
|
+
) {
|
150
|
+
return isInFlaggedContext(node.parent);
|
151
|
+
}
|
152
|
+
|
153
|
+
/*
|
154
|
+
* Check last expression only in a sequence, i.e. if ((1, 2, Boolean(3))) {}, since
|
155
|
+
* the others don't affect the result of the expression.
|
156
|
+
*/
|
157
|
+
if (
|
158
|
+
node.parent.type === "SequenceExpression" &&
|
159
|
+
node.parent.expressions.at(-1) === node
|
160
|
+
) {
|
161
|
+
return isInFlaggedContext(node.parent);
|
162
|
+
}
|
163
|
+
|
164
|
+
}
|
165
|
+
|
166
|
+
return isInBooleanContext(node);
|
124
167
|
}
|
125
168
|
|
126
169
|
|
@@ -147,7 +190,6 @@ module.exports = {
|
|
147
190
|
* Determines whether the given node needs to be parenthesized when replacing the previous node.
|
148
191
|
* It assumes that `previousNode` is the node to be reported by this rule, so it has a limited list
|
149
192
|
* of possible parent node types. By the same assumption, the node's role in a particular parent is already known.
|
150
|
-
* For example, if the parent is `ConditionalExpression`, `previousNode` must be its `test` child.
|
151
193
|
* @param {ASTNode} previousNode Previous node.
|
152
194
|
* @param {ASTNode} node The node to check.
|
153
195
|
* @throws {Error} (Unreachable.)
|
@@ -157,6 +199,7 @@ module.exports = {
|
|
157
199
|
if (previousNode.parent.type === "ChainExpression") {
|
158
200
|
return needsParens(previousNode.parent, node);
|
159
201
|
}
|
202
|
+
|
160
203
|
if (isParenthesized(previousNode)) {
|
161
204
|
|
162
205
|
// parentheses around the previous node will stay, so there is no need for an additional pair
|
@@ -174,9 +217,18 @@ module.exports = {
|
|
174
217
|
case "DoWhileStatement":
|
175
218
|
case "WhileStatement":
|
176
219
|
case "ForStatement":
|
220
|
+
case "SequenceExpression":
|
177
221
|
return false;
|
178
222
|
case "ConditionalExpression":
|
179
|
-
|
223
|
+
if (previousNode === parent.test) {
|
224
|
+
return precedence(node) <= precedence(parent);
|
225
|
+
}
|
226
|
+
if (previousNode === parent.consequent || previousNode === parent.alternate) {
|
227
|
+
return precedence(node) < precedence({ type: "AssignmentExpression" });
|
228
|
+
}
|
229
|
+
|
230
|
+
/* c8 ignore next */
|
231
|
+
throw new Error("Ternary child must be test, consequent, or alternate.");
|
180
232
|
case "UnaryExpression":
|
181
233
|
return precedence(node) < precedence(parent);
|
182
234
|
case "LogicalExpression":
|
@@ -85,12 +85,10 @@ function isUnicodeCodePointEscape(char) {
|
|
85
85
|
const findCharacterSequences = {
|
86
86
|
*surrogatePairWithoutUFlag(chars) {
|
87
87
|
for (const [index, char] of chars.entries()) {
|
88
|
-
if (index === 0) {
|
89
|
-
continue;
|
90
|
-
}
|
91
88
|
const previous = chars[index - 1];
|
92
89
|
|
93
90
|
if (
|
91
|
+
previous && char &&
|
94
92
|
isSurrogatePair(previous.value, char.value) &&
|
95
93
|
!isUnicodeCodePointEscape(previous) &&
|
96
94
|
!isUnicodeCodePointEscape(char)
|
@@ -102,12 +100,10 @@ const findCharacterSequences = {
|
|
102
100
|
|
103
101
|
*surrogatePair(chars) {
|
104
102
|
for (const [index, char] of chars.entries()) {
|
105
|
-
if (index === 0) {
|
106
|
-
continue;
|
107
|
-
}
|
108
103
|
const previous = chars[index - 1];
|
109
104
|
|
110
105
|
if (
|
106
|
+
previous && char &&
|
111
107
|
isSurrogatePair(previous.value, char.value) &&
|
112
108
|
(
|
113
109
|
isUnicodeCodePointEscape(previous) ||
|
@@ -119,14 +115,17 @@ const findCharacterSequences = {
|
|
119
115
|
}
|
120
116
|
},
|
121
117
|
|
122
|
-
*combiningClass(chars) {
|
118
|
+
*combiningClass(chars, unfilteredChars) {
|
119
|
+
|
120
|
+
/*
|
121
|
+
* When `allowEscape` is `true`, a combined character should only be allowed if the combining mark appears as an escape sequence.
|
122
|
+
* This means that the base character should be considered even if it's escaped.
|
123
|
+
*/
|
123
124
|
for (const [index, char] of chars.entries()) {
|
124
|
-
|
125
|
-
continue;
|
126
|
-
}
|
127
|
-
const previous = chars[index - 1];
|
125
|
+
const previous = unfilteredChars[index - 1];
|
128
126
|
|
129
127
|
if (
|
128
|
+
previous && char &&
|
130
129
|
isCombiningCharacter(char.value) &&
|
131
130
|
!isCombiningCharacter(previous.value)
|
132
131
|
) {
|
@@ -137,12 +136,10 @@ const findCharacterSequences = {
|
|
137
136
|
|
138
137
|
*emojiModifier(chars) {
|
139
138
|
for (const [index, char] of chars.entries()) {
|
140
|
-
if (index === 0) {
|
141
|
-
continue;
|
142
|
-
}
|
143
139
|
const previous = chars[index - 1];
|
144
140
|
|
145
141
|
if (
|
142
|
+
previous && char &&
|
146
143
|
isEmojiModifier(char.value) &&
|
147
144
|
!isEmojiModifier(previous.value)
|
148
145
|
) {
|
@@ -153,12 +150,10 @@ const findCharacterSequences = {
|
|
153
150
|
|
154
151
|
*regionalIndicatorSymbol(chars) {
|
155
152
|
for (const [index, char] of chars.entries()) {
|
156
|
-
if (index === 0) {
|
157
|
-
continue;
|
158
|
-
}
|
159
153
|
const previous = chars[index - 1];
|
160
154
|
|
161
155
|
if (
|
156
|
+
previous && char &&
|
162
157
|
isRegionalIndicatorSymbol(char.value) &&
|
163
158
|
isRegionalIndicatorSymbol(previous.value)
|
164
159
|
) {
|
@@ -171,17 +166,18 @@ const findCharacterSequences = {
|
|
171
166
|
let sequence = null;
|
172
167
|
|
173
168
|
for (const [index, char] of chars.entries()) {
|
174
|
-
|
175
|
-
|
176
|
-
|
169
|
+
const previous = chars[index - 1];
|
170
|
+
const next = chars[index + 1];
|
171
|
+
|
177
172
|
if (
|
173
|
+
previous && char && next &&
|
178
174
|
char.value === 0x200d &&
|
179
|
-
|
180
|
-
|
175
|
+
previous.value !== 0x200d &&
|
176
|
+
next.value !== 0x200d
|
181
177
|
) {
|
182
178
|
if (sequence) {
|
183
|
-
if (sequence.at(-1) ===
|
184
|
-
sequence.push(char,
|
179
|
+
if (sequence.at(-1) === previous) {
|
180
|
+
sequence.push(char, next); // append to the sequence
|
185
181
|
} else {
|
186
182
|
yield sequence;
|
187
183
|
sequence = chars.slice(index - 1, index + 2);
|
@@ -227,6 +223,41 @@ function getStaticValueOrRegex(node, initialScope) {
|
|
227
223
|
return staticValue;
|
228
224
|
}
|
229
225
|
|
226
|
+
/**
|
227
|
+
* Checks whether a specified regexpp character is represented as an acceptable escape sequence.
|
228
|
+
* This function requires the source text of the character to be known.
|
229
|
+
* @param {Character} char Character to check.
|
230
|
+
* @param {string} charSource Source text of the character to check.
|
231
|
+
* @returns {boolean} Whether the specified regexpp character is represented as an acceptable escape sequence.
|
232
|
+
*/
|
233
|
+
function checkForAcceptableEscape(char, charSource) {
|
234
|
+
if (!charSource.startsWith("\\")) {
|
235
|
+
return false;
|
236
|
+
}
|
237
|
+
const match = /(?<=^\\+).$/su.exec(charSource);
|
238
|
+
|
239
|
+
return match?.[0] !== String.fromCodePoint(char.value);
|
240
|
+
}
|
241
|
+
|
242
|
+
/**
|
243
|
+
* Checks whether a specified regexpp character is represented as an acceptable escape sequence.
|
244
|
+
* This function works with characters that are produced by a string or template literal.
|
245
|
+
* It requires the source text and the CodeUnit list of the literal to be known.
|
246
|
+
* @param {Character} char Character to check.
|
247
|
+
* @param {string} nodeSource Source text of the string or template literal that produces the character.
|
248
|
+
* @param {CodeUnit[]} codeUnits List of CodeUnit objects of the literal that produces the character.
|
249
|
+
* @returns {boolean} Whether the specified regexpp character is represented as an acceptable escape sequence.
|
250
|
+
*/
|
251
|
+
function checkForAcceptableEscapeInString(char, nodeSource, codeUnits) {
|
252
|
+
const firstIndex = char.start;
|
253
|
+
const lastIndex = char.end - 1;
|
254
|
+
const start = codeUnits[firstIndex].start;
|
255
|
+
const end = codeUnits[lastIndex].end;
|
256
|
+
const charSource = nodeSource.slice(start, end);
|
257
|
+
|
258
|
+
return checkForAcceptableEscape(char, charSource);
|
259
|
+
}
|
260
|
+
|
230
261
|
//------------------------------------------------------------------------------
|
231
262
|
// Rule Definition
|
232
263
|
//------------------------------------------------------------------------------
|
@@ -244,7 +275,18 @@ module.exports = {
|
|
244
275
|
|
245
276
|
hasSuggestions: true,
|
246
277
|
|
247
|
-
schema: [
|
278
|
+
schema: [
|
279
|
+
{
|
280
|
+
type: "object",
|
281
|
+
properties: {
|
282
|
+
allowEscape: {
|
283
|
+
type: "boolean",
|
284
|
+
default: false
|
285
|
+
}
|
286
|
+
},
|
287
|
+
additionalProperties: false
|
288
|
+
}
|
289
|
+
],
|
248
290
|
|
249
291
|
messages: {
|
250
292
|
surrogatePairWithoutUFlag: "Unexpected surrogate pair in character class. Use 'u' flag.",
|
@@ -257,6 +299,7 @@ module.exports = {
|
|
257
299
|
}
|
258
300
|
},
|
259
301
|
create(context) {
|
302
|
+
const allowEscape = context.options[0]?.allowEscape;
|
260
303
|
const sourceCode = context.sourceCode;
|
261
304
|
const parser = new RegExpParser();
|
262
305
|
const checkedPatternNodes = new Set();
|
@@ -288,24 +331,62 @@ module.exports = {
|
|
288
331
|
return;
|
289
332
|
}
|
290
333
|
|
334
|
+
let codeUnits = null;
|
335
|
+
|
336
|
+
/**
|
337
|
+
* Checks whether a specified regexpp character is represented as an acceptable escape sequence.
|
338
|
+
* For the purposes of this rule, an escape sequence is considered acceptable if it consists of one or more backslashes followed by the character being escaped.
|
339
|
+
* @param {Character} char Character to check.
|
340
|
+
* @returns {boolean} Whether the specified regexpp character is represented as an acceptable escape sequence.
|
341
|
+
*/
|
342
|
+
function isAcceptableEscapeSequence(char) {
|
343
|
+
if (node.type === "Literal" && node.regex) {
|
344
|
+
return checkForAcceptableEscape(char, char.raw);
|
345
|
+
}
|
346
|
+
if (node.type === "Literal" && typeof node.value === "string") {
|
347
|
+
const nodeSource = node.raw;
|
348
|
+
|
349
|
+
codeUnits ??= parseStringLiteral(nodeSource);
|
350
|
+
|
351
|
+
return checkForAcceptableEscapeInString(char, nodeSource, codeUnits);
|
352
|
+
}
|
353
|
+
if (astUtils.isStaticTemplateLiteral(node)) {
|
354
|
+
const nodeSource = sourceCode.getText(node);
|
355
|
+
|
356
|
+
codeUnits ??= parseTemplateToken(nodeSource);
|
357
|
+
|
358
|
+
return checkForAcceptableEscapeInString(char, nodeSource, codeUnits);
|
359
|
+
}
|
360
|
+
return false;
|
361
|
+
}
|
362
|
+
|
291
363
|
const foundKindMatches = new Map();
|
292
364
|
|
293
365
|
visitRegExpAST(patternNode, {
|
294
366
|
onCharacterClassEnter(ccNode) {
|
295
|
-
for (const
|
367
|
+
for (const unfilteredChars of iterateCharacterSequence(ccNode.elements)) {
|
368
|
+
let chars;
|
369
|
+
|
370
|
+
if (allowEscape) {
|
371
|
+
|
372
|
+
// Replace escape sequences with null to avoid having them flagged.
|
373
|
+
chars = unfilteredChars.map(char => (isAcceptableEscapeSequence(char) ? null : char));
|
374
|
+
} else {
|
375
|
+
chars = unfilteredChars;
|
376
|
+
}
|
296
377
|
for (const kind of kinds) {
|
378
|
+
const matches = findCharacterSequences[kind](chars, unfilteredChars);
|
379
|
+
|
297
380
|
if (foundKindMatches.has(kind)) {
|
298
|
-
foundKindMatches.get(kind).push(...
|
381
|
+
foundKindMatches.get(kind).push(...matches);
|
299
382
|
} else {
|
300
|
-
foundKindMatches.set(kind, [...
|
383
|
+
foundKindMatches.set(kind, [...matches]);
|
301
384
|
}
|
302
385
|
}
|
303
386
|
}
|
304
387
|
}
|
305
388
|
});
|
306
389
|
|
307
|
-
let codeUnits = null;
|
308
|
-
|
309
390
|
/**
|
310
391
|
* Finds the report loc(s) for a range of matches.
|
311
392
|
* Only literals and expression-less templates generate granular errors.
|
@@ -37,7 +37,8 @@ module.exports = {
|
|
37
37
|
type: "string"
|
38
38
|
},
|
39
39
|
uniqueItems: true
|
40
|
-
}
|
40
|
+
},
|
41
|
+
restrictedNamedExportsPattern: { type: "string" }
|
41
42
|
},
|
42
43
|
additionalProperties: false
|
43
44
|
},
|
@@ -52,6 +53,7 @@ module.exports = {
|
|
52
53
|
},
|
53
54
|
uniqueItems: true
|
54
55
|
},
|
56
|
+
restrictedNamedExportsPattern: { type: "string" },
|
55
57
|
restrictDefaultExports: {
|
56
58
|
type: "object",
|
57
59
|
properties: {
|
@@ -98,6 +100,7 @@ module.exports = {
|
|
98
100
|
create(context) {
|
99
101
|
|
100
102
|
const restrictedNames = new Set(context.options[0] && context.options[0].restrictedNamedExports);
|
103
|
+
const restrictedNamePattern = context.options[0] && context.options[0].restrictedNamedExportsPattern;
|
101
104
|
const restrictDefaultExports = context.options[0] && context.options[0].restrictDefaultExports;
|
102
105
|
const sourceCode = context.sourceCode;
|
103
106
|
|
@@ -109,7 +112,15 @@ module.exports = {
|
|
109
112
|
function checkExportedName(node) {
|
110
113
|
const name = astUtils.getModuleExportName(node);
|
111
114
|
|
112
|
-
|
115
|
+
let matchesRestrictedNamePattern = false;
|
116
|
+
|
117
|
+
if (restrictedNamePattern && name !== "default") {
|
118
|
+
const patternRegex = new RegExp(restrictedNamePattern, "u");
|
119
|
+
|
120
|
+
matchesRestrictedNamePattern = patternRegex.test(name);
|
121
|
+
}
|
122
|
+
|
123
|
+
if (matchesRestrictedNamePattern || restrictedNames.has(name)) {
|
113
124
|
context.report({
|
114
125
|
node,
|
115
126
|
messageId: "restrictedNamed",
|
@@ -284,35 +284,22 @@ module.exports = {
|
|
284
284
|
const arrowToken = sourceCode.getTokenBefore(node.value.body, astUtils.isArrowToken);
|
285
285
|
const fnBody = sourceCode.text.slice(arrowToken.range[1], node.value.range[1]);
|
286
286
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
tokenBeforeParams = sourceCode.getFirstToken(node.value, astUtils.isOpeningParenToken);
|
292
|
-
} else {
|
293
|
-
tokenBeforeParams = sourceCode.getTokenBefore(node.value.params[0]);
|
294
|
-
}
|
295
|
-
|
296
|
-
if (node.value.params.length === 1) {
|
297
|
-
const hasParen = astUtils.isOpeningParenToken(tokenBeforeParams);
|
298
|
-
const isTokenOutsideNode = tokenBeforeParams.range[0] < node.range[0];
|
299
|
-
|
300
|
-
shouldAddParensAroundParameters = !hasParen || isTokenOutsideNode;
|
301
|
-
}
|
287
|
+
// First token should not be `async`
|
288
|
+
const firstValueToken = sourceCode.getFirstToken(node.value, {
|
289
|
+
skip: node.value.async ? 1 : 0
|
290
|
+
});
|
302
291
|
|
303
|
-
const sliceStart =
|
304
|
-
? node.value.params[0].range[0]
|
305
|
-
: tokenBeforeParams.range[0];
|
292
|
+
const sliceStart = firstValueToken.range[0];
|
306
293
|
const sliceEnd = sourceCode.getTokenBefore(arrowToken).range[1];
|
294
|
+
const shouldAddParens = node.value.params.length === 1 && node.value.params[0].range[0] === sliceStart;
|
307
295
|
|
308
296
|
const oldParamText = sourceCode.text.slice(sliceStart, sliceEnd);
|
309
|
-
const newParamText =
|
297
|
+
const newParamText = shouldAddParens ? `(${oldParamText})` : oldParamText;
|
310
298
|
|
311
299
|
return fixer.replaceTextRange(
|
312
300
|
fixRange,
|
313
301
|
methodPrefix + newParamText + fnBody
|
314
302
|
);
|
315
|
-
|
316
303
|
}
|
317
304
|
|
318
305
|
/**
|
@@ -497,6 +484,13 @@ module.exports = {
|
|
497
484
|
node,
|
498
485
|
messageId: "expectedPropertyShorthand",
|
499
486
|
fix(fixer) {
|
487
|
+
|
488
|
+
// x: /* */ x
|
489
|
+
// x: (/* */ x)
|
490
|
+
if (sourceCode.getCommentsInside(node).length > 0) {
|
491
|
+
return null;
|
492
|
+
}
|
493
|
+
|
500
494
|
return fixer.replaceText(node, node.value.name);
|
501
495
|
}
|
502
496
|
});
|
@@ -510,6 +504,13 @@ module.exports = {
|
|
510
504
|
node,
|
511
505
|
messageId: "expectedPropertyShorthand",
|
512
506
|
fix(fixer) {
|
507
|
+
|
508
|
+
// "x": /* */ x
|
509
|
+
// "x": (/* */ x)
|
510
|
+
if (sourceCode.getCommentsInside(node).length > 0) {
|
511
|
+
return null;
|
512
|
+
}
|
513
|
+
|
513
514
|
return fixer.replaceText(node, node.value.name);
|
514
515
|
}
|
515
516
|
});
|
@@ -9,9 +9,9 @@
|
|
9
9
|
// Requirements
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
const path = require("path");
|
12
|
+
const path = require("node:path");
|
13
13
|
const spawn = require("cross-spawn");
|
14
|
-
const os = require("os");
|
14
|
+
const os = require("node:os");
|
15
15
|
const log = require("../shared/logging");
|
16
16
|
const packageJson = require("../../package.json");
|
17
17
|
|
@@ -1063,7 +1063,7 @@ class SourceCode extends TokenStore {
|
|
1063
1063
|
* https://github.com/eslint/eslint/issues/16302
|
1064
1064
|
*/
|
1065
1065
|
const configGlobals = Object.assign(
|
1066
|
-
|
1066
|
+
Object.create(null), // https://github.com/eslint/eslint/issues/18363
|
1067
1067
|
getGlobalsForEcmaVersion(languageOptions.ecmaVersion),
|
1068
1068
|
languageOptions.sourceType === "commonjs" ? globals.commonjs : void 0,
|
1069
1069
|
languageOptions.globals
|
@@ -8,7 +8,7 @@
|
|
8
8
|
// Requirements
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
|
-
const assert = require("assert");
|
11
|
+
const assert = require("node:assert");
|
12
12
|
const { isCommentToken } = require("@eslint-community/eslint-utils");
|
13
13
|
const cursors = require("./cursors");
|
14
14
|
const ForwardTokenCursor = require("./forward-token-cursor");
|
@@ -0,0 +1,16 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
module.exports = function() {
|
4
|
+
return `
|
5
|
+
ESLint couldn't find an eslint.config.(js|mjs|cjs) file.
|
6
|
+
|
7
|
+
From ESLint v9.0.0, the default configuration file is now eslint.config.js.
|
8
|
+
If you are using a .eslintrc.* file, please follow the migration guide
|
9
|
+
to update your configuration file to the new format:
|
10
|
+
|
11
|
+
https://eslint.org/docs/latest/use/configure/migration-guide
|
12
|
+
|
13
|
+
If you still have problems after following the migration guide, please stop by
|
14
|
+
https://eslint.org/chat/help to chat with the team.
|
15
|
+
`.trimStart();
|
16
|
+
};
|
@@ -11,6 +11,9 @@ Flat config uses "languageOptions.globals" to define global variables for your f
|
|
11
11
|
|
12
12
|
Please see the following page for information on how to convert your config object into the correct format:
|
13
13
|
https://eslint.org/docs/latest/use/configure/migration-guide#configuring-language-options
|
14
|
+
|
15
|
+
If you're not using "env" directly (it may be coming from a plugin), please see the following:
|
16
|
+
https://eslint.org/docs/latest/use/configure/migration-guide#using-eslintrc-configs-in-flat-config
|
14
17
|
`,
|
15
18
|
|
16
19
|
extends: `
|
@@ -18,8 +21,11 @@ A config object is using the "extends" key, which is not supported in flat confi
|
|
18
21
|
|
19
22
|
Instead of "extends", you can include config objects that you'd like to extend from directly in the flat config array.
|
20
23
|
|
21
|
-
|
24
|
+
If you're using "extends" in your config file, please see the following:
|
22
25
|
https://eslint.org/docs/latest/use/configure/migration-guide#predefined-and-shareable-configs
|
26
|
+
|
27
|
+
If you're not using "extends" directly (it may be coming from a plugin), please see the following:
|
28
|
+
https://eslint.org/docs/latest/use/configure/migration-guide#using-eslintrc-configs-in-flat-config
|
23
29
|
`,
|
24
30
|
|
25
31
|
globals: `
|
@@ -29,6 +35,9 @@ Flat config uses "languageOptions.globals" to define global variables for your f
|
|
29
35
|
|
30
36
|
Please see the following page for information on how to convert your config object into the correct format:
|
31
37
|
https://eslint.org/docs/latest/use/configure/migration-guide#configuring-language-options
|
38
|
+
|
39
|
+
If you're not using "globals" directly (it may be coming from a plugin), please see the following:
|
40
|
+
https://eslint.org/docs/latest/use/configure/migration-guide#using-eslintrc-configs-in-flat-config
|
32
41
|
`,
|
33
42
|
|
34
43
|
ignorePatterns: `
|
@@ -38,6 +47,9 @@ Flat config uses "ignores" to specify files to ignore.
|
|
38
47
|
|
39
48
|
Please see the following page for information on how to convert your config object into the correct format:
|
40
49
|
https://eslint.org/docs/latest/use/configure/migration-guide#ignoring-files
|
50
|
+
|
51
|
+
If you're not using "ignorePatterns" directly (it may be coming from a plugin), please see the following:
|
52
|
+
https://eslint.org/docs/latest/use/configure/migration-guide#using-eslintrc-configs-in-flat-config
|
41
53
|
`,
|
42
54
|
|
43
55
|
noInlineConfig: `
|
@@ -56,6 +68,9 @@ Flat config is an array that acts like the eslintrc "overrides" array.
|
|
56
68
|
|
57
69
|
Please see the following page for information on how to convert your config object into the correct format:
|
58
70
|
https://eslint.org/docs/latest/use/configure/migration-guide#glob-based-configs
|
71
|
+
|
72
|
+
If you're not using "overrides" directly (it may be coming from a plugin), please see the following:
|
73
|
+
https://eslint.org/docs/latest/use/configure/migration-guide#using-eslintrc-configs-in-flat-config
|
59
74
|
`,
|
60
75
|
|
61
76
|
parser: `
|
@@ -65,6 +80,9 @@ Flat config uses "languageOptions.parser" to override the default parser.
|
|
65
80
|
|
66
81
|
Please see the following page for information on how to convert your config object into the correct format:
|
67
82
|
https://eslint.org/docs/latest/use/configure/migration-guide#custom-parsers
|
83
|
+
|
84
|
+
If you're not using "parser" directly (it may be coming from a plugin), please see the following:
|
85
|
+
https://eslint.org/docs/latest/use/configure/migration-guide#using-eslintrc-configs-in-flat-config
|
68
86
|
`,
|
69
87
|
|
70
88
|
parserOptions: `
|
@@ -74,6 +92,9 @@ Flat config uses "languageOptions.parserOptions" to specify parser options.
|
|
74
92
|
|
75
93
|
Please see the following page for information on how to convert your config object into the correct format:
|
76
94
|
https://eslint.org/docs/latest/use/configure/migration-guide#configuring-language-options
|
95
|
+
|
96
|
+
If you're not using "parserOptions" directly (it may be coming from a plugin), please see the following:
|
97
|
+
https://eslint.org/docs/latest/use/configure/migration-guide#using-eslintrc-configs-in-flat-config
|
77
98
|
`,
|
78
99
|
|
79
100
|
reportUnusedDisableDirectives: `
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "eslint",
|
3
|
-
"version": "9.
|
3
|
+
"version": "9.3.0",
|
4
4
|
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
|
5
5
|
"description": "An AST-based pattern checker for JavaScript.",
|
6
6
|
"bin": {
|
@@ -68,11 +68,11 @@
|
|
68
68
|
"dependencies": {
|
69
69
|
"@eslint-community/eslint-utils": "^4.2.0",
|
70
70
|
"@eslint-community/regexpp": "^4.6.1",
|
71
|
-
"@eslint/eslintrc": "^3.0
|
72
|
-
"@eslint/js": "9.
|
71
|
+
"@eslint/eslintrc": "^3.1.0",
|
72
|
+
"@eslint/js": "9.3.0",
|
73
73
|
"@humanwhocodes/config-array": "^0.13.0",
|
74
74
|
"@humanwhocodes/module-importer": "^1.0.1",
|
75
|
-
"@humanwhocodes/retry": "^0.
|
75
|
+
"@humanwhocodes/retry": "^0.3.0",
|
76
76
|
"@nodelib/fs.walk": "^1.2.8",
|
77
77
|
"ajv": "^6.12.4",
|
78
78
|
"chalk": "^4.0.0",
|
@@ -104,6 +104,7 @@
|
|
104
104
|
"devDependencies": {
|
105
105
|
"@babel/core": "^7.4.3",
|
106
106
|
"@babel/preset-env": "^7.4.3",
|
107
|
+
"@eslint-community/eslint-plugin-eslint-comments": "^4.3.0",
|
107
108
|
"@types/estree": "^1.0.5",
|
108
109
|
"@types/node": "^20.11.5",
|
109
110
|
"@wdio/browser-runner": "^8.14.6",
|
@@ -120,12 +121,11 @@
|
|
120
121
|
"ejs": "^3.0.2",
|
121
122
|
"eslint": "file:.",
|
122
123
|
"eslint-config-eslint": "file:packages/eslint-config-eslint",
|
123
|
-
"eslint-plugin-eslint-comments": "^3.2.0",
|
124
124
|
"eslint-plugin-eslint-plugin": "^6.0.0",
|
125
125
|
"eslint-plugin-internal-rules": "file:tools/internal-rules",
|
126
|
-
"eslint-plugin-jsdoc": "^
|
127
|
-
"eslint-plugin-n": "^
|
128
|
-
"eslint-plugin-unicorn": "^
|
126
|
+
"eslint-plugin-jsdoc": "^48.2.3",
|
127
|
+
"eslint-plugin-n": "^17.2.0",
|
128
|
+
"eslint-plugin-unicorn": "^52.0.0",
|
129
129
|
"eslint-release": "^3.2.2",
|
130
130
|
"eslump": "^3.0.0",
|
131
131
|
"esprima": "^4.0.1",
|
@@ -142,7 +142,7 @@
|
|
142
142
|
"markdown-it": "^12.2.0",
|
143
143
|
"markdown-it-container": "^3.0.0",
|
144
144
|
"markdownlint": "^0.34.0",
|
145
|
-
"markdownlint-cli": "^0.
|
145
|
+
"markdownlint-cli": "^0.40.0",
|
146
146
|
"marked": "^4.0.8",
|
147
147
|
"metascraper": "^5.25.7",
|
148
148
|
"metascraper-description": "^5.25.7",
|
@@ -1,36 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @fileoverview Pattern for detecting any letter (even letters outside of ASCII).
|
3
|
-
* NOTE: This file was generated using this script in JSCS based on the Unicode 7.0.0 standard: https://github.com/jscs-dev/node-jscs/blob/f5ed14427deb7e7aac84f3056a5aab2d9f3e563e/publish/helpers/generate-patterns.js
|
4
|
-
* Do not edit this file by hand-- please use https://github.com/mathiasbynens/regenerate to regenerate the regular expression exported from this file.
|
5
|
-
* @author Kevin Partington
|
6
|
-
* @license MIT License (from JSCS). See below.
|
7
|
-
*/
|
8
|
-
|
9
|
-
/*
|
10
|
-
* The MIT License (MIT)
|
11
|
-
*
|
12
|
-
* Copyright 2013-2016 Dulin Marat and other contributors
|
13
|
-
*
|
14
|
-
* Permission is hereby granted, free of charge, to any person obtaining
|
15
|
-
* a copy of this software and associated documentation files (the
|
16
|
-
* "Software"), to deal in the Software without restriction, including
|
17
|
-
* without limitation the rights to use, copy, modify, merge, publish,
|
18
|
-
* distribute, sublicense, and/or sell copies of the Software, and to
|
19
|
-
* permit persons to whom the Software is furnished to do so, subject to
|
20
|
-
* the following conditions:
|
21
|
-
*
|
22
|
-
* The above copyright notice and this permission notice shall be
|
23
|
-
* included in all copies or substantial portions of the Software.
|
24
|
-
*
|
25
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
26
|
-
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
27
|
-
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
28
|
-
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
29
|
-
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
30
|
-
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
31
|
-
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
32
|
-
*/
|
33
|
-
|
34
|
-
"use strict";
|
35
|
-
|
36
|
-
module.exports = /[A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/u;
|