Every way of counting a string at once — UTF-8 bytes, UTF-16 code units, code points and grapheme clusters — plus the code point behind each character and a flag on anything invisible, combining or deceptive.
The four counts disagree, which is the usual source of truncated emoji and off-by-one column limits: a database VARCHAR(n) counts one of them, your validator probably counts another.
Code points above U+FFFF take two UTF-16 units, so slicing by JS string index can cut one in half.
| # | Char | Code point | Name | UTF-8 | UTF-16 | Escape |
|---|---|---|---|---|---|---|
| 0 | c | U+0063 | ASCII | 63 | 0063 | \u0063 |
| 1 | a | U+0061 | ASCII | 61 | 0061 | \u0061 |
| 2 | f | U+0066 | ASCII | 66 | 0066 | \u0066 |
| 3 | é | U+00E9 | Latin-1 supplement | C3 A9 | 00E9 | \u00E9 |
| 4 | ␣ | U+0020 | Whitespace | 20 | 0020 | \u0020 |
| 5 | 👋 | U+1F44B | Supplementary plane | F0 9F 91 8B | D83D DC4B | \u{1F44B} |
| Form | Code points | UTF-8 bytes | Changes input | Result |
|---|---|---|---|---|
| NFC | 6 | 10 | no | café 👋 |
| NFD | 7 | 11 | yes | café 👋 |
| NFKC | 6 | 10 | no | café 👋 |
| NFKD | 7 | 11 | yes | café 👋 |
63 61 66 c3 a9 20 f0 9f 91 8b
marduc812
© 202620260824_1c411cc