中文EN

dsh-composer-live

ui已测通过npmMIT

打 Markdown,边打边渲染——给 DeepSeek Harness(DSH)Web 输入框带来 Open WebUI 风格的实时编辑体验,代码块语法高亮、任务列表、格式工具栏、智能粘贴。

下载量 / Downloads
2,394
依赖体积 / node_modules
2.51 MB
测试时间 / Tested
2026-11-06
DSH 版本 / Version
0.2.2-rc.1

安装

dsh plugin --profile web add dsh-composer-live

沙箱测试结果

阶段结果
1 安装✓
2 列装✓
3 挂载✓
4 启动—

四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。

README

<p align="center"><img src="https://github.com/zeusxx/dsh-composer-live/raw/main/assets/icon-180.png" width="96" alt="dsh-composer-live 图标"></p>

<h1 align="center">dsh-composer-live</h1>

<p align="center"><b>打 Markdown,边打边渲染</b>——给 DeepSeek Harness(DSH)Web 输入框带来 Open WebUI 风格的实时编辑体验。</p>

<p align="center">[English](./README.md) · [简体中文](./README.zh-CN.md)</p>

<p align="center">

<img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT">

<img src="https://img.shields.io/badge/DSH-%3E%3D%200.1.5--rc.2-4c6ef5" alt="DSH >= 0.1.5-rc.2">

<img src="https://img.shields.io/badge/tests-206%20unit%20%C2%B7%20129%20E2E-2ea44f" alt="tests">

</p>

dsh-composer-live 把 DSH Web 的输入框变成 Open WebUI 风格的实时编辑器:你打 Markdown,它边打边渲染——加粗、斜体、带语法高亮的代码块、列表、引用、表格——而草稿本身始终是纯 Markdown 源文本,发送出去的就是你输入的原文。

它是一个纯浏览器端插件:零运行时依赖、不注入任何官方服务、不改官方源码。它在官方 0.1.5 Lexical 输入框之上叠加增强,不重复 DSH 已原生提供的功能。

找 DSH 0.1.x(textarea 架构输入框)的版本?那是 [dsh-composer-md](#faq)——本插件的前身,已停止维护。

截图

Markdown 实时渲染

代码块

选区浮动格式条

功能

Markdown 实时渲染

  • 行内样式边打边生效:加粗、斜体、` 行内代码 (品牌蓝胶囊)、~~删除线~~、[链接](url)(白名单协议)、![图片](url)` 胶囊。
  • 光标字符级精确对齐。标记字符(**、` `、~~、[]()`)淡化显示但保留精确宽度,粗体/标题用 paint-only 伪粗——渲染行与编辑器透明文字逐字符完全对齐,光标落在行内任何位置(包括格式区间内部)都精确贴齐,打字零漂移。
  • 任务列表项:- [ ] / - [x] 渲染成勾选胶囊;已完成项内容划线。
  • 草稿始终是纯 Markdown 源文本。渲染纯视觉——发送的消息就是你输入的源文本。

代码块

  • 输入 ``` 时按普通文本显示,直到围栏闭合——不会出现打一半就被渲染的残块。
  • 未闭合围栏行上按 Shift+Enter 自动补全封闭块(块内空行 + 闭合围栏 + 块后空行),光标落回块内,直接开写。
  • 已闭合块最后一个内容行按 ↓ 直接跳出,落到块后的普通行。
  • 零依赖正则语法高亮:js/ts/py/sh/json/yml/css/html,未标语言按内容自动推断——中文长文不会误判成代码。
  • 围栏行右上角语言标签;GitHub-dark / GitHub-light 两套块主题;围栏字符淡化。
  • 等宽:草稿含已闭合代码块期间,整个输入框(编辑器 + 渲染层)同步切换等宽字体栈(与官方代码字体同源)。中文字符刻意保持界面字体,两侧换行点永不发散。

列表、引用、表格

  • 列表行尾按 Enter 自动续项:无序列表保持符号(- * +)、有序列表递增编号(1. → 2.、3) → 4))、缩进保留。空列表项上按 Enter 退出列表——两次 Shift+Enter 结束一个列表。
  • > 引用行同样续项(>text 无空格也算);空引用项上按 Enter 退出。
  • Tab / Shift+Tab 缩进 / 反缩进两空格——单行或整块选区。光标在列表标记或行首空白处按 Tab 即嵌套子列表。Tab 全境拦截:焦点永远不会被切出输入框。
  • 表格首行(|列A|列B|,至少 2 列)行尾按 Enter 自动补 |---|---| 分隔行加一个空行,光标落空行。

工具栏与快捷键

  • 常驻格式工具栏(v0.2.14 起在输入卡外正上方):加粗 / 斜体 / 行内代码 / 链接 / 列表 / 代码块 / 展开。选中文字时包裹、未选中插入空标记;光标落在 … 内时加粗键自动点亮。工具栏是与输入卡等宽的独立细条,不占输入框内部高度,也永不与正文或图片附件重叠。
  • 选区浮动格式条(Open WebUI 形态):选中一段文字,加粗/斜体/代码/链接四键浮现在选区上方。
  • Ctrl+B / Ctrl+I / Ctrl+E 快捷加粗 / 斜体 / 行内代码——同时拦掉浏览器对 contenteditable 的原生加粗(那会悄悄往草稿里插入真正的 <b> 标签)。

粘贴处理

  • 大段粘贴(超过 8 行或 4KB)且内容像代码/日志时,自动用代码围栏包起来——单一撤销单元,配 toast 轻提示。中文长文不误判;光标已在代码块内或内容本身含围栏时不包。

Esc 分发、主题、兼容

  • Esc 按语境做对的事:官方候选菜单开着 → 归官方处理;展开态 → 收起;AI 生成中 → 停止生成。
  • 一键展开 70vh 长文写作模式。
  • 明暗主题自适应;输入法安全(拼音组字不闪烁);渲染按 rAF 合帧、增量进行。
  • @ 引用胶囊保持官方原样、可编辑。含胶囊的段落优雅降级为官方显示(胶囊宽度无法复刻,零错位优先)。热词文本装饰不受影响——/ 命令与技能名的引用装饰在渲染层沿用官方引用色,官方 hover 背景已禁用(它画在渲染层之上,会盖住文字)。
  • 顺带修复官方在图片附件在场时的两个定位问题:候选菜单悬空浮出输入框、工具栏盖住缩略图。

不与 DSH 0.1.5 重复

官方输入框已原生提供、本插件刻意不重做的:/ 命令菜单、@ 文件引用、粘贴图片/文件转附件、Enter 发送 / Shift+Enter 换行、输入法保护、草稿持久化。

速查表

按键 · 语境 · 行为

Enter · 普通行 · 发送(官方)

Shift+Enter · 普通行 · 换行(官方)

Enter / Shift+Enter · 列表 / 引用行尾 · 续标记(有序递增编号)

Enter / Shift+Enter · 空列表 / 空引用项 · 删标记,退出列表 / 引用

Enter / Shift+Enter · 未闭合围栏行 · 封闭代码块;光标落块内

Enter / Shift+Enter · 表格首行(≥ 2 列) · 补分隔行 + 空行

Tab · 代码块内 · 光标处插 2 空格

Tab · 列表/引用标记头或行首空白 · 行首缩进(嵌套列表)

Tab · 其他位置 · 光标处插 2 空格

Tab / Shift+Tab · 多行选区 · 整块缩进 / 反缩进

Shift+Tab · 任意行 · 行首反缩进最多 2 空格(无缩进时只吞按键)

Ctrl+B / Ctrl+I / Ctrl+E · 任意 · 包裹选中加粗 / 斜体 / 代码,或插入空标记

↓ · 已闭合块最后一个内容行 · 跳到块后

Esc · 菜单开着→官方 · 展开态→收起 · 生成中→停止 · 按语境分发

实测版本

每个版本发布前都在两个真实实例上跑完整 129 场景 E2E(覆盖两代支持的架构):

DSH 版本 · 状态

0.1.5-rc.2 · ✅ E2E 实测通过

0.2.0-rc.2 · ✅ E2E 实测通过

0.2.1-rc.5 · ✅ E2E 实测通过(主力环境)

环境要求

  • DSH ≥ 0.1.5-rc.2,web profile——本插件面向 0.1.5 的 Lexical contenteditable 输入框。
  • Chromium 系浏览器(Chrome、Edge 等):透明化技术依赖 -webkit-text-fill-color。
  • 与操作系统无关——纯 DOM/CSS,无原生依赖。

安装

# 从 npm 安装(推荐)
dsh plugin --profile web add dsh-composer-live

# 或从本地目录安装(file: 安装为物理拷贝)
dsh plugin --profile web add "file:/path/to/dsh-composer-live"

装完必须重启 web 实例。 插件按启动时快照加载,光刷新页面会新旧 bundle 并存。

跑的是隔离实例?用 DSH_HOME 指向它,插件就装进那个实例(否则装进默认的 ~/.dsh):

DSH_HOME=/path/to/your/.dsh dsh plugin --profile web add dsh-composer-live

使用

装上即全量生效——安装、重启、直接在输入框里打 Markdown。

典型工作流:

  • 代码块:输入 ``` `js ```,按 Shift+Enter——封闭块出现、光标在块内。写代码实时高亮;Tab 缩进两空格;最后一个内容行按 ↓ 跳出块后。
  • 列表:输入 - 项目,Shift+Enter 逐项续写;空项上再按一次 Shift+Enter 结束列表。Tab 嵌套,Shift+Tab 升回。
  • 长文写作:点展开键——输入框拉到 70vh;Esc 收起。
  • 贴日志:一大段代码或日志自动变成代码块;不想要就 Ctrl+Z。

工作原理

官方输入框是一个 Lexical contenteditable 编辑器。本插件用 -webkit-text-fill-color: transparent 把它的文字变透明(color 属性保留,所以光标和官方装饰照常工作),再绘制自己的渲染层——每个渲染字符都定位在编辑器文字的真实坐标上(逐字符测量 Range rect)。

渲染层从不自己排版,所以对齐类问题(漂移、抖动、错位)在架构上不存在:实测各场景偏差 ≤ 0.02px,连续打字逐帧偏差 0.00。

插件不注入任何官方服务。它直接读编辑器 DOM 推导「投影文本」(胶囊 → U+FFFC,<br>/段落边界 → 换行),对官方 client API 变化免疫;DOM 锚定用稳定的 data- 属性而非哈希过的 CSS Modules 类名。改动草稿的操作(列表续项、围栏补全、缩进……)走 Lexical 原生通道——保撤销栈的合成 beforeinput 事件——绝不直接改 DOM。

完整深读见 [docs/architecture.md](./docs/architecture.md)。

已知限制

  • 含 @ 胶囊的段落按官方纯文本显示(胶囊宽度无法复刻,零错位优先)。热词文本装饰不受影响。
  • 块级视觉(标题、引用、列表、表格标记)只上色/加粗/加背景——不改字号、行高、缩进;源文布局保留,行度量永不变化。
  • 只要草稿含已闭合代码块,整个输入框切等宽(不是逐行——字面 \n 单文本节点的草稿形态让逐行换字体物理不可行)。
  • 围栏补全的光标落位等 80ms(Lexical 异步提交);极慢机器上光标可能偶发落位偏后。
  • ↓ 跳出仅在已闭合块最后一个内容行触发;未闭合围栏走官方默认行为。
  • 「停止生成」按 aria-label 双语枚举匹配;官方改文案时请直接点按钮。
  • 仅 web profile;仅 Chromium 系浏览器。

开发

node test-live.cjs    # 206 项单测(纯函数,无需浏览器)
node e2e/run-e2e.mjs  # 129 场景 × 10 不变量的 E2E 套件(对着运行中的实例测)

E2E runner 要求被测实例已部署当

…(truncated)

以上内容来自 npm 上的 README,我们只做格式化,不改内容。

版本

npm 上共发布:11,最后更新 2026-11-01

链接

GitHub · Homepage · npm

同类插件