Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wip] Add convert for v1 format #70

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions 1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const no = require('./lib/normalize');
console.log(JSON.stringify(
{
block: 'block',
elems: [
{ elem: 'elem', mods: { m1:'v1' } },
{ elem: 'elem2' },
{ elem: 'elem', mods: { m2:'v2' } }
]
}, null, 4
));
console.log('===========');
console.log(no([
{
block: 'block',
elems: [
{ elem: 'elem', mods: { m1:'v1' } },
{ elem: 'elem2' },
{ elem: 'elem', mods: { m2:'v2' } }
]
}
], { format: 'v2' }));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wtf?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this pr now is in wip status

2 changes: 1 addition & 1 deletion lib/convert/enb.js → lib/format/enb.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

/**
* Convert normalized declaration to enb format
* Formats normalized declaration to enb format
*
* @param {Array|Object} decl Source declaration
* @return {Array}
Expand Down
14 changes: 7 additions & 7 deletions lib/convert.js → lib/format/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ const isNotSupported = () => {
);
};

const converters = {
enb: require('./convert/enb'),
const formatters = {
enb: require('./enb'),
v2: isNotSupported,
v1: isNotSupported,
v1: require('./v1'),
harmony: isNotSupported
};

/**
* Convert normalized declaration to target format
* Formats normalized declaration to target format
*
* @param {Array|Object} decl normalized declaration
* @param {Object} opts Addtional options
* @param {String} opts.format format format
* @return {Array} Array with converted declaration
* @return {Array} Array with formatted declaration
*/
module.exports = function (decl, opts) {
opts || (opts = {});
Expand All @@ -30,9 +30,9 @@ module.exports = function (decl, opts) {

assert(format, 'You must declare target format');

if (!converters[format]) {
if (!formatters[format]) {
throw new Error('Unknown format');
}

return converters[format](decl);
return formatters[format](decl);
};
102 changes: 102 additions & 0 deletions lib/format/v1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
'use strict';

/**
* Formats normalized declaration to v1 format
*
* @param {Array|Object} decl Source declaration
* @return {Array}
*/
module.exports = function (decl) {
Array.isArray(decl) || (decl = [decl]);

// previous block in declaration
let prevBlock = '';

return !decl.length ? [] : decl.reduce((acc, dep) => {
const canGroup = dep.entity.block === prevBlock;
const entity = dep.entity;
const item = { name: entity[entity.elem ? 'elem' : 'block'] };

if (entity.modName) {
item.mods = [{
name: entity.modName,
vals: [entity.modVal]
}];
}

const result = entity.elem ? { name: entity.block, elems: [item] } : item;

if (result.elems && entity.elem) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Зачем проверка на entity.elem, если у result выставится elems, только если есть entity.elem.

// If exists block
const curBlock = acc.find(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Зачем переносы строк?

curEntity => curEntity.name === entity.block
);

if (curBlock && canGroup) {
if (curBlock.elems) {
// check if elem exists
const curElem = curBlock.elems.find(elem => elem.name === entity.elem);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Так как мы уже проходились ранее по элементам, которые добавили, мы можем знать, какие были добавлены, а какие нет.

Чтобы не ходить каждый раз заново по наполняемому массиву можно хранить карту, где ключ это скоуп БЭМ-сущности, а значение ссылка на объект БЭМ-сущности внутри acc.

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 === 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 && canGroup) {
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);
}
// save previous block
prevBlock = dep.entity.block;

return acc;
}, []);
};
8 changes: 4 additions & 4 deletions lib/normalize.js → lib/normalize/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
'use strict';

const normalizer = {
v1: require('./normalize/v1'),
v2: require('./normalize/v2'),
harmony: require('./normalize/harmony'),
enb: require('./normalize/v2')
v1: require('./v1'),
v2: require('./v2'),
harmony: require('./harmony'),
enb: require('./v2')
};

module.exports = (decl, opts) => {
Expand Down
6 changes: 3 additions & 3 deletions lib/stringify.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const assert = require('assert');

const convert = require('./convert');
const formatter = require('./format');

/**
* Create string representation of declaration
Expand All @@ -20,8 +20,8 @@ module.exports = function (decl, opts) {

Array.isArray(decl) || (decl = [decl]);

const formatedDecl = convert(decl, { format });
const jsonStr = JSON.stringify(formatedDecl, null, 4);
const formattedDecl = formatter(decl, { format });
const jsonStr = JSON.stringify(formattedDecl, null, 4);

let exportsStr = '';

Expand Down
16 changes: 8 additions & 8 deletions test/convert/enb.test.js → test/format/enb.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@

const test = require('ava');

const convert = require('../../lib/convert');
const format = require('../../lib/format');

test('should throw exception if no format given', t => {
t.throws(() => convert({ entity: { block: 'block' }, tech: null }), 'You must declare target format');
t.throws(() => format({ entity: { block: 'block' }, tech: null }), 'You must declare target format');
});

test('should convert to enb format', t => {
t.deepEqual(convert({ entity: { block: 'block' }, tech: null }, { format: 'enb' }), [{ block: 'block' }]);
test('should format to enb format', t => {
t.deepEqual(format({ entity: { block: 'block' }, tech: null }, { format: 'enb' }), [{ block: 'block' }]);
});

test('should convert with elem', t => {
test('should format with elem', t => {
t.deepEqual(
convert([
format([
{ entity: { block: 'block' }, tech: null },
{ entity: { block: 'block', elem: 'elem' }, tech: null }
], { format: 'enb' }),
Expand All @@ -25,9 +25,9 @@ test('should convert with elem', t => {
);
});

test('should convert with mod', t => {
test('should format with mod', t => {
t.deepEqual(
convert([
format([
{ entity: { block: 'block', modName: 'mod', modVal: 'val' }, tech: null }
], { format: 'enb' }),
[{ block: 'block', mod: 'mod', val: 'val' }]
Expand Down
Loading