Normalizátor Unicode

Unicode má štyri normalizačné formy a nie sú zameniteľné. NFC a NFD prerovnávajú ten istý znak medzi jedným kódovým bodom a základom plus kombinujúcou značkou; NFKC a NFKD idú ďalej a prepisujú znaky, ktoré sa len podobajú jeden druhému — ligatúru fi, plnošírkové A, krúžkovanú ①, rímsku číslicu Ⅻ. Táto stránka prežene ten istý text všetkými štyrmi, vypíše riadok na znak s uvedením, čo sa zmenilo a prečo, spočíta grafémy oproti kódovým bodom a bajtom UTF-8 a porovná dva reťazce podľa formy, ktorú zvolíte. Druhá polovica sa týka znakov, ktoré sa vôbec neobjavia: nulové medzery, spojky, obojsmerné riadiace znaky, výberové znaky variácií, riadiace znaky C0 a C1, kódové body súkromného použitia a poškodené polovice náhradných dvojíc, každý s pozíciou a názvom a s možnosťou ich odstrániť z kópie textu.
Všetky výpočty prebiehajú lokálne v prehliadači — údaje sa nikdy nenahrávajú na žiadny server.

Nie je jasné, čo je normalizácia? Normalizácia Unicode vysvetlená obyčajnou rečou — prečo môže byť é jeden znak alebo dva a prečo to rozbije prihlásenie.
Forma na vykázanie a porovnanie:
Dve políčka sa po použití porovnajú:
NFC (zatiaľ nič)
NFD (zatiaľ nič)
NFKC (zatiaľ nič)
NFKD (zatiaľ nič)
Zatiaľ nič nie je porovnané. Vložia sa dva reťazce a stlačí sa Porovnať dva reťazce.
prvý reťazec, normalizovaný (zatiaľ nič)
druhý reťazec, normalizovaný (zatiaľ nič)
Zatiaľ nič nie je skenované. Stlačí sa Skontrolovať neviditeľné a nebezpečné znaky, potom Odstrániť, ak sa chce text bez týchto znakov.
text bez zvolených tried znakov (zatiaľ nič)
Ctrl+Enter v prvom políčku spustí aktívny režim.
Zvolí sa režim a klikne sa na jeho akčné tlačidlo. Normalizovať zapíše všetky štyri formy textu a riadok na každý znak; Porovnať povie, či sú dva reťazce po normalizácii rovnaké; Skenovať vypíše znaky, ktoré sa nezobrazia, a dá sa z nich text vyčistiť. Tlačidlo Samotest znovu spustí každý zdokumentovaný prípad v dátovom súbore tejto stránky, každý znak uvedený v tabuľkách neviditeľných a riadiacich znakov, a nahlási počet tu.
Každý znak, jeden riadok na znak:čo je znak, čo s ním robí každá zo štyroch foriem a prečo. Zatienený riadok je znak, ktorý aspoň jedna forma mení; stĺpec NFD ukazuje, na čo sa znak rozloží, ak sa vôbec rozkladá.
Koľko znakov to je?Ten istý text spočítaný štyrmi spôsobmi: zhluky grafém (čo počíta čitateľ), kódové body (čo Unicode priraďuje), jednotky UTF-16 (čo JavaScript indexuje) a bajty UTF-8 (čo sa prenáša). Normalizácia presúva čísla medzi druhým a tretím stĺpcom bez zmeny prvého.
Čo sa našlo, v poradí výskytu:pozícia počíta kódové body, trieda je tá, do ktorej znak patrí, a poznámka hovorí, čo tento znak urobí s tým, čo text číta ďalej.
Triedy, ktoré táto stránka považuje za podozrivé:tabuľka sa vypisuje priamo zo skenera, takže slová na tejto stránke a správanie tlačidiel sa nemôžu rozísť. Závažnosť sa týka účinku na porovnanie, nie toho, aký je znak pravdepodobne nevinný.
Znaky súkromného použitia sú označené ako podozrivé z iného dôvodu než ostatné: vykreslia sa, len nemajú dohodnutý význam, takže ten istý kódový bod je iný obrázok v každom písme, ktoré ho definuje.
Aký veľký vstup táto stránka prijíma a prečo:Normalizácia je prestavba celého reťazca a táto stránka robí niekoľko takých prestavieb plus skenovanie a počítanie grafém, takže náklad rastie priamo úmerne dĺžke vstupu. Limity nižšie existujú, lebo tabuľka po jednom znaku sa kreslí v dokumente a tabuľka s miliónom riadkov je presne to, čo prehliadač zastaví.
Čo je normalizácia Unicode?

Unicode dáva pre niektoré znaky viac než jeden spôsob zápisu. Písmeno é môže byť jediný kódový bod, U+00E9, alebo obyčajné e za ktorým nasleduje kombinujúca akútová značka, U+0065 U+0301. Obe vyzerajú na obrazovke rovnako, vytlačia sa rovnako, a ako reťazce sú rôzne: majú iné dĺžky, iné bajty UTF-8 a 'é' === 'é' je false.

To nie je zvedavosť, je to trieda chýb. To, či sa dostane jedna alebo druhá forma, závisí od rozloženia klávesnice, operačného systému, vstupnej metódy a od toho, či sa text niekedy skopíroval cez textový procesor. Kontrola hesla, jedinečný index databázy, zoznam zakázaných alebo kľúč vyrovnávacej pamäte, ktorý porovnáva reťazce bajt po bajte, bude obe podoby považovať za dve rôzne hodnoty — takže používateľ môže nastaviť heslo na jednom zariadení a nemôže sa prihlásiť z iného a to isté slovo sa môže v zozname „už obsadených“ mien objaviť dvakrát.

Verzia na 30 sekúnd: NFC a NFD sú ten istý text zapísaný dvoma spôsobmi — NFC skladá (e + diakritika sa stane jedným znakom), NFD rozkladá (jeden znak sa stane e + diakritika). Majú byť bezstratové a sú to dve formy, ktoré sa používajú na porovnávanie a ukladanie. NFKC a NFKD robia všetko, čo prvé dve, a navyše nahrádzajú znaky kompatibility: ligatúra fi sa stane dvomi písmenami, ½ sa stane 1⁄2, rímska číslica ⅲ sa stane XII, plnošírkové A sa stane obyčajným A. Presne to chce vyhľadávací index alebo filter kľúčových slov a presne to nesmie nikdy použiť na heslo.
Prečo štyri formy a nie jedna

Rozdelenie existuje, pretože slúžia dva rozdielne ciele. Zloženie a rozklad textu je kanonická zmena: výsledok znamená to isté a pri prvých dvoch formách sa nič nestráca. Zjednotenie ligatúr, horných indexov, krúžkovaných písmen a plnošírkových tvarov je zmena kompatibility: robí sa kvôli pohodlnosti porovnávania a naozaj zrušuje rozlíšenie dvoch reťazcov, ktoré Unicode považuje za rozdielne. Štyri formy sú všetky kombinácie oboch rozhodnutí.

Tabuľka vyššie je zoznam prípadov z dátového súboru tejto stránky, overený voči vlastnému String.prototype.normalize platformy, a Samotest každý jej riadok znovu overí pred zobrazením. Prvé dva riadky sa čítajú spoločne: je to ten istý text zapísaný dvoma spôsobmi a po normalizácii je to ten istý reťazec.

Prepracované príklady

Toto sú reťazce, ktorými prechádza tlačidlo Vzorka; stránka ich normalizuje naživo namiesto toho, aby ich ponúkala ako hotové odpovede. Každý bol vybraný preto, že na ňom forma urobí niečo viditeľné.

Znaky kompatibility: čo stojí NFKC

NFKC a NFKD sú stratové a strata je zámerná. Odpovedajú na otázku „je to to isté slovo“, nie na otázku „je to ten istý reťazec“. Z toho vyplývajú tri dôsledky, všetky sa v produkčnom kóde ľahko pokazia:

  • Heslo, token ani podpis sa nikdy neukladajú v tvare kompatibility. Dva rôzne vstupy by sa zlúčili do rovnakej uloženej hodnoty, čo kontrolu dĺžky alebo znakov oslabí. Heslá sa normalizujú cez NFC (alebo vôbec) a porovnávajú sa ako bajty po tom, čo sa na oboch stranách urobí presne to isté.
  • Zhodnocovanie kompatibility môže jeden znak premeniť na niekoľko. Ligatúra fi je jeden kódový bod, ktorý sa stane dvomi písmenami, takže pole overené na dĺžku pred normalizáciou môže byť po nej dlhšie. Najprv sa normalizuje, potom overí a až potom uloží.
  • NFKC neodstráni všetko neviditeľné. Výberový znak variácie prežije NFKC aj NFKD a rovnako nulová spojka. Preto má táto stránka režim skenovania: normalizácia odpovedá na otázku o tvare a identite znaku, skener odpovedá na otázku, či tam niečo vôbec je.
Grafémy, kódové body a bajty

Normalizácia mení druhý z týchto počtov a zvyčajne prvý nechá tak. Všetky tri čísla sú „dĺžka textu“ a všetky sú rôzne, a preto môže pole s limitom 20 znakov obsahovať reťazec, ktorý má 20 kódových bodov, 30 jednotiek UTF-16 a 47 bajtov.

Číslo v stĺpci grafém je to, čo človek spočíta. Rozdiel oproti počtu kódových bodov je presne to, čím sa zaoberá skener: meno zložené z 12 kódových bodov sa môže zobraziť ako 12 písmen, ako 3 písmená s 9 neviditeľnými značkami medzi nimi, alebo ako jedno emoji.

Znaky, ktoré nevidíte

Nulová šírka medzery nezaberá žiadnu šírku, nemení glyf a je to skutočný znak so skutočným kódovým bodom. Dva identifikátory, ktoré vyzerajú na obrazovke rovnako, sa môžu líšiť práve jedným z nich, a tak môže meno v zozname byť podvrhnuté: triedi sa, vyhľadáva a overuje inak než meno vedľa neho. To isté platí pre obojsmerné riadiace znaky, ktoré môžu spôsobiť, že reťazec sa vykreslí v inom poradí, než v akom bol zapísaný — tento trik sa použil na maskovanie názvov súborov.

Skener v treťom režime vypíše každý z nich s pozíciou: nulová šírka a spojky, obojsmerné riadiace znaky, výberové znaky variácií, nezvyčajné medzery, riadiace znaky C0 a C1, kódové body súkromného použitia a náhradný znak, ktorý nie je polovicou platnej dvojice, čo vôbec nie je znak. Tabuľka tried vyššie na tejto stránke hovorí, čo každá trieda robí, a tlačidlo odstránenia odstráni kópiu týchto znakov bez toho, aby sa dotklo vstupu.

Chyby, na ktoré je táto stránka navrhnutá
  • Porovnávanie dvoch reťazcov bez normalizácie. 'é' === 'é' je nepravda. Obe strany sa normalizujú rovnakou formou pred porovnaním a rovnaká forma sa použije aj v indexe, s ktorým sa porovnáva.
  • Normalizácia iba na jednej strane. Vyhľadávanie, ktoré normalizuje dopyt, ale nie uloženú hodnotu, nič nenájde a vyzerá to ako problém s dátami, nie s normalizáciou.
  • Štylizovanie formulára formou kompatibility a označenie za bezpečné pre NFC. NFKC aplikovaný na heslo zmenší priestor možných hesiel a zlúči vstupy, ktoré mali byť rozdielne.
  • Predpoklad, že normalizačná forma opraví podvrh. Neodstráni nulovú spojku, výberový znak variácie ani homoglyf — cyrilské а a latinské a sú rôzne kódové body, ktoré NFC nechá tak, ako sú.
  • Dôverovanie počtu znakov. Počet, ktorý vidí používateľ, počet, ktorý vynucuje stĺpec databázy, a počet, ktorý vynucuje limit bajtov, sú tri rôzne čísla a riadky vyššie ukazujú, ako ďaleko od seba môžu byť.
  • Predpoklad, že text je už v NFC. Text, ktorý príde zo vstupnej metódy, zo súboru alebo z iného systému, je v tej forme, akú vytvoril ten systém. Táto stránka začína na NFC, lebo to je forma, ktorú web očakáva, nie preto, že to je to, čo je na vstupe.
Rýchle odpovede

„Prečo nie sú tieto dva reťazce rovnaké, keď vyzerajú rovnako?“

Pretože jeden z nich je zapísaný zloženým znakom a druhý základným písmenom plus kombinujúcou značkou, alebo jeden obsahuje znak, ktorý sa vôbec nekreslí. Prepne sa do režimu Porovnanie a jeden reťazec sa vloží do každého políčka: stránka nahlási prvú pozíciu, kde sa normalizované reťazce líšia, a čo je na tej pozícii v každom z nich.

„Ktorú formu mám použiť v aplikácii?“

NFC pre všetko, čo bude čítať, zobrazovať, ukladať a vyhľadávať človek; je to forma, ktorú W3C odporúča pre web. NFD je správna voľba, keď kód na strane spracovania chce základné písmená a samostatné značky, čo je bežné pri spracovaní textu a v niektorých súborových systémoch na macOS. NFKC alebo NFKD sa použijú len tam, kde sa niečo zhoduje, a nie ukladá: vyhľadávacie indexy, filtre kľúčových slov, detekcia duplicít.

„Zostáva reťazec, ktorý je už normalizovaný, normalizovaný aj po tom, čo k nemu niečo pripojím?“

Nie nutne. Normalizácia sa spojením nezachováva: spojenie dvoch reťazcov NFC môže vytvoriť postupnosť, ktorú by NFC zapísalo inak, lebo kombinujúca značka na začiatku druhého reťazca sa môže pripojiť k znaku na konci prvého. Normalizuje sa až po zostavení, nie len pred ním.

„Odstraňuje normalizácia neviditeľné znaky?“

Nie, s jednou čiastočnou výnimkou: NFKC a NFKD nahradia nezalomiteľnú medzeru obyčajnou medzerou, čo je viditeľný výsledok zhodnotenia kompatibility. Všetko ostatné — nulové medzery, spojky, obojsmerné riadiace znaky, výberové znaky variácií — prejde všetkými štyrmi formami nedotknuté. Na to slúži tretí režim.

„Prečo sa mení počet bajtov, keď sa počet znakov nemení?“

Pretože tieto dve formy sú zostavené z rôznych kódových bodov, ktoré v UTF-8 stoja rôzny počet bajtov. Predskladané é sú dva bajty; rozložený pár sú tri. Tabuľka počtov vyššie vypíše všetky štyri čísla vedľa seba pre vstup a pre každú formu, takže rozdiel je viditeľný, nie len opísaný.

„Ako viem, že výsledky na tejto stránke sú správne?“

Kliknutím na Samotest sa normalizuje každý prípad v dátovom súbore tejto stránky, znovu overí štyri formy voči sebe navzájom pre zdokumentované vzťahy (NFC je idempotentné, NFD reťazca NFC je rovnaké ako NFD pôvodného atď.), prevedie každý znak uvedený v tabuľkách neviditeľných a riadiacich znakov skenerom a porovná počty grafém s Intl.Segmenter.

Normy a zdroje

Štyri formy a ich definície pochádzajú z Unicode Standard, Annex 15 (Unicode Normalization Forms). Kódové body použité ako príklady rozkladu sú tie, ktoré štandard priraďuje; táto stránka nevykonáva tabuľky rozkladu sama — volá vlastné String.prototype.normalize prehliadača, teda rovnakú implementáciu, akú platforma používa na vstup textu, triedenie a porovnávanie, takže to, čo sa tu uvádza, je to, čo s tým istým reťazcom robí zvyšok systému. Zhluky grafém pochádzajú z Intl.Segmenter, ak ho prehliadač má, a z zdokumentovanej aproximácie, ak nie.

Text stránky bol napísaný pre tento web. Každý prepracovaný príklad na tejto stránke vytvoril kód tejto stránky a potom bol overený voči zaznamenanému zoznamu prípadov v dátovom súbore, ktorý bol zase overený voči dátam NormalizationTest Unicode pre tie isté znaky. Tabuľky neviditeľných a nebezpečných znakov sú kurátorská podmnožina napísaná na čitateľné upozornenia, nie úplný bezpečnostný profil Unicode (UTS #39), a stránka to hovorí otvorene, namiesto toho, aby naznačovala úplnosť, ktorú nemá.