eslint 9.0.0-beta.0 → 9.0.0-beta.1

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
@@ -103,7 +103,7 @@ We are now at or near 100% compatibility with JSCS. If you try ESLint and believ
103
103
 
104
104
  ### Does Prettier replace ESLint?
105
105
 
106
- No, ESLint and Prettier have diffent jobs: ESLint is a linter (looking for problematic patterns) and Prettier is a code formatter. Using both tools is common, refer to [Prettier's documentation](https://prettier.io/docs/en/install#eslint-and-other-linters) to learn how to configure them to work well with each other.
106
+ No, ESLint and Prettier have different jobs: ESLint is a linter (looking for problematic patterns) and Prettier is a code formatter. Using both tools is common, refer to [Prettier's documentation](https://prettier.io/docs/en/install#eslint-and-other-linters) to learn how to configure them to work well with each other.
107
107
 
108
108
  ### Why can't ESLint find my plugins?
109
109
 
@@ -294,7 +294,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
294
294
  <p><a href="#"><img src="https://images.opencollective.com/2021-frameworks-fund/logo.png" alt="Chrome Frameworks Fund" height="undefined"></a> <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>
295
295
  <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>
296
296
  <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>
297
- <p><a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" 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>
297
+ <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://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" 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>
298
298
  <!--sponsorsend-->
299
299
 
300
300
  ## Technology Sponsors
@@ -43,7 +43,7 @@ const
43
43
  const { getRuleFromConfig } = require("../config/flat-config-helpers");
44
44
  const { FlatConfigArray } = require("../config/flat-config-array");
45
45
  const { RuleValidator } = require("../config/rule-validator");
46
- const { assertIsRuleOptions, assertIsRuleSeverity } = require("../config/flat-config-schema");
46
+ const { assertIsRuleSeverity } = require("../config/flat-config-schema");
47
47
  const { normalizeSeverityToString } = require("../shared/severity");
48
48
  const debug = require("debug")("eslint:linter");
49
49
  const MAX_AUTOFIX_PASSES = 10;
@@ -326,10 +326,11 @@ function createDisableDirectives(options) {
326
326
  * @param {SourceCode} sourceCode The SourceCode object to get comments from.
327
327
  * @param {function(string): {create: Function}} ruleMapper A map from rule IDs to defined rules
328
328
  * @param {string|null} warnInlineConfig If a string then it should warn directive comments as disabled. The string value is the config name what the setting came from.
329
+ * @param {ConfigData} config Provided config.
329
330
  * @returns {{configuredRules: Object, enabledGlobals: {value:string,comment:Token}[], exportedVariables: Object, problems: LintMessage[], disableDirectives: DisableDirective[]}}
330
331
  * A collection of the directive comments that were found, along with any problems that occurred when parsing
331
332
  */
332
- function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig) {
333
+ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config) {
333
334
  const configuredRules = {};
334
335
  const enabledGlobals = Object.create(null);
335
336
  const exportedVariables = {};
@@ -438,8 +439,50 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig) {
438
439
  return;
439
440
  }
440
441
 
442
+ let ruleOptions = Array.isArray(ruleValue) ? ruleValue : [ruleValue];
443
+
444
+ /*
445
+ * If the rule was already configured, inline rule configuration that
446
+ * only has severity should retain options from the config and just override the severity.
447
+ *
448
+ * Example:
449
+ *
450
+ * {
451
+ * rules: {
452
+ * curly: ["error", "multi"]
453
+ * }
454
+ * }
455
+ *
456
+ * /* eslint curly: ["warn"] * /
457
+ *
458
+ * Results in:
459
+ *
460
+ * curly: ["warn", "multi"]
461
+ */
462
+ if (
463
+
464
+ /*
465
+ * If inline config for the rule has only severity
466
+ */
467
+ ruleOptions.length === 1 &&
468
+
469
+ /*
470
+ * And the rule was already configured
471
+ */
472
+ config.rules && Object.hasOwn(config.rules, name)
473
+ ) {
474
+
475
+ /*
476
+ * Then use severity from the inline config and options from the provided config
477
+ */
478
+ ruleOptions = [
479
+ ruleOptions[0], // severity from the inline config
480
+ ...Array.isArray(config.rules[name]) ? config.rules[name].slice(1) : [] // options from the provided config
481
+ ];
482
+ }
483
+
441
484
  try {
442
- validator.validateRuleOptions(rule, name, ruleValue);
485
+ validator.validateRuleOptions(rule, name, ruleOptions);
443
486
  } catch (err) {
444
487
 
445
488
  /*
@@ -460,7 +503,7 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig) {
460
503
  return;
461
504
  }
462
505
 
463
- configuredRules[name] = ruleValue;
506
+ configuredRules[name] = ruleOptions;
464
507
  });
465
508
  } else {
466
509
  problems.push(parseResult.error);
@@ -1322,7 +1365,7 @@ class Linter {
1322
1365
 
1323
1366
  const sourceCode = slots.lastSourceCode;
1324
1367
  const commentDirectives = options.allowInlineConfig
1325
- ? getDirectiveComments(sourceCode, ruleId => getRule(slots, ruleId), options.warnInlineConfig)
1368
+ ? getDirectiveComments(sourceCode, ruleId => getRule(slots, ruleId), options.warnInlineConfig, config)
1326
1369
  : { configuredRules: {}, enabledGlobals: {}, exportedVariables: {}, problems: [], disableDirectives: [] };
1327
1370
 
1328
1371
  // augment global scope with declared global variables
@@ -1332,56 +1375,8 @@ class Linter {
1332
1375
  { exportedVariables: commentDirectives.exportedVariables, enabledGlobals: commentDirectives.enabledGlobals }
1333
1376
  );
1334
1377
 
1335
- /*
1336
- * Now we determine the final configurations for rules.
1337
- * First, let all inline rule configurations override those from the config.
1338
- * Then, check for a special case: if a rule is configured in both places,
1339
- * inline rule configuration that only has severity should retain options from
1340
- * the config and just override the severity.
1341
- *
1342
- * Example:
1343
- *
1344
- * {
1345
- * rules: {
1346
- * curly: ["error", "multi"]
1347
- * }
1348
- * }
1349
- *
1350
- * /* eslint curly: ["warn"] * /
1351
- *
1352
- * Results in:
1353
- *
1354
- * curly: ["warn", "multi"]
1355
- */
1356
1378
  const configuredRules = Object.assign({}, config.rules, commentDirectives.configuredRules);
1357
1379
 
1358
- if (config.rules) {
1359
- for (const [ruleId, ruleInlineConfig] of Object.entries(commentDirectives.configuredRules)) {
1360
- if (
1361
-
1362
- /*
1363
- * If inline config for the rule has only severity
1364
- */
1365
- (!Array.isArray(ruleInlineConfig) || ruleInlineConfig.length === 1) &&
1366
-
1367
- /*
1368
- * And provided config for the rule has options
1369
- */
1370
- Object.hasOwn(config.rules, ruleId) &&
1371
- (Array.isArray(config.rules[ruleId]) && config.rules[ruleId].length > 1)
1372
- ) {
1373
-
1374
- /*
1375
- * Then use severity from the inline config and options from the provided config
1376
- */
1377
- configuredRules[ruleId] = [
1378
- Array.isArray(ruleInlineConfig) ? ruleInlineConfig[0] : ruleInlineConfig, // severity from the inline config
1379
- ...config.rules[ruleId].slice(1) // options from the provided config
1380
- ];
1381
- }
1382
- }
1383
- }
1384
-
1385
1380
  let lintingProblems;
1386
1381
 
1387
1382
  try {
@@ -1713,17 +1708,67 @@ class Linter {
1713
1708
 
1714
1709
  try {
1715
1710
 
1716
- const ruleOptions = Array.isArray(ruleValue) ? ruleValue : [ruleValue];
1711
+ let ruleOptions = Array.isArray(ruleValue) ? ruleValue : [ruleValue];
1717
1712
 
1718
- assertIsRuleOptions(ruleId, ruleValue);
1719
1713
  assertIsRuleSeverity(ruleId, ruleOptions[0]);
1720
1714
 
1721
- ruleValidator.validate({
1722
- plugins: config.plugins,
1723
- rules: {
1724
- [ruleId]: ruleOptions
1715
+ /*
1716
+ * If the rule was already configured, inline rule configuration that
1717
+ * only has severity should retain options from the config and just override the severity.
1718
+ *
1719
+ * Example:
1720
+ *
1721
+ * {
1722
+ * rules: {
1723
+ * curly: ["error", "multi"]
1724
+ * }
1725
+ * }
1726
+ *
1727
+ * /* eslint curly: ["warn"] * /
1728
+ *
1729
+ * Results in:
1730
+ *
1731
+ * curly: ["warn", "multi"]
1732
+ */
1733
+
1734
+ let shouldValidateOptions = true;
1735
+
1736
+ if (
1737
+
1738
+ /*
1739
+ * If inline config for the rule has only severity
1740
+ */
1741
+ ruleOptions.length === 1 &&
1742
+
1743
+ /*
1744
+ * And the rule was already configured
1745
+ */
1746
+ config.rules && Object.hasOwn(config.rules, ruleId)
1747
+ ) {
1748
+
1749
+ /*
1750
+ * Then use severity from the inline config and options from the provided config
1751
+ */
1752
+ ruleOptions = [
1753
+ ruleOptions[0], // severity from the inline config
1754
+ ...config.rules[ruleId].slice(1) // options from the provided config
1755
+ ];
1756
+
1757
+ // if the rule was enabled, the options have already been validated
1758
+ if (config.rules[ruleId][0] > 0) {
1759
+ shouldValidateOptions = false;
1725
1760
  }
1726
- });
1761
+ }
1762
+
1763
+ if (shouldValidateOptions) {
1764
+ ruleValidator.validate({
1765
+ plugins: config.plugins,
1766
+ rules: {
1767
+ [ruleId]: ruleOptions
1768
+ }
1769
+ });
1770
+ }
1771
+
1727
1772
  mergedInlineConfig.rules[ruleId] = ruleOptions;
1728
1773
  } catch (err) {
1729
1774
 
@@ -1763,58 +1808,8 @@ class Linter {
1763
1808
  )
1764
1809
  : { problems: [], disableDirectives: [] };
1765
1810
 
1766
- /*
1767
- * Now we determine the final configurations for rules.
1768
- * First, let all inline rule configurations override those from the config.
1769
- * Then, check for a special case: if a rule is configured in both places,
1770
- * inline rule configuration that only has severity should retain options from
1771
- * the config and just override the severity.
1772
- *
1773
- * Example:
1774
- *
1775
- * {
1776
- * rules: {
1777
- * curly: ["error", "multi"]
1778
- * }
1779
- * }
1780
- *
1781
- * /* eslint curly: ["warn"] * /
1782
- *
1783
- * Results in:
1784
- *
1785
- * curly: ["warn", "multi"]
1786
- *
1787
- * At this point, all rule configurations are normalized to arrays.
1788
- */
1789
1811
  const configuredRules = Object.assign({}, config.rules, mergedInlineConfig.rules);
1790
1812
 
1791
- if (config.rules) {
1792
- for (const [ruleId, ruleInlineConfig] of Object.entries(mergedInlineConfig.rules)) {
1793
- if (
1794
-
1795
- /*
1796
- * If inline config for the rule has only severity
1797
- */
1798
- ruleInlineConfig.length === 1 &&
1799
-
1800
- /*
1801
- * And provided config for the rule has options
1802
- */
1803
- Object.hasOwn(config.rules, ruleId) &&
1804
- config.rules[ruleId].length > 1
1805
- ) {
1806
-
1807
- /*
1808
- * Then use severity from the inline config and options from the provided config
1809
- */
1810
- configuredRules[ruleId] = [
1811
- ruleInlineConfig[0], // severity from the inline config
1812
- ...config.rules[ruleId].slice(1) // options from the provided config
1813
- ];
1814
- }
1815
- }
1816
- }
1817
-
1818
1813
  let lintingProblems;
1819
1814
 
1820
1815
  sourceCode.finalize();
@@ -5,8 +5,7 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- const globals = require("globals");
9
- const { isNullLiteral, isConstant, isReferenceToGlobalVariable, isLogicalAssignmentOperator } = require("./utils/ast-utils");
8
+ const { isNullLiteral, isConstant, isReferenceToGlobalVariable, isLogicalAssignmentOperator, ECMASCRIPT_GLOBALS } = require("./utils/ast-utils");
10
9
 
11
10
  const NUMERIC_OR_STRING_BINARY_OPERATORS = new Set(["+", "-", "*", "/", "%", "|", "^", "&", "**", "<<", ">>", ">>>"]);
12
11
 
@@ -376,7 +375,7 @@ function isAlwaysNew(scope, node) {
376
375
  * Catching these is especially useful for primitive constructors
377
376
  * which return boxed values, a surprising gotcha' in JavaScript.
378
377
  */
379
- return Object.hasOwn(globals.builtin, node.callee.name) &&
378
+ return Object.hasOwn(ECMASCRIPT_GLOBALS, node.callee.name) &&
380
379
  isReferenceToGlobalVariable(scope, node.callee);
381
380
  }
382
381
  case "Literal":
@@ -10,7 +10,6 @@
10
10
  //------------------------------------------------------------------------------
11
11
 
12
12
  const astUtils = require("./utils/ast-utils");
13
- const globals = require("globals");
14
13
 
15
14
  //------------------------------------------------------------------------------
16
15
  // Rule Definition
@@ -54,7 +53,7 @@ module.exports = {
54
53
  const sourceCode = context.sourceCode;
55
54
  const exceptions = new Set(config.exceptions || []);
56
55
  const modifiedBuiltins = new Set(
57
- Object.keys(globals.builtin)
56
+ Object.keys(astUtils.ECMASCRIPT_GLOBALS)
58
57
  .filter(builtin => builtin[0].toUpperCase() === builtin[0])
59
58
  .filter(builtin => !exceptions.has(builtin))
60
59
  );
@@ -74,7 +74,8 @@ module.exports = {
74
74
  caseNaN: "'case NaN' can never match. Use Number.isNaN before the switch.",
75
75
  indexOfNaN: "Array prototype method '{{ methodName }}' cannot find NaN.",
76
76
  replaceWithIsNaN: "Replace with Number.isNaN.",
77
- replaceWithCastingAndIsNaN: "Replace with Number.isNaN cast to a Number."
77
+ replaceWithCastingAndIsNaN: "Replace with Number.isNaN and cast to a Number.",
78
+ replaceWithFindIndex: "Replace with Array.prototype.{{ methodName }}."
78
79
  }
79
80
  },
80
81
 
@@ -126,10 +127,10 @@ module.exports = {
126
127
  const NaNNode = isNaNIdentifier(node.left) ? node.left : node.right;
127
128
 
128
129
  const isSequenceExpression = NaNNode.type === "SequenceExpression";
129
- const isFixable = fixableOperators.has(node.operator) && !isSequenceExpression;
130
+ const isSuggestable = fixableOperators.has(node.operator) && !isSequenceExpression;
130
131
  const isCastable = castableOperators.has(node.operator);
131
132
 
132
- if (isFixable) {
133
+ if (isSuggestable) {
133
134
  suggestedFixes.push({
134
135
  messageId: "replaceWithIsNaN",
135
136
  fix: getBinaryExpressionFixer(node, value => `Number.isNaN(${value})`)
@@ -184,7 +185,35 @@ module.exports = {
184
185
  node.arguments.length === 1 &&
185
186
  isNaNIdentifier(node.arguments[0])
186
187
  ) {
187
- context.report({ node, messageId: "indexOfNaN", data: { methodName } });
188
+
189
+ /*
190
+ * To retain side effects, it's essential to address `NaN` beforehand, which
191
+ * is not possible with fixes like `arr.findIndex(Number.isNaN)`.
192
+ */
193
+ const isSuggestable = node.arguments[0].type !== "SequenceExpression";
194
+ const suggestedFixes = [];
195
+
196
+ if (isSuggestable) {
197
+ const shouldWrap = callee.computed;
198
+ const findIndexMethod = methodName === "indexOf" ? "findIndex" : "findLastIndex";
199
+ const propertyName = shouldWrap ? `"${findIndexMethod}"` : findIndexMethod;
200
+
201
+ suggestedFixes.push({
202
+ messageId: "replaceWithFindIndex",
203
+ data: { methodName: findIndexMethod },
204
+ fix: fixer => [
205
+ fixer.replaceText(callee.property, propertyName),
206
+ fixer.replaceText(node.arguments[0], "Number.isNaN")
207
+ ]
208
+ });
209
+ }
210
+
211
+ context.report({
212
+ node,
213
+ messageId: "indexOfNaN",
214
+ data: { methodName },
215
+ suggest: suggestedFixes
216
+ });
188
217
  }
189
218
  }
190
219
  }
@@ -19,6 +19,8 @@ const {
19
19
  lineBreakPattern,
20
20
  shebangPattern
21
21
  } = require("../../shared/ast-utils");
22
+ const globals = require("../../../conf/globals");
23
+ const { LATEST_ECMA_VERSION } = require("../../../conf/ecma-version");
22
24
 
23
25
  //------------------------------------------------------------------------------
24
26
  // Helpers
@@ -46,6 +48,12 @@ const OCTAL_OR_NON_OCTAL_DECIMAL_ESCAPE_PATTERN = /^(?:[^\\]|\\.)*\\(?:[1-9]|0[0
46
48
 
47
49
  const LOGICAL_ASSIGNMENT_OPERATORS = new Set(["&&=", "||=", "??="]);
48
50
 
51
+ /**
52
+ * All builtin global variables defined in the latest ECMAScript specification.
53
+ * @type {Record<string,boolean>} Key is the name of the variable. Value is `true` if the variable is considered writable, `false` otherwise.
54
+ */
55
+ const ECMASCRIPT_GLOBALS = globals[`es${LATEST_ECMA_VERSION}`];
56
+
49
57
  /**
50
58
  * Checks reference if is non initializer and writable.
51
59
  * @param {Reference} reference A reference to check.
@@ -1133,6 +1141,7 @@ module.exports = {
1133
1141
  LINEBREAK_MATCHER: lineBreakPattern,
1134
1142
  SHEBANG_MATCHER: shebangPattern,
1135
1143
  STATEMENT_LIST_PARENTS,
1144
+ ECMASCRIPT_GLOBALS,
1136
1145
 
1137
1146
  /**
1138
1147
  * Determines whether two adjacent tokens are on the same line.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint",
3
- "version": "9.0.0-beta.0",
3
+ "version": "9.0.0-beta.1",
4
4
  "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
5
5
  "description": "An AST-based pattern checker for JavaScript.",
6
6
  "bin": {
@@ -65,8 +65,8 @@
65
65
  "dependencies": {
66
66
  "@eslint-community/eslint-utils": "^4.2.0",
67
67
  "@eslint-community/regexpp": "^4.6.1",
68
- "@eslint/eslintrc": "^3.0.1",
69
- "@eslint/js": "9.0.0-beta.0",
68
+ "@eslint/eslintrc": "^3.0.2",
69
+ "@eslint/js": "9.0.0-beta.1",
70
70
  "@humanwhocodes/config-array": "^0.11.14",
71
71
  "@humanwhocodes/module-importer": "^1.0.1",
72
72
  "@nodelib/fs.walk": "^1.2.8",
@@ -84,7 +84,6 @@
84
84
  "file-entry-cache": "^8.0.0",
85
85
  "find-up": "^5.0.0",
86
86
  "glob-parent": "^6.0.2",
87
- "globals": "^13.19.0",
88
87
  "graphemer": "^1.4.0",
89
88
  "ignore": "^5.2.0",
90
89
  "imurmurhash": "^0.1.4",
@@ -122,12 +121,13 @@
122
121
  "eslint-plugin-jsdoc": "^46.9.0",
123
122
  "eslint-plugin-n": "^16.6.0",
124
123
  "eslint-plugin-unicorn": "^49.0.0",
125
- "eslint-release": "^3.2.0",
124
+ "eslint-release": "^3.2.2",
126
125
  "eslump": "^3.0.0",
127
126
  "esprima": "^4.0.1",
128
127
  "fast-glob": "^3.2.11",
129
128
  "fs-teardown": "^0.1.3",
130
129
  "glob": "^10.0.0",
130
+ "globals": "^14.0.0",
131
131
  "got": "^11.8.3",
132
132
  "gray-matter": "^4.0.3",
133
133
  "js-yaml": "^4.1.0",