Skip to content

Commit

Permalink
Adaptation of @tsing80’s node flattening merge tree
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanpenner committed Aug 9, 2018
1 parent f588e5f commit d474145
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 3 deletions.
46 changes: 46 additions & 0 deletions flatten.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use strict';

var ASSIMILATION_PROTOCOL_VERSION = '_1';

function canFlatten(node, options = { overwrite: false /* broccoli-merge-tree's default */ }) {
const hasSameProtocol = node.ASSIMILATION_PROTOCOL_VERSION === ASSIMILATION_PROTOCOL_VERSION;
const nodeOptions = node.options !== null && typeof node.options === 'object' ? node.options : { overwrite: false };
const hasSameOverwrite = nodeOptions.overwrite === options.overwrite;

return hasSameProtocol && hasSameOverwrite;
}

function doFlatten(inputNodes, options) {
var nodes = [];
for (var i = 0 ; i < inputNodes.length ; i++ ) {
var node = inputNodes[i];

if (canFlatten(node, options)) {
nodes = nodes.concat(doFlatten(node._inputNodes, node.options));
} else {
nodes.push(node);
}
}

return nodes;
}

module.exports = function flattenNodes(inputNodes) {
let seen = new Set();
let flattened = doFlatten(inputNodes);
let result = [];

for (let i = flattened.length - 1; i >= 0; i--) {
let node = flattened[i];

if (seen.has(node) === false) {
seen.add(node);
result.push(node);
}
}

return result.reverse();
};

module.exports.ASSIMILATION_PROTOCOL_VERSION = ASSIMILATION_PROTOCOL_VERSION;
module.exports.canFlatten = canFlatten;
8 changes: 6 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

var Plugin = require('broccoli-plugin');
var MergeTrees = require('merge-trees');

var flatten = require('./flatten');
module.exports = BroccoliMergeTrees;
BroccoliMergeTrees.prototype = Object.create(Plugin.prototype);
BroccoliMergeTrees.prototype.constructor = BroccoliMergeTrees;
Expand All @@ -13,7 +13,7 @@ function BroccoliMergeTrees(inputNodes, options) {
if (!Array.isArray(inputNodes)) {
throw new TypeError(name + ': Expected array, got: [' + inputNodes +']');
}
Plugin.call(this, inputNodes, {
Plugin.call(this, flatten(inputNodes, options), {
persistentOutput: true,
needsCache: false,
annotation: options.annotation
Expand Down Expand Up @@ -44,3 +44,7 @@ BroccoliMergeTrees.prototype.build = function() {
throw err;
}
};

BroccoliMergeTrees.prototype.ASSIMILATION_PROTOCOL_VERSION = flatten.ASSIMILATION_PROTOCOL_VERSION;


3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"copy"
],
"files": [
"index.js"
"index.js",
"flatten.js"
],
"engines": {
"node": ">=6.0.0"
Expand Down
64 changes: 64 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,70 @@ function inputFixture(obj) {
return new Fixture.Node(obj);
}

describe('flatten', function() {
var flatten = require('./flatten');

describe('ASSIMILATION_PROTOCOL_VERSION', function() {
it('exists', function() {
expect(flatten).to.have.property('ASSIMILATION_PROTOCOL_VERSION', '_1');
expect(new MergeTrees([])).to.have.property('ASSIMILATION_PROTOCOL_VERSION', '_1');
});
});

describe('canFlatten', function() {
var ASSIMILATION_PROTOCOL_VERSION = flatten.ASSIMILATION_PROTOCOL_VERSION;

it('works', function() {
expect(flatten.canFlatten({})).to.eql(false);
expect(flatten.canFlatten(1)).to.eql(false);
expect(flatten.canFlatten({ ASSIMILATION_PROTOCOL_VERSION })).to.eql(true);
expect(flatten.canFlatten({ ASSIMILATION_PROTOCOL_VERSION: 'BANANA' })).to.eql(false);

expect(flatten.canFlatten({ ASSIMILATION_PROTOCOL_VERSION, options: { overwrite: true }} )).to.eql(false);
expect(flatten.canFlatten({ ASSIMILATION_PROTOCOL_VERSION, options: { overwrite: true }}, { overwrite: true })).to.eql(true);
expect(flatten.canFlatten({ ASSIMILATION_PROTOCOL_VERSION, options: { overwrite: false }}, { overwrite: true })).to.eql(false);
expect(flatten.canFlatten({ ASSIMILATION_PROTOCOL_VERSION, options: { overwrite: true }}, { overwrite: false})).to.eql(false);
expect(flatten.canFlatten({ ASSIMILATION_PROTOCOL_VERSION, options: { overwrite: false }}, { overwrite: false})).to.eql(true);
});
});

function mockMergeTree(name, _inputNodes = [], ASSIMILATION_PROTOCOL_VERSION = '_1') {
return {
name,
_inputNodes,
ASSIMILATION_PROTOCOL_VERSION,
isMergeTree: true
};
}

function mockTree(name, _inputNodes = []) {
return {
name,
_inputNodes
};
}

it('flattens', function() {

let broccoli = mockTree('broccoli');
let css = mockTree('css');
let images = mockTree('images');
let js = mockTree('js');
let aa = mockMergeTree('aa', [broccoli, images]);
let bb = mockMergeTree('bb', [css, js]);
let a = mockMergeTree('a', [aa, bb]);
let b = mockMergeTree('b');
let c = mockMergeTree('c', [a, b]);
let e = mockTree('e');
let d = mockTree('d');

let flattened = flatten([c, d, e, broccoli, css]);
expect(flattened.some(x => x.isMergeTree)).to.eql(false); // ensure no merge trees

expect(flattened.map(x => x.name)).to.eql([images, js, d, e, broccoli, css].map(x => x.name));
});
});

describe('MergeTrees', function() {
it('smoke test', function() {
return expect(mergeFixtures([
Expand Down

0 comments on commit d474145

Please sign in to comment.