dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
在文档预览中渲染 Jupyter 笔记本,支持代码语法高亮、离线 KaTeX 行内与块级公式,以及可缩放的图像查看器。
A DeepSeek Harness plugin that renders Jupyter notebooks in the document preview pane: syntax-highlighted code, real LaTeX, and zoomable figures — instead of raw JSON.
Without it, opening a .ipynb in DSH shows its JSON source. With it, the file
opens as a notebook.
| Feature | Notes |
|---|---|
| Syntax highlighting | Python, JavaScript/TypeScript, JSON, Bash, and INI, with per-language grammars |
| LaTeX math | Vendored KaTeX, so it works offline; inline $…$ and display $$…$$, including inside tables and lists |
| Markdown subset | Headings, lists, tables with column alignment, blockquotes, task lists, fenced code, links, bold and italic, code spans |
| Figure zoom | Click any output figure to open it, then scroll or + / − to zoom continuously, drag to pan, 0 to fit |
| Save figures | Names each figure after the notebook, e.g. sample-notebook-cell3-out1.png |
| Outputs | Streams, display_data, execute_result, and error tracebacks with ANSI escapes stripped |
Everything is self-contained: the KaTeX engine and its web fonts are inlined into the client bundle, so no request leaves your machine.
dsh plugin --profile <your-profile> add dsh-ipynb-preview
Then restart DSH. The plugin is a client-side renderer, so it needs a restart rather than a page refresh: the shell computes its client bundle revision at startup.
To install from a checkout or a git URL instead:
dsh plugin --profile <your-profile> add ./dsh-ipynb-preview
dsh plugin --profile <your-profile> add github:WuShichao/dsh-ipynb-preview
The git form makes pnpm ask for permission to run this package's prepare
script, because pnpm >= 10 refuses a git dependency's install-time script until
it is allowlisted. The built lib/client.js is committed, and the npm package
ships it too, so neither a tarball nor a registry install asks for anything.
DSH discovers the package through the profile's bundle list, reads dsh.client
from this manifest, and serves lib/client.js to the browser as part of the
client roster. That bundle registers a document-preview renderer for the ipynb
extension:
lib/index.js host half; deliberately empty, the plugin is browser-only
lib/client.template.js the editable client source, with two KaTeX placeholders
lib/client.js the generated artifact the shell serves
cordis.patch.yml the bundle layer that inserts the plugin row
tools/build-client.mjs generates lib/client.js from the template
lib/client.js is generated, not hand-edited. Change lib/client.template.js
and run npm run build.
pnpm install # installs KaTeX (build), React (tests)
pnpm run build # regenerate lib/client.js
pnpm test # build, then the verifier, the bundle lint, and the mount harness
The repository ships a pnpm-lock.yaml, and pnpm is what the DSH CLI itself uses
to install plugins, so CI installs with pnpm install --frozen-lockfile. npm and
yarn also work: every script is a plain node invocation rather than a chained
npm run, so no script depends on which package manager started it.
pnpm test runs three suites, all offline:
tests/verify.mjs — materializes the bundle the way the shell's module
loader does, then checks the manifest contract, the registrations, the
highlighter, the math renderer, the Markdown subset, the zoom arithmetic, the
stylesheet, and a full render of the fixture notebook. Around 170 assertions.tests/lint-bundle.mjs — sweeps both the template and the built bundle for
identifiers that are referenced but never declared. A free variable makes the
factory throw while the shell materializes it, and the whole client roster then
fails to load — a blank window that node --check cannot detect.tests/mount.mjs — mounts the plugin against a DOM stub so effects and
event wiring actually run, and asserts the notebook tree survives opening the
lightbox.The fixture notebook is generated by tests/make-fixture.mjs, and the assertions
read their expected counts from that fixture, so the input and the expectation
cannot drift apart.
React's synthetic event system does not work against a hand-written DOM stub, so the controls' click handlers are verified in a real browser instead:
node tests/make-page.mjs # writes test-page.html at the repo root
node tests/make-page.mjs out.html # or choose the output path
Open the page, click Open the lightbox, and press every control; each
interaction, the zoom readout, and any error is written to the log at the top of
the page. Append ?auto=1 to the URL and the page drives itself, which is how a
headless run reads the result back:
msedge --headless=new --virtual-time-budget=15000 --dump-dom \
"file:///path/to/test-page.html?auto=1"
That page also hit-tests every control with document.elementFromPoint, which is
how a stacking-order bug was found: a fixed application header with a higher
z-index than the lightbox covered the middle of the toolbar, so only its edges
responded to a click.
Two things this plugin learned the hard way, both now covered by assertions:
z-index above every host layer. 9999 is not
enough: application chrome is often a fixed header with its own stacking
context, and it will silently swallow clicks aimed at your controls.MIT — see LICENSE. KaTeX is bundled under its own MIT license; see THIRD_PARTY_NOTICES.md.
Published to npm by @nightwingng.