@dsh-workbench/module-tools 0.1.14 → 0.1.16
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 +71 -0
- package/bin/dsh-wb-module.mjs +4 -2
- package/package.json +3 -2
- package/src/build.mjs +2 -11
- package/src/check.mjs +88 -7
- package/src/checks/alias.mjs +51 -29
- package/src/checks/bundles.mjs +44 -31
- package/src/checks/cards.mjs +119 -107
- package/src/checks/contracts.mjs +621 -116
- package/src/checks/kit.mjs +127 -64
- package/src/checks/markers.mjs +55 -32
- package/src/checks/primitives.mjs +82 -57
- package/src/checks/source.mjs +106 -92
- package/src/checks/standalone.mjs +54 -24
- package/src/checks/style.mjs +133 -94
- package/src/css-injection.mjs +27 -0
- package/src/design.mjs +424 -0
- package/src/discover.mjs +1 -1
- package/src/init.mjs +6 -1
- package/src/publish.mjs +134 -0
- package/template/scripts/smoke.mjs.tpl +104 -4
- package/template-diy/README.md.tpl +282 -0
- package/template-diy/cordis.patch.yml.tpl +3 -0
- package/template-diy/design.json.tpl +38 -0
- package/template-diy/package.json.tpl +43 -0
- package/template-diy/scripts/smoke.mjs.tpl +232 -0
- package/template-diy/src/client.tsx.tpl +258 -0
- package/template-diy/src/host.ts.tpl +131 -0
- package/template-diy/src/messages.ts.tpl +28 -0
- package/template-diy/src/plugin.test.ts.tpl +359 -0
- package/template-diy/tsconfig.json +20 -0
- package/template-diy/types/globals.d.ts +27 -0
- package/template-diy/vitest.config.ts +14 -0
package/src/checks/cards.mjs
CHANGED
|
@@ -11,13 +11,15 @@
|
|
|
11
11
|
// 手法与 packages/workbench/scripts/selfcheck.mjs 里那套一致:产物是
|
|
12
12
|
// `window.__ModuleLoader__.load({id, factory})`,用假的 loader / require 把它拉起来。
|
|
13
13
|
// 覆盖范围跟着 `dsh.workbench` 自述清单走 —— 新模块不用改这里。
|
|
14
|
+
//
|
|
15
|
+
// 形状(十条判据统一):导出 `title` 与 `run()`,`run()` 返回三态结果;
|
|
16
|
+
// 打印与退出码归 `../check.mjs` 那一层。
|
|
14
17
|
|
|
15
18
|
import { existsSync, readFileSync } from 'node:fs';
|
|
16
19
|
import { join } from 'node:path';
|
|
17
20
|
import { discoverModulePackages } from '../discover.mjs';
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
const modulePackages = () => discoverModulePackages({ root: process.cwd() });
|
|
22
|
+
export const title = '卡片渲染';
|
|
21
23
|
|
|
22
24
|
// 任何属性都拿得到、任何调用都返回自己的替身 —— 这样「外壳还没给数据」的各种形状
|
|
23
25
|
// 都不会让卡片因为我们**没桩到某个字段**而假红。真红只留给卡片自己的代码。
|
|
@@ -163,120 +165,130 @@ function render(node, depth, budget) {
|
|
|
163
165
|
return count;
|
|
164
166
|
}
|
|
165
167
|
|
|
166
|
-
|
|
167
|
-
const
|
|
168
|
+
export async function run() {
|
|
169
|
+
const modulePackages = discoverModulePackages({ root: process.cwd() });
|
|
170
|
+
const problems = [];
|
|
171
|
+
const rows = [];
|
|
168
172
|
|
|
169
|
-
for (const pkg of modulePackages
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
for (const pkg of modulePackages) {
|
|
174
|
+
const name = pkg.manifest.name;
|
|
175
|
+
const clientFile = join(pkg.dir, 'client.js');
|
|
176
|
+
if (!existsSync(clientFile)) {
|
|
177
|
+
problems.push(`${name}: 没有 client.js —— 先 build`);
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
176
180
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
181
|
+
let face;
|
|
182
|
+
try {
|
|
183
|
+
const loaded = loadFace(clientFile);
|
|
184
|
+
face = loaded.exports;
|
|
185
|
+
} catch (error) {
|
|
186
|
+
problems.push(`${name}: 产物加载不起来 —— ${error.message}`);
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
185
189
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
190
|
+
let registered;
|
|
191
|
+
const ctx = {
|
|
192
|
+
get: (key) =>
|
|
193
|
+
key === 'workbenchUnits'
|
|
194
|
+
? {
|
|
195
|
+
registerUnit: (value) => {
|
|
196
|
+
registered = value;
|
|
197
|
+
return () => {};
|
|
198
|
+
},
|
|
199
|
+
}
|
|
200
|
+
: undefined,
|
|
201
|
+
effect: (fn) => {
|
|
202
|
+
fn();
|
|
203
|
+
return () => {};
|
|
204
|
+
},
|
|
205
|
+
provide: () => {},
|
|
206
|
+
logger: { info: () => {}, warn: () => {}, error: () => {} },
|
|
207
|
+
};
|
|
208
|
+
const apply = face?.apply ?? face?.default?.apply;
|
|
209
|
+
if (typeof apply !== 'function') {
|
|
210
|
+
problems.push(`${name}: 产物没有导出 apply(外壳挂不上这个模块)`);
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
try {
|
|
214
|
+
apply(ctx);
|
|
215
|
+
} catch (error) {
|
|
216
|
+
problems.push(`${name}: apply 抛了 —— ${error.message}`);
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
215
219
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
220
|
+
const card = registered?.card;
|
|
221
|
+
if (typeof card !== 'function') {
|
|
222
|
+
problems.push(`${name}: apply 之后没登记卡片(registerUnit 没拿到 card)`);
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
221
225
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
226
|
+
const props = {
|
|
227
|
+
world: { current: {} },
|
|
228
|
+
t: (key) => key,
|
|
229
|
+
refreshToken: 0,
|
|
230
|
+
onRefresh: () => {},
|
|
231
|
+
onNavigate: () => {},
|
|
232
|
+
onOpenMarket: () => {},
|
|
233
|
+
onSummary: () => {},
|
|
234
|
+
};
|
|
231
235
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
236
|
+
let tree;
|
|
237
|
+
try {
|
|
238
|
+
tree = card(props);
|
|
239
|
+
} catch (error) {
|
|
240
|
+
problems.push(`${name}: 空数据下卡片抛了 —— ${error.message}`);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
239
243
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
+
if (tree === null || tree === undefined) {
|
|
245
|
+
problems.push(`${name}: 空数据下卡片返回空(界面上就是一片空白)`);
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
244
248
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
249
|
+
const budget = { left: 20000, maxDepth: 0, classNames: new Set(), stubs: new Set() };
|
|
250
|
+
let count;
|
|
251
|
+
try {
|
|
252
|
+
count = render(tree, 0, budget);
|
|
253
|
+
} catch (error) {
|
|
254
|
+
const where = (error.stack ?? '').split('\n').slice(1, 4).join(' | ');
|
|
255
|
+
problems.push(`${name}: 卡片体内的组件抛了 —— ${error.message}\n ${where}`);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (count <= 1) {
|
|
259
|
+
problems.push(`${name}: 卡片只画出一个节点 —— 卡片体没跑(或什么都没画)`);
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
// 卡片得**套上外壳给的卡壳**:要么用 `kit.components.Card` 这个组件(推荐、也是 hello 现在的做法),
|
|
263
|
+
// 要么自己写契约类 `wb-card`(`board.css` 里那条,兄弟模块现在还是这么写的)。
|
|
264
|
+
//
|
|
265
|
+
// 用户实测(2026-10-09):"我们的 hello module 怎么不是卡片" —— 面板里那块内容既没有底色也没有
|
|
266
|
+
// 描边,看着就是标题加一段话。原因是卡片函数没套壳:当时用的是 `wb-view`(那是面板列布局),
|
|
267
|
+
// 更早那份装进 profile 的产物还自己搓过 `wb-hello*`。两种都查得出来:组件走 stub 名,类名走 classNames。
|
|
268
|
+
const shelled = budget.classNames.has('wb-card') || budget.stubs.has('Card');
|
|
269
|
+
if (!shelled) {
|
|
270
|
+
problems.push(
|
|
271
|
+
`${name}: 卡片没套外壳的卡壳 —— 用 kit.components.Card(推荐),或自己写契约类 wb-card + ` +
|
|
272
|
+
`wb-cardBody;裸内容在面板里看起来就"不是一张卡片"`,
|
|
273
|
+
);
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
rows.push(`${name}: 空数据下画得出 ${count} 个节点(最深 ${budget.maxDepth} 层)`);
|
|
253
277
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
278
|
+
|
|
279
|
+
if (problems.length > 0) {
|
|
280
|
+
return { status: 'fail', notes: [], problems };
|
|
257
281
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const shelled = budget.classNames.has('wb-card') || budget.stubs.has('Card');
|
|
265
|
-
if (!shelled) {
|
|
266
|
-
problems.push(
|
|
267
|
-
`${name}: 卡片没套外壳的卡壳 —— 用 kit.components.Card(推荐),或自己写契约类 wb-card + ` +
|
|
268
|
-
`wb-cardBody;裸内容在面板里看起来就"不是一张卡片"`,
|
|
269
|
-
);
|
|
270
|
-
continue;
|
|
282
|
+
if (modulePackages.length === 0) {
|
|
283
|
+
return {
|
|
284
|
+
status: 'skip',
|
|
285
|
+
notes: ['没有模块包(没有声明 dsh.workbench 的包)—— 没有卡片可渲染'],
|
|
286
|
+
problems: [],
|
|
287
|
+
};
|
|
271
288
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
for (const problem of problems) console.error(` · ${problem}`);
|
|
278
|
-
process.exit(1);
|
|
289
|
+
return {
|
|
290
|
+
status: 'pass',
|
|
291
|
+
notes: [`${rows.length} 张卡片在**空数据**下都画得出来(不许抛)`, ...rows],
|
|
292
|
+
problems: [],
|
|
293
|
+
};
|
|
279
294
|
}
|
|
280
|
-
|
|
281
|
-
console.log(`✔ 卡片渲染通过:${rows.length} 张卡片在**空数据**下都画得出来(不许抛)`);
|
|
282
|
-
for (const row of rows) console.log(` ${row}`);
|