mirror of
https://github.com/maikka39/Personal-Website.git
synced 2026-10-02 14:46:25 +00:00
Add a ToC that is always visible on desktop
This commit is contained in:
@@ -40,6 +40,12 @@ page = ["HTML", "RSS"]
|
|||||||
[pagination]
|
[pagination]
|
||||||
pagerSize = 12
|
pagerSize = 12
|
||||||
|
|
||||||
|
[markup]
|
||||||
|
[markup.tableOfContents]
|
||||||
|
endLevel = 4
|
||||||
|
ordered = true
|
||||||
|
startLevel = 2
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
dateform = "Jan 2, 2006"
|
dateform = "Jan 2, 2006"
|
||||||
dateformShort = "Jan 2"
|
dateformShort = "Jan 2"
|
||||||
|
|||||||
@@ -1,3 +1,14 @@
|
|||||||
|
const throttle = (func, timeFrame) => {
|
||||||
|
let lastTime = 0;
|
||||||
|
return () => {
|
||||||
|
let now = new Date();
|
||||||
|
if (now - lastTime >= timeFrame) {
|
||||||
|
func();
|
||||||
|
lastTime = now;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
window.addEventListener("load", () => {
|
window.addEventListener("load", () => {
|
||||||
// Enlarged floating figures
|
// Enlarged floating figures
|
||||||
for (let figure of document.getElementsByTagName("figure")) {
|
for (let figure of document.getElementsByTagName("figure")) {
|
||||||
@@ -51,6 +62,50 @@ window.addEventListener("load", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set active toc heading
|
||||||
|
const toc = document.getElementById("toc");
|
||||||
|
const tocNav = toc.getElementsByTagName("nav")[0];
|
||||||
|
const headingsForToc = [
|
||||||
|
...document.getElementsByTagName("article"),
|
||||||
|
].flatMap((article) =>
|
||||||
|
[...article.querySelectorAll("h1, h2, h3, h4")]
|
||||||
|
.filter((heading) => heading.offsetParent.tagName === "MAIN")
|
||||||
|
.reverse()
|
||||||
|
);
|
||||||
|
const onTocScroll = () => {
|
||||||
|
for (const heading of headingsForToc) {
|
||||||
|
if (window.scrollY + window.innerHeight / 3 > heading.offsetTop) {
|
||||||
|
const headingAnchor = heading.getElementsByTagName("a")[0];
|
||||||
|
|
||||||
|
for (const tocAnchor of toc.getElementsByTagName("a")) {
|
||||||
|
tocAnchor.classList.remove("current-toc");
|
||||||
|
|
||||||
|
if (tocAnchor.href !== headingAnchor.href) continue;
|
||||||
|
|
||||||
|
tocAnchor.classList.add("current-toc");
|
||||||
|
|
||||||
|
// Scroll toc element into view
|
||||||
|
const tocNavRect = tocNav.getBoundingClientRect();
|
||||||
|
const tocAnchorRect = tocAnchor.getBoundingClientRect();
|
||||||
|
|
||||||
|
const offset =
|
||||||
|
tocAnchorRect.top -
|
||||||
|
tocNavRect.top -
|
||||||
|
tocNav.clientHeight / 2;
|
||||||
|
|
||||||
|
const direction = offset / Math.abs(offset);
|
||||||
|
const limit = (tocNav.clientHeight / 2) * 0.5;
|
||||||
|
|
||||||
|
if (Math.abs(offset) > limit)
|
||||||
|
tocNav.scrollTop += offset - direction * limit;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener("scroll", throttle(onTocScroll, 50));
|
||||||
|
onTocScroll();
|
||||||
|
|
||||||
// Code copy button
|
// Code copy button
|
||||||
for (let codeblock of document.querySelectorAll(".highlight pre")) {
|
for (let codeblock of document.querySelectorAll(".highlight pre")) {
|
||||||
if (codeblock.querySelector(".lnt")) continue; // skip line numbers
|
if (codeblock.querySelector(".lnt")) continue; // skip line numbers
|
||||||
@@ -70,6 +125,5 @@ window.addEventListener("load", () => {
|
|||||||
|
|
||||||
button.classList.add("current-code");
|
button.classList.add("current-code");
|
||||||
});
|
});
|
||||||
console.log(codeblock);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -715,3 +715,132 @@ table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#toc {
|
||||||
|
&.desktop-only {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.625rem;
|
||||||
|
line-height: 1.3;
|
||||||
|
margin: 0.83em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
li::marker {
|
||||||
|
content: "- ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1840px) {
|
||||||
|
display: block !important;
|
||||||
|
position: absolute;
|
||||||
|
top: 100vh;
|
||||||
|
height: calc(100% - 100vh - 380px);
|
||||||
|
|
||||||
|
.toc-content {
|
||||||
|
position: sticky;
|
||||||
|
top: 10vh;
|
||||||
|
height: 70vh;
|
||||||
|
margin-bottom: -2em;
|
||||||
|
margin-left: calc(-300px - 100px);
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 300px;
|
||||||
|
right: calc(100% + 100px);
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
background: darken($light-background, 10%);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: darken($light-background, 25%);
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: darken($light-background, 40%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-theme & {
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
background: lighten($dark-background, 10%);
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: lighten($dark-background, 25%);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: lighten($dark-background, 40%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-title {
|
||||||
|
font-size: 1.375rem;
|
||||||
|
min-height: calc(1.625rem * 1.3);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
overflow-y: auto;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: block;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: darken($light-background, 10%);
|
||||||
|
|
||||||
|
.dark-theme & {
|
||||||
|
background: lighten($dark-background, 10%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.current-toc {
|
||||||
|
background: darken($light-background, 10%);
|
||||||
|
|
||||||
|
.dark-theme & {
|
||||||
|
background: lighten($dark-background, 10%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: "- ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
li::marker {
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
li a {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
li li a {
|
||||||
|
padding-left: 40px;
|
||||||
|
}
|
||||||
|
li li li a {
|
||||||
|
padding-left: 60px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,14 +38,12 @@
|
|||||||
{{- partial "image.html" (dict "path" .Params.Cover "alt" (.Title | plainify) "class" "post-cover") }}
|
{{- partial "image.html" (dict "path" .Params.Cover "alt" (.Title | plainify) "class" "post-cover") }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- if .Params.toc }}
|
<aside id="toc" class="{{- if not .Params.toc }}desktop-only{{- end }}">
|
||||||
<hr />
|
<div class="toc-content">
|
||||||
<aside id="toc">
|
|
||||||
<div class="toc-title">{{ i18n "tableOfContents" }}</div>
|
<div class="toc-title">{{ i18n "tableOfContents" }}</div>
|
||||||
{{ .TableOfContents }}
|
{{ .TableOfContents }}
|
||||||
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
<hr />
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
<div class="post-content">
|
<div class="post-content">
|
||||||
{{ .Content }}
|
{{ .Content }}
|
||||||
|
|||||||
Reference in New Issue
Block a user