bem / bh

BH template engine
http://bem.github.io/bh/
MIT License
68 stars 31 forks source link

Add global matcher #121

Closed dosyara closed 9 years ago

dosyara commented 9 years ago

For extension purposes of BH-core functionality it wood be good to have API to set global matcher. This matcher must be executed on each BEMJSON-node to make necessary modifications. As I understand, it's possible to want to execute some code before and after other user matchers. So, probably, we need beforeEach and afterEach kind of matchers.

mishanga commented 9 years ago

Предлагаемый синтаксис: beforeEach: bh.match('<', function(ctx) { ... }) afterEach: bh.match('>', function(ctx) { ... })

mishanga commented 9 years ago

Второй вариант: bh.beforeEach(function(ctx) { ... }) bh.afterEach(function(ctx) { ... })

sameoldmadness commented 9 years ago

Я за второй вариант. По нему можно догадаться, что происходит, не заглядывая в документацию.

qfox commented 9 years ago

Все-таки решились на это? ;-\

tadatuta commented 9 years ago

Предлагаю в этом месте сделать консистентно с BEMHTML:

bh.match(function() {}, function() {});

смотреть в typeof первого аргумента и если там функция, выполнять шаблон только для кейсов, когда она возвращает truly-значение.

dosyara commented 9 years ago

Это же нельзя делать консистентно c BEMHTML, у шаблонизаторов разная "механика". У BH нет нигде подобного паттерна.

tadatuta commented 9 years ago

@dosyara Разве с точки зрения механики

bh.match(function(ctx) {
    return ctx === 'bla';
}, function(ctx) { doSomething(); });`

чем-то отличается от

bh.beforeEach(function(ctx) {
   if (ctx === 'bla') doSomething();
});

?

qfox commented 9 years ago

Там не все так просто, не получится смотреть в typeof. Из этих матчеров собираются switch-case, и при добавлении матчера оно сбрасывает «кеш» собранных свичкейсов и пересобирает его при следующем вызове apply.

Т.е. ты прав, но этот function должен будет отрабатывать в switch-case, а с учетом того, что порядок играет — я не очень себе представляю, как это должно будет работать так, что результат был ожидаемым. Может я перебдел, конечно, но пока кажется, что это просто нереально.

Но даже если я не прав в предыдущем — то beforeEach — это последний матчер, afterEach — первый, но

Пара проблем из тех, которые, кмк, не позволяют это сделать.

mishanga commented 9 years ago

@tadatuta @zxqfox все шаблоны перед запуском компилируются примерно в такую конструкцию:

function applyMatchers(ctx, json) {
    subRes = _m2(ctx, json); // beforeEach
    switch (json.block) {
       case "button":
           switch (json.elem) {
               case undefined:
                   subRes = _m0(ctx, json); // match('button')
           }
       }
    }         
    subRes = _m1(ctx, json); // afterEach
};

То есть там получается один большой switch, в который нельзя добавить глобальный шаблон. Можно только перед switch или после. Но для разных задач нужен разный порядок исполнения: где-то глобальный шаблон должен применяться до всех остальных, где-то после. Поэтому пришлось сделать явное разделение на beforeEach и afterEach.

gruzzilkin commented 9 years ago

А можно дополнить README с описанием и примером применения этой фичи? @zxqfox

qfox commented 9 years ago

@gruzzilkin Есть предложение что написать в ридми? ;)

gruzzilkin commented 9 years ago

@zxqfox Например, что данные методы можно использовать для преобразования входящего JSON в BEMJSON и последующим применением шаблонов bh. Т.е. по сути с помощью beforeEach можно делать то же самое, что и с помощью bemtree.

mishanga commented 9 years ago

Про это даже есть issue: #142 Но у меня руки не доходят.