feat: add link button to toggle TOC items

This commit is contained in:
Mark Dumay
2025-08-15 09:52:20 +02:00
parent 3332b437dd
commit a57e0da164
8 changed files with 171 additions and 152 deletions

13
assets/js/toc.js Normal file
View File

@@ -0,0 +1,13 @@
const btnTOCShowMore = document.getElementById('btnTOCShowMore')
if (btnTOCShowMore !== null) {
btnTOCShowMore.addEventListener('click', (e) => {
btnTOCShowMore.style.display = 'none'
})
}
const btnTOCShowLess = document.getElementById('btnTOCShowLess')
if ((btnTOCShowLess !== null) && (btnTOCShowMore !== null)) {
btnTOCShowLess.addEventListener('click', (e) => {
btnTOCShowMore.style.display = 'initial'
})
}

View File

@@ -74,6 +74,14 @@
}
}
.btn-link.toc-item {
font-size: inherit;
}
#btnTOCShowMore {
padding-top: 0.875rem;
}
a.toc-item {
display: block;
}

View File

@@ -97,6 +97,9 @@
toc = true
sidebar = true
size = "md"
startLevel = 2
endLevel = 3
maxNumHeadings = 9
[navigation.padding]
x = 4
y = 4

View File

@@ -51,6 +51,9 @@
toc = true
sidebar = true
size = "md"
startLevel = 2
endLevel = 3
maxNumHeadings = 9
[navigation.padding]
x = 4
y = 4

View File

@@ -616,6 +616,8 @@
"body-file-collapse-1",
"bouton",
"breadcrumb",
"btnTOCShowLess",
"btnTOCShowMore",
"button",
"button-group",
"c4-diagram",
@@ -642,11 +644,11 @@
"docs",
"documentation",
"dropdown-nav-0",
"dropdown-panel-2a268a8b3931b61a7583f392002008fe",
"dropdown-panel-5bf6f23e5fc93f9c342a4b0a1b32b838",
"dropdown-panel-8cd9607610b5a8fff779d38787437e7e",
"dropdown-panel-93636449c1ef8ec23d583052c9fe7a4b",
"dropdown-panel-a97ffb4aaea3a2e4aa01b1ce556dd275",
"dropdown-panel-084bf092239e5f25a71841b46134e2b5",
"dropdown-panel-09e05d29554c47c7d092c3c332e8ab42",
"dropdown-panel-5acf6806020477b731604b7c3506126d",
"dropdown-panel-6bdf123559ba44e375634c7e5392b912",
"dropdown-panel-d09398439fd994d4aafbc4a3a9c28bf2",
"elements-type",
"entity-relationship-diagram",
"example",
@@ -664,11 +666,11 @@
"fab-medium",
"fab-whatsapp",
"fab-x-twitter",
"faq-a69e21a1b0b61dac8b322b1d68137cc6",
"faq-a69e21a1b0b61dac8b322b1d68137cc6-heading-faq-a69e21a1b0b61dac8b322b1d68137cc6",
"faq-a69e21a1b0b61dac8b322b1d68137cc6-item-0",
"faq-a69e21a1b0b61dac8b322b1d68137cc6-item-1",
"faq-a69e21a1b0b61dac8b322b1d68137cc6-item-2",
"faq-c3e9e2ab69a8c88825f39038d15bc04f",
"faq-c3e9e2ab69a8c88825f39038d15bc04f-heading-faq-c3e9e2ab69a8c88825f39038d15bc04f",
"faq-c3e9e2ab69a8c88825f39038d15bc04f-item-0",
"faq-c3e9e2ab69a8c88825f39038d15bc04f-item-1",
"faq-c3e9e2ab69a8c88825f39038d15bc04f-item-2",
"fas-1",
"fas-2",
"fas-3",
@@ -760,11 +762,11 @@
"nav-0-btn-1",
"nav-0-btn-2",
"nav-nav-0",
"nav-panel-2a268a8b3931b61a7583f392002008fe",
"nav-panel-5bf6f23e5fc93f9c342a4b0a1b32b838",
"nav-panel-8cd9607610b5a8fff779d38787437e7e",
"nav-panel-93636449c1ef8ec23d583052c9fe7a4b",
"nav-panel-a97ffb4aaea3a2e4aa01b1ce556dd275",
"nav-panel-084bf092239e5f25a71841b46134e2b5",
"nav-panel-09e05d29554c47c7d092c3c332e8ab42",
"nav-panel-5acf6806020477b731604b7c3506126d",
"nav-panel-6bdf123559ba44e375634c7e5392b912",
"nav-panel-d09398439fd994d4aafbc4a3a9c28bf2",
"navbar",
"navbar-0-collapse",
"navbar-mode",
@@ -773,36 +775,36 @@
"navigation",
"notification",
"overview",
"panel-2a268a8b3931b61a7583f392002008fe-0",
"panel-2a268a8b3931b61a7583f392002008fe-1",
"panel-2a268a8b3931b61a7583f392002008fe-2",
"panel-2a268a8b3931b61a7583f392002008fe-btn-0",
"panel-2a268a8b3931b61a7583f392002008fe-btn-1",
"panel-2a268a8b3931b61a7583f392002008fe-btn-2",
"panel-5bf6f23e5fc93f9c342a4b0a1b32b838-0",
"panel-5bf6f23e5fc93f9c342a4b0a1b32b838-1",
"panel-5bf6f23e5fc93f9c342a4b0a1b32b838-2",
"panel-5bf6f23e5fc93f9c342a4b0a1b32b838-btn-0",
"panel-5bf6f23e5fc93f9c342a4b0a1b32b838-btn-1",
"panel-5bf6f23e5fc93f9c342a4b0a1b32b838-btn-2",
"panel-8cd9607610b5a8fff779d38787437e7e-0",
"panel-8cd9607610b5a8fff779d38787437e7e-1",
"panel-8cd9607610b5a8fff779d38787437e7e-2",
"panel-8cd9607610b5a8fff779d38787437e7e-btn-0",
"panel-8cd9607610b5a8fff779d38787437e7e-btn-1",
"panel-8cd9607610b5a8fff779d38787437e7e-btn-2",
"panel-93636449c1ef8ec23d583052c9fe7a4b-0",
"panel-93636449c1ef8ec23d583052c9fe7a4b-1",
"panel-93636449c1ef8ec23d583052c9fe7a4b-2",
"panel-93636449c1ef8ec23d583052c9fe7a4b-btn-0",
"panel-93636449c1ef8ec23d583052c9fe7a4b-btn-1",
"panel-93636449c1ef8ec23d583052c9fe7a4b-btn-2",
"panel-a97ffb4aaea3a2e4aa01b1ce556dd275-0",
"panel-a97ffb4aaea3a2e4aa01b1ce556dd275-1",
"panel-a97ffb4aaea3a2e4aa01b1ce556dd275-2",
"panel-a97ffb4aaea3a2e4aa01b1ce556dd275-btn-0",
"panel-a97ffb4aaea3a2e4aa01b1ce556dd275-btn-1",
"panel-a97ffb4aaea3a2e4aa01b1ce556dd275-btn-2",
"panel-084bf092239e5f25a71841b46134e2b5-0",
"panel-084bf092239e5f25a71841b46134e2b5-1",
"panel-084bf092239e5f25a71841b46134e2b5-2",
"panel-084bf092239e5f25a71841b46134e2b5-btn-0",
"panel-084bf092239e5f25a71841b46134e2b5-btn-1",
"panel-084bf092239e5f25a71841b46134e2b5-btn-2",
"panel-09e05d29554c47c7d092c3c332e8ab42-0",
"panel-09e05d29554c47c7d092c3c332e8ab42-1",
"panel-09e05d29554c47c7d092c3c332e8ab42-2",
"panel-09e05d29554c47c7d092c3c332e8ab42-btn-0",
"panel-09e05d29554c47c7d092c3c332e8ab42-btn-1",
"panel-09e05d29554c47c7d092c3c332e8ab42-btn-2",
"panel-5acf6806020477b731604b7c3506126d-0",
"panel-5acf6806020477b731604b7c3506126d-1",
"panel-5acf6806020477b731604b7c3506126d-2",
"panel-5acf6806020477b731604b7c3506126d-btn-0",
"panel-5acf6806020477b731604b7c3506126d-btn-1",
"panel-5acf6806020477b731604b7c3506126d-btn-2",
"panel-6bdf123559ba44e375634c7e5392b912-0",
"panel-6bdf123559ba44e375634c7e5392b912-1",
"panel-6bdf123559ba44e375634c7e5392b912-2",
"panel-6bdf123559ba44e375634c7e5392b912-btn-0",
"panel-6bdf123559ba44e375634c7e5392b912-btn-1",
"panel-6bdf123559ba44e375634c7e5392b912-btn-2",
"panel-d09398439fd994d4aafbc4a3a9c28bf2-0",
"panel-d09398439fd994d4aafbc4a3a9c28bf2-1",
"panel-d09398439fd994d4aafbc4a3a9c28bf2-2",
"panel-d09398439fd994d4aafbc4a3a9c28bf2-btn-0",
"panel-d09398439fd994d4aafbc4a3a9c28bf2-btn-1",
"panel-d09398439fd994d4aafbc4a3a9c28bf2-btn-2",
"persona",
"pie-chart",
"pills",
@@ -839,6 +841,7 @@
"toast-example-2",
"toast-message-email-4",
"toc-collapse",
"toc-collapse-items",
"tooltip",
"types-de-cookies-que-nous-utilisons",
"types-of-cookies-we-use",

View File

@@ -101,6 +101,10 @@
translation: "See also"
- id: sectionMenu
translation: "Select a topic"
- id: tocShowMore
translation: "Show {{ . }} more"
- id: tocShowLess
translation: "Show less"
# Sidebar
- id: toggleSidebar

View File

@@ -99,6 +99,10 @@
translation: "Zie ook"
- id: sectionMenu
translation: "Selecteer een onderwerp"
- id: tocShowMore
translation: "Toon {{ . }} meer"
- id: tocShowLess
translation: "Toon minder"
# Sidebar
- id: toggleSidebar

View File

@@ -1,107 +1,88 @@
{{- /*
Copyright 2023 Veriphor, LLC
Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy of
the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations under
the License.
*/}}
{{- /*
Renders a table of contents by parsing rendered content.
In site configuration, set the default start level, end level, and the minimum
number of headings required to show the table of contents:
[params.toc]
startLevel = 2 # default is 2
endLevel = 3 # default is 3
minNumHeadings = 2 # default is 2
To display the table of contents on a page:
+++
title = 'Post 1'
toc = true
+++
To display the table of contents on a page, and override one or more of the
default settings:
+++
title = 'Post 1'
[toc]
startLevel = 2 # default is 2
endLevel = 3 # default is 3
minNumHeadings = 2 # default is 2
+++
Change or localize the title with a "toc_title" key in your i18n file(s).
Start with these basic CSS rules to style the table of contents:
a.toc-item {
display: block;
}
a.toc-level-1 {
margin-left: 0em;
}
a.toc-level-2 {
margin-left: 1em;
}
a.toc-level-3 {
margin-left: 2em;
}
a.toc-level-4 {
margin-left: 3em;
}
a.toc-level-5 {
margin-left: 4em;
}
a.toc-level-6 {
margin-left: 5em;
}
@context {page} .
@returns {template.HTML}
@example {{ partial "toc-parse-content.html" . }}
*/}}
{{- /* Get configuration. */}}
{{- $startLevel := or (.Site.Params.navigation.startLevel | int) 2 }}
{{- $endLevel := or (.Site.Params.navigation.endLevel | int) 3 }}
{{- $minNumHeadings := or (.Site.Params.navigation.minNumHeadings | int) 2 }}
{{- /* Initialize. */}}
{{ $headings := partial "assets/toc-headings.html" . }}
{{- /* Render */}}
{{- if .Site.Params.navigation.toc }}
{{- with $headings }}
{{- if ge (len .) $minNumHeadings }}
<strong class="d-block h6 my-2 pt-4">{{ T "toc" }}:</strong>
<nav class="toc">
{{- range . }}
{{- $attrs := dict "class" (printf "toc-item toc-level-%d" (add 1 (sub .level $startLevel))) }}
{{- with .id }}
{{- $attrs = merge $attrs (dict "href" (printf "%s#%s" $.RelPermalink .)) }}
{{- end }}
<a
{{- range $k, $v := $attrs }}
{{- printf " %s=%q" $k $v | safeHTMLAttr }}
{{- end -}}
>{{ .text }}</a>
{{- end }}
</nav>
{{- end }}
{{- end }}
{{- end }}
{{/*
Copyright © 2025 The Hinode Team / Mark Dumay. All rights reserved.
Use of this source code is governed by The MIT License (MIT) that can be found in the LICENSE file.
Visit gethinode.com/license for more details.
*/}}
{{ define "_partials/inline/toc-item.html" }}
{{ $base := .base }}
{{ $startLevel := .startLevel }}
{{ $endLevel := .endLevel }}
{{ $item := .item }}
{{ $maxNumHeadings := .maxNumHeadings }}
{{ $result := .result | default slice }}
{{ if and (ge $item.Level $startLevel) (le $item.Level $endLevel) }}
{{- $attrs := dict "class" (printf "toc-item toc-level-%d" (add 1 (sub $item.Level $startLevel))) }}
{{- with $item.ID }}
{{- $attrs = merge $attrs (dict "href" (printf "%s#%s" $base .)) }}
{{- end }}
{{ $htmlAttr := "" }}
{{ range $k, $v := $attrs }}{{ $htmlAttr = printf "%s %s=%q" $htmlAttr $k $v | safeHTMLAttr }}{{ end }}
{{ $rendered := printf "<a %s>%s</a>" $htmlAttr $item.Title }}
{{ $result = $result | append $rendered }}
{{ end }}
{{ range $item.Headings }}
{{ $result = $result | append (partial "inline/toc-item.html" (dict
"base" $base
"item" .
"startLevel" $startLevel
"endLevel" $endLevel
"maxNumHeadings" $maxNumHeadings
)) }}
{{ end }}
{{ return $result }}
{{ end }}
{{- /* Get configuration. */}}
{{- $startLevel := or (.Site.Params.navigation.startLevel | int) 2 }}
{{- $endLevel := or (.Site.Params.navigation.endLevel | int) 3 }}
{{- $minNumHeadings := or (.Site.Params.navigation.minNumHeadings | int) 2 }}
{{- $maxNumHeadings := or (.Site.Params.navigation.maxNumHeadings | int) 9 }}
{{- /* Render */}}
{{- if and .Site.Params.navigation.toc (ge (len .Fragments.HeadingsMap) $minNumHeadings) }}
<strong class="d-block h6 my-2 pt-4">{{ T "toc" }}:</strong>
<nav class="toc">
{{ $result := slice }}
{{ range .Fragments.Headings }}
{{ $result = $result | append (partial "inline/toc-item.html" (dict
"base" $.RelPermalink
"item" .
"startLevel" $startLevel
"endLevel" $endLevel
"maxNumHeadings" $maxNumHeadings
)) }}
{{ end }}
{{ range $i, $v := $result }}
{{ if eq $i $maxNumHeadings }}
{{ partial "assets/button.html" (dict
"id" "btnTOCShowMore"
"collapse-id" "toc-collapse-items"
"link-type" "link"
"class" "toc-item"
"title" (T "tocShowMore" (sub (len $result) $i))
"spacing" false
) }}
<div class="collapse" id="toc-collapse-items">
{{ end }}
{{ print $v | safeHTML }}
{{ end }}
{{ if gt (len $result) $maxNumHeadings }}
&nbsp;
{{ partial "assets/button.html" (dict
"id" "btnTOCShowLess"
"collapse-id" "toc-collapse-items"
"link-type" "link"
"class" "toc-item"
"title" (T "tocShowLess")
"spacing" false
) }}
</div>{{ end }}
</nav>
{{ end }}