lcap-frontend-library 0.0.1
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/README.md +271 -0
- package/bin/lcap-frontend-library.mjs +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +27 -0
- package/dist/init.d.ts +6 -0
- package/dist/init.js +79 -0
- package/dist/sync.d.ts +4 -0
- package/dist/sync.js +70 -0
- package/dist/utils.d.ts +19 -0
- package/dist/utils.js +101 -0
- package/package.json +34 -0
- package/packages/lcap-frontend-library/LEARNINGS.md +11 -0
- package/packages/lcap-frontend-library/SKILL.md +86 -0
- package/packages/lcap-frontend-library/commands/migrate.check.md +287 -0
- package/packages/lcap-frontend-library/commands/migrate.green.md +190 -0
- package/packages/lcap-frontend-library/commands/migrate.plan.md +169 -0
- package/packages/lcap-frontend-library/commands/migrate.red.md +160 -0
- package/packages/lcap-frontend-library/commands/migrate.scan.md +151 -0
- package/packages/lcap-frontend-library/commands/migrate.spec.md +144 -0
- package/packages/lcap-frontend-library/commands/migrate.tasks.md +179 -0
- package/packages/lcap-frontend-library/commands/speckit.create.md +201 -0
- package/packages/lcap-frontend-library/commands/speckit.implement.md +88 -0
- package/packages/lcap-frontend-library/commands/speckit.plan.md +79 -0
- package/packages/lcap-frontend-library/commands/speckit.self-check.md +177 -0
- package/packages/lcap-frontend-library/commands/speckit.specify.md +91 -0
- package/packages/lcap-frontend-library/commands/speckit.tasks.md +61 -0
- package/packages/lcap-frontend-library/references/frontend-design/LICENSE.txt +177 -0
- package/packages/lcap-frontend-library/references/frontend-design/SKILL.md +42 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/SKILL.md +360 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/api.md +331 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/block.md +160 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/i18n.md +95 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/icon.md +27 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/ide/container.md +728 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/ide/element.md +312 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/ide/expression.md +154 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/ide/index.md +113 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/ide/modal.md +189 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/ide/popover.md +171 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/ide.md +799 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/implementation-rules.md +242 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/index.md +27 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/nasl-view-component.md +895 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/platform/accessibility.md +185 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/platform/child.md +82 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/platform/data-source.md +261 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/platform/event.md +171 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/platform/form.md +266 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/platform/function.md +80 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/platform/link.md +137 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/platform/slot.md +128 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/platform/theme-variables-ant-design.md +1470 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/platform/theme-variables-cloud-ui.md +259 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/platform/theme-variables-element-plus.md +580 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/platform/theme-variables-element-ui.md +1007 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/platform/theme-variables-mobile-ui.md +85 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/theme.md +234 -0
- package/packages/lcap-frontend-library/references/lcap-extension-component/workflow-guardrails.md +328 -0
- package/packages/lcap-frontend-library/references/nasl-logic-authoring/SKILL.md +201 -0
- package/packages/lcap-frontend-library/scripts/bash/create-component-files.sh +95 -0
- package/packages/lcap-frontend-library/scripts/bash/create-extension-project.sh +109 -0
- package/packages/lcap-frontend-library/scripts/bash/create-logic-files.sh +149 -0
- package/packages/lcap-frontend-library/scripts/bash/create-spec.sh +109 -0
- package/packages/lcap-frontend-library/scripts/bash/get-available-port.sh +35 -0
- package/packages/lcap-frontend-library/scripts/bash/list-specs.sh +19 -0
- package/packages/lcap-frontend-library/scripts/node/setup-extension-project.mjs +166 -0
- package/packages/lcap-frontend-library/templates/component-self-check.md +31 -0
- package/packages/lcap-frontend-library/templates/component-template.md +96 -0
- package/packages/lcap-frontend-library/templates/library-report-template.md +52 -0
- package/packages/lcap-frontend-library/templates/logic-template.md +44 -0
- package/packages/lcap-frontend-library/templates/migration-manifest-template.md +84 -0
- package/packages/lcap-frontend-library/templates/migration-plan-template.md +138 -0
- package/packages/lcap-frontend-library/templates/migration-report-template.md +227 -0
- package/packages/lcap-frontend-library/templates/migration-spec-template.md +135 -0
- package/packages/lcap-frontend-library/templates/migration-tasks-template.md +129 -0
- package/packages/lcap-frontend-library/templates/plan-template.md +299 -0
- package/packages/lcap-frontend-library/templates/self-check-report-template.md +148 -0
- package/packages/lcap-frontend-library/templates/tasks-template.md +81 -0
- package/packages/lcap-frontend-library/workflows/create/flow.md +199 -0
- package/packages/lcap-frontend-library/workflows/evolve/flow.md +249 -0
- package/packages/lcap-frontend-library/workflows/generate/flow.md +10 -0
- package/packages/lcap-frontend-library/workflows/harness/flow.md +82 -0
- package/packages/lcap-frontend-library/workflows/migrate/flow.md +302 -0
- package/packages/lcap-frontend-library/workflows/migrate/knowledge-base.md +564 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# 使用 CloudUI 全局主题变量
|
|
2
|
+
|
|
3
|
+
## 复制变量文件
|
|
4
|
+
|
|
5
|
+
创建文件 `.storybook/vars.css`, 内容如下:
|
|
6
|
+
|
|
7
|
+
```css
|
|
8
|
+
|
|
9
|
+
:root {
|
|
10
|
+
/**
|
|
11
|
+
* ========================
|
|
12
|
+
* Global Variables
|
|
13
|
+
* ========================
|
|
14
|
+
*/
|
|
15
|
+
--van-space-baset: 16px;
|
|
16
|
+
|
|
17
|
+
/* Brand Colors */
|
|
18
|
+
--van-brand-primary: #337eff;
|
|
19
|
+
--van-brand-success: #26bd71;
|
|
20
|
+
--van-brand-problem: #ffb21a;
|
|
21
|
+
--van-brand-warning: #ffb21a;
|
|
22
|
+
--van-brand-error: #f24957;
|
|
23
|
+
--van-brand-disabled: #ebebeb;
|
|
24
|
+
|
|
25
|
+
/* Component Base Colors */
|
|
26
|
+
--van-component-text-color: #333;
|
|
27
|
+
--van-component-active-color: #f2f3f5;
|
|
28
|
+
--van-component-active-opacity: 0.7;
|
|
29
|
+
--van-component-disabled-opacity: 0.5;
|
|
30
|
+
--van-component-background-color: #f7f8fa;
|
|
31
|
+
--van-component-background-color-light: #fafafa;
|
|
32
|
+
--van-component-text-link-color: #576b95;
|
|
33
|
+
|
|
34
|
+
/* Font */
|
|
35
|
+
--van-font-color: #333;
|
|
36
|
+
--van-font-size-xs: 10px;
|
|
37
|
+
--van-font-size-sm: 12px;
|
|
38
|
+
--van-font-size-md: 14px;
|
|
39
|
+
--van-font-size-lg: 16px;
|
|
40
|
+
--van-font-weight-bold: 500;
|
|
41
|
+
--van-line-height-xs: 14px;
|
|
42
|
+
--van-line-height-sm: 18px;
|
|
43
|
+
--van-line-height-md: 20px;
|
|
44
|
+
--van-line-height-lg: 22px;
|
|
45
|
+
--van-base-font-family: blinkmacsystemfont, 'Helvetica Neue',
|
|
46
|
+
helvetica, segoe ui, arial, roboto, 'PingFang SC', 'miui',
|
|
47
|
+
'Hiragino Sans GB', 'Microsoft Yahei', sans-serif, -apple-system;
|
|
48
|
+
--van-price-integer-font-family: avenir-heavy, pingfang sc, helvetica neue,
|
|
49
|
+
arial, sans-serif;
|
|
50
|
+
|
|
51
|
+
/* Border Color */
|
|
52
|
+
--van-border-color: #e5e5e5;
|
|
53
|
+
--van-border-width-base: 1px;
|
|
54
|
+
--van-border-radius-sm: 2px;
|
|
55
|
+
--van-border-radius-md: 4px;
|
|
56
|
+
--van-border-radius-lg: 8px;
|
|
57
|
+
--van-border-radius-max: 16px;
|
|
58
|
+
|
|
59
|
+
/* Padding */
|
|
60
|
+
--van-padding-base: 6px;
|
|
61
|
+
--van-padding-xs: calc(var(--van-padding-base) * 2);
|
|
62
|
+
--van-padding-sm: calc(var(--van-padding-base) * 3);
|
|
63
|
+
--van-padding-md: calc(var(--van-padding-base) * 4);
|
|
64
|
+
--van-padding-lg: calc(var(--van-padding-base) * 6);
|
|
65
|
+
--van-padding-xl: calc(var(--van-padding-base) * 8);
|
|
66
|
+
|
|
67
|
+
--van-space-base: var(
|
|
68
|
+
--van-space-baset
|
|
69
|
+
); /* @desc 布局内各元素之间的外间距, 如:1px */ /* @prefix van */
|
|
70
|
+
--van-space-shrink: -1px;
|
|
71
|
+
--van-space-mini: 4px;
|
|
72
|
+
--van-space-small: 10px;
|
|
73
|
+
--van-space-large: 30px;
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## 在 `.storybook/preview.js` 文件中导入全局变量
|
|
78
|
+
|
|
79
|
+
```js
|
|
80
|
+
import './vars.css';
|
|
81
|
+
|
|
82
|
+
// ......
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
完成后就可以在组件中使用以上的全局 css 变量
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
---
|
|
2
|
+
outline: deep
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
<script setup>
|
|
6
|
+
import { VTCodeGroup, VTCodeGroupTab } from '../../.vitepress/components'
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
# 主题样式配置
|
|
10
|
+
|
|
11
|
+
## 1. 功能说明
|
|
12
|
+
|
|
13
|
+
在IDE的 **更多**->**自定义主题样式** 中配置组件的默认外观,或者在 **组件属性**->**样式面板** 中设置主题样式。
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## 2. 功能实现
|
|
18
|
+
|
|
19
|
+
### 2.1 创建主题文件
|
|
20
|
+
|
|
21
|
+
在组件目录下创建文件夹 theme,theme文件夹下创建文件 index.vue / index.jsx 和 vars.css 。
|
|
22
|
+
|
|
23
|
+
<VTCodeGroup>
|
|
24
|
+
<VTCodeGroupTab label="Vue2">
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
|-- src
|
|
28
|
+
|---- components
|
|
29
|
+
|------- cwd-capsule-switch
|
|
30
|
+
|----------- theme // 主题目录
|
|
31
|
+
|------------- index.vue // 组件主题预览
|
|
32
|
+
|------------- vars.css // 可配置变量
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
</VTCodeGroupTab>
|
|
36
|
+
<VTCodeGroupTab label="React">
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
|-- src
|
|
40
|
+
|---- components
|
|
41
|
+
|------- CwdCapluse
|
|
42
|
+
|---------- theme // 主题目录
|
|
43
|
+
|------------- index.jsx // 组件主题预览
|
|
44
|
+
|------------- vars.css // 可配置变量
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
</VTCodeGroupTab>
|
|
48
|
+
</VTCodeGroup>
|
|
49
|
+
|
|
50
|
+
示意图如下:
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
### 2.2 配置文件
|
|
55
|
+
|
|
56
|
+
1. 配置文件 index.vue / index.jsx。默认可使用组件区块实例作为主题配置预览。
|
|
57
|
+
|
|
58
|
+
<VTCodeGroup>
|
|
59
|
+
<VTCodeGroupTab label="Vue2">
|
|
60
|
+
|
|
61
|
+
```vue
|
|
62
|
+
<!-- index.vue -->
|
|
63
|
+
<template>
|
|
64
|
+
<demo-preview></demo-preview>
|
|
65
|
+
</template>
|
|
66
|
+
<script>
|
|
67
|
+
// 默认可使用组件区块实例作为主题配置预览
|
|
68
|
+
import createStoriesPreview from '@lcap/builder/input/vue2/stories-preview';
|
|
69
|
+
import * as stories from '../stories/block.stories';
|
|
70
|
+
|
|
71
|
+
const DemoPreview = createStoriesPreview(stories);
|
|
72
|
+
|
|
73
|
+
export default {
|
|
74
|
+
components: {
|
|
75
|
+
DemoPreview,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
</script>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
</VTCodeGroupTab>
|
|
83
|
+
<VTCodeGroupTab label="React">
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// index.jsx
|
|
87
|
+
// 默认可使用组件区块实例作为主题配置预览
|
|
88
|
+
import createStoriesPreview from '@lcap/builder/input/react/stories-preview';
|
|
89
|
+
import * as stories from '../stories/block.stories';
|
|
90
|
+
|
|
91
|
+
export default createStoriesPreview(stories);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
</VTCodeGroupTab>
|
|
95
|
+
</VTCodeGroup>
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
2. 配置文件 vars.css 。标注支持自定义主题样式的组件以及组件样式相应的变量。
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
<div class="highlight">
|
|
105
|
+
|
|
106
|
+
vars.css 文件配置规范:
|
|
107
|
+
|
|
108
|
+
- 组件主题注释
|
|
109
|
+
|
|
110
|
+
- @component 必需,注释支持自定义主题样式的组件的组件名称,组件名称与 api.ts 中一致。
|
|
111
|
+
- @hidden 非必需,表示隐藏该组件主题配置功能
|
|
112
|
+
- 变量注释
|
|
113
|
+
|
|
114
|
+
- @desc 必需,注释组件样式对应的变量
|
|
115
|
+
- @type 注释变量类型,默认为 input,支持填写color、size、input。
|
|
116
|
+
- @group 表示变量分组
|
|
117
|
+
- @hidden 非必需,表示隐藏该变量配置功能
|
|
118
|
+
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
<details>
|
|
122
|
+
<summary title="点击展开示例代码">
|
|
123
|
+
点击展开示例代码
|
|
124
|
+
</summary>
|
|
125
|
+
|
|
126
|
+
```css
|
|
127
|
+
/**
|
|
128
|
+
* @component cwd-capsule
|
|
129
|
+
*/
|
|
130
|
+
.cwd-capsule {
|
|
131
|
+
/**
|
|
132
|
+
* @desc 背景颜色
|
|
133
|
+
* @type color
|
|
134
|
+
*/
|
|
135
|
+
--cwd-capsule-background-color: rgb(236, 236, 236);
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @desc 背景颜色(选中态)
|
|
139
|
+
* @type color
|
|
140
|
+
*/
|
|
141
|
+
--cwd-capsule-background-color-active: #fff;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* @desc 字体颜色
|
|
145
|
+
* @type color
|
|
146
|
+
*/
|
|
147
|
+
--cwd-capsule-color: #666;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @desc 字体颜色(选中态)
|
|
151
|
+
* @type color
|
|
152
|
+
*/
|
|
153
|
+
--cwd-capsule-color-active: #333;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @desc 字体大小
|
|
157
|
+
* @type input
|
|
158
|
+
*/
|
|
159
|
+
--cwd-capsule-font-size: 14px;
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
</details>
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
## 3. 本地预览调试
|
|
167
|
+
|
|
168
|
+
1. 在 src 目录下配置文件 theme.stories.js,用于本地调试主题配置预览。
|
|
169
|
+
|
|
170
|
+
<VTCodeGroup>
|
|
171
|
+
<VTCodeGroupTab label="Vue2">
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
import ComponentPreview from 'virtual:lcap-theme-component-previews.js';
|
|
175
|
+
|
|
176
|
+
export default {
|
|
177
|
+
title: '主题配置预览',
|
|
178
|
+
// More on argTypes: https://storybook.js.org/docs/api/argtypes
|
|
179
|
+
argTypes: {
|
|
180
|
+
backgroundColor: { control: 'color' },
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
export const Components = {
|
|
185
|
+
name: '组件预览',
|
|
186
|
+
render: (args, { argTypes }) => {
|
|
187
|
+
return {
|
|
188
|
+
props: Object.keys(argTypes),
|
|
189
|
+
components: {
|
|
190
|
+
ComponentPreview,
|
|
191
|
+
},
|
|
192
|
+
template: '<ComponentPreview v-bind="$props" />',
|
|
193
|
+
};
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
</VTCodeGroupTab>
|
|
199
|
+
<VTCodeGroupTab label="React">
|
|
200
|
+
|
|
201
|
+
```javascript
|
|
202
|
+
import ComponentPreview from 'virtual:lcap-theme-component-previews.js';
|
|
203
|
+
|
|
204
|
+
export default {
|
|
205
|
+
title: '主题配置预览',
|
|
206
|
+
// More on argTypes: https://storybook.js.org/docs/api/argtypes
|
|
207
|
+
argTypes: {
|
|
208
|
+
backgroundColor: { control: 'color' },
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
export const Components = {
|
|
213
|
+
name: '组件预览',
|
|
214
|
+
render: ComponentPreview,
|
|
215
|
+
};
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
</VTCodeGroupTab>
|
|
219
|
+
</VTCodeGroup>
|
|
220
|
+
|
|
221
|
+
2. 打开终端运行 npm run dev 启动服务,预览默认主题配置效果。
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
## 4. 使用效果演示
|
|
226
|
+
|
|
227
|
+
npm run build之后dist-theme目录下会生成theme.config.json文件与theme/index.html预览文件。
|
|
228
|
+
|
|
229
|
+
以下效果为依赖库打包发布并在IDE中引入后的使用演示。
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
package/packages/lcap-frontend-library/references/lcap-extension-component/workflow-guardrails.md
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
---
|
|
2
|
+
outline: deep
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# 工作流护栏(避免常见疏漏)
|
|
6
|
+
|
|
7
|
+
本文档将"经验教训"沉淀为**可执行规则**:每条规则都包含触发条件、推荐做法与可验收的落点。用于 `speckit.plan` / `speckit.implement` 以及日常组件开发自检。
|
|
8
|
+
|
|
9
|
+
> 核心原则:**规范文档不是用来"读"的,是用来"转化"的**。计划阶段就要把规则落成表格与具体参数,实现阶段严格按计划执行。
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. 本地脚本执行前:权限与环境预检
|
|
14
|
+
|
|
15
|
+
### 触发条件
|
|
16
|
+
|
|
17
|
+
- 需要执行仓库内的本地脚本(如 `scripts/bash/*.sh`)。
|
|
18
|
+
|
|
19
|
+
### 推荐做法
|
|
20
|
+
|
|
21
|
+
- **先检查可执行性**:优先 `test -x <script>` 或 `ls -l <script>` 确认权限位。
|
|
22
|
+
- 若脚本**不可执行**:
|
|
23
|
+
- **优先**用解释器直接运行:`bash <script>`(避免改权限位带来的协作/CI 副作用)。
|
|
24
|
+
- 只有在确有需要(例如工具链明确要求可执行位)时,才执行 `chmod +x <script>`,并将权限位修复纳入仓库(避免下次再踩坑)。
|
|
25
|
+
- 运行 `npm` 命令前,如遇"缺依赖/缺环境"错误:**按报错补齐依赖**,而不是每次都人工检查 `package.json`。
|
|
26
|
+
- **单测前检查测试依赖**:执行 `npm run test` 前,若项目含 Vue 组件单测(Vitest + @vue/test-utils),须先确认已安装 `@vue/test-utils`、`jsdom`(如 `npm list @vue/test-utils jsdom` 或查看 package.json);未安装或出现 `Failed to resolve import "@vue/test-utils"` 时,先执行 `npm install -D @vue/test-utils jsdom`,再跑单测。
|
|
27
|
+
|
|
28
|
+
### 验收要点
|
|
29
|
+
|
|
30
|
+
- [ ] 执行脚本前已确认可执行性;不可执行时采用 `bash` 运行或已修复权限位并纳入仓库。
|
|
31
|
+
- [ ] 依赖缺失时按报错补装,并确保后续命令可重复通过。
|
|
32
|
+
- [ ] 跑单测前已确认 `@vue/test-utils`、`jsdom` 已安装;若报解析失败则先安装再重跑。
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 2. CSS Modules / `<style module>`:测试定位规则
|
|
37
|
+
|
|
38
|
+
### 触发条件
|
|
39
|
+
|
|
40
|
+
- 组件使用 CSS Modules(如 Vue SFC 的 `<style module>`)或构建会对 className 哈希化。
|
|
41
|
+
|
|
42
|
+
### 推荐做法(按优先级)
|
|
43
|
+
|
|
44
|
+
1. **首选 `data-testid`/`data-test`**:在关键交互/断言节点添加稳定的测试标识(同时利于 Vitest 与测试脚本复用)。
|
|
45
|
+
2. **语义定位**:优先按可访问性语义定位(如 role/label/text),若组件具备对应语义。
|
|
46
|
+
3. **组件级定位**:Vue Test Utils 使用 `findComponent(...)` 或按组件结构定位。
|
|
47
|
+
4. **兜底**:仅在无法引入上述方式时,才使用 CSS 选择器;避免依赖精确类名(如 `.root`)。`[class*="xxx"]` 可以作为临时兜底,但需确保不会误匹配,并尽量配合父容器或更具体结构收敛范围。
|
|
48
|
+
|
|
49
|
+
### 验收要点
|
|
50
|
+
|
|
51
|
+
- [ ] 单测/交互测试不依赖 CSS Modules 哈希后的精确类名。
|
|
52
|
+
- [ ] 关键断言点具备稳定定位方式(优先 `data-testid`)。
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 3. 浮点数/比例/缩放:断言精度容差
|
|
57
|
+
|
|
58
|
+
### 触发条件
|
|
59
|
+
|
|
60
|
+
- 涉及缩放、比例、百分比、动画进度、布局计算等浮点数运算。
|
|
61
|
+
|
|
62
|
+
### 推荐做法
|
|
63
|
+
|
|
64
|
+
- **禁止**使用 `toBe` / `toEqual` 对浮点数做精确相等断言。
|
|
65
|
+
- 统一使用 `toBeCloseTo(value, digits)`,digits 依据业务精度选择(例如 2 或 3)。
|
|
66
|
+
|
|
67
|
+
### 验收要点
|
|
68
|
+
|
|
69
|
+
- [ ] 浮点数相关断言使用 `toBeCloseTo`,且精度位数合理。
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 4. 测试定位与事件隔离(Storybook / 单测)
|
|
74
|
+
|
|
75
|
+
### 触发条件
|
|
76
|
+
|
|
77
|
+
- 测试定位不稳定(同一选择器命中多个元素)。
|
|
78
|
+
- 控制台出现 Vue 警告(如 `Wrong type passed as event handler`),或 Storybook Demo 中事件未触发/触发异常。
|
|
79
|
+
|
|
80
|
+
### 推荐做法
|
|
81
|
+
|
|
82
|
+
#### 4.1 选择器唯一性(优先级)
|
|
83
|
+
|
|
84
|
+
1. **首选**稳定测试标识与可访问性语义(如 `data-testid`、role、label、text)。
|
|
85
|
+
2. 次选结构化选择器(限定容器范围、组合标签/属性/文本)。
|
|
86
|
+
3. 只有在必要时才使用 `.first()` / `.nth()` 作为兜底;兜底前先保证选择器语义足够明确。
|
|
87
|
+
|
|
88
|
+
#### 4.2 Storybook 中 Props 与 Events 分离(条件触发)
|
|
89
|
+
|
|
90
|
+
- 当出现"事件被当作 prop 传入"导致的控制台 warning/错误时:
|
|
91
|
+
- 将 `args` 拆为 `props` 与 `events`:
|
|
92
|
+
- `props` 用 `v-bind="props"`
|
|
93
|
+
- `events` 用 `v-on="events"`(或逐个显式绑定)
|
|
94
|
+
- 不要求所有组件都一刀切拆分;以"**无警告 + 事件行为正确**"为准。
|
|
95
|
+
|
|
96
|
+
### 验收要点
|
|
97
|
+
|
|
98
|
+
- [ ] 测试定位唯一且稳定(优先 testid/role/label)。
|
|
99
|
+
- [ ] Storybook demo 控制台无上述事件处理警告,且断言覆盖关键行为。
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 5. "计划即契约":将规则转化为可检查产出
|
|
104
|
+
|
|
105
|
+
### 触发条件
|
|
106
|
+
|
|
107
|
+
- 执行 `speckit.plan` 生成 `plan.md`。
|
|
108
|
+
|
|
109
|
+
### 推荐做法
|
|
110
|
+
|
|
111
|
+
- **必须**把实现规则转化为计划中的"具体表格/具体参数",而不是只写成验收勾选项。
|
|
112
|
+
- 常见"规则 → 产出"的映射示例:
|
|
113
|
+
- **样式规范** → `plan.md` 中的「样式与主题适配」+ **样式变量映射表**(并明确引用 `theme-variables-*.md` 的具体变量名)。
|
|
114
|
+
- **展示类默认值** → 在 Props 表中写出具体默认值/示例数据结构(NASL 类型)与空数据表现。
|
|
115
|
+
- **双向绑定** → 在接口设计中标注 sync/回写事件,并在实现顺序中安排验证点(含测试)。
|
|
116
|
+
- **根节点透传** → 明确透传策略(Vue2/Vue3/React)与对应验收方式。
|
|
117
|
+
|
|
118
|
+
### 验收要点
|
|
119
|
+
|
|
120
|
+
- [ ] `plan.md` 中可直接看到样式映射表、默认值结构、双向绑定回写路径等"可执行细节"。
|
|
121
|
+
- [ ] 实现阶段严格按计划落地;若计划变更,先更新计划再改代码。
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 6. 第三方库集成规范 (Third-party Library Integration)
|
|
126
|
+
|
|
127
|
+
### 触发条件
|
|
128
|
+
|
|
129
|
+
- 组件依赖第三方 npm 包(如图表、PDF、富文本等渲染库)。
|
|
130
|
+
|
|
131
|
+
### 推荐做法
|
|
132
|
+
|
|
133
|
+
- **强制调研步骤**:引入或使用三方库后,必须执行 `npm list <package>` 确认实际安装版本,并直接查看 `node_modules/<package>/package.json` 中的 `exports` 或 `types` 定义,确认关键 API(Props、Events、Methods)在**当前版本**中的真实名称与签名。
|
|
134
|
+
- **避坑**:不要依赖过往经验或 AI 的旧数据;版本升级(如 v1 → v2)常伴随破坏性变更,必须以当前依赖的版本为准编写 api.ts 与实现。
|
|
135
|
+
|
|
136
|
+
### 验收要点
|
|
137
|
+
|
|
138
|
+
- [ ] 计划/实现中引用的三方库 API 与当前安装版本一致;Props/Events 名称已对照 node_modules 或官方文档核实。
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 7. 测试质量要求 (Testing Standards)
|
|
143
|
+
|
|
144
|
+
### Mock 准则(单元/交互测试)
|
|
145
|
+
|
|
146
|
+
- 在单元测试中 Mock 第三方组件时,**禁止**基于"假设"编写事件触发逻辑。
|
|
147
|
+
- 必须先通过运行真实组件(或最小 Demo)并打印/观察真实事件流,再将事件名与参数同步到 Mock 代码。
|
|
148
|
+
|
|
149
|
+
### 测试用例零容忍
|
|
150
|
+
|
|
151
|
+
- **严禁**为通过测试而删除或跳过失败用例;任何失败必须按逻辑 Bug 排查并修复。
|
|
152
|
+
- **Timeout** 视为逻辑或环境问题,须排查原因(选择器不稳定、未等待加载、端口冲突等),不得以"跳过"或"忽略"处理。
|
|
153
|
+
- 失败时保留现场信息(如错误信息、步骤)便于复现。
|
|
154
|
+
|
|
155
|
+
### 验收要点
|
|
156
|
+
|
|
157
|
+
- [ ] 单测中 Mock 的事件与真实组件行为一致(经实测或文档确认)。
|
|
158
|
+
- [ ] 无被注释掉或跳过的失败用例;Timeout 已排查并修复。
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 8. Vitest 与 E2E 职责分层
|
|
163
|
+
|
|
164
|
+
### 触发条件
|
|
165
|
+
|
|
166
|
+
- 编写任何组件的 Vitest 单元测试或 Playwright E2E 测试时。
|
|
167
|
+
|
|
168
|
+
### 核心原则
|
|
169
|
+
|
|
170
|
+
jsdom 是**纯 JavaScript DOM 模拟器**,没有布局引擎、图形引擎和 CSS 解析引擎。
|
|
171
|
+
|
|
172
|
+
| 维度 | Vitest(jsdom) | Playwright(E2E) |
|
|
173
|
+
|------|----------------|-------------------|
|
|
174
|
+
| 职责 | 逻辑正确性、DOM 结构、事件触发 | 渲染结果、视觉表现、浏览器 API 产出 |
|
|
175
|
+
| 判定 | "DOM 属性被正确设置了吗?" | "浏览器渲染出了正确的效果吗?" |
|
|
176
|
+
|
|
177
|
+
### jsdom 不支持的 API(禁止在 Vitest 中依赖其结果)
|
|
178
|
+
|
|
179
|
+
> **判定规则**:凡需要**布局引擎**(位置/尺寸)、**图形引擎**(Canvas/SVG)、**CSS 引擎**(样式计算)的 API,jsdom 中均不可靠。
|
|
180
|
+
|
|
181
|
+
| 分类 | 不支持的 API | jsdom 表现 |
|
|
182
|
+
|------|-------------|-----------|
|
|
183
|
+
| 图形 | Canvas 2D / WebGL `getContext()` | 返回 null |
|
|
184
|
+
| 图形 | `OffscreenCanvas`、`createImageBitmap` | 不存在 |
|
|
185
|
+
| 图形 | SVG `getBBox()` / `getCTM()` | 抛错或返回 0 |
|
|
186
|
+
| 图形 | `URL.createObjectURL()` | 不存在或空 |
|
|
187
|
+
| 图形 | `HTMLMediaElement.play()/pause()` | stub,不触发事件 |
|
|
188
|
+
| 布局 | `getBoundingClientRect()` | 全部为 0 |
|
|
189
|
+
| 布局 | `offsetWidth/Height`、`clientWidth/Height` | 始终为 0 |
|
|
190
|
+
| 布局 | `scrollWidth/Height`、`scrollTo()`、`scrollIntoView()` | 为 0 或无效 |
|
|
191
|
+
| CSS | `getComputedStyle()` 读 class 样式 | 不解析 `<style>`,仅返回默认值 |
|
|
192
|
+
| CSS | `matchMedia()` | 不存在 |
|
|
193
|
+
| CSS | CSS Transition/Animation 事件 | 不触发 |
|
|
194
|
+
| CSS | `element.animate()` | 不存在 |
|
|
195
|
+
| 浏览器 | `Web Worker` / `SharedWorker` | 不存在 |
|
|
196
|
+
| 浏览器 | `IntersectionObserver` / `ResizeObserver` | 不存在 |
|
|
197
|
+
| 浏览器 | `navigator.clipboard` / `requestFullscreen` | 不存在 |
|
|
198
|
+
| 浏览器 | `DragEvent` 实际拖拽行为 | 无真实拖拽 |
|
|
199
|
+
|
|
200
|
+
### Mock 决策原则
|
|
201
|
+
|
|
202
|
+
**一句话**:mock 浏览器 API 是为了**防崩溃 + 验证调用参数**;**不是**为了伪造返回值再断言渲染产出。
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
组件用了 jsdom 不支持的 API?
|
|
206
|
+
├─ 否 → 正常 Vitest,无需 mock
|
|
207
|
+
└─ 是 → 你要断言该 API 的"产出"(返回值/渲染结果)?
|
|
208
|
+
├─ 是 → ❌ 移至 E2E
|
|
209
|
+
└─ 否(只验证调用逻辑)→ ✅ mock 后仅断言【参数】
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Vitest 应该测试 / 禁止测试
|
|
213
|
+
|
|
214
|
+
| ✅ Vitest 测试 | ❌ 禁止(移至 E2E) |
|
|
215
|
+
|---------------|-------------------|
|
|
216
|
+
| DOM 结构(节点存在、class、data-testid) | Canvas/SVG 渲染输出(toDataURL、data:image) |
|
|
217
|
+
| Props 响应式(prop → DOM 属性更新) | `getComputedStyle` 读取 class 样式 |
|
|
218
|
+
| 事件 emit(触发 + 参数) | 元素尺寸/位置(offsetWidth、getBoundingClientRect) |
|
|
219
|
+
| 纯逻辑(计算函数、composable) | CSS 渲染效果(定位/穿透/层叠/滚动/动画) |
|
|
220
|
+
| Slot 渲染、$attrs 透传 | 响应式断点(matchMedia) |
|
|
221
|
+
| 条件渲染(v-if/v-show) | mock API 返回值或其驱动的渲染产出 |
|
|
222
|
+
| mock 后验证 API 调用参数 | — |
|
|
223
|
+
|
|
224
|
+
### `element.style.xxx` 使用边界
|
|
225
|
+
|
|
226
|
+
| 值来源 | Vitest 可断言 | 原因 |
|
|
227
|
+
|--------|:------------:|------|
|
|
228
|
+
| Props 直传 / 纯 JS 计算 | ✅ | 不依赖浏览器 API |
|
|
229
|
+
| Canvas/toDataURL 产出 | ❌ | jsdom 无图形引擎 |
|
|
230
|
+
| getBoundingClientRect / offsetWidth | ❌ | jsdom 返回 0 |
|
|
231
|
+
| getComputedStyle / ResizeObserver 回调 | ❌ | jsdom 不支持 |
|
|
232
|
+
|
|
233
|
+
**规则**:若内联样式值的计算链中**任一环节**经过 jsdom 不支持的 API,则禁止在 Vitest 中断言,移至 E2E。
|
|
234
|
+
|
|
235
|
+
### 禁令红线
|
|
236
|
+
|
|
237
|
+
| # | 禁止行为 |
|
|
238
|
+
|:-:|----------|
|
|
239
|
+
| P1 | Vitest 中引入 canvas-mock 来**断言渲染结果**(可引入防崩,禁止断言 toDataURL) |
|
|
240
|
+
| P2 | Vitest 中使用 `getComputedStyle(el).xxx`(用 `element.style.xxx` 替代) |
|
|
241
|
+
| P3 | Vitest 中断言 offsetWidth / getBoundingClientRect(始终为 0) |
|
|
242
|
+
| P4 | Vitest 中验证 CSS 渲染效果(定位/穿透/层叠是浏览器行为) |
|
|
243
|
+
| P5 | 为迁就 Vitest 把静态样式内联到 `:style`(见规则 9) |
|
|
244
|
+
| P6 | E2E 中测试纯逻辑(那是 Vitest 的事) |
|
|
245
|
+
|
|
246
|
+
### 验收要点
|
|
247
|
+
|
|
248
|
+
- [ ] Vitest 中无 `getComputedStyle` / 无 Canvas 渲染产出断言 / 无 offsetWidth 断言。
|
|
249
|
+
- [ ] Mock 仅用于防崩溃 + 验证调用参数,未断言 mock 返回值。
|
|
250
|
+
- [ ] `element.style.xxx` 仅断言 props 直传值,未断言浏览器 API 产出。
|
|
251
|
+
- [ ] CSS 渲染效果(穿透、定位、层叠、尺寸)仅在 E2E 断言。
|
|
252
|
+
- [ ] 每个 spec 验收标准在 Vitest 或 E2E 中至少被一个覆盖。
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## 9. 组件样式放置规范
|
|
257
|
+
|
|
258
|
+
### 触发条件
|
|
259
|
+
|
|
260
|
+
- 编写任何 Vue SFC 组件的样式时。
|
|
261
|
+
|
|
262
|
+
### 核心原则
|
|
263
|
+
|
|
264
|
+
样式隔离 + 样式放置决定测试策略(与规则 8 互锁):
|
|
265
|
+
|
|
266
|
+
| 优先级 | 方式 | 适用 | 测试影响 |
|
|
267
|
+
|--------|------|------|----------|
|
|
268
|
+
| **1** | `<style scoped>` | 绝大多数组件 | class 名稳定,E2E 验证效果 |
|
|
269
|
+
| **2** | `<style module>` | 极强隔离/多主题 | hash 类名,需 data-testid 定位 |
|
|
270
|
+
| **3** | 内联 `:style` | **仅**运行时动态计算值 | Vitest 可断言(限 props 直传) |
|
|
271
|
+
|
|
272
|
+
### 关键约束
|
|
273
|
+
|
|
274
|
+
- **禁止**裸 `<style>`(无 scoped/module),会污染全局。
|
|
275
|
+
- **静态样式必须写在 `<style scoped>`**:position、pointer-events、z-index、background-repeat 等。
|
|
276
|
+
- **内联 `:style` 仅用于动态值**:prop 计算的宽高、Canvas 生成的 backgroundImage、JS 控制的 display。
|
|
277
|
+
- **禁止**为迁就 Vitest 而将静态样式内联(jsdom 不解析 scoped 样式不是内联的理由)。
|
|
278
|
+
|
|
279
|
+
### 样式放置 → 测试方式
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
静态定位/层叠/间距 → <style scoped> → E2E 验证效果
|
|
283
|
+
动态 prop 计算值 → 内联 :style → Vitest 验证 element.style.xxx
|
|
284
|
+
Canvas/API 产出 → 内联 :style → E2E 验证(Vitest 禁止断言)
|
|
285
|
+
条件 class 切换 → <style scoped> → Vitest 验证 classes()
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### 代码示例
|
|
289
|
+
|
|
290
|
+
```vue
|
|
291
|
+
<!-- ✅ 正确:静态样式在 scoped,仅动态值内联 -->
|
|
292
|
+
<template>
|
|
293
|
+
<div class="my-component" v-bind="$attrs">
|
|
294
|
+
<slot />
|
|
295
|
+
<div
|
|
296
|
+
class="overlay"
|
|
297
|
+
:style="{ backgroundImage: `url(${generatedUrl})` }"
|
|
298
|
+
data-testid="overlay"
|
|
299
|
+
/>
|
|
300
|
+
</div>
|
|
301
|
+
</template>
|
|
302
|
+
|
|
303
|
+
<style scoped>
|
|
304
|
+
.my-component { position: relative; }
|
|
305
|
+
.overlay {
|
|
306
|
+
position: absolute;
|
|
307
|
+
inset: 0;
|
|
308
|
+
pointer-events: none;
|
|
309
|
+
z-index: 10;
|
|
310
|
+
}
|
|
311
|
+
</style>
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
```vue
|
|
315
|
+
<!-- ❌ 错误:静态样式内联(为迁就 Vitest 测试) -->
|
|
316
|
+
<template>
|
|
317
|
+
<div :style="{ position: 'relative' }">
|
|
318
|
+
<div :style="{ position: 'absolute', pointerEvents: 'none', zIndex: 10 }" />
|
|
319
|
+
</div>
|
|
320
|
+
</template>
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### 验收要点
|
|
324
|
+
|
|
325
|
+
- [ ] 无裸 `<style>`(必须 scoped 或 module)。
|
|
326
|
+
- [ ] 静态样式在 `<style scoped>` 中,未因测试需求而内联。
|
|
327
|
+
- [ ] 内联 `:style` 仅含运行时动态值。
|
|
328
|
+
- [ ] Vitest 验证 class 存在 + props 内联值;渲染效果在 E2E 验证。
|