@mzzsfy/dsh-shell-select 0.4.5 → 0.4.7
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 +8 -11
- package/package.json +1 -1
- package/src/client.js +54 -55
- package/test/client-render.test.mjs +37 -0
package/README.md
CHANGED
|
@@ -40,20 +40,17 @@ Windows 宿主 shell 链接管:接管根组合中的官方 `pwsh` 工具与执
|
|
|
40
40
|
```yaml
|
|
41
41
|
shell-select:
|
|
42
42
|
shells:
|
|
43
|
-
- id: pwsh
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
env: {} # 条目级环境变量,如 { MSYSTEM: MINGW64 };wsl 形键自动经 WSLENV 透传
|
|
43
|
+
- id: pwsh # id 亦作显示名
|
|
44
|
+
kind: pwsh # pwsh | bash | cmd | wsl
|
|
45
|
+
path: "" # 留空自动探测;bash 形探测序含 msys2 锚位(见下)
|
|
46
|
+
args: [] # 留空用形态默认;自定义模板以 {command} 为命令占位
|
|
47
|
+
login: false # bash 形 true 时 -lc 登录壳(-lc 只取 /usr/bin;/mingw64/bin 需另配 env MSYSTEM=MINGW64)
|
|
48
|
+
distro: "" # wsl 形发行版(如 Ubuntu-22.04),留空用 wsl 默认;args 模板条目忽略
|
|
49
|
+
env: {} # 条目级环境变量,如 { MSYSTEM: MINGW64 };wsl 形键自动经 WSLENV 透传
|
|
51
50
|
- id: git-bash
|
|
52
|
-
name: Git Bash
|
|
53
51
|
kind: bash
|
|
54
52
|
path: ""
|
|
55
53
|
- id: cmd
|
|
56
|
-
name: CMD
|
|
57
54
|
kind: cmd
|
|
58
55
|
path: ""
|
|
59
56
|
default: pwsh
|
|
@@ -98,4 +95,4 @@ env 优先级(同键高右):内置覆盖集(NO_COLOR/PAGER/GIT_PAGER)< 条目 `e
|
|
|
98
95
|
|
|
99
96
|
## dsh 版本兼容
|
|
100
97
|
|
|
101
|
-
按仓库动态窗口验证(scripts/compat/window.mjs),不预置任何固定版本槽:主测 = 渠道 dist-tag 最新 rc,完全适配口径;基线 = npm latest,不崩溃底线口径;主测与基线同版时收敛单槽。本包声明 `dsh.hostMin = "0.1.7-rc.1"`:低于该代际的宿主 API 面未验证,compat 装载层自动排除。逐轮实测结论见 `docs/兼容性测试/逐包测试进度.md`
|
|
98
|
+
按仓库动态窗口验证(scripts/compat/window.mjs),不预置任何固定版本槽:主测 = 渠道 dist-tag 最新 rc,完全适配口径;基线 = npm latest,不崩溃底线口径;主测与基线同版时收敛单槽。本包声明 `dsh.hostMin = "0.1.7-rc.1"`:低于该代际的宿主 API 面未验证,compat 装载层自动排除。逐轮实测结论见 `docs/兼容性测试/逐包测试进度.md`(本地维护,不入库)与本包 `兼容性测试.md`。
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mzzsfy/dsh-shell-select",
|
|
3
3
|
"description": "Windows shell 接管:替换默认 pwsh 工具为可配置多客户端的 shell 工具(git bash/WSL/cmd/pwsh,自定义路径,默认客户端,模型按名选择);支持命令 deny 黑名单、会话终端卡增强和直接 pwsh 接管徽章,接管失败自动回退官方 pwsh 链",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.7",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"exports": {
|
package/src/client.js
CHANGED
|
@@ -27,12 +27,14 @@ window.__ModuleLoader__.load({
|
|
|
27
27
|
}
|
|
28
28
|
return fallback
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
// 降级自绘状态点:色相经 CSS 类消费包令牌(禁 JS 侧字面色,主题切换跟随)
|
|
31
|
+
const DOT_CLASS = { done: 'sls-dot--ok', error: 'sls-dot--err', warning: 'sls-dot--warn', ongoing: 'sls-dot--idle' }
|
|
31
32
|
// 降级自绘:模块表缺 primitives 时保持可见性(形态近似官方 StateDot/图标)
|
|
32
33
|
const TOOLVIEW_ICONS = {
|
|
33
34
|
StateDot: createElementOf(['StateDot'], ({ state }) => h('span', {
|
|
35
|
+
className: 'sls-dot ' + (DOT_CLASS[state] ?? DOT_CLASS.ongoing),
|
|
34
36
|
style: {
|
|
35
|
-
width: 8, height: 8, borderRadius: '50%',
|
|
37
|
+
width: 8, height: 8, borderRadius: '50%',
|
|
36
38
|
display: 'inline-block', flex: 'none',
|
|
37
39
|
},
|
|
38
40
|
})),
|
|
@@ -203,43 +205,50 @@ window.__ModuleLoader__.load({
|
|
|
203
205
|
}
|
|
204
206
|
|
|
205
207
|
const CSS = [
|
|
206
|
-
|
|
208
|
+
// 色彩令牌:直接引用宿主语义别名,禁止字面 fallback(DEVELOPMENT/plugin-ui-design.md)
|
|
209
|
+
'.sls-card { --sls-border:var(--dsw-alias-border-l1); --sls-accent:var(--dsw-alias-brand-primary); --sls-track:var(--dsw-alias-border-l1); --sls-thumb:var(--dsw-alias-label-tertiary); --sls-bg-base:var(--dsw-alias-bg-base); --sls-mono:var(--ds-font-family-code);',
|
|
210
|
+
' display:flex; flex-direction:column; gap:10px; }',
|
|
207
211
|
'.sls-row { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }',
|
|
208
|
-
'.sls-entry { display:flex; flex-direction:column; gap:6px; padding:10px; border:1px solid var(--sls-border
|
|
212
|
+
'.sls-entry { display:flex; flex-direction:column; gap:6px; padding:10px; border:1px solid var(--sls-border); border-radius:8px; }',
|
|
209
213
|
'.sls-entry__head { display:flex; align-items:center; gap:8px; }',
|
|
210
214
|
'.sls-grid { display:grid; grid-template-columns: 90px 1fr; gap:4px 8px; align-items:center; }',
|
|
211
215
|
'.sls-grid__label { opacity:.75; font-size:12px; }',
|
|
212
|
-
'.sls-input { padding:4px 8px; border-radius:6px; border:1px solid var(--sls-border
|
|
216
|
+
'.sls-input { padding:4px 8px; border-radius:6px; border:1px solid var(--sls-border); background:transparent; color:inherit; min-width:0; }',
|
|
213
217
|
'.sls-input--wide { width:100%; box-sizing:border-box; }',
|
|
214
|
-
'.sls-btn { padding:3px 10px; border-radius:6px; border:1px solid var(--sls-border
|
|
218
|
+
'.sls-btn { padding:3px 10px; border-radius:6px; border:1px solid var(--sls-border); background:transparent; color:inherit; cursor:pointer; font-size:12px; }',
|
|
215
219
|
'.sls-btn:disabled { opacity:.5; cursor:default; }',
|
|
216
|
-
'.sls-btn--primary { border-color: transparent; background: var(--sls-accent
|
|
217
|
-
'.sls-badge { font-size:11px; padding:1px 8px; border-radius:999px; border:1px solid var(--sls-border
|
|
218
|
-
'.sls-badge--ok { color
|
|
219
|
-
'.sls-badge--bad { color
|
|
220
|
-
'.sls-badge--default { color
|
|
220
|
+
'.sls-btn--primary { border-color: transparent; background: var(--sls-accent); color:var(--sls-bg-base); }',
|
|
221
|
+
'.sls-badge { font-size:11px; padding:1px 8px; border-radius:999px; border:1px solid var(--sls-border); opacity:.85; }',
|
|
222
|
+
'.sls-badge--ok { color:var(--dsw-alias-state-success-primary); border-color:var(--dsw-alias-state-success-primary); }',
|
|
223
|
+
'.sls-badge--bad { color:var(--dsw-alias-state-error-primary); border-color:var(--dsw-alias-state-error-primary); }',
|
|
224
|
+
'.sls-badge--default { color:var(--sls-bg-base); background:var(--sls-accent); border-color:transparent; }',
|
|
221
225
|
'.sls-hint { font-size:12px; opacity:.7; white-space:pre-wrap; overflow-wrap:anywhere; }',
|
|
222
|
-
'.sls-error { font-size:12px; color
|
|
223
|
-
'.sls-args { font-size:12px; font-family:var(--sls-mono
|
|
224
|
-
'.sls-rules { display:flex; flex-direction:column; gap:6px; padding:10px; border:1px solid var(--sls-border
|
|
226
|
+
'.sls-error { font-size:12px; color:var(--dsw-alias-state-error-primary); white-space:pre-wrap; }',
|
|
227
|
+
'.sls-args { font-size:12px; font-family:var(--sls-mono); }',
|
|
228
|
+
'.sls-rules { display:flex; flex-direction:column; gap:6px; padding:10px; border:1px solid var(--sls-border); border-radius:8px; }',
|
|
225
229
|
'.sls-rules__head { display:flex; align-items:center; gap:8px; }',
|
|
226
230
|
'.sls-rules__title { font-weight:500; }',
|
|
227
231
|
'.sls-rules__note { font-size:12px; opacity:.7; }',
|
|
228
232
|
'.sls-rule { display:flex; align-items:center; gap:6px; }',
|
|
229
233
|
'.sls-rule__no { flex:none; width:18px; text-align:right; font-size:12px; opacity:.45; user-select:none; }',
|
|
230
|
-
'.sls-rule__input { flex:1; min-width:0; padding:4px 8px; border-radius:6px; border:1px solid var(--sls-border
|
|
231
|
-
'.sls-rule__input:focus-visible { outline:2px solid var(--sls-accent
|
|
232
|
-
'.sls-rule--bad .sls-rule__input { border-color
|
|
233
|
-
'.sls-rule__err { flex:none; max-width:40%; font-size:11px; color
|
|
234
|
+
'.sls-rule__input { flex:1; min-width:0; padding:4px 8px; border-radius:6px; border:1px solid var(--sls-border); background:transparent; color:inherit; font-size:12px; font-family:var(--sls-mono); resize:vertical; }',
|
|
235
|
+
'.sls-rule__input:focus-visible { outline:2px solid var(--sls-accent); outline-offset:1px; }',
|
|
236
|
+
'.sls-rule--bad .sls-rule__input { border-color:var(--dsw-alias-state-error-primary); }',
|
|
237
|
+
'.sls-rule__err { flex:none; max-width:40%; font-size:11px; color:var(--dsw-alias-state-error-primary); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }',
|
|
238
|
+
// 降级状态点:色相消费状态语义令牌
|
|
239
|
+
'.sls-dot--ok { background:var(--dsw-alias-state-success-primary); }',
|
|
240
|
+
'.sls-dot--err { background:var(--dsw-alias-state-error-primary); }',
|
|
241
|
+
'.sls-dot--warn { background:var(--dsw-alias-state-warn-primary); }',
|
|
242
|
+
'.sls-dot--idle { background:var(--dsw-alias-label-tertiary); }',
|
|
234
243
|
'.sls-rule__del { flex:none; padding:2px 8px; }',
|
|
235
244
|
'.sls-switch { display:inline-flex; align-items:center; cursor:pointer; }',
|
|
236
245
|
'.sls-switch input[type="checkbox"] { position:absolute; opacity:0; width:1px; height:1px; }',
|
|
237
|
-
'.sls-switch__track { position:relative; width:34px; height:19px; border-radius:999px; box-sizing:border-box; background:var(--sls-track
|
|
238
|
-
'.sls-switch__thumb { position:absolute; top:50%; left:2px; width:13px; height:13px; border-radius:50%; background:var(--sls-thumb
|
|
239
|
-
'.sls-switch:hover .sls-switch__track { border-color:var(--sls-accent
|
|
240
|
-
'.sls-switch input[type="checkbox"]:checked + .sls-switch__track { background:var(--sls-accent
|
|
241
|
-
'.sls-switch input[type="checkbox"]:checked + .sls-switch__track .sls-switch__thumb { left:17px; background:var(--sls-bg-base
|
|
242
|
-
'.sls-switch input[type="checkbox"]:focus-visible + .sls-switch__track { outline:2px solid var(--sls-accent
|
|
246
|
+
'.sls-switch__track { position:relative; width:34px; height:19px; border-radius:999px; box-sizing:border-box; background:var(--sls-track); border:1px solid var(--sls-border); transition:background .15s, border-color .15s; }',
|
|
247
|
+
'.sls-switch__thumb { position:absolute; top:50%; left:2px; width:13px; height:13px; border-radius:50%; background:var(--sls-thumb); transform:translateY(-50%); transition:left .15s, background .15s; }',
|
|
248
|
+
'.sls-switch:hover .sls-switch__track { border-color:var(--sls-accent); }',
|
|
249
|
+
'.sls-switch input[type="checkbox"]:checked + .sls-switch__track { background:var(--sls-accent); border-color:var(--sls-accent); }',
|
|
250
|
+
'.sls-switch input[type="checkbox"]:checked + .sls-switch__track .sls-switch__thumb { left:17px; background:var(--sls-bg-base); }',
|
|
251
|
+
'.sls-switch input[type="checkbox"]:focus-visible + .sls-switch__track { outline:2px solid var(--sls-accent); outline-offset:1px; }',
|
|
243
252
|
'.sls-switch input[type="checkbox"]:disabled + .sls-switch__track { opacity:.5; }',
|
|
244
253
|
// tool.call.toolview 卡片(key 'shell'):官方 terminal 行同构 + 复制/折行增强。
|
|
245
254
|
// 色彩对齐官方 ToolRow:标题 label-secondary、icon 盒 label-tertiary(实证自
|
|
@@ -249,39 +258,35 @@ window.__ModuleLoader__.load({
|
|
|
249
258
|
'.sls-tv__row--exp { cursor:pointer; user-select:none; }',
|
|
250
259
|
'.sls-tv__lead { display:flex; align-items:center; gap:4px; color:var(--dsw-alias-label-tertiary, inherit); }',
|
|
251
260
|
// 官方 ToolRow 同构:行首仅 icon,无展开箭头(可展开性由指针与整行点击承载);
|
|
252
|
-
//
|
|
253
|
-
'.sls-tv__leadStack { position:relative; width:16px; height:16px; display:inline-flex; align-items:center; justify-content:center; flex:none; }',
|
|
254
|
-
'.sls-tv__iconIdle { display:inline-flex; }',
|
|
255
|
-
'.sls-tv__stateCover { position:absolute; inset:0; margin:auto; display:inline-flex; align-items:center; justify-content:center; background:transparent; }',
|
|
256
|
-
'.sls-tv__stateCover::before { content:""; position:absolute; inset:-2px; border-radius:50%; background:var(--dsw-alias-bg-primary, #fff); }',
|
|
257
|
-
'.sls-tv__stateCover > span { position:relative; }',
|
|
261
|
+
// 错误/进行中状态点原位替换 icon(官方 icon 槽 StateDot 同型先例,无背景依赖)
|
|
258
262
|
'.sls-tv__sr { position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); }',
|
|
259
263
|
'.sls-tv__title { font-weight:400; }',
|
|
260
264
|
'.sls-tv__sep { width:2px; height:2px; border-radius:1px; background:var(--dsw-alias-label-caption, currentColor); opacity:.8; flex:none; }',
|
|
261
265
|
'.sls-tv__sum { color:var(--dsw-alias-label-tertiary, inherit); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }',
|
|
262
|
-
'.sls-tv__sum--err { color:var(--dsw-alias-state-error-primary
|
|
263
|
-
'.sls-tv__body { margin:6px 0 4px; border:1px solid
|
|
264
|
-
'.sls-tv__head { display:flex; align-items:center; gap:8px; padding:6px 10px; border-bottom:1px solid
|
|
266
|
+
'.sls-tv__sum--err { color:var(--dsw-alias-state-error-primary); }',
|
|
267
|
+
'.sls-tv__body { margin:6px 0 4px; border:1px solid var(--sls-border); border-radius:8px; overflow:hidden; }',
|
|
268
|
+
'.sls-tv__head { display:flex; align-items:center; gap:8px; padding:6px 10px; border-bottom:1px solid var(--sls-border); background:color-mix(in srgb, var(--dsw-alias-label-tertiary) 5%, transparent); }',
|
|
265
269
|
// 头部单行片段禁折行:cwd 行宽不足时收缩出省略号,徽章不收缩不折行
|
|
266
|
-
'.sls-tv__cwd { font-family:var(--sls-mono
|
|
270
|
+
'.sls-tv__cwd { font-family:var(--sls-mono); font-size:12px; opacity:.7; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }',
|
|
267
271
|
'.sls-tv__takeover { font-size:11px; padding:0 7px; border-radius:999px; border:1px solid currentColor; opacity:.75; flex:none; white-space:nowrap; }',
|
|
268
|
-
'.sls-tv__badge { font-size:11px; padding:0 7px; border-radius:999px; border:1px solid
|
|
269
|
-
'.sls-tv__pill { font-size:12px; color
|
|
272
|
+
'.sls-tv__badge { font-size:11px; padding:0 7px; border-radius:999px; border:1px solid var(--sls-border); opacity:.85; flex:none; white-space:nowrap; }',
|
|
273
|
+
'.sls-tv__pill { font-size:12px; color:var(--dsw-alias-state-error-primary); flex:none; white-space:nowrap; }',
|
|
270
274
|
'.sls-tv__pill--bg { color:var(--dsw-alias-label-tertiary, inherit); }',
|
|
271
|
-
'.sls-tv__duration { font-family:var(--sls-mono
|
|
275
|
+
'.sls-tv__duration { font-family:var(--sls-mono); font-size:12px; color:var(--dsw-alias-label-tertiary, inherit); flex:none; white-space:nowrap; font-variant-numeric:tabular-nums; }',
|
|
272
276
|
// 运行中脉冲文字:零信息窗口(参数未到)的活体反馈
|
|
273
277
|
'.sls-tv__pulse { font-size:12px; color:var(--dsw-alias-label-tertiary, inherit); flex:none; white-space:nowrap; animation:sls-pulse 1.5s ease-in-out infinite; }',
|
|
274
278
|
'@keyframes sls-pulse { 0%,100% { opacity:.35; } 50% { opacity:1; } }',
|
|
275
279
|
'.sls-tv__sp { flex:1; }',
|
|
276
280
|
'.sls-tv__copy { display:flex; align-items:center; gap:2px; flex:none; }',
|
|
277
|
-
'.sls-tv__copyBtn { padding:2px 8px; border:1px solid
|
|
281
|
+
'.sls-tv__copyBtn { padding:2px 8px; border:1px solid var(--sls-border); border-radius:6px; background:transparent; color:inherit; cursor:pointer; font-size:12px; }',
|
|
278
282
|
'.sls-tv__copyBtn:disabled { opacity:.4; cursor:default; }',
|
|
279
|
-
'.sls-tv__copyBtn:not(:disabled):hover { background:
|
|
280
|
-
'.sls-tv__cmd { padding:8px 10px; font-family:var(--sls-mono
|
|
283
|
+
'.sls-tv__copyBtn:not(:disabled):hover { background:var(--dsw-alias-interactive-bg-hover); }',
|
|
284
|
+
'.sls-tv__cmd { padding:8px 10px; font-family:var(--sls-mono); font-size:12.5px; white-space:pre-wrap; word-break:break-all; display:flex; }',
|
|
281
285
|
'.sls-tv__cmdNo { flex:none; text-align:right; margin-right:10px; opacity:.4; user-select:none; }',
|
|
282
286
|
'.sls-tv__cmdText { flex:1; min-width:0; }',
|
|
283
|
-
'.sls-tv__out { margin:0; padding:8px 10px; border-top:1px solid
|
|
284
|
-
'.sls-
|
|
287
|
+
'.sls-tv__out { margin:0; padding:8px 10px; border-top:1px solid var(--sls-border); font-family:var(--sls-mono); font-size:12.5px; white-space:pre; overflow-x:auto; max-height:320px; overflow-y:auto; }',
|
|
288
|
+
'.sls-tv__out--inline { border:1px solid var(--sls-border); border-radius:8px; }',
|
|
289
|
+
'.sls-tv__inspect { display:flex; align-items:center; gap:4px; padding:4px 10px; border:none; border-top:1px solid var(--sls-border); background:transparent; color:inherit; opacity:.6; cursor:pointer; font-size:12px; }',
|
|
285
290
|
'.sls-tv__inspect:hover { opacity:1; }',
|
|
286
291
|
].join('\n')
|
|
287
292
|
|
|
@@ -428,18 +433,12 @@ window.__ModuleLoader__.load({
|
|
|
428
433
|
}
|
|
429
434
|
// LOGIC-END shellCardModel
|
|
430
435
|
|
|
431
|
-
// 官方
|
|
432
|
-
//
|
|
433
|
-
function
|
|
436
|
+
// 行首状态节点:错误/进行中原位替换 icon(官方 icon 槽 running→StateDot 同型
|
|
437
|
+
// 先例;不叠白片遮罩——宿主无 bg-primary token,遮罩恒落 #fff 白圆,暗色刺眼)
|
|
438
|
+
function leadingNode({ status, icons }) {
|
|
434
439
|
const failed = status === 'failed' || status === 'signaled' || status === 'generic-error'
|
|
435
440
|
const dot = failed ? icons.StateDot({ state: 'error' }) : status === 'generic-warn' ? icons.StateDot({ state: 'warning' }) : status === 'running' ? icons.StateDot({ state: 'ongoing' }) : null
|
|
436
|
-
|
|
437
|
-
return h('span', { className: 'sls-tv__leadStack' },
|
|
438
|
-
h('span', { className: 'sls-tv__iconIdle' }, icons.IconApi({ size: 14 })),
|
|
439
|
-
h('span', { className: 'sls-tv__stateCover' }, dot),
|
|
440
|
-
)
|
|
441
|
-
}
|
|
442
|
-
return icons.IconApi({ size: 14 })
|
|
441
|
+
return dot !== null ? dot : icons.IconApi({ size: 14 })
|
|
443
442
|
}
|
|
444
443
|
|
|
445
444
|
// 时长格式:秒 → m:ss;超一小时 → h:mm:ss
|
|
@@ -536,7 +535,7 @@ window.__ModuleLoader__.load({
|
|
|
536
535
|
} : undefined,
|
|
537
536
|
},
|
|
538
537
|
h('span', { className: 'sls-tv__lead' },
|
|
539
|
-
|
|
538
|
+
leadingNode({ status, icons: TOOLVIEW_ICONS }),
|
|
540
539
|
),
|
|
541
540
|
h('span', { className: 'sls-tv__title' }, 'Shell'),
|
|
542
541
|
summary !== '' ? h('span', { className: 'sls-tv__sep', 'aria-hidden': true }) : null,
|
|
@@ -544,7 +543,7 @@ window.__ModuleLoader__.load({
|
|
|
544
543
|
model.intercepted ? h(TakeoverBadge, { en }) : null,
|
|
545
544
|
status === 'running' ? h('span', { className: 'sls-tv__pulse' }, en ? 'running…' : '运行中…') : null,
|
|
546
545
|
),
|
|
547
|
-
open && expandable ? h('pre', { className: 'sls-tv__out
|
|
546
|
+
open && expandable ? h('pre', { className: 'sls-tv__out sls-tv__out--inline' }, model.command + (model.output !== null && model.output !== '' ? `\n${model.output}` : '')) : null,
|
|
548
547
|
inspect !== undefined ? h('button', { className: 'sls-tv__inspect', onClick: inspect }, TOOLVIEW_ICONS.IconInspect({}), en ? 'Inspect' : '检查') : null,
|
|
549
548
|
)
|
|
550
549
|
}
|
|
@@ -637,7 +636,7 @@ window.__ModuleLoader__.load({
|
|
|
637
636
|
},
|
|
638
637
|
},
|
|
639
638
|
h('span', { className: 'sls-tv__lead' },
|
|
640
|
-
|
|
639
|
+
leadingNode({ status: model.status, icons: TOOLVIEW_ICONS }),
|
|
641
640
|
),
|
|
642
641
|
srStatus !== null ? h('span', { className: 'sls-tv__sr' }, srStatus) : null,
|
|
643
642
|
h('span', { className: 'sls-tv__title' }, 'Shell'),
|
|
@@ -162,6 +162,43 @@ test('后台卡头部守卫:状态点缺省渲染(bg pill 即标识),非法 Stat
|
|
|
162
162
|
assert.doesNotMatch(source, /dot: 'none'/)
|
|
163
163
|
})
|
|
164
164
|
|
|
165
|
+
test('状态点原位替换:失败/进行中只渲染状态点,不再叠图标与白片遮罩', () => {
|
|
166
|
+
// Given 失败/进行中/完成的调用块;When 折叠渲染;Then 行首仅状态点或图标,
|
|
167
|
+
// 无图标+状态点叠加、无遮罩容器(遮罩白底 #fff 在暗色主题呈现白圆事故)。
|
|
168
|
+
const nodesOf = (element) => {
|
|
169
|
+
const nodes = []
|
|
170
|
+
const walk = (node) => { if (!node || typeof node !== 'object') return; if (Array.isArray(node)) return node.forEach(walk); nodes.push(node); node.children?.forEach(walk) }
|
|
171
|
+
walk(element)
|
|
172
|
+
return nodes
|
|
173
|
+
}
|
|
174
|
+
const failed = nodesOf(toolviewOf(loadClient(), 'shell')({
|
|
175
|
+
block: settledBlock(JSON.stringify({ command: 'exit 3', description: 'boom' }), 'err\n[exit code: 3]'),
|
|
176
|
+
cwd: 'C:\\repo',
|
|
177
|
+
}))
|
|
178
|
+
assert.ok(failed.some((node) => String(node.props?.className ?? '').includes('sls-dot--err')), '失败行应有红色状态点(sls-dot--err 令牌类,主题自适应)')
|
|
179
|
+
assert.ok(failed.every((node) => node.props?.style?.borderRadius !== 3), '状态点行不应再渲染降级图标矩形(叠加形态)')
|
|
180
|
+
assert.ok(failed.every((node) => !String(node.props?.className ?? '').includes('stateCover')), '不应存在遮罩容器')
|
|
181
|
+
const running = nodesOf(toolviewOf(loadClient(), 'shell')({
|
|
182
|
+
block: { callId: 'c9', name: 'shell', argsRaw: JSON.stringify({ command: 'sleep 1', description: 'wait' }), time: Date.now() },
|
|
183
|
+
cwd: 'C:\\repo',
|
|
184
|
+
}))
|
|
185
|
+
assert.ok(running.some((node) => String(node.props?.className ?? '').includes('sls-dot--idle')), '进行中行应有状态点(sls-dot--idle 令牌类)')
|
|
186
|
+
assert.ok(running.every((node) => node.props?.style?.borderRadius !== 3), '进行中行不应再渲染降级图标矩形(叠加形态)')
|
|
187
|
+
const done = nodesOf(toolviewOf(loadClient(), 'shell')({
|
|
188
|
+
block: settledBlock(JSON.stringify({ command: 'echo ok', description: 'fine' }), 'ok\n[exit code: 0]'),
|
|
189
|
+
cwd: 'C:\\repo',
|
|
190
|
+
}))
|
|
191
|
+
assert.ok(done.some((node) => node.props?.style?.borderRadius === 3), '完成行保留工具图标')
|
|
192
|
+
assert.ok(done.every((node) => node.props?.style?.background === undefined), '完成行无状态点')
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
test('遮罩路径清除守卫:遮罩容器类与白底 token 不再存在', () => {
|
|
196
|
+
// Given 修复后的 client.js;When 源码扫描;Then 遮罩结构与其背景依赖全部消失,
|
|
197
|
+
// 状态点以原位替换呈现,双主题无背景依赖。
|
|
198
|
+
assert.doesNotMatch(source, /stateCover|leadStack|iconIdle/)
|
|
199
|
+
assert.doesNotMatch(source, /--dsw-alias-bg-primary/)
|
|
200
|
+
})
|
|
201
|
+
|
|
165
202
|
test('hooks 恒序守卫:组件内 hook 调用必须全部位于第一个提前 return 之前', () => {
|
|
166
203
|
// 真实 React 的 hooks 链表按调用序对位:提前 return 之后的 hook 使不同
|
|
167
204
|
// 块形态(generic/terminal)的 hook 数量分叉 → "Rendered fewer hooks
|