gulp-nav
Version:
gulp plugin to help build navigation elements
251 lines (236 loc) • 8.22 kB
JavaScript
// Generated by CoffeeScript 1.10.0
/*
copyright © 201{4,5,6} Jess Austin <jess.austin@gmail.com>, MIT license
gulp-nav is a gulp plugin to help build navigation elements. gulp-nav adds
"nav" objects to vinyl file objects. nav objects contain titles, (relative)
href links, active flags, parents, children, and siblings. The last two
properties are arrays, which optionally may be ordered. For other than default
behavior, call the exported function with an object that defines one or more
of the following options (the first five can be a single property name, or an
array of property names):
sources
targets
titles
orders
skips
hrefExtension
demoteTopIndex
*/
(function() {
var basename, navInContext, relative, resolve, soak, through, url,
slice = [].slice;
basename = require('path').basename;
through = require('through2');
module.exports = function(arg) {
var demoteTopIndex, files, hrefExtension, navTree, orderGen, orders, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, root, skips, sources, targets, titles;
ref = arg != null ? arg : {}, sources = (ref1 = ref.sources) != null ? ref1 : ['data', 'frontMatter'], targets = (ref2 = ref.targets) != null ? ref2 : ['nav', 'data.nav'], titles = (ref3 = ref.titles) != null ? ref3 : ['short_title', 'title'], orders = (ref4 = ref.orders) != null ? ref4 : 'order', skips = (ref5 = ref.skips) != null ? ref5 : 'skipThis', hrefExtension = (ref6 = ref.hrefExtension) != null ? ref6 : 'html', demoteTopIndex = (ref7 = ref.demoteTopIndex) != null ? ref7 : false;
if (!Array.isArray(sources)) {
sources = [sources];
}
if (!Array.isArray(targets)) {
targets = [targets];
}
if (!Array.isArray(titles)) {
titles = [titles];
}
if (!Array.isArray(orders)) {
orders = [orders];
}
if (!Array.isArray(skips)) {
skips = [skips];
}
files = [];
navTree = {
parent: null,
children: {},
exists: false,
title: null
};
orderGen = 9999;
root = {};
return through.obj(function(file, encoding, transformCallback) {
var base, current, element, i, j, k, l, last, len, len1, len2, len3, m, nav, obj, order, path, properties, property, ref8, ref9, skip, source, target, title;
source = ((function() {
var i, len, results;
results = [];
for (i = 0, len = sources.length; i < len; i++) {
source = sources[i];
results.push(file[source]);
}
return results;
})()).reduce(soak);
if (source == null) {
source = file;
}
title = ((function() {
var i, len, results;
results = [];
for (i = 0, len = titles.length; i < len; i++) {
title = titles[i];
results.push(source[title]);
}
return results;
})()).reduce(soak);
order = ((function() {
var i, len, results;
results = [];
for (i = 0, len = orders.length; i < len; i++) {
order = orders[i];
results.push(source[order]);
}
return results;
})()).reduce(soak);
for (i = 0, len = skips.length; i < len; i++) {
skip = skips[i];
if (skip in source && source[skip]) {
return transformCallback(null, file);
}
}
path = resolve('/', file.relative.replace(/\\/g, '/')).replace(/index\.[^\/]+$/, '').replace(/\.[^.\/]+$/, '.' + hrefExtension);
current = navTree;
ref8 = path.split(/([^\/]*\/)/).filter(function(element) {
return element !== '';
});
for (j = 0, len1 = ref8.length; j < len1; j++) {
element = ref8[j];
current = (base = current.children)[element] != null ? base[element] : base[element] = {
parent: current,
children: {},
exists: false,
order: orderGen++,
title: basename(element.replace(/\/?index[^\/]*$/, '')).toLowerCase().replace(/\.[^.]*$/, '').replace(/[-._]/g, ' ').replace(/\b\w/g, function(first) {
return first.toUpperCase();
}).replace(/^$/, '/')
};
}
current.exists = true;
current.title = title != null ? title : current.title;
current.order = order != null ? order : current.order;
nav = navInContext(current, [path], root);
for (k = 0, len2 = targets.length; k < len2; k++) {
target = targets[k];
obj = file;
ref9 = target.split('.'), properties = 2 <= ref9.length ? slice.call(ref9, 0, l = ref9.length - 1) : (l = 0, []), last = ref9[l++];
for (m = 0, len3 = properties.length; m < len3; m++) {
property = properties[m];
obj = obj[property] != null ? obj[property] : obj[property] = {};
}
obj[last] = nav;
}
files.push(file);
return transformCallback();
}, function(flushCallback) {
var child, file, i, len, name, ref8, ref9;
ref8 = navTree.children;
for (name in ref8) {
child = ref8[name];
root.obj = child;
root.name = name;
}
if (demoteTopIndex) {
ref9 = root.obj.children;
for (name in ref9) {
child = ref9[name];
navTree.children[resolve(root.name, name)] = child;
child.parent = navTree;
}
root.obj.children = {};
}
for (i = 0, len = files.length; i < len; i++) {
file = files[i];
this.push(file);
}
return flushCallback();
});
};
navInContext = function(nav, context, root) {
var postFix, ref;
postFix = (ref = context.slice(-1)[0].slice(-1)) === '/' || ref === '.' ? '..' : '.';
return Object.defineProperties({
title: nav.title,
href: nav.exists ? relative(context[0], resolve.apply(null, context)) : void 0,
active: context[0] === resolve.apply(null, context)
}, {
parent: {
enumerable: true,
get: function() {
return navInContext(nav.parent, context.concat(postFix), root);
}
},
children: {
enumerable: true,
get: function() {
var child, i, len, name, ref1, ref2, results;
ref1 = ((function() {
var ref1, results1;
ref1 = nav.children;
results1 = [];
for (name in ref1) {
child = ref1[name];
results1.push([child, name]);
}
return results1;
})()).sort(function(arg, arg1) {
var a, b;
a = arg[0];
b = arg1[0];
return a.order - b.order;
});
results = [];
for (i = 0, len = ref1.length; i < len; i++) {
ref2 = ref1[i], child = ref2[0], name = ref2[1];
results.push(navInContext(child, context.concat(name), root));
}
return results;
}
},
siblings: {
enumerable: true,
get: function() {
return this.parent.children;
}
},
root: {
enumerable: true,
get: function() {
return navInContext(root.obj, context.concat(root.name), root);
}
},
hasActiveDescendant: {
enumerable: true,
get: function() {
return this.children.some(function(child) {
return child.active || child.hasActiveDescendant;
});
}
}
});
};
relative = function(source, target) {
var _, last;
source = source.split('/');
target = target.split('/');
while (source.length && source.shift() === (last = target[0])) {
target.shift();
}
return ((function() {
var i, len, results;
results = [];
for (i = 0, len = source.length; i < len; i++) {
_ = source[i];
results.push('..');
}
return results;
})()).concat(target.length ? target : last).join('/').replace(/(^|\.\/)$/, '.');
};
url = require('url');
resolve = function() {
var parts;
parts = 1 <= arguments.length ? slice.call(arguments, 0) : [];
return parts.reduce(url.resolve);
};
soak = function(x, y) {
return x != null ? x : y;
};
}).call(this);
//# sourceMappingURL=gulp-nav.js.map