Last active
April 27, 2021 13:39
-
-
Save SJongeJongeJonge/c6c92707e70f60a0c3187b4e70bd3215 to your computer and use it in GitHub Desktop.
devhints.io TOC userscript
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
// ==UserScript== | |
// @name devhints.io TOC | |
// @description 26-4-2021 23:12:54 Adds a table of contents to the devhint cheatsheets. | |
// @version 1.0 | |
// @author SJongeJongeJonge | |
// @match http*://devhints.io/* | |
// @exclude http*://devhints.io/ | |
// @run-at document-end | |
// @grant none | |
// @downloadURL https://gist.github.com/SJongeJongeJonge/c6c92707e70f60a0c3187b4e70bd3215/raw/devhints-toc-userscript.js | |
// @updateURL https://gist.github.com/SJongeJongeJonge/c6c92707e70f60a0c3187b4e70bd3215/raw/devhints-toc-userscript.js | |
// @supportURL https://gist.github.com/SJongeJongeJonge/c6c92707e70f60a0c3187b4e70bd3215#comments | |
// ==/UserScript== | |
// TODO: make toc-list an actual list element | |
// TODO: make toc a nav element | |
const css = ` | |
#toc { | |
position: fixed; | |
margin-left: 3em; | |
} | |
#toc h2 { | |
color: #89a; | |
} | |
.toc-list > a { | |
display: block; | |
line-height: 2em; | |
} | |
` | |
let createStyleNode = cssText => { | |
let elem = document.createElement('style') | |
elem.innerText = cssText | |
return elem | |
} | |
let getAnchorRef = anchor => anchor.href | |
let getSectionName = anchor => anchor.parentElement.textContent | |
let sectionFromElem = elem => ({ 'name': getSectionName(elem), 'href': getAnchorRef(elem) }) | |
let shouldRemoveFirstSection = anchors => { | |
if (anchors.length < 1) return false | |
return !anchors[0] | |
.parentElement | |
.parentElement | |
.classList | |
.contains('-no-hide') | |
} | |
let createTOCItem = ({name, href}) => { | |
let elem = document.createElement('a') | |
elem.textContent = name | |
elem.href = href | |
return elem | |
} | |
let createTOCBase = () => { | |
let base = document.createElement('div') | |
base.id = 'toc' | |
let title = document.createElement('h2') | |
title.innerText = "Table of Contents" | |
base.appendChild(title) | |
return base | |
} | |
let createTOCList = () => { | |
let elem = document.createElement('div') | |
elem.classList.add('toc-list') | |
return elem | |
} | |
let main = () => { | |
let topNavs = document.getElementsByClassName('top-nav') | |
let anchors = document.getElementsByClassName('anchor') | |
let sections = [{ name: '#Top', href: '#'}] | |
for (elem of anchors) { | |
sections.push(sectionFromElem(elem)) | |
} | |
if (shouldRemoveFirstSection(anchors)) { | |
sections.splice(1, 1) | |
} | |
let tocBase = createTOCBase() | |
let tocList = createTOCList() | |
sections.map(createTOCItem) | |
.forEach(elem => tocList.appendChild(elem)) | |
tocBase.appendChild(tocList) | |
if (topNavs.length === 0) { | |
console.error('No top-nav element found, unable to add Table of Contents') | |
return; | |
} | |
let topNav = topNavs[0]; | |
topNav.insertAdjacentElement("afterend", tocBase) | |
document.head.appendChild(createStyleNode(css)) | |
} | |
/* Wait for the page to be formatted before reading the sections and adding the toc. */ | |
let observerCallback = (mutationList, observer) => { | |
mutationList.forEach( mutation => { | |
if (mutation.target.classList.contains('LoadDone')) { | |
setTimeout(main) | |
observer.disconnect() | |
} | |
}) | |
} | |
if (document.documentElement.classList.contains('LoadDone')) { | |
setTimeout(main) | |
} else { | |
let observer = new MutationObserver(observerCallback) | |
observer.observe(document.documentElement, { | |
attributeFilter: [ 'class' ] | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment