@dauphaihau/eslint-config 0.2.0 → 0.2.2
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/README.md +30 -12
- package/dist/index.d.ts +5 -4
- package/dist/index.js +228 -93
- package/package.json +16 -7
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
- Auto fix for formatting (aimed to be used standalone without Prettier)
|
|
4
4
|
- Opinionated, but very customizable
|
|
5
|
-
-
|
|
5
|
+
- Auto-detects your tech stack (React, TypeScript, Tailwind, etc.)
|
|
6
6
|
- ESLint Flat config, compose easily!
|
|
7
7
|
|
|
8
8
|
## Installation
|
|
@@ -15,9 +15,12 @@ And create `eslint.config.mjs` in your project root:
|
|
|
15
15
|
|
|
16
16
|
```js
|
|
17
17
|
// eslint.config.mjs
|
|
18
|
-
import
|
|
18
|
+
import dauphaihauConfig from '@dauphaihau/eslint-config'
|
|
19
|
+
import { defineConfig } from 'eslint/config'
|
|
19
20
|
|
|
20
|
-
export default
|
|
21
|
+
export default defineConfig([
|
|
22
|
+
...(await dauphaihauConfig())
|
|
23
|
+
])
|
|
21
24
|
```
|
|
22
25
|
|
|
23
26
|
### Add script for package.json
|
|
@@ -36,25 +39,40 @@ For example:
|
|
|
36
39
|
## Usage
|
|
37
40
|
|
|
38
41
|
### Basic
|
|
39
|
-
Normally you only need to import the
|
|
42
|
+
Normally you only need to import the dauphaihauConfig preset:
|
|
40
43
|
|
|
41
44
|
```js
|
|
42
45
|
// eslint.config.js
|
|
43
|
-
import
|
|
46
|
+
import dauphaihauConfig from '@dauphaihau/eslint-config'
|
|
47
|
+
import { defineConfig } from 'eslint/config'
|
|
44
48
|
|
|
45
|
-
export default
|
|
49
|
+
export default defineConfig([
|
|
50
|
+
...(await dauphaihauConfig())
|
|
51
|
+
])
|
|
46
52
|
```
|
|
47
53
|
|
|
48
54
|
### Customize
|
|
49
55
|
|
|
56
|
+
The config auto-detects your tech stack. Pass `false` to explicitly disable rules for a specific stack:
|
|
57
|
+
|
|
50
58
|
```js
|
|
51
59
|
// eslint.config.js
|
|
52
|
-
import
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
import dauphaihauConfig from '@dauphaihau/eslint-config'
|
|
61
|
+
import { defineConfig } from 'eslint/config'
|
|
62
|
+
|
|
63
|
+
export default defineConfig([
|
|
64
|
+
...(await dauphaihauConfig({
|
|
65
|
+
tailwind: false, // disable Tailwind rules
|
|
66
|
+
})),
|
|
67
|
+
|
|
68
|
+
// Your configs and overrides
|
|
69
|
+
{
|
|
70
|
+
files: ['**/*.{ts,tsx}'],
|
|
71
|
+
rules: {
|
|
72
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
])
|
|
58
76
|
```
|
|
59
77
|
## License
|
|
60
78
|
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ type Options = {
|
|
|
4
4
|
typescript?: boolean;
|
|
5
5
|
react?: boolean;
|
|
6
6
|
vue?: boolean;
|
|
7
|
+
tailwind?: boolean;
|
|
7
8
|
};
|
|
8
9
|
/**
|
|
9
10
|
* Default factory function for creating ESLint configurations.
|
|
@@ -11,10 +12,10 @@ type Options = {
|
|
|
11
12
|
*
|
|
12
13
|
* @example
|
|
13
14
|
* ```ts
|
|
14
|
-
* import
|
|
15
|
-
* export default
|
|
15
|
+
* import eslintConfig from '@dauphaihau/eslint-config'
|
|
16
|
+
* export default eslintConfig({ typescript: true })
|
|
16
17
|
* ```
|
|
17
18
|
*/
|
|
18
|
-
declare function
|
|
19
|
+
declare function eslintConfig(options?: Options): Promise<Config[]>;
|
|
19
20
|
|
|
20
|
-
export { type Options,
|
|
21
|
+
export { type Options, eslintConfig as default };
|
package/dist/index.js
CHANGED
|
@@ -109,6 +109,27 @@ var ComponentFilesStrategy = class {
|
|
|
109
109
|
return true;
|
|
110
110
|
}
|
|
111
111
|
};
|
|
112
|
+
var TailwindStrategy = class {
|
|
113
|
+
getName() {
|
|
114
|
+
return "tailwind";
|
|
115
|
+
}
|
|
116
|
+
getFilePatterns(options) {
|
|
117
|
+
const patterns = ["**/*.html"];
|
|
118
|
+
if (options.react) {
|
|
119
|
+
patterns.push(options.typescript ? "**/*.{jsx,tsx}" : "**/*.jsx");
|
|
120
|
+
}
|
|
121
|
+
if (options.vue) {
|
|
122
|
+
patterns.push("**/*.vue");
|
|
123
|
+
}
|
|
124
|
+
if (!options.react && !options.vue) {
|
|
125
|
+
patterns.push(options.typescript ? "**/*.{jsx,tsx}" : "**/*.jsx");
|
|
126
|
+
}
|
|
127
|
+
return patterns;
|
|
128
|
+
}
|
|
129
|
+
shouldApply(options) {
|
|
130
|
+
return options.tailwind === true;
|
|
131
|
+
}
|
|
132
|
+
};
|
|
112
133
|
|
|
113
134
|
// src/strategies/strategy-manager.ts
|
|
114
135
|
var StrategyManager = class {
|
|
@@ -122,6 +143,7 @@ var StrategyManager = class {
|
|
|
122
143
|
this.register(new AllFilesStrategy());
|
|
123
144
|
this.register(new SourceFilesStrategy());
|
|
124
145
|
this.register(new ComponentFilesStrategy());
|
|
146
|
+
this.register(new TailwindStrategy());
|
|
125
147
|
}
|
|
126
148
|
/**
|
|
127
149
|
* Register a new strategy.
|
|
@@ -195,6 +217,12 @@ var StrategyManager = class {
|
|
|
195
217
|
getTestFiles(options) {
|
|
196
218
|
return this.getFilePatterns("test", options);
|
|
197
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Convenience method: Get Tailwind CSS file patterns.
|
|
222
|
+
*/
|
|
223
|
+
getTailwindFiles(options) {
|
|
224
|
+
return this.getFilePatterns("tailwind", options);
|
|
225
|
+
}
|
|
198
226
|
};
|
|
199
227
|
var strategyManager = new StrategyManager();
|
|
200
228
|
|
|
@@ -264,7 +292,14 @@ function baseConfig(options = {}) {
|
|
|
264
292
|
// Operators
|
|
265
293
|
"@stylistic/multiline-ternary": ["error", "always-multiline"],
|
|
266
294
|
"@stylistic/no-mixed-operators": "error",
|
|
267
|
-
"@stylistic/operator-linebreak": ["error", "after"
|
|
295
|
+
"@stylistic/operator-linebreak": ["error", "after", {
|
|
296
|
+
overrides: {
|
|
297
|
+
"?": "before",
|
|
298
|
+
"|": "before",
|
|
299
|
+
":": "before",
|
|
300
|
+
"||": "before"
|
|
301
|
+
}
|
|
302
|
+
}],
|
|
268
303
|
"@stylistic/dot-location": ["error", "property"],
|
|
269
304
|
// Disallow
|
|
270
305
|
"@stylistic/no-multiple-empty-lines": ["error", { max: 2, maxEOF: 0 }],
|
|
@@ -515,8 +550,150 @@ async function reactConfig(options = {}) {
|
|
|
515
550
|
];
|
|
516
551
|
}
|
|
517
552
|
|
|
553
|
+
// src/configs/tailwind.ts
|
|
554
|
+
async function tailwindConfig(options = {}) {
|
|
555
|
+
const tailwindFiles = strategyManager.getTailwindFiles(options);
|
|
556
|
+
if (tailwindFiles.length === 0) {
|
|
557
|
+
return [];
|
|
558
|
+
}
|
|
559
|
+
const { default: tailwind } = await import("eslint-plugin-tailwindcss");
|
|
560
|
+
return [
|
|
561
|
+
{
|
|
562
|
+
name: "dauphaihau/tailwind",
|
|
563
|
+
files: tailwindFiles,
|
|
564
|
+
plugins: { tailwindcss: tailwind },
|
|
565
|
+
settings: {
|
|
566
|
+
tailwindcss: {
|
|
567
|
+
// Common utility function callees to analyze for class names
|
|
568
|
+
callees: ["classnames", "clsx", "ctl", "cva", "cx", "cn"],
|
|
569
|
+
// Support tagged template literals: tw`bg-blue-500`
|
|
570
|
+
tags: ["tw"]
|
|
571
|
+
}
|
|
572
|
+
},
|
|
573
|
+
rules: {
|
|
574
|
+
"tailwindcss/classnames-order": "warn",
|
|
575
|
+
"tailwindcss/enforces-negative-arbitrary-values": "warn",
|
|
576
|
+
"tailwindcss/enforces-shorthand": "warn",
|
|
577
|
+
"tailwindcss/migration-from-tailwind-2": "off",
|
|
578
|
+
// projects target v3+
|
|
579
|
+
"tailwindcss/no-arbitrary-value": "off",
|
|
580
|
+
// too restrictive globally; colors enforced below via no-restricted-syntax
|
|
581
|
+
"tailwindcss/no-contradicting-classname": "error",
|
|
582
|
+
"tailwindcss/no-custom-classname": "warn",
|
|
583
|
+
"tailwindcss/no-unnecessary-arbitrary-value": "warn",
|
|
584
|
+
// Partial enforcement of no-arbitrary-value scoped to color utilities.
|
|
585
|
+
// Arbitrary color values (bg-[#fff], text-[rgba(...)]) bypass the design
|
|
586
|
+
// system and should use config tokens instead. Covers: bg, text, border,
|
|
587
|
+
// ring, fill, stroke, from, via, to, accent, caret, decoration, outline,
|
|
588
|
+
// placeholder, shadow, divide — for hex, rgb(), rgba(), hsl(), hsla(), oklch().
|
|
589
|
+
"no-restricted-syntax": [
|
|
590
|
+
"warn",
|
|
591
|
+
{
|
|
592
|
+
selector: "Literal[value=/(?:^|\\s)(?:bg|text|border|ring|fill|stroke|from|via|to|accent|caret|decoration|outline|placeholder|shadow|divide)-\\[(?:#[0-9a-fA-F]|rgba?\\(|hsla?\\(|oklch\\()/]",
|
|
593
|
+
message: "Avoid arbitrary color values (e.g. bg-[#fff]). Use a design system color token from the Tailwind config instead."
|
|
594
|
+
}
|
|
595
|
+
]
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
];
|
|
599
|
+
}
|
|
600
|
+
|
|
518
601
|
// src/configs/naming.ts
|
|
519
602
|
import ts2 from "typescript-eslint";
|
|
603
|
+
var identifierQualityRules = {
|
|
604
|
+
// Invalid example: const n = 'Name User'
|
|
605
|
+
"id-length": [
|
|
606
|
+
"warn",
|
|
607
|
+
{
|
|
608
|
+
min: 2,
|
|
609
|
+
exceptions: ["i", "j", "x", "y"]
|
|
610
|
+
}
|
|
611
|
+
],
|
|
612
|
+
// Discourage vague placeholder names.
|
|
613
|
+
// Prefer domain-specific names such as users, payload, responseBody, or config.
|
|
614
|
+
"id-denylist": ["warn", "foo", "bar", "baz", "tmp", "arr", "obj", "data"]
|
|
615
|
+
};
|
|
616
|
+
var variableNamingSelectors = [
|
|
617
|
+
// ---------- Boolean naming ----------
|
|
618
|
+
{
|
|
619
|
+
selector: "variable",
|
|
620
|
+
types: ["boolean"],
|
|
621
|
+
format: ["PascalCase", "camelCase"],
|
|
622
|
+
prefix: ["is", "has", "should", "can", "did", "will"],
|
|
623
|
+
filter: { regex: "^(is|has|should|can|did|will)[A-Z]", match: true }
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
// Valid examples: apiBaseUrl, DEFAULT_TIMEOUT_MS, _internalValue
|
|
627
|
+
selector: "variable",
|
|
628
|
+
modifiers: ["const"],
|
|
629
|
+
format: ["camelCase", "UPPER_CASE"],
|
|
630
|
+
leadingUnderscore: "allow"
|
|
631
|
+
},
|
|
632
|
+
// Valid examples: userName, fetchUsers, _internalValue
|
|
633
|
+
{
|
|
634
|
+
selector: ["variable", "function"],
|
|
635
|
+
format: ["camelCase"],
|
|
636
|
+
leadingUnderscore: "allow"
|
|
637
|
+
// allows _privateVar
|
|
638
|
+
}
|
|
639
|
+
];
|
|
640
|
+
var baseNamingSelectors = [
|
|
641
|
+
...variableNamingSelectors,
|
|
642
|
+
// ---------- Interfaces ----------
|
|
643
|
+
{
|
|
644
|
+
selector: "interface",
|
|
645
|
+
format: ["PascalCase"],
|
|
646
|
+
custom: { regex: "^I[A-Z]", match: false }
|
|
647
|
+
// forbid I prefix
|
|
648
|
+
},
|
|
649
|
+
// ---------- Type Aliases ----------
|
|
650
|
+
{
|
|
651
|
+
selector: "typeAlias",
|
|
652
|
+
format: ["PascalCase"]
|
|
653
|
+
// User, UserPayload
|
|
654
|
+
},
|
|
655
|
+
// ---------- Classes ----------
|
|
656
|
+
{
|
|
657
|
+
selector: "class",
|
|
658
|
+
format: ["PascalCase"]
|
|
659
|
+
},
|
|
660
|
+
// ---------- Enums ----------
|
|
661
|
+
{
|
|
662
|
+
selector: "enum",
|
|
663
|
+
format: ["PascalCase"]
|
|
664
|
+
},
|
|
665
|
+
{
|
|
666
|
+
selector: "enumMember",
|
|
667
|
+
format: ["UPPER_CASE"]
|
|
668
|
+
// STATUS.OK
|
|
669
|
+
},
|
|
670
|
+
// ---------- Parameters ----------
|
|
671
|
+
{
|
|
672
|
+
selector: "parameter",
|
|
673
|
+
format: ["camelCase"],
|
|
674
|
+
leadingUnderscore: "allow"
|
|
675
|
+
// allow _unused
|
|
676
|
+
},
|
|
677
|
+
// ---------- Properties (object keys) ----------
|
|
678
|
+
{
|
|
679
|
+
selector: "objectLiteralProperty",
|
|
680
|
+
format: null
|
|
681
|
+
// allow anything -> API response, snake_case keys allowed
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
// internal domain types
|
|
685
|
+
selector: "typeProperty",
|
|
686
|
+
format: ["camelCase"]
|
|
687
|
+
},
|
|
688
|
+
// ---------- Private members ----------
|
|
689
|
+
{
|
|
690
|
+
selector: "classProperty",
|
|
691
|
+
modifiers: ["private"],
|
|
692
|
+
format: ["camelCase"],
|
|
693
|
+
leadingUnderscore: "allow"
|
|
694
|
+
// _value
|
|
695
|
+
}
|
|
696
|
+
];
|
|
520
697
|
function namingConfig(options = {}) {
|
|
521
698
|
const { typescript = false } = options;
|
|
522
699
|
if (!typescript) {
|
|
@@ -537,93 +714,11 @@ function namingConfig(options = {}) {
|
|
|
537
714
|
"@typescript-eslint": ts2.plugin
|
|
538
715
|
},
|
|
539
716
|
rules: {
|
|
540
|
-
|
|
541
|
-
"@typescript-eslint/naming-convention": [
|
|
542
|
-
"error",
|
|
543
|
-
// ---------- Variable, Function ----------
|
|
544
|
-
{
|
|
545
|
-
selector: ["variable", "function"],
|
|
546
|
-
format: ["camelCase"],
|
|
547
|
-
leadingUnderscore: "allow"
|
|
548
|
-
// allows _privateVar
|
|
549
|
-
},
|
|
550
|
-
{
|
|
551
|
-
selector: "variable",
|
|
552
|
-
// constants (like env, config)
|
|
553
|
-
modifiers: ["const"],
|
|
554
|
-
format: ["UPPER_CASE"],
|
|
555
|
-
filter: {
|
|
556
|
-
regex: "^[A-Z0-9_]+$",
|
|
557
|
-
match: true
|
|
558
|
-
}
|
|
559
|
-
},
|
|
560
|
-
// ---------- Interfaces ----------
|
|
561
|
-
{
|
|
562
|
-
selector: "interface",
|
|
563
|
-
format: ["PascalCase"],
|
|
564
|
-
custom: { regex: "^I[A-Z]", match: false }
|
|
565
|
-
// forbid I prefix
|
|
566
|
-
},
|
|
567
|
-
// ---------- Type Aliases ----------
|
|
568
|
-
{
|
|
569
|
-
selector: "typeAlias",
|
|
570
|
-
format: ["PascalCase"]
|
|
571
|
-
// User, UserPayload
|
|
572
|
-
},
|
|
573
|
-
// ---------- Classes ----------
|
|
574
|
-
{
|
|
575
|
-
selector: "class",
|
|
576
|
-
format: ["PascalCase"]
|
|
577
|
-
},
|
|
578
|
-
// ---------- Enums ----------
|
|
579
|
-
{
|
|
580
|
-
selector: "enum",
|
|
581
|
-
format: ["PascalCase"]
|
|
582
|
-
},
|
|
583
|
-
{
|
|
584
|
-
selector: "enumMember",
|
|
585
|
-
format: ["UPPER_CASE"]
|
|
586
|
-
// STATUS.OK
|
|
587
|
-
},
|
|
588
|
-
// ---------- Parameters ----------
|
|
589
|
-
{
|
|
590
|
-
selector: "parameter",
|
|
591
|
-
format: ["camelCase"],
|
|
592
|
-
leadingUnderscore: "allow"
|
|
593
|
-
// allow _unused
|
|
594
|
-
},
|
|
595
|
-
// ---------- Properties (object keys) ----------
|
|
596
|
-
{
|
|
597
|
-
selector: "objectLiteralProperty",
|
|
598
|
-
format: null
|
|
599
|
-
// allow anything -> API response, snake_case keys allowed
|
|
600
|
-
},
|
|
601
|
-
{
|
|
602
|
-
// internal domain types
|
|
603
|
-
selector: "typeProperty",
|
|
604
|
-
format: ["camelCase"]
|
|
605
|
-
},
|
|
606
|
-
// ---------- Private members ----------
|
|
607
|
-
{
|
|
608
|
-
selector: "classProperty",
|
|
609
|
-
modifiers: ["private"],
|
|
610
|
-
format: ["camelCase"],
|
|
611
|
-
leadingUnderscore: "allow"
|
|
612
|
-
// _value
|
|
613
|
-
},
|
|
614
|
-
// ---------- Boolean naming ----------
|
|
615
|
-
{
|
|
616
|
-
selector: "variable",
|
|
617
|
-
types: ["boolean"],
|
|
618
|
-
format: ["PascalCase", "camelCase"],
|
|
619
|
-
prefix: ["is", "has", "should", "can", "did", "will"],
|
|
620
|
-
filter: { regex: "^(is|has|should|can|did|will)[A-Z]", match: true }
|
|
621
|
-
}
|
|
622
|
-
]
|
|
717
|
+
...identifierQualityRules,
|
|
718
|
+
"@typescript-eslint/naming-convention": ["error", ...baseNamingSelectors]
|
|
623
719
|
}
|
|
624
720
|
},
|
|
625
|
-
// TSX/JSX specific: Allow PascalCase for functions (React components)
|
|
626
|
-
// Helper functions will still be camelCase due to the general rule above
|
|
721
|
+
// TSX/JSX specific: Allow PascalCase for functions (React components) and component variables
|
|
627
722
|
{
|
|
628
723
|
name: "dauphaihau/naming-tsx",
|
|
629
724
|
files: componentFiles,
|
|
@@ -634,23 +729,23 @@ function namingConfig(options = {}) {
|
|
|
634
729
|
"@typescript-eslint": ts2.plugin
|
|
635
730
|
},
|
|
636
731
|
rules: {
|
|
732
|
+
...identifierQualityRules,
|
|
637
733
|
"@typescript-eslint/naming-convention": [
|
|
638
734
|
"error",
|
|
735
|
+
// TSX overrides come first — same-specificity selectors use first-match wins
|
|
639
736
|
{
|
|
640
737
|
selector: "function",
|
|
641
738
|
format: ["PascalCase", "camelCase"]
|
|
642
|
-
// Allow both for components and helpers
|
|
643
739
|
},
|
|
644
740
|
{
|
|
645
741
|
selector: "variable",
|
|
646
742
|
format: ["camelCase", "PascalCase"],
|
|
647
|
-
// Allow PascalCase for component variables
|
|
648
743
|
filter: {
|
|
649
|
-
|
|
650
|
-
regex: "^[A-Z]",
|
|
744
|
+
regex: "^[A-Z][a-zA-Z0-9]*$",
|
|
651
745
|
match: true
|
|
652
746
|
}
|
|
653
|
-
}
|
|
747
|
+
},
|
|
748
|
+
...baseNamingSelectors
|
|
654
749
|
]
|
|
655
750
|
}
|
|
656
751
|
}
|
|
@@ -708,6 +803,7 @@ var ESLintConfigBuilder = class {
|
|
|
708
803
|
this.fileNamesAdded = false;
|
|
709
804
|
this.typescriptAdded = false;
|
|
710
805
|
this.reactAdded = false;
|
|
806
|
+
this.tailwindAdded = false;
|
|
711
807
|
}
|
|
712
808
|
/**
|
|
713
809
|
* Set options that will be used for all subsequent config additions.
|
|
@@ -787,6 +883,21 @@ var ESLintConfigBuilder = class {
|
|
|
787
883
|
this.reactAdded = true;
|
|
788
884
|
return this;
|
|
789
885
|
}
|
|
886
|
+
/**
|
|
887
|
+
* Add Tailwind CSS-specific rules and plugins.
|
|
888
|
+
* Requires tailwind option to be set to true.
|
|
889
|
+
*/
|
|
890
|
+
withTailwind(options) {
|
|
891
|
+
const mergedOptions = { ...this.options, ...options };
|
|
892
|
+
if (!mergedOptions.tailwind) {
|
|
893
|
+
console.warn(
|
|
894
|
+
"ESLintConfigBuilder: Tailwind config added but tailwind option is not set. Consider calling setOptions({ tailwind: true }) first."
|
|
895
|
+
);
|
|
896
|
+
}
|
|
897
|
+
this.pendingConfigs.push(tailwindConfig(mergedOptions));
|
|
898
|
+
this.tailwindAdded = true;
|
|
899
|
+
return this;
|
|
900
|
+
}
|
|
790
901
|
/**
|
|
791
902
|
* Add a custom config object directly.
|
|
792
903
|
* Useful for adding project-specific rules or third-party configs.
|
|
@@ -816,6 +927,9 @@ var ESLintConfigBuilder = class {
|
|
|
816
927
|
if (mergedOptions.react) {
|
|
817
928
|
this.withReact(mergedOptions);
|
|
818
929
|
}
|
|
930
|
+
if (mergedOptions.tailwind) {
|
|
931
|
+
this.withTailwind(mergedOptions);
|
|
932
|
+
}
|
|
819
933
|
return this;
|
|
820
934
|
}
|
|
821
935
|
/**
|
|
@@ -839,6 +953,7 @@ var ESLintConfigBuilder = class {
|
|
|
839
953
|
this.fileNamesAdded = false;
|
|
840
954
|
this.typescriptAdded = false;
|
|
841
955
|
this.reactAdded = false;
|
|
956
|
+
this.tailwindAdded = false;
|
|
842
957
|
return this;
|
|
843
958
|
}
|
|
844
959
|
/**
|
|
@@ -868,6 +983,9 @@ var ESLintConfigBuilder = class {
|
|
|
868
983
|
hasReact() {
|
|
869
984
|
return this.reactAdded;
|
|
870
985
|
}
|
|
986
|
+
hasTailwind() {
|
|
987
|
+
return this.tailwindAdded;
|
|
988
|
+
}
|
|
871
989
|
};
|
|
872
990
|
|
|
873
991
|
// src/index.ts
|
|
@@ -889,14 +1007,31 @@ var hasReact = () => {
|
|
|
889
1007
|
}
|
|
890
1008
|
return false;
|
|
891
1009
|
};
|
|
892
|
-
|
|
1010
|
+
var hasTailwind = () => {
|
|
1011
|
+
try {
|
|
1012
|
+
const packageJsonPath = "package.json";
|
|
1013
|
+
if (fs2.existsSync(packageJsonPath)) {
|
|
1014
|
+
const packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf-8"));
|
|
1015
|
+
const deps = {
|
|
1016
|
+
...packageJson.dependencies,
|
|
1017
|
+
...packageJson.devDependencies,
|
|
1018
|
+
...packageJson.peerDependencies
|
|
1019
|
+
};
|
|
1020
|
+
if ("tailwindcss" in deps) return true;
|
|
1021
|
+
}
|
|
1022
|
+
} catch {
|
|
1023
|
+
}
|
|
1024
|
+
return fs2.existsSync("tailwind.config.js") || fs2.existsSync("tailwind.config.ts") || fs2.existsSync("tailwind.config.mjs") || fs2.existsSync("tailwind.config.cjs");
|
|
1025
|
+
};
|
|
1026
|
+
function eslintConfig(options = {}) {
|
|
893
1027
|
const finalOptions = {
|
|
894
1028
|
typescript: options.typescript ?? hasTsConfig,
|
|
895
1029
|
react: options.react ?? hasReact(),
|
|
1030
|
+
tailwind: options.tailwind ?? hasTailwind(),
|
|
896
1031
|
...options
|
|
897
1032
|
};
|
|
898
1033
|
return new ESLintConfigBuilder().setOptions(finalOptions).withAll().build();
|
|
899
1034
|
}
|
|
900
1035
|
export {
|
|
901
|
-
|
|
1036
|
+
eslintConfig as default
|
|
902
1037
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dauphaihau/eslint-config",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"typescript-eslint": "^8.56.1"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
|
-
"eslint": "^9.0.0 || ^10.0.0"
|
|
22
|
+
"eslint": "^9.0.0 || ^10.0.0",
|
|
23
|
+
"eslint-plugin-tailwindcss": ">=3.0.0"
|
|
23
24
|
},
|
|
24
25
|
"peerDependenciesMeta": {
|
|
25
26
|
"eslint-plugin-react": {
|
|
@@ -30,6 +31,9 @@
|
|
|
30
31
|
},
|
|
31
32
|
"eslint-plugin-react-refresh": {
|
|
32
33
|
"optional": true
|
|
34
|
+
},
|
|
35
|
+
"eslint-plugin-tailwindcss": {
|
|
36
|
+
"optional": true
|
|
33
37
|
}
|
|
34
38
|
},
|
|
35
39
|
"devDependencies": {
|
|
@@ -38,17 +42,22 @@
|
|
|
38
42
|
"eslint-plugin-react": "^7.37.5",
|
|
39
43
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
40
44
|
"eslint-plugin-react-refresh": "^0.5.2",
|
|
45
|
+
"eslint-plugin-tailwindcss": "^3.18.2",
|
|
41
46
|
"jiti": "^2.0.0",
|
|
42
47
|
"tsup": "^8.0.0",
|
|
43
|
-
"typescript": "^5.4.0"
|
|
48
|
+
"typescript": "^5.4.0",
|
|
49
|
+
"vitest": "^3.2.4"
|
|
44
50
|
},
|
|
45
51
|
"scripts": {
|
|
46
|
-
"build": "pnpm exec tsup src/index.ts --dts --format esm --external @eslint/js --external @stylistic/eslint-plugin --external typescript-eslint --external eslint-plugin-check-file --external eslint-plugin-react --external eslint-plugin-react-hooks --external eslint-plugin-react-refresh",
|
|
52
|
+
"build": "pnpm exec tsup src/index.ts --dts --format esm --external @eslint/js --external @stylistic/eslint-plugin --external typescript-eslint --external eslint-plugin-check-file --external eslint-plugin-react --external eslint-plugin-react-hooks --external eslint-plugin-react-refresh --external eslint-plugin-tailwindcss",
|
|
47
53
|
"lint": "eslint .",
|
|
48
54
|
"lint:fix": "eslint . --fix",
|
|
55
|
+
"test": "vitest run",
|
|
49
56
|
"typecheck": "tsc --noEmit",
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
57
|
+
"version:patch": "pnpm build && pnpm version patch",
|
|
58
|
+
"version:minor": "pnpm build && pnpm version minor",
|
|
59
|
+
"version:major": "pnpm build && pnpm version major",
|
|
60
|
+
"push:tags": "git push --follow-tags",
|
|
61
|
+
"ship": "pnpm publish --no-git-checks"
|
|
53
62
|
}
|
|
54
63
|
}
|