Владение HTML5: Правила определения области действия

9 января 2018

Одной из наиболее важных концепций HTML5 является унифицированная модель синтаксического анализа. В более ранних версиях спецификации HTML разработчик обладал большой свободой. В основном можно было выбрать, как обрабатывать определенные сценарии. В результате расхождения были одной из самых важных причин для разных интерпретаций многих веб-сайтов в нескольких браузерах. С HTML5 обработка ошибок была описана очень подробно, не оставляя места для интерпретаций.

В этой первой статье серии «Мастерство HTML5» мы рассмотрим алгоритмы обработки ошибок, указанные в стандарте. Мы увидим, что некоторые из этих потенциальных ошибок являются фактически принятым поведением, что делает их пригодными для использования на популярных веб-сайтах. В основной части этой статьи будут обсуждаться правила определения области охвата, которые охватывают большую часть опытного поведения, поскольку они вызывают определенные алгоритмы. Начнем с практического примера, показывающего подразумеваемые закрывающие теги.

Примеры реального мира

Две из наиболее часто используемых способностей стандартизованного анализатора HTML5 - это автоматическое построение правильной структуры документа и вставка подразумеваемых конечных тегов. Начнем с последнего. Хорошим примером для иллюстрации этой функции является построение простого списка. Следующий фрагмент кода показывает несортированный список с тремя элементами.

<ul>
<li>First item
<li>Second item
<li>Third item
</ul>

Несмотря на то, что мы опускаем закрывающий тег (

), страница отображается правильно. Правильный рендеринг возможен только в том случае, если дерево DOM было построено правильно из данного источника. Дерево DOM представляет собой представление узлов DOM в иерархии деревьев. Узел DOM может быть элементом, комментарием, текстом или некоторой другой конструкцией, которая представлена ​​в других частях этой серии.

Иерархия дерева DOM начинается с так называемого корня и показывает дочерние узлы корня. Корень - это первый узел дерева. У него нет родительского элемента. Некоторые узлы, такие как элементы, могут иметь дочерние узлы самостоятельно. Дерево дает нам информацию о фактической построенной DOM, тогда как источник просто предлагает конструкцию.

Парсер HTML5 гарантирует, что теги, которые были опущены, вставлены перед добавлением новых элементов списка. Это соответствует нашей интуиции. Естественно, мы считаем, что данный список должен иметь три элемента. До HTML5 мы могли на самом деле получить один элемент, содержащий текст и другой элемент, в котором снова содержался текст и элемент с текстом.

В браузере мы видим следующий рендеринг (слева). Мы также можем проверить дерево DOM, чтобы проверить, правильно ли обработчик сценария правильно (правая сторона).

Несмотря на то, что Opera (здесь в версии 31) использовалась для создания скриншотов выше, поведение браузера не зависит, как было указано в стандарте HTML5.

Изучив исходный код некоторых очень популярных сайтов, мы увидим некоторые странности. Например, страница ошибок, отображаемая Google, содержит следующую разметку.

<!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>Error 404 (Not Found)!!1</title>
  <style>/* ... */</style>
  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
  <p><b>404.</b> <ins>That’s an error.</ins>
  <p>The requested URL <code>/error</code> was not found on this server.  <ins>That’s all we know.</ins>

Даже без указания элементаилиэлементы строятся. Также параграфы подразумевают закрытие тегов. По-видимому, параграфы обрабатываются аналогично элементам списка. Они не встречаются вложенными - по крайней мере, при построении из источника парсером HTML5.

Поэтому браузер генерирует дерево справа, которое будет отображать макет слева.

Одной из наиболее важных строк в предыдущем коде является объявление правильного типа документа HTML5. В противном случае мы можем оказаться в режиме quirks, что существенно эквивалентно неопределенному поведению с точки зрения кросс-браузерной разработки.

Подразумеваемые конечные теги

Поведение, которое мы видели в предыдущем разделе, основывается на генерации подразумеваемых конечных тегов. Механизм генерации подразумеваемых конечных тегов работает, закрывая текущий узел, в то время как текущий узел является одним из следующих элементов:

или
или
  • или

  • Мы признаем, что это действительно имеет смысл для всех эти теги. Вложенный параграф не определен. Аналогично вложенные списки или параметры. Они имеют смысл только в другом контейнере.

    Элемент с подразумеваемым конечным тегом не совпадает с самозакрывающимся элементом. В стандарте HTML есть такие элементы, как,или, которые являются самозакрывающимися. Хотя они и являются элементами, у них не должно быть детей. Парсер немедленно закрывает их. В то время как XML обозначает эти элементы с завершающим косой чертой, HTML поощряет исключение косой черты.

    Области HTML

    Существует множество сценариев, в которых применяется область охвата. В принципе, как только парсер HTML5 сталкивается с определенными элементами во время построения дерева, он смотрит, находится ли элемент в определенной области. В этом случае последуют дальнейшие действия. В противном случае текущий элемент обычно игнорируется.

    Процесс определения того, находится ли элемент в заданной области, начинается с просмотра текущего элемента. Если элемент является узлом области видимости, мы находимся в его области. Если элемент находится в специальном подмножестве элементов, заданных областью действия, мы не находимся в области видимости. В противном случае мы продолжим поиск в родительском элементе текущего элемента.

    Подмножество элементов можно разделить на пять групп. Каждая область выбирает одну из этих групп, чтобы указать элементы исключения. Эти пять групп называются:

      Общий элемент списка Button Table Select

    Группы элементов списка и кнопок также содержат все элементы общей группы. Группа таблиц содержит толькои сам элемент таблицы. Группа выбора включает все элементы, кромеи

    Приоритетные примеры

    Группа выбора может использоваться, чтобы хорошо иллюстрировать то, что мы получим, используя эти правила определения области видимости. Если мы, например, закрываем элемент select, то проверяется, есть ли у меня элемент

    Давайте посмотрим на некоторый код. Какое дерево будет создано?

    <select><optgroup><option>First</select>

    На самом деле это было слишком легко. Наша интуиция говорит нам, что

    закрывает вариант и группу опций. Это верно. На самом деле мы ограничены только использованием элементов опций и групп параметров в элементе select. Это контролируется парсером. Итак, как насчет сейчас?
    <p><optgroup><option>First</select>

    Здесь два основных отличия. Во-первых, мы не вводим элемент выбора в первую очередь. Поэтомуи

    Давайте рассмотрим некоторое поведение, которое может повлиять на ваш дизайн разметки. Как будет выглядеть построенное дерево DOM для следующего фрагмента?

    <p>I am from <address>Germany</address>.</p>

    Ничего проще, не так ли? Ну, не так быстро. Наценка может показаться законной с первого взгляда. В конце концов, это просто семантически объявление адреса внутри, не так ли? К сожалению нет. Элемент

    также считается блоком, как абзац. Этот блок не имеет ничего общего с CSS, поэтому мы не можем изменить поведение, используя другое объявление отображения.

    Мы уже видим, что построенный DOM делает разницу (справа). После этого выполняется рендеринг (слева).

    Это поведение относится к нескольким элементам. Спецификация гласит:

    Начальный тег, имя тега которого является одним из следующих: «адрес», «статья», «в сторону», «blockquote», «center», «details», «dir», «div», «dl «Headset», «figcaption», «figure», «footer», «header», «hgroup», «menu», «nav», «ol», «p», «section», «summary», "Ul" [...]

    Все эти элементы проведут проверку наличия элемента абзаца в группе кнопок. Если это так, то пункт будет закрыт.

    Есть много других мест, где элементы предка контекста действительно имеют значение. Все это делает HTML-фрагменты очень нелокальными. Однако на данный момент мы рассмотрим еще одну тему обработки ошибок.

    Переформатирование и таблицы

    Начнем с простого вопроса. Как выглядит дерево DOM для следующего кода?

    <p>1<b>2<i>3</b>4</i>5</p>

    Конечно, не очень сложно вычислить полученное дерево до 3, но затем проблемы начинаются. Нет никакого хорошего аргумента в пользу того, что должно произойти дальше. Именно по этой причине некоторые разработчики браузеров решили ввести алгоритм, описывающий работу переформатирования.

    Во-первых, заключительный жирный тег подразумевает конец для всех включенных тегов. В нашем примере это влияет на курсив. Но поскольку мы не закрывали курсив, мы должны рассматривать его специально. После того, как все внутренние теги были закрыты, нам нужно открыть новые для неявно закрытых тегов форматирования. Тег форматирования является нормальным тегом, который соответствует элементу, который имеет (исторические) последствия для форматирования содержащегося текста.

    На следующем рисунке показан результат. Дерево слева - это конструкция до 3, а дерево справа - полное изображение после фрагмента кода.

    Во времена CSS восстановление элементов форматирования можно считать устаревшим, но оно далеко не устарело. Он не запускается напрямую, когда элементы закрыты, а скорее при вставке нового текста.

    Еще одна интересная тема - соединение форматирования с элементами таблицы. Обработка ошибок в таблицах довольно странная. Кажется, никто не понимает это правильно интуитивно. Исторически это было разработано многими поставщиками с различной философией.

    Давайте снова рассмотрим пример. Как дерево DOM будет искать следующий фрагмент?

    <table><b><tr><td>aaa</td></tr>bbb</table>ccc

    В

    допускаются только элементы таблицы. Как ранее видели основные элементы HTML (такие какили), парсер обычно позаботится об этом. Например, если строка добавляется непосредственно в таблицу, разделавтоматически вставлен, чтобы заботиться о строке.

    Естественным моментом является добавление полужирного элемента форматирования к. Но, поскольку мы указали полужирное форматирование текста, нам все равно нужно иметь его для любого текста (вне таблицы). Поэтому первый шаг - на любом произведении таблицы (после вставленного элемента), с некоторым (нормальным) текстом.

    После закрытия строки мы сталкиваемся с еще одним текстом. Этот текст находится внутри таблицы, но он не был помещен в ячейку. Поэтому он должен быть добавлен перед таблицей, как жирный элемент. Здесь полужирное форматирование по-прежнему активно, т. Е. Текст не будет добавляться автономно, но должен быть завернут в тег.

    Наконец, у нас есть текст за пределами таблицы. Мы можем правильно предположить, что этот текст должен появиться после таблицы в дереве DOM, но ключевой вопрос: следует ли форматировать? Единственный правильный ответ - нет, он не должен. Зачем? Причина в том, что мы никогда не закрывали жирный тег. Поскольку жирный тег смещен от таблицы к телу, мы все равно не закрываем его.

    Разметка в предыдущем примере не может считаться читаемой, интуитивно понятной или вообще не нужна. Поведение, которое мы видели, - это модель восстановления ошибок на рабочем месте, и ничего не нужно. Я выбрал этот пример, чтобы проиллюстрировать проблему (и показанное решение парсером) вложенности несовместимых тегов. В большинстве случаев такие проблемы возникают из-за ошибок слияния с копией или контроля версий.

    Заключение

    Важно знать внутренние элементы синтаксического анализа HTML5. Это знание приводит к правильным правилам минимизации, которые могут сэкономить много байтов и некоторое время синтаксического анализа. Также теперь у нас есть базовое понимание обработанной обработки ошибок с помощью парсера HTML.

    Правила определения области видимости всегда проявляются в процессе разбора HTML5. Мы имеем дело с чрезвычайно состоятельным процессом, который не принимает элементы как равные или неизвестные. Вместо этого у нас есть огромный набор специальных действий, которые сильно зависят от текущей области, которая определяется рассматриваемым элементом.

    Мы также видели, что угадывание правильного дерева не всегда настолько интуитивно, как должно быть. В целом мы должны стараться избегать таких проблемных областей.

    Ссылки

    Спецификация W3C Как работают браузеры: за кулисами современных веб-браузеров Джон Хартли: В чем большая разница между HTML4 и HTML5? Закрыть или не закрыть теги в HTML5 Tiffany B. Brown - HTML5 НЕ разрешает теги «самозакрывающиеся»