king-design-analyzer 2.1.7 → 2.2.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.
Files changed (311) hide show
  1. package/components/actions.json +101 -0
  2. package/components/advancedset.json +127 -0
  3. package/components/affix.json +7 -0
  4. package/components/aksk.json +172 -0
  5. package/components/az.json +15 -2
  6. package/components/badge.json +7 -0
  7. package/components/billtypes.json +14 -2
  8. package/components/breadcrumb.json +7 -0
  9. package/components/button.json +191 -0
  10. package/components/buttonlink.json +73 -0
  11. package/components/card.json +8 -1
  12. package/components/cardcol.json +142 -0
  13. package/components/cardcols.json +121 -0
  14. package/components/cardcontent.json +15 -3
  15. package/components/cardtabs.json +172 -0
  16. package/components/carousel.json +7 -0
  17. package/components/cascader.json +520 -368
  18. package/components/checkbox.json +51 -4
  19. package/components/cidrinput.json +140 -0
  20. package/components/code.json +8 -1
  21. package/components/collapse.json +7 -0
  22. package/components/colorpicker.json +217 -0
  23. package/components/copy.json +7 -0
  24. package/components/copyhover.json +111 -0
  25. package/components/copyrow.json +124 -0
  26. package/components/datepicker.json +656 -524
  27. package/components/description.json +98 -0
  28. package/components/dialog.json +522 -455
  29. package/components/divider.json +8 -1
  30. package/components/drawer.json +571 -558
  31. package/components/dropdown.json +464 -384
  32. package/components/duration.json +125 -0
  33. package/components/editable.json +66 -0
  34. package/components/ellipsis.json +34 -1
  35. package/components/filtertablefieldsdialog.json +128 -0
  36. package/components/flex.json +151 -0
  37. package/components/form.json +131 -0
  38. package/components/formiteminput.json +214 -0
  39. package/components/formitemspinner.json +213 -0
  40. package/components/formitemswitch.json +185 -0
  41. package/components/formitemtableconfigs.json +210 -0
  42. package/components/grid.json +7 -0
  43. package/components/header.json +161 -0
  44. package/components/icon.json +13 -1
  45. package/components/icontooltip.json +19 -1
  46. package/components/input.json +188 -4
  47. package/components/instancelist.json +194 -0
  48. package/components/instancenum.json +196 -0
  49. package/components/ipinput.json +117 -0
  50. package/components/kspstatus.json +205 -0
  51. package/components/kvcode.json +120 -0
  52. package/components/layoutcontent.json +15 -3
  53. package/components/layoutlistcontent.json +148 -0
  54. package/components/layoutpermissioncontent.json +155 -0
  55. package/components/layoutstandardlist.json +275 -0
  56. package/components/layouttabs.json +168 -0
  57. package/components/lazymount.json +86 -0
  58. package/components/lazyteleport.json +118 -0
  59. package/components/menu.json +7 -0
  60. package/components/pagination.json +12 -0
  61. package/components/paginationplus.json +30 -3
  62. package/components/password.json +121 -0
  63. package/components/popover.json +457 -437
  64. package/components/projects.json +129 -0
  65. package/components/protable.json +97 -8
  66. package/components/queuevisualrange.json +110 -0
  67. package/components/radio.json +82 -2
  68. package/components/rate.json +199 -0
  69. package/components/region.json +14 -2
  70. package/components/search.json +221 -0
  71. package/components/searchinput.json +132 -0
  72. package/components/searchitems.json +215 -0
  73. package/components/searchselect.json +195 -0
  74. package/components/select.json +686 -666
  75. package/components/sidebar.json +198 -0
  76. package/components/skeleton.json +233 -0
  77. package/components/spin.json +8 -1
  78. package/components/split.json +260 -0
  79. package/components/sshkeys.json +138 -0
  80. package/components/status.json +60 -3
  81. package/components/steps.json +7 -0
  82. package/components/switch.json +8 -1
  83. package/components/table.json +18 -1
  84. package/components/tablecolumnid.json +14 -2
  85. package/components/tabs.json +12 -0
  86. package/components/timeline.json +213 -0
  87. package/components/timepicker.json +147 -3
  88. package/components/timerange.json +262 -0
  89. package/components/tip.json +7 -0
  90. package/components/tooltip.json +484 -395
  91. package/components/tour.json +418 -372
  92. package/components/transfer.json +27 -3
  93. package/components/tree.json +6 -4
  94. package/components/treeselect.json +556 -475
  95. package/components/upload.json +474 -473
  96. package/components/vdialog.json +308 -0
  97. package/components/vdrawer.json +331 -0
  98. package/components/virtuallist.json +7 -0
  99. package/dist/ast/index.d.mts +35 -1
  100. package/dist/ast/index.d.ts +35 -1
  101. package/dist/ast/index.js +5 -3
  102. package/dist/ast/index.mjs +3 -1
  103. package/dist/{chunk-DSWKLUIX.mjs → chunk-3LYQ5XFM.mjs} +1 -1
  104. package/dist/chunk-BI5TIQID.mjs +330 -0
  105. package/dist/{chunk-6QS5IGS6.js → chunk-CJGGFVQJ.js} +8 -8
  106. package/dist/chunk-CR3GC4H3.js +353 -0
  107. package/dist/{chunk-NZ6TLWMD.mjs → chunk-D2SXGGTX.mjs} +28 -17
  108. package/dist/{chunk-D3Y6FGWA.js → chunk-EYKZY2F3.js} +29 -18
  109. package/dist/chunk-JSBRDJBE.js +30 -0
  110. package/dist/chunk-KF5YBEM5.js +143 -0
  111. package/dist/chunk-KMIDURUR.mjs +33324 -0
  112. package/dist/chunk-QC6VTSA3.mjs +117 -0
  113. package/dist/chunk-SZYVGYKK.js +33350 -0
  114. package/dist/{chunk-WYSRJVX4.js → chunk-TA3SV4SP.js} +2 -2
  115. package/dist/chunk-UJCSKKID.mjs +27 -0
  116. package/dist/{chunk-FVSQ6BU6.mjs → chunk-XGPHQHLR.mjs} +4 -4
  117. package/dist/docs/index.js +1 -1
  118. package/dist/docs/index.mjs +1 -1
  119. package/dist/full/index.js +8 -6
  120. package/dist/full/index.mjs +6 -4
  121. package/dist/index.d.mts +1 -0
  122. package/dist/index.d.ts +1 -0
  123. package/dist/index.js +15 -13
  124. package/dist/index.mjs +7 -5
  125. package/dist/metadata/index.d.mts +22 -2
  126. package/dist/metadata/index.d.ts +22 -2
  127. package/dist/metadata/index.js +27 -17
  128. package/dist/metadata/index.mjs +27 -16
  129. package/dist/resolve-BsLBxlBi.d.mts +24 -0
  130. package/dist/resolve-BsLBxlBi.d.ts +24 -0
  131. package/dist/runtime/index.js +5 -4
  132. package/dist/runtime/index.mjs +3 -2
  133. package/dist/shared/index.d.mts +10 -0
  134. package/dist/shared/index.d.ts +10 -0
  135. package/dist/shared/index.js +23 -0
  136. package/dist/shared/index.mjs +2 -0
  137. package/dist/static/index.js +6 -5
  138. package/dist/static/index.mjs +3 -2
  139. package/docs_for_llm/actions.doc.md +77 -0
  140. package/docs_for_llm/advancedset.doc.md +89 -0
  141. package/docs_for_llm/affix.doc.md +15 -7
  142. package/docs_for_llm/aksk.doc.md +111 -0
  143. package/docs_for_llm/az.doc.md +17 -11
  144. package/docs_for_llm/badge.doc.md +6 -5
  145. package/docs_for_llm/billtypes.doc.md +17 -11
  146. package/docs_for_llm/breadcrumb.doc.md +6 -3
  147. package/docs_for_llm/button.doc.md +34 -18
  148. package/docs_for_llm/buttonlink.doc.md +55 -0
  149. package/docs_for_llm/card.doc.md +8 -5
  150. package/docs_for_llm/cardcol.doc.md +78 -0
  151. package/docs_for_llm/cardcols.doc.md +84 -0
  152. package/docs_for_llm/cardcontent.doc.md +10 -10
  153. package/docs_for_llm/cardtabs.doc.md +106 -0
  154. package/docs_for_llm/carousel.doc.md +8 -7
  155. package/docs_for_llm/cascader.doc.md +46 -25
  156. package/docs_for_llm/checkbox.doc.md +25 -13
  157. package/docs_for_llm/cidrinput.doc.md +83 -0
  158. package/docs_for_llm/code.doc.md +22 -11
  159. package/docs_for_llm/collapse.doc.md +9 -6
  160. package/docs_for_llm/colorpicker.doc.md +104 -0
  161. package/docs_for_llm/copy.doc.md +15 -13
  162. package/docs_for_llm/copyhover.doc.md +59 -0
  163. package/docs_for_llm/copyrow.doc.md +71 -0
  164. package/docs_for_llm/datepicker.doc.md +51 -39
  165. package/docs_for_llm/description.doc.md +75 -0
  166. package/docs_for_llm/descriptions.doc.md +9 -6
  167. package/docs_for_llm/dialog.doc.md +48 -77
  168. package/docs_for_llm/divider.doc.md +9 -7
  169. package/docs_for_llm/drawer.doc.md +43 -84
  170. package/docs_for_llm/dropdown.doc.md +52 -21
  171. package/docs_for_llm/duration.doc.md +76 -0
  172. package/docs_for_llm/editable.doc.md +36 -14
  173. package/docs_for_llm/ellipsis.doc.md +10 -5
  174. package/docs_for_llm/filtertablefieldsdialog.doc.md +99 -0
  175. package/docs_for_llm/flex.doc.md +74 -0
  176. package/docs_for_llm/form.doc.md +33 -14
  177. package/docs_for_llm/formiteminput.doc.md +128 -0
  178. package/docs_for_llm/formitemspinner.doc.md +105 -0
  179. package/docs_for_llm/formitemswitch.doc.md +113 -0
  180. package/docs_for_llm/formitemtableconfigs.doc.md +95 -0
  181. package/docs_for_llm/grid.doc.md +7 -5
  182. package/docs_for_llm/header.doc.md +85 -0
  183. package/docs_for_llm/icon.doc.md +12 -8
  184. package/docs_for_llm/icontooltip.doc.md +121 -0
  185. package/docs_for_llm/input.doc.md +90 -39
  186. package/docs_for_llm/instancelist.doc.md +113 -0
  187. package/docs_for_llm/instancenum.doc.md +95 -0
  188. package/docs_for_llm/ipinput.doc.md +77 -0
  189. package/docs_for_llm/kspstatus.doc.md +82 -0
  190. package/docs_for_llm/kvcode.doc.md +76 -0
  191. package/docs_for_llm/layoutcontent.doc.md +17 -17
  192. package/docs_for_llm/layoutlistcontent.doc.md +95 -0
  193. package/docs_for_llm/layoutpermissioncontent.doc.md +84 -0
  194. package/docs_for_llm/layoutstandardlist.doc.md +120 -0
  195. package/docs_for_llm/layouttabs.doc.md +101 -0
  196. package/docs_for_llm/lazymount.doc.md +73 -0
  197. package/docs_for_llm/lazyteleport.doc.md +76 -0
  198. package/docs_for_llm/menu.doc.md +14 -11
  199. package/docs_for_llm/message.doc.md +48 -10
  200. package/docs_for_llm/pagination.doc.md +30 -17
  201. package/docs_for_llm/paginationplus.doc.md +31 -10
  202. package/docs_for_llm/password.doc.md +86 -0
  203. package/docs_for_llm/popover.doc.md +24 -55
  204. package/docs_for_llm/progress.doc.md +13 -10
  205. package/docs_for_llm/projects.doc.md +91 -0
  206. package/docs_for_llm/protable.doc.md +89 -15
  207. package/docs_for_llm/queuevisualrange.doc.md +78 -0
  208. package/docs_for_llm/radio.doc.md +23 -8
  209. package/docs_for_llm/rate.doc.md +122 -0
  210. package/docs_for_llm/region.doc.md +25 -13
  211. package/docs_for_llm/search.doc.md +120 -0
  212. package/docs_for_llm/searchinput.doc.md +111 -0
  213. package/docs_for_llm/searchitems.doc.md +116 -0
  214. package/docs_for_llm/searchselect.doc.md +126 -0
  215. package/docs_for_llm/select.doc.md +40 -55
  216. package/docs_for_llm/sidebar.doc.md +133 -0
  217. package/docs_for_llm/skeleton.doc.md +117 -0
  218. package/docs_for_llm/slider.doc.md +31 -21
  219. package/docs_for_llm/spin.doc.md +8 -5
  220. package/docs_for_llm/spinner.doc.md +28 -18
  221. package/docs_for_llm/split.doc.md +157 -0
  222. package/docs_for_llm/sshkeys.doc.md +88 -0
  223. package/docs_for_llm/status.doc.md +14 -9
  224. package/docs_for_llm/steps.doc.md +10 -7
  225. package/docs_for_llm/switch.doc.md +17 -14
  226. package/docs_for_llm/table.doc.md +118 -51
  227. package/docs_for_llm/tablecolumnid.doc.md +36 -16
  228. package/docs_for_llm/tabs.doc.md +19 -10
  229. package/docs_for_llm/tag.doc.md +19 -10
  230. package/docs_for_llm/timeline.doc.md +109 -0
  231. package/docs_for_llm/timepicker.doc.md +57 -38
  232. package/docs_for_llm/timerange.doc.md +157 -0
  233. package/docs_for_llm/tip.doc.md +20 -11
  234. package/docs_for_llm/tooltip.doc.md +55 -29
  235. package/docs_for_llm/tour.doc.md +48 -29
  236. package/docs_for_llm/transfer.doc.md +40 -29
  237. package/docs_for_llm/tree.doc.md +65 -23
  238. package/docs_for_llm/treeselect.doc.md +37 -48
  239. package/docs_for_llm/upload.doc.md +56 -32
  240. package/docs_for_llm/useCRUD.doc.md +49 -0
  241. package/docs_for_llm/useCountdown.doc.md +43 -0
  242. package/docs_for_llm/useDetail.doc.md +48 -0
  243. package/docs_for_llm/useDialog.doc.md +46 -0
  244. package/docs_for_llm/useEntity.doc.md +45 -0
  245. package/docs_for_llm/useEventListener.doc.md +44 -0
  246. package/docs_for_llm/useFalseUntilTruthy.doc.md +41 -0
  247. package/docs_for_llm/useGetCopyAuthText.doc.md +35 -0
  248. package/docs_for_llm/useGetUserPermission.doc.md +43 -0
  249. package/docs_for_llm/useGroup.doc.md +48 -0
  250. package/docs_for_llm/useIdEntities.doc.md +48 -0
  251. package/docs_for_llm/useIdEntity.doc.md +103 -0
  252. package/docs_for_llm/useInterval.doc.md +43 -0
  253. package/docs_for_llm/useLayoutStandardList.doc.md +38 -0
  254. package/docs_for_llm/useMessage.doc.md +46 -0
  255. package/docs_for_llm/useModifyCache.doc.md +37 -0
  256. package/docs_for_llm/useOpenDialog.doc.md +41 -0
  257. package/docs_for_llm/usePagination.doc.md +60 -0
  258. package/docs_for_llm/usePersist.doc.md +54 -0
  259. package/docs_for_llm/usePoll.doc.md +41 -0
  260. package/docs_for_llm/useRoutePlus.doc.md +34 -0
  261. package/docs_for_llm/useRouterPlus.doc.md +34 -0
  262. package/docs_for_llm/useSearch.doc.md +68 -0
  263. package/docs_for_llm/useShell.doc.md +43 -0
  264. package/docs_for_llm/useSkip.doc.md +41 -0
  265. package/docs_for_llm/useStorageIdEntity.doc.md +46 -0
  266. package/docs_for_llm/useStore.doc.md +34 -0
  267. package/docs_for_llm/useTable.doc.md +57 -0
  268. package/docs_for_llm/useTableGroup.doc.md +47 -0
  269. package/docs_for_llm/useTableSort.doc.md +40 -0
  270. package/docs_for_llm/useToState.doc.md +112 -0
  271. package/docs_for_llm/useUser.doc.md +38 -0
  272. package/docs_for_llm/useValidForm.doc.md +41 -0
  273. package/docs_for_llm/vdialog.doc.md +129 -0
  274. package/docs_for_llm/vdrawer.doc.md +119 -0
  275. package/docs_for_llm/virtuallist.doc.md +6 -3
  276. package/hooks/useCRUD.json +61 -0
  277. package/hooks/useCountdown.json +49 -0
  278. package/hooks/useDetail.json +67 -0
  279. package/hooks/useDialog.json +49 -0
  280. package/hooks/useEntity.json +61 -0
  281. package/hooks/useEventListener.json +61 -0
  282. package/hooks/useFalseUntilTruthy.json +43 -0
  283. package/hooks/useGetCopyAuthText.json +36 -0
  284. package/hooks/useGetUserPermission.json +55 -0
  285. package/hooks/useGroup.json +49 -0
  286. package/hooks/useIdEntities.json +61 -0
  287. package/hooks/useInterval.json +55 -0
  288. package/hooks/useLayoutStandardList.json +36 -0
  289. package/hooks/useMessage.json +73 -0
  290. package/hooks/useModifyCache.json +36 -0
  291. package/hooks/useOpenDialog.json +43 -0
  292. package/hooks/usePagination.json +49 -0
  293. package/hooks/usePersist.json +61 -0
  294. package/hooks/usePoll.json +43 -0
  295. package/hooks/useRoutePlus.json +36 -0
  296. package/hooks/useRouterPlus.json +36 -0
  297. package/hooks/useSearch.json +56 -0
  298. package/hooks/useShell.json +49 -0
  299. package/hooks/useSkip.json +43 -0
  300. package/hooks/useStorageIdEntity.json +67 -0
  301. package/hooks/useStore.json +36 -0
  302. package/hooks/useTable.json +49 -0
  303. package/hooks/useTableGroup.json +43 -0
  304. package/hooks/useTableSort.json +43 -0
  305. package/hooks/useUser.json +36 -0
  306. package/hooks/useValidForm.json +43 -0
  307. package/package.json +12 -6
  308. package/dist/chunk-HDV7ETXE.mjs +0 -1055
  309. package/dist/chunk-HPAUCD5I.js +0 -156
  310. package/dist/chunk-L4DS3EXI.mjs +0 -133
  311. package/dist/chunk-YWY3D4J7.js +0 -1082
@@ -1,1082 +0,0 @@
1
- 'use strict';
2
-
3
- var fs = require('fs/promises');
4
- var fsSync = require('fs');
5
- var path = require('path');
6
- var url = require('url');
7
- var compilerSfc = require('@vue/compiler-sfc');
8
- var ts = require('typescript');
9
-
10
- var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
11
- function _interopNamespace(e) {
12
- if (e && e.__esModule) return e;
13
- var n = Object.create(null);
14
- if (e) {
15
- Object.keys(e).forEach(function (k) {
16
- if (k !== 'default') {
17
- var d = Object.getOwnPropertyDescriptor(e, k);
18
- Object.defineProperty(n, k, d.get ? d : {
19
- enumerable: true,
20
- get: function () { return e[k]; }
21
- });
22
- }
23
- });
24
- }
25
- n.default = e;
26
- return Object.freeze(n);
27
- }
28
-
29
- var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
30
- var fsSync__namespace = /*#__PURE__*/_interopNamespace(fsSync);
31
- var path__namespace = /*#__PURE__*/_interopNamespace(path);
32
- var ts__namespace = /*#__PURE__*/_interopNamespace(ts);
33
-
34
- // src/analysis/componentRegistry.ts
35
- var __filename$1 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-YWY3D4J7.js', document.baseURI).href)));
36
- var __dirname$1 = path__namespace.dirname(__filename$1);
37
- function resolveComponentsPath() {
38
- const prodPath = path__namespace.join(__dirname$1, "../components");
39
- if (fsSync__namespace.existsSync(prodPath)) return prodPath;
40
- const devPath = path__namespace.join(__dirname$1, "../../components");
41
- if (fsSync__namespace.existsSync(devPath)) return devPath;
42
- return prodPath;
43
- }
44
- var ComponentRegistry = class {
45
- constructor() {
46
- this.components = /* @__PURE__ */ new Map();
47
- this.loaded = false;
48
- this.watcher = null;
49
- // Path to components directory (resolved dynamically for dev/prod compatibility)
50
- this.metadataPath = resolveComponentsPath();
51
- }
52
- async load() {
53
- if (this.loaded) return;
54
- await this.reload();
55
- this.loaded = true;
56
- this.startWatching();
57
- }
58
- /**
59
- * 重新加载所有组件元数据
60
- */
61
- async reload() {
62
- const newComponents = /* @__PURE__ */ new Map();
63
- try {
64
- const files = await fs__namespace.readdir(this.metadataPath);
65
- for (const file of files) {
66
- if (!file.endsWith(".json")) continue;
67
- const content = await fs__namespace.readFile(path__namespace.join(this.metadataPath, file), "utf-8");
68
- const data = JSON.parse(content);
69
- newComponents.set(data.name, data);
70
- if (data.subComponents) {
71
- for (const sub of data.subComponents) {
72
- newComponents.set(sub.name, sub);
73
- }
74
- }
75
- }
76
- this.components = newComponents;
77
- console.log(`[ComponentRegistry] ${this.loaded ? "Reloaded" : "Loaded"} ${this.components.size} components.`);
78
- } catch (error) {
79
- console.error("[ComponentRegistry] Failed to load metadata:", error);
80
- }
81
- }
82
- /**
83
- * 开始监听文件变化
84
- */
85
- startWatching() {
86
- if (this.watcher) return;
87
- try {
88
- let reloadTimeout = null;
89
- this.watcher = fsSync__namespace.watch(this.metadataPath, (eventType, filename) => {
90
- if (!filename?.endsWith(".json")) return;
91
- console.log(`[ComponentRegistry] Detected change: ${filename} (${eventType})`);
92
- if (reloadTimeout) {
93
- clearTimeout(reloadTimeout);
94
- }
95
- reloadTimeout = setTimeout(() => {
96
- this.reload();
97
- }, 500);
98
- });
99
- console.log(`[ComponentRegistry] Hot reload enabled for: ${this.metadataPath}`);
100
- } catch (error) {
101
- console.warn("[ComponentRegistry] Could not enable hot reload:", error);
102
- }
103
- }
104
- /**
105
- * 停止监听
106
- */
107
- stopWatching() {
108
- if (this.watcher) {
109
- this.watcher.close();
110
- this.watcher = null;
111
- console.log("[ComponentRegistry] Hot reload disabled.");
112
- }
113
- }
114
- getComponent(name) {
115
- return this.components.get(name);
116
- }
117
- getAllComponentNames() {
118
- return Array.from(this.components.keys());
119
- }
120
- isKnownComponent(name) {
121
- return this.components.has(name);
122
- }
123
- };
124
- var componentRegistry = new ComponentRegistry();
125
- var __filename2 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-YWY3D4J7.js', document.baseURI).href)));
126
- var __dirname2 = path__namespace.dirname(__filename2);
127
- function resolveHooksPath() {
128
- const prodPath = path__namespace.join(__dirname2, "../hooks");
129
- if (fsSync__namespace.existsSync(prodPath)) return prodPath;
130
- const devPath = path__namespace.join(__dirname2, "../../hooks");
131
- if (fsSync__namespace.existsSync(devPath)) return devPath;
132
- return prodPath;
133
- }
134
- var HooksRegistry = class {
135
- constructor() {
136
- this.hooks = /* @__PURE__ */ new Map();
137
- this.loaded = false;
138
- this.watcher = null;
139
- this.metadataPath = resolveHooksPath();
140
- }
141
- async load() {
142
- if (this.loaded) return;
143
- await this.reload();
144
- this.loaded = true;
145
- this.startWatching();
146
- }
147
- /**
148
- * 重新加载所有 hooks 元数据
149
- */
150
- async reload() {
151
- const newHooks = /* @__PURE__ */ new Map();
152
- try {
153
- const files = await fs__namespace.readdir(this.metadataPath);
154
- for (const file of files) {
155
- if (!file.endsWith(".json")) continue;
156
- const content = await fs__namespace.readFile(path__namespace.join(this.metadataPath, file), "utf-8");
157
- const data = JSON.parse(content);
158
- newHooks.set(data.name, data);
159
- }
160
- this.hooks = newHooks;
161
- if (this.hooks.size > 0) {
162
- console.log(`[HooksRegistry] ${this.loaded ? "Reloaded" : "Loaded"} ${this.hooks.size} hooks.`);
163
- }
164
- } catch (error) {
165
- if (error.code !== "ENOENT") {
166
- console.error("[HooksRegistry] Failed to load metadata:", error);
167
- }
168
- }
169
- }
170
- /**
171
- * 开始监听文件变化
172
- */
173
- startWatching() {
174
- if (this.watcher) return;
175
- try {
176
- let reloadTimeout = null;
177
- this.watcher = fsSync__namespace.watch(this.metadataPath, (eventType, filename) => {
178
- if (!filename?.endsWith(".json")) return;
179
- console.log(`[HooksRegistry] Detected change: ${filename} (${eventType})`);
180
- if (reloadTimeout) {
181
- clearTimeout(reloadTimeout);
182
- }
183
- reloadTimeout = setTimeout(() => {
184
- this.reload();
185
- }, 500);
186
- });
187
- } catch (error) {
188
- }
189
- }
190
- /**
191
- * 停止监听
192
- */
193
- stopWatching() {
194
- if (this.watcher) {
195
- this.watcher.close();
196
- this.watcher = null;
197
- }
198
- }
199
- getHook(name) {
200
- return this.hooks.get(name);
201
- }
202
- getAllHookNames() {
203
- return Array.from(this.hooks.keys());
204
- }
205
- isKnownHook(name) {
206
- return this.hooks.has(name);
207
- }
208
- /**
209
- * 获取 hook 的必填参数数量
210
- */
211
- getRequiredParamCount(name) {
212
- const hook = this.hooks.get(name);
213
- if (!hook) return 0;
214
- return hook.params.filter((p) => p.required).length;
215
- }
216
- /**
217
- * 获取 hook 的总参数数量
218
- */
219
- getTotalParamCount(name) {
220
- const hook = this.hooks.get(name);
221
- if (!hook) return 0;
222
- return hook.params.length;
223
- }
224
- };
225
- var hooksRegistry = new HooksRegistry();
226
-
227
- // src/analysis/astReviewer.ts
228
- var VUE_BUILTINS = /* @__PURE__ */ new Set([
229
- // Reactivity
230
- "ref",
231
- "reactive",
232
- "computed",
233
- "watch",
234
- "watchEffect",
235
- "watchPostEffect",
236
- "watchSyncEffect",
237
- "toRef",
238
- "toRefs",
239
- "toRaw",
240
- "markRaw",
241
- "isRef",
242
- "isReactive",
243
- "isReadonly",
244
- "isProxy",
245
- "shallowRef",
246
- "shallowReactive",
247
- "shallowReadonly",
248
- "triggerRef",
249
- "customRef",
250
- "readonly",
251
- "effectScope",
252
- "getCurrentScope",
253
- "onScopeDispose",
254
- // Lifecycle
255
- "onMounted",
256
- "onUnmounted",
257
- "onBeforeMount",
258
- "onBeforeUnmount",
259
- "onUpdated",
260
- "onBeforeUpdate",
261
- "onActivated",
262
- "onDeactivated",
263
- "onErrorCaptured",
264
- "onRenderTracked",
265
- "onRenderTriggered",
266
- "onServerPrefetch",
267
- // Composition API
268
- "defineProps",
269
- "defineEmits",
270
- "defineExpose",
271
- "defineOptions",
272
- "defineSlots",
273
- "defineModel",
274
- "withDefaults",
275
- "useSlots",
276
- "useAttrs",
277
- // Others
278
- "nextTick",
279
- "inject",
280
- "provide",
281
- "getCurrentInstance",
282
- "h",
283
- "createVNode",
284
- "resolveComponent",
285
- "resolveDirective",
286
- "withDirectives"
287
- ]);
288
- var JS_GLOBALS = /* @__PURE__ */ new Set([
289
- "console",
290
- "window",
291
- "document",
292
- "globalThis",
293
- "self",
294
- "Math",
295
- "JSON",
296
- "Date",
297
- "Array",
298
- "Object",
299
- "String",
300
- "Number",
301
- "Boolean",
302
- "Promise",
303
- "Error",
304
- "TypeError",
305
- "RangeError",
306
- "SyntaxError",
307
- "RegExp",
308
- "Map",
309
- "Set",
310
- "WeakMap",
311
- "WeakSet",
312
- "Symbol",
313
- "Proxy",
314
- "Reflect",
315
- "parseInt",
316
- "parseFloat",
317
- "isNaN",
318
- "isFinite",
319
- "encodeURI",
320
- "decodeURI",
321
- "encodeURIComponent",
322
- "decodeURIComponent",
323
- "atob",
324
- "btoa",
325
- "setTimeout",
326
- "setInterval",
327
- "clearTimeout",
328
- "clearInterval",
329
- "requestAnimationFrame",
330
- "cancelAnimationFrame",
331
- "fetch",
332
- "URL",
333
- "URLSearchParams",
334
- "FormData",
335
- "Blob",
336
- "File",
337
- "FileReader",
338
- "undefined",
339
- "null",
340
- "NaN",
341
- "Infinity",
342
- "true",
343
- "false"
344
- ]);
345
- var JS_KEYWORDS = /* @__PURE__ */ new Set([
346
- "if",
347
- "else",
348
- "for",
349
- "while",
350
- "do",
351
- "switch",
352
- "case",
353
- "break",
354
- "continue",
355
- "return",
356
- "try",
357
- "catch",
358
- "finally",
359
- "throw",
360
- "new",
361
- "delete",
362
- "typeof",
363
- "instanceof",
364
- "void",
365
- "in",
366
- "of",
367
- "this",
368
- "class",
369
- "extends",
370
- "super",
371
- "import",
372
- "export",
373
- "default",
374
- "const",
375
- "let",
376
- "var",
377
- "function",
378
- "async",
379
- "await",
380
- "yield",
381
- "true",
382
- "false",
383
- "null",
384
- "undefined",
385
- "NaN",
386
- "Infinity"
387
- ]);
388
- var TEMPLATE_BUILTINS = /* @__PURE__ */ new Set([
389
- "$event",
390
- "$refs",
391
- "$slots",
392
- "$attrs",
393
- "$emit",
394
- "$el",
395
- "$parent",
396
- "$root",
397
- "$data",
398
- "$options",
399
- "$route",
400
- "$router",
401
- "$t",
402
- "$i18n",
403
- "$n",
404
- "$d",
405
- "$te"
406
- // Vue Router & i18n
407
- ]);
408
- var NATIVE_EVENTS = /* @__PURE__ */ new Set([
409
- // Mouse
410
- "click",
411
- "dblclick",
412
- "mousedown",
413
- "mouseup",
414
- "mousemove",
415
- "mouseenter",
416
- "mouseleave",
417
- "mouseover",
418
- "mouseout",
419
- // Keyboard
420
- "keydown",
421
- "keyup",
422
- "keypress",
423
- // Focus
424
- "focus",
425
- "blur",
426
- "focusin",
427
- "focusout",
428
- // Form
429
- "input",
430
- "change",
431
- "submit",
432
- "reset",
433
- "invalid",
434
- // Drag
435
- "drag",
436
- "dragstart",
437
- "dragend",
438
- "dragenter",
439
- "dragleave",
440
- "dragover",
441
- "drop",
442
- // Clipboard
443
- "copy",
444
- "cut",
445
- "paste",
446
- // Touch
447
- "touchstart",
448
- "touchend",
449
- "touchmove",
450
- "touchcancel",
451
- // Scroll & Resize
452
- "scroll",
453
- "resize",
454
- "wheel",
455
- // Other
456
- "contextmenu",
457
- "pointerdown",
458
- "pointerup",
459
- "pointermove",
460
- "pointerenter",
461
- "pointerleave"
462
- ]);
463
- var NATIVE_HTML_ATTRIBUTES = /* @__PURE__ */ new Set([
464
- // Form attributes
465
- "maxlength",
466
- "minlength",
467
- "max",
468
- "min",
469
- "step",
470
- "pattern",
471
- "autocomplete",
472
- "autofocus",
473
- "required",
474
- "readonly",
475
- "disabled",
476
- "checked",
477
- "selected",
478
- "multiple",
479
- "accept",
480
- "name",
481
- "value",
482
- "placeholder",
483
- "form",
484
- "formaction",
485
- "formmethod",
486
- "formtarget",
487
- // Link/Navigation attributes
488
- "href",
489
- "target",
490
- "rel",
491
- "download",
492
- "hreflang",
493
- "ping",
494
- "referrerpolicy",
495
- // Media attributes
496
- "src",
497
- "alt",
498
- "width",
499
- "height",
500
- "loading",
501
- "decoding",
502
- "crossorigin",
503
- "controls",
504
- "autoplay",
505
- "loop",
506
- "muted",
507
- "poster",
508
- "preload",
509
- // Table attributes
510
- "colspan",
511
- "rowspan",
512
- "headers",
513
- "scope",
514
- // Global attributes
515
- "id",
516
- "title",
517
- "lang",
518
- "dir",
519
- "hidden",
520
- "tabindex",
521
- "accesskey",
522
- "draggable",
523
- "contenteditable",
524
- "spellcheck",
525
- "translate",
526
- "role",
527
- // ARIA attributes (common ones)
528
- "aria-label",
529
- "aria-labelledby",
530
- "aria-describedby",
531
- "aria-hidden",
532
- "aria-expanded",
533
- "aria-selected",
534
- "aria-checked",
535
- "aria-disabled",
536
- "aria-controls",
537
- "aria-haspopup"
538
- ]);
539
- var STRICT_CHECK_ATTRIBUTES = /* @__PURE__ */ new Set([
540
- "required",
541
- "disabled",
542
- "readonly",
543
- "value",
544
- "name",
545
- "checked",
546
- "selected"
547
- ]);
548
- var VERSATILE_COMPONENTS = /* @__PURE__ */ new Set([
549
- "BillTypes",
550
- "Region",
551
- "AZ",
552
- "LayoutContent",
553
- "CardContent",
554
- "ProTable",
555
- "PaginationPlus",
556
- "Status",
557
- "TableColumnId",
558
- "IconTooltip",
559
- "ButtonLink"
560
- ]);
561
- var DUAL_EXPORT_COMPONENTS = /* @__PURE__ */ new Set([
562
- "TableColumn"
563
- // 可与 ProTable 配合从 versatile 导入,也可与 Table 配合从 king-design 导入
564
- ]);
565
- var NESTING_RULES = {
566
- "DropdownItem": ["DropdownMenu"],
567
- "DropdownMenu": ["Dropdown"],
568
- "TableColumn": ["Table", "ProTable"],
569
- "FormItem": ["Form"],
570
- "Tab": ["Tabs"],
571
- "Step": ["Steps"],
572
- "MenuItem": ["Menu", "SubMenu"],
573
- "SubMenu": ["Menu"],
574
- "BreadcrumbItem": ["Breadcrumb"],
575
- "CollapseItem": ["Collapse"],
576
- "CarouselItem": ["Carousel"],
577
- "DescriptionItem": ["Descriptions"]
578
- };
579
- async function analyzeCodeWithAST(code) {
580
- await componentRegistry.load();
581
- await hooksRegistry.load();
582
- const violations = [];
583
- const { descriptor, errors } = compilerSfc.parse(code);
584
- if (errors.length > 0) {
585
- return violations;
586
- }
587
- const scriptContent = descriptor.scriptSetup?.content || descriptor.script?.content || "";
588
- if (scriptContent) {
589
- const sourceFile = ts__namespace.createSourceFile(
590
- "temp.ts",
591
- scriptContent,
592
- ts__namespace.ScriptTarget.Latest,
593
- true
594
- );
595
- ts__namespace.forEachChild(sourceFile, (node) => {
596
- if (ts__namespace.isImportDeclaration(node)) {
597
- checkImport(node, violations, sourceFile);
598
- }
599
- });
600
- }
601
- if (descriptor.template?.ast) {
602
- checkTemplate(descriptor.template.ast, violations, []);
603
- }
604
- if (scriptContent && descriptor.template) {
605
- const scriptBindings = extractScriptBindings(scriptContent);
606
- checkTemplateVariables(descriptor.template, scriptBindings, violations);
607
- }
608
- if (scriptContent) {
609
- const scriptBindings = extractScriptBindings(scriptContent);
610
- checkScriptFunctionCalls(scriptContent, scriptBindings, violations);
611
- }
612
- return violations;
613
- }
614
- function extractScriptBindings(scriptContent) {
615
- const bindings = /* @__PURE__ */ new Set();
616
- VUE_BUILTINS.forEach((b) => bindings.add(b));
617
- JS_GLOBALS.forEach((b) => bindings.add(b));
618
- try {
619
- let extractNames2 = function(name) {
620
- if (ts__namespace.isIdentifier(name)) {
621
- bindings.add(name.text);
622
- } else if (ts__namespace.isObjectBindingPattern(name) || ts__namespace.isArrayBindingPattern(name)) {
623
- name.elements.forEach((element) => {
624
- if (ts__namespace.isBindingElement(element)) {
625
- extractNames2(element.name);
626
- }
627
- });
628
- }
629
- }, visit2 = function(node) {
630
- if (ts__namespace.isVariableStatement(node)) {
631
- node.declarationList.declarations.forEach((decl) => extractNames2(decl.name));
632
- } else if (ts__namespace.isFunctionDeclaration(node) && node.name) {
633
- bindings.add(node.name.text);
634
- } else if (ts__namespace.isClassDeclaration(node) && node.name) {
635
- bindings.add(node.name.text);
636
- } else if (ts__namespace.isImportDeclaration(node)) {
637
- const namedBindings = node.importClause?.namedBindings;
638
- if (namedBindings && ts__namespace.isNamedImports(namedBindings)) {
639
- namedBindings.elements.forEach((element) => {
640
- bindings.add(element.name.text);
641
- });
642
- }
643
- if (node.importClause?.name) {
644
- bindings.add(node.importClause.name.text);
645
- }
646
- }
647
- };
648
- var extractNames = extractNames2, visit = visit2;
649
- const sourceFile = ts__namespace.createSourceFile(
650
- "temp.ts",
651
- scriptContent,
652
- ts__namespace.ScriptTarget.Latest,
653
- true
654
- );
655
- sourceFile.statements.forEach(visit2);
656
- } catch (err) {
657
- return bindings;
658
- }
659
- return bindings;
660
- }
661
- function checkScriptFunctionCalls(scriptContent, bindings, violations) {
662
- try {
663
- let visit2 = function(node) {
664
- if (ts__namespace.isCallExpression(node)) {
665
- const callee = node.expression;
666
- if (ts__namespace.isIdentifier(callee)) {
667
- const funcName = callee.text;
668
- const isHookCall = funcName.startsWith("use") && funcName.length > 3 && funcName[3] === funcName[3].toUpperCase();
669
- if (isHookCall) {
670
- if (!bindings.has(funcName)) {
671
- violations.push({
672
- rule: "\u4F7F\u7528\u4E86\u672A\u5BFC\u5165\u7684 Hook",
673
- match: `${funcName}()`,
674
- suggestion: `\u8BF7\u5148\u5BFC\u5165 ${funcName}: import { ${funcName} } from '@ksyun-internal/versatile'`
675
- });
676
- }
677
- }
678
- }
679
- }
680
- ts__namespace.forEachChild(node, visit2);
681
- };
682
- var visit = visit2;
683
- const sourceFile = ts__namespace.createSourceFile(
684
- "temp.ts",
685
- scriptContent,
686
- ts__namespace.ScriptTarget.Latest,
687
- true
688
- );
689
- ts__namespace.forEachChild(sourceFile, visit2);
690
- } catch (err) {
691
- }
692
- }
693
- function checkTemplateVariables(template, bindings, violations) {
694
- const templateContent = template.content;
695
- const templateAst = template.ast;
696
- const localVariables = /* @__PURE__ */ new Set();
697
- if (templateAst) {
698
- let walk2 = function(node) {
699
- if (node.type === 0 || node.type === 1) {
700
- const vFor = node.props?.find((p) => p.type === 7 && p.name === "for");
701
- if (vFor && vFor.exp) {
702
- if (vFor.parseResult) {
703
- const { value, key, index } = vFor.parseResult;
704
- if (value) extractIdentifiersFromTemplateAST(value, localVariables);
705
- if (key) extractIdentifiersFromTemplateAST(key, localVariables);
706
- if (index) extractIdentifiersFromTemplateAST(index, localVariables);
707
- } else if (vFor.exp.content) {
708
- extractIdentifiersFromTemplateAST(vFor.exp, localVariables);
709
- }
710
- }
711
- const vSlot = node.props?.find((p) => p.type === 7 && p.name === "slot");
712
- if (vSlot && vSlot.exp) {
713
- extractIdentifiersFromTemplateAST(vSlot.exp, localVariables);
714
- }
715
- if (node.children) {
716
- node.children.forEach(walk2);
717
- }
718
- }
719
- };
720
- walk2(templateAst);
721
- }
722
- const allBindings = /* @__PURE__ */ new Set([...bindings, ...localVariables]);
723
- const interpolationRegex = /\{\{\s*([^}]+)\s*\}\}/g;
724
- let match;
725
- while ((match = interpolationRegex.exec(templateContent)) !== null) {
726
- const expression = match[1].trim();
727
- const { identifiers, locals } = extractIdentifiersFromExpression(expression);
728
- const combinedBindings = /* @__PURE__ */ new Set([...allBindings, ...locals]);
729
- for (const id of identifiers) {
730
- if (!combinedBindings.has(id) && !isTemplateBuiltin(id)) {
731
- violations.push({
732
- rule: `\u6A21\u677F\u5F15\u7528\u4E86\u672A\u5B9A\u4E49\u7684\u53D8\u91CF: ${id}`,
733
- match: `{{ ${expression} }}`,
734
- suggestion: `\u8BF7\u786E\u4FDD\u5728 <script setup> \u4E2D\u5B9A\u4E49\u53D8\u91CF ${id}\uFF0C\u6216\u68C0\u67E5\u62FC\u5199\u662F\u5426\u6B63\u786E`
735
- });
736
- }
737
- }
738
- }
739
- const bindRegex = /(?::|v-bind:)[\w.-]+="([^"]+)"/g;
740
- while ((match = bindRegex.exec(templateContent)) !== null) {
741
- const expression = match[1].trim();
742
- const { identifiers, locals } = extractIdentifiersFromExpression(expression);
743
- const combinedBindings = /* @__PURE__ */ new Set([...allBindings, ...locals]);
744
- for (const id of identifiers) {
745
- if (!combinedBindings.has(id) && !isTemplateBuiltin(id)) {
746
- violations.push({
747
- rule: `\u7ED1\u5B9A\u5C5E\u6027\u5F15\u7528\u4E86\u672A\u5B9A\u4E49\u7684\u53D8\u91CF: ${id}`,
748
- match: match[0],
749
- suggestion: `\u8BF7\u786E\u4FDD\u5728 <script setup> \u4E2D\u5B9A\u4E49\u53D8\u91CF ${id}`
750
- });
751
- }
752
- }
753
- }
754
- const eventRegex = /(?:@|v-on:)[\w.-]+="([^"]+)"/g;
755
- while ((match = eventRegex.exec(templateContent)) !== null) {
756
- const expression = match[1].trim();
757
- const { identifiers, locals } = extractIdentifiersFromExpression(expression);
758
- const combinedBindings = /* @__PURE__ */ new Set([...allBindings, ...locals]);
759
- for (const id of identifiers) {
760
- if (!combinedBindings.has(id) && !isTemplateBuiltin(id)) {
761
- violations.push({
762
- rule: `\u4E8B\u4EF6\u5904\u7406\u5668\u5F15\u7528\u4E86\u672A\u5B9A\u4E49\u7684\u51FD\u6570/\u53D8\u91CF: ${id}`,
763
- match: match[0],
764
- suggestion: `\u8BF7\u786E\u4FDD\u5728 <script setup> \u4E2D\u5B9A\u4E49 ${id}`
765
- });
766
- }
767
- }
768
- }
769
- }
770
- function extractIdentifiersFromTemplateAST(node, set) {
771
- if (!node || typeof node !== "object") return;
772
- const n = node;
773
- if (n.type === 4 && n.content) {
774
- const matches = n.content.match(/\b([a-zA-Z_$][a-zA-Z0-9_$]*)\b/g);
775
- if (matches) {
776
- matches.forEach((m) => {
777
- if (!isJsKeyword(m)) set.add(m);
778
- });
779
- }
780
- } else if (n.type === 8 && n.children) {
781
- n.children.forEach((c) => extractIdentifiersFromTemplateAST(c, set));
782
- }
783
- }
784
- function extractIdentifiersFromExpression(expression) {
785
- const identifiers = [];
786
- const locals = [];
787
- const arrowFuncRegex = /(?:(?:\(([^)]+)\))|([a-zA-Z_$][\w$]*))\s*=>/g;
788
- let arrowMatch;
789
- while ((arrowMatch = arrowFuncRegex.exec(expression)) !== null) {
790
- const params = arrowMatch[1] || arrowMatch[2];
791
- if (params) {
792
- const paramNames = params.split(",").map((p) => p.trim().split(":")[0].trim());
793
- paramNames.forEach((p) => {
794
- const subMatches = p.match(/\b([a-zA-Z_$][\w$]*)\b/g);
795
- if (subMatches) subMatches.forEach((sm) => {
796
- if (!isJsKeyword(sm)) locals.push(sm);
797
- });
798
- });
799
- }
800
- }
801
- const cleanExpr = expression.replace(/'[^']*'/g, "").replace(/"[^"]*"/g, "").replace(/`[^`]*`/g, "");
802
- const idRegex = /(?:^|[^.\w$])([a-zA-Z_$][\w$]*)\b(?!\s*:)/g;
803
- let match;
804
- while ((match = idRegex.exec(cleanExpr)) !== null) {
805
- const id = match[1];
806
- if (!isJsKeyword(id) && !locals.includes(id)) {
807
- identifiers.push(id);
808
- }
809
- }
810
- return { identifiers: [...new Set(identifiers)], locals: [...new Set(locals)] };
811
- }
812
- function isTemplateBuiltin(id) {
813
- return TEMPLATE_BUILTINS.has(id);
814
- }
815
- function isJsKeyword(id) {
816
- return JS_KEYWORDS.has(id);
817
- }
818
- function checkImport(node, violations, sourceFile) {
819
- const moduleSpecifier = node.moduleSpecifier.getText(sourceFile).replace(/['\"]/g, "");
820
- if (moduleSpecifier === "@king-design/vue" || moduleSpecifier === "@ksyun-internal/versatile") {
821
- const namedBindings = node.importClause?.namedBindings;
822
- if (namedBindings && ts__namespace.isNamedImports(namedBindings)) {
823
- namedBindings.elements.forEach((element) => {
824
- const originalName = element.propertyName ? element.propertyName.text : element.name.text;
825
- const localName = element.name.text;
826
- const isAlias = !!element.propertyName;
827
- const isHook = originalName.startsWith("use") && originalName.length > 3 && originalName[3] === originalName[3].toUpperCase();
828
- if (isHook) {
829
- if (moduleSpecifier !== "@ksyun-internal/versatile") {
830
- violations.push({
831
- rule: `Hook ${originalName} \u5BFC\u5165\u6E90\u9519\u8BEF`,
832
- match: `import { ${originalName} } from '${moduleSpecifier}'`,
833
- suggestion: `\u5E94\u4ECE '@ksyun-internal/versatile' \u5BFC\u5165`
834
- });
835
- return;
836
- }
837
- if (!hooksRegistry.isKnownHook(originalName)) {
838
- violations.push({
839
- rule: "\u5F15\u7528\u4E86\u4E0D\u5B58\u5728\u7684 Hook",
840
- match: originalName,
841
- suggestion: `Hook ${originalName} \u4E0D\u5B58\u5728\u4E8E @ksyun-internal/versatile\u3002\u53EF\u7528\u7684 Hooks: ${hooksRegistry.getAllHookNames().join(", ") || "\u6682\u65E0"}`
842
- });
843
- return;
844
- }
845
- if (isAlias) {
846
- violations.push({
847
- rule: `\u7981\u6B62\u5BF9 Hook ${originalName} \u4F7F\u7528\u522B\u540D\u5BFC\u5165`,
848
- match: `${originalName} as ${localName}`,
849
- suggestion: `\u76F4\u63A5\u4F7F\u7528\u539F\u540D: import { ${originalName} } from '${moduleSpecifier}'`
850
- });
851
- }
852
- return;
853
- }
854
- if (isAlias) {
855
- violations.push({
856
- rule: `\u7981\u6B62\u5BF9\u7EC4\u4EF6 ${originalName} \u4F7F\u7528\u522B\u540D\u5BFC\u5165`,
857
- match: `${originalName} as ${localName}`,
858
- suggestion: `\u76F4\u63A5\u4F7F\u7528\u539F\u540D: import { ${originalName} } from '${moduleSpecifier}'`
859
- });
860
- }
861
- if (componentRegistry.isKnownComponent(originalName)) {
862
- if (DUAL_EXPORT_COMPONENTS.has(originalName)) {
863
- return;
864
- }
865
- const isVersatile = VERSATILE_COMPONENTS.has(originalName);
866
- const expectedPackage = isVersatile ? "@ksyun-internal/versatile" : "@king-design/vue";
867
- if (expectedPackage !== moduleSpecifier) {
868
- violations.push({
869
- rule: `\u7EC4\u4EF6 ${originalName} \u5BFC\u5165\u6E90\u9519\u8BEF`,
870
- match: `import { ... } from '${moduleSpecifier}'`,
871
- suggestion: `\u5E94\u4ECE '${expectedPackage}' \u5BFC\u5165`
872
- });
873
- }
874
- } else {
875
- violations.push({
876
- rule: "\u5F15\u7528\u4E86\u4E0D\u5B58\u5728\u7684\u7EC4\u4EF6/\u5BFC\u51FA",
877
- match: originalName,
878
- suggestion: `\u8BF7\u786E\u8BA4 ${originalName} \u662F\u5426\u5B58\u5728\u4E8E ${moduleSpecifier}\u3002\u5EFA\u8BAE\u67E5\u770B\u6587\u6863\u3002`
879
- });
880
- }
881
- });
882
- }
883
- }
884
- }
885
- function checkNestingRules(tagName, metadata, ancestors, violations) {
886
- const requiredParents = metadata?.requiredParent ? [metadata.requiredParent] : NESTING_RULES[tagName];
887
- if (!requiredParents || requiredParents.length === 0) return;
888
- const hasValidAncestor = ancestors.some(
889
- (ancestor) => requiredParents.includes(ancestor) || ancestor === "template"
890
- );
891
- if (!hasValidAncestor && ancestors.length > 0) {
892
- violations.push({
893
- rule: `${tagName} \u5FC5\u987B\u653E\u5728 ${requiredParents.join(" \u6216 ")} \u7EC4\u4EF6\u5185`,
894
- match: tagName,
895
- suggestion: `\u8BF7\u5C06 ${tagName} \u79FB\u52A8\u5230 ${requiredParents[0]} \u7EC4\u4EF6\u4E2D`
896
- });
897
- }
898
- }
899
- function checkComponentSpecificRules(tagName, node, violations) {
900
- if (tagName === "Dropdown") {
901
- node.children?.forEach((child) => {
902
- if (child.type === 1 && child.tag === "template") {
903
- const slotProp = child.props?.find(
904
- (p) => p.type === 7 && p.name === "slot" && p.arg?.content === "menu"
905
- );
906
- if (slotProp) {
907
- violations.push({
908
- rule: "DropdownMenu \u4E0D\u80FD\u653E\u5728 #menu \u63D2\u69FD\u4E2D",
909
- match: "<template #menu>",
910
- suggestion: "\u8BF7\u79FB\u9664 <template #menu>\uFF0C\u5C06 DropdownMenu \u76F4\u63A5\u4F5C\u4E3A Dropdown \u7684\u7B2C\u4E8C\u4E2A\u5B50\u5143\u7D20"
911
- });
912
- }
913
- }
914
- });
915
- }
916
- if (tagName === "Table") {
917
- node.props.forEach((prop) => {
918
- if (prop.type === 6 && (prop.name === "rowKey" || prop.name === "row-key")) {
919
- violations.push({
920
- rule: "Table\u7EC4\u4EF6 rowKey \u5C5E\u6027 usage \u9519\u8BEF",
921
- match: `rowKey="${prop.value?.content || ""}"`,
922
- suggestion: 'rowKey \u5FC5\u987B\u662F\u4E00\u4E2A\u8FD4\u56DE\u552F\u4E00\u503C\u7684\u51FD\u6570\u3002\u8BF7\u4F7F\u7528\u7ED1\u5B9A\u8BED\u6CD5\uFF0C\u4F8B\u5982 :rowKey="(row) => row.id"'
923
- });
924
- }
925
- });
926
- }
927
- if (tagName === "Icon") {
928
- node.props.forEach((prop) => {
929
- if (prop.type === 6 && prop.name === "name") {
930
- violations.push({
931
- rule: "Icon \u7EC4\u4EF6\u7981\u6B62\u4F7F\u7528 name \u5C5E\u6027",
932
- match: `name="${prop.value?.content || ""}"`,
933
- suggestion: '\u8BF7\u4F7F\u7528 class \u5C5E\u6027\u6307\u5B9A\u56FE\u6807\uFF0C\u4F8B\u5982: class="k-icon-search"'
934
- });
935
- }
936
- });
937
- }
938
- if (tagName === "TableColumn") {
939
- node.children?.forEach((child) => {
940
- if (child.type === 1 && child.tag === "template") {
941
- const slotProp = child.props?.find((p) => p.type === 7 && p.name === "slot");
942
- if (slotProp && slotProp.exp && slotProp.exp.content) {
943
- const exp = slotProp.exp.content.trim();
944
- if (exp.startsWith("{") && exp.endsWith("}")) {
945
- violations.push({
946
- rule: "TableColumn \u63D2\u69FD\u53C2\u6570\u5E94\u4E3A\u6570\u7EC4\u7ED3\u6784",
947
- match: exp,
948
- suggestion: `King Design \u8868\u683C\u63D2\u69FD\u53C2\u6570\u4E3A\u6570\u7EC4\u987A\u5E8F\u4F20\u9012\uFF0C\u8BF7\u5C06 ${exp} \u6539\u4E3A [row]`
949
- });
950
- }
951
- }
952
- }
953
- });
954
- }
955
- }
956
- function checkProps(tagName, node, metadata, violations) {
957
- let customTagName = null;
958
- const tagNameProp = node.props.find(
959
- (p) => p.type === 6 && p.name === "tagName" || p.type === 7 && p.name === "bind" && p.arg?.content === "tagName"
960
- );
961
- if (tagNameProp?.type === 6 && tagNameProp.value?.content) {
962
- customTagName = tagNameProp.value.content;
963
- }
964
- const dynamicAllowedProps = [];
965
- if (customTagName === "a") {
966
- dynamicAllowedProps.push("href", "target", "rel", "download");
967
- }
968
- node.props.forEach((prop) => {
969
- if (prop.type !== 6) return;
970
- const propName = prop.name;
971
- const camelCaseProp = propName.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
972
- const isPropValid = metadata.props?.some(
973
- (p) => p.name === propName || p.name === camelCaseProp || p.name.toLowerCase() === propName.toLowerCase()
974
- );
975
- const isDynamicallyAllowed = dynamicAllowedProps.includes(propName);
976
- const isBuiltinProp = ["class", "style", "key", "ref"].includes(propName) || propName.startsWith("data-");
977
- const isNativeHtmlAttr = NATIVE_HTML_ATTRIBUTES.has(propName) || propName.startsWith("aria-");
978
- const isStrictAttr = STRICT_CHECK_ATTRIBUTES.has(propName);
979
- const isNativeIgnored = isNativeHtmlAttr && isStrictAttr && metadata.props;
980
- if (!isPropValid && !isDynamicallyAllowed && !isBuiltinProp && (!isNativeHtmlAttr || isNativeIgnored)) {
981
- if (metadata.props && metadata.props.length > 0) {
982
- violations.push({
983
- rule: `\u5C5E\u6027 ${propName} \u4E0D\u5B58\u5728\u4E8E ${tagName}${isNativeIgnored ? " (\u8BE5\u7EC4\u4EF6\u4E0D\u652F\u6301\u6B64\u539F\u751F\u5C5E\u6027)" : ""}`,
984
- match: propName,
985
- suggestion: `\u53EF\u7528\u5C5E\u6027: ${metadata.props.map((p) => p.name).join(", ")}`
986
- });
987
- }
988
- }
989
- if (isPropValid && metadata.props) {
990
- const targetProp = metadata.props.find(
991
- (p) => p.name === propName || p.name === camelCaseProp || p.name.toLowerCase() === propName.toLowerCase()
992
- );
993
- if (targetProp) {
994
- const attrValue = prop.value?.content;
995
- if (attrValue) {
996
- let cleanAllowedValues = [];
997
- if (targetProp.allowedValues && targetProp.allowedValues.length > 0) {
998
- cleanAllowedValues = targetProp.allowedValues.map((av) => String(av.value).replace(/['"]/g, ""));
999
- } else if (targetProp.type?.kind === "union" && targetProp.type.unionTypes) {
1000
- cleanAllowedValues = targetProp.type.unionTypes.map((v) => String(v).replace(/['"]/g, ""));
1001
- }
1002
- if (cleanAllowedValues.length > 0 && !cleanAllowedValues.includes(attrValue)) {
1003
- violations.push({
1004
- rule: `${tagName} \u7684\u5C5E\u6027 ${propName} \u7684\u503C "${attrValue}" \u65E0\u6548`,
1005
- match: `${propName}="${attrValue}"`,
1006
- suggestion: `\u5141\u8BB8\u7684\u503C: ${cleanAllowedValues.join(" | ")}`
1007
- });
1008
- }
1009
- }
1010
- }
1011
- }
1012
- });
1013
- }
1014
- function checkEvents(tagName, node, metadata, violations) {
1015
- node.props.forEach((prop) => {
1016
- if (prop.type !== 7) return;
1017
- if (prop.name !== "on") return;
1018
- const arg = prop.arg;
1019
- const eventName = arg && "content" in arg ? arg.content : null;
1020
- if (!eventName) return;
1021
- if (eventName.startsWith("$change:") || eventName.startsWith("update:")) {
1022
- return;
1023
- }
1024
- const camelCaseEvent = eventName.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
1025
- const isEventValid = metadata.events?.some(
1026
- (e) => e.name === eventName || e.name === camelCaseEvent || e.name.toLowerCase() === eventName.toLowerCase()
1027
- );
1028
- const isNativeEvent = NATIVE_EVENTS.has(eventName);
1029
- if (!isEventValid && !isNativeEvent && metadata.events && metadata.events.length > 0) {
1030
- violations.push({
1031
- rule: `\u4E8B\u4EF6 @${eventName} \u4E0D\u5B58\u5728\u4E8E ${tagName}`,
1032
- match: `@${eventName}`,
1033
- suggestion: `\u53EF\u7528\u4E8B\u4EF6: ${metadata.events.map((e) => e.name).join(", ") || "\u65E0\u81EA\u5B9A\u4E49\u4E8B\u4EF6"}`
1034
- });
1035
- }
1036
- });
1037
- }
1038
- function checkSlots(tagName, node, metadata, violations) {
1039
- if (!node.children || !metadata.slots?.length) return;
1040
- node.children.forEach((child) => {
1041
- if (child.type !== 1 || child.tag !== "template") return;
1042
- child.props.forEach((prop) => {
1043
- if (prop.type !== 7 || prop.name !== "slot") return;
1044
- const slotName = prop.arg?.content || "default";
1045
- const isSlotValid = metadata.slots?.some((s) => s.name === slotName);
1046
- if (!isSlotValid) {
1047
- violations.push({
1048
- rule: `\u63D2\u69FD #${slotName} \u4E0D\u5B58\u5728\u4E8E ${tagName}`,
1049
- match: `#${slotName}`,
1050
- suggestion: `\u53EF\u7528\u63D2\u69FD: ${metadata.slots.map((s) => s.name).join(", ")}`
1051
- });
1052
- }
1053
- });
1054
- });
1055
- }
1056
- function checkTemplate(node, violations, ancestors) {
1057
- if (node.type === 1) {
1058
- const elementNode = node;
1059
- const tagName = elementNode.tag;
1060
- const metadata = componentRegistry.isKnownComponent(tagName) ? componentRegistry.getComponent(tagName) : null;
1061
- if (metadata) {
1062
- checkNestingRules(tagName, metadata, ancestors, violations);
1063
- }
1064
- checkComponentSpecificRules(tagName, elementNode, violations);
1065
- if (metadata) {
1066
- checkProps(tagName, elementNode, metadata, violations);
1067
- checkEvents(tagName, elementNode, metadata, violations);
1068
- checkSlots(tagName, elementNode, metadata, violations);
1069
- }
1070
- }
1071
- if ("children" in node && Array.isArray(node.children)) {
1072
- const newAncestors = node.type === 1 && "tag" in node ? [...ancestors, node.tag] : ancestors;
1073
- node.children.forEach((child) => {
1074
- if (typeof child === "object" && child !== null && "type" in child) {
1075
- checkTemplate(child, violations, newAncestors);
1076
- }
1077
- });
1078
- }
1079
- }
1080
-
1081
- exports.analyzeCodeWithAST = analyzeCodeWithAST;
1082
- exports.componentRegistry = componentRegistry;