Skip to content

Instantly share code, notes, and snippets.

@pkcpkc
Last active December 22, 2023 20:27
Show Gist options
  • Save pkcpkc/e1e1dd20bd2ccac11eae490f7e1bf1fd to your computer and use it in GitHub Desktop.
Save pkcpkc/e1e1dd20bd2ccac11eae490f7e1bf1fd to your computer and use it in GitHub Desktop.
JavaScript: HTML heading Table of Contents: Generate a navigatable, stylable table of contents based on the heading structure of an html document
/*
Collect headers (h1, h2, ..., hx) from html and generates navigatable, stylable table of contents.
@param maxHeaderLevel int Define header level depth, defaults to 3.
@param styleItem function Function that accepts text:string, level:int and itemAnchor:string to style toc entry, default renderer is set already (check source for usage).
@return string HTML table of contents
*/
function generateTableOfContents(maxHeaderLevel = 3, styleItem = function (text, level, itemAnchor) {
var spaces = " ".repeat(Math.max(0, (level - 1)) * 3);
var tocEntry = spaces + '<a href="#' + itemAnchor + '">' + text + '</a><br/>';
return tocEntry;
}) {
var headers = [];
for (var i = 0; i < maxHeaderLevel; i++) {
for (var element of document.getElementsByTagName("h" + i)) {
headers.push(element);
}
}
headers.sort(function (a, b) {
return a.getBoundingClientRect().y - b.getBoundingClientRect().y;
});
headers = headers.map(function (element) {
var tocElementId = 'toc-' + Math.random(Number.MAX_VALUE);
var styledItem = styleItem(element.innerHTML, element.tagName.substring(1), tocElementId);
element.innerHTML = '<a name="' + tocElementId + '" href="#"></a>' + element.innerHTML;
return styledItem;
});
return headers.join("");
}
@zackbiernat
Copy link

zackbiernat commented Dec 12, 2022

You can maintain the original order/hierarchy by changing this to document.querySelectorAll("h1, h2, h3, h4, h5, h6") instead of sorting by getBoundingClientRect()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment