Download big5.js from HelloSun/dosllm: direct link, hf CLI and curl.
- Browser
- Download file 3.52 kB
-
https://huggingface.co/spaces/HelloSun/dosllm/resolve/main/big5.js
- Command line
-
hf download hf://spaces/HelloSun/dosllm/big5.js
-
curl -L -o big5.js https://huggingface.co/spaces/HelloSun/dosllm/resolve/main/big5.js
3.52 kB
| /* | |
| * Big5 <-> Unicode helpers (the encoding XiaoMao Chinese shows on the DOS screen). | |
| * Decoding uses the browser's built-in TextDecoder('big5'); encoding is a reverse table built from it | |
| * (lead A1..F9, trail 40..7E / A1..FE: the range XiaoMao's font covers). Characters outside Big5 | |
| * (Simplified Chinese, emoji, ...) cannot be shown by DOS and become '?'. | |
| */ | |
| (function () { | |
| 'use strict'; | |
| let dec = null; | |
| try { dec = new TextDecoder('big5'); } catch (e) { dec = null; } | |
| const toCode = new Map(); | |
| if (dec) { | |
| const pair = new Uint8Array(2); | |
| for (let lead = 0xA1; lead <= 0xF9; lead++) { | |
| for (let trail = 0x40; trail <= 0xFE; trail++) { | |
| if (trail > 0x7E && trail < 0xA1) continue; | |
| pair[0] = lead; pair[1] = trail; | |
| const s = dec.decode(pair); | |
| if (s.length === 1 && s !== '\uFFFD' && !toCode.has(s)) toCode.set(s, (lead << 8) | trail); // lowest code wins | |
| } | |
| } | |
| } | |
| const isLead = (b) => b >= 0xA1 && b <= 0xF9; | |
| const isTrail = (b) => (b >= 0x40 && b <= 0x7E) || (b >= 0xA1 && b <= 0xFE); | |
| const Big5 = { | |
| available: !!dec && toCode.size > 10000, | |
| size: toCode.size, | |
| hasHighBytes: (bytes) => bytes.some((b) => b >= 0x80), | |
| // Big5 bytes -> JS string (NUL shown as space) | |
| decode(bytes) { return dec ? dec.decode(Uint8Array.from(bytes, (b) => (b === 0 ? 0x20 : b))) : String.fromCharCode(...bytes); }, | |
| // JS string -> { bytes, lost }: ASCII as is, Big5 characters as two bytes, anything else '?' | |
| encode(str) { | |
| const out = []; const lost = []; | |
| for (const ch of str) { | |
| const cp = ch.codePointAt(0); | |
| if (cp < 0x80) out.push(cp); | |
| else if (toCode.has(ch)) { const c = toCode.get(ch); out.push(c >> 8, c & 255); } | |
| else { out.push(0x3F); lost.push(ch); } | |
| } | |
| return { bytes: Uint8Array.from(out), lost }; | |
| }, | |
| // what the DOS screen can actually show for this text (lost characters -> '?') | |
| displayable(str) { return Array.from(str, (ch) => (ch.codePointAt(0) < 0x80 || toCode.has(ch) ? ch : '?')).join(''); }, | |
| // JSON text from Gradio is ASCII with \uXXXX escapes: turn every non-ASCII escape (or raw non-ASCII | |
| // character) into Big5 bytes (or '?'), keep every other escape as it is, return bytes. | |
| jsonToBig5Bytes(text) { | |
| const out = []; | |
| const put = (cp) => { | |
| const ch = String.fromCodePoint(cp); | |
| if (cp < 0x80) out.push(cp); | |
| else if (toCode.has(ch)) { const c = toCode.get(ch); out.push(c >> 8, c & 255); } | |
| else out.push(0x3F); | |
| }; | |
| for (let i = 0; i < text.length;) { | |
| const ch = text[i]; | |
| if (ch === '\\' && i + 1 < text.length) { | |
| if (text[i + 1] === 'u' && /^[0-9a-fA-F]{4}$/.test(text.substr(i + 2, 4))) { | |
| let cp = parseInt(text.substr(i + 2, 4), 16); i += 6; | |
| if (cp >= 0xD800 && cp <= 0xDBFF && text.substr(i, 2) === '\\u' && /^[dD][c-fC-F][0-9a-fA-F]{2}$/.test(text.substr(i + 2, 4))) { | |
| cp = 0x10000 + ((cp - 0xD800) << 10) + (parseInt(text.substr(i + 2, 4), 16) - 0xDC00); i += 6; | |
| } | |
| if (cp < 0x80) { out.push(0x5C, 0x75, ...Array.from(cp.toString(16).padStart(4, '0'), (c) => c.charCodeAt(0))); } // keep \u00XX escapes of ASCII | |
| else put(cp); | |
| } else { out.push(0x5C, text.charCodeAt(i + 1) & 0x7F); i += 2; } | |
| } else { const cp = text.codePointAt(i); i += cp > 0xFFFF ? 2 : 1; put(cp); } | |
| } | |
| return Uint8Array.from(out); | |
| }, | |
| }; | |
| window.Big5 = Big5; | |
| })(); | |