From 2721a93cc3c75390894be65f74192d36971922e8 Mon Sep 17 00:00:00 2001 From: miripiruni Date: Mon, 12 Sep 2016 17:49:36 +0300 Subject: [PATCH] Fixed #274: Support `mod(m)` and `elemMod(em)` without second argument --- docs/ru/5-templates-syntax.md | 32 ++++++++++++++++++++++++++++++-- lib/bemxjst/match.js | 4 ++++ lib/bemxjst/tree.js | 6 ++++-- test/modes-elemmod-test.js | 28 ++++++++++++++++++++++++++++ test/modes-mod-test.js | 28 ++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 4 deletions(-) diff --git a/docs/ru/5-templates-syntax.md b/docs/ru/5-templates-syntax.md index c3edae65..2221674c 100644 --- a/docs/ru/5-templates-syntax.md +++ b/docs/ru/5-templates-syntax.md @@ -64,7 +64,7 @@ elem(name) ```js /** * @param {String} modName имя модификатора блока - * @param {String|Boolean} modVal значение модификатора блока + * @param {String|Boolean|'*'} [modVal] значение модификатора блока */ mod(modName, modVal) ``` @@ -117,12 +117,36 @@ block('item') ``` +Если второй аргумет `mod()` отсутствует либо равен '*' тогда будут к узлу будут +применены шаблоны для соответствующего модификатора с любым значением. + +```js +block('a').mod('size').tag()('span'); +block('a').mod('size', '*').mix()('sized'); +``` +Оба шаблона будут применены к узлам BEMJSON-а, у которых блок равен 'a' и +присутствует модификатор 'size' (со значением отличным от `undefined`). + +```js +{ block: 'a', mods: { size: 's' } }, +{ block: 'a', mods: { size: 10 } }, +{ block: 'a', mods: { size: '', theme: 'dark' } } +``` + +Но шаблоны не будут применены к узлам: +```js +{ block: 'a', mods: { theme: 'dark' } }, +{ block: 'a', mods: { size: undefined } }, +{ block: 'a', mods: {} } +``` + + ### elemMod ```js /** * @param {String} elemModName имя модификатора элемента - * @param {String|Boolean} elemModVal значение модификатора элемента + * @param {String|Boolean|'*'} [elemModVal] значение модификатора элемента */ elemMod(elemModName, elemModVal) ``` @@ -152,6 +176,10 @@ block('page').elem('content').elemMod('type', 'index').mix()({ block: 'mixed' }) `elemModVal` проверяются на соответствие после приведения к строке. Это поведение аналогично поведению проверки `modVal`. +Второй аргумент `elemMods()` так же может отстуствовать или быть равен '*', в +этом случае поведение аналогичное режиму `mods()` — будут примерены шаблоны с +подпредикатом модификатора любого значения. + ### match ```js diff --git a/lib/bemxjst/match.js b/lib/bemxjst/match.js index c17b38a7..ad2965e7 100644 --- a/lib/bemxjst/match.js +++ b/lib/bemxjst/match.js @@ -22,12 +22,16 @@ function MatchNested(template, pred) { MatchNested.prototype.exec = function exec(context) { var val = context; + for (var i = 0; i < this.keys.length - 1; i++) { val = val[this.keys[i]]; if (!val) return false; } + if (this.value === '*') + return val[this.keys[i]] !== undefined; + return String(val[this.keys[i]]) === this.value; }; diff --git a/lib/bemxjst/tree.js b/lib/bemxjst/tree.js index 0481520d..593dbc05 100644 --- a/lib/bemxjst/tree.js +++ b/lib/bemxjst/tree.js @@ -367,11 +367,13 @@ Tree.prototype.mode = function mode(name) { }; Tree.prototype.mod = function mod(name, value) { - return this.match(new PropertyMatch([ 'mods', name ], String(value))); + return this.match(new PropertyMatch([ 'mods', name ], + value === undefined ? '*' : String(value))); }; Tree.prototype.elemMod = function elemMod(name, value) { - return this.match(new PropertyMatch([ 'elemMods', name ], String(value))); + return this.match(new PropertyMatch([ 'elemMods', name ], + value === undefined ? '*' : String(value))); }; Tree.prototype.def = function def() { diff --git a/test/modes-elemmod-test.js b/test/modes-elemmod-test.js index 237b33ce..05c097ad 100644 --- a/test/modes-elemmod-test.js +++ b/test/modes-elemmod-test.js @@ -60,6 +60,34 @@ describe('Modes elemMod(elemModName, elemModVal)', function() { }); describe('elemModVal types', function() { + it('string should support elemMod with wildcard', function() { + test(function() { + block('b').elem('e').elemMod('m', '*').tag()('span'); + }, + [ + { block: 'b', elem: 'e', elemMods: { m: true } }, + { block: 'b', elem: 'e', elemMods: { m: 'test' } }, + { block: 'b', elem: 'e', elemMods: { no: 'test' } } + ], + '' + + '' + + '
'); + }); + + it('string should support elemMod with one argument', function() { + test(function() { + block('b').elem('e').elemMod('m').tag()('span'); + }, + [ + { block: 'b', elem: 'e', elemMods: { m: true } }, + { block: 'b', elem: 'e', elemMods: { m: 'test' } }, + { block: 'b', elem: 'e', elemMods: { no: 'test' } } + ], + '' + + '' + + '
'); + }); + it('number should match to string', function() { test(function() { block('b').elem('e').elemMod('em', 1).tag()('span'); diff --git a/test/modes-mod-test.js b/test/modes-mod-test.js index dec06ac1..f88df91d 100644 --- a/test/modes-mod-test.js +++ b/test/modes-mod-test.js @@ -83,5 +83,33 @@ describe('Modes .mod(modName, modVal)', function() { { block: 'b', mods: { m: null } }, '
'); }); + + it('should support mod with wildcard', function() { + test(function() { + block('b').mod('m', '*').tag()('span'); + }, + [ + { block: 'b', mods: { m: true } }, + { block: 'b', mods: { m: 'test' } }, + { block: 'b', mods: { no: 'test' } } + ], + '' + + '' + + '
'); + }); + + it('string should support mod with one argument', function() { + test(function() { + block('b').mod('m').tag()('span'); + }, + [ + { block: 'b', mods: { m: true } }, + { block: 'b', mods: { m: 'test' } }, + { block: 'b', mods: { no: 'test' } } + ], + '' + + '' + + '
'); + }); }); });