Skip to content

Commit

Permalink
Merge pull request #13 from bem-sdk/yeti-or.docs
Browse files Browse the repository at this point in the history
Merge to master
  • Loading branch information
Yeti-or committed Mar 10, 2017
2 parents a4b338e + 66cc725 commit f0d6c38
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 4 deletions.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Tool for working with BEM import strings.
[dependency-img]: http://img.shields.io/david/bem-sdk/bem-import-notation.svg


Extract [BEM entities](https://en.bem.info/methodology/key-concepts/#bem-entity) from import strings.
Extract [BEM entities] from import strings.

Installation
------------
Expand Down Expand Up @@ -51,6 +51,7 @@ API
---

* [parse](#parsestr-ctx)
* [stringify](#stringify)

### parse(str, ctx)

Expand Down Expand Up @@ -84,6 +85,15 @@ Note that, using context exludes `{ block: 'button'}` from result.

So `parse('m:theme=normal', { block: 'button' })` is not same as `parse('b:button m:theme=normal')`

### stringify

Parameter | Type | Description
----------|----------|------------------------------------------------------------------------------
`entities`| `array` | Array of [BEM entities] to merge into import string [notation](#notation)

Forms a string from [BEM entities]. Be aware to merge only one type of entities.
The array should contains one block or one elem and optionally it's modifiers.

Notation
--------

Expand Down Expand Up @@ -211,3 +221,5 @@ License
-------

Code and documentation copyright 2017 YANDEX LLC. Code released under the [Mozilla Public License 2.0](LICENSE.txt).

[BEM entities]: https://en.bem.info/methodology/key-concepts/#bem-entity
38 changes: 36 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
* `import 'm:modOfThisBlock`
* @returns {BemCell[]}
*/

function parse(importString, ctx) {
const main = {};
ctx || (ctx = {});
Expand Down Expand Up @@ -60,6 +59,41 @@ function parse(importString, ctx) {
}, []);
}

/**
* Create import string notation of passed bem-cells.
*
* Example:
* ```js
* stringify([{ block : 'button' }, { block : 'button', mod : { name : 'theme', val : 'normal' } }])
* // 'b:button m:theme=normal'
* ```
* @public
* @param {BemCell[]} - Set of BEM entites to merge into import string notation
* @returns {String}
*/
function stringify(cells) {
const merged = [].concat(cells).reduce((acc, cell) => {
cell.block && (acc.b = cell.block);
cell.elem && (acc.e = cell.elem);
cell.mod && (acc.m[cell.mod.name] || (acc.m[cell.mod.name] = []))
&& cell.mod.val && acc.m[cell.mod.name].push(cell.mod.val);
cell.tech && (acc.t = cell.tech);
return acc;
}, { m : {} });

return ['b', 'e', 'm', 't'].map(k => tmpl[k](merged[k])).join('');
}

const tmpl = {
b : b => `b:${b}`,
e : e => e ? ` e:${e}` : '',
m : m => Object.keys(m).map(name => `${tmpl.mn(name)}${tmpl.mv(m[name])}`).join(''),
mn : m => ` m:${m}`,
mv : v => v.length ? `=${v.join('|')}` : '',
t : t => t ? ` t:${t}` : ''
};

module.exports = {
parse
parse,
stringify
};
2 changes: 1 addition & 1 deletion test.js → test/parse.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var expect = require('chai').expect,
p = require('.').parse;
p = require('..').parse;

it('should return an array', () => {
expect(p('b:button')).to.be.an('Array');
Expand Down
118 changes: 118 additions & 0 deletions test/stringify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
var expect = require('chai').expect,
s = require('..').stringify;

it('should return a string', () => {
expect(s([{ block : 'button' }])).to.be.an('String');
});

describe('block', () => {
it('should stringify block', () => {
expect(s({ block : 'button' })).to.be.equal('b:button');
});

it('should stringify block with simple modifier', () => {
expect(s([
{ block : 'popup' },
{ block : 'popup', mod : { name : 'autoclosable' } }
])).to.be.equal('b:popup m:autoclosable');
});

it('should stringify block with modifier', () => {
expect(s([
{ block : 'popup' },
{ block : 'popup', mod : { name : 'autoclosable' } },
{ block : 'popup', mod : { name : 'autoclosable', val : 'yes' } }
])).to.equal('b:popup m:autoclosable=yes');
});

it('should stringify block with modifier and several values', () => {
expect(s([
{ block : 'popup' },
{ block : 'popup', mod : { name : 'theme' } },
{ block : 'popup', mod : { name : 'theme', val : 'normal' } },
{ block : 'popup', mod : { name : 'theme', val : 'action' } }
])).to.equal('b:popup m:theme=normal|action');
});

it('should stringify block with several modifiers', () => {
expect(s([
{ block : 'popup' },
{ block : 'popup', mod : { name : 'theme' } },
{ block : 'popup', mod : { name : 'autoclosable' } }
])).to.equal('b:popup m:theme m:autoclosable');
});

it('should stringify block with several modifiers and several values', () => {
expect(s([
{ block : 'popup' },
{ block : 'popup', mod : { name : 'theme' } },
{ block : 'popup', mod : { name : 'theme', val : 'normal' } },
{ block : 'popup', mod : { name : 'theme', val : 'action' } },
{ block : 'popup', mod : { name : 'autoclosable' } },
{ block : 'popup', mod : { name : 'autoclosable', val : 'yes' } }
])).to.equal('b:popup m:theme=normal|action m:autoclosable=yes');
});
});

describe('elem', () => {
it('should stringify elem', () => {
expect(s([{ block : 'button', elem : 'text' }])).to.be.equal('b:button e:text');
});

it('should stringify elem with simple modifier', () => {
expect(s([
{ block : 'button2', elem : 'text' },
{ block : 'button2', elem : 'text', mod : { name : 'pseudo' } }
])).to.equal('b:button2 e:text m:pseudo');
});

it('should stringify elem with modifier', () => {
expect(s([
{ block : 'button2', elem : 'text' },
{ block : 'button2', elem : 'text', mod : { name : 'pseudo' } },
{ block : 'button2', elem : 'text', mod : { name : 'pseudo', val : 'yes' } }
])).to.equal('b:button2 e:text m:pseudo=yes');
});

it('should stringify elem with modifier and several values', () => {
expect(s([
{ block : 'button2', elem : 'text' },
{ block : 'button2', elem : 'text', mod : { name : 'theme' } },
{ block : 'button2', elem : 'text', mod : { name : 'theme', val : 'normal' } },
{ block : 'button2', elem : 'text', mod : { name : 'theme', val : 'action' } }
])).to.equal('b:button2 e:text m:theme=normal|action');
});

it('should stringify elem with several modifiers', () => {
expect(s([
{ block : 'popup', elem : 'tail' },
{ block : 'popup', elem : 'tail', mod : { name : 'theme' } },
{ block : 'popup', elem : 'tail', mod : { name : 'autoclosable' } }
])).to.equal('b:popup e:tail m:theme m:autoclosable');
});

it('should stringify elem with several modifiers and several values', () => {
expect(s([
{ block : 'popup', elem : 'tail' },
{ block : 'popup', elem : 'tail', mod : { name : 'theme' } },
{ block : 'popup', elem : 'tail', mod : { name : 'theme', val : 'normal' } },
{ block : 'popup', elem : 'tail', mod : { name : 'theme', val : 'action' } },
{ block : 'popup', elem : 'tail', mod : { name : 'autoclosable' } },
{ block : 'popup', elem : 'tail', mod : { name : 'autoclosable', val : 'yes' } }
])).to.equal('b:popup e:tail m:theme=normal|action m:autoclosable=yes');
});
});

describe('tech', () => {
it('should stringify block with tech', () => {
expect(s({ block : 'button', tech : 'css' })).to.be.equal('b:button t:css');
});

it('should stringify block with mod and tech', () => {
expect(s([
{ block : 'popup', tech : 'js' },
{ block : 'popup', mod : { name : 'autoclosable' }, tech : 'js' },
{ block : 'popup', mod : { name : 'autoclosable', val : 'yes' }, tech : 'js' }
])).to.be.equal('b:popup m:autoclosable=yes t:js');
});
});

0 comments on commit f0d6c38

Please sign in to comment.