my-code-style 1.2.0 → 1.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/package.json CHANGED
@@ -1,127 +1,223 @@
1
1
  {
2
- "name": "my-code-style",
3
- "version": "1.2.0",
4
- "description": "Lint/Format/Git 配置工程化 npm 包(ESLint + Prettier + Stylelint + Commitlint + Husky + standard-version)",
5
- "type": "commonjs",
6
- "main": "src/eslint/uniapp.cjs",
7
- "bin": {
8
- "my-code-style-init": "./bin/init"
9
- },
10
- "exports": {
11
- ".": "./src/eslint/uniapp.cjs",
12
- "./eslint": "./src/eslint/base.cjs",
13
- "./eslint/vue3": "./src/eslint/vue3.cjs",
14
- "./eslint/uniapp": "./src/eslint/uniapp.cjs",
15
- "./eslint/flat": "./src/eslint/flat/base.mjs",
16
- "./eslint/flat/vue3": "./src/eslint/flat/vue3.mjs",
17
- "./eslint/flat/uniapp": "./src/eslint/flat/uniapp.mjs",
18
- "./prettier": "./src/prettier/index.cjs",
19
- "./stylelint": "./src/stylelint/index.cjs",
20
- "./stylelint/less": "./src/stylelint/less.cjs",
21
- "./stylelint/less-override": "./src/stylelint/less-override.cjs",
22
- "./commitlint": "./src/commitlint/base.cjs",
23
- "./commitlint/scopes": "./src/commitlint/scopes.cjs",
24
- "./versionrc": "./src/versionrc/index.cjs"
25
- },
26
- "files": [
27
- "src",
28
- "bin",
29
- "README.md"
2
+ "name": "my-code-style",
3
+ "version": "1.4.0",
4
+ "description": "Lint/Format/Git 配置工程化 npm 包(ESLint + Prettier + Stylelint + Commitlint + Husky + standard-version)",
5
+ "type": "commonjs",
6
+ "main": "src/eslint/uniapp.cjs",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/myvn/codeStyle.git"
10
+ },
11
+ "homepage": "https://github.com/myvn/codeStyle#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/myvn/codeStyle/issues"
14
+ },
15
+ "bin": {
16
+ "my-code-style-init": "./bin/init"
17
+ },
18
+ "exports": {
19
+ ".": "./src/eslint/uniapp.cjs",
20
+ "./eslint": "./src/eslint/base.cjs",
21
+ "./eslint/vue3": "./src/eslint/vue3.cjs",
22
+ "./eslint/uniapp": "./src/eslint/uniapp.cjs",
23
+ "./eslint/flat": "./src/eslint/flat/base.mjs",
24
+ "./eslint/flat/vue3": "./src/eslint/flat/vue3.mjs",
25
+ "./eslint/flat/uniapp": "./src/eslint/flat/uniapp.mjs",
26
+ "./prettier": "./src/prettier/index.cjs",
27
+ "./stylelint": "./src/stylelint/index.cjs",
28
+ "./stylelint/less": "./src/stylelint/less.cjs",
29
+ "./stylelint/less-override": "./src/stylelint/less-override.cjs",
30
+ "./commitlint": "./src/commitlint/base.cjs",
31
+ "./commitlint/scopes": "./src/commitlint/scopes.cjs",
32
+ "./versionrc": "./src/versionrc/index.cjs"
33
+ },
34
+ "files": [
35
+ "src",
36
+ "bin",
37
+ "README.md"
38
+ ],
39
+ "publishConfig": {
40
+ "access": "public",
41
+ "registry": "https://registry.npmjs.org/"
42
+ },
43
+ "scripts": {
44
+ "test": "node --test tests/*.test.cjs demo-test/*.test.cjs",
45
+ "test:demo": "node --test demo-test/*.test.cjs",
46
+ "test:integration:setup": "node demo-test/setup-integration.cjs",
47
+ "test:integration": "node --test demo-test/integration/*.test.cjs",
48
+ "test:legacy:setup": "node demo-test/setup-legacy.cjs",
49
+ "test:legacy": "node --test demo-test/legacy/*.test.cjs",
50
+ "test:all": "npm test && npm run test:integration && npm run test:legacy",
51
+ "lint": "eslint .",
52
+ "lint:fix": "eslint . --fix",
53
+ "format": "prettier --write .",
54
+ "prepare": "node -e \"if (!process.env.CI) { try { require('child_process').execSync('husky', { stdio: 'ignore' }) } catch {} }\"",
55
+ "release": "standard-version",
56
+ "release:push": "standard-version && git push --follow-tags origin HEAD",
57
+ "pub": "npm run release:push",
58
+ "cz": "czg",
59
+ "link": "pnpm link --global",
60
+ "unlink": "pnpm unlink --global",
61
+ "pack": "npm pack"
62
+ },
63
+ "engines": {
64
+ "node": ">=18"
65
+ },
66
+ "peerDependencies": {
67
+ "@commitlint/cli": "^19.0.0",
68
+ "@commitlint/config-conventional": "^19.0.0",
69
+ "@eslint/eslintrc": "^3.0.0",
70
+ "@eslint/js": "^9.0.0",
71
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
72
+ "@typescript-eslint/parser": "^8.0.0",
73
+ "czg": "^1.0.0",
74
+ "eslint": "^8.57.0 || ^9.0.0",
75
+ "eslint-config-prettier": "^10.1.8",
76
+ "eslint-import-resolver-typescript": "^3.0.0",
77
+ "eslint-plugin-import": "^2.0.0",
78
+ "eslint-plugin-import-x": "^4.0.0",
79
+ "eslint-plugin-prettier": "^5.2.0",
80
+ "eslint-plugin-vue": "^10.0.0",
81
+ "globals": "^16.0.0",
82
+ "husky": "^9.0.0",
83
+ "lint-staged": "^16.0.0",
84
+ "postcss-html": "^2.0.0",
85
+ "postcss-less": "^6.0.0",
86
+ "postcss-scss": "^4.0.0",
87
+ "prettier": "^3.0.0",
88
+ "standard-version": "^9.0.0",
89
+ "stylelint": "^16.0.0",
90
+ "stylelint-config-html": "^2.0.0",
91
+ "stylelint-config-recess-order": "^5.0.0",
92
+ "stylelint-config-recommended": "^17.0.0",
93
+ "stylelint-config-recommended-scss": "^16.0.0",
94
+ "stylelint-config-recommended-vue": "^2.0.0",
95
+ "stylelint-prettier": "^5.0.0",
96
+ "typescript-eslint": "^8.0.0",
97
+ "vue-eslint-parser": "^10.3.0"
98
+ },
99
+ "peerDependenciesMeta": {
100
+ "@commitlint/cli": {
101
+ "optional": true
102
+ },
103
+ "@commitlint/config-conventional": {
104
+ "optional": true
105
+ },
106
+ "@eslint/eslintrc": {
107
+ "optional": true
108
+ },
109
+ "@eslint/js": {
110
+ "optional": true
111
+ },
112
+ "@typescript-eslint/eslint-plugin": {
113
+ "optional": true
114
+ },
115
+ "@typescript-eslint/parser": {
116
+ "optional": true
117
+ },
118
+ "czg": {
119
+ "optional": true
120
+ },
121
+ "eslint": {
122
+ "optional": true
123
+ },
124
+ "eslint-config-prettier": {
125
+ "optional": true
126
+ },
127
+ "eslint-import-resolver-typescript": {
128
+ "optional": true
129
+ },
130
+ "eslint-plugin-import": {
131
+ "optional": true
132
+ },
133
+ "eslint-plugin-import-x": {
134
+ "optional": true
135
+ },
136
+ "eslint-plugin-prettier": {
137
+ "optional": true
138
+ },
139
+ "eslint-plugin-vue": {
140
+ "optional": true
141
+ },
142
+ "globals": {
143
+ "optional": true
144
+ },
145
+ "husky": {
146
+ "optional": true
147
+ },
148
+ "lint-staged": {
149
+ "optional": true
150
+ },
151
+ "postcss-html": {
152
+ "optional": true
153
+ },
154
+ "postcss-less": {
155
+ "optional": true
156
+ },
157
+ "postcss-scss": {
158
+ "optional": true
159
+ },
160
+ "prettier": {
161
+ "optional": true
162
+ },
163
+ "standard-version": {
164
+ "optional": true
165
+ },
166
+ "stylelint": {
167
+ "optional": true
168
+ },
169
+ "stylelint-config-html": {
170
+ "optional": true
171
+ },
172
+ "stylelint-config-recess-order": {
173
+ "optional": true
174
+ },
175
+ "stylelint-config-recommended": {
176
+ "optional": true
177
+ },
178
+ "stylelint-config-recommended-scss": {
179
+ "optional": true
180
+ },
181
+ "stylelint-config-recommended-vue": {
182
+ "optional": true
183
+ },
184
+ "stylelint-prettier": {
185
+ "optional": true
186
+ },
187
+ "typescript-eslint": {
188
+ "optional": true
189
+ },
190
+ "vue-eslint-parser": {
191
+ "optional": true
192
+ }
193
+ },
194
+ "devDependencies": {
195
+ "standard-version": "^9.5.0"
196
+ },
197
+ "keywords": [
198
+ "eslint-config",
199
+ "prettier-config",
200
+ "stylelint-config",
201
+ "commitlint-config",
202
+ "vue",
203
+ "uni-app",
204
+ "typescript"
205
+ ],
206
+ "license": "MIT",
207
+ "lint-staged": {
208
+ "**/*.{vue,nvue}": [
209
+ "prettier --write",
210
+ "eslint --fix"
211
+ ],
212
+ "**/*.{js,ts,jsx,tsx,cjs,mjs,mts,cts}": [
213
+ "prettier --write",
214
+ "eslint --fix"
30
215
  ],
31
- "scripts": {
32
- "link": "pnpm link --global",
33
- "unlink": "pnpm unlink --global",
34
- "pack": "npm pack",
35
- "release": "standard-version"
36
- },
37
- "engines": {
38
- "node": ">=18"
39
- },
40
- "peerDependencies": {
41
- "@commitlint/cli": "^19.0.0",
42
- "@commitlint/config-conventional": "^19.0.0",
43
- "@eslint/eslintrc": "^3.0.0",
44
- "@eslint/js": "^9.0.0",
45
- "@typescript-eslint/eslint-plugin": "^8.0.0",
46
- "@typescript-eslint/parser": "^8.0.0",
47
- "czg": "^1.0.0",
48
- "eslint": "^9.0.0",
49
- "eslint-config-prettier": "^10.1.8",
50
- "eslint-import-resolver-typescript": "^3.0.0",
51
- "eslint-plugin-import": "^2.0.0",
52
- "eslint-plugin-import-x": "^4.0.0",
53
- "eslint-plugin-prettier": "^5.2.0",
54
- "eslint-plugin-vue": "^10.0.0",
55
- "globals": "^16.0.0",
56
- "husky": "^9.0.0",
57
- "lint-staged": "^16.0.0",
58
- "postcss-html": "^1.0.0",
59
- "postcss-less": "^6.0.0",
60
- "postcss-scss": "^4.0.0",
61
- "prettier": "^3.0.0",
62
- "standard-version": "^9.0.0",
63
- "stylelint": "^16.0.0",
64
- "stylelint-config-html": "^1.0.0",
65
- "stylelint-config-recess-order": "^5.0.0",
66
- "stylelint-config-recommended": "^17.0.0",
67
- "stylelint-config-recommended-scss": "^16.0.0",
68
- "stylelint-config-recommended-vue": "^2.0.0",
69
- "stylelint-prettier": "^5.0.0",
70
- "typescript-eslint": "^8.0.0",
71
- "vue-eslint-parser": "^9.0.0"
72
- },
73
- "peerDependenciesMeta": {
74
- "@eslint/eslintrc": {
75
- "optional": true
76
- },
77
- "@eslint/js": {
78
- "optional": true
79
- },
80
- "eslint-plugin-vue": {
81
- "optional": true
82
- },
83
- "eslint-plugin-import-x": {
84
- "optional": true
85
- },
86
- "globals": {
87
- "optional": true
88
- },
89
- "postcss-less": {
90
- "optional": true
91
- },
92
- "postcss-scss": {
93
- "optional": true
94
- },
95
- "postcss-html": {
96
- "optional": true
97
- },
98
- "stylelint-config-recommended-scss": {
99
- "optional": true
100
- },
101
- "stylelint-config-recommended-vue": {
102
- "optional": true
103
- },
104
- "stylelint-config-html": {
105
- "optional": true
106
- },
107
- "typescript-eslint": {
108
- "optional": true
109
- },
110
- "vue-eslint-parser": {
111
- "optional": true
112
- }
113
- },
114
- "devDependencies": {
115
- "standard-version": "^9.5.0"
116
- },
117
- "keywords": [
118
- "eslint-config",
119
- "prettier-config",
120
- "stylelint-config",
121
- "commitlint-config",
122
- "vue",
123
- "uni-app",
124
- "typescript"
216
+ "**/*.{html,css}": [
217
+ "prettier --write"
125
218
  ],
126
- "license": "MIT"
219
+ "**/*.{json,json5,md,yml,yaml}": [
220
+ "prettier --write"
221
+ ]
222
+ }
127
223
  }
@@ -1,6 +1,5 @@
1
1
  // Commitlint base config (without project-specific dynamic scopes)
2
2
  module.exports = {
3
- ignores: [(commit) => commit.includes("init")],
4
3
  extends: ["@commitlint/config-conventional"],
5
4
  rules: {
6
5
  "body-leading-blank": [2, "always"],
@@ -84,19 +84,130 @@ function generateScopes(srcDirs = "src") {
84
84
  return [...new Set(allScopes)]
85
85
  }
86
86
 
87
+ function getStagedFiles(cwd) {
88
+ try {
89
+ const output = execSync("git diff --cached --name-only -z", {
90
+ cwd,
91
+ stdio: ["pipe", "pipe", "ignore"],
92
+ }).toString()
93
+ return output.split("\0").filter(Boolean)
94
+ } catch {
95
+ try {
96
+ const output = execSync("git status --porcelain -z", {
97
+ cwd,
98
+ stdio: ["pipe", "pipe", "ignore"],
99
+ }).toString()
100
+ const parts = output.split("\0")
101
+ const staged = []
102
+ for (let i = 0; i < parts.length; i++) {
103
+ const entry = parts[i]
104
+ if (!entry) continue
105
+ const x = entry[0]
106
+ const isRenameOrCopy = x === "R" || x === "C"
107
+ const filePath = entry.slice(3)
108
+ if (x !== " " && x !== "?" && x !== "!") {
109
+ if (filePath) staged.push(filePath)
110
+ }
111
+ if (isRenameOrCopy) {
112
+ i++
113
+ }
114
+ }
115
+ return staged
116
+ } catch {
117
+ return []
118
+ }
119
+ }
120
+ }
121
+
87
122
  /**
88
- * Guess the current scope from git status (modified files under src/)
89
- * @returns {string|undefined}
123
+ * Guess the current scope from staged files in the git index.
124
+ * Only staged files are considered (unstaged and untracked changes are ignored).
125
+ * Multi-directory strategy: votes by the number of staged changes under each candidate scope directory;
126
+ * in case of a tie, the first encountered scope among staged files is chosen.
127
+ *
128
+ * @param {string|string[]} [srcDirs="src"] - Source directory name(s) relative to cwd
129
+ * @returns {string|undefined} Guessed scope name, or undefined if none matched
90
130
  */
91
- function guessCurrentScope() {
131
+ function guessCurrentScope(srcDirs = "src") {
92
132
  try {
93
- const output = execSync("git status --porcelain || true").toString().trim()
94
- const line = output.split("\n").find((r) => r.includes("M src"))
95
- if (!line) {
133
+ const cwd = process.cwd()
134
+ const rawPrefix = execSync("git rev-parse --show-prefix", {
135
+ cwd,
136
+ stdio: ["pipe", "pipe", "ignore"],
137
+ })
138
+ .toString()
139
+ .trim()
140
+ const prefix = rawPrefix.replace(/\\/g, "/")
141
+
142
+ const stagedFiles = getStagedFiles(cwd)
143
+ if (!stagedFiles || stagedFiles.length === 0) {
96
144
  return undefined
97
145
  }
98
- const rawName = line.replace(/\//g, "%%").match(/src%%((\w|-)*)/)?.[1]
99
- return toSingular(rawName)
146
+
147
+ const normalizedDirs = (Array.isArray(srcDirs) ? srcDirs : [srcDirs])
148
+ .map((d) => d.replace(/\\/g, "/").replace(/^\/+|\/+$/g, ""))
149
+ .filter(Boolean)
150
+
151
+ const candidateScopes = []
152
+
153
+ for (const file of stagedFiles) {
154
+ const normalizedFile = file.replace(/\\/g, "/")
155
+ if (prefix && !normalizedFile.startsWith(prefix)) {
156
+ continue
157
+ }
158
+ const relativeToCwd = prefix ? normalizedFile.slice(prefix.length) : normalizedFile
159
+
160
+ for (const srcDir of normalizedDirs) {
161
+ const dirPrefix = srcDir ? `${srcDir}/` : ""
162
+ if (relativeToCwd.startsWith(dirPrefix)) {
163
+ const subPath = relativeToCwd.slice(dirPrefix.length)
164
+ const segments = subPath.split("/").filter(Boolean)
165
+ // Must have at least 2 segments (directory + file) to belong to a scope directory
166
+ if (segments.length >= 2) {
167
+ const rawName = segments[0]
168
+ const resolvedDir = path.resolve(cwd, srcDir, rawName)
169
+ if (fs.existsSync(resolvedDir)) {
170
+ if (fs.statSync(resolvedDir).isDirectory()) {
171
+ candidateScopes.push(toSingular(rawName))
172
+ break
173
+ }
174
+ } else {
175
+ // If deleted on disk, having segments >= 2 indicates it was a directory in git
176
+ candidateScopes.push(toSingular(rawName))
177
+ break
178
+ }
179
+ }
180
+ }
181
+ }
182
+ }
183
+
184
+ if (candidateScopes.length === 0) {
185
+ return undefined
186
+ }
187
+
188
+ // Multi-directory selection strategy: vote by frequency; first encountered breaks ties
189
+ const counts = new Map()
190
+ const order = []
191
+
192
+ for (const scope of candidateScopes) {
193
+ if (!counts.has(scope)) {
194
+ counts.set(scope, 0)
195
+ order.push(scope)
196
+ }
197
+ counts.set(scope, counts.get(scope) + 1)
198
+ }
199
+
200
+ let bestScope = undefined
201
+ let maxCount = 0
202
+ for (const scope of order) {
203
+ const count = counts.get(scope)
204
+ if (count > maxCount) {
205
+ maxCount = count
206
+ bestScope = scope
207
+ }
208
+ }
209
+
210
+ return bestScope
100
211
  } catch {
101
212
  return undefined
102
213
  }
@@ -16,8 +16,17 @@ module.exports = {
16
16
  parserOptions: {
17
17
  ecmaVersion: "latest",
18
18
  sourceType: "module",
19
+ ecmaFeatures: {
20
+ jsx: true,
21
+ },
19
22
  },
20
23
  plugins: ["@typescript-eslint", "prettier", "import"],
24
+ overrides: [
25
+ {
26
+ files: ["**/*.cjs", "**/.*rc.js", "**/*.config.js"],
27
+ rules: { "@typescript-eslint/no-require-imports": "off" },
28
+ },
29
+ ],
21
30
  rules: {
22
31
  // Prettier 集成
23
32
  "prettier/prettier": [
@@ -31,7 +40,7 @@ module.exports = {
31
40
  },
32
41
  ],
33
42
  // 格式化与风格
34
- indent: ["error", 4],
43
+ indent: "off",
35
44
  semi: ["error", "never"],
36
45
  quotes: ["error", "double", { avoidEscape: false, allowTemplateLiterals: true }],
37
46
  curly: ["error", "all"],
@@ -53,6 +62,9 @@ module.exports = {
53
62
  "@typescript-eslint/no-redeclare": "error",
54
63
  "@typescript-eslint/no-explicit-any": "off",
55
64
  "@typescript-eslint/no-unused-vars": "off",
65
+ "@typescript-eslint/no-unused-expressions": "off",
66
+ "@typescript-eslint/ban-ts-comment": "off",
67
+ "@typescript-eslint/no-empty-object-type": "off",
56
68
 
57
69
  // 常用关闭
58
70
  "no-console": "off",
@@ -62,6 +74,7 @@ module.exports = {
62
74
  "no-use-before-define": "off",
63
75
  "no-undef": "off",
64
76
  "no-unused-vars": "off",
77
+ "no-unused-expressions": "off",
65
78
  "no-param-reassign": "off",
66
79
  "no-redeclare": "off",
67
80
  "prefer-promise-reject-errors": "off",
@@ -75,4 +88,3 @@ module.exports = {
75
88
  "import/resolver": { typescript: {} },
76
89
  },
77
90
  }
78
-
@@ -20,8 +20,8 @@ export const prettierRules = {
20
20
  * Common rules shared across all flat config levels — mirrors base.cjs rules
21
21
  */
22
22
  export const commonRules = {
23
- // 缩进与换行
24
- indent: ["error", 4],
23
+ // 缩进由 Prettier 统一负责,关闭 ESLint 缩进避免打架
24
+ indent: "off",
25
25
  semi: ["error", "never"],
26
26
  quotes: ["error", "double", { avoidEscape: false, allowTemplateLiterals: true }],
27
27
  curly: ["error", "all"],
@@ -31,11 +31,7 @@ export const commonRules = {
31
31
 
32
32
  // Import rules (using import-x for flat config compatibility)
33
33
  "import-x/no-unresolved": "off",
34
- "import-x/extensions": [
35
- "error",
36
- "ignorePackages",
37
- { js: "never", jsx: "never", ts: "never", tsx: "never" },
38
- ],
34
+ "import-x/extensions": "off",
39
35
  "import-x/prefer-default-export": "off",
40
36
  "import-x/no-extraneous-dependencies": "off",
41
37
 
@@ -43,6 +39,9 @@ export const commonRules = {
43
39
  "@typescript-eslint/no-redeclare": "error",
44
40
  "@typescript-eslint/no-explicit-any": "off",
45
41
  "@typescript-eslint/no-unused-vars": "off",
42
+ "@typescript-eslint/no-unused-expressions": "off",
43
+ "@typescript-eslint/ban-ts-comment": "off",
44
+ "@typescript-eslint/no-empty-object-type": "off",
46
45
 
47
46
  // Commonly disabled
48
47
  "no-console": "off",
@@ -52,6 +51,7 @@ export const commonRules = {
52
51
  "no-use-before-define": "off",
53
52
  "no-undef": "off",
54
53
  "no-unused-vars": "off",
54
+ "no-unused-expressions": "off",
55
55
  "no-param-reassign": "off",
56
56
  "no-redeclare": "off",
57
57
  "prefer-promise-reject-errors": "off",
@@ -76,4 +76,3 @@ export const uniappGlobals = {
76
76
  App: true,
77
77
  NodeJS: true,
78
78
  }
79
-
@@ -11,7 +11,15 @@ import { prettierRules, commonRules } from "./_shared.mjs"
11
11
  export default [
12
12
  // Ignore patterns
13
13
  {
14
- ignores: ["**/node_modules/**", "**/dist/**", "**/coverage/**"],
14
+ ignores: [
15
+ "**/node_modules/**",
16
+ "**/dist/**",
17
+ "**/coverage/**",
18
+ "**/public/**",
19
+ "**/assets/iconfont/**",
20
+ "**/*.min.js",
21
+ "**/*.min.css",
22
+ ],
15
23
  },
16
24
 
17
25
  // TypeScript recommended rules
@@ -21,7 +29,7 @@ export default [
21
29
  // eslint-plugin-import-x configuration
22
30
  // Replaces: plugin:import/recommended + eslint-config-standard (via FlatCompat)
23
31
  {
24
- files: ["**/*.{js,mjs,cjs,ts,mts,cts}"],
32
+ files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx,vue,nvue}"],
25
33
  plugins: {
26
34
  "import-x": importX,
27
35
  },
@@ -36,16 +44,9 @@ export default [
36
44
  },
37
45
  },
38
46
 
39
- // Prettier integration
40
- // Replaces: extends: ["plugin:prettier/recommended"]
41
- eslintPluginPrettierRecommended,
42
-
43
- // eslint-config-prettier MUST be last — disables conflicting ESLint rules
44
- eslintConfigPrettier,
45
-
46
- // Global language options for JS/TS
47
+ // Global language options for JS/TS/JSX/TSX
47
48
  {
48
- files: ["**/*.{js,mjs,cjs,ts,mts,cts}"],
49
+ files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
49
50
  languageOptions: {
50
51
  ecmaVersion: "latest",
51
52
  sourceType: "module",
@@ -58,16 +59,27 @@ export default [
58
59
  parserOptions: {
59
60
  ecmaVersion: "latest",
60
61
  sourceType: "module",
62
+ ecmaFeatures: {
63
+ jsx: true,
64
+ },
61
65
  },
62
66
  },
63
67
  },
64
68
 
65
- // Shared rules for all JS, TS and Vue files
69
+ // Shared rules for all JS, TS, JSX, TSX and Vue files
66
70
  {
67
- files: ["**/*.{js,mjs,cjs,ts,mts,cts,vue}"],
71
+ files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx,vue,nvue}"],
68
72
  rules: {
69
- ...prettierRules,
70
73
  ...commonRules,
74
+ ...prettierRules,
75
+ },
76
+ },
77
+
78
+ // CommonJS files and config files legitimately need require()
79
+ {
80
+ files: ["**/*.cjs", "**/.*rc.js", "**/*.config.js"],
81
+ rules: {
82
+ "@typescript-eslint/no-require-imports": "off",
71
83
  },
72
84
  },
73
85
 
@@ -80,4 +92,10 @@ export default [
80
92
  },
81
93
  },
82
94
  },
95
+
96
+ // Prettier integration (replaces: extends: ["plugin:prettier/recommended"])
97
+ eslintPluginPrettierRecommended,
98
+
99
+ // eslint-config-prettier MUST be last — disables conflicting ESLint rules
100
+ eslintConfigPrettier,
83
101
  ]