@ncontiero/eslint-config 7.0.1 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,1739 @@
1
+ import createCommand from "eslint-plugin-command/config";
2
+ import pluginComments from "@eslint-community/eslint-plugin-eslint-comments";
3
+ import pluginAntfu from "eslint-plugin-antfu";
4
+ import pluginDeMorgan from "eslint-plugin-de-morgan";
5
+ import pluginImport from "eslint-plugin-import-x";
6
+ import pluginNode from "eslint-plugin-n";
7
+ import pluginPerfectionist from "eslint-plugin-perfectionist";
8
+ import pluginUnicorn from "eslint-plugin-unicorn";
9
+ import pluginUnusedImports from "eslint-plugin-unused-imports";
10
+ import { isPackageExists } from "local-pkg";
11
+ import globals from "globals";
12
+ import { mergeProcessors, processorPassThrough } from "eslint-merge-processors";
13
+ import { configs } from "eslint-plugin-regexp";
14
+ import path from "node:path";
15
+ //#region src/configs/command.ts
16
+ function command() {
17
+ return [{
18
+ ...createCommand(),
19
+ name: "ncontiero/command/rules"
20
+ }];
21
+ }
22
+ //#endregion
23
+ //#region src/configs/comments.ts
24
+ function comments() {
25
+ return [{
26
+ name: "ncontiero/comments/rules",
27
+ plugins: { "eslint-comments": pluginComments },
28
+ rules: {
29
+ "eslint-comments/disable-enable-pair": ["error", { allowWholeFile: true }],
30
+ "eslint-comments/no-aggregating-enable": "error",
31
+ "eslint-comments/no-duplicate-disable": "error",
32
+ "eslint-comments/no-unlimited-disable": "error",
33
+ "eslint-comments/no-unused-enable": "error"
34
+ }
35
+ }];
36
+ }
37
+ //#endregion
38
+ //#region src/configs/de-morgan.ts
39
+ function deMorgan() {
40
+ return [{
41
+ ...pluginDeMorgan.configs.recommended,
42
+ name: "ncontiero/de-morgan"
43
+ }];
44
+ }
45
+ //#endregion
46
+ //#region src/globs.ts
47
+ const GLOB_SRC_EXT = "?([cm])[jt]s?(x)";
48
+ const GLOB_SRC = "**/*.?([cm])[jt]s?(x)";
49
+ const GLOB_JS = "**/*.?([cm])js";
50
+ const GLOB_JSX = "**/*.?([cm])jsx";
51
+ const GLOB_TS = "**/*.?([cm])ts";
52
+ const GLOB_TSX = "**/*.?([cm])tsx";
53
+ const GLOB_REACT = "**/*.?([cm])?(j|t)sx";
54
+ const GLOB_STYLE = "**/*.{c,le,sc}ss";
55
+ const GLOB_CSS = "**/*.css";
56
+ const GLOB_POSTCSS = "**/*.{p,post}css";
57
+ const GLOB_LESS = "**/*.less";
58
+ const GLOB_SCSS = "**/*.scss";
59
+ const GLOB_JSON = "**/*.json";
60
+ const GLOB_JSON5 = "**/*.json5";
61
+ const GLOB_JSONC = "**/*.jsonc";
62
+ const GLOB_MARKDOWN = "**/*.md";
63
+ const GLOB_MARKDOWN_IN_MARKDOWN = "**/*.md/*.md";
64
+ const GLOB_YAML = "**/*.y?(a)ml";
65
+ const GLOB_TOML = "**/*.toml";
66
+ const GLOB_HTML = "**/*.htm?(l)";
67
+ const GLOB_MARKDOWN_CODE = `${GLOB_MARKDOWN}/${GLOB_SRC}`;
68
+ const GLOB_ALL_SRC = [
69
+ GLOB_SRC,
70
+ GLOB_STYLE,
71
+ GLOB_JSON,
72
+ GLOB_JSON5,
73
+ GLOB_MARKDOWN,
74
+ GLOB_YAML,
75
+ GLOB_HTML
76
+ ];
77
+ const GLOB_NODE_MODULES = "**/node_modules";
78
+ const GLOB_DIST = "**/dist";
79
+ const GLOB_LOCKFILE = [
80
+ "**/package-lock.json",
81
+ "**/yarn.lock",
82
+ "**/pnpm-lock.yaml",
83
+ "**/bun.lockb"
84
+ ];
85
+ const GLOB_EXCLUDE = [
86
+ GLOB_NODE_MODULES,
87
+ GLOB_DIST,
88
+ ...GLOB_LOCKFILE,
89
+ "**/output",
90
+ "**/coverage",
91
+ "**/temp",
92
+ "**/.temp",
93
+ "**/tmp",
94
+ "**/.tmp",
95
+ "**/.history",
96
+ "**/fixtures",
97
+ "**/.git",
98
+ "**/.vitepress/cache",
99
+ "**/.nuxt",
100
+ "**/.next",
101
+ "**/.vercel",
102
+ "**/.contentlayer",
103
+ "**/.changeset",
104
+ "**/.idea",
105
+ "**/.cache",
106
+ "**/.output",
107
+ "**/.vite-inspect",
108
+ "**/.yarn",
109
+ "**/next-env.d.ts",
110
+ "**/.nitro",
111
+ "**/CHANGELOG*.md",
112
+ "**/*.min.*",
113
+ "**/LICENSE*",
114
+ "**/__snapshots__",
115
+ "**/auto-import?(s).d.ts",
116
+ "**/components.d.ts"
117
+ ];
118
+ //#endregion
119
+ //#region src/utils.ts
120
+ const isCwdInScope = isPackageExists("@ncontiero/eslint-config");
121
+ const parserPlain = {
122
+ meta: { name: "parser-plain" },
123
+ parseForESLint: (code) => ({
124
+ ast: {
125
+ body: [],
126
+ comments: [],
127
+ loc: {
128
+ end: code.length,
129
+ start: 0
130
+ },
131
+ range: [0, code.length],
132
+ tokens: [],
133
+ type: "Program"
134
+ },
135
+ scopeManager: null,
136
+ services: { isPlain: true },
137
+ visitorKeys: { Program: [] }
138
+ })
139
+ };
140
+ /**
141
+ * Combine array and non-array configs into a single array.
142
+ */
143
+ async function combine(...configs) {
144
+ return (await Promise.all(configs)).flat();
145
+ }
146
+ async function interopDefault(m) {
147
+ const resolved = await m;
148
+ return resolved.default || resolved;
149
+ }
150
+ function ensurePackages(packages) {
151
+ if (process.env.CI || !process.stdout.isTTY || !isCwdInScope) return;
152
+ const nonExistingPackages = packages.filter((i) => i && !isPackageExists(i));
153
+ if (nonExistingPackages.length === 0) return;
154
+ throw new Error(`This package(s) are required for this config: ${nonExistingPackages.join(", ")}. Please install them.`);
155
+ }
156
+ async function composer(...items) {
157
+ let configs = [];
158
+ const flatResolved = (await Promise.all(items)).flat();
159
+ configs = [...configs, ...flatResolved];
160
+ return configs;
161
+ }
162
+ function toArray(value) {
163
+ return Array.isArray(value) ? value : [value];
164
+ }
165
+ //#endregion
166
+ //#region src/configs/html.ts
167
+ async function html(options) {
168
+ const { overrides = {} } = options;
169
+ const [eslintParserHTML, eslintPluginHTML] = await Promise.all([interopDefault(import("@html-eslint/parser")), interopDefault(import("@html-eslint/eslint-plugin"))]);
170
+ const templateEngineSyntax = options.templateEngineSyntax ?? {
171
+ "{{": "}}",
172
+ "{%": "%}"
173
+ };
174
+ return [{
175
+ files: [GLOB_HTML],
176
+ languageOptions: {
177
+ parser: eslintParserHTML,
178
+ parserOptions: { templateEngineSyntax }
179
+ },
180
+ name: "ncontiero/html/setup",
181
+ plugins: { html: eslintPluginHTML }
182
+ }, {
183
+ files: [GLOB_HTML],
184
+ name: "ncontiero/html/rules",
185
+ rules: {
186
+ "html/attrs-newline": ["warn", { ifAttrsMoreThan: 5 }],
187
+ "html/element-newline": ["warn", { inline: [`$inline`] }],
188
+ "html/indent": ["warn", 2],
189
+ "html/lowercase": "warn",
190
+ "html/no-aria-hidden-body": "error",
191
+ "html/no-aria-hidden-on-focusable": "warn",
192
+ "html/no-duplicate-attrs": "error",
193
+ "html/no-duplicate-class": "warn",
194
+ "html/no-duplicate-id": "error",
195
+ "html/no-duplicate-in-head": "error",
196
+ "html/no-empty-headings": "warn",
197
+ "html/no-extra-spacing-attrs": ["warn", {
198
+ disallowInAssignment: true,
199
+ disallowMissing: true,
200
+ enforceBeforeSelfClose: true
201
+ }],
202
+ "html/no-extra-spacing-text": "warn",
203
+ "html/no-heading-inside-button": "warn",
204
+ "html/no-ineffective-attrs": "warn",
205
+ "html/no-invalid-entity": "warn",
206
+ "html/no-invalid-role": "warn",
207
+ "html/no-multiple-empty-lines": ["warn", { max: 1 }],
208
+ "html/no-multiple-h1": "error",
209
+ "html/no-nested-interactive": "error",
210
+ "html/no-non-scalable-viewport": "warn",
211
+ "html/no-obsolete-tags": "error",
212
+ "html/no-redundant-role": "warn",
213
+ "html/no-script-style-type": "warn",
214
+ "html/no-target-blank": "error",
215
+ "html/no-trailing-spaces": "warn",
216
+ "html/quotes": "warn",
217
+ "html/require-button-type": "warn",
218
+ "html/require-closing-tags": ["warn", { selfClosing: "always" }],
219
+ "html/require-doctype": "error",
220
+ "html/require-form-method": "warn",
221
+ "html/require-img-alt": "warn",
222
+ "html/require-lang": "warn",
223
+ "html/require-li-container": "warn",
224
+ "html/require-meta-charset": "warn",
225
+ "html/require-meta-viewport": "warn",
226
+ "html/require-title": "warn",
227
+ "html/sort-attrs": ["warn", { priority: [
228
+ "name",
229
+ "content",
230
+ "id",
231
+ "type",
232
+ { pattern: "data-.*" },
233
+ "class",
234
+ "style"
235
+ ] }],
236
+ "html/use-baseline": "error",
237
+ ...overrides
238
+ }
239
+ }];
240
+ }
241
+ //#endregion
242
+ //#region src/configs/ignores.ts
243
+ function ignores(userIgnores = []) {
244
+ return [{
245
+ ignores: [...GLOB_EXCLUDE, ...userIgnores],
246
+ name: "ncontiero/global-ignores"
247
+ }];
248
+ }
249
+ //#endregion
250
+ //#region src/configs/imports.ts
251
+ function imports(options = {}) {
252
+ const { nextJs = false } = options;
253
+ return [{
254
+ name: "ncontiero/imports/rules",
255
+ plugins: {
256
+ antfu: pluginAntfu,
257
+ import: pluginImport
258
+ },
259
+ rules: {
260
+ "antfu/import-dedupe": "error",
261
+ "import/first": "error",
262
+ "import/newline-after-import": ["error", { count: 1 }],
263
+ "import/no-default-export": "error",
264
+ "import/no-duplicates": "error",
265
+ "import/no-mutable-exports": "error",
266
+ "import/no-named-default": "error",
267
+ "import/no-self-import": "error",
268
+ "import/no-webpack-loader-syntax": "error"
269
+ }
270
+ }, {
271
+ files: [
272
+ `**/*config*.${GLOB_SRC_EXT}`,
273
+ `**/{views,pages,routes,middleware,plugins,api,app}/${GLOB_SRC}`,
274
+ nextJs ? "{,src/}{middleware,proxy}.{ts,js}" : "",
275
+ `**/{index,vite,esbuild,rollup,rolldown,webpack,rspack}.ts`,
276
+ "**/*.d.ts",
277
+ `${GLOB_MARKDOWN}/**`,
278
+ "**/.prettierrc*"
279
+ ],
280
+ name: "ncontiero/imports/allow-default-export",
281
+ rules: { "import/no-default-export": "off" }
282
+ }];
283
+ }
284
+ //#endregion
285
+ //#region src/configs/javascript.ts
286
+ const restrictedSyntaxJs = [
287
+ "ForInStatement",
288
+ "LabeledStatement",
289
+ "WithStatement"
290
+ ];
291
+ function javascript(options = {}) {
292
+ const { overrides = {} } = options;
293
+ return [
294
+ {
295
+ languageOptions: {
296
+ ecmaVersion: "latest",
297
+ globals: {
298
+ ...globals.browser,
299
+ ...globals.es2026,
300
+ ...globals.node,
301
+ document: "readonly",
302
+ navigator: "readonly",
303
+ window: "readonly"
304
+ },
305
+ parserOptions: {
306
+ ecmaFeatures: { jsx: true },
307
+ ecmaVersion: "latest",
308
+ sourceType: "module"
309
+ },
310
+ sourceType: "module"
311
+ },
312
+ linterOptions: { reportUnusedDisableDirectives: true },
313
+ name: "ncontiero/javascript/rules",
314
+ plugins: {
315
+ antfu: pluginAntfu,
316
+ "unused-imports": pluginUnusedImports
317
+ },
318
+ rules: {
319
+ "array-callback-return": "error",
320
+ "block-scoped-var": "error",
321
+ "constructor-super": "error",
322
+ "dot-notation": "warn",
323
+ eqeqeq: ["error", "smart"],
324
+ "for-direction": "error",
325
+ "getter-return": "error",
326
+ "no-alert": "warn",
327
+ "no-async-promise-executor": "error",
328
+ "no-case-declarations": "error",
329
+ "no-class-assign": "error",
330
+ "no-compare-neg-zero": "error",
331
+ "no-cond-assign": "error",
332
+ "no-console": ["warn", { allow: ["warn", "error"] }],
333
+ "no-const-assign": "error",
334
+ "no-constant-condition": "error",
335
+ "no-control-regex": "error",
336
+ "no-debugger": "warn",
337
+ "no-delete-var": "error",
338
+ "no-dupe-args": "error",
339
+ "no-dupe-class-members": "error",
340
+ "no-dupe-else-if": "error",
341
+ "no-dupe-keys": "error",
342
+ "no-duplicate-case": "error",
343
+ "no-duplicate-imports": "error",
344
+ "no-empty": ["error", { allowEmptyCatch: true }],
345
+ "no-empty-character-class": "error",
346
+ "no-empty-pattern": "error",
347
+ "no-ex-assign": "error",
348
+ "no-extra-boolean-cast": "error",
349
+ "no-fallthrough": ["warn", { commentPattern: "break[\\s\\w]*omitted" }],
350
+ "no-func-assign": "error",
351
+ "no-global-assign": "error",
352
+ "no-import-assign": "error",
353
+ "no-inner-declarations": "error",
354
+ "no-invalid-regexp": "error",
355
+ "no-irregular-whitespace": "error",
356
+ "no-lonely-if": "error",
357
+ "no-loss-of-precision": "error",
358
+ "no-misleading-character-class": "error",
359
+ "no-multi-str": "error",
360
+ "no-new-native-nonconstructor": "error",
361
+ "no-nonoctal-decimal-escape": "error",
362
+ "no-obj-calls": "error",
363
+ "no-octal": "error",
364
+ "no-prototype-builtins": "error",
365
+ "no-redeclare": "error",
366
+ "no-regex-spaces": "error",
367
+ "no-restricted-syntax": ["error", ...restrictedSyntaxJs],
368
+ "no-self-assign": "error",
369
+ "no-setter-return": "error",
370
+ "no-shadow-restricted-names": "error",
371
+ "no-sparse-arrays": "error",
372
+ "no-this-before-super": "error",
373
+ "no-undef": "error",
374
+ "no-unexpected-multiline": "error",
375
+ "no-unreachable": "error",
376
+ "no-unsafe-finally": "error",
377
+ "no-unsafe-negation": "error",
378
+ "no-unsafe-optional-chaining": "error",
379
+ "no-unused-expressions": ["error", {
380
+ allowShortCircuit: true,
381
+ allowTaggedTemplates: true,
382
+ allowTernary: true
383
+ }],
384
+ "no-unused-labels": "error",
385
+ "no-unused-vars": "off",
386
+ "no-useless-backreference": "error",
387
+ "no-useless-catch": "error",
388
+ "no-useless-computed-key": "error",
389
+ "no-useless-constructor": "error",
390
+ "no-useless-escape": "error",
391
+ "no-useless-rename": "error",
392
+ "no-var": "error",
393
+ "no-void": "error",
394
+ "no-with": "error",
395
+ "object-shorthand": [
396
+ "error",
397
+ "always",
398
+ {
399
+ avoidQuotes: true,
400
+ ignoreConstructors: false
401
+ }
402
+ ],
403
+ "prefer-arrow-callback": ["error", {
404
+ allowNamedFunctions: false,
405
+ allowUnboundThis: true
406
+ }],
407
+ "prefer-const": ["warn", {
408
+ destructuring: "all",
409
+ ignoreReadBeforeAssign: true
410
+ }],
411
+ "prefer-exponentiation-operator": "error",
412
+ "prefer-regex-literals": ["error", { disallowRedundantWrapping: true }],
413
+ "prefer-rest-params": "error",
414
+ "prefer-spread": "error",
415
+ "prefer-template": "error",
416
+ "require-await": "error",
417
+ "require-yield": "error",
418
+ "unicode-bom": ["error", "never"],
419
+ "unused-imports/no-unused-imports": "warn",
420
+ "unused-imports/no-unused-vars": ["error", {
421
+ args: "after-used",
422
+ ignoreRestSiblings: true
423
+ }],
424
+ "use-isnan": ["error", {
425
+ enforceForIndexOf: true,
426
+ enforceForSwitchCase: true
427
+ }],
428
+ "valid-typeof": ["error", { requireStringLiterals: true }],
429
+ "vars-on-top": "error",
430
+ ...overrides
431
+ }
432
+ },
433
+ {
434
+ files: [`**/{scripts,cli}/${GLOB_SRC}`, `**/cli.${GLOB_SRC_EXT}`],
435
+ name: "ncontiero/javascript/cli-rules",
436
+ rules: { "no-console": "off" }
437
+ },
438
+ {
439
+ files: [`**/*.{test,spec}.${GLOB_SRC_EXT}`],
440
+ name: "ncontiero/javascript/test-rules",
441
+ rules: {
442
+ "no-unused-expressions": "off",
443
+ "unicorn/consistent-function-scoping": "off"
444
+ }
445
+ }
446
+ ];
447
+ }
448
+ //#endregion
449
+ //#region src/configs/jsdoc.ts
450
+ async function jsdoc() {
451
+ return [{
452
+ name: "ncontiero/jsdoc/setup",
453
+ plugins: { jsdoc: await interopDefault(import("eslint-plugin-jsdoc")) }
454
+ }, {
455
+ files: [GLOB_SRC],
456
+ name: "ncontiero/jsdoc/rules",
457
+ rules: {
458
+ "jsdoc/check-access": "warn",
459
+ "jsdoc/check-param-names": "warn",
460
+ "jsdoc/check-property-names": "warn",
461
+ "jsdoc/check-types": "warn",
462
+ "jsdoc/empty-tags": "warn",
463
+ "jsdoc/implements-on-classes": "warn",
464
+ "jsdoc/no-defaults": "warn",
465
+ "jsdoc/no-multi-asterisks": "warn",
466
+ "jsdoc/require-param-name": "warn",
467
+ "jsdoc/require-property": "warn",
468
+ "jsdoc/require-property-description": "warn",
469
+ "jsdoc/require-property-name": "warn",
470
+ "jsdoc/require-returns-check": "warn",
471
+ "jsdoc/require-returns-description": "warn",
472
+ "jsdoc/require-yields-check": "warn"
473
+ }
474
+ }];
475
+ }
476
+ //#endregion
477
+ //#region src/configs/jsonc.ts
478
+ async function jsonc(options = {}) {
479
+ const { files = [
480
+ GLOB_JSON,
481
+ GLOB_JSON5,
482
+ GLOB_JSONC
483
+ ], overrides = {}, style = true } = options;
484
+ const { indent = 2 } = typeof style === "boolean" ? {} : style;
485
+ const [pluginJsonc] = await Promise.all([interopDefault(import("eslint-plugin-jsonc"))]);
486
+ return [...pluginJsonc.configs["recommended-with-jsonc"].map((config) => ({
487
+ ...config,
488
+ name: `ncontiero/jsonc/${config.name || "recommended"}`
489
+ })), {
490
+ files,
491
+ name: "ncontiero/jsonc/rules",
492
+ rules: {
493
+ "jsonc/array-bracket-spacing": ["error", "never"],
494
+ "jsonc/comma-style": ["error", "last"],
495
+ "jsonc/indent": ["error", indent],
496
+ "jsonc/key-spacing": ["error", {
497
+ afterColon: true,
498
+ beforeColon: false
499
+ }],
500
+ "jsonc/object-curly-newline": ["error", {
501
+ consistent: true,
502
+ multiline: true
503
+ }],
504
+ "jsonc/object-curly-spacing": ["error", "always"],
505
+ "jsonc/object-property-newline": ["error", { allowAllPropertiesOnSameLine: true }],
506
+ "jsonc/quote-props": "off",
507
+ "jsonc/quotes": "off",
508
+ ...overrides
509
+ }
510
+ }];
511
+ }
512
+ //#endregion
513
+ //#region src/configs/markdown.ts
514
+ async function markdown(options = {}) {
515
+ const { files = [GLOB_MARKDOWN], overrides = {} } = options;
516
+ const pluginMarkdown = await interopDefault(import("@eslint/markdown"));
517
+ return [
518
+ {
519
+ name: "ncontiero/markdown/setup",
520
+ plugins: { markdown: pluginMarkdown }
521
+ },
522
+ {
523
+ files,
524
+ ignores: [GLOB_MARKDOWN_IN_MARKDOWN],
525
+ name: "ncontiero/markdown/processor",
526
+ processor: mergeProcessors([pluginMarkdown.processors.markdown, processorPassThrough])
527
+ },
528
+ {
529
+ files,
530
+ languageOptions: { parser: parserPlain },
531
+ name: "ncontiero/markdown/parser"
532
+ },
533
+ {
534
+ files: [GLOB_MARKDOWN_CODE],
535
+ languageOptions: { parserOptions: { ecmaFeatures: { impliedStrict: true } } },
536
+ name: "ncontiero/markdown/rules",
537
+ rules: {
538
+ "@typescript-eslint/comma-dangle": "off",
539
+ "@typescript-eslint/consistent-type-imports": "off",
540
+ "@typescript-eslint/no-extraneous-class": "off",
541
+ "@typescript-eslint/no-namespace": "off",
542
+ "@typescript-eslint/no-redeclare": "off",
543
+ "@typescript-eslint/no-require-imports": "off",
544
+ "@typescript-eslint/no-unused-expressions": "off",
545
+ "@typescript-eslint/no-unused-vars": "off",
546
+ "@typescript-eslint/no-use-before-define": "off",
547
+ "import/newline-after-import": "off",
548
+ "no-alert": "off",
549
+ "no-console": "off",
550
+ "no-restricted-imports": "off",
551
+ "no-undef": "off",
552
+ "no-unused-expressions": "off",
553
+ "no-unused-vars": "off",
554
+ "node/prefer-global/buffer": "off",
555
+ "node/prefer-global/process": "off",
556
+ "unused-imports/no-unused-imports": "off",
557
+ "unused-imports/no-unused-vars": "off",
558
+ ...overrides
559
+ }
560
+ }
561
+ ];
562
+ }
563
+ //#endregion
564
+ //#region src/configs/nextjs.ts
565
+ async function nextJs(options = {}) {
566
+ const { files = [GLOB_REACT], overrides = {} } = options;
567
+ return [{
568
+ files,
569
+ name: "ncontiero/nextjs/rules",
570
+ plugins: { nextjs: await interopDefault(import("@next/eslint-plugin-next")) },
571
+ rules: {
572
+ "nextjs/google-font-display": "warn",
573
+ "nextjs/google-font-preconnect": "warn",
574
+ "nextjs/inline-script-id": "error",
575
+ "nextjs/next-script-for-ga": "warn",
576
+ "nextjs/no-assign-module-variable": "error",
577
+ "nextjs/no-async-client-component": "warn",
578
+ "nextjs/no-before-interactive-script-outside-document": "warn",
579
+ "nextjs/no-css-tags": "warn",
580
+ "nextjs/no-document-import-in-page": "error",
581
+ "nextjs/no-duplicate-head": "error",
582
+ "nextjs/no-head-element": "warn",
583
+ "nextjs/no-head-import-in-document": "error",
584
+ "nextjs/no-html-link-for-pages": "warn",
585
+ "nextjs/no-img-element": "warn",
586
+ "nextjs/no-page-custom-font": "warn",
587
+ "nextjs/no-script-component-in-head": "error",
588
+ "nextjs/no-styled-jsx-in-document": "warn",
589
+ "nextjs/no-sync-scripts": "warn",
590
+ "nextjs/no-title-in-document-head": "warn",
591
+ "nextjs/no-typos": "warn",
592
+ "nextjs/no-unwanted-polyfillio": "warn",
593
+ ...overrides
594
+ }
595
+ }];
596
+ }
597
+ //#endregion
598
+ //#region src/configs/node.ts
599
+ function node() {
600
+ return [{
601
+ name: "ncontiero/node/setup",
602
+ plugins: { node: pluginNode }
603
+ }, {
604
+ files: [GLOB_SRC],
605
+ name: "ncontiero/node/rules",
606
+ rules: {
607
+ "node/handle-callback-err": ["error", "^(err|error)$"],
608
+ "node/no-deprecated-api": "error",
609
+ "node/no-exports-assign": "error",
610
+ "node/no-new-require": "error",
611
+ "node/no-path-concat": "error",
612
+ "node/no-unsupported-features/es-builtins": "error",
613
+ "node/no-unsupported-features/es-syntax": "error",
614
+ "node/no-unsupported-features/node-builtins": "error",
615
+ "node/prefer-global/console": ["error", "always"],
616
+ "node/prefer-global/process": ["error", "always"],
617
+ "node/prefer-global/url": ["error", "always"],
618
+ "node/prefer-global/url-search-params": ["error", "always"],
619
+ "node/process-exit-as-throw": "error"
620
+ }
621
+ }];
622
+ }
623
+ //#endregion
624
+ //#region src/configs/perfectionist.ts
625
+ /**
626
+ * Perfectionist plugin for props and items sorting.
627
+ *
628
+ * @see https://github.com/azat-io/eslint-plugin-perfectionist
629
+ */
630
+ function perfectionist() {
631
+ return [{
632
+ name: "ncontiero/perfectionist/rules",
633
+ plugins: { perfectionist: pluginPerfectionist },
634
+ rules: {
635
+ "perfectionist/sort-exports": ["warn", { type: "natural" }],
636
+ "perfectionist/sort-imports": ["warn", {
637
+ customGroups: [{
638
+ elementNamePattern: ["^react$", "^react-(?!.*.css$).+"],
639
+ groupName: "react"
640
+ }],
641
+ groups: [
642
+ "side-effect-style",
643
+ "style",
644
+ "type-import",
645
+ "type-external",
646
+ "type-internal",
647
+ [
648
+ "type-parent",
649
+ "type-sibling",
650
+ "type-index"
651
+ ],
652
+ "builtin",
653
+ "react",
654
+ "external",
655
+ "internal",
656
+ [
657
+ "parent",
658
+ "sibling",
659
+ "index"
660
+ ],
661
+ "unknown"
662
+ ],
663
+ internalPattern: ["^[~@#]/.*"],
664
+ newlinesBetween: "ignore",
665
+ type: "natural"
666
+ }],
667
+ "perfectionist/sort-named-exports": ["warn", { groups: ["type-export", "value-export"] }],
668
+ "perfectionist/sort-named-imports": ["warn", { groups: ["type-import", "value-import"] }]
669
+ }
670
+ }];
671
+ }
672
+ //#endregion
673
+ //#region src/configs/prettier.ts
674
+ async function prettier(options = {}) {
675
+ return [
676
+ {
677
+ name: "ncontiero/prettier/setup",
678
+ plugins: { prettier: await interopDefault(import("eslint-plugin-prettier")) }
679
+ },
680
+ {
681
+ files: [GLOB_SRC],
682
+ name: "ncontiero/prettier/disables",
683
+ rules: {
684
+ "antfu/consistent-list-newline": "off",
685
+ "arrow-body-style": "off",
686
+ curly: "off",
687
+ "no-unexpected-multiline": "off",
688
+ "prefer-arrow-callback": "off",
689
+ "unicorn/empty-brace-spaces": "off",
690
+ "unicorn/no-nested-ternary": "off",
691
+ "unicorn/number-literal-case": "off",
692
+ "unicorn/template-indent": "off"
693
+ }
694
+ },
695
+ {
696
+ files: [GLOB_SRC],
697
+ name: "ncontiero/prettier/rules",
698
+ rules: { "prettier/prettier": ["warn", options] }
699
+ },
700
+ {
701
+ files: [GLOB_MARKDOWN],
702
+ languageOptions: { parser: parserPlain },
703
+ name: "ncontiero/prettier/markdown",
704
+ rules: { "prettier/prettier": ["warn", {
705
+ ...options,
706
+ parser: "markdown"
707
+ }] }
708
+ },
709
+ {
710
+ files: [GLOB_CSS, GLOB_POSTCSS],
711
+ languageOptions: { parser: parserPlain },
712
+ name: "ncontiero/prettier/css",
713
+ rules: { "prettier/prettier": ["warn", {
714
+ ...options,
715
+ parser: "css"
716
+ }] }
717
+ },
718
+ {
719
+ files: [GLOB_SCSS],
720
+ languageOptions: { parser: parserPlain },
721
+ name: "ncontiero/prettier/scss",
722
+ rules: { "prettier/prettier": ["warn", {
723
+ ...options,
724
+ parser: "scss"
725
+ }] }
726
+ },
727
+ {
728
+ files: [GLOB_LESS],
729
+ languageOptions: { parser: parserPlain },
730
+ name: "ncontiero/prettier/less",
731
+ rules: { "prettier/prettier": ["warn", {
732
+ ...options,
733
+ parser: "less"
734
+ }] }
735
+ }
736
+ ];
737
+ }
738
+ //#endregion
739
+ //#region src/configs/promise.ts
740
+ async function promise() {
741
+ return [{
742
+ ...(await interopDefault(import("eslint-plugin-promise"))).configs["flat/recommended"],
743
+ name: "ncontiero/promise/setup"
744
+ }, {
745
+ name: "ncontiero/promise/rules",
746
+ rules: {
747
+ "promise/always-return": ["error", { ignoreLastCallback: true }],
748
+ "promise/no-multiple-resolved": "warn"
749
+ }
750
+ }];
751
+ }
752
+ //#endregion
753
+ //#region src/configs/react.ts
754
+ const ReactRefreshAllowPackages = ["vite"];
755
+ const ReactRouterPackages = [
756
+ "@react-router/node",
757
+ "@react-router/react",
758
+ "@react-router/serve",
759
+ "@react-router/dev"
760
+ ];
761
+ const NextJsPackages = ["next"];
762
+ async function react(options = {}) {
763
+ const { files = [GLOB_REACT], overrides = {}, reactQuery, typescript } = options;
764
+ if (reactQuery) ensurePackages(["@tanstack/eslint-plugin-query"]);
765
+ const [pluginA11y, pluginReact, pluginReactHooks, pluginReactRefresh] = await Promise.all([
766
+ interopDefault(import("eslint-plugin-jsx-a11y")),
767
+ interopDefault(import("eslint-plugin-react")),
768
+ interopDefault(import("eslint-plugin-react-hooks")),
769
+ interopDefault(import("eslint-plugin-react-refresh"))
770
+ ]);
771
+ const isAllowConstantExport = ReactRefreshAllowPackages.some((i) => isPackageExists(i));
772
+ const isUsingReactRouter = ReactRouterPackages.some((i) => isPackageExists(i));
773
+ const isUsingNextJs = NextJsPackages.some((i) => isPackageExists(i));
774
+ return [
775
+ {
776
+ files,
777
+ name: "ncontiero/react/setup",
778
+ plugins: {
779
+ "jsx-a11y": pluginA11y,
780
+ react: pluginReact,
781
+ "react-hooks": pluginReactHooks,
782
+ "react-refresh": pluginReactRefresh
783
+ },
784
+ settings: { react: { version: "detect" } }
785
+ },
786
+ reactQuery ? {
787
+ ...(await interopDefault(import("@tanstack/eslint-plugin-query"))).configs["flat/recommended"][0],
788
+ name: "ncontiero/tanstack-query"
789
+ } : {},
790
+ {
791
+ files,
792
+ languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } },
793
+ name: "ncontiero/react/rules",
794
+ rules: {
795
+ "react-hooks/component-hook-factories": "warn",
796
+ "react-hooks/error-boundaries": "warn",
797
+ "react-hooks/exhaustive-deps": "warn",
798
+ "react-hooks/globals": "warn",
799
+ "react-hooks/immutability": "warn",
800
+ "react-hooks/incompatible-library": "warn",
801
+ "react-hooks/preserve-manual-memoization": "warn",
802
+ "react-hooks/purity": "warn",
803
+ "react-hooks/refs": "warn",
804
+ "react-hooks/rules-of-hooks": "error",
805
+ "react-hooks/set-state-in-effect": "warn",
806
+ "react-hooks/set-state-in-render": "warn",
807
+ "react-hooks/static-components": "warn",
808
+ "react-hooks/unsupported-syntax": "warn",
809
+ "react-hooks/use-memo": "warn",
810
+ "react-refresh/only-export-components": ["warn", {
811
+ allowConstantExport: isAllowConstantExport,
812
+ allowExportNames: [...isUsingNextJs ? [
813
+ "experimental_ppr",
814
+ "dynamic",
815
+ "dynamicParams",
816
+ "revalidate",
817
+ "fetchCache",
818
+ "runtime",
819
+ "preferredRegion",
820
+ "maxDuration",
821
+ "metadata",
822
+ "generateMetadata",
823
+ "viewport",
824
+ "generateViewport",
825
+ "generateImageMetadata",
826
+ "generateSitemaps",
827
+ "generateStaticParams"
828
+ ] : [], ...isUsingReactRouter ? [
829
+ "meta",
830
+ "links",
831
+ "headers",
832
+ "loader",
833
+ "action",
834
+ "clientLoader",
835
+ "clientAction",
836
+ "handle",
837
+ "shouldRevalidate"
838
+ ] : []]
839
+ }],
840
+ "react/boolean-prop-naming": ["off", {
841
+ rule: "^(is|has|are|can|should|did|will)[A-Z]([A-Za-z0-9])+",
842
+ validateNested: true
843
+ }],
844
+ "react/button-has-type": ["error", {
845
+ button: true,
846
+ reset: false,
847
+ submit: true
848
+ }],
849
+ "react/display-name": ["error", { ignoreTranspilerName: false }],
850
+ "react/hook-use-state": ["error"],
851
+ "react/iframe-missing-sandbox": ["error"],
852
+ "react/jsx-boolean-value": ["error", "never"],
853
+ "react/jsx-filename-extension": ["warn", { extensions: [".tsx"] }],
854
+ "react/jsx-fragments": ["error", "syntax"],
855
+ "react/jsx-handler-names": ["error", {
856
+ eventHandlerPrefix: "handle",
857
+ eventHandlerPropPrefix: "on"
858
+ }],
859
+ "react/jsx-key": ["error", {
860
+ checkFragmentShorthand: true,
861
+ checkKeyMustBeforeSpread: true,
862
+ warnOnDuplicates: true
863
+ }],
864
+ "react/jsx-no-bind": ["error", { allowArrowFunctions: true }],
865
+ "react/jsx-no-comment-textnodes": "error",
866
+ "react/jsx-no-constructed-context-values": "error",
867
+ "react/jsx-no-duplicate-props": ["error"],
868
+ "react/jsx-no-leaked-render": ["error"],
869
+ "react/jsx-no-script-url": ["error", [{
870
+ name: "Link",
871
+ props: ["to"]
872
+ }]],
873
+ "react/jsx-no-target-blank": ["error", {
874
+ forms: true,
875
+ links: true,
876
+ warnOnSpreadAttributes: true
877
+ }],
878
+ "react/jsx-no-undef": "error",
879
+ "react/jsx-no-useless-fragment": "error",
880
+ "react/jsx-uses-react": "error",
881
+ "react/jsx-uses-vars": "error",
882
+ "react/no-access-state-in-setstate": "error",
883
+ "react/no-array-index-key": "error",
884
+ "react/no-arrow-function-lifecycle": "error",
885
+ "react/no-children-prop": "error",
886
+ "react/no-danger": "error",
887
+ "react/no-danger-with-children": "error",
888
+ "react/no-deprecated": "error",
889
+ "react/no-did-update-set-state": "error",
890
+ "react/no-direct-mutation-state": "error",
891
+ "react/no-find-dom-node": "error",
892
+ "react/no-invalid-html-attribute": "error",
893
+ "react/no-is-mounted": "error",
894
+ "react/no-namespace": "error",
895
+ "react/no-object-type-as-default-prop": "error",
896
+ "react/no-redundant-should-component-update": "error",
897
+ "react/no-render-return-value": "error",
898
+ "react/no-string-refs": ["error", { noTemplateLiterals: true }],
899
+ "react/no-this-in-sfc": ["error"],
900
+ "react/no-typos": ["error"],
901
+ "react/no-unescaped-entities": "error",
902
+ "react/no-unknown-property": "error",
903
+ "react/no-unstable-nested-components": ["error"],
904
+ "react/no-unused-class-component-methods": ["error"],
905
+ "react/no-unused-prop-types": ["error", {
906
+ customValidators: [],
907
+ skipShapeProps: true
908
+ }],
909
+ "react/no-unused-state": ["error"],
910
+ "react/no-will-update-set-state": ["error"],
911
+ "react/prefer-es6-class": ["error", "always"],
912
+ "react/prefer-exact-props": ["error"],
913
+ "react/prefer-read-only-props": ["error"],
914
+ "react/prefer-stateless-function": ["error", { ignorePureComponents: true }],
915
+ "react/prop-types": ["error", {
916
+ customValidators: [],
917
+ ignore: [],
918
+ skipUndeclared: false
919
+ }],
920
+ "react/react-in-jsx-scope": "off",
921
+ "react/require-render-return": "error",
922
+ "react/self-closing-comp": ["error", {
923
+ component: true,
924
+ html: true
925
+ }],
926
+ "react/sort-default-props": ["error"],
927
+ "react/state-in-constructor": ["error", "never"],
928
+ "react/static-property-placement": ["error", "property assignment"],
929
+ "react/style-prop-object": ["error", { allow: ["FormattedNumber"] }],
930
+ "react/void-dom-elements-no-children": ["error"],
931
+ ...typescript ? {
932
+ "react/jsx-no-undef": "off",
933
+ "react/prop-types": "off"
934
+ } : {},
935
+ "jsx-a11y/alt-text": ["warn", {
936
+ area: [],
937
+ elements: [
938
+ "img",
939
+ "object",
940
+ "area",
941
+ "input[type=\"image\"]"
942
+ ],
943
+ img: [],
944
+ "input[type=\"image\"]": [],
945
+ object: []
946
+ }],
947
+ "jsx-a11y/anchor-has-content": ["warn", { components: [] }],
948
+ "jsx-a11y/anchor-is-valid": ["warn", {
949
+ aspects: [
950
+ "noHref",
951
+ "invalidHref",
952
+ "preferButton"
953
+ ],
954
+ components: ["Link"],
955
+ specialLink: ["to"]
956
+ }],
957
+ "jsx-a11y/aria-activedescendant-has-tabindex": ["warn"],
958
+ "jsx-a11y/aria-props": ["warn"],
959
+ "jsx-a11y/aria-proptypes": ["warn"],
960
+ "jsx-a11y/aria-role": ["warn", { ignoreNonDOM: false }],
961
+ "jsx-a11y/aria-unsupported-elements": ["warn"],
962
+ "jsx-a11y/autocomplete-valid": ["off", { inputComponents: [] }],
963
+ "jsx-a11y/click-events-have-key-events": ["warn"],
964
+ "jsx-a11y/control-has-associated-label": ["warn", {
965
+ controlComponents: [],
966
+ depth: 5,
967
+ ignoreElements: [
968
+ "audio",
969
+ "canvas",
970
+ "embed",
971
+ "input",
972
+ "textarea",
973
+ "tr",
974
+ "video"
975
+ ],
976
+ ignoreRoles: [
977
+ "grid",
978
+ "listbox",
979
+ "menu",
980
+ "menubar",
981
+ "radiogroup",
982
+ "row",
983
+ "tablist",
984
+ "toolbar",
985
+ "tree",
986
+ "treegrid"
987
+ ],
988
+ labelAttributes: ["label"]
989
+ }],
990
+ "jsx-a11y/heading-has-content": ["warn", { components: [""] }],
991
+ "jsx-a11y/html-has-lang": ["warn"],
992
+ "jsx-a11y/iframe-has-title": ["warn"],
993
+ "jsx-a11y/img-redundant-alt": ["warn"],
994
+ "jsx-a11y/interactive-supports-focus": ["warn"],
995
+ "jsx-a11y/label-has-associated-control": "warn",
996
+ "jsx-a11y/lang": ["warn"],
997
+ "jsx-a11y/media-has-caption": ["warn", {
998
+ audio: [],
999
+ track: [],
1000
+ video: []
1001
+ }],
1002
+ "jsx-a11y/mouse-events-have-key-events": ["warn"],
1003
+ "jsx-a11y/no-access-key": ["warn"],
1004
+ "jsx-a11y/no-autofocus": ["warn", { ignoreNonDOM: true }],
1005
+ "jsx-a11y/no-distracting-elements": ["warn", { elements: ["marquee", "blink"] }],
1006
+ "jsx-a11y/no-interactive-element-to-noninteractive-role": ["warn", { tr: ["none", "presentation"] }],
1007
+ "jsx-a11y/no-noninteractive-element-interactions": ["warn", { handlers: [
1008
+ "onClick",
1009
+ "onMouseDown",
1010
+ "onMouseUp",
1011
+ "onKeyPress",
1012
+ "onKeyDown",
1013
+ "onKeyUp"
1014
+ ] }],
1015
+ "jsx-a11y/no-noninteractive-element-to-interactive-role": ["warn", {
1016
+ li: [
1017
+ "menuitem",
1018
+ "option",
1019
+ "row",
1020
+ "tab",
1021
+ "treeitem"
1022
+ ],
1023
+ ol: [
1024
+ "listbox",
1025
+ "menu",
1026
+ "menubar",
1027
+ "radiogroup",
1028
+ "tablist",
1029
+ "tree",
1030
+ "treegrid"
1031
+ ],
1032
+ table: ["grid"],
1033
+ td: ["gridcell"],
1034
+ ul: [
1035
+ "listbox",
1036
+ "menu",
1037
+ "menubar",
1038
+ "radiogroup",
1039
+ "tablist",
1040
+ "tree",
1041
+ "treegrid"
1042
+ ]
1043
+ }],
1044
+ "jsx-a11y/no-noninteractive-tabindex": ["warn", {
1045
+ roles: ["tabpanel"],
1046
+ tags: []
1047
+ }],
1048
+ "jsx-a11y/no-redundant-roles": ["warn"],
1049
+ "jsx-a11y/no-static-element-interactions": ["off", { handlers: [
1050
+ "onClick",
1051
+ "onMouseDown",
1052
+ "onMouseUp",
1053
+ "onKeyPress",
1054
+ "onKeyDown",
1055
+ "onKeyUp"
1056
+ ] }],
1057
+ "jsx-a11y/role-has-required-aria-props": ["warn"],
1058
+ "jsx-a11y/role-supports-aria-props": ["warn"],
1059
+ "jsx-a11y/scope": ["warn"],
1060
+ "jsx-a11y/tabindex-no-positive": ["warn"],
1061
+ ...overrides
1062
+ }
1063
+ }
1064
+ ];
1065
+ }
1066
+ //#endregion
1067
+ //#region src/configs/regexp.ts
1068
+ function regexp(options = {}) {
1069
+ const config = configs["flat/recommended"];
1070
+ const rules = {
1071
+ ...config.rules,
1072
+ ...options.overrides
1073
+ };
1074
+ return [{
1075
+ ...config,
1076
+ name: "ncontiero/regexp/rules",
1077
+ rules
1078
+ }];
1079
+ }
1080
+ //#endregion
1081
+ //#region src/configs/sort.ts
1082
+ function sortPackageJson() {
1083
+ return [{
1084
+ files: ["**/package.json"],
1085
+ name: "ncontiero/sort/package-json",
1086
+ rules: {
1087
+ "jsonc/sort-array-values": ["error", {
1088
+ order: { type: "asc" },
1089
+ pathPattern: "^files$"
1090
+ }],
1091
+ "jsonc/sort-keys": [
1092
+ "error",
1093
+ {
1094
+ order: [
1095
+ "publisher",
1096
+ "name",
1097
+ "displayName",
1098
+ "type",
1099
+ "version",
1100
+ "private",
1101
+ "packageManager",
1102
+ "description",
1103
+ "author",
1104
+ "contributors",
1105
+ "license",
1106
+ "funding",
1107
+ "homepage",
1108
+ "repository",
1109
+ "bugs",
1110
+ "keywords",
1111
+ "categories",
1112
+ "sideEffects",
1113
+ "imports",
1114
+ "exports",
1115
+ "main",
1116
+ "module",
1117
+ "unpkg",
1118
+ "jsdelivr",
1119
+ "browser",
1120
+ "types",
1121
+ "typesVersions",
1122
+ "bin",
1123
+ "icon",
1124
+ "files",
1125
+ "directories",
1126
+ "publishConfig",
1127
+ "scripts",
1128
+ "peerDependencies",
1129
+ "peerDependenciesMeta",
1130
+ "optionalDependencies",
1131
+ "dependencies",
1132
+ "devDependencies",
1133
+ "engines",
1134
+ "prisma",
1135
+ "config",
1136
+ "pnpm",
1137
+ "overrides",
1138
+ "resolutions",
1139
+ "husky",
1140
+ "lint-staged",
1141
+ "eslintConfig",
1142
+ "prettier"
1143
+ ],
1144
+ pathPattern: "^$"
1145
+ },
1146
+ {
1147
+ order: { type: "asc" },
1148
+ pathPattern: "^(?:dev|peer|optional|bundled)?[Dd]ependencies(Meta)?$"
1149
+ },
1150
+ {
1151
+ order: [
1152
+ "types",
1153
+ "require",
1154
+ "import",
1155
+ "default"
1156
+ ],
1157
+ pathPattern: "^exports.*$"
1158
+ },
1159
+ {
1160
+ order: { type: "asc" },
1161
+ pathPattern: "^(?:resolutions|overrides|pnpm.overrides)$"
1162
+ },
1163
+ {
1164
+ order: { type: "asc" },
1165
+ pathPattern: "^workspaces\\.catalog$"
1166
+ },
1167
+ {
1168
+ order: { type: "asc" },
1169
+ pathPattern: "^workspaces\\.catalogs\\.[^.]+$"
1170
+ }
1171
+ ]
1172
+ }
1173
+ }];
1174
+ }
1175
+ function sortTsconfig() {
1176
+ return [{
1177
+ files: ["**/[jt]sconfig.json", "**/[jt]sconfig.*.json"],
1178
+ name: "ncontiero/sort/tsconfig",
1179
+ rules: { "jsonc/sort-keys": [
1180
+ "error",
1181
+ {
1182
+ order: [
1183
+ "extends",
1184
+ "compilerOptions",
1185
+ "references",
1186
+ "files",
1187
+ "include",
1188
+ "exclude"
1189
+ ],
1190
+ pathPattern: "^$"
1191
+ },
1192
+ {
1193
+ order: [
1194
+ "incremental",
1195
+ "composite",
1196
+ "tsBuildInfoFile",
1197
+ "disableSourceOfProjectReferenceRedirect",
1198
+ "disableSolutionSearching",
1199
+ "disableReferencedProjectLoad",
1200
+ "target",
1201
+ "jsx",
1202
+ "jsxFactory",
1203
+ "jsxFragmentFactory",
1204
+ "jsxImportSource",
1205
+ "lib",
1206
+ "moduleDetection",
1207
+ "noLib",
1208
+ "reactNamespace",
1209
+ "useDefineForClassFields",
1210
+ "emitDecoratorMetadata",
1211
+ "experimentalDecorators",
1212
+ "libReplacement",
1213
+ "baseUrl",
1214
+ "rootDir",
1215
+ "rootDirs",
1216
+ "customConditions",
1217
+ "module",
1218
+ "moduleResolution",
1219
+ "moduleSuffixes",
1220
+ "noResolve",
1221
+ "paths",
1222
+ "resolveJsonModule",
1223
+ "resolvePackageJsonExports",
1224
+ "resolvePackageJsonImports",
1225
+ "typeRoots",
1226
+ "types",
1227
+ "allowArbitraryExtensions",
1228
+ "allowImportingTsExtensions",
1229
+ "allowUmdGlobalAccess",
1230
+ "allowJs",
1231
+ "checkJs",
1232
+ "maxNodeModuleJsDepth",
1233
+ "strict",
1234
+ "strictBindCallApply",
1235
+ "strictFunctionTypes",
1236
+ "strictNullChecks",
1237
+ "strictPropertyInitialization",
1238
+ "allowUnreachableCode",
1239
+ "allowUnusedLabels",
1240
+ "alwaysStrict",
1241
+ "exactOptionalPropertyTypes",
1242
+ "noFallthroughCasesInSwitch",
1243
+ "noImplicitAny",
1244
+ "noImplicitOverride",
1245
+ "noImplicitReturns",
1246
+ "noImplicitThis",
1247
+ "noPropertyAccessFromIndexSignature",
1248
+ "noUncheckedIndexedAccess",
1249
+ "noUnusedLocals",
1250
+ "noUnusedParameters",
1251
+ "useUnknownInCatchVariables",
1252
+ "declaration",
1253
+ "declarationDir",
1254
+ "declarationMap",
1255
+ "downlevelIteration",
1256
+ "emitBOM",
1257
+ "emitDeclarationOnly",
1258
+ "importHelpers",
1259
+ "importsNotUsedAsValues",
1260
+ "inlineSourceMap",
1261
+ "inlineSources",
1262
+ "isolatedDeclarations",
1263
+ "mapRoot",
1264
+ "newLine",
1265
+ "noEmit",
1266
+ "noEmitHelpers",
1267
+ "noEmitOnError",
1268
+ "outDir",
1269
+ "outFile",
1270
+ "preserveConstEnums",
1271
+ "preserveValueImports",
1272
+ "removeComments",
1273
+ "sourceMap",
1274
+ "sourceRoot",
1275
+ "stripInternal",
1276
+ "allowSyntheticDefaultImports",
1277
+ "esModuleInterop",
1278
+ "forceConsistentCasingInFileNames",
1279
+ "isolatedModules",
1280
+ "preserveSymlinks",
1281
+ "verbatimModuleSyntax",
1282
+ "erasableSyntaxOnly",
1283
+ "skipDefaultLibCheck",
1284
+ "skipLibCheck"
1285
+ ],
1286
+ pathPattern: "^compilerOptions$"
1287
+ }
1288
+ ] }
1289
+ }];
1290
+ }
1291
+ const sortPnpmWorkspace = () => [{
1292
+ files: ["**/pnpm-workspace.yaml"],
1293
+ name: "ncontiero/sort/pnpm-workspace",
1294
+ rules: { "yml/sort-keys": [
1295
+ "error",
1296
+ {
1297
+ order: [
1298
+ "packages",
1299
+ "overrides",
1300
+ "patchedDependencies",
1301
+ "defines",
1302
+ "catalog",
1303
+ "catalogs",
1304
+ { order: { type: "asc" } }
1305
+ ],
1306
+ pathPattern: "^$"
1307
+ },
1308
+ {
1309
+ allowLineSeparatedGroups: true,
1310
+ order: { type: "asc" },
1311
+ pathPattern: "^(catalog|catalogs|overrides)$"
1312
+ },
1313
+ {
1314
+ allowLineSeparatedGroups: true,
1315
+ order: { type: "asc" },
1316
+ pathPattern: String.raw`^catalogs\..+$`
1317
+ }
1318
+ ] }
1319
+ }];
1320
+ //#endregion
1321
+ //#region src/configs/tailwindcss.ts
1322
+ async function tailwindcss(options = {}) {
1323
+ const { overrides = {} } = options;
1324
+ const resolvePath = (p) => {
1325
+ if (path.isAbsolute(p)) return p;
1326
+ return path.resolve(process.cwd(), p);
1327
+ };
1328
+ const cssGlobalPath = resolvePath(options.cssGlobalPath ?? path.join("src", "app", "globals.css"));
1329
+ const configPath = resolvePath(options.configPath ?? path.join("tailwind.config.ts"));
1330
+ const cwd = options.cwd ? resolvePath(options.cwd) : void 0;
1331
+ return [{
1332
+ name: "ncontiero/tailwindcss/setup",
1333
+ plugins: { tailwindcss: await interopDefault(import("eslint-plugin-better-tailwindcss")) },
1334
+ settings: { tailwindcss: {
1335
+ cwd,
1336
+ entryPoint: cssGlobalPath,
1337
+ tailwindConfig: configPath
1338
+ } }
1339
+ }, {
1340
+ files: [GLOB_REACT, GLOB_HTML],
1341
+ name: "ncontiero/tailwindcss/rules",
1342
+ rules: {
1343
+ "tailwindcss/enforce-consistent-class-order": "warn",
1344
+ "tailwindcss/enforce-consistent-important-position": "warn",
1345
+ "tailwindcss/enforce-consistent-line-wrapping": ["warn", {
1346
+ group: "never",
1347
+ preferSingleLine: true,
1348
+ printWidth: 120
1349
+ }],
1350
+ "tailwindcss/enforce-consistent-variable-syntax": "error",
1351
+ "tailwindcss/enforce-shorthand-classes": "warn",
1352
+ "tailwindcss/no-conflicting-classes": "error",
1353
+ "tailwindcss/no-deprecated-classes": "error",
1354
+ "tailwindcss/no-duplicate-classes": "error",
1355
+ "tailwindcss/no-restricted-classes": "error",
1356
+ "tailwindcss/no-unknown-classes": "off",
1357
+ "tailwindcss/no-unnecessary-whitespace": "warn",
1358
+ ...overrides
1359
+ }
1360
+ }];
1361
+ }
1362
+ //#endregion
1363
+ //#region src/configs/toml.ts
1364
+ async function toml(options = {}) {
1365
+ const { files = [GLOB_TOML], overrides = {}, style = true } = options;
1366
+ const { indent = 2 } = typeof style === "boolean" ? {} : style;
1367
+ const [pluginToml, parserToml] = await Promise.all([interopDefault(import("eslint-plugin-toml")), interopDefault(import("toml-eslint-parser"))]);
1368
+ return [{
1369
+ name: "ncontiero/toml/setup",
1370
+ plugins: { toml: pluginToml }
1371
+ }, {
1372
+ files,
1373
+ languageOptions: { parser: parserToml },
1374
+ name: "ncontiero/toml/rules",
1375
+ rules: {
1376
+ "toml/array-bracket-newline": "error",
1377
+ "toml/array-bracket-spacing": "error",
1378
+ "toml/array-element-newline": "off",
1379
+ "toml/comma-style": "error",
1380
+ "toml/indent": ["error", indent],
1381
+ "toml/inline-table-curly-spacing": "error",
1382
+ "toml/key-spacing": "error",
1383
+ "toml/keys-order": "error",
1384
+ "toml/no-space-dots": "error",
1385
+ "toml/no-unreadable-number-separator": "error",
1386
+ "toml/padding-line-between-pairs": "error",
1387
+ "toml/padding-line-between-tables": "error",
1388
+ "toml/precision-of-fractional-seconds": "error",
1389
+ "toml/precision-of-integer": "error",
1390
+ "toml/quoted-keys": "error",
1391
+ "toml/spaced-comment": "error",
1392
+ "toml/table-bracket-spacing": "error",
1393
+ "toml/tables-order": "error",
1394
+ "toml/vue-custom-block/no-parsing-error": "error",
1395
+ "unicorn/filename-case": "off",
1396
+ ...overrides
1397
+ }
1398
+ }];
1399
+ }
1400
+ //#endregion
1401
+ //#region src/configs/typescript.ts
1402
+ async function typescript(options = {}) {
1403
+ const { files = [GLOB_TS, GLOB_TSX], overrides = {}, parserOptions = {} } = options;
1404
+ const [pluginTs, parserTs] = await Promise.all([interopDefault(import("@typescript-eslint/eslint-plugin")), interopDefault(import("@typescript-eslint/parser"))]);
1405
+ return [
1406
+ {
1407
+ name: "ncontiero/typescript/setup",
1408
+ plugins: { "@typescript-eslint": pluginTs }
1409
+ },
1410
+ {
1411
+ files,
1412
+ languageOptions: {
1413
+ parser: parserTs,
1414
+ parserOptions: {
1415
+ sourceType: "module",
1416
+ ...parserOptions
1417
+ }
1418
+ },
1419
+ name: "ncontiero/typescript/parser"
1420
+ },
1421
+ {
1422
+ files,
1423
+ name: "ncontiero/typescript/rules",
1424
+ rules: {
1425
+ ...pluginTs.configs["eslint-recommended"].overrides[0].rules,
1426
+ ...pluginTs.configs.recommended.rules,
1427
+ "@typescript-eslint/ban-ts-comment": ["error", { "ts-ignore": "allow-with-description" }],
1428
+ "@typescript-eslint/consistent-type-assertions": ["error", {
1429
+ assertionStyle: "as",
1430
+ objectLiteralTypeAssertions: "allow-as-parameter"
1431
+ }],
1432
+ "@typescript-eslint/consistent-type-imports": ["error", {
1433
+ disallowTypeAnnotations: false,
1434
+ fixStyle: "inline-type-imports"
1435
+ }],
1436
+ "@typescript-eslint/method-signature-style": ["error", "property"],
1437
+ "@typescript-eslint/no-empty-object-type": ["error", { allowInterfaces: "always" }],
1438
+ "@typescript-eslint/no-explicit-any": "off",
1439
+ "@typescript-eslint/no-import-type-side-effects": "error",
1440
+ "@typescript-eslint/no-non-null-assertion": "off",
1441
+ "@typescript-eslint/no-redeclare": "error",
1442
+ "@typescript-eslint/no-unused-expressions": ["error", {
1443
+ allowShortCircuit: true,
1444
+ allowTaggedTemplates: false,
1445
+ allowTernary: true,
1446
+ enforceForJSX: true
1447
+ }],
1448
+ "@typescript-eslint/no-unused-vars": "off",
1449
+ "@typescript-eslint/no-useless-constructor": "error",
1450
+ "@typescript-eslint/no-wrapper-object-types": "error",
1451
+ "@typescript-eslint/prefer-as-const": "warn",
1452
+ "@typescript-eslint/prefer-literal-enum-member": ["error", { allowBitwiseExpressions: true }],
1453
+ "no-restricted-syntax": [
1454
+ "error",
1455
+ ...restrictedSyntaxJs,
1456
+ "TSEnumDeclaration[const=true]"
1457
+ ],
1458
+ ...overrides
1459
+ }
1460
+ },
1461
+ {
1462
+ files: ["**/*.d.ts"],
1463
+ name: "ncontiero/typescript/dts-rules",
1464
+ rules: {
1465
+ "eslint-comments/no-unlimited-disable": "off",
1466
+ "import/no-duplicates": "off",
1467
+ "no-restricted-syntax": ["error", ...restrictedSyntaxJs],
1468
+ "unused-imports/no-unused-vars": "off"
1469
+ }
1470
+ },
1471
+ {
1472
+ files: [GLOB_JS, "**/*.cjs"],
1473
+ name: "ncontiero/typescript/cjs-rules",
1474
+ rules: { "@typescript-eslint/no-require-imports": "off" }
1475
+ }
1476
+ ];
1477
+ }
1478
+ //#endregion
1479
+ //#region src/configs/unicorn.ts
1480
+ function unicorn(options = {}) {
1481
+ const { allRecommended, overrides = {}, regexp = false } = options;
1482
+ return [{
1483
+ name: "ncontiero/unicorn/rules",
1484
+ plugins: { unicorn: pluginUnicorn },
1485
+ rules: {
1486
+ ...allRecommended ? pluginUnicorn.configs.recommended.rules : {
1487
+ "unicorn/better-regex": regexp ? "off" : "error",
1488
+ "unicorn/catch-error-name": "error",
1489
+ "unicorn/consistent-date-clone": "error",
1490
+ "unicorn/consistent-empty-array-spread": "error",
1491
+ "unicorn/consistent-existence-index-check": "error",
1492
+ "unicorn/consistent-function-scoping": "error",
1493
+ "unicorn/custom-error-definition": "error",
1494
+ "unicorn/error-message": "error",
1495
+ "unicorn/escape-case": "error",
1496
+ "unicorn/explicit-length-check": "error",
1497
+ "unicorn/new-for-builtins": "error",
1498
+ "unicorn/no-array-callback-reference": "error",
1499
+ "unicorn/no-array-method-this-argument": "error",
1500
+ "unicorn/no-await-in-promise-methods": "error",
1501
+ "unicorn/no-console-spaces": "error",
1502
+ "unicorn/no-for-loop": "error",
1503
+ "unicorn/no-hex-escape": "error",
1504
+ "unicorn/no-instanceof-builtins": "error",
1505
+ "unicorn/no-invalid-remove-event-listener": "error",
1506
+ "unicorn/no-lonely-if": "error",
1507
+ "unicorn/no-negation-in-equality-check": "error",
1508
+ "unicorn/no-new-array": "error",
1509
+ "unicorn/no-new-buffer": "error",
1510
+ "unicorn/no-single-promise-in-promise-methods": "error",
1511
+ "unicorn/no-static-only-class": "error",
1512
+ "unicorn/no-unnecessary-array-flat-depth": "error",
1513
+ "unicorn/no-unnecessary-array-splice-count": "error",
1514
+ "unicorn/no-unnecessary-await": "error",
1515
+ "unicorn/no-unnecessary-slice-end": "error",
1516
+ "unicorn/no-useless-iterator-to-array": "error",
1517
+ "unicorn/no-zero-fractions": "error",
1518
+ "unicorn/number-literal-case": "error",
1519
+ "unicorn/prefer-add-event-listener": "error",
1520
+ "unicorn/prefer-array-find": "error",
1521
+ "unicorn/prefer-array-flat-map": "error",
1522
+ "unicorn/prefer-array-index-of": "error",
1523
+ "unicorn/prefer-array-some": "error",
1524
+ "unicorn/prefer-at": "error",
1525
+ "unicorn/prefer-blob-reading-methods": "error",
1526
+ "unicorn/prefer-class-fields": "error",
1527
+ "unicorn/prefer-date-now": "error",
1528
+ "unicorn/prefer-dom-node-append": "error",
1529
+ "unicorn/prefer-dom-node-dataset": "error",
1530
+ "unicorn/prefer-dom-node-remove": "error",
1531
+ "unicorn/prefer-dom-node-text-content": "error",
1532
+ "unicorn/prefer-includes": "error",
1533
+ "unicorn/prefer-keyboard-event-key": "error",
1534
+ "unicorn/prefer-math-min-max": "error",
1535
+ "unicorn/prefer-math-trunc": "error",
1536
+ "unicorn/prefer-modern-dom-apis": "error",
1537
+ "unicorn/prefer-modern-math-apis": "error",
1538
+ "unicorn/prefer-negative-index": "error",
1539
+ "unicorn/prefer-node-protocol": "error",
1540
+ "unicorn/prefer-number-properties": "error",
1541
+ "unicorn/prefer-optional-catch-binding": "error",
1542
+ "unicorn/prefer-prototype-methods": "error",
1543
+ "unicorn/prefer-query-selector": "error",
1544
+ "unicorn/prefer-reflect-apply": "error",
1545
+ "unicorn/prefer-regexp-test": "error",
1546
+ "unicorn/prefer-simple-condition-first": "error",
1547
+ "unicorn/prefer-single-call": "error",
1548
+ "unicorn/prefer-string-replace-all": "error",
1549
+ "unicorn/prefer-string-slice": "error",
1550
+ "unicorn/prefer-string-starts-ends-with": "error",
1551
+ "unicorn/prefer-string-trim-start-end": "error",
1552
+ "unicorn/prefer-type-error": "error",
1553
+ "unicorn/switch-case-break-position": "error",
1554
+ "unicorn/throw-new-error": "error"
1555
+ },
1556
+ ...overrides
1557
+ }
1558
+ }];
1559
+ }
1560
+ //#endregion
1561
+ //#region src/configs/yml.ts
1562
+ async function yml(options = {}) {
1563
+ const { files = [GLOB_YAML], overrides = {}, style = true } = options;
1564
+ const { indent = 2, quotes = "double" } = typeof style === "boolean" ? {} : style;
1565
+ const [pluginYml, parserYml] = await Promise.all([interopDefault(import("eslint-plugin-yml")), interopDefault(import("yaml-eslint-parser"))]);
1566
+ return [
1567
+ {
1568
+ name: "ncontiero/yml/setup",
1569
+ plugins: { yml: pluginYml }
1570
+ },
1571
+ {
1572
+ files,
1573
+ languageOptions: { parser: parserYml },
1574
+ name: "ncontiero/yml/rules",
1575
+ rules: {
1576
+ "yml/block-mapping": "error",
1577
+ "yml/block-mapping-question-indicator-newline": "error",
1578
+ "yml/block-sequence": "error",
1579
+ "yml/block-sequence-hyphen-indicator-newline": "error",
1580
+ "yml/flow-mapping-curly-newline": "error",
1581
+ "yml/flow-mapping-curly-spacing": "error",
1582
+ "yml/flow-sequence-bracket-newline": "error",
1583
+ "yml/flow-sequence-bracket-spacing": "error",
1584
+ "yml/indent": ["error", indent],
1585
+ "yml/key-spacing": "error",
1586
+ "yml/no-empty-document": "error",
1587
+ "yml/no-empty-key": "error",
1588
+ "yml/no-empty-sequence-entry": "error",
1589
+ "yml/no-irregular-whitespace": "error",
1590
+ "yml/no-tab-indent": "error",
1591
+ "yml/plain-scalar": "error",
1592
+ "yml/quotes": ["error", {
1593
+ avoidEscape: false,
1594
+ prefer: quotes
1595
+ }],
1596
+ "yml/spaced-comment": "error",
1597
+ "yml/vue-custom-block/no-parsing-error": "error",
1598
+ ...overrides
1599
+ }
1600
+ },
1601
+ {
1602
+ files: ["pnpm-workspace.yaml"],
1603
+ name: "ncontiero/yml/pnpm-workspace",
1604
+ rules: { "yml/sort-keys": [
1605
+ "error",
1606
+ {
1607
+ order: [
1608
+ "packages",
1609
+ "overrides",
1610
+ "patchedDependencies",
1611
+ "hoistPattern",
1612
+ "catalog",
1613
+ "catalogs",
1614
+ "allowedDeprecatedVersions",
1615
+ "allowNonAppliedPatches",
1616
+ "allowUnusedPatches",
1617
+ "configDependencies",
1618
+ "ignoredBuiltDependencies",
1619
+ "ignoredOptionalDependencies",
1620
+ "ignorePatchFailures",
1621
+ "neverBuiltDependencies",
1622
+ "onlyBuiltDependencies",
1623
+ "onlyBuiltDependenciesFile",
1624
+ "packageExtensions",
1625
+ "peerDependencyRules",
1626
+ "supportedArchitectures"
1627
+ ],
1628
+ pathPattern: "^$"
1629
+ },
1630
+ {
1631
+ order: { type: "asc" },
1632
+ pathPattern: ".*"
1633
+ }
1634
+ ] }
1635
+ }
1636
+ ];
1637
+ }
1638
+ //#endregion
1639
+ //#region src/env.ts
1640
+ const hasTypeScript = isPackageExists("typescript");
1641
+ const hasReact = isPackageExists("react");
1642
+ const hasNextJs = isPackageExists("next");
1643
+ const hasTailwind = isPackageExists("tailwindcss");
1644
+ const hasTanStackReactQuery = isPackageExists("@tanstack/react-query");
1645
+ //#endregion
1646
+ //#region src/factory.ts
1647
+ const flatConfigProps = [
1648
+ "name",
1649
+ "languageOptions",
1650
+ "linterOptions",
1651
+ "processor",
1652
+ "plugins",
1653
+ "rules",
1654
+ "settings"
1655
+ ];
1656
+ function resolveSubOptions(options, key) {
1657
+ return typeof options[key] === "boolean" ? {} : options[key] || {};
1658
+ }
1659
+ function getOverrides(options, key) {
1660
+ const sub = resolveSubOptions(options, key);
1661
+ return {
1662
+ ...("overrides" in options ? options.overrides : {})?.[key],
1663
+ ..."overrides" in sub ? sub.overrides : {}
1664
+ };
1665
+ }
1666
+ function getStyleOptions(options) {
1667
+ if ("tabWidth" in options || "singleQuote" in options || "semi" in options) return {
1668
+ indent: options.tabWidth || 2,
1669
+ quotes: options.singleQuote ? "single" : "double",
1670
+ semi: options.semi ?? true
1671
+ };
1672
+ return false;
1673
+ }
1674
+ /**
1675
+ * Merges ESLint configurations with optional support for Markdown, React, Next.js, TailwindCSS, and Prettier.
1676
+ *
1677
+ * @param options - Optional settings for Markdown, React, Next.js, TailwindCSS and Prettier.
1678
+ * @param userConfigs - The user configurations to be merged with the generated configurations.
1679
+ * @returns Merged ESLint configurations based on provided options.
1680
+ */
1681
+ function ncontiero(options = {}, ...userConfigs) {
1682
+ const { gitignore: enableGitignore = true, nextjs: enableNextJs = hasNextJs, react: enableReact = hasReact, reactQuery: enableTanStackReactQuery = hasTanStackReactQuery, regexp: enableRegexp = true, tailwindcss: enableTailwindCSS = hasTailwind, typescript: enableTypescript = hasTypeScript, unicorn: enableUnicorn = true } = options;
1683
+ const prettierOptions = typeof options.prettier === "object" ? options.prettier : {};
1684
+ const styleOptions = getStyleOptions(prettierOptions);
1685
+ const configs = [];
1686
+ if (enableGitignore) if (typeof enableGitignore !== "boolean") configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
1687
+ name: "ncontiero/gitignore",
1688
+ ...enableGitignore
1689
+ })]));
1690
+ else configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
1691
+ name: "ncontiero/gitignore",
1692
+ strict: false
1693
+ })]));
1694
+ if (!enableTypescript) options.ignores ? options.ignores.push(GLOB_TS, GLOB_TSX) : options.ignores = [GLOB_TS, GLOB_TSX];
1695
+ configs.push(ignores(options.ignores), javascript({ overrides: getOverrides(options, "javascript") }), comments(), jsdoc(), imports({ nextJs: !!enableNextJs }), node(), promise(), command(), perfectionist(), deMorgan());
1696
+ if (enableUnicorn) configs.push(unicorn(enableUnicorn === true ? { regexp: !!enableRegexp } : enableUnicorn));
1697
+ if (enableTypescript) configs.push(typescript({
1698
+ ...resolveSubOptions(options, "typescript"),
1699
+ overrides: getOverrides(options, "typescript")
1700
+ }));
1701
+ if (options.jsonc ?? true) configs.push(jsonc({
1702
+ overrides: getOverrides(options, "jsonc"),
1703
+ style: styleOptions
1704
+ }), sortPackageJson(), sortTsconfig());
1705
+ if (options.yaml ?? true) configs.push(yml({
1706
+ overrides: getOverrides(options, "yaml"),
1707
+ style: styleOptions
1708
+ }));
1709
+ if (options.toml ?? true) configs.push(toml({
1710
+ overrides: getOverrides(options, "toml"),
1711
+ style: styleOptions
1712
+ }));
1713
+ if (options.markdown ?? true) configs.push(markdown({ overrides: getOverrides(options, "markdown") }));
1714
+ if (enableRegexp) configs.push(regexp(typeof enableRegexp === "boolean" ? {} : enableRegexp));
1715
+ if (enableReact) configs.push(react({
1716
+ overrides: getOverrides(options, "react"),
1717
+ reactQuery: !!enableTanStackReactQuery,
1718
+ typescript: !!enableTypescript
1719
+ }));
1720
+ if (enableNextJs) configs.push(nextJs({ overrides: getOverrides(options, "nextjs") }));
1721
+ if (options.html ?? true) configs.push(html({
1722
+ ...resolveSubOptions(options, "html"),
1723
+ overrides: getOverrides(options, "html")
1724
+ }));
1725
+ if (enableTailwindCSS) configs.push(tailwindcss({
1726
+ ...resolveSubOptions(options, "tailwindcss"),
1727
+ overrides: getOverrides(options, "tailwindcss")
1728
+ }));
1729
+ if (options.prettier ?? true) configs.push(prettier(prettierOptions));
1730
+ if ("files" in options) throw new Error("[@ncontiero/eslint-config] The first argument should not contain the \"files\" property as the options are supposed to be global. Place it in the second or later config instead.");
1731
+ const fusedConfig = flatConfigProps.reduce((acc, key) => {
1732
+ if (key in options) acc[key] = options[key];
1733
+ return acc;
1734
+ }, {});
1735
+ if (Object.keys(fusedConfig).length > 0) configs.push([fusedConfig]);
1736
+ return composer(...configs, ...userConfigs);
1737
+ }
1738
+ //#endregion
1739
+ export { GLOB_ALL_SRC, GLOB_CSS, GLOB_DIST, GLOB_EXCLUDE, GLOB_HTML, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSX, GLOB_LESS, GLOB_LOCKFILE, GLOB_MARKDOWN, GLOB_MARKDOWN_CODE, GLOB_MARKDOWN_IN_MARKDOWN, GLOB_NODE_MODULES, GLOB_POSTCSS, GLOB_REACT, GLOB_SCSS, GLOB_SRC, GLOB_SRC_EXT, GLOB_STYLE, GLOB_TOML, GLOB_TS, GLOB_TSX, GLOB_YAML, combine, command, comments, composer, deMorgan, ensurePackages, getOverrides, hasNextJs, hasReact, hasTailwind, hasTanStackReactQuery, hasTypeScript, html, ignores, imports, interopDefault, javascript, jsdoc, jsonc, markdown, ncontiero, nextJs, node, parserPlain, perfectionist, prettier, promise, react, regexp, resolveSubOptions, restrictedSyntaxJs, sortPackageJson, sortPnpmWorkspace, sortTsconfig, tailwindcss, toArray, toml, typescript, unicorn, yml };