Для реализации выбрал TypeScript, чтобы использовать преимущества статической типизации. Сборка проекта осуществляется с помощью webpack.
Из сторонних библиотек использовал - json-to-ast. Библиотека упрощает получение местоположения конкретного БЕМ-блока в файле.
Перед тем как проводить анализ, перевожу json во внутреннию структуру БЕМ-блоков (BemBlock, BemBlockArray). За это отвечает функция jsonToBem (json-to-bem.ts). Сначала функция переводит json с помощью json-to-ast в AST-сущности, затем AST-сущности переводятся в БЕМ-сущности, включая информацию о положении блока в файле.
Добавил абстрактный класс LinterRule, а так же выделил 2 типа правил, которые наследуются от него:
- Правило для конкретного блока -
NodeLinterRule; - Правило для всего документа -
DocumentLinterRule(н-р, для всех правил типа "TEXT").
Реализация правил находится в папке linter-rules: warning, text, grid.
За анализ отвечает класс LinterStrategy. Функция lint() выполняет проход по документу и применяет правила проверки. Набор правил LinterStrategy получает из configuration:
{
WARNING: {
TEXT_SIZES_SHOULD_BE_EQUAL: LinterRules.Warning.TextSizesShouldBeEqual,
INVALID_BUTTON_SIZE: LinterRules.Warning.InvalidButtonSize,
INVALID_BUTTON_POSITION: LinterRules.Warning.InvalidButtonPosition,
INVALID_PLACEHOLDER_SIZE: LinterRules.Warning.InvalidPlaceholderSize
},
TEXT: {
SEVERAL_H1: LinterRules.Text.SeveralH1,
INVALID_H2_POSITION: LinterRules.Text.InvalidH2Position,
INVALID_H3_POSITION: LinterRules.Text.InvalidH3Position
},
GRID: {
TOO_MUCH_MARKETING_BLOCKS: LinterRules.Grid.TooMuchMarketingBlocks
}
}Выполняется один проход по дереву. В качестве результата возвращается массив LinterProblem.
Во время прохода правила для конкретных блоков выполняют проверку тут же, правила для всего документа сначала собирают потенциальные блоки, и в конце выполняют проверку, - сделано для оптимизации.
В файле linter.ts создаётся глобальная функция, которая получает экземпляр LinterStrategy и вызывает функцию lint().
Для unit-тестирования использовал Jest. Тесты находятся в соответствующей папке tests.
Примечание:
В ветке task-3-integration собрал библиотеку с помощью rollup.js, т.к. этот инструмент поддерживает ES модули, что упростило интеграцию с плагином в задании 3.