my-code-style 1.9.1 → 1.9.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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  ## 变更日志
2
2
 
3
+ ## [1.9.2](https://github.com/myvn/codeStyle/compare/v1.9.1...v1.9.2) (2026-09-23)
4
+
5
+ ### 🐛 Bug Fixes | Bug 修复
6
+
7
+ - **init:** 兼容段 off→warn——带/不带 .ts 扩展名 import 双向兼容 ([a26cfb6](https://github.com/myvn/codeStyle/commit/a26cfb6884b96c466e45b935a606c217bd39069c))
8
+ - **init:** 显式 .ts 扩展名 import 自动兼容,fresh init 保持绿起点(BUG-037) ([4c63221](https://github.com/myvn/codeStyle/commit/4c632219817cf188d80963a45076817bcfd9d6ef))
9
+
3
10
  ## [1.9.1](https://github.com/myvn/codeStyle/compare/v1.9.0...v1.9.1) (2026-09-23)
4
11
 
5
12
  ### 🐛 Bug Fixes | Bug 修复
package/README.md CHANGED
@@ -206,13 +206,24 @@ npx my-code-style-init [--dry-run] [--backup] [--merge] [--version|-v] [--help|-
206
206
 
207
207
  ## lint 覆盖范围须知
208
208
 
209
- `lint` 脚本只跑 **ESLint**;Stylelint 默认只在 pre-commit 的 lint-staged 里对**本次改动的文件**执行。CI 如果只跑 `pnpm lint`,CSS/SCSS/Vue 内嵌样式不会被检查。有 CSS 预处理器的项目,init 会额外生成全量样式检查入口:
209
+ | 入口 | 覆盖 | 典型用途 |
210
+ | ------------------------- | ----------------------------------------------- | ------------------ |
211
+ | `pnpm lint` | ESLint(JS/TS/Vue 脚本层) | 本地与 CI 基础门禁 |
212
+ | `pnpm lint:style` | Stylelint 全仓(Vue/HTML 内嵌 + css/scss/less) | CI 补齐样式检查 |
213
+ | `pnpm lint:all` | ESLint + Stylelint 全仓 | CI 一条命令全覆盖 |
214
+ | lint-staged(pre-commit) | 仅本次改动的文件(三件套自动修复) | 提交门禁 |
210
215
 
211
- ```bash
212
- pnpm lint:style # stylelint "**/*.{vue,nvue,html,css,scss,less}"
213
- ```
216
+ `lint` 只跑 **ESLint**;Stylelint 默认只在 pre-commit 对**本次改动的文件**执行——CI 只跑 `pnpm lint` 时 CSS/SCSS/Vue 内嵌样式不会被检查。有 CSS 预处理器的项目,init 会生成 `lint:style` 与 `lint:all`。
217
+
218
+ ### 显式扩展名 import 的兼容行为
219
+
220
+ `import-x/extensions` 默认要求相对导入**省略** `.ts/.tsx` 扩展名。Vite 等 bundler resolution 项目常写 `import x from "@/types/Foo.ts"`(合法但与该规则冲突)。
221
+
222
+ init 会**自动检测**:命中显式扩展名 import 时,生成的 `eslint.config.mjs` 注入兼容段——该规则**降级为 warn**,`pnpm lint` 退出码不受影响:
214
223
 
215
- 把 `lint:style` 加进 CI(或并进 `lint:all`)即可补齐覆盖面。
224
+ - **带 `.ts` 与不带 `.ts` 都可以写**,两种风格共存不报错;
225
+ - 不一致的写法仍会出 warning,作为渐进统一的风格信号;
226
+ - 团队统一后想恢复严格检查(error 级、只允许省略),删除 `eslint.config.mjs` 里的兼容段即可。
216
227
 
217
228
  ## 项目体检:my-code-style-doctor
218
229
 
@@ -268,12 +279,12 @@ npx my-code-style-doctor
268
279
  ## 测试套件
269
280
 
270
281
  ```bash
271
- npm run test:all # 全量运行 197 项:用例明细 + 分类统计 + 最慢文件定位
282
+ npm run test:all # 全量运行 200 项:用例明细 + 分类统计 + 最慢文件定位
272
283
  npm run diagnose # 换机器后先跑它:进程 / git / 文件系统 / hooks 各占多少
273
284
  npm run sweep # 给本机找最佳文件级并发(扫 integration 套件)
274
- npm test # 只跑基础 CLI 与配置矩阵(96 项)
285
+ npm test # 只跑基础 CLI 与配置矩阵(98 项)
275
286
  npm run test:integration:setup # 安装现代化隔离依赖运行环境
276
- npm run test:integration # Flat Config、真实 Husky 及提交链路测试(65 项)
287
+ npm run test:integration # Flat Config、真实 Husky 及提交链路测试(66 项)
277
288
  npm run test:legacy:setup # 安装 ESLint 8 隔离运行环境
278
289
  npm run test:legacy # ESLint 8.57.0 兼容性回归测试(27 项)
279
290
  npm run test:stylelint17:setup # 安装 Stylelint 17 隔离运行环境
@@ -286,47 +297,47 @@ npm run test:stylelint17 # Stylelint 17 生态兼容性回归(8 项)
286
297
  ```text
287
298
  my-code-style 测试套件
288
299
 
289
- ▶ [1/4] 基础 CLI 与配置矩阵 (共 96 项,5 文件 · 3 文件并发(自动:2 核 / 内存 4G))
300
+ ▶ [1/4] 基础 CLI 与配置矩阵 (共 98 项,5 文件 · 3 文件并发(自动:2 核 / 内存 4G))
290
301
  ✓ 运行器 TAP 解析:统计通过与失败、SKIP 与每用例耗时 · 7ms
291
302
  ✓ cz 交互提示为中文,且可选类型与 type-enum 一一对应 · 1ms
292
303
  ✓ peer 范围覆盖我们声明支持的上游大版本(校准防回退,BUG-027) · 0ms
293
304
  ✓ 一键安装命令对含 || 的版本范围加引号,可整段粘贴执行 · 40ms
294
305
  ✓ 初始化结尾指引把 cz 用法说清楚(先 git add + 指到 README 手册) · 80ms
295
306
  …
296
- ✓ 通过 96 · 3.6s · 最慢文件 init-matrix.test.cjs 3.4s
307
+ ✓ 通过 98 · 4.2s · 最慢文件 init-matrix.test.cjs 4.0s
297
308
 
298
- ▶ [2/4] 现代工具链与提交链 (共 65 项,24 文件 · 3 文件并发(自动:2 核 / 内存 4G))
309
+ ▶ [2/4] 现代工具链与提交链 (共 66 项,24 文件 · 3 文件并发(自动:2 核 / 内存 4G))
299
310
  ✓ 完整提交链:JS/TS/Vue/nvue/CSS/less 自动修复及二次复检 · 10.4s
300
311
  ✓ 发布防呆:HEAD 已有 v* tag 时拦截(此时 release 工具会静默抬版并写出空 CHANGELOG) · 609ms
301
312
  …
302
- ✓ 通过 65 · 39.5s · 最慢文件 commit-chain-scss.test.cjs 12.7s
313
+ ✓ 通过 66 · 43.8s · 最慢文件 commit-chain-both.test.cjs 11.9s
303
314
 
304
315
  ▶ [3/4] ESLint 8 兼容性 (共 27 项,1 文件 · 3 文件并发(自动:2 核 / 内存 4G))
305
316
  ✓ 独立运行 ESLint 8 支持下限而非 ESLint 9 · 1ms
306
317
  ✓ ESLint 8 base:实际 CLI 加载生成配置并接受正常文件 · 1.3s
307
318
  …
308
- ✓ 通过 27 · 16.3s
319
+ ✓ 通过 27 · 20.2s
309
320
 
310
321
  ▶ [4/4] Stylelint 17 兼容性 (共 9 项,1 文件 · 3 文件并发(自动:2 核 / 内存 4G))
311
322
  ✓ 隔离环境装的是 stylelint 17(不是 16) · 2ms
312
323
  ✓ 生成的 .stylelintrc.cjs 在 stylelint 17 下可加载并放过正常 SCSS · 700ms
313
324
  …
314
- ✓ 通过 9 · 7.4s
325
+ ✓ 通过 9 · 8.8s
315
326
 
316
327
  ──────────────────────────────────────────────────────
317
328
  套件 通过 失败 跳过 用时
318
329
  ──────────────────────────────────────────────────────
319
- 基础 CLI 与配置矩阵 96 0 - 3.6s
320
- 现代工具链与提交链 65 0 - 39.5s
321
- ESLint 8 兼容性 27 0 - 16.3s
322
- Stylelint 17 兼容性 9 0 - 7.4s
330
+ 基础 CLI 与配置矩阵 98 0 - 4.2s
331
+ 现代工具链与提交链 66 0 - 43.8s
332
+ ESLint 8 兼容性 27 0 - 20.2s
333
+ Stylelint 17 兼容性 9 0 - 8.8s
323
334
  ──────────────────────────────────────────────────────
324
- 合计 197 0 - 66.8s
335
+ 合计 200 0 - 77.1s
325
336
  ──────────────────────────────────────────────────────
326
337
 
327
338
  ⏱ 最慢文件:eslint8.test.cjs 18.0s · commit-chain-less.test.cjs 11.4s · commit-chain-both.test.cjs 11.3s
328
339
 
329
- ✅ 全部通过:197/197 项,用时 66.8s
340
+ ✅ 全部通过:200/200 项,用时 77.1s
330
341
  ```
331
342
 
332
343
  终端里每个套件下方还有一条实时进度条(`██████░░░░ 38/66 失败 0 4.0s`)。附加参数:
@@ -404,7 +415,7 @@ npm run test:all -- --profile # 看每个测试文件耗时,定位瓶颈
404
415
  | `npm run test:integration`(运行器调度,自动并发 3) | 30.6s(只看集成套件那一段) |
405
416
  | 串行套件 + 文件级并发 23(全部一波) | ✗ 3.8G 内存沙箱被 OOM 压垮(19 项 SIGKILL) |
406
417
 
407
- 同机复测(197 项,同一台 2 核沙箱连续跑;绝对秒数随机器负载波动,相对关系稳定):默认自动并发 3 = 66.8s、`npm run test:integration` = 39.5s(本轮实跑;串行与 parallel 口径为早前基线实测,相对关系稳定)。
418
+ 同机复测(200 项,同一台 2 核沙箱连续跑;绝对秒数随机器负载波动,相对关系稳定):默认自动并发 3 = 77.1s、`npm run test:integration` = 43.8s(本轮实跑;串行与 parallel 口径为早前基线实测,相对关系稳定)。
408
419
 
409
420
  (2 核沙箱里并行收益被 CPU 争抢吃掉大半,`--concurrency=1` 时单个文件只要 0.7–4.2s;
410
421
  16 核机器上集成套件那段 ≈ 最慢子文件,即"一次真实提交"的量级。)
package/bin/init CHANGED
@@ -555,7 +555,55 @@ module.exports = config
555
555
  `
556
556
  }
557
557
 
558
- function eslintFlatConfigContent(projectType) {
558
+ /**
559
+ * 检测项目源码是否存在显式 .ts/.tsx/.mts/.cts 扩展名 import(下游 1.9.1 实测:
560
+ * Vite 等 bundler resolution 项目大量使用 `import xxx from "@/types/Foo.ts"`,
561
+ * 全部合法,但默认的 import-x/extensions 强制省略扩展名会让 fresh init 直接
562
+ * 报数百个错误)。命中则生成的配置注入兼容段,fresh init 保持"绿起点"。
563
+ */
564
+ function detectExplicitTsImports() {
565
+ const roots = ["src", "app", "pages", "scripts"].filter((dir) =>
566
+ fs.existsSync(path.resolve(PROJECT_ROOT, dir)),
567
+ )
568
+ const scanRoots = roots.length > 0 ? roots : ["."]
569
+ const exts = new Set([".ts", ".tsx", ".mts", ".cts", ".vue", ".js", ".jsx", ".mjs", ".cjs"])
570
+ const pattern =
571
+ /(?:from\s+|import\s*\(\s*|require\s*\(\s*)["'][^"']+:?[\w@/.-]*\.(?:ts|tsx|mts|cts)["']/
572
+ let scanned = 0
573
+ const walk = (dir) => {
574
+ let entries
575
+ try {
576
+ entries = fs.readdirSync(dir, { withFileTypes: true })
577
+ } catch {
578
+ return false
579
+ }
580
+ for (const entry of entries) {
581
+ if (scanned > 2000) return false
582
+ const full = path.join(dir, entry.name)
583
+ if (entry.isDirectory()) {
584
+ if (
585
+ entry.name === "node_modules" ||
586
+ entry.name === "dist" ||
587
+ entry.name.startsWith(".")
588
+ )
589
+ continue
590
+ if (walk(full)) return true
591
+ } else if (exts.has(path.extname(entry.name))) {
592
+ scanned++
593
+ try {
594
+ if (pattern.test(fs.readFileSync(full, "utf8"))) return true
595
+ } catch {}
596
+ }
597
+ }
598
+ return false
599
+ }
600
+ for (const root of scanRoots) {
601
+ if (walk(path.resolve(PROJECT_ROOT, root))) return true
602
+ }
603
+ return false
604
+ }
605
+
606
+ function eslintFlatConfigContent(projectType, { compatExplicitTsImports = false } = {}) {
559
607
  let importPath = "my-code-style/eslint/flat"
560
608
  let varName = "baseConfig"
561
609
  if (projectType === "uniapp") {
@@ -566,11 +614,22 @@ function eslintFlatConfigContent(projectType) {
566
614
  varName = "vue3Config"
567
615
  }
568
616
 
617
+ const compatBlock = compatExplicitTsImports
618
+ ? `,
619
+ // 兼容存量代码:检测到项目存在显式 .ts/.tsx 扩展名 import(Vite 等 bundler
620
+ // resolution 下合法)。降级为 warn:带与不带扩展名都可写、不再报错阻断,
621
+ // 两种写法的"风格不一致"仍会以警告提示,团队可渐进统一;想恢复严格检查
622
+ // (error + 只允许省略)删除此段即可。
623
+ {
624
+ files: ["**/*.{ts,tsx,mts,cts}"],
625
+ rules: { "import-x/extensions": "warn" },
626
+ }`
627
+ : ""
569
628
  return `// ESLint Flat Config — powered by my-code-style
570
629
  // https://www.npmjs.com/package/my-code-style
571
630
  import ${varName} from "${importPath}"
572
631
 
573
- export default [...${varName}]
632
+ export default [...${varName}${compatBlock}]
574
633
  `
575
634
  }
576
635
 
@@ -837,6 +896,12 @@ function main() {
837
896
  console.log(" 保留已有 ESLint 配置,不生成额外入口")
838
897
  } else if (useFlatConfig) {
839
898
  console.log(" 生成 Flat Config 入口 eslint.config.mjs")
899
+ const compatExplicitTsImports = detectExplicitTsImports()
900
+ if (compatExplicitTsImports) {
901
+ console.log(
902
+ " · 检测到显式 .ts 扩展名 import:已注入兼容段(import-x/extensions 降级为 warn,带/不带扩展名均可写;统一风格时删除该段)",
903
+ )
904
+ }
840
905
  files.push({
841
906
  path: "eslint.config.mjs",
842
907
  exists:
@@ -844,7 +909,7 @@ function main() {
844
909
  fileExists("eslint.config.js") ||
845
910
  fileExists("eslint.config.ts") ||
846
911
  fileExists("eslint.config.cjs"),
847
- content: eslintFlatConfigContent(projectType),
912
+ content: eslintFlatConfigContent(projectType, { compatExplicitTsImports }),
848
913
  })
849
914
  } else {
850
915
  console.log(" 生成传统格式入口 .eslintrc.cjs")
@@ -984,11 +1049,13 @@ function main() {
984
1049
  stepHeader(4, 6, "package.json")
985
1050
  if (dryRun) {
986
1051
  console.log(
987
- " · 将更新 scripts(lint / lint:fix / format / prepare / release / cz)与 lint-staged",
1052
+ " · 将更新 scripts(lint / lint:fix / lint:style / lint:all / format / prepare / release / cz)与 lint-staged",
988
1053
  )
989
1054
  return
990
1055
  }
991
- console.log(" ✓ scripts 已更新(lint / lint:fix / format / prepare / release / cz)")
1056
+ console.log(
1057
+ " ✓ scripts 已更新(lint / lint:fix / lint:style / lint:all / format / prepare / release / cz)",
1058
+ )
992
1059
  console.log(" ✓ lint-staged 已按检测到的 CSS 预处理器生成")
993
1060
  }
994
1061
 
@@ -1156,7 +1223,10 @@ function main() {
1156
1223
  // 配置里排除 node_modules/dist 等,glob 全仓是安全的
1157
1224
  ...(skipStylelint
1158
1225
  ? {}
1159
- : { "lint:style": 'stylelint "**/*.{vue,nvue,html,css,scss,less}"' }),
1226
+ : {
1227
+ "lint:style": 'stylelint "**/*.{vue,nvue,html,css,scss,less}"',
1228
+ "lint:all": `${lintCommand} && stylelint "**/*.{vue,nvue,html,css,scss,less}"`,
1229
+ }),
1160
1230
  format: "prettier --write .",
1161
1231
  prepare: "husky",
1162
1232
  release: "commit-and-tag-version",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-code-style",
3
- "version": "1.9.1",
3
+ "version": "1.9.2",
4
4
  "description": "Lint/Format/Git 配置工程化 npm 包(ESLint + Prettier + Stylelint + Commitlint + Husky + standard-version)",
5
5
  "type": "commonjs",
6
6
  "main": "src/eslint/uniapp.cjs",