/* Progressive enhancement only: every page works without this file. */
(function () {
"use strict";
/* The band's active tab: the longest link that prefixes the path. */
var p = location.pathname, best = null;
document.querySelectorAll(".band a").forEach(function (a) {
var h = a.getAttribute("href");
if (h !== "/" && (p === h || p.indexOf(h + "/") === 0) && (!best || h.length > best.getAttribute("href").length)) best = a;
});
if (best) best.classList.add("on");
/* Off-the-shelf editors, loaded only where a page asks for them:
CodeMirror 6 over textarea.code, EasyMDE over textarea.md. */
function load(src, css) {
return new Promise(function (ok) {
if (css) { var l = document.createElement("link"); l.rel = "stylesheet"; l.href = css; document.head.appendChild(l); }
var s = document.createElement("script"); s.src = src; s.onload = ok; document.head.appendChild(s);
});
}
if (document.querySelector("textarea.code")) load("/static/vendor/editor.js");
var mds = document.querySelectorAll("textarea.md");
if (mds.length) load("/static/vendor/easymde.min.js", "/static/vendor/easymde.min.css").then(function () {
var E = window.EasyMDE;
function b(name, action, text, title) { return { name: name, action: action, text: text, title: title, className: "mde-btn" }; }
var toolbar = [b("bold", E.toggleBold, "B", "Bold"), b("italic", E.toggleItalic, "I", "Italic"), b("heading", E.toggleHeadingSmaller, "H", "Heading"), "|",
b("code", E.toggleCodeBlock, ">", "Code"), b("quote", E.toggleBlockquote, "“", "Quote"), b("ul", E.toggleUnorderedList, "•", "List"), b("ol", E.toggleOrderedList, "1.", "Numbered list"), "|",
b("link", E.drawLink, "link", "Link"), "|", b("preview", E.togglePreview, "preview", "Preview")];
mds.forEach(function (t) { new E({ element: t, spellChecker: false, status: false, forceSync: true, autoDownloadFontAwesome: false, toolbar: toolbar }); });
});
/* Theme switch in the header: dark, light, auto (follows the system); kept in the theme cookie. */
var toggle = document.querySelector("[data-theme-toggle]");
if (toggle) {
var root = document.documentElement, order = ["dark", "light", "auto"], glyph = { dark: "◐", light: "☀", auto: "◑" };
var show = function () {
var p = root.dataset.themePref || "dark";
toggle.title = "Theme: " + p + " (click to change)";
toggle.setAttribute("aria-label", toggle.title);
toggle.firstElementChild.textContent = glyph[p];
};
show();
toggle.addEventListener("click", function () {
var p = order[(order.indexOf(root.dataset.themePref || "dark") + 1) % order.length];
document.cookie = "theme=" + p + "; path=/; max-age=31536000; samesite=lax";
root.dataset.themePref = p;
root.dataset.theme = p === "auto" ? (window.matchMedia && matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark") : p;
show();
});
}
/* Diffs: unified or split (remembered in the diff cookie), collapse all. */
var diffs = document.querySelectorAll("table.code.diff");
if (diffs.length) {
var pane = function (tr, col, side) {
var n = document.createElement("td"), t = document.createElement("td");
n.className = "n"; t.className = "t" + (side === "right" ? " mid" : "");
if (!tr) { n.className += " none"; t.className += " none"; return [n, t]; }
var kind = tr.classList.contains("add") ? "add" : tr.classList.contains("del") ? "del" : "ctx";
if (kind !== "ctx") { n.className += " " + kind; t.className += " " + kind; }
n.textContent = tr.cells[col].textContent;
t.innerHTML = tr.cells[3].innerHTML;
// Line comments belong to the projected (right) side only.
if (side === "left") t.querySelectorAll(".linecomment").forEach(function (d) { d.remove(); });
return [n, t];
};
var split = function (table) {
var s = document.createElement("table");
s.className = "code diff split";
s.innerHTML = '
';
var rows = [].slice.call(table.rows), i = 0;
var add = function (l, r) {
var tr = s.insertRow();
pane(l, 0, "left").concat(pane(r, 1, "right")).forEach(function (c) { tr.appendChild(c); });
};
while (i < rows.length) {
var r = rows[i];
if (r.classList.contains("del") || r.classList.contains("add")) {
var dels = [], adds = [];
while (i < rows.length && rows[i].classList.contains("del")) dels.push(rows[i++]);
while (i < rows.length && rows[i].classList.contains("add")) adds.push(rows[i++]);
for (var k = 0; k < Math.max(dels.length, adds.length); k++) add(dels[k], adds[k]);
continue;
}
if (r.classList.contains("gap") || r.querySelector("td.thread")) {
var tr = s.insertRow(), td = tr.insertCell();
tr.className = r.className; td.colSpan = 4; td.className = r.cells[r.cells.length - 1].className;
td.innerHTML = r.cells[r.cells.length - 1].innerHTML;
} else {
add(r, r);
}
i++;
}
return s;
};
var cookieMode = (document.cookie.match(/(?:^|; )diff=(split|unified)/) || [])[1] || "unified";
var apply = function (mode) {
diffs.forEach(function (t) {
if (mode === "split" && !t._split) { t._split = split(t); t.parentNode.insertBefore(t._split, t.nextSibling); }
t.hidden = mode === "split";
if (t._split) t._split.hidden = mode !== "split";
});
document.querySelectorAll("[data-diff-mode]").forEach(function (a) { a.classList.toggle("on", a.getAttribute("data-diff-mode") === mode); });
};
document.querySelectorAll("[data-diff-modes], [data-diff-collapse]").forEach(function (e) { e.hidden = false; });
document.querySelectorAll("[data-diff-mode]").forEach(function (a) {
a.addEventListener("click", function (ev) {
ev.preventDefault();
var mode = a.getAttribute("data-diff-mode");
document.cookie = "diff=" + mode + "; path=/; max-age=31536000; samesite=lax";
apply(mode);
});
});
document.querySelectorAll("[data-diff-collapse]").forEach(function (a) {
a.addEventListener("click", function (ev) {
ev.preventDefault();
var files = document.querySelectorAll("details.file-diff"), anyOpen = [].some.call(files, function (d) { return d.open; });
files.forEach(function (d) { d.open = !anyOpen; });
a.textContent = anyOpen ? "expand all" : "collapse all";
});
});
apply(cookieMode);
}
/* Settings pages: mark the section in view in the list of sections. */
var navLinks = document.querySelectorAll(".section-nav a[href^='#']");
if (navLinks.length && "IntersectionObserver" in window) {
var byId = {};
navLinks.forEach(function (a) { byId[a.getAttribute("href").slice(1)] = a; });
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (e) {
if (e.isIntersecting && byId[e.target.id]) {
navLinks.forEach(function (a) { a.classList.remove("on"); });
byId[e.target.id].classList.add("on");
}
});
}, { rootMargin: "0px 0px -70% 0px" });
Object.keys(byId).forEach(function (id) { var el = document.getElementById(id); if (el) io.observe(el); });
}
/* Copy buttons. */
document.querySelectorAll("[data-copy]").forEach(function (b) {
b.addEventListener("click", function () {
navigator.clipboard.writeText(b.getAttribute("data-copy")).then(function () {
var t = b.textContent; b.textContent = "copied"; setTimeout(function () { b.textContent = t; }, 1200);
});
});
});
/* Tree rows: the last change per entry, fetched after the page paints. */
var tree = document.querySelector("table.tree[data-last]");
if (tree) {
var paths = [].map.call(tree.querySelectorAll("tr[data-path]"), function (r) { return r.getAttribute("data-path"); });
if (paths.length) {
fetch(tree.getAttribute("data-last") + "?paths=" + encodeURIComponent(paths.join(",")), { credentials: "same-origin" })
.then(function (r) { return r.json(); })
.then(function (rows) {
rows.forEach(function (c) {
var tr = tree.querySelector('tr[data-path="' + CSS.escape(c.path) + '"]');
if (!tr) return;
var a = tr.querySelector("td.last a"), t = tr.querySelector("td.age");
if (a) { a.textContent = c.title; a.href = tree.getAttribute("data-change") + c.hash; }
if (t) { t.textContent = c.ago; t.title = c.when; }
});
}).catch(function () {});
}
}
/* Line anchors: #L12 or #L12-L20 highlight a range and clicking a number selects. */
function mark() {
var m = location.hash.match(/^#L(\d+)(?:-L(\d+))?$/);
document.querySelectorAll("tr.hl").forEach(function (r) { r.classList.remove("hl"); });
if (!m) { showBar(0, 0); return; }
var a = +m[1], b = +(m[2] || m[1]);
for (var i = Math.min(a, b); i <= Math.max(a, b); i++) {
var row = document.getElementById("L" + i);
if (row) row.classList.add("hl");
}
var first = document.getElementById("L" + Math.min(a, b));
if (first && !mark.done) { first.scrollIntoView({ block: "center" }); mark.done = true; }
showBar(Math.min(a, b), Math.max(a, b));
}
/* The bar for a selected range: copy its text, or a permalink to it. */
var bar = document.querySelector(".linebar");
function showBar(a, b) {
if (!bar) return;
bar.hidden = !a;
if (!a) return;
bar.querySelector("[data-linebar-label]").textContent = a === b ? "Line " + a : "Lines " + a + "–" + b;
bar.setAttribute("data-range", a + "-" + b);
}
function flash(btn) { var t = btn.textContent; btn.textContent = "Copied"; setTimeout(function () { btn.textContent = t; }, 1200); }
if (bar) {
bar.querySelector("[data-copy-lines]").addEventListener("click", function (ev) {
var r = bar.getAttribute("data-range").split("-"), out = [];
for (var i = +r[0]; i <= +r[1]; i++) { var row = document.getElementById("L" + i); if (row) out.push(row.querySelector("td.t").textContent); }
navigator.clipboard.writeText(out.join("\n") + "\n").then(function () { flash(ev.target); });
});
var pl = bar.querySelector("[data-copy-permalink]");
if (pl) pl.addEventListener("click", function () {
navigator.clipboard.writeText(new URL(document.body.getAttribute("data-permalink"), location.href).href + location.hash).then(function () { flash(pl); });
});
}
function permalink() { var p = document.body.getAttribute("data-permalink"); return p ? p + location.hash : null; }
window.addEventListener("hashchange", mark);
mark();
document.querySelectorAll("table.code td.n").forEach(function (td) {
td.addEventListener("click", function (e) {
var n = td.parentNode.id;
if (e.shiftKey && location.hash.match(/^#L(\d+)/)) location.hash = location.hash.replace(/^#(L\d+).*/, "$1-" + n);
else location.hash = n;
});
});
/* Flow run page: statuses and new log lines while the run is live. */
var liveUrl = document.body.getAttribute("data-flow-live");
if (liveUrl) {
var tick = function () {
var after = [].map.call(document.querySelectorAll("details[data-job]"), function (d) {
return d.getAttribute("data-job") + ":" + d.querySelector("[data-log]").getAttribute("data-seq");
}).join(",");
fetch(liveUrl + "?after=" + after, { headers: { accept: "application/json" } })
.then(function (r) { return r.json(); })
.then(function (s) {
s.jobs.forEach(function (j) {
var cls = "st-" + j.status;
var node = document.querySelector("[data-job-node='" + j.id + "']");
if (node) {
node.setAttribute("class", "node " + cls);
node.querySelector("[data-glyph]").textContent = j.glyph;
node.querySelector("[data-meta]").textContent = j.status + " · " + j.duration;
}
var d = document.querySelector("details[data-job='" + j.id + "']");
if (!d) return;
d.className = "panel flow-job " + cls;
var g = d.querySelector("summary [data-glyph]");
g.className = "flow-glyph " + cls; g.textContent = j.glyph;
d.querySelector("summary [data-meta]").textContent = j.status + (j.exit_code !== null ? " · exit " + j.exit_code : "") + " · " + j.duration;
if (j.status === "running" || j.status === "failed") d.open = true;
var log = d.querySelector("[data-log]");
var stick = log.scrollTop + log.clientHeight >= log.scrollHeight - 4;
j.lines.forEach(function (l) {
var ln = document.createElement("span"); ln.className = "ln s-" + l.stream;
var t = document.createElement("span"); t.className = "t"; t.textContent = (l.t / 1000).toFixed(1) + "s";
ln.appendChild(t); ln.appendChild(document.createTextNode(l.text));
log.appendChild(ln); log.appendChild(document.createTextNode("\n"));
log.setAttribute("data-seq", l.seq);
});
if (stick && j.lines.length) log.scrollTop = log.scrollHeight;
});
var st = document.querySelector("[data-run-status]"); if (st) st.textContent = s.status;
if (s.live) setTimeout(tick, 1500); else setTimeout(function () { location.reload(); }, 800);
})
.catch(function () { setTimeout(tick, 5000); });
};
setTimeout(tick, 1500);
}
/* Keyboard: / focuses search; g c / g p / g i jump; ? shows the sheet. */
var pending = null;
document.addEventListener("keydown", function (e) {
if (e.target && /^(INPUT|TEXTAREA|SELECT)$/.test(e.target.tagName)) return;
if (e.key === "/") { var s = document.querySelector("input[name=q]"); if (s) { e.preventDefault(); s.focus(); } return; }
if (e.key === "y" && !e.ctrlKey && !e.metaKey && !e.altKey && permalink()) { history.replaceState(null, "", permalink()); pending = null; return; }
if (e.key === "?") { var k = document.getElementById("keys"); if (k) k.hidden = !k.hidden; return; }
var repo = document.body.getAttribute("data-repo");
if (pending === "g" && repo) {
var to = { c: "", p: "/proposals", i: "/issues", h: "/changes/" + (document.body.getAttribute("data-ref") || "main"), b: "/bookmarks", t: "/trust" }[e.key];
if (to !== undefined) location.href = repo + to;
pending = null; return;
}
pending = e.key === "g" ? "g" : null;
});
})();