DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

Cieux /

Cieux/dsh-zoom-scale

Verified

Interface zoom for DeepSeek Harness (DSH): a complete page-zoom shim (rects, viewport units, media queries and pointer math converted), with Ctrl+wheel, a session-header stepper and a settings row.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@8adb80a9

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) + wheel
    • Ctrl/⌘ + =, -, 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.6.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. schemastery is 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 zoom on the root. The shim owns html { zoom }; a second html declaration overwrites it (or is overwritten, depending on cascade order) and desynchronises every conversion. zoom on a descendant multiplies with the root zoom, so leave zoom alone outside the shim.
  • Do not use transform: scale() to zoom. It multiplies with the root zoom, creates a containing block that re-anchors position: fixed overlays (the shim cannot correct that), makes getBoundingClientRect disagree 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, replaceSync and adoptedStyleSheets. Inline style attributes 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() or html[data-dshzs] (published by the head shim itself, absent at 100 %). Do not read documentElement.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 and data-dshzs is absent — that does not mean the plugin is missing.
  • Do not install a second shim. window.__dshzs has one owner; wrapping the same properties again divides every rect twice. Drive the existing object with set().

Changelog

0.2.6 (latest)
  • Fix: schemastery is resolved optionally instead of through a top-level import. A profile that carries only this plugin has no schemastery (it is a host-internal peer dependency), so the previous import made the whole plugin fail to load there; without it the configurable scale is absent and the seed stays at 100 %.
  • Manifest: engines.dsh is now >=0.1.7-rc.1 — the first release whose published packages provide webserver/index-inject; 0.1.0–0.1.6 were not tested.
0.2.5
  • Fix: when the fallback had written zoom inline and the head shim took over later, that inline value stayed and outranked the shim's stylesheet — every later scale change moved --dshzs-scale while the painted zoom stayed at the old value. The hand-over now gives the property back.
  • Fix: a seed the host could not resolve (Config.scale is volatile, typed number | undefined) or a stray non-finite set() call no longer reaches the arithmetic as zoom: NaN; both fall back to 100 %.
  • Manifest: engines.dsh states the minimum DSH (>=0.2.1-rc.3), because the head script depends on webserver/index-inject, and the bundled patch id is now dsh-zoom-scale instead of zoom.
  • Accessibility: the header percentage button announces the current value and the reset action (Current scale 125%; activate to reset to 100%) instead of only "Reset to 100%".
  • Cleanup: unloading the plugin disposes the head shim, reverting every patched prototype instead of leaving them behind.
  • Contract: html[data-dshzs] is published by the shim's set() on every change, so it exists as soon as the head script runs instead of waiting for the client module.
  • Performance: the native MediaQueryList for a scaled query is reused through a bounded cache, matchMedia lists are swept on GC, and currentCSSZoom answers a detached element without a layout query.

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.6.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.6(最新)
  • 修复:schemastery 改为可选解析,不再是顶层 import。只装本插件的 profile 里没有它(它是宿主内部的 peer 依赖),原来的 import 会让整个插件加载失败;缺省时没有可配置的缩放项,种子保持 100 %。
  • 清单:engines.dsh 放宽为 >=0.1.7-rc.1 —— 查证过第一个提供 webserver/index-inject 的发布;0.1.0–0.1.6 未验证。
0.2.5
  • 修复:兜底 shim 写过内联 zoom、head shim 稍后接管时,那个内联值会留下并压过 shim 的样式表 —— 之后每次换档只改 --dshzs-scale,绘制的 zoom 停在原值。交接时现在会把该属性归还。
  • 修复:宿主解析不到的种子(Config.scale 是 volatile,类型为 number | undefined)或页面代码传入的非有限值,不再以 zoom: NaN 进入运算,两者都回落到 100 %。
  • 清单:engines.dsh 声明最低 DSH 版本(>=0.2.1-rc.3)——head 脚本依赖 webserver/index-inject;patch 里的 id 从 zoom 改为 dsh-zoom-scale。
  • 无障碍:头部百分比按钮会播报当前值与重置动作(「当前缩放 125%,按下重置为 100%」),不再只读「重置为 100%」。
  • 清理:卸载插件时销毁 head shim,把每个被 patch 的原型都还原,不再留在页面里。
  • 契约:html[data-dshzs] 由 shim 的 set() 在每次变更时发布,head 脚本一执行就存在,不再等客户端模块。
  • 性能:缩放后的原生 MediaQueryList 按查询串复用(有界缓存);matchMedia 列表在 GC 后自动清理;currentCSSZoom 对未挂载元素不再触发布局查询。

许可

MIT

—/ 5

No ratings yet

Verified DSH bundle

Commit 8adb80a9615c

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout