訂明本例驗收任務
假設引用介面用由零起計的 code point 位置,不包括終點。驗算用 Array.from 組該位置序列,核整數及界內位置才摘錄。Node Buffer 另示 UTF-8 位元組長度;位元組數不可借作本例位置。
- 先訂位置單位
- 按該序列核界限
- 摘錄時不借位元組數
位置無效便列片段錯誤,不靜默截短。
使用已填個案
| 個案 | 已提供輸入 | 預期結構化結果 | 判斷及原因 |
|---|---|---|---|
| 中文字片段 | {"source":"A中B","start":1,"end":2} | {"text":"中","pointLength":3,"byteLength":5} | 本位置取一個中文字;來源另佔五個 UTF-8 位元組。 |
| 誤用位元組終點 | {"source":"A中B","start":1,"end":4} | {"error":"span-bounds","pointLength":3} | 四超過本例三個位置的序列。 |
| 補充字元符號 | {"source":"A😀B","start":1,"end":2} | {"text":"😀","pointLength":3,"byteLength":6} | 按本例座標,Array.from 把此符號留為一個位置。 |
逐步處理 supplementary-symbol 個案,須得到甚麼結果?原因是甚麼?
查看參考答案
{"text":"😀","pointLength":3,"byteLength":6}。按本例座標,Array.from 把此符號留為一個位置。
執行完整本機驗算
import assert from 'node:assert/strict';
import {Buffer} from 'node:buffer';
function evaluate(x){
const points=Array.from(x.source);if(!Number.isInteger(x.start)||!Number.isInteger(x.end)||x.start<0||x.end<x.start||x.end>points.length)return {error:'span-bounds',pointLength:points.length};
return {text:points.slice(x.start,x.end).join(''),pointLength:points.length,byteLength:Buffer.byteLength(x.source,'utf8')};
}
const cases = [
{
"id": "chinese-span",
"input": {
"source": "A中B",
"start": 1,
"end": 2
},
"expected": {
"text": "中",
"pointLength": 3,
"byteLength": 5
}
},
{
"id": "byte-end-reused",
"input": {
"source": "A中B",
"start": 1,
"end": 4
},
"expected": {
"error": "span-bounds",
"pointLength": 3
}
},
{
"id": "supplementary-symbol",
"input": {
"source": "A😀B",
"start": 1,
"end": 2
},
"expected": {
"text": "😀",
"pointLength": 3,
"byteLength": 6
}
}
];
for (const c of cases) assert.deepEqual(evaluate(c.input), c.expected, c.id);
console.log(JSON.stringify({checked:cases.length,caseIds:cases.map(c=>c.id)}));
每筆引用連同位置單位保存。此 code point 模型不是畫面字形群組模型;若按畫面選取,須另訂介面規則。