dsh-plugin-workbench 0.0.16 → 0.0.20
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/CHANGELOG.md +67 -1
- package/README.en.md +19 -3
- package/README.md +16 -2
- package/docs/banner.svg +25 -0
- package/lib/client.js +1 -1
- package/lib/index.js +5 -2
- package/package.json +1 -1
- package/scripts/patch-layout.mjs +131 -6
- package/src/client/files.module.css +0 -12
- package/src/index.ts +13 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.20] - 2026-09-07
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- 全链路代码审查(子代理逐变体模拟验证)后的三处收尾:
|
|
8
|
+
1. **`npm-delta` 变体缺 watch 块**(中危):0.0.16/17 旧补丁(无 occupancy)用户经
|
|
9
|
+
delta 打完后没有 `slots/changed` 同步——运行时卸载插件列不即时收起(重启后才由
|
|
10
|
+
inject hook 兜底)。delta 表补上 watch 块注入,已用构造的旧补丁态产物实测命中。
|
|
11
|
+
2. **host 自愈 marker 是脚本的弱子集**(形式问题):`src/index.ts` 的清单缺
|
|
12
|
+
`renderSlot("explorer.preview"` 且 explorerCol 用短前缀——受损/半回退 bundle 可能
|
|
13
|
+
过 host 检查却过不了脚本校验,自愈永不触发。host 清单已与脚本 `PATCHED_MARKERS`
|
|
14
|
+
7 项逐字同步。
|
|
15
|
+
3. **`--target` 污染共享 pristine 备份**(运维隐患):脚本对任意 `--target` 文件也会
|
|
16
|
+
刷新仓库内的 `client.js.orig`。现在备份簿记仅在默认 profile 路径下执行,
|
|
17
|
+
`--target` 时明确跳过。
|
|
18
|
+
|
|
19
|
+
## [0.0.19] - 2026-09-07
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- **0.0.18 的 occupancy 门控把列永久收起了(装着插件也不显示 explorer 列)**。
|
|
24
|
+
根因是时序:布局 store 的 actions 要到 root entry **首次渲染组装**时才经
|
|
25
|
+
`inject` hook 交给 `LayoutController`(`attachPanels`),而 0.0.18 把初始
|
|
26
|
+
occupancy 同步放在了 ui-layout 的 apply 阶段——那时 `#panels` 还是 undefined,
|
|
27
|
+
同步被空实现吞掉;workbench 的注册又恰好发生在同一调用栈内(声明提交触发),
|
|
28
|
+
`slots/changed` 事件在监听器安装之前就已发完,之后再无事件 → `explorerOccupied`
|
|
29
|
+
恒为 false → 列永不出现。修复:occupancy 同步**同时**放进 root 注册的 inject
|
|
30
|
+
hook(actions 刚 bind、首帧渲染前,此时插槽查询已能拿到已注册条目),
|
|
31
|
+
`slots/changed` 监听继续负责运行时装卸;补丁脚本对应新增 `npm-delta2` /
|
|
32
|
+
`desktop-ci-delta2` 变体与 marker。
|
|
33
|
+
|
|
34
|
+
## [0.0.18] - 2026-09-07
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- **卸载插件后残留一条空白侧边栏([issue #2](https://github.com/Pasumao/dsh-plugin-workbench/issues/2))**。
|
|
39
|
+
根因:布局补丁给 `dsh-client-ui-layout` 注入的第四列(explorer)是无条件渲染的——
|
|
40
|
+
网格轨道恒为 `panels.explorer`(默认 260px,带侧栏底色与右边框),列内容来自本插件注册的
|
|
41
|
+
`explorer` 插槽;卸载本插件后插槽清空,但补丁仍留在布局 bundle 里(且插件的
|
|
42
|
+
`ensureLayoutPatch` 自愈机制还会在下次启动把补丁打回去),于是永远残留一条空列,
|
|
43
|
+
刷新/重启都无法消除。修复:布局 store 新增 `explorerOccupied` 标志,`ui-layout` 的
|
|
44
|
+
apply 现在监听 `slots/changed` 事件,实时统计 `explorer` / `explorer.preview` 插槽的
|
|
45
|
+
注册条目数——没有任何插件贡献时列宽归 0 自动收起,装回插件即刻恢复。
|
|
46
|
+
补丁脚本新增 **delta 变体**(`npm-delta` / `desktop-ci-delta`):已带旧版补丁的 bundle
|
|
47
|
+
无需还原即可原地升级到带 occupancy 门槛的新补丁;全新 bundle 走原有完整变体。
|
|
48
|
+
`src/index.ts` 的自愈 marker 列表同步追加 `explorerOccupied`。
|
|
49
|
+
同时新增 `patch-layout.mjs --restore`(卸载恢复命令):用首次打补丁时备份的
|
|
50
|
+
pristine 副本把 `dsh-client-ui-layout` 还原为官方原始 bundle;备份策略改为
|
|
51
|
+
「dsh 升级后首次重打时自动刷新 pristine」,并带两道防呆(目标是更新的原生 bundle、
|
|
52
|
+
或备份属于更旧 dsh 版本时拒绝回滚,`--force` 覆盖)。
|
|
53
|
+
|
|
54
|
+
## [0.0.17] - 2026-09-05
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
- **与 maid-atelier 皮肤同装时,页面顶部/底部装饰横条从画面一半才开始显示**。
|
|
59
|
+
根因:本插件 CSS 末尾一段旧「skin chrome fix」规则(`translate: calc(var(--maid-sidebar-width) +
|
|
60
|
+
var(--dsh-explorer-width) + var(--dsh-preview-width))`)写于皮肤装饰条还是
|
|
61
|
+
`position: fixed` 钉满整窗的时期,用来把它推过侧栏和文件列;maid-atelier 升级到
|
|
62
|
+
上游 78722ef 后装饰条改为挂在会话列内部的绝对定位元素(本就从列左缘开始),
|
|
63
|
+
这条规则反而造成双重偏移(列左缘 540px + translate 540px = 从 x≈1080 起画,
|
|
64
|
+
右半截伸出屏幕外)。已整段删除——装饰条定位由皮肤自持,插件不再外部平移。
|
|
65
|
+
|
|
66
|
+
### Changed
|
|
67
|
+
|
|
68
|
+
- README:首屏新增横幅图(`docs/banner.svg`),徽章顺序调整并补充 npm downloads。
|
|
69
|
+
|
|
3
70
|
## [0.0.16] - 2026-09-04
|
|
4
71
|
|
|
5
72
|
### Fixed
|
|
@@ -10,7 +77,6 @@
|
|
|
10
77
|
`.5px solid var(--dsw-alias-border-l3)`,锚点与注入规则同步更新;⑵
|
|
11
78
|
`appframe.explorerColumn`:DetailsColumn 的 children 在新版被 `SessionProvider`
|
|
12
79
|
包裹,锚点按新结构更新。其余 22 个锚点与 `computeColumns` 函数体逐字节未变。
|
|
13
|
-
# Changelog
|
|
14
80
|
|
|
15
81
|
## [0.0.15] - 2026-08-29
|
|
16
82
|
|
package/README.en.md
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/banner.svg" alt="dsh-plugin-workbench banner" width="100%">
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
5
|
# dsh-plugin-workbench
|
|
4
6
|
|
|
5
7
|

|
|
6
|
-

|
|
7
9
|

|
|
10
|
+

|
|
8
11
|

|
|
9
12
|

|
|
10
13
|
|
|
14
|
+
[中文](./README.md) | **English**
|
|
15
|
+
|
|
11
16
|
**A VS Code-style workbench that edits files directly** — not a read-only preview: file tree + editable code preview
|
|
12
17
|
(syntax highlighting, tabs, line-number gutter) + right-click file operations (new / rename / delete / copy / cut /
|
|
13
18
|
paste / open in system / reveal in file explorer) + inline image preview, with state saved independently per workspace.
|
|
@@ -136,9 +141,19 @@ pnpm run typecheck
|
|
|
136
141
|
|
|
137
142
|
```powershell
|
|
138
143
|
dsh plugin --profile web remove dsh-plugin-workbench
|
|
139
|
-
#
|
|
144
|
+
# optional but recommended: restore the layout bundle to the stock dsh file
|
|
145
|
+
node node_modules/dsh-plugin-workbench/scripts/patch-layout.mjs --restore
|
|
146
|
+
# restart dsh web
|
|
140
147
|
```
|
|
141
148
|
|
|
149
|
+
> Skipping `--restore` is fine too: since 0.0.18 the layout patch is adaptive —
|
|
150
|
+
> the explorer column auto-collapses (width 0) whenever no plugin contributes to
|
|
151
|
+
> the `explorer` / `explorer.preview` slots, so an uninstall leaves no empty
|
|
152
|
+
> column behind. `--restore` simply returns the bundle to its pristine,
|
|
153
|
+
> unpatched state. The script has two safety guards: it refuses to restore when
|
|
154
|
+
> the target already looks like a newer pristine bundle (just-upgraded dsh) or
|
|
155
|
+
> when the backup belongs to an older dsh version (`--force` overrides).
|
|
156
|
+
|
|
142
157
|
## Notes
|
|
143
158
|
|
|
144
159
|
- The `/dsh-plugin-files` RPC channel is loopback-only; write operations are executed explicitly under
|
|
@@ -180,6 +195,7 @@ alongside it:
|
|
|
180
195
|
| [dsh-plugin-image-tools](https://www.npmjs.com/package/dsh-plugin-image-tools) | [GitHub repo](https://github.com/Pasumao/dsh-plugin-image-tools) | Image choice cards + inline images in replies + image intake for text-only models |
|
|
181
196
|
| [dsh-plugin-table-zoom](https://www.npmjs.com/package/dsh-plugin-table-zoom) | [GitHub repo](https://github.com/Pasumao/dsh-plugin-table-zoom) | Floating window for long chat tables + one-click Markdown copy |
|
|
182
197
|
| [dsh-plugin-windows-guard](https://www.npmjs.com/package/dsh-plugin-windows-guard) | [GitHub repo](https://github.com/Pasumao/dsh-plugin-windows-guard) | Windows environment safeguards: guideline skills + mojibake detection / dangerous-write interception / encoding diagnosis & repair |
|
|
198
|
+
| [dsh-plugin-context-trim](https://www.npmjs.com/package/dsh-plugin-context-trim) | [GitHub repo](https://github.com/Pasumao/dsh-plugin-context-trim) | Per-session injection gate: trim skills / tools / prompt sections per session |
|
|
183
199
|
|
|
184
200
|
> For the remaining plugins in the series, see [Pasumao · dsh plugins](https://github.com/Pasumao); if you find them useful, a ⭐ on GitHub is always welcome.
|
|
185
201
|
|
package/README.md
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/banner.svg" alt="dsh-plugin-workbench banner" width="100%">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
1
5
|
# dsh-plugin-workbench
|
|
2
6
|
|
|
3
7
|

|
|
4
|
-

|
|
5
9
|

|
|
10
|
+

|
|
6
11
|

|
|
7
12
|

|
|
8
13
|
|
|
@@ -125,9 +130,17 @@ pnpm run typecheck
|
|
|
125
130
|
|
|
126
131
|
```powershell
|
|
127
132
|
dsh plugin --profile web remove dsh-plugin-workbench
|
|
128
|
-
#
|
|
133
|
+
# 可选:把布局 bundle 还原为官方原始版本(推荐,卸载后干净如初)
|
|
134
|
+
node node_modules/dsh-plugin-workbench/scripts/patch-layout.mjs --restore
|
|
135
|
+
# 重启 dsh web
|
|
129
136
|
```
|
|
130
137
|
|
|
138
|
+
> 不跑 `--restore` 也没关系:0.0.18 起布局补丁会自适应——explorer 列在没有插件
|
|
139
|
+
> 往 `explorer` / `explorer.preview` 插槽注册内容时自动收起(宽度归 0),
|
|
140
|
+
> 卸载后不会残留空列。`--restore` 只是把它还原成完全未打补丁的原始 bundle。
|
|
141
|
+
> 脚本带两道防呆:目标看起来已是未打补丁的新版 bundle(dsh 刚升级过)、或备份
|
|
142
|
+
> 属于更旧的 dsh 版本时,会拒绝回滚并提示(`--force` 可强行恢复)。
|
|
143
|
+
|
|
131
144
|
## 说明
|
|
132
145
|
|
|
133
146
|
- `/dsh-plugin-files` RPC 通道仅限 loopback;写操作显式以 `danger-full-access` 执行;
|
|
@@ -166,6 +179,7 @@ dsh plugin --profile web remove dsh-plugin-workbench
|
|
|
166
179
|
| [dsh-plugin-table-zoom](https://www.npmjs.com/package/dsh-plugin-table-zoom) | [GitHub 仓库](https://github.com/Pasumao/dsh-plugin-table-zoom) | 聊天长表格浮窗查看 + 一键复制 Markdown |
|
|
167
180
|
| [dsh-plugin-windows-guard](https://www.npmjs.com/package/dsh-plugin-windows-guard) | [GitHub 仓库](https://github.com/Pasumao/dsh-plugin-windows-guard) | Windows 环境防坑:守则技能 + 乱码检测 / 危险写拦截 / 编码诊断修复 |
|
|
168
181
|
|
|
182
|
+
| [dsh-plugin-context-trim](https://www.npmjs.com/package/dsh-plugin-context-trim) | [GitHub 仓库](https://github.com/Pasumao/dsh-plugin-context-trim) | 会话注入门控:skill / tool / 提示词段落按会话裁剪 |
|
|
169
183
|
> 本系列其余插件见 [Pasumao · dsh 插件](https://github.com/Pasumao);觉得好用欢迎到 GitHub 点 ⭐。
|
|
170
184
|
|
|
171
185
|
## AI 生成声明
|
package/docs/banner.svg
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="260" viewBox="0 0 1200 260" role="img" aria-label="dsh-plugin-workbench banner">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
|
4
|
+
<stop offset="0" stop-color="#0a1830"/>
|
|
5
|
+
<stop offset="1" stop-color="#102a4c"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<radialGradient id="glow" cx="0.85" cy="0.1" r="0.9">
|
|
8
|
+
<stop offset="0" stop-color="#4FC3F7" stop-opacity="0.22"/>
|
|
9
|
+
<stop offset="1" stop-color="#4FC3F7" stop-opacity="0"/>
|
|
10
|
+
</radialGradient>
|
|
11
|
+
<linearGradient id="whale" x1="0" y1="0" x2="0" y2="1">
|
|
12
|
+
<stop offset="0" stop-color="#ffffff"/>
|
|
13
|
+
<stop offset="1" stop-color="#cfe3ff"/>
|
|
14
|
+
</linearGradient>
|
|
15
|
+
</defs>
|
|
16
|
+
<rect width="1200" height="260" rx="18" fill="url(#bg)"/>
|
|
17
|
+
<rect width="1200" height="260" rx="18" fill="url(#glow)"/>
|
|
18
|
+
<rect x="0" y="0" width="1200" height="6" rx="3" fill="#4FC3F7" opacity="0.85"/>
|
|
19
|
+
<g transform="translate(64,80) scale(2.0)">
|
|
20
|
+
<path d="M48.8354 10.0479C48.3232 9.79199 48.1025 10.2798 47.8032 10.5278C47.7007 10.6079 47.6143 10.7119 47.5273 10.8076C46.7793 11.624 45.9048 12.1597 44.7622 12.0957C43.0923 12 41.666 12.5356 40.4058 13.8398C40.1377 12.2319 39.2476 11.272 37.8926 10.6558C37.1836 10.3359 36.4668 10.0156 35.9702 9.31982C35.6235 8.82373 35.5293 8.27197 35.356 7.72754C35.2456 7.3999 35.1353 7.06396 34.7651 7.00781C34.3633 6.94385 34.2056 7.2876 34.0479 7.57568C33.418 8.75195 33.1733 10.0479 33.1973 11.3599C33.2524 14.312 34.4736 16.6641 36.8999 18.3359C37.1758 18.5278 37.2466 18.7197 37.1597 19C36.9946 19.5757 36.7974 20.1357 36.624 20.7119C36.5137 21.0801 36.3486 21.1597 35.9624 21C34.6309 20.4321 33.481 19.5918 32.4644 18.5757C30.7393 16.8721 29.1792 14.9917 27.2334 13.52C26.7764 13.1758 26.3193 12.856 25.8467 12.5518C23.8618 10.584 26.1069 8.96777 26.627 8.77588C27.1704 8.57568 26.8159 7.8877 25.0591 7.896C23.3022 7.90381 21.6953 8.50391 19.647 9.30371C19.3477 9.42383 19.0322 9.51172 18.7095 9.58398C16.8501 9.22363 14.9199 9.14355 12.9033 9.37598C9.10596 9.80762 6.07275 11.6396 3.84326 14.7681C1.16455 18.5278 0.53418 22.7998 1.30664 27.2559C2.11768 31.9521 4.46582 35.8398 8.07373 38.8799C11.8159 42.0322 16.1255 43.5762 21.041 43.2803C24.0269 43.104 27.3516 42.6963 31.1016 39.4561C32.0469 39.936 33.0396 40.1279 34.686 40.272C35.9546 40.3921 37.1758 40.208 38.1211 40.0078C39.6021 39.688 39.4995 38.2881 38.9639 38.0322C34.623 35.9678 35.5762 36.8081 34.71 36.1279C36.9155 33.4639 40.2402 30.6958 41.54 21.728C41.6426 21.0161 41.5557 20.5679 41.54 19.9917C41.5322 19.6396 41.6108 19.5039 42.0049 19.4639C43.0923 19.3359 44.1479 19.0317 45.1167 18.4878C47.9292 16.9199 49.064 14.3438 49.3315 11.2559C49.3711 10.7837 49.3237 10.2959 48.8354 10.0479ZM24.3262 37.8398C20.1196 34.4639 18.0791 33.3521 17.2358 33.3999C16.4482 33.4482 16.5898 34.3682 16.7632 34.9678C16.9443 35.5601 17.1812 35.9683 17.5117 36.4878C17.7402 36.832 17.8979 37.3442 17.2832 37.728C15.9282 38.584 13.5728 37.4399 13.4624 37.3838C10.7207 35.7358 8.42822 33.5601 6.81348 30.584C5.25342 27.7197 4.34766 24.6479 4.19775 21.3677C4.1582 20.5757 4.38672 20.2959 5.15869 20.1519C6.17529 19.96 7.22314 19.9199 8.23926 20.0718C12.5327 20.7119 16.1885 22.6719 19.2529 25.7759C21.002 27.5439 22.3252 29.6558 23.6885 31.7202C25.1377 33.9121 26.6978 36 28.6831 37.7119C29.3843 38.312 29.9434 38.7681 30.479 39.104C28.8643 39.2881 26.1699 39.3281 24.3262 37.8398ZM26.3433 24.6001C26.3433 24.248 26.6191 23.9678 26.9658 23.9678C27.0444 23.9678 27.1152 23.9839 27.1782 24.0078C27.2651 24.04 27.3438 24.0879 27.4067 24.1602C27.5171 24.272 27.5801 24.4321 27.5801 24.6001C27.5801 24.9521 27.3042 25.2319 26.9575 25.2319C26.6108 25.2319 26.3433 24.9521 26.3433 24.6001ZM32.6064 27.8799C32.2046 28.0479 31.8027 28.1919 31.4165 28.208C30.8179 28.2397 30.1641 27.9922 29.8096 27.688C29.2583 27.2158 28.8643 26.9521 28.6987 26.1279C28.6279 25.7759 28.6675 25.2319 28.7305 24.9199C28.8721 24.248 28.7144 23.8159 28.2495 23.4238C27.8716 23.104 27.3911 23.0161 26.8633 23.0161C26.666 23.0161 26.4849 22.9277 26.3511 22.856C26.1304 22.7441 25.9492 22.4639 26.1226 22.1201C26.1777 22.0078 26.4458 21.7358 26.5088 21.688C27.2256 21.272 28.0527 21.4077 28.8169 21.7197C29.5259 22.0161 30.0615 22.5601 30.834 23.3281C31.6216 24.2559 31.7632 24.5117 32.2124 25.208C32.5669 25.752 32.8901 26.312 33.1104 26.9521C33.2446 27.3521 33.0713 27.6802 32.6064 27.8799Z" fill="url(#whale)"/>
|
|
21
|
+
</g>
|
|
22
|
+
<text x="212" y="86" font-family="'Segoe UI','PingFang SC','Microsoft YaHei',sans-serif" font-size="17" font-weight="600" letter-spacing="5" fill="#4FC3F7">DEEPSEEK HARNESS · DSH PLUGIN</text>
|
|
23
|
+
<text x="212" y="152" font-family="ui-monospace,'Cascadia Code',Consolas,monospace" font-size="46" font-weight="700" fill="#f4f8ff">dsh-plugin-workbench</text>
|
|
24
|
+
<text x="212" y="204" font-family="'Segoe UI','PingFang SC','Microsoft YaHei',sans-serif" font-size="22" fill="#9fb3c8">VS Code 风格工作台 · 文件树 · 可编辑预览 · 右键文件操作</text>
|
|
25
|
+
</svg>
|
package/lib/client.js
CHANGED
|
@@ -39,7 +39,7 @@ window.__ModuleLoader__.load({
|
|
|
39
39
|
let react = require("react");
|
|
40
40
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
41
41
|
//#region \0dsh-css:src/client/files.module.css.mjs
|
|
42
|
-
const css$1 = "[data-fe-theme=light]{--fe-bg:#fff;--fe-sidebar-bg:#f3f3f3;--fe-fg:#1f1f1f;--fe-muted:#6e6e6e;--fe-faint:#9d9d9d;--fe-border:#e5e5e5;--fe-border-strong:#c8c8c8;--fe-accent:#005fb8;--fe-hover:#e8e8e8;--fe-selection:#add6ff;--fe-token-keyword:#00f;--fe-token-string:#a31515;--fe-token-comment:green;--fe-token-number:#098658;--fe-token-function:#795e26;--fe-token-type:#267f99;--fe-token-variable:#001080;--fe-token-tag:maroon;--fe-token-meta:#6e6e6e}[data-fe-theme=dark]{--fe-bg:#1e1e1e;--fe-sidebar-bg:#252526;--fe-fg:#d4d4d4;--fe-muted:#ccc;--fe-faint:#9d9d9d;--fe-border:#3c3c3c;--fe-border-strong:#454545;--fe-accent:#007acc;--fe-hover:#2a2d2e;--fe-selection:#264f78;--fe-token-keyword:#569cd6;--fe-token-string:#ce9178;--fe-token-comment:#6a9955;--fe-token-number:#b5cea8;--fe-token-function:#dcdcaa;--fe-token-type:#4ec9b0;--fe-token-variable:#9cdcfe;--fe-token-tag:#569cd6;--fe-token-meta:#9b9b9b}.Myjg4a_column{box-sizing:border-box;background:var(--fe-sidebar-bg);min-width:0;height:100%;color:var(--fe-fg);flex-direction:column;font-size:13px;display:flex;overflow:hidden}.Myjg4a_header{box-sizing:border-box;border-bottom:1px solid var(--fe-border);flex:none;align-items:center;gap:6px;height:34px;padding:0 8px;display:flex}.Myjg4a_headerTitle{text-overflow:ellipsis;white-space:nowrap;text-transform:uppercase;letter-spacing:.04em;min-width:0;color:var(--fe-muted);flex:1;font-size:11px;font-weight:600;overflow:hidden}.Myjg4a_headerActions{flex:none;align-items:center;gap:2px;display:flex}.Myjg4a_action{appearance:none;color:var(--fe-muted);cursor:pointer;background:0 0;border:none;border-radius:5px;justify-content:center;align-items:center;width:22px;height:22px;padding:0;font-size:13px;line-height:1;display:inline-flex}.Myjg4a_action:hover:not(:disabled){background:var(--fe-hover);color:var(--fe-fg)}.Myjg4a_action:disabled{opacity:.5;cursor:default}.Myjg4a_treeArea{flex:1;min-height:0;padding:4px;overflow-y:auto}.Myjg4a_treeArea:focus{outline:none}.Myjg4a_row{cursor:pointer;user-select:none;white-space:nowrap;height:22px;color:var(--fe-fg);border-radius:3px;align-items:center;gap:6px;font-size:13px;display:flex}.Myjg4a_row:hover{background:var(--fe-hover)}.Myjg4a_rowSelected{background:var(--fe-selection)}.Myjg4a_rowSelected .Myjg4a_name{color:var(--fe-fg)}.Myjg4a_rowCut{opacity:.45}.Myjg4a_rowDropTarget{box-shadow:inset 0 0 0 1.5px var(--fe-accent);background:var(--fe-selection)}.Myjg4a_clipboardBar{border-bottom:1px solid var(--fe-border);background:var(--fe-hover);color:var(--fe-fg);flex:none;align-items:center;gap:6px;padding:4px 8px;font-size:12px;display:flex}.Myjg4a_clipboardText{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.Myjg4a_clipboardHint{color:var(--fe-faint)}.Myjg4a_chevron{text-align:center;width:12px;color:var(--fe-muted);flex:none;font-size:10px;line-height:22px}.Myjg4a_icon{text-align:center;flex:none;width:16px;font-size:13px;line-height:22px}.Myjg4a_fileBadge{letter-spacing:-.3px;box-sizing:border-box;vertical-align:middle;user-select:none;border-radius:3px;justify-content:center;align-items:center;width:16px;height:15px;padding:0 1px;font-size:8px;font-weight:700;line-height:1;display:inline-flex}.Myjg4a_fileBadgeLong{letter-spacing:-.4px;font-size:6.5px}.Myjg4a_name{text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.Myjg4a_size{color:var(--fe-faint);flex:none;font-size:11px}.Myjg4a_actions{opacity:0;flex:none;align-items:center;gap:2px;transition:opacity .12s;display:flex}.Myjg4a_row:hover .Myjg4a_actions,.Myjg4a_row:focus-within .Myjg4a_actions{opacity:1}.Myjg4a_rowHint{color:var(--fe-faint);padding:2px 8px 2px 0;font-size:12px;line-height:20px}.Myjg4a_rowError{color:#f48771;padding:2px 8px 2px 0;font-size:12px;line-height:18px}.Myjg4a_contextMenu{z-index:10000;box-sizing:border-box;border:1px solid var(--fe-border-strong);user-select:none;border-radius:6px;min-width:180px;padding:4px;font-size:13px;position:fixed;box-shadow:0 6px 24px #00000047;background:var(--fe-bg)!important;color:var(--fe-fg)!important}.Myjg4a_contextMenuItem{cursor:pointer;white-space:nowrap;color:inherit;border-radius:4px;align-items:center;gap:8px;padding:5px 10px;display:flex}.Myjg4a_contextMenuItem:hover{background:var(--fe-selection)!important;color:var(--fe-fg)!important}.Myjg4a_contextMenuItemDanger{color:#f48771!important}.Myjg4a_contextMenuItemDisabled{opacity:.45;cursor:default;pointer-events:none}.Myjg4a_contextMenuDivider{background:var(--fe-border);height:1px;margin:4px 6px}.Myjg4a_preview{border-right:1px solid var(--fe-border);background:var(--fe-bg);flex-direction:column;flex:0 0 55%;min-width:240px;min-height:0;animation:.18s Myjg4a_fe-preview-in;display:flex;overflow:hidden}.Myjg4a_previewClosing{animation:.2s forwards Myjg4a_fe-preview-out}@keyframes Myjg4a_fe-preview-in{0%{opacity:0}to{opacity:1}}@keyframes Myjg4a_fe-preview-out{0%{opacity:1}to{opacity:0}}.Myjg4a_handle{cursor:col-resize;touch-action:none;z-index:2;background:0 0;flex:none;width:6px;margin-left:-4px;margin-right:-2px}.Myjg4a_handle:hover,.Myjg4a_handle:active{background:var(--fe-accent);opacity:.35}.Myjg4a_tabBar{border-bottom:1px solid var(--fe-border);background:var(--fe-sidebar-bg);flex:none;align-items:stretch;height:34px;display:flex}.Myjg4a_tabScroller{scrollbar-width:thin;flex:1;align-items:stretch;min-width:0;display:flex;overflow-x:auto}.Myjg4a_collapse,.Myjg4a_tabAction{appearance:none;color:var(--fe-muted);cursor:pointer;background:0 0;border:none;border-radius:4px;flex:none;justify-content:center;align-items:center;width:26px;height:26px;margin:auto 4px;padding:0;font-size:14px;line-height:1;display:inline-flex}.Myjg4a_collapse:hover,.Myjg4a_tabAction:hover{background:var(--fe-hover);color:var(--fe-fg)}.Myjg4a_tabActionActive{background:var(--fe-hover);color:var(--fe-accent)}.Myjg4a_tab{max-width:180px;color:var(--fe-muted);border-right:1px solid var(--fe-border);cursor:pointer;user-select:none;white-space:nowrap;flex:none;align-items:center;gap:6px;padding:0 8px 0 12px;font-size:13px;display:flex}.Myjg4a_tab:hover{background:var(--fe-hover)}.Myjg4a_tabActive{background:var(--fe-bg);color:var(--fe-fg);box-shadow:inset 0 -1px 0 var(--fe-accent)}.Myjg4a_tabName{text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.Myjg4a_tabIcon{flex:none;justify-content:center;align-items:center;width:16px;font-size:13px;line-height:1;display:inline-flex}.Myjg4a_tabClose{appearance:none;color:var(--fe-faint);cursor:pointer;background:0 0;border:none;border-radius:3px;justify-content:center;align-items:center;width:16px;height:16px;padding:0;font-size:11px;display:inline-flex}.Myjg4a_tabClose:hover{background:var(--fe-hover);color:var(--fe-fg)}.Myjg4a_tabDot{background:var(--fe-fg);opacity:.85;border-radius:50%;flex:none;width:8px;height:8px}.Myjg4a_tabDiskBadge{appearance:none;color:var(--fe-accent);cursor:pointer;background:0 0;border:none;border-radius:3px;flex:none;justify-content:center;align-items:center;width:16px;height:16px;padding:0;font-size:12px;line-height:1;display:inline-flex}.Myjg4a_tabDiskBadge:hover{background:var(--fe-hover);color:var(--fe-fg)}.Myjg4a_previewBody{flex:1;min-height:0;overflow:auto}.Myjg4a_editor{--fe-gutter:44px;contain:layout paint;height:100%;min-height:0;position:relative}.Myjg4a_gutter{width:var(--fe-gutter);box-sizing:border-box;border-right:1px solid var(--fe-border);background:var(--fe-sidebar-bg);color:var(--fe-faint);user-select:none;pointer-events:none;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.5;position:absolute;top:0;bottom:0;left:0;overflow:hidden}.Myjg4a_gutterNumbers{white-space:pre;text-align:right;padding:12px 8px}.Myjg4a_editorPlain .Myjg4a_editorTextarea{color:var(--fe-fg)}.Myjg4a_editorHint{left:calc(var(--fe-gutter) + 8px);background:var(--fe-hover);color:var(--fe-muted);pointer-events:none;border-radius:4px;padding:4px 10px;font-size:11px;position:absolute;bottom:8px}.Myjg4a_editorHighlight{top:0;bottom:0;left:var(--fe-gutter);pointer-events:none;white-space:pre;tab-size:2;color:var(--fe-fg);background:0 0;margin:0;padding:12px 12px calc(12px + 1.5em);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.5;position:absolute;right:0;overflow:auto}.Myjg4a_editorHighlight code{font-family:inherit;font-size:inherit;line-height:inherit;white-space:inherit}.Myjg4a_editorTextarea{top:0;bottom:0;left:var(--fe-gutter);box-sizing:border-box;resize:none;color:#0000;caret-color:var(--fe-fg);white-space:pre;tab-size:2;background:0 0;border:none;outline:none;margin:0;padding:12px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.5;position:absolute;right:0;overflow:auto}.Myjg4a_editor[data-wrap=on] .Myjg4a_editorHighlight,.Myjg4a_editor[data-wrap=on] .Myjg4a_editorTextarea{white-space:pre-wrap;overflow-wrap:anywhere}.Myjg4a_editor[data-wrap=on] .Myjg4a_editorTextarea{overflow-x:hidden}.Myjg4a_saveError{color:#1e1e1e;background:#f48771;border-radius:4px;padding:4px 10px;font-size:12px;position:absolute;bottom:8px;right:8px}.Myjg4a_previewHint{color:var(--fe-faint);padding:12px;font-size:12px;line-height:18px}.Myjg4a_imageView{box-sizing:border-box;background:var(--fe-bg);flex-direction:column;justify-content:center;align-items:center;gap:8px;height:100%;min-height:0;padding:12px;display:flex;overflow:auto}.Myjg4a_image{object-fit:contain;max-width:100%;max-height:100%;box-shadow:0 0 0 1px var(--fe-border);border-radius:4px}.Myjg4a_previewMeta{color:var(--fe-faint);font-size:11px}.Myjg4a_mdPreview{box-sizing:border-box;height:100%;color:var(--fe-fg);word-wrap:break-word;padding:16px 20px 48px;font-size:14px;line-height:1.7;overflow:auto}.Myjg4a_mdPreview>:first-child{margin-top:0}.Myjg4a_mdPreview>:last-child{margin-bottom:0}.Myjg4a_mdPreview h1,.Myjg4a_mdPreview h2,.Myjg4a_mdPreview h3,.Myjg4a_mdPreview h4,.Myjg4a_mdPreview h5,.Myjg4a_mdPreview h6{color:var(--fe-fg);margin:1.2em 0 .5em;font-weight:600;line-height:1.3}.Myjg4a_mdPreview h1{border-bottom:1px solid var(--fe-border);padding-bottom:.3em;font-size:1.7em}.Myjg4a_mdPreview h2{border-bottom:1px solid var(--fe-border);padding-bottom:.3em;font-size:1.4em}.Myjg4a_mdPreview h3{font-size:1.2em}.Myjg4a_mdPreview h4,.Myjg4a_mdPreview h5,.Myjg4a_mdPreview h6{font-size:1.05em}.Myjg4a_mdPreview p{margin:.6em 0}.Myjg4a_mdPreview ul,.Myjg4a_mdPreview ol{margin:.6em 0;padding-left:1.6em}.Myjg4a_mdPreview li,.Myjg4a_mdPreview li>ul,.Myjg4a_mdPreview li>ol{margin:.2em 0}.Myjg4a_mdPreview a{color:var(--fe-accent);text-decoration:none}.Myjg4a_mdPreview a:hover{text-decoration:underline}.Myjg4a_mdPreview blockquote{border-left:3px solid var(--fe-border-strong);color:var(--fe-muted);background:var(--fe-sidebar-bg);margin:.8em 0;padding:.3em 1em}.Myjg4a_mdPreview code{background:var(--fe-hover);border-radius:3px;padding:.15em .4em;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.92em}.Myjg4a_mdPreview pre{background:var(--fe-sidebar-bg);border:1px solid var(--fe-border);border-radius:4px;margin:.8em 0;padding:12px;line-height:1.5;overflow:auto}.Myjg4a_mdPreview pre code{background:0 0;padding:0;font-size:13px}.Myjg4a_mdPreview table{border-collapse:collapse;max-width:100%;margin:.8em 0;display:block;overflow-x:auto}.Myjg4a_mdPreview th,.Myjg4a_mdPreview td{border:1px solid var(--fe-border-strong);padding:6px 12px}.Myjg4a_mdPreview th{background:var(--fe-sidebar-bg);font-weight:600}.Myjg4a_mdPreview img{border-radius:4px;max-width:100%}.Myjg4a_mdPreview hr{border:none;border-top:1px solid var(--fe-border-strong);margin:1.5em 0}.Myjg4a_mdPreview .hljs-keyword,.Myjg4a_mdPreview .hljs-selector-tag,.Myjg4a_mdPreview .hljs-literal{color:var(--fe-token-keyword)}.Myjg4a_mdPreview .hljs-string,.Myjg4a_mdPreview .hljs-regexp,.Myjg4a_mdPreview .hljs-addition{color:var(--fe-token-string)}.Myjg4a_mdPreview .hljs-comment,.Myjg4a_mdPreview .hljs-quote{color:var(--fe-token-comment);font-style:italic}.Myjg4a_mdPreview .hljs-number,.Myjg4a_mdPreview .hljs-symbol,.Myjg4a_mdPreview .hljs-bullet{color:var(--fe-token-number)}.Myjg4a_mdPreview .hljs-title,.Myjg4a_mdPreview .hljs-section,.Myjg4a_mdPreview .hljs-title.function_{color:var(--fe-token-function)}.Myjg4a_mdPreview .hljs-type,.Myjg4a_mdPreview .hljs-built_in,.Myjg4a_mdPreview .hljs-class .hljs-title{color:var(--fe-token-type)}.Myjg4a_mdPreview .hljs-attr,.Myjg4a_mdPreview .hljs-attribute,.Myjg4a_mdPreview .hljs-variable,.Myjg4a_mdPreview .hljs-template-variable,.Myjg4a_mdPreview .hljs-params{color:var(--fe-token-variable)}.Myjg4a_mdPreview .hljs-tag,.Myjg4a_mdPreview .hljs-name{color:var(--fe-token-tag)}.Myjg4a_mdPreview .hljs-meta{color:var(--fe-token-meta)}.Myjg4a_mdPreview .hljs-emphasis{font-style:italic}.Myjg4a_mdPreview .hljs-strong{font-weight:600}.Myjg4a_placeholder{text-align:center;color:var(--fe-faint);flex:1;justify-content:center;align-items:center;padding:16px;font-size:12px;line-height:18px;display:flex}.Myjg4a_editorHighlight .hljs-keyword,.Myjg4a_editorHighlight .hljs-selector-tag,.Myjg4a_editorHighlight .hljs-literal{color:var(--fe-token-keyword)}.Myjg4a_editorHighlight .hljs-string,.Myjg4a_editorHighlight .hljs-regexp,.Myjg4a_editorHighlight .hljs-addition{color:var(--fe-token-string)}.Myjg4a_editorHighlight .hljs-comment,.Myjg4a_editorHighlight .hljs-quote{color:var(--fe-token-comment);font-style:italic}.Myjg4a_editorHighlight .hljs-number,.Myjg4a_editorHighlight .hljs-symbol,.Myjg4a_editorHighlight .hljs-bullet{color:var(--fe-token-number)}.Myjg4a_editorHighlight .hljs-title,.Myjg4a_editorHighlight .hljs-section,.Myjg4a_editorHighlight .hljs-title.function_{color:var(--fe-token-function)}.Myjg4a_editorHighlight .hljs-type,.Myjg4a_editorHighlight .hljs-built_in,.Myjg4a_editorHighlight .hljs-class .hljs-title{color:var(--fe-token-type)}.Myjg4a_editorHighlight .hljs-attr,.Myjg4a_editorHighlight .hljs-attribute,.Myjg4a_editorHighlight .hljs-variable,.Myjg4a_editorHighlight .hljs-template-variable,.Myjg4a_editorHighlight .hljs-params{color:var(--fe-token-variable)}.Myjg4a_editorHighlight .hljs-tag,.Myjg4a_editorHighlight .hljs-name{color:var(--fe-token-tag)}.Myjg4a_editorHighlight .hljs-meta{color:var(--fe-token-meta)}.Myjg4a_editorHighlight .hljs-emphasis{font-style:italic}.Myjg4a_editorHighlight .hljs-strong{color:var(--fe-accent);font-weight:inherit}body[data-dsh-maid-atelier] [data-skin-chrome=top-trim],body[data-dsh-maid-atelier] [data-skin-chrome=bottom-trim]{translate:calc(var(--maid-sidebar-width,0px) + var(--dsh-explorer-width,0px) + var(--dsh-preview-width,0px)) 0!important}[class*=explorerCol]{border-right:1px solid var(--fe-border)!important}";
|
|
42
|
+
const css$1 = "[data-fe-theme=light]{--fe-bg:#fff;--fe-sidebar-bg:#f3f3f3;--fe-fg:#1f1f1f;--fe-muted:#6e6e6e;--fe-faint:#9d9d9d;--fe-border:#e5e5e5;--fe-border-strong:#c8c8c8;--fe-accent:#005fb8;--fe-hover:#e8e8e8;--fe-selection:#add6ff;--fe-token-keyword:#00f;--fe-token-string:#a31515;--fe-token-comment:green;--fe-token-number:#098658;--fe-token-function:#795e26;--fe-token-type:#267f99;--fe-token-variable:#001080;--fe-token-tag:maroon;--fe-token-meta:#6e6e6e}[data-fe-theme=dark]{--fe-bg:#1e1e1e;--fe-sidebar-bg:#252526;--fe-fg:#d4d4d4;--fe-muted:#ccc;--fe-faint:#9d9d9d;--fe-border:#3c3c3c;--fe-border-strong:#454545;--fe-accent:#007acc;--fe-hover:#2a2d2e;--fe-selection:#264f78;--fe-token-keyword:#569cd6;--fe-token-string:#ce9178;--fe-token-comment:#6a9955;--fe-token-number:#b5cea8;--fe-token-function:#dcdcaa;--fe-token-type:#4ec9b0;--fe-token-variable:#9cdcfe;--fe-token-tag:#569cd6;--fe-token-meta:#9b9b9b}.Myjg4a_column{box-sizing:border-box;background:var(--fe-sidebar-bg);min-width:0;height:100%;color:var(--fe-fg);flex-direction:column;font-size:13px;display:flex;overflow:hidden}.Myjg4a_header{box-sizing:border-box;border-bottom:1px solid var(--fe-border);flex:none;align-items:center;gap:6px;height:34px;padding:0 8px;display:flex}.Myjg4a_headerTitle{text-overflow:ellipsis;white-space:nowrap;text-transform:uppercase;letter-spacing:.04em;min-width:0;color:var(--fe-muted);flex:1;font-size:11px;font-weight:600;overflow:hidden}.Myjg4a_headerActions{flex:none;align-items:center;gap:2px;display:flex}.Myjg4a_action{appearance:none;color:var(--fe-muted);cursor:pointer;background:0 0;border:none;border-radius:5px;justify-content:center;align-items:center;width:22px;height:22px;padding:0;font-size:13px;line-height:1;display:inline-flex}.Myjg4a_action:hover:not(:disabled){background:var(--fe-hover);color:var(--fe-fg)}.Myjg4a_action:disabled{opacity:.5;cursor:default}.Myjg4a_treeArea{flex:1;min-height:0;padding:4px;overflow-y:auto}.Myjg4a_treeArea:focus{outline:none}.Myjg4a_row{cursor:pointer;user-select:none;white-space:nowrap;height:22px;color:var(--fe-fg);border-radius:3px;align-items:center;gap:6px;font-size:13px;display:flex}.Myjg4a_row:hover{background:var(--fe-hover)}.Myjg4a_rowSelected{background:var(--fe-selection)}.Myjg4a_rowSelected .Myjg4a_name{color:var(--fe-fg)}.Myjg4a_rowCut{opacity:.45}.Myjg4a_rowDropTarget{box-shadow:inset 0 0 0 1.5px var(--fe-accent);background:var(--fe-selection)}.Myjg4a_clipboardBar{border-bottom:1px solid var(--fe-border);background:var(--fe-hover);color:var(--fe-fg);flex:none;align-items:center;gap:6px;padding:4px 8px;font-size:12px;display:flex}.Myjg4a_clipboardText{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.Myjg4a_clipboardHint{color:var(--fe-faint)}.Myjg4a_chevron{text-align:center;width:12px;color:var(--fe-muted);flex:none;font-size:10px;line-height:22px}.Myjg4a_icon{text-align:center;flex:none;width:16px;font-size:13px;line-height:22px}.Myjg4a_fileBadge{letter-spacing:-.3px;box-sizing:border-box;vertical-align:middle;user-select:none;border-radius:3px;justify-content:center;align-items:center;width:16px;height:15px;padding:0 1px;font-size:8px;font-weight:700;line-height:1;display:inline-flex}.Myjg4a_fileBadgeLong{letter-spacing:-.4px;font-size:6.5px}.Myjg4a_name{text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.Myjg4a_size{color:var(--fe-faint);flex:none;font-size:11px}.Myjg4a_actions{opacity:0;flex:none;align-items:center;gap:2px;transition:opacity .12s;display:flex}.Myjg4a_row:hover .Myjg4a_actions,.Myjg4a_row:focus-within .Myjg4a_actions{opacity:1}.Myjg4a_rowHint{color:var(--fe-faint);padding:2px 8px 2px 0;font-size:12px;line-height:20px}.Myjg4a_rowError{color:#f48771;padding:2px 8px 2px 0;font-size:12px;line-height:18px}.Myjg4a_contextMenu{z-index:10000;box-sizing:border-box;border:1px solid var(--fe-border-strong);user-select:none;border-radius:6px;min-width:180px;padding:4px;font-size:13px;position:fixed;box-shadow:0 6px 24px #00000047;background:var(--fe-bg)!important;color:var(--fe-fg)!important}.Myjg4a_contextMenuItem{cursor:pointer;white-space:nowrap;color:inherit;border-radius:4px;align-items:center;gap:8px;padding:5px 10px;display:flex}.Myjg4a_contextMenuItem:hover{background:var(--fe-selection)!important;color:var(--fe-fg)!important}.Myjg4a_contextMenuItemDanger{color:#f48771!important}.Myjg4a_contextMenuItemDisabled{opacity:.45;cursor:default;pointer-events:none}.Myjg4a_contextMenuDivider{background:var(--fe-border);height:1px;margin:4px 6px}.Myjg4a_preview{border-right:1px solid var(--fe-border);background:var(--fe-bg);flex-direction:column;flex:0 0 55%;min-width:240px;min-height:0;animation:.18s Myjg4a_fe-preview-in;display:flex;overflow:hidden}.Myjg4a_previewClosing{animation:.2s forwards Myjg4a_fe-preview-out}@keyframes Myjg4a_fe-preview-in{0%{opacity:0}to{opacity:1}}@keyframes Myjg4a_fe-preview-out{0%{opacity:1}to{opacity:0}}.Myjg4a_handle{cursor:col-resize;touch-action:none;z-index:2;background:0 0;flex:none;width:6px;margin-left:-4px;margin-right:-2px}.Myjg4a_handle:hover,.Myjg4a_handle:active{background:var(--fe-accent);opacity:.35}.Myjg4a_tabBar{border-bottom:1px solid var(--fe-border);background:var(--fe-sidebar-bg);flex:none;align-items:stretch;height:34px;display:flex}.Myjg4a_tabScroller{scrollbar-width:thin;flex:1;align-items:stretch;min-width:0;display:flex;overflow-x:auto}.Myjg4a_collapse,.Myjg4a_tabAction{appearance:none;color:var(--fe-muted);cursor:pointer;background:0 0;border:none;border-radius:4px;flex:none;justify-content:center;align-items:center;width:26px;height:26px;margin:auto 4px;padding:0;font-size:14px;line-height:1;display:inline-flex}.Myjg4a_collapse:hover,.Myjg4a_tabAction:hover{background:var(--fe-hover);color:var(--fe-fg)}.Myjg4a_tabActionActive{background:var(--fe-hover);color:var(--fe-accent)}.Myjg4a_tab{max-width:180px;color:var(--fe-muted);border-right:1px solid var(--fe-border);cursor:pointer;user-select:none;white-space:nowrap;flex:none;align-items:center;gap:6px;padding:0 8px 0 12px;font-size:13px;display:flex}.Myjg4a_tab:hover{background:var(--fe-hover)}.Myjg4a_tabActive{background:var(--fe-bg);color:var(--fe-fg);box-shadow:inset 0 -1px 0 var(--fe-accent)}.Myjg4a_tabName{text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.Myjg4a_tabIcon{flex:none;justify-content:center;align-items:center;width:16px;font-size:13px;line-height:1;display:inline-flex}.Myjg4a_tabClose{appearance:none;color:var(--fe-faint);cursor:pointer;background:0 0;border:none;border-radius:3px;justify-content:center;align-items:center;width:16px;height:16px;padding:0;font-size:11px;display:inline-flex}.Myjg4a_tabClose:hover{background:var(--fe-hover);color:var(--fe-fg)}.Myjg4a_tabDot{background:var(--fe-fg);opacity:.85;border-radius:50%;flex:none;width:8px;height:8px}.Myjg4a_tabDiskBadge{appearance:none;color:var(--fe-accent);cursor:pointer;background:0 0;border:none;border-radius:3px;flex:none;justify-content:center;align-items:center;width:16px;height:16px;padding:0;font-size:12px;line-height:1;display:inline-flex}.Myjg4a_tabDiskBadge:hover{background:var(--fe-hover);color:var(--fe-fg)}.Myjg4a_previewBody{flex:1;min-height:0;overflow:auto}.Myjg4a_editor{--fe-gutter:44px;contain:layout paint;height:100%;min-height:0;position:relative}.Myjg4a_gutter{width:var(--fe-gutter);box-sizing:border-box;border-right:1px solid var(--fe-border);background:var(--fe-sidebar-bg);color:var(--fe-faint);user-select:none;pointer-events:none;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.5;position:absolute;top:0;bottom:0;left:0;overflow:hidden}.Myjg4a_gutterNumbers{white-space:pre;text-align:right;padding:12px 8px}.Myjg4a_editorPlain .Myjg4a_editorTextarea{color:var(--fe-fg)}.Myjg4a_editorHint{left:calc(var(--fe-gutter) + 8px);background:var(--fe-hover);color:var(--fe-muted);pointer-events:none;border-radius:4px;padding:4px 10px;font-size:11px;position:absolute;bottom:8px}.Myjg4a_editorHighlight{top:0;bottom:0;left:var(--fe-gutter);pointer-events:none;white-space:pre;tab-size:2;color:var(--fe-fg);background:0 0;margin:0;padding:12px 12px calc(12px + 1.5em);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.5;position:absolute;right:0;overflow:auto}.Myjg4a_editorHighlight code{font-family:inherit;font-size:inherit;line-height:inherit;white-space:inherit}.Myjg4a_editorTextarea{top:0;bottom:0;left:var(--fe-gutter);box-sizing:border-box;resize:none;color:#0000;caret-color:var(--fe-fg);white-space:pre;tab-size:2;background:0 0;border:none;outline:none;margin:0;padding:12px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.5;position:absolute;right:0;overflow:auto}.Myjg4a_editor[data-wrap=on] .Myjg4a_editorHighlight,.Myjg4a_editor[data-wrap=on] .Myjg4a_editorTextarea{white-space:pre-wrap;overflow-wrap:anywhere}.Myjg4a_editor[data-wrap=on] .Myjg4a_editorTextarea{overflow-x:hidden}.Myjg4a_saveError{color:#1e1e1e;background:#f48771;border-radius:4px;padding:4px 10px;font-size:12px;position:absolute;bottom:8px;right:8px}.Myjg4a_previewHint{color:var(--fe-faint);padding:12px;font-size:12px;line-height:18px}.Myjg4a_imageView{box-sizing:border-box;background:var(--fe-bg);flex-direction:column;justify-content:center;align-items:center;gap:8px;height:100%;min-height:0;padding:12px;display:flex;overflow:auto}.Myjg4a_image{object-fit:contain;max-width:100%;max-height:100%;box-shadow:0 0 0 1px var(--fe-border);border-radius:4px}.Myjg4a_previewMeta{color:var(--fe-faint);font-size:11px}.Myjg4a_mdPreview{box-sizing:border-box;height:100%;color:var(--fe-fg);word-wrap:break-word;padding:16px 20px 48px;font-size:14px;line-height:1.7;overflow:auto}.Myjg4a_mdPreview>:first-child{margin-top:0}.Myjg4a_mdPreview>:last-child{margin-bottom:0}.Myjg4a_mdPreview h1,.Myjg4a_mdPreview h2,.Myjg4a_mdPreview h3,.Myjg4a_mdPreview h4,.Myjg4a_mdPreview h5,.Myjg4a_mdPreview h6{color:var(--fe-fg);margin:1.2em 0 .5em;font-weight:600;line-height:1.3}.Myjg4a_mdPreview h1{border-bottom:1px solid var(--fe-border);padding-bottom:.3em;font-size:1.7em}.Myjg4a_mdPreview h2{border-bottom:1px solid var(--fe-border);padding-bottom:.3em;font-size:1.4em}.Myjg4a_mdPreview h3{font-size:1.2em}.Myjg4a_mdPreview h4,.Myjg4a_mdPreview h5,.Myjg4a_mdPreview h6{font-size:1.05em}.Myjg4a_mdPreview p{margin:.6em 0}.Myjg4a_mdPreview ul,.Myjg4a_mdPreview ol{margin:.6em 0;padding-left:1.6em}.Myjg4a_mdPreview li,.Myjg4a_mdPreview li>ul,.Myjg4a_mdPreview li>ol{margin:.2em 0}.Myjg4a_mdPreview a{color:var(--fe-accent);text-decoration:none}.Myjg4a_mdPreview a:hover{text-decoration:underline}.Myjg4a_mdPreview blockquote{border-left:3px solid var(--fe-border-strong);color:var(--fe-muted);background:var(--fe-sidebar-bg);margin:.8em 0;padding:.3em 1em}.Myjg4a_mdPreview code{background:var(--fe-hover);border-radius:3px;padding:.15em .4em;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.92em}.Myjg4a_mdPreview pre{background:var(--fe-sidebar-bg);border:1px solid var(--fe-border);border-radius:4px;margin:.8em 0;padding:12px;line-height:1.5;overflow:auto}.Myjg4a_mdPreview pre code{background:0 0;padding:0;font-size:13px}.Myjg4a_mdPreview table{border-collapse:collapse;max-width:100%;margin:.8em 0;display:block;overflow-x:auto}.Myjg4a_mdPreview th,.Myjg4a_mdPreview td{border:1px solid var(--fe-border-strong);padding:6px 12px}.Myjg4a_mdPreview th{background:var(--fe-sidebar-bg);font-weight:600}.Myjg4a_mdPreview img{border-radius:4px;max-width:100%}.Myjg4a_mdPreview hr{border:none;border-top:1px solid var(--fe-border-strong);margin:1.5em 0}.Myjg4a_mdPreview .hljs-keyword,.Myjg4a_mdPreview .hljs-selector-tag,.Myjg4a_mdPreview .hljs-literal{color:var(--fe-token-keyword)}.Myjg4a_mdPreview .hljs-string,.Myjg4a_mdPreview .hljs-regexp,.Myjg4a_mdPreview .hljs-addition{color:var(--fe-token-string)}.Myjg4a_mdPreview .hljs-comment,.Myjg4a_mdPreview .hljs-quote{color:var(--fe-token-comment);font-style:italic}.Myjg4a_mdPreview .hljs-number,.Myjg4a_mdPreview .hljs-symbol,.Myjg4a_mdPreview .hljs-bullet{color:var(--fe-token-number)}.Myjg4a_mdPreview .hljs-title,.Myjg4a_mdPreview .hljs-section,.Myjg4a_mdPreview .hljs-title.function_{color:var(--fe-token-function)}.Myjg4a_mdPreview .hljs-type,.Myjg4a_mdPreview .hljs-built_in,.Myjg4a_mdPreview .hljs-class .hljs-title{color:var(--fe-token-type)}.Myjg4a_mdPreview .hljs-attr,.Myjg4a_mdPreview .hljs-attribute,.Myjg4a_mdPreview .hljs-variable,.Myjg4a_mdPreview .hljs-template-variable,.Myjg4a_mdPreview .hljs-params{color:var(--fe-token-variable)}.Myjg4a_mdPreview .hljs-tag,.Myjg4a_mdPreview .hljs-name{color:var(--fe-token-tag)}.Myjg4a_mdPreview .hljs-meta{color:var(--fe-token-meta)}.Myjg4a_mdPreview .hljs-emphasis{font-style:italic}.Myjg4a_mdPreview .hljs-strong{font-weight:600}.Myjg4a_placeholder{text-align:center;color:var(--fe-faint);flex:1;justify-content:center;align-items:center;padding:16px;font-size:12px;line-height:18px;display:flex}.Myjg4a_editorHighlight .hljs-keyword,.Myjg4a_editorHighlight .hljs-selector-tag,.Myjg4a_editorHighlight .hljs-literal{color:var(--fe-token-keyword)}.Myjg4a_editorHighlight .hljs-string,.Myjg4a_editorHighlight .hljs-regexp,.Myjg4a_editorHighlight .hljs-addition{color:var(--fe-token-string)}.Myjg4a_editorHighlight .hljs-comment,.Myjg4a_editorHighlight .hljs-quote{color:var(--fe-token-comment);font-style:italic}.Myjg4a_editorHighlight .hljs-number,.Myjg4a_editorHighlight .hljs-symbol,.Myjg4a_editorHighlight .hljs-bullet{color:var(--fe-token-number)}.Myjg4a_editorHighlight .hljs-title,.Myjg4a_editorHighlight .hljs-section,.Myjg4a_editorHighlight .hljs-title.function_{color:var(--fe-token-function)}.Myjg4a_editorHighlight .hljs-type,.Myjg4a_editorHighlight .hljs-built_in,.Myjg4a_editorHighlight .hljs-class .hljs-title{color:var(--fe-token-type)}.Myjg4a_editorHighlight .hljs-attr,.Myjg4a_editorHighlight .hljs-attribute,.Myjg4a_editorHighlight .hljs-variable,.Myjg4a_editorHighlight .hljs-template-variable,.Myjg4a_editorHighlight .hljs-params{color:var(--fe-token-variable)}.Myjg4a_editorHighlight .hljs-tag,.Myjg4a_editorHighlight .hljs-name{color:var(--fe-token-tag)}.Myjg4a_editorHighlight .hljs-meta{color:var(--fe-token-meta)}.Myjg4a_editorHighlight .hljs-emphasis{font-style:italic}.Myjg4a_editorHighlight .hljs-strong{color:var(--fe-accent);font-weight:inherit}[class*=explorerCol]{border-right:1px solid var(--fe-border)!important}";
|
|
43
43
|
const tagId = "dsh-plugin-workbench/files.module.css";
|
|
44
44
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
45
45
|
const tag = document.createElement("style");
|
package/lib/index.js
CHANGED
|
@@ -165,10 +165,13 @@ function pathOf(payload) {
|
|
|
165
165
|
* fine — this is the exact failure this auto-heal guards against.
|
|
166
166
|
*/
|
|
167
167
|
const LAYOUT_PATCH_MARKERS = [
|
|
168
|
-
"\"explorerCol\": \"",
|
|
168
|
+
"\"explorerCol\": \"pI_x6G_explorerCol\"",
|
|
169
169
|
"setExplorer: (d, px) => {",
|
|
170
170
|
"renderSlot(\"explorer\"",
|
|
171
|
-
"
|
|
171
|
+
"renderSlot(\"explorer.preview\"",
|
|
172
|
+
"conversationSeat",
|
|
173
|
+
"explorerOccupied",
|
|
174
|
+
"entries(\"explorer\").length + ctx.slots"
|
|
172
175
|
];
|
|
173
176
|
/** Resolve the installed dsh-client-ui-layout client bundle (profile node_modules junction). */
|
|
174
177
|
function layoutClientPath() {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-workbench",
|
|
3
3
|
"description": "VS Code-style workspace file explorer for the DeepSeek Harness web GUI — editable preview with syntax highlighting, tabs and line numbers, full right-click file operations (create / rename / delete / copy / cut / paste / reveal in file manager), inline image & markdown preview, @-mention files into chat, drag files into the composer, per-workspace state with undo. Turns the dsh web page into a lightweight code editor.",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.20",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "pnpm@11.21.0",
|
|
7
7
|
"engines": {
|
package/scripts/patch-layout.mjs
CHANGED
|
@@ -21,6 +21,14 @@
|
|
|
21
21
|
*
|
|
22
22
|
* Usage:
|
|
23
23
|
* node scripts/patch-layout.mjs [--target <abs path to client.js>] [--force]
|
|
24
|
+
* node scripts/patch-layout.mjs [--target <abs path to client.js>] --restore
|
|
25
|
+
*
|
|
26
|
+
* --restore copies the pristine backup (patches/layout.backup/client.js.orig,
|
|
27
|
+
* written by the first successful patch) back over the target — the uninstall
|
|
28
|
+
* recovery path: after removing this plugin, run this once and restart dsh web
|
|
29
|
+
* to get the stock dsh-client-ui-layout bundle back. Without it a leftover
|
|
30
|
+
* patch is harmless since 0.0.18 (the explorer column auto-hides when no
|
|
31
|
+
* plugin contributes to its slots), but restoring is the clean state.
|
|
24
32
|
*
|
|
25
33
|
* Default target resolves the profile junction to its npx-cache copy:
|
|
26
34
|
* <DSH_HOME>/profiles/node_modules/@deepseek-ai/dsh-client-ui-layout/lib/client.js
|
|
@@ -37,6 +45,7 @@ const BACKUP_DIR = join(REPO_ROOT, 'patches', 'layout.backup')
|
|
|
37
45
|
const args = process.argv.slice(2)
|
|
38
46
|
const targetArg = args.includes('--target') ? args[args.indexOf('--target') + 1] : undefined
|
|
39
47
|
const force = args.includes('--force')
|
|
48
|
+
const restore = args.includes('--restore')
|
|
40
49
|
|
|
41
50
|
const dshHome = process.env.DSH_HOME ?? join(homedir(), '.dsh')
|
|
42
51
|
const defaultTarget = join(dshHome, 'profiles', 'node_modules', '@deepseek-ai', 'dsh-client-ui-layout', 'lib', 'client.js')
|
|
@@ -125,17 +134,32 @@ const REPLACEMENTS = [
|
|
|
125
134
|
{
|
|
126
135
|
id: 'store.init.explorer',
|
|
127
136
|
anchor: '\t\t\t\t\tsidebar: 280,\n\t\t\t\t\tdetails: 0,',
|
|
128
|
-
replacement: '\t\t\t\t\tsidebar: 280,\n\t\t\t\t\texplorer: 260,\n\t\t\t\t\tdetails: 0,',
|
|
137
|
+
replacement: '\t\t\t\t\tsidebar: 280,\n\t\t\t\t\texplorer: 260,\n\t\t\t\t\texplorerOccupied: false,\n\t\t\t\t\tdetails: 0,',
|
|
129
138
|
},
|
|
130
139
|
{
|
|
131
140
|
id: 'store.action.setExplorer',
|
|
132
141
|
anchor: '\t\t\t\t\tsetDetails: (d, px) => {\n\t\t\t\t\t\td.details = clampWidth(px, 300, 520);\n\t\t\t\t\t},',
|
|
133
|
-
replacement: '\t\t\t\t\tsetDetails: (d, px) => {\n\t\t\t\t\t\td.details = clampWidth(px, 300, 520);\n\t\t\t\t\t},\n\t\t\t\t\tsetExplorer: (d, px) => {\n\t\t\t\t\t\td.explorer = clampWidth(px, 200, 420);\n\t\t\t\t\t},',
|
|
142
|
+
replacement: '\t\t\t\t\tsetDetails: (d, px) => {\n\t\t\t\t\t\td.details = clampWidth(px, 300, 520);\n\t\t\t\t\t},\n\t\t\t\t\tsetExplorer: (d, px) => {\n\t\t\t\t\t\td.explorer = clampWidth(px, 200, 420);\n\t\t\t\t\t},\n\t\t\t\t\tsetExplorerOccupied: (d, occupied) => {\n\t\t\t\t\t\td.explorerOccupied = occupied;\n\t\t\t\t\t},',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
id: 'controller.setExplorerOccupied',
|
|
146
|
+
anchor: '\t\t\tcloseDetails() {\n\t\t\t\tthis.#require().closeDetails();\n\t\t\t}',
|
|
147
|
+
replacement: '\t\t\tcloseDetails() {\n\t\t\t\tthis.#require().closeDetails();\n\t\t\t}\n\t\t\tsetExplorerOccupied(occupied) {\n\t\t\t\tif (this.#panels !== void 0) this.#panels.setExplorerOccupied(occupied);\n\t\t\t}',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
id: 'apply.explorerOccupancy',
|
|
151
|
+
anchor: '\t\t\t\t\tinject: (actions) => {\n\t\t\t\t\t\tlayout.attachPanels(actions);\n\t\t\t\t\t\treturn {};\n\t\t\t\t\t}',
|
|
152
|
+
replacement: '\t\t\t\t\tinject: (actions) => {\n\t\t\t\t\t\tlayout.attachPanels(actions);\n\t\t\t\t\t\tlayout.setExplorerOccupied(ctx.slots.entries("explorer").length + ctx.slots.entries("explorer.preview").length > 0);\n\t\t\t\t\t\treturn {};\n\t\t\t\t\t}',
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
id: 'apply.explorerOccupancyWatch',
|
|
156
|
+
anchor: '\t\t\t\treturn () => {\n\t\t\t\t\tdisposeRegistration();\n\t\t\t\t\tdisposeService();\n\t\t\t\t};\n\t\t\t}, "ui-layout: service + root registration");',
|
|
157
|
+
replacement: '\t\t\t\treturn () => {\n\t\t\t\t\tdisposeRegistration();\n\t\t\t\t\tdisposeService();\n\t\t\t\t};\n\t\t\t}, "ui-layout: service + root registration");\n\t\t\tctx.effect(() => {\n\t\t\t\tconst syncExplorer = () => {\n\t\t\t\t\tlayout.setExplorerOccupied(ctx.slots.entries("explorer").length > 0 || ctx.slots.entries("explorer.preview").length > 0);\n\t\t\t\t};\n\t\t\t\tsyncExplorer();\n\t\t\t\treturn ctx.on("slots/changed", syncExplorer);\n\t\t\t}, "ui-layout: explorer occupancy sync");',
|
|
134
158
|
},
|
|
135
159
|
{
|
|
136
160
|
id: 'appframe.computeCall',
|
|
137
161
|
anchor: 'const cols = computeColumns(viewport, sidebarCollapsed ? 0 : panels.sidebar === 0 ? 280 : panels.sidebar, detailsSession === void 0 ? 0 : panels.details);',
|
|
138
|
-
replacement: 'const explorerEffective = narrow ? 0 : panels.explorer;\n\t\t\tconst cols = computeColumns(viewport, sidebarCollapsed ? 0 : panels.sidebar === 0 ? 280 : panels.sidebar, explorerEffective, detailsSession === void 0 ? 0 : panels.details);',
|
|
162
|
+
replacement: 'const explorerEffective = narrow || !panels.explorerOccupied ? 0 : panels.explorer;\n\t\t\tconst cols = computeColumns(viewport, sidebarCollapsed ? 0 : panels.sidebar === 0 ? 280 : panels.sidebar, explorerEffective, detailsSession === void 0 ? 0 : panels.details);',
|
|
139
163
|
},
|
|
140
164
|
{
|
|
141
165
|
id: 'appframe.explorerBase',
|
|
@@ -257,8 +281,55 @@ const REPLACEMENTS = [
|
|
|
257
281
|
// desktop-ci variant: same table, with `computeColumns` swapped for the anchor
|
|
258
282
|
// pair extracted mechanically from a real DSH Desktop packaged bundle.
|
|
259
283
|
const DESKTOP_CI = JSON.parse(readFileSync(join(SCRIPT_DIR, 'layout-anchors.desktop-ci.json'), 'utf8'))
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Delta table for bundles already carrying the PREVIOUS revision of this patch
|
|
287
|
+
* (explorer column without occupancy gating). Anchors exist only in that
|
|
288
|
+
* intermediate state, so these variants never match a pristine bundle — the
|
|
289
|
+
* full variants above win there. Same for both npm and desktop-ci builds:
|
|
290
|
+
* none of the delta anchors touch the `computeColumns` body.
|
|
291
|
+
*/
|
|
292
|
+
const DELTA_REPLACEMENTS = [
|
|
293
|
+
{
|
|
294
|
+
id: 'delta.appframe.computeCall',
|
|
295
|
+
anchor: 'const explorerEffective = narrow ? 0 : panels.explorer;',
|
|
296
|
+
replacement: 'const explorerEffective = narrow || !panels.explorerOccupied ? 0 : panels.explorer;',
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
id: 'delta.store.init',
|
|
300
|
+
anchor: '\t\t\t\t\texplorer: 260,\n\t\t\t\t\tdetails: 0,',
|
|
301
|
+
replacement: '\t\t\t\t\texplorer: 260,\n\t\t\t\t\texplorerOccupied: false,\n\t\t\t\t\tdetails: 0,',
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
id: 'delta.store.action',
|
|
305
|
+
anchor: '\t\t\t\t\tsetExplorer: (d, px) => {\n\t\t\t\t\t\td.explorer = clampWidth(px, 200, 420);\n\t\t\t\t\t},',
|
|
306
|
+
replacement: '\t\t\t\t\tsetExplorer: (d, px) => {\n\t\t\t\t\t\td.explorer = clampWidth(px, 200, 420);\n\t\t\t\t\t},\n\t\t\t\t\tsetExplorerOccupied: (d, occupied) => {\n\t\t\t\t\t\td.explorerOccupied = occupied;\n\t\t\t\t\t},',
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
id: 'delta.controller',
|
|
310
|
+
anchor: '\t\t\tcloseDetails() {\n\t\t\t\tthis.#require().closeDetails();\n\t\t\t}',
|
|
311
|
+
replacement: '\t\t\tcloseDetails() {\n\t\t\t\tthis.#require().closeDetails();\n\t\t\t}\n\t\t\tsetExplorerOccupied(occupied) {\n\t\t\t\tif (this.#panels !== void 0) this.#panels.setExplorerOccupied(occupied);\n\t\t\t}',
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
id: 'delta.watch',
|
|
315
|
+
anchor: '\t\t\t\treturn () => {\n\t\t\t\t\tdisposeRegistration();\n\t\t\t\t\tdisposeService();\n\t\t\t\t};\n\t\t\t}, "ui-layout: service + root registration");',
|
|
316
|
+
replacement: '\t\t\t\treturn () => {\n\t\t\t\t\tdisposeRegistration();\n\t\t\t\t\tdisposeService();\n\t\t\t\t};\n\t\t\t}, "ui-layout: service + root registration");\n\t\t\tctx.effect(() => {\n\t\t\t\tconst syncExplorer = () => {\n\t\t\t\t\tlayout.setExplorerOccupied(ctx.slots.entries("explorer").length > 0 || ctx.slots.entries("explorer.preview").length > 0);\n\t\t\t\t};\n\t\t\t\tsyncExplorer();\n\t\t\t\treturn ctx.on("slots/changed", syncExplorer);\n\t\t\t}, "ui-layout: explorer occupancy sync");',
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
id: 'delta.apply',
|
|
320
|
+
anchor: '\t\t\t\t\tinject: (actions) => {\n\t\t\t\t\t\tlayout.attachPanels(actions);\n\t\t\t\t\t\treturn {};\n\t\t\t\t\t}',
|
|
321
|
+
replacement: '\t\t\t\t\tinject: (actions) => {\n\t\t\t\t\t\tlayout.attachPanels(actions);\n\t\t\t\t\t\tlayout.setExplorerOccupied(ctx.slots.entries("explorer").length + ctx.slots.entries("explorer.preview").length > 0);\n\t\t\t\t\t\treturn {};\n\t\t\t\t\t}',
|
|
322
|
+
},
|
|
323
|
+
]
|
|
324
|
+
|
|
325
|
+
/** Delta #2: bundles carrying the FIRST occupancy delta (watch effect only, no
|
|
326
|
+
* inject-hook sync). Just the inject-hook injection; the watch block already exists. */
|
|
327
|
+
const DELTA2_REPLACEMENTS = DELTA_REPLACEMENTS.filter((item) => item.id === 'delta.apply')
|
|
328
|
+
|
|
260
329
|
const VARIANTS = [
|
|
261
330
|
{ id: 'npm', replacements: REPLACEMENTS },
|
|
331
|
+
{ id: 'npm-delta', replacements: DELTA_REPLACEMENTS },
|
|
332
|
+
{ id: 'npm-delta2', replacements: DELTA2_REPLACEMENTS },
|
|
262
333
|
{
|
|
263
334
|
id: 'desktop-ci',
|
|
264
335
|
replacements: REPLACEMENTS.map((item) =>
|
|
@@ -267,9 +338,11 @@ const VARIANTS = [
|
|
|
267
338
|
: item
|
|
268
339
|
),
|
|
269
340
|
},
|
|
341
|
+
{ id: 'desktop-ci-delta', replacements: DELTA_REPLACEMENTS },
|
|
342
|
+
{ id: 'desktop-ci-delta2', replacements: DELTA2_REPLACEMENTS },
|
|
270
343
|
]
|
|
271
344
|
|
|
272
|
-
const PATCHED_MARKERS = ['"explorerCol": "pI_x6G_explorerCol"', 'setExplorer: (d, px) => {', 'renderSlot("explorer"', 'renderSlot("explorer.preview"', 'conversationSeat']
|
|
345
|
+
const PATCHED_MARKERS = ['"explorerCol": "pI_x6G_explorerCol"', 'setExplorer: (d, px) => {', 'renderSlot("explorer"', 'renderSlot("explorer.preview"', 'conversationSeat', 'explorerOccupied', 'entries("explorer").length + ctx.slots']
|
|
273
346
|
|
|
274
347
|
function applyReplacements(original, replacements) {
|
|
275
348
|
let patched = original
|
|
@@ -300,6 +373,44 @@ function main() {
|
|
|
300
373
|
const real = realpathSync(target)
|
|
301
374
|
const original = readFileSync(real, 'utf8')
|
|
302
375
|
|
|
376
|
+
// Uninstall recovery: copy the pristine pre-patch bundle back over the
|
|
377
|
+
// target. Runs before every other check — restoring must work regardless of
|
|
378
|
+
// the current bundle's patch state.
|
|
379
|
+
if (restore) {
|
|
380
|
+
const pristine = join(BACKUP_DIR, 'client.js.orig')
|
|
381
|
+
if (!existsSync(pristine)) {
|
|
382
|
+
console.error('[patch-layout] no pristine backup found at ' + pristine)
|
|
383
|
+
console.error('[patch-layout] recover by reinstalling the package instead:')
|
|
384
|
+
console.error(' cd <dsh profile dir> && pnpm install # (or upgrade dsh — the bundle ships with it)')
|
|
385
|
+
process.exit(1)
|
|
386
|
+
}
|
|
387
|
+
// Staleness guard 1: the target may be a NEWER pristine from a dsh upgrade
|
|
388
|
+
// (nothing to restore). Refuse unless --force.
|
|
389
|
+
const looksPatched = PATCHED_MARKERS.some((marker) => original.includes(marker))
|
|
390
|
+
// Staleness guard 2: the backup must itself be a pristine this script can
|
|
391
|
+
// still patch (an old-dsh backup is useless on a newer dsh — restoring it
|
|
392
|
+
// would be a silent downgrade). Refuse unless --force.
|
|
393
|
+
const backupText = readFileSync(pristine, 'utf8')
|
|
394
|
+
const backupPatchable = VARIANTS.filter((v) => v.id !== 'npm-delta' && v.id !== 'desktop-ci-delta')
|
|
395
|
+
.some((variant) => applyReplacements(backupText, variant.replacements).failures.length === 0)
|
|
396
|
+
if ((!looksPatched || !backupPatchable) && !force) {
|
|
397
|
+
if (!looksPatched) {
|
|
398
|
+
console.error('[patch-layout] target does not look patched — it may be a newer pristine bundle from a dsh upgrade.')
|
|
399
|
+
}
|
|
400
|
+
if (!backupPatchable) {
|
|
401
|
+
console.error('[patch-layout] the pristine backup predates the installed dsh version (its anchors no longer match).')
|
|
402
|
+
console.error('[patch-layout] recover by reinstalling the package instead:')
|
|
403
|
+
console.error(' cd <dsh profile dir> && pnpm install # (or upgrade dsh — the bundle ships with it)')
|
|
404
|
+
}
|
|
405
|
+
console.error('[patch-layout] refusing a risky restore; pass --force to restore anyway.')
|
|
406
|
+
process.exit(1)
|
|
407
|
+
}
|
|
408
|
+
copyFileSync(pristine, real)
|
|
409
|
+
console.log(`[patch-layout] restored the pristine dsh-client-ui-layout bundle: ${real}`)
|
|
410
|
+
console.log('[patch-layout] restart dsh web to serve the restored bundle.')
|
|
411
|
+
return
|
|
412
|
+
}
|
|
413
|
+
|
|
303
414
|
const alreadyPatched = PATCHED_MARKERS.every((marker) => original.includes(marker))
|
|
304
415
|
if (alreadyPatched && !force) {
|
|
305
416
|
console.log(`[patch-layout] already patched (${real}) — nothing to do.`)
|
|
@@ -324,9 +435,23 @@ function main() {
|
|
|
324
435
|
|
|
325
436
|
mkdirSync(BACKUP_DIR, { recursive: true })
|
|
326
437
|
const pristine = join(BACKUP_DIR, 'client.js.orig')
|
|
327
|
-
|
|
438
|
+
// client.js.orig must hold the PRISTINE bundle of the CURRENT dsh version —
|
|
439
|
+
// it is what --restore hands back on uninstall. A dsh upgrade reverts the
|
|
440
|
+
// bundle to a fresh pristine, so whenever the pre-patch target itself looks
|
|
441
|
+
// unpatched, promote it (the previous orig belongs to an older dsh and would
|
|
442
|
+
// otherwise be restored over a newer install — a silent downgrade). Only a
|
|
443
|
+
// pre-patch state that already carries our markers gets the timestamped bak.
|
|
444
|
+
const targetLooksPatched = PATCHED_MARKERS.some((marker) => original.includes(marker))
|
|
445
|
+
const hadPristine = existsSync(pristine)
|
|
446
|
+
// The shared pristine backup backs --restore for the DEFAULT profile bundle.
|
|
447
|
+
// With an explicit --target (testing / another machine's bundle) never touch
|
|
448
|
+
// it — an unrelated file must not overwrite the restore source.
|
|
449
|
+
if (targetArg !== undefined) {
|
|
450
|
+
console.log('[patch-layout] --target given: skipping backup bookkeeping (the shared pristine backup is only managed for the default profile bundle).')
|
|
451
|
+
} else if (!hadPristine || !targetLooksPatched) {
|
|
328
452
|
copyFileSync(real, pristine)
|
|
329
|
-
console.log(`[patch-layout] pristine backup written: ${pristine}`)
|
|
453
|
+
if (!hadPristine) console.log(`[patch-layout] pristine backup written: ${pristine}`)
|
|
454
|
+
else console.log('[patch-layout] pristine backup refreshed (dsh upgrade detected — the old orig was a different version).')
|
|
330
455
|
} else {
|
|
331
456
|
const stamp = new Date().toISOString().replace(/[:.]/g, '-')
|
|
332
457
|
copyFileSync(real, join(BACKUP_DIR, `client.js.${stamp}.bak`))
|
|
@@ -997,18 +997,6 @@
|
|
|
997
997
|
font-weight: inherit;
|
|
998
998
|
}
|
|
999
999
|
|
|
1000
|
-
/* ---- Skin chrome fix ----
|
|
1001
|
-
Shift the maid-atelier fixed top/bottom trim past the explorer column and
|
|
1002
|
-
the split preview, so it only decorates the chat instead of overlaying the
|
|
1003
|
-
file column, preview header/buttons, or file content. */
|
|
1004
|
-
body[data-dsh-maid-atelier] [data-skin-chrome=top-trim] {
|
|
1005
|
-
translate: calc(var(--maid-sidebar-width, 0px) + var(--dsh-explorer-width, 0px) + var(--dsh-preview-width, 0px)) 0 !important;
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
body[data-dsh-maid-atelier] [data-skin-chrome=bottom-trim] {
|
|
1009
|
-
translate: calc(var(--maid-sidebar-width, 0px) + var(--dsh-explorer-width, 0px) + var(--dsh-preview-width, 0px)) 0 !important;
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
1000
|
[class*='explorerCol'] {
|
|
1013
1001
|
border-right: 1px solid var(--fe-border) !important;
|
|
1014
1002
|
}
|
package/src/index.ts
CHANGED
|
@@ -262,10 +262,22 @@ function pathOf(payload: unknown): string | undefined {
|
|
|
262
262
|
* fine — this is the exact failure this auto-heal guards against.
|
|
263
263
|
*/
|
|
264
264
|
const LAYOUT_PATCH_MARKERS = [
|
|
265
|
-
|
|
265
|
+
// Keep in exact sync with PATCHED_MARKERS in scripts/patch-layout.mjs — a
|
|
266
|
+
// weaker subset here means a damaged/partially-reverted bundle could pass
|
|
267
|
+
// the host check yet fail the script's verification, and auto-heal never
|
|
268
|
+
// fires for it.
|
|
269
|
+
'"explorerCol": "pI_x6G_explorerCol"',
|
|
266
270
|
'setExplorer: (d, px) => {',
|
|
267
271
|
'renderSlot("explorer"',
|
|
272
|
+
'renderSlot("explorer.preview"',
|
|
268
273
|
'conversationSeat',
|
|
274
|
+
// 0.0.18+: occupancy gating — the explorer column must auto-hide when no
|
|
275
|
+
// plugin contributes to the explorer / explorer.preview slots (issue #2).
|
|
276
|
+
// 0.0.19: the sync must ALSO run inside the root registration's inject hook —
|
|
277
|
+
// apply-time sync lands before attachPanels (a no-op) and after the one-shot
|
|
278
|
+
// registration emit, so without this the column stayed collapsed forever.
|
|
279
|
+
'explorerOccupied',
|
|
280
|
+
'entries("explorer").length + ctx.slots',
|
|
269
281
|
] as const
|
|
270
282
|
|
|
271
283
|
/** Resolve the installed dsh-client-ui-layout client bundle (profile node_modules junction). */
|