Last active
December 22, 2023 20:27
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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(""); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can maintain the original order/hierarchy by changing this to
document.querySelectorAll("h1, h2, h3, h4, h5, h6")
instead of sorting bygetBoundingClientRect()