eslint.config.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. // ESLint 9 flat config:vue3 + TS strict 配套(README §3.5:any 全面禁用)
  2. import js from '@eslint/js';
  3. import tseslint from 'typescript-eslint';
  4. import pluginVue from 'eslint-plugin-vue';
  5. import prettier from 'eslint-config-prettier';
  6. /**
  7. * 框架运行时模块名(业务代码禁"值 import",见 README §3.3-1)。
  8. *
  9. * 精确边界:
  10. * - `import type { Ref } from 'vue'` 属**类型导入**(编译期擦除、零运行时足迹)——
  11. * 不在限内,TS strict 下类型必须有来源,type import 是唯一合规写法;
  12. * - `import { ref } from 'vue'` 属**值导入**——会把框架运行时打包进 dist,必须拦。
  13. *
  14. * 实现用 `no-restricted-syntax`(而非 no-restricted-imports,后者不区分 type/value):
  15. * `importKind` 属性仅 @typescript-eslint/parser 产生:
  16. * import type {...} → 'type'(放行) | import {...} → 'value'(拦截)
  17. */
  18. const FRAMEWORK_MODULE_SELECTOR =
  19. ":is([source.value='vue'],[source.value='vue-router'],[source.value='pinia'],[source.value='axios'],[source.value='element-plus'])";
  20. export default [
  21. js.configs.recommended,
  22. ...tseslint.configs.recommended,
  23. ...pluginVue.configs['flat/essential'],
  24. prettier,
  25. {
  26. // shims/ 由 scripts/gen-shims.cjs 生成(含逐行 eslint-disable 注释,引用了未安装的 import 插件),不 lint
  27. // scripts/ 是 Node CJS 工具脚本(require / __dirname),不属于浏览器 TS 产物,不 lint
  28. ignores: ['dist/**', 'vendor/**', 'node_modules/**', 'shims/**', 'scripts/**', '**/*.cjs'],
  29. },
  30. {
  31. // .vue:SFC 内 <script lang="ts"> 交给 @typescript-eslint/parser,
  32. // 否则 TS 语法(类型注解 / interface / 泛型)在 SFC 内触发 Parsing error。
  33. // vue-eslint-parser 解析 SFC 结构,本 block 只补"内部 script 用哪个 parser"。
  34. files: ['**/*.vue'],
  35. languageOptions: {
  36. parserOptions: {
  37. parser: tseslint.parser,
  38. sourceType: 'module',
  39. },
  40. },
  41. },
  42. {
  43. // TS 项目里 no-undef 必须由 TS 编译器负责(global.d.ts 声明的 ref/reactive/window 等
  44. // 对 JS 规则的 no-undef 不可见,会误报);关掉它,TS 编译器 + 上面的"值 import 拦截"已足够。
  45. files: ['**/*.ts', '**/*.vue', '**/*.tsx'],
  46. rules: {
  47. 'no-undef': 'off',
  48. },
  49. },
  50. {
  51. rules: {
  52. '@typescript-eslint/no-explicit-any': 'error',
  53. 'vue/multi-word-component-names': 'off',
  54. '@typescript-eslint/no-unused-vars': [
  55. 'error',
  56. { argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
  57. ],
  58. // 拦截"值 import 框架"(值导入会把框架运行时打包进 dist,违反 README §3.3-1)。
  59. // 放行 import type(编译期擦除)。importKind='value' 只匹配值导入。
  60. 'no-restricted-syntax': [
  61. 'error',
  62. {
  63. selector: `ImportDeclaration[importKind='value']${FRAMEWORK_MODULE_SELECTOR}`,
  64. message:
  65. '框架运行时经 UMD 全局使用(README §3.3-1),业务代码禁止值 import 框架模块;仅允许 `import type`(编译期擦除,零运行时足迹)。',
  66. },
  67. ],
  68. },
  69. },
  70. ];