112 lines
2.1 KiB
JavaScript
112 lines
2.1 KiB
JavaScript
(() => {
|
|
|
|
const template = `
|
|
<style>
|
|
ol {
|
|
list-style: none;
|
|
padding: 0;
|
|
}
|
|
|
|
li[data-depth='h1'] {
|
|
font-size: 1.2rem;
|
|
font-weight: 700;
|
|
margin-inline-start: 1rem;
|
|
}
|
|
|
|
li[data-depth='h2'] {
|
|
font-size: 1.1rem;
|
|
font-weight: 600;
|
|
margin-inline-start: 2rem;
|
|
}
|
|
|
|
li[data-depth='h3'] {
|
|
margin-inline-start: 3rem;
|
|
}
|
|
|
|
li[data-depth='h4'] {
|
|
font-size: 0.9rem;
|
|
margin-inline-start: 4rem;
|
|
}
|
|
|
|
li[data-depth='h5'] {
|
|
font-size: 0.9rem;
|
|
margin-inline-start: 5rem;
|
|
}
|
|
|
|
li[data-depth='h6'] {
|
|
font-size: 0.9rem;
|
|
margin-inline-start: 6rem;
|
|
}
|
|
|
|
a {
|
|
color: var(--theme-text-link);
|
|
}
|
|
|
|
a:active,
|
|
a:hover,
|
|
a:focus {
|
|
color: var(--theme-text-link-active);
|
|
}
|
|
|
|
a:visited {
|
|
color: var(--theme-text-link-visited);
|
|
}
|
|
</style>
|
|
<nav id="outline-inline" aria-hidden="true">
|
|
<em>Outline will render when the page has loaded...</em>
|
|
</nav>
|
|
`;
|
|
|
|
customElements.define('outline-inline',
|
|
class OutlineButton extends HTMLElement {
|
|
#outline = null;
|
|
|
|
constructor() {
|
|
super();
|
|
this.attachShadow({ mode: 'open' });
|
|
this.shadowRoot.innerHTML = template;
|
|
this.#outline = this.shadowRoot.querySelector('#outline-inline');
|
|
}
|
|
|
|
connectedCallback() {
|
|
if (document.readyState === 'complete') {
|
|
this.#render();
|
|
}
|
|
|
|
window.addEventListener('DOMContentLoaded', () => {
|
|
this.#render();
|
|
});
|
|
}
|
|
|
|
#render() {
|
|
const root_selector = this.getAttribute('content-root');
|
|
const outline = build_outline(root_selector);
|
|
this.#outline.innerHTML = `<ol>${outline}</ol>`;
|
|
}
|
|
}
|
|
);
|
|
|
|
function build_outline(root_selector) {
|
|
const root = document.querySelector(root_selector);
|
|
const headings = root.querySelectorAll('h1, h2, h3, h4, h5, h6');
|
|
const outline = [ ];
|
|
|
|
for (const heading of headings) {
|
|
const content = heading.cloneNode(true);
|
|
const anchor = content.querySelector('a.heading-anchor');
|
|
|
|
if (anchor) {
|
|
anchor.parentNode.removeChild(anchor);
|
|
}
|
|
|
|
outline.push(`
|
|
<li data-depth="${heading.tagName.toLowerCase()}">
|
|
<a href="#${heading.id}">${content.innerHTML}</a>
|
|
</li>
|
|
`);
|
|
}
|
|
|
|
return outline.join('');
|
|
}
|
|
|
|
})(); |