From 6e915a5977462a21fefe78954843ec1686a60f4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=A5=E6=B5=A9?= Date: Tue, 4 Nov 2025 00:52:22 +0800 Subject: [PATCH] =?UTF-8?q?feat(eslint):=20=E6=B7=BB=E5=8A=A0=20jsonc=20?= =?UTF-8?q?=E6=8F=92=E4=BB=B6=E5=B9=B6=E5=90=AF=E7=94=A8=20JSON=20?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E9=94=AE=E6=8E=92=E5=BA=8F=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 `eslint-plugin-jsonc` 插件,并在 `.json` 文件中启用 `jsonc/sort-keys` 规则, 以确保本地化文件中的键名按字母顺序排列。此举有助于减少多人协作时的合并冲突, 同时提升代码一致性和可维护性。 此外,调整了 VS Code 配置项顺序以优化读写逻辑,并更新相关依赖版本。 --- .vscode/settings.json | 7 ++-- eslint.config.ts | 29 ++++++++++++---- package.json | 2 ++ pnpm-lock.yaml | 69 ++++++++++++++++++++++++++++++++++--- src/locales/demo/en-US.json | 6 ++-- src/locales/demo/zh-CN.json | 6 ++-- 6 files changed, 99 insertions(+), 20 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 859c101..6bbc083 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,22 +6,23 @@ "source.fixAll.oxc": "explicit", "source.organizeImports": "never" }, + "eslint.enable": true, + "stylelint.enable": true, + "oxc.enable": true, "editor.formatOnSave": true, - "stylelint.enable": true, "stylelint.validate": ["css", "less", "postcss", "scss", "vue"], "scss.lint.unknownAtRules": "ignore", "css.lint.unknownAtRules": "ignore", "less.lint.unknownAtRules": "ignore", - "eslint.enable": true, - "oxc.enable": true, "[vue]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "editor.defaultFormatter": "esbenp.prettier-vscode", // >>>>> + "i18n-ally.readonly": true, "i18n-ally.namespace": false /* 禁用命名空间(@intlify/unplugin-vue-i18n不支持吧?) */, "i18n-ally.localesPaths": ["src/locales/demo", "src/locales"], // https://github.com/lokalise/i18n-ally/wiki/Path-Matcher diff --git a/eslint.config.ts b/eslint.config.ts index 6ad923a..243ae89 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -1,15 +1,17 @@ -import pluginImport from 'eslint-plugin-import'; -import { globalIgnores } from 'eslint/config'; +import pluginVitest from '@vitest/eslint-plugin'; +import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'; import { + configureVueProject, defineConfigWithVueTs, vueTsConfigs, - configureVueProject, } from '@vue/eslint-config-typescript'; -import pluginVue from 'eslint-plugin-vue'; -import pluginVitest from '@vitest/eslint-plugin'; -import pluginPlaywright from 'eslint-plugin-playwright'; +import pluginImport from 'eslint-plugin-import'; +import pluginJsonc from 'eslint-plugin-jsonc'; import pluginOxlint from 'eslint-plugin-oxlint'; -import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'; +import pluginPlaywright from 'eslint-plugin-playwright'; +import pluginVue from 'eslint-plugin-vue'; +import { globalIgnores } from 'eslint/config'; +import jsoncParser from 'jsonc-eslint-parser'; configureVueProject({ scriptLangs: ['ts', 'tsx'] }); // More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup @@ -52,6 +54,19 @@ export default defineConfigWithVueTs( }, }, + { + /** + * 启用 sort-keys 规则以强制对象键按字母顺序排序 + * 原因: + * 1. 减少多人协作时的合并冲突 + * 2. 保持代码一致性,提高可维护性 + */ + files: ['src/locales/**/*.json'], + languageOptions: { parser: jsoncParser }, + plugins: { jsonc: pluginJsonc }, + rules: { 'jsonc/sort-keys': 'error' }, + }, + { rules: { '@typescript-eslint/no-explicit-any': 'off', diff --git a/package.json b/package.json index 1efad1f..3177ba4 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "@unhead/vue": "^2.0.14", "@vueuse/core": "^13.9.0", "highlight.js": "^11.11.1", + "jsonc-eslint-parser": "^2.4.1", "lodash-es": "^4.17.21", "naive-ui": "^2.43.1", "pinia": "^3.0.3", @@ -103,6 +104,7 @@ "consola": "^3.4.2", "eslint": "^9.35.0", "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jsonc": "^2.21.0", "eslint-plugin-oxlint": "~1.23.0", "eslint-plugin-playwright": "^2.2.2", "eslint-plugin-vue": "~10.5.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1e75fef..e746055 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,6 +38,9 @@ importers: highlight.js: specifier: ^11.11.1 version: 11.11.1 + jsonc-eslint-parser: + specifier: ^2.4.1 + version: 2.4.1 lodash-es: specifier: ^4.17.21 version: 4.17.21 @@ -162,6 +165,9 @@ importers: eslint-plugin-import: specifier: ^2.32.0 version: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.38.0(jiti@2.6.1)) + eslint-plugin-jsonc: + specifier: ^2.21.0 + version: 2.21.0(eslint@9.38.0(jiti@2.6.1)) eslint-plugin-oxlint: specifier: ~1.23.0 version: 1.23.0 @@ -3261,6 +3267,10 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + diff-sequences@27.5.1: + resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -3405,6 +3415,12 @@ packages: engines: {node: '>=6.0'} hasBin: true + eslint-compat-utils@0.6.5: + resolution: {integrity: sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + eslint-config-prettier@10.1.8: resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} hasBin: true @@ -3414,6 +3430,17 @@ packages: eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + eslint-json-compat-utils@0.2.1: + resolution: {integrity: sha512-YzEodbDyW8DX8bImKhAcCeu/L31Dd/70Bidx2Qex9OFUtgzXLqtfWL4Hr5fM/aCCB8QUZLuJur0S9k6UfgFkfg==} + engines: {node: '>=12'} + peerDependencies: + '@eslint/json': '*' + eslint: '*' + jsonc-eslint-parser: ^2.4.0 + peerDependenciesMeta: + '@eslint/json': + optional: true + eslint-module-utils@2.12.1: resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} engines: {node: '>=4'} @@ -3445,6 +3472,12 @@ packages: '@typescript-eslint/parser': optional: true + eslint-plugin-jsonc@2.21.0: + resolution: {integrity: sha512-HttlxdNG5ly3YjP1cFMP62R4qKLxJURfBZo2gnMY+yQojZxkLyOpY1H1KRTKBmvQeSG9pIpSGEhDjE17vvYosg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + eslint-plugin-oxlint@1.23.0: resolution: {integrity: sha512-YT/ObCQMluSHVEqDJPwrVLERkUUQnmcRYYQbB7h6t2P4243WE3Z1UmUcPy1Q6vSVP/U7vw5affptlGV2RizDuw==} @@ -4148,8 +4181,8 @@ packages: engines: {node: '>=6'} hasBin: true - jsonc-eslint-parser@2.4.0: - resolution: {integrity: sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==} + jsonc-eslint-parser@2.4.1: + resolution: {integrity: sha512-uuPNLJkKN8NXAlZlQ6kmUF9qO+T6Kyd7oV4+/7yy8Jz6+MZNyhPq8EdLpdfnPVzUC8qSf1b4j1azKaGnFsjmsw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} jsonc-parser@3.3.1: @@ -7104,7 +7137,7 @@ snapshots: esbuild: 0.25.12 escodegen: 2.1.0 estree-walker: 2.0.2 - jsonc-eslint-parser: 2.4.0 + jsonc-eslint-parser: 2.4.1 source-map-js: 1.2.1 yaml-eslint-parser: 1.3.0 optionalDependencies: @@ -9006,6 +9039,8 @@ snapshots: detect-libc@2.1.2: {} + diff-sequences@27.5.1: {} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 @@ -9268,6 +9303,11 @@ snapshots: optionalDependencies: source-map: 0.6.1 + eslint-compat-utils@0.6.5(eslint@9.38.0(jiti@2.6.1)): + dependencies: + eslint: 9.38.0(jiti@2.6.1) + semver: 7.7.3 + eslint-config-prettier@10.1.8(eslint@9.38.0(jiti@2.6.1)): dependencies: eslint: 9.38.0(jiti@2.6.1) @@ -9280,6 +9320,12 @@ snapshots: transitivePeerDependencies: - supports-color + eslint-json-compat-utils@0.2.1(eslint@9.38.0(jiti@2.6.1))(jsonc-eslint-parser@2.4.1): + dependencies: + eslint: 9.38.0(jiti@2.6.1) + esquery: 1.6.0 + jsonc-eslint-parser: 2.4.1 + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.43.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.38.0(jiti@2.6.1)): dependencies: debug: 3.2.7 @@ -9319,6 +9365,21 @@ snapshots: - eslint-import-resolver-webpack - supports-color + eslint-plugin-jsonc@2.21.0(eslint@9.38.0(jiti@2.6.1)): + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1)) + diff-sequences: 27.5.1 + eslint: 9.38.0(jiti@2.6.1) + eslint-compat-utils: 0.6.5(eslint@9.38.0(jiti@2.6.1)) + eslint-json-compat-utils: 0.2.1(eslint@9.38.0(jiti@2.6.1))(jsonc-eslint-parser@2.4.1) + espree: 10.4.0 + graphemer: 1.4.0 + jsonc-eslint-parser: 2.4.1 + natural-compare: 1.4.0 + synckit: 0.11.11 + transitivePeerDependencies: + - '@eslint/json' + eslint-plugin-oxlint@1.23.0: dependencies: jsonc-parser: 3.3.1 @@ -10033,7 +10094,7 @@ snapshots: json5@2.2.3: {} - jsonc-eslint-parser@2.4.0: + jsonc-eslint-parser@2.4.1: dependencies: acorn: 8.15.0 eslint-visitor-keys: 3.4.3 diff --git a/src/locales/demo/en-US.json b/src/locales/demo/en-US.json index dd704a3..38cefd2 100644 --- a/src/locales/demo/en-US.json +++ b/src/locales/demo/en-US.json @@ -1,10 +1,10 @@ { "page": { "i18n-demo": { - "title": "Vue I18n Demo", - "current-language": "Current Language", "change-language": "Change Language", - "hello": "Hello, {name}!" + "current-language": "Current Language", + "hello": "Hello, {name}!", + "title": "Vue I18n Demo" } } } diff --git a/src/locales/demo/zh-CN.json b/src/locales/demo/zh-CN.json index c47a038..71adeaf 100644 --- a/src/locales/demo/zh-CN.json +++ b/src/locales/demo/zh-CN.json @@ -1,10 +1,10 @@ { "page": { "i18n-demo": { - "title": "Vue I18n 示例", - "current-language": "当前语言", "change-language": "切换语言", - "hello": "你好, {name}!" + "current-language": "当前语言", + "hello": "你好, {name}!", + "title": "Vue I18n 示例" } } }