From 53677f19d8b81fb161421d1ba57bb570498c264b Mon Sep 17 00:00:00 2001
From: Steven Engler <sengler@uwaterloo.ca>
Date: Thu, 12 Sep 2019 17:14:59 -0400
Subject: [PATCH] Added optional page table of contents

You can use the 'tableofcontents' front matter option to enable or
disable the display of a table of contents. Setting this option will
override the new site-wide parameter 'tableofcontentswordcount' which
will automatically add a table of contents on pages with more than
the specified number of words. Set to '0' to always show a table of
contents, or set to '-1' to never show a table of contents (the
default behaviour).
---
 layouts/_default/single.html | 16 ++++++++++++++++
 static/css/styles.css        | 32 ++++++++++++++++++++++++++++++++
 static/css/themes/dark.css   |  5 +++++
 static/css/themes/light.css  |  5 +++++
 4 files changed, 58 insertions(+)

diff --git a/layouts/_default/single.html b/layouts/_default/single.html
index f719484..cc72110 100644
--- a/layouts/_default/single.html
+++ b/layouts/_default/single.html
@@ -11,5 +11,21 @@
       {{- end }}
     </div>
   </div>
+  {{ if or (.Params.tableofcontents) (and (ne .Params.tableofcontents false) (isset .Site.Params "tableofcontentswordcount") (ge .Site.Params.TableOfContentsWordCount 0) (gt .WordCount .Site.Params.TableOfContentsWordCount)) }}
+    {{/* If the front matter parameter is true, show the toc */}}
+    {{/* Elif the front matter parameter is false, don't show the toc */}}
+    {{/* Elif the front matter parameter is not set, show the toc if the site parameter is set, non-negative, and less than the word count */}}
+    <div class="table-of-contents">
+      <details open="open">
+        <summary>
+          <span class="table-of-contents-title">Table of Contents</span>
+        </summary>
+        {{ $toc := .TableOfContents -}}
+        {{- $toc := replaceRE `<ul>\s?<li>\s?<ul>` `<ul>` $toc -}}
+        {{- $toc := replaceRE `</ul>\s?</li>\s?</ul>` `</ul>` $toc -}}
+        {{- safeHTML $toc }}
+      </details>
+    </div>
+  {{ end }}
   {{ .Content }}
 {{ end }}
diff --git a/static/css/styles.css b/static/css/styles.css
index 60d4d98..df956ef 100644
--- a/static/css/styles.css
+++ b/static/css/styles.css
@@ -112,6 +112,38 @@ blockquote {
 	font-size: 80%;
 }
 
+.table-of-contents {
+	border-width: 2px;
+	border-style: solid;
+	padding: 1em;
+	margin-bottom: 2em;
+	font-size: 0.9em;
+}
+
+.table-of-contents nav > ul {
+	/* only the most-parent ul element */
+	margin-bottom: 0;
+}
+
+.table-of-contents ul {
+	list-style: none;
+	padding-left: 0;
+}
+
+.table-of-contents li {
+	margin-top: 0.8em;
+}
+
+.table-of-contents ul ul {
+	list-style: none;
+	padding-left: 1.5em;
+}
+
+.table-of-contents-title {
+	font-size: 1.2em;
+	font-weight: bold;
+}
+
 .links {
 	font-size: 120%;
 	list-style-type: none;
diff --git a/static/css/themes/dark.css b/static/css/themes/dark.css
index 47724b0..a05523e 100644
--- a/static/css/themes/dark.css
+++ b/static/css/themes/dark.css
@@ -53,6 +53,11 @@ blockquote {
 	color: rgb(150, 150, 150);
 }
 
+.table-of-contents {
+	border-color: #505050;
+	background-color: #1A1A1A;
+}
+
 @media only screen and (max-width: 400pt) {
 	.links {
 		background-color: rgb(30, 30, 30);
diff --git a/static/css/themes/light.css b/static/css/themes/light.css
index 4696842..93c5796 100644
--- a/static/css/themes/light.css
+++ b/static/css/themes/light.css
@@ -37,3 +37,8 @@ blockquote {
 .footer {
 	color: #383838;
 }
+
+.table-of-contents {
+	border-color: #E0E0E0;
+	background-color: #FAFAFA;
+}