king-design-analyzer 2.1.1 → 2.1.3

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/dist/ast/index.js CHANGED
@@ -1,15 +1,15 @@
1
1
  'use strict';
2
2
 
3
3
  require('../chunk-YTEYDSDW.js');
4
- var chunkTKBNPZIO_js = require('../chunk-TKBNPZIO.js');
4
+ var chunkGW5YOUB7_js = require('../chunk-GW5YOUB7.js');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "analyzeCodeWithAST", {
9
9
  enumerable: true,
10
- get: function () { return chunkTKBNPZIO_js.analyzeCodeWithAST; }
10
+ get: function () { return chunkGW5YOUB7_js.analyzeCodeWithAST; }
11
11
  });
12
12
  Object.defineProperty(exports, "componentRegistry", {
13
13
  enumerable: true,
14
- get: function () { return chunkTKBNPZIO_js.componentRegistry; }
14
+ get: function () { return chunkGW5YOUB7_js.componentRegistry; }
15
15
  });
@@ -1,2 +1,2 @@
1
1
  import '../chunk-5H7N2A5X.mjs';
2
- export { analyzeCodeWithAST, componentRegistry } from '../chunk-27IE6LRY.mjs';
2
+ export { analyzeCodeWithAST, componentRegistry } from '../chunk-UYVGHUC5.mjs';
@@ -1,4 +1,4 @@
1
- import { analyzeCodeWithAST } from './chunk-27IE6LRY.mjs';
1
+ import { analyzeCodeWithAST } from './chunk-UYVGHUC5.mjs';
2
2
  import { validateRuntimePrecheck } from './chunk-ZONZNAWA.mjs';
3
3
  import { compileSFC } from './chunk-WJAGRAWV.mjs';
4
4
 
@@ -32,7 +32,7 @@ var path__namespace = /*#__PURE__*/_interopNamespace(path);
32
32
  var ts__namespace = /*#__PURE__*/_interopNamespace(ts);
33
33
 
34
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-TKBNPZIO.js', document.baseURI).href)));
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-GW5YOUB7.js', document.baseURI).href)));
36
36
  var __dirname$1 = path__namespace.dirname(__filename$1);
37
37
  function resolveComponentsPath() {
38
38
  const prodPath = path__namespace.join(__dirname$1, "../components");
@@ -122,7 +122,7 @@ var ComponentRegistry = class {
122
122
  }
123
123
  };
124
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-TKBNPZIO.js', document.baseURI).href)));
125
+ var __filename2 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-GW5YOUB7.js', document.baseURI).href)));
126
126
  var __dirname2 = path__namespace.dirname(__filename2);
127
127
  function resolveHooksPath() {
128
128
  const prodPath = path__namespace.join(__dirname2, "../hooks");
@@ -596,6 +596,10 @@ async function analyzeCodeWithAST(code) {
596
596
  const scriptBindings = extractScriptBindings(scriptContent);
597
597
  checkTemplateVariables(descriptor.template, scriptBindings, violations);
598
598
  }
599
+ if (scriptContent) {
600
+ const scriptBindings = extractScriptBindings(scriptContent);
601
+ checkScriptFunctionCalls(scriptContent, scriptBindings, violations);
602
+ }
599
603
  return violations;
600
604
  }
601
605
  function extractScriptBindings(scriptContent) {
@@ -645,6 +649,38 @@ function extractScriptBindings(scriptContent) {
645
649
  }
646
650
  return bindings;
647
651
  }
652
+ function checkScriptFunctionCalls(scriptContent, bindings, violations) {
653
+ try {
654
+ let visit2 = function(node) {
655
+ if (ts__namespace.isCallExpression(node)) {
656
+ const callee = node.expression;
657
+ if (ts__namespace.isIdentifier(callee)) {
658
+ const funcName = callee.text;
659
+ const isHookCall = funcName.startsWith("use") && funcName.length > 3 && funcName[3] === funcName[3].toUpperCase();
660
+ if (isHookCall) {
661
+ if (!bindings.has(funcName)) {
662
+ violations.push({
663
+ rule: "\u4F7F\u7528\u4E86\u672A\u5BFC\u5165\u7684 Hook",
664
+ match: `${funcName}()`,
665
+ suggestion: `\u8BF7\u5148\u5BFC\u5165 ${funcName}: import { ${funcName} } from '@ksyun-internal/versatile'`
666
+ });
667
+ }
668
+ }
669
+ }
670
+ }
671
+ ts__namespace.forEachChild(node, visit2);
672
+ };
673
+ var visit = visit2;
674
+ const sourceFile = ts__namespace.createSourceFile(
675
+ "temp.ts",
676
+ scriptContent,
677
+ ts__namespace.ScriptTarget.Latest,
678
+ true
679
+ );
680
+ ts__namespace.forEachChild(sourceFile, visit2);
681
+ } catch (err) {
682
+ }
683
+ }
648
684
  function checkTemplateVariables(template, bindings, violations) {
649
685
  const templateContent = template.content;
650
686
  const templateAst = template.ast;
@@ -790,6 +826,11 @@ function checkImport(node, violations, sourceFile) {
790
826
  return;
791
827
  }
792
828
  if (!hooksRegistry.isKnownHook(originalName)) {
829
+ violations.push({
830
+ rule: "\u5F15\u7528\u4E86\u4E0D\u5B58\u5728\u7684 Hook",
831
+ match: originalName,
832
+ suggestion: `Hook ${originalName} \u4E0D\u5B58\u5728\u4E8E @ksyun-internal/versatile\u3002\u53EF\u7528\u7684 Hooks: ${hooksRegistry.getAllHookNames().join(", ") || "\u6682\u65E0"}`
833
+ });
793
834
  return;
794
835
  }
795
836
  if (isAlias) {
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkTKBNPZIO_js = require('./chunk-TKBNPZIO.js');
3
+ var chunkGW5YOUB7_js = require('./chunk-GW5YOUB7.js');
4
4
  var chunkY77A3DEY_js = require('./chunk-Y77A3DEY.js');
5
5
  var chunk2L37YJOJ_js = require('./chunk-2L37YJOJ.js');
6
6
 
@@ -64,7 +64,7 @@ function validateCompilation(code) {
64
64
  }
65
65
  async function validateAST(code) {
66
66
  try {
67
- const violations = await chunkTKBNPZIO_js.analyzeCodeWithAST(code);
67
+ const violations = await chunkGW5YOUB7_js.analyzeCodeWithAST(code);
68
68
  if (violations.length > 0) {
69
69
  return {
70
70
  name: "AST\u89C4\u5219\u68C0\u67E5",
@@ -570,6 +570,10 @@ async function analyzeCodeWithAST(code) {
570
570
  const scriptBindings = extractScriptBindings(scriptContent);
571
571
  checkTemplateVariables(descriptor.template, scriptBindings, violations);
572
572
  }
573
+ if (scriptContent) {
574
+ const scriptBindings = extractScriptBindings(scriptContent);
575
+ checkScriptFunctionCalls(scriptContent, scriptBindings, violations);
576
+ }
573
577
  return violations;
574
578
  }
575
579
  function extractScriptBindings(scriptContent) {
@@ -619,6 +623,38 @@ function extractScriptBindings(scriptContent) {
619
623
  }
620
624
  return bindings;
621
625
  }
626
+ function checkScriptFunctionCalls(scriptContent, bindings, violations) {
627
+ try {
628
+ let visit2 = function(node) {
629
+ if (ts.isCallExpression(node)) {
630
+ const callee = node.expression;
631
+ if (ts.isIdentifier(callee)) {
632
+ const funcName = callee.text;
633
+ const isHookCall = funcName.startsWith("use") && funcName.length > 3 && funcName[3] === funcName[3].toUpperCase();
634
+ if (isHookCall) {
635
+ if (!bindings.has(funcName)) {
636
+ violations.push({
637
+ rule: "\u4F7F\u7528\u4E86\u672A\u5BFC\u5165\u7684 Hook",
638
+ match: `${funcName}()`,
639
+ suggestion: `\u8BF7\u5148\u5BFC\u5165 ${funcName}: import { ${funcName} } from '@ksyun-internal/versatile'`
640
+ });
641
+ }
642
+ }
643
+ }
644
+ }
645
+ ts.forEachChild(node, visit2);
646
+ };
647
+ var visit = visit2;
648
+ const sourceFile = ts.createSourceFile(
649
+ "temp.ts",
650
+ scriptContent,
651
+ ts.ScriptTarget.Latest,
652
+ true
653
+ );
654
+ ts.forEachChild(sourceFile, visit2);
655
+ } catch (err) {
656
+ }
657
+ }
622
658
  function checkTemplateVariables(template, bindings, violations) {
623
659
  const templateContent = template.content;
624
660
  const templateAst = template.ast;
@@ -764,6 +800,11 @@ function checkImport(node, violations, sourceFile) {
764
800
  return;
765
801
  }
766
802
  if (!hooksRegistry.isKnownHook(originalName)) {
803
+ violations.push({
804
+ rule: "\u5F15\u7528\u4E86\u4E0D\u5B58\u5728\u7684 Hook",
805
+ match: originalName,
806
+ suggestion: `Hook ${originalName} \u4E0D\u5B58\u5728\u4E8E @ksyun-internal/versatile\u3002\u53EF\u7528\u7684 Hooks: ${hooksRegistry.getAllHookNames().join(", ") || "\u6682\u65E0"}`
807
+ });
767
808
  return;
768
809
  }
769
810
  if (isAlias) {
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkDMQS5OPY_js = require('../chunk-DMQS5OPY.js');
4
- require('../chunk-TKBNPZIO.js');
3
+ var chunkRHPVVTOE_js = require('../chunk-RHPVVTOE.js');
4
+ require('../chunk-GW5YOUB7.js');
5
5
  require('../chunk-Y77A3DEY.js');
6
6
  require('../chunk-2L37YJOJ.js');
7
7
 
@@ -9,9 +9,9 @@ require('../chunk-2L37YJOJ.js');
9
9
 
10
10
  Object.defineProperty(exports, "validateCode", {
11
11
  enumerable: true,
12
- get: function () { return chunkDMQS5OPY_js.validateCode; }
12
+ get: function () { return chunkRHPVVTOE_js.validateCode; }
13
13
  });
14
14
  Object.defineProperty(exports, "validateCodeSync", {
15
15
  enumerable: true,
16
- get: function () { return chunkDMQS5OPY_js.validateCodeSync; }
16
+ get: function () { return chunkRHPVVTOE_js.validateCodeSync; }
17
17
  });
@@ -1,4 +1,4 @@
1
- export { validateCode, validateCodeSync } from '../chunk-WHYAD7JV.mjs';
2
- import '../chunk-27IE6LRY.mjs';
1
+ export { validateCode, validateCodeSync } from '../chunk-4G533OEX.mjs';
2
+ import '../chunk-UYVGHUC5.mjs';
3
3
  import '../chunk-ZONZNAWA.mjs';
4
4
  import '../chunk-WJAGRAWV.mjs';
package/dist/index.js CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  var chunkREPE4KTQ_js = require('./chunk-REPE4KTQ.js');
4
4
  require('./chunk-YTEYDSDW.js');
5
- var chunkDMQS5OPY_js = require('./chunk-DMQS5OPY.js');
6
- var chunkTKBNPZIO_js = require('./chunk-TKBNPZIO.js');
5
+ var chunkRHPVVTOE_js = require('./chunk-RHPVVTOE.js');
6
+ var chunkGW5YOUB7_js = require('./chunk-GW5YOUB7.js');
7
7
  var chunkY77A3DEY_js = require('./chunk-Y77A3DEY.js');
8
8
  var chunk2L37YJOJ_js = require('./chunk-2L37YJOJ.js');
9
9
 
@@ -15,19 +15,19 @@ Object.defineProperty(exports, "validateCompilation", {
15
15
  });
16
16
  Object.defineProperty(exports, "validateCode", {
17
17
  enumerable: true,
18
- get: function () { return chunkDMQS5OPY_js.validateCode; }
18
+ get: function () { return chunkRHPVVTOE_js.validateCode; }
19
19
  });
20
20
  Object.defineProperty(exports, "validateCodeSync", {
21
21
  enumerable: true,
22
- get: function () { return chunkDMQS5OPY_js.validateCodeSync; }
22
+ get: function () { return chunkRHPVVTOE_js.validateCodeSync; }
23
23
  });
24
24
  Object.defineProperty(exports, "analyzeCodeWithAST", {
25
25
  enumerable: true,
26
- get: function () { return chunkTKBNPZIO_js.analyzeCodeWithAST; }
26
+ get: function () { return chunkGW5YOUB7_js.analyzeCodeWithAST; }
27
27
  });
28
28
  Object.defineProperty(exports, "componentRegistry", {
29
29
  enumerable: true,
30
- get: function () { return chunkTKBNPZIO_js.componentRegistry; }
30
+ get: function () { return chunkGW5YOUB7_js.componentRegistry; }
31
31
  });
32
32
  Object.defineProperty(exports, "validateRuntimePrecheck", {
33
33
  enumerable: true,
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  export { validateCompilation } from './chunk-YYKRQHUZ.mjs';
2
2
  import './chunk-5H7N2A5X.mjs';
3
- export { validateCode, validateCodeSync } from './chunk-WHYAD7JV.mjs';
4
- export { analyzeCodeWithAST, componentRegistry } from './chunk-27IE6LRY.mjs';
3
+ export { validateCode, validateCodeSync } from './chunk-4G533OEX.mjs';
4
+ export { analyzeCodeWithAST, componentRegistry } from './chunk-UYVGHUC5.mjs';
5
5
  export { validateRuntimePrecheck } from './chunk-ZONZNAWA.mjs';
6
6
  export { compileSFC, scopeStyles } from './chunk-WJAGRAWV.mjs';
@@ -0,0 +1,92 @@
1
+ {
2
+ "id": "useIdEntity",
3
+ "name": "useIdEntity",
4
+ "displayName": "ID 实体映射",
5
+ "category": "state",
6
+ "description": "根据 ID 从列表中查找对应的实体对象。当 ID 或列表变化时自动更新实体,并可选择性地触发回调。常用于 Select 等组件中需要根据选中 ID 获取完整对象信息的场景。",
7
+ "importStatement": "import { useIdEntity } from '@ksyun-internal/versatile';",
8
+ "source": "@ksyun-internal/versatile",
9
+ "params": [
10
+ {
11
+ "name": "id",
12
+ "type": "Ref<string | number | undefined | null>",
13
+ "required": true,
14
+ "description": "要查找的实体 ID(响应式值)"
15
+ },
16
+ {
17
+ "name": "list",
18
+ "type": "Ref<Entity[] | undefined | null>",
19
+ "required": true,
20
+ "description": "实体列表(响应式值)"
21
+ },
22
+ {
23
+ "name": "key",
24
+ "type": "keyof Entity",
25
+ "required": true,
26
+ "description": "用于匹配的实体属性名(如 'id', 'WorkspaceId' 等)"
27
+ },
28
+ {
29
+ "name": "emit",
30
+ "type": "(entity: Entity | undefined) => void",
31
+ "required": false,
32
+ "description": "实体变化时的回调函数"
33
+ },
34
+ {
35
+ "name": "deps",
36
+ "type": "WatchSource[]",
37
+ "required": false,
38
+ "description": "额外的依赖项,当这些依赖变化时也会触发重新查找"
39
+ },
40
+ {
41
+ "name": "enable",
42
+ "type": "(item: Entity, index: number) => boolean",
43
+ "required": false,
44
+ "description": "过滤函数,用于筛选可用的实体"
45
+ }
46
+ ],
47
+ "returnType": "Ref<Entity | undefined>",
48
+ "examples": [
49
+ {
50
+ "id": "basic_usage",
51
+ "title": "基础用法",
52
+ "description": "根据选中的 ID 获取对应的工作空间对象",
53
+ "code": "<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport { useIdEntity } from '@ksyun-internal/versatile';\n\nconst selectedId = ref('ws-001');\nconst workspaceList = ref([\n { WorkspaceId: 'ws-001', WorkspaceName: '工作空间1' },\n { WorkspaceId: 'ws-002', WorkspaceName: '工作空间2' },\n]);\n\nconst selectedWorkspace = useIdEntity(selectedId, workspaceList, 'WorkspaceId');\n// selectedWorkspace.value = { WorkspaceId: 'ws-001', WorkspaceName: '工作空间1' }\n</script>"
54
+ },
55
+ {
56
+ "id": "with_callback",
57
+ "title": "带回调函数",
58
+ "description": "当实体变化时触发回调",
59
+ "code": "<script setup lang=\"ts\">\nimport { useToState, useIdEntity } from '@ksyun-internal/versatile';\n\nconst props = defineProps<{ modelValue?: string }>();\nconst emit = defineEmits<{ (e: 'update:modelValue', v?: string): void }>();\n\nconst modelValue = useToState(props, 'modelValue', emit, '');\nconst { workspaceList } = useWorkspaces();\n\nuseIdEntity(modelValue, workspaceList, 'WorkspaceId', (entity) => {\n emit('update:modelValue', entity?.WorkspaceId);\n});\n</script>"
60
+ },
61
+ {
62
+ "id": "with_enable_filter",
63
+ "title": "带过滤函数",
64
+ "description": "只在启用状态的实体中查找",
65
+ "code": "<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport { useIdEntity } from '@ksyun-internal/versatile';\n\nconst selectedId = ref('item-1');\nconst itemList = ref([\n { id: 'item-1', name: '项目1', enabled: true },\n { id: 'item-2', name: '项目2', enabled: false },\n]);\n\n// 只在 enabled: true 的项目中查找\nconst entity = useIdEntity(\n selectedId,\n itemList,\n 'id',\n undefined,\n undefined,\n (item) => item.enabled\n);\n</script>"
66
+ }
67
+ ],
68
+ "commonMistakes": [
69
+ {
70
+ "id": "non_ref_id",
71
+ "description": "id 参数传入非响应式值",
72
+ "wrongCode": "const entity = useIdEntity('ws-001', workspaceList, 'WorkspaceId');",
73
+ "correctCode": "const id = ref('ws-001');\nconst entity = useIdEntity(id, workspaceList, 'WorkspaceId');",
74
+ "explanation": "id 参数必须是 Ref 类型,否则无法监听变化"
75
+ },
76
+ {
77
+ "id": "wrong_key_name",
78
+ "description": "key 参数与实体属性名不匹配",
79
+ "wrongCode": "useIdEntity(id, workspaceList, 'id'); // 实体中是 WorkspaceId",
80
+ "correctCode": "useIdEntity(id, workspaceList, 'WorkspaceId');",
81
+ "explanation": "key 必须与实体对象中用作唯一标识的属性名完全匹配"
82
+ }
83
+ ],
84
+ "searchKeywords": [
85
+ "useIdEntity",
86
+ "id",
87
+ "entity",
88
+ "列表查找",
89
+ "实体映射",
90
+ "select"
91
+ ]
92
+ }
@@ -0,0 +1,97 @@
1
+ {
2
+ "id": "useToState",
3
+ "name": "useToState",
4
+ "displayName": "Props 转 State",
5
+ "category": "state",
6
+ "description": "将 props 中的属性转换为响应式 state,支持 v-model 双向绑定。当 props 变化时自动更新 state,当 state 变化时自动触发 emit 更新父组件。",
7
+ "importStatement": "import { useToState } from '@ksyun-internal/versatile';",
8
+ "source": "@ksyun-internal/versatile",
9
+ "params": [
10
+ {
11
+ "name": "props",
12
+ "type": "P extends object",
13
+ "required": true,
14
+ "description": "组件的 props 对象(通过 defineProps 获取)"
15
+ },
16
+ {
17
+ "name": "key",
18
+ "type": "keyof P",
19
+ "required": true,
20
+ "description": "要监听的 prop 名称(字符串)"
21
+ },
22
+ {
23
+ "name": "emit",
24
+ "type": "Emits<K & string, P[K]>",
25
+ "required": true,
26
+ "description": "组件的 emit 函数(通过 defineEmits 获取),需要包含 update:key 事件"
27
+ },
28
+ {
29
+ "name": "defaults",
30
+ "type": "NonNullable<P[K]>",
31
+ "required": false,
32
+ "description": "默认值。如果提供,返回的 Ref 将保证不为 undefined"
33
+ }
34
+ ],
35
+ "returnType": "Ref<P[K]>",
36
+ "overloads": [
37
+ {
38
+ "signature": "useToState<P, K>(props: P, key: K, emit: Emits): Ref<P[K]>",
39
+ "description": "基础用法,返回可能为 undefined 的响应式值"
40
+ },
41
+ {
42
+ "signature": "useToState<P, K>(props: P, key: K, emit: Emits, defaults: NonNullable<P[K]>): Ref<NonNullable<P[K]>>",
43
+ "description": "带默认值用法,返回保证非 undefined 的响应式值"
44
+ }
45
+ ],
46
+ "examples": [
47
+ {
48
+ "id": "basic_usage",
49
+ "title": "基础用法",
50
+ "description": "将 modelValue prop 转换为响应式 state",
51
+ "code": "<script setup lang=\"ts\">\nimport { useToState } from '@ksyun-internal/versatile';\n\ntype Props = { modelValue?: string };\ntype Emits = { (e: 'update:modelValue', v?: string): void };\n\nconst props = defineProps<Props>();\nconst emit = defineEmits<Emits>();\n\nconst value = useToState(props, 'modelValue', emit);\n</script>\n<template>\n <input v-model=\"value\" />\n</template>"
52
+ },
53
+ {
54
+ "id": "with_defaults",
55
+ "title": "带默认值用法",
56
+ "description": "提供默认值,确保返回值不为 undefined",
57
+ "code": "<script setup lang=\"ts\">\nimport { useToState } from '@ksyun-internal/versatile';\n\nconst props = defineProps<{ count?: number }>();\nconst emit = defineEmits(['update:count']);\n\n// 默认值为 0,count 永远不为 undefined\nconst count = useToState(props, 'count', emit, 0);\n</script>\n<template>\n <div>{{ count }}</div>\n</template>"
58
+ },
59
+ {
60
+ "id": "object_value",
61
+ "title": "对象类型值",
62
+ "description": "将对象类型的 prop 转换为响应式 state",
63
+ "code": "<script setup lang=\"ts\">\nimport { useToState } from '@ksyun-internal/versatile';\n\ntype FormData = { name: string; age: number };\ntype Props = { modelValue?: FormData };\ntype Emits = { (e: 'update:modelValue', v?: FormData): void };\n\nconst props = defineProps<Props>();\nconst emit = defineEmits<Emits>();\n\nconst formData = useToState(props, 'modelValue', emit, { name: '', age: 0 });\n</script>\n<template>\n <input v-model=\"formData.name\" />\n <input v-model.number=\"formData.age\" />\n</template>"
64
+ }
65
+ ],
66
+ "commonMistakes": [
67
+ {
68
+ "id": "missing_emit",
69
+ "description": "忘记传递 emit 参数",
70
+ "wrongCode": "const value = useToState(props, 'modelValue');",
71
+ "correctCode": "const value = useToState(props, 'modelValue', emit);",
72
+ "explanation": "useToState 需要 emit 函数来实现双向绑定,缺少 emit 会导致编译错误"
73
+ },
74
+ {
75
+ "id": "wrong_emit_event",
76
+ "description": "emit 没有定义对应的 update:key 事件",
77
+ "wrongCode": "const emit = defineEmits(['change']);\nconst value = useToState(props, 'modelValue', emit);",
78
+ "correctCode": "const emit = defineEmits(['update:modelValue']);\nconst value = useToState(props, 'modelValue', emit);",
79
+ "explanation": "useToState 内部会调用 emit('update:key', newValue),必须在 defineEmits 中声明对应事件"
80
+ },
81
+ {
82
+ "id": "key_not_in_props",
83
+ "description": "key 参数不是 props 中定义的属性",
84
+ "wrongCode": "const props = defineProps<{ name: string }>();\nconst value = useToState(props, 'age', emit);",
85
+ "correctCode": "const props = defineProps<{ name: string; age?: number }>();\nconst value = useToState(props, 'age', emit);",
86
+ "explanation": "key 必须是 props 中已定义的属性名"
87
+ }
88
+ ],
89
+ "searchKeywords": [
90
+ "useToState",
91
+ "props",
92
+ "state",
93
+ "v-model",
94
+ "双向绑定",
95
+ "响应式"
96
+ ]
97
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "king-design-analyzer",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "AST-based code analyzer for King Design Vue components with on-demand modular imports",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -45,7 +45,8 @@
45
45
  "files": [
46
46
  "dist",
47
47
  "components",
48
- "docs_for_llm"
48
+ "docs_for_llm",
49
+ "hooks"
49
50
  ],
50
51
  "scripts": {
51
52
  "build": "tsup",