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 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/eb04ddc/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>
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://transloadit.com/"><img src="https://avatars.githubusercontent.com/u/125754?v=4" alt="Transloadit" 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>
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");
@@ -9,10 +9,9 @@
9
9
  // Requirements
10
10
  //------------------------------------------------------------------------------
11
11
 
12
- // Note: Node.js 12 does not support fs/promises.
13
- const fs = require("fs").promises;
14
- const { existsSync } = require("fs");
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
  //------------------------------------------------------------------------------
@@ -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; // TODO: Combine w/ max-len pattern?
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
- const firstWordChar = commentWordCharsOnly[0];
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
- return fixer.replaceTextRange(
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
- // Offset match.index by 2 to account for the first 2 characters that start the comment (// or /*)
280
- [comment.range[0] + match.index + 2, comment.range[0] + match.index + 3],
281
- capitalize === "always" ? match[0].toLocaleUpperCase() : match[0].toLocaleLowerCase()
282
+ return fixer.replaceTextRange(
283
+ [charIndex, charIndex + char.length],
284
+ capitalize === "always" ? char.toLocaleUpperCase() : char.toLocaleLowerCase()
282
285
  );
283
286
  }
284
287
  });
@@ -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 (!enforceDeclarations && node.parent.type !== "ExportDefaultDeclaration") {
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 (enforceDeclarations && node.parent.type === "VariableDeclarator") {
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 (enforceDeclarations && !hasThisExpr && node.parent.type === "VariableDeclarator") {
90
- context.report({ node: node.parent, messageId: "declaration" });
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
- * Javascript `==` operator works by converting the boolean to `1` (true) or
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
- type: "object",
34
- properties: {
35
- enforceForLogicalOperands: {
36
- type: "boolean",
37
- default: false
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
- return isInBooleanContext(node) ||
119
- (isLogicalContext(node.parent) &&
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
- // For nested logical statements
122
- isInFlaggedContext(node.parent)
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
- return precedence(node) <= precedence(parent);
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
- if (index === 0) {
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
- if (index === 0 || index === chars.length - 1) {
175
- continue;
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
- chars[index - 1].value !== 0x200d &&
180
- chars[index + 1].value !== 0x200d
175
+ previous.value !== 0x200d &&
176
+ next.value !== 0x200d
181
177
  ) {
182
178
  if (sequence) {
183
- if (sequence.at(-1) === chars[index - 1]) {
184
- sequence.push(char, chars[index + 1]); // append to the sequence
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 chars of iterateCharacterSequence(ccNode.elements)) {
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(...findCharacterSequences[kind](chars));
381
+ foundKindMatches.get(kind).push(...matches);
299
382
  } else {
300
- foundKindMatches.set(kind, [...findCharacterSequences[kind](chars)]);
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
- if (restrictedNames.has(name)) {
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
- let shouldAddParensAroundParameters = false;
288
- let tokenBeforeParams;
289
-
290
- if (node.value.params.length === 0) {
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 = shouldAddParensAroundParameters
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 = shouldAddParensAroundParameters ? `(${oldParamText})` : oldParamText;
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
- Please see the following page for more information:
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.1.1",
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.2",
72
- "@eslint/js": "9.1.1",
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.2.3",
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": "^46.9.0",
127
- "eslint-plugin-n": "^16.6.0",
128
- "eslint-plugin-unicorn": "^49.0.0",
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.39.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;