Skip to content

Commit 7226d1c

Browse files
committed
Adds the @outline tag
1 parent b429bbd commit 7226d1c

File tree

3 files changed

+99
-19
lines changed

3 files changed

+99
-19
lines changed

bit-docs.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
var path = require("path");
2+
var tags = require("./tags");
23

34
module.exports = function(bitDocs){
4-
var pkg = require("./package.json");
5-
var dependencies = {};
6-
dependencies[pkg.name] = pkg.version;
5+
var pkg = require("./package.json");
6+
var dependencies = {};
7+
dependencies[pkg.name] = pkg.version;
78

8-
bitDocs.register("html", {
9-
dependencies: dependencies
10-
});
9+
bitDocs.register("html", {
10+
dependencies: dependencies
11+
});
12+
13+
bitDocs.register("tags", tags);
1114
}

tags.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @constructor documentjs.tags.outline @outline
3+
* @parent documentjs.tags
4+
*
5+
* @description
6+
*
7+
* Controls the outline behavior.
8+
*
9+
* @signature `@outline DEPTH TAG`
10+
*
11+
* Controls the outline's depth and type.
12+
*
13+
* @param {Number} [DEPTH=1] The number of headers below and including h2. For example,
14+
* `2` will include `h2` and `h3` elements.
15+
*
16+
* @param {String} [TAG="ul"] Make the list an ordered list.
17+
*
18+
* @body
19+
*
20+
*/
21+
exports.outline = {
22+
add: function (line, curData, scope, docMap) {
23+
var m = line.match(/@outline\s+(\d+)(?:\s+(ol|ul))?/);
24+
if(m) {
25+
if(!this.outline) {
26+
this.outline = {};
27+
}
28+
if(m[1]) {
29+
this.outline.depth = +m[1];
30+
}
31+
if(m[2]) {
32+
this.outline.tag = m[2];
33+
}
34+
}
35+
}
36+
};

toc.js

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ var template = stache("{{#each titles}}" +
66
"<li><a ($click)='scrollTo(., %event)' href='#{{id}}'>{{text}}</a></li>" +
77
"{{/each}}");
88

9-
var toc = document.getElementsByClassName("on-this-page")[0];
10-
119
function throttle(fn, ms){
1210
var wait = false;
1311
return function(){
@@ -22,19 +20,30 @@ function throttle(fn, ms){
2220
};
2321
}
2422

23+
function outerHeight(el) {
24+
var height = el.offsetHeight;
25+
var style = getComputedStyle(el);
26+
27+
height += parseInt(style.marginTop) + parseInt(style.marginBottom);
28+
return height;
29+
}
30+
2531
var TableOfContents = Control.extend({
2632
init: function(el, options){
2733
this.scroller = document.body;
28-
this.titleSelector = options.titleSelector || ".signature-title";
34+
this.container = this.element.parentNode;
2935

30-
this.navHeight = this.getNavHeight();
36+
this.depth = window.docObject.outline && window.docObject.outline.depth || 1;
3137

38+
this.navHeight = this.getNavHeight();
3239
this.titles = this.collectTitles();
3340

3441
// If there are no titles, bail
3542
if(!this.titles.length) {
3643
el.parentNode.removeChild(el);
3744
return;
45+
} else {
46+
el.parentNode.style.display = 'block';
3847
}
3948
this.titleIndex = 0;
4049
this.calculateActive();
@@ -46,7 +55,8 @@ var TableOfContents = Control.extend({
4655
scrollTo: function(item, ev){
4756
ev.preventDefault();
4857
toc.disabled(true);
49-
window.scrollTo(0, item.pos + 1);
58+
var pos = item.pos + toc.TOCHeight;
59+
window.scrollTo(0, pos + 1);
5060
toc.calculateActive();
5161

5262
requestAnimationFrame(function(){
@@ -55,6 +65,8 @@ var TableOfContents = Control.extend({
5565
}
5666
}));
5767
this.setActive(this.titleIndex);
68+
this.TOCHeight = this.getTOCHeight();
69+
this.container.style.height = this.TOCHeight + 'px';
5870

5971
// Wait until we've appended the TOC so it can be part of the calculation
6072
this.fixed(!this.isFirstTitleVisible());
@@ -67,14 +79,22 @@ var TableOfContents = Control.extend({
6779
return nav.clientHeight;
6880
},
6981

82+
getTOCHeight: function(){
83+
return outerHeight(this.element);
84+
},
85+
7086
isFirstTitleVisible: function(){
7187
var firstPosition = this.titles[0].pos + this.element.clientHeight +
7288
this.navHeight;
7389
return firstPosition > this.scroller.scrollTop;
7490
},
7591

7692
collectTitles: function(){
77-
var titles = document.querySelectorAll("article " + this.titleSelector);
93+
var selector = this.getHeadings().map(function(h){
94+
return "article " + h;
95+
}).join(",");
96+
97+
var titles = document.querySelectorAll(selector);
7898
var curScroll = this.scroller.scrollTop;
7999
var navHeight = this.navHeight;
80100
return [].map.call(titles, function(title, idx){
@@ -89,6 +109,14 @@ var TableOfContents = Control.extend({
89109
});
90110
},
91111

112+
getHeadings: function(){
113+
var headings = [];
114+
for(var i = 0; i < this.depth; i++) {
115+
headings.push("h" + (i + 2));
116+
}
117+
return headings;
118+
},
119+
92120
fixed: function(fixed){
93121
if(fixed === this._fixed) {
94122
return;
@@ -131,35 +159,48 @@ var TableOfContents = Control.extend({
131159

132160
calculateActive: function(){
133161
var scrollTop = this.scroller.scrollTop;
162+
var TOCHeight = this.TOCHeight;
134163

135164
// Determine which h2 should be showing
136165
var prev = this.getTitle(this.titleIndex);
137166
var next = this.getTitle(this.titleIndex + 1);
138167

139168
// See if we need to jump to the next when scrolling down
140-
var cur;
141-
while(scrollTop > next.pos) {
169+
var cur, nextPos = next.pos + TOCHeight;
170+
while(scrollTop > nextPos) {
142171
cur = next;
143172
next = this.getTitle(cur.index + 1);
173+
nextPos = next.pos + TOCHeight;
144174
}
145175

146176
// See if we need to move to the previous when scrolling up
147177
if(!cur) {
178+
var curPos;
148179
do {
149180
cur = prev;
181+
curPos = cur.pos + TOCHeight;
150182
prev = this.getTitle(prev.index - 1);
151-
} while(scrollTop < cur.pos);
183+
} while(scrollTop < curPos);
152184
}
153185

154186
if(typeof cur.pos !== "undefined") {
155187
this.setActive(cur.index);
156188
}
157-
},
189+
}
190+
});
158191

192+
var TOCContainer = Control.extend({
193+
init: function(el){
194+
el.style.display = 'none';
159195

196+
var toc = document.createElement("ul");
197+
toc.className = "on-this-page";
198+
el.appendChild(toc);
160199

200+
new TableOfContents(toc);
201+
}
161202
});
162203

163-
if(toc) {
164-
new TableOfContents(toc);
165-
}
204+
new TOCContainer(
205+
document.getElementsByClassName("on-this-page-container")[0]
206+
);

0 commit comments

Comments
 (0)