dsh-composer-ux 0.29.2 → 0.29.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  本项目遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
4
4
 
5
+ ## [0.29.3] — 2026-11-04(适配 DSH 0.2.2:面板列表的「更多」变成 span 包按钮)
6
+
7
+ 对接 `dsh-v0.2.2-rc.1`(本地源码仓库切到该 tag 后重建网页版)时,实测发现一个真实回归:
8
+
9
+ **0.2.1**:面板列表里每一项都是 `nav > button[aria-label]`(含「更多」)。
10
+ **0.2.2**:「更多」变成 `<span>` **包着一颗按钮**。
11
+
12
+ 我们的折叠判据是"直接子节点是 button + aria-label + 内含 aria-hidden 图标",于是那颗 span 被当成
13
+ **别人的节点**,后果有两个:
14
+
15
+ - 「只留图标」模式不压缩它 → 它的文字留在图标行里(和 0.27.0 那个「更多」漏字问题同源);
16
+ - 「收成一条」模式因为"组里还有别人的节点"而**不敢收起整只 nav** → 折叠看起来坏了。
17
+
18
+ **修法**(仍然只看结构,不看哈希类名):子节点本身是面板行按钮 **或** 它是"只包着一颗面板行按钮"
19
+ 的包装层,都算这一组的行;包装层也被打标记,CSS 才能压到它的宽度/字号,标题挂到里面那颗按钮上。
20
+ 多于一颗按钮的包装层仍然算"别人的"(那通常是别人放的一组按钮)。
21
+
22
+ **验证**(真机,0.2.2-rc.1 网页版):`data-ux-nav-row` 3 颗(含 span 包装层)、
23
+ 「更多」`font-size:0` + 宽度 34px、`bar` 模式 `nav` 被隐藏且「全局面板▾」正常、
24
+ 底部区「账号与其他」收起/展开正常、快捷指令面板能打开。
25
+
26
+ **测试**:`test/sidebar-nav.mjs` 新增第 8 节(6 条,含"包装层不再挡路")。
27
+
5
28
  ## [0.29.2] — 2026-10-29(展开时把「账号与其他 ▴」缩进到账号行右端)
6
29
 
7
30
  用户 2026-10-29(截图圈住「方文」右侧的空白):「这个展开时,把这个账号和其他和收缩按钮放到这个位置」。
package/README.md CHANGED
@@ -682,9 +682,9 @@ node build.mjs # 产出 lib/index.js + lib/client.js
682
682
  # ⚠️ 宿主半会**内联** schemastery / cosmokit:
683
683
  # 优先用 DSH 检出里的 vendor 副本,检出不在时退到 node_modules
684
684
  # 里同版本的 npm 包(两者逐字节相同)——CI 上走的就是退路
685
- npm test # 30 个套件;当前 2621 passed, 0 failed(2026-10-28 实测;CI 三平台同样全绿)
685
+ npm test # 30 个套件;当前 2627 passed, 0 failed(2026-10-28 实测;CI 三平台同样全绿)
686
686
  # 走 scripts/run-tests.mjs:顺带把"多少套件/多少条"记进 test/.last-run.json
687
- npm run test:mutations # 手动跑:变异测试,证明那套护栏真的在咬人(206 条,须单独跑)
687
+ npm run test:mutations # 手动跑:变异测试,证明那套护栏真的在咬人(208 条,须单独跑)
688
688
  # 同样记录结果,供下面的文档门禁核对
689
689
  npm run gates # 发版门禁三条一起跑:tag 指向 / 包内容 / 文档数字
690
690
  npm run check:tag # ① tag 名里的版本 == 该 tag 所指提交里的 package.json 版本
@@ -765,6 +765,7 @@ Remove-Item "$env:USERPROFILE\.dsh\profiles\web\package.json.lock" -Force
765
765
  | 0.1.7-rc.1 / rc.2 | 可用 | 依赖窗口的第一段 |
766
766
  | 0.2.0-rc.1 / rc.2 | 可用 | 桌面版装的这一版 |
767
767
  | **0.2.1-alpha.1 / alpha.2** | **可用(0.20.0 起)** | 2026-10-10 把 `D:\DeepSeek Harness` 未封装版升上去后真机验证(含设置页开关点击与写入落盘) |
768
+ | **0.2.2-rc.1** | **可用(0.29.3 起)** | 2026-11-04 源码仓库切到 `dsh-v0.2.2-rc.1`、`pnpm build:web` 后真机验证:doctor 8 行 / 29 字段全声明、`bar` 与 `icons` 两种折叠、底部区「账号与其他」、快捷指令面板都正常。**0.2.2 把面板列表的「更多」改成了 `span` 包一颗按钮**,0.29.3 之前会把它当"别人的节点"→ 折叠坏一半(详见 CHANGELOG) |
768
769
 
769
770
  **依赖窗口**:`@deepseek-ai/dsh-tool-terminal` 声明为
770
771
  `>=0.1.7-rc.1 <0.1.8 || >=0.2.0-rc.1 <0.2.1-alpha.0 || >=0.2.1-alpha.1 <0.3.0`。
package/dsh-plugin.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "manifestVersion": "0.15",
4
4
  "id": "dsh-composer-ux.input-experience",
5
5
  "name": "dsh-composer-ux",
6
- "version": "0.29.2",
6
+ "version": "0.29.3",
7
7
  "license": "MIT",
8
8
  "facets": {
9
9
  "host": {
package/lib/client.js CHANGED
@@ -2855,14 +2855,15 @@ function ensureStyle(doc) {
2855
2855
  if (tag.textContent !== NAV_FOLD_CSS) tag.textContent = NAV_FOLD_CSS;
2856
2856
  }
2857
2857
  function applyTitles(rows, on) {
2858
- for (const button of rows) {
2858
+ for (const row2 of rows) {
2859
+ const button = isPanelRowButton(row2) ? row2 : solePanelRowButton(row2) ?? row2;
2859
2860
  if (on) {
2860
2861
  const label = (button.getAttribute("aria-label") ?? "").trim();
2861
2862
  if (label !== "" && button.getAttribute(NAV_FOLD_TITLE_ATTR) !== label) {
2862
2863
  button.setAttribute("title", label);
2863
2864
  button.setAttribute(NAV_FOLD_TITLE_ATTR, label);
2864
2865
  }
2865
- for (const span of [...button.querySelectorAll("span")]) {
2866
+ for (const span of [...row2.querySelectorAll("span")]) {
2866
2867
  if (span.querySelector("svg") !== null) continue;
2867
2868
  span.style.display = "none";
2868
2869
  }
@@ -2872,17 +2873,24 @@ function applyTitles(rows, on) {
2872
2873
  button.removeAttribute("title");
2873
2874
  button.removeAttribute(NAV_FOLD_TITLE_ATTR);
2874
2875
  }
2875
- for (const span of [...button.querySelectorAll("span")]) {
2876
+ for (const span of [...row2.querySelectorAll("span")]) {
2876
2877
  if (span.style.display === "none") span.style.display = "";
2877
2878
  }
2878
2879
  }
2879
2880
  }
2881
+ function isPanelRowButton(element) {
2882
+ const label = (element.getAttribute("aria-label") ?? "").trim();
2883
+ return element.tagName === "BUTTON" && label !== "" && element.querySelector('[aria-hidden="true"]') !== null;
2884
+ }
2885
+ function solePanelRowButton(wrapper) {
2886
+ const buttons = [...wrapper.querySelectorAll("button")].filter(isPanelRowButton);
2887
+ return buttons.length === 1 ? buttons[0] : null;
2888
+ }
2880
2889
  function splitPanelRows(nav, mark = true) {
2881
2890
  const rows = [];
2882
2891
  const foreign = [];
2883
2892
  for (const child of [...nav.children]) {
2884
- const label = (child.getAttribute("aria-label") ?? "").trim();
2885
- const isRow = child.tagName === "BUTTON" && label !== "" && child.querySelector('[aria-hidden="true"]') !== null;
2893
+ const isRow = isPanelRowButton(child) || solePanelRowButton(child) !== null;
2886
2894
  const shouldMark = isRow && mark;
2887
2895
  if (!shouldMark) {
2888
2896
  if (child.hasAttribute(NAV_FOLD_ROW_ATTR)) child.removeAttribute(NAV_FOLD_ROW_ATTR);