JSFiddle - React, Tailwind, and code Playground
by Oliver Caldwell
HTML
<script src="https://rawgit.com/lodash/lodash/3.9.3/lodash.js"></script>
JavaScript
var input = [
{
name: 'foo',
url: '/somewhere1',
templateUrl: 'foo.tpl.html',
title: 'title A',
subtitle: 'description A'
},
{
name: 'foo.bar',
url: '/somewhere2',
templateUrl: 'anotherpage.tpl.html',
title: 'title B',
subtitle: 'description B'
},
{
name: 'buzz.fizz',
url: '/another/place',
templateUrl: 'hello.tpl.html',
title: 'title C',
subtitle: 'description C'
},
{
name: 'foo.hello.world',
url: '/',
templateUrl: 'world.tpl.html',
title: 'title D',
subtitle: 'description D'
}
];
function formatRoute(route) {
return _.merge(_.pick(route, ['url', 'templateUrl']), {
name: route.name.split('.'),
data: _.pick(route, ['title', 'subtitle']),
children: []
});
}
function getNameLength(route) {
return route.name.length;
}
function buildTree(tree, route) {
var path = _.slice(route.name, 0, -1);
insertAtPath(tree, path, _.merge({}, route, {
name: _.last(route.name)
}));
return tree;
}
function insertAtPath(children, path, route) {
var head = _.first(path);
var match = _.find(children, function (child) {
return child.name === head;
});
if (path.length === 0) {
children.push(route);
}
else {
if (!match) {
match = {
name: head,
data: {},
children: []
};
children.push(match);
}
insertAtPath(match.children, _.rest(path), route);
}
}
// Map the routes into their correct formats.
var routes = _.sortBy(_.map(input, formatRoute), getNameLength);
// Now we can reduce this well formatted array into the desired format.
var out = _.reduce(routes, buildTree, []);
console.log(out);