dsh-composer-markdown
Markdown editing aids for the DSH web composer: ordered and unordered list continuation with continuous renumbering, Tab-nested list levels, inline-code styling, and code-fence auto-closing, with the sent draft kept as literal Markdown.
Install
dsh plugin --profile web add dsh-composer-markdown
Sandbox test
This plugin has not been tested yet. Submit a test →
README
dsh-composer-markdown
[English](./README.md) · npm · GitHub
一句话简介:DSH(DeepSeek Harness)Web 纯客户端插件,为对话输入框(composer)提供 Markdown 编辑增强 —— 列表自动续行与序号规整、行内代码样式(反引号渲染后隐藏)、代码块围栏自动闭合与原子化交互。所有编辑手势做在 Shift+Enter 上;Enter 保持 DSH 原生「直接发送」语义,从不拦截。除「有序列表序号规整」外一切只作用于编辑态视觉与按键,发送文本始终保持字面 Markdown、逐字节保真。
- 平台:web(DSH Web GUI,
dsh plugin --profile web) - 形态:纯客户端插件 —— host 半为空操作载体,零运行时依赖,可在「设置 → 插件」中随时开关
- 测试:475 个断言全部通过(零依赖测试器:产物新鲜度 + 纯逻辑单测 + bundle 形状断言 + 可选宿主契约冒烟)
- 许可:MIT
目录
- [用途与适用场景](#用途与适用场景)
- [功能一览](#功能一览)
- [安装](#安装)
- [使用](#使用)
- [技术架构](#技术架构)
- [兼容性](#兼容性)
- [已知限制](#已知限制)
- [开发须知与规范](#开发须知与规范)
用途与适用场景
DSH 的 composer 是一个 Lexical 纯文本编辑器,原生只提供「Enter 发送 / Shift+Enter 软换行」——写 Markdown 全靠手敲字面字符。本插件把输入框的 Markdown 编辑体验补齐到成熟聊天产品的水平:
- 在输入框里写结构化内容:列表、步骤、代码片段、代码块,不用离开键盘去点工具栏;
- 让字面 Markdown 变得可读:
•圆点标记、等宽序号、行内代码底色、成对的 ``````` 渲染成一个真正的代码块 —— 所见接近发送后消息的渲染效果; - 保住「纯文本」的契约:一切增强都是编辑态视觉层,发出的就是你敲的字面 Markdown,逐字节一致 —— 模型侧、消息渲染侧、剪贴板投影完全不受影响;
- 不改变任何原生习惯:Enter 照常发送,
/、@菜单、@xxx引用 chip、图像粘贴、IME 中文输入全部照旧。
不适用:需要富文本(非 Markdown)编辑、或希望在发送阶段改写/美化 Markdown 语法的场景 —— 本插件刻意不做任何发送态变换。
功能一览
你输入 编辑态呈现 发送文本
─────────────────────────────────────────────────────────────────────
- 苹果 • 苹果 (圆点标记) - 苹果
⇧↵ (Shift+Enter) - ␣ (下一行自动带前缀) …
1. 第一步 1. 第一步 (等宽序号) 1. 第一步
⇧↵ 2. ␣ (自动递增,组内恒连续) …
`code` code (等宽+底色,反引号隐藏) `code`
│ ts 徽标 │ (空行)
│ ␣ (光标在此) │ ```
└─────────────────┘
按功能域: | 域 | 能力 | |---|---| | **列表** | 无序/有序续行(任意视觉行与任意嵌套深度,含软换行与多行粘贴行)、光标处截断续行、空项退出、组内序号恒连续(删行接上/隔断重起/合并累加/嵌套感知)、中间插入整体顺延、**层级缩进阶梯(Tab 降级 / Shift+Tab 或前缀后 Backspace 升级,整棵子树递归联动,顶层取消列表回归普通文本;降级上限 = 父级下一级,不可无限降级)**、前缀原子删除(缩进并入原子)、方向键原子跨越(含缩进)、原子内部不可停留、标记差异化渲染(`• ` 圆点 / 等宽序号) | | **行内代码** | 成对反引号内部文本呈行内代码样式、反引号闭合瞬间隐藏(零步进隐形,保留字体度量)、选区覆盖时显形(所选即所见) | | **代码块** | ```` ``` ```` / ```` ```ts ```` + Shift+Enter 自动闭合骨架、行首敲 ```` ``` ```` 的保留内容流、成对提交制渲染(整块代码观感 + 语言徽标浮层 + 标记行零高度)、块边界一次解包(去围栏保正文)、↑/↓ 跳过标记行、围栏内 Shift+Enter 插入新段、任意行行首开块(软行提升——引用 chip 内嵌换行只阻断其自身边界,其余边界照常提升,v0.1.3)、孤儿闭合标记自动清理 | ## 安装 ### 前提 - DSH `0.1.7-rc.x`(已对 0.1.7-rc.2 实测;composer 为 Lexical 纯文本编辑器 + `@lexical/plain-text`,lexical `0.49`); - Node.js `^22.19.0 || >=24.0.0`(与 DSH 本体的支持窗口一致,包的 `engines` 字段与其对齐); - 现代桌面浏览器(Chrome / Edge / Firefox / Safari)。 ### 安装插件 包内声明了 `dsh.bundle.patch`(`cordis.patch.yml`:一条 insert 行,挂载 host 半空操作 entry,使插件出现在「设置 → 插件」中)。 本地检出(开发常用):
dsh plugin --profile web add link:/absolute/path/to/dsh-composer-markdown
从 npm registry:
dsh plugin --profile web add dsh-composer-markdown
从 GitHub(构建产物 `client.js` 随仓库提交,即使 pnpm 跳过 `prepare` 构建脚本插件也能正常加载;建议用 `#<sha>` 固定 commit,避免后续 push 改变实际运行的代码):
dsh plugin --profile web add github:chendefine/dsh-composer-markdown
> pnpm ≥ 10 会在用户显式放行前阻塞 git 依赖的 `prepare` 脚本。若希望安装时从 `src/client/` 重新构建 `client.js`,请把 pnpm 打印的键(如 `dsh-composer-markdown: true`)加进 profile 的 `pnpm-workspace.yaml` 的 `allowBuilds` 下再重新 `add` —— 这一步等于授权该包在你机器上于安装期执行代码,请仅放行信任的源。
或经 DSH 插件市场(设置 → DSH 插件市场)—— 给仓库打上 `dsh-plugin` topic 即被自动收录。
安装后**重启 `dsh web` 服务**并刷新浏览器页面生效。本地 link 方式安装后,修改 `src/client/` 源码并执行 `node scripts/build.mjs` 重新生成 `client.js`,开发态下 HMR 会自动热载重新生成的产物(无需刷新页面;若 HMR 未运行则刷新一次)。
### 开关与卸载
- **开关**:设置 → 插件 → `composer-markdown`,禁用即恢复全部原生行为(刷新后生效);
- **卸载**:`dsh plugin --profile web remove dsh-composer-markdown`。
禁用/卸载时自动清理:document 监听器、注入的样式标签,并清除编辑器内所有代码样式标志位(草稿文本内容不变)。
## 使用
所有编辑手势在 **Shift+Enter** 上;**Enter = 原生发送,从不拦截**;未命中任何场景的 Shift+Enter = 原生软换行。**Tab / Shift+Tab 仅当光标行是列表项时被认领**(层级阶梯),其余场景保持原生(焦点移动等)。普通 Backspace / Delete / 方向键仅在恰好命中下述边界时被认领,其余保持原生逐字符/逐字符移动。
### 列表
| 操作 | 触发 | 行为 |
|---|---|---|
| 无序/有序续行 | 行首 `- ` / `* ` / `N. `(**任意缩进深度**)后输入内容,按 **Shift+Enter** | 下方新行自动带 `{indent}- ` / `{n+1}. ` 前缀(嵌套层级原样保留),光标停在前缀后;段落首行、软换行行、多行粘贴行**任意视觉行**均生效 |
| 行中间截断 | 光标在列表项**内容中间**按 **Shift+Enter** | 从光标处截断:光标后的内容移到新 item、接在新前缀之后(字节保真);光标在行首/前缀内部/行尾时维持「下方新增整行」 |
| 中间插入顺延 | 在有序组中间 Shift+Enter 插入新项 | 新行拿到 `n+1`,其下同组所有成员依次 +1(`1. 2. 3.` 在 1 与 2 之间插入 → `1. 2. 3. 4.`),整组保持连续且不重复;插入与顺延同属一个撤销步 |
| 序号规整(不变式) | 任意改动之后(删除/插入行、空项退出、粘贴、撤销/重做) | 每个有序组(连续有序行、同缩进、围栏外)**恒为 `1. … n.` 从首成员连续编号**:删行接上;组被普通行/空行/无序行隔断 → 后一组从 `1.` 重起;隔断行被删、两组相连 → 合并累加;**更深缩进只挂起外层组**(嵌套子列表不打断外层,外层缩进回归时续接原计数),嵌套组自身独立规整。有意取舍:组不能保留非 1 起始号或手动跳号——手改序号立即回弹(连续性即契约) |
| 空项退出 | 只有前缀的空列表项上按 **Shift+Enter** | 移除前缀,保留空段(软行上保留空行)—— 连按两次即可干净退出列表;**光标留在清空后的本行**(v0.1.2)——空项在尾部、段中或块首行均如此,既不回上一项行尾、也不跳下一行行首 |
| 层级缩进(降级) | 光标在列表项**那一行的任意一处**(含内容中间)按 **Tab** | 该项连同**下方全部更深层级**(嵌套子列表、更深缩进的续行文本)每行缩进 +2 空格;同层兄弟项与其后内容不动;光标在行内相对位置随行平移;整棵子树一次按键、一个撤销步;嵌套有序组随后按不变式独立规整(如 `2.` 挂到上层后重排为嵌套组的 `1.`)。**降级有上限(v2.9)**:任何项最多只能降到其**父级**(上方最近的列表项,普通行跳过、空行/围栏隔断)的**下一级**——已处于父级下一级的项、以及列表**首项**(上方无可嵌套的父级)按 Tab 为**认领但不动**的空操作(焦点不会因此跳出输入框),不会无限降级 |
| 层级缩进(升级/取消) | 同上位置按 **Shift+Tab**,或折叠光标恰在**前缀原子之后**(内容首)按 **Backspace** | 嵌套项(缩进 ≥1 空格)→ 该项及全部子层级各 −2 空格(奇数缩进按 `min(2, 缩进)` 取整到 0);**顶层项 → 取消列表**:删除整个前缀原子,只留正文成普通文本行(光标留在该行,v0.1.2),子层级仍各升一级。取消列表留下普通行会隔断有序组,其后同缩进成员按不变式从 `1.` 重起。长按 Tab 降一级后停在层级上限(认领但不动);长按 Shift+Tab 每次重复升一级——两键焦点都不会从列表行跳走 |
| 前缀原子删除 | 折叠光标恰在列表项**行首**(整个原子之前)按 **Delete** | **缩进 + 前缀**整体一次删净(如 `␣␣1. ` 六字符一并消失),该行回归顶层普通文本,独立撤销步;缩进无法被逐字符选中删除 |
| 前缀方向键原子跨越 | 折叠光标贴在任意列表原子边界按 **← / →**
…(truncated)Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::5,最后更新 2026-09-28