Skip to content

Instantly share code, notes, and snippets.

@MatthewCallis
Created January 5, 2022 00:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MatthewCallis/99b440a0e1231f6b328dd0f3a3fcb88d to your computer and use it in GitHub Desktop.
Save MatthewCallis/99b440a0e1231f6b328dd0f3a3fcb88d to your computer and use it in GitHub Desktop.
Table of Contents Generator
const tableOfContents = (options) => {
if (!options.element) {
return;
}
const container = options.container ? document.querySelector(options.container) : document.body;
const selectors = options.selectors ? options.selectors.split(',').map((s) => s.trim()) : ['h2', 'h3'];
const tocItems = [];
// Building dict
let i = 1;
selectors.forEach((selector) => {
const items = container.querySelectorAll(selector);
items.forEach((item) => {
const index = item.id || `toc-${i++}`;
const text = item.textContent.trim();
const className = selector.replace(/((:+[\w-\d]*)|[^\d\s-A-z])/g, ' ').replace(/\s{2,}/g, ' ').trim();
// Set it if none
if (item.id !== index) {
item.id = index;
}
tocItems.push({ index, text, className });
});
});
// Building markup
if (tocItems.length > 0) {
let html = '<ul>';
tocItems.forEach((item, j) => {
html += `\n<li class="toc-li-${j} toc-${item.className}"><a href="${window.location.pathname}#${item.index}">${item.text}</a></li>`;
});
html += '</ul>';
document.querySelector(options.element).innerHTML = html;
} else {
document.querySelector(options.element).style.display = 'none';
}
if (window.location.hash) {
const element = document.querySelector(window.location.hash);
if (element) {
setTimeout(() => {
element.scrollIntoView();
}, 500);
}
}
};
document.addEventListener('DOMContentLoaded', () => {
tableOfContents({
element: '.toc',
container: 'article',
selectors: 'h1,h2,h3',
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment