Многие HTML-страницы содержат в своей разметке комментарии. Они нужны для разработчиков, но иногда они могут быть также полезны и для всех остальных пользователей интернета. В комментариях можно встретить полезную информацию. Как их получить? Как получить объекты HTML-элементов комментариев? Как получить строковое представление этих комментариев в виде массива?
Давайте разбираться.
Решение
В решении нам поможет стандарт объектной модели документа (DOM) и стандарт языка разметки гипертекста (HTML).
И самым главным инструментом всех наших вычислений будут регулярные выражения RegExp из JavaScript.
За выборку данных будет отвечать стандарт (Fetch).
Также нам нужно хорошо понимать, что считается комментарием в HTML, как они оформляются, что можно и что нельзя.
Шаг № 1 — Получение всей разметки страницы в виде одной большой строки
Если мы находимся в стандартном вебе и пользуемся доступом к контенту через URI-схемы:
http, https, ipns, chrome-untrusted, ipfs, data, chrome, chrome-extension
то можно смело посылать запрос на выборку данных с сервера по текущему адресу
let str = await fetch(location.pathname).then(resp=>resp.text())
Эта команда вернёт нам нужную строковую разметку текущего открытого документа в браузере.
Строка уже есть.
Шаг № 2 — Что считается HTML-комментарием?
Здесь нужно собрать немного информации из разных мест документации по HTML.
Комментарии должны иметь следующий формат:
- Строка «<!—«.
- Опционально, текст с дополнительным ограничением: текст не должен начинаться со строки «>«, начинаться со строки «->» и содержать строки «<!—«, «—>» или » —!>«, и не заканчиваться строкой «<!-«.
- Строка «—>«.
Примечание!
Текст может заканчиваться строкой «<!«, как в <!— Моими любимыми операторами являются > и <!—>.
Из этого следует то, что комментарии нельзя вкладывать один в один. Браузер это не распознает корректно.
Эта ошибка возникает, если синтаксический анализатор встречает вложенный комментарий (например, <!— <!— вложенный —> —>). Такой комментарий будет закрыт первой попавшейся последовательностью кодовых точек «—>«, а все последующие будут рассматриваться как разметка.
Эта ошибка возникает, если синтаксический анализатор встречает кодовую точку U+003F (?), где ожидается первая кодовая точка имени начального тега. U+003F (?) и всё содержимое, следующее за кодовой точкой U+003E (>) (если присутствует) или до конца входного потока, рассматриваются как комментарий.
Например, рассмотрим следующую разметку:
<?xml-stylesheet type=»text/css» href=»style.css»?>
Распространенной причиной этой ошибки является инструкция по обработке XML (например, <?xml-stylesheet type=»text/css» href=»style.css»?>) или декларация XML (например, <?xml version=»1.0 » encoding=»UTF-8″?>) используется в HTML.
Самый простой и безопасный способ избежать довольно странных ограничений, описанных в этом разделе, — это всегда экранировать соответствие ASCII без учета регистра для:
- «<!—» как «\x3C!—«
- «<script» как «\x3Cscript«
- «</script» как «\x3C/script«
когда эти последовательности появляются в литералах в сценариях (например, в строках, регулярных выражениях или комментариях), и чтобы избежать написания кода, который использует такие конструкции в выражениях. Это позволяет избежать ловушек, к которым могут привести ограничения в этом разделе: а именно, что по историческим причинам синтаксический анализ блоков скриптов в HTML является странной и экзотической практикой, которая действует неинтуитивно перед лицом этих последовательностей.
Это говорит о том, что в строке, полученной через JavaScript могут быть начальные символы «\x3C!—» для открывания комментария.
Есть ещё моменты касающиеся doctype, но мы их не будем учитывать. Нам это мало интересно. Но если вам нужно, то придётся усчитывать.
Написание кода с учётом условий
Первое регулярное выражение:
/<!--.*?-->/g[Symbol.match](str)||[]
или
Второе регулярное выражение:
/\x3C!--.*?-->/g[Symbol.match](str)||[]
Каждое выражение должно возвращать одинаковый массив элементов. Если сопоставления не будут найдены, то метод [Symbol.match]() вернёт нам null. При сравнении null и пустого массива, нам вернётся пустой массив. То есть мы в любом случае получим массив.
Пример работы выражений:
Обязательно добавляйте символ вопроса для квантификатора звёздочки. Так вы будете отбирать самые короткие последовательности сопоставления.
Тестовые строки для проверки
let str2 = 'Стол<!-- Петя -->Стул<-- Дима -->Кровать<!-- Коля --><-- Гриша --><!-- Иван --><-- Маша -->'
Функция для извлечения HTML-комментариев из строки разметки
function getHTMLCommentsArr(str){return /<!—.*?—>/g[Symbol.match](str)||[]}
Собственный метод, расширяющий стандартный класс String
Мы можем написать свой собственный метод для расширения стандартного набора методов класса String.
String.prototype.getHTMLCommentsArr = function(){return /<!--.*?-->/g[Symbol.match](this)||[]}
Пример работы метода:
Информационные ссылки
Стандарт ECMAScript — https://tc39.es/ecma262/multipage/
Стандарт ECMAScript — Раздел «22.2.5.8 RegExp.prototype [ @@match ] ( string )» — https://tc39.es/ecma262/multipage/text-processing.html#sec-regexp.prototype-@@match
Стандарт ECMAScript — Раздел «22.1.3.12 String.prototype.match ( regexp )» — https://tc39.es/ecma262/multipage/text-processing.html#sec-regexp.prototype-@@match
Стандарт DOM — https://dom.spec.whatwg.org
Стандарт DOM — Русская версия