No description, website, or topics provided.
Switch branches/tags
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
lib
plugins
spec
.gitignore
README.md
package-lock.json
package.json

README.md

bemhint-estree

Плагины к bemhint для парсинга js и поиска недостающих депсов.

Что внутри

  • plugins/browser — плагин для технологии js.
  • plugins/templates — плагин для технологий bh.js и bemhtml.js.

Как работает

Оба плагина используют хелпер, который умеет парсить js-файлы, и искать в AST объектные литералы, которые похожи на BEMJSON (есть поля block, elem, mods, elemMods). Плагины, затем, проверяют наличие зависимостей от найденных БЭМ-сущностей в deps.js.

Когда мы пишем BEMJSON в шаблонах, мы, обычно, хотим передать его в applyCtx или вернуть из дефолтной моды, то есть хотим вместо текущего BEMJSON обработать какой-то другой. Чтобы для нового BEMJSON отработали шаблоны и на клиент попали стили и javascript, нужно чтобы все БЭМ-сущности были указаны в shouldDeps или в mustDeps. У блока могут быть опциональные зависимости, которые нужно подключать только если API блока используется определённым образом. Например, если у блока button2 используется поле icon, нужно дополнительно прописать зависимость от блока icon. Чтобы уменьшить вероятность ложных срабатываний в таких случаях, плагин игнорирует код находящийся внутри условных конструкций (if, ? :, &&, ||).

// a.bemhtml.js
block('a').def()(function() {
    return {
        block: 'b',
        mix: [{block: 'mixed', mods: {name: 'val'}, js: true}],
        content: [
            {elem: 'e'},
            this.ctx.d && {elem: 'd'}
        ]
    }
});

// a.deps.js
({
    mustDeps: [
        // Такая зависимость должна быть у всех блоков с bemhtml (до bem-xjst 4.0), плагин это не проверяет
        {block: 'i-bem', elem: 'html'},
        // Элемент d опциональный, находится за логическим оператором, плагином игнорируется
        {block: 'b', elems: ['e']},
        {block: 'mixed', mods: {name: 'val'}}
    ]
});

Когда BEMJSON встречается внутри клиентского js, это значит, обычно, что мы собираемся передать его шаблонизатору. В этом случае справедливо всё что написано в предыдущем абзаце: нужно указать shouldDeps/mustDeps от всех сущностей из BEMJSON, кроме опциональных. Кроме того, в клиентский js должны попасть шаблоны этих сущностей. Для этого должны быть правильно прописаны depsByTech: в зависимости по технологиям jsbemhtml нужно прописать все блоки, кроме тех, которые переданы в поле mix (они не участвуют в шаблонизации). Для защиты от ложных срабатываний, кроме конструкций ветвления, плагин игнорирет findBlock*() методы, BEM.create(), BEM.HTML.decl(), BEM.HTML.build(), первый аргумент BEM.DOM.decl().

// a.js
BEM.dom.decl({block: 'a'}, {
    method: function() {
        var c = this.findBlockInside({block: 'c'});
        BEM.DOM.update(this.elem('e'), BEMHTML.apply({
            block: 'b',
            mix: {block: 'a', elem: 'e'},
            content: [
                {elem: 'e1'},
                _buildOther(),
                this.params.d ? {block: 'd'} : ''
            ]
        }))
    },
    _buildOther: function() {
        return [
            {elem: 'e2'},
            {block: 'f'}
        ],
    }
});

// a.deps.js
([{
    mustDeps: [
        // Зависимость должна быть у всех блоков использующих BEM.DOM
        {block: 'i-bem', elem: 'dom'}
    ],
    shouldDeps: [
        // Элемент используется внутри поля mix, depsByTech для него не нужны
        {elem: 'e'},
        // Плагин игнорирует не предупреждает про e2, т.к. не умеет прокидывать контекст блока в другой литерал
        {block: 'b', elems: ['e1', 'e2']},
        {block: 'f'}
        // Блок d опциональный, находится за условным оператором, плагином игнорируется
    ]
}, {
    // Для сущностей участвующих в шаблонизации прописываем depsByTech
    tech: 'js',
    shouldDeps: [
        {tech: 'bemhtml', block: 'b', elems: ['e1', 'e2']},
        {tech: 'bemhtml', block: 'f'}
    ]
}]);