DSH Plugins Marketplace

DSH Plugins

Plugins

/

UI & Experience

/

dsh-mermaid

d

dsh-mermaid

Manifest valid

Renders mermaid code blocks in dsh web chat as diagrams. Each block gets a toggle in its header to switch between the diagram and the source; blocks still streaming stay as code until the message sett

UI (client)hasBundlePatch

dsh-mermaid

A DeepSeek Harness (DSH) web GUI plugin that renders ```mermaid code fences in chat messages as diagrams.

  • Settled mermaid fences show the diagram inside the stock code-block card. A toggle button in the card header ("Show code" / "Show diagram") switches between the diagram and its source. The Copy button still copies the source.
  • Fences that are still streaming stay as plain code until the message settles.
  • Diagrams re-render when DSH switches between light and dark (document.documentElement.style.colorScheme).
  • If a diagram has a syntax error, the code stays visible with a muted Mermaid: <error> line under it.
  • mermaid (v12, securityLevel: 'strict') lives in a lazy chunk, lib/client.mermaid.js, so it loads only after the first mermaid fence appears. Page boot loads only the small lib/client.js.

Install

The package is a DSH bundle: package.json declares dsh.bundle.patch (./cordis.patch.yml, which inserts the ui-mermaid row) and dsh.client (the web half). Install it into a web profile with dsh plugin add, then restart dsh web:

# prebuilt tarball from a GitHub release (no build step)
dsh plugin --profile web add https://github.com/jakehemmerle/dsh-mermaid/releases/download/v0.1.0-rc.1/dsh-mermaid-0.1.0-rc.1.tgz
# or a local checkout, after building it
pnpm install && pnpm build
dsh plugin --profile web add link:/path/to/dsh-mermaid

dsh plugin add records the package as a profile dependency and appends it to dsh.profile.bundles; dsh --profile web --dump-config then shows one id: ui-mermaid row with name: dsh-mermaid. Remove it with dsh plugin --profile web remove dsh-mermaid.

Without the bundle, add the row to the profile patch yourself (for example ~/.dsh/profiles/web/cordis.patch.yml; this is how nix-config installs it). The name must then be the absolute path to the Node entry file; a directory path fails with ERR_UNSUPPORTED_DIR_IMPORT. Use one way or the other, not both, or the profile composes two ui-mermaid rows.

- insert:
    - id: ui-mermaid
      name: /path/to/dsh-mermaid/lib/index.js

Disabling the plugin removes its observers, injected nodes, <style> element and data attributes.

How it detects mermaid fences

DSH renders every fence through a React CodeBlock component with root div.md-code-block. For mermaid the visible label is the generic "Code block", so the language is not in the DOM. The plugin reads it from React's fiber props instead: it takes the element's __reactFiber$… fiber, walks up at most 4 levels, and uses the first memoizedProps that has string code and lang fields (src/fiber.ts). The same props carry streaming. When a message settles, the DOM may not change at all, so a MutationObserver can miss it. While any mermaid block is still streaming, the plugin also rescans every 500 ms.

A DOM node keeps the fiber it was created with. After every other commit, that fiber is the stale alternate. So the plugin reads the props chain of both the fiber and its alternate. It keeps the props whose code matches the text React rendered into [data-code-block-content] code, and if both match, it prefers the settled one.

The per-block logic is a pure state machine in src/fence.ts. Its states are waiting, rendering, rendered and failed. It is idempotent per (code, theme), and it drops stale render completions.

Development

pnpm build        # esbuild -> lib/client.js + lib/client.mermaid.js (module-loader wrapped CJS)
pnpm typecheck
pnpm test         # all tests
pnpm test:unit    # fast-check properties of the pure core
pnpm test:e2e     # real clients: shipped bundles in Chromium + Playwright campaigns on real `dsh web` + dsh-TUI inertness

The real-client suites run against a real dsh web and a real dsh-TUI on the vendored rig (test/rig/): every run gets its own private HOME/DSH_HOME, free port and private tmux socket, and the only model is the local mock (test/rig/mock-llm.mjs). Nothing reads a live ~/.dsh or ~/.dsh-tui; set DSH_BIN, DSH_ROOT, DSH_TUI_DIR and PLAYWRIGHT_BROWSERS_PATH to pinned store builds (see flake.nix's devShell) and run the suites via nix develop. MMD_INSTALL picks how the web and TUI suites install the plugin (test/install.ts): row (default, an explicit lib/index.js row as nix-config writes it), link (dsh plugin add link:<checkout>) or tarball (dsh plugin add of the pnpm pack output).

  • test/web/bundle-install.e2e.test.ts — dsh plugin add of the checkout and of the packed tarball: one composed ui-mermaid row, one bundle entry (also after a repeated add), and a rendered, visible diagram whose arrowhead resolves.
  • test/web/mermaid.web.property.test.ts — fast-check generated action sequences (send / held send / toggle / theme / reload) against the real web client, invariants checked after every step; replay with NUM_RUNS, FC_SEED, FC_PATH.
  • test/web/streaming.e2e.test.ts — paced-chunk streaming: the fence stays plain code while the turn streams, then renders once after settle; prints RELEASE_TO_DIAGRAM_MS=….
  • test/web/duplicate-ids.test.ts — two identical fences get distinct SVG element ids.
  • test/render.property.test.ts, test/client.dispose.test.ts — the shipped lazy chunk and browser bundle in headless Chromium (render properties incl. hostile labels; dispose restores the DOM and stops reacting).
  • test/tui/mermaid.tui.inertness.test.ts — the plugin is web-only; on a real dsh-TUI the row composes, loads without warnings and full turns render byte-identically to a TUI without the plugin.
  • test/contract/dsh-seam.contract.test.ts — pins the DSH seams (CodeBlock props, banner, fiber keying, module loader) against the exact DSH_ROOT build.

Suites write screenshots to test/artifacts/ on failure.

Nix

The flake builds the plugin for x86_64-linux, aarch64-linux and aarch64-darwin. packages.<system>.default contains lib/, package.json and cordis.patch.yml. Its build runs tsc --noEmit and the unit vitest project, and checks.<system>.default is the same package.

nix build github:jakehemmerle/dsh-mermaid   # result/lib/index.js
nix flake check -L

As a flake input, use ${dsh-mermaid.packages.${system}.default}/lib/index.js as the name in the profile patch row above. After a pnpm-lock.yaml change, update hash in nix/package.nix with the value Nix reports.

CI (.github/workflows/nix.yml) runs nix flake check -L on Linux and macOS runners, so the package build with its tsc + unit checks and the DSH-seam contract check is exercised on both OSes. The real-client web/TUI suites need the pinned dsh web, dsh-TUI and Nix Chromium of the flake devShell, so they run locally or in the repo environment (nix run .#e2e).

Limitations

  • The plugin depends on DSH CodeBlock internals: the .md-code-block, [data-code-block-banner] and [data-code-block-content] hooks, and the React fiber props { code, lang, streaming }. If DSH changes them, the plugin finds no fences and you see the stock code block. Nothing breaks.
  • The diagram replaces the code view only visually. React still owns and renders the code block. The plugin adds a single container as the last child of the card and a single button in the header actions.
  • lib/client.mermaid.js is about 5 MB (about 1.5 MB gzipped), because the full mermaid build is bundled, including elk/cytoscape/katex. It loads once, on demand.

Comments

Loading…

Similar plugins

dsh-mermaid-plugin

by shinelon

Render mermaid code blocks in DSH chat as diagrams - 在 DSH 聊天中将 mermaid 代码块渲染为图形

UI & ExperienceManifest valid

★ 0

MIT

JavaScript

Sep 28, 2026

dsh plugin --profile web add @local/mermaid-chat

Mermaid diagram renderer for the Web UI conversation: renders mermaid code blocks into interactive cards (zoom, fit-width, fullscreen viewer, preview/code toggle) with official UI primitives, and keep

Tools & CapabilitiesDevelopment & InfrastructureManifest valid

★ 0

↓ 204/wk

dsh plugin --profile web add dsh-mermaid-render

by baconbao

Preview Mermaid diagrams as images via local rendering in DSH Web when the chat message contains a Mermaid fenced code block, and also allow integration with external rendering servers.

Tools & CapabilitiesDevelopment & InfrastructureTerminal & ClientsManifest valid

★ 4

MIT

JavaScript

Oct 3, 2026

dsh plugin --profile web add @baconbao/dsh-mermaid-image-preview

Renders mermaid code blocks in the chat as diagrams in place (flowchart, sequence, class, state, ER, gantt, pie), with zoom, source toggle, copy PNG and SVG download.

UI & ExperienceManifest valid

★ 0

dsh plugin --profile web add @dsh-local/dsh-diagram

by XiaoBinGan

Render settled ```mermaid fences in the dsh Web GUI chat as SVG diagrams — hardened output, source toggle, and a code-block fallback that never loses the source.

Manifest valid

★ 0

MIT

JavaScript

Sep 23, 2026

dsh plugin --profile web add dsh-mermaid-fence

by kjx-talesofai

Draws mermaid code blocks in DSH replies as diagrams, including while the reply is still streaming.

Manifest valid

★ 0

MIT

JavaScript

Oct 18, 2026

dsh plugin --profile web add dsh-plugin-mermaid