Skip to content

Commit c2a0423

Browse files
committed
fix(ai): surrogate pair rendering in smd water-flow animation
Characters outside BMP (math symbols 𝛼𝛽, emoji 🧠, rare CJK 𠮷) are surrogate pairs in UTF-16. The old for(i;i<text.length;i++) loop split them into two unpaired surrogates → browser showed □ blocks. Fixes: - text iteration: for..of (iterates by code point, not code unit) - _isCJK: charCodeAt → codePointAt + add CJK extension B~F range
1 parent 0ae96b0 commit c2a0423

1 file changed

Lines changed: 5 additions & 4 deletions

File tree

src/med_exam_toolkit/static/quiz_ai.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,22 +360,23 @@ function makeStreamingRenderer(container, scrollTarget) {
360360
// 这样既保留了 smd 的实时 markdown 渲染(加粗/标题/列表立即成形),又拿回
361361
// Session A 那种水流逐字动画;CJK 字符得到更长的动画时长,节奏更符合中文阅读。
362362
function _isCJK(ch) {
363-
const c = ch.charCodeAt(0);
363+
const c = ch.codePointAt(0);
364364
return (c >= 0x3400 && c <= 0x9FFF) || // 统一汉字 + 扩展 A
365365
(c >= 0xF900 && c <= 0xFAFF) || // 兼容汉字
366366
(c >= 0x3040 && c <= 0x30FF) || // 日文假名
367367
(c >= 0xAC00 && c <= 0xD7AF) || // 韩文
368368
(c >= 0x3000 && c <= 0x303F) || // CJK 标点
369-
(c >= 0xFF00 && c <= 0xFFEF); // 全宽
369+
(c >= 0xFF00 && c <= 0xFFEF) || // 全宽
370+
(c >= 0x20000 && c <= 0x2FA1F); // CJK 扩展 B~F + 兼容补充
370371
}
371372
function _makeFlowRenderer(root) {
372373
const base = window.smd.default_renderer(root);
373374
base.add_text = function (data, text) {
374375
const parent = data.nodes[data.index];
375376
if (!parent || !text) return;
376377
const frag = document.createDocumentFragment();
377-
for (let i = 0; i < text.length; i++) {
378-
const ch = text[i];
378+
// for...of 按 Unicode 码点迭代,正确处理代理对(BMP 外字符)
379+
for (const ch of text) {
379380
const span = document.createElement('span');
380381
span.className = _isCJK(ch) ? 'ai-ch ai-ch-cjk' : 'ai-ch';
381382
span.textContent = ch;

0 commit comments

Comments
 (0)