/* eslint-env browser */ import { marked } from 'marked' customElements.define('docs-viewer', class extends HTMLElement { static get observedAttributes () { return ['data-load'] } attributeChangedCallback (name, _, page) { if (name === 'data-load') this.load(page).catch((err) => this.#error(err)) } constructor () { super() this.template = document.createElement('template') this.template.innerHTML = `
` this.root = this.attachShadow({ mode: 'open' }) this.root.appendChild(this.template.content.cloneNode(true)) this.panel = this.root.querySelector('#panel') this.header = this.root.querySelector('header') this.panel.addEventListener('click', (evt) => { if (evt.target?.tagName !== 'A') return const href = evt.target.getAttribute('href') const { origin } = new URL(location.href) const url = new URL(href, location.href) if (url.origin !== origin) return window.open(href) evt.preventDefault() document.documentElement.scrollTo(0, 0) this.load(url.pathname).catch((err) => this.#error(err)).finally(() => { this.header.querySelector('a').style.display = 'inline-block' }) }) window.addEventListener('popstate', (evt) => { document.documentElement.scrollTo(0, 0) if (evt.state?.page === 'readme.md') this.header.querySelector('a').style.display = 'none' evt.preventDefault() this.load(evt.state?.page || this.page, true).catch((err) => this.#error(err)) }) window.onbeforeunload = (e) => { this.#load() e.returnValue = false } this.page = this.dataset.load this.load(this.page).catch((err) => this.#error(err)) } #error (err) { try { this.panel.querySelector('slot').innerHTML = err.stack } catch (e) { console.error(err, e) } } load (page = 'readme.md', replace) { if (replace) history.replaceState({ page }, page, page) else history.pushState({ page }, page, page) this.page = page return this.#load() } async #load () { this.panel.querySelector('slot').innerHTML = marked.parse(await (await fetch(this.page)).text(), {headerIds: false, mangle: false}) } })