@curev/eslint-config 0.3.6 → 0.4.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 DELETED
@@ -1,2061 +0,0 @@
1
- import fs from 'node:fs';
2
- import process from 'node:process';
3
- import { isPackageExists } from 'local-pkg';
4
- import pluginCurev from '@curev/eslint-plugin';
5
- import pluginComments from 'eslint-plugin-eslint-comments';
6
- import * as pluginImport from 'eslint-plugin-i';
7
- import pluginNode from 'eslint-plugin-n';
8
- import pluginPerfectionist from 'eslint-plugin-perfectionist';
9
- import pluginUnicorn from 'eslint-plugin-unicorn';
10
- import pluginUnusedImports from 'eslint-plugin-unused-imports';
11
- import globals from 'globals';
12
- import { mergeProcessors, processorPassThrough } from 'eslint-merge-processors';
13
-
14
- async function comments() {
15
- return [
16
- {
17
- name: "curev:eslint-comments",
18
- plugins: {
19
- "eslint-comments": pluginComments
20
- },
21
- rules: {
22
- "eslint-comments/no-aggregating-enable": "error",
23
- "eslint-comments/no-duplicate-disable": "error",
24
- "eslint-comments/no-unlimited-disable": "error",
25
- "eslint-comments/no-unused-enable": "error"
26
- }
27
- }
28
- ];
29
- }
30
-
31
- const GLOB_SRC_EXT = "?([cm])[jt]s?(x)";
32
- const GLOB_SRC = "**/*.?([cm])[jt]s?(x)";
33
- const GLOB_JS = "**/*.?([cm])js";
34
- const GLOB_JSX = "**/*.?([cm])jsx";
35
- const GLOB_TS = "**/*.?([cm])ts";
36
- const GLOB_TSX = "**/*.?([cm])tsx";
37
- const GLOB_STYLE = "**/*.{c,le,sc}ss";
38
- const GLOB_CSS = "**/*.css";
39
- const GLOB_POSTCSS = "**/*.{p,post}css";
40
- const GLOB_LESS = "**/*.less";
41
- const GLOB_SCSS = "**/*.scss";
42
- const GLOB_JSON = "**/*.json";
43
- const GLOB_JSON5 = "**/*.json5";
44
- const GLOB_JSONC = "**/*.jsonc";
45
- const GLOB_MARKDOWN = "**/*.md";
46
- const GLOB_MARKDOWN_IN_MARKDOWN = "**/*.md/*.md";
47
- const GLOB_SVELTE = "**/*.svelte";
48
- const GLOB_VUE = "**/*.vue";
49
- const GLOB_YAML = "**/*.y?(a)ml";
50
- const GLOB_TOML = "**/*.toml";
51
- const GLOB_HTML = "**/*.htm?(l)";
52
- const GLOB_MARKDOWN_CODE = `${GLOB_MARKDOWN}/${GLOB_SRC}`;
53
- const GLOB_TESTS = [
54
- `**/__tests__/**/*.${GLOB_SRC_EXT}`,
55
- `**/*.spec.${GLOB_SRC_EXT}`,
56
- `**/*.test.${GLOB_SRC_EXT}`,
57
- `**/*.bench.${GLOB_SRC_EXT}`,
58
- `**/*.benchmark.${GLOB_SRC_EXT}`
59
- ];
60
- const GLOB_ALL_SRC = [
61
- GLOB_SRC,
62
- GLOB_STYLE,
63
- GLOB_JSON,
64
- GLOB_JSON5,
65
- GLOB_MARKDOWN,
66
- GLOB_SVELTE,
67
- GLOB_VUE,
68
- GLOB_YAML,
69
- GLOB_HTML
70
- ];
71
- const GLOB_EXCLUDE = [
72
- "**/node_modules",
73
- "**/dist",
74
- "**/package-lock.json",
75
- "**/yarn.lock",
76
- "**/pnpm-lock.yaml",
77
- "**/bun.lockb",
78
- "**/output",
79
- "**/coverage",
80
- "**/temp",
81
- "**/.temp",
82
- "**/tmp",
83
- "**/.tmp",
84
- "**/.history",
85
- "**/.vitepress/cache",
86
- "**/.nuxt",
87
- "**/.next",
88
- "**/.vercel",
89
- "**/.changeset",
90
- "**/.idea",
91
- "**/.cache",
92
- "**/.output",
93
- "**/.vite-inspect",
94
- "**/CHANGELOG*.md",
95
- "**/*.min.*",
96
- "**/LICENSE*",
97
- "**/__snapshots__",
98
- "**/auto-import?(s).d.ts",
99
- "**/components.d.ts"
100
- ];
101
-
102
- async function ignores() {
103
- return [
104
- {
105
- ignores: GLOB_EXCLUDE
106
- }
107
- ];
108
- }
109
-
110
- async function imports(options = {}) {
111
- const {
112
- stylistic = true
113
- } = options;
114
- return [
115
- {
116
- name: "curev:imports",
117
- plugins: {
118
- curev: pluginCurev,
119
- import: pluginImport
120
- },
121
- rules: {
122
- "curev/import-dedupe": "error",
123
- "curev/no-import-dist": "error",
124
- "curev/no-import-node-modules-by-path": "error",
125
- "import/first": "error",
126
- "import/no-duplicates": "error",
127
- "import/no-mutable-exports": "error",
128
- "import/no-named-default": "error",
129
- "import/no-self-import": "error",
130
- "import/no-webpack-loader-syntax": "error",
131
- "import/order": "error",
132
- ...stylistic ? {
133
- "import/newline-after-import": ["error", { considerComments: true, count: 1 }]
134
- } : {}
135
- }
136
- },
137
- {
138
- files: ["**/bin/**/*", `**/bin.${GLOB_SRC_EXT}`],
139
- name: "curev:imports:bin",
140
- rules: {
141
- "curev/no-import-dist": "off",
142
- "curev/no-import-node-modules-by-path": "off"
143
- }
144
- }
145
- ];
146
- }
147
-
148
- async function javascript(options = {}) {
149
- const {
150
- isInEditor = false,
151
- overrides = {}
152
- } = options;
153
- return [
154
- {
155
- languageOptions: {
156
- ecmaVersion: 2022,
157
- globals: {
158
- ...globals.browser,
159
- ...globals.es2021,
160
- ...globals.node,
161
- document: "readonly",
162
- navigator: "readonly",
163
- window: "readonly"
164
- },
165
- parserOptions: {
166
- ecmaFeatures: {
167
- jsx: true
168
- },
169
- ecmaVersion: 2022,
170
- sourceType: "module"
171
- },
172
- sourceType: "module"
173
- },
174
- linterOptions: {
175
- reportUnusedDisableDirectives: true
176
- },
177
- name: "curev:javascript",
178
- plugins: {
179
- "curev": pluginCurev,
180
- "unused-imports": pluginUnusedImports
181
- },
182
- rules: {
183
- "accessor-pairs": ["error", { enforceForClassMembers: true, setWithoutGet: true }],
184
- "array-callback-return": ["error", {
185
- allowImplicit: false,
186
- checkForEach: false
187
- }],
188
- "block-scoped-var": "error",
189
- "camelcase": ["error", {
190
- allow: ["^UNSAFE_"],
191
- ignoreGlobals: true,
192
- ignoreImports: true,
193
- properties: "never"
194
- }],
195
- "constructor-super": "error",
196
- "default-case-last": "error",
197
- "eol-last": "error",
198
- "eqeqeq": ["error", "always", { null: "ignore" }],
199
- "func-call-spacing": ["error", "never"],
200
- "generator-star-spacing": ["error", { after: true, before: true }],
201
- "import/export": "error",
202
- "import/first": "error",
203
- "import/no-absolute-path": ["error", { amd: false, commonjs: true, esmodule: true }],
204
- "import/no-duplicates": "error",
205
- "import/no-named-default": "error",
206
- "import/no-webpack-loader-syntax": "error",
207
- "lines-between-class-members": ["error", "always", { exceptAfterSingleLine: true }],
208
- "multiline-ternary": ["error", "always-multiline"],
209
- "new-cap": ["error", { capIsNew: false, newIsCap: true, properties: true }],
210
- "new-parens": "error",
211
- "no-alert": "error",
212
- "no-array-constructor": "error",
213
- "no-async-promise-executor": "error",
214
- "no-caller": "error",
215
- "no-case-declarations": "error",
216
- "no-class-assign": "error",
217
- "no-compare-neg-zero": "error",
218
- "no-cond-assign": "error",
219
- "no-console": ["error", { allow: ["warn", "error"] }],
220
- "no-const-assign": "error",
221
- "no-constant-condition": ["error", { checkLoops: false }],
222
- "no-control-regex": "error",
223
- "no-debugger": "error",
224
- "no-delete-var": "error",
225
- "no-dupe-args": "error",
226
- "no-dupe-class-members": "error",
227
- "no-dupe-keys": "error",
228
- "no-duplicate-case": "error",
229
- "no-empty": ["error", { allowEmptyCatch: true }],
230
- "no-empty-character-class": "error",
231
- "no-empty-pattern": "error",
232
- "no-eval": "error",
233
- "no-ex-assign": "error",
234
- "no-extend-native": "error",
235
- "no-extra-bind": "error",
236
- "no-extra-boolean-cast": "error",
237
- "no-extra-parens": ["error", "functions"],
238
- "no-fallthrough": "error",
239
- "no-floating-decimal": "error",
240
- "no-func-assign": "error",
241
- "no-global-assign": "error",
242
- "no-implied-eval": "error",
243
- "no-import-assign": "error",
244
- "no-invalid-regexp": "error",
245
- "no-irregular-whitespace": "error",
246
- "no-iterator": "error",
247
- "no-labels": ["error", { allowLoop: false, allowSwitch: false }],
248
- "no-lone-blocks": "error",
249
- "no-loss-of-precision": "error",
250
- "no-misleading-character-class": "error",
251
- "no-mixed-operators": ["error", {
252
- allowSamePrecedence: true,
253
- groups: [
254
- ["==", "!=", "===", "!==", ">", ">=", "<", "<="],
255
- ["&&", "||"],
256
- ["in", "instanceof"]
257
- ]
258
- }],
259
- "no-mixed-spaces-and-tabs": "error",
260
- "no-multi-spaces": "error",
261
- "no-multi-str": "error",
262
- "no-multiple-empty-lines": [
263
- "error",
264
- {
265
- max: 3,
266
- maxBOF: 0,
267
- maxEOF: 1
268
- }
269
- ],
270
- "no-new": "error",
271
- "no-new-func": "error",
272
- "no-new-object": "error",
273
- "no-new-symbol": "error",
274
- "no-new-wrappers": "error",
275
- "no-obj-calls": "error",
276
- "no-octal": "error",
277
- "no-octal-escape": "error",
278
- "no-proto": "error",
279
- "no-prototype-builtins": "error",
280
- "no-redeclare": ["error", { builtinGlobals: false }],
281
- "no-regex-spaces": "error",
282
- "no-restricted-globals": [
283
- "error",
284
- { message: "Use `globalThis` instead.", name: "global" },
285
- { message: "Use `globalThis` instead.", name: "self" }
286
- ],
287
- "no-restricted-properties": [
288
- "error",
289
- { message: "Use `Object.getPrototypeOf` or `Object.setPrototypeOf` instead.", property: "__proto__" },
290
- { message: "Use `Object.defineProperty` instead.", property: "__defineGetter__" },
291
- { message: "Use `Object.defineProperty` instead.", property: "__defineSetter__" },
292
- { message: "Use `Object.getOwnPropertyDescriptor` instead.", property: "__lookupGetter__" },
293
- { message: "Use `Object.getOwnPropertyDescriptor` instead.", property: "__lookupSetter__" }
294
- ],
295
- "no-restricted-syntax": [
296
- "error",
297
- "DebuggerStatement",
298
- "LabeledStatement",
299
- "WithStatement",
300
- "TSEnumDeclaration[const=true]",
301
- "TSExportAssignment"
302
- ],
303
- "no-return-assign": ["error", "except-parens"],
304
- "no-self-assign": ["error", { props: true }],
305
- "no-self-compare": "error",
306
- "no-sequences": "error",
307
- "no-shadow-restricted-names": "error",
308
- "no-sparse-arrays": "error",
309
- "no-tabs": "error",
310
- "no-template-curly-in-string": "error",
311
- "no-this-before-super": "error",
312
- "no-throw-literal": "error",
313
- "no-trailing-spaces": [
314
- "error",
315
- {
316
- skipBlankLines: true
317
- }
318
- ],
319
- "no-undef": "error",
320
- "no-undef-init": "error",
321
- "no-unexpected-multiline": "error",
322
- "no-unmodified-loop-condition": "error",
323
- "no-unneeded-ternary": ["error", { defaultAssignment: false }],
324
- "no-unreachable": "error",
325
- "no-unreachable-loop": "error",
326
- "no-unsafe-finally": "error",
327
- "no-unsafe-negation": "error",
328
- "no-unused-expressions": ["error", {
329
- allowShortCircuit: true,
330
- allowTaggedTemplates: true,
331
- allowTernary: true
332
- }],
333
- "no-unused-vars": ["error", {
334
- args: "none",
335
- caughtErrors: "none",
336
- ignoreRestSiblings: true,
337
- vars: "all"
338
- }],
339
- "no-use-before-define": ["error", { classes: false, functions: false, variables: false }],
340
- "no-useless-backreference": "error",
341
- "no-useless-call": "error",
342
- "no-useless-catch": "error",
343
- "no-useless-computed-key": "error",
344
- "no-useless-constructor": "error",
345
- "no-useless-escape": "error",
346
- "no-useless-rename": "error",
347
- "no-useless-return": "error",
348
- "no-var": "warn",
349
- "no-void": "error",
350
- "no-with": "error",
351
- "object-curly-newline": ["error", { consistent: true, multiline: true }],
352
- "object-curly-spacing": ["error", "always"],
353
- "object-property-newline": ["error", { allowMultiplePropertiesPerLine: true }],
354
- "object-shorthand": ["warn", "properties"],
355
- "one-var": ["error", { initialized: "never" }],
356
- "padded-blocks": ["error", { blocks: "never", classes: "never", switches: "never" }],
357
- "prefer-arrow-callback": [
358
- "error",
359
- {
360
- allowNamedFunctions: false,
361
- allowUnboundThis: true
362
- }
363
- ],
364
- "prefer-const": ["error", { destructuring: "all" }],
365
- "prefer-exponentiation-operator": "error",
366
- "prefer-promise-reject-errors": "error",
367
- "prefer-regex-literals": ["error", { disallowRedundantWrapping: true }],
368
- "prefer-rest-params": "error",
369
- "prefer-spread": "error",
370
- "prefer-template": "error",
371
- "rest-spread-spacing": ["error", "never"],
372
- "sort-imports": [
373
- "error",
374
- {
375
- allowSeparatedGroups: false,
376
- ignoreCase: false,
377
- ignoreDeclarationSort: true,
378
- ignoreMemberSort: false,
379
- memberSyntaxSortOrder: ["none", "all", "multiple", "single"]
380
- }
381
- ],
382
- "symbol-description": "error",
383
- "template-curly-spacing": ["error", "never"],
384
- "template-tag-spacing": ["error", "never"],
385
- "unicode-bom": ["error", "never"],
386
- "unused-imports/no-unused-imports": isInEditor ? "off" : "error",
387
- "unused-imports/no-unused-vars": [
388
- "error",
389
- { args: "after-used", argsIgnorePattern: "^_", vars: "all", varsIgnorePattern: "^_" }
390
- ],
391
- "use-isnan": ["error", {
392
- enforceForIndexOf: true,
393
- enforceForSwitchCase: true
394
- }],
395
- "valid-typeof": ["error", { requireStringLiterals: true }],
396
- "vars-on-top": "error",
397
- "wrap-iife": ["error", "any", { functionPrototypeMethods: true }],
398
- "yield-star-spacing": ["error", "both"],
399
- "yoda": ["error", "never"],
400
- ...overrides
401
- },
402
- settings: {
403
- env: {
404
- browser: true,
405
- es6: true,
406
- node: true
407
- }
408
- }
409
- },
410
- {
411
- files: [`scripts/${GLOB_SRC}`, `cli.${GLOB_SRC_EXT}`],
412
- name: "curev:scripts-overrides",
413
- rules: {
414
- "no-console": "off"
415
- }
416
- }
417
- ];
418
- }
419
-
420
- const parserPlain = {
421
- meta: {
422
- name: "parser-plain"
423
- },
424
- parseForESLint: (code) => ({
425
- ast: {
426
- body: [],
427
- comments: [],
428
- loc: { end: code.length, start: 0 },
429
- range: [0, code.length],
430
- tokens: [],
431
- type: "Program"
432
- },
433
- scopeManager: null,
434
- services: { isPlain: true },
435
- visitorKeys: {
436
- Program: []
437
- }
438
- })
439
- };
440
- async function combine(...configs) {
441
- const resolved = await Promise.all(configs);
442
- return resolved.flat();
443
- }
444
- function renameRules(rules, from, to) {
445
- return Object.fromEntries(
446
- Object.entries(rules).map(([key, value]) => {
447
- if (key.startsWith(from)) {
448
- return [to + key.slice(from.length), value];
449
- }
450
- return [key, value];
451
- })
452
- );
453
- }
454
- function toArray(value) {
455
- return Array.isArray(value) ? value : [value];
456
- }
457
- async function interopDefault(m) {
458
- const resolved = await m;
459
- return resolved.default || resolved;
460
- }
461
- async function ensurePackages(packages) {
462
- if (process.env.CI || process.stdout.isTTY === false) {
463
- return;
464
- }
465
- const nonExistingPackages = packages.filter((i) => !isPackageExists(i));
466
- if (nonExistingPackages.length === 0) {
467
- return;
468
- }
469
- const { default: prompts } = await import('prompts');
470
- const { result } = await prompts([
471
- {
472
- message: `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?`,
473
- name: "result",
474
- type: "confirm"
475
- }
476
- ]);
477
- if (result) {
478
- await import('@antfu/install-pkg').then((i) => i.installPackage(nonExistingPackages, { dev: true }));
479
- }
480
- }
481
-
482
- async function jsdoc(options = {}) {
483
- const {
484
- stylistic = true
485
- } = options;
486
- return [
487
- {
488
- name: "curev:jsdoc",
489
- plugins: {
490
- jsdoc: await interopDefault(import('eslint-plugin-jsdoc'))
491
- },
492
- rules: {
493
- "jsdoc/check-access": "warn",
494
- "jsdoc/check-param-names": "warn",
495
- "jsdoc/check-property-names": "warn",
496
- "jsdoc/check-types": "warn",
497
- "jsdoc/empty-tags": "warn",
498
- "jsdoc/implements-on-classes": "warn",
499
- "jsdoc/no-defaults": "warn",
500
- "jsdoc/no-multi-asterisks": "warn",
501
- "jsdoc/require-param-name": "warn",
502
- "jsdoc/require-property": "warn",
503
- "jsdoc/require-property-description": "warn",
504
- "jsdoc/require-property-name": "warn",
505
- "jsdoc/require-returns-check": "warn",
506
- "jsdoc/require-returns-description": "warn",
507
- "jsdoc/require-yields-check": "warn",
508
- ...stylistic ? {
509
- "jsdoc/check-alignment": "warn",
510
- "jsdoc/multiline-blocks": "warn"
511
- } : {}
512
- }
513
- }
514
- ];
515
- }
516
-
517
- async function jsonc(options = {}) {
518
- const {
519
- files = [GLOB_JSON, GLOB_JSON5, GLOB_JSONC],
520
- overrides = {},
521
- stylistic = true
522
- } = options;
523
- const {
524
- indent = 2
525
- } = typeof stylistic === "boolean" ? {} : stylistic;
526
- const [
527
- pluginJsonc,
528
- parserJsonc
529
- ] = await Promise.all([
530
- interopDefault(import('eslint-plugin-jsonc')),
531
- interopDefault(import('jsonc-eslint-parser'))
532
- ]);
533
- return [
534
- {
535
- name: "curev:jsonc:setup",
536
- plugins: {
537
- jsonc: pluginJsonc
538
- }
539
- },
540
- {
541
- files,
542
- languageOptions: {
543
- parser: parserJsonc
544
- },
545
- name: "curev:jsonc:rules",
546
- rules: {
547
- "jsonc/no-bigint-literals": "error",
548
- "jsonc/no-binary-expression": "error",
549
- "jsonc/no-binary-numeric-literals": "error",
550
- "jsonc/no-dupe-keys": "error",
551
- "jsonc/no-escape-sequence-in-identifier": "error",
552
- "jsonc/no-floating-decimal": "error",
553
- "jsonc/no-hexadecimal-numeric-literals": "error",
554
- "jsonc/no-infinity": "error",
555
- "jsonc/no-multi-str": "error",
556
- "jsonc/no-nan": "error",
557
- "jsonc/no-number-props": "error",
558
- "jsonc/no-numeric-separators": "error",
559
- "jsonc/no-octal": "error",
560
- "jsonc/no-octal-escape": "error",
561
- "jsonc/no-octal-numeric-literals": "error",
562
- "jsonc/no-parenthesized": "error",
563
- "jsonc/no-plus-sign": "error",
564
- "jsonc/no-regexp-literals": "error",
565
- "jsonc/no-sparse-arrays": "error",
566
- "jsonc/no-template-literals": "error",
567
- "jsonc/no-undefined-value": "error",
568
- "jsonc/no-unicode-codepoint-escapes": "error",
569
- "jsonc/no-useless-escape": "error",
570
- "jsonc/space-unary-ops": "error",
571
- "jsonc/valid-json-number": "error",
572
- "jsonc/vue-custom-block/no-parsing-error": "error",
573
- ...stylistic ? {
574
- "jsonc/array-bracket-spacing": ["error", "never"],
575
- "jsonc/comma-dangle": ["error", "never"],
576
- "jsonc/comma-style": ["error", "last"],
577
- "jsonc/indent": ["error", indent],
578
- "jsonc/key-spacing": ["error", { afterColon: true, beforeColon: false }],
579
- "jsonc/object-curly-newline": ["error", { consistent: true, multiline: true }],
580
- "jsonc/object-curly-spacing": ["error", "always"],
581
- "jsonc/object-property-newline": ["error", { allowMultiplePropertiesPerLine: true }],
582
- "jsonc/quote-props": "error",
583
- "jsonc/quotes": "error"
584
- } : {},
585
- ...overrides
586
- }
587
- }
588
- ];
589
- }
590
-
591
- async function markdown(options = {}) {
592
- const {
593
- componentExts = [],
594
- files = [GLOB_MARKDOWN],
595
- overrides = {}
596
- } = options;
597
- const markdown2 = await interopDefault(import('eslint-plugin-markdown'));
598
- return [
599
- {
600
- name: "curev:markdown:setup",
601
- plugins: {
602
- markdown: markdown2
603
- }
604
- },
605
- {
606
- files,
607
- ignores: [GLOB_MARKDOWN_IN_MARKDOWN],
608
- name: "curev:markdown:processor",
609
- // `eslint-plugin-markdown` only creates virtual files for code blocks,
610
- // but not the markdown file itself. We use `eslint-merge-processors` to
611
- // add a pass-through processor for the markdown file itself.
612
- processor: mergeProcessors([
613
- markdown2.processors.markdown,
614
- processorPassThrough
615
- ])
616
- },
617
- {
618
- files,
619
- languageOptions: {
620
- parser: parserPlain
621
- },
622
- name: "curev:markdown:parser"
623
- },
624
- {
625
- files: [
626
- GLOB_MARKDOWN_CODE,
627
- ...componentExts.map((ext) => `${GLOB_MARKDOWN}/**/*.${ext}`)
628
- ],
629
- languageOptions: {
630
- parserOptions: {
631
- ecmaFeatures: {
632
- impliedStrict: true
633
- }
634
- }
635
- },
636
- name: "curev:markdown:disables",
637
- rules: {
638
- "import/newline-after-import": "off",
639
- "no-alert": "off",
640
- "no-console": "off",
641
- "no-labels": "off",
642
- "no-lone-blocks": "off",
643
- "no-restricted-syntax": "off",
644
- "no-undef": "off",
645
- "no-unused-expressions": "off",
646
- "no-unused-labels": "off",
647
- "no-unused-vars": "off",
648
- "node/prefer-global/process": "off",
649
- "style/comma-dangle": "off",
650
- "style/eol-last": "off",
651
- "ts/consistent-type-imports": "off",
652
- "ts/no-namespace": "off",
653
- "ts/no-redeclare": "off",
654
- "ts/no-require-imports": "off",
655
- "ts/no-unused-vars": "off",
656
- "ts/no-use-before-define": "off",
657
- "ts/no-var-requires": "off",
658
- "unicode-bom": "off",
659
- "unused-imports/no-unused-imports": "off",
660
- "unused-imports/no-unused-vars": "off",
661
- // Type aware rules
662
- ...{
663
- "ts/await-thenable": "off",
664
- "ts/dot-notation": "off",
665
- "ts/no-floating-promises": "off",
666
- "ts/no-for-in-array": "off",
667
- "ts/no-implied-eval": "off",
668
- "ts/no-misused-promises": "off",
669
- "ts/no-throw-literal": "off",
670
- "ts/no-unnecessary-type-assertion": "off",
671
- "ts/no-unsafe-argument": "off",
672
- "ts/no-unsafe-assignment": "off",
673
- "ts/no-unsafe-call": "off",
674
- "ts/no-unsafe-member-access": "off",
675
- "ts/no-unsafe-return": "off",
676
- "ts/restrict-plus-operands": "off",
677
- "ts/restrict-template-expressions": "off",
678
- "ts/unbound-method": "off"
679
- },
680
- ...overrides
681
- }
682
- }
683
- ];
684
- }
685
-
686
- async function node() {
687
- return [
688
- {
689
- name: "curev:node",
690
- plugins: {
691
- node: pluginNode
692
- },
693
- rules: {
694
- "node/handle-callback-err": ["error", "^(err|error)$"],
695
- "node/no-callback-literal": "error",
696
- "node/no-deprecated-api": "error",
697
- "node/no-exports-assign": "error",
698
- "node/no-new-require": "error",
699
- "node/no-path-concat": "error",
700
- "node/prefer-global/buffer": ["error", "never"],
701
- "node/prefer-global/process": ["error", "never"],
702
- "node/process-exit-as-throw": "error"
703
- }
704
- }
705
- ];
706
- }
707
-
708
- async function perfectionist() {
709
- return [
710
- {
711
- plugins: {
712
- perfectionist: pluginPerfectionist
713
- },
714
- rules: {
715
- "perfectionist/sort-named-exports": [
716
- "error",
717
- {
718
- order: "asc",
719
- type: "natural"
720
- }
721
- ],
722
- "perfectionist/sort-named-imports": [
723
- "error",
724
- {
725
- order: "asc",
726
- type: "natural"
727
- }
728
- ],
729
- "perfectionist/sort-object-types": [
730
- "error",
731
- {
732
- order: "asc",
733
- type: "natural"
734
- }
735
- ],
736
- "perfectionist/sort-objects": [
737
- "error",
738
- {
739
- order: "asc",
740
- type: "natural"
741
- }
742
- ],
743
- "perfectionist/sort-union-types": [
744
- "error",
745
- {
746
- order: "asc",
747
- type: "natural"
748
- }
749
- ],
750
- "sort-keys": "off"
751
- }
752
- }
753
- ];
754
- }
755
-
756
- const StylisticConfigDefaults = {
757
- arrowParens: true,
758
- braceStyle: "1tbs",
759
- commaDangle: "never",
760
- indent: 2,
761
- jsx: true,
762
- quotes: "double",
763
- semi: true
764
- };
765
- async function stylistic(options = {}) {
766
- const mergeOptions = {
767
- ...StylisticConfigDefaults,
768
- ...options
769
- };
770
- const { overrides = {} } = mergeOptions;
771
- const pluginStylistic = await interopDefault(import('@stylistic/eslint-plugin'));
772
- const config = pluginStylistic.configs.customize({
773
- flat: true,
774
- pluginName: "style",
775
- ...mergeOptions
776
- });
777
- return [
778
- {
779
- name: "curev:stylistic",
780
- plugins: {
781
- curev: pluginCurev,
782
- style: pluginStylistic
783
- },
784
- rules: {
785
- ...config.rules,
786
- "curev/consistent-list-newline": "error",
787
- "curev/if-newline": "off",
788
- "curev/max-statements-per-line": ["error", { max: 1 }],
789
- "curev/top-level-function": "error",
790
- "curly": ["error", "all"],
791
- "semi-spacing": ["error", { after: true, before: false }],
792
- "style/brace-style": ["error", "1tbs", { allowSingleLine: true }],
793
- "style/max-statements-per-line": ["off"],
794
- ...overrides
795
- }
796
- }
797
- ];
798
- }
799
-
800
- async function formatters(options = {}, stylistic = {}) {
801
- await ensurePackages([
802
- "eslint-plugin-format"
803
- ]);
804
- if (options === true) {
805
- options = {
806
- css: true,
807
- graphql: true,
808
- html: true,
809
- markdown: true
810
- };
811
- }
812
- const {
813
- indent,
814
- quotes,
815
- semi
816
- } = {
817
- ...StylisticConfigDefaults,
818
- ...stylistic
819
- };
820
- const prettierOptions = Object.assign(
821
- {
822
- endOfLine: "auto",
823
- semi,
824
- singleQuote: quotes === "single",
825
- tabWidth: typeof indent === "number" ? indent : 2,
826
- trailingComma: "all",
827
- useTabs: indent === "tab"
828
- },
829
- options.prettierOptions || {}
830
- );
831
- const dprintOptions = Object.assign(
832
- {
833
- indentWidth: typeof indent === "number" ? indent : 2,
834
- quoteStyle: quotes === "single" ? "preferSingle" : "preferDouble",
835
- useTabs: indent === "tab"
836
- },
837
- options.dprintOptions || {}
838
- );
839
- const pluginFormat = await interopDefault(import('eslint-plugin-format'));
840
- const configs = [
841
- {
842
- name: "curev:formatters:setup",
843
- plugins: {
844
- format: pluginFormat
845
- }
846
- }
847
- ];
848
- if (options.css) {
849
- configs.push(
850
- {
851
- files: [GLOB_CSS, GLOB_POSTCSS],
852
- languageOptions: {
853
- parser: parserPlain
854
- },
855
- name: "curev:formatter:css",
856
- rules: {
857
- "format/prettier": [
858
- "error",
859
- {
860
- ...prettierOptions,
861
- parser: "css"
862
- }
863
- ]
864
- }
865
- },
866
- {
867
- files: [GLOB_SCSS],
868
- languageOptions: {
869
- parser: parserPlain
870
- },
871
- name: "curev:formatter:scss",
872
- rules: {
873
- "format/prettier": [
874
- "error",
875
- {
876
- ...prettierOptions,
877
- parser: "scss"
878
- }
879
- ]
880
- }
881
- },
882
- {
883
- files: [GLOB_LESS],
884
- languageOptions: {
885
- parser: parserPlain
886
- },
887
- name: "curev:formatter:less",
888
- rules: {
889
- "format/prettier": [
890
- "error",
891
- {
892
- ...prettierOptions,
893
- parser: "less"
894
- }
895
- ]
896
- }
897
- }
898
- );
899
- }
900
- if (options.html) {
901
- configs.push({
902
- files: ["**/*.html"],
903
- languageOptions: {
904
- parser: parserPlain
905
- },
906
- name: "curev:formatter:html",
907
- rules: {
908
- "format/prettier": [
909
- "error",
910
- {
911
- ...prettierOptions,
912
- parser: "html"
913
- }
914
- ]
915
- }
916
- });
917
- }
918
- if (options.markdown) {
919
- const formater = options.markdown === true ? "prettier" : options.markdown;
920
- configs.push({
921
- files: [GLOB_MARKDOWN],
922
- languageOptions: {
923
- parser: parserPlain
924
- },
925
- name: "curev:formatter:markdown",
926
- rules: {
927
- [`format/${formater}`]: [
928
- "error",
929
- formater === "prettier" ? {
930
- printWidth: 120,
931
- ...prettierOptions,
932
- embeddedLanguageFormatting: "off",
933
- parser: "markdown"
934
- } : {
935
- ...dprintOptions,
936
- language: "markdown"
937
- }
938
- ]
939
- }
940
- });
941
- }
942
- if (options.graphql) {
943
- configs.push({
944
- files: ["**/*.graphql"],
945
- languageOptions: {
946
- parser: parserPlain
947
- },
948
- name: "curev:formatter:graphql",
949
- rules: {
950
- "format/prettier": [
951
- "error",
952
- {
953
- ...prettierOptions,
954
- parser: "graphql"
955
- }
956
- ]
957
- }
958
- });
959
- }
960
- return configs;
961
- }
962
-
963
- const ReactRefreshAllowConstantExportPackages = [
964
- "vite"
965
- ];
966
- async function react(options = {}) {
967
- const {
968
- files = [GLOB_JSX, GLOB_TSX],
969
- overrides = {},
970
- typescript = true
971
- } = options;
972
- await ensurePackages([
973
- "eslint-plugin-react",
974
- "eslint-plugin-react-hooks",
975
- "eslint-plugin-react-refresh"
976
- ]);
977
- const [
978
- pluginReact,
979
- pluginReactHooks,
980
- pluginReactRefresh
981
- ] = await Promise.all([
982
- interopDefault(import('eslint-plugin-react')),
983
- interopDefault(import('eslint-plugin-react-hooks')),
984
- interopDefault(import('eslint-plugin-react-refresh'))
985
- ]);
986
- const isAllowConstantExport = ReactRefreshAllowConstantExportPackages.some(
987
- (i) => isPackageExists(i)
988
- );
989
- return [
990
- {
991
- name: "curev:react:setup",
992
- plugins: {
993
- "react": pluginReact,
994
- "react-hooks": pluginReactHooks,
995
- "react-refresh": pluginReactRefresh
996
- },
997
- settings: {
998
- react: {
999
- version: "detect"
1000
- }
1001
- }
1002
- },
1003
- {
1004
- files,
1005
- languageOptions: {
1006
- parserOptions: {
1007
- ecmaFeatures: {
1008
- jsx: true
1009
- }
1010
- }
1011
- },
1012
- name: "curev:react:rules",
1013
- rules: {
1014
- // recommended rules react
1015
- "react/display-name": "error",
1016
- "react/jsx-key": "error",
1017
- "react/jsx-no-comment-textnodes": "error",
1018
- "react/jsx-no-duplicate-props": "error",
1019
- "react/jsx-no-target-blank": "error",
1020
- "react/jsx-no-undef": "error",
1021
- "react/jsx-uses-react": "error",
1022
- "react/jsx-uses-vars": "error",
1023
- "react/no-children-prop": "error",
1024
- "react/no-danger-with-children": "error",
1025
- "react/no-deprecated": "error",
1026
- "react/no-direct-mutation-state": "error",
1027
- "react/no-find-dom-node": "error",
1028
- "react/no-is-mounted": "error",
1029
- "react/no-render-return-value": "error",
1030
- "react/no-string-refs": "error",
1031
- "react/no-unescaped-entities": "error",
1032
- "react/no-unknown-property": "error",
1033
- "react/no-unsafe": "off",
1034
- "react/prop-types": "error",
1035
- "react/react-in-jsx-scope": "off",
1036
- "react/require-render-return": "error",
1037
- // recommended rules react-hooks
1038
- "react-hooks/exhaustive-deps": "warn",
1039
- "react-hooks/rules-of-hooks": "error",
1040
- // react refresh
1041
- "react-refresh/only-export-components": [
1042
- "warn",
1043
- { allowConstantExport: isAllowConstantExport }
1044
- ],
1045
- ...typescript ? {
1046
- "react/jsx-no-undef": "off",
1047
- "react/prop-type": "off"
1048
- } : {},
1049
- // overrides
1050
- ...overrides
1051
- }
1052
- }
1053
- ];
1054
- }
1055
-
1056
- async function sortPackageJson() {
1057
- return [
1058
- {
1059
- files: ["**/package.json"],
1060
- name: "curev:sort-package-json",
1061
- rules: {
1062
- "jsonc/sort-array-values": [
1063
- "error",
1064
- {
1065
- order: { type: "asc" },
1066
- pathPattern: "^files$"
1067
- }
1068
- ],
1069
- "jsonc/sort-keys": [
1070
- "error",
1071
- {
1072
- order: [
1073
- "publisher",
1074
- "name",
1075
- "displayName",
1076
- "type",
1077
- "version",
1078
- "private",
1079
- "packageManager",
1080
- "description",
1081
- "author",
1082
- "license",
1083
- "funding",
1084
- "homepage",
1085
- "repository",
1086
- "bugs",
1087
- "keywords",
1088
- "categories",
1089
- "sideEffects",
1090
- "exports",
1091
- "main",
1092
- "module",
1093
- "unpkg",
1094
- "jsdelivr",
1095
- "types",
1096
- "typesVersions",
1097
- "bin",
1098
- "icon",
1099
- "files",
1100
- "engines",
1101
- "activationEvents",
1102
- "contributes",
1103
- "scripts",
1104
- "peerDependencies",
1105
- "peerDependenciesMeta",
1106
- "dependencies",
1107
- "optionalDependencies",
1108
- "devDependencies",
1109
- "pnpm",
1110
- "overrides",
1111
- "resolutions",
1112
- "husky",
1113
- "simple-git-hooks",
1114
- "lint-staged",
1115
- "eslintConfig"
1116
- ],
1117
- pathPattern: "^$"
1118
- },
1119
- {
1120
- order: { type: "asc" },
1121
- pathPattern: "^(?:dev|peer|optional|bundled)?[Dd]ependencies(Meta)?$"
1122
- },
1123
- {
1124
- order: { type: "asc" },
1125
- pathPattern: "^(?:resolutions|overrides|pnpm.overrides)$"
1126
- },
1127
- {
1128
- order: [
1129
- "types",
1130
- "import",
1131
- "require",
1132
- "default"
1133
- ],
1134
- pathPattern: "^exports.*$"
1135
- }
1136
- ]
1137
- }
1138
- }
1139
- ];
1140
- }
1141
- function sortTsconfig() {
1142
- return [
1143
- {
1144
- files: ["**/tsconfig.json", "**/tsconfig.*.json"],
1145
- name: "curev:sort-tsconfig",
1146
- rules: {
1147
- "jsonc/sort-keys": [
1148
- "error",
1149
- {
1150
- order: [
1151
- "extends",
1152
- "compilerOptions",
1153
- "references",
1154
- "files",
1155
- "include",
1156
- "exclude"
1157
- ],
1158
- pathPattern: "^$"
1159
- },
1160
- {
1161
- order: [
1162
- /* Projects */
1163
- "incremental",
1164
- "composite",
1165
- "tsBuildInfoFile",
1166
- "disableSourceOfProjectReferenceRedirect",
1167
- "disableSolutionSearching",
1168
- "disableReferencedProjectLoad",
1169
- /* Language and Environment */
1170
- "target",
1171
- "jsx",
1172
- "jsxFactory",
1173
- "jsxFragmentFactory",
1174
- "jsxImportSource",
1175
- "lib",
1176
- "moduleDetection",
1177
- "noLib",
1178
- "reactNamespace",
1179
- "useDefineForClassFields",
1180
- "emitDecoratorMetadata",
1181
- "experimentalDecorators",
1182
- /* Modules */
1183
- "baseUrl",
1184
- "rootDir",
1185
- "rootDirs",
1186
- "customConditions",
1187
- "module",
1188
- "moduleResolution",
1189
- "moduleSuffixes",
1190
- "noResolve",
1191
- "paths",
1192
- "resolveJsonModule",
1193
- "resolvePackageJsonExports",
1194
- "resolvePackageJsonImports",
1195
- "typeRoots",
1196
- "types",
1197
- "allowArbitraryExtensions",
1198
- "allowImportingTsExtensions",
1199
- "allowUmdGlobalAccess",
1200
- /* JavaScript Support */
1201
- "allowJs",
1202
- "checkJs",
1203
- "maxNodeModuleJsDepth",
1204
- /* Type Checking */
1205
- "strict",
1206
- "strictBindCallApply",
1207
- "strictFunctionTypes",
1208
- "strictNullChecks",
1209
- "strictPropertyInitialization",
1210
- "allowUnreachableCode",
1211
- "allowUnusedLabels",
1212
- "alwaysStrict",
1213
- "exactOptionalPropertyTypes",
1214
- "noFallthroughCasesInSwitch",
1215
- "noImplicitAny",
1216
- "noImplicitOverride",
1217
- "noImplicitReturns",
1218
- "noImplicitThis",
1219
- "noPropertyAccessFromIndexSignature",
1220
- "noUncheckedIndexedAccess",
1221
- "noUnusedLocals",
1222
- "noUnusedParameters",
1223
- "useUnknownInCatchVariables",
1224
- /* Emit */
1225
- "declaration",
1226
- "declarationDir",
1227
- "declarationMap",
1228
- "downlevelIteration",
1229
- "emitBOM",
1230
- "emitDeclarationOnly",
1231
- "importHelpers",
1232
- "importsNotUsedAsValues",
1233
- "inlineSourceMap",
1234
- "inlineSources",
1235
- "mapRoot",
1236
- "newLine",
1237
- "noEmit",
1238
- "noEmitHelpers",
1239
- "noEmitOnError",
1240
- "outDir",
1241
- "outFile",
1242
- "preserveConstEnums",
1243
- "preserveValueImports",
1244
- "removeComments",
1245
- "sourceMap",
1246
- "sourceRoot",
1247
- "stripInternal",
1248
- /* Interop Constraints */
1249
- "allowSyntheticDefaultImports",
1250
- "esModuleInterop",
1251
- "forceConsistentCasingInFileNames",
1252
- "isolatedModules",
1253
- "preserveSymlinks",
1254
- "verbatimModuleSyntax",
1255
- /* Completeness */
1256
- "skipDefaultLibCheck",
1257
- "skipLibCheck"
1258
- ],
1259
- pathPattern: "^compilerOptions$"
1260
- }
1261
- ]
1262
- }
1263
- }
1264
- ];
1265
- }
1266
-
1267
- async function svelte(options = {}) {
1268
- const {
1269
- files = [GLOB_SVELTE],
1270
- overrides = {},
1271
- stylistic = true
1272
- } = options;
1273
- const {
1274
- indent = 2,
1275
- quotes = "single"
1276
- } = typeof stylistic === "boolean" ? {} : stylistic;
1277
- await ensurePackages([
1278
- "eslint-plugin-svelte"
1279
- ]);
1280
- const [
1281
- pluginSvelte,
1282
- parserSvelte
1283
- ] = await Promise.all([
1284
- interopDefault(import('eslint-plugin-svelte')),
1285
- interopDefault(import('svelte-eslint-parser'))
1286
- ]);
1287
- return [
1288
- {
1289
- name: "curev:svelte:setup",
1290
- plugins: {
1291
- svelte: pluginSvelte
1292
- }
1293
- },
1294
- {
1295
- files,
1296
- languageOptions: {
1297
- parser: parserSvelte,
1298
- parserOptions: {
1299
- extraFileExtensions: [".svelte"],
1300
- parser: options.typescript ? await interopDefault(import('@typescript-eslint/parser')) : null
1301
- }
1302
- },
1303
- name: "curev:svelte:rules",
1304
- processor: pluginSvelte.processors[".svelte"],
1305
- rules: {
1306
- "import/no-mutable-exports": "off",
1307
- "no-undef": "off",
1308
- // incompatible with most recent (attribute-form) generic types RFC
1309
- "no-unused-vars": ["error", {
1310
- args: "none",
1311
- caughtErrors: "none",
1312
- ignoreRestSiblings: true,
1313
- vars: "all",
1314
- varsIgnorePattern: "^\\$\\$Props$"
1315
- }],
1316
- "svelte/comment-directive": "error",
1317
- "svelte/no-at-debug-tags": "warn",
1318
- "svelte/no-at-html-tags": "error",
1319
- "svelte/no-dupe-else-if-blocks": "error",
1320
- "svelte/no-dupe-style-properties": "error",
1321
- "svelte/no-dupe-use-directives": "error",
1322
- "svelte/no-dynamic-slot-name": "error",
1323
- "svelte/no-export-load-in-svelte-module-in-kit-pages": "error",
1324
- "svelte/no-inner-declarations": "error",
1325
- "svelte/no-not-function-handler": "error",
1326
- "svelte/no-object-in-text-mustaches": "error",
1327
- "svelte/no-reactive-functions": "error",
1328
- "svelte/no-reactive-literals": "error",
1329
- "svelte/no-shorthand-style-property-overrides": "error",
1330
- "svelte/no-unknown-style-directive-property": "error",
1331
- "svelte/no-unused-svelte-ignore": "error",
1332
- "svelte/no-useless-mustaches": "error",
1333
- "svelte/require-store-callbacks-use-set-param": "error",
1334
- "svelte/system": "error",
1335
- "svelte/valid-compile": "error",
1336
- "svelte/valid-each-key": "error",
1337
- "unused-imports/no-unused-vars": [
1338
- "error",
1339
- { args: "after-used", argsIgnorePattern: "^_", vars: "all", varsIgnorePattern: "^(_|\\$\\$Props$)" }
1340
- ],
1341
- ...stylistic ? {
1342
- "style/no-trailing-spaces": "off",
1343
- // superseded by svelte/no-trailing-spaces
1344
- "svelte/derived-has-same-inputs-outputs": "error",
1345
- "svelte/html-closing-bracket-spacing": "error",
1346
- "svelte/html-quotes": ["error", { prefer: quotes }],
1347
- "svelte/indent": ["error", { alignAttributesVertically: true, indent }],
1348
- "svelte/mustache-spacing": "error",
1349
- "svelte/no-spaces-around-equal-signs-in-attribute": "error",
1350
- "svelte/no-trailing-spaces": "error",
1351
- "svelte/spaced-html-comment": "error"
1352
- } : {},
1353
- ...overrides
1354
- }
1355
- }
1356
- ];
1357
- }
1358
-
1359
- async function test(options = {}) {
1360
- const {
1361
- files = GLOB_TESTS,
1362
- isInEditor = false,
1363
- overrides = {}
1364
- } = options;
1365
- const [
1366
- pluginVitest,
1367
- pluginNoOnlyTests
1368
- ] = await Promise.all([
1369
- interopDefault(import('eslint-plugin-vitest')),
1370
- // @ts-expect-error missing types
1371
- interopDefault(import('eslint-plugin-no-only-tests'))
1372
- ]);
1373
- return [
1374
- {
1375
- name: "curev:test:setup",
1376
- plugins: {
1377
- test: {
1378
- ...pluginVitest,
1379
- rules: {
1380
- ...pluginVitest.rules,
1381
- // extend `test/no-only-tests` rule
1382
- ...pluginNoOnlyTests.rules
1383
- }
1384
- }
1385
- }
1386
- },
1387
- {
1388
- files,
1389
- name: "curev:test:rules",
1390
- rules: {
1391
- "node/prefer-global/process": "off",
1392
- "test/consistent-test-it": ["error", { fn: "it", withinDescribe: "it" }],
1393
- "test/no-identical-title": "error",
1394
- "test/no-import-node-test": "error",
1395
- "test/no-only-tests": isInEditor ? "off" : "error",
1396
- "test/prefer-hooks-in-order": "error",
1397
- "test/prefer-lowercase-title": "error",
1398
- ...overrides
1399
- }
1400
- }
1401
- ];
1402
- }
1403
-
1404
- async function typescript(options = {}) {
1405
- const {
1406
- componentExts = [],
1407
- overrides = {},
1408
- parserOptions = {}
1409
- } = options;
1410
- const files = options.files ?? [
1411
- GLOB_SRC,
1412
- ...componentExts.map((ext) => `**/*.${ext}`)
1413
- ];
1414
- const filesTypeAware = options.filesTypeAware ?? [GLOB_TS, GLOB_TSX];
1415
- const tsconfigPath = options?.tsconfigPath ? toArray(options.tsconfigPath) : void 0;
1416
- const isTypeAware = !!tsconfigPath;
1417
- const typeAwareRules = {
1418
- "dot-notation": "off",
1419
- "no-implied-eval": "off",
1420
- "no-throw-literal": "off",
1421
- "ts/await-thenable": "error",
1422
- "ts/dot-notation": ["error", { allowKeywords: true }],
1423
- "ts/no-floating-promises": "error",
1424
- "ts/no-for-in-array": "error",
1425
- "ts/no-implied-eval": "error",
1426
- "ts/no-misused-promises": "error",
1427
- "ts/no-throw-literal": "error",
1428
- "ts/no-unnecessary-type-assertion": "error",
1429
- "ts/no-unsafe-argument": "error",
1430
- "ts/no-unsafe-assignment": "error",
1431
- "ts/no-unsafe-call": "error",
1432
- "ts/no-unsafe-member-access": "error",
1433
- "ts/no-unsafe-return": "error",
1434
- "ts/restrict-plus-operands": "error",
1435
- "ts/restrict-template-expressions": "error",
1436
- "ts/unbound-method": "error"
1437
- };
1438
- const [
1439
- pluginTs,
1440
- parserTs
1441
- ] = await Promise.all([
1442
- interopDefault(import('@typescript-eslint/eslint-plugin')),
1443
- interopDefault(import('@typescript-eslint/parser'))
1444
- ]);
1445
- function makeParser(typeAware, files2, ignores) {
1446
- return {
1447
- files: files2,
1448
- ...ignores ? { ignores } : {},
1449
- languageOptions: {
1450
- parser: parserTs,
1451
- parserOptions: {
1452
- extraFileExtensions: componentExts.map((ext) => `.${ext}`),
1453
- sourceType: "module",
1454
- ...typeAware ? {
1455
- project: tsconfigPath,
1456
- tsconfigRootDir: process.cwd()
1457
- } : {},
1458
- ...parserOptions
1459
- }
1460
- },
1461
- name: `curev:typescript:${typeAware ? "type-aware-parser" : "parser"}`
1462
- };
1463
- }
1464
- return [
1465
- {
1466
- // Install the plugins without globs, so they can be configured separately.
1467
- name: "curev:typescript:setup",
1468
- plugins: {
1469
- curev: pluginCurev,
1470
- ts: pluginTs
1471
- }
1472
- },
1473
- // assign type-aware parser for type-aware files and type-unaware parser for the rest
1474
- ...isTypeAware ? [
1475
- makeParser(true, filesTypeAware),
1476
- makeParser(false, files, filesTypeAware)
1477
- ] : [makeParser(false, files)],
1478
- {
1479
- files,
1480
- name: "curev:typescript:rules",
1481
- rules: {
1482
- ...renameRules(
1483
- pluginTs.configs["eslint-recommended"].overrides[0].rules,
1484
- "@typescript-eslint/",
1485
- "ts/"
1486
- ),
1487
- ...renameRules(
1488
- pluginTs.configs.strict.rules,
1489
- "@typescript-eslint/",
1490
- "ts/"
1491
- ),
1492
- "no-dupe-class-members": "off",
1493
- "no-loss-of-precision": "off",
1494
- "no-redeclare": "off",
1495
- "no-use-before-define": "off",
1496
- "no-useless-constructor": "off",
1497
- "ts/ban-ts-comment": ["error", { "ts-ignore": "allow-with-description" }],
1498
- "ts/ban-types": ["error", { types: { Function: false } }],
1499
- "ts/consistent-type-definitions": ["error", "interface"],
1500
- "ts/consistent-type-imports": ["error", { disallowTypeAnnotations: false, prefer: "type-imports" }],
1501
- "ts/no-dupe-class-members": "error",
1502
- "ts/no-dynamic-delete": "off",
1503
- "ts/no-explicit-any": "off",
1504
- "ts/no-extraneous-class": "off",
1505
- "ts/no-import-type-side-effects": "error",
1506
- "ts/no-invalid-void-type": "off",
1507
- "ts/no-loss-of-precision": "error",
1508
- "ts/no-non-null-assertion": "off",
1509
- "ts/no-redeclare": "error",
1510
- "ts/no-require-imports": "error",
1511
- "ts/no-unused-vars": "off",
1512
- "ts/no-use-before-define": ["error", { classes: false, functions: false, variables: true }],
1513
- "ts/no-useless-constructor": "off",
1514
- "ts/prefer-ts-expect-error": "error",
1515
- "ts/triple-slash-reference": "off",
1516
- "ts/unified-signatures": "off",
1517
- ...overrides
1518
- }
1519
- },
1520
- {
1521
- files: filesTypeAware,
1522
- name: "curev:typescript:rules-type-aware",
1523
- rules: {
1524
- ...tsconfigPath ? typeAwareRules : {},
1525
- ...overrides
1526
- }
1527
- },
1528
- {
1529
- files: ["**/*.d.ts"],
1530
- name: "curev:typescript:dts-overrides",
1531
- rules: {
1532
- "eslint-comments/no-unlimited-disable": "off",
1533
- "import/no-duplicates": "off",
1534
- "no-restricted-syntax": "off",
1535
- "unused-imports/no-unused-vars": "off"
1536
- }
1537
- },
1538
- {
1539
- files: ["**/*.{test,spec}.ts?(x)"],
1540
- name: "curev:typescript:tests-overrides",
1541
- rules: {
1542
- "no-unused-expressions": "off"
1543
- }
1544
- },
1545
- {
1546
- files: ["**/*.js", "**/*.cjs"],
1547
- name: "curev:typescript:javascript-overrides",
1548
- rules: {
1549
- "ts/no-require-imports": "off",
1550
- "ts/no-var-requires": "off"
1551
- }
1552
- }
1553
- ];
1554
- }
1555
-
1556
- async function unicorn() {
1557
- return [
1558
- {
1559
- name: "curev:unicorn",
1560
- plugins: {
1561
- unicorn: pluginUnicorn
1562
- },
1563
- rules: {
1564
- // Pass error message when throwing errors
1565
- "unicorn/error-message": "error",
1566
- // Uppercase regex escapes
1567
- "unicorn/escape-case": "error",
1568
- // Array.isArray instead of instanceof
1569
- "unicorn/no-instanceof-array": "error",
1570
- // Ban `new Array` as `Array` constructor's params are ambiguous
1571
- "unicorn/no-new-array": "error",
1572
- // Prevent deprecated `new Buffer()`
1573
- "unicorn/no-new-buffer": "error",
1574
- // Lowercase number formatting for octal, hex, binary (0x1'error' instead of 0X1'error')
1575
- "unicorn/number-literal-case": "error",
1576
- // textContent instead of innerText
1577
- "unicorn/prefer-dom-node-text-content": "error",
1578
- // includes over indexOf when checking for existence
1579
- "unicorn/prefer-includes": "error",
1580
- // Prefer using the node: protocol
1581
- "unicorn/prefer-node-protocol": "error",
1582
- // Prefer using number properties like `Number.isNaN` rather than `isNaN`
1583
- "unicorn/prefer-number-properties": "error",
1584
- // String methods startsWith/endsWith instead of more complicated stuff
1585
- "unicorn/prefer-string-starts-ends-with": "error",
1586
- // Enforce throwing type error when throwing error while checking typeof
1587
- "unicorn/prefer-type-error": "error",
1588
- // Use new when throwing error
1589
- "unicorn/throw-new-error": "error"
1590
- }
1591
- }
1592
- ];
1593
- }
1594
-
1595
- async function unocss(options = {}) {
1596
- const {
1597
- attributify = true,
1598
- strict = false
1599
- } = options;
1600
- await ensurePackages([
1601
- "@unocss/eslint-plugin"
1602
- ]);
1603
- const [
1604
- pluginUnoCSS
1605
- ] = await Promise.all([
1606
- interopDefault(import('@unocss/eslint-plugin'))
1607
- ]);
1608
- return [
1609
- {
1610
- name: "curev:unocss",
1611
- plugins: {
1612
- unocss: pluginUnoCSS
1613
- },
1614
- rules: {
1615
- "unocss/order": "warn",
1616
- ...attributify ? {
1617
- "unocss/order-attributify": "warn"
1618
- } : {},
1619
- ...strict ? {
1620
- "unocss/blocklist": "error"
1621
- } : {}
1622
- }
1623
- }
1624
- ];
1625
- }
1626
-
1627
- async function vue(options = {}) {
1628
- const {
1629
- files = [GLOB_VUE],
1630
- overrides = {},
1631
- stylistic = true,
1632
- vueVersion = 3
1633
- } = options;
1634
- const sfcBlocks = options.sfcBlocks === true ? {} : options.sfcBlocks ?? {};
1635
- const {
1636
- indent = 2
1637
- } = typeof stylistic === "boolean" ? {} : stylistic;
1638
- const [
1639
- pluginVue,
1640
- parserVue,
1641
- processorVueBlocks
1642
- ] = await Promise.all([
1643
- // @ts-expect-error missing types
1644
- interopDefault(import('eslint-plugin-vue')),
1645
- interopDefault(import('vue-eslint-parser')),
1646
- interopDefault(import('eslint-processor-vue-blocks'))
1647
- ]);
1648
- return [
1649
- {
1650
- name: "curev:vue:setup",
1651
- plugins: {
1652
- vue: pluginVue
1653
- }
1654
- },
1655
- {
1656
- files,
1657
- languageOptions: {
1658
- parser: parserVue,
1659
- parserOptions: {
1660
- ecmaFeatures: {
1661
- jsx: true
1662
- },
1663
- extraFileExtensions: [".vue"],
1664
- parser: options.typescript ? await interopDefault(import('@typescript-eslint/parser')) : null,
1665
- sourceType: "module"
1666
- }
1667
- },
1668
- name: "curev:vue:rules",
1669
- processor: sfcBlocks === false ? pluginVue.processors[".vue"] : mergeProcessors([
1670
- pluginVue.processors[".vue"],
1671
- processorVueBlocks({
1672
- ...sfcBlocks,
1673
- blocks: {
1674
- styles: true,
1675
- ...sfcBlocks.blocks
1676
- }
1677
- })
1678
- ]),
1679
- rules: {
1680
- ...pluginVue.configs.base.rules,
1681
- ...vueVersion === 2 ? {
1682
- ...pluginVue.configs.essential.rules,
1683
- ...pluginVue.configs["strongly-recommended"].rules,
1684
- ...pluginVue.configs.recommended.rules
1685
- } : {
1686
- ...pluginVue.configs["vue3-essential"].rules,
1687
- ...pluginVue.configs["vue3-strongly-recommended"].rules,
1688
- ...pluginVue.configs["vue3-recommended"].rules
1689
- },
1690
- "node/prefer-global/process": "off",
1691
- "vue/block-order": ["error", {
1692
- order: ["script", "template", "style"]
1693
- }],
1694
- "vue/component-name-in-template-casing": ["error", "PascalCase"],
1695
- "vue/component-options-name-casing": ["error", "PascalCase"],
1696
- // this is deprecated
1697
- "vue/component-tags-order": "off",
1698
- "vue/custom-event-name-casing": ["error", "camelCase"],
1699
- "vue/define-macros-order": ["error", {
1700
- order: ["defineOptions", "defineProps", "defineEmits", "defineSlots"]
1701
- }],
1702
- "vue/dot-location": ["error", "property"],
1703
- "vue/dot-notation": ["error", { allowKeywords: true }],
1704
- "vue/eqeqeq": ["error", "smart"],
1705
- "vue/html-indent": ["error", indent],
1706
- "vue/html-quotes": ["error", "double"],
1707
- "vue/max-attributes-per-line": "off",
1708
- "vue/multi-word-component-names": "off",
1709
- "vue/no-dupe-keys": "off",
1710
- "vue/no-empty-pattern": "error",
1711
- "vue/no-irregular-whitespace": "error",
1712
- "vue/no-loss-of-precision": "error",
1713
- "vue/no-restricted-syntax": [
1714
- "error",
1715
- "DebuggerStatement",
1716
- "LabeledStatement",
1717
- "WithStatement"
1718
- ],
1719
- "vue/no-restricted-v-bind": ["error", "/^v-/"],
1720
- "vue/no-setup-props-reactivity-loss": "off",
1721
- "vue/no-sparse-arrays": "error",
1722
- "vue/no-unused-refs": "error",
1723
- "vue/no-useless-v-bind": "error",
1724
- "vue/no-v-html": "off",
1725
- "vue/object-shorthand": [
1726
- "error",
1727
- "always",
1728
- {
1729
- avoidQuotes: true,
1730
- ignoreConstructors: false
1731
- }
1732
- ],
1733
- "vue/prefer-separate-static-class": "error",
1734
- "vue/prefer-template": "error",
1735
- "vue/prop-name-casing": ["error", "camelCase"],
1736
- "vue/require-default-prop": "off",
1737
- "vue/require-prop-types": "off",
1738
- "vue/space-infix-ops": "error",
1739
- "vue/space-unary-ops": ["error", { nonwords: false, words: true }],
1740
- ...stylistic ? {
1741
- "vue/array-bracket-spacing": ["error", "never"],
1742
- "vue/arrow-spacing": ["error", { after: true, before: true }],
1743
- "vue/block-spacing": ["error", "always"],
1744
- "vue/block-tag-newline": ["error", {
1745
- multiline: "always",
1746
- singleline: "always"
1747
- }],
1748
- "vue/brace-style": ["error", "stroustrup", { allowSingleLine: true }],
1749
- "vue/comma-dangle": ["error", "always-multiline"],
1750
- "vue/comma-spacing": ["error", { after: true, before: false }],
1751
- "vue/comma-style": ["error", "last"],
1752
- "vue/html-comment-content-spacing": ["error", "always", {
1753
- exceptions: ["-"]
1754
- }],
1755
- "vue/key-spacing": ["error", { afterColon: true, beforeColon: false }],
1756
- "vue/keyword-spacing": ["error", { after: true, before: true }],
1757
- "vue/object-curly-newline": "off",
1758
- "vue/object-curly-spacing": ["error", "always"],
1759
- "vue/object-property-newline": ["error", { allowMultiplePropertiesPerLine: true }],
1760
- "vue/operator-linebreak": ["error", "before"],
1761
- "vue/padding-line-between-blocks": ["error", "always"],
1762
- "vue/quote-props": ["error", "consistent-as-needed"],
1763
- "vue/space-in-parens": ["error", "never"],
1764
- "vue/template-curly-spacing": "error"
1765
- } : {},
1766
- ...overrides
1767
- }
1768
- }
1769
- ];
1770
- }
1771
-
1772
- async function yaml(options = {}) {
1773
- const {
1774
- files = [GLOB_YAML],
1775
- overrides = {},
1776
- stylistic = true
1777
- } = options;
1778
- const {
1779
- indent = 2,
1780
- quotes = "single"
1781
- } = typeof stylistic === "boolean" ? {} : stylistic;
1782
- const [
1783
- pluginYaml,
1784
- parserYaml
1785
- ] = await Promise.all([
1786
- interopDefault(import('eslint-plugin-yml')),
1787
- interopDefault(import('yaml-eslint-parser'))
1788
- ]);
1789
- return [
1790
- {
1791
- name: "curev:yaml:setup",
1792
- plugins: {
1793
- yaml: pluginYaml
1794
- }
1795
- },
1796
- {
1797
- files,
1798
- languageOptions: {
1799
- parser: parserYaml
1800
- },
1801
- name: "curev:yaml:rules",
1802
- rules: {
1803
- "style/spaced-comment": "off",
1804
- "yaml/block-mapping": "error",
1805
- "yaml/block-sequence": "error",
1806
- "yaml/no-empty-key": "error",
1807
- "yaml/no-empty-sequence-entry": "error",
1808
- "yaml/no-irregular-whitespace": "error",
1809
- "yaml/plain-scalar": "error",
1810
- "yaml/vue-custom-block/no-parsing-error": "error",
1811
- ...stylistic ? {
1812
- "yaml/block-mapping-question-indicator-newline": "error",
1813
- "yaml/block-sequence-hyphen-indicator-newline": "error",
1814
- "yaml/flow-mapping-curly-newline": "error",
1815
- "yaml/flow-mapping-curly-spacing": "error",
1816
- "yaml/flow-sequence-bracket-newline": "error",
1817
- "yaml/flow-sequence-bracket-spacing": "error",
1818
- "yaml/indent": ["error", indent === "tab" ? 2 : indent],
1819
- "yaml/key-spacing": "error",
1820
- "yaml/no-tab-indent": "error",
1821
- "yaml/quotes": ["error", { avoidEscape: false, prefer: quotes }],
1822
- "yaml/spaced-comment": "error"
1823
- } : {},
1824
- ...overrides
1825
- }
1826
- }
1827
- ];
1828
- }
1829
-
1830
- async function toml(options = {}) {
1831
- const {
1832
- files = [GLOB_TOML],
1833
- overrides = {},
1834
- stylistic = true
1835
- } = options;
1836
- const {
1837
- indent = 2
1838
- } = typeof stylistic === "boolean" ? {} : stylistic;
1839
- const [
1840
- pluginToml,
1841
- parserToml
1842
- ] = await Promise.all([
1843
- interopDefault(import('eslint-plugin-toml')),
1844
- interopDefault(import('toml-eslint-parser'))
1845
- ]);
1846
- return [
1847
- {
1848
- name: "curev:toml:setup",
1849
- plugins: {
1850
- toml: pluginToml
1851
- }
1852
- },
1853
- {
1854
- files,
1855
- languageOptions: {
1856
- parser: parserToml
1857
- },
1858
- name: "curev:toml:rules",
1859
- rules: {
1860
- "style/spaced-comment": "off",
1861
- "toml/comma-style": "error",
1862
- "toml/keys-order": "error",
1863
- "toml/no-space-dots": "error",
1864
- "toml/no-unreadable-number-separator": "error",
1865
- "toml/precision-of-fractional-seconds": "error",
1866
- "toml/precision-of-integer": "error",
1867
- "toml/tables-order": "error",
1868
- "toml/vue-custom-block/no-parsing-error": "error",
1869
- ...stylistic ? {
1870
- "toml/array-bracket-newline": "error",
1871
- "toml/array-bracket-spacing": "error",
1872
- "toml/array-element-newline": "error",
1873
- "toml/indent": ["error", indent === "tab" ? 2 : indent],
1874
- "toml/inline-table-curly-spacing": "error",
1875
- "toml/key-spacing": "error",
1876
- "toml/padding-line-between-pairs": "error",
1877
- "toml/padding-line-between-tables": "error",
1878
- "toml/quoted-keys": "error",
1879
- "toml/spaced-comment": "error",
1880
- "toml/table-bracket-spacing": "error"
1881
- } : {},
1882
- ...overrides
1883
- }
1884
- }
1885
- ];
1886
- }
1887
-
1888
- const flatConfigProps = [
1889
- "name",
1890
- "files",
1891
- "ignores",
1892
- "languageOptions",
1893
- "linterOptions",
1894
- "processor",
1895
- "plugins",
1896
- "rules",
1897
- "settings"
1898
- ];
1899
- const VuePackages = [
1900
- "vue",
1901
- "nuxt",
1902
- "vitepress",
1903
- "@slidev/cli"
1904
- ];
1905
- async function curev(options = {}, ...userConfigs) {
1906
- const {
1907
- componentExts = [],
1908
- gitignore: enableGitignore = true,
1909
- isInEditor = !!((process.env.VSCODE_PID || process.env.JETBRAINS_IDE || process.env.VIM) && !process.env.CI),
1910
- react: enableReact = false,
1911
- svelte: enableSvelte = false,
1912
- typescript: enableTypeScript = isPackageExists("typescript"),
1913
- unocss: enableUnoCSS = false,
1914
- vue: enableVue = VuePackages.some((i) => isPackageExists(i))
1915
- } = options;
1916
- const stylisticOptions = options.stylistic === false ? false : typeof options.stylistic === "object" ? options.stylistic : {};
1917
- if (stylisticOptions && !("jsx" in stylisticOptions)) {
1918
- stylisticOptions.jsx = options.jsx ?? true;
1919
- }
1920
- const configs = [];
1921
- if (enableGitignore) {
1922
- if (typeof enableGitignore !== "boolean") {
1923
- configs.push(interopDefault(import('eslint-config-flat-gitignore')).then((r) => [r(enableGitignore)]));
1924
- } else {
1925
- if (fs.existsSync(".gitignore")) {
1926
- configs.push(interopDefault(import('eslint-config-flat-gitignore')).then((r) => [r()]));
1927
- }
1928
- }
1929
- }
1930
- configs.push(
1931
- ignores(),
1932
- javascript({
1933
- isInEditor,
1934
- overrides: getOverrides(options, "javascript")
1935
- }),
1936
- comments(),
1937
- node(),
1938
- jsdoc({
1939
- stylistic: stylisticOptions
1940
- }),
1941
- imports({
1942
- stylistic: stylisticOptions
1943
- }),
1944
- unicorn(),
1945
- // Optional plugins (installed but not enabled by default)
1946
- perfectionist()
1947
- );
1948
- if (enableVue) {
1949
- componentExts.push("vue");
1950
- }
1951
- if (enableTypeScript) {
1952
- configs.push(typescript({
1953
- ...resolveSubOptions(options, "typescript"),
1954
- componentExts,
1955
- overrides: getOverrides(options, "typescript")
1956
- }));
1957
- }
1958
- if (stylisticOptions) {
1959
- configs.push(stylistic({
1960
- ...stylisticOptions,
1961
- overrides: getOverrides(options, "stylistic")
1962
- }));
1963
- }
1964
- if (options.test ?? true) {
1965
- configs.push(test({
1966
- isInEditor,
1967
- overrides: getOverrides(options, "test")
1968
- }));
1969
- }
1970
- if (enableVue) {
1971
- configs.push(vue({
1972
- ...resolveSubOptions(options, "vue"),
1973
- overrides: getOverrides(options, "vue"),
1974
- stylistic: stylisticOptions,
1975
- typescript: !!enableTypeScript
1976
- }));
1977
- }
1978
- if (enableReact) {
1979
- configs.push(react({
1980
- overrides: getOverrides(options, "react"),
1981
- typescript: !!enableTypeScript
1982
- }));
1983
- }
1984
- if (enableSvelte) {
1985
- configs.push(svelte({
1986
- overrides: getOverrides(options, "svelte"),
1987
- stylistic: stylisticOptions,
1988
- typescript: !!enableTypeScript
1989
- }));
1990
- }
1991
- if (enableUnoCSS) {
1992
- configs.push(unocss({
1993
- ...resolveSubOptions(options, "unocss"),
1994
- overrides: getOverrides(options, "unocss")
1995
- }));
1996
- }
1997
- if (options.jsonc ?? true) {
1998
- configs.push(
1999
- jsonc({
2000
- overrides: getOverrides(options, "jsonc"),
2001
- stylistic: stylisticOptions
2002
- }),
2003
- sortPackageJson(),
2004
- sortTsconfig()
2005
- );
2006
- }
2007
- if (options.yaml ?? true) {
2008
- configs.push(yaml({
2009
- overrides: getOverrides(options, "yaml"),
2010
- stylistic: stylisticOptions
2011
- }));
2012
- }
2013
- if (options.toml ?? true) {
2014
- configs.push(toml({
2015
- overrides: getOverrides(options, "toml"),
2016
- stylistic: stylisticOptions
2017
- }));
2018
- }
2019
- if (options.markdown ?? true) {
2020
- configs.push(
2021
- markdown(
2022
- {
2023
- componentExts,
2024
- overrides: getOverrides(options, "markdown")
2025
- }
2026
- )
2027
- );
2028
- }
2029
- if (options.formatters) {
2030
- configs.push(formatters(
2031
- options.formatters,
2032
- typeof stylisticOptions === "boolean" ? {} : stylisticOptions
2033
- ));
2034
- }
2035
- const fusedConfig = flatConfigProps.reduce((acc, key) => {
2036
- if (key in options) {
2037
- acc[key] = options[key];
2038
- }
2039
- return acc;
2040
- }, {});
2041
- if (Object.keys(fusedConfig).length) {
2042
- configs.push([fusedConfig]);
2043
- }
2044
- const merged = combine(
2045
- ...configs,
2046
- ...userConfigs
2047
- );
2048
- return merged;
2049
- }
2050
- function resolveSubOptions(options, key) {
2051
- return typeof options[key] === "boolean" ? {} : options[key] || {};
2052
- }
2053
- function getOverrides(options, key) {
2054
- const sub = resolveSubOptions(options, key);
2055
- return {
2056
- ...options.overrides?.[key],
2057
- ..."overrides" in sub ? sub.overrides : {}
2058
- };
2059
- }
2060
-
2061
- export { GLOB_ALL_SRC, GLOB_CSS, GLOB_EXCLUDE, GLOB_HTML, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSX, GLOB_LESS, GLOB_MARKDOWN, GLOB_MARKDOWN_CODE, GLOB_MARKDOWN_IN_MARKDOWN, GLOB_POSTCSS, GLOB_SCSS, GLOB_SRC, GLOB_SRC_EXT, GLOB_STYLE, GLOB_SVELTE, GLOB_TESTS, GLOB_TOML, GLOB_TS, GLOB_TSX, GLOB_VUE, GLOB_YAML, StylisticConfigDefaults, combine, comments, curev, curev as default, ensurePackages, formatters, getOverrides, ignores, imports, interopDefault, javascript, jsdoc, jsonc, markdown, node, parserPlain, perfectionist, react, renameRules, resolveSubOptions, sortPackageJson, sortTsconfig, stylistic, svelte, test, toArray, toml, typescript, unicorn, unocss, vue, yaml };