eslint 7.25.0 → 7.29.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.
Files changed (65) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +7 -7
  3. package/bin/eslint.js +2 -12
  4. package/lib/cli-engine/cli-engine.js +2 -7
  5. package/lib/cli-engine/file-enumerator.js +1 -1
  6. package/lib/cli-engine/formatters/html.js +193 -9
  7. package/lib/eslint/eslint.js +38 -2
  8. package/lib/init/autoconfig.js +2 -2
  9. package/lib/init/config-file.js +1 -0
  10. package/lib/init/config-initializer.js +14 -1
  11. package/lib/init/npm-utils.js +2 -2
  12. package/lib/linter/apply-disable-directives.js +15 -3
  13. package/lib/linter/linter.js +15 -9
  14. package/lib/linter/node-event-generator.js +43 -6
  15. package/lib/rule-tester/rule-tester.js +83 -23
  16. package/lib/rules/arrow-body-style.js +21 -11
  17. package/lib/rules/comma-dangle.js +16 -7
  18. package/lib/rules/comma-spacing.js +1 -1
  19. package/lib/rules/comma-style.js +1 -2
  20. package/lib/rules/complexity.js +2 -3
  21. package/lib/rules/consistent-return.js +2 -2
  22. package/lib/rules/eol-last.js +2 -7
  23. package/lib/rules/indent.js +10 -13
  24. package/lib/rules/max-lines-per-function.js +2 -3
  25. package/lib/rules/max-lines.js +32 -7
  26. package/lib/rules/max-params.js +2 -3
  27. package/lib/rules/max-statements.js +2 -3
  28. package/lib/rules/no-duplicate-imports.js +214 -66
  29. package/lib/rules/no-fallthrough.js +18 -13
  30. package/lib/rules/no-implicit-coercion.js +21 -2
  31. package/lib/rules/no-restricted-imports.js +61 -24
  32. package/lib/rules/no-unused-vars.js +40 -10
  33. package/lib/rules/no-useless-backreference.js +1 -2
  34. package/lib/rules/no-useless-computed-key.js +8 -2
  35. package/lib/rules/no-warning-comments.js +1 -1
  36. package/lib/rules/object-curly-newline.js +19 -4
  37. package/lib/rules/radix.js +19 -3
  38. package/lib/rules/require-atomic-updates.js +23 -20
  39. package/lib/rules/spaced-comment.js +2 -2
  40. package/lib/rules/utils/ast-utils.js +2 -2
  41. package/lib/shared/deprecation-warnings.js +12 -3
  42. package/lib/shared/string-utils.js +22 -0
  43. package/lib/source-code/source-code.js +6 -5
  44. package/lib/source-code/token-store/utils.js +4 -12
  45. package/messages/{all-files-ignored.txt → all-files-ignored.js} +10 -2
  46. package/messages/extend-config-missing.js +13 -0
  47. package/messages/failed-to-read-json.js +11 -0
  48. package/messages/file-not-found.js +10 -0
  49. package/messages/{no-config-found.txt → no-config-found.js} +9 -1
  50. package/messages/plugin-conflict.js +22 -0
  51. package/messages/plugin-invalid.js +16 -0
  52. package/messages/plugin-missing.js +19 -0
  53. package/messages/{print-config-with-directory-path.txt → print-config-with-directory-path.js} +6 -0
  54. package/messages/whitespace-found.js +11 -0
  55. package/package.json +8 -8
  56. package/lib/cli-engine/formatters/html-template-message.html +0 -8
  57. package/lib/cli-engine/formatters/html-template-page.html +0 -115
  58. package/lib/cli-engine/formatters/html-template-result.html +0 -6
  59. package/messages/extend-config-missing.txt +0 -5
  60. package/messages/failed-to-read-json.txt +0 -3
  61. package/messages/file-not-found.txt +0 -2
  62. package/messages/plugin-conflict.txt +0 -7
  63. package/messages/plugin-invalid.txt +0 -8
  64. package/messages/plugin-missing.txt +0 -11
  65. package/messages/whitespace-found.txt +0 -3
package/CHANGELOG.md CHANGED
@@ -1,3 +1,58 @@
1
+ v7.29.0 - June 18, 2021
2
+
3
+ * [`bfbfe5c`](https://github.com/eslint/eslint/commit/bfbfe5c1fd4c39a06d5e159dbe48479ca4305fc0) New: Add only to RuleTester (refs eslint/rfcs#73) (#14677) (Brandon Mills)
4
+ * [`c2cd7b4`](https://github.com/eslint/eslint/commit/c2cd7b4a18057ca6067bdfc16de771dc5d90c0ea) New: Add ESLint#getRulesMetaForResults() (refs #13654) (#14716) (Nicholas C. Zakas)
5
+ * [`eea7e0d`](https://github.com/eslint/eslint/commit/eea7e0d09d6ef43d6663cbe424e7974764a5f7fe) Chore: remove duplicate code (#14719) (Nitin Kumar)
6
+ * [`6a1c7a0`](https://github.com/eslint/eslint/commit/6a1c7a0dac050ea5876972c50563a7eb867b38d3) Fix: allow fallthrough comment inside block (fixes #14701) (#14702) (Kevin Gibbons)
7
+ * [`a47e5e3`](https://github.com/eslint/eslint/commit/a47e5e30b0da364593b6881f6826c595da8696f5) Docs: Add Mega-Linter to the list of integrations (#14707) (Nicolas Vuillamy)
8
+ * [`353ddf9`](https://github.com/eslint/eslint/commit/353ddf965078030794419b089994373e27ffc86e) Chore: enable reportUnusedDisableDirectives in eslint-config-eslint (#14699) (薛定谔的猫)
9
+ * [`757c495`](https://github.com/eslint/eslint/commit/757c49584a5852c468c1b4a0b74ad3aa39d954e5) Chore: add some rules to eslint-config-eslint (#14692) (薛定谔的猫)
10
+ * [`c93a222`](https://github.com/eslint/eslint/commit/c93a222563177a9b5bc7a59aa106bc0a6d31e063) Docs: fix a broken link (#14697) (Sam Chen)
11
+ * [`655c118`](https://github.com/eslint/eslint/commit/655c1187fc845bac61ae8d06c556f1a59ee2071b) Sponsors: Sync README with website (ESLint Jenkins)
12
+ * [`e2bed2e`](https://github.com/eslint/eslint/commit/e2bed2ead22b575d55ccaeed94eecd3a979dd871) Sponsors: Sync README with website (ESLint Jenkins)
13
+ * [`8490fb4`](https://github.com/eslint/eslint/commit/8490fb42e559ef0b3c34ac60be4e05e0d879a9cb) Sponsors: Sync README with website (ESLint Jenkins)
14
+ * [`ddbe877`](https://github.com/eslint/eslint/commit/ddbe877c95224e127215d35562a175c6f2b7ba22) Sponsors: Sync README with website (ESLint Jenkins)
15
+
16
+ v7.28.0 - June 4, 2021
17
+
18
+ * [`1237705`](https://github.com/eslint/eslint/commit/1237705dd08c209c5e3136045ec51a4ba87a3abe) Upgrade: @eslint/eslintrc to 0.4.2 (#14672) (Milos Djermanovic)
19
+ * [`123fb86`](https://github.com/eslint/eslint/commit/123fb8648731c2c23313c544ffa1872d3024fe68) Docs: Add Feedback Needed triage description (#14670) (Nicholas C. Zakas)
20
+ * [`c545163`](https://github.com/eslint/eslint/commit/c5451635b4e89827cfc8d8d77083647c74506e42) Update: support multiline /*eslint-env*/ directives (fixes #14652) (#14660) (薛定谔的猫)
21
+ * [`8d1e75a`](https://github.com/eslint/eslint/commit/8d1e75a31b3e3d67130709a219bdd07ce6f3cf74) Upgrade: glob-parent version in package.json (#14658) (Hamza Najeeb)
22
+ * [`1f048cb`](https://github.com/eslint/eslint/commit/1f048cb0eec660d2052f1758f4b2ad7b1cb424e1) Fix: no-implicit-coercion false positive with `String()` (fixes #14623) (#14641) (Milos Djermanovic)
23
+ * [`d709abf`](https://github.com/eslint/eslint/commit/d709abfdde087325d4578b6709dc61040b8ca9d8) Chore: fix comment location in no-unused-vars (#14648) (Milos Djermanovic)
24
+ * [`e44ce0a`](https://github.com/eslint/eslint/commit/e44ce0a8acfaad513c385150c25e76e82a1b8f12) Fix: no-duplicate-imports allow unmergeable (fixes #12758, fixes #12760) (#14238) (Soufiane Boutahlil)
25
+ * [`bb66a3d`](https://github.com/eslint/eslint/commit/bb66a3d91af426dac9a7ffdbe47bdbbc0ffd4dd7) New: add `getPhysicalFilename()` method to rule context (fixes #11989) (#14616) (Nitin Kumar)
26
+ * [`2e43dac`](https://github.com/eslint/eslint/commit/2e43dacd24337a82d4184fac9b44d497675f46ef) Docs: fix `no-sequences` example (#14643) (Nitin Kumar)
27
+ * [`958ff4e`](https://github.com/eslint/eslint/commit/958ff4e8a5102f204f1484d09985e28a79790996) Docs: add note for arrow functions in no-seq rule (#14578) (Nitin Kumar)
28
+ * [`e4f111b`](https://github.com/eslint/eslint/commit/e4f111b67d114adbf76a9c9dbb18fa4f49bc91b6) Fix: arrow-body-style crash with object pattern (fixes #14633) (#14635) (Milos Djermanovic)
29
+ * [`ec28b5a`](https://github.com/eslint/eslint/commit/ec28b5a2bdc69f34ce29d670f5e84d2446774a00) Chore: upgrade eslint-plugin-eslint-plugin (#14590) (薛定谔的猫)
30
+ * [`85a2725`](https://github.com/eslint/eslint/commit/85a2725b1fade5538e727102d9701ccb503e54d4) Docs: Update README team and sponsors (ESLint Jenkins)
31
+
32
+ v7.27.0 - May 21, 2021
33
+
34
+ * [`2c0868c`](https://github.com/eslint/eslint/commit/2c0868cbeadc9f42716fa1178ebdc6b4cee6d31e) Chore: merge all html formatter files into `html.js` (#14612) (Milos Djermanovic)
35
+ * [`9e9b5e0`](https://github.com/eslint/eslint/commit/9e9b5e07475564813b62cd1d7562a93c5fb4bc74) Update: no-unused-vars false negative with comma operator (fixes #14325) (#14354) (Nitin Kumar)
36
+ * [`afe9569`](https://github.com/eslint/eslint/commit/afe95693e1e4316a1c6f01d39345061d4c5921c7) Chore: use includes instead of indexOf (#14607) (Mikhail Bodrov)
37
+ * [`c0f418e`](https://github.com/eslint/eslint/commit/c0f418e2476df98519bc156b81d20431984e8704) Chore: Remove lodash (#14287) (Stephen Wade)
38
+ * [`52655dd`](https://github.com/eslint/eslint/commit/52655dd54925ee02af2ba3a0ebc09de959ae3101) Update: no-restricted-imports custom message for patterns (fixes #11843) (#14580) (Alex Holden)
39
+ * [`967b1c4`](https://github.com/eslint/eslint/commit/967b1c4ceca8f5248378477da94ff118dafaa647) Chore: Fix typo in large.js (#14589) (Ikko Ashimine)
40
+ * [`2466a05`](https://github.com/eslint/eslint/commit/2466a05160de60958457d984b79fd445c12ebc98) Sponsors: Sync README with website (ESLint Jenkins)
41
+ * [`fe29f18`](https://github.com/eslint/eslint/commit/fe29f18227fd02fd7c3da033417d621275b00d0a) Sponsors: Sync README with website (ESLint Jenkins)
42
+ * [`086c1d6`](https://github.com/eslint/eslint/commit/086c1d6e8593cf8e7851daa8f2a890c213cf6999) Chore: add more test cases for `no-sequences` (#14579) (Nitin Kumar)
43
+ * [`6a2ced8`](https://github.com/eslint/eslint/commit/6a2ced892c0dc43fa4942293b9f1c4b9151c3741) Docs: Update README team and sponsors (ESLint Jenkins)
44
+
45
+ v7.26.0 - May 7, 2021
46
+
47
+ * [`aaf65e6`](https://github.com/eslint/eslint/commit/aaf65e629adb74401092c3ccc9cb4e4bd1c8609b) Upgrade: eslintrc for ModuleResolver fix (#14577) (Brandon Mills)
48
+ * [`ae6dbd1`](https://github.com/eslint/eslint/commit/ae6dbd148aaca83e4bd04b9351b54029c50fac8a) Fix: track variables, not names in require-atomic-updates (fixes #14208) (#14282) (Patrick Ahmetovic)
49
+ * [`6a86e50`](https://github.com/eslint/eslint/commit/6a86e5018a3733049c09261bcabae422fbea893d) Chore: remove loose-parser tests (fixes #14315) (#14569) (Milos Djermanovic)
50
+ * [`ee3a3ea`](https://github.com/eslint/eslint/commit/ee3a3ead893d185cc4b1ae9041940cb0968767e1) Fix: create `.eslintrc.cjs` for `module` type (#14304) (Nitin Kumar)
51
+ * [`6791dec`](https://github.com/eslint/eslint/commit/6791decfc58b7b09cfd0aabd15a3d14148aae073) Docs: fix example for require-atomic-updates (#14562) (Milos Djermanovic)
52
+ * [`388eb7e`](https://github.com/eslint/eslint/commit/388eb7e14039b8951462b311d6121002ca5232cb) Sponsors: Sync README with website (ESLint Jenkins)
53
+ * [`f071d1e`](https://github.com/eslint/eslint/commit/f071d1ef91286bf2e3fb63d9b679ff7702819a1e) Update: Add automated suggestion to `radix` rule for parsing decimals (#14291) (Bryan Mishkin)
54
+ * [`0b6a3f3`](https://github.com/eslint/eslint/commit/0b6a3f31e6e78825114f82d4e0aed9cd72f784ac) New: Include XO style guide in `eslint --init` (#14193) (Federico Brigante)
55
+
1
56
  v7.25.0 - April 23, 2021
2
57
 
3
58
  * [`5df5e4a`](https://github.com/eslint/eslint/commit/5df5e4a9976964fcf4dc67e241d4e22ec1370fe0) Update: highlight last write reference for no-unused-vars (fixes #14324) (#14335) (Nitin Kumar)
package/README.md CHANGED
@@ -223,11 +223,6 @@ Nicholas C. Zakas
223
223
  Brandon Mills
224
224
  </a>
225
225
  </td><td align="center" valign="top" width="11%">
226
- <a href="https://github.com/mysticatea">
227
- <img src="https://github.com/mysticatea.png?s=75" width="75" height="75"><br />
228
- Toru Nagashima
229
- </a>
230
- </td><td align="center" valign="top" width="11%">
231
226
  <a href="https://github.com/mdjermanovic">
232
227
  <img src="https://github.com/mdjermanovic.png?s=75" width="75" height="75"><br />
233
228
  Milos Djermanovic
@@ -240,6 +235,11 @@ Milos Djermanovic
240
235
  The people who review and implement new features.
241
236
 
242
237
  <table><tbody><tr><td align="center" valign="top" width="11%">
238
+ <a href="https://github.com/mysticatea">
239
+ <img src="https://github.com/mysticatea.png?s=75" width="75" height="75"><br />
240
+ Toru Nagashima
241
+ </a>
242
+ </td><td align="center" valign="top" width="11%">
243
243
  <a href="https://github.com/aladdin-add">
244
244
  <img src="https://github.com/aladdin-add.png?s=75" width="75" height="75"><br />
245
245
  薛定谔的猫
@@ -281,9 +281,9 @@ The following companies, organizations, and individuals support ESLint's ongoing
281
281
  <!--sponsorsstart-->
282
282
  <h3>Platinum Sponsors</h3>
283
283
  <p><a href="https://automattic.com"><img src="https://images.opencollective.com/photomatt/d0ef3e1/logo.png" alt="Automattic" height="undefined"></a></p><h3>Gold Sponsors</h3>
284
- <p><a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" height="96"></a> <a href="https://google.com/chrome"><img src="https://images.opencollective.com/chrome/dc55bd4/logo.png" alt="Chrome's Web Framework & Tools Performance Fund" height="96"></a> <a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/e780cd4/logo.png" alt="Shopify" height="96"></a> <a href="https://www.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> <a href="https://opensource.microsoft.com"><img src="https://avatars.githubusercontent.com/u/6154722?v=4" alt="Microsoft" height="96"></a> <a href="https://substack.com/"><img src="https://avatars.githubusercontent.com/u/53023767?v=4" alt="Substack" height="96"></a></p><h3>Silver Sponsors</h3>
284
+ <p><a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" height="96"></a> <a href="https://google.com/chrome"><img src="https://images.opencollective.com/chrome/dc55bd4/logo.png" alt="Chrome's Web Framework & Tools Performance Fund" height="96"></a> <a href="https://www.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> <a href="https://coinbase.com"><img src="https://avatars.githubusercontent.com/u/1885080?v=4" alt="Coinbase" height="96"></a> <a href="https://substack.com/"><img src="https://avatars.githubusercontent.com/u/53023767?v=4" alt="Substack" height="96"></a></p><h3>Silver Sponsors</h3>
285
285
  <p><a href="https://retool.com/"><img src="https://images.opencollective.com/retool/98ea68e/logo.png" alt="Retool" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a></p><h3>Bronze Sponsors</h3>
286
- <p><a href="https://buy.fineproxy.org/eng/"><img src="https://images.opencollective.com/buy-fineproxy-org/b282e39/logo.png" alt="Buy.Fineproxy.Org" 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="null"><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" 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.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a></p>
286
+ <p><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="null"><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" 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.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://www.practiceignition.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Practice Ignition" height="32"></a></p>
287
287
  <!--sponsorsend-->
288
288
 
289
289
  ## <a name="technology-sponsors"></a>Technology Sponsors
package/bin/eslint.js CHANGED
@@ -66,11 +66,8 @@ function readStdin() {
66
66
  */
67
67
  function getErrorMessage(error) {
68
68
 
69
- // Lazy loading because those are used only if error happened.
70
- const fs = require("fs");
71
- const path = require("path");
69
+ // Lazy loading because this is used only if an error happened.
72
70
  const util = require("util");
73
- const lodash = require("lodash");
74
71
 
75
72
  // Foolproof -- thirdparty module might throw non-object.
76
73
  if (typeof error !== "object" || error === null) {
@@ -80,14 +77,7 @@ function getErrorMessage(error) {
80
77
  // Use templates if `error.messageTemplate` is present.
81
78
  if (typeof error.messageTemplate === "string") {
82
79
  try {
83
- const templateFilePath = path.resolve(
84
- __dirname,
85
- `../messages/${error.messageTemplate}.txt`
86
- );
87
-
88
- // Use sync API because Node.js should exit at this tick.
89
- const templateText = fs.readFileSync(templateFilePath, "utf-8");
90
- const template = lodash.template(templateText);
80
+ const template = require(`../messages/${error.messageTemplate}.js`);
91
81
 
92
82
  return template(error.messageData || {});
93
83
  } catch {
@@ -27,16 +27,11 @@ const {
27
27
  naming,
28
28
  CascadingConfigArrayFactory,
29
29
  IgnorePattern,
30
- getUsedExtractedConfigs
30
+ getUsedExtractedConfigs,
31
+ ModuleResolver
31
32
  }
32
33
  } = require("@eslint/eslintrc");
33
34
 
34
- /*
35
- * For some reason, ModuleResolver must be included via filepath instead of by
36
- * API exports in order to work properly. That's why this is separated out onto
37
- * its own require() statement.
38
- */
39
- const ModuleResolver = require("@eslint/eslintrc/lib/shared/relative-module-resolver");
40
35
  const { FileEnumerator } = require("./file-enumerator");
41
36
 
42
37
  const { Linter } = require("../linter");
@@ -38,7 +38,7 @@ const fs = require("fs");
38
38
  const path = require("path");
39
39
  const getGlobParent = require("glob-parent");
40
40
  const isGlob = require("is-glob");
41
- const { escapeRegExp } = require("lodash");
41
+ const escapeRegExp = require("escape-string-regexp");
42
42
  const { Minimatch } = require("minimatch");
43
43
 
44
44
  const {
@@ -4,17 +4,153 @@
4
4
  */
5
5
  "use strict";
6
6
 
7
- const lodash = require("lodash");
8
- const fs = require("fs");
9
- const path = require("path");
10
-
11
7
  //------------------------------------------------------------------------------
12
8
  // Helpers
13
9
  //------------------------------------------------------------------------------
14
10
 
15
- const pageTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-page.html"), "utf-8"));
16
- const messageTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-message.html"), "utf-8"));
17
- const resultTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-result.html"), "utf-8"));
11
+ const encodeHTML = (function() {
12
+ const encodeHTMLRules = {
13
+ "&": "&#38;",
14
+ "<": "&#60;",
15
+ ">": "&#62;",
16
+ '"': "&#34;",
17
+ "'": "&#39;"
18
+ };
19
+ const matchHTML = /[&<>"']/ug;
20
+
21
+ return function(code) {
22
+ return code
23
+ ? code.toString().replace(matchHTML, m => encodeHTMLRules[m] || m)
24
+ : "";
25
+ };
26
+ }());
27
+
28
+ /**
29
+ * Get the final HTML document.
30
+ * @param {Object} it data for the document.
31
+ * @returns {string} HTML document.
32
+ */
33
+ function pageTemplate(it) {
34
+ const { reportColor, reportSummary, date, results } = it;
35
+
36
+ return `
37
+ <!DOCTYPE html>
38
+ <html>
39
+ <head>
40
+ <meta charset="UTF-8">
41
+ <title>ESLint Report</title>
42
+ <style>
43
+ body {
44
+ font-family:Arial, "Helvetica Neue", Helvetica, sans-serif;
45
+ font-size:16px;
46
+ font-weight:normal;
47
+ margin:0;
48
+ padding:0;
49
+ color:#333
50
+ }
51
+ #overview {
52
+ padding:20px 30px
53
+ }
54
+ td, th {
55
+ padding:5px 10px
56
+ }
57
+ h1 {
58
+ margin:0
59
+ }
60
+ table {
61
+ margin:30px;
62
+ width:calc(100% - 60px);
63
+ max-width:1000px;
64
+ border-radius:5px;
65
+ border:1px solid #ddd;
66
+ border-spacing:0px;
67
+ }
68
+ th {
69
+ font-weight:400;
70
+ font-size:medium;
71
+ text-align:left;
72
+ cursor:pointer
73
+ }
74
+ td.clr-1, td.clr-2, th span {
75
+ font-weight:700
76
+ }
77
+ th span {
78
+ float:right;
79
+ margin-left:20px
80
+ }
81
+ th span:after {
82
+ content:"";
83
+ clear:both;
84
+ display:block
85
+ }
86
+ tr:last-child td {
87
+ border-bottom:none
88
+ }
89
+ tr td:first-child, tr td:last-child {
90
+ color:#9da0a4
91
+ }
92
+ #overview.bg-0, tr.bg-0 th {
93
+ color:#468847;
94
+ background:#dff0d8;
95
+ border-bottom:1px solid #d6e9c6
96
+ }
97
+ #overview.bg-1, tr.bg-1 th {
98
+ color:#f0ad4e;
99
+ background:#fcf8e3;
100
+ border-bottom:1px solid #fbeed5
101
+ }
102
+ #overview.bg-2, tr.bg-2 th {
103
+ color:#b94a48;
104
+ background:#f2dede;
105
+ border-bottom:1px solid #eed3d7
106
+ }
107
+ td {
108
+ border-bottom:1px solid #ddd
109
+ }
110
+ td.clr-1 {
111
+ color:#f0ad4e
112
+ }
113
+ td.clr-2 {
114
+ color:#b94a48
115
+ }
116
+ td a {
117
+ color:#3a33d1;
118
+ text-decoration:none
119
+ }
120
+ td a:hover {
121
+ color:#272296;
122
+ text-decoration:underline
123
+ }
124
+ </style>
125
+ </head>
126
+ <body>
127
+ <div id="overview" class="bg-${reportColor}">
128
+ <h1>ESLint Report</h1>
129
+ <div>
130
+ <span>${reportSummary}</span> - Generated on ${date}
131
+ </div>
132
+ </div>
133
+ <table>
134
+ <tbody>
135
+ ${results}
136
+ </tbody>
137
+ </table>
138
+ <script type="text/javascript">
139
+ var groups = document.querySelectorAll("tr[data-group]");
140
+ for (i = 0; i < groups.length; i++) {
141
+ groups[i].addEventListener("click", function() {
142
+ var inGroup = document.getElementsByClassName(this.getAttribute("data-group"));
143
+ this.innerHTML = (this.innerHTML.indexOf("+") > -1) ? this.innerHTML.replace("+", "-") : this.innerHTML.replace("-", "+");
144
+ for (var j = 0; j < inGroup.length; j++) {
145
+ inGroup[j].style.display = (inGroup[j].style.display !== "none") ? "none" : "table-row";
146
+ }
147
+ });
148
+ }
149
+ </script>
150
+ </body>
151
+ </html>
152
+ `.trimLeft();
153
+ }
18
154
 
19
155
  /**
20
156
  * Given a word and a count, append an s if count is not one.
@@ -58,6 +194,35 @@ function renderColor(totalErrors, totalWarnings) {
58
194
  return 0;
59
195
  }
60
196
 
197
+ /**
198
+ * Get HTML (table row) describing a single message.
199
+ * @param {Object} it data for the message.
200
+ * @returns {string} HTML (table row) describing the message.
201
+ */
202
+ function messageTemplate(it) {
203
+ const {
204
+ parentIndex,
205
+ lineNumber,
206
+ columnNumber,
207
+ severityNumber,
208
+ severityName,
209
+ message,
210
+ ruleUrl,
211
+ ruleId
212
+ } = it;
213
+
214
+ return `
215
+ <tr style="display:none" class="f-${parentIndex}">
216
+ <td>${lineNumber}:${columnNumber}</td>
217
+ <td class="clr-${severityNumber}">${severityName}</td>
218
+ <td>${encodeHTML(message)}</td>
219
+ <td>
220
+ <a href="${ruleUrl ? ruleUrl : ""}" target="_blank" rel="noopener noreferrer">${ruleId ? ruleId : ""}</a>
221
+ </td>
222
+ </tr>
223
+ `.trimLeft();
224
+ }
225
+
61
226
  /**
62
227
  * Get HTML (table rows) describing the messages.
63
228
  * @param {Array} messages Messages.
@@ -80,7 +245,9 @@ function renderMessages(messages, parentIndex, rulesMeta) {
80
245
  if (rulesMeta) {
81
246
  const meta = rulesMeta[message.ruleId];
82
247
 
83
- ruleUrl = lodash.get(meta, "docs.url", null);
248
+ if (meta && meta.docs && meta.docs.url) {
249
+ ruleUrl = meta.docs.url;
250
+ }
84
251
  }
85
252
 
86
253
  return messageTemplate({
@@ -96,6 +263,24 @@ function renderMessages(messages, parentIndex, rulesMeta) {
96
263
  }).join("\n");
97
264
  }
98
265
 
266
+ /**
267
+ * Get HTML (table row) describing the result for a single file.
268
+ * @param {Object} it data for the file.
269
+ * @returns {string} HTML (table row) describing the result for the file.
270
+ */
271
+ function resultTemplate(it) {
272
+ const { color, index, filePath, summary } = it;
273
+
274
+ return `
275
+ <tr class="bg-${color}" data-group="f-${index}">
276
+ <th colspan="4">
277
+ [+] ${encodeHTML(filePath)}
278
+ <span>${encodeHTML(summary)}</span>
279
+ </th>
280
+ </tr>
281
+ `.trimLeft();
282
+ }
283
+
99
284
  // eslint-disable-next-line jsdoc/require-description
100
285
  /**
101
286
  * @param {Array} results Test results.
@@ -108,7 +293,6 @@ function renderResults(results, rulesMeta) {
108
293
  color: renderColor(result.errorCount, result.warningCount),
109
294
  filePath: result.filePath,
110
295
  summary: renderSummary(result.errorCount, result.warningCount)
111
-
112
296
  }) + renderMessages(result.messages, index, rulesMeta)).join("\n");
113
297
  }
114
298
 
@@ -514,6 +514,39 @@ class ESLint {
514
514
  return CLIEngine.getErrorResults(results);
515
515
  }
516
516
 
517
+ /**
518
+ * Returns meta objects for each rule represented in the lint results.
519
+ * @param {LintResult[]} results The results to fetch rules meta for.
520
+ * @returns {Object} A mapping of ruleIds to rule meta objects.
521
+ */
522
+ getRulesMetaForResults(results) {
523
+
524
+ const resultRuleIds = new Set();
525
+
526
+ // first gather all ruleIds from all results
527
+
528
+ for (const result of results) {
529
+ for (const { ruleId } of result.messages) {
530
+ resultRuleIds.add(ruleId);
531
+ }
532
+ }
533
+
534
+ // create a map of all rules in the results
535
+
536
+ const { cliEngine } = privateMembersMap.get(this);
537
+ const rules = cliEngine.getRules();
538
+ const resultRules = new Map();
539
+
540
+ for (const [ruleId, rule] of rules) {
541
+ if (resultRuleIds.has(ruleId)) {
542
+ resultRules.set(ruleId, rule);
543
+ }
544
+ }
545
+
546
+ return createRulesMeta(resultRules);
547
+
548
+ }
549
+
517
550
  /**
518
551
  * Executes the current configuration on an array of file and directory names.
519
552
  * @param {string[]} patterns An array of file and directory names.
@@ -552,9 +585,12 @@ class ESLint {
552
585
  ...unknownOptions
553
586
  } = options || {};
554
587
 
555
- for (const key of Object.keys(unknownOptions)) {
556
- throw new Error(`'options' must not include the unknown option '${key}'`);
588
+ const unknownOptionKeys = Object.keys(unknownOptions);
589
+
590
+ if (unknownOptionKeys.length > 0) {
591
+ throw new Error(`'options' must not include the unknown option(s): ${unknownOptionKeys.join(", ")}`);
557
592
  }
593
+
558
594
  if (filePath !== void 0 && !isNonEmptyString(filePath)) {
559
595
  throw new Error("'options.filePath' must be a non-empty string or undefined");
560
596
  }
@@ -9,7 +9,7 @@
9
9
  // Requirements
10
10
  //------------------------------------------------------------------------------
11
11
 
12
- const lodash = require("lodash"),
12
+ const equal = require("fast-deep-equal"),
13
13
  recConfig = require("../../conf/eslint-recommended"),
14
14
  ConfigOps = require("@eslint/eslintrc/lib/shared/config-ops"),
15
15
  { Linter } = require("../linter"),
@@ -329,7 +329,7 @@ function extendFromRecommended(config) {
329
329
  const recRules = Object.keys(recConfig.rules).filter(ruleId => ConfigOps.isErrorSeverity(recConfig.rules[ruleId]));
330
330
 
331
331
  recRules.forEach(ruleId => {
332
- if (lodash.isEqual(recConfig.rules[ruleId], newConfig.rules[ruleId])) {
332
+ if (equal(recConfig.rules[ruleId], newConfig.rules[ruleId])) {
333
333
  delete newConfig.rules[ruleId];
334
334
  }
335
335
  });
@@ -117,6 +117,7 @@ function writeJSConfigFile(config, filePath) {
117
117
  function write(config, filePath) {
118
118
  switch (path.extname(filePath)) {
119
119
  case ".js":
120
+ case ".cjs":
120
121
  writeJSConfigFile(config, filePath);
121
122
  break;
122
123
 
@@ -12,6 +12,7 @@
12
12
 
13
13
  const util = require("util"),
14
14
  path = require("path"),
15
+ fs = require("fs"),
15
16
  enquirer = require("enquirer"),
16
17
  ProgressBar = require("progress"),
17
18
  semver = require("semver"),
@@ -48,6 +49,16 @@ function writeFile(config, format) {
48
49
  extname = ".yml";
49
50
  } else if (format === "JSON") {
50
51
  extname = ".json";
52
+ } else if (format === "JavaScript") {
53
+ const pkgJSONPath = npmUtils.findPackageJson();
54
+
55
+ if (pkgJSONPath) {
56
+ const pkgJSONContents = JSON.parse(fs.readFileSync(pkgJSONPath, "utf8"));
57
+
58
+ if (pkgJSONContents.type === "module") {
59
+ extname = ".cjs";
60
+ }
61
+ }
51
62
  }
52
63
 
53
64
  const installedESLint = config.installedESLint;
@@ -531,7 +542,8 @@ function promptUser() {
531
542
  choices: [
532
543
  { message: "Airbnb: https://github.com/airbnb/javascript", name: "airbnb" },
533
544
  { message: "Standard: https://github.com/standard/standard", name: "standard" },
534
- { message: "Google: https://github.com/google/eslint-config-google", name: "google" }
545
+ { message: "Google: https://github.com/google/eslint-config-google", name: "google" },
546
+ { message: "XO: https://github.com/xojs/eslint-config-xo", name: "xo" }
535
547
  ],
536
548
  skip() {
537
549
  this.state.answers.packageJsonExists = npmUtils.checkPackageJson();
@@ -683,6 +695,7 @@ const init = {
683
695
  hasESLintVersionConflict,
684
696
  installModules,
685
697
  processAnswers,
698
+ writeFile,
686
699
  /* istanbul ignore next */initializeConfig() {
687
700
  return promptUser();
688
701
  }
@@ -50,8 +50,7 @@ function findPackageJson(startDir) {
50
50
  */
51
51
  function installSyncSaveDev(packages) {
52
52
  const packageList = Array.isArray(packages) ? packages : [packages];
53
- const npmProcess = spawn.sync("npm", ["i", "--save-dev"].concat(packageList),
54
- { stdio: "inherit" });
53
+ const npmProcess = spawn.sync("npm", ["i", "--save-dev"].concat(packageList), { stdio: "inherit" });
55
54
  const error = npmProcess.error;
56
55
 
57
56
  if (error && error.code === "ENOENT") {
@@ -172,6 +171,7 @@ function checkPackageJson(startDir) {
172
171
  module.exports = {
173
172
  installSyncSaveDev,
174
173
  fetchPeerDependencies,
174
+ findPackageJson,
175
175
  checkDeps,
176
176
  checkDevDeps,
177
177
  checkPackageJson
@@ -5,8 +5,6 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- const lodash = require("lodash");
9
-
10
8
  /**
11
9
  * Compares the locations of two objects in a source file
12
10
  * @param {{line: number, column: number}} itemA The first object
@@ -124,7 +122,21 @@ module.exports = ({ directives, problems, reportUnusedDisableDirectives = "off"
124
122
  .map(directive => Object.assign({}, directive, { unprocessedDirective: directive }))
125
123
  .sort(compareLocations);
126
124
 
127
- const lineDirectives = lodash.flatMap(directives, directive => {
125
+ /**
126
+ * Returns a new array formed by applying a given callback function to each element of the array, and then flattening the result by one level.
127
+ * TODO(stephenwade): Replace this with array.flatMap when we drop support for Node v10
128
+ * @param {any[]} array The array to process
129
+ * @param {Function} fn The function to use
130
+ * @returns {any[]} The result array
131
+ */
132
+ function flatMap(array, fn) {
133
+ const mapped = array.map(fn);
134
+ const flattened = [].concat(...mapped);
135
+
136
+ return flattened;
137
+ }
138
+
139
+ const lineDirectives = flatMap(directives, directive => {
128
140
  switch (directive.type) {
129
141
  case "disable":
130
142
  case "enable":