From 41fa65cbf5c43301c56b74a7cb2a8bb2edc54f1e Mon Sep 17 00:00:00 2001 From: Jimmy Cai Date: Mon, 21 Jun 2021 18:44:54 +0200 Subject: [PATCH] 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
    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 --- README.md | 1 + assets/scss/grid.scss | 7 +- assets/scss/partials/base.scss | 1 + assets/scss/partials/layout/article.scss | 108 +++++++++++++++++++++++ assets/scss/partials/sidebar.scss | 8 +- exampleSite/config.yaml | 5 ++ i18n/en.yaml | 12 +++ layouts/_default/baseof.html | 6 +- layouts/_default/single.html | 47 +++++++++- layouts/post/single.html | 21 ----- 10 files changed, 182 insertions(+), 34 deletions(-) delete mode 100644 layouts/post/single.html diff --git a/README.md b/README.md index c16389d..9cd73fb 100644 --- a/README.md +++ b/README.md @@ -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 - Properly cropped thumbnails - Subsection support +- Table of contents ## Requirements diff --git a/assets/scss/grid.scss b/assets/scss/grid.scss index c0dc9fc..a0eddca 100644 --- a/assets/scss/grid.scss +++ b/assets/scss/grid.scss @@ -92,7 +92,6 @@ main.main { min-width: 0; - padding: 0 15px; max-width: 100%; flex-grow: 1; padding-top: var(--main-top-padding); @@ -101,12 +100,10 @@ main.main { .main-container { min-height: 100vh; align-items: flex-start; + padding: 0 15px; + column-gap: var(--section-separation); @include respond(md) { - padding: 0 10px; - } - - @include respond(lg) { padding: 0 20px; } } diff --git a/assets/scss/partials/base.scss b/assets/scss/partials/base.scss index e7aefe6..ab3bf42 100644 --- a/assets/scss/partials/base.scss +++ b/assets/scss/partials/base.scss @@ -1,6 +1,7 @@ html { font-size: 62.5%; overflow-y: scroll; + scroll-behavior: smooth; } * { diff --git a/assets/scss/partials/layout/article.scss b/assets/scss/partials/layout/article.scss index 03e8ea1..618ca54 100644 --- a/assets/scss/partials/layout/article.scss +++ b/assets/scss/partials/layout/article.scss @@ -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 { margin-bottom: var(--section-separation); } diff --git a/assets/scss/partials/sidebar.scss b/assets/scss/partials/sidebar.scss index f5abe1e..462729d 100644 --- a/assets/scss/partials/sidebar.scss +++ b/assets/scss/partials/sidebar.scss @@ -1,5 +1,4 @@ .sidebar { - padding: 0 15px; &.sticky { @include respond(md) { position: sticky; @@ -22,8 +21,8 @@ @include respond(md) { width: auto; - margin-right: 1%; - padding: var(--main-top-padding) 15px; + padding-top: var(--main-top-padding); + padding-bottom: var(--main-top-padding); max-height: 100vh; } @@ -46,7 +45,6 @@ } @include respond(lg) { - margin-left: 1%; padding-top: var(--main-top-padding); } } @@ -55,7 +53,7 @@ z-index: 1; transition: box-shadow 0.5s ease; - padding: 15px 30px; + padding: 15px; @include respond(md) { padding: 0; diff --git a/exampleSite/config.yaml b/exampleSite/config.yaml index 51274d6..bf03343 100644 --- a/exampleSite/config.yaml +++ b/exampleSite/config.yaml @@ -42,6 +42,7 @@ params: article: math: false + toc: true license: enabled: true default: Licensed under CC BY-NC-SA 4.0 @@ -145,5 +146,9 @@ related: weight: 200 markup: + tableOfContents: + endLevel: 4 + ordered: true + startLevel: 2 highlight: noClasses: false diff --git a/i18n/en.yaml b/i18n/en.yaml index 99d34ce..21b1310 100644 --- a/i18n/en.yaml +++ b/i18n/en.yaml @@ -17,8 +17,15 @@ list: other: Subsections article: + back: + other: Back + + tableOfContents: + other: Table of contents + relatedContents: other: Related contents + lastUpdatedOn: other: Last updated on @@ -32,8 +39,10 @@ widget: archives: title: other: Archives + more: other: More + tagCloud: title: other: Tags @@ -41,13 +50,16 @@ widget: search: title: other: Search + placeholder: other: Type something... + resultTitle: other: "#PAGES_COUNT pages (#TIME_SECONDS seconds)" footer: builtWith: other: Built with {{ .Generator }} + designedBy: other: Theme {{ .Theme }} designed by {{ .DesignedBy }} diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html index ce0ddae..8a5ff95 100644 --- a/layouts/_default/baseof.html +++ b/layouts/_default/baseof.html @@ -6,8 +6,10 @@ {{- partial "head/colorScheme" . -}} -
    - {{ partial "sidebar/left.html" . }} +
    + {{- block "left-sidebar" . -}} + {{ partial "sidebar/left.html" . }} + {{- end -}}
    {{- block "main" . }}{{- end }}
    diff --git a/layouts/_default/single.html b/layouts/_default/single.html index d9d2f3e..040b547 100644 --- a/layouts/_default/single.html +++ b/layouts/_default/single.html @@ -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" }} {{ partial "article/article.html" . }} + {{ partial "article/components/related-contents" . }} + {{ if or (not (isset .Params "comments")) (eq .Params.comments "true")}} {{ partial "comments/include" . }} {{ end }} @@ -9,4 +24,34 @@ {{ partialCached "footer/footer" . }} {{ partialCached "article/components/photoswipe" . }} +{{ end }} + +{{ define "left-sidebar" }} + {{ if (.Scratch.Get "hasTOC") }} +
    + + {{ (resources.Get "icons/back.svg").Content | safeHTML }} + {{ T "article.back" }} + +
    + {{ else }} + {{ partial "sidebar/left.html" . }} + {{ end }} +{{ end }} + +{{ define "right-sidebar" }} + {{ if (.Scratch.Get "hasTOC") }} + + {{ end }} {{ end }} \ No newline at end of file diff --git a/layouts/post/single.html b/layouts/post/single.html deleted file mode 100644 index be983ec..0000000 --- a/layouts/post/single.html +++ /dev/null @@ -1,21 +0,0 @@ -{{ define "container-class" }}article-page with-toolbar hide-sidebar-sm{{ end }} -{{ define "main" }} -
    - - {{ (resources.Get "icons/back.svg").Content | safeHTML }} - Back - -
    - - {{ 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 }} \ No newline at end of file