@dauphaihau/eslint-config 0.1.5 → 0.2.1
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.d.ts +5 -4
- package/dist/index.js +259 -110
- package/package.json +20 -14
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
|
|
|
@@ -216,7 +244,7 @@ function baseConfig(options = {}) {
|
|
|
216
244
|
plugins: { "@stylistic": stylistic },
|
|
217
245
|
rules: {
|
|
218
246
|
// Spacing
|
|
219
|
-
"@stylistic/
|
|
247
|
+
"@stylistic/function-call-spacing": "error",
|
|
220
248
|
"@stylistic/space-before-function-paren": ["error", {
|
|
221
249
|
anonymous: "always",
|
|
222
250
|
named: "never",
|
|
@@ -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 }],
|
|
@@ -423,6 +458,17 @@ function typescriptConfig(options = {}) {
|
|
|
423
458
|
}
|
|
424
459
|
|
|
425
460
|
// src/configs/react.ts
|
|
461
|
+
import fs from "fs";
|
|
462
|
+
function getReactVersion() {
|
|
463
|
+
try {
|
|
464
|
+
const pkg = JSON.parse(fs.readFileSync("package.json", "utf-8"));
|
|
465
|
+
const dep = pkg.dependencies?.react || pkg.devDependencies?.react || pkg.peerDependencies?.react;
|
|
466
|
+
const match = dep?.match(/\d+/);
|
|
467
|
+
if (match) return `${match[0]}.0`;
|
|
468
|
+
} catch {
|
|
469
|
+
}
|
|
470
|
+
return "18.0";
|
|
471
|
+
}
|
|
426
472
|
async function reactConfig(options = {}) {
|
|
427
473
|
const reactFiles = strategyManager.getReactFiles(options);
|
|
428
474
|
if (reactFiles.length === 0) {
|
|
@@ -461,8 +507,7 @@ async function reactConfig(options = {}) {
|
|
|
461
507
|
},
|
|
462
508
|
settings: {
|
|
463
509
|
react: {
|
|
464
|
-
version:
|
|
465
|
-
// Automatically detect React version
|
|
510
|
+
version: getReactVersion()
|
|
466
511
|
}
|
|
467
512
|
},
|
|
468
513
|
rules: {
|
|
@@ -505,8 +550,154 @@ async function reactConfig(options = {}) {
|
|
|
505
550
|
];
|
|
506
551
|
}
|
|
507
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
|
+
|
|
508
601
|
// src/configs/naming.ts
|
|
509
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
|
+
// Valid examples: userName, fetchUsers, _internalValue
|
|
618
|
+
{
|
|
619
|
+
selector: ["variable", "function"],
|
|
620
|
+
format: ["camelCase"],
|
|
621
|
+
leadingUnderscore: "allow"
|
|
622
|
+
// allows _privateVar
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
// Enforce UPPER_CASE for exported constants.
|
|
626
|
+
// Valid examples: API_BASE_URL, MAX_RETRY_COUNT, DEFAULT_TIMEOUT_MS
|
|
627
|
+
selector: "variable",
|
|
628
|
+
modifiers: ["const", "exported"],
|
|
629
|
+
format: ["UPPER_CASE"],
|
|
630
|
+
filter: {
|
|
631
|
+
regex: "^[A-Z0-9_]+$",
|
|
632
|
+
match: true
|
|
633
|
+
}
|
|
634
|
+
},
|
|
635
|
+
// ---------- Boolean naming ----------
|
|
636
|
+
{
|
|
637
|
+
selector: "variable",
|
|
638
|
+
types: ["boolean"],
|
|
639
|
+
format: ["PascalCase", "camelCase"],
|
|
640
|
+
prefix: ["is", "has", "should", "can", "did", "will"],
|
|
641
|
+
filter: { regex: "^(is|has|should|can|did|will)[A-Z]", match: true }
|
|
642
|
+
}
|
|
643
|
+
];
|
|
644
|
+
var baseNamingSelectors = [
|
|
645
|
+
...variableNamingSelectors,
|
|
646
|
+
// ---------- Interfaces ----------
|
|
647
|
+
{
|
|
648
|
+
selector: "interface",
|
|
649
|
+
format: ["PascalCase"],
|
|
650
|
+
custom: { regex: "^I[A-Z]", match: false }
|
|
651
|
+
// forbid I prefix
|
|
652
|
+
},
|
|
653
|
+
// ---------- Type Aliases ----------
|
|
654
|
+
{
|
|
655
|
+
selector: "typeAlias",
|
|
656
|
+
format: ["PascalCase"]
|
|
657
|
+
// User, UserPayload
|
|
658
|
+
},
|
|
659
|
+
// ---------- Classes ----------
|
|
660
|
+
{
|
|
661
|
+
selector: "class",
|
|
662
|
+
format: ["PascalCase"]
|
|
663
|
+
},
|
|
664
|
+
// ---------- Enums ----------
|
|
665
|
+
{
|
|
666
|
+
selector: "enum",
|
|
667
|
+
format: ["PascalCase"]
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
selector: "enumMember",
|
|
671
|
+
format: ["UPPER_CASE"]
|
|
672
|
+
// STATUS.OK
|
|
673
|
+
},
|
|
674
|
+
// ---------- Parameters ----------
|
|
675
|
+
{
|
|
676
|
+
selector: "parameter",
|
|
677
|
+
format: ["camelCase"],
|
|
678
|
+
leadingUnderscore: "allow"
|
|
679
|
+
// allow _unused
|
|
680
|
+
},
|
|
681
|
+
// ---------- Properties (object keys) ----------
|
|
682
|
+
{
|
|
683
|
+
selector: "objectLiteralProperty",
|
|
684
|
+
format: null
|
|
685
|
+
// allow anything -> API response, snake_case keys allowed
|
|
686
|
+
},
|
|
687
|
+
{
|
|
688
|
+
// internal domain types
|
|
689
|
+
selector: "typeProperty",
|
|
690
|
+
format: ["camelCase"]
|
|
691
|
+
},
|
|
692
|
+
// ---------- Private members ----------
|
|
693
|
+
{
|
|
694
|
+
selector: "classProperty",
|
|
695
|
+
modifiers: ["private"],
|
|
696
|
+
format: ["camelCase"],
|
|
697
|
+
leadingUnderscore: "allow"
|
|
698
|
+
// _value
|
|
699
|
+
}
|
|
700
|
+
];
|
|
510
701
|
function namingConfig(options = {}) {
|
|
511
702
|
const { typescript = false } = options;
|
|
512
703
|
if (!typescript) {
|
|
@@ -527,93 +718,11 @@ function namingConfig(options = {}) {
|
|
|
527
718
|
"@typescript-eslint": ts2.plugin
|
|
528
719
|
},
|
|
529
720
|
rules: {
|
|
530
|
-
|
|
531
|
-
"@typescript-eslint/naming-convention": [
|
|
532
|
-
"error",
|
|
533
|
-
// ---------- Variable, Function ----------
|
|
534
|
-
{
|
|
535
|
-
selector: ["variable", "function"],
|
|
536
|
-
format: ["camelCase"],
|
|
537
|
-
leadingUnderscore: "allow"
|
|
538
|
-
// allows _privateVar
|
|
539
|
-
},
|
|
540
|
-
{
|
|
541
|
-
selector: "variable",
|
|
542
|
-
// constants (like env, config)
|
|
543
|
-
modifiers: ["const"],
|
|
544
|
-
format: ["UPPER_CASE"],
|
|
545
|
-
filter: {
|
|
546
|
-
regex: "^[A-Z0-9_]+$",
|
|
547
|
-
match: true
|
|
548
|
-
}
|
|
549
|
-
},
|
|
550
|
-
// ---------- Interfaces ----------
|
|
551
|
-
{
|
|
552
|
-
selector: "interface",
|
|
553
|
-
format: ["PascalCase"],
|
|
554
|
-
custom: { regex: "^I[A-Z]", match: false }
|
|
555
|
-
// forbid I prefix
|
|
556
|
-
},
|
|
557
|
-
// ---------- Type Aliases ----------
|
|
558
|
-
{
|
|
559
|
-
selector: "typeAlias",
|
|
560
|
-
format: ["PascalCase"]
|
|
561
|
-
// User, UserPayload
|
|
562
|
-
},
|
|
563
|
-
// ---------- Classes ----------
|
|
564
|
-
{
|
|
565
|
-
selector: "class",
|
|
566
|
-
format: ["PascalCase"]
|
|
567
|
-
},
|
|
568
|
-
// ---------- Enums ----------
|
|
569
|
-
{
|
|
570
|
-
selector: "enum",
|
|
571
|
-
format: ["PascalCase"]
|
|
572
|
-
},
|
|
573
|
-
{
|
|
574
|
-
selector: "enumMember",
|
|
575
|
-
format: ["UPPER_CASE"]
|
|
576
|
-
// STATUS.OK
|
|
577
|
-
},
|
|
578
|
-
// ---------- Parameters ----------
|
|
579
|
-
{
|
|
580
|
-
selector: "parameter",
|
|
581
|
-
format: ["camelCase"],
|
|
582
|
-
leadingUnderscore: "allow"
|
|
583
|
-
// allow _unused
|
|
584
|
-
},
|
|
585
|
-
// ---------- Properties (object keys) ----------
|
|
586
|
-
{
|
|
587
|
-
selector: "objectLiteralProperty",
|
|
588
|
-
format: null
|
|
589
|
-
// allow anything -> API response, snake_case keys allowed
|
|
590
|
-
},
|
|
591
|
-
{
|
|
592
|
-
// internal domain types
|
|
593
|
-
selector: "typeProperty",
|
|
594
|
-
format: ["camelCase"]
|
|
595
|
-
},
|
|
596
|
-
// ---------- Private members ----------
|
|
597
|
-
{
|
|
598
|
-
selector: "classProperty",
|
|
599
|
-
modifiers: ["private"],
|
|
600
|
-
format: ["camelCase"],
|
|
601
|
-
leadingUnderscore: "allow"
|
|
602
|
-
// _value
|
|
603
|
-
},
|
|
604
|
-
// ---------- Boolean naming ----------
|
|
605
|
-
{
|
|
606
|
-
selector: "variable",
|
|
607
|
-
types: ["boolean"],
|
|
608
|
-
format: ["PascalCase", "camelCase"],
|
|
609
|
-
prefix: ["is", "has", "should", "can", "did", "will"],
|
|
610
|
-
filter: { regex: "^(is|has|should|can|did|will)[A-Z]", match: true }
|
|
611
|
-
}
|
|
612
|
-
]
|
|
721
|
+
...identifierQualityRules,
|
|
722
|
+
"@typescript-eslint/naming-convention": ["error", ...baseNamingSelectors]
|
|
613
723
|
}
|
|
614
724
|
},
|
|
615
|
-
// TSX/JSX specific: Allow PascalCase for functions (React components)
|
|
616
|
-
// Helper functions will still be camelCase due to the general rule above
|
|
725
|
+
// TSX/JSX specific: Allow PascalCase for functions (React components) and component variables
|
|
617
726
|
{
|
|
618
727
|
name: "dauphaihau/naming-tsx",
|
|
619
728
|
files: componentFiles,
|
|
@@ -624,23 +733,23 @@ function namingConfig(options = {}) {
|
|
|
624
733
|
"@typescript-eslint": ts2.plugin
|
|
625
734
|
},
|
|
626
735
|
rules: {
|
|
736
|
+
...identifierQualityRules,
|
|
627
737
|
"@typescript-eslint/naming-convention": [
|
|
628
738
|
"error",
|
|
739
|
+
// TSX overrides come first — same-specificity selectors use first-match wins
|
|
629
740
|
{
|
|
630
741
|
selector: "function",
|
|
631
742
|
format: ["PascalCase", "camelCase"]
|
|
632
|
-
// Allow both for components and helpers
|
|
633
743
|
},
|
|
634
744
|
{
|
|
635
745
|
selector: "variable",
|
|
636
746
|
format: ["camelCase", "PascalCase"],
|
|
637
|
-
// Allow PascalCase for component variables
|
|
638
747
|
filter: {
|
|
639
|
-
// Only allow PascalCase if it's likely a component (starts with uppercase)
|
|
640
748
|
regex: "^[A-Z]",
|
|
641
749
|
match: true
|
|
642
750
|
}
|
|
643
|
-
}
|
|
751
|
+
},
|
|
752
|
+
...baseNamingSelectors
|
|
644
753
|
]
|
|
645
754
|
}
|
|
646
755
|
}
|
|
@@ -648,7 +757,7 @@ function namingConfig(options = {}) {
|
|
|
648
757
|
}
|
|
649
758
|
|
|
650
759
|
// src/configs/file-names.ts
|
|
651
|
-
import
|
|
760
|
+
import checkFile from "eslint-plugin-check-file";
|
|
652
761
|
function fileNamesConfig(options = {}) {
|
|
653
762
|
const allFiles = strategyManager.getSourceFiles(options);
|
|
654
763
|
const tsxFiles = strategyManager.getComponentFiles(options);
|
|
@@ -657,15 +766,15 @@ function fileNamesConfig(options = {}) {
|
|
|
657
766
|
name: "dauphaihau/file-names",
|
|
658
767
|
files: allFiles,
|
|
659
768
|
plugins: {
|
|
660
|
-
"
|
|
769
|
+
"check-file": checkFile
|
|
661
770
|
},
|
|
662
771
|
rules: {
|
|
663
772
|
// Enforce kebab-case for regular files
|
|
664
|
-
"
|
|
773
|
+
"check-file/filename-naming-convention": [
|
|
665
774
|
"error",
|
|
666
|
-
{
|
|
667
|
-
|
|
668
|
-
|
|
775
|
+
{ "**/*": "KEBAB_CASE" },
|
|
776
|
+
{ ignoreMiddleExtensions: true }
|
|
777
|
+
]
|
|
669
778
|
}
|
|
670
779
|
},
|
|
671
780
|
// TSX/JSX files: Allow PascalCase for React components (e.g., MyComponent.tsx)
|
|
@@ -673,14 +782,14 @@ function fileNamesConfig(options = {}) {
|
|
|
673
782
|
name: "dauphaihau/file-names-tsx",
|
|
674
783
|
files: tsxFiles,
|
|
675
784
|
plugins: {
|
|
676
|
-
"
|
|
785
|
+
"check-file": checkFile
|
|
677
786
|
},
|
|
678
787
|
rules: {
|
|
679
|
-
"
|
|
788
|
+
"check-file/filename-naming-convention": [
|
|
680
789
|
"error",
|
|
681
|
-
{
|
|
682
|
-
|
|
683
|
-
|
|
790
|
+
{ "**/*": "PASCAL_CASE" },
|
|
791
|
+
{ ignoreMiddleExtensions: true }
|
|
792
|
+
]
|
|
684
793
|
}
|
|
685
794
|
}
|
|
686
795
|
];
|
|
@@ -698,6 +807,7 @@ var ESLintConfigBuilder = class {
|
|
|
698
807
|
this.fileNamesAdded = false;
|
|
699
808
|
this.typescriptAdded = false;
|
|
700
809
|
this.reactAdded = false;
|
|
810
|
+
this.tailwindAdded = false;
|
|
701
811
|
}
|
|
702
812
|
/**
|
|
703
813
|
* Set options that will be used for all subsequent config additions.
|
|
@@ -777,6 +887,21 @@ var ESLintConfigBuilder = class {
|
|
|
777
887
|
this.reactAdded = true;
|
|
778
888
|
return this;
|
|
779
889
|
}
|
|
890
|
+
/**
|
|
891
|
+
* Add Tailwind CSS-specific rules and plugins.
|
|
892
|
+
* Requires tailwind option to be set to true.
|
|
893
|
+
*/
|
|
894
|
+
withTailwind(options) {
|
|
895
|
+
const mergedOptions = { ...this.options, ...options };
|
|
896
|
+
if (!mergedOptions.tailwind) {
|
|
897
|
+
console.warn(
|
|
898
|
+
"ESLintConfigBuilder: Tailwind config added but tailwind option is not set. Consider calling setOptions({ tailwind: true }) first."
|
|
899
|
+
);
|
|
900
|
+
}
|
|
901
|
+
this.pendingConfigs.push(tailwindConfig(mergedOptions));
|
|
902
|
+
this.tailwindAdded = true;
|
|
903
|
+
return this;
|
|
904
|
+
}
|
|
780
905
|
/**
|
|
781
906
|
* Add a custom config object directly.
|
|
782
907
|
* Useful for adding project-specific rules or third-party configs.
|
|
@@ -806,6 +931,9 @@ var ESLintConfigBuilder = class {
|
|
|
806
931
|
if (mergedOptions.react) {
|
|
807
932
|
this.withReact(mergedOptions);
|
|
808
933
|
}
|
|
934
|
+
if (mergedOptions.tailwind) {
|
|
935
|
+
this.withTailwind(mergedOptions);
|
|
936
|
+
}
|
|
809
937
|
return this;
|
|
810
938
|
}
|
|
811
939
|
/**
|
|
@@ -829,6 +957,7 @@ var ESLintConfigBuilder = class {
|
|
|
829
957
|
this.fileNamesAdded = false;
|
|
830
958
|
this.typescriptAdded = false;
|
|
831
959
|
this.reactAdded = false;
|
|
960
|
+
this.tailwindAdded = false;
|
|
832
961
|
return this;
|
|
833
962
|
}
|
|
834
963
|
/**
|
|
@@ -858,16 +987,19 @@ var ESLintConfigBuilder = class {
|
|
|
858
987
|
hasReact() {
|
|
859
988
|
return this.reactAdded;
|
|
860
989
|
}
|
|
990
|
+
hasTailwind() {
|
|
991
|
+
return this.tailwindAdded;
|
|
992
|
+
}
|
|
861
993
|
};
|
|
862
994
|
|
|
863
995
|
// src/index.ts
|
|
864
|
-
import
|
|
865
|
-
var hasTsConfig =
|
|
996
|
+
import fs2 from "fs";
|
|
997
|
+
var hasTsConfig = fs2.existsSync("tsconfig.json") || fs2.existsSync("tsconfig.base.json");
|
|
866
998
|
var hasReact = () => {
|
|
867
999
|
try {
|
|
868
1000
|
const packageJsonPath = "package.json";
|
|
869
|
-
if (
|
|
870
|
-
const packageJson = JSON.parse(
|
|
1001
|
+
if (fs2.existsSync(packageJsonPath)) {
|
|
1002
|
+
const packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf-8"));
|
|
871
1003
|
const deps = {
|
|
872
1004
|
...packageJson.dependencies,
|
|
873
1005
|
...packageJson.devDependencies,
|
|
@@ -879,14 +1011,31 @@ var hasReact = () => {
|
|
|
879
1011
|
}
|
|
880
1012
|
return false;
|
|
881
1013
|
};
|
|
882
|
-
|
|
1014
|
+
var hasTailwind = () => {
|
|
1015
|
+
try {
|
|
1016
|
+
const packageJsonPath = "package.json";
|
|
1017
|
+
if (fs2.existsSync(packageJsonPath)) {
|
|
1018
|
+
const packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf-8"));
|
|
1019
|
+
const deps = {
|
|
1020
|
+
...packageJson.dependencies,
|
|
1021
|
+
...packageJson.devDependencies,
|
|
1022
|
+
...packageJson.peerDependencies
|
|
1023
|
+
};
|
|
1024
|
+
if ("tailwindcss" in deps) return true;
|
|
1025
|
+
}
|
|
1026
|
+
} catch {
|
|
1027
|
+
}
|
|
1028
|
+
return fs2.existsSync("tailwind.config.js") || fs2.existsSync("tailwind.config.ts") || fs2.existsSync("tailwind.config.mjs") || fs2.existsSync("tailwind.config.cjs");
|
|
1029
|
+
};
|
|
1030
|
+
function eslintConfig(options = {}) {
|
|
883
1031
|
const finalOptions = {
|
|
884
1032
|
typescript: options.typescript ?? hasTsConfig,
|
|
885
1033
|
react: options.react ?? hasReact(),
|
|
1034
|
+
tailwind: options.tailwind ?? hasTailwind(),
|
|
886
1035
|
...options
|
|
887
1036
|
};
|
|
888
1037
|
return new ESLintConfigBuilder().setOptions(finalOptions).withAll().build();
|
|
889
1038
|
}
|
|
890
1039
|
export {
|
|
891
|
-
|
|
1040
|
+
eslintConfig as default
|
|
892
1041
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dauphaihau/eslint-config",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -12,14 +12,15 @@
|
|
|
12
12
|
"README.md"
|
|
13
13
|
],
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@eslint/js": "^
|
|
16
|
-
"@stylistic/eslint-plugin": "^
|
|
17
|
-
"eslint-plugin-
|
|
15
|
+
"@eslint/js": "^10.0.0",
|
|
16
|
+
"@stylistic/eslint-plugin": "^5.9.0",
|
|
17
|
+
"eslint-plugin-check-file": "^3.3.1",
|
|
18
18
|
"globals": "^16.5.0",
|
|
19
|
-
"typescript-eslint": "^8.
|
|
19
|
+
"typescript-eslint": "^8.56.1"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
|
-
"eslint": "^9.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,25 +31,30 @@
|
|
|
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": {
|
|
36
40
|
"@types/node": "^22.0.0",
|
|
37
|
-
"eslint": "^
|
|
38
|
-
"eslint-plugin-react": "^7.
|
|
39
|
-
"eslint-plugin-react-hooks": "^
|
|
40
|
-
"eslint-plugin-react-refresh": "^0.
|
|
41
|
+
"eslint": "^10.0.0",
|
|
42
|
+
"eslint-plugin-react": "^7.37.5",
|
|
43
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
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
48
|
"typescript": "^5.4.0"
|
|
44
49
|
},
|
|
45
50
|
"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-
|
|
51
|
+
"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
52
|
"lint": "eslint .",
|
|
48
53
|
"lint:fix": "eslint . --fix",
|
|
49
54
|
"typecheck": "tsc --noEmit",
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
55
|
+
"version:patch": "pnpm build && pnpm version patch",
|
|
56
|
+
"version:minor": "pnpm build && pnpm version minor",
|
|
57
|
+
"version:major": "pnpm build && pnpm version major",
|
|
58
|
+
"push": "git push --follow-tags"
|
|
53
59
|
}
|
|
54
60
|
}
|