Skip to content

Commit

Permalink
Merge f1c9ce4 into 1fb53b0
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew Abramov committed Sep 12, 2014
2 parents 1fb53b0 + f1c9ce4 commit 654fc29
Show file tree
Hide file tree
Showing 4 changed files with 273 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

### Крупные изменения

* Добавлена `levels-to-bemdecl` технология.
* Опция `levels` из `levels` технологии теперь может принимать пути относительно корня, вместо абсолютных.
* Технология `bemdecl-from-bemjson` переименована в `bemjson-to-bemdecl`.
* Технология `bemdecl-merge` переименована в `merge-bemdecl`.
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ $ npm install --save-dev enb-bem
----------

* [`levels`](#levels)
* [`levels-to-bemdecl`](#levels-to-bemdecl)
* [`provide-bemdecl`](#provide-bemdecl)
* [`bemdecl-from-deps-by-tech`](#bemdecl-from-deps-by-tech)
* [`bemjson-to-bemdecl`](#bemjson-to-bemdecl)
Expand Down Expand Up @@ -54,6 +55,23 @@ nodeConfig.addTech([require('enb/techs/levels'), {

-------------------------------------------------------------------------------

### levels-to-bemdecl

Формирует `bemdecl`, состоящий из всех сущностей, найденных на уровнях.

**Опции**

* *String* **target** — Результирующий bemdecl-таргет. По умолчанию — `?.bemdecl.js`.
* *String* **levelsTarget** — Исходный levels. По умолчанию — `?.levels`.

**Пример**

```javascript
nodeConfig.addTech(require('enb-bem/techs/levels-to-bemdecl'));
```Ad
-------------------------------------------------------------------------------
### provide-bemdecl
Копирует `bemdecl` в текущую ноду под нужным именем из другой ноды. Может понадобиться, например, для объединения bemdecl'ов.
Expand Down
114 changes: 114 additions & 0 deletions techs/levels-to-bemdecl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* levels-to-bemdecl
* =================
*
* Формирует *bemdecl*, состоящий из всех сущностей, найденных на уровнях.
*
* **Опции**
*
* * *String* **target** — Результирующий bemdecl-таргет. По умолчанию — `?.bemdecl.js`.
* * *String* **levelsTarget** — Исходный levels. По умолчанию — `?.levels`.
*
* * **Пример**
*
* ```javascript
* nodeConfig.addTech(require('enb-bem/techs/levels-to-bemdecl'));
* ```
*/
var inherit = require('inherit'),
vfs = require('enb/lib/fs/async-fs'),
deps = require('../lib/deps/deps'),
asyncRequire = require('enb/lib/fs/async-require'),
dropRequireCache = require('enb/lib/fs/drop-require-cache');

module.exports = inherit(require('enb/lib/tech/base-tech'), {
getName: function () {
return 'levels-to-bemdecl';
},

configure: function () {
this._target = this.node.unmaskTargetName(
this.getOption('target', this.node.getTargetName('bemdecl.js')));
this._levelsTarget = this.node.unmaskTargetName(
this.getOption('levelsTarget', this.node.getTargetName('levels')));
},

getTargets: function () {
return [this.node.unmaskTargetName(this._target)];
},

build: function () {
var node = this.node,
target = this._target,
bemdeclFilename = node.resolvePath(target),
cache = node.getNodeCache(target);

return node.requireSources([this._levelsTarget]).spread(function (levels) {
if (cache.needRebuildFile('bemdecl-file', bemdeclFilename)) {
var resDeps = [],
blocks = [],
str;

levels.items.forEach(function (level) {
Object.keys(level.blocks).forEach(function (name) {
var block = level.blocks[name];

resDeps.push({
block: name
});

processMods(resDeps, name, block.mods);
processElems(resDeps, name, block.elements);
});
});

blocks = deps.toBemdecl(resDeps);
str = 'exports.blocks = ' + JSON.stringify(blocks, null, 4) + ';\n';

return vfs.write(bemdeclFilename, str, 'utf8')
.then(function () {
cache.cacheFileInfo('bemdecl-file', bemdeclFilename);
node.resolveTarget(target, { blocks: blocks });
});
} else {
node.isValidTarget(target);
dropRequireCache(require, bemdeclFilename);

return asyncRequire(bemdeclFilename)
.then(function (result) {
node.resolveTarget(target, result);
return null;
});
}
});
}
});

function processElems(deps, block, elems) {
if (elems) {
Object.keys(elems).forEach(function (elemName) {
deps.push({
block: block,
elem: elemName
});

processMods(deps, block, elems[elemName].mods, elemName);
});
}
}

function processMods(deps, block, mods, elem) {
if (mods) {
Object.keys(mods).forEach(function (modName) {
var dep = {
block: block,
mod: modName,
val: Object.keys(mods[modName])[0]
};

elem && (dep.elem = elem);

deps.push(dep);
});
}
}
140 changes: 140 additions & 0 deletions test/techs/levels-to-bemdecl.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
var FileSystem = require('enb/lib/test/mocks/test-file-system'),
TestNode = require('enb/lib/test/mocks/test-node'),
levelsTech = require('../../techs/levels'),
bemdeclTech = require('../../techs/levels-to-bemdecl');

describe('techs', function () {
describe('levels-to-bemdecl', function () {
var fileSystem,
bundle,
bemdecl = {
blocks: [
{ name: 'fully-block' },
{
name: 'fully-block',
mods: [
{
name: 'bool-mod',
vals: [{ name: 'true' }]
}
]
},
{
name: 'fully-block',
mods: [
{
name: 'mod-name',
vals: [{ name: 'mod-val' }]
}
]
},
{
name: 'fully-block',
elems: [{ name: 'elem' }]
},
{
name: 'fully-block',
elems: [{
name: 'elem',
mods: [
{
name: 'bool-mod',
vals: [{ name: 'true' }]
}
]
}]
},
{
name: 'fully-block',
elems: [{
name: 'elem',
mods: [{
name: 'mod-name',
vals: [{ name: 'mod-val' }]
}]
}]
}
]
};

beforeEach(function () {
fileSystem = new FileSystem([{
directory: 'blocks',
items: [{
directory: 'fully-block',
items: [
{ file: 'fully-block' },
{ directory: 'fully-block.dir', items: [] },
{ directory: '_bool-mod',
items: [
{ file: 'fully-block_bool-mod' },
{ directory: 'fully-block_bool-mod.dir', items: [] }
]
},
{ directory: '_mod-name',
items: [
{ file: 'fully-block_mod-name_mod-val' },
{ directory: 'fully-block_mod-name_mod-val.dir', items: [] }
]
},
{ directory: '__elem',
items: [
{ file: 'fully-block__elem' },
{ directory: 'fully-block__elem.dir', items: [] },
{ directory: '_bool-mod',
items: [
{ file: 'fully-block__elem_bool-mod' },
{ directory: 'fully-block__elem_bool-mod.dir', items: [] }
]
},
{ directory: '_mod-name',
items: [
{ file: 'fully-block__elem_mod-name_mod-val' },
{ directory: 'fully-block__elem_mod-name_mod-val.dir', items: [] }
]
}
]
}
]
}]
},
{
directory: 'bundle',
items: []
}]);
fileSystem.setup();

bundle = new TestNode('bundle');
});

afterEach(function () {
fileSystem.teardown();
});

it('must provide result target', function (done) {
bundle.runTech(levelsTech, { levels: ['blocks'] })
.then(function (levels) {
bundle.provideTechData('?.levels', levels);

return bundle.runTechAndGetResults(bemdeclTech);
})
.then(function (results) {
results['bundle.bemdecl.js'].must.eql(bemdecl);
})
.then(done, done);
});

it('must require result target', function (done) {
bundle.runTech(levelsTech, { levels: ['blocks'] })
.then(function (levels) {
bundle.provideTechData('?.levels', levels);

return bundle.runTechAndRequire(bemdeclTech);
})
.spread(function (target) {
target.must.eql(bemdecl);
})
.then(done, done);
});
});
});

0 comments on commit 654fc29

Please sign in to comment.