dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
将 DSH 设置界面归一为同一套设计语言:统一各设置页的排版、卡片、控件、焦点与动效,包括其他插件贡献的页面。
One design language for the DSH settings surface.
DSH's settings are composed from many plugins, and each page historically speaks a slightly different typography and surface language — page titles in 16/18/22px, explanations in 12/13/14px, cards with 8/10/12px radii, controls with their own heights and focus styles.
dsh-settings-beautify normalizes every settings page onto a single design language:
--dsw-* tokens, so light / dark / system themes keep working.prefers-reduced-motion and can be turned off.data-dshb-scan), and the DOM normalizer handles the rest.localStorage.It works without touching DSH's source: the plugin observes the settings
panel, marks each structural role with a stable data-dshb-* attribute (the
built-in class names are build-hashed and can't be relied on), and a scoped
stylesheet applies the language on top.
| Surface | Built in |
|---|---|
| Settings shell (nav rail, header, close, scrollbars) | ✅ |
| 通用 General — every preference row (language, appearance, font size, Enter behavior, agent presets, permissions, …) | ✅ |
| 模型 Models | ✅ |
| 智能体预设 Agent presets | ✅ |
| 内置插件 Built-in plugins (search, scope groups, catalog) | ✅ |
| Agent 预设 Agent presets (group headings, preset cards, tags) | ✅ |
Any third-party page that adds data-dshb-scan to its root (e.g. an archived-conversations page) | ✅ |
dsh-settings-beautify follows the DSH community-market package contract
(dsh.bundle.patch + dsh.client manifest), so it can be installed from the
market or with:
dsh plugin --profile <profile> add dsh-settings-beautify
pnpm add dsh-settings-beautify # into the profile's package set
# and ensure the bundle entry is declared, e.g. via the profile patch:
# - insert:
# - id: dsh-settings-beautify
# name: dsh-settings-beautify
After install, restart DSH Desktop (or reload the web window). The design language is applied automatically — nothing is added to the settings nav rail.
The plugin has no settings page of its own. Preferences are read from the
browser's localStorage under dsh-settings-beautify:prefs:
| Key | Values | Effect |
|---|---|---|
enabled | true / false | Apply the language or restore DSH's original look. |
density | compact / default / comfortable | Row and list spacing. |
motion | true / false | Card hover micro-motion. prefers-reduced-motion always wins. |
Defaults: {"enabled": true, "density": "default", "motion": true}. To tune
them, open the browser console and run:
window.DSHB.setPrefs({ density: "compact" }) // or { enabled: false }, { motion: false }
No host files or settings namespaces are touched.
The full specification — tokens, hierarchy, spacing/radius/motion scale, and
the data-dshb-* attribute contract — lives in
docs/DESIGN.md. A condensed version:
| Role | Font | Color |
|---|---|---|
| Page title (页面标题) | 18px / 600 / 26px | --dsw-alias-label-primary |
| Page explanation (页面解释) | 13px / 400 / 20px | --dsw-alias-label-tertiary |
| Group title (组标题) | 14px / 600 / 22px | --dsw-alias-label-primary |
| Item title (条目标题) | 14px / 500 / 22px | --dsw-alias-label-primary |
| Item description (条目解释) | 13px / 400 / 20px | --dsw-alias-label-tertiary |
| Body (正文) | 14px / 400 / 22px | --dsw-alias-label-primary |
| Caption (辅助文字) | 12px / 400 / 18px | --dsw-alias-label-tertiary |
Cards: 12px radius · --dsw-alias-border-l2 · --dsw-alias-bg-layer-3 (elevated over the panel).
Controls: 8px radius, 36px min-height, brand focus ring. The title → caption
gap is a uniform 4px everywhere the language applies (--dshb-gap-title-desc,
matching DSH's row convention). Radii are tokenized (--dshb-*) so a future
version can offer alternate palettes.
The DOM normalizer auto-tags the built-in pages. For your plugin's page, either:
data-dshb-scan to the page root (a third-party section hosted
inside the settings dialog works the same way) — the normalizer then
applies the same heading/prose/card/row/control rules generically,
including the uniform 4px title → caption gap; ordata-dshb-page-title,
data-dshb-item-title, data-dshb-card, …) for full control.See the extensibility contract.
The plugin is intentionally headless: it only restyles the settings surface. If you would rather have a visible control page, that is a small follow-up change — open an issue and it can be added behind a preference.
pnpm install
pnpm check # syntax checks
pnpm test # fixture-driven jsdom tests (135 assertions)
pnpm sync-styles # regenerate lib/styles/settings.css from lib/client.js
pnpm capture-fixtures # re-record test/fixtures/ from a running DSH Desktop
The tests do not hand-write a stand-in DOM. test/fixtures/<version>.json is
captured from a running DSH Desktop — the settings panel's markup and the
stylesheets the host injects — and test/cascade.mjs recomputes the cascade in
jsdom (specificity, inheritance, var() substitution, the shorthands the tagger
reads). Every heuristic is therefore exercised against the computed styles the
real build produces, not against inline styles that would silently stop
matching it.
After a DSH upgrade: pnpm capture-fixtures, run pnpm test, and fix what the
new surface broke. The fixture is committed, so a regression is reproducible
offline without a browser.
nav / content / header / options /
[data-slot="settings.section"]), but every page below it was re-laid out —
cards moved from 12px to 20px radius, the plugin-market page is gone
(replaced by a searchable built-in plugin inventory), the DSH Desktop
settings page no longer contributes a settings section, the header gained a
second button, and tag/chip labels became a shared _tag_* primitive.
0.3.0 removed the selectors that no longer exist and taught the tagger the
new shapes (a preference row is now detected by its divider + padding, cards
by their border box, chip labels by their pill radius).@deepseek-ai/dsh-typert-protocol
stopped exporting TypertRemoteFailure in 0.1.2-rc.1) — one failing
plugin import can take down the entire profile plugin tree and with it
this plugin. The tagger is defensive: anything it cannot recognize is
simply left untouched.No network requests, no host APIs, no file access, no remote code. Preferences
live in localStorage. See SECURITY.md.
MIT — see LICENSE.