Как работает кодирование HTML-сущностей
HTML-сущность — это символьная ссылка, которую браузер разбирает обратно в один символ. Пять зарезервированных HTML-символов (<, >, &, ", ') всегда требуют кодирования при отображении текста в HTML; всё остальное — по необходимости, в зависимости от кодировки документа.
- Выберите режим и область. Режим кодирования обходит ввод посимвольно. Режим декодирования ищет в тексте паттерны сущностей. Переключатель области определяет, кодируются ли только пять HTML-символов или все не-ASCII символы.
- Выберите стиль сущности. Именованные сущности (
©) хорошо читаются в исходном коде. Десятичные (©) и шестнадцатеричные (©) ссылки охватывают все кодовые точки Unicode без имён. Старые почтовые клиенты и XML-парсеры предпочитают числовые форматы. - Обход ввода. При кодировании каждая кодовая точка ищется во встроенной таблице около 200 распространённых именованных сущностей. Если совпадения нет, используется числовой формат. При декодировании применяется одно регулярное выражение, совпадающее с
&name;,&#NNN;и&#xHH;за один проход. - Сопоставление с символами. Именованные совпадения разрешаются через обратную таблицу. Числовые совпадения обрабатываются через
String.fromCodePointс основанием 10 или 16. Неизвестные именованные сущности остаются нетронутыми, чтобы частичный ввод не терял данных. - Режим реального времени. Включите режим реального времени, и каждое нажатие клавиши будет перезапускать преобразование с задержкой 150 мс. Удобно при доработке фрагмента, когда нужна мгновенная обратная связь перед вставкой в шаблон.
Зачем кодировать HTML-сущности
- Предотвращение поломки вёрстки. Если пользователь вводит лишний символ
<в поле комментария, и этот текст попадает прямо в HTML, браузер перепишет остаток страницы. Предварительное кодирование зарезервированных символов заставит браузер отобразить символ, а не интерпретировать его как начало тега. - Корректность значений атрибутов. Встраивание строки в кавычках внутри HTML-атрибута требует замены кавычки на
"(для атрибутов в двойных кавычках) или'(для одинарных). Иначе парсер преждевременно закроет атрибут, а остаток строки станет лишней разметкой. - Обезвреживание HTML в хранимых данных. Логи, отчёты об ошибках и экспорт чатов часто содержат угловые скобки и амперсанды. Кодирование дампа перед вставкой в документацию оставляет содержимое видимым как текст вместо того, чтобы запустить рендерер или автодетектор ссылок.
- Безопасный обмен фрагментами кода. Публикация примера тега вроде
<script>alert(1)</script>в блог-посте, письме или сообщении требует кодирования скобок, чтобы фрагмент отображался, а не выполнялся. Та же техника применима к телам RSS-лент и полям `description` в JSON-LD.
Типичные случаи применения
Кодирование сущностей встречается везде, где необработанный текст составляется в HTML во время выполнения — даже когда фреймворк обычно делает это за вас, ручной инструмент полезен в случаях, когда автоматика отключена.
- Серверные шаблоны: Jinja2, ERB, Twig и Handlebars автоматически экранируют по умолчанию, но блоки raw и маркеры `safe` это отключают — кодек позволяет проверить, что именно произвело бы экранирование.
- Электронные письма и рассылки: многие движки ESP-шаблонов не экранируют merge-поля автоматически, поэтому типографские кавычки и символы авторского права в именах пользователей требуют предварительного кодирования.
- Документация и примеры кода: вставка примерного HTML-тега в Markdown-пост или фрагмент статического сайта требует кодирования скобок, чтобы рендерер воспринимал их как видимый текст.
Разобранный пример
Вставьте <script>alert('hi')</script> в поле ввода, установив режим «Кодировать», стиль «Именованный», область «Минимальная». На выходе получится <script>alert('hi')</script>. Переключите стиль на «Числовой шестнадцатеричный» — тот же ввод даст <script>alert('hi')</script>. Переведите режим в «Декодировать», вставьте закодированную строку обратно — и исходный тег восстановится.
FAQ
Что такое HTML-сущности?
HTML-сущности — это символьные ссылки, которые браузер при разборе страницы заменяет одиночными символами. Они существуют в трёх формах: именованные (например & для &), десятичные числовые (&) и шестнадцатеричные числовые (&). Пять зарезервированных HTML-символов (<, >, &, ", ') требуют кодирования при любом попадании текста в HTML. Остальные около 2225 именованных сущностей охватывают символы, диакритические знаки и греческие буквы, но необязательны при кодировке документа UTF-8.
Когда использовать именованные, а когда числовые сущности?
Используйте именованные сущности, когда хотите, чтобы исходный код читался легко (разработчик, видя © в шаблоне, сразу понимает смысл). Применяйте числовые (десятичные или шестнадцатеричные), когда потребитель — старый или строгий: XML-парсеры, устаревшие почтовые клиенты и некоторые читалки лент распознают лишь небольшое подмножество именованных HTML5-сущностей, тогда как числовые понимают все. Шестнадцатеричный формат предпочтителен в контексте безопасности, поскольку соответствует нотации кодовых точек Unicode в спецификациях.
Декодирует ли инструмент шестнадцатеричные сущности вроде &?
Да. Декодер использует одно регулярное выражение, совпадающее со всеми тремя формами сущностей за один проход: &name;, &#NNN; и &#xHH;. Числовые совпадения разрешаются через String.fromCodePoint с основанием 10 или 16. Смешанный ввод (именованные и числовые в одной строке) декодируется корректно, а неизвестные имена остаются как литеральный текст — частичный ввод не теряет данных.
Безопасен ли инструмент для недоверенных данных?
Кодек работает только в браузере и не передаёт ввод куда-либо. Безопасность вывода для встраивания зависит от контекста. Кодирование сущностей покрывает контексты HTML-тела и значений атрибутов — это соответствует требованиям OWASP Rule #1. Для JavaScript-контекстов (обработчики событий, блоки `<script>`), CSS и URL требуются отдельные правила кодирования — одних сущностей там недостаточно. Для глубокой серверной защиты сочетайте с контекстно-осведомлённым шаблонизатором, таким как DOMPurify или встроенное автоэкранирование фреймворка.
Кодирование сущностей на стороне браузера стоит на границе между пользовательским вводом и отображаемым HTML. Локальное выполнение преобразования позволяет проверить, что именно выдал бы ваш фреймворк, не отправляя исходный текст сторонним инструментам.