Skip to content

Commit

Permalink
Add normalize2 + fix/add some tests issue#3
Browse files Browse the repository at this point in the history
  • Loading branch information
skad0 committed Jul 4, 2016
1 parent 3334a72 commit 3119478
Show file tree
Hide file tree
Showing 10 changed files with 245 additions and 24 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ parserOptions:
ecmaVersion: 6

env:
es6: true
node: true
mocha: true

Expand Down
192 changes: 191 additions & 1 deletion lib/normalize2.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,195 @@
const naming = require('bem-naming');

module.exports = function (decl) {
return [naming, decl];
const res = [];
const hash = {};

if (!decl) { return []; }

if (typeof decl === 'string' || !(Symbol.iterator in decl)) {
decl = [decl];
}

for (let entity of decl) {
let block, mod, mods, elem, elems;

if (typeof entity === 'string') {
block = entity;
} else {
block = entity.block;
elem = entity.elem;
elems = entity.elems;
mod = getMod(entity);
mods = getMods(entity);
}

if (block) {
let elemsOrMods = elems || !isNotActual(mods);
let noOther = !elems && !elem && isNotActual(mods) && isNotActual(mod);

if (elemsOrMods || noOther) {
add({ block: block });
}

if (!isNotActual(mod) && !elem) {
normalizeMods(block, mod);
}
}

if (elem) {
if (!Array.isArray(elem)) {
elem = [elem];
}
for (let elItem of elem) {
if (typeof elItem === 'string') {
add({ block: block, elem: elItem });

if (!isNotActual(mod)) {
normalizeMods(block, elItem, mod);
}
} else {
let elemNames = elItem.elem;

if (!Array.isArray(elemNames)) {
elemNames = [elemNames];
}

let modsExists = !isNotActual(elItem.mods);

for (let elemName of elemNames) {
add({ block: block, elem: elemName });

if (!isNotActual(mod)) {
normalizeMods(block, elemName, mod);
}

if (modsExists) {
normalizeMods(block, elemName, elItem.mods);
}
}
}
}
}

if (!isNotActual(mod) && elems) {
normalizeMods(block, mod);
}

if (!isNotActual(mods)) {
normalizeMods(block, mods);
}

if (elems) {
if (!Array.isArray(elems)) {
elems = [elems];
}
for (let elItem of elems) {
if (typeof elItem === 'string') {
add({ block: block, elem: elItem });
} else {
let elemNames = elItem.elem;

if (!Array.isArray(elemNames)) {
elemNames = [elemNames];
}

let modsExists = !isNotActual(elItem.mods);

for (let elemName of elemNames) {
add({ block: block, elem: elemName });
if (modsExists) {
normalizeMods(block, elemName, elItem.mods);
}
}
}
}
}
}

return res;

function add(entity) {
const str = naming.stringify(entity);

if (!hash[str]) {
res.push(entity);
}

hash[str] = true;
}

function getMod(entity) {
let mod = entity.mod;
let val;

const res = {};

if (!mod) { return res; }

if (entity.hasOwnProperty('val')) {
val = entity.val;
} else {
val = true;
}

if (val === 0 || val) {
res[mod] = val;
}
return res;
}

function getMods(entity) {
let mods = entity.mods;
const res = {};

if (mods) {
for (let modName in mods) {
res[modName] = mods[modName];
}
}

return res;
}

function normalizeMods(block, elem, mods) {
const isElem = arguments.length === 3;
if (!isElem) {
mods = elem;
}

const modNames = Object.keys(mods);

for (let modName of modNames) {
let modVals = mods[modName];

if (!Array.isArray(modVals)) {
modVals = [modVals];
}

for (let modVal of modVals) {
const item = {};

item.block = block;
isElem && (item.elem = elem);
item.modName = modName;
item.modVal = modVal;

add(item);
}
}
}

function isNotActual(obj) {
if (!obj) {
return true;
}

for (let prop in obj) {
if (obj.hasOwnProperty(prop)) {
return false;
}
}

return true && JSON.stringify(obj) === JSON.stringify({});
}
};
16 changes: 16 additions & 0 deletions test/normalize2/block-mods.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@ test('sould support mods', t => {
]);
});

test('should pass mods to block', t => {
const decl = {
block: 'block',
elem: 'elem',
mods: {
m1: 'v1'
}
};

t.deepEqual(normalize(decl), [
{ block: 'block' },
{ block: 'block', elem: 'elem' },
{ block: 'block', modName: 'm1', modVal: 'v1' }
]);
});

test('should support several mods', t => {
const decl = {
block: 'block',
Expand Down
4 changes: 2 additions & 2 deletions test/normalize2/block.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ test('should support block as string', t => {
});

test('should support array of blocks', t => {
t.deepEqual(normalize(['block', 'block']), [
{ block: 'block' }, { block: 'block' }
t.deepEqual(normalize(['block1', 'block2']), [
{ block: 'block1' }, { block: 'block2' }
]);
});
24 changes: 22 additions & 2 deletions test/normalize2/elem-mod.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,30 @@ test('should support elem array mod', t => {
elem: ['elem1', 'elem2'],
mod: 'm1',
val: 'v1'
}
};

t.deepEqual(normalize(decl), [
{ block: 'block', elem: 'elem1' },
{ block: 'block', elem: 'elem1', modName: 'm1', modVal: 'v1' },
{ block: 'block', elem: 'elem2', modName: 'm1', modVal: 'v2' }
{ block: 'block', elem: 'elem2' },
{ block: 'block', elem: 'elem2', modName: 'm1', modVal: 'v1' }
]);
});

test('should support elem of elem as array with mod', t => {
const decl = {
block: 'block',
elem: {
elem: ['elem1', 'elem2'],
},
mod: 'm1',
val: 'v1'
};

t.deepEqual(normalize(decl), [
{ block: 'block', elem: 'elem1' },
{ block: 'block', elem: 'elem1', modName: 'm1', modVal: 'v1' },
{ block: 'block', elem: 'elem2' },
{ block: 'block', elem: 'elem2', modName: 'm1', modVal: 'v1' }
]);
});
3 changes: 3 additions & 0 deletions test/normalize2/elem-mods.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ test('should support elem as object and mod', t => {
};

t.deepEqual(normalize(decl), [
{ block: 'block', elem: 'elem' },
{ block: 'block', elem: 'elem', modName: 'mod1', modVal: 'v1' }
]);
});
Expand All @@ -32,7 +33,9 @@ test('should support elem of elem as array mods', t => {
};

t.deepEqual(normalize(decl), [
{ block: 'block', elem: 'elem1' },
{ block: 'block', elem: 'elem1', modName: 'm1', modVal: 'v1' },
{ block: 'block', elem: 'elem2' },
{ block: 'block', elem: 'elem2', modName: 'm1', modVal: 'v1' }
]);
});
8 changes: 4 additions & 4 deletions test/normalize2/elems-mod.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ test('should support shortcut for bool mod of elem', t => {

t.deepEqual(normalize(decl), [
{ block: 'block' },
{ block: 'block', elem: 'elem' },
{ block: 'block', modName: 'mod', modVal: true }
{ block: 'block', modName: 'mod', modVal: true },
{ block: 'block', elem: 'elem' }
]);
});
test('should support bool mod of elems', t => {
const decl = { block: 'block', elems: 'elem', mod: 'mod', val: true };

t.deepEqual(normalize(decl), [
{ block: 'block' },
{ block: 'block', elem: 'elem' },
{ block: 'block', modName: 'mod', modVal: true }
{ block: 'block', modName: 'mod', modVal: true },
{ block: 'block', elem: 'elem' }
]);
});
test('should remove bool mod on elem if falsy except 0', t => {
Expand Down
3 changes: 3 additions & 0 deletions test/normalize2/elems-mods.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ test('should support elem as object and mod', t => {

t.deepEqual(normalize(decl), [
{ block: 'block' },
{ block: 'block', elem: 'elem' },
{ block: 'block', elem: 'elem', modName: 'mod1', modVal: 'v1' }
]);
});
Expand All @@ -34,7 +35,9 @@ test('should support elem of elem as array mods', t => {

t.deepEqual(normalize(decl), [
{ block: 'block' },
{ block: 'block', elem: 'elem1' },
{ block: 'block', elem: 'elem1', modName: 'm1', modVal: 'v1' },
{ block: 'block', elem: 'elem2' },
{ block: 'block', elem: 'elem2', modName: 'm1', modVal: 'v1' }
]);
});
Expand Down
13 changes: 0 additions & 13 deletions test/normalize2/iterable.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,3 @@ test('should support iterable set', t => {
{ block: 'block1', elem: 'elem' }
]);
});

test('should support iterable map', t => {
const decl = new Map();

decl.set(1, {
block: 'block',
elem: 'elem'
});

t.deepEqual(normalize(decl), [
{ block: 'block', elem: 'elem' }
]);
});
5 changes: 3 additions & 2 deletions test/normalize2/unusual.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ test('should support both elem and elems', t => {
};

t.deepEqual(normalize(decl), [
{ block: 'block' },
{ block: 'block', elem: 'elem1' },
{ block: 'block', elem: 'elem2' }
]);
Expand All @@ -49,9 +50,9 @@ test('should support both mod, mods, elem and elems :\'(', t => {
t.deepEqual(normalize(decl), [
{ block: 'block' },
{ block: 'block', elem: 'elem1' },
{ block: 'block', elem: 'elem2' },
{ block: 'block', elem: 'elem1', modName: 'mod1', modVal: 'v1' },
{ block: 'block', modName: 'mod1', modVal: 'v1' },
{ block: 'block', modName: 'mod2', modVal: 'v2' },
{ block: 'block', elem: 'eleme1', modName: 'mod1', modVal: 'v1' }
{ block: 'block', elem: 'elem2' }
]);
});

0 comments on commit 3119478

Please sign in to comment.