dsh-unicode-toolkit
v0.1.0
Published
Unicode toolkit for DeepSeek Harness: inspect code points (U+, UTF-8 bytes, display width, category), escape/unescape text (js/json/html/url), and normalize or convert between full-width and half-width forms. Zero runtime dependencies, read-only.
Maintainers
Readme
dsh-unicode-toolkit
DeepSeek Harness 的 Unicode 工具箱:inspect_codepoints 逐字符查看码位、UTF-8 字节、显示宽度与类别,escape_text 在 js / json / html / url 四种风格间转义与反转义,normalize_text 做 Unicode 规范化与全半角转换。只读、零运行时依赖。
- 源码:https://github.com/geeklei/dsh-plugins/tree/main/dsh-unicode-toolkit
- npm:https://www.npmjs.com/package/dsh-unicode-toolkit
功能说明
乱码、对不齐、搜不到、粘贴后多出看不见的字符——这类问题的根因都在码点层面:全角与半角混用、组合标记与预组合字符混用、夹了零宽字符、表情占了两个 UTF-16 单元。肉眼看不出来,但会实实在在影响比较、检索与排版。本插件把这些问题变成可读的表格。
inspect_codepoints —— 看清每个字符到底是什么
来源:(内联文本)
概览:字符 14 个(UTF-16 单元 15,UTF-8 字节 34);显示宽度 19
构成:组合标记 1,零宽字符 1,补充平面字符 1,控制字符 0
过滤:all,命中 14 个字符
| # | 字符 | 码位 | UTF-8 | 宽度 | 类别 |
| --- | ------ | ------- | ----------- | ---- | -------- |
| 0 | 订 | U+8BA2 | E8 AE A2 | 2 | 汉字 |
| 1 | 单 | U+5355 | E5 8D 95 | 2 | 汉字 |
| 2 | ① | U+2460 | E2 91 A0 | 1 | 数字符号 |
| 3 | 号 | U+53F7 | E5 8F B7 | 2 | 汉字 |
| 4 | (空格) | U+0020 | 20 | 1 | 空白 |
| 5 | A | U+FF21 | EF BC A1 | 2 | 全角字符 |
| 6 | B | U+FF22 | EF BC A2 | 2 | 全角字符 |
| 7 | C | U+FF23 | EF BC A3 | 2 | 全角字符 |
| 8 | (空格) | U+0020 | 20 | 1 | 空白 |
| 9 | 😀 | U+1F600 | F0 9F 98 80 | 2 | 表情符号 |
| 10 | (空格) | U+0020 | 20 | 1 | 空白 |
| 11 | e | U+0065 | 65 | 1 | 字母 |
| 12 | ◌́ | U+0301 | CC 81 | 0 | 组合标记 |
| 13 | (零宽) | U+200B | E2 80 8B | 0 | 零宽字符 |无法直接显示的字符会给出安全标注((空格)、\n、\x01、(零宽)、(全角空格)),宽度按终端显示宽度计算(汉字与表情为 2,组合标记与零宽字符为 0)。
用 only 可以只列出可疑字符,聚焦排查:
过滤:non_ascii,命中 10 个字符only 可选:all(默认)、non_ascii、wide、combining、zero_width、control、emoji、space。
escape_text —— 四种风格的转义与反转义
方向:escape,风格:js,保留非 ASCII:否
字符数:7 → 20
\u4e2d\u6587 \"A\"\n方向:escape,风格:html,保留非 ASCII:否
字符数:7 → 18
A & B 中| 风格 | 转义规则 | 典型用途 |
|---|---|---|
| js | 非 ASCII → \uXXXX(补充平面用代理对),控制字符 → \n/\x01 | 生成 JS 字符串字面量 |
| json | 只转义 " \ 与控制字符,非 ASCII 原样保留 | 生成 JSON 值 |
| html | & 等命名实体 + 非 ASCII → &#xXXXX; | 嵌入 HTML |
| url | UTF-8 字节 → %XX 百分号编码 | URL 参数 |
direction=unescape 反向还原,\uXXXX、\xXX、\u{...}、八进制、&#xXXXX;、命名实体、%XX 都能识别;无法识别的写法原样保留,不会误吞。keep_non_ascii=true 则只转义 ASCII 中的特殊字符。
normalize_text —— 规范化与全半角转换
处理:NFKC + 宽度 half
变化:有
字符数:8 → 7;UTF-16 单元:8 → 7;UTF-8 字节:19 → 8;显示宽度:11 → 7
字符数发生变化,不做逐位比对(8 → 7)。
结果:
ABC 1 éform:NFC(默认,预组合)/NFD(分解)/NFKC/NFKD(兼容折叠,会做①→1、A→A、ア→ア)width:keep(默认)/half(全角转半角)/full(半角转全角)
其余字符数不变时,会给出逐字符变更明细,标明原码位与新码位,便于确认到底改了什么:
变更明细(2 处):
| # | 原字符 | 原码位 | 新字符 | 新码位 |需要注意 width 与 NFKC 的分工:width 只做宽度上的算术变换(U+FF01–U+FF5E 与 U+3000),不会折叠 ①→1、㈱→(株) 这类兼容字符,语义更安全;需要兼容折叠时用 form=NFKC。半角片假名转全角也属于兼容折叠,用 form=NFKC 处理。
安装
npm install dsh-unicode-toolkit安装后在 cordis.patch.yml 中加入:
- insert:
- id: unicode-toolkit
name: "dsh-unicode-toolkit"使用说明
三个工具都支持 path(文件路径)或 text(内联文本)二选一,text 优先。
inspect_codepoints
| 参数 | 类型 | 说明 |
|---|---|---|
| path | string | 文件路径(与 text 二选一) |
| text | string | 内联文本(优先于 path) |
| only | string | 过滤:all(默认)| non_ascii | wide | combining | zero_width | control | emoji | space |
| limit | number | 最多列出字符数,默认 40,上限 500 |
| max_chars | number | 输出字符上限,默认 20000,上限 200000 |
| max_size | number | 文件大小上限(KB),默认 10240,上限 51200 |
用户:这段文本里是不是混了看不见的字符
inspect_codepoints(text="订单①号 ABC 😀 e\u0301\u200b", only="zero_width")用户:看看这个文件的非 ASCII 字符有哪些
inspect_codepoints(path="data.txt", only="non_ascii", limit=100)escape_text
| 参数 | 类型 | 说明 |
|---|---|---|
| path / text | string | 同上 |
| direction | string | escape(默认)| unescape |
| style | string | js(默认)| json | html | url |
| keep_non_ascii | boolean | 保留非 ASCII 不转义,默认 false |
| max_chars / max_size | number | 同上 |
用户:把这段中文转成 JS 转义写法
escape_text(text="中文", style="js")用户:这个
%E4%B8%AD是什么字
escape_text(text="%E4%B8%AD", direction="unescape", style="url")normalize_text
| 参数 | 类型 | 说明 |
|---|---|---|
| path / text | string | 同上 |
| form | string | NFC(默认)| NFD | NFKC | NFKD |
| width | string | keep(默认)| half | full |
| limit | number | 变更明细上限,默认 40,上限 500 |
| max_chars / max_size | number | 同上 |
用户:这份文案全角半角混用了,统一成半角
normalize_text(path="copy.txt", width="half")用户:把这两个看起来一样的字符串规范化,方便做去重
normalize_text(text="ABC ①", form="NFKC", width="half")典型场景
- 乱码定位:
inspect_codepoints直接给出码位与 UTF-8 字节,判断是编码问题还是字符本身就不同。 - 隐形字符排查:
only="zero_width"或only="control"找出零宽字符、BOM、控制符——它们常导致「看着一样却不相等」。 - 全半角混排:
only="wide"先定位,再用normalize_text(width="half")统一。 - 去重前归一:比较、去重、建索引前先
form=NFKC归一,避免同一内容多个形态。 - 跨语言文本处理:确认汉字、假名、谚文、表情的码位分布,规划列宽与截断策略。
- 生成代码字面量:把含中文 / 换行的文案转成
js或json转义写法,直接粘进源码。 - 实体互转:
html风格在实体与原文之间双向转换,处理接口返回的 HTML 片段。 - 终端对齐校验:用「显示宽度」确认字符串在终端里的实际占位,排查表格错位。
安全边界
- 只读:三个工具都不写入、不修改、不删除文件;测试含源文件 size/mtime 不变的只读性断言。
- 不访问网络:全部处理在本地完成,无任何外部请求。
- 不执行输入:只做字符级处理,不做
eval、不解析表达式、不加载模块。 - 二进制拒绝:读取时检测 NUL 字节,疑似二进制文件直接拒绝解析。
- 多层上限:文件大小上限 51200 KB、输出字符上限 200000、列出 / 明细行数上限 500。超限即拒绝或截断并显式提示。
- 不做语言猜测:分类基于码点区间,不做字符集探测,也不会因文本内容改变行为。
- 不脱敏:字符原样输出。若文本含密钥等敏感信息,请先用
dsh-credential-scan检查。
其他插件集成说明
| 协作插件 | 集成方式 | |---|---| | dsh-regex-lab | 先用 inspect_codepoints 确认字符真实码位,再写精确的正则 | | dsh-text-diff | 对比结果异常时(差异不可见),用 inspect_codepoints 找出零宽 / 组合标记差异 | | dsh-text-stats | 字符级明细与词频统计互补,共同评估文本体量与构成 | | dsh-string-case | 大小写转换前先归一化,避免全角字母被漏掉 | | dsh-base64-codec | base64 解码后文本异常时,用 inspect_codepoints 核对码点 | | dsh-hash-checksum | 哈希不一致时排查隐形字符差异 | | dsh-json-yaml-toolkit | 生成 JSON 字面量前用 escape_text 转义字符串 | | dsh-csv-explorer | 定位 CSV 中全半角混排、隐形字符导致的列错位 | | dsh-credential-scan | 处理前扫描文本中是否混入凭据、密钥 |
版本说明
- 0.1.0(2026-10-01):初始版本。
inspect_codepoints:码位 / UTF-8 字节 / 显示宽度 / 类别逐字符表;字符数、UTF-16 单元、UTF-8 字节、总宽度、组合标记、零宽、补充平面、控制字符概览;8 种过滤条件escape_text:js / json / html / url 四种风格的双向转换,支持keep_non_asciinormalize_text:NFC / NFD / NFKC / NFKD 规范化 + 全半角转换,输出逐字符变更明细- 中日韩字符按显示宽度对齐;不可见字符安全标注;二进制拒绝与多层上限保护
RoadMap
v0.2(计划)
inspect_codepoints增加show_names:为常见区间输出可读名称(如LEFT DOUBLE QUOTATION MARK)escape_text增加csv与xml风格(字段引用 /&实体)normalize_text增加width=katakana:半角片假名与全角片假名互转(含浊音合成)detect_mixed:一次性报告全半角、繁简、组合标记混用情况
v0.3(展望)
strip_invisible:一键清除零宽字符、BOM、控制符(可选保留换行)unicode_lookup:按码位或名称反查字符信息- 双向文本(Bidi)与同形字(homoglyph)检测
- 大文件流式扫描,输出可疑字符的位置分布
FAQ
Q:① 为什么归到「数字符号」而不是「数字」?
类别按码点区间判定,U+2460 属于带圈数字符号区(U+2460–U+24FF),与 ASCII 数字分开统计。需要把它变成普通数字请用 form=NFKC。
Q:显示宽度和字符数为什么不一样? 汉字、全角字符、表情占 2 列,组合标记与零宽字符占 0 列。终端对齐要按显示宽度算,字符数只反映码点个数。
Q:😀 的码位是 U+1F600,为什么 UTF-16 单元数比字符数多 1?
补充平面字符在 UTF-16 中用一对代理码位表示。概览会分别给出「字符数」与「UTF-16 单元数」,两者差值即补充平面字符数。
Q:\uXXXX 和 %XX 转义有什么区别?
\uXXXX 表示一个 UTF-16 码位;%XX 表示一个 UTF-8 字节,所以一个汉字对应 3 个 %XX。两者都支持双向转换。
Q:unescape 遇到不认识的转义会怎样?
原样保留,不会丢弃也不会报错。例如 \q 输出仍是 \q。
Q:url 风格会把 + 当成空格吗?
不会。只处理 %XX 形式;表单编码里的 + 属于 application/x-www-form-urlencoded 规则,不在本插件范围内。
Q:width=half 和 form=NFKC 转全角字符,结果一样吗?
对全角字母数字一样,但 NFKC 还会折叠 ①→1、㈱→(株)、ア→ア 等兼容字符。只要宽度变换、不想改变语义时用 width=half。
Q:文本很长会不会很慢?
处理是线性的。默认列出前 40 个字符,概览统计始终针对全文;文件超过 max_size(默认 10 MB)会直接拒绝。
Q:能直接改文件里的字符吗? 不能。本插件只读,输出处理结果供你使用,不写回文件。
源码与发布地址
- 源码:https://github.com/geeklei/dsh-plugins/tree/main/dsh-unicode-toolkit
- npm:https://www.npmjs.com/package/dsh-unicode-toolkit
许可证
MIT
