[Перевод] Этот восхитительный Юникод
Перед вами обновляемый список самых замечательных «вкусностей» Юникода, а также пакетов и ресурсов
Юникод — это потрясающе! До его появления международная коммуникация была изнурительной: каждый определял свой отдельный расширенный набор символов в верхней половине ASCII (так называемые кодовые страницы). Это порождало конфликты. Просто подумайте, что немцам приходилось договариваться с корейцами, где чья кодовая страница на 127 символа. К счастью, появился Юникод и унифицировал коммуникации. Стандарт Юникод 8.0 охватывает более 120 000 символов из более 129 письменностей. И современные, и древние, и до сих пор не расшифрованные. Юникод поддерживает текст слева направо и справа налево, наложение символов и включает самые разные культурные, политические, религиозные символы и эмодзи. Юникод потрясающе человечен, а его возможности сильно недооцениваются.
Какие символы входят в Стандарт Юникод?
Стандарт Юникод определяет коды для символов основных современных языков. Это европейские алфавитные письменности, ближневосточные письменности справа налево и многие письменности Азии.
Стандарт также содержит знаки пунктуации, диакритические знаки, математические символы, технические символы, стрелки, дингбаты, эмодзи и т. д. Он предоставляет коды для диакритических знаков, изменяющих знаки символов, такие как тильда (~). Они используются в сочетании с основными для представления акцентированных символов (например, ñ). В целом, Юникод версии 9.0 предоставляет коды для 128 172 символов из мировых алфавитов, наборов идеограмм и коллекций символов.
Большинство символов общего пользования помещаются в первые 64K кодовых точек, область кодового пространства, которая называется основной многоязычной плоскостью, или BMP для краткости. Есть ещё шестнадцать других дополнительных плоскостей, доступных для кодирования других символов, с более чем 850 000 неиспользуемых кодовых точек. Они могут пригодиться для добавления новых символов в будущие версии стандарта.
Стандарт Юникод также резервирует кодовые точки для частного использования. Вендоры или конечные пользователи могут назначать их в своих собственных системах для своих символов или использовать со специализированными шрифтами. На BMP находится 6400 кодовых точек для частного использования и ещё 131 068 дополнительных кодовых точек частного использования, если 6400 недостаточно для конкретных приложений.
Кодировки символов Юникода
Стандарты кодирования символов определяют не только идентичность каждого символа и его числовое значение или кодовую точку, но и то, как это значение представлено в битах.
Стандарт Юникод определяет три формы кодирования, которые позволяют передавать одни и те же данные: это байт, слово и двойное слово (то есть 8, 16 или 32 бит на единицу кода). Все три формы кодируют один и тот же общий набор символов и могут быть эффективно преобразованы друг в друга без потери данных. Консорциум Юникод полностью одобряет использование любой из этих форм кодирования в качестве согласованного способа реализации Стандарта Юникод.
UTF-8 популярен для HTML и подобных протоколов. UTF-8 — это способ преобразования всех символов Юникода в кодировку переменной байтовой длины. Его преимущество в том, что символы Юникода, соответствующие знакомому набору ASCII, имеют те же байтовые значения, что и ASCII, а символы Юникода, преобразованные в UTF-8, могут использоваться с большим количеством существующего программного обеспечения без серьёзной доработки ПО.
UTF-16 популярен во многих средах, где необходимо сбалансировать эффективный доступ к символам с экономичным хранением. Он достаточно компактен, и все часто используемые символы помещаются в один 16-битный кодовый блок, в то время как все остальные символы доступны через пары 16-битных кодовых блоков.
UTF-32 полезен там, где объём памяти не вызывает беспокойства, но требуется доступ к символам по единому коду фиксированной ширины. Здесь каждый символ Юникода кодируется в одном 32-разрядном кодовом блоке.
Все три формы кодирования требуют для каждого символа не более 4 байт (или 32 бит).
Поговорим о цифрах
Набор символов Юникода разделён на 17 основных сегментов (плоскостей), которые далее делятся на блоки. В каждой плоскости есть место для 65 536 (216) кодовых точек, что создаёт в сумме 1 114 112 кодовых точек. Есть две «плоскости частного использования» (№ 16 и № 17), которые выделяются для использования на усмотрение компаний/пользователей. В них 131 072 кодовые точки.
Первая плоскость называется основной многоязычной плоскостью или BMP. Она содержит кодовые точки от U+0000 до U+FFFF, то есть наиболее часто используемые символы. Остальные шестнадцать плоскостей (U+010000 → U+10FFFF) называются дополнительными или астральными.
Суррогатные пары UTF-16
Символы вне основной плоскости, как тетраграмматон, означающий центр (U+1D306), можно закодировать в UTF-16 только двумя 16-битными кодовыми единицами: 0xD834 0xDF06. Это называется суррогатной парой. Обратите внимание, что суррогатная пара представляет только один символ.Первая кодовая единица суррогатной пары всегда находится в диапазоне от 0xD800 до 0xDBFF и называется верхней частью пары.
Вторая кодовая единица суррогатной пары всегда находится в диапазоне от 0xDC00 до 0xDFFF и называется нижней частью пары.
Матиас Байненс
Суррогатная пара: представление одного абстрактного символа, состоящего из последовательности двух 16-разрядных кодовых единиц, где первое значение пары является верхней суррогатной кодовой единицей, а второе — нижней суррогатной кодовой единицей. Суррогатные пары используются только в UTF-16.Unicode 8.0 Глава 3.8 − Суррогаты
Вычисление суррогатных пар
Юникодовский символ «Куча дерьма» (U+1F4A9) в UTF-16 придётся кодировать как суррогатную пару, т. е. два суррогата. Чтобы преобразовать любую кодовую точку в суррогатную пару, используйте такой алгоритм (на JavaScript). Имейте в виду, что мы используем шестнадцатеричную нотацию.
var High_Surrogate = function(Code_Point){ return Math.floor((Code_Point - 0x10000) / 0x400) + 0xD800 };
var Low_Surrogate = function(Code_Point){ return (Code_Point - 0x10000) % 0x400 + 0xDC00 };
// Reverses The Conversion
var Code_Point = function(High_Surrogate, Low_Surrogate){
return (High_Surrogate - 0xD800) * 0x400 + Low_Surrogate - 0xDC00 + 0x10000;
};
> var codepoint = 0x1F4A9; // 0x1F4A9 == 128169
> High_Surrogate(codepoint).toString(16)
"d83d" // 0xD83D == 55357
> Low_Surrogate(codepoint).toString(16)
"dca9" // 0xDCA9 == 56489
> String.fromCharCode( High_Surrogate(codepoint) , Low_Surrogate(codepoint) );
""
> String.fromCodePoint(0x1F4A9)
""
> '\ud83d\udca9'
""
Композиция и декомпозиция
Юникод включает в себя механизм для изменения формы символа, который значительно расширяет поддерживаемый набор глифов. Это касается комбинируемых диакритических знаков. Они вставляются после главного знака. На один и тот же знак можно наложить несколько комбинируемых диакритических знаков. Юникод также содержит предварительно составленные версии большинства таких комбинаций для нормального использования.
Некоторые последовательности символов также можно представить в виде одного символа, который называется предварительно составленным символом (precomposed character), он же составной символ (composite character). Например, символ [ü] можно закодировать как единственную кодовую точку U+00FC или как базовый символ U+0075 (u), за которым следует несамостоятельный знак U+0308 (¨). Стандарт Юникод кодирует составные символы для совместимости с установленными стандартами, такими как Latin 1, который включает в себя множество составных символов, таких как [ü] и [ñ].
Составные символы можно разложить для согласованности или анализа. Например, при сортировке имён по алфавиту символ [ü] можно разложить на [u], за которым следует несамостоятельный знак [¨]. После такой декомпозиции алгоритму проще работать с последовательностью символов. Это позволяет упростить сортировку в языках, где модификаторы символов не влияют на алфавитный порядок. Стандарт Юникод устанавливает порядок декомпозиции для всех составных символов. Он также определяет формы нормализации для обеспечения уникальных представлений символов.
Мифы о Юникоде
Из слайдов презентации Марка Дэвиса «Мифы Юникода».
- Юникод — это просто 16-битный код. — Некоторые ошибочно полагают, что Юникод — это просто 16-битный код, в котором каждый символ занимает 16 бит, и поэтому существует 65 536 возможных символов. На самом деле это не совсем так. Это самый распространённый миф о Юникоде, так что если вы тоже так думали раньше, не расстраивайтесь.
- Можно взять для своих нужд любую кодовую точку, которая не используется. — Нет. Когда-нибудь это место займёт другой символ. Вместо этого используйте плоскости для частного использования или области без символов в каждой плоскости, где по стандарту не будет никаких символов.
- Каждая кодовая точка Юникода представляет символ. — Нет. Есть много точек без символов (FFFE, FFFF, 1FFFE и др.) Кроме того, суррогатные кодовые точки, приватные и неиспользуемые кодовые точки, а также управляющие/форматирующие «символы» (RLM, ZWNJ и др.)
- В Юникоде заканчивается место. — Если бы оно заполнялось линейно, то закончилось бы в 2140 году. Но место не заполняется линейно. Планы на будущее см. здесь.
- Все знаки сопоставляются один к одному. — Нет. Возможны варианты:
- Один ко многим: (β → SS)
- С учётом контекста: (…Σ ←→ …ς и в то же время …ΣΤ… ←→ …στ…)
- С учётом локали: (I ←→ ı и в то же время İ ←→ i)
- Один ко многим: (β → SS)
Прикладные кодировки Юникода
Исходный код
Совместный доступ к документу может быстро превратить редактирование в письменную рэп-битву, ведущуюся все более запутанной расстановкой управляющих от U+202a до U+202e
Специальные символы
Консорциум Unicode опубликовал диаграмму общей пунктуации, где можете найти более подробную информацию.
Подожди… что я только что прочитал?
Идентификаторы переменных могут включать пробелы!
U+3164 Заполнитель хангыль отображается в виде широкого пробела. Если символ явно не поддерживается в рендеринге, то отображается как полностью невидимый (и не занимает место, т. е. «нулевой ширины»). Это означает, что вы никогда не увидите уродливый символ замены символов (�).
Я пока не уверен, почему U+3164 указано вести себя таким образом. Интересно, что U+3164 был добавлен в Юникод в версии 1.1 (1993) — так что у специалистов Консорциума было много времени, чтобы его продумать. Во всяком случае, вот несколько примеров.
> var ᅟ = 'foo';
undefined
> ᅟ
'foo'
> var ㅤ= alert;
undefined
> var foo = 'bar'
undefined
> if ( foo ===ㅤ`baz` ){} // alert
undefined
> var varㅤfooㅤ\u{A60C}ㅤπ = 'bar';
undefined
> varㅤfooㅤꘌㅤπ
'bar'
**Примечание:** я тестировал рендеринг U+3164 на Ubuntu и OS X со следующими параметрами: `node`, `php`, `ruby`, `python3.5`, `scala`, `vim`, `cat`, `chrome`+`github gist'. Atom — единственная система, которая терпит неудачу, (некорректно) отображая пустые поля. Мне ещё предстоит проверить код в Emacs и Sublime. Насколько я понимаю, Консорциум Юникод не будет переназначать или переименовывать символы или кодовые точки, но его можно убедить изменить свойства символов, таких как ID_Start и ID_Continue.
Модификаторы
Объединитель нулевой ширины (ZWJ) является непечатным символом в компьютерном наборе некоторых сложных шрифтов, таких как арабский или любой индийский шрифт. При помещении между двумя символами, которые в противном случае не были бы связаны, ZWJ заставляет их печататься в объединённой форме.
Разъединитель нулевой ширины (ZWNJ) — это непечатный символ в компьютерных наборах письменностей с лигатурами. При размещении между двумя символами, которые в противном случае были бы соединены в лигатуру, ZWNJ заставляет их печататься в их окончательной и первоначальной формах, соответственно. Действует как пробел, но используется в том случае, когда желательно удерживать слова рядом друг с другом или соединить слово с его морфемой.
> 'a'
"a"
> 'a\u{0308}'
"ä"
> 'a\u{20DE}\u{0308}'
"a⃞̈"
> 'a\u{20DE}\u{0308}\u{20DD}'
"a⃞̈⃝"
// Modifying Invisible Characters
> '\u{200E}\u{200E}\u{200E}\u{200E}\u{200E}\u{200E}\u{200E}\u{200E}\u{200E}\u{200E}'
""
> '\u{200E}\u{200E}\u{200E}\u{200E}\u{200E}\u{200E}\u{200E}\u{200E}\u{200E}\u{200E}'.length
10
Коллизии преобразований в верхнем регистре
Коллизии преобразований в нижнем регистре
- Длина строки обычно определяется по количеству кодовых точек. Это означает, что суррогатные пары будут считаться двумя символами. На символ может быть наложено нескольких диакритических знаков:
a + ̈ == ̈a
. Это увеличивает длину строки, производя только один символ. - Аналогично, обращение строки часто становится нетривиальной задачей. Опять же, суррогатные пары и диакритические знаки следует обращать вместе. ES Reverser предлагает довольно хорошее решение.
- Сопоставления верхнего и нижнего регистра не всегда совпадают. Они могут выражаться и такими отношениями:
- Один ко многим: (ß → SS)
- С учётом контекста: (…Σ ←→ …ς и …ΣΤ… ←→ …στ…)
- С учётом локали: (I ←→ ı и İ ←→ i)
Сопоставления одного ко многим
Большинство нижеприведенных символов выражают свои сопоставления «один ко многим» в верхнем регистре, а другие в нижнем. В принципе, список можно разделить на две части.- PhantomScript — : ghost: : flashlight: Выполнение невидимого JavaScript и социальная инженерия
- ESReverser — Обращение строка на JavaScript с учётом Юникода.
- mimic — Некорректное использование Юникода
- python-ftfy — Пытается создать максимальную корректное и цельное представление текста, поступившего в Юникоде.
- vim-troll-stopper — Защита вашего кода от юникод-троллей.
Многообразие
Консорциум Unicode приложил огромные усилия для лучшего отражения человеческого многообразия (diversity), включая культурные практики. Вот отчёт Консорциума о многообразии.Теперь доступны эмодзи для разных гендерных ситуаций, включая однополые семьи, держащиеся руки и поцелуи. Последний функционал — это составные последовательности эмодзи. Основные примеры:
Кроме того, эмодзи теперь поддерживают модификаторы цвета кожи.В Юникоде версии 8.0 (середина 2015 года) появилось пять символов-модификаторов символов для оттенков человеческой кожи. Эти символы основаны на шести оттенках по шкале Фицпатрика, признанного стандарта в дерматологии (в интернете много примеров этой шкалы, таких как FitzpatrickSkinType.pdf). Точные оттенки зависят от реализации.
Отчёт Консорциума Unicode о многообразии
Просто выбирайте нужный эмодзи, указав один из модификаторов цвета кожи\u{1F466}\u{1F3FE}
.
+
→
Примеры на JavaScript (ES6)Обычно символы, обозначенные свойством ID_START, можно ставить в начале названия переменной. Символы, обозначенные свойством ID_CONTINUE, можно ставить после первого символа в имени переменной.
// How convenient! var π = Math.PI; // Sometimes, you just have to use the Bad Parts of JavaScript: var ಠ_ಠ = eval; // Code, Y U NO WORK?! var ლ_ಠ益ಠ_ლ = 42; // How about a JavaScript library for functional programming? var λ = function() {}; // Obfuscate boring variable names for great justice var \u006C\u006F\u006C\u0077\u0061\u0074 = 'heh'; // …or just make up random ones var Ꙭൽↈⴱ = 'huh'; // While perfectly valid, this doesn’t work in most browsers: var foo\u200Cbar = 42; // This is *not* a bitwise left shift (`<<`): var 〱〱 = 2; // This is, though: 〱〱 << 〱〱; // 8 // Give yourself a discount: var price_9̶9̶_89 = 'cheap'; // Fun with Roman numerals var Ⅳ = 4; var Ⅴ = 5; Ⅳ + Ⅴ; // 9 // Cthulhu was here var Hͫ̆̒̐ͣ̊̄ͯ͗͏̵̗̻̰̠̬͝ͅE̴̷̬͎̱̘͇͍̾ͦ͊͒͊̓̓̐_̫̠̱̩̭̤͈̑̎̋ͮͩ̒͑̾͋͘Ç̳͕̯̭̱̲̣̠̜͋̍O̴̦̗̯̹̼ͭ̐ͨ̊̈͘͠M̶̝̠̭̭̤̻͓͑̓̊ͣͤ̎͟͠E̢̞̮̹͍̞̳̣ͣͪ͐̈T̡̯̳̭̜̠͕͌̈́̽̿ͤ̿̅̑Ḧ̱̱̺̰̳̹̘̰́̏ͪ̂̽͂̀͠ = 'Zalgo';
А вот некоторые юникодовские классы CSS от Дэвида Уолша.You do not have access to this page.Your changes have been saved successfully!.ಠ_ಠ { border: 1px solid #f00; } . { background: lightgreen; }
Скрипт рекурсивного переименования тегов HTML
Если вы хотите переименовать все свои HTML-теги в нечто невидимое, вот скрипт, который вам нужен.Только обратите внимание, что HTML поддерживает не все символы Юникода.
// U+1160 HANGUL JUNGSEONG FILLER transformAllTags('ᅠ'); // An actual HTML element node designed to look like a comment node, using the U+01C3 LATIN LETTER RETROFLEX CLICK // <ǃ-- name="viewport" content="width=device-width">ǃ--> transformAllTags('ǃ--'); // or even <ᅠ⃝ transformAllTags('\u{1160}\u{20dd}'); // and for a bonus, all existing tag names will have each character ensquared. h⃞t⃞m⃞l⃞ transformAllTags(); function transformAllTags (newName){ // querySelectorAll doesn't actually return an array. Array.from(document.querySelectorAll('*')) .forEach(function(x){ transformTag(x, newName); }); } function wonky(str){ return str.split('').join('\u{20de}') + '\u{20de}'; } function transformTag(tagIdOrElem, tagType){ var elem = (tagIdOrElem instanceof HTMLElement) ? tagIdOrElem : document.getElementById(tagIdOrElem); if(!elem || !(elem instanceof HTMLElement))return; var children = elem.childNodes; var parent = elem.parentNode; var newNode = document.createElement(tagType||wonky(elem.tagName)); for(var a=0;a
Вот что он поддерживает:function testBegin(str){ try{ eval(`document.createElement( '${str}' );`) return true; } catch(e){ return false; } } function testContinue(str){ try{ eval(`document.createElement( 'a${str}' );`) return true; } catch(e){ return false; } }
А вот некоторые результаты:// Test if dashes can start an HTML Tag > testBegin('-') < false > testContinue('-') < true > testBegin('ᅠ-') // Prepend dash with U+1160 HANGUL JUNGSEONG FILLER < true
Ни один шрифт TrueType или OpenType не способен охватить все символы UTF-8, поскольку есть жёсткое ограничение на 65 535 символов в шрифте. Если у нас более 1,1 миллиона глифов UTF-8, то для полного покрытия придётся делать семейство шрифтов.Карта основной многоязычной плоскости
Каждое нумерованное поле представляет собой 256 кодовых точек.Китайские, японские и корейские (ККЯ) письменности объединены одним цветом как символы ККЯ (CJK). В процессе, который называется унификацией Хань, распознаются общие символы и составляется список «унифицированных идеограмм ККЯ».
Блоки Юникода
Стандарт Юникод объединяет группы символов в блоки. Вот полный список блоков по всем 17-ти плоскостям.Принципы Стандарта Юникод
Стандарт Юникод устанавливает следующие фундаментальные принципы:- Универсальность — каждую когда-либо используемую письменную система следует уважать и представить в стандарте.
- Логический порядок — в двунаправленном тексте символы хранятся в логическом порядке, а не в соответствии с представлением.
- Эффективность — документация должна быть эффективной и полной.
- Унификация — если разные культуры или языки используют один и тот же символ, он должен быть включен только один раз. Это ведёт к следующему пункту.
- Символы, а не глифы — кодируются только символы, а не глифы. В двух словах, глифы являются фактической графической репрезентацией.
- Динамическая композиция — новые символы могут быть составлены из других, уже стандартизированных символов. Например, символ [Ä] может состоять из символа [A] и символа диерезиса [¨].
- Семантика — включённые символы должны быть чётко определены и отличаться от других.
- Стабильность — однажды определённые, символы никогда не будут удалены, а их кодовые точки никогда не будут переназначены. В случае ошибки кодовая точка считается устаревшей.
- Обычный текст — символы в стандарте являются текстом, они никогда не могут быть разметкой или метасимволами.
- Конвертируемость — любая другая используемая кодировка должна иметь возможность быть представленной в терминах кодировки Юникода.
Источник: описание принципов c codepoints.net.