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