Skip to content

Commit d09d10f

Browse files
committed
docs: add a pagetoc to the theme
1 parent 8c21e88 commit d09d10f

File tree

3 files changed

+246
-1
lines changed

3 files changed

+246
-1
lines changed

guide/book.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[book]
2-
title = "The `trunk` Guide"
2+
title = "The Trunk Guide"
33
description = "Documention of Trunk, a web application bundler for Rust"
44
src = "src"
55

@@ -21,7 +21,9 @@ assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
2121
[output.html]
2222
additional-css = [
2323
"./mdbook-admonish.css",
24+
"theme/pagetoc.css"
2425
]
2526
additional-js = [
27+
"theme/pagetoc.js"
2628
]
2729

guide/theme/pagetoc.css

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
:root {
2+
--toc-width: 270px;
3+
--center-content-toc-shift: calc(-1 * var(--toc-width) / 2);
4+
}
5+
6+
.nav-chapters {
7+
/* adjust width of buttons that bring to the previous or the next page */
8+
min-width: 50px;
9+
}
10+
11+
.previous {
12+
/*
13+
adjust the space between the left sidebar or the left side of the screen
14+
and the button that leads to the previous page
15+
*/
16+
margin-left: var(--page-padding);
17+
}
18+
19+
@media only screen {
20+
main {
21+
display: flex;
22+
}
23+
24+
@media (max-width: 1179px) {
25+
.sidebar-hidden .sidetoc {
26+
display: none;
27+
}
28+
}
29+
30+
@media (max-width: 1439px) {
31+
.sidebar-visible .sidetoc {
32+
display: none;
33+
}
34+
}
35+
36+
@media (1180px <= width <= 1439px) {
37+
.sidebar-hidden main {
38+
position: relative;
39+
left: var(--center-content-toc-shift);
40+
}
41+
}
42+
43+
@media (1440px <= width <= 1700px) {
44+
.sidebar-visible main {
45+
position: relative;
46+
left: var(--center-content-toc-shift);
47+
}
48+
}
49+
50+
.content-wrap {
51+
overflow-y: auto;
52+
width: 100%;
53+
}
54+
55+
.sidetoc {
56+
margin-top: 20px;
57+
margin-left: 10px;
58+
margin-right: auto;
59+
}
60+
.pagetoc {
61+
position: fixed;
62+
/* adjust TOC width */
63+
width: var(--toc-width);
64+
height: calc(100vh - var(--menu-bar-height) - 0.67em * 4);
65+
overflow: auto;
66+
}
67+
.pagetoc a {
68+
border-left: 1px solid var(--sidebar-bg);
69+
color: var(--fg) !important;
70+
display: block;
71+
padding-bottom: 5px;
72+
padding-top: 5px;
73+
padding-left: 10px;
74+
text-align: left;
75+
text-decoration: none;
76+
}
77+
.pagetoc a:hover,
78+
.pagetoc a.active {
79+
background: var(--sidebar-bg);
80+
color: var(--sidebar-fg) !important;
81+
}
82+
.pagetoc .active {
83+
background: var(--sidebar-bg);
84+
color: var(--sidebar-fg);
85+
font-weight: bold;
86+
}
87+
.pagetoc .pagetoc-H2 {
88+
padding-left: 20px;
89+
font-size: 90%;
90+
}
91+
.pagetoc .pagetoc-H3 {
92+
padding-left: 40px;
93+
font-size: 90%;
94+
}
95+
.pagetoc .pagetoc-H4 {
96+
padding-left: 60px;
97+
font-size: 90%;
98+
}
99+
}
100+
101+
@media print {
102+
.sidetoc {
103+
display: none;
104+
}
105+
}

guide/theme/pagetoc.js

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
function forEach(elems, fun) {
2+
Array.prototype.forEach.call(elems, fun);
3+
}
4+
5+
function getPagetoc(){
6+
const pagetoc = document.getElementsByClassName("pagetoc")[0];
7+
8+
if (pagetoc) {
9+
return pagetoc;
10+
}
11+
12+
return autoCreatePagetoc();
13+
}
14+
15+
function autoCreatePagetoc() {
16+
const main = document.querySelector("#content > main");
17+
18+
const content = document.createElement("div");
19+
content.classList.add("content-wrap");
20+
content.append(...main.childNodes);
21+
22+
main.appendChild(content);
23+
24+
main.insertAdjacentHTML("beforeend", `
25+
<div class="sidetoc">
26+
<nav class="pagetoc"></nav>
27+
</div>
28+
`);
29+
30+
return document.getElementsByClassName("pagetoc")[0]
31+
}
32+
33+
function getPagetocElems() {
34+
return getPagetoc().children;
35+
}
36+
37+
function getHeaders(){
38+
return document.getElementsByClassName("header")
39+
}
40+
41+
// Un-active everything when you click it
42+
function forPagetocElem(fun) {
43+
forEach(getPagetocElems(), fun);
44+
}
45+
46+
function getRect(element) {
47+
return element.getBoundingClientRect();
48+
}
49+
50+
function overflowTop(container, element) {
51+
return getRect(container).top - getRect(element).top;
52+
}
53+
54+
function overflowBottom(container, element) {
55+
return getRect(container).bottom - getRect(element).bottom;
56+
}
57+
58+
var activeHref = location.href;
59+
60+
var updateFunction = function (elem = undefined) {
61+
var id = elem;
62+
63+
if (!id && location.href != activeHref) {
64+
activeHref = location.href;
65+
forPagetocElem(function (el) {
66+
if (el.href === activeHref) {
67+
id = el;
68+
}
69+
});
70+
}
71+
72+
if (!id) {
73+
var elements = getHeaders();
74+
let margin = window.innerHeight / 3;
75+
76+
forEach(elements, function (el, i, arr) {
77+
if (!id && getRect(el).top >= 0) {
78+
if (getRect(el).top < margin) {
79+
id = el;
80+
} else {
81+
id = arr[Math.max(0, i - 1)];
82+
}
83+
}
84+
// a very long last section
85+
// its heading is over the screen
86+
if (!id && i == arr.length - 1) {
87+
id = el
88+
}
89+
});
90+
}
91+
92+
forPagetocElem(function (el) {
93+
el.classList.remove("active");
94+
});
95+
96+
if (!id) return;
97+
98+
forPagetocElem(function (el) {
99+
if (id.href.localeCompare(el.href) == 0) {
100+
el.classList.add("active");
101+
let pagetoc = getPagetoc();
102+
if (overflowTop(pagetoc, el) > 0) {
103+
pagetoc.scrollTop = el.offsetTop;
104+
}
105+
if (overflowBottom(pagetoc, el) < 0) {
106+
pagetoc.scrollTop -= overflowBottom(pagetoc, el);
107+
}
108+
}
109+
});
110+
};
111+
112+
let elements = getHeaders();
113+
114+
if (elements.length > 1) {
115+
// Populate sidebar on load
116+
window.addEventListener("load", function () {
117+
var pagetoc = getPagetoc();
118+
var elements = getHeaders();
119+
forEach(elements, function (el) {
120+
var link = document.createElement("a");
121+
link.appendChild(document.createTextNode(el.text));
122+
link.href = el.hash;
123+
link.classList.add("pagetoc-" + el.parentElement.tagName);
124+
pagetoc.appendChild(link);
125+
link.onclick = function () {
126+
updateFunction(link);
127+
};
128+
});
129+
updateFunction();
130+
});
131+
132+
// Handle active elements on scroll
133+
window.addEventListener("scroll", function () {
134+
updateFunction();
135+
});
136+
} else {
137+
document.getElementsByClassName("sidetoc")[0].remove();
138+
}

0 commit comments

Comments
 (0)