Как стать автором
Обновить

PowerShell: распознавание БЭМ-сущностей на HTML-странице

Разработка веб-сайтов *Программирование *PowerShell *Регулярные выражения *
Tutorial

Продолжаю дорабатывать небольшой скрипт на языке PowerShell для работы в программах-оболочках «Windows PowerShell» версии 5.1 и «PowerShell» версии 7 (я работаю в операционной системе «Windows 10»). Скрипт разбирает заданный файл с кодом на языке HTML с помощью методов библиотеки «HTML Agility Pack» и выводит в консоль HTML-дерево HTML-страницы из файла. При выводе в консоль HTML-дерева внимание пользователя с помощью цвета фокусирую на значениях атрибутов «class» HTML-элементов. Далее выполняю анализ названий БЭМ-сущностей на соответствие методологии БЭМ («Блок, Элемент, Модификатор»). Скрипт может быть полезен при изучении методологии БЭМ, схем именования в БЭМ и так далее.

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

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

Порядок действий

В вышеупомянутой статье я описал функцию testBEMNameClassic, в которой с помощью ряда регулярных выражений, применяемых в определенном порядке, происходит анализ слова (названия класса CSS) из атрибута «class» HTML-элемента на ошибки с точки зрения схемы именования в методологии БЭМ. Эта функция возвращает число 0, если ошибок не обнаружено, или число, отличное от нуля (код ошибки), если обнаружена ошибка.

После этой проверки, если найдена ошибка, я вывожу сообщение об ошибке. Если ошибка не найдена, можно заняться распознаванием типа БЭМ-сущности. В коде на языке PowerShell это может выглядеть примерно так:

$err = testBEMNameClassic($class)
if ($err) {
    #   Выводим сообщение об ошибке
    #   ...
} else {
    #   Распознаём тип БЭМ-сущности, выводим в консоль
    #   ...
}

В переменной $class содержится одно из слов из значения атрибута «class» HTML-элемента. Если в этом атрибуте содержится несколько слов, то они будут проанализированы поочередно в цикле (этот цикл в коде выше не показан). Напомню, слова в атрибуте «class» HTML-элемента разделяются пробельными символами (пробелом, символом горизонтальной табуляции, символами новой строки).

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

Распознание типа БЭМ-сущности

Насколько я понимаю, типов БЭМ-сущности может быть всего шесть:

  • блок;

  • модификатор блока булевый;

  • модификатор блока ключ-значение;

  • элемент;

  • модификатор элемента булевый;

  • модификатор элемента ключ-значение.

Добавим в код выше код на языке PowerShell для распознавания типа БЭМ-сущности по ее названию с помощью регулярных выражений:

    #   Распознаём тип БЭМ-сущности, выводим в консоль
    if     ($class -cmatch '^[a-z-]+$')
        { "блок" }
    elseif ($class -cmatch '^[a-z-]+_[a-z-]+$')
        { "модификатор блока булевый" }
    elseif ($class -cmatch '^[a-z-]+_[a-z-]+_[a-z-]+$')
        { "модификатор блока ключ-значение" }
    elseif ($class -cmatch '^[a-z-]+__[a-z-]+$')
        { "элемент" }
    elseif ($class -cmatch '^[a-z-]+__[a-z-]+_[a-z-]+$')
        { "модификатор элемента булевый" }
    elseif ($class -cmatch '^[a-z-]+__[a-z-]+_[a-z-]+_[a-z-]+$')
        { "модификатор элемента ключ-значение" }
    else   #   если эта ветка задействуется, значит, ранее что-то
           #   не учтено и следует проверить предыдущие шаги,
           #   в том числе на этапе поиска ошибок
        { "не знаю, что это" }

В языке PowerShell оператор -match — один из ряда операторов, работающих с регулярными выражениями. Этот оператор не чувствителен к регистру букв. В коде выше я использую оператор -cmatch. Добавленная в начало названия этого оператора латинская буква c обозначает слово «case» (по-русски в данном случае оно означает «регистр букв»), то есть оператор -cmatch чувствителен к регистру букв.

Для нас это важно, потому что классическая схема именования в методологии БЭМ разрешает составлять названия БЭМ-сущностей только из латиницы в нижнем регистре (то есть разрешается использовать только строчные (маленькие) буквы). Кроме латиницы в названиях могут использоваться символ дефиса-минуса - и символ подчеркивания _.

Я уже немного описывал в другой статье синтаксис регулярных выражений, но не повредит напомнить, что символ ^ (карет) обозначает в регулярном выражении начало строки, а символ $ (доллар) — конец строки. Регулярное выражение в коде выше заключено в одинарные кавычки потому, что при использовании двойных кавычек символ $ будет интерпретирован не так, как нам нужно для регулярных выражений (в языке PowerShell с символа $ начинаются переменные).

Символ + в регулярном выражении имеет специальное значение (такие символы в регулярных выражениях называют «квантификаторами»). В данном случае он означает повторение символа, стоящего перед ним, один или более раз. В данном случае перед символом + в регулярных выражениях выше находятся квадратные скобки, которые означают один любой символ из содержащихся внутри квадратных скобок. Таким образом, выражение [a-z-]+ означает один или более символов, каждый из которых может быть либо строчной (маленькой) буквой латиницы, либо дефисом-минусом -.

Диапазон строчных букв латиницы внутри квадратных скобок обозначен выражением a-z. Так как в данном случае дефис-минус - обозначает диапазон, то сам символ дефиса-минуса - можно указать либо в начале выражения внутри квадратных скобок, либо в конце выражения внутри квадратных скобок (наш случай).

Учитывая, что название любой БЭМ-сущности сводится к одному или нескольким наборам символов [a-z-]+, отделенных друг от друга соответствующими разделителями _ (одинарный символ подчеркивания) и __ (двойной символ подчеркивания), можно легко произвести распознавание разных типов БЭМ-сущностей:

  1. Название блока содержит только один набор символов [a-z-]+, разделителей нет;

  2. Название булевого модификатора блока содержит два набора символов [a-z-]+, отделенных друг от друга разделителем _;

  3. Название модификатора блока ключ-значение содержит три набора символов [a-z-]+, отделенных друг от друга двумя разделителями _;

  4. Название элемента содержит два набора символов [a-z-]+, отделенных друг от друга разделителем __;

  5. Название булевого модификатора элемента содержит три набора символов [a-z-]+, отделенных друг от друга разделителем __ и разделителем _;

  6. Название модификатора элемента ключ-значение содержит четыре набора символов [a-z-]+, отделенных друг от друга разделителями __ и двумя _.

Два замечания

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

Кроме этого, стоит обратить внимание на последнюю ветку в коде выше. Если я в скрипте всё написал правильно, то эта ветка никогда не будет задействована: для любого слова из атрибута «class» HTML-элемента либо будет показана ошибка (слово не укладывается в схему именования методологии БЭМ), либо будет показан тип БЭМ-сущности. Если эта ветка таки задействуется, значит, где-то ранее в скрипте допущена ошибка.

Заключение

Работа скрипта с распознаванием типа БЭМ-сущностей может выглядеть так:

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

Теги:
Хабы:
Всего голосов 1: ↑1 и ↓0 +1
Просмотры 796
Комментарии 0
Комментарии Комментировать