
Security News
Deno Goes the Way of the Dinosaur
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.
dsh-message-copy-enhance
Advanced tools
Copy dsh assistant output as Markdown, preserving links, LaTeX sources and code fences.
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.
DSH renders model output via dsh-client-ui-conversation → dsh-client-ui-primitives:
| Content | DOM shape | Recovery |
|---|---|---|
| Links | <a href="..."> | Take the href directly, output [label](url) |
| Inline / block LaTeX | KaTeX-rendered .katex / .katex-display | Retrieve the TeX source from the <annotation encoding="application/x-tex"> in the MathML branch, output $...$ / $$...$$ |
| Code blocks | .md-code-block (banner shows the language) + pre | Output a fenced code block; the language comes from the language-* class or the banner's infostring |
| Headings / emphasis / lists / quotes / tables | Standard HTML | Recovered 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:
.katex element (selecting in the middle of a formula still gets the complete source)Range.cloneContents()src/client/toMarkdown.ts, written in TypeScript, type-erased and inlined into the bundle)preventDefault() and write text/plain and text/markdownOther selections (user bubbles, tool cards, plain text) and empty selections are completely unaffected; if conversion fails, the default copy behavior is restored automatically.
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
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
Releases are driven by release-it with a Conventional Commits changelog. Run from the main branch with a clean working tree:
pnpm release
It is interactive: first the commits since the last tag are shown as a changelog preview (grouped by type, including the conventional-commits recommended version), then you pick the next version from a prompt (patch / minor / major / pre-release variants / custom). What happens, in order:
npm run check:release): version is valid SemVer, the version is not already published on npm (or there are new commits since its tag), GITHUB_TOKEN is set, npm is authenticated; then typecheck and the test suite run.feat → minor, fix/perf/revert → patch, breaking changes → major).CHANGELOG.md is regenerated from the commits since the last tag, under the chosen version.npm run build (the DSH module-loader client bundle).chore(release): vX.Y.Z, tag vX.Y.Z, push to GitHub, create a GitHub Release (release notes from the changelog), then npm publish.Prerequisites:
GITHUB_PAT_TOKEN exported (a GitHub PAT — a classic token with repo scope, or a fine-grained token with Contents: Read and write on this repo; gh auth token also works; GITHUB_TOKEN is accepted as a fallback), and npm login. The collaborator pre-check is skipped (github.skipChecks), since fine-grained tokens get a 403 on that endpoint; GitHub still enforces the real permissions when the release is created.Useful variants:
pnpm release:dry # dry-run: previews everything without changing anything
pnpm release -- --increment=patch # skip the prompt and force a patch bump (or minor/major)
pnpm release -- --ci # fully non-interactive (for CI; falls back to a patch bump)
Note: if a CI environment variable is set, release-it automatically switches to non-interactive mode.
dsh plugin --profile desktop add dsh-message-copy-enhance
dsh plugin --profile desktop add dsh-message-copy-enhance@latest
This package is pre-1.0, and a caret range like ^0.1.0 covers patch releases only (0.1.x) — a minor bump (0.1 → 0.2) falls outside the range, so dsh plugin update will not pick it up. Upgrade explicitly with @latest (or @<version>).
Select content in any model answer and press Ctrl/Cmd+C, then paste into Typora / Obsidian / VS Code / any markdown editor to get the full markdown.
file:, relative links) have no href to begin with and cannot be recovered..katex-error (KaTeX render failure) are output as $source$.| is escaped.MIT — Copyright (c) 2026 Asianfleet
FAQs
Copy dsh assistant output as Markdown, preserving links, LaTeX sources and code fences.
We found that dsh-message-copy-enhance demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.

Security News
Anthropic’s free OSS Scanner uses Mythos and other Claude models to find open source vulnerabilities and send maintainers reports with proposed fixes.

Security News
On Front Lines’ Early Adopters: CISO podcast, Andrew Becherer shares lessons from Datadog, weighs the long-term costs of AI-built tools, and explains how founders can actually gain a CISO’s trust.