-
-
Notifications
You must be signed in to change notification settings - Fork 16
/
eleventy-navigation.js
108 lines (96 loc) · 3.47 KB
/
eleventy-navigation.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
const DepGraph = require("dependency-graph").DepGraph;
function findNavigationEntries(nodes = [], key = "") {
let pages = [];
for(let entry of nodes) {
if(entry.data && entry.data.eleventyNavigation) {
let nav = entry.data.eleventyNavigation;
if(!key && !nav.parent || nav.parent === key) {
pages.push(Object.assign({}, nav, {
url: entry.data.page.url,
pluginType: "eleventy-navigation"
}, key ? { parentKey: key } : {}));
}
}
}
return pages.sort(function(a, b) {
return (a.order || 0) - (b.order || 0);
}).map(function(entry) {
if(!entry.title) {
entry.title = entry.key;
}
if(entry.key) {
entry.children = findNavigationEntries(nodes, entry.key);
}
return entry;
});
}
function findDependencies(pages, depGraph, parentKey) {
for( let page of pages ) {
depGraph.addNode(page.key, page);
if(parentKey) {
depGraph.addDependency(page.key, parentKey);
}
if(page.children) {
findDependencies(page.children, depGraph, page.key);
}
}
}
function findBreadcrumbEntries(nodes, activeKey) {
let pages = findNavigationEntries(nodes);
let graph = new DepGraph();
findDependencies(pages, graph);
return activeKey ? graph.dependenciesOf(activeKey).map(key => {
let data = Object.assign({}, graph.getNodeData(key));
delete data.children;
data._isBreadcrumb = true;
return data;
}) : [];
}
function navigationToHtml(pages, options = {}) {
options = Object.assign({
listElement: "ul",
listItemElement: "li",
listClass: "",
listItemClass: "",
listItemHasChildrenClass: "",
activeKey: "",
activeListItemClass: "",
showExcerpt: false,
isChildList: false
}, options);
let isChildList = !!options.isChildList;
options.isChildList = true;
let urlFilter;
if("getFilter" in this) {
// v0.10.0.beta.2 and above
urlFilter = this.getFilter("url");
} else if("nunjucksFilters" in this) {
// backwards compat, hardcoded key
urlFilter = this.nunjucksFilters.url;
} else {
// Theoretically we could just move on here with a `url => url` but then `pathPrefix`
// would not work and it wouldn’t be obvious why—so let’s fail loudly to avoid that.
throw new Error("Could not find a `url` filter for the eleventy-navigation plugin in eleventyNavigationToHtml filter.");
}
if(pages.length && pages[0].pluginType !== "eleventy-navigation") {
throw new Error("Incorrect argument passed to eleventyNavigationToHtml filter. You must call `eleventyNavigation` or `eleventyNavigationBreadcrumb` first, like: `collection.all | eleventyNavigation | eleventyNavigationToHtml | safe`");
}
return pages.length ? `<${options.listElement}${!isChildList && options.listClass ? ` class="${options.listClass}"` : ''}>${pages.map(entry => {
let liClass = [];
if(options.listItemClass) {
liClass.push(options.listItemClass);
}
if(options.activeKey === entry.key && options.activeListItemClass) {
liClass.push(options.activeListItemClass);
}
if(options.listItemHasChildrenClass && entry.children && entry.children.length) {
liClass.push(options.listItemHasChildrenClass);
}
return `<${options.listItemElement}${liClass.length ? ` class="${liClass.join(" ")}"` : ''}><a href="${urlFilter(entry.url)}">${entry.title}</a>${options.showExcerpt && entry.excerpt ? `: ${entry.excerpt}` : ""}${entry.children ? navigationToHtml.call(this, entry.children, options) : ""}</${options.listItemElement}>`;
}).join("\n")}</${options.listElement}>` : "";
}
module.exports = {
findNavigationEntries,
findBreadcrumbEntries,
toHtml: navigationToHtml
};