-
-
Save cferdinandi/3a7dfd171551e71335e6a434edea181d to your computer and use it in GitHub Desktop.
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
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Table of Contents</title> | |
<style type="text/css"> | |
body { | |
margin: 1em auto; | |
max-width: 30em; | |
width: 88%; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Table of Contents</h1> | |
<table-of-contents levels="h2, h3" heading="On This Page..."></table-of-contents> | |
<h2>Cat O'Nine Tails</h2> | |
<p>Cat o'nine tails Pieces of Eight swab carouser tackle. Pink hornswaggle gabion Sea Legs Davy Jones' Locker.</p> | |
<p>Hang the jib Nelsons folly trysail ahoy prow. Transom strike colors scallywag aft league.</p> | |
<h3 id="the-brig">The Brig</h3> | |
<p>Dead men tell no tales topmast Sail ho Davy Jones' Locker chantey. Wherry fluke pillage rope's end brig.</p> | |
<h4>Privateer</h4> | |
<p>Tack topgallant draft line flogging. Maroon overhaul grog blossom Privateer main sheet.</p> | |
<p>Provost me cackle fruit Corsair Cat o'nine tails. Hempen halter Davy Jones' Locker clipper bring a spring upon her cable run a shot across the bow.</p> | |
<h2>Ahoy</h2> | |
<p>Booty squiffy wench overhaul ahoy. Parrel Pirate Round long clothes long boat come about.</p> | |
<p>Squiffy jack crow's nest bilged on her anchor barkadeer. Snow bucko mizzen six pounders tack.</p> | |
<h3 id="man-of-war">Man-of-War</h3> | |
<p>Lee lad nipperkin avast pressgang. Man-of-war prow ho Sail ho landlubber or just lubber.</p> | |
<p>Ho no prey, no pay fire ship salmagundi capstan. Hail-shot doubloon wherry loaded to the gunwalls cutlass.</p> | |
<h2 id="corsair">Corsair</h2> | |
<p>Corsair chantey hardtack ahoy snow. Maroon cog galleon topmast tender.</p> | |
<h3 id="shiver-me-timbers">Shiver Me Timbers</h3> | |
<p>Galleon nipper Shiver me timbers lugger Nelsons folly. Wench ballast scurvy man-of-war hearties.</p> | |
<p>Poop deck clap of thunder Corsair grog hornswaggle. Dead men tell no tales brigantine long clothes black spot sutler.</p> | |
<h4 id="scurvy-dog">Scurvy Dog</h4> | |
<p>Jury mast Letter of Marque boatswain scurvy sheet. Jolly boat plunder jack starboard Pirate Round.</p> | |
<p>Holystone bring a spring upon her cable grog blossom deadlights league. Lanyard gabion reef sails booty gaff.</p> | |
<h4>Sea Legs</h4> | |
<p>Sea Legs to go on account skysail Yellow Jack heave down. Spanker heave down yawl starboard barque.</p> | |
<p>To go on account hulk swing the lead heave to tack. Fore fire in the hole prow run a rig Jack Ketch.</p> | |
<h2 id="quarterdeck">On the Quarterdeck</h2> | |
<p>Tack chase red ensign league pinnace. Holystone quarterdeck me boatswain rope's end.</p> | |
<p>Sink me lanyard Pieces of Eight starboard black spot. Blimey heave down crimp mutiny matey.</p> | |
<h3 id="jolly-roger">Jolly Roger</h3> | |
<p>Belay piracy come about jolly boat transom. Heave to gally snow Arr wherry.</p> | |
<p>Sutler Davy Jones' Locker ahoy walk the plank lugger. Jolly Roger matey hornswaggle Privateer marooned.</p> | |
<h2>Davy Jones' Locker</h2> | |
<p>Davy Jones' Locker jib trysail bowsprit heave down. Transom square-rigged clipper Jack Ketch chandler.</p> | |
<p>Square-rigged yawl execution dock sloop American Main. Six pounders red ensign lugger heave to dead men tell no tales.</p> | |
<h3 id="sloop">Sloop</h3> | |
<p>Spanker rutters Arr sloop pinnace. List crimp swab Blimey grog.</p> | |
<p>Shiver me timbers hulk black jack Pirate Round clap of thunder. Scuppers six pounders carouser spirits jib.</p> | |
<h4 id="swab">Swab</h4> | |
<p>Spanker rutters Arr sloop pinnace. List crimp swab Blimey grog.</p> | |
<p>Shiver me timbers hulk black jack Pirate Round clap of thunder. Scuppers six pounders carouser spirits jib.</p> | |
<h5>Grog</h5> | |
<p>Spanker rutters Arr sloop pinnace. List crimp swab Blimey grog.</p> | |
<p>Shiver me timbers hulk black jack Pirate Round clap of thunder. Scuppers six pounders carouser spirits jib.</p> | |
<script> | |
customElements.define('table-of-contents', class extends HTMLElement { | |
/** | |
* Instantiate the Web Component | |
*/ | |
constructor () { | |
// Get parent class properties | |
super(); | |
// Define properties | |
this.content = this.getAttribute('content') || document; | |
this.levels = this.getAttribute('levels') || 'h2, h3, h4, h5, h6'; | |
this.heading = this.getAttribute('heading') || 'Table of Contents'; | |
this.headingLevel = this.getAttribute('heading-level') || 'h2'; | |
this.listType = this.getAttribute('list-type') || 'ul'; | |
// Get the headings | |
// If none are found, don't render a list | |
this.headings = this.content.querySelectorAll(this.levels); | |
if (!this.headings.length) return; | |
// Render the list | |
this.render(); | |
} | |
/** | |
* Inject the table of contents into the DOM | |
*/ | |
render () { | |
// Track the current heading level | |
let level = this.headings[0].tagName.slice(1); | |
let startingLevel = level; | |
// Cache the number of headings | |
let len = this.headings.length - 1; | |
// Inject the HTML into the DOM | |
this.innerHTML = | |
`<${this.headingLevel}>${this.heading}</${this.headingLevel}> | |
<${this.listType}> | |
${Array.from(this.headings).map((heading, index) => { | |
// Add an ID if one is missing | |
this.createID(heading); | |
// Check the heading level vs. the current list | |
let currentLevel = heading.tagName.slice(1); | |
let levelDifference = currentLevel - level; | |
level = currentLevel; | |
let html = this.getStartingHTML(levelDifference, index); | |
// Generate the HTML | |
html += | |
`<li> | |
<a href="#${heading.id}">${heading.innerHTML.trim()}</a>`; | |
// If the last item, close it all out | |
if (index === len) { | |
html += this.getOutdent(Math.abs(startingLevel - currentLevel)); | |
} | |
return html; | |
}).join('')} | |
</${this.listType}>`; | |
} | |
/** | |
* Create an ID for a heading if one does not exist | |
* @param {Node} heading The heading element | |
*/ | |
createID (heading) { | |
if (heading.id.length) return; | |
heading.id = `toc_${crypto.randomUUID()}`; | |
} | |
/** | |
* Get the HTML to indent a list a specific number of levels | |
* @param {Integer} count The number of times to indent the list | |
* @return {String} The HTML | |
*/ | |
getIndent (count) { | |
let html = ''; | |
for (let i = 0; i < count; i++) { | |
html += `<${this.listType}>`; | |
} | |
return html; | |
} | |
/** | |
* Get the HTML to close an indented list a specific number of levels | |
* @param {Integer} count The number of times to "outdent" the list | |
* @return {String} The HTML | |
*/ | |
getOutdent (count) { | |
let html = ''; | |
for (let i = 0; i < count; i++) { | |
html += `</${this.listType}></li>`; | |
} | |
return html; | |
} | |
/** | |
* Get the HTML string to start a new list of headings | |
* @param {Integer} diff The number of levels in or out from the current level the list is | |
* @param {Integer} index The index of the heading in the "headings" NodeList | |
* @return {String} The HTML | |
*/ | |
getStartingHTML (diff, index) { | |
// If indenting | |
if (diff > 0) { | |
return this.getIndent(diff); | |
} | |
// If outdenting | |
if (diff < 0) { | |
return this.getOutdent(Math.abs(diff)); | |
} | |
// If it's not the first item and there's no difference | |
if (index && !diff) { | |
return '</li>'; | |
} | |
return ''; | |
} | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment