Unicode-normalisoija

Unicodessa on neljä normalisointimuotoa, eivätkä ne ole keskenään vaihtokelpoisia. NFC ja NFD järjestelevät saman merkin uudelleen yhden koodipisteen ja perusmerkin sekä yhdistävän merkin välillä; NFKC ja NFKD menevät pidemmälle ja kirjoittavat uudelleen merkit, jotka vain näyttävät toisiltaan — ligatuurin fi, täysleveän A:n, ympyröidyn ①:n, roomalaisen numeron Ⅻ:n. Tämä sivu syöttää saman tekstin kaikkien neljän läpi, tulostaa rivin per merkki kertoen, mikä muuttui ja miksi, laskee grafeemimäärän koodipisteitä ja UTF-8-tavuja vastaan ja vertaa kahta merkkijonoa valitsemallasi muodolla. Toinen puoli koskee merkkejä, joita ei näy lainkaan: nollanleveitä välilyöntejä, liittimiä, kaksisuuntaisia ohjauksia, muunnosvalitsimia, C0- ja C1-ohjausmerkkejä, yksityisen käytön koodipisteitä ja rikkinäisiä surrogaattipuoliskoja, joista kustakin näkyy sijainti ja nimi, sekä vaihtoehto poistaa ne tekstin kopiosta.
Kaikki käsittely tapahtuu paikallisesti selaimessa — tietoja ei lähetetä mihinkään palvelimelle.

Etkö ole varma, mitä normalisointi on? Unicode-normalisointi selitettynä yksinkertaisesti — miksi é voi olla yksi merkki tai kaksi, ja miksi se rikkoo kirjautumisen.
Raportoitava ja vertailtava muoto:
Vertaa kahta ruutua sen jälkeen, kun on sovellettu:
NFC (ei vielä mitään)
NFD (ei vielä mitään)
NFKC (ei vielä mitään)
NFKD (ei vielä mitään)
Vertailua ei ole vielä tehty. Liitä kaksi merkkijonoa ja paina Vertaa kahta merkkijonoa.
ensimmäinen merkkijono, normalisoitu (ei vielä mitään)
toinen merkkijono, normalisoitu (ei vielä mitään)
Tarkistusta ei ole vielä tehty. Paina Tarkista näkymättömien ja vaarallisten merkkien varalta ja sen jälkeen Poista, jos halutaan tekstin ilman näitä merkkejä.
teksti valittujen luokkien poistamisen jälkeen (ei vielä mitään)
Ctrl+Enter ensimmäisessä ruudussa suorittaa aktiivisen tilan.
Valitse tila ja napsauta sen toimintopainiketta. Normalisoi kirjoittaa tekstistäsi kaikki neljä muotoa ja rivin per merkki; Vertaa kertoo, ovatko kaksi merkkijonoa samat normalisoinnin jälkeen; Tarkista luettelee merkit, jotka eivät näy, ja voi poistaa ne. Itsetestipainike ajaa uudelleen kaikki tämän sivun tietotiedostossa dokumentoidut tapaukset, jokaisen merkin, jonka näkymättömät- ja ohjaustaulukot nimeävät, ja raportoi määrän tässä.
Jokainen merkki, yksi rivi kullekin:mikä merkki on, mitä neljä muotoa siihen tekevät ja miksi. Varjostettu rivi on merkki, jota ainakin yksi muoto muuttaa; NFD-sarake näyttää, mihin merkki hajoaa, jos se hajoaa ollenkaan.
Kuinka monta merkkiä se on?Sama teksti laskettuna neljällä tavalla: grafeemiklusterit (mitä lukija laskee), koodipisteet (mitä Unicode määrittää), UTF-16-yksiköt (mitä JavaScript indeksoi) ja UTF-8-tavut (mitä kulkee). Normalisointi siirtää lukuja toisen ja kolmannen sarakkeen välillä muuttamatta ensimmäistä.
Löydetty, siinä järjestyksessä kuin ne esiintyvät:sijainti laskee koodipisteitä, luokka on merkin kuuluva luokka, ja huomautus kertoo, mitä merkki tekee seuraavalle tekstin lukijalle.
Luokat, joita tämä sivu pitää epäilyttävinä:taulukko tulostetaan suoraan tarkistimesta, joten sivun sanat ja painikkeiden toiminta eivät voi erkaantua toisistaan. Vakavuus koskee vertailuun kohdistuvaa vaikutusta, ei sitä, kuinka todennäköisesti merkki on viaton.
Yksityisen käytön merkit luetellaan epäilyttävinä eri syystä kuin muut: ne piirtyvät, mutta niillä ei ole sovittua merkitystä, joten sama koodipiste on eri kuva jokaisessa fontissa, joka sen määrittelee.
Kuinka suuren syötteen tämä sivu hyväksyy ja miksi:normalisointi rakentaa koko merkkijonon uudelleen, ja tämä sivu tekee useita sellaisia sekä tarkistuksen ja grafeemilaskennan, joten kustannus kasvaa suoraviivaisesti syötteen pituuden mukana. Alla olevat rajat ovat olemassa, koska merkkikohtainen taulukko piirretään dokumenttiin, ja miljoonan rivin taulukko on se, mikä oikeasti pysäyttää selaimen.
Mikä on Unicode-normalisointi?

Unicode antaa joillekin merkeille useamman kirjoitustavan. Kirjain é voi olla yksi koodipiste, U+00E9, tai tavallinen e ja sen perässä yhdistävä akuutti, U+0065 U+0301. Ne näyttävät samalta ruudulla, tulostuvat samalla tavalla, ja merkkijonoina ne eroavat: niillä on eri pituus, eri UTF-8-tavut, ja 'é' === 'é' on false.

Tämä ei ole kuriositeetti, vaan bugiluokka. Saatko yhden vai toisen muodon, riippuu näppäimistöasettelusta, käyttöjärjestelmästä, syöttötavasta ja siitä, onko teksti koskaan kopioitu tekstinkäsittelyohjelman kautta. Salasanatarkistus, tietokannan uniikki indeksi, estolista tai välimuistiavain, joka vertaa merkkijonoja tavu tavulta, käsittelee kahta kirjoitusasua kahtena eri arvona — joten käyttäjä voi asettaa salasanan yhdellä laitteella eikä pääse sisään toiselta, ja sama sana voi esiintyä kahdesti "jo varattujen" nimien listassa.

Lyhyt versio: NFC ja NFD ovat sama teksti kahdella tavalla kirjoitettuna — NFC yhdistää (e + korostemerkki muuttuu yhdeksi merkiksi), NFD hajottaa (yksi merkki muuttuu e:ksi + korostemerkiksi). Ne on tarkoitettu häviöttömiksi, ja ne ovat kaksi muotoa, joita kannattaa käyttää vertailuun ja tallennukseen. NFKC ja NFKD tekevät kaiken, mitä kaksi ensimmäistä tekevät, ja korvaavat lisäksi yhteensopivuusmerkit: ligatuuri fi muuttuu kahdeksi kirjaimeksi, ½ muuttuu 1⁄2:ksi, roomalainen numero ⅲ muuttuu XII:ksi ja täysleveä A muuttuu tavalliseksi A:ksi. Juuri sitä hakemisto tai avainsanasuodatin tarvitsee, ja juuri sitä ei saa koskaan soveltaa salasanaan.
Miksi neljä muotoa eikä yksi

Jako on olemassa, koska palvelussa on kaksi eri tavoitetta. Tekstin kirjoittaminen ja hajottaminen on kanoninen muutos: tulos tarkoittaa samaa asiaa, ja kahdessa ensimmäisessä muodossa ei häviä mitään. Ligatuurien, yläindeksien, ympyröityjen kirjainten ja täysleveiden muotojen taittaminen on yhteensopivuusmuutos: se tehdään vertailun helpottamiseksi, ja se todella tuhoaa eron kahden merkkijonon välillä, jotka Unicode sanoo eriksi. Neljä muotoa ovat kaikki kahden päätöksen yhdistelmiä.

Yllä oleva taulukko on tämän sivun tietotiedoston tapauslista, tarkistettuna alustan omaa String.prototype.normalize-funktiota vastaan, ja Itsetesti tarkistaa jokaisen sen rivin näkyvillä. Lue kaksi ensimmäistä riviä yhdessä: ne ovat sama teksti kahdella tavalla kirjoitettuna, ja normalisoinnin jälkeen ne ovat sama merkkijono.

Esimerkkejä

Nämä ovat merkkijonot, joiden läpi Esimerkki-painike kulkee; sivu normalisoi ne suoraan eikä niitä kirjoiteta vastauksiksi. Jokainen on valittu, koska jokin muoto tekee niille jotain näkyvää.

Yhteensopivuusmerkit: mitä NFKC maksaa

NFKC ja NFKD hävittävät tietoa, ja häviö on tarkoituksellinen. Ne vastaavat kysymykseen "onko tämä sama sana", eivät kysymykseen "onko tämä sama merkkijono". Tästä seuraa kolme asiaa, ja kaikki kolme on helppo tehdä väärin tuotantokoodissa:

  • Älä koskaan tallenna salasanaa, tunnistetta tai allekirjoitusta yhteensopivuusmuodossa. Kaksi eri syötettä romahtaisi samaksi tallennetuksi arvoksi, mikä tekee pituus- tai merkkitarkistuksesta heikomman. Normalisoi salasanat NFC-muodossa (tai älä ollenkaan) ja vertaa niitä tavuina sen jälkeen, kun molemmilla puolilla on tehty täsmälleen sama.
  • Yhteensopivuuden taittaminen voi muuttaa yhden merkin useammaksi. Ligatuuri fi on yksi koodipiste, josta tulee kaksi kirjainta, joten kenttä, joka tarkistettiin pituuden perusteella ennen normalisointia, voi olla pidempi sen jälkeen. Normalisoi ensin, tarkista sitten, ja tallenna vasta lopuksi.
  • NFKC ei poista kaikkea näkymätöntä. Muunnosvalitsin säilyy NFKC:ssa ja NFKD:ssä, samoin nollanleveä liitin. Siksi tällä sivulla on tarkistustila: normalisointi vastaa kysymykseen merkin muodosta ja identiteetistä, tarkistin vastaa kysymykseen, onko jotain ylipäätään läsnä.
Grafeemit, koodipisteet ja tavut

Normalisointi muuttaa näistä lukumääristä toista ja jättää yleensä ensimmäisen ennalleen. Kolme lukua ovat kaikki "tekstin pituus" ja kaikki eri, minkä vuoksi 20 merkin rajoitettu lomakekenttä voi sisältää merkkijonon, joka on 20 koodipistettä, 30 UTF-16-yksikköä ja 47 tavua pitkä.

Grafeemisarakkeen luku on se, minkä ihminen laskee. Ero siihen koodipisteiden määrään on juuri se, mistä tarkistimessa on kyse: 12 koodipisteestä koostuva nimi voi näkyä 12 kirjaimena, 3 kirjaimena, joiden välissä on 9 näkymätöntä merkkiä, tai yhtenä emojina.

Merkit, joita et näe

Nollanleveä välilyönti ei vie leveyttä, ei muuta glyphiä ja on oikea merkki oikealla koodipisteellä. Kaksi tunnistetta, jotka näyttävät samalta ruudulla, voivat erota juuri sen vuoksi, ja niin luettelon nimi voi olla huijari, joka lajittelee, hakee ja tunnistautuu eri tavalla kuin viereinen nimi. Sama pätee kaksisuuntaisiin ohjauksiin, jotka voivat saada merkkijonon piirtymään eri järjestyksessä kuin se on kirjoitettu — temppua on käytetty tiedostonimien peittämiseen.

Kolmannen tilan tarkistin luettelee jokaisen niistä sijaintinsa kanssa: nollanleveät ja liitinmerkit, kaksisuuntaiset ohjaukset, muunnosvalitsimet, epätavalliset välilyönnit, C0- ja C1-ohjausmerkit, yksityisen käytön koodipisteet ja surrogaatti, joka ei ole kelvollisen parin puolikas, eikä siis merkki lainkaan. Tämän sivun yläosan luokkataulukko kertoo, mitä kukin luokka tekee, ja poistopainike poistaa kopiosta nuo merkit koskematta syötteeseesi.

Virheet, joita tämä sivu on tehty havaitsemaan
  • Kahden merkkijonon vertaaminen ilman normalisointia. 'é' === 'é' on epätosi. Normalisoi molemmat puolet samalla muodolla ennen vertailua ja käytä samaa muotoa indeksissä, johon vertaat.
  • Normalisointi vain toisella puolella. Haku, joka normalisoi kyselyn mutta ei tallennettua arvoa, ei löydä mitään, ja näyttää datavirheeltä eikä normalisointivirheeltä.
  • Lomakkeen tyylittely yhteensopivuusmuodolla ja väitetään sen olevan NFC-turvallinen. NFKC:n soveltaminen salasanaan supistaa mahdollisten salasanojen joukkoa ja yhdistää syötteitä, jotka oli tarkoitettu erillisiksi.
  • Oletus, että normalisointimuoto korjaa väärennöksen. Se ei poista nollanleveää liitintä, muunnosvalitsinta eikä homoglyfiä — kyrillinen а ja latinalainen a ovat eri koodipisteitä, joita NFC ei muuta.
  • Merkkimäärään luottaminen. Käyttäjän näkemä määrä, tietokantasarakkeen rajoittama määrä ja tavuraja ovat kolme eri lukua, ja yllä olevat rivit osoittavat, kuinka kaukana toisistaan ne voivat olla.
  • Oletus, että saadaan NFC-muodon. Syöttömenetelmästä, tiedostosta tai toisesta järjestelmästä saapuva teksti on siinä muodossa, jonka se järjestelmä tuotti. Tämä sivu alkaa oletusarvoisesti NFC-muodosta, koska verkon odotetaan käyttävän sitä, ei siksi, että syötteesi olisi sitä.
Pikavastaukset

“Miksi nämä kaksi merkkijonoa eivät ole yhtä, vaikka ne näyttävät samoilta?”

Koska toinen on kirjoitettu yhdistetyllä merkillä ja toinen perusmerkillä plus yhdistävällä merkillä, tai koska toisessa on merkki, joka ei piirrä mitään. Vaihda Vertailu-tilaan ja laita yksi merkkijono kumpaankin ruutuun: sivu raportoi ensimmäisen kohdan, jossa normalisoidut merkkijonot eroavat, ja mitä kyseisessä kohdassa on kummassakin.

“Mitä muotoa sovelluksessa tulisi käyttää?”

NFC kaikelle, minkä ihminen lukee, näyttää, tallentaa ja hakee - W3C suosittelee sitä verkkoon. NFD sopii, kun taustalla oleva koodi haluaa perusmerkit ja erilliset merkit, mikä on tavallista tekstinkäsittelyssä ja joissakin macOS-tiedostojärjestelmissä. Käytä NFKC:tä tai NFKD:tä vain silloin, kun vertaat eikä tallenna: hakemistoissa, avainsanasuodattimissa ja kaksoiskappaleiden tunnistuksessa.

“Pysyykö jo normalisoitu merkkijono normalisoituna, kun siihen liitetään jotain?”

Ei välttämättä. Liittäminen ei säilytä normalisointia: kahden NFC-merkkijonon yhdistäminen voi tuottaa sekvenssin, jonka NFC olisi kirjoittanut eri tavalla, koska toisen merkkijonon alussa oleva yhdistävä merkki voi kiinnittyä ensimmäisen lopussa olevaan merkkiin. Normalisoi kokoamisen jälkeen, ei vain ennen sitä.

“Poistaako normalisointi näkymättömät merkit?”

Ei, yhdellä osittaisella poikkeuksella: NFKC ja NFKD korvaavat sidotun välilyönnin tavallisella välilyönnillä, mikä on yhteensopivuustaittamisen näkyvä tulos. Kaikki muu — nollanleveät välilyönnit, liittimet, kaksisuuntaiset ohjaukset, muunnosvalitsimet — kulkee kaikkien neljän muodon läpi koskemattomana. Siihen kolmas tila on olemassa.

“Miksi tavumäärä muuttuu, kun merkkimäärä ei muutu?”

Koska muodot rakentuvat eri koodipisteistä, jotka vievät eri määrän tavuja UTF-8:ssa. Esisävelletty é on kaksi tavua; hajotettu pari on kolme. Yllä oleva lukutaulukko tulostaa kaikki neljä lukua rinnakkain syötteelle ja jokaiselle muodolle, joten ero näkyy eikä sitä vain kuvata.

“Mistä tiedän, että tämän sivun tulokset ovat oikein?”

Paina Itsetesti. Se normalisoi jokaisen tämän sivun tietotiedoston tapauksen, tarkistaa neljä muotoa keskenään dokumentoitujen suhteiden varalta (NFC on idempotentti, NFC:n NFD on sama kuin alkuperäisen NFD jne.), ajaa jokaisen näkymättömien ja ohjausmerkkien taulukoiden nimeämän merkin tarkistimen läpi ja laskee grafeemitapaukset Intl.Segmenter-kirjastoa vastaan.

Standardit ja tekijyys

Neljä muotoa ja niiden määritelmät ovat peräisin Unicode-standardin liitteestä 15 (Unicode Normalization Forms). Hajotusesimerkeissä käytetyt koodipisteet ovat standardin määrittelemiä; tämä sivu ei itse toteuta hajotustaulukoita — se kutsuu selaimen omaa String.prototype.normalize-funktiota, joka on sama toteutus, jota alusta käyttää tekstisyötteessä, lajittelussa ja vertailussa, joten tässä raportoitu on sama, mitä muu järjestelmä tekee samalle merkkijonolle. Grafeemiklusterit tulevat Intl.Segmenter-kirjastosta, kun selain sen tarjoaa, ja dokumentoidusta approksimaatiosta muuten.

Sivun teksti on kirjoitettu tälle sivustolle. Jokainen tämän sivun työstetty esimerkki on tuotettu sivun omalla koodilla ja tarkistettu tietotiedoston kirjattua tapauslistaa vastaan, joka puolestaan on tarkistettu saman merkkien Unicode NormalizationTest-aineistoa vastaan. Näkymättömien ja vaarallisten merkkien taulukot ovat kuratoitu osajoukko ihmisluettaviin varoituksiin, eivät täydellinen Unicode-turvaprofiili (UTS #39), ja sivu sanoo tämän sen sijaan, että viittaisi täydellisyyteen, jota sillä ei ole.