双向文本排版 MojtabaFaraji/dsh-plugin-rtl-text
DeepSeek 客户端v0.2.2DeepSeek HarnessCordis插件,修复 Web 和 Desktop GUI 上聊天消息里从右到左 /…
30.7/100
综合分
1
GitHub 星标
50
npm 周下载
—/5
用户评分
数据截至 2026/10/12 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/MojtabaFaraji/dsh-plugin-rtl-text.git状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
生态插件
可安装,未声明 dsh 能力
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 24 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-plugin-rtl-text @ 0.2.2
✓Node 引擎要求 ^22.19 || >=24 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/14 00:34:53
安全扫描自动 · 静态分析源码v2.7.0🟢 扫描:未发现敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 按块定文本方向
- 列表标记随文本定向
DeepSeek Harness 插件,修复聊天里的 RTL/LTR 双向文本渲染:波斯语和阿拉伯语消息夹带英文时按块定方向,列表标记和引用条也跟着各自文本走
README
由 DeepSeek 最新模型翻译生成dsh-plugin-rtl-text
DeepSeek Harness(Cordis)插件,修复 Web 和 Desktop GUI 上聊天消息里从右到左 / 从左到右混排文本的渲染问题。
当一条回复把波斯语或阿拉伯语和英文单词、代码、数字混在一起时,LTR 页面会打乱整行顺序:句子倒着读,标点粘到错误的一侧,列表序号和项目符号留在左边缘,引用条也跑到错误的一侧。这个插件给每个聊天块按自身内容算出方向——消息文本一个字符都不改。
目录
- 修复什么
- 不改变什么
- 安装
- 工作原理
- 兼容性
- 配置
- cordis.yml 在哪?
- 疑难排查
- 安全与隐私
- 示例
- 测试
- 从源码构建
- 发布版本
- 包内容
- 作者
- 许可
修复什么
- 波斯语或阿拉伯语段落里夹着英文(سلام، how are you?):整段按 RTL 排版,其中的英文片段方向正确。
- 英文开头的波斯语句子(build سبز + ۴ تست پاس …):只看首字符的启发式会把它当成 LTR。
- 波斯语开头、但含大量拉丁技术词的句子(سطح رندر: تابع واقعی renderIndexInjections …)——永远不会被翻成 LTR。
- 列表标记和引用条:ol 序号、ul 项目符号、blockquote 引用条,都跟着内容一起移到右侧。
展开完整文档(README 剩余 1 节)
dsh-plugin-rtl-text
DeepSeek Harness(Cordis)插件,修复 Web 和 Desktop GUI 上聊天消息里从右到左 / 从左到右混排文本的渲染问题。
当一条回复把波斯语或阿拉伯语和英文单词、代码、数字混在一起时,LTR 页面会打乱整行顺序:句子倒着读,标点粘到错误的一侧,列表序号和项目符号留在左边缘,引用条也跑到错误的一侧。这个插件给每个聊天块按自身内容算出方向——消息文本一个字符都不改。
目录
- 修复什么
- 不改变什么
- 安装
- 工作原理
- 兼容性
- 配置
- cordis.yml 在哪?
- 疑难排查
- 安全与隐私
- 示例
- 测试
- 从源码构建
- 发布版本
- 包内容
- 作者
- 许可
修复什么
- 波斯语或阿拉伯语段落里夹着英文(سلام، how are you?):整段按 RTL 排版,其中的英文片段方向正确。
- 英文开头的波斯语句子(build سبز + ۴ تست پاس …):只看首字符的启发式会把它当成 LTR。
- 波斯语开头、但含大量拉丁技术词的句子(سطح رندر: تابع واقعی renderIndexInjections …)——永远不会被翻成 LTR。
- 列表标记和引用条:ol 序号、ul 项目符号、blockquote 引用条,都跟着内容一起移到右侧。
- 混排的行内代码(newest=2026-10-07, age=3 روز):这个 span 被隔离,按自己的多数方向排版,代码里的 =、-、,、括号、方括号不再和段落互相错位。
- 代码块保持结构:pre 固定为 LTR 并做隔离,RTL 上下文永远打不乱代码——里面的波斯语注释按 RTL 片段渲染。
- 带文件名的波斯语项目符号(README.md: دو بخش جدید …):拉丁标签开头,字母数甚至超过波斯语,但句子结尾是波斯语——「最后强字符」规则让整个列表保持 RTL,项目符号在右侧。
- 数字开头的波斯语句子(۱. push به GitHub: …):阿拉伯-印度数字在 Unicode 里是弱字符,所以脚本和样式表一样跳过它们——句子靠波斯语多数方向钉住 RTL,而不是从 LTR 开头然后乱掉。
- 表格:表格固定一个方向,让各列按 RTL 排布(第一列在最右边),同时每个单元格保留自己的内容方向(unicode-bidi: plaintext)——这样在波斯语表格里,拉丁字母较多的结果单元格依然好读。
- 已有历史记录和实时回复都适用:修复只涉及一行样式表和一段脚本,所以每个已经加载的会话都立刻受益——不用重新推流。
它不会改变什么
- 消息文本。 持久化的会话日志、模型历史、命令行输出保持逐字节一致;插件只动展示层。
- 其他配置档。 无头配置档和 TUI 配置档没有可加样式的 GUI——注入的行在那里永远不会被收集,插件就是个无害的空操作。
- 代码块内容。 pre 保持作者写下的 LTR 顺序(它被固定住,从不重写)——只修正它的 direction 上下文。
安装
插件以打包层的形式装进配置档——真正完成挂载的就是这一步:
from the npm registry
pnpm dsh plugin --profile <name> add dsh-plugin-rtl-text
from a local checkout (no registry needed)
pnpm dsh plugin --profile <name> add <path-to-this-package>
你也可以用 GUI 的 Add plugin 按钮,填包名即可。单纯 pnpm add 只会把文件复制进配置档的 node_modules,不会追加打包层,插件就永远不会挂载——请用上面的命令。
对等依赖:@deepseek-ai/cordis(已发布到 npm,每个 Harness 安装里本来就有)。
为什么这个包要声明 dsh.bundle
Harness 插件管理器会拒绝没有 dsh.bundle 的包,报错 declares no dsh.bundle,因为没有补丁文件可以加进配置档的组成。这个包声明了:
"dsh": {
"bundle": {
"patch": "./cordis.patch.yml"
}
}
安装做三件事:
1. 把包 pnpm add 进 <DSH_HOME>/profiles/<name>/,并写进配置档 package.json 的 dependencies。
2. 把 dsh-plugin-rtl-text 追加到配置档清单的 dsh.profile.bundles。
3. 把包的 cordis.patch.yml 作为组成层贡献进去:
- insert:
- id: rtl-text
name: dsh-plugin-rtl-text
config:
enabled: true
用 pnpm dsh --profile <name> --dump-config 验证组成——输出里会有一个 == dsh-plugin-rtl-text 层,带 id: rtl-text 条目。
装进正在运行的配置档之后
注入的行在页面加载时从正在运行、已挂载的插件收集,所以:
1. 重新挂载插件——在 GUI 插件页把它关掉再打开,或者重启宿主。
2. 重新加载页面。index.html 按请求渲染,会带上这些行。
更新已有安装(新构建或新注册表版本)也需要同样两步。
工作原理
Web markdown 渲染器刻意让原始 HTML 保持惰性——它的流水线里不引入任何 HTML 解析器——所以显示层面的修复没法藏在消息文本里。于是插件改用 Harness 的索引注入扩展点(webserver/index-inject,也就是 ui-theme 用的同一个事件):每次页面加载时,webserver 收集注入行并渲染进 index.html,而这个插件追加两行。
style 行
无 JavaScript 时的默认方案:每个块根据第一个强字符决定方向(unicode-bidi: plaintext),并通过稳定的 data-chat- 属性限定在聊天行内:
:where([data-chat-group-key],[data-chat-flow-key]) :is(p,li,h1,h2,h3,h4,h5,h6,blockquote,dd,dt,td,th,figcaption){unicode-bidi:plaintext}
以主导语言开头的句子,不用任何脚本就能正确解析。
script 行:拉丁字母开头的波斯语句子
只看第一个强字符,会把 build سبز + ۴ تست پاس 读成 LTR,因为它以英文开头。当一个文本块以 LTR 开头,但 RTL 单词(任何含希伯来/阿拉伯字符的单词,包括阿拉伯标点和变音符号)数量超过拉丁/希腊/西里尔单词时,脚本会固定 dir="rtl"——多数决按单词计数,不按字符计数,因为波斯语正文里的英文短语字符密度高(README.md: بند جدید در «What it fixes» … 的字符数是 60/60 打平,但按单词算是波斯语,18 比 9),同时加内联 unicode-bidi: isolate,让显式方向压过样式表。以波斯语开头的句子永远不会被固定——像 renderIndexInjections 这样的技术拉丁 token 不能把 سطح رندر: تابع واقعی … 翻成 LTR,所以第一个强字符规则让它们保持 RTL。以拉丁标签开头、却以波斯语结尾的句子(README.md: دو بخش جدید …)属于波斯语写作:最后一个强字符是波斯语的块和列表也固定为 RTL。阿拉伯-印度数字和波斯数字(۰–۹)是数字,不是强字符——RTL 范围把它们排除在外,所以以 ۱. 开头的条目读起来和 unicode-bidi: plaintext 完全一样,并且仍通过多数决规则固定为 RTL。
容器方向:列表编号、项目符号、引用条
标记跟随容器自身的 direction 属性,内层文本上的 unicode-bidi: plaintext 改不了它——在 LTR 页面上它们会一直待在左边缘。对于聊天范围内的 ul、ol、blockquote 和 table,脚本套用完整规则(文本以波斯语开头、以波斯语结尾,或 RTL 占多数时用 RTL),并固定内联 direction: rtl,所以以 1. اولین مورد … 开头的列表,编号和文本一起待在右侧。英文列表保持左侧。表格按同一规则处理列顺序(مرحله / نتیجه 表格的第一列待在右侧),而每个单元格的内容保持 unicode-bidi: plaintext——拉丁字母多的结果单元格在 RTL 表格里仍是 LTR。
行内代码、链接和代码块
=、-、,、(、) 和 都是中性字符:在段落内部,它们的方向由周围文本决定,这正是 newest=2026-10-07, age=3 روز 在 RTL 上下文中乱序的原因。因此,会话作用域内的 code、kbd、samp、var 和 a 各自采用自己的多数方向(平局时回退到首个强方向字符),并加上行内 unicode-bidi: isolate——每个都成为一个连贯的孤岛,符号停留在原本书写的位置,而拉丁字母占多数的代码里嵌套的波斯文仍按 RTL 渲染。代码块(pre 和 pre code)固定为 dir="ltr",这样代码结构永远不会从被固定的祖先继承 RTL 方向。任何元素之外的纯文本符号,遵循插件计算出的段落方向;如果仍有看起来不对的地方,请附上原句开 issue。
MutationObserver 会在流式文本增长时重新应用每一项决策,当文本不再符合条件时移除过期的固定,并且只监听文本和子节点变更——属性写入永远不会造成循环。
绝不触碰的内容: 消息文本本身。持久会话日志、模型历史和命令行输出保持逐字节一致,历史中已有的消息也会被修正,因为这套机制只作用于呈现层。
兼容性
- 需要 DeepSeek Harness 版本暴露 webserver/index-inject,并且聊天行带有 data-chat-group-key / data-chat-flow-key——当前版本满足。
- 这两个扩展点都是尚未稳定的公开 API。跨版本升级 Harness 时,请重新运行 pnpm run test,并确认聊天行仍带有这些属性;如果 Harness 侧改名,这里需要同步更新选择器。
- 适用于 Web GUI 和 Desktop GUI(同一个文档)。Headless 和 TUI 配置档不受影响。
配置
| 字段 | 默认值 | 含义 |
| enabled | true | 设为 false 可让插件保持挂载但不贡献行。 |
在配置档的 cordis.patch.yml 中用按 id 定位的补丁覆盖:
- id: rtl-text
config:
enabled: false
cordis.yml 在哪里?
有三个不同的文件共用这个名字:
1. <profile>/cordis.yml —— 配置档的根入口列表。它保持为空;文件头会提示改为编辑 cordis.patch.yml。
2. <profile>/cordis.patch.yml —— 配置档自己的补丁层(按 id 定位的覆盖和 disabled 标记),应用在所有* bundle 层之上。
3. 本包内的 cordis.patch.yml —— 本插件的 bundle 层,随包发布,由 dsh.bundle.patch 引用。当包作为 bundle 安装时,加载器会读取它;你不要编辑它。
故障排查
| 现象 | 怎么办 |
| 安装并重新加载后,没有任何变化 | 先重新挂载(插件页面:关 → 开,或重启宿主),然后重新加载。行是在页面加载时从已挂载的实时插件收集的。 |
| 还有一句话方向判断错误 | 启发式限制:接近双语平衡的句子会回退到第一个强方向字符。请带上原句[提交 issue。 |
| 列表编号或项目符号仍在左侧 | 确认重新加载确实触发了重新挂载。如果你的 Harness 版本改了聊天行的属性名,选择器也要同步更新(见兼容性)。 |
| 你想关掉它 | 按配置里的说明设置 enabled: false。 |
安全与隐私
- 插件只贡献两行静态内容——一个 CSS 块和一个内联脚本——都由包内常量构建。不嵌入任何消息内容,不发网络请求,也不存储任何东西。
- 脚本读取聊天块的 textContent,并在其上写入 dir/内联样式;MutationObserver 只监听新内容。数据不会离开页面。
- 因为消息文本从不被改写,转录记录和模型历史保持逐字节一致。
示例
页面方向为 LTR:
- 回复 سلام، how are you?:处理前,段落跟随页面方向,文字和标点顺序错乱;处理后,方向来自 سلام——整行 RTL,其中 how are you 按 LTR 渲染。
- 以 build سبز + ۴ تست پاس … 开头的列表项:first-strong 把开头的 build 读作 LTR,破坏了波斯语句子;脚本统计出波斯字母占多数,于是给整个块固定 dir="rtl"。
- سطح رندر: تابع واقعی renderIndexInjections → style در …:first-strong 已经把开头的 سطح 读作 RTL,所以脚本不介入——拉丁技术 token 数量超过波斯字母,但这里若按多数覆盖,会错误地把句子翻成 LTR。
- 以数字(1. اولین مورد …)或项目符号开头的列表或引用:标记跟随容器的方向,而不是文本的方向——脚本给 ul/ol/blockquote 本身固定 dir="rtl" 和内联 direction: rtl,于是编号和项目符号随条目一起移到右侧。
测试
pnpm run test # node:test suite against a real Cordis Context
测试套件覆盖:两行注入(保留其他行,绝不输出 </script);针对两种已报告的错误方向验证固定规则(英文开头的波斯语强制 RTL;波斯语开头但拉丁字母偏多的交给 first-strong);列表和引用的容器固定(编号、项目符号、引用竖线);针对已报告的 newest=2026-10-07, age=3 روز 场景验证行内代码隔离;LTR 代码块固定;带文件标签的波斯语项目符号按 last-strong 固定;过期固定的移除、enabled: false 配置、fiber.dispose() 时监听器解绑,以及每个集合两行的语义。
从源码构建
pnpm run build # tsdown → lib/index.js + lib/index.d.ts
只在包目录里运行。DeepSeek Harness 仓库根目录有自己的 monorepo tsdown.config.ts,它期望 tsc 产出的 lib/types/{index,invariant,startup}.js 入口;从仓库根目录构建会读到那份配置,而不是包本地的配置,于是失败。
这个包没有运行时依赖,所以不必单独为它跑 pnpm install。构建和测试需要 tsdown 和 @deepseek-ai/cordis,它们从相邻的 DeepSeek Harness 检出目录解析——开发就在这里进行。
发布版本
1. 检查全绿:pnpm run build 和 pnpm run test(在 Harness 目录树内的检出目录里运行,如上所述)。
2. 检查 tarball:npm pack --dry-run —— 应当看到 lib/index.js、lib/index.d.ts、cordis.patch.yml、README.md、CHANGELOG.md 和 LICENSE。
3. 提升 version,并在 CHANGELOG.md 里加一条记录。
4. npm login,然后 npm publish —— prepublishOnly 会自动重新构建 lib/。
5. 推送到 GitHub(MojtabaFaraji/dsh-plugin-rtl-text):仓库有意提交 lib/,这样直接 clone 就能用,不需要 Harness 工具链;.gitignore 只排除 node_modules/、本地 npm 缓存、tarball 和日志。
包内容
| 文件 | 用途 |
| lib/index.js | 运行时入口(apply) |
| lib/index.d.ts | 类型声明(apply、Config) |
| cordis.patch.yml | bundle 补丁层(dsh.bundle.patch) |
| README.md | 本文件 |
| CHANGELOG.md | 发布历史 |
| LICENSE | MIT 许可证文本 |
作者
Mojtaba Faraji
许可证
MIT —— 见 LICENSE。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
MojtabaFaraji/dsh-plugin-rtl-text
DeepSeek HarnessCordis插件,修复 Web 和 Desktop GUI 上聊天消息里从右到左 /…
相关插件 · 对话 / 记忆
上下文中枢oceanbase/powercontext
上下文跟着工作走 —— 跨会话、跨智能体、跨人。
★ 1,489已汉化DSH
73.1
智能体记忆库plastic-labs/honcho
Honcho 是记忆基础设施,用来构建有状态的智能体。这些智能体能理解不断变化的人、智能体、群组、项目和想法。
★ 7,918已汉化DSH
71.7
长程智能体控制面loopx-project/loopx
给 Agent 一个目标,让工作持续向前。
★ 6,358已汉化DSH
71.3
智能体上下文数据库volcengine/OpenViking
给 AI 智能体用的上下文数据库
★ 41,453已汉化DSH
71.3
长效机器人团队Fei2411/DS-Bot
Download DS Bot for Windows 10/11 64-bit / 下载 Windows…
★ 5,293已汉化DSH
71.2
可携带记忆层EverMind-AI/EverOS
为什么选择 EverOS
★ 13,797已汉化DSH
71.1
这是你的仓库?认领条目