Skip to content

Commit

Permalink
Poehali!
Browse files Browse the repository at this point in the history
  • Loading branch information
Vladimir Varankin committed Jan 18, 2014
0 parents commit 5e77adf
Show file tree
Hide file tree
Showing 5 changed files with 388 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
depsormalize
============

`deps` normalizer
193 changes: 193 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/*
{
block : 'b1',
elem : 'e1',
mod : 'm1'
val : 'v1'
tech : 't1'
}
*/

var toString = Object.prototype.toString,
isArray = Array.isArray,
isObject = function(o) {
return toString.call(o) === '[object Object]';
};

module.exports = function depsormalize(deps) {
if(isArray(deps)) return deps.map(normalize);
return normalize(deps);
};

function normalize(deps) {
if(!isObject(deps)) {
throw new Error('invalid declaration ' + deps);
}

var result = [],
cache = {};

if(deps.blocks) {
var blocks = deps.blocks;
if(!isArray(blocks)) blocks = [blocks];

pushBlocks(blocks);
}

var block = deps.block,
elem = deps.elem,
i, slen, decl;

if(deps.elems) {
var elems = deps.elems;

if(!isArray(elems)) elems = [elems];

i = 0;
slen = result.length;

do {
decl = result[i] || {};

if(decl.block) block = decl.block;
pushElems(block, elems);
} while(++i < slen);
}

if(deps.mods) {
var mods = deps.mods;

if(!isArray(mods)) mods = [mods];

i = 0;
slen = result.length;

do {
decl = result[i] || {};

if(decl.block) block = decl.block;
if(decl.elem) elem = decl.elem;

pushMods(block, elem, mods);
} while(++i < slen);
}

if(!result.length) {
push(extendDecl({}, deps));
}

return result;

function push(decl) {
var key = identify(decl);

if(cache[key]) return;
cache[key] = true;

result.push(decl);
}

function pushOne(block, elem) {
if(block) {
var d = {
block : block
};
if(elem) d.elem = elem;
push(d);
}
}

function pushBlocks(blocks) {
blocks.reduce(function(decls, block) {
pushOne(block);
push(extendDecl({ block : block }, deps));

return decls;
}, []);
}

function pushElems(block, elems) {
pushOne(block);

elems.forEach(function(elem) {
var d = {};

if(block) d.block = block;
d.elem = elem;

push(extendDecl(d, deps));
});
}

function pushMods(block, elem, mods) {
pushOne(block, elem);

mods.forEach(function(mod) {
Object.keys(mod).forEach(function(name) {
var d = { mod : name };
if(block) {
d.block = block;
if(elem) d.elem = elem;
}

push(extendDecl({}, d));

var vals = mod[name];
if(!vals) {
return;
}

if(!isArray(vals)) vals = [vals];

vals.forEach(function(val) {
push(extendDecl({ val : val }, d));
});
});
});
}
}

function extendDecl(dest, src) {
extendBlock(dest ,src);
extendElem(dest, src);
extendMod(dest, src);
extendVal(dest, src);
extendTech(dest, src);
return dest;
}

function extendBlock(d, s) {
if(d.block) return d;
if(s.block) d.block = s.block;
return d;
}

function extendElem(d, s) {
if(d.elem) return d;
if(s.elem) d.elem = s.elem;
return d;
}

function extendMod(d, s) {
if(d.mod) return d;
if(s.mod) d.mod = s.mod;
return d;
}

function extendVal(d, s) {
if(d.val) return d;
if(s.val) d.val = s.val;
return d;
}

function extendTech(d, s) {
if(d.tech) return d;
if(s.tech) d.tech = s.tech;
return d;
}

function identify(decl) {
return decl.block +
(decl.elem? '__' + decl.elem : '') +
(decl.mod? '_' + decl.mod + (decl.val? '_' + decl.val : '') : '');
}
15 changes: 15 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "depsormalize",
"version": "0.0.1",
"description": "deps normalizer",
"main": "index.js",
"scripts": {
"test": "mocha -R spec test"
},
"author": "Vladimir Varankin <[email protected]> (http://github.com/narqo)",
"license": "WTFPL",
"devDependencies": {
"mocha": "~1.17.0",
"must": "~0.10.0"
}
}
175 changes: 175 additions & 0 deletions test/normalize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
require('must');
var depsormalize = require('../');

describe('deps normalizer', function() {
describe('simple', function() {
it('should return array', function() {
var deps = depsormalize({ block : 'b1' });
deps.must.be.array();
deps.must.not.be.empty();
});

it('should consume array of declarations', function() {
var deps = depsormalize([{ block : 'b1' }, { block : 'b2' }]);
deps.must.be.array();
deps.must.have.length(2);
});
});

describe('full declaration', function() {
var inDeps = [
{ block : 'b' },
{ block : 'b', mod : 'm' },
{ block : 'b', mod : 'm', val : 'v' },
{ block : 'b', elem : 'e' },
{ block : 'b', elem : 'e', mod : 'm' },
{ block : 'b', elem : 'e', mod : 'm', val : 'v' }
];

it('should pass full declaration', function() {
inDeps.forEach(function(idep) {
depsormalize(idep).must.be.eql([idep]);
});
});
});

describe.skip('single forms', function() {
describe('block', function() {
it('should accept declare "block" with array', function() {
depsormalize({ block : ['b1', 'b2'] })
.must.eql([
{ block : 'b1' },
{ block : 'b2' }
]);

depsormalize({ block : ['b1', 'b2'], elem : 'e' })
.must.eql([
{ block : 'b1', elem : 'e' },
{ block : 'b2', elem : 'e' }
]);
});
});

describe('elem', function() {
it('should accept declare "elem" with array', function() {
depsormalize({ block : 'b', elem : ['e1', 'e2'] })
.must.eql([
{ block : 'b', elem : 'e1' },
{ block : 'b', elem : 'e2' }
]);
});
})
});

describe('plural forms', function() {
describe('blocks', function() {
it('should understand "blocks" declaration', function() {
depsormalize({ blocks : 'b1' })
.must.eql([{ block : 'b1' }]);

depsormalize({ blocks : ['b1'] })
.must.eql([{ block : 'b1' }]);

depsormalize({ blocks : ['b1'], elem : 'e' })
.must.eql([{ block : 'b1' }, { block : 'b1', elem : 'e' }]);

depsormalize({ blocks : ['b1', 'b2'] })
.must.eql([{ block : 'b1' }, { block : 'b2'}]);

depsormalize({ blocks : ['b1', 'b2'], elem : 'e' })
.must.eql([
{ block : 'b1' },
{ block : 'b1', elem : 'e' },
{ block : 'b2' },
{ block : 'b2', elem : 'e' }
]);
});
});

describe('elems', function() {
it('should understand "elems" declaration', function() {
depsormalize({ block : 'b', elems : 'e1' })
.must.eql([
{ block : 'b' },
{ block : 'b', elem : 'e1' }
]);

depsormalize({ block : 'b', elems : ['e1', 'e2'] })
.must.eql([
{ block : 'b' },
{ block : 'b', elem : 'e1' },
{ block : 'b', elem : 'e2' }
]);
});
});

describe('mods', function() {
it('should understand "mods" declaration', function() {
depsormalize({ block : 'b', mods : { m : 'v' } })
.must.eql([
{ block : 'b' },
{ block : 'b', mod : 'm' },
{ block : 'b', mod : 'm', val : 'v' }
]);

depsormalize({ block : 'b', mods : [{ m1 : 'v' }, { m2 : 'v' }] })
.must.eql([
{ block : 'b' },
{ block : 'b', mod : 'm1' },
{ block : 'b', mod : 'm1', val : 'v' },
{ block : 'b', mod : 'm2' },
{ block : 'b', mod : 'm2', val : 'v' }
]);

depsormalize({ block : 'b', mods : { m : ['v1', 'v2'] } })
.must.eql([
{ block : 'b' },
{ block : 'b', mod : 'm' },
{ block : 'b', mod : 'm', val : 'v1' },
{ block : 'b', mod : 'm', val : 'v2' }
]);

depsormalize({ block : 'b', mods : { m1 : 'v', m2 : 'v' } })
.must.eql([
{ block : 'b' },
{ block : 'b', mod : 'm1' },
{ block : 'b', mod : 'm1', val : 'v' },
{ block : 'b', mod : 'm2' },
{ block : 'b', mod : 'm2', val : 'v' }
]);
});

it.skip('should understand "mods-names" notations', function() {
depsormalize({ block : 'b', mod : { names : ['m1', 'm2'] } })
.must.eql([
{ block : 'b' },
{ block : 'b', mod : 'm1' },
{ block : 'b', mod : 'm2' }
]);
});
});

describe('blocks + elems', function() {
it('should understand both "blocks" and "elems" declaration', function() {
depsormalize({ blocks : 'b1', elems : 'e1' })
.must.eql([
{ block : 'b1' },
{ block : 'b1', elem : 'e1' }
]);
});
});

describe('uniqness', function() {
it('should return uniq set of declaration', function() {
depsormalize({ blocks : ['b', 'b', 'b'] })
.must.eql([{ block : 'b' }]);

depsormalize({ block : 'b', elems : ['e', 'e', 'e'] })
.must.eql([
{ block : 'b' },
{ block : 'b', elem : 'e' }
]);
});
});
});
});

0 comments on commit 5e77adf

Please sign in to comment.