@weibaohui/dsh-sidebar-tidy
dsh 侧栏收纳:插件装多了,「新会话」下面被各插件塞满了入口行。本插件把这些入口(全局面板行、插件注入的家族行、底部入口)统统收进一个菜单按钮,点开二级菜单原样触发;想常驻的加白名单即可。
功能
- 一键收纳:「新会话」下方出现一个菜单按钮(默认跟随语言自动命名,带收起数量徽标),点开二级菜单——按「全局面板 / 插件入口 / 底部入口」分组(组名直接读宿主容器的 aria-label),每项带原按钮的图标与名称
- 原样触发:菜单项点击就是对原入口按钮的真实点击,各面板自己的打开逻辑(含中栏接管视图)不受影响;当前打开的面板带蓝点标记
- 三类范围独立开关:全局面板行(任务/数据面板/收藏…)、插件入口行(流程/知识库/Git/任务看板及一切第三方 DOM 注入——按「新会话的兄弟 button」结构规则识别,不依赖各家属性)、底部入口(设置区永不碰)
- 白名单:按名称保留常驻入口(如「任务, 收藏」),名称包含即留在侧栏原位不收
- 窄轨适配:侧栏折叠成 56px 轨时按钮变纯图标,菜单从右侧弹出
- 明暗主题自动跟随:全程使用宿主设计 token(菜单表面用宿主 MenuSurface 同款
--dsw-menu-surface-fill),无任何硬编码主题判断 - 卸载即恢复:禁用插件或停用后,所有被收入口原样还原
设置入口:dsh 设置页左侧导航「侧栏收纳」。所有改动即时生效,偏好存在浏览器 localStorage(dsh-tidy:prefs)。
安装
dsh plugin --profile web add @weibaohui/dsh-sidebar-tidy -w
兼容性
- DSH
>=0.1.7-rc.2(纯客户端 DOM 适配,零字面选择器:锚点经宿主公开词典取词、容器靠结构特征推导,宿主改 CSS 类名/哈希完全不受影响) - 对被收纳插件零侵入:只隐藏入口按钮本身,不改任何插件逻辑;卸载后一切复原
工作原理(零字面选择器)
对宿主不写任何 CSS 类名、data 属性或文案字面量,只依赖两类公开契约加三条结构事实:
| 依赖 | 性质 | 用途 |
|---|---|---|
locale.bind('sidebar') |
宿主侧栏自己的公开词典 NS | 用 session.new.label 在当前语言下动态取词定位「新会话」锚点;panels.label 等由容器 aria-label 直接读到 |
slots / locale 服务名、settings.section 槽位 |
宿主公开 API | 注册设置页 |
| 锚点存在 | 结构事实 | 新会话按钮是一切推导的起点 |
| 面板列表 = 「直接子全是按钮」的容器 | 结构事实 | 广度优先取最浅命中 |
| 底部区块 = 根最后一个直接子元素,末位容器是设置区 | 结构事实(宿主渲染顺序) | 只收非设置容器里的条目 |
推导链:锚点(词典取词匹配 aria-label)→ 根(从锚点向上爬到「直接持有列表容器」的祖先)→ 面板列表(结构特征)→ 家族行(锚点之后、面板列表之前的可点击根子元素,含「容器内是按钮」的包裹型注入)→ 底部条目。窄轨态按根的几何宽度判定(<120px),不看任何类名。找不到锚点就静默待机续扫,绝不猜选择器。
客户端 bundle 幂等重扫侧栏(childList 观察器只盯根直接子级 + 2s 兜底 interval,绝不挂 childList+subtree 观察器);隐藏写内联 display:none(React 重渲染不会抹掉),节点被重建则由重扫重放。菜单按钮插在锚点之后,弹层挂 body,打开时按当前 DOM 重建菜单项(图标克隆、名称实时读、分组标题读容器 aria-label),点击 .click() 原按钮。
仍然留在代码里的只有:回退用的中英文词典(locale 服务缺席时的最终兜底)、装饰性图标 SVG、行为参数(2s 扫描、z-index、localStorage 键名)。npm test 里有一条断言机器守住这个边界:bundle 中不得出现宿主类名、家族 data 属性或锚点文案。
宿主半体(src/index.js)是零逻辑薄壳:无服务面、无存储域,存在意义只是让 composition 里有这一行、web 外壳按包名关联加载客户端 bundle。
开发
npm run build:client # 重新生成 client/bundle.js(改了 client/*.js 必须重跑)
npm run check # 语法检查
npm test # 离线测试(偏好归一化/白名单/收纳判定/bundle 协议)
License
MIT
No comments yet. Be the first to write one.