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 +3 -3
- package/dist/ast/index.mjs +1 -1
- package/dist/{chunk-WHYAD7JV.mjs → chunk-4G533OEX.mjs} +1 -1
- package/dist/{chunk-TKBNPZIO.js → chunk-GW5YOUB7.js} +43 -2
- package/dist/{chunk-DMQS5OPY.js → chunk-RHPVVTOE.js} +2 -2
- package/dist/{chunk-27IE6LRY.mjs → chunk-UYVGHUC5.mjs} +41 -0
- package/dist/full/index.js +4 -4
- package/dist/full/index.mjs +2 -2
- package/dist/index.js +6 -6
- package/dist/index.mjs +2 -2
- package/hooks/useIdEntity.json +92 -0
- package/hooks/usetoState.json +97 -0
- package/package.json +3 -2
package/dist/ast/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
require('../chunk-YTEYDSDW.js');
|
|
4
|
-
var
|
|
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
|
|
10
|
+
get: function () { return chunkGW5YOUB7_js.analyzeCodeWithAST; }
|
|
11
11
|
});
|
|
12
12
|
Object.defineProperty(exports, "componentRegistry", {
|
|
13
13
|
enumerable: true,
|
|
14
|
-
get: function () { return
|
|
14
|
+
get: function () { return chunkGW5YOUB7_js.componentRegistry; }
|
|
15
15
|
});
|
package/dist/ast/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import '../chunk-5H7N2A5X.mjs';
|
|
2
|
-
export { analyzeCodeWithAST, componentRegistry } from '../chunk-
|
|
2
|
+
export { analyzeCodeWithAST, componentRegistry } from '../chunk-UYVGHUC5.mjs';
|
|
@@ -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-
|
|
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-
|
|
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
|
|
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
|
|
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) {
|
package/dist/full/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
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
|
|
12
|
+
get: function () { return chunkRHPVVTOE_js.validateCode; }
|
|
13
13
|
});
|
|
14
14
|
Object.defineProperty(exports, "validateCodeSync", {
|
|
15
15
|
enumerable: true,
|
|
16
|
-
get: function () { return
|
|
16
|
+
get: function () { return chunkRHPVVTOE_js.validateCodeSync; }
|
|
17
17
|
});
|
package/dist/full/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { validateCode, validateCodeSync } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
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
|
|
6
|
-
var
|
|
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
|
|
18
|
+
get: function () { return chunkRHPVVTOE_js.validateCode; }
|
|
19
19
|
});
|
|
20
20
|
Object.defineProperty(exports, "validateCodeSync", {
|
|
21
21
|
enumerable: true,
|
|
22
|
-
get: function () { return
|
|
22
|
+
get: function () { return chunkRHPVVTOE_js.validateCodeSync; }
|
|
23
23
|
});
|
|
24
24
|
Object.defineProperty(exports, "analyzeCodeWithAST", {
|
|
25
25
|
enumerable: true,
|
|
26
|
-
get: function () { return
|
|
26
|
+
get: function () { return chunkGW5YOUB7_js.analyzeCodeWithAST; }
|
|
27
27
|
});
|
|
28
28
|
Object.defineProperty(exports, "componentRegistry", {
|
|
29
29
|
enumerable: true,
|
|
30
|
-
get: function () { return
|
|
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-
|
|
4
|
-
export { analyzeCodeWithAST, componentRegistry } from './chunk-
|
|
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.
|
|
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",
|