hosted/dossier_site/app.js

157 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* global marked */
const DOCS = [
{
id: "submission",
title: "Submission Edition (Clean)",
file: "../DANNY_STOCKER_INFRAFABRIC_DOSSIER_SUBMISSION_EDITION.md",
},
{
id: "submission-full",
title: "Submission Edition (Clean, Full) v2.0",
file: "../DANNY_STOCKER_INFRAFABRIC_DOSSIER_SUBMISSION_EDITION_FULL.md",
},
{
id: "data",
title: "DataDriven Technical Report (Microlab)",
file: "../DANNY_STOCKER_INFRAFABRIC_DOSSIER_DATA_DRIVEN_EDITION.md",
},
{
id: "data-full",
title: "DataDriven Edition (Full) v2.0",
file: "../DANNY_STOCKER_INFRAFABRIC_DOSSIER_DATA_DRIVEN_EDITION_FULL.md",
},
{
id: "uncut",
title: "Uncut Dossier (Full)",
file: "../DANNY_STOCKER_INFRAFABRIC_DOSSIER_UNCUT.md",
},
];
function slugify(value) {
return String(value)
.replace(/<[^>]+>/g, "")
.trim()
.toLowerCase()
.replace(/[^\w\s-]/g, "")
.replace(/\s+/g, "-")
.replace(/-+/g, "-");
}
function createSlugger() {
const seen = new Map();
return (headingText) => {
const base = slugify(headingText) || "section";
const current = seen.get(base) || 0;
seen.set(base, current + 1);
return current === 0 ? base : `${base}-${current + 1}`;
};
}
function setStatus(text) {
const statusEl = document.getElementById("status");
statusEl.textContent = text || "";
}
function buildToc() {
const tocEl = document.getElementById("toc");
tocEl.innerHTML = "";
const title = document.createElement("div");
title.className = "toc-title";
title.textContent = "On this page";
tocEl.appendChild(title);
const headings = Array.from(document.querySelectorAll("#content h1, #content h2, #content h3, #content h4"));
for (const heading of headings) {
const level = Number(heading.tagName.slice(1));
if (!heading.id) continue;
const a = document.createElement("a");
a.href = `#${heading.id}`;
a.textContent = heading.textContent || heading.id;
a.className = `depth-${level}`;
tocEl.appendChild(a);
}
}
function scrollToHash() {
const id = (location.hash || "").replace(/^#/, "");
if (!id) return;
const el = document.getElementById(id);
if (el) el.scrollIntoView({ block: "start" });
}
function setQueryParam(key, value) {
const url = new URL(location.href);
if (value == null) url.searchParams.delete(key);
else url.searchParams.set(key, value);
history.replaceState(null, "", url.toString());
}
async function loadDoc(docId) {
const doc = DOCS.find((d) => d.id === docId) || DOCS[0];
setQueryParam("doc", doc.id);
const rawLink = document.getElementById("openRaw");
rawLink.href = doc.file;
setStatus(`Loading: ${doc.title}`);
const slugger = createSlugger();
const renderer = new marked.Renderer();
renderer.heading = (text, level) => {
const id = slugger(text);
return `<h${level} id="${id}">${text}</h${level}>`;
};
marked.setOptions({
renderer,
gfm: true,
breaks: false,
mangle: false,
headerIds: false,
});
try {
const res = await fetch(doc.file, { cache: "no-cache" });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const markdown = await res.text();
const html = marked.parse(markdown);
const contentEl = document.getElementById("content");
contentEl.innerHTML = html;
buildToc();
setStatus(`Loaded: ${doc.title}`);
scrollToHash();
} catch (err) {
setStatus(`Failed to load ${doc.title}: ${String(err)}`);
document.getElementById("content").textContent = "";
}
}
function init() {
const select = document.getElementById("docSelect");
for (const doc of DOCS) {
const opt = document.createElement("option");
opt.value = doc.id;
opt.textContent = doc.title;
select.appendChild(opt);
}
const initial = new URLSearchParams(location.search).get("doc") || DOCS[0].id;
select.value = DOCS.some((d) => d.id === initial) ? initial : DOCS[0].id;
select.addEventListener("change", () => {
location.hash = "";
loadDoc(select.value);
});
window.addEventListener("hashchange", () => scrollToHash());
loadDoc(select.value);
}
init();