“Improve” the table of contents generator
-
January 5, 2021 at 10:12 am #4953[anonymous]
Hello everyone, happy new year.
I was wondering if it would be possible for them to add the html details and summary tags to generate the table of contents within the article. I do not know if it contributes any semantic value to the structure (I am not an expert) the plus of hiding and expanding the content of the toc is a good thing and with a little css it could be styled to give it a better visual appearance.
<summary>: The Disclosure Summary element
If this is not possible, could you tell me which files I should modify to implement it on my own.
Thank you.
January 11, 2021 at 8:54 pm #4986[anonymous]In your theme templates. For example, post.hbs.
January 12, 2021 at 8:49 am #4988[anonymous]Hi cumlaude, happpy new year to you too!
Curiously, this very morning I found myself in the same situation as yours, looking for a way to restyle my blog’s tables of content and make them more semantically meaningful.
Beware that this is a quick and dirty solution…The proper way would be to attach some script to the rendering process that wold be notified when the toc is being renderend thus being able to change its layout. Actually I don’t know if that’s even possible yet!
So here it goes…
Provided that you already have your “default” toc placed inside your posts, you can change your post.hbs file and do the following:
<!-- Replace the following --> {{{ text }}} <!-- With this --> {{{ addCustomToc text }}}
add then, append the “addCustomToc” helper code to your helpers.js file as follows:
/* * Custom theme helpers for Handlebars.js */ const htmlParser = require("node-html-parser"); let themeHelpers = { addCustomToc: function (postHtml) { const parsedHtml = htmlParser.parse(postHtml); const defaultToc = parsedHtml.querySelector(".post__toc"); defaultToc.insertAdjacentHTML("afterend", customTocHtml(defaultToc).toString()); defaultToc.remove(); return parsedHtml.toString(); } }; const customTocHtml = function (defaultToc) { const summary = defaultToc.querySelector("h3") ? ` <summary class="toc__sumary" title="Click to expand"> ${defaultToc.querySelector("h3").toString()} </summary> ` : ""; return ` <nav class="toc"> <details> ${summary} <ol> ${defaultToc .querySelectorAll("li") .map((item) => { return ``; }) .join("")} </ol> </details> </nav> `; }; module.exports = themeHelpers;
January 12, 2021 at 8:58 am #4990[anonymous]const customTocHtml = function (defaultToc) { const summary = defaultToc.querySelector("h3") ? ` <summary class="toc__sumary" title="Click to expand"> ${defaultToc.querySelector("h3").toString()} </summary> ` : ""; return ` <nav class="toc"> <details> ${summary} <ol> ${defaultToc .querySelectorAll("li") .map((item) => { return `
- ${ item.rawText }
`; }) .join("")} </ol> </details> </nav> `; };This is correct…😅
January 12, 2021 at 6:39 pm #4996[anonymous]That seems like an overly complicated solution. If you want your toc to be inside a <details> element, edit the template .hbs file where that toc appears. I don’t have a theme that generates a toc, so I’m guessing that there’s a handlebars tag of some sort, maybe {{ toc }}? So if your template is currently
{{ toc }}change it to this:
<details> <summary>view table of contents</summary> {{ toc }} </details>
That’s really all you need to do. If your template has more granular control, say something like this which I found in a “knowledge based theme”:
<h2>table of contents</h2> {{ toc }}then change it to this:
<details class="post__toc"> <summary>table of contents</summary> {{ toc }} </details>
If the handlebars table-of-contents tag is different, or if your template is different, you can almost certainly adapt it to a <details> element. Feel free to show what is currently in your .hbs files that generates the toc and I’ll have a look.
January 19, 2021 at 3:04 pm #5057[anonymous][anonymous] wrote:That seems like an overly complicated solution. If you want your toc to be inside a <details> element, edit the template .hbs file where that toc appears. I don’t have a theme that generates a toc, so I’m guessing that there’s a handlebars tag of some sort, maybe {{ toc }}? So if your template is currently
<span class=”enlighter-g1″><</span><span class=”enlighter-text”>div</span><span class=”enlighter-g1″>></span><span class=”enlighter-g1″>{{</span><span class=”enlighter-text”> toc </span><span class=”enlighter-g1″>}}</span><span class=”enlighter-g1″><</span><span class=”enlighter-text”>/div</span><span class=”enlighter-g1″>></span>{{ toc }}{{ toc }}change it to this:
<span class=”enlighter-g1″><</span><span class=”enlighter-text”>details</span><span class=”enlighter-g1″>></span><span class=”enlighter-g1″><</span><span class=”enlighter-text”>summary</span><span class=”enlighter-g1″>></span><span class=”enlighter-text”>view table </span><span class=”enlighter-k1″>of</span><span class=”enlighter-text”> contents</span><span class=”enlighter-g1″><</span><span class=”enlighter-text”>/summary</span><span class=”enlighter-g1″>></span><span class=”enlighter-g1″>{{</span><span class=”enlighter-text”> toc </span><span class=”enlighter-g1″>}}</span><span class=”enlighter-g1″><</span><span class=”enlighter-text”>/details</span><span class=”enlighter-g1″>></span><details> <summary>view table of contents</summary> {{ toc }} </details><details> <summary>view table of contents</summary> {{ toc }} </details> That’s really all you need to do. If your template has more granular control, say something like this which I found in a “knowledge based theme”:
<span class=”enlighter-g1″><</span><span class=”enlighter-text”>div </span><span class=”enlighter-k1″>class</span><span class=”enlighter-text”>=</span><span class=”enlighter-s0″>”post__toc”</span><span class=”enlighter-g1″>></span><span class=”enlighter-g1″><</span><span class=”enlighter-text”>h2</span><span class=”enlighter-g1″>></span><span class=”enlighter-text”>table </span><span class=”enlighter-k1″>of</span><span class=”enlighter-text”> contents</span><span class=”enlighter-g1″><</span><span class=”enlighter-text”>/h2</span><span class=”enlighter-g1″>></span><span class=”enlighter-g1″>{{</span><span class=”enlighter-text”> toc </span><span class=”enlighter-g1″>}}</span><span class=”enlighter-g1″><</span><span class=”enlighter-text”>/div</span><span class=”enlighter-g1″>></span><h2>table of contents</h2> {{ toc }}<h2>table of contents</h2> {{ toc }}then change it to this:
<span class=”enlighter-g1″><</span><span class=”enlighter-text”>details </span><span class=”enlighter-k1″>class</span><span class=”enlighter-text”>=</span><span class=”enlighter-s0″>”post__toc”</span><span class=”enlighter-g1″>></span><span class=”enlighter-g1″><</span><span class=”enlighter-text”>summary</span><span class=”enlighter-g1″>></span><span class=”enlighter-text”>table </span><span class=”enlighter-k1″>of</span><span class=”enlighter-text”> contents</span><span class=”enlighter-g1″><</span><span class=”enlighter-text”>/summary</span><span class=”enlighter-g1″>></span><span class=”enlighter-g1″>{{</span><span class=”enlighter-text”> toc </span><span class=”enlighter-g1″>}}</span><span class=”enlighter-g1″><</span><span class=”enlighter-text”>/details</span><span class=”enlighter-g1″>></span><details class=”post__toc”> <summary>table of contents</summary> {{ toc }} </details><details class=”post__toc”> <summary>table of contents</summary> {{ toc }} </details> If the handlebars table-of-contents tag is different, or if your template is different, you can almost certainly adapt it to a <details> element. Feel free to show what is currently in your .hbs files that generates the toc and I’ll have a look.
I use the TechNews theme, I searched all the hbs files and found nothing that refers to the tables of contents. I guess it’s Publii’s core that generates that element.
Thanks for your answers.
January 19, 2021 at 3:24 pm #5058BobThe TOC is generated by Tiny WYSIWYG and by Block Editor, there is no easy way to change its structure. @ kettleblaze shows how this can be done.
An ordered list is the right and semantic HTML element used to generate the table of contents; I really don’t see any benefit in changing its HTML structure.