Comparing version 4.1.0 to 4.1.1
# Changelog | ||
## 4.1.1 | ||
- Some documentation fixes. | ||
- Added `shortTags` option (#149). | ||
- Added `delimElem` и `delimMod` options (#150). | ||
## 4.1.0 | ||
@@ -4,0 +9,0 @@ - Ability to replace `toHtml` method for only node (#144). |
# История изменений | ||
## 4.1.1 | ||
- Дополнена и исправлена документация. | ||
- Добавлена опция `shortTags` (#149). | ||
- Добавлена опции `delimElem` и `delimMod` (#150). | ||
## 4.1.0 | ||
@@ -4,0 +9,0 @@ - Добавлена возможность переопределять метод `toHtml` для любого узла (#144). |
155
lib/bh.js
@@ -44,2 +44,9 @@ var BH = (function() { | ||
/** | ||
* Оптимизация коротких тегов. Они могут быть расширены через setOptions({ shortTags: [...] }) | ||
*/ | ||
this._shortTags = {}; | ||
for (var i = 0; i < SHORT_TAGS.length; i++) { | ||
this._shortTags[SHORT_TAGS[i]] = 1; | ||
} | ||
/** | ||
* Опции BH. Задаются через setOptions. | ||
@@ -55,2 +62,4 @@ * @type {Object} | ||
this._optNobaseMods = false; | ||
this._optDelimElem = '__'; | ||
this._optDelimMod = '_'; | ||
this.utils = { | ||
@@ -313,13 +322,14 @@ _expandoId: new Date().getTime(), | ||
* ``` | ||
* @param {String} [tagName] | ||
* @param {String} [value] | ||
* @param {Boolean} [force] | ||
* @returns {String|undefined|Ctx} | ||
*/ | ||
tag: function(tagName, force) { | ||
if (tagName !== undefined) { | ||
this.ctx.tag = this.ctx.tag === undefined || force ? tagName : this.ctx.tag; | ||
return this; | ||
} else { | ||
tag: function(value, force) { | ||
if (value === undefined) { | ||
return this.ctx.tag; | ||
} | ||
if (force || this.ctx.tag === undefined) { | ||
this.ctx.tag = value; | ||
} | ||
return this; | ||
}, | ||
@@ -347,3 +357,2 @@ /** | ||
} | ||
this.ctx.mix = (force || !this.ctx.mix) ? | ||
@@ -353,3 +362,2 @@ mix : | ||
.concat(mix); | ||
return this; | ||
@@ -393,8 +401,7 @@ }, | ||
var attrs = this.ctx.attrs || {}; | ||
if (values !== undefined) { | ||
this.ctx.attrs = force ? this.extend(attrs, values) : this.extend(values, attrs); | ||
return this; | ||
} else { | ||
if (values === undefined) { | ||
return attrs; | ||
} | ||
this.ctx.attrs = force ? this.extend(attrs, values) : this.extend(values, attrs); | ||
return this; | ||
}, | ||
@@ -410,13 +417,14 @@ /** | ||
* ``` | ||
* @param {Boolean} [bem] | ||
* @param {Boolean} [value] | ||
* @param {Boolean} [force] | ||
* @returns {Boolean|undefined|Ctx} | ||
*/ | ||
bem: function(bem, force) { | ||
if (bem !== undefined) { | ||
this.ctx.bem = this.ctx.bem === undefined || force ? bem : this.ctx.bem; | ||
return this; | ||
} else { | ||
bem: function(value, force) { | ||
if (value === undefined) { | ||
return this.ctx.bem; | ||
} | ||
if (force || this.ctx.bem === undefined) { | ||
this.ctx.bem = value; | ||
} | ||
return this; | ||
}, | ||
@@ -437,10 +445,9 @@ /** | ||
js: function(js, force) { | ||
if (js !== undefined) { | ||
this.ctx.js = force ? | ||
(js === true ? {} : js) : | ||
js ? this.extend(this.ctx.js, js) : this.ctx.js; | ||
return this; | ||
} else { | ||
if (js === undefined) { | ||
return this.ctx.js; | ||
} | ||
this.ctx.js = force ? | ||
(js === true ? {} : js) : | ||
js ? this.extend(this.ctx.js, js) : this.ctx.js; | ||
return this; | ||
}, | ||
@@ -455,13 +462,14 @@ /** | ||
* ``` | ||
* @param {String} [cls] | ||
* @param {String} [value] | ||
* @param {Boolean} [force] | ||
* @returns {String|Ctx} | ||
*/ | ||
cls: function(cls, force) { | ||
if (cls !== undefined) { | ||
this.ctx.cls = this.ctx.cls === undefined || force ? cls : this.ctx.cls; | ||
return this; | ||
} else { | ||
cls: function(value, force) { | ||
if (value === undefined) { | ||
return this.ctx.cls; | ||
} | ||
if (force || this.ctx.cls === undefined) { | ||
this.ctx.cls = value; | ||
} | ||
return this; | ||
}, | ||
@@ -484,8 +492,9 @@ /** | ||
param: function(key, value, force) { | ||
if (value !== undefined) { | ||
this.ctx[key] = this.ctx[key] === undefined || force ? value : this.ctx[key]; | ||
return this; | ||
} else { | ||
if (value === undefined) { | ||
return this.ctx[key]; | ||
} | ||
if (force || this.ctx[key] === undefined) { | ||
this.ctx[key] = value; | ||
} | ||
return this; | ||
}, | ||
@@ -505,8 +514,9 @@ /** | ||
content: function(value, force) { | ||
if (arguments.length > 0) { | ||
this.ctx.content = this.ctx.content === undefined || force ? value : this.ctx.content; | ||
return this; | ||
} else { | ||
if (value === undefined) { | ||
return this.ctx.content; | ||
} | ||
if (force || this.ctx.content === undefined) { | ||
this.ctx.content = value; | ||
} | ||
return this; | ||
}, | ||
@@ -526,8 +536,9 @@ /** | ||
html: function(value, force) { | ||
if (arguments.length > 0) { | ||
this.ctx.html = this.ctx.html === undefined || force ? value : this.ctx.html; | ||
return this; | ||
} else { | ||
if (value === undefined) { | ||
return this.ctx.html; | ||
} | ||
if (force || this.ctx.html === undefined) { | ||
this.ctx.html = value; | ||
} | ||
return this; | ||
}, | ||
@@ -589,2 +600,14 @@ /** | ||
} | ||
if (options.delimElem) { | ||
this._optDelimElem = options.delimElem; | ||
} | ||
if (options.delimMod) { | ||
this._optDelimMod = options.delimMod; | ||
} | ||
if (options.shortTags) { | ||
for (var j = 0; j < options.shortTags.length; j++) { | ||
this._shortTags[options.shortTags[j]] = 1; | ||
} | ||
} | ||
return this; | ||
@@ -753,5 +776,5 @@ }, | ||
decl = { fn: matcherInfo[1], index: i }; | ||
if (~expr.indexOf('__')) { | ||
exprBits = expr.split('__'); | ||
blockExprBits = exprBits[0].split('_'); | ||
if (~expr.indexOf(this._optDelimElem)) { | ||
exprBits = expr.split(this._optDelimElem); | ||
blockExprBits = exprBits[0].split(this._optDelimMod); | ||
decl.block = blockExprBits[0]; | ||
@@ -762,3 +785,3 @@ if (blockExprBits.length > 1) { | ||
} | ||
exprBits = exprBits[1].split('_'); | ||
exprBits = exprBits[1].split(this._optDelimMod); | ||
decl.elem = exprBits[0]; | ||
@@ -770,3 +793,3 @@ if (exprBits.length > 1) { | ||
} else { | ||
exprBits = expr.split('_'); | ||
exprBits = expr.split(this._optDelimMod); | ||
decl.block = exprBits[0]; | ||
@@ -922,6 +945,6 @@ if (exprBits.length > 1) { | ||
if (json.__processCounter > 100) { | ||
throw new Error('Infinite json loop detected at "' + json.block + (json.elem ? '__' + json.elem : '') + '".'); | ||
throw new Error('Infinite json loop detected at "' + json.block + (json.elem ? this._optDelimElem + json.elem : '') + '".'); | ||
} | ||
if (compiledMatcher.__processCounter > 1000) { | ||
throw new Error('Infinite matcher loop detected at "' + json.block + (json.elem ? '__' + json.elem : '') + '".'); | ||
throw new Error('Infinite matcher loop detected at "' + json.block + (json.elem ? this._optDelimElem + json.elem : '') + '".'); | ||
} | ||
@@ -1045,6 +1068,6 @@ } | ||
if (isBEM) { | ||
var base = json.block + (json.elem ? '__' + json.elem : ''); | ||
var base = json.block + (json.elem ? this._optDelimElem + json.elem : ''); | ||
if (json.block) { | ||
cls = toBemCssClasses(json, base, null, this._optNobaseMods); | ||
cls = toBemCssClasses(json, base, null, this._optNobaseMods, this._optDelimMod); | ||
if (json.js) { | ||
@@ -1064,6 +1087,6 @@ (jsParams = {})[base] = json.js === true ? {} : json.js; | ||
mixElem = mix.elem || (mix.block ? null : json.block && json.elem), | ||
mixBase = mixBlock + (mixElem ? '__' + mixElem : ''); | ||
mixBase = mixBlock + (mixElem ? this._optDelimElem + mixElem : ''); | ||
if (mixBlock) { | ||
cls += toBemCssClasses(mix, mixBase, base, this._optNobaseMods); | ||
cls += toBemCssClasses(mix, mixBase, base, this._optNobaseMods, this._optDelimMod); | ||
if (mix.js) { | ||
@@ -1098,3 +1121,3 @@ (jsParams = jsParams || {})[mixBase] = mix.js === true ? {} : mix.js; | ||
if (selfCloseHtmlTags[tag]) { | ||
if (this._shortTags[tag]) { | ||
this._buf += '/>'; | ||
@@ -1114,21 +1137,3 @@ } else { | ||
var selfCloseHtmlTags = { | ||
area: 1, | ||
base: 1, | ||
br: 1, | ||
col: 1, | ||
command: 1, | ||
embed: 1, | ||
hr: 1, | ||
img: 1, | ||
input: 1, | ||
keygen: 1, | ||
link: 1, | ||
menuitem: 1, | ||
meta: 1, | ||
param: 1, | ||
source: 1, | ||
track: 1, | ||
wbr: 1 | ||
}; | ||
var SHORT_TAGS = 'area base br col command embed hr img input keygen link menuitem meta param source track wbr'.split(' '); | ||
@@ -1145,3 +1150,3 @@ var xmlEscape = BH.prototype.xmlEscape = function(str) { | ||
var toBemCssClasses = function(json, base, parentBase, nobase) { | ||
var toBemCssClasses = function(json, base, parentBase, nobase, delimMod) { | ||
var mods, mod, res = '', i; | ||
@@ -1158,3 +1163,3 @@ | ||
if (mod || mod === 0) { | ||
res += (nobase ? ' _' : ' ' + base + '_') + i + (mod === true ? '' : '_' + mod); | ||
res += ' ' + (nobase ? delimMod : base + delimMod) + i + (mod === true ? '' : delimMod + mod); | ||
} | ||
@@ -1161,0 +1166,0 @@ } |
@@ -5,3 +5,3 @@ { | ||
"name": "bh", | ||
"version": "4.1.0", | ||
"version": "4.1.1", | ||
"repository": "https://github.com/bem/bh", | ||
@@ -8,0 +8,0 @@ "licence": "MIT", |
@@ -15,7 +15,7 @@ BH [![NPM version](https://badge.fury.io/js/bh.svg)](http://badge.fury.io/js/bh) [![Build Status](https://travis-ci.org/bem/bh.svg?branch=master)](https://travis-ci.org/bem/bh) [![Dependency Status](https://gemnasium.com/bem/bh.svg)](https://gemnasium.com/bem/bh) [![Coverage Status](https://img.shields.io/coveralls/bem/bh.svg?branch=master)](https://coveralls.io/r/bem/bh) | ||
1. fast; | ||
1. easy to debug due to no need of compilation to another code; | ||
1. based on JavaScript (usage and extensions); | ||
1. easy to understand – it is a wrapper over a regular conversion of source BEMJSON to output BEMJSON / HTML; | ||
1. compact on client side (12.4 Kb after compression, 3.7 Kb after gzip); | ||
1. does not require a compilation. | ||
2. easy to debug due to no need of compilation to another code; | ||
3. based on JavaScript (usage and extensions); | ||
4. easy to understand – it is a wrapper over a regular conversion of source BEMJSON to output BEMJSON / HTML; | ||
5. compact on client side (12.4 Kb after compression, 3.7 Kb after gzip); | ||
6. does not require a compilation. | ||
@@ -40,3 +40,5 @@ ## Install | ||
Use `apply` method to convert source tree of BEMJSON into an output HTML. Use `processBemJson` method to get an interim result in detailed BEMJSON tree form. | ||
Use `apply` method to convert source tree of BEMJSON into an output HTML. | ||
Use `processBemJson` method to get an interim result in detailed BEMJSON tree form. | ||
Use `toHtml` method to get an output HTML without BEMJSON tree transform. | ||
@@ -52,2 +54,3 @@ Common use case: | ||
bh.apply({ block: 'button' }); // '<button class="button"></button>' | ||
bh.toHtml({ block: 'button' }); // '<div class="button"></div>' | ||
``` | ||
@@ -191,2 +194,16 @@ | ||
### jsElem | ||
`jsElem` controls the set up of an additional class of the [jsCls](https://github.com/bem/bh/blob/master/README.md#jscls) parameter for elements with `js`. Default value is `true`. If you set the `false` value, the additional class will not be added. | ||
```javascript | ||
bh.setOptions({ jsElem: false }); | ||
bh.apply({ block: 'button', elem: 'box', js: true }); | ||
``` | ||
```html | ||
<div class="button__box" onclick='return {"button__box":{}}'></div> | ||
``` | ||
### escapeContent | ||
@@ -204,2 +221,59 @@ | ||
### clsNobaseMods | ||
`clsNobaseMods` removes the block or element name from the modifier names in the class. Default value is `false`. | ||
```javascript | ||
bh.setOptions({ clsNobaseMods: true }); | ||
bh.apply({ | ||
block: 'button', | ||
mods: { disabled: true, theme: 'new' }, | ||
mix: [ | ||
{ block: 'clearfix' }, | ||
{ elem: 'box', elemMods: { pick: 'left' } } | ||
], | ||
content: { | ||
elem: 'control', | ||
elemMods: { disabled: true } | ||
} | ||
}); | ||
``` | ||
```html | ||
<div class="button _disabled _theme_new clearfix button__box _pick_left"> | ||
<div class="button__control _disabled"></div> | ||
</div> | ||
``` | ||
### delimElem | ||
Defines the delimiter between block and element names. Default value is `__`. | ||
```javascript | ||
bh.setOptions({ delimElem: '_' }); | ||
bh.apply({ block: 'button', elem: 'text' }); | ||
``` | ||
```html | ||
<div class="button_text"></div> | ||
``` | ||
### delimMod | ||
Defines the delimiter between block or element and they modifier. Default value is `_`. | ||
```javascript | ||
bh.setOptions({ delimMod: '--' }); | ||
bh.apply({ block: 'button', mods: { disabled: true } }); | ||
``` | ||
```html | ||
<div class="button button--disabled"></div> | ||
``` | ||
### shortTags | ||
`shortTags` extend default short tag list. | ||
```javascript | ||
bh.setOptions({ shortTags: ['rect'] }); | ||
``` | ||
## Additional examples | ||
@@ -206,0 +280,0 @@ |
@@ -37,3 +37,5 @@ BH [![NPM version](https://badge.fury.io/js/bh.svg)](http://badge.fury.io/js/bh) [![Build Status](https://travis-ci.org/bem/bh.svg?branch=master)](https://travis-ci.org/bem/bh) [![Dependency Status](https://gemnasium.com/bem/bh.svg)](https://gemnasium.com/bem/bh) [![Coverage Status](https://img.shields.io/coveralls/bem/bh.svg?branch=master)](https://coveralls.io/r/bem/bh) | ||
Для преобразования исходного дерева BEMJSON в конечный HTML используется метод `apply`. Для получения промежуточного результата в виде развернутого BEMJSON-дерева нужно использовать метод `processBemJson`. | ||
Для преобразования исходного дерева BEMJSON в конечный HTML используется метод `apply`. | ||
Для получения промежуточного результата в виде развернутого BEMJSON-дерева нужно использовать метод `processBemJson`. | ||
Для получения конечного HTML без преобразования BEMJSON-дерева используется метод `toHtml`. | ||
@@ -48,2 +50,3 @@ Простой пример использования: | ||
bh.apply({ block: 'button' }); // '<button class="button"></button>' | ||
bh.toHtml({ block: 'button' }); // '<div class="button"></div>' | ||
``` | ||
@@ -189,2 +192,15 @@ | ||
### jsElem | ||
Регулирует установку дополнительного класса, указанного в параметре [jsCls](https://github.com/bem/bh/blob/master/README.ru.md#jscls), для элемента с `js`-реализацией. По умолчанию `true`. Если задать значение `false`, дополнительный класс добавляться не будет. | ||
```javascript | ||
bh.setOptions({ jsElem: false }); | ||
bh.apply({ block: 'button', elem: 'box', js: true }); | ||
``` | ||
```html | ||
<div class="button__box" onclick='return {"button__box":{}}'></div> | ||
``` | ||
### escapeContent | ||
@@ -202,2 +218,59 @@ | ||
### clsNobaseMods | ||
Удаляет имя блока и/или элемента из имен модификаторов в классе. По умолчанию `false`. | ||
```javascript | ||
bh.setOptions({ clsNobaseMods: true }); | ||
bh.apply({ | ||
block: 'button', | ||
mods: { disabled: true, theme: 'new' }, | ||
mix: [ | ||
{ block: 'clearfix' }, | ||
{ elem: 'box', elemMods: { pick: 'left' } } | ||
], | ||
content: { | ||
elem: 'control', | ||
elemMods: { disabled: true } | ||
} | ||
}); | ||
``` | ||
```html | ||
<div class="button _disabled _theme_new clearfix button__box _pick_left"> | ||
<div class="button__control _disabled"></div> | ||
</div> | ||
``` | ||
### delimElem | ||
Задает разделитель между блоком и элементом. По умолчанию `__`. | ||
```javascript | ||
bh.setOptions({ delimElem: '_' }); | ||
bh.apply({ block: 'button', elem: 'text' }); | ||
``` | ||
```html | ||
<div class="button_text"></div> | ||
``` | ||
### delimMod | ||
Задает разделитель между блоком или элементом и их модификатором. По умолчанию `_`. | ||
```javascript | ||
bh.setOptions({ delimMod: '--' }); | ||
bh.apply({ block: 'button', mods: { disabled: true } }); | ||
``` | ||
```html | ||
<div class="button button--disabled"></div> | ||
``` | ||
### shortTags | ||
`shortTags` расширяет стандартный набор коротких тегов. | ||
```javascript | ||
bh.setOptions({ shortTags: ['rect'] }); | ||
``` | ||
## Дополнительные примеры | ||
@@ -204,0 +277,0 @@ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
343359
1178
661