import { onRestoreAnchor, onSaveAnchor } from './functions/scroll' import { on, ready } from './functions/browser' import tippy from 'tippy.js' Promise.resolve() .then(onImageFallback) .then(() => ready) .then(onTableStyle) .then(onMobileHeader) .then(onLanguageSwitch) .then(onRestoreAnchor) .then(onSaveAnchor) .then(onRestoreEmailAddress) .then(onReferenceLinks) .then(onAbbreviation) .then(onLinkTitle) function onTableStyle() { const content = document.querySelector('article.content') if (!content) return const template = document.createElement('section') template.classList.add('table-container') for (const element of content.querySelectorAll('table')) { element.classList.add( 'table', 'is-bordered', 'is-narrow', 'is-hoverable', 'is-fullwidth', 'is-no-wrap', 'is-align-middle' ) const container = template.cloneNode() container.appendChild(element.cloneNode(true)) element.replaceWith(container) } } function onMobileHeader() { on(document, 'click', '.navbar-burger', (event) => { const target = event.target as HTMLElement const menu = target.closest('.navbar')!.querySelector('.navbar-menu')! menu.classList.toggle('is-active') target.closest('.navbar-burger')!.ariaExpanded = String(menu.classList.contains('is-active')) }) } function onLanguageSwitch() { on(document, 'click', '.navbar-item.language a', (event) => { event.preventDefault() const target = event.target as HTMLAnchorElement const url = new URL(target.href) url.hash = location.hash location.replace(url.toString()) }) } function onRestoreEmailAddress() { const content = document.querySelector('article.content') if (!content) return for (const link of content.querySelectorAll('a[href^="mailto:"]')) { const address = atob(link.pathname) link.href = `mailto:${address}` if (link.textContent === '') { link.textContent = address } } } function onReferenceLinks() { const content = document.querySelector('article.content') if (!content) return const citationMap = new Map() for (const link of content.querySelectorAll('#references + ul a')) { citationMap.set(link.href, link.closest('li')!) } if (citationMap.size === 0) return const links = Array.from(content.querySelectorAll('a')) .filter((link) => link.closest('#references + ul') === null) .filter((link) => citationMap.has(link.href)) tippy(links, { touch: 'hold', theme: 'light-border', interactive: true, appendTo: document.body, content(ref) { const cite = citationMap.get((ref as HTMLAnchorElement).href) const citation = document.createDocumentFragment() for (const node of cite!.childNodes) { citation.append(node.cloneNode(true)) } return citation }, }) } function onAbbreviation() { const content = document.querySelector('article.content') if (!content) return tippy(content.querySelectorAll('abbr[title][data-origin]'), { touch: 'hold', theme: 'light-border', interactive: true, appendTo: document.body, content(ref) { const fragment = document.createDocumentFragment() fragment.append( ref.getAttribute('data-origin')!, document.createElement('br'), document.createTextNode(`${ref.getAttribute('title')} (${ref.textContent})`) ) return fragment }, }) } function onLinkTitle() { for (const link of document.links) { if (link.title) continue let title = getTitle(link as HTMLAnchorElement) if (!title) continue title = decodeURIComponent(title) if (link.textContent === title) continue link.title = title } function getTitle(link: HTMLAnchorElement) { const host = link.host const path = link.pathname let title: string | undefined if (host === 'doi.org') return path.slice(1) if (host === 'files.transfemscience.org' && path.startsWith('/pdfs/')) return path.slice(6) if (host.endsWith('wikipedia.org') && path.startsWith('/wiki/')) { title = path.slice(path.lastIndexOf('/') + 1) if (link.hash) title = link.hash.slice(1) + ' on ' + link.title return title.replace(/_/g, ' ') } } } function onImageFallback() { document.addEventListener('load', onLoad, { capture: true }) document.addEventListener('error', onError, { capture: true }) const attribute = 'data-origin' function onLoad(event: Event) { if (!isHTMLImageElement(event.target)) return event.target.removeAttribute(attribute) } function onError(event: Event) { if (!isHTMLImageElement(event.target)) return const origin = event.target.getAttribute(attribute) if (origin) event.target.src = origin event.target.removeAttribute(attribute) } function isHTMLImageElement(target: EventTarget | null): target is HTMLImageElement { if (target === null) return false return (target as HTMLElement).tagName === 'IMG' } }