diff --git a/lib/convert/v1.js b/lib/convert/v1.js index 8700cdc..5848a61 100644 --- a/lib/convert/v1.js +++ b/lib/convert/v1.js @@ -16,7 +16,73 @@ module.exports = function (decl) { entity.modName && (item.mods = [{ name: entity.modName }]); entity.modVal && (item.mods[0].vals = [{ name: entity.modVal }]); - acc.push(entity.elem ? { name: entity.block, elems: [item] } : item); + const result = entity.elem ? { name: entity.block, elems: [item] } : item; + + if (result.elems && entity.elem) { + // If exists block with existing elems property + const curBlock = acc.find( + curEntity => curEntity.name === entity.block + ); + if (curBlock) { + if (curBlock.elems) { + // check if elem exists + const curElem = curBlock.elems.find(elem => elem.name === entity.elem); + curElem || curBlock.elems.push(result.elems[0]); + } else { + curBlock.elems = result.elems; + } + } else { + acc.push(result); + } + + // If such element already exists and we have mod + const modsAddition = acc.find(curEntity => { + const curElem = curEntity.elems ? + curEntity.elems.find(elem => elem.name === entity.elem) : false; + return curEntity.name === entity.block && curElem; + }); + if (entity.modName) { + const curElem = modsAddition.elems.find(elem => elem.name === entity.elem); + if (curElem.mods) { + // have an array of mods in elem + // check if such mod already exists + const curMod = curElem.mods.find( + mod => mod.name === entity.modName + ); + if (curMod) { + // check if val already exists + const curVal = curMod.vals.find(val => + val.name === entity.modVal + ); + curVal || curMod.vals.push(result.elems[0].mods[0].vals[0]); + } else { + // add new mod + curElem.mods.push(result.elems[0].mods[0]); + } + } + } + } else if (entity.modName) { + const curBlock = acc.find(curEntity => curEntity.name === entity.block); + // if block with mods prop exists search for such mod + if (curBlock) { + if (curBlock.mods) { + const curMod = curBlock.mods.find(mod => mod.name === entity.modName); + if (curMod) { + // if such mod exists push new val + curMod.vals.push(result.mods[0].vals[0]); + } else { + // if no such mod push new mod + curBlock.mods.push(result.mods[0]); + } + } else { + curBlock.mods = result.mods; + } + } else { + acc.push(result); + } + } else { + acc.push(result); + } return acc; }, []); }; diff --git a/test/convert/v1.test.js b/test/convert/v1.test.js index 52e84f2..e5cc4b5 100644 --- a/test/convert/v1.test.js +++ b/test/convert/v1.test.js @@ -8,22 +8,109 @@ test('must return empty decl', t => { t.deepEqual(convert([], { format: 'v1' }), []); }); -test('must transform deps to bemdecl', t => { +test('must split elems of one block', t => { const input = [ { entity: { block: 'block1' }, tech: null }, - { entity: { block: 'block1', modName: 'mod1', modVal: true }, tech: null }, - { entity: { block: 'block1', modName: 'mod1', modVal: 'val1' }, tech: null }, { entity: { block: 'block1', elem: 'elem1' }, tech: null }, - { entity: { block: 'block1', elem: 'elem1', modName: 'mod2', modVal: true }, tech: null }, + { entity: { block: 'block1', elem: 'elem2' }, tech: null } + ]; + const output = [ + { name: 'block1', elems: [{ name: 'elem1' }, { name: 'elem2' }] } + ]; + + t.deepEqual( + convert(input, { format: 'v1' }), + output + ); +}); + +test('must split mods of one block', t => { + const input = [ + { entity: { block: 'block1' }, tech: null }, + { entity: { block: 'block1', modName: 'mod1', modVal: 'val1' }, tech: null }, + { entity: { block: 'block1', modName: 'mod2', modVal: 'val2' }, tech: null } + ]; + const output = [ + { + name: 'block1', + mods: [ + { name: 'mod1', vals: [{ name: 'val1' }] }, + { name: 'mod2', vals: [{ name: 'val2' }] } + ] + } + ]; + + t.deepEqual( + convert(input, { format: 'v1' }), + output + ); +}); + +test('must split vals of mods block', t => { + const input = [ + { entity: { block: 'block1' }, tech: null }, + { entity: { block: 'block1', modName: 'mod1', modVal: true }, tech: null }, + { entity: { block: 'block1', modName: 'mod1', modVal: 'val1' }, tech: null } + ]; + const output = [ + { + name: 'block1', + mods: [ + { name: 'mod1', vals: [{ name: true }, { name: 'val1' }] } + ] + } + ]; + + t.deepEqual( + convert(input, { format: 'v1' }), + output + ); +}); + +test('must split elem mods of block', t => { + const input = [ + { entity: { block: 'block1' }, tech: null }, + { entity: { block: 'block1', elem: 'elem1', modName: 'mod1', modVal: 'val1' }, tech: null }, { entity: { block: 'block1', elem: 'elem1', modName: 'mod2', modVal: 'val2' }, tech: null } ]; const output = [ - { name: 'block1' }, - { name: 'block1', mods: [{ name: 'mod1', vals: [{ name: true }] }] }, - { name: 'block1', mods: [{ name: 'mod1', vals: [{ name: 'val1' }] }] }, - { name: 'block1', elems: [{ name: 'elem1' }] }, - { name: 'block1', elems: [{ name: 'elem1', mods: [{ name: 'mod2', vals: [{ name: true }] }] }] }, - { name: 'block1', elems: [{ name: 'elem1', mods: [{ name: 'mod2', vals: [{ name: 'val2' }] }] }] } + { + name: 'block1', + elems: [ + { + name: 'elem1', + mods: [ + { name: 'mod1', vals: [{ name: 'val1' }] }, { name: 'mod2', vals: [{ name: 'val2' }] } + ] + } + ] + } + ]; + + t.deepEqual( + convert(input, { format: 'v1' }), + output + ); +}); + +test('must split vals of elem mods', t => { + const input = [ + { entity: { block: 'block1' }, tech: null }, + { entity: { block: 'block1', elem: 'elem1', modName: 'mod1', modVal: 'val1' }, tech: null }, + { entity: { block: 'block1', elem: 'elem1', modName: 'mod1', modVal: 'val2' }, tech: null } + ]; + const output = [ + { + name: 'block1', + elems: [ + { + name: 'elem1', + mods: [ + { name: 'mod1', vals: [{ name: 'val1' }, { name: 'val2' }] } + ] + } + ] + } ]; t.deepEqual( @@ -31,3 +118,18 @@ test('must transform deps to bemdecl', t => { output ); }); + +test('should create full entity with mods', t => { + t.deepEqual( + convert({ entity: { block: 'block1', modName: 'mod1', modVal: 'val1' } }, { format: 'v1' }), + [{ + name: 'block1', + mods: [{ + name: 'mod1', + vals: [{ + name: 'val1' + }] + }] + }] + ); +}); diff --git a/test/stringify/common.test.js b/test/stringify/common.test.js new file mode 100644 index 0000000..6336eea --- /dev/null +++ b/test/stringify/common.test.js @@ -0,0 +1,7 @@ +const test = require('ava'); + +const stringify = require('../../lib/stringify'); + +test('should throws error if no format given', t => { + t.throws(() => stringify({ entity: { block: 'block' }, tech: null }), 'You must declare target format'); +}); diff --git a/test/stringify/enb.test.js b/test/stringify/enb.test.js index 53d5566..5e75fc7 100644 --- a/test/stringify/enb.test.js +++ b/test/stringify/enb.test.js @@ -2,10 +2,6 @@ const test = require('ava'); const stringify = require('../../lib/stringify'); -test('should throws error if no format given', t => { - t.throws(() => stringify({ entity: { block: 'block' }, tech: null }), 'You must declare target format'); -}); - test('should stringify enb declaration', t => { const obj = [{ block: 'block', elem: 'elem', mod: 'mod', val: 'val' }]; t.deepEqual( diff --git a/test/stringify/v1.test.js b/test/stringify/v1.test.js new file mode 100644 index 0000000..e504593 --- /dev/null +++ b/test/stringify/v1.test.js @@ -0,0 +1,25 @@ +const test = require('ava'); + +const stringify = require('../../lib/stringify'); + +test('should stringify enb declaration', t => { + const obj = [{ + name: 'block', + elems: [{ + name: 'elem', + mods: [{ + name: 'mod', + vals: [{ + name: 'val' + }] + }] + }] + }]; + t.deepEqual( + stringify( + { entity: { block: 'block', elem: 'elem', modName: 'mod', modVal: 'val' }, tech: null }, + { format: 'v1' } + ), + 'exports.blocks = ' + JSON.stringify(obj, null, 4) + ';\n' + ); +});