Add Tables of Contents to articles

pull/100/head
James Panther 2022-01-18 16:24:33 +11:00
parent ace158ed42
commit acc4aee752
No known key found for this signature in database
GPG Key ID: D36F789E45745D17
15 changed files with 175 additions and 9 deletions

View File

@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Site search powered by Fuse.js - Site search powered by Fuse.js
- Automatic Markdown image resizing and srcset generation - Automatic Markdown image resizing and srcset generation
- Performance and Accessibility improvements to achieve perfect Lighthouse scores - Performance and Accessibility improvements to achieve perfect Lighthouse scores
- Tables of Contents on article pages
- Taxonomies on article and list pages - Taxonomies on article and list pages
- Author `headline` parameter - Author `headline` parameter
- Skip to content links - Skip to content links

View File

@ -994,6 +994,40 @@ body a, body button {
padding-left: 0px; padding-left: 0px;
} }
/* Table of Contents */
.toc ul, .toc li {
margin-top: 0.25rem;
margin-bottom: 0.25rem;
list-style-type: none;
padding-left: 0px;
padding-right: 0px;
line-height: 1.375;
}
[dir="ltr"] .toc ul ul {
padding-left: 1rem;
}
[dir="rtl"] .toc ul ul {
padding-right: 1rem;
}
.toc a {
font-weight: 400;
--tw-text-opacity: 1;
color: rgba(var(--color-neutral-700), var(--tw-text-opacity));
}
.dark .toc a {
--tw-text-opacity: 1;
color: rgba(var(--color-neutral-400), var(--tw-text-opacity));
}
[dir="rtl"] .toc ul > li {
margin-right: 0px;
}
/* -- Chroma Highlight -- */ /* -- Chroma Highlight -- */
/* Background */ /* Background */
@ -1418,6 +1452,10 @@ body a, body button {
z-index: 10; z-index: 10;
} }
.order-first {
order: -9999;
}
.m-auto { .m-auto {
margin: auto; margin: auto;
} }
@ -1636,6 +1674,10 @@ body a, body button {
max-width: 65ch; max-width: 65ch;
} }
.max-w-full {
max-width: 100%;
}
.max-w-\[10rem\] { .max-w-\[10rem\] {
max-width: 10rem; max-width: 10rem;
} }
@ -1644,10 +1686,6 @@ body a, body button {
max-width: 48rem; max-width: 48rem;
} }
.max-w-full {
max-width: 100%;
}
.flex-none { .flex-none {
flex: none; flex: none;
} }
@ -1739,6 +1777,10 @@ body a, body button {
border-radius: 0.25rem; border-radius: 0.25rem;
} }
.rounded-lg {
border-radius: 0.5rem;
}
.\!rounded-md { .\!rounded-md {
border-radius: 0.375rem !important; border-radius: 0.375rem !important;
} }
@ -1861,6 +1903,11 @@ body a, body button {
padding-bottom: 2rem; padding-bottom: 2rem;
} }
.px-0 {
padding-left: 0px;
padding-right: 0px;
}
.px-2 { .px-2 {
padding-left: 0.5rem; padding-left: 0.5rem;
padding-right: 0.5rem; padding-right: 0.5rem;
@ -2229,6 +2276,10 @@ body a, body button {
margin-left: 0.25rem; margin-left: 0.25rem;
} }
[dir="ltr"] .ltr\:-ml-5 {
margin-left: -1.25rem;
}
[dir="ltr"] .ltr\:block { [dir="ltr"] .ltr\:block {
display: block; display: block;
} }
@ -2241,10 +2292,18 @@ body a, body button {
display: none; display: none;
} }
[dir="ltr"] .ltr\:border-l {
border-left-width: 1px;
}
[dir="ltr"] .ltr\:pr-2 { [dir="ltr"] .ltr\:pr-2 {
padding-right: 0.5rem; padding-right: 0.5rem;
} }
[dir="ltr"] .ltr\:pl-5 {
padding-left: 1.25rem;
}
[dir="ltr"] .ltr\:pr-3 { [dir="ltr"] .ltr\:pr-3 {
padding-right: 0.75rem; padding-right: 0.75rem;
} }
@ -2269,6 +2328,10 @@ body a, body button {
margin-right: 0.25rem; margin-right: 0.25rem;
} }
[dir="rtl"] .rtl\:-mr-5 {
margin-right: -1.25rem;
}
[dir="rtl"] .rtl\:block { [dir="rtl"] .rtl\:block {
display: block; display: block;
} }
@ -2281,10 +2344,18 @@ body a, body button {
display: none; display: none;
} }
[dir="rtl"] .rtl\:border-r {
border-right-width: 1px;
}
[dir="rtl"] .rtl\:pl-2 { [dir="rtl"] .rtl\:pl-2 {
padding-left: 0.5rem; padding-left: 0.5rem;
} }
[dir="rtl"] .rtl\:pr-5 {
padding-right: 1.25rem;
}
[dir="rtl"] .rtl\:pl-3 { [dir="rtl"] .rtl\:pl-3 {
padding-left: 0.75rem; padding-left: 0.75rem;
} }
@ -2413,6 +2484,11 @@ body a, body button {
color: rgba(var(--color-neutral-800), var(--tw-text-opacity)); color: rgba(var(--color-neutral-800), var(--tw-text-opacity));
} }
.dark .dark\:text-neutral-100 {
--tw-text-opacity: 1;
color: rgba(var(--color-neutral-100), var(--tw-text-opacity));
}
.dark .dark\:hover\:border-primary-600:hover { .dark .dark\:hover\:border-primary-600:hover {
--tw-border-opacity: 1; --tw-border-opacity: 1;
border-color: rgba(var(--color-primary-600), var(--tw-border-opacity)); border-color: rgba(var(--color-primary-600), var(--tw-border-opacity));
@ -2530,10 +2606,39 @@ body a, body button {
} }
@media (min-width: 1024px) { @media (min-width: 1024px) {
.lg\:sticky {
position: -webkit-sticky;
position: sticky;
}
.lg\:top-10 {
top: 2.5rem;
}
.lg\:order-last {
order: 9999;
}
.lg\:mt-3 {
margin-top: 0.75rem;
}
.lg\:hidden {
display: none;
}
.lg\:w-1\/4 { .lg\:w-1\/4 {
width: 25%; width: 25%;
} }
.lg\:max-w-xs {
max-width: 20rem;
}
.lg\:flex-row {
flex-direction: row;
}
.lg\:p-\[12vh\] { .lg\:p-\[12vh\] {
padding: 12vh; padding: 12vh;
} }
@ -2542,6 +2647,14 @@ body a, body button {
padding-left: 8rem; padding-left: 8rem;
padding-right: 8rem; padding-right: 8rem;
} }
[dir="ltr"] .ltr\:lg\:pl-8 {
padding-left: 2rem;
}
[dir="rtl"] .rtl\:lg\:pr-8 {
padding-right: 2rem;
}
} }
@media (min-width: 1280px) { @media (min-width: 1280px) {

View File

@ -62,6 +62,21 @@ body button {
@apply rtl:pl-0; @apply rtl:pl-0;
} }
/* Table of Contents */
.toc ul,
.toc li {
@apply px-0 my-1 leading-snug list-none;
}
.toc ul ul {
@apply ltr:pl-4 rtl:pr-4;
}
.toc a {
@apply font-normal text-neutral-700 dark:text-neutral-400;
}
.toc ul > li {
@apply rtl:mr-0;
}
/* -- Chroma Highlight -- */ /* -- Chroma Highlight -- */
/* Background */ /* Background */
.markdown .chroma { .markdown .chroma {

View File

@ -7,3 +7,7 @@
[highlight] [highlight]
noClasses = false noClasses = false
[tableOfContents]
startLevel = 2
endLevel = 4

View File

@ -30,6 +30,7 @@ enableSearch = false
showPagination = true showPagination = true
showReadingTime = true showReadingTime = true
showTaxonomies = false showTaxonomies = false
showTableOfContents = false
showWordCount = false showWordCount = false
# sharingLinks = ["facebook", "twitter", "pinterest", "reddit", "linkedin", "email"] # sharingLinks = ["facebook", "twitter", "pinterest", "reddit", "linkedin", "email"]

View File

@ -7,3 +7,7 @@
[highlight] [highlight]
noClasses = false noClasses = false
[tableOfContents]
startLevel = 2
endLevel = 4

View File

@ -30,6 +30,7 @@ mainSections = ["samples"]
showPagination = true showPagination = true
showReadingTime = true showReadingTime = true
showTaxonomies = false showTaxonomies = false
showTableOfContents = true
showWordCount = false showWordCount = false
# sharingLinks = ["facebook", "twitter", "pinterest", "reddit", "linkedin", "email"] # sharingLinks = ["facebook", "twitter", "pinterest", "reddit", "linkedin", "email"]

View File

@ -6,6 +6,7 @@ article:
one: "{{ .Count }} min" one: "{{ .Count }} min"
other: "{{ .Count }} min" other: "{{ .Count }} min"
reading_time_title: "Lesezeit" reading_time_title: "Lesezeit"
# table_of_contents: "Table of Contents"
# word_count: # word_count:
# one: "{{ .Count }} word" # one: "{{ .Count }} word"
# other: "{{ .Count }} words" # other: "{{ .Count }} words"

View File

@ -6,6 +6,7 @@ article:
one: "{{ .Count }} min" one: "{{ .Count }} min"
other: "{{ .Count }} mins" other: "{{ .Count }} mins"
reading_time_title: "Reading time" reading_time_title: "Reading time"
table_of_contents: "Table of Contents"
word_count: word_count:
one: "{{ .Count }} word" one: "{{ .Count }} word"
other: "{{ .Count }} words" other: "{{ .Count }} words"

View File

@ -6,6 +6,7 @@ article:
one: "{{ .Count }} min" one: "{{ .Count }} min"
other: "{{ .Count }} mins" other: "{{ .Count }} mins"
reading_time_title: "Tiempo de lectura" reading_time_title: "Tiempo de lectura"
# table_of_contents: "Table of Contents"
# word_count: # word_count:
# one: "{{ .Count }} word" # one: "{{ .Count }} word"
# other: "{{ .Count }} words" # other: "{{ .Count }} words"

View File

@ -6,6 +6,7 @@ article:
one: "{{ .Count }} min" one: "{{ .Count }} min"
other: "{{ .Count }} mins" other: "{{ .Count }} mins"
reading_time_title: "Temps de lecture" reading_time_title: "Temps de lecture"
# table_of_contents: "Table of Contents"
# word_count: # word_count:
# one: "{{ .Count }} word" # one: "{{ .Count }} word"
# other: "{{ .Count }} words" # other: "{{ .Count }} words"

View File

@ -6,6 +6,7 @@ article:
one: "{{ .Count }} minuto" one: "{{ .Count }} minuto"
other: "{{ .Count }} minutos" other: "{{ .Count }} minutos"
reading_time_title: "Tempo de leitura" reading_time_title: "Tempo de leitura"
# table_of_contents: "Table of Contents"
# word_count: # word_count:
# one: "{{ .Count }} word" # one: "{{ .Count }} word"
# other: "{{ .Count }} words" # other: "{{ .Count }} words"

View File

@ -5,6 +5,7 @@ article:
reading_time: reading_time:
other: "{{ .Count }} 分钟" other: "{{ .Count }} 分钟"
reading_time_title: "预计阅读" reading_time_title: "预计阅读"
# table_of_contents: "Table of Contents"
word_count: word_count:
one: "{{ .Count }} 字" one: "{{ .Count }} 字"
other: "{{ .Count }} 字" other: "{{ .Count }} 字"

View File

@ -1,6 +1,6 @@
{{ define "main" }} {{ define "main" }}
<article class="max-w-prose"> <article>
<header> <header class="max-w-prose">
{{ if .Site.Params.article.showBreadcrumbs | default false }} {{ if .Site.Params.article.showBreadcrumbs | default false }}
{{ partial "breadcrumbs.html" . }} {{ partial "breadcrumbs.html" . }}
{{ end }} {{ end }}
@ -11,10 +11,19 @@
{{ partial "article-meta.html" (dict "context" . "scope" "single") }} {{ partial "article-meta.html" (dict "context" . "scope" "single") }}
</div> </div>
</header> </header>
<section class="markdown dark:markdown-invert"> <section class="flex flex-col max-w-full mt-0 lg:flex-row markdown dark:markdown-invert">
{{ .Content | emojify }} {{ if and (.Params.showTableOfContents | default (.Site.Params.article.showTableOfContents | default false)) (in .TableOfContents "<ul") }}
<div class="order-first px-0 lg:max-w-xs ltr:lg:pl-8 rtl:lg:pr-8 lg:order-last">
<div class="ltr:pl-5 rtl:pr-5 toc lg:sticky lg:top-10">
{{ partial "toc.html" . }}
</div>
</div>
{{ end }}
<div class="max-w-prose">
{{ .Content | emojify }}
</div>
</section> </section>
<footer class="pt-8"> <footer class="pt-8 max-w-prose">
{{ partial "author.html" . }} {{ partial "author.html" . }}
{{ partial "sharing-links.html" . }} {{ partial "sharing-links.html" . }}
{{ partial "article-pagination.html" . }} {{ partial "article-pagination.html" . }}

View File

@ -0,0 +1,12 @@
<details open class="mt-0 overflow-hidden rounded-lg rtl:pr-5 ltr:pl-5 ltr:-ml-5 rtl:-mr-5 lg:mt-3">
<summary
class="block py-1 text-lg font-semibold rtl:pr-5 ltr:pl-5 ltr:-ml-5 rtl:-mr-5 text-neutral-800 dark:text-neutral-100 lg:hidden bg-neutral-100 dark:bg-neutral-700"
>
{{ i18n "article.table_of_contents" }}
</summary>
<div
class="py-2 border-dotted ltr:border-l rtl:border-r rtl:pr-5 ltr:pl-5 ltr:-ml-5 rtl:-mr-5 border-neutral-300 dark:border-neutral-600"
>
{{ .TableOfContents }}
</div>
</details>