DSH Hub

Asianfleet/dsh-message-copy-enhance

dsh-message-copy-enhance

UIWeb UI0 GitHub stars· updated 2026-08-19

Copy dsh assistant output as Markdown, preserving links, LaTeX sources and code fences.

Install

npx @deepseek-ai/dsh plugin --profile desktop add dsh-message-copy-enhance

Restart `dsh web` after install. Bundle APIs can change during the developer preview.

README badge

dsh-message-copy-enhance DSH Hub badge
[![DSH Hub](https://dshhub.dev/badge/dsh-message-copy-enhance.svg)](https://dshhub.dev/plugins/dsh-message-copy-enhance)

Paste this into your README. The star count updates with every catalog sync.

From the README

Excerpt from Asianfleet/dsh-message-copy-enhance, cleaned of badges and images.

dsh-message-copy-enhance

English · 中文

A DeepSeek Harness client UI plugin: when you select text in a model message and copy it, the clipboard content is rewritten to Markdown, so links, LaTeX source, code-fence language info, and more are no longer lost.

How it works

DSH renders model output via dsh-client-ui-conversationdsh-client-ui-primitives:

ContentDOM shapeRecovery
Links<a href="...">Take the href directly, output [label](url)
Inline / block LaTeXKaTeX-rendered .katex / .katex-displayRetrieve the TeX source from the <annotation encoding="application/x-tex"> in the MathML branch, output $...$ / $$...$$
Code blocks.md-code-block (banner shows the language) + preOutput a fenced code block; the language comes from the language-* class or the banner's infostring
Headings / emphasis / lists / quotes / tablesStandard HTMLRecovered as GFM

The plugin listens for copy on document in the capture phase, and takes over only when the selection starts inside a [data-chat-flow-kind="assistant"] message and contains markdown-significant elements:

  1. Expand the selection to the full .katex element (selecting in the middle of a formula still gets the complete source)
  2. Clone the selection DOM with Range.cloneContents()
  3. Recover the markdown with the built-in zero-dependency DOM→Markdown converter (src/client/toMarkdown.ts, written in TypeScript, type-erased and inlined into the bundle)
  4. preventDefault() and write text/plain and text/markdown

Other selections (user bubbles, tool cards, plain text) and empty selections are completely unaffected; if conversion fails, the default copy behavior is restored automatically.

Project structure

dsh-message-copy-enhance/
├── package.json            # dsh.client metadata (client plugin declaration)
├── tsconfig.json           # typecheck config (strict, includes src/test/vite.config.ts)
├── vite.config.ts          # vite build (DSH module-loader output) + vitest config
├── src/client/
│   ├── index.ts            # plugin entry: copy interception + apply/inject (TS, apply(ctx) uses the official
│   │                       #   @deepseek-ai/cordis Context type, same as dsh-client-ui-*)
│   └── toMarkdown.ts       # DOM→Markdown converter (TS, zero dependencies)
├── lib/
│   ├── index.js            # Host-side no-op plugin (JS entry loaded by the DSH Loader)
│   └── index.d.ts          # type declarations for the host entry
├── dist/client.js          # build artifact (pre-generated)
└── test/                   # vitest (.test.ts): converter / bundle / package layout

Build & test

npm install           # dev deps: typescript / vite / vitest / @types/node / linkedom / @deepseek-ai/cordis (official types)
npm run typecheck     # tsc -p tsconfig.json — full type check (strict)
npm run build         # vite build — bundle src/client into dist/client.js in the DSH module-loader format
npm test              # vitest run — 36 cases (converter / real bundle / package layout)
npm run test:watch    # vitest — watch mode
npm run test:coverage # vitest run --coverage — v8 coverage report

Release

Releases are driven by release-it with a Conventional Commits changelog. Run from the main branch with a clean working tree:

pnpm release

Related plugins