about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorEmilio Ziniades2024-05-12 15:54:40 +0200
committerAlan Pearce2024-05-13 10:32:48 +0000
commitbaabcb634bdffb8623eacc410e8707a3b4afe2b5 (patch)
treecc19bc0ee1fc64ae834c2adac172435e27e4e99e
parent2c9ca00042ec7c1a4da5ad927f19e8849e5ae96c (diff)
downloadzola-bearblog-baabcb634bdffb8623eacc410e8707a3b4afe2b5.tar.lz
zola-bearblog-baabcb634bdffb8623eacc410e8707a3b4afe2b5.tar.zst
zola-bearblog-baabcb634bdffb8623eacc410e8707a3b4afe2b5.zip
feat(table of contents): Add table of contents
This feature is disabled by default, but can be enabled/disabled
globally or per-page.

Zola already provides `page.toc`, this PR simply adds a macro
to recursively render that data in nested `ul`s.

It also establishes some configuration options to display it
and set a maximum headers level.
-rw-r--r--README.md23
-rw-r--r--config.toml6
-rw-r--r--content/zola.md1
-rw-r--r--templates/macros.html12
-rw-r--r--templates/page.html7
-rw-r--r--theme.toml5
6 files changed, 53 insertions, 1 deletions
diff --git a/README.md b/README.md
index 7ebe80b..5152949 100644
--- a/README.md
+++ b/README.md
@@ -73,6 +73,29 @@ The contents of the `index`-page may be changed by editing your `content/_index.
 
 Add a `custom_head.html`-file to your `templates/`-directory. In there you may add a `<style>`-tag, *or* you may add a `<link>`-tag referencing your own `custom.css` (in case you prefer to have a separate `.css`-file). Check out the [`style.html`](https://codeberg.org/alanpearce/zola-bearblog/src/branch/main/templates/style.html)-file to find out which CSS-styles are applied by default.
 
+### Table of contents
+
+Table of contents are not rendered by default. To render them, set `extra.table_of_contents.show = true` in `config.toml`.
+
+The table of contents is rendered inside a `details` element.
+If you want the section to be collapsed on page load, set `extra.table_of_contents.visible_on_load = false`.
+This defaults to `true`.
+
+In addition, `extra.table_of_contents.max_level` can limit the maximum level of headers to show.
+To show only `h1`s, set `max_level = 1`, to show `h1`s and `h2`s, set `max_level = 2`, and so on.
+By default, `max_level` is set to 6, so all headers on the page are shown.
+
+Below is an example of how to configure the table of contents in `config.toml`.
+
+```toml
+[extra.table_of_contents]
+show = true
+max_level = 2
+visible_on_load = false
+```
+
+It can also be toggled on page-by-page basis. Add `extra.hide_table_of_contents = true` to the page's frontmatter to hide the table of contents for that specific page.
+
 ## Issues / Feedback / Contributing
 Please use [Codeberg issues](https://codeberg.org/alanpearce/zola-bearblog/issues) and [Pull Requests](https://codeberg.org/alanpearce/zola-bearblog/pulls).
 
diff --git a/config.toml b/config.toml
index fcb1d61..8927d04 100644
--- a/config.toml
+++ b/config.toml
@@ -45,12 +45,16 @@ highlight_code = true
 date_format="%Y-%m-%d"
 webserver_sends_csp_headers=true
 language_switcher=true
-
 translations = [
   { code="en", name="English" },
   { code="de", name="Deutsch" },
 ]
 
+[extra.table_of_contents]
+show=true
+max_level=2
+visible_on_load=true
+
 [[extra.main_menu]]
 name = "Home"
 name_de = "Startseite"
diff --git a/content/zola.md b/content/zola.md
index 5458750..bbce998 100644
--- a/content/zola.md
+++ b/content/zola.md
@@ -1,5 +1,6 @@
 +++
 title = "Zola"
+extra.hide_table_of_contents = true
 +++
 ## No dependencies
 
diff --git a/templates/macros.html b/templates/macros.html
new file mode 100644
index 0000000..2ad23e6
--- /dev/null
+++ b/templates/macros.html
@@ -0,0 +1,12 @@
+{% macro table_of_contents(toc, max_level) %}
+<ul>
+  {% for header in toc %}
+    <li>
+      <a href="{{ header.permalink | safe }}">{{ header.title }}</a>
+        {% if header.children and header.level < max_level %}
+          {{ self::table_of_contents(toc=header.children, max_level=max_level) }}
+        {% endif %}
+    </li>
+  {% endfor %}
+</ul>
+{% endmacro %}
diff --git a/templates/page.html b/templates/page.html
index 5c1a80b..2e2ef86 100644
--- a/templates/page.html
+++ b/templates/page.html
@@ -1,3 +1,4 @@
+{% import "macros.html" as macros %}
 {% extends "base.html" %}
 
 {% block title %}{{ page.title }} | {{ super() }}{% endblock %}
@@ -15,6 +16,12 @@
       </p>
     {%- endif %}
   {%- endif %}
+  {%- if config.extra.table_of_contents.show and not page.extra.hide_table_of_contents and page.toc %}
+    <details {%if config.extra.table_of_contents.visible_on_load %}open{% endif %}>
+      <summary>Table of Contents</summary>
+      {{ macros::table_of_contents(toc=page.toc, max_level=config.extra.table_of_contents.max_level) }}
+    </details>
+  {%- endif %}
   <main>
     {{ page.content | safe }}
   </main>
diff --git a/theme.toml b/theme.toml
index 902c8ec..894f7fa 100644
--- a/theme.toml
+++ b/theme.toml
@@ -15,6 +15,11 @@ demo = "https://zola-bearblog.netlify.app/"
 date_format="%d %b, %Y"
 webserver_sends_csp_headers=false
 
+[extra.table_of_contents]
+show=false
+max_level=6
+visible_on_load=true
+
 [author]
 name = "Alan Pearce"
 homepage = "https://alanpearce.eu"