charset
import charset from "charset";
let text: string = charset.decode_label("iso-8859-1", body) or {
charset.decode(charset.Encoding.Windows1252, body)
};Tape’s text is UTF-8. charset turns text in other encodings into UTF-8:
mail in ISO-8859-2, an old file in windows-1251, a Japanese message in
Shift_JIS or ISO-2022-JP.
It has every encoding of the WHATWG Encoding Standard, the one browsers and mail readers use, with its names and labels, plus UTF-7 and IMAP’s mailbox-name encoding.
Decoding never fails. Bytes that aren’t valid in the encoding become
U+FFFD (�), so a damaged message still shows.
Encodings
| Family | Encoding values |
|---|---|
| Unicode | Utf8, Utf16Le, Utf16Be, Utf7 |
| Western and Central European | Windows1252, Windows1250, Iso8859_2 … Iso8859_16, Macintosh |
| Cyrillic | Windows1251, Koi8R, Koi8U, Ibm866, Iso8859_5, XMacCyrillic |
| Greek, Turkish, Baltic, Vietnamese | Windows1253, Windows1254, Windows1257, Windows1258, Iso8859_7 … |
| Hebrew, Arabic, Thai | Windows1255, Iso8859_8, Iso8859_8I, Windows1256, Iso8859_6, Windows874 |
| Chinese | Gbk, Gb18030, Big5 |
| Japanese | ShiftJis, EucJp, Iso2022Jp |
| Korean | EucKr |
| Other | Replacement, XUserDefined |
"{e}" is an encoding’s standard name (windows-1252, Shift_JIS).
Labels
| Function | Does |
|---|---|
lookup(label) -> ?Encoding | The encoding a label names, or null |
bom(data) -> ?Encoding | The encoding a byte order mark at the start announces, or null |
A label is what a mail’s charset= or an HTTP header says. lookup
accepts every label of the Standard, in any case and with white space
around it: utf8, latin1, cp1251, gb2312, x-sjis,
ks_c_5601-1987, and UTF-7’s utf-7.
As in browsers, us-ascii, iso-8859-1 and latin1 mean windows-1252:
mail labelled ISO-8859-1 is very often windows-1252 (curly quotes, €).
An unknown label is null. What to do then is your choice; mail readers
usually fall back to windows-1252.
Decoding
| Function | Does |
|---|---|
decode(enc, data) -> string | data in encoding enc, as UTF-8 |
decode_label(label, data) -> string or CharsetError | The same by label; UnknownLabel for an unknown one |
let e: charset.Encoding = charset.lookup("Shift_JIS") or { return 1; };
io.println(charset.decode(e, data));A byte order mark of the encoding itself is removed: EF BB BF before
UTF-8, FF FE before UTF-16LE. The label decides the encoding, not the
mark. To let a mark override the label, as browsers do, write
charset.decode(charset.bom(data) or { enc }, data).
IMAP mailbox names
IMAP sends mailbox names in a modified UTF-7: Entwürfe is Entw&APw-rfe.
| Function | Does |
|---|---|
imap_utf7_decode(name) -> string or CharsetError | A name from the server, as UTF-8 |
imap_utf7_encode(name) -> string | A UTF-8 name, as the server wants it |
let shown: string = charset.imap_utf7_decode("Entw&APw-rfe") or { return 1; }; // Entwürfe
let sent: string = charset.imap_utf7_encode("Entwürfe"); // Entw&APw-rfeimap_utf7_decode is strict: a malformed name is CharsetError.Malformed,
not a guess, because the name goes back to the server to select the
mailbox. A server that has enabled UTF8=ACCEPT sends plain UTF-8; don’t
decode those.
Size
The tables (185 KB, most of it for Chinese, Japanese and Korean) are built
into every program that imports charset, and into no other.
Last modified: