Skip to content

fix(encoding): (多AI) 重构 encoding.ts 以整合并改进检测机制#1426

Open
cyfung1031 wants to merge 6 commits intomainfrom
fix/encoding/1
Open

fix(encoding): (多AI) 重构 encoding.ts 以整合并改进检测机制#1426
cyfung1031 wants to merge 6 commits intomainfrom
fix/encoding/1

Conversation

@cyfung1031
Copy link
Copy Markdown
Collaborator

@cyfung1031 cyfung1031 commented May 8, 2026

#1115 https://github.com/caigg188/LDStatusPro/releases/download/v3.5.2.4/LDStatusPro.user.js
#1425 https://github.com/dongdevcom/video-speed-controller/releases/download/v2.0.1/video-speed-controller.user.js


问题说明

修复 #1425

原有编码处理逻辑中,安装页会自行调用 detectEncodingbytesDecode 来解码下载后的脚本内容,而 encoding.ts 中也已经存在 readBlobContent 这一套较完整的 Blob/File 读取与编码检测流程。两套逻辑并存,容易造成不同入口的解码行为不一致,也使后续维护和扩展编码检测规则变得困难。

#1425 中,通过 GitHub Release URL 安装 userscript 时,响应内容可能没有明确提供 charset,例如只有 application/octet-stream。当脚本前段主要是 ASCII,而越南语、Emoji 等 UTF-8 字符出现在较靠后位置时,旧检测方式容易在样本不足的情况下把实际 UTF-8 内容误判为其他编码,导致安装页显示乱码。

修改内容

1. 整合安装页的脚本解码流程

src/pages/install/App.tsx 中原本手动执行的:

  • detectEncoding(chunksAll, contentType)
  • bytesDecode(encode, chunksAll)
  • 解码失败后回退 UTF-8

改为统一调用 readBlobContent

这样安装页不再维护独立的编码检测与回退逻辑,而是复用 encoding.ts 中统一的 Blob 内容读取机制,减少重复实现,并确保不同入口的解码行为一致。

2. 重构 encoding.ts 的检测优先级

本次将编码检测流程整理为更明确的优先级:

  1. 优先使用有效的 Content-Type charset
  2. 检测 BOM
  3. 使用空字节分布启发式判断 UTF-16 / UTF-32
  4. 对 UTF-8 做严格校验
  5. 对“几乎有效的 UTF-8”保留 UTF-8 解码结果
  6. 最后才进入 chardet legacy 编码检测

这样可以优先保护现代脚本中最常见的 UTF-8 内容,避免在没有 charset 的情况下过早依赖 chardet,降低 UTF-8 被误判为 legacy 编码的概率。

3. 改进 Content-Type charset 解析

增强 parseCharsetFromContentType 的解析能力:

  • 支持 charset = UTF-8 这类带空格的写法
  • 支持单引号或双引号包裹 charset
  • 支持大小写不敏感的 charset 参数
  • 避免把后续参数错误并入 charset

4. 改进 UTF-32 解码实现

重构 decodeUTF32

  • 使用 DataView 按端序读取 code point
  • 正确支持 UTF-32LE / UTF-32BE
  • 正确跳过 UTF-32 BOM
  • 支持带非零 byteOffsetUint8Array.subarray
  • 分块调用 String.fromCodePoint,避免大文件一次性展开过多参数

同时 bytesDecode 会先规范化 charset 大小写,使 UTF-32LEUTF-32BE 等写法也能被正确处理。

5. 改进大文件 UTF-8 检测策略

对于较大的内容,新增采样范围检测逻辑:

  • 小文件直接做完整 UTF-8 严格校验
  • 大文件采样开头、中间、结尾,以及包含高位字节的位置
  • 采样边界会避开 UTF-8 continuation byte,避免从多字节字符中间截断造成误判

这可以覆盖 GitHub Release userscript 的常见情况:文件前段多为 metadata 或 ASCII 代码,真正的多语言文本或 Emoji 可能出现在文件后部。

6. 改进 legacy 编码回退逻辑

当 UTF-8 判断失败后,才进入 chardet-based legacy 检测,并改进以下行为:

  • legacy 检测样本优先覆盖第一个高位字节附近,而不是固定只取文件开头
  • 跳过已经由前置流程处理的 Unicode 编码候选
  • 对启发式 UTF-16 / UTF-32 结果增加可疑控制字符校验
  • 在没有可靠 legacy 结果时回退到 windows-1252

这能在保护 UTF-8 的同时,继续兼容 GBK、Big5、Shift_JIS 等 legacy 编码脚本。

7. 增加回归测试与边界测试

新增并扩充 encoding.test.ts,覆盖:

  • Content-Type charset 解析
  • UTF-8 / UTF-16 / UTF-32 解码
  • UTF-32 BOM、非零 byteOffset、大内容分块解码
  • 无 charset 的有效 UTF-8 内容
  • GitHub Release 类似场景下的 UTF-8 越南语与 Emoji
  • 多语言 UTF-8 内容,包括中文、日文、韩文、越南语、俄文、阿拉伯文、希腊文、希伯来文、泰文、印地文、拉丁重音字符与 Emoji
  • 大文件 UTF-8 内容
  • 采样边界跨越 Emoji 多字节字符
  • 少量损坏字节但整体仍接近 UTF-8 的情况
  • GBK、Big5、Shift_JIS 等 legacy CJK 编码
  • 防止 legacy CJK 或带空字节内容被误判为 UTF-16 / UTF-32

影响范围

本次主要影响 encoding.ts 的编码检测与 Blob 内容读取逻辑,以及安装页读取远程 userscript 时的解码流程。

预期改善:

  • 统一脚本安装页与通用 Blob/File 读取的解码行为
  • 修复无 charset 的 GitHub Release userscript 中 UTF-8 文本被误判导致的乱码问题
  • 提升 UTF-8、UTF-16、UTF-32 与 legacy CJK 编码检测的稳定性
  • 降低后续维护编码检测逻辑的复杂度

风险说明

编码检测本身仍然依赖一定启发式判断,极端混合编码或伪文本二进制内容仍可能存在误判风险。本次通过更明确的检测优先级、UTF-8 严格校验、启发式结果验证和更完整的测试覆盖来降低风险。

测试

已增加并调整 src/pkg/utils/encoding.test.ts 相关测试,覆盖本次重构涉及的主要检测路径、回归场景与边界情况。

@cyfung1031 cyfung1031 added the P1 🔥 重要但是不紧急的内容 label May 8, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 主要围绕脚本内容的“读取 + 编码检测 + 解码”流程做统一与重构:将安装页原先独立的编码检测/解码逻辑整合到 src/pkg/utils/encoding.tsreadBlobContent,并显著调整编码检测优先级以更稳健地保护 UTF-8(尤其是 GitHub Release 场景中无 charset、非 ASCII 内容出现在后段的 userscript)。

Changes:

  • 安装页改为统一调用 readBlobContent 解码脚本内容,避免多套检测逻辑并存导致行为不一致。
  • 重构 encoding.ts:增强 Content-Type charset 解析、UTF-32 解码实现,并将检测优先级调整为 header charset → BOM → UTF-16/32 启发式 → UTF-8 严格校验/近似保留 → chardet legacy 回退。
  • 大幅扩充 encoding.test.ts,覆盖 UTF-8/16/32、GitHub Release 回归场景、多语言与大文件采样等边界。

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/pkg/utils/encoding.ts 重构编码检测与解码流程(charset 解析、UTF-32、UTF-8 采样校验、legacy 回退策略)。
src/pkg/utils/encoding.test.ts 新增/扩充大量回归与边界测试,验证重构后的检测优先级与解码正确性。
src/pages/install/App.tsx 安装页脚本下载后统一改用 readBlobContent 解码,移除手写 detect/decode/fallback 流程。

Comment thread src/pages/install/App.tsx Outdated
Comment thread src/pkg/utils/encoding.ts
@cyfung1031
Copy link
Copy Markdown
Collaborator Author

可以合并

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P1 🔥 重要但是不紧急的内容

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Encoding issue: Vietnamese/Emoji characters displayed incorrectly when installing via GitHub Release URL

2 participants