docs2website/extras/components/outline-inline.js

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('');
}
})();