- Startseite
- Plugins
- UI-Erweiterungen
- dsh-zoom-scale
dsh-zoom-scale
cieux/dsh-zoom-scale
Whole-interface zoom from 75% to 200% in 5% steps via a Settings row, a session-header stepper or Ctrl/⌘+wheel, with a shim that converts rects, viewport units, media queries and pointer coordinates so fixed overlays stay anchored to their triggers.
Installation
dsh plugin --profile web add github:cieux/dsh-zoom-scaleREADME
dsh-zoom-scale
Interface zoom for DeepSeek Harness (DSH). Scales the whole Web / Desktop UI and keeps every overlay (menus, tooltips, hover cards, dialogs) anchored to its trigger at any zoom level.
Features
- Range: 75% – 200%, 5% steps
- Entry points
- Settings → General → Interface zoom (stepper + reset)
- Session header
− 125% +control (click the percentage to reset to 100%) Ctrl(⌘on macOS) + wheelCtrl/⌘+=,-,0
- Persistence: same-origin cookie (the desktop shell changes ports between launches) mirrored to localStorage
Two halves
| File | Runs in | Owns |
|---|---|---|
index.js | host (Node) | the head script: the shim source, the seed scale, a reserved desktop-window-restore hook (not implemented, see Desktop window memory) |
lib/shim.cjs | page, before any client module | every geometry conversion; publishes window.__dshzs |
client.js | page, as a Loader module | the controls, the preference, the locale dictionaries, a fallback shim |
index.js injects one head script, so the shim is installed before any client module runs and applies the remembered scale before the shell's first mount. client.js drives window.__dshzs when it exists and installs a fallback only when it does not, so no rect is divided twice.
What the shim converts
Chromium reports rects, window size and pointer coordinates in visual pixels after html { zoom }, while CSS lengths stay in layout pixels — every position: fixed overlay would drift. The shim divides that back out, roughly for: element and Range rects, window and VisualViewport metrics, scrolling APIs, pointer and wheel coordinates, hit testing, SVG screen matrices, viewport units (vw/vh/vmin/vmax → calc(… / var(--dshzs-scale))), media-query bounds and devicePixelRatio. Every step is guarded on its own, so a missing API degrades one behaviour instead of the whole zoom.
Stylesheet coverage
Converted declarations follow --dshzs-scale, so a scale change only re-derives media-query bounds and no stylesheet is rescanned. New CSS is caught by a MutationObserver, the adoptedStyleSheets setter, CSSStyleSheet.insertRule / replaceSync, and a capture-phase load listener.
Desktop window memory
Reserved, not implemented. The head script reads localStorage['dshzs:window'] and, under the dsh-app: protocol the desktop shell uses, restores the main window with resizeTo / moveTo. This plugin never writes that key, so the branch does nothing today; it is kept only as the contract a later implementation would fill.
Payload — CSS pixels (DIP), screen coordinates:
{ "x": 234, "y": 90, "w": 1440, "h": 900 }
Only a position inside the current display's work area is restored: saved.x / saved.y are checked against screen.availLeft / availTop, so a position on another monitor is dropped while the size still applies. The shell may also impose a minimum size of its own.
If you need the feature now, install one of these instead:
| Plugin | Platform | Notes |
|---|---|---|
dsh-window-bounds | all | page-side resizeTo / moveTo, logical pixels; does not restore the maximized state |
dsh-window-state | Windows | native user32.dll, also remembers the maximized state; the window may flash at the default size first |
Install only one. They write different keys but drive the same window, so the last writer wins. Neither needs a change here: a window resize needs no hook, because vw / vh are already rewritten to calc(… / var(--dshzs-scale)).
Install
# from a local directory
dsh plugin add /path/to/dsh-zoom-scale
# or from the packaged artifact
dsh plugin add ./dsh-zoom-scale-0.2.7.tgz
After installation reload DSH (a restart is recommended for the desktop app). The "Interface zoom" row appears under Settings → General.
Compatibility
- DSH 0.1.7 or newer. The head script is delivered through
webserver/index-inject, and 0.1.7-rc.1 is the first release whose published packages provide it. 0.1.0–0.1.6 were not tested.schemasteryis loaded optionally, so a profile that carries only this plugin still boots (the configurable scale is then absent and the seed stays at 100 %). - Do not set
zoomon the root. The shim ownshtml { zoom }; a secondhtmldeclaration overwrites it (or is overwritten, depending on cascade order) and desynchronises every conversion.zoomon a descendant multiplies with the root zoom, so leavezoomalone outside the shim. - Do not use
transform: scale()to zoom. It multiplies with the root zoom, creates a containing block that re-anchorsposition: fixedoverlays (the shim cannot correct that), makesgetBoundingClientRectdisagree with the conversions, and stretches glyphs instead of re-rasterising them. - Do not write
--dshzs-scale. The shim rewrites it on every change; an inline value on<html>wins over the shim's stylesheet and breaks every converted length. Read the variable, never write it. - Viewport units are rewritten in stylesheets and in rules added through
insertRule,replaceSyncandadoptedStyleSheets. Inlinestyleattributes are converted too, but only after they are observed, so put first-paint-critical measurements in stylesheet rules. - Colours: use the
--dsw-*tokens. Hard-coded colours do not follow the dark theme. - To read the current scale, use
window.__dshzs?.get()orhtml[data-dshzs](published by the head shim itself, absent at 100 %). Do not readdocumentElement.style.zoom: in shim mode the zoom lives in a<style>element and only the fallback path writes it inline. At 100 % that style is empty anddata-dshzsis absent — that does not mean the plugin is missing. - Do not install a second shim.
window.__dshzshas one owner; wrapping the same properties again divides every rect twice. Drive the existing object withset().
Changelog
0.2.7 (latest)
- Refactor:
escapeScriptTextmoved tolib/util.cjsso it can be tested on its own, and it now neutralises a</scriptthat sits at the end of the injected source too. - Refactor: persistence keys and the scale range live in
lib/zoom-constants.cjs;client.jsis an IIFE and keeps its own literals, and a test fails when the two drift apart. - Naming:
SCALE_KEY/SCALE_COOKIE/LOCALE_NAMESPACEinclient.js,SCALE_PROPERTY/MEDIA_QUERY_STATEin the shim. - Tests:
util(3), dictionary key parity (1), constants drift (2).
License
MIT
dsh-zoom-scale(中文)
DeepSeek Harness(DSH)Web / Desktop 界面的整体缩放插件。把整个 UI 按比例缩放,同时保证所有浮层(菜单、tooltip、hover card、弹窗)在任意缩放下仍然贴住各自的触发元素。
功能
- 区间:75% – 200%,5% 步进
- 入口
- 设置 → 通用设置 → 界面缩放(带 +/- 步进与重置)
- 会话头部右侧的
− 125% +控件(点击百分比重置为 100%) Ctrl(macOS 为⌘)+ 滚轮直接缩放Ctrl/⌘+=、-、0
- 记忆:缩放值写入同源 cookie(桌面壳每次启动端口会变,cookie 按 host 保留)并镜像到 localStorage
两半
| 文件 | 运行位置 | 负责 |
|---|---|---|
index.js | 宿主(Node) | head 脚本:shim 源码、初始缩放值、预留的桌面窗口还原接口(未实装,见桌面窗口记忆) |
lib/shim.cjs | 页面,早于任何客户端模块 | 全部几何换算;发布 window.__dshzs |
client.js | 页面,作为 Loader 模块 | 控件、偏好读写、语言词条、兜底 shim |
index.js 注入一段 head 脚本,shim 因此在任何客户端模块之前安装,并在宿主首次挂载前应用记住的缩放值。client.js 在 window.__dshzs 存在时驱动它,不存在时才安装兜底 shim,同一个 rect 不会被除两次。
shim 换算什么
html { zoom } 之后,Chromium 在窗口像素里报告 rect、窗口尺寸和指针坐标,而 CSS 长度仍在布局像素里 —— 每个 position: fixed 浮层都会漂移。shim 把这些量除回去,大致覆盖:元素与 Range 的 rect、窗口与 VisualViewport 尺寸、滚动 API、指针与滚轮坐标、命中测试、SVG 屏幕矩阵、视口单位(vw/vh/vmin/vmax → calc(… / var(--dshzs-scale)))、媒体查询边界与 devicePixelRatio。每一步单独兜底:某个 API 缺失只退化一项行为,不会连带停掉整个缩放。
样式表覆盖
换算后的声明通过 --dshzs-scale 跟随缩放,所以换档时只需重新推导媒体查询边界,不会重扫样式表。新来的 CSS 由 MutationObserver、adoptedStyleSheets 的 setter、CSSStyleSheet.insertRule / replaceSync 以及捕获阶段的 load 监听收拢。
桌面窗口记忆
预留接口,未实装。 head 脚本会读 localStorage['dshzs:window'],在桌面壳使用的 dsh-app: 协议下用 resizeTo / moveTo 还原主窗口。本插件从不写这个键,所以这条分支目前不会生效 —— 它只是留给将来实装时用的契约。
负载格式为 CSS 像素(DIP)、屏幕坐标:
{ "x": 234, "y": 90, "w": 1440, "h": 900 }
只还原当前显示器工作区内的位置:saved.x / saved.y 相对 screen.availLeft / availTop 校验,位于其它显示器的位置会被丢弃,尺寸仍然生效。壳也可能有自己的最小尺寸约束。
现在就想要这个功能,请改装下面的插件:
| 插件 | 平台 | 说明 |
|---|---|---|
dsh-window-bounds | 全平台 | 页面侧 resizeTo / moveTo,逻辑像素;不还原最大化 |
dsh-window-state | 仅 Windows | 原生 user32.dll,能记住最大化;窗口会先以默认尺寸闪现一次 |
两者只装一个:键不同,但操作的是同一个窗口,谁后跑谁赢。装哪个都不需要改本插件 —— 窗口尺寸变化不需要钩子,vw / vh 已被改写成 calc(… / var(--dshzs-scale))。
安装
# 本地目录
dsh plugin add /path/to/dsh-zoom-scale
# 或安装打包产物
dsh plugin add ./dsh-zoom-scale-0.2.7.tgz
安装后重载 DSH(桌面应用建议重启),在 设置 → 通用设置 中即可看到「界面缩放」一行。
与其它 CSS / 插件共处
- 需要 DSH 0.1.7 及以上:head 脚本经
webserver/index-inject注入,0.1.7-rc.1 是查证过第一个提供该事件的发布;0.1.0–0.1.6 未验证。schemastery改为可选加载,所以只装本插件的干净 profile 也能启动(此时没有可配置的缩放项,种子保持 100 %)。 - 不要给根元素写
zoom:html { zoom }归 shim 所有,再写一条会覆盖它(或被它覆盖,取决于层叠顺序),换算随之错位;而后代元素上的zoom会与根缩放相乘,所以 shim 之外不要碰zoom。 - 不要用
transform: scale()做缩放:它会与根缩放相乘,创建新的包含块使position: fixed浮层改相对它定位(shim 修正不了),让getBoundingClientRect与换算结果不一致,而且文字是被拉伸而非重新栅格化。 - 不要写
--dshzs-scale:shim 每次换档都会重写它;写在<html>内联样式上反而会赢过 shim 的样式表,让所有换算长度失效。请读它,不要写它。 - 视口单位会被改写:样式表里的
100vh变成calc(100vh / var(--dshzs-scale, 1)),运行时经insertRule、replaceSync、adoptedStyleSheets插入的规则同样接管。内联style也会转换,但要等它被观察到,所以首帧就要准确的尺寸优先写成样式表规则。 - 颜色用
--dsw-*令牌:硬编码颜色不会跟随暗色主题。 - 判断当前缩放用
window.__dshzs?.get()(百分比)或html[data-dshzs](由 head shim 自己发布,100 % 时不存在)。不要读documentElement.style.zoom:shim 模式下 zoom 写在<style>里,只有降级路径才写内联;100 % 时那条样式表是空的、也没有data-dshzs,但这不代表插件没装。 - 不要再装一套 shim:
window.__dshzs只有一个持有者,重复包装同一批属性会让每个 rect 被除两次。要接管请调用它的set()。
变更记录
0.2.7(最新)
- 重构:
escapeScriptText移到lib/util.cjs以便单独测试;顺带补上「</script位于注入源码末尾」这一漏转义。 - 重构:持久化键与缩放范围收进
lib/zoom-constants.cjs;client.js是 IIFE、保留自己的字面量,由测试保证两边不漂移。 - 命名:
client.js的SCALE_KEY/SCALE_COOKIE/LOCALE_NAMESPACE,shim 的SCALE_PROPERTY/MEDIA_QUERY_STATE。 - 测试:
util(3)、字典 key 一致(1)、常量漂移(2)。
许可
MIT
Ähnliche Plugins
dsh-web (dsh-task-board)
zhu1090093659/dsh-web
dsh-web (dsh-web-all)
zhu1090093659/dsh-web
dsh-web-ui (dsh-task-board)
zhu1090093659/dsh-web-ui
dsh-TUI
ccch1mneyyy/dsh-tui