(function(d) { let p = d.body; // container of slides; assume for now const s1 = ':scope > hr:not([class])', s2 = ':scope > h2'; // find a container that has at least n "slides" function findContainer(s, n = 1) { if (p.querySelectorAll(s).length >= n) return true; // if body doesn't contain headings or
s, look into children for (let i = 0; i < p.children.length; i++) { if (p.children[i].querySelectorAll(s).length >= n) { p = p.children[i]; break; } } return false; } function newEl(tag, cls) { const el = d.createElement(tag); if (cls) el.className = cls; return el; } if (!findContainer(s1, 3)) { // if not enough
s found in children; look for

instead if (p.tagName === 'BODY') { // not enough h2 found, this page is not appropriate for slides if (!findContainer(s2) && p.tagName === 'BODY') return; p.querySelectorAll(s2).forEach(h2 => h2.before(newEl('hr'))); } } p.classList.add('slide-container'); // add 'slide' class to the frontmatter div and toc ['.frontmatter', '#TOC'].forEach(s => { d.body.querySelector(s)?.classList.add('slide'); }); function newSlide(s) { return (s?.innerText === '') ? s : newEl('div', 'slide'); } function isSep(el) { return el.tagName === 'HR' && el.attributes.length === 0; } let el = p.firstElementChild; if (isSep(el)) el.remove(); el = p.firstElementChild; if (!el) return; let s = newSlide(); el.before(s); while (true) { let el = s.nextSibling; if (!el) break; // remove slide separators (
) and create new slide if (isSep(el)) { s = newSlide(s); el.before(s); el.remove(); } else if (el.classList?.contains('slide')) { s = newSlide(s); el.after(s); } else { s.append(el); } } function setAttr(el, attr) { const m = newEl('div'); m.innerHTML = `
`; const attrs = m.firstElementChild.attributes; for (let i = 0; i < attrs.length; i++) { let a = attrs[i]; el.setAttribute(a.name, a.value); } m.remove(); } const slides = d.querySelectorAll('div.slide'), N = slides.length, tm = d.querySelector('span.timer'), fn = d.querySelector('.footnotes'); slides.forEach((s, i) => { // append footnotes if (fn) s.querySelectorAll('.footnote-ref > a[href^="#fn"]').forEach(a => { const li = fn.querySelector('li' + a.getAttribute('href')); if (!li) return; let f = s.querySelector('section.footnotes'); if (!f) { f = newEl('section', 'footnotes'); s.append(f); } f.append(li); li.firstElementChild?.insertAdjacentHTML('afterbegin', `[${a.innerHTML}] `); li.outerHTML = li.innerHTML; }); // add a timer s.append(tm ? tm.cloneNode() : newEl('span', 'timer')); // add page numbers const n = newEl('span', 'page-number'); n.innerText = i + 1 + '/' + N; n.onclick = e => location.hash = i + 1; s.append(n); // apply slide attributes in for (let k in s.childNodes) { const node = s.childNodes[k]; if (node.nodeType !== Node.COMMENT_NODE) continue; let t = node.textContent; if (!/^#/.test(t)) continue; t = t.replace(/^#/, ''); const r = /[\s\n]class="([^"]+)"/, m = t.match(r); if (m) { t = t.replace(r, '').trim(); s.className += ' ' + m[1]; } if (t) setAttr(s, t); break; } s.classList.contains('extend') && s.append(newEl('div', 'spacer fade')); location.hash === ('#' + (i + 1)) && s.scrollIntoView(); s.addEventListener('click', e => { if (!e.altKey) return; d.body.classList.toggle('overview'); setTimeout(() => e.target.scrollIntoView(), 100); }); }); [...d.querySelectorAll('a.footnote-backref'), fn, tm].forEach(el => el?.remove()); const tms = d.querySelectorAll('span.timer'), t1 = 1000 * tms[0].dataset.total; let t0; function startTimers() { t0 = new Date(); setInterval(setTimers, 1000); } function setTimers() { let t = (new Date() - t0); if (t1) t = t1 - t; const t2 = new Date(Math.abs(t)).toISOString().substr(11, 8).replace(/^00:/, ''); tms.forEach(el => { el.innerText = t2; if (t < 0) el.style.display = el.style.display === 'none' ? '' : 'none'; }); } // press f for fullscreen mode d.addEventListener('keyup', (e) => { if (e.target !== d.body) return; e.key === 'f' && d.documentElement.requestFullscreen(); e.key === 'o' && d.body.classList.toggle('overview'); e.key === 'm' && d.body.classList.toggle('mirrored'); sessionStorage.setItem('body-class', d.body.className); }); // start timer on fullscreen d.onfullscreenchange = (e) => d.fullscreenElement && !t0 && startTimers(); tms.forEach(el => el.addEventListener('click', e => startTimers())); // restore previously saved body class const bc = sessionStorage.getItem('body-class'); if (bc) d.body.className += ' ' + bc; })(document);