-
Notifications
You must be signed in to change notification settings - Fork 1
/
make-tree.js
99 lines (79 loc) · 2.26 KB
/
make-tree.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
module.exports = function makeTree(elements) {
var treeData = makeTreeData(elements || []);
var rootNode = { level: 0, children: [] };
var tree = rootNode.children;
var lastNode;
treeData.forEach(function(node) {
node.children = [];
if (!lastNode) {
tree.push(node);
}
else if (node.level === lastNode.level) {
findParentNode(lastNode, rootNode).children.push(node);
}
else if (node.level > lastNode.level) {
lastNode.children.push(node);
}
else {
findAncestorOfLevel(node.level, lastNode, rootNode).children.push(node);
}
lastNode = node;
});
return tree;
};
function findParentNode(needle, haystack) {
var parent;
if (haystack.children.indexOf(needle) !== -1) {
return haystack;
}
for (var i = 0; i < haystack.children.length; i += 1) {
parent = findParentNode(needle, haystack.children[i]);
if (parent) { break; }
}
return parent;
}
function findAncestorOfLevel(level, needle, haystack) {
var parent = findParentNode(needle, haystack);
return (parent.level < level) ?
parent :
findAncestorOfLevel(level, parent, haystack);
}
function makeHeadingId(text) {
return (text || "")
.replace(/\s/g, "-") // replace spaces with dashes
.replace(/[^\w\-]/g, "") // remove punctuation
.toLowerCase();
}
function makeTreeData(elements) {
var ids = {};
var map = [].map;
// Get elements without [data-skip] attribute only
elements = elements.filter(function(element) {
// check if element has attributes (for testing)
if (element.attributes) {
return !element.attributes['data-skip'];
}
return true;
});
return map.call(elements, function(element) {
var text = element.textContent;
var id = element.id || makeHeadingId(text);
element.id = id;
var level = getElementLevel(element);
// generate unique id for elements with same text
var count = ids[id] || 0;
var uniq = count > 0 ? id + "-" + count : id;
ids[id] = count + 1;
return { id: uniq, text: text, level: level };
});
}
function getElementLevel(element) {
var defaultLevel = 2;
var tagName = element.tagName.toLowerCase();
var headingTagNames = ["h1", "h2", "h3", "h4", "h5", "h6"];
if (headingTagNames.indexOf(tagName) !== -1) {
return parseInt(tagName.slice(1), 10);
}
// default value if not a heading tag
return defaultLevel;
}