feat: Table of Contents (#232)
Currently, the new table of contents is disabled by default. I will change that after several versions. ------------- * feat: Table of Content (WIP) * fix: set scratch inside define block * fix(toc): darkmode text color * feat: unify page layout, and add config to disable toc * feat: add scroll-behavior: smooth to html * fix: use <ol> for TOC. And Disable TOC by default for now * refactor: use css flexbox for article page with toc enable toc for example site * feat(i18n): add i18n entry for "Back" and "Table of Contents" * style: remove unused `keep-sidebar` class * doc: add table of contents as feature
This commit is contained in:
parent
dda55f87e2
commit
41fa65cbf5
@ -27,6 +27,7 @@ Stack is a simple card-style Hugo theme designed for bloggers, some of its featu
|
|||||||
- No CSS framework, keep it simple and minimal
|
- No CSS framework, keep it simple and minimal
|
||||||
- Properly cropped thumbnails
|
- Properly cropped thumbnails
|
||||||
- Subsection support
|
- Subsection support
|
||||||
|
- Table of contents
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
|
@ -92,7 +92,6 @@
|
|||||||
|
|
||||||
main.main {
|
main.main {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
padding: 0 15px;
|
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
padding-top: var(--main-top-padding);
|
padding-top: var(--main-top-padding);
|
||||||
@ -101,12 +100,10 @@ main.main {
|
|||||||
.main-container {
|
.main-container {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
padding: 0 15px;
|
||||||
|
column-gap: var(--section-separation);
|
||||||
|
|
||||||
@include respond(md) {
|
@include respond(md) {
|
||||||
padding: 0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include respond(lg) {
|
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
html {
|
html {
|
||||||
font-size: 62.5%;
|
font-size: 62.5%;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
scroll-behavior: smooth;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
@ -114,6 +114,114 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.article-page.has-toc {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
|
||||||
|
.left-sidebar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-sidebar {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
@include respond(xl) {
|
||||||
|
display: block;
|
||||||
|
top: var(--main-top-padding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#article-toolbar {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
@include respond(md) {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include respond(xl) {
|
||||||
|
margin-top: 0;
|
||||||
|
position: sticky;
|
||||||
|
top: var(--main-top-padding);
|
||||||
|
flex-shrink: 1;
|
||||||
|
|
||||||
|
a {
|
||||||
|
background: transparent;
|
||||||
|
box-shadow: none;
|
||||||
|
border: 1px solid var(--body-text-color);
|
||||||
|
width: 100%;
|
||||||
|
margin-right: 0;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-container {
|
||||||
|
align-items: start;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
@include respond(xl) {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
padding-top: 0;
|
||||||
|
|
||||||
|
@include respond(xl) {
|
||||||
|
padding-top: var(--main-top-padding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget--toc {
|
||||||
|
background-color: var(--card-background);
|
||||||
|
border-radius: var(--card-border-radius);
|
||||||
|
box-shadow: var(--shadow-l1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
color: var(--card-text-color-main);
|
||||||
|
|
||||||
|
#TableOfContents {
|
||||||
|
ol {
|
||||||
|
counter-reset: item;
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > li {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin: 15px 20px;
|
||||||
|
padding: 5px;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
counter-increment: item;
|
||||||
|
content: counters(item, ".") ". ";
|
||||||
|
font-weight: bold;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > ol {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding-left: 10px;
|
||||||
|
margin-bottom: -5px;
|
||||||
|
|
||||||
|
& > li:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.related-contents--wrapper {
|
.related-contents--wrapper {
|
||||||
margin-bottom: var(--section-separation);
|
margin-bottom: var(--section-separation);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
.sidebar {
|
.sidebar {
|
||||||
padding: 0 15px;
|
|
||||||
&.sticky {
|
&.sticky {
|
||||||
@include respond(md) {
|
@include respond(md) {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
@ -22,8 +21,8 @@
|
|||||||
|
|
||||||
@include respond(md) {
|
@include respond(md) {
|
||||||
width: auto;
|
width: auto;
|
||||||
margin-right: 1%;
|
padding-top: var(--main-top-padding);
|
||||||
padding: var(--main-top-padding) 15px;
|
padding-bottom: var(--main-top-padding);
|
||||||
max-height: 100vh;
|
max-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +45,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@include respond(lg) {
|
@include respond(lg) {
|
||||||
margin-left: 1%;
|
|
||||||
padding-top: var(--main-top-padding);
|
padding-top: var(--main-top-padding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,7 +53,7 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
transition: box-shadow 0.5s ease;
|
transition: box-shadow 0.5s ease;
|
||||||
|
|
||||||
padding: 15px 30px;
|
padding: 15px;
|
||||||
|
|
||||||
@include respond(md) {
|
@include respond(md) {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -42,6 +42,7 @@ params:
|
|||||||
|
|
||||||
article:
|
article:
|
||||||
math: false
|
math: false
|
||||||
|
toc: true
|
||||||
license:
|
license:
|
||||||
enabled: true
|
enabled: true
|
||||||
default: Licensed under CC BY-NC-SA 4.0
|
default: Licensed under CC BY-NC-SA 4.0
|
||||||
@ -145,5 +146,9 @@ related:
|
|||||||
weight: 200
|
weight: 200
|
||||||
|
|
||||||
markup:
|
markup:
|
||||||
|
tableOfContents:
|
||||||
|
endLevel: 4
|
||||||
|
ordered: true
|
||||||
|
startLevel: 2
|
||||||
highlight:
|
highlight:
|
||||||
noClasses: false
|
noClasses: false
|
||||||
|
12
i18n/en.yaml
12
i18n/en.yaml
@ -17,8 +17,15 @@ list:
|
|||||||
other: Subsections
|
other: Subsections
|
||||||
|
|
||||||
article:
|
article:
|
||||||
|
back:
|
||||||
|
other: Back
|
||||||
|
|
||||||
|
tableOfContents:
|
||||||
|
other: Table of contents
|
||||||
|
|
||||||
relatedContents:
|
relatedContents:
|
||||||
other: Related contents
|
other: Related contents
|
||||||
|
|
||||||
lastUpdatedOn:
|
lastUpdatedOn:
|
||||||
other: Last updated on
|
other: Last updated on
|
||||||
|
|
||||||
@ -32,8 +39,10 @@ widget:
|
|||||||
archives:
|
archives:
|
||||||
title:
|
title:
|
||||||
other: Archives
|
other: Archives
|
||||||
|
|
||||||
more:
|
more:
|
||||||
other: More
|
other: More
|
||||||
|
|
||||||
tagCloud:
|
tagCloud:
|
||||||
title:
|
title:
|
||||||
other: Tags
|
other: Tags
|
||||||
@ -41,13 +50,16 @@ widget:
|
|||||||
search:
|
search:
|
||||||
title:
|
title:
|
||||||
other: Search
|
other: Search
|
||||||
|
|
||||||
placeholder:
|
placeholder:
|
||||||
other: Type something...
|
other: Type something...
|
||||||
|
|
||||||
resultTitle:
|
resultTitle:
|
||||||
other: "#PAGES_COUNT pages (#TIME_SECONDS seconds)"
|
other: "#PAGES_COUNT pages (#TIME_SECONDS seconds)"
|
||||||
|
|
||||||
footer:
|
footer:
|
||||||
builtWith:
|
builtWith:
|
||||||
other: Built with {{ .Generator }}
|
other: Built with {{ .Generator }}
|
||||||
|
|
||||||
designedBy:
|
designedBy:
|
||||||
other: Theme {{ .Theme }} designed by {{ .DesignedBy }}
|
other: Theme {{ .Theme }} designed by {{ .DesignedBy }}
|
||||||
|
@ -6,8 +6,10 @@
|
|||||||
</head>
|
</head>
|
||||||
<body class="{{ block `body-class` . }}{{ end }}">
|
<body class="{{ block `body-class` . }}{{ end }}">
|
||||||
{{- partial "head/colorScheme" . -}}
|
{{- partial "head/colorScheme" . -}}
|
||||||
<div class="container main-container flex on-phone--column {{ if .Site.Params.widgets.enabled }}extended{{ else }}compact{{ end }} {{ block `container-class` . }}{{end}}">
|
<div class="container main-container flex {{ block `container-class` . }}on-phone--column {{ if .Site.Params.widgets.enabled }}extended{{ else }}compact{{ end }}{{ end }}">
|
||||||
{{ partial "sidebar/left.html" . }}
|
{{- block "left-sidebar" . -}}
|
||||||
|
{{ partial "sidebar/left.html" . }}
|
||||||
|
{{- end -}}
|
||||||
<main class="main full-width">
|
<main class="main full-width">
|
||||||
{{- block "main" . }}{{- end }}
|
{{- block "main" . }}{{- end }}
|
||||||
</main>
|
</main>
|
||||||
|
@ -1,7 +1,22 @@
|
|||||||
{{ define "body-class" }}article-page{{ end }}
|
{{ define "body-class" }}
|
||||||
|
{{ $TOCEnabled := default (default false .Site.Params.article.toc) .Params.toc }}
|
||||||
|
{{- .Scratch.Set "hasTOC" (and (ge (len .TableOfContents) 100) $TOCEnabled) -}}
|
||||||
|
article-page {{ if (.Scratch.Get "hasTOC") }}has-toc{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "container-class" }}
|
||||||
|
{{ if (.Scratch.Get "hasTOC") }}
|
||||||
|
extended
|
||||||
|
{{ else }}
|
||||||
|
on-phone--column {{ if .Site.Params.widgets.enabled }}extended{{ else }}compact{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
{{ define "main" }}
|
{{ define "main" }}
|
||||||
{{ partial "article/article.html" . }}
|
{{ partial "article/article.html" . }}
|
||||||
|
|
||||||
|
{{ partial "article/components/related-contents" . }}
|
||||||
|
|
||||||
{{ if or (not (isset .Params "comments")) (eq .Params.comments "true")}}
|
{{ if or (not (isset .Params "comments")) (eq .Params.comments "true")}}
|
||||||
{{ partial "comments/include" . }}
|
{{ partial "comments/include" . }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
@ -9,4 +24,34 @@
|
|||||||
{{ partialCached "footer/footer" . }}
|
{{ partialCached "footer/footer" . }}
|
||||||
|
|
||||||
{{ partialCached "article/components/photoswipe" . }}
|
{{ partialCached "article/components/photoswipe" . }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "left-sidebar" }}
|
||||||
|
{{ if (.Scratch.Get "hasTOC") }}
|
||||||
|
<div id="article-toolbar">
|
||||||
|
<a href="{{ .Site.BaseURL }}" class="back-home">
|
||||||
|
{{ (resources.Get "icons/back.svg").Content | safeHTML }}
|
||||||
|
<span>{{ T "article.back" }}</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{ else }}
|
||||||
|
{{ partial "sidebar/left.html" . }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "right-sidebar" }}
|
||||||
|
{{ if (.Scratch.Get "hasTOC") }}
|
||||||
|
<aside class="sidebar right-sidebar sticky">
|
||||||
|
<section class="widget archives">
|
||||||
|
<div class="widget-icon">
|
||||||
|
{{ partial "helper/icon" "hash" }}
|
||||||
|
</div>
|
||||||
|
<h2 class="widget-title section-title">{{ T "article.tableOfContents" }}</h2>
|
||||||
|
|
||||||
|
<div class="widget--toc">
|
||||||
|
{{ .TableOfContents }}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</aside>
|
||||||
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
@ -1,21 +0,0 @@
|
|||||||
{{ define "container-class" }}article-page with-toolbar hide-sidebar-sm{{ end }}
|
|
||||||
{{ define "main" }}
|
|
||||||
<div id="article-toolbar">
|
|
||||||
<a href="{{ .Site.BaseURL }}" class="back-home">
|
|
||||||
{{ (resources.Get "icons/back.svg").Content | safeHTML }}
|
|
||||||
<span>Back</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{ partial "article/article.html" . }}
|
|
||||||
|
|
||||||
{{ partial "article/components/related-contents" . }}
|
|
||||||
|
|
||||||
{{ if or (not (isset .Params "comments")) (eq .Params.comments "true")}}
|
|
||||||
{{ partial "comments/include" . }}
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
{{ partialCached "footer/footer" . }}
|
|
||||||
|
|
||||||
{{- partialCached "article/components/photoswipe.html" . -}}
|
|
||||||
{{ end }}
|
|
Loading…
Reference in New Issue
Block a user