@luxass/eslint-config 4.0.0-beta.8 → 4.0.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 (149) hide show
  1. package/README.md +351 -48
  2. package/dist/{chunk-TQ476NL2.mjs → chunk-4YBQZLPS.mjs} +13 -2
  3. package/dist/{chunk-NDNDG7BH.mjs → chunk-5NK24IKQ.mjs} +2 -5
  4. package/dist/{chunk-2SW2E3TH.mjs → chunk-5SDSWPKR.mjs} +14 -4
  5. package/dist/chunk-6T7MXPCT.mjs +17 -0
  6. package/dist/{chunk-ADP4MYOS.mjs → chunk-ANUYBAYV.mjs} +1 -1
  7. package/dist/{chunk-R4NSLRAE.mjs → chunk-ATRL3UZP.mjs} +14 -8
  8. package/dist/{chunk-P3N5WLFL.mjs → chunk-BXBN56WI.mjs} +11 -7
  9. package/dist/chunk-CJ3ZUYUJ.mjs +183 -0
  10. package/dist/chunk-DAJA5AV3.mjs +29 -0
  11. package/dist/{chunk-FK567E7G.mjs → chunk-DVQQVCGF.mjs} +7 -3
  12. package/dist/chunk-DZCXT6HT.mjs +288 -0
  13. package/dist/chunk-FU5SRKZU.mjs +104 -0
  14. package/dist/{chunk-LQLF2CMA.mjs → chunk-GBLPCM3X.mjs} +14 -17
  15. package/dist/chunk-KJ7ZCBK4.mjs +48 -0
  16. package/dist/{chunk-BAKUP7QM.mjs → chunk-P3QUAOFO.mjs} +36 -34
  17. package/dist/{chunk-I2ECCPNN.mjs → chunk-PYS26PF3.mjs} +15 -10
  18. package/dist/chunk-Q57BF3CR.mjs +63 -0
  19. package/dist/{chunk-SPQZTV4E.mjs → chunk-QK56GX3F.mjs} +12 -14
  20. package/dist/{chunk-3QHLEAXK.mjs → chunk-RDZJT36Z.mjs} +22 -8
  21. package/dist/{chunk-HE56XDG6.mjs → chunk-RVSUTDCE.mjs} +15 -5
  22. package/dist/chunk-UMUUVFB7.mjs +69 -0
  23. package/dist/{chunk-NUG6FLHN.mjs → chunk-VZ2YFMWH.mjs} +54 -11
  24. package/dist/chunk-WDSV2EFG.mjs +7 -0
  25. package/dist/{chunk-M5WNLLBT.mjs → chunk-WOYZWHPM.mjs} +20 -7
  26. package/dist/chunk-WRURTO5T.mjs +144 -0
  27. package/dist/configs/astro.cjs +11 -21
  28. package/dist/configs/astro.d.cts +3 -6
  29. package/dist/configs/astro.d.ts +3 -6
  30. package/dist/configs/astro.mjs +3 -3
  31. package/dist/configs/comments.cjs +9 -12
  32. package/dist/configs/comments.d.cts +3 -2
  33. package/dist/configs/comments.d.ts +3 -2
  34. package/dist/configs/comments.mjs +1 -2
  35. package/dist/configs/formatters.cjs +274 -0
  36. package/dist/configs/formatters.d.cts +11 -0
  37. package/dist/configs/formatters.d.ts +11 -0
  38. package/dist/configs/formatters.mjs +9 -0
  39. package/dist/configs/ignores.cjs +1 -8
  40. package/dist/configs/ignores.d.cts +3 -2
  41. package/dist/configs/ignores.d.ts +3 -2
  42. package/dist/configs/ignores.mjs +2 -2
  43. package/dist/configs/imports.cjs +35 -9
  44. package/dist/configs/imports.d.cts +13 -4
  45. package/dist/configs/imports.d.ts +13 -4
  46. package/dist/configs/imports.mjs +2 -2
  47. package/dist/configs/index.cjs +1116 -707
  48. package/dist/configs/index.d.cts +7 -18
  49. package/dist/configs/index.d.ts +7 -18
  50. package/dist/configs/index.mjs +40 -36
  51. package/dist/configs/javascript.cjs +9 -23
  52. package/dist/configs/javascript.d.cts +3 -6
  53. package/dist/configs/javascript.d.ts +3 -6
  54. package/dist/configs/javascript.mjs +2 -3
  55. package/dist/configs/jsdoc.cjs +6 -2
  56. package/dist/configs/jsdoc.d.cts +17 -4
  57. package/dist/configs/jsdoc.d.ts +17 -4
  58. package/dist/configs/jsdoc.mjs +2 -2
  59. package/dist/configs/jsonc.cjs +8 -11
  60. package/dist/configs/jsonc.d.cts +3 -6
  61. package/dist/configs/jsonc.d.ts +3 -6
  62. package/dist/configs/jsonc.mjs +3 -3
  63. package/dist/configs/markdown.cjs +46 -35
  64. package/dist/configs/markdown.d.cts +25 -4
  65. package/dist/configs/markdown.d.ts +25 -4
  66. package/dist/configs/markdown.mjs +3 -3
  67. package/dist/configs/nextjs.cjs +15 -12
  68. package/dist/configs/nextjs.d.cts +3 -6
  69. package/dist/configs/nextjs.d.ts +3 -6
  70. package/dist/configs/nextjs.mjs +3 -3
  71. package/dist/configs/node.cjs +0 -10
  72. package/dist/configs/node.d.cts +3 -2
  73. package/dist/configs/node.d.ts +3 -2
  74. package/dist/configs/node.mjs +1 -2
  75. package/dist/configs/perfectionist.cjs +2 -20
  76. package/dist/configs/perfectionist.d.cts +4 -3
  77. package/dist/configs/perfectionist.d.ts +4 -3
  78. package/dist/configs/perfectionist.mjs +1 -2
  79. package/dist/configs/react.cjs +201 -203
  80. package/dist/configs/react.d.cts +3 -6
  81. package/dist/configs/react.d.ts +3 -6
  82. package/dist/configs/react.mjs +3 -3
  83. package/dist/configs/sort.cjs +6 -6
  84. package/dist/configs/sort.d.cts +3 -2
  85. package/dist/configs/sort.d.ts +3 -2
  86. package/dist/configs/sort.mjs +1 -1
  87. package/dist/configs/stylistic.cjs +20 -11
  88. package/dist/configs/stylistic.d.cts +4 -7
  89. package/dist/configs/stylistic.d.ts +4 -7
  90. package/dist/configs/stylistic.mjs +4 -3
  91. package/dist/configs/tailwindcss.cjs +34 -45
  92. package/dist/configs/tailwindcss.d.cts +3 -6
  93. package/dist/configs/tailwindcss.d.ts +3 -6
  94. package/dist/configs/tailwindcss.mjs +3 -3
  95. package/dist/configs/test.cjs +103 -16
  96. package/dist/configs/test.d.cts +3 -6
  97. package/dist/configs/test.d.ts +3 -6
  98. package/dist/configs/test.mjs +4 -3
  99. package/dist/configs/toml.cjs +131 -0
  100. package/dist/configs/toml.d.cts +11 -0
  101. package/dist/configs/toml.d.ts +11 -0
  102. package/dist/configs/toml.mjs +8 -0
  103. package/dist/configs/typescript.cjs +32 -43
  104. package/dist/configs/typescript.d.cts +3 -6
  105. package/dist/configs/typescript.d.ts +3 -6
  106. package/dist/configs/typescript.mjs +3 -4
  107. package/dist/configs/unicorn.cjs +13 -10
  108. package/dist/configs/unicorn.d.cts +3 -2
  109. package/dist/configs/unicorn.d.ts +3 -2
  110. package/dist/configs/unicorn.mjs +1 -2
  111. package/dist/configs/unocss.cjs +74 -4
  112. package/dist/configs/unocss.d.cts +3 -6
  113. package/dist/configs/unocss.d.ts +3 -6
  114. package/dist/configs/unocss.mjs +3 -2
  115. package/dist/configs/vue.cjs +51 -15
  116. package/dist/configs/vue.d.cts +3 -6
  117. package/dist/configs/vue.d.ts +3 -6
  118. package/dist/configs/vue.mjs +3 -3
  119. package/dist/configs/yaml.cjs +17 -11
  120. package/dist/configs/yaml.d.cts +3 -6
  121. package/dist/configs/yaml.d.ts +3 -6
  122. package/dist/configs/yaml.mjs +3 -3
  123. package/dist/custom-rules/utils.cjs +31 -0
  124. package/dist/custom-rules/utils.d.cts +6 -0
  125. package/dist/custom-rules/utils.d.ts +6 -0
  126. package/dist/custom-rules/utils.mjs +6 -0
  127. package/dist/globs.cjs +157 -0
  128. package/dist/globs.d.cts +28 -0
  129. package/dist/globs.d.ts +28 -0
  130. package/dist/globs.mjs +56 -0
  131. package/dist/index.cjs +1470 -1040
  132. package/dist/index.d.cts +10 -44
  133. package/dist/index.d.ts +10 -44
  134. package/dist/index.mjs +106 -140
  135. package/dist/types-spTEGSaV.d.cts +632 -0
  136. package/dist/types-spTEGSaV.d.ts +632 -0
  137. package/package.json +69 -37
  138. package/dist/chunk-24KJPXII.mjs +0 -51
  139. package/dist/chunk-4HH6LYJ6.mjs +0 -25
  140. package/dist/chunk-4JKENKIP.mjs +0 -67
  141. package/dist/chunk-C5VMTRKT.mjs +0 -18
  142. package/dist/chunk-CFSYEIE4.mjs +0 -23
  143. package/dist/chunk-ERFDRAGW.mjs +0 -86
  144. package/dist/chunk-HLDEUDLN.mjs +0 -28
  145. package/dist/chunk-UBPIYSHC.mjs +0 -284
  146. package/dist/types-fxhbVLKI.d.cts +0 -235
  147. package/dist/types-fxhbVLKI.d.ts +0 -235
  148. package/dist/{chunk-FKAOMYGL.mjs → chunk-ME2OAMS3.mjs} +0 -0
  149. package/dist/{chunk-FOIFEV73.mjs → chunk-XBASVDU6.mjs} +6 -6
@@ -32,6 +32,7 @@ var configs_exports = {};
32
32
  __export(configs_exports, {
33
33
  astro: () => astro,
34
34
  comments: () => comments,
35
+ formatters: () => formatters,
35
36
  ignores: () => ignores,
36
37
  imports: () => imports,
37
38
  javascript: () => javascript,
@@ -55,16 +56,8 @@ __export(configs_exports, {
55
56
  });
56
57
  module.exports = __toCommonJS(configs_exports);
57
58
 
58
- // src/plugins.ts
59
- var import_eslint_plugin_antfu = __toESM(require("eslint-plugin-antfu"), 1);
60
- var import_eslint_plugin_eslint_comments = __toESM(require("eslint-plugin-eslint-comments"), 1);
61
- var pluginImport = __toESM(require("eslint-plugin-i"), 1);
62
- var import_eslint_plugin_n = __toESM(require("eslint-plugin-n"), 1);
63
- var import_eslint_plugin_unicorn = __toESM(require("eslint-plugin-unicorn"), 1);
64
- var import_eslint_plugin_unused_imports = __toESM(require("eslint-plugin-unused-imports"), 1);
65
- var import_eslint_plugin_perfectionist = __toESM(require("eslint-plugin-perfectionist"), 1);
66
-
67
59
  // src/configs/comments.ts
60
+ var import_eslint_plugin_eslint_comments = __toESM(require("@eslint-community/eslint-plugin-eslint-comments"), 1);
68
61
  async function comments() {
69
62
  return [
70
63
  {
@@ -73,10 +66,71 @@ async function comments() {
73
66
  "eslint-comments": import_eslint_plugin_eslint_comments.default
74
67
  },
75
68
  rules: {
69
+ // https://github.com/eslint-community/eslint-plugin-eslint-comments/blob/main/docs/rules/disable-enable-pair.md
70
+ "eslint-comments/disable-enable-pair": "error",
71
+ // https://github.com/eslint-community/eslint-plugin-eslint-comments/blob/main/docs/rules/no-aggregating-enable.md
76
72
  "eslint-comments/no-aggregating-enable": "error",
73
+ // https://github.com/eslint-community/eslint-plugin-eslint-comments/blob/main/docs/rules/no-duplicate-disable.md
77
74
  "eslint-comments/no-duplicate-disable": "error",
75
+ // https://github.com/eslint-community/eslint-plugin-eslint-comments/blob/main/docs/rules/no-unlimited-disable.md
78
76
  "eslint-comments/no-unlimited-disable": "error",
79
- "eslint-comments/no-unused-enable": "error"
77
+ // Deprecated in favor of official reportUnusedDisableDirectives
78
+ // https://github.com/eslint-community/eslint-plugin-eslint-comments/issues/133
79
+ "eslint-comments/no-unused-enable": "off"
80
+ }
81
+ }
82
+ ];
83
+ }
84
+
85
+ // src/configs/unicorn.ts
86
+ var import_eslint_plugin_unicorn = __toESM(require("eslint-plugin-unicorn"), 1);
87
+ function unicorn() {
88
+ return [
89
+ {
90
+ name: "luxass:unicorn",
91
+ plugins: {
92
+ unicorn: import_eslint_plugin_unicorn.default
93
+ },
94
+ rules: {
95
+ // Pass error message when throwing errors
96
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/error-message.md
97
+ "unicorn/error-message": "error",
98
+ // Uppercase regex escapes
99
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/escape-case.md
100
+ "unicorn/escape-case": "error",
101
+ // Array.isArray instead of instanceof
102
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-instanceof-array.md
103
+ "unicorn/no-instanceof-array": "error",
104
+ // Ban `new Array` as `Array` constructor's params are ambiguous
105
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-new-array.md
106
+ "unicorn/no-new-array": "error",
107
+ // Prevent deprecated `new Buffer()`
108
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-new-buffer.md
109
+ "unicorn/no-new-buffer": "error",
110
+ // Lowercase number formatting for octal, hex, binary (0x1'error' instead of 0X1'error')
111
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/number-literal-case.md
112
+ "unicorn/number-literal-case": "error",
113
+ // textContent instead of innerText
114
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-dom-node-text-content.md
115
+ "unicorn/prefer-dom-node-text-content": "error",
116
+ // includes over indexOf when checking for existence
117
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-includes.md
118
+ "unicorn/prefer-includes": "error",
119
+ // Prefer using the node: protocol
120
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-node-protocol.md
121
+ "unicorn/prefer-node-protocol": "error",
122
+ // Prefer using number properties like `Number.isNaN` rather than `isNaN`
123
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-number-properties.md
124
+ "unicorn/prefer-number-properties": "error",
125
+ // String methods startsWith/endsWith instead of more complicated stuff
126
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-starts-ends-with.md
127
+ "unicorn/prefer-string-starts-ends-with": "error",
128
+ // Enforce throwing type error when throwing error while checking typeof
129
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-type-error.md
130
+ "unicorn/prefer-type-error": "error",
131
+ // Use new when throwing error
132
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/throw-new-error.md
133
+ "unicorn/throw-new-error": "error"
80
134
  }
81
135
  }
82
136
  ];
@@ -84,16 +138,21 @@ async function comments() {
84
138
 
85
139
  // src/globs.ts
86
140
  var GLOB_SRC_EXT = "?([cm])[jt]s?(x)";
87
- var GLOB_SRC = "**/*.?([cm])[jt]s?(x)";
88
- var GLOB_JSX_EXT = "[jt]sx";
89
- var GLOB_JSX = `**/*.${GLOB_JSX_EXT}`;
141
+ var GLOB_SRC = `**/*.${GLOB_SRC_EXT}`;
142
+ var GLOB_JSX = "**/*.?([cm])jsx";
143
+ var GLOB_TS = "**/*.?([cm])ts";
144
+ var GLOB_TSX = "**/*.?([cm])tsx";
145
+ var GLOB_CSS = "**/*.css";
146
+ var GLOB_POSTCSS = "**/*.{p,post}css";
147
+ var GLOB_LESS = "**/*.less";
148
+ var GLOB_SCSS = "**/*.scss";
90
149
  var GLOB_JSON = "**/*.json";
91
150
  var GLOB_JSON5 = "**/*.json5";
92
151
  var GLOB_JSONC = "**/*.jsonc";
93
152
  var GLOB_MARKDOWN = "**/*.md";
153
+ var GLOB_MARKDOWN_IN_MARKDOWN = "**/*.md/*.md";
94
154
  var GLOB_VUE = "**/*.vue";
95
155
  var GLOB_YAML = "**/*.y?(a)ml";
96
- var GLOB_HTML = "**/*.htm?(l)";
97
156
  var GLOB_ASTRO = "**/*.astro";
98
157
  var GLOB_MARKDOWN_CODE = `${GLOB_MARKDOWN}/${GLOB_SRC}`;
99
158
  var GLOB_TESTS = [
@@ -104,9 +163,9 @@ var GLOB_TESTS = [
104
163
  `**/*.benchmark.${GLOB_SRC_EXT}`
105
164
  ];
106
165
  var GLOB_NEXTJS_OG = [
107
- `**/app/**/opengraph-image.${GLOB_JSX_EXT}`,
108
- `**/app/**/twitter-image.${GLOB_JSX_EXT}`,
109
- `**/app/**/route.${GLOB_JSX_EXT}`
166
+ `**/app/**/opengraph-image.[jt]s?(x)`,
167
+ `**/app/**/twitter-image.[jt]s?(x)`,
168
+ `**/app/**/route.[jt]s?(x)`
110
169
  ];
111
170
  var GLOB_NEXTJS_ROUTES = [
112
171
  `**/app/**/page.${GLOB_SRC_EXT}`,
@@ -162,7 +221,257 @@ function ignores() {
162
221
  ];
163
222
  }
164
223
 
224
+ // src/configs/node.ts
225
+ var import_eslint_plugin_n = __toESM(require("eslint-plugin-n"), 1);
226
+ function node() {
227
+ return [
228
+ {
229
+ name: "luxass:node",
230
+ plugins: {
231
+ node: import_eslint_plugin_n.default
232
+ },
233
+ rules: {
234
+ "node/handle-callback-err": ["error", "^(err|error)$"],
235
+ "node/no-deprecated-api": "error",
236
+ "node/no-exports-assign": "error",
237
+ "node/no-new-require": "error",
238
+ "node/no-path-concat": "error",
239
+ "node/prefer-global/buffer": ["error", "never"],
240
+ "node/prefer-global/process": ["error", "never"],
241
+ "node/process-exit-as-throw": "error"
242
+ }
243
+ }
244
+ ];
245
+ }
246
+
247
+ // src/configs/sort.ts
248
+ function sortPackageJson() {
249
+ return [
250
+ {
251
+ name: "luxass:sort-package-json",
252
+ files: ["**/package.json"],
253
+ rules: {
254
+ "jsonc/sort-array-values": [
255
+ "error",
256
+ {
257
+ order: { type: "asc" },
258
+ pathPattern: "^files$"
259
+ }
260
+ ],
261
+ "jsonc/sort-keys": [
262
+ "error",
263
+ {
264
+ order: [
265
+ "name",
266
+ "displayName",
267
+ "version",
268
+ "description",
269
+ "type",
270
+ "private",
271
+ "author",
272
+ "publisher",
273
+ "packageManager",
274
+ "license",
275
+ "funding",
276
+ "homepage",
277
+ "repository",
278
+ "bugs",
279
+ "keywords",
280
+ "categories",
281
+ "sideEffects",
282
+ "exports",
283
+ "main",
284
+ "module",
285
+ "unpkg",
286
+ "jsdelivr",
287
+ "types",
288
+ "typesVersions",
289
+ "bin",
290
+ "icon",
291
+ "files",
292
+ "engines",
293
+ "activationEvents",
294
+ "contributes",
295
+ "scripts",
296
+ "peerDependencies",
297
+ "peerDependenciesMeta",
298
+ "dependencies",
299
+ "optionalDependencies",
300
+ "devDependencies",
301
+ "pnpm",
302
+ "overrides",
303
+ "resolutions",
304
+ "husky",
305
+ "simple-git-hooks",
306
+ "lint-staged",
307
+ "eslintConfig"
308
+ ],
309
+ pathPattern: "^$"
310
+ },
311
+ {
312
+ order: { type: "asc" },
313
+ pathPattern: "^(?:dev|peer|optional|bundled)?[Dd]ependencies$"
314
+ },
315
+ {
316
+ order: { type: "asc" },
317
+ pathPattern: "^resolutions$"
318
+ },
319
+ {
320
+ order: { type: "asc" },
321
+ pathPattern: "^pnpm.overrides$"
322
+ },
323
+ {
324
+ order: ["types", "import", "require", "default"],
325
+ pathPattern: "^exports.*$"
326
+ }
327
+ ]
328
+ }
329
+ }
330
+ ];
331
+ }
332
+ function sortTsconfig() {
333
+ return [
334
+ {
335
+ name: "luxass:sort-tsconfig",
336
+ files: ["**/tsconfig.json", "**/tsconfig.*.json"],
337
+ rules: {
338
+ "jsonc/sort-keys": [
339
+ "error",
340
+ {
341
+ order: [
342
+ "extends",
343
+ "compilerOptions",
344
+ "references",
345
+ "files",
346
+ "include",
347
+ "exclude"
348
+ ],
349
+ pathPattern: "^$"
350
+ },
351
+ {
352
+ order: [
353
+ /* Projects */
354
+ "incremental",
355
+ "composite",
356
+ "tsBuildInfoFile",
357
+ "disableSourceOfProjectReferenceRedirect",
358
+ "disableSolutionSearching",
359
+ "disableReferencedProjectLoad",
360
+ /* Language and Environment */
361
+ "target",
362
+ "jsx",
363
+ "jsxFactory",
364
+ "jsxFragmentFactory",
365
+ "jsxImportSource",
366
+ "lib",
367
+ "moduleDetection",
368
+ "noLib",
369
+ "reactNamespace",
370
+ "useDefineForClassFields",
371
+ "emitDecoratorMetadata",
372
+ "experimentalDecorators",
373
+ /* Modules */
374
+ "baseUrl",
375
+ "rootDir",
376
+ "rootDirs",
377
+ "customConditions",
378
+ "module",
379
+ "moduleResolution",
380
+ "moduleSuffixes",
381
+ "noResolve",
382
+ "paths",
383
+ "resolveJsonModule",
384
+ "resolvePackageJsonExports",
385
+ "resolvePackageJsonImports",
386
+ "typeRoots",
387
+ "types",
388
+ "allowArbitraryExtensions",
389
+ "allowImportingTsExtensions",
390
+ "allowUmdGlobalAccess",
391
+ /* JavaScript Support */
392
+ "allowJs",
393
+ "checkJs",
394
+ "maxNodeModuleJsDepth",
395
+ /* Type Checking */
396
+ "strict",
397
+ "strictBindCallApply",
398
+ "strictFunctionTypes",
399
+ "strictNullChecks",
400
+ "strictPropertyInitialization",
401
+ "allowUnreachableCode",
402
+ "allowUnusedLabels",
403
+ "alwaysStrict",
404
+ "exactOptionalPropertyTypes",
405
+ "noFallthroughCasesInSwitch",
406
+ "noImplicitAny",
407
+ "noImplicitOverride",
408
+ "noImplicitReturns",
409
+ "noImplicitThis",
410
+ "noPropertyAccessFromIndexSignature",
411
+ "noUncheckedIndexedAccess",
412
+ "noUnusedLocals",
413
+ "noUnusedParameters",
414
+ "useUnknownInCatchVariables",
415
+ /* Emit */
416
+ "declaration",
417
+ "declarationDir",
418
+ "declarationMap",
419
+ "downlevelIteration",
420
+ "emitBOM",
421
+ "emitDeclarationOnly",
422
+ "importHelpers",
423
+ "importsNotUsedAsValues",
424
+ "inlineSourceMap",
425
+ "inlineSources",
426
+ "mapRoot",
427
+ "newLine",
428
+ "noEmit",
429
+ "noEmitHelpers",
430
+ "noEmitOnError",
431
+ "outDir",
432
+ "outFile",
433
+ "preserveConstEnums",
434
+ "preserveValueImports",
435
+ "removeComments",
436
+ "sourceMap",
437
+ "sourceRoot",
438
+ "stripInternal",
439
+ /* Interop Constraints */
440
+ "allowSyntheticDefaultImports",
441
+ "esModuleInterop",
442
+ "forceConsistentCasingInFileNames",
443
+ "isolatedModules",
444
+ "preserveSymlinks",
445
+ "verbatimModuleSyntax",
446
+ /* Completeness */
447
+ "skipDefaultLibCheck",
448
+ "skipLibCheck"
449
+ ],
450
+ pathPattern: "^compilerOptions$"
451
+ }
452
+ ]
453
+ }
454
+ }
455
+ ];
456
+ }
457
+
458
+ // src/configs/perfectionist.ts
459
+ var import_eslint_plugin_perfectionist = __toESM(require("eslint-plugin-perfectionist"), 1);
460
+ async function perfectionist() {
461
+ return [
462
+ {
463
+ name: "luxass:perfectionist",
464
+ plugins: {
465
+ perfectionist: import_eslint_plugin_perfectionist.default
466
+ },
467
+ rules: {}
468
+ }
469
+ ];
470
+ }
471
+
165
472
  // src/configs/imports.ts
473
+ var import_eslint_plugin_i = __toESM(require("eslint-plugin-i"), 1);
474
+ var import_eslint_plugin_antfu = __toESM(require("eslint-plugin-antfu"), 1);
166
475
  async function imports(options = {}) {
167
476
  const {
168
477
  stylistic: stylistic2 = true
@@ -172,10 +481,11 @@ async function imports(options = {}) {
172
481
  name: "luxass:imports",
173
482
  plugins: {
174
483
  antfu: import_eslint_plugin_antfu.default,
175
- import: pluginImport
484
+ import: import_eslint_plugin_i.default
176
485
  },
177
486
  rules: {
178
487
  "antfu/import-dedupe": "error",
488
+ "antfu/no-import-dist": "error",
179
489
  "antfu/no-import-node-modules-by-path": "error",
180
490
  "import/first": "error",
181
491
  "import/no-duplicates": "error",
@@ -188,16 +498,27 @@ async function imports(options = {}) {
188
498
  "import/newline-after-import": ["error", { considerComments: true, count: 1 }]
189
499
  } : {}
190
500
  }
501
+ },
502
+ {
503
+ name: "luxass:imports:bin",
504
+ files: ["**/bin/**/*", `**/bin.${GLOB_SRC_EXT}`],
505
+ rules: {
506
+ "antfu/no-import-dist": "off",
507
+ "antfu/no-import-node-modules-by-path": "off"
508
+ }
191
509
  }
192
510
  ];
193
511
  }
194
512
 
195
513
  // src/configs/javascript.ts
196
514
  var import_globals = __toESM(require("globals"), 1);
515
+ var import_eslint_plugin_unused_imports = __toESM(require("eslint-plugin-unused-imports"), 1);
516
+ var import_eslint_plugin_antfu2 = __toESM(require("eslint-plugin-antfu"), 1);
197
517
  async function javascript(options = {}) {
198
- const { isEditor = false, overrides = {} } = options;
518
+ const { editor = false, overrides = {} } = options;
199
519
  return [
200
520
  {
521
+ name: "luxass:javascript",
201
522
  languageOptions: {
202
523
  ecmaVersion: 2022,
203
524
  globals: {
@@ -220,9 +541,8 @@ async function javascript(options = {}) {
220
541
  linterOptions: {
221
542
  reportUnusedDisableDirectives: true
222
543
  },
223
- name: "luxass:javascript",
224
544
  plugins: {
225
- "antfu": import_eslint_plugin_antfu.default,
545
+ "antfu": import_eslint_plugin_antfu2.default,
226
546
  "unused-imports": import_eslint_plugin_unused_imports.default
227
547
  },
228
548
  rules: {
@@ -249,7 +569,7 @@ async function javascript(options = {}) {
249
569
  "no-compare-neg-zero": "error",
250
570
  "no-cond-assign": ["error", "always"],
251
571
  "no-console": [
252
- isEditor ? "off" : "error",
572
+ editor ? "off" : "error",
253
573
  { allow: ["warn", "error"] }
254
574
  ],
255
575
  "no-const-assign": "error",
@@ -296,8 +616,8 @@ async function javascript(options = {}) {
296
616
  "no-regex-spaces": "error",
297
617
  "no-restricted-globals": [
298
618
  "error",
299
- { message: "Use `globalThis` instead.", name: "global" },
300
- { message: "Use `globalThis` instead.", name: "self" }
619
+ { name: "global", message: "Use `globalThis` instead." },
620
+ { name: "self", message: "Use `globalThis` instead." }
301
621
  ],
302
622
  "no-restricted-properties": [
303
623
  "error",
@@ -418,7 +738,7 @@ async function javascript(options = {}) {
418
738
  ],
419
739
  "symbol-description": "error",
420
740
  "unicode-bom": ["error", "never"],
421
- "unused-imports/no-unused-imports": isEditor ? "off" : "error",
741
+ "unused-imports/no-unused-imports": editor ? "off" : "error",
422
742
  "unused-imports/no-unused-vars": [
423
743
  "error",
424
744
  {
@@ -439,8 +759,8 @@ async function javascript(options = {}) {
439
759
  }
440
760
  },
441
761
  {
442
- files: [`scripts/${GLOB_SRC}`, `cli.${GLOB_SRC_EXT}`],
443
762
  name: "luxass:scripts-overrides",
763
+ files: [`scripts/${GLOB_SRC}`, `cli.${GLOB_SRC_EXT}`],
444
764
  rules: {
445
765
  "no-console": "off"
446
766
  }
@@ -481,8 +801,8 @@ async function ensure(packages) {
481
801
  const { default: prompts } = await import("prompts");
482
802
  const { result } = await prompts([
483
803
  {
484
- message: `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?`,
485
804
  name: "result",
805
+ message: `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?`,
486
806
  type: "confirm"
487
807
  }
488
808
  ]);
@@ -496,7 +816,10 @@ async function ensure(packages) {
496
816
 
497
817
  // src/configs/jsdoc.ts
498
818
  async function jsdoc(options = {}) {
499
- const { stylistic: stylistic2 = true } = options;
819
+ const {
820
+ overrides,
821
+ stylistic: stylistic2 = true
822
+ } = options;
500
823
  return [
501
824
  {
502
825
  name: "luxass:jsdoc",
@@ -522,7 +845,8 @@ async function jsdoc(options = {}) {
522
845
  ...stylistic2 ? {
523
846
  "jsdoc/check-alignment": "warn",
524
847
  "jsdoc/multiline-blocks": "warn"
525
- } : {}
848
+ } : {},
849
+ ...overrides
526
850
  }
527
851
  }
528
852
  ];
@@ -530,7 +854,11 @@ async function jsdoc(options = {}) {
530
854
 
531
855
  // src/configs/jsonc.ts
532
856
  async function jsonc(options = {}) {
533
- const { overrides = {}, stylistic: stylistic2 = true } = options;
857
+ const {
858
+ files = [GLOB_JSON, GLOB_JSON5, GLOB_JSONC],
859
+ overrides = {},
860
+ stylistic: stylistic2 = true
861
+ } = options;
534
862
  const [
535
863
  pluginJsonc,
536
864
  parserJsonc
@@ -546,11 +874,11 @@ async function jsonc(options = {}) {
546
874
  }
547
875
  },
548
876
  {
549
- files: [GLOB_JSON, GLOB_JSON5, GLOB_JSONC],
877
+ name: "luxass:jsonc:rules",
878
+ files,
550
879
  languageOptions: {
551
880
  parser: parserJsonc
552
881
  },
553
- name: "luxass:jsonc:rules",
554
882
  rules: {
555
883
  "jsonc/no-bigint-literals": "error",
556
884
  "jsonc/no-binary-expression": "error",
@@ -606,316 +934,116 @@ async function jsonc(options = {}) {
606
934
  }
607
935
 
608
936
  // src/configs/markdown.ts
937
+ var parserPlain = __toESM(require("eslint-parser-plain"), 1);
938
+ var import_eslint_merge_processors = require("eslint-merge-processors");
609
939
  async function markdown(options = {}) {
610
- const { componentExts = [], overrides = {} } = options;
611
- return [
612
- {
613
- name: "luxass:markdown:setup",
614
- plugins: {
615
- markdown: await interop(import("eslint-plugin-markdown"))
616
- }
617
- },
618
- {
619
- files: [GLOB_MARKDOWN],
620
- name: "luxass:markdown:processor",
621
- processor: "markdown/markdown"
622
- },
623
- {
624
- files: [
625
- GLOB_MARKDOWN_CODE,
626
- ...componentExts.map((ext) => `${GLOB_MARKDOWN}/**/*.${ext}`)
627
- ],
628
- languageOptions: {
629
- parserOptions: {
630
- ecmaFeatures: {
631
- impliedStrict: true
632
- }
633
- }
634
- },
635
- name: "luxass:markdown:rules",
636
- rules: {
637
- "antfu/no-cjs-exports": "off",
638
- "antfu/no-ts-export-equal": "off",
639
- "import/newline-after-import": "off",
640
- "no-alert": "off",
641
- "no-console": "off",
642
- "no-undef": "off",
643
- "no-unused-expressions": "off",
644
- "no-unused-vars": "off",
645
- "node/prefer-global/process": "off",
646
- "style/comma-dangle": "off",
647
- "style/eol-last": "off",
648
- "ts/consistent-type-imports": "off",
649
- "ts/no-namespace": "off",
650
- "ts/no-redeclare": "off",
651
- "ts/no-require-imports": "off",
652
- "ts/no-unused-vars": "off",
653
- "ts/no-use-before-define": "off",
654
- "ts/no-var-requires": "off",
655
- "unicode-bom": "off",
656
- "unused-imports/no-unused-imports": "off",
657
- "unused-imports/no-unused-vars": "off",
658
- // Type aware rules
659
- ...{
660
- "ts/await-thenable": "off",
661
- "ts/dot-notation": "off",
662
- "ts/no-floating-promises": "off",
663
- "ts/no-for-in-array": "off",
664
- "ts/no-implied-eval": "off",
665
- "ts/no-misused-promises": "off",
666
- "ts/no-throw-literal": "off",
667
- "ts/no-unnecessary-type-assertion": "off",
668
- "ts/no-unsafe-argument": "off",
669
- "ts/no-unsafe-assignment": "off",
670
- "ts/no-unsafe-call": "off",
671
- "ts/no-unsafe-member-access": "off",
672
- "ts/no-unsafe-return": "off",
673
- "ts/restrict-plus-operands": "off",
674
- "ts/restrict-template-expressions": "off",
675
- "ts/unbound-method": "off"
676
- },
677
- ...overrides
678
- }
679
- }
680
- ];
681
- }
682
-
683
- // src/configs/node.ts
684
- function node() {
685
- return [
686
- {
687
- name: "luxass:node",
688
- plugins: {
689
- node: import_eslint_plugin_n.default
690
- },
691
- rules: {
692
- "node/handle-callback-err": ["error", "^(err|error)$"],
693
- "node/no-deprecated-api": "error",
694
- "node/no-exports-assign": "error",
695
- "node/no-new-require": "error",
696
- "node/no-path-concat": "error",
697
- "node/prefer-global/buffer": ["error", "never"],
698
- "node/prefer-global/process": ["error", "never"],
699
- "node/process-exit-as-throw": "error"
700
- }
701
- }
702
- ];
703
- }
704
-
705
- // src/configs/sort.ts
706
- function sortPackageJson() {
707
- return [
708
- {
709
- files: ["**/package.json"],
710
- name: "luxass:sort-package-json",
711
- rules: {
712
- "jsonc/sort-array-values": [
713
- "error",
714
- {
715
- order: { type: "asc" },
716
- pathPattern: "^files$"
717
- }
718
- ],
719
- "jsonc/sort-keys": [
720
- "error",
721
- {
722
- order: [
723
- "publisher",
724
- "name",
725
- "displayName",
726
- "type",
727
- "version",
728
- "private",
729
- "packageManager",
730
- "description",
731
- "author",
732
- "license",
733
- "funding",
734
- "homepage",
735
- "repository",
736
- "bugs",
737
- "keywords",
738
- "categories",
739
- "sideEffects",
740
- "exports",
741
- "main",
742
- "module",
743
- "unpkg",
744
- "jsdelivr",
745
- "types",
746
- "typesVersions",
747
- "bin",
748
- "icon",
749
- "files",
750
- "engines",
751
- "activationEvents",
752
- "contributes",
753
- "scripts",
754
- "peerDependencies",
755
- "peerDependenciesMeta",
756
- "dependencies",
757
- "optionalDependencies",
758
- "devDependencies",
759
- "pnpm",
760
- "overrides",
761
- "resolutions",
762
- "husky",
763
- "simple-git-hooks",
764
- "lint-staged",
765
- "eslintConfig"
766
- ],
767
- pathPattern: "^$"
768
- },
769
- {
770
- order: { type: "asc" },
771
- pathPattern: "^(?:dev|peer|optional|bundled)?[Dd]ependencies$"
772
- },
773
- {
774
- order: { type: "asc" },
775
- pathPattern: "^resolutions$"
776
- },
777
- {
778
- order: { type: "asc" },
779
- pathPattern: "^pnpm.overrides$"
780
- },
781
- {
782
- order: ["types", "import", "require", "default"],
783
- pathPattern: "^exports.*$"
784
- }
785
- ]
786
- }
787
- }
788
- ];
789
- }
790
- function sortTsconfig() {
940
+ const {
941
+ exts = [],
942
+ files = [GLOB_MARKDOWN],
943
+ overrides = {}
944
+ } = options;
945
+ const markdown2 = await interop(import("eslint-plugin-markdown"));
791
946
  return [
792
947
  {
793
- files: ["**/tsconfig.json", "**/tsconfig.*.json"],
794
- name: "luxass:sort-tsconfig",
795
- rules: {
796
- "jsonc/sort-keys": [
797
- "error",
798
- {
799
- order: [
800
- "extends",
801
- "compilerOptions",
802
- "references",
803
- "files",
804
- "include",
805
- "exclude"
806
- ],
807
- pathPattern: "^$"
808
- },
809
- {
810
- order: [
811
- /* Projects */
812
- "incremental",
813
- "composite",
814
- "tsBuildInfoFile",
815
- "disableSourceOfProjectReferenceRedirect",
816
- "disableSolutionSearching",
817
- "disableReferencedProjectLoad",
818
- /* Language and Environment */
819
- "target",
820
- "jsx",
821
- "jsxFactory",
822
- "jsxFragmentFactory",
823
- "jsxImportSource",
824
- "lib",
825
- "moduleDetection",
826
- "noLib",
827
- "reactNamespace",
828
- "useDefineForClassFields",
829
- "emitDecoratorMetadata",
830
- "experimentalDecorators",
831
- /* Modules */
832
- "baseUrl",
833
- "rootDir",
834
- "rootDirs",
835
- "customConditions",
836
- "module",
837
- "moduleResolution",
838
- "moduleSuffixes",
839
- "noResolve",
840
- "paths",
841
- "resolveJsonModule",
842
- "resolvePackageJsonExports",
843
- "resolvePackageJsonImports",
844
- "typeRoots",
845
- "types",
846
- "allowArbitraryExtensions",
847
- "allowImportingTsExtensions",
848
- "allowUmdGlobalAccess",
849
- /* JavaScript Support */
850
- "allowJs",
851
- "checkJs",
852
- "maxNodeModuleJsDepth",
853
- /* Type Checking */
854
- "strict",
855
- "strictBindCallApply",
856
- "strictFunctionTypes",
857
- "strictNullChecks",
858
- "strictPropertyInitialization",
859
- "allowUnreachableCode",
860
- "allowUnusedLabels",
861
- "alwaysStrict",
862
- "exactOptionalPropertyTypes",
863
- "noFallthroughCasesInSwitch",
864
- "noImplicitAny",
865
- "noImplicitOverride",
866
- "noImplicitReturns",
867
- "noImplicitThis",
868
- "noPropertyAccessFromIndexSignature",
869
- "noUncheckedIndexedAccess",
870
- "noUnusedLocals",
871
- "noUnusedParameters",
872
- "useUnknownInCatchVariables",
873
- /* Emit */
874
- "declaration",
875
- "declarationDir",
876
- "declarationMap",
877
- "downlevelIteration",
878
- "emitBOM",
879
- "emitDeclarationOnly",
880
- "importHelpers",
881
- "importsNotUsedAsValues",
882
- "inlineSourceMap",
883
- "inlineSources",
884
- "mapRoot",
885
- "newLine",
886
- "noEmit",
887
- "noEmitHelpers",
888
- "noEmitOnError",
889
- "outDir",
890
- "outFile",
891
- "preserveConstEnums",
892
- "preserveValueImports",
893
- "removeComments",
894
- "sourceMap",
895
- "sourceRoot",
896
- "stripInternal",
897
- /* Interop Constraints */
898
- "allowSyntheticDefaultImports",
899
- "esModuleInterop",
900
- "forceConsistentCasingInFileNames",
901
- "isolatedModules",
902
- "preserveSymlinks",
903
- "verbatimModuleSyntax",
904
- /* Completeness */
905
- "skipDefaultLibCheck",
906
- "skipLibCheck"
907
- ],
908
- pathPattern: "^compilerOptions$"
948
+ name: "luxass:markdown:setup",
949
+ plugins: {
950
+ markdown: markdown2
951
+ }
952
+ },
953
+ {
954
+ name: "luxass:markdown:processor",
955
+ files,
956
+ ignores: [GLOB_MARKDOWN_IN_MARKDOWN],
957
+ // `eslint-plugin-markdown` only creates virtual files for code blocks,
958
+ // but not the markdown file itself. We use `eslint-merge-processors` to
959
+ // add a pass-through processor for the markdown file itself.
960
+ processor: (0, import_eslint_merge_processors.mergeProcessors)([
961
+ markdown2.processors.markdown,
962
+ import_eslint_merge_processors.processorPassThrough
963
+ ])
964
+ },
965
+ {
966
+ name: "luxass:markdown:parser",
967
+ files,
968
+ languageOptions: {
969
+ parser: parserPlain
970
+ }
971
+ },
972
+ {
973
+ name: "luxass:markdown:disables",
974
+ files: [
975
+ GLOB_MARKDOWN_CODE,
976
+ ...exts.map((ext) => `${GLOB_MARKDOWN}/**/*.${ext}`)
977
+ ],
978
+ languageOptions: {
979
+ parserOptions: {
980
+ ecmaFeatures: {
981
+ impliedStrict: true
909
982
  }
910
- ]
983
+ }
984
+ },
985
+ rules: {
986
+ "import/newline-after-import": "off",
987
+ "no-alert": "off",
988
+ "no-console": "off",
989
+ "no-undef": "off",
990
+ "no-unused-expressions": "off",
991
+ "no-unused-vars": "off",
992
+ "node/prefer-global/process": "off",
993
+ "style/comma-dangle": "off",
994
+ "style/eol-last": "off",
995
+ // Type aware rules
996
+ "ts/await-thenable": "off",
997
+ "ts/consistent-type-imports": "off",
998
+ "ts/dot-notation": "off",
999
+ "ts/no-floating-promises": "off",
1000
+ "ts/no-for-in-array": "off",
1001
+ "ts/no-implied-eval": "off",
1002
+ "ts/no-misused-promises": "off",
1003
+ "ts/no-namespace": "off",
1004
+ "ts/no-redeclare": "off",
1005
+ "ts/no-require-imports": "off",
1006
+ "ts/no-throw-literal": "off",
1007
+ "ts/no-unnecessary-type-assertion": "off",
1008
+ "ts/no-unsafe-argument": "off",
1009
+ "ts/no-unsafe-assignment": "off",
1010
+ "ts/no-unsafe-call": "off",
1011
+ "ts/no-unsafe-member-access": "off",
1012
+ "ts/no-unsafe-return": "off",
1013
+ "ts/no-unused-vars": "off",
1014
+ "ts/no-use-before-define": "off",
1015
+ "ts/no-var-requires": "off",
1016
+ "ts/restrict-plus-operands": "off",
1017
+ "ts/restrict-template-expressions": "off",
1018
+ "ts/unbound-method": "off",
1019
+ "unicode-bom": "off",
1020
+ "unused-imports/no-unused-imports": "off",
1021
+ "unused-imports/no-unused-vars": "off",
1022
+ ...overrides
911
1023
  }
912
1024
  }
913
1025
  ];
914
1026
  }
915
1027
 
916
1028
  // src/configs/stylistic.ts
1029
+ var import_eslint_plugin_antfu3 = __toESM(require("eslint-plugin-antfu"), 1);
1030
+ var StylisticConfigDefaults = {
1031
+ indent: 2,
1032
+ jsx: true,
1033
+ quotes: "double",
1034
+ semi: true
1035
+ };
917
1036
  async function stylistic(options = {}) {
918
- const { indent = 2, jsx = true, quotes = "double", semi = true } = options;
1037
+ const {
1038
+ indent,
1039
+ jsx,
1040
+ overrides = {},
1041
+ quotes,
1042
+ semi
1043
+ } = {
1044
+ ...StylisticConfigDefaults,
1045
+ ...options
1046
+ };
919
1047
  const pluginStylistic = await interop(import("@stylistic/eslint-plugin"));
920
1048
  const config = pluginStylistic.configs.customize({
921
1049
  flat: true,
@@ -929,18 +1057,18 @@ async function stylistic(options = {}) {
929
1057
  {
930
1058
  name: "luxass:stylistic",
931
1059
  plugins: {
932
- antfu: import_eslint_plugin_antfu.default,
1060
+ antfu: import_eslint_plugin_antfu3.default,
933
1061
  style: pluginStylistic
934
1062
  },
935
1063
  rules: {
936
1064
  ...config.rules,
937
1065
  "antfu/consistent-list-newline": "error",
938
1066
  "antfu/if-newline": "off",
939
- "antfu/indent-binary-ops": ["error", { indent }],
940
1067
  "antfu/top-level-function": "error",
941
1068
  "curly": ["error", "multi-line", "consistent"],
942
1069
  "style/arrow-parens": ["error", "always", { requireForBlockBody: true }],
943
- "style/brace-style": ["error", "1tbs", { allowSingleLine: true }]
1070
+ "style/brace-style": ["error", "1tbs", { allowSingleLine: true }],
1071
+ ...overrides
944
1072
  }
945
1073
  }
946
1074
  ];
@@ -948,9 +1076,10 @@ async function stylistic(options = {}) {
948
1076
 
949
1077
  // src/configs/typescript.ts
950
1078
  var import_node_process2 = __toESM(require("process"), 1);
951
- async function typescript(options) {
1079
+ var import_eslint_plugin_antfu4 = __toESM(require("eslint-plugin-antfu"), 1);
1080
+ async function typescript(options = {}) {
952
1081
  const {
953
- componentExts = [],
1082
+ exts = [],
954
1083
  overrides = {},
955
1084
  parserOptions = {}
956
1085
  } = options ?? {};
@@ -975,6 +1104,11 @@ async function typescript(options) {
975
1104
  "ts/restrict-template-expressions": "error",
976
1105
  "ts/unbound-method": "error"
977
1106
  };
1107
+ const files = options.files ?? [
1108
+ GLOB_SRC,
1109
+ ...exts.map((ext) => `**/*.${ext}`)
1110
+ ];
1111
+ const filesTypeAware = options.typeAwareFileS ?? [GLOB_TS, GLOB_TSX];
978
1112
  const tsconfigPath = options?.tsconfigPath ? toArray(options.tsconfigPath) : void 0;
979
1113
  const [
980
1114
  pluginTs,
@@ -988,16 +1122,17 @@ async function typescript(options) {
988
1122
  // Install the plugins without globs, so they can be configured separately.
989
1123
  name: "luxass:typescript:setup",
990
1124
  plugins: {
991
- antfu: import_eslint_plugin_antfu.default,
1125
+ antfu: import_eslint_plugin_antfu4.default,
992
1126
  ts: pluginTs
993
1127
  }
994
1128
  },
995
1129
  {
996
- files: [GLOB_SRC, ...componentExts.map((ext) => `**/*.${ext}`)],
1130
+ name: "luxass:typescript:rules",
1131
+ files,
997
1132
  languageOptions: {
998
1133
  parser: parserTs,
999
1134
  parserOptions: {
1000
- extraFileExtensions: componentExts.map((ext) => `.${ext}`),
1135
+ extraFileExtensions: exts.map((ext) => `.${ext}`),
1001
1136
  sourceType: "module",
1002
1137
  ...tsconfigPath ? {
1003
1138
  project: tsconfigPath,
@@ -1006,7 +1141,6 @@ async function typescript(options) {
1006
1141
  ...parserOptions
1007
1142
  }
1008
1143
  },
1009
- name: "luxass:typescript:rules",
1010
1144
  rules: {
1011
1145
  ...renameRules(
1012
1146
  pluginTs.configs["eslint-recommended"].overrides[0].rules,
@@ -1018,9 +1152,6 @@ async function typescript(options) {
1018
1152
  "@typescript-eslint/",
1019
1153
  "ts/"
1020
1154
  ),
1021
- "antfu/generic-spacing": "error",
1022
- "antfu/named-tuple-spacing": "error",
1023
- "antfu/no-cjs-exports": "error",
1024
1155
  "no-dupe-class-members": "off",
1025
1156
  "no-invalid-this": "off",
1026
1157
  "no-loss-of-precision": "off",
@@ -1034,41 +1165,34 @@ async function typescript(options) {
1034
1165
  "ts/ban-types": ["error", {
1035
1166
  extendDefaults: false,
1036
1167
  types: {
1037
- "BigInt": {
1168
+ BigInt: {
1038
1169
  fixWith: "bigint",
1039
1170
  message: "Use `bigint` instead."
1040
1171
  },
1041
- "Boolean": {
1172
+ Boolean: {
1042
1173
  fixWith: "boolean",
1043
1174
  message: "Use `boolean` instead."
1044
1175
  },
1045
- "Function": "Use a specific function type instead, like `() => void`.",
1046
- "Number": {
1176
+ Function: "Use a specific function type instead, like `() => void`.",
1177
+ Number: {
1047
1178
  fixWith: "number",
1048
1179
  message: "Use `number` instead."
1049
1180
  },
1050
- "Object": {
1181
+ Object: {
1051
1182
  fixWith: "Record<string, unknown>",
1052
1183
  message: "The `Object` type is mostly the same as `unknown`. You probably want `Record<string, unknown>` instead. See https://github.com/typescript-eslint/typescript-eslint/pull/848"
1053
1184
  },
1054
- "String": {
1185
+ String: {
1055
1186
  fixWith: "string",
1056
1187
  message: "Use `string` instead."
1057
1188
  },
1058
- "Symbol": {
1189
+ Symbol: {
1059
1190
  fixWith: "symbol",
1060
1191
  message: "Use `symbol` instead."
1061
1192
  },
1062
- "[]": {
1063
- message: "Don't use the empty array type `[]`. It only allows empty arrays. Use `SomeType[]` instead."
1064
- },
1065
- "object": {
1193
+ object: {
1066
1194
  fixWith: "Record<string, unknown>",
1067
1195
  message: "The `object` type is hard to use. Use `Record<string, unknown>` instead. See: https://github.com/typescript-eslint/typescript-eslint/pull/848"
1068
- },
1069
- "{}": {
1070
- fixWith: "Record<string, unknown>",
1071
- message: "The `{}` type is mostly the same as `unknown`. You probably want `Record<string, unknown>` instead."
1072
1196
  }
1073
1197
  }
1074
1198
  }],
@@ -1097,13 +1221,20 @@ async function typescript(options) {
1097
1221
  "ts/prefer-ts-expect-error": "error",
1098
1222
  "ts/triple-slash-reference": "off",
1099
1223
  "ts/unified-signatures": "off",
1224
+ ...overrides
1225
+ }
1226
+ },
1227
+ {
1228
+ name: "luxass:typescript:rules-type-aware",
1229
+ files: filesTypeAware,
1230
+ rules: {
1100
1231
  ...tsconfigPath ? typeAwareRules : {},
1101
1232
  ...overrides
1102
1233
  }
1103
1234
  },
1104
1235
  {
1105
- files: ["**/*.d.ts"],
1106
1236
  name: "luxass:typescript:dts-overrides",
1237
+ files: ["**/*.d.ts"],
1107
1238
  rules: {
1108
1239
  "eslint-comments/no-unlimited-disable": "off",
1109
1240
  "import/no-duplicates": "off",
@@ -1112,15 +1243,15 @@ async function typescript(options) {
1112
1243
  }
1113
1244
  },
1114
1245
  {
1115
- files: ["**/*.{test,spec}.ts?(x)"],
1116
1246
  name: "luxass:typescript:tests-overrides",
1247
+ files: ["**/*.{test,spec}.ts?(x)"],
1117
1248
  rules: {
1118
1249
  "no-unused-expressions": "off"
1119
1250
  }
1120
1251
  },
1121
1252
  {
1122
- files: ["**/*.js", "**/*.cjs"],
1123
1253
  name: "luxass:typescript:javascript-overrides",
1254
+ files: ["**/*.js", "**/*.cjs"],
1124
1255
  rules: {
1125
1256
  "ts/no-require-imports": "off",
1126
1257
  "ts/no-var-requires": "off"
@@ -1129,56 +1260,27 @@ async function typescript(options) {
1129
1260
  ];
1130
1261
  }
1131
1262
 
1132
- // src/configs/unicorn.ts
1133
- function unicorn() {
1134
- return [
1135
- {
1136
- name: "luxass:unicorn",
1137
- plugins: {
1138
- unicorn: import_eslint_plugin_unicorn.default
1139
- },
1140
- rules: {
1141
- // Pass error message when throwing errors
1142
- "unicorn/error-message": "error",
1143
- // Uppercase regex escapes
1144
- "unicorn/escape-case": "error",
1145
- // Array.isArray instead of instanceof
1146
- "unicorn/no-instanceof-array": "error",
1147
- // Ban `new Array` as `Array` constructor's params are ambiguous
1148
- "unicorn/no-new-array": "error",
1149
- // Prevent deprecated `new Buffer()`
1150
- "unicorn/no-new-buffer": "error",
1151
- // Lowercase number formatting for octal, hex, binary (0x1'error' instead of 0X1'error')
1152
- "unicorn/number-literal-case": "error",
1153
- // textContent instead of innerText
1154
- "unicorn/prefer-dom-node-text-content": "error",
1155
- // includes over indexOf when checking for existence
1156
- "unicorn/prefer-includes": "error",
1157
- // Prefer using the node: protocol
1158
- "unicorn/prefer-node-protocol": "error",
1159
- // Prefer using number properties like `Number.isNaN` rather than `isNaN`
1160
- "unicorn/prefer-number-properties": "error",
1161
- // String methods startsWith/endsWith instead of more complicated stuff
1162
- "unicorn/prefer-string-starts-ends-with": "error",
1163
- // Enforce throwing type error when throwing error while checking typeof
1164
- "unicorn/prefer-type-error": "error",
1165
- // Use new when throwing error
1166
- "unicorn/throw-new-error": "error"
1167
- }
1168
- }
1169
- ];
1170
- }
1171
-
1172
1263
  // src/configs/vue.ts
1264
+ var import_eslint_merge_processors2 = require("eslint-merge-processors");
1173
1265
  async function vue(options = {}) {
1174
- const { overrides = {}, stylistic: stylistic2 = true } = options;
1266
+ const {
1267
+ a11y = true,
1268
+ files = [GLOB_VUE],
1269
+ overrides = {},
1270
+ stylistic: stylistic2 = true
1271
+ } = options;
1175
1272
  const [
1176
1273
  pluginVue,
1177
- parserVue
1274
+ parserVue,
1275
+ processorVueBlocks,
1276
+ pluginA11y
1178
1277
  ] = await Promise.all([
1179
1278
  interop(import("eslint-plugin-vue")),
1180
- interop(import("vue-eslint-parser"))
1279
+ interop(import("vue-eslint-parser")),
1280
+ interop(import("eslint-processor-vue-blocks")),
1281
+ ...a11y ? [interop(import("eslint-plugin-vuejs-accessibility"))] : []
1181
1282
  ]);
1283
+ const sfcBlocks = options.sfcBlocks === true ? {} : options.sfcBlocks ?? {};
1182
1284
  const {
1183
1285
  indent = 2
1184
1286
  } = typeof stylistic2 === "boolean" ? {} : stylistic2;
@@ -1186,11 +1288,13 @@ async function vue(options = {}) {
1186
1288
  {
1187
1289
  name: "luxass:vue:setup",
1188
1290
  plugins: {
1189
- vue: pluginVue
1291
+ vue: pluginVue,
1292
+ ...a11y ? { "vue-a11y": pluginA11y } : {}
1190
1293
  }
1191
1294
  },
1192
1295
  {
1193
- files: [GLOB_VUE],
1296
+ name: "luxass:vue:rules",
1297
+ files,
1194
1298
  languageOptions: {
1195
1299
  parser: parserVue,
1196
1300
  parserOptions: {
@@ -1202,8 +1306,16 @@ async function vue(options = {}) {
1202
1306
  sourceType: "module"
1203
1307
  }
1204
1308
  },
1205
- name: "luxass:vue:rules",
1206
- processor: pluginVue.processors[".vue"],
1309
+ processor: sfcBlocks === false ? pluginVue.processors[".vue"] : (0, import_eslint_merge_processors2.mergeProcessors)([
1310
+ pluginVue.processors[".vue"],
1311
+ processorVueBlocks({
1312
+ ...sfcBlocks,
1313
+ blocks: {
1314
+ styles: true,
1315
+ ...sfcBlocks.blocks
1316
+ }
1317
+ })
1318
+ ]),
1207
1319
  rules: {
1208
1320
  ...pluginVue.configs.base.rules,
1209
1321
  ...pluginVue.configs["vue3-essential"].rules,
@@ -1312,6 +1424,28 @@ async function vue(options = {}) {
1312
1424
  "vue/space-in-parens": ["error", "never"],
1313
1425
  "vue/template-curly-spacing": "error"
1314
1426
  } : {},
1427
+ ...a11y ? {
1428
+ "vue-a11y/alt-text": "error",
1429
+ "vue-a11y/anchor-has-content": "error",
1430
+ "vue-a11y/aria-props": "error",
1431
+ "vue-a11y/aria-role": "error",
1432
+ "vue-a11y/aria-unsupported-elements": "error",
1433
+ "vue-a11y/click-events-have-key-events": "error",
1434
+ "vue-a11y/form-control-has-label": "error",
1435
+ "vue-a11y/heading-has-content": "error",
1436
+ "vue-a11y/iframe-has-title": "error",
1437
+ "vue-a11y/interactive-supports-focus": "error",
1438
+ "vue-a11y/label-has-for": "error",
1439
+ "vue-a11y/media-has-caption": "error",
1440
+ "vue-a11y/mouse-events-have-key-events": "error",
1441
+ "vue-a11y/no-access-key": "error",
1442
+ "vue-a11y/no-autofocus": "error",
1443
+ "vue-a11y/no-distracting-elements": "error",
1444
+ "vue-a11y/no-redundant-roles": "error",
1445
+ "vue-a11y/no-static-element-interactions": "error",
1446
+ "vue-a11y/role-has-required-aria-props": "error",
1447
+ "vue-a11y/tabindex-no-positive": "error"
1448
+ } : {},
1315
1449
  ...overrides
1316
1450
  }
1317
1451
  }
@@ -1320,7 +1454,11 @@ async function vue(options = {}) {
1320
1454
 
1321
1455
  // src/configs/yaml.ts
1322
1456
  async function yaml(options = {}) {
1323
- const { overrides = {}, stylistic: stylistic2 = true } = options;
1457
+ const {
1458
+ files = [GLOB_YAML],
1459
+ overrides = {},
1460
+ stylistic: stylistic2 = true
1461
+ } = options;
1324
1462
  const [
1325
1463
  pluginYaml,
1326
1464
  parserYaml
@@ -1340,16 +1478,17 @@ async function yaml(options = {}) {
1340
1478
  }
1341
1479
  },
1342
1480
  {
1343
- files: [GLOB_YAML],
1481
+ name: "luxass:yaml:rules",
1482
+ files,
1344
1483
  languageOptions: {
1345
1484
  parser: parserYaml
1346
1485
  },
1347
- name: "luxass:yaml:rules",
1348
1486
  rules: {
1349
1487
  "style/spaced-comment": "off",
1350
1488
  "yaml/block-mapping": "error",
1351
1489
  "yaml/block-sequence": "error",
1352
1490
  "yaml/no-empty-key": "error",
1491
+ "yaml/no-empty-mapping-value": "error",
1353
1492
  "yaml/no-empty-sequence-entry": "error",
1354
1493
  "yaml/no-irregular-whitespace": "error",
1355
1494
  "yaml/plain-scalar": "error",
@@ -1372,19 +1511,121 @@ async function yaml(options = {}) {
1372
1511
  } : {},
1373
1512
  ...overrides
1374
1513
  }
1514
+ },
1515
+ {
1516
+ name: "luxass:yaml:github-actions",
1517
+ files: ["**/.github/workflows/*.{yml,yaml}"],
1518
+ rules: {
1519
+ // GitHub Actions supports empty values to enable features
1520
+ "yaml/no-empty-mapping-value": "off"
1521
+ }
1375
1522
  }
1376
1523
  ];
1377
1524
  }
1378
1525
 
1526
+ // src/custom-rules/utils.ts
1527
+ var import_utils8 = require("@typescript-eslint/utils");
1528
+ var createRule = import_utils8.ESLintUtils.RuleCreator((ruleName) => `https://github.com/luxass/eslint-config/blob/main/src/custom-rules/${ruleName}/README.md`);
1529
+
1530
+ // src/custom-rules/no-only-tests/index.ts
1531
+ var DEFAULT_OPTIONS = {
1532
+ blocks: ["describe", "it", "test"],
1533
+ focus: ["only"]
1534
+ };
1535
+ function getPath(node2, path = []) {
1536
+ if (node2) {
1537
+ const nodeName = node2.name || node2.property && node2.property.name;
1538
+ if (node2.object) {
1539
+ return getPath(node2.object, [
1540
+ nodeName,
1541
+ ...path
1542
+ ]);
1543
+ }
1544
+ if (node2.callee)
1545
+ return getPath(node2.callee, path);
1546
+ return [nodeName, ...path];
1547
+ }
1548
+ return path;
1549
+ }
1550
+ var noOnlyTests = createRule({
1551
+ name: "no-only-tests",
1552
+ create: (context, [options]) => {
1553
+ const {
1554
+ blocks = DEFAULT_OPTIONS.blocks,
1555
+ focus = DEFAULT_OPTIONS.focus
1556
+ } = options;
1557
+ const handler = {
1558
+ Identifier(node2) {
1559
+ const parent = node2.parent?.object;
1560
+ if (!parent)
1561
+ return;
1562
+ if (!focus.includes(node2.name))
1563
+ return;
1564
+ const callPath = getPath(node2.parent).join(".");
1565
+ const found = blocks.find((block) => {
1566
+ if (block.endsWith("*"))
1567
+ return callPath.startsWith(block.replace(/\*$/, ""));
1568
+ return callPath.startsWith(`${block}.`);
1569
+ });
1570
+ if (found) {
1571
+ context.report({
1572
+ data: { block: callPath.split(".")[0], focus: node2.name },
1573
+ messageId: "notPermitted",
1574
+ node: node2
1575
+ });
1576
+ }
1577
+ }
1578
+ };
1579
+ return handler;
1580
+ },
1581
+ defaultOptions: [{
1582
+ blocks: ["describe", "it", "test"],
1583
+ focus: ["only"]
1584
+ }],
1585
+ meta: {
1586
+ docs: {
1587
+ description: "disallow .only blocks in tests",
1588
+ recommended: "recommended"
1589
+ },
1590
+ messages: {
1591
+ notPermitted: "{{ block }}.{{ focus }} not permitted"
1592
+ },
1593
+ schema: [{
1594
+ additionalProperties: false,
1595
+ properties: {
1596
+ blocks: {
1597
+ items: {
1598
+ type: "string"
1599
+ },
1600
+ type: "array",
1601
+ uniqueItems: true
1602
+ },
1603
+ focus: {
1604
+ items: {
1605
+ type: "string"
1606
+ },
1607
+ type: "array",
1608
+ uniqueItems: true
1609
+ }
1610
+ },
1611
+ type: "object"
1612
+ }],
1613
+ type: "layout"
1614
+ }
1615
+ // i need to have this here, otherwise typechecking fails.
1616
+ });
1617
+
1379
1618
  // src/configs/test.ts
1380
1619
  async function test(options = {}) {
1381
- const { isEditor = false, overrides = {} } = options;
1620
+ const {
1621
+ editor = false,
1622
+ files = GLOB_TESTS,
1623
+ overrides = {}
1624
+ } = options;
1382
1625
  const [
1383
- pluginVitest,
1384
- pluginNoOnlyTests
1626
+ pluginVitest
1385
1627
  ] = await Promise.all([
1386
- interop(import("eslint-plugin-vitest")),
1387
- interop(import("eslint-plugin-no-only-tests"))
1628
+ interop(import("eslint-plugin-vitest"))
1388
1629
  ]);
1389
1630
  return [
1390
1631
  {
@@ -1394,21 +1635,21 @@ async function test(options = {}) {
1394
1635
  ...pluginVitest,
1395
1636
  rules: {
1396
1637
  ...pluginVitest.rules,
1397
- ...pluginNoOnlyTests.rules
1638
+ "no-only-tests": noOnlyTests
1398
1639
  }
1399
1640
  }
1400
1641
  }
1401
1642
  },
1402
1643
  {
1403
- files: GLOB_TESTS,
1404
1644
  name: "luxass:test:rules",
1645
+ files,
1405
1646
  rules: {
1406
1647
  "test/consistent-test-it": [
1407
1648
  "error",
1408
1649
  { fn: "it", withinDescribe: "it" }
1409
1650
  ],
1410
1651
  "test/no-identical-title": "error",
1411
- "test/no-only-tests": isEditor ? "off" : "error",
1652
+ "test/no-only-tests": editor ? "off" : "error",
1412
1653
  "test/prefer-hooks-in-order": "error",
1413
1654
  "test/prefer-lowercase-title": "error",
1414
1655
  ...overrides
@@ -1417,93 +1658,38 @@ async function test(options = {}) {
1417
1658
  ];
1418
1659
  }
1419
1660
 
1420
- // src/configs/perfectionist.ts
1421
- async function perfectionist(options = {}) {
1422
- const { enableAllRules = false } = options;
1423
- return [
1424
- {
1425
- name: "luxass:perfectionist",
1426
- plugins: {
1427
- perfectionist: import_eslint_plugin_perfectionist.default
1428
- },
1429
- rules: {
1430
- ...enableAllRules ? {
1431
- ...import_eslint_plugin_perfectionist.default.configs["recommended-natural"].rules,
1432
- "perfectionist/sort-imports": "off",
1433
- // TODO: This rule should probably be enabled in favor of import/order?
1434
- "perfectionist/sort-vue-attributes": "off"
1435
- } : {}
1436
- }
1437
- }
1438
- ];
1439
- }
1440
-
1441
1661
  // src/configs/unocss.ts
1442
- async function unocss() {
1443
- const pluginUnoCSS = await interop(import("@unocss/eslint-plugin"));
1444
- return [
1445
- {
1446
- name: "luxass:unocss",
1447
- plugins: {
1448
- "@unocss": pluginUnoCSS
1449
- },
1450
- rules: {
1451
- ...pluginUnoCSS.configs.recommended.rules
1452
- }
1453
- }
1454
- ];
1455
- }
1456
-
1457
- // src/configs/tailwindcss.ts
1458
- var DEFAULT_TAILWIND_CALLEES = ["classnames", "clsx", "cx", "cn"];
1459
- var DEFAULT_CLASS_REGEX = "^class(Name)?$";
1460
- async function tailwindcss(options = {}) {
1662
+ async function unocss(options = {}) {
1461
1663
  const {
1462
- callees = DEFAULT_TAILWIND_CALLEES,
1463
- classRegex = DEFAULT_CLASS_REGEX,
1464
- config = void 0,
1465
- nextjs: nextjs2,
1466
- removeDuplicates = true
1664
+ attributify = true,
1665
+ files = [GLOB_SRC],
1666
+ overrides,
1667
+ strict = false
1467
1668
  } = options;
1468
1669
  await ensure([
1469
- "eslint-plugin-tailwindcss"
1670
+ "@unocss/eslint-plugin"
1671
+ ]);
1672
+ const [
1673
+ pluginUnoCSS
1674
+ ] = await Promise.all([
1675
+ interop(import("@unocss/eslint-plugin"))
1470
1676
  ]);
1471
- const pluginTailwindCSS = await interop(import("eslint-plugin-tailwindcss"));
1472
- const tailwindCSSCallee = callees ?? DEFAULT_TAILWIND_CALLEES;
1473
1677
  return [
1474
1678
  {
1475
- name: "luxass:tailwindcss",
1679
+ name: "luxass:unocss",
1680
+ files,
1476
1681
  plugins: {
1477
- tailwindcss: pluginTailwindCSS
1478
- }
1479
- },
1480
- {
1481
- files: [GLOB_SRC, GLOB_HTML],
1482
- name: "luxass:tailwindcss:rules",
1483
- rules: {
1484
- "tailwindcss/classnames-order": ["error"],
1485
- "tailwindcss/enforces-negative-arbitrary-values": ["warn"],
1486
- "tailwindcss/enforces-shorthand": ["warn"],
1487
- "tailwindcss/migration-from-tailwind-2": ["warn"],
1488
- "tailwindcss/no-arbitrary-value": ["off"],
1489
- "tailwindcss/no-contradicting-classname": ["error"],
1490
- "tailwindcss/no-custom-classname": ["warn"]
1682
+ unocss: pluginUnoCSS
1491
1683
  },
1492
- settings: {
1493
- tailwindcss: {
1494
- callees: tailwindCSSCallee,
1495
- classRegex: nextjs2 ? "^(class(Name)?|tw)$" : classRegex,
1496
- config,
1497
- removeDuplicates
1498
- }
1499
- }
1500
- },
1501
- {
1502
- files: ["**/tailwind.config.?([cm])[jt]s"],
1503
- name: "luxass:tailwindcss:sort-keys-override",
1504
1684
  rules: {
1505
- "sort-keys": "off",
1506
- "sort-keys/sort-keys-fix": "off"
1685
+ "unocss/order": "warn",
1686
+ ...attributify ? {
1687
+ "unocss/order-attributify": "warn"
1688
+ } : {},
1689
+ ...strict ? {
1690
+ "unocss/blocklist": "error"
1691
+ } : {},
1692
+ ...overrides
1507
1693
  }
1508
1694
  }
1509
1695
  ];
@@ -1511,7 +1697,11 @@ async function tailwindcss(options = {}) {
1511
1697
 
1512
1698
  // src/configs/nextjs.ts
1513
1699
  async function nextjs(options = {}) {
1514
- const { overrides, rootDir } = options;
1700
+ const {
1701
+ files = [GLOB_SRC],
1702
+ overrides,
1703
+ rootDir
1704
+ } = options;
1515
1705
  await ensure([
1516
1706
  "@next/eslint-plugin-next"
1517
1707
  ]);
@@ -1524,8 +1714,8 @@ async function nextjs(options = {}) {
1524
1714
  }
1525
1715
  },
1526
1716
  {
1527
- files: [GLOB_SRC],
1528
1717
  name: "luxass:nextjs:rules",
1718
+ files,
1529
1719
  rules: {
1530
1720
  ...pluginNextjs.configs.recommended.rules,
1531
1721
  ...pluginNextjs.configs["core-web-vitals"].rules,
@@ -1564,15 +1754,16 @@ async function nextjs(options = {}) {
1564
1754
  }
1565
1755
  },
1566
1756
  {
1567
- files: GLOB_NEXTJS_ROUTES,
1568
1757
  name: "luxass:nextjs:default-export-override",
1758
+ files: GLOB_NEXTJS_ROUTES,
1569
1759
  rules: {
1570
- "import/prefer-default-export": "error"
1760
+ "import/prefer-default-export": "error",
1761
+ "react-refresh/only-export-components": "off"
1571
1762
  }
1572
1763
  },
1573
1764
  {
1574
- files: GLOB_NEXTJS_OG,
1575
1765
  name: "luxass:nextjs:og-override",
1766
+ files: GLOB_NEXTJS_OG,
1576
1767
  rules: {
1577
1768
  "@next/next/no-img-element": "off",
1578
1769
  "react/no-unknown-property": ["error", {
@@ -1584,9 +1775,10 @@ async function nextjs(options = {}) {
1584
1775
  }
1585
1776
 
1586
1777
  // src/configs/react.ts
1587
- async function react(options) {
1778
+ async function react(options = {}) {
1588
1779
  const {
1589
1780
  a11y = false,
1781
+ files = [GLOB_JSX, GLOB_TSX],
1590
1782
  overrides = {},
1591
1783
  typescript: typescript2 = true
1592
1784
  } = options;
@@ -1605,7 +1797,7 @@ async function react(options) {
1605
1797
  interop(import("eslint-plugin-react")),
1606
1798
  interop(import("eslint-plugin-react-hooks")),
1607
1799
  interop(import("eslint-plugin-react-refresh")),
1608
- ...options.a11y ? [interop(import("eslint-plugin-jsx-a11y"))] : []
1800
+ ...a11y ? [interop(import("eslint-plugin-jsx-a11y"))] : []
1609
1801
  ]);
1610
1802
  return [
1611
1803
  {
@@ -1618,7 +1810,8 @@ async function react(options) {
1618
1810
  }
1619
1811
  },
1620
1812
  {
1621
- files: [GLOB_JSX],
1813
+ name: "luxass:react:rules",
1814
+ files,
1622
1815
  languageOptions: {
1623
1816
  parserOptions: {
1624
1817
  ecmaFeatures: {
@@ -1626,198 +1819,194 @@ async function react(options) {
1626
1819
  }
1627
1820
  }
1628
1821
  },
1629
- name: "luxass:react:rules",
1630
1822
  rules: {
1631
- // recommended rules for jsx-a11y
1632
- "jsx-a11y/alt-text": "error",
1633
- "jsx-a11y/anchor-ambiguous-text": "off",
1634
- "jsx-a11y/anchor-has-content": "error",
1635
- "jsx-a11y/anchor-is-valid": "error",
1636
- "jsx-a11y/aria-activedescendant-has-tabindex": "error",
1637
- "jsx-a11y/aria-props": "error",
1638
- "jsx-a11y/aria-proptypes": "error",
1639
- "jsx-a11y/aria-role": "error",
1640
- "jsx-a11y/aria-unsupported-elements": "error",
1641
- "jsx-a11y/autocomplete-valid": "error",
1642
- "jsx-a11y/click-events-have-key-events": "error",
1643
- "jsx-a11y/control-has-associated-label": [
1644
- "off",
1645
- {
1646
- ignoreElements: [
1647
- "audio",
1648
- "canvas",
1649
- "embed",
1650
- "input",
1651
- "textarea",
1652
- "tr",
1653
- "video"
1654
- ],
1655
- ignoreRoles: [
1656
- "grid",
1657
- "listbox",
1658
- "menu",
1659
- "menubar",
1660
- "radiogroup",
1661
- "row",
1662
- "tablist",
1663
- "toolbar",
1664
- "tree",
1665
- "treegrid"
1666
- ],
1667
- includeRoles: [
1668
- "alert",
1669
- "dialog"
1670
- ]
1671
- }
1672
- ],
1673
- "jsx-a11y/heading-has-content": "error",
1674
- "jsx-a11y/html-has-lang": "error",
1675
- "jsx-a11y/iframe-has-title": "error",
1676
- "jsx-a11y/img-redundant-alt": "error",
1677
- "jsx-a11y/interactive-supports-focus": [
1678
- "error",
1679
- {
1680
- tabbable: [
1681
- "button",
1682
- "checkbox",
1683
- "link",
1684
- "searchbox",
1685
- "spinbutton",
1686
- "switch",
1687
- "textbox"
1688
- ]
1689
- }
1690
- ],
1691
- "jsx-a11y/label-has-associated-control": "error",
1692
- "jsx-a11y/label-has-for": "off",
1693
- "jsx-a11y/media-has-caption": "error",
1694
- "jsx-a11y/mouse-events-have-key-events": "error",
1695
- "jsx-a11y/no-access-key": "error",
1696
- "jsx-a11y/no-autofocus": "error",
1697
- "jsx-a11y/no-distracting-elements": "error",
1698
- "jsx-a11y/no-interactive-element-to-noninteractive-role": [
1699
- "error",
1700
- {
1701
- canvas: [
1702
- "img"
1703
- ],
1704
- tr: [
1705
- "none",
1706
- "presentation"
1707
- ]
1708
- }
1709
- ],
1710
- "jsx-a11y/no-noninteractive-element-interactions": [
1711
- "error",
1712
- {
1713
- alert: [
1714
- "onKeyUp",
1715
- "onKeyDown",
1716
- "onKeyPress"
1717
- ],
1718
- body: [
1719
- "onError",
1720
- "onLoad"
1721
- ],
1722
- dialog: [
1723
- "onKeyUp",
1724
- "onKeyDown",
1725
- "onKeyPress"
1726
- ],
1727
- handlers: [
1728
- "onClick",
1729
- "onError",
1730
- "onLoad",
1731
- "onMouseDown",
1732
- "onMouseUp",
1733
- "onKeyPress",
1734
- "onKeyDown",
1735
- "onKeyUp"
1736
- ],
1737
- iframe: [
1738
- "onError",
1739
- "onLoad"
1740
- ],
1741
- img: [
1742
- "onError",
1743
- "onLoad"
1744
- ]
1745
- }
1746
- ],
1747
- "jsx-a11y/no-noninteractive-element-to-interactive-role": [
1748
- "error",
1749
- {
1750
- fieldset: [
1751
- "radiogroup",
1752
- "presentation"
1753
- ],
1754
- li: [
1755
- "menuitem",
1756
- "option",
1757
- "row",
1758
- "tab",
1759
- "treeitem"
1760
- ],
1761
- ol: [
1762
- "listbox",
1763
- "menu",
1764
- "menubar",
1765
- "radiogroup",
1766
- "tablist",
1767
- "tree",
1768
- "treegrid"
1769
- ],
1770
- table: [
1771
- "grid"
1772
- ],
1773
- td: [
1774
- "gridcell"
1775
- ],
1776
- ul: [
1777
- "listbox",
1778
- "menu",
1779
- "menubar",
1780
- "radiogroup",
1781
- "tablist",
1782
- "tree",
1783
- "treegrid"
1784
- ]
1785
- }
1786
- ],
1787
- "jsx-a11y/no-noninteractive-tabindex": [
1788
- "error",
1789
- {
1790
- allowExpressionValues: true,
1791
- roles: [
1792
- "tabpanel"
1793
- ],
1794
- tags: []
1795
- }
1796
- ],
1797
- "jsx-a11y/no-redundant-roles": "error",
1798
- "jsx-a11y/no-static-element-interactions": [
1799
- "error",
1800
- {
1801
- allowExpressionValues: true,
1802
- handlers: [
1803
- "onClick",
1804
- "onMouseDown",
1805
- "onMouseUp",
1806
- "onKeyPress",
1807
- "onKeyDown",
1808
- "onKeyUp"
1809
- ]
1810
- }
1811
- ],
1812
- "jsx-a11y/role-has-required-aria-props": "error",
1813
- "jsx-a11y/role-supports-aria-props": "error",
1814
- "jsx-a11y/scope": "error",
1815
- "jsx-a11y/tabindex-no-positive": "error",
1816
- // recommended rules react-hooks
1817
- "react-hooks/exhaustive-deps": "warn",
1818
- "react-hooks/rules-of-hooks": "error",
1819
- // react refresh
1820
- "react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
1823
+ ...a11y ? {
1824
+ // recommended rules for jsx-a11y
1825
+ "jsx-a11y/alt-text": "error",
1826
+ "jsx-a11y/anchor-ambiguous-text": "off",
1827
+ "jsx-a11y/anchor-has-content": "error",
1828
+ "jsx-a11y/anchor-is-valid": "error",
1829
+ "jsx-a11y/aria-activedescendant-has-tabindex": "error",
1830
+ "jsx-a11y/aria-props": "error",
1831
+ "jsx-a11y/aria-proptypes": "error",
1832
+ "jsx-a11y/aria-role": "error",
1833
+ "jsx-a11y/aria-unsupported-elements": "error",
1834
+ "jsx-a11y/autocomplete-valid": "error",
1835
+ "jsx-a11y/click-events-have-key-events": "error",
1836
+ "jsx-a11y/control-has-associated-label": [
1837
+ "off",
1838
+ {
1839
+ ignoreElements: [
1840
+ "audio",
1841
+ "canvas",
1842
+ "embed",
1843
+ "input",
1844
+ "textarea",
1845
+ "tr",
1846
+ "video"
1847
+ ],
1848
+ ignoreRoles: [
1849
+ "grid",
1850
+ "listbox",
1851
+ "menu",
1852
+ "menubar",
1853
+ "radiogroup",
1854
+ "row",
1855
+ "tablist",
1856
+ "toolbar",
1857
+ "tree",
1858
+ "treegrid"
1859
+ ],
1860
+ includeRoles: [
1861
+ "alert",
1862
+ "dialog"
1863
+ ]
1864
+ }
1865
+ ],
1866
+ "jsx-a11y/heading-has-content": "error",
1867
+ "jsx-a11y/html-has-lang": "error",
1868
+ "jsx-a11y/iframe-has-title": "error",
1869
+ "jsx-a11y/img-redundant-alt": "error",
1870
+ "jsx-a11y/interactive-supports-focus": [
1871
+ "error",
1872
+ {
1873
+ tabbable: [
1874
+ "button",
1875
+ "checkbox",
1876
+ "link",
1877
+ "searchbox",
1878
+ "spinbutton",
1879
+ "switch",
1880
+ "textbox"
1881
+ ]
1882
+ }
1883
+ ],
1884
+ "jsx-a11y/label-has-associated-control": "error",
1885
+ "jsx-a11y/label-has-for": "off",
1886
+ "jsx-a11y/media-has-caption": "error",
1887
+ "jsx-a11y/mouse-events-have-key-events": "error",
1888
+ "jsx-a11y/no-access-key": "error",
1889
+ "jsx-a11y/no-autofocus": "error",
1890
+ "jsx-a11y/no-distracting-elements": "error",
1891
+ "jsx-a11y/no-interactive-element-to-noninteractive-role": [
1892
+ "error",
1893
+ {
1894
+ canvas: [
1895
+ "img"
1896
+ ],
1897
+ tr: [
1898
+ "none",
1899
+ "presentation"
1900
+ ]
1901
+ }
1902
+ ],
1903
+ "jsx-a11y/no-noninteractive-element-interactions": [
1904
+ "error",
1905
+ {
1906
+ alert: [
1907
+ "onKeyUp",
1908
+ "onKeyDown",
1909
+ "onKeyPress"
1910
+ ],
1911
+ body: [
1912
+ "onError",
1913
+ "onLoad"
1914
+ ],
1915
+ dialog: [
1916
+ "onKeyUp",
1917
+ "onKeyDown",
1918
+ "onKeyPress"
1919
+ ],
1920
+ handlers: [
1921
+ "onClick",
1922
+ "onError",
1923
+ "onLoad",
1924
+ "onMouseDown",
1925
+ "onMouseUp",
1926
+ "onKeyPress",
1927
+ "onKeyDown",
1928
+ "onKeyUp"
1929
+ ],
1930
+ iframe: [
1931
+ "onError",
1932
+ "onLoad"
1933
+ ],
1934
+ img: [
1935
+ "onError",
1936
+ "onLoad"
1937
+ ]
1938
+ }
1939
+ ],
1940
+ "jsx-a11y/no-noninteractive-element-to-interactive-role": [
1941
+ "error",
1942
+ {
1943
+ fieldset: [
1944
+ "radiogroup",
1945
+ "presentation"
1946
+ ],
1947
+ li: [
1948
+ "menuitem",
1949
+ "option",
1950
+ "row",
1951
+ "tab",
1952
+ "treeitem"
1953
+ ],
1954
+ ol: [
1955
+ "listbox",
1956
+ "menu",
1957
+ "menubar",
1958
+ "radiogroup",
1959
+ "tablist",
1960
+ "tree",
1961
+ "treegrid"
1962
+ ],
1963
+ table: [
1964
+ "grid"
1965
+ ],
1966
+ td: [
1967
+ "gridcell"
1968
+ ],
1969
+ ul: [
1970
+ "listbox",
1971
+ "menu",
1972
+ "menubar",
1973
+ "radiogroup",
1974
+ "tablist",
1975
+ "tree",
1976
+ "treegrid"
1977
+ ]
1978
+ }
1979
+ ],
1980
+ "jsx-a11y/no-noninteractive-tabindex": [
1981
+ "error",
1982
+ {
1983
+ allowExpressionValues: true,
1984
+ roles: [
1985
+ "tabpanel"
1986
+ ],
1987
+ tags: []
1988
+ }
1989
+ ],
1990
+ "jsx-a11y/no-redundant-roles": "error",
1991
+ "jsx-a11y/no-static-element-interactions": [
1992
+ "error",
1993
+ {
1994
+ allowExpressionValues: true,
1995
+ handlers: [
1996
+ "onClick",
1997
+ "onMouseDown",
1998
+ "onMouseUp",
1999
+ "onKeyPress",
2000
+ "onKeyDown",
2001
+ "onKeyUp"
2002
+ ]
2003
+ }
2004
+ ],
2005
+ "jsx-a11y/role-has-required-aria-props": "error",
2006
+ "jsx-a11y/role-supports-aria-props": "error",
2007
+ "jsx-a11y/scope": "error",
2008
+ "jsx-a11y/tabindex-no-positive": "error"
2009
+ } : {},
1821
2010
  // recommended rules react
1822
2011
  "react/display-name": "error",
1823
2012
  "react/jsx-key": "error",
@@ -1841,6 +2030,11 @@ async function react(options) {
1841
2030
  "react/prop-types": "error",
1842
2031
  "react/react-in-jsx-scope": "off",
1843
2032
  "react/require-render-return": "error",
2033
+ // recommended rules react-hooks
2034
+ "react-hooks/exhaustive-deps": "warn",
2035
+ "react-hooks/rules-of-hooks": "error",
2036
+ // react refresh
2037
+ "react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
1844
2038
  ...typescript2 ? {
1845
2039
  "react/prop-type": "off"
1846
2040
  } : {},
@@ -1860,14 +2054,10 @@ async function react(options) {
1860
2054
  async function astro(options) {
1861
2055
  const {
1862
2056
  a11y = false,
1863
- overrides = {}
1864
- // typescript = true,
2057
+ files = [GLOB_ASTRO],
2058
+ overrides = {},
2059
+ typescript: typescript2 = true
1865
2060
  } = options;
1866
- await interop([
1867
- "eslint-plugin-astro",
1868
- "astro-eslint-parser",
1869
- ...options.a11y ? ["eslint-plugin-jsx-a11y"] : []
1870
- ]);
1871
2061
  const [
1872
2062
  pluginAstro,
1873
2063
  parserAstro,
@@ -1875,7 +2065,7 @@ async function astro(options) {
1875
2065
  ] = await Promise.all([
1876
2066
  interop(import("eslint-plugin-astro")),
1877
2067
  interop(import("astro-eslint-parser")),
1878
- ...options.a11y ? [interop(import("eslint-plugin-jsx-a11y"))] : []
2068
+ ...a11y ? [interop(import("eslint-plugin-jsx-a11y"))] : []
1879
2069
  ]);
1880
2070
  return [
1881
2071
  {
@@ -1886,7 +2076,8 @@ async function astro(options) {
1886
2076
  }
1887
2077
  },
1888
2078
  {
1889
- files: [GLOB_ASTRO],
2079
+ name: "luxass:astro:rules",
2080
+ files,
1890
2081
  languageOptions: {
1891
2082
  // @ts-expect-error hmmm
1892
2083
  globals: {
@@ -1895,21 +2086,22 @@ async function astro(options) {
1895
2086
  parser: parserAstro,
1896
2087
  parserOptions: {
1897
2088
  extraFileExtensions: [".astro"],
1898
- parser: options.typescript ? await interop(import("@typescript-eslint/parser")) : null,
2089
+ parser: typescript2 ? await interop(import("@typescript-eslint/parser")) : null,
1899
2090
  sourceType: "module"
1900
2091
  }
1901
2092
  },
1902
- name: "luxass:astro:rules",
1903
2093
  // @ts-expect-error hmmm
1904
2094
  rules: {
1905
2095
  "style/jsx-closing-tag-location": "off",
1906
2096
  "style/jsx-indent": "off",
1907
2097
  "style/jsx-one-expression-per-line": "off",
1908
2098
  ...pluginAstro.configs.all.rules,
2099
+ "style/multiline-ternary": ["error", "never"],
1909
2100
  ...overrides
1910
2101
  }
1911
2102
  },
1912
2103
  {
2104
+ name: "luxass:astro:rules:scripts",
1913
2105
  files: [
1914
2106
  "**/*.astro/*.js",
1915
2107
  "*.astro/*.js"
@@ -1922,15 +2114,232 @@ async function astro(options) {
1922
2114
  parserOptions: {
1923
2115
  sourceType: "module"
1924
2116
  }
2117
+ }
2118
+ }
2119
+ ];
2120
+ }
2121
+
2122
+ // src/configs/tailwindcss.ts
2123
+ async function tailwindcss(options = {}) {
2124
+ const {
2125
+ files = [GLOB_SRC],
2126
+ overrides
2127
+ } = options;
2128
+ await ensure([
2129
+ "eslint-plugin-tailwindcss"
2130
+ ]);
2131
+ const [
2132
+ pluginTailwindCSS
2133
+ ] = await Promise.all([
2134
+ interop(import("eslint-plugin-tailwindcss"))
2135
+ ]);
2136
+ return [
2137
+ {
2138
+ name: "luxass:tailwindcss:setup",
2139
+ languageOptions: {
2140
+ parserOptions: {
2141
+ ecmaFeatures: {
2142
+ jsx: true
2143
+ }
2144
+ }
1925
2145
  },
1926
- name: "luxass:astro:rules:scripts"
2146
+ plugins: {
2147
+ tailwind: pluginTailwindCSS
2148
+ }
2149
+ },
2150
+ {
2151
+ name: "luxass:tailwindcss:rules",
2152
+ files,
2153
+ rules: {
2154
+ // https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/master/docs/rules/classnames-order.md
2155
+ "tailwind/classnames-order": "warn",
2156
+ // https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/master/docs/rules/enforces-negative-arbitrary-values.md
2157
+ "tailwind/enforces-negative-arbitrary-values": "warn",
2158
+ // https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/master/docs/rules/enforces-shorthand.md
2159
+ "tailwind/enforces-shorthand": "warn",
2160
+ // https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/master/docs/rules/migration-from-tailwind-2.md
2161
+ "tailwind/migration-from-tailwind-2": "warn",
2162
+ // https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/master/docs/rules/no-arbitrary-value.md
2163
+ "tailwind/no-arbitrary-value": "off",
2164
+ // https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/master/docs/rules/no-contradicting-classname.md
2165
+ "tailwind/no-contradicting-classname": "error",
2166
+ // https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/master/docs/rules/no-custom-classname.md
2167
+ "tailwind/no-custom-classname": "warn",
2168
+ ...overrides
2169
+ }
2170
+ }
2171
+ ];
2172
+ }
2173
+
2174
+ // src/configs/formatters.ts
2175
+ var parserPlain2 = __toESM(require("eslint-parser-plain"), 1);
2176
+ async function formatters(options = {}, stylistic2 = {}) {
2177
+ await ensure([
2178
+ "eslint-plugin-format"
2179
+ ]);
2180
+ if (options === true) {
2181
+ options = {
2182
+ css: true,
2183
+ graphql: true,
2184
+ html: true,
2185
+ markdown: true
2186
+ };
2187
+ }
2188
+ const {
2189
+ indent,
2190
+ quotes,
2191
+ semi
2192
+ } = {
2193
+ ...StylisticConfigDefaults,
2194
+ ...stylistic2
2195
+ };
2196
+ const prettierOptions = Object.assign(
2197
+ {
2198
+ endOfLine: "auto",
2199
+ semi,
2200
+ singleQuote: quotes === "single",
2201
+ tabWidth: typeof indent === "number" ? indent : 2,
2202
+ trailingComma: "all",
2203
+ useTabs: indent === "tab"
2204
+ },
2205
+ options.prettierOptions || {}
2206
+ );
2207
+ const dprintOptions = Object.assign(
2208
+ {
2209
+ indentWidth: typeof indent === "number" ? indent : 2,
2210
+ quoteStyle: quotes === "single" ? "preferSingle" : "preferDouble",
2211
+ useTabs: indent === "tab"
2212
+ },
2213
+ options.dprintOptions || {}
2214
+ );
2215
+ const pluginFormat = await interop(import("eslint-plugin-format"));
2216
+ const configs = [
2217
+ {
2218
+ name: "luxass:formatters:setup",
2219
+ plugins: {
2220
+ format: pluginFormat
2221
+ }
1927
2222
  }
1928
2223
  ];
2224
+ if (options.css) {
2225
+ configs.push(
2226
+ {
2227
+ name: "luxass:formatter:css",
2228
+ files: [GLOB_CSS, GLOB_POSTCSS],
2229
+ languageOptions: {
2230
+ parser: parserPlain2
2231
+ },
2232
+ rules: {
2233
+ "format/prettier": [
2234
+ "error",
2235
+ {
2236
+ ...prettierOptions,
2237
+ parser: "css"
2238
+ }
2239
+ ]
2240
+ }
2241
+ },
2242
+ {
2243
+ name: "luxass:formatter:scss",
2244
+ files: [GLOB_SCSS],
2245
+ languageOptions: {
2246
+ parser: parserPlain2
2247
+ },
2248
+ rules: {
2249
+ "format/prettier": [
2250
+ "error",
2251
+ {
2252
+ ...prettierOptions,
2253
+ parser: "scss"
2254
+ }
2255
+ ]
2256
+ }
2257
+ },
2258
+ {
2259
+ name: "luxass:formatter:less",
2260
+ files: [GLOB_LESS],
2261
+ languageOptions: {
2262
+ parser: parserPlain2
2263
+ },
2264
+ rules: {
2265
+ "format/prettier": [
2266
+ "error",
2267
+ {
2268
+ ...prettierOptions,
2269
+ parser: "less"
2270
+ }
2271
+ ]
2272
+ }
2273
+ }
2274
+ );
2275
+ }
2276
+ if (options.html) {
2277
+ configs.push({
2278
+ name: "luxass:formatter:html",
2279
+ files: ["**/*.html"],
2280
+ languageOptions: {
2281
+ parser: parserPlain2
2282
+ },
2283
+ rules: {
2284
+ "format/prettier": [
2285
+ "error",
2286
+ {
2287
+ ...prettierOptions,
2288
+ parser: "html"
2289
+ }
2290
+ ]
2291
+ }
2292
+ });
2293
+ }
2294
+ if (options.markdown) {
2295
+ const formater = options.markdown === true ? "prettier" : options.markdown;
2296
+ configs.push({
2297
+ name: "luxass:formatter:markdown",
2298
+ files: [GLOB_MARKDOWN],
2299
+ languageOptions: {
2300
+ parser: parserPlain2
2301
+ },
2302
+ rules: {
2303
+ [`format/${formater}`]: [
2304
+ "error",
2305
+ formater === "prettier" ? {
2306
+ printWidth: 120,
2307
+ ...prettierOptions,
2308
+ embeddedLanguageFormatting: "off",
2309
+ parser: "markdown"
2310
+ } : {
2311
+ ...dprintOptions,
2312
+ language: "markdown"
2313
+ }
2314
+ ]
2315
+ }
2316
+ });
2317
+ }
2318
+ if (options.graphql) {
2319
+ configs.push({
2320
+ name: "luxass:formatter:graphql",
2321
+ files: ["**/*.graphql"],
2322
+ languageOptions: {
2323
+ parser: parserPlain2
2324
+ },
2325
+ rules: {
2326
+ "format/prettier": [
2327
+ "error",
2328
+ {
2329
+ ...prettierOptions,
2330
+ parser: "graphql"
2331
+ }
2332
+ ]
2333
+ }
2334
+ });
2335
+ }
2336
+ return configs;
1929
2337
  }
1930
2338
  // Annotate the CommonJS export names for ESM import in node:
1931
2339
  0 && (module.exports = {
1932
2340
  astro,
1933
2341
  comments,
2342
+ formatters,
1934
2343
  ignores,
1935
2344
  imports,
1936
2345
  javascript,