Skip to content
This repository was archived by the owner on Feb 4, 2018. It is now read-only.

Commit a13afe1

Browse files
committed
BREAKING: simplify construct and add create method
1 parent 5408901 commit a13afe1

File tree

4 files changed

+158
-63
lines changed

4 files changed

+158
-63
lines changed

index.js

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
'use strict';
22

3+
const assert = require('assert');
34
const util = require('util');
45

56
const stringifyEntity = require('bem-naming').stringify;
7+
const parseEntity = require('bem-naming').parse;
68

79
/**
810
* Enum for types of BEM entities.
@@ -23,30 +25,17 @@ module.exports = class BemEntityName {
2325
* @param {string} obj.block — the block name of entity.
2426
* @param {string} [obj.elem] — the element name of entity.
2527
* @param {object} [obj.mod] — the modifier of entity.
26-
* @param {string} [obj.mod.name] — the modifier name of entity.
28+
* @param {string} obj.mod.name — the modifier name of entity.
2729
* @param {string} [obj.mod.val] — the modifier value of entity.
2830
*/
2931
constructor(obj) {
30-
if (!obj.block) {
31-
throw new Error('This is not valid BEM entity: the field `block` is undefined.');
32-
}
32+
assert(obj.block, 'This is not valid BEM entity: the field `block` is undefined.');
33+
assert(!obj.mod || obj.mod.name, 'This is not valid BEM entity: the field `mod.name` is undefined.');
3334

3435
const data = this._data = { block: obj.block };
3536

3637
obj.elem && (data.elem = obj.elem);
37-
38-
const modObj = obj.mod;
39-
const modName = (typeof modObj === 'string' ? modObj : modObj && modObj.name) || obj.modName;
40-
const hasModVal = modObj && modObj.hasOwnProperty('val') || obj.hasOwnProperty('modVal');
41-
42-
if (modName) {
43-
data.mod = {
44-
name: modName,
45-
val: hasModVal ? modObj && modObj.val || obj.modVal : true
46-
};
47-
} else if (modObj || hasModVal) {
48-
throw new Error('This is not valid BEM entity: the field `mod.name` is undefined.');
49-
}
38+
obj.mod && (data.mod = { name: obj.mod.name, val: obj.mod.val || true });
5039

5140
this.__isBemEntityName__ = true;
5241
}
@@ -285,4 +274,50 @@ module.exports = class BemEntityName {
285274
static isBemEntityName(entityName) {
286275
return entityName && entityName.__isBemEntityName__;
287276
}
277+
278+
/**
279+
* Creates BemEntityName instance by the any object representation.
280+
*
281+
* @param {object} obj — representation of entity name.
282+
* @param {string} obj.block — the block name of entity.
283+
* @param {string} [obj.elem] — the element name of entity.
284+
* @param {object|string} [obj.mod] — the modifier of entity.
285+
* @param {string} [obj.mod.name] — the modifier name of entity.
286+
* @param {string} [obj.mod.val] — the modifier value of entity.
287+
* @param {string} [obj.modName] — the modifier name of entity.
288+
* @param {string} [obj.modVal] — the modifier value of entity.
289+
*
290+
* @returns {BemEntityName} An object representing entity name.
291+
* @example
292+
* const BemEntityName = require('@bem/entity-name');
293+
*
294+
* BemEntityName.create('my-button_theme_red');
295+
* BemEntityName.create({ block: 'my-button', mod: 'theme', val: 'red' });
296+
* BemEntityName.create({ block: 'my-button', modName: 'theme', modVal: 'red' });
297+
* // BemEntityName { block: 'my-button', mod: { name: 'theme', val: 'red' } }
298+
*/
299+
static create(obj) {
300+
if (BemEntityName.isBemEntityName(obj)) {
301+
return obj;
302+
}
303+
304+
const data = { block: obj.block };
305+
const mod = obj.mod;
306+
307+
obj.elem && (data.elem = obj.elem);
308+
309+
if (mod || obj.modName) {
310+
const isString = typeof mod === 'string';
311+
const modName = (isString ? mod : mod && mod.name) || obj.modName;
312+
const modObj = !isString && mod || obj;
313+
const hasModVal = modObj.hasOwnProperty('val') || obj.hasOwnProperty('modVal');
314+
315+
data.mod = {
316+
name: modName,
317+
val: hasModVal ? modObj.val || obj.modVal : true
318+
};
319+
}
320+
321+
return new BemEntityName(data);
322+
}
288323
};

test/valid.test.js renamed to test/construct.test.js

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,30 @@ const test = require('ava');
22

33
const BemEntityName = require('../index');
44

5+
test('should create object for block', t => {
6+
const data = { block: 'b' };
7+
8+
t.deepEqual((new BemEntityName(data)).valueOf(), data);
9+
});
10+
11+
test('should create object for block and elem', t => {
12+
const data = { block: 'b', elem: 'e' };
13+
14+
t.deepEqual((new BemEntityName(data)).valueOf(), data);
15+
});
16+
17+
test('should create object for block and mod', t => {
18+
const data = { block: 'b', mod: { name: 'm', val: 'v' } };
19+
20+
t.deepEqual((new BemEntityName(data)).valueOf(), data);
21+
});
22+
23+
test('should create object and normalize boolean modifier', t => {
24+
const entity = new BemEntityName({ block: 'block', mod: { name: 'mod' } });
25+
26+
t.deepEqual(entity.valueOf(), { block: 'block', mod: { name: 'mod', val: true } });
27+
});
28+
529
test('should throw error for if entity object is not valid', t => {
630
t.throws(
731
() => new BemEntityName({ elem: 'elem' }),
@@ -22,10 +46,3 @@ test('should throw error for if mod name is undefined', t => {
2246
'This is not valid BEM entity: the field `mod.name` is undefined.'
2347
);
2448
});
25-
26-
test('should throw error for if modName is undefined', t => {
27-
t.throws(
28-
() => new BemEntityName({ block: 'block', modVal: 'val' }),
29-
'This is not valid BEM entity: the field `mod.name` is undefined.'
30-
);
31-
});

test/create.test.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
const test = require('ava');
2+
3+
const BemEntityName = require('../index');
4+
5+
test('should return object as is if it`s a BemEntityName', t => {
6+
const entity = new BemEntityName({ block: 'b' });
7+
8+
t.is(BemEntityName.create(entity), entity);
9+
});
10+
11+
test('should create BemEntityName for block from obj', t => {
12+
const entity = BemEntityName.create({ block: 'b' });
13+
14+
t.pass(entity instanceof BemEntityName, 'Should be an instance of BemEntityName');
15+
t.deepEqual(entity.valueOf(), { block: 'b' }, 'Should contain a name for same entity');
16+
});
17+
18+
test('should create entity for elem from obj', t => {
19+
const entity = BemEntityName.create({ block: 'b', elem: 'e' });
20+
21+
t.deepEqual(entity.valueOf(), { block: 'b', elem: 'e' });
22+
});
23+
24+
test('should create entity from obj with deps mods without value', t => {
25+
const entity = BemEntityName.create({ block: 'b', mod: 'm' });
26+
27+
t.deepEqual(entity.valueOf(), { block: 'b', mod: { name: 'm', val: true } });
28+
});
29+
30+
test('should create entity from obj with deps mods', t => {
31+
const entity = BemEntityName.create({ block: 'b', mod: 'm', val: 'v' });
32+
33+
t.deepEqual(entity.valueOf(), { block: 'b', mod: { name: 'm', val: 'v' } });
34+
});
35+
36+
test('should normalize boolean modifier', t => {
37+
const entity = BemEntityName.create({ block: 'block', mod: { name: 'mod' } });
38+
39+
t.true(entity.mod.val);
40+
});
41+
42+
test('should normalize short entry for boolean modifier', t => {
43+
const entity = BemEntityName.create({ block: 'block', mod: 'mod' });
44+
45+
t.true(entity.mod.val);
46+
});
47+
48+
test('should support `modName` and `modVal` fields', t => {
49+
const entity = BemEntityName.create({ block: 'block', modName: 'mod', modVal: 'val' });
50+
51+
t.deepEqual(entity.mod, { name: 'mod', val: 'val' });
52+
});
53+
54+
test('should support `modName` field only', t => {
55+
const entity = BemEntityName.create({ block: 'block', modName: 'mod' });
56+
57+
t.deepEqual(entity.mod, { name: 'mod', val: true });
58+
});
59+
60+
test('should use `mod.name` field instead of `modName`', t => {
61+
const entity = BemEntityName.create({ block: 'block', mod: { name: 'mod1' }, modName: 'mod2' });
62+
63+
t.is(entity.mod.name, 'mod1');
64+
});
65+
66+
test('should use `mod.val` field instead of `modVal`', t => {
67+
const entity = BemEntityName.create({ block: 'block', mod: { name: 'm', val: 'v1' }, modVal: 'v2' });
68+
69+
t.is(entity.mod.val, 'v1');
70+
});
71+
72+
test('should use `mod.name` and `mod.val` instead of `val`', t => {
73+
const entity = BemEntityName.create({ block: 'block', mod: { name: 'm', val: 'v1' }, val: 'v3'});
74+
75+
t.is(entity.mod.val, 'v1');
76+
});
77+
78+
test('should use `mod.name` and `mod.val` instead of `modVal` and `val`', t => {
79+
const entity = BemEntityName.create({ block: 'block', mod: { name: 'm', val: 'v1' }, modVal: 'v2', val: 'v3'});
80+
81+
t.is(entity.mod.val, 'v1');
82+
});

test/normalize.test.js

Lines changed: 0 additions & 39 deletions
This file was deleted.

0 commit comments

Comments
 (0)