Продолжаю дорабатывать небольшой скрипт на языке 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 это может выглядеть примерно так: В переменной $class содержится одно из слов из значения атрибута «class» HTML-элемента. Если в этом атрибуте содержится несколько слов, то они будут проанализированы поочередно в цикле (этот цикл в коде выше не показан). Напомню, слова в атрибуте «class» HTML-элемента разделяются пробельными символами (пробелом, символом горизонтальной табуляции, символами новой строки). Таким образом, на этапе распознавания типа БЭМ-сущности можно считать, что входящие для распознавания слова написаны с полным соблюдением соглашения по именованию методологии БЭМ. (В нашем случае — это классическая схема именования, но в скрипте я реализую еще две альтернативные схемы именования. При желании кроме реализованных трех схем по именованию можно добавить какие-нибудь еще.) Насколько я понимаю, типов БЭМ-сущности может быть всего шесть: блок; модификатор блока булевый; модификатор блока ключ-значение; элемент; модификатор элемента булевый; модификатор элемента ключ-значение. Добавим в код выше код на языке PowerShell для распознавания типа БЭМ-сущности по ее названию с помощью регулярных выражений: В языке PowerShell оператор -match — один из ряда операторов, работающих с регулярными выражениями. Этот оператор не чувствителен к регистру букв. В коде выше я использую оператор -cmatch. Добавленная в начало названия этого оператора латинская буква c обозначает слово «case» (по-русски в данном случае оно означает «регистр букв»), то есть оператор -cmatch чувствителен к регистру букв. Для нас это важно, потому что классическая схема именования в методологии БЭМ разрешает составлять названия БЭМ-сущностей только из латиницы в нижнем регистре (то есть разрешается использовать только строчные (маленькие) буквы). Кроме латиницы в названиях могут использоваться символ дефиса-минуса - и символ подчеркивания _. Я уже немного описывал в другой статье синтаксис регулярных выражений, но не повредит напомнить, что символ ^ (карет) обозначает в регулярном выражении начало строки, а символ $ (доллар) — конец строки. Регулярное выражение в коде выше заключено в одинарные кавычки потому, что при использовании двойных кавычек символ $ будет интерпретирован не так, как нам нужно для регулярных выражений (в языке PowerShell с символа $ начинаются переменные). Символ + в регулярном выражении имеет специальное значение (такие символы в регулярных выражениях называют «квантификаторами»). В данном случае он означает повторение символа, стоящего перед ним, один или более раз. В данном случае перед символом + в регулярных выражениях выше находятся квадратные скобки, которые означают один любой символ из содержащихся внутри квадратных скобок. Таким образом, выражение [a-z-]+ означает один или более символов, каждый из которых может быть либо строчной (маленькой) буквой латиницы, либо дефисом-минусом -. Диапазон строчных букв латиницы внутри квадратных скобок обозначен выражением a-z. Так как в данном случае дефис-минус - обозначает диапазон, то сам символ дефиса-минуса - можно указать либо в начале выражения внутри квадратных скобок, либо в конце выражения внутри квадратных скобок (наш случай). Учитывая, что название любой БЭМ-сущности сводится к одному или нескольким наборам символов [a-z-]+, отделенных друг от друга соответствующими разделителями _ (одинарный символ подчеркивания) и __ (двойной символ подчеркивания), можно легко произвести распознавание разных типов БЭМ-сущностей: Название блока содержит только один набор символов [a-z-]+, разделителей нет; Название булевого модификатора блока содержит два набора символов [a-z-]+, отделенных друг от друга разделителем _; Название модификатора блока ключ-значение содержит три набора символов [a-z-]+, отделенных друг от друга двумя разделителями _; Название элемента содержит два набора символов [a-z-]+, отделенных друг от друга разделителем __; Название булевого модификатора элемента содержит три набора символов [a-z-]+, отделенных друг от друга разделителем __ и разделителем _; Название модификатора элемента ключ-значение содержит четыре набора символов [a-z-]+, отделенных друг от друга разделителями __ и двумя _. Интересно, что шесть веток распознавания типов БЭМ-сущностей в коде выше можно безболезненно переставить местами в любом порядке. То есть регулярные выражения в этих ветках не зависят от предыдущих регулярных выражений. Это отличается от того, как написан анализ названий БЭМ-сущностей на ошибки в функции testBEMNameClassic. Напомню, что там тоже используется ряд относительно коротких регулярных выражений, используемых поочередно. В функции testBEMNameClassic порядок использования регулярных выражений важен. Кроме этого, стоит обратить внимание на последнюю ветку в коде выше. Если я в скрипте всё написал правильно, то эта ветка никогда не будет задействована: для любого слова из атрибута «class» HTML-элемента либо будет показана ошибка (слово не укладывается в схему именования методологии БЭМ), либо будет показан тип БЭМ-сущности. Если эта ветка таки задействуется, значит, где-то ранее в скрипте допущена ошибка. Работа скрипта с распознаванием типа БЭМ-сущностей может выглядеть так: В принципе, это уже можно использовать для обучения. Но мне интересно написать поиск более сложных ошибок. Например, поиск нарушений принципа принадлежности (элемент не должен находиться вне контекста своего блока) и других. Для этого, по идее, нужно будет сопоставлять названия разных БЭМ-сущностей на одном и том же узле HTML-дерева, а также на разных узлах.