(function () { var POLL_MS = 30000; var MONTHS = [ "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec", ]; function cookieEdition() { var m = document.cookie.match(/(?:^|; )tdpd_edition=([^;]*)/); if (!m) return "flask"; try { return decodeURIComponent(m[1]) || "flask"; } catch (e) { return "flask"; } } function setEditionCookie(edition) { document.cookie = "tdpd_edition=" + encodeURIComponent(edition) + "; Path=/; Max-Age=31536000; SameSite=Lax"; } function keepPath() { return location.pathname + location.search; } function useHref(edition) { var path = keepPath(); var href = "/_cascade/use/" + encodeURIComponent(edition); if (!path || path.indexOf("/_cascade/use/") === 0) return href; return href + "?next=" + encodeURIComponent(path); } function hintEl() { return document.getElementById("cascade-hint"); } function showHint(msg) { var el = hintEl(); if (!el) { var bar = document.getElementById("cascade-bar"); if (!bar) return; el = document.createElement("div"); el.id = "cascade-hint"; el.className = "cascade-hint"; el.setAttribute("role", "status"); bar.appendChild(el); } el.hidden = false; el.textContent = msg; pinBar(); } function clearHint() { var el = hintEl(); if (!el) return; el.hidden = true; el.textContent = ""; pinBar(); } function responseKeepsBar(res, text) { if (res && res.ok) return true; var body = text || ""; return ( body.indexOf("cascade-bar") !== -1 || body.indexOf("cascade-missing") !== -1 ); } function switchEdition(edition, branchLabel) { var prev = cookieEdition(); var here = keepPath() || "/"; var label = branchLabel || edition; if (!edition) return; if (edition === prev) { clearHint(); return; } setEditionCookie(edition); fetch(here, { cache: "no-store", credentials: "same-origin" }) .then(function (res) { return res.text().then(function (text) { return { res: res, text: text }; }); }) .then(function (got) { if (responseKeepsBar(got.res, got.text)) { location.replace(here + location.hash); return; } setEditionCookie(prev); showHint( "This path is not in " + label + ". Choose another branch above." ); }) .catch(function () { setEditionCookie(prev); showHint( "This path is not in " + label + ". Choose another branch above." ); }); } function esc(s) { return String(s) .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """); } /** ISO → "sep30 16:12" (3-letter English month + DD + HH:MM). */ function shortTime(iso) { if (!iso) return ""; var m = String(iso).match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}:\d{2})/); if (m) { var mon = MONTHS[Number(m[2]) - 1] || m[2]; return mon + m[3] + " " + m[4]; } return String(iso).slice(0, 16).replace("T", " "); } function fmtBuildSec(sec) { if (sec == null || sec === "") return ""; var n = Number(sec); if (!isFinite(n)) return ""; if (n < 10) return n.toFixed(1) + "s"; return Math.round(n) + "s"; } function builtText(row) { var sec = fmtBuildSec(row.build_seconds); var at = shortTime(row.built_at || ""); if (sec && at) return sec + " " + at; return sec || at; } function freezeOk(row) { return row && row.freeze_ok === true; } function freezeLabel(row) { if (freezeOk(row)) return "freeze ok"; var err = row && row.freeze_error ? String(row.freeze_error) : ""; return err ? "freeze failed: " + err : "freeze failed"; } function freezeMarkHtml(row) { var ok = freezeOk(row); return ( '' + (ok ? "✓" : "✗") + "" ); } function plusHtml(row) { if (row.vs_parent_plus != null) { var p = Number(row.vs_parent_plus); if (!isFinite(p)) return ""; return '+' + esc(String(p)) + ""; } if (row.loc != null) { var n = Number(row.loc); if (!isFinite(n)) return ""; return '' + esc(String(n)) + ""; } return ""; } function minusHtml(row) { if (row.vs_parent_minus != null) { var m = Number(row.vs_parent_minus); if (!isFinite(m)) return ""; return '−' + esc(String(m)) + ""; } if (row.loc != null) { return 'LOC'; } return ""; } function setText(el, text) { if (!el) return; var t = text || ""; if (el.textContent !== t) el.textContent = t; } function rowTitle(row) { var tip = row.tip || ""; var tipTime = row.tip_time || ""; var vs = ""; if (row.vs_parent_plus != null || row.vs_parent_minus != null) { vs = " vs parent +" + String(row.vs_parent_plus == null ? 0 : row.vs_parent_plus) + "/−" + String(row.vs_parent_minus == null ? 0 : row.vs_parent_minus); } else if (row.loc != null) { vs = " loc=" + String(row.loc); } var built = builtText(row); return ( "Switch build to " + (row.branch || "") + (tip ? " @ " + tip : "") + (tipTime ? " tip=" + shortTime(tipTime) : "") + (built ? " build=" + built : "") + " " + freezeLabel(row) + vs ); } function structureKey(list) { var parts = []; for (var i = 0; i < list.length; i++) { var row = list[i]; parts.push( (row.edition || "") + "\t" + (row.branch || "") + "\t" + (row.prefix || "") + "\t" + (row.parent || "") ); } return parts.join("\n"); } function pinBar(timingMsg) { var bar = document.getElementById("cascade-bar"); if (!bar) return; if (timingMsg) { bar.setAttribute("data-timing", timingMsg); bar.setAttribute("title", timingMsg); } var h = bar.offsetHeight || 0; document.documentElement.style.setProperty("--cascade-pad", h + "px"); } function markActive(root, edition) { var links = root.querySelectorAll("a[data-edition]"); for (var i = 0; i < links.length; i++) { var a = links[i]; var ed = a.getAttribute("data-edition"); var on = ed === edition || (edition === "flask" && a.getAttribute("data-default") === "1"); if (on) { a.classList.add("is-active"); a.setAttribute("aria-current", "page"); } else { a.classList.remove("is-active"); a.removeAttribute("aria-current"); } } } function timingText(timing, listLen) { if (!timing || timing.wall_seconds == null) return ""; return ( "last full pass ~" + String(timing.wall_seconds) + "s · built " + String(timing.built || 0) + " / skipped " + String(timing.skipped || 0) + " / " + String(timing.branches || listLen) ); } function updateValues(mount, data) { var list = (data && data.branches) || []; var defaultBranch = (data && data.default_branch) || "feat/website-views"; var timing = (data && data.rebuild_timing) || null; var rows = mount.querySelectorAll("a.cascade-tree-row[data-edition]"); if (rows.length !== list.length) return false; for (var i = 0; i < list.length; i++) { var row = list[i]; var a = rows[i]; if (a.getAttribute("data-edition") !== (row.edition || "")) return false; if (a.getAttribute("data-branch") !== (row.branch || "")) return false; var isDefault = (row.branch || "") === defaultBranch; if (isDefault) a.setAttribute("data-default", "1"); else a.removeAttribute("data-default"); setText(a.querySelector(".cascade-when"), shortTime(row.tip_time || "")); setText(a.querySelector(".cascade-built"), builtText(row)); var markEl = a.querySelector(".cascade-mark"); if (markEl) { var markHtml = freezeMarkHtml(row); if (markEl.outerHTML !== markHtml) markEl.outerHTML = markHtml; } var plusEl = a.querySelector(".cascade-plus"); if (plusEl) { var ph = plusHtml(row); if (plusEl.innerHTML !== ph) plusEl.innerHTML = ph; } var minusEl = a.querySelector(".cascade-minus"); if (minusEl) { var mh = minusHtml(row); if (minusEl.innerHTML !== mh) minusEl.innerHTML = mh; } a.setAttribute("title", rowTitle(row)); } var timingEl = mount.querySelector(".cascade-timing"); var t = timingText(timing, list.length); if (t) { if (!timingEl) { timingEl = document.createElement("div"); timingEl.className = "cascade-timing"; mount.appendChild(timingEl); } if (timingEl.textContent !== t) timingEl.textContent = t; } else if (timingEl) { timingEl.parentNode.removeChild(timingEl); } markActive(mount, cookieEdition()); pinBar(t); return true; } function renderTree(data, soft) { var mount = document.getElementById("cascade-tree"); if (!mount) return; var list = (data && data.branches) || []; if (!list.length) { mount.textContent = "No branches in branch-status.json"; pinBar(); return; } if (soft && mount.getAttribute("data-structure") === structureKey(list)) { if (updateValues(mount, data)) return; } var defaultBranch = (data && data.default_branch) || "feat/website-views"; var timing = (data && data.rebuild_timing) || null; var html = []; html.push('
" +
esc(branch) +
"" +
'' +
esc(shortTime(row.tip_time || "")) +
"" +
'' +
esc(builtText(row)) +
"" +
'' +
plusHtml(row) +
"" +
'' +
minusHtml(row) +
"" +
""
);
}
html.push("flask' +
' (branch-status unavailable)';
markActive(mount, cookieEdition());
pinBar();
}
});
}
document.addEventListener("click", function (ev) {
var a = ev.target.closest
? ev.target.closest("a.cascade-tree-row[data-edition]")
: null;
if (!a || ev.defaultPrevented) return;
if (ev.button !== 0 || ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey)
return;
ev.preventDefault();
switchEdition(
a.getAttribute("data-edition"),
a.getAttribute("data-branch") || a.getAttribute("data-edition")
);
});
if (document.body && document.body.classList.contains("cascade-missing")) {
showHint(
"This path is not in the current branch. Choose another branch above."
);
}
loadStatus(false);
setInterval(function () {
loadStatus(true);
}, POLL_MS);
window.addEventListener("resize", function () {
pinBar();
});
})();