eslintrc-universal.cjs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var util = require('util');
  4. var path = require('path');
  5. var Ajv = require('ajv');
  6. var globals = require('globals');
  7. function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
  8. var util__default = /*#__PURE__*/_interopDefaultLegacy(util);
  9. var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
  10. var Ajv__default = /*#__PURE__*/_interopDefaultLegacy(Ajv);
  11. var globals__default = /*#__PURE__*/_interopDefaultLegacy(globals);
  12. /**
  13. * @fileoverview Config file operations. This file must be usable in the browser,
  14. * so no Node-specific code can be here.
  15. * @author Nicholas C. Zakas
  16. */
  17. //------------------------------------------------------------------------------
  18. // Private
  19. //------------------------------------------------------------------------------
  20. const RULE_SEVERITY_STRINGS = ["off", "warn", "error"],
  21. RULE_SEVERITY = RULE_SEVERITY_STRINGS.reduce((map, value, index) => {
  22. map[value] = index;
  23. return map;
  24. }, {}),
  25. VALID_SEVERITIES = [0, 1, 2, "off", "warn", "error"];
  26. //------------------------------------------------------------------------------
  27. // Public Interface
  28. //------------------------------------------------------------------------------
  29. /**
  30. * Normalizes the severity value of a rule's configuration to a number
  31. * @param {(number|string|[number, ...*]|[string, ...*])} ruleConfig A rule's configuration value, generally
  32. * received from the user. A valid config value is either 0, 1, 2, the string "off" (treated the same as 0),
  33. * the string "warn" (treated the same as 1), the string "error" (treated the same as 2), or an array
  34. * whose first element is one of the above values. Strings are matched case-insensitively.
  35. * @returns {(0|1|2)} The numeric severity value if the config value was valid, otherwise 0.
  36. */
  37. function getRuleSeverity(ruleConfig) {
  38. const severityValue = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
  39. if (severityValue === 0 || severityValue === 1 || severityValue === 2) {
  40. return severityValue;
  41. }
  42. if (typeof severityValue === "string") {
  43. return RULE_SEVERITY[severityValue.toLowerCase()] || 0;
  44. }
  45. return 0;
  46. }
  47. /**
  48. * Converts old-style severity settings (0, 1, 2) into new-style
  49. * severity settings (off, warn, error) for all rules. Assumption is that severity
  50. * values have already been validated as correct.
  51. * @param {Object} config The config object to normalize.
  52. * @returns {void}
  53. */
  54. function normalizeToStrings(config) {
  55. if (config.rules) {
  56. Object.keys(config.rules).forEach(ruleId => {
  57. const ruleConfig = config.rules[ruleId];
  58. if (typeof ruleConfig === "number") {
  59. config.rules[ruleId] = RULE_SEVERITY_STRINGS[ruleConfig] || RULE_SEVERITY_STRINGS[0];
  60. } else if (Array.isArray(ruleConfig) && typeof ruleConfig[0] === "number") {
  61. ruleConfig[0] = RULE_SEVERITY_STRINGS[ruleConfig[0]] || RULE_SEVERITY_STRINGS[0];
  62. }
  63. });
  64. }
  65. }
  66. /**
  67. * Determines if the severity for the given rule configuration represents an error.
  68. * @param {int|string|Array} ruleConfig The configuration for an individual rule.
  69. * @returns {boolean} True if the rule represents an error, false if not.
  70. */
  71. function isErrorSeverity(ruleConfig) {
  72. return getRuleSeverity(ruleConfig) === 2;
  73. }
  74. /**
  75. * Checks whether a given config has valid severity or not.
  76. * @param {number|string|Array} ruleConfig The configuration for an individual rule.
  77. * @returns {boolean} `true` if the configuration has valid severity.
  78. */
  79. function isValidSeverity(ruleConfig) {
  80. let severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
  81. if (typeof severity === "string") {
  82. severity = severity.toLowerCase();
  83. }
  84. return VALID_SEVERITIES.indexOf(severity) !== -1;
  85. }
  86. /**
  87. * Checks whether every rule of a given config has valid severity or not.
  88. * @param {Object} config The configuration for rules.
  89. * @returns {boolean} `true` if the configuration has valid severity.
  90. */
  91. function isEverySeverityValid(config) {
  92. return Object.keys(config).every(ruleId => isValidSeverity(config[ruleId]));
  93. }
  94. /**
  95. * Normalizes a value for a global in a config
  96. * @param {(boolean|string|null)} configuredValue The value given for a global in configuration or in
  97. * a global directive comment
  98. * @returns {("readable"|"writeable"|"off")} The value normalized as a string
  99. * @throws Error if global value is invalid
  100. */
  101. function normalizeConfigGlobal(configuredValue) {
  102. switch (configuredValue) {
  103. case "off":
  104. return "off";
  105. case true:
  106. case "true":
  107. case "writeable":
  108. case "writable":
  109. return "writable";
  110. case null:
  111. case false:
  112. case "false":
  113. case "readable":
  114. case "readonly":
  115. return "readonly";
  116. default:
  117. throw new Error(`'${configuredValue}' is not a valid configuration for a global (use 'readonly', 'writable', or 'off')`);
  118. }
  119. }
  120. var ConfigOps = {
  121. __proto__: null,
  122. getRuleSeverity: getRuleSeverity,
  123. normalizeToStrings: normalizeToStrings,
  124. isErrorSeverity: isErrorSeverity,
  125. isValidSeverity: isValidSeverity,
  126. isEverySeverityValid: isEverySeverityValid,
  127. normalizeConfigGlobal: normalizeConfigGlobal
  128. };
  129. /**
  130. * @fileoverview Provide the function that emits deprecation warnings.
  131. * @author Toru Nagashima <http://github.com/mysticatea>
  132. */
  133. //------------------------------------------------------------------------------
  134. // Private
  135. //------------------------------------------------------------------------------
  136. // Defitions for deprecation warnings.
  137. const deprecationWarningMessages = {
  138. ESLINT_LEGACY_ECMAFEATURES:
  139. "The 'ecmaFeatures' config file property is deprecated and has no effect.",
  140. ESLINT_PERSONAL_CONFIG_LOAD:
  141. "'~/.eslintrc.*' config files have been deprecated. " +
  142. "Please use a config file per project or the '--config' option.",
  143. ESLINT_PERSONAL_CONFIG_SUPPRESS:
  144. "'~/.eslintrc.*' config files have been deprecated. " +
  145. "Please remove it or add 'root:true' to the config files in your " +
  146. "projects in order to avoid loading '~/.eslintrc.*' accidentally."
  147. };
  148. const sourceFileErrorCache = new Set();
  149. /**
  150. * Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted
  151. * for each unique file path, but repeated invocations with the same file path have no effect.
  152. * No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.
  153. * @param {string} source The name of the configuration source to report the warning for.
  154. * @param {string} errorCode The warning message to show.
  155. * @returns {void}
  156. */
  157. function emitDeprecationWarning(source, errorCode) {
  158. const cacheKey = JSON.stringify({ source, errorCode });
  159. if (sourceFileErrorCache.has(cacheKey)) {
  160. return;
  161. }
  162. sourceFileErrorCache.add(cacheKey);
  163. const rel = path__default["default"].relative(process.cwd(), source);
  164. const message = deprecationWarningMessages[errorCode];
  165. process.emitWarning(
  166. `${message} (found in "${rel}")`,
  167. "DeprecationWarning",
  168. errorCode
  169. );
  170. }
  171. /**
  172. * @fileoverview The instance of Ajv validator.
  173. * @author Evgeny Poberezkin
  174. */
  175. //-----------------------------------------------------------------------------
  176. // Helpers
  177. //-----------------------------------------------------------------------------
  178. /*
  179. * Copied from ajv/lib/refs/json-schema-draft-04.json
  180. * The MIT License (MIT)
  181. * Copyright (c) 2015-2017 Evgeny Poberezkin
  182. */
  183. const metaSchema = {
  184. id: "http://json-schema.org/draft-04/schema#",
  185. $schema: "http://json-schema.org/draft-04/schema#",
  186. description: "Core schema meta-schema",
  187. definitions: {
  188. schemaArray: {
  189. type: "array",
  190. minItems: 1,
  191. items: { $ref: "#" }
  192. },
  193. positiveInteger: {
  194. type: "integer",
  195. minimum: 0
  196. },
  197. positiveIntegerDefault0: {
  198. allOf: [{ $ref: "#/definitions/positiveInteger" }, { default: 0 }]
  199. },
  200. simpleTypes: {
  201. enum: ["array", "boolean", "integer", "null", "number", "object", "string"]
  202. },
  203. stringArray: {
  204. type: "array",
  205. items: { type: "string" },
  206. minItems: 1,
  207. uniqueItems: true
  208. }
  209. },
  210. type: "object",
  211. properties: {
  212. id: {
  213. type: "string"
  214. },
  215. $schema: {
  216. type: "string"
  217. },
  218. title: {
  219. type: "string"
  220. },
  221. description: {
  222. type: "string"
  223. },
  224. default: { },
  225. multipleOf: {
  226. type: "number",
  227. minimum: 0,
  228. exclusiveMinimum: true
  229. },
  230. maximum: {
  231. type: "number"
  232. },
  233. exclusiveMaximum: {
  234. type: "boolean",
  235. default: false
  236. },
  237. minimum: {
  238. type: "number"
  239. },
  240. exclusiveMinimum: {
  241. type: "boolean",
  242. default: false
  243. },
  244. maxLength: { $ref: "#/definitions/positiveInteger" },
  245. minLength: { $ref: "#/definitions/positiveIntegerDefault0" },
  246. pattern: {
  247. type: "string",
  248. format: "regex"
  249. },
  250. additionalItems: {
  251. anyOf: [
  252. { type: "boolean" },
  253. { $ref: "#" }
  254. ],
  255. default: { }
  256. },
  257. items: {
  258. anyOf: [
  259. { $ref: "#" },
  260. { $ref: "#/definitions/schemaArray" }
  261. ],
  262. default: { }
  263. },
  264. maxItems: { $ref: "#/definitions/positiveInteger" },
  265. minItems: { $ref: "#/definitions/positiveIntegerDefault0" },
  266. uniqueItems: {
  267. type: "boolean",
  268. default: false
  269. },
  270. maxProperties: { $ref: "#/definitions/positiveInteger" },
  271. minProperties: { $ref: "#/definitions/positiveIntegerDefault0" },
  272. required: { $ref: "#/definitions/stringArray" },
  273. additionalProperties: {
  274. anyOf: [
  275. { type: "boolean" },
  276. { $ref: "#" }
  277. ],
  278. default: { }
  279. },
  280. definitions: {
  281. type: "object",
  282. additionalProperties: { $ref: "#" },
  283. default: { }
  284. },
  285. properties: {
  286. type: "object",
  287. additionalProperties: { $ref: "#" },
  288. default: { }
  289. },
  290. patternProperties: {
  291. type: "object",
  292. additionalProperties: { $ref: "#" },
  293. default: { }
  294. },
  295. dependencies: {
  296. type: "object",
  297. additionalProperties: {
  298. anyOf: [
  299. { $ref: "#" },
  300. { $ref: "#/definitions/stringArray" }
  301. ]
  302. }
  303. },
  304. enum: {
  305. type: "array",
  306. minItems: 1,
  307. uniqueItems: true
  308. },
  309. type: {
  310. anyOf: [
  311. { $ref: "#/definitions/simpleTypes" },
  312. {
  313. type: "array",
  314. items: { $ref: "#/definitions/simpleTypes" },
  315. minItems: 1,
  316. uniqueItems: true
  317. }
  318. ]
  319. },
  320. format: { type: "string" },
  321. allOf: { $ref: "#/definitions/schemaArray" },
  322. anyOf: { $ref: "#/definitions/schemaArray" },
  323. oneOf: { $ref: "#/definitions/schemaArray" },
  324. not: { $ref: "#" }
  325. },
  326. dependencies: {
  327. exclusiveMaximum: ["maximum"],
  328. exclusiveMinimum: ["minimum"]
  329. },
  330. default: { }
  331. };
  332. //------------------------------------------------------------------------------
  333. // Public Interface
  334. //------------------------------------------------------------------------------
  335. var ajvOrig = (additionalOptions = {}) => {
  336. const ajv = new Ajv__default["default"]({
  337. meta: false,
  338. useDefaults: true,
  339. validateSchema: false,
  340. missingRefs: "ignore",
  341. verbose: true,
  342. schemaId: "auto",
  343. ...additionalOptions
  344. });
  345. ajv.addMetaSchema(metaSchema);
  346. // eslint-disable-next-line no-underscore-dangle
  347. ajv._opts.defaultMeta = metaSchema.id;
  348. return ajv;
  349. };
  350. /**
  351. * @fileoverview Defines a schema for configs.
  352. * @author Sylvan Mably
  353. */
  354. const baseConfigProperties = {
  355. $schema: { type: "string" },
  356. env: { type: "object" },
  357. extends: { $ref: "#/definitions/stringOrStrings" },
  358. globals: { type: "object" },
  359. overrides: {
  360. type: "array",
  361. items: { $ref: "#/definitions/overrideConfig" },
  362. additionalItems: false
  363. },
  364. parser: { type: ["string", "null"] },
  365. parserOptions: { type: "object" },
  366. plugins: { type: "array" },
  367. processor: { type: "string" },
  368. rules: { type: "object" },
  369. settings: { type: "object" },
  370. noInlineConfig: { type: "boolean" },
  371. reportUnusedDisableDirectives: { type: "boolean" },
  372. ecmaFeatures: { type: "object" } // deprecated; logs a warning when used
  373. };
  374. const configSchema = {
  375. definitions: {
  376. stringOrStrings: {
  377. oneOf: [
  378. { type: "string" },
  379. {
  380. type: "array",
  381. items: { type: "string" },
  382. additionalItems: false
  383. }
  384. ]
  385. },
  386. stringOrStringsRequired: {
  387. oneOf: [
  388. { type: "string" },
  389. {
  390. type: "array",
  391. items: { type: "string" },
  392. additionalItems: false,
  393. minItems: 1
  394. }
  395. ]
  396. },
  397. // Config at top-level.
  398. objectConfig: {
  399. type: "object",
  400. properties: {
  401. root: { type: "boolean" },
  402. ignorePatterns: { $ref: "#/definitions/stringOrStrings" },
  403. ...baseConfigProperties
  404. },
  405. additionalProperties: false
  406. },
  407. // Config in `overrides`.
  408. overrideConfig: {
  409. type: "object",
  410. properties: {
  411. excludedFiles: { $ref: "#/definitions/stringOrStrings" },
  412. files: { $ref: "#/definitions/stringOrStringsRequired" },
  413. ...baseConfigProperties
  414. },
  415. required: ["files"],
  416. additionalProperties: false
  417. }
  418. },
  419. $ref: "#/definitions/objectConfig"
  420. };
  421. /**
  422. * @fileoverview Defines environment settings and globals.
  423. * @author Elan Shanker
  424. */
  425. //------------------------------------------------------------------------------
  426. // Helpers
  427. //------------------------------------------------------------------------------
  428. /**
  429. * Get the object that has difference.
  430. * @param {Record<string,boolean>} current The newer object.
  431. * @param {Record<string,boolean>} prev The older object.
  432. * @returns {Record<string,boolean>} The difference object.
  433. */
  434. function getDiff(current, prev) {
  435. const retv = {};
  436. for (const [key, value] of Object.entries(current)) {
  437. if (!Object.hasOwnProperty.call(prev, key)) {
  438. retv[key] = value;
  439. }
  440. }
  441. return retv;
  442. }
  443. const newGlobals2015 = getDiff(globals__default["default"].es2015, globals__default["default"].es5); // 19 variables such as Promise, Map, ...
  444. const newGlobals2017 = {
  445. Atomics: false,
  446. SharedArrayBuffer: false
  447. };
  448. const newGlobals2020 = {
  449. BigInt: false,
  450. BigInt64Array: false,
  451. BigUint64Array: false,
  452. globalThis: false
  453. };
  454. const newGlobals2021 = {
  455. AggregateError: false,
  456. FinalizationRegistry: false,
  457. WeakRef: false
  458. };
  459. //------------------------------------------------------------------------------
  460. // Public Interface
  461. //------------------------------------------------------------------------------
  462. /** @type {Map<string, import("../lib/shared/types").Environment>} */
  463. var environments = new Map(Object.entries({
  464. // Language
  465. builtin: {
  466. globals: globals__default["default"].es5
  467. },
  468. es6: {
  469. globals: newGlobals2015,
  470. parserOptions: {
  471. ecmaVersion: 6
  472. }
  473. },
  474. es2015: {
  475. globals: newGlobals2015,
  476. parserOptions: {
  477. ecmaVersion: 6
  478. }
  479. },
  480. es2016: {
  481. globals: newGlobals2015,
  482. parserOptions: {
  483. ecmaVersion: 7
  484. }
  485. },
  486. es2017: {
  487. globals: { ...newGlobals2015, ...newGlobals2017 },
  488. parserOptions: {
  489. ecmaVersion: 8
  490. }
  491. },
  492. es2018: {
  493. globals: { ...newGlobals2015, ...newGlobals2017 },
  494. parserOptions: {
  495. ecmaVersion: 9
  496. }
  497. },
  498. es2019: {
  499. globals: { ...newGlobals2015, ...newGlobals2017 },
  500. parserOptions: {
  501. ecmaVersion: 10
  502. }
  503. },
  504. es2020: {
  505. globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020 },
  506. parserOptions: {
  507. ecmaVersion: 11
  508. }
  509. },
  510. es2021: {
  511. globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
  512. parserOptions: {
  513. ecmaVersion: 12
  514. }
  515. },
  516. es2022: {
  517. globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
  518. parserOptions: {
  519. ecmaVersion: 13
  520. }
  521. },
  522. es2023: {
  523. globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
  524. parserOptions: {
  525. ecmaVersion: 14
  526. }
  527. },
  528. es2024: {
  529. globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
  530. parserOptions: {
  531. ecmaVersion: 15
  532. }
  533. },
  534. // Platforms
  535. browser: {
  536. globals: globals__default["default"].browser
  537. },
  538. node: {
  539. globals: globals__default["default"].node,
  540. parserOptions: {
  541. ecmaFeatures: {
  542. globalReturn: true
  543. }
  544. }
  545. },
  546. "shared-node-browser": {
  547. globals: globals__default["default"]["shared-node-browser"]
  548. },
  549. worker: {
  550. globals: globals__default["default"].worker
  551. },
  552. serviceworker: {
  553. globals: globals__default["default"].serviceworker
  554. },
  555. // Frameworks
  556. commonjs: {
  557. globals: globals__default["default"].commonjs,
  558. parserOptions: {
  559. ecmaFeatures: {
  560. globalReturn: true
  561. }
  562. }
  563. },
  564. amd: {
  565. globals: globals__default["default"].amd
  566. },
  567. mocha: {
  568. globals: globals__default["default"].mocha
  569. },
  570. jasmine: {
  571. globals: globals__default["default"].jasmine
  572. },
  573. jest: {
  574. globals: globals__default["default"].jest
  575. },
  576. phantomjs: {
  577. globals: globals__default["default"].phantomjs
  578. },
  579. jquery: {
  580. globals: globals__default["default"].jquery
  581. },
  582. qunit: {
  583. globals: globals__default["default"].qunit
  584. },
  585. prototypejs: {
  586. globals: globals__default["default"].prototypejs
  587. },
  588. shelljs: {
  589. globals: globals__default["default"].shelljs
  590. },
  591. meteor: {
  592. globals: globals__default["default"].meteor
  593. },
  594. mongo: {
  595. globals: globals__default["default"].mongo
  596. },
  597. protractor: {
  598. globals: globals__default["default"].protractor
  599. },
  600. applescript: {
  601. globals: globals__default["default"].applescript
  602. },
  603. nashorn: {
  604. globals: globals__default["default"].nashorn
  605. },
  606. atomtest: {
  607. globals: globals__default["default"].atomtest
  608. },
  609. embertest: {
  610. globals: globals__default["default"].embertest
  611. },
  612. webextensions: {
  613. globals: globals__default["default"].webextensions
  614. },
  615. greasemonkey: {
  616. globals: globals__default["default"].greasemonkey
  617. }
  618. }));
  619. /**
  620. * @fileoverview Validates configs.
  621. * @author Brandon Mills
  622. */
  623. const ajv = ajvOrig();
  624. const ruleValidators = new WeakMap();
  625. const noop = Function.prototype;
  626. //------------------------------------------------------------------------------
  627. // Private
  628. //------------------------------------------------------------------------------
  629. let validateSchema;
  630. const severityMap = {
  631. error: 2,
  632. warn: 1,
  633. off: 0
  634. };
  635. const validated = new WeakSet();
  636. // JSON schema that disallows passing any options
  637. const noOptionsSchema = Object.freeze({
  638. type: "array",
  639. minItems: 0,
  640. maxItems: 0
  641. });
  642. //-----------------------------------------------------------------------------
  643. // Exports
  644. //-----------------------------------------------------------------------------
  645. class ConfigValidator {
  646. constructor({ builtInRules = new Map() } = {}) {
  647. this.builtInRules = builtInRules;
  648. }
  649. /**
  650. * Gets a complete options schema for a rule.
  651. * @param {Rule} rule A rule object
  652. * @throws {TypeError} If `meta.schema` is specified but is not an array, object or `false`.
  653. * @returns {Object|null} JSON Schema for the rule's options.
  654. * `null` if rule wasn't passed or its `meta.schema` is `false`.
  655. */
  656. getRuleOptionsSchema(rule) {
  657. if (!rule) {
  658. return null;
  659. }
  660. if (!rule.meta) {
  661. return { ...noOptionsSchema }; // default if `meta.schema` is not specified
  662. }
  663. const schema = rule.meta.schema;
  664. if (typeof schema === "undefined") {
  665. return { ...noOptionsSchema }; // default if `meta.schema` is not specified
  666. }
  667. // `schema:false` is an allowed explicit opt-out of options validation for the rule
  668. if (schema === false) {
  669. return null;
  670. }
  671. if (typeof schema !== "object" || schema === null) {
  672. throw new TypeError("Rule's `meta.schema` must be an array or object");
  673. }
  674. // ESLint-specific array form needs to be converted into a valid JSON Schema definition
  675. if (Array.isArray(schema)) {
  676. if (schema.length) {
  677. return {
  678. type: "array",
  679. items: schema,
  680. minItems: 0,
  681. maxItems: schema.length
  682. };
  683. }
  684. // `schema:[]` is an explicit way to specify that the rule does not accept any options
  685. return { ...noOptionsSchema };
  686. }
  687. // `schema:<object>` is assumed to be a valid JSON Schema definition
  688. return schema;
  689. }
  690. /**
  691. * Validates a rule's severity and returns the severity value. Throws an error if the severity is invalid.
  692. * @param {options} options The given options for the rule.
  693. * @returns {number|string} The rule's severity value
  694. */
  695. validateRuleSeverity(options) {
  696. const severity = Array.isArray(options) ? options[0] : options;
  697. const normSeverity = typeof severity === "string" ? severityMap[severity.toLowerCase()] : severity;
  698. if (normSeverity === 0 || normSeverity === 1 || normSeverity === 2) {
  699. return normSeverity;
  700. }
  701. throw new Error(`\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '${util__default["default"].inspect(severity).replace(/'/gu, "\"").replace(/\n/gu, "")}').\n`);
  702. }
  703. /**
  704. * Validates the non-severity options passed to a rule, based on its schema.
  705. * @param {{create: Function}} rule The rule to validate
  706. * @param {Array} localOptions The options for the rule, excluding severity
  707. * @returns {void}
  708. */
  709. validateRuleSchema(rule, localOptions) {
  710. if (!ruleValidators.has(rule)) {
  711. try {
  712. const schema = this.getRuleOptionsSchema(rule);
  713. if (schema) {
  714. ruleValidators.set(rule, ajv.compile(schema));
  715. }
  716. } catch (err) {
  717. const errorWithCode = new Error(err.message, { cause: err });
  718. errorWithCode.code = "ESLINT_INVALID_RULE_OPTIONS_SCHEMA";
  719. throw errorWithCode;
  720. }
  721. }
  722. const validateRule = ruleValidators.get(rule);
  723. if (validateRule) {
  724. validateRule(localOptions);
  725. if (validateRule.errors) {
  726. throw new Error(validateRule.errors.map(
  727. error => `\tValue ${JSON.stringify(error.data)} ${error.message}.\n`
  728. ).join(""));
  729. }
  730. }
  731. }
  732. /**
  733. * Validates a rule's options against its schema.
  734. * @param {{create: Function}|null} rule The rule that the config is being validated for
  735. * @param {string} ruleId The rule's unique name.
  736. * @param {Array|number} options The given options for the rule.
  737. * @param {string|null} source The name of the configuration source to report in any errors. If null or undefined,
  738. * no source is prepended to the message.
  739. * @returns {void}
  740. */
  741. validateRuleOptions(rule, ruleId, options, source = null) {
  742. try {
  743. const severity = this.validateRuleSeverity(options);
  744. if (severity !== 0) {
  745. this.validateRuleSchema(rule, Array.isArray(options) ? options.slice(1) : []);
  746. }
  747. } catch (err) {
  748. let enhancedMessage = err.code === "ESLINT_INVALID_RULE_OPTIONS_SCHEMA"
  749. ? `Error while processing options validation schema of rule '${ruleId}': ${err.message}`
  750. : `Configuration for rule "${ruleId}" is invalid:\n${err.message}`;
  751. if (typeof source === "string") {
  752. enhancedMessage = `${source}:\n\t${enhancedMessage}`;
  753. }
  754. const enhancedError = new Error(enhancedMessage, { cause: err });
  755. if (err.code) {
  756. enhancedError.code = err.code;
  757. }
  758. throw enhancedError;
  759. }
  760. }
  761. /**
  762. * Validates an environment object
  763. * @param {Object} environment The environment config object to validate.
  764. * @param {string} source The name of the configuration source to report in any errors.
  765. * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded environments.
  766. * @returns {void}
  767. */
  768. validateEnvironment(
  769. environment,
  770. source,
  771. getAdditionalEnv = noop
  772. ) {
  773. // not having an environment is ok
  774. if (!environment) {
  775. return;
  776. }
  777. Object.keys(environment).forEach(id => {
  778. const env = getAdditionalEnv(id) || environments.get(id) || null;
  779. if (!env) {
  780. const message = `${source}:\n\tEnvironment key "${id}" is unknown\n`;
  781. throw new Error(message);
  782. }
  783. });
  784. }
  785. /**
  786. * Validates a rules config object
  787. * @param {Object} rulesConfig The rules config object to validate.
  788. * @param {string} source The name of the configuration source to report in any errors.
  789. * @param {function(ruleId:string): Object} getAdditionalRule A map from strings to loaded rules
  790. * @returns {void}
  791. */
  792. validateRules(
  793. rulesConfig,
  794. source,
  795. getAdditionalRule = noop
  796. ) {
  797. if (!rulesConfig) {
  798. return;
  799. }
  800. Object.keys(rulesConfig).forEach(id => {
  801. const rule = getAdditionalRule(id) || this.builtInRules.get(id) || null;
  802. this.validateRuleOptions(rule, id, rulesConfig[id], source);
  803. });
  804. }
  805. /**
  806. * Validates a `globals` section of a config file
  807. * @param {Object} globalsConfig The `globals` section
  808. * @param {string|null} source The name of the configuration source to report in the event of an error.
  809. * @returns {void}
  810. */
  811. validateGlobals(globalsConfig, source = null) {
  812. if (!globalsConfig) {
  813. return;
  814. }
  815. Object.entries(globalsConfig)
  816. .forEach(([configuredGlobal, configuredValue]) => {
  817. try {
  818. normalizeConfigGlobal(configuredValue);
  819. } catch (err) {
  820. throw new Error(`ESLint configuration of global '${configuredGlobal}' in ${source} is invalid:\n${err.message}`);
  821. }
  822. });
  823. }
  824. /**
  825. * Validate `processor` configuration.
  826. * @param {string|undefined} processorName The processor name.
  827. * @param {string} source The name of config file.
  828. * @param {function(id:string): Processor} getProcessor The getter of defined processors.
  829. * @returns {void}
  830. */
  831. validateProcessor(processorName, source, getProcessor) {
  832. if (processorName && !getProcessor(processorName)) {
  833. throw new Error(`ESLint configuration of processor in '${source}' is invalid: '${processorName}' was not found.`);
  834. }
  835. }
  836. /**
  837. * Formats an array of schema validation errors.
  838. * @param {Array} errors An array of error messages to format.
  839. * @returns {string} Formatted error message
  840. */
  841. formatErrors(errors) {
  842. return errors.map(error => {
  843. if (error.keyword === "additionalProperties") {
  844. const formattedPropertyPath = error.dataPath.length ? `${error.dataPath.slice(1)}.${error.params.additionalProperty}` : error.params.additionalProperty;
  845. return `Unexpected top-level property "${formattedPropertyPath}"`;
  846. }
  847. if (error.keyword === "type") {
  848. const formattedField = error.dataPath.slice(1);
  849. const formattedExpectedType = Array.isArray(error.schema) ? error.schema.join("/") : error.schema;
  850. const formattedValue = JSON.stringify(error.data);
  851. return `Property "${formattedField}" is the wrong type (expected ${formattedExpectedType} but got \`${formattedValue}\`)`;
  852. }
  853. const field = error.dataPath[0] === "." ? error.dataPath.slice(1) : error.dataPath;
  854. return `"${field}" ${error.message}. Value: ${JSON.stringify(error.data)}`;
  855. }).map(message => `\t- ${message}.\n`).join("");
  856. }
  857. /**
  858. * Validates the top level properties of the config object.
  859. * @param {Object} config The config object to validate.
  860. * @param {string} source The name of the configuration source to report in any errors.
  861. * @returns {void}
  862. */
  863. validateConfigSchema(config, source = null) {
  864. validateSchema = validateSchema || ajv.compile(configSchema);
  865. if (!validateSchema(config)) {
  866. throw new Error(`ESLint configuration in ${source} is invalid:\n${this.formatErrors(validateSchema.errors)}`);
  867. }
  868. if (Object.hasOwnProperty.call(config, "ecmaFeatures")) {
  869. emitDeprecationWarning(source, "ESLINT_LEGACY_ECMAFEATURES");
  870. }
  871. }
  872. /**
  873. * Validates an entire config object.
  874. * @param {Object} config The config object to validate.
  875. * @param {string} source The name of the configuration source to report in any errors.
  876. * @param {function(ruleId:string): Object} [getAdditionalRule] A map from strings to loaded rules.
  877. * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded envs.
  878. * @returns {void}
  879. */
  880. validate(config, source, getAdditionalRule, getAdditionalEnv) {
  881. this.validateConfigSchema(config, source);
  882. this.validateRules(config.rules, source, getAdditionalRule);
  883. this.validateEnvironment(config.env, source, getAdditionalEnv);
  884. this.validateGlobals(config.globals, source);
  885. for (const override of config.overrides || []) {
  886. this.validateRules(override.rules, source, getAdditionalRule);
  887. this.validateEnvironment(override.env, source, getAdditionalEnv);
  888. this.validateGlobals(config.globals, source);
  889. }
  890. }
  891. /**
  892. * Validate config array object.
  893. * @param {ConfigArray} configArray The config array to validate.
  894. * @returns {void}
  895. */
  896. validateConfigArray(configArray) {
  897. const getPluginEnv = Map.prototype.get.bind(configArray.pluginEnvironments);
  898. const getPluginProcessor = Map.prototype.get.bind(configArray.pluginProcessors);
  899. const getPluginRule = Map.prototype.get.bind(configArray.pluginRules);
  900. // Validate.
  901. for (const element of configArray) {
  902. if (validated.has(element)) {
  903. continue;
  904. }
  905. validated.add(element);
  906. this.validateEnvironment(element.env, element.name, getPluginEnv);
  907. this.validateGlobals(element.globals, element.name);
  908. this.validateProcessor(element.processor, element.name, getPluginProcessor);
  909. this.validateRules(element.rules, element.name, getPluginRule);
  910. }
  911. }
  912. }
  913. /**
  914. * @fileoverview Common helpers for naming of plugins, formatters and configs
  915. */
  916. const NAMESPACE_REGEX = /^@.*\//iu;
  917. /**
  918. * Brings package name to correct format based on prefix
  919. * @param {string} name The name of the package.
  920. * @param {string} prefix Can be either "eslint-plugin", "eslint-config" or "eslint-formatter"
  921. * @returns {string} Normalized name of the package
  922. * @private
  923. */
  924. function normalizePackageName(name, prefix) {
  925. let normalizedName = name;
  926. /**
  927. * On Windows, name can come in with Windows slashes instead of Unix slashes.
  928. * Normalize to Unix first to avoid errors later on.
  929. * https://github.com/eslint/eslint/issues/5644
  930. */
  931. if (normalizedName.includes("\\")) {
  932. normalizedName = normalizedName.replace(/\\/gu, "/");
  933. }
  934. if (normalizedName.charAt(0) === "@") {
  935. /**
  936. * it's a scoped package
  937. * package name is the prefix, or just a username
  938. */
  939. const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`, "u"),
  940. scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`, "u");
  941. if (scopedPackageShortcutRegex.test(normalizedName)) {
  942. normalizedName = normalizedName.replace(scopedPackageShortcutRegex, `$1/${prefix}`);
  943. } else if (!scopedPackageNameRegex.test(normalizedName.split("/")[1])) {
  944. /**
  945. * for scoped packages, insert the prefix after the first / unless
  946. * the path is already @scope/eslint or @scope/eslint-xxx-yyy
  947. */
  948. normalizedName = normalizedName.replace(/^@([^/]+)\/(.*)$/u, `@$1/${prefix}-$2`);
  949. }
  950. } else if (!normalizedName.startsWith(`${prefix}-`)) {
  951. normalizedName = `${prefix}-${normalizedName}`;
  952. }
  953. return normalizedName;
  954. }
  955. /**
  956. * Removes the prefix from a fullname.
  957. * @param {string} fullname The term which may have the prefix.
  958. * @param {string} prefix The prefix to remove.
  959. * @returns {string} The term without prefix.
  960. */
  961. function getShorthandName(fullname, prefix) {
  962. if (fullname[0] === "@") {
  963. let matchResult = new RegExp(`^(@[^/]+)/${prefix}$`, "u").exec(fullname);
  964. if (matchResult) {
  965. return matchResult[1];
  966. }
  967. matchResult = new RegExp(`^(@[^/]+)/${prefix}-(.+)$`, "u").exec(fullname);
  968. if (matchResult) {
  969. return `${matchResult[1]}/${matchResult[2]}`;
  970. }
  971. } else if (fullname.startsWith(`${prefix}-`)) {
  972. return fullname.slice(prefix.length + 1);
  973. }
  974. return fullname;
  975. }
  976. /**
  977. * Gets the scope (namespace) of a term.
  978. * @param {string} term The term which may have the namespace.
  979. * @returns {string} The namespace of the term if it has one.
  980. */
  981. function getNamespaceFromTerm(term) {
  982. const match = term.match(NAMESPACE_REGEX);
  983. return match ? match[0] : "";
  984. }
  985. var naming = {
  986. __proto__: null,
  987. normalizePackageName: normalizePackageName,
  988. getShorthandName: getShorthandName,
  989. getNamespaceFromTerm: getNamespaceFromTerm
  990. };
  991. /**
  992. * @fileoverview Package exports for @eslint/eslintrc
  993. * @author Nicholas C. Zakas
  994. */
  995. //-----------------------------------------------------------------------------
  996. // Exports
  997. //-----------------------------------------------------------------------------
  998. const Legacy = {
  999. environments,
  1000. // shared
  1001. ConfigOps,
  1002. ConfigValidator,
  1003. naming
  1004. };
  1005. exports.Legacy = Legacy;
  1006. //# sourceMappingURL=eslintrc-universal.cjs.map