| d23464c0 Andy McCall ↶ |
1 |
|
| 2 |
(function () { |
| 3 |
"use strict"; |
| 4 |
|
| 5 |
var p = location.pathname, best = null; |
| 6 |
document.querySelectorAll(".band a").forEach(function (a) { |
| 7 |
var h = a.getAttribute("href"); |
| 8 |
if (h !== "/" && (p === h || p.indexOf(h + "/") === 0) && (!best || h.length > best.getAttribute("href").length)) best = a; |
| 9 |
}); |
| 10 |
if (best) best.classList.add("on"); |
| 11 |
|
| 16ee5d19 Andy McCall ↶ |
12 |
|
| 13 |
|
| 14 |
|
| 15 |
var menus = document.querySelectorAll("[data-tab-menu]"); |
| 16 |
function closeMenus(except) { |
| 17 |
menus.forEach(function (m) { if (m !== except) m.open = false; }); |
| 18 |
} |
| 19 |
menus.forEach(function (m) { |
| 20 |
m.addEventListener("toggle", function () { if (m.open) closeMenus(m); }); |
| 21 |
}); |
| 22 |
if (menus.length) { |
| 23 |
document.addEventListener("click", function (ev) { |
| 24 |
if (!ev.target.closest || !ev.target.closest("[data-tab-menu]")) closeMenus(null); |
| 25 |
}); |
| 26 |
document.addEventListener("keydown", function (ev) { |
| 27 |
if (ev.key !== "Escape") return; |
| 28 |
var open = document.querySelector("[data-tab-menu][open]"); |
| 29 |
if (open) { open.open = false; open.querySelector("summary").focus(); } |
| 30 |
}); |
| 31 |
} |
| 32 |
|
| 14530604 Andy McCall ↶ |
33 |
|
| 34 |
|
| 35 |
function load(src, css) { |
| 36 |
return new Promise(function (ok) { |
| 37 |
if (css) { var l = document.createElement("link"); l.rel = "stylesheet"; l.href = css; document.head.appendChild(l); } |
| 38 |
var s = document.createElement("script"); s.src = src; s.onload = ok; document.head.appendChild(s); |
| 39 |
}); |
| 40 |
} |
| 41 |
if (document.querySelector("textarea.code")) load("/static/vendor/editor.js"); |
| 42 |
var mds = document.querySelectorAll("textarea.md"); |
| ffb67a81 Andy McCall |
43 |
|
| 44 |
|
| 45 |
|
| 14530604 Andy McCall ↶ |
46 |
if (mds.length) load("/static/vendor/easymde.min.js", "/static/vendor/easymde.min.css").then(function () { |
| 47 |
var E = window.EasyMDE; |
| ffb67a81 Andy McCall |
48 |
function svg(d) { return '<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">' + d + '</svg>'; } |
| 49 |
var I = { |
| 50 |
bold: svg('<path d="M4.5 2.5h4.25a2.75 2.75 0 0 1 0 5.5H4.5zM4.5 8h5a2.75 2.75 0 0 1 0 5.5h-5z"/>'), |
| 51 |
italic: svg('<path d="M6.5 2.5h6M3.5 13.5h6M10 2.5l-4 11"/>'), |
| 52 |
strike: svg('<path d="M2.5 8h11M11 4.5c-.5-1.2-1.7-2-3.2-2-1.9 0-3.3 1-3.3 2.6 0 .9.4 1.5 1.2 2M5 11.5c.5 1.2 1.8 2 3.3 2 2 0 3.4-1.1 3.4-2.7"/>'), |
| 53 |
heading: svg('<path d="M3.5 2.5v11M12.5 2.5v11M3.5 8h9"/>'), |
| 54 |
quote: svg('<path d="M2.5 3.5h11M5.5 8h8M5.5 12.5h8M2.5 7v6"/>'), |
| 55 |
code: svg('<path d="M5.5 4.5 2 8l3.5 3.5M10.5 4.5 14 8l-3.5 3.5"/>'), |
| 56 |
link: svg('<path d="M7 9a3 3 0 0 0 4.2.3l2-2a3 3 0 0 0-4.2-4.2l-1 1M9 7a3 3 0 0 0-4.2-.3l-2 2a3 3 0 0 0 4.2 4.2l1-1"/>'), |
| 57 |
ul: svg('<path d="M6 4h7.5M6 8h7.5M6 12h7.5"/><circle cx="2.75" cy="4" r=".75" fill="currentColor"/><circle cx="2.75" cy="8" r=".75" fill="currentColor"/><circle cx="2.75" cy="12" r=".75" fill="currentColor"/>'), |
| 58 |
ol: svg('<path d="M6.5 4h7M6.5 8h7M6.5 12h7M2 2.5h1v3M2 7.5h1.5L2 9.5h1.5M2 10.5h1.5v3H2M2 12h1.5"/>'), |
| 59 |
task: svg('<rect x="2" y="2.5" width="4" height="4" rx=".75"/><path d="m2.75 11 1 1 1.75-2M8.5 4.5h5M8.5 11.5h5"/>'), |
| 60 |
table: svg('<rect x="2" y="2.5" width="12" height="11" rx="1"/><path d="M2 6.5h12M2 10h12M6.5 6.5v7"/>'), |
| 61 |
full: svg('<path d="M2.5 6V2.5H6M10 2.5h3.5V6M13.5 10v3.5H10M6 13.5H2.5V10"/>') |
| 62 |
}; |
| 63 |
function b(name, action, title, icon, text) { return { name: name, action: action, title: title, icon: icon ? '<span class="mde-ico">' + icon + '</span>' : undefined, text: text, className: "mde-btn" + (text ? " mde-text" : "") }; } |
| 64 |
function task(ed) { |
| 65 |
var cm = ed.codemirror, from = cm.getCursor("from"), to = cm.getCursor("to"); |
| 66 |
for (var l = from.line; l <= to.line; l++) { |
| 67 |
var line = cm.getLine(l), m = line.match(/^(\s*)[-*] \[[ xX]\] /); |
| 68 |
if (m) cm.replaceRange(m[1], { line: l, ch: 0 }, { line: l, ch: m[0].length }); |
| 69 |
else cm.replaceRange("- [ ] ", { line: l, ch: (line.match(/^\s*/) || [""])[0].length }); |
| 70 |
} |
| 71 |
cm.focus(); |
| 72 |
} |
| 73 |
var toolbar = [b("preview", E.togglePreview, "Preview", null, "Preview"), "|", |
| 74 |
b("bold", E.toggleBold, "Bold (Ctrl+B)", I.bold), b("italic", E.toggleItalic, "Italic (Ctrl+I)", I.italic), b("strikethrough", E.toggleStrikethrough, "Strikethrough", I.strike), b("heading", E.toggleHeadingSmaller, "Heading", I.heading), "|", |
| 75 |
b("quote", E.toggleBlockquote, "Quote", I.quote), b("code", E.toggleCodeBlock, "Code", I.code), b("link", E.drawLink, "Link (Ctrl+K)", I.link), "|", |
| 76 |
b("unordered-list", E.toggleUnorderedList, "Bullet list", I.ul), b("ordered-list", E.toggleOrderedList, "Numbered list", I.ol), b("task-list", task, "Task list", I.task), b("table", E.drawTable, "Table", I.table), "|", |
| 77 |
b("fullscreen", E.toggleFullScreen, "Fullscreen", I.full)]; |
| 78 |
mds.forEach(function (t) { |
| 79 |
t._mde = new E({ element: t, spellChecker: false, status: false, forceSync: true, autoDownloadFontAwesome: false, toolbar: toolbar, |
| 80 |
placeholder: t.getAttribute("placeholder") || "Write in Markdown…", minHeight: "120px", sideBySideFullscreen: false }); |
| 81 |
var c = t._mde.element.parentNode.querySelector(".EasyMDEContainer") || t.nextElementSibling; |
| 82 |
if (c && c.classList.contains("EasyMDEContainer")) { |
| 83 |
var f = document.createElement("div"); |
| 84 |
f.className = "mde-foot small mute"; |
| 85 |
f.innerHTML = '<span>Markdown supported</span><span class="mde-md" title="Markdown" aria-hidden="true">M↓</span>'; |
| 86 |
c.appendChild(f); |
| 87 |
} |
| 88 |
}); |
| 4f37afcc Andy McCall ↶ |
89 |
|
| 90 |
window.addEventListener("hashchange", function () { mds.forEach(function (t) { if (t._mde) setTimeout(function () { t._mde.codemirror.refresh(); }, 0); }); }); |
| 14530604 Andy McCall ↶ |
91 |
}); |
| 92 |
|
| 84751769 Andy McCall ↶ |
93 |
|
| 94 |
|
| 95 |
|
| 96 |
|
| 97 |
var diagrams = document.querySelectorAll("pre > code.language-mermaid"); |
| 98 |
if (diagrams.length) load("/static/vendor/mermaid.min.js").then(function () { |
| 99 |
var m = window.mermaid, dark = document.documentElement.dataset.theme === "dark"; |
| 100 |
m.initialize({ startOnLoad: false, securityLevel: "strict", suppressErrorRendering: true, theme: dark ? "dark" : "default" }); |
| 101 |
diagrams.forEach(function (code, i) { |
| 102 |
var pre = code.parentNode, source = code.textContent; |
| 103 |
m.render("mermaid-" + i, source).then(function (r) { |
| 104 |
var fig = document.createElement("figure"); |
| 105 |
fig.className = "mermaid-diagram"; |
| 106 |
fig.innerHTML = r.svg; |
| 107 |
fig.setAttribute("aria-label", "Diagram"); |
| 108 |
pre.replaceWith(fig); |
| 109 |
}).catch(function (e) { |
| 110 |
var note = document.createElement("p"); |
| 111 |
note.className = "small warn"; |
| 112 |
note.textContent = "This diagram could not be drawn: " + ((e && e.message) || e); |
| 113 |
pre.after(note); |
| 114 |
}); |
| 115 |
}); |
| 116 |
}); |
| 117 |
|
| f3e5e2bc Andy McCall ↶ |
118 |
|
| 119 |
|
| 120 |
|
| 121 |
var frames = document.querySelectorAll("iframe.rep-frame"); |
| 122 |
var themeToFrames = function () { |
| 123 |
frames.forEach(function (f) { if (f.contentWindow) f.contentWindow.postMessage({ oxygenhubTheme: document.documentElement.dataset.theme || "dark" }, "*"); }); |
| 124 |
}; |
| 125 |
if (frames.length) window.addEventListener("message", function (e) { |
| 126 |
frames.forEach(function (f) { |
| 127 |
if (e.source !== f.contentWindow) return; |
| 128 |
var r = e.data && e.data.oxygenhubReport; |
| 129 |
if (!r) return; |
| 130 |
if (r.ready) themeToFrames(); |
| 131 |
if (typeof r.height === "number" && r.height > 0) { |
| 132 |
f.style.height = Math.min(Math.max(r.height, 120), 40000) + "px"; |
| 133 |
f.classList.add("sized"); |
| 134 |
} |
| 135 |
}); |
| 136 |
}); |
| 137 |
|
| 95b525b0 Andy McCall ↶ |
138 |
|
| 139 |
|
| 140 |
|
| 141 |
|
| 142 |
if (frames.length) window.addEventListener("message", function (e) { |
| 143 |
frames.forEach(function (f) { |
| 144 |
if (e.source !== f.contentWindow) return; |
| 145 |
var ask = e.data && e.data.oxygenhubAsk; |
| 146 |
if (!ask) return; |
| 147 |
var runs = []; try { runs = JSON.parse(f.dataset.reportRuns || "[]"); } catch (_) {} |
| 148 |
var current = Number(f.dataset.reportCurrent); |
| 149 |
var reply = function (body) { f.contentWindow.postMessage({ oxygenhubAnswer: { n: ask.n, value: body.value, error: body.error } }, "*"); }; |
| 150 |
var meta = function (r) { return { run: r.run, bookmark: r.bookmark, created_ms: r.created_ms, summary: r.summary, current: r.id === current }; }; |
| 151 |
if (ask.what === "run") { |
| 152 |
var r = runs.filter(function (x) { return x.id === current; })[0]; |
| 153 |
reply({ value: r ? meta(r) : null }); |
| 154 |
} else if (ask.what === "history" && typeof ask.dataset === "string" && /^[A-Za-z0-9._+-]+(\/[A-Za-z0-9._+-]+)*$/.test(ask.dataset)) { |
| 155 |
Promise.all(runs.map(function (r) { |
| 156 |
return fetch(r.files + "/data/" + ask.dataset).then(function (res) { return res.ok ? res.text() : null; }).catch(function () { return null; }) |
| 157 |
.then(function (text) { var m = meta(r); m.text = text; return m; }); |
| 158 |
})).then(function (all) { reply({ value: all.filter(function (x) { return x.text !== null; }) }); }); |
| 159 |
} else { |
| 160 |
reply({ error: "ask for run, or history with a file name under data/" }); |
| 161 |
} |
| 162 |
}); |
| 163 |
}); |
| 164 |
|
| 165 |
|
| 166 |
|
| 167 |
var tl = document.querySelector("[data-timeline]"); |
| 168 |
if (tl) { |
| 169 |
var stops = Array.prototype.slice.call(tl.querySelectorAll("[data-tl-stop]")); |
| 170 |
var at = stops.findIndex(function (a) { return a.classList.contains("on"); }); |
| 171 |
var go = function (i, play) { |
| 172 |
if (i < 0 || i >= stops.length) return; |
| 173 |
var u = new URL(stops[i].href, location.href); |
| 174 |
if (play) u.searchParams.set("play", play); else u.searchParams.delete("play"); |
| 175 |
location.href = u.toString(); |
| 176 |
}; |
| 177 |
document.addEventListener("keydown", function (e) { |
| 178 |
if (e.target.closest("input, select, textarea, [contenteditable]")) return; |
| 179 |
if (e.key === "ArrowLeft") { e.preventDefault(); go(at - 1, tl.dataset.play); } |
| 180 |
if (e.key === "ArrowRight") { e.preventDefault(); go(at + 1, tl.dataset.play); } |
| 181 |
}); |
| 182 |
var speed = tl.querySelector("[data-tl-speed]"), button = tl.querySelector("[data-tl-play]"); |
| 183 |
if (button) button.addEventListener("click", function () { |
| 184 |
if (tl.dataset.play) { go(at, null); return; } |
| 185 |
go(at >= stops.length - 1 ? 0 : at + 1, speed ? speed.value : "2"); |
| 186 |
}); |
| 187 |
if (speed) speed.addEventListener("change", function () { if (tl.dataset.play) go(at, speed.value); }); |
| 188 |
if (tl.dataset.play) { |
| 189 |
var next = at + 1; |
| 190 |
if (next < stops.length) setTimeout(function () { go(next, tl.dataset.play); }, Number(tl.dataset.play) * 1000); |
| 191 |
else setTimeout(function () { go(at, null); }, Number(tl.dataset.play) * 1000); |
| 192 |
} |
| 193 |
} |
| 194 |
|
| c40c2d3e Andy McCall ↶ |
195 |
|
| 196 |
var toggle = document.querySelector("[data-theme-toggle]"); |
| 197 |
if (toggle) { |
| d98a93c1 Andy McCall ↶ |
198 |
var root = document.documentElement, order = ["light", "dark", "auto"], glyph = { dark: "◐", light: "☀", auto: "◑" }; |
| c40c2d3e Andy McCall ↶ |
199 |
var show = function () { |
| d98a93c1 Andy McCall ↶ |
200 |
var p = root.dataset.themePref || "light"; |
| c40c2d3e Andy McCall ↶ |
201 |
toggle.title = "Theme: " + p + " (click to change)"; |
| 202 |
toggle.setAttribute("aria-label", toggle.title); |
| 203 |
toggle.firstElementChild.textContent = glyph[p]; |
| 204 |
}; |
| 205 |
show(); |
| 206 |
toggle.addEventListener("click", function () { |
| d98a93c1 Andy McCall ↶ |
207 |
var p = order[(order.indexOf(root.dataset.themePref || "light") + 1) % order.length]; |
| c40c2d3e Andy McCall ↶ |
208 |
document.cookie = "theme=" + p + "; path=/; max-age=31536000; samesite=lax"; |
| 209 |
root.dataset.themePref = p; |
| 210 |
root.dataset.theme = p === "auto" ? (window.matchMedia && matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark") : p; |
| 211 |
show(); |
| f3e5e2bc Andy McCall ↶ |
212 |
themeToFrames(); |
| c40c2d3e Andy McCall ↶ |
213 |
}); |
| 214 |
} |
| 215 |
|
| 9df855f2 Andy McCall ↶ |
216 |
|
| 217 |
var diffs = document.querySelectorAll("table.code.diff"); |
| 218 |
if (diffs.length) { |
| 219 |
var pane = function (tr, col, side) { |
| 220 |
var n = document.createElement("td"), t = document.createElement("td"); |
| 221 |
n.className = "n"; t.className = "t" + (side === "right" ? " mid" : ""); |
| 222 |
if (!tr) { n.className += " none"; t.className += " none"; return [n, t]; } |
| 223 |
var kind = tr.classList.contains("add") ? "add" : tr.classList.contains("del") ? "del" : "ctx"; |
| 224 |
if (kind !== "ctx") { n.className += " " + kind; t.className += " " + kind; } |
| 225 |
n.textContent = tr.cells[col].textContent; |
| 226 |
t.innerHTML = tr.cells[3].innerHTML; |
| 227 |
|
| 228 |
if (side === "left") t.querySelectorAll(".linecomment").forEach(function (d) { d.remove(); }); |
| 229 |
return [n, t]; |
| 230 |
}; |
| 231 |
var split = function (table) { |
| 232 |
var s = document.createElement("table"); |
| 233 |
s.className = "code diff split"; |
| 234 |
s.innerHTML = '<colgroup><col class="n"><col><col class="n"><col></colgroup>'; |
| 235 |
var rows = [].slice.call(table.rows), i = 0; |
| 236 |
var add = function (l, r) { |
| 237 |
var tr = s.insertRow(); |
| 238 |
pane(l, 0, "left").concat(pane(r, 1, "right")).forEach(function (c) { tr.appendChild(c); }); |
| 239 |
}; |
| 240 |
while (i < rows.length) { |
| 241 |
var r = rows[i]; |
| 242 |
if (r.classList.contains("del") || r.classList.contains("add")) { |
| 243 |
var dels = [], adds = []; |
| 244 |
while (i < rows.length && rows[i].classList.contains("del")) dels.push(rows[i++]); |
| 245 |
while (i < rows.length && rows[i].classList.contains("add")) adds.push(rows[i++]); |
| 246 |
for (var k = 0; k < Math.max(dels.length, adds.length); k++) add(dels[k], adds[k]); |
| 247 |
continue; |
| 248 |
} |
| 249 |
if (r.classList.contains("gap") || r.querySelector("td.thread")) { |
| 250 |
var tr = s.insertRow(), td = tr.insertCell(); |
| 251 |
tr.className = r.className; td.colSpan = 4; td.className = r.cells[r.cells.length - 1].className; |
| 252 |
td.innerHTML = r.cells[r.cells.length - 1].innerHTML; |
| 253 |
} else { |
| 254 |
add(r, r); |
| 255 |
} |
| 256 |
i++; |
| 257 |
} |
| 258 |
return s; |
| 259 |
}; |
| 260 |
var cookieMode = (document.cookie.match(/(?:^|; )diff=(split|unified)/) || [])[1] || "unified"; |
| 261 |
var apply = function (mode) { |
| 262 |
diffs.forEach(function (t) { |
| 263 |
if (mode === "split" && !t._split) { t._split = split(t); t.parentNode.insertBefore(t._split, t.nextSibling); } |
| 264 |
t.hidden = mode === "split"; |
| 265 |
if (t._split) t._split.hidden = mode !== "split"; |
| 266 |
}); |
| 267 |
document.querySelectorAll("[data-diff-mode]").forEach(function (a) { a.classList.toggle("on", a.getAttribute("data-diff-mode") === mode); }); |
| 268 |
}; |
| 269 |
document.querySelectorAll("[data-diff-modes], [data-diff-collapse]").forEach(function (e) { e.hidden = false; }); |
| 270 |
document.querySelectorAll("[data-diff-mode]").forEach(function (a) { |
| 271 |
a.addEventListener("click", function (ev) { |
| 272 |
ev.preventDefault(); |
| 273 |
var mode = a.getAttribute("data-diff-mode"); |
| 274 |
document.cookie = "diff=" + mode + "; path=/; max-age=31536000; samesite=lax"; |
| 275 |
apply(mode); |
| 276 |
}); |
| 277 |
}); |
| 278 |
document.querySelectorAll("[data-diff-collapse]").forEach(function (a) { |
| 279 |
a.addEventListener("click", function (ev) { |
| 280 |
ev.preventDefault(); |
| 281 |
var files = document.querySelectorAll("details.file-diff"), anyOpen = [].some.call(files, function (d) { return d.open; }); |
| 282 |
files.forEach(function (d) { d.open = !anyOpen; }); |
| 283 |
a.textContent = anyOpen ? "expand all" : "collapse all"; |
| 284 |
}); |
| 285 |
}); |
| 286 |
apply(cookieMode); |
| 287 |
} |
| 288 |
|
| 64caed18 Andy McCall ↶ |
289 |
|
| 290 |
var navLinks = document.querySelectorAll(".section-nav a[href^='#']"); |
| 291 |
if (navLinks.length && "IntersectionObserver" in window) { |
| 292 |
var byId = {}; |
| 293 |
navLinks.forEach(function (a) { byId[a.getAttribute("href").slice(1)] = a; }); |
| 294 |
var io = new IntersectionObserver(function (entries) { |
| 295 |
entries.forEach(function (e) { |
| 296 |
if (e.isIntersecting && byId[e.target.id]) { |
| 297 |
navLinks.forEach(function (a) { a.classList.remove("on"); }); |
| 298 |
byId[e.target.id].classList.add("on"); |
| 299 |
} |
| 300 |
}); |
| 301 |
}, { rootMargin: "0px 0px -70% 0px" }); |
| 302 |
Object.keys(byId).forEach(function (id) { var el = document.getElementById(id); if (el) io.observe(el); }); |
| 303 |
} |
| 304 |
|
| d23464c0 Andy McCall ↶ |
305 |
|
| 306 |
document.querySelectorAll("[data-copy]").forEach(function (b) { |
| 307 |
b.addEventListener("click", function () { |
| 308 |
navigator.clipboard.writeText(b.getAttribute("data-copy")).then(function () { |
| 309 |
var t = b.textContent; b.textContent = "copied"; setTimeout(function () { b.textContent = t; }, 1200); |
| 310 |
}); |
| 311 |
}); |
| 312 |
}); |
| 313 |
|
| 314 |
|
| 315 |
var tree = document.querySelector("table.tree[data-last]"); |
| 316 |
if (tree) { |
| 317 |
var paths = [].map.call(tree.querySelectorAll("tr[data-path]"), function (r) { return r.getAttribute("data-path"); }); |
| 318 |
if (paths.length) { |
| 319 |
fetch(tree.getAttribute("data-last") + "?paths=" + encodeURIComponent(paths.join(",")), { credentials: "same-origin" }) |
| 320 |
.then(function (r) { return r.json(); }) |
| 321 |
.then(function (rows) { |
| 322 |
rows.forEach(function (c) { |
| 323 |
var tr = tree.querySelector('tr[data-path="' + CSS.escape(c.path) + '"]'); |
| 324 |
if (!tr) return; |
| 325 |
var a = tr.querySelector("td.last a"), t = tr.querySelector("td.age"); |
| 326 |
if (a) { a.textContent = c.title; a.href = tree.getAttribute("data-change") + c.hash; } |
| 327 |
if (t) { t.textContent = c.ago; t.title = c.when; } |
| 328 |
}); |
| 329 |
}).catch(function () {}); |
| 330 |
} |
| 331 |
} |
| 332 |
|
| 333 |
|
| 334 |
function mark() { |
| 335 |
var m = location.hash.match(/^#L(\d+)(?:-L(\d+))?$/); |
| 336 |
document.querySelectorAll("tr.hl").forEach(function (r) { r.classList.remove("hl"); }); |
| 6ae41081 Andy McCall ↶ |
337 |
if (!m) { showBar(0, 0); return; } |
| d23464c0 Andy McCall ↶ |
338 |
var a = +m[1], b = +(m[2] || m[1]); |
| 339 |
for (var i = Math.min(a, b); i <= Math.max(a, b); i++) { |
| 340 |
var row = document.getElementById("L" + i); |
| 341 |
if (row) row.classList.add("hl"); |
| 342 |
} |
| 343 |
var first = document.getElementById("L" + Math.min(a, b)); |
| 344 |
if (first && !mark.done) { first.scrollIntoView({ block: "center" }); mark.done = true; } |
| 6ae41081 Andy McCall ↶ |
345 |
showBar(Math.min(a, b), Math.max(a, b)); |
| 346 |
} |
| 347 |
|
| 348 |
var bar = document.querySelector(".linebar"); |
| 349 |
function showBar(a, b) { |
| 350 |
if (!bar) return; |
| 351 |
bar.hidden = !a; |
| 352 |
if (!a) return; |
| 353 |
bar.querySelector("[data-linebar-label]").textContent = a === b ? "Line " + a : "Lines " + a + "–" + b; |
| 354 |
bar.setAttribute("data-range", a + "-" + b); |
| 355 |
} |
| 356 |
function flash(btn) { var t = btn.textContent; btn.textContent = "Copied"; setTimeout(function () { btn.textContent = t; }, 1200); } |
| 357 |
if (bar) { |
| 358 |
bar.querySelector("[data-copy-lines]").addEventListener("click", function (ev) { |
| 359 |
var r = bar.getAttribute("data-range").split("-"), out = []; |
| 360 |
for (var i = +r[0]; i <= +r[1]; i++) { var row = document.getElementById("L" + i); if (row) out.push(row.querySelector("td.t").textContent); } |
| 361 |
navigator.clipboard.writeText(out.join("\n") + "\n").then(function () { flash(ev.target); }); |
| 362 |
}); |
| 363 |
var pl = bar.querySelector("[data-copy-permalink]"); |
| 364 |
if (pl) pl.addEventListener("click", function () { |
| 365 |
navigator.clipboard.writeText(new URL(document.body.getAttribute("data-permalink"), location.href).href + location.hash).then(function () { flash(pl); }); |
| 366 |
}); |
| d23464c0 Andy McCall ↶ |
367 |
} |
| 6ae41081 Andy McCall ↶ |
368 |
function permalink() { var p = document.body.getAttribute("data-permalink"); return p ? p + location.hash : null; } |
| d23464c0 Andy McCall ↶ |
369 |
window.addEventListener("hashchange", mark); |
| 370 |
mark(); |
| 371 |
document.querySelectorAll("table.code td.n").forEach(function (td) { |
| 372 |
td.addEventListener("click", function (e) { |
| 373 |
var n = td.parentNode.id; |
| 374 |
if (e.shiftKey && location.hash.match(/^#L(\d+)/)) location.hash = location.hash.replace(/^#(L\d+).*/, "$1-" + n); |
| 375 |
else location.hash = n; |
| 376 |
}); |
| 377 |
}); |
| 378 |
|
| 42fa9554 Andy McCall ↶ |
379 |
|
| 380 |
var liveUrl = document.body.getAttribute("data-flow-live"); |
| 381 |
if (liveUrl) { |
| 382 |
var tick = function () { |
| 383 |
var after = [].map.call(document.querySelectorAll("details[data-job]"), function (d) { |
| 384 |
return d.getAttribute("data-job") + ":" + d.querySelector("[data-log]").getAttribute("data-seq"); |
| 385 |
}).join(","); |
| 386 |
fetch(liveUrl + "?after=" + after, { headers: { accept: "application/json" } }) |
| 387 |
.then(function (r) { return r.json(); }) |
| 388 |
.then(function (s) { |
| 389 |
s.jobs.forEach(function (j) { |
| 390 |
var cls = "st-" + j.status; |
| 391 |
var node = document.querySelector("[data-job-node='" + j.id + "']"); |
| 392 |
if (node) { |
| 393 |
node.setAttribute("class", "node " + cls); |
| 394 |
node.querySelector("[data-glyph]").textContent = j.glyph; |
| 395 |
node.querySelector("[data-meta]").textContent = j.status + " · " + j.duration; |
| 396 |
} |
| 397 |
var d = document.querySelector("details[data-job='" + j.id + "']"); |
| 398 |
if (!d) return; |
| 399 |
d.className = "panel flow-job " + cls; |
| 400 |
var g = d.querySelector("summary [data-glyph]"); |
| 401 |
g.className = "flow-glyph " + cls; g.textContent = j.glyph; |
| 402 |
d.querySelector("summary [data-meta]").textContent = j.status + (j.exit_code !== null ? " · exit " + j.exit_code : "") + " · " + j.duration; |
| 403 |
if (j.status === "running" || j.status === "failed") d.open = true; |
| 858eca0d Andy McCall ↶ |
404 |
|
| 405 |
if (j.status !== "queued") [].forEach.call(d.querySelectorAll("[data-queued-note]"), function (p) { p.remove(); }); |
| 42fa9554 Andy McCall ↶ |
406 |
var log = d.querySelector("[data-log]"); |
| 407 |
var stick = log.scrollTop + log.clientHeight >= log.scrollHeight - 4; |
| 408 |
j.lines.forEach(function (l) { |
| 409 |
var ln = document.createElement("span"); ln.className = "ln s-" + l.stream; |
| 410 |
var t = document.createElement("span"); t.className = "t"; t.textContent = (l.t / 1000).toFixed(1) + "s"; |
| 411 |
ln.appendChild(t); ln.appendChild(document.createTextNode(l.text)); |
| 412 |
log.appendChild(ln); log.appendChild(document.createTextNode("\n")); |
| 413 |
log.setAttribute("data-seq", l.seq); |
| 414 |
}); |
| 415 |
if (stick && j.lines.length) log.scrollTop = log.scrollHeight; |
| 416 |
}); |
| 417 |
var st = document.querySelector("[data-run-status]"); if (st) st.textContent = s.status; |
| 418 |
if (s.live) setTimeout(tick, 1500); else setTimeout(function () { location.reload(); }, 800); |
| 419 |
}) |
| 420 |
.catch(function () { setTimeout(tick, 5000); }); |
| 421 |
}; |
| 422 |
setTimeout(tick, 1500); |
| 423 |
} |
| 424 |
|
| d23464c0 Andy McCall ↶ |
425 |
|
| 426 |
var pending = null; |
| 427 |
document.addEventListener("keydown", function (e) { |
| 428 |
if (e.target && /^(INPUT|TEXTAREA|SELECT)$/.test(e.target.tagName)) return; |
| 429 |
if (e.key === "/") { var s = document.querySelector("input[name=q]"); if (s) { e.preventDefault(); s.focus(); } return; } |
| 6ae41081 Andy McCall ↶ |
430 |
if (e.key === "y" && !e.ctrlKey && !e.metaKey && !e.altKey && permalink()) { history.replaceState(null, "", permalink()); pending = null; return; } |
| d23464c0 Andy McCall ↶ |
431 |
if (e.key === "?") { var k = document.getElementById("keys"); if (k) k.hidden = !k.hidden; return; } |
| 432 |
var repo = document.body.getAttribute("data-repo"); |
| 433 |
if (pending === "g" && repo) { |
| 434 |
var to = { c: "", p: "/proposals", i: "/issues", h: "/changes/" + (document.body.getAttribute("data-ref") || "main"), b: "/bookmarks", t: "/trust" }[e.key]; |
| 435 |
if (to !== undefined) location.href = repo + to; |
| 436 |
pending = null; return; |
| 437 |
} |
| 438 |
pending = e.key === "g" ? "g" : null; |
| 439 |
}); |
| 5e6d6484 Andy McCall ↶ |
440 |
|
| 441 |
|
| 442 |
|
| 443 |
|
| 444 |
var live = document.querySelector("[data-resolve-live]"); |
| 445 |
if (live && window.EventSource && window.fetch) { |
| 446 |
var url = live.getAttribute("data-resolve-live"), csrf = live.getAttribute("data-csrf"); |
| 447 |
var client = Math.random().toString(36).slice(2) + Date.now().toString(36); |
| 448 |
var present = document.querySelector("[data-live-present]"), landed = document.querySelector("[data-live-landed]"); |
| 449 |
var applying = false; |
| 450 |
var fieldsOf = function (region) { |
| 451 |
return region === "keep" |
| 452 |
? { radios: live.querySelectorAll('input[name="keep"]'), text: null } |
| 453 |
: { radios: live.querySelectorAll('input[name="r' + region + '"]'), text: live.querySelector('textarea[name="t' + region + '"]') }; |
| 454 |
}; |
| 455 |
var apply = function (region, c) { |
| 456 |
var f = fieldsOf(region); |
| 457 |
applying = true; |
| 458 |
f.radios.forEach(function (r) { r.checked = r.value === c.choice; }); |
| 459 |
if (f.text && c.choice === "text") f.text.value = c.text; |
| 460 |
applying = false; |
| 461 |
var sec = f.radios.length ? f.radios[0].closest("section") : null; |
| 462 |
if (sec) sec.setAttribute("title", "chosen by " + c.by); |
| 463 |
}; |
| 464 |
var send = function (region, choice, text) { |
| 465 |
fetch(url, { method: "POST", headers: { "content-type": "application/json" }, credentials: "same-origin", |
| 466 |
body: JSON.stringify({ _csrf: csrf, client: client, region: region, choice: choice, text: text || "" }) }); |
| 467 |
}; |
| 468 |
var timers = {}; |
| 469 |
live.addEventListener("change", function (ev) { |
| 470 |
var t = ev.target; |
| 471 |
if (applying || !t.name || t.type !== "radio") return; |
| 472 |
var region = t.name === "keep" ? "keep" : t.name.slice(1); |
| 473 |
var ta = live.querySelector('textarea[name="t' + region + '"]'); |
| 474 |
send(region, t.value, t.value === "text" && ta ? ta.value : ""); |
| 475 |
}); |
| 476 |
live.addEventListener("input", function (ev) { |
| 477 |
var t = ev.target; |
| 478 |
if (applying || t.tagName !== "TEXTAREA") return; |
| 479 |
var region = t.name.slice(1); |
| 480 |
live.querySelectorAll('input[name="r' + region + '"]').forEach(function (r) { r.checked = r.value === "text"; }); |
| 481 |
clearTimeout(timers[region]); |
| 482 |
timers[region] = setTimeout(function () { send(region, "text", t.value); }, 400); |
| 483 |
}); |
| 484 |
var es = new EventSource(url + "?client=" + encodeURIComponent(client)); |
| 485 |
var showPresent = function (names) { |
| 486 |
present.hidden = names.length < 2; |
| 487 |
present.textContent = "Resolving together: " + names.join(", ") + ". Choices are shared as you make them; the last choice for a conflict wins."; |
| 488 |
}; |
| 489 |
es.addEventListener("snapshot", function (e) { |
| 490 |
var d = JSON.parse(e.data); |
| 491 |
showPresent(d.present); |
| 492 |
Object.keys(d.choices).forEach(function (r) { apply(r, d.choices[r]); }); |
| 493 |
if (d.keep) apply("keep", d.keep); |
| 494 |
}); |
| 495 |
es.addEventListener("presence", function (e) { showPresent(JSON.parse(e.data).present); }); |
| 496 |
es.addEventListener("choice", function (e) { |
| 497 |
var d = JSON.parse(e.data); |
| 498 |
if (d.client !== client) apply(d.region, d.choice); |
| 499 |
}); |
| 500 |
es.addEventListener("landed", function (e) { |
| 501 |
var d = JSON.parse(e.data); |
| 502 |
es.close(); |
| 503 |
landed.hidden = false; |
| 504 |
landed.textContent = ""; |
| 505 |
landed.appendChild(document.createTextNode(d.by + " committed the resolution: ")); |
| 506 |
var a = document.createElement("a"); |
| 507 |
a.href = d.url; |
| 508 |
a.textContent = "see the change"; |
| 509 |
landed.appendChild(a); |
| 510 |
live.querySelectorAll("input, textarea, button").forEach(function (x) { x.disabled = true; }); |
| 511 |
}); |
| 512 |
} |
| 2bfe5ef6 Andy McCall ↶ |
513 |
|
| 514 |
|
| 515 |
|
| 516 |
|
| 517 |
var plan = document.querySelector("[data-plan]"); |
| 518 |
if (plan && window.fetch) { |
| 519 |
var panel = document.querySelector("[data-plan-panel]"), from = null, moved = false; |
| 520 |
plan.querySelectorAll("[data-change]").forEach(function (a) { |
| 521 |
a.style.cursor = "grab"; |
| 522 |
a.addEventListener("pointerdown", function (ev) { from = a.getAttribute("data-change"); moved = false; ev.preventDefault(); }); |
| 523 |
a.addEventListener("pointermove", function () { if (from) moved = true; }); |
| 524 |
a.addEventListener("click", function (ev) { if (moved) ev.preventDefault(); }); |
| 525 |
}); |
| 526 |
document.addEventListener("pointerup", function (ev) { |
| 527 |
var start = from; |
| 528 |
from = null; |
| 529 |
if (!start) return; |
| 530 |
var el = document.elementFromPoint(ev.clientX, ev.clientY), onto = el && el.closest ? el.closest("[data-change]") : null; |
| 531 |
if (!onto || onto.getAttribute("data-change") === start) return; |
| 532 |
var body = new URLSearchParams({ _csrf: plan.getAttribute("data-csrf"), change: start, target: onto.getAttribute("data-change") }); |
| 533 |
fetch(plan.getAttribute("data-plan"), { method: "POST", credentials: "same-origin", body: body }) |
| 534 |
.then(function (r) { return r.json(); }) |
| 535 |
.then(function (d) { |
| 536 |
panel.hidden = false; |
| 537 |
panel.textContent = ""; |
| 538 |
if (d.error) { panel.textContent = d.error; return; } |
| 539 |
d.options.forEach(function (o) { |
| 540 |
var p = document.createElement("p"); |
| 541 |
p.appendChild(document.createTextNode(o.summary + " ")); |
| 542 |
var a = document.createElement("a"); |
| 543 |
a.href = o.vscode; |
| 544 |
a.textContent = "Apply in VS Code"; |
| 545 |
p.appendChild(a); |
| 546 |
var code = document.createElement("pre"); |
| 547 |
code.className = "snippet"; |
| 548 |
code.textContent = o.command; |
| 549 |
panel.appendChild(p); |
| 550 |
panel.appendChild(code); |
| 551 |
}); |
| 552 |
}); |
| 553 |
}); |
| 554 |
} |
| cb71e18e Andy McCall ↶ |
555 |
|
| 556 |
|
| 557 |
|
| 558 |
document.querySelectorAll("[data-menu-filter]").forEach(function (input) { |
| 559 |
var items = input.closest(".menu-pop").querySelectorAll(".menu-item"); |
| 560 |
input.addEventListener("input", function () { |
| 561 |
var q = input.value.trim().toLowerCase(); |
| 562 |
items.forEach(function (it) { it.hidden = q !== "" && it.textContent.toLowerCase().indexOf(q) < 0; }); |
| 563 |
}); |
| 564 |
}); |
| 565 |
document.querySelectorAll("details.menu").forEach(function (d) { |
| 566 |
d.addEventListener("toggle", function () { |
| 567 |
var f = d.querySelector("[data-menu-filter]"); |
| 568 |
if (d.open && f) f.focus(); |
| 569 |
}); |
| 570 |
}); |
| 571 |
document.addEventListener("click", function (ev) { |
| 572 |
document.querySelectorAll("details.menu[open]").forEach(function (d) { if (!d.contains(ev.target)) d.open = false; }); |
| 573 |
}); |
| 4f37afcc Andy McCall ↶ |
574 |
|
| 575 |
|
| 576 |
function copied(btn, text) { |
| 577 |
if (navigator.clipboard) navigator.clipboard.writeText(text).then(function () { |
| 578 |
var was = btn.textContent; btn.textContent = "Copied"; setTimeout(function () { btn.textContent = was; }, 1200); |
| 579 |
}); |
| 580 |
var d = btn.closest("details"); if (d) d.open = false; |
| 581 |
} |
| 582 |
document.querySelectorAll("[data-copy-link]").forEach(function (b) { |
| 583 |
b.addEventListener("click", function () { copied(b, location.origin + location.pathname + location.search + b.getAttribute("data-copy-link")); }); |
| 584 |
}); |
| 585 |
document.querySelectorAll("[data-copy-text]").forEach(function (b) { |
| 586 |
b.addEventListener("click", function () { copied(b, b.getAttribute("data-copy-text")); }); |
| 587 |
}); |
| 588 |
document.querySelectorAll('.menu-actions a[href^="#"]').forEach(function (a) { |
| 589 |
a.addEventListener("click", function () { var d = a.closest("details"); if (d) d.open = false; }); |
| 590 |
}); |
| ed89fae5 Andy McCall ↶ |
591 |
|
| 592 |
|
| 593 |
|
| 594 |
|
| 595 |
document.addEventListener("submit", function (e) { |
| 596 |
var sec = e.target.closest ? e.target.closest("section[id], form[id], details[id], div[id]") : null; |
| 597 |
if (!sec || !sec.id) return; |
| 598 |
try { sessionStorage.setItem("oxy-return", location.pathname + "#" + sec.id); } catch (err) { } |
| 599 |
}); |
| 600 |
try { |
| 601 |
var back = sessionStorage.getItem("oxy-return"); |
| 602 |
if (back && back.indexOf(location.pathname + "#") === 0) { |
| 603 |
sessionStorage.removeItem("oxy-return"); |
| 604 |
var target = document.getElementById(back.split("#")[1]); |
| 605 |
if (target) { |
| 606 |
var flash = document.querySelector("main > .note, main > .error, .sections > .note, .sections > .error"); |
| 607 |
if (flash && !target.contains(flash)) target.parentNode.insertBefore(flash, target); |
| 608 |
target.scrollIntoView({ block: "start" }); |
| 609 |
} |
| 610 |
} |
| 611 |
} catch (err) { } |
| 155cab14 Andy McCall ↶ |
612 |
|
| 16626c0d Andy McCall ↶ |
613 |
|
| 614 |
|
| 615 |
|
| 616 |
|
| 617 |
|
| 618 |
var SPIN = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; |
| 619 |
var waitTimer = 0, spinTimer = 0, pointer = null, mark = null; |
| 620 |
document.addEventListener("pointermove", function (e) { |
| 621 |
pointer = e.pointerType === "mouse" ? { x: e.clientX, y: e.clientY } : null; |
| 622 |
if (mark && pointer) place(); |
| 623 |
}, { passive: true }); |
| 624 |
function place() { |
| 625 |
if (pointer) { mark.style.left = pointer.x + 14 + "px"; mark.style.top = pointer.y + 14 + "px"; mark.classList.remove("corner"); } |
| 626 |
else mark.classList.add("corner"); |
| 627 |
} |
| 628 |
function waiting() { |
| 629 |
clearTimeout(waitTimer); |
| 630 |
waitTimer = setTimeout(function () { |
| 631 |
if (!mark) { |
| 632 |
var logo = document.querySelector("header .brand svg"); |
| 633 |
mark = document.createElement("div"); |
| 634 |
mark.className = "oxy-wait-mark"; |
| 635 |
mark.setAttribute("role", "status"); |
| 636 |
mark.setAttribute("aria-label", "Working"); |
| 637 |
if (logo) mark.appendChild(logo.cloneNode(true)); |
| 638 |
document.body.appendChild(mark); |
| 639 |
} |
| 640 |
place(); |
| 641 |
document.documentElement.classList.add("oxy-wait"); |
| 642 |
}, 300); |
| 643 |
} |
| 644 |
function busy(button, form) { |
| 645 |
if (!button) return; |
| 646 |
var label = button.getAttribute("data-busy") || button.textContent.trim(); |
| 647 |
button.dataset.idle = button.innerHTML; |
| 648 |
button.style.minWidth = button.offsetWidth + "px"; |
| 649 |
button.textContent = label + " "; |
| 650 |
var glyph = document.createElement("span"); |
| 651 |
glyph.className = "oxy-spin"; |
| 652 |
glyph.setAttribute("aria-hidden", "true"); |
| 653 |
glyph.textContent = SPIN[0]; |
| 654 |
button.appendChild(glyph); |
| 655 |
button.setAttribute("aria-busy", "true"); |
| 656 |
var i = 0; |
| 657 |
clearInterval(spinTimer); |
| 658 |
spinTimer = setInterval(function () { glyph.textContent = SPIN[++i % SPIN.length]; }, 80); |
| 659 |
|
| 660 |
|
| 661 |
setTimeout(function () { button.disabled = true; }, 0); |
| 662 |
form.dataset.sending = "1"; |
| 663 |
} |
| 664 |
document.addEventListener("submit", function (e) { |
| 665 |
var form = e.target; |
| 666 |
if (form.dataset.sending) { e.preventDefault(); return; } |
| 667 |
if (e.defaultPrevented || (form.target && form.target !== "_self")) return; |
| 668 |
if ((form.getAttribute("method") || "get").toLowerCase() === "post") { |
| 669 |
busy(e.submitter || form.querySelector("button[type=submit], button:not([type])"), form); |
| 670 |
} |
| 671 |
waiting(); |
| 672 |
}); |
| 673 |
document.addEventListener("click", function (e) { |
| 674 |
if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return; |
| 675 |
var a = e.target.closest ? e.target.closest("a[href]") : null; |
| 676 |
if (!a || a.hasAttribute("download") || (a.target && a.target !== "_self")) return; |
| 677 |
var url = new URL(a.href, location.href); |
| 678 |
if (url.origin !== location.origin) return; |
| 679 |
if (url.pathname === location.pathname && url.search === location.search && url.hash) return; |
| 680 |
waiting(); |
| 681 |
}); |
| 682 |
|
| 683 |
window.addEventListener("pageshow", function (e) { |
| 684 |
if (!e.persisted) return; |
| 685 |
clearTimeout(waitTimer); |
| 686 |
clearInterval(spinTimer); |
| 687 |
document.documentElement.classList.remove("oxy-wait"); |
| 688 |
document.querySelectorAll("[aria-busy=true][data-idle]").forEach(function (b) { |
| 689 |
b.innerHTML = b.dataset.idle; |
| 690 |
b.disabled = false; |
| 691 |
b.removeAttribute("aria-busy"); |
| 692 |
b.style.minWidth = ""; |
| 693 |
if (b.form) delete b.form.dataset.sending; |
| 694 |
}); |
| 695 |
}); |
| 696 |
|
| 155cab14 Andy McCall ↶ |
697 |
|
| 698 |
|
| 699 |
|
| 700 |
document.querySelectorAll("[data-preset-select]").forEach(function (sel) { |
| 701 |
var form = sel.form; |
| 702 |
function apply() { |
| 703 |
var o = sel.options[sel.selectedIndex]; |
| 704 |
if (!o || !o.value) return; |
| 705 |
var name = form.querySelector("[name=name]"), ep = form.querySelector("[name=endpoint]"), api = form.querySelector("[name=api]"); |
| 706 |
name.placeholder = o.dataset.name; ep.value = o.dataset.endpoint; api.value = o.dataset.api; |
| 707 |
} |
| 708 |
sel.addEventListener("change", apply); |
| 709 |
apply(); |
| 710 |
}); |
| 711 |
document.querySelectorAll("[data-list-models]").forEach(function (b) { |
| 712 |
b.addEventListener("click", function () { |
| 713 |
var form = b.form, input = document.getElementById(b.dataset.for); |
| 714 |
var list = document.getElementById(b.dataset.for + "-list"), note = document.querySelector("[data-models-note='" + b.dataset.for + "']"); |
| 715 |
var body = new URLSearchParams(); |
| 716 |
body.set("_csrf", b.dataset.csrf); |
| 717 |
["endpoint", "api", "token", "preset"].forEach(function (k) { var el = form.querySelector("[name=" + k + "]"); if (el) body.set(k, el.value); }); |
| 718 |
if (b.dataset.id) body.set("id", b.dataset.id); |
| 719 |
if (note) note.textContent = "Asking the provider…"; |
| 720 |
fetch(b.dataset.listModels, { method: "POST", body: body, credentials: "same-origin" }) |
| 721 |
.then(function (r) { return r.json(); }) |
| 722 |
.then(function (j) { |
| 723 |
if (j.models) { |
| 724 |
list.innerHTML = ""; |
| 725 |
j.models.forEach(function (m) { var o = document.createElement("option"); o.value = m; list.appendChild(o); }); |
| 726 |
if (note) note.textContent = j.models.length + " models: pick one in the Model field."; |
| 727 |
input.focus(); |
| 728 |
} else if (note) { |
| 729 |
note.textContent = "No list: " + (j.error || "unknown") + ". Type the model's name."; |
| 730 |
} |
| 731 |
}) |
| 732 |
.catch(function () { if (note) note.textContent = "The hub could not ask; type the model's name."; }); |
| 733 |
}); |
| 734 |
}); |
| d23464c0 Andy McCall ↶ |
735 |
})(); |
| 67be8ac0 Andy McCall ↶ |
736 |
|
| 737 |
|
| 738 |
|
| 739 |
|
| 740 |
|
| 741 |
|
| 742 |
|
| 743 |
(function () { |
| 744 |
var marked = document.querySelectorAll("[data-live][data-fragment]"); |
| 745 |
if (!marked.length || !window.EventSource || !window.fetch) return; |
| 746 |
var topics = {}; |
| b5a0a69b Andy McCall ↶ |
747 |
|
| 748 |
var topicsOf = function (el) { return el.getAttribute("data-live").split(/\s+/).filter(Boolean); }; |
| 749 |
Array.prototype.forEach.call(marked, function (el) { topicsOf(el).forEach(function (t) { topics[t] = true; }); }); |
| 67be8ac0 Andy McCall ↶ |
750 |
var busy = {}; |
| 751 |
var typingIn = function (el) { |
| 752 |
var a = document.activeElement; |
| 753 |
return a && el.contains(a) && (a.tagName === "TEXTAREA" || (a.tagName === "INPUT" && a.type !== "hidden")) && a.value; |
| 754 |
}; |
| 755 |
var refresh = function (el) { |
| 756 |
var name = el.getAttribute("data-fragment"); |
| 757 |
if (busy[name]) return; |
| 758 |
if (typingIn(el)) { |
| 759 |
el.addEventListener("focusout", function again() { |
| 760 |
el.removeEventListener("focusout", again); |
| 761 |
setTimeout(function () { refresh(el); }, 0); |
| 762 |
}); |
| 763 |
return; |
| 764 |
} |
| 765 |
busy[name] = true; |
| 766 |
var url = new URL(location.href); |
| 767 |
url.searchParams.set("fragment", name); |
| 768 |
fetch(url.toString(), { credentials: "same-origin", headers: { "X-Fragment": name } }) |
| 769 |
.then(function (r) { return r.ok ? r.text() : null; }) |
| 770 |
.then(function (html) { |
| 771 |
busy[name] = false; |
| 772 |
if (html !== null && !typingIn(el)) el.innerHTML = html; |
| 773 |
}) |
| 774 |
.catch(function () { busy[name] = false; }); |
| 775 |
}; |
| 776 |
var es = new EventSource("/live?topics=" + encodeURIComponent(Object.keys(topics).join(","))); |
| 777 |
es.addEventListener("change", function (e) { |
| 778 |
var d; |
| 779 |
try { d = JSON.parse(e.data); } catch (err) { return; } |
| 780 |
Array.prototype.forEach.call(marked, function (el) { |
| b5a0a69b Andy McCall ↶ |
781 |
if (topicsOf(el).indexOf(d.topic) >= 0) refresh(el); |
| 67be8ac0 Andy McCall ↶ |
782 |
}); |
| 783 |
}); |
| 784 |
|
| 785 |
es.addEventListener("reload", function () { |
| 786 |
Array.prototype.forEach.call(marked, refresh); |
| 787 |
}); |
| 788 |
})(); |
| 119fd17d Andy McCall ↶ |
789 |
|
| e97500b7 Andy McCall ↶ |
790 |
|
| 791 |
|
| 792 |
|
| 793 |
|
| 794 |
(function () { |
| 795 |
"use strict"; |
| 796 |
var parts = document.querySelectorAll("[data-refresh][data-fragment]"); |
| 797 |
if (!parts.length || !window.fetch || !window.DOMParser) return; |
| 798 |
var every = Math.max(10, parseInt(parts[0].getAttribute("data-refresh"), 10) || 30) * 1000; |
| 799 |
var busy = false; |
| 800 |
var inUse = function (el) { |
| 801 |
var a = document.activeElement; |
| 802 |
return a && el.contains(a) && /^(SELECT|INPUT|TEXTAREA)$/.test(a.tagName); |
| 803 |
}; |
| 804 |
var tick = function () { |
| 805 |
if (busy || document.hidden) return; |
| 806 |
busy = true; |
| 807 |
fetch(location.href, { credentials: "same-origin", headers: { "X-Fragment": "page" } }) |
| 808 |
.then(function (r) { return r.ok ? r.text() : null; }) |
| 809 |
.then(function (html) { |
| 810 |
busy = false; |
| 811 |
if (html === null) return; |
| 812 |
var doc = new DOMParser().parseFromString(html, "text/html"); |
| 813 |
Array.prototype.forEach.call(parts, function (el) { |
| 814 |
if (inUse(el)) return; |
| 815 |
var fresh = doc.querySelector('[data-fragment="' + el.getAttribute("data-fragment") + '"]'); |
| 816 |
if (fresh) el.innerHTML = fresh.innerHTML; |
| 817 |
}); |
| 818 |
}) |
| 819 |
.catch(function () { busy = false; }); |
| 820 |
}; |
| 821 |
setInterval(tick, every); |
| 822 |
document.addEventListener("visibilitychange", function () { if (!document.hidden) tick(); }); |
| 823 |
})(); |
| 824 |
|
| 119fd17d Andy McCall ↶ |
825 |
|
| 826 |
|
| 827 |
|
| 828 |
|
| 829 |
(function () { |
| 830 |
"use strict"; |
| 831 |
if (!window.fetch || !window.TextDecoder || !window.URLSearchParams) return; |
| 832 |
document.querySelectorAll("button.agent-btn[data-stream]").forEach(function (btn) { |
| 833 |
btn.addEventListener("click", function (e) { |
| 834 |
var form = btn.form, area = form && form.querySelector('textarea[name="body"]'); |
| 835 |
if (!form || !area) return; |
| 836 |
e.preventDefault(); |
| 837 |
function get() { return area._mde ? area._mde.value() : area.value; } |
| 838 |
function show(t) { if (area._mde) area._mde.value(t); else area.value = t; } |
| c43e4f63 Andy McCall ↶ |
839 |
|
| 840 |
|
| 841 |
var titleField = form.querySelector('input[name="title"]'); |
| 842 |
function untitled(t) { return t.replace(/^\s*title:[^\n]*(\n\s*|$)/i, ""); } |
| 119fd17d Andy McCall ↶ |
843 |
var before = get(), text = ""; |
| 844 |
var box = (area._mde && area.parentNode.querySelector(".EasyMDEContainer")) || area; |
| 845 |
var note = form.querySelector(".draft-note"); |
| 846 |
if (!note) { note = document.createElement("p"); note.className = "draft-note small mute"; box.parentNode.insertBefore(note, box.nextSibling); } |
| 847 |
note.textContent = btn.value + " is drafting the description…"; |
| 848 |
var buttons = form.querySelectorAll("button.agent-btn"); |
| 849 |
buttons.forEach(function (b) { b.disabled = true; }); |
| 850 |
var data = new URLSearchParams(new FormData(form)); |
| 851 |
data.set("assistant", btn.value); |
| 852 |
var finished = false; |
| 853 |
function end(message, keep) { finished = true; if (!keep) show(before); note.textContent = message; } |
| 854 |
fetch(btn.dataset.stream, { method: "POST", body: data, credentials: "same-origin" }) |
| 855 |
.then(function (r) { |
| 856 |
if (!r.ok || !r.body) throw new Error("the hub answered " + r.status); |
| 857 |
var reader = r.body.getReader(), dec = new TextDecoder(), buf = ""; |
| 858 |
function pump() { |
| 859 |
return reader.read().then(function (res) { |
| 860 |
if (res.done) { if (!finished) end(btn.value + " stopped before finishing.", text !== ""); return; } |
| 861 |
buf += dec.decode(res.value, { stream: true }); |
| 862 |
var i; |
| 863 |
while ((i = buf.indexOf("\n\n")) >= 0) { |
| 864 |
var block = buf.slice(0, i), kind = "message", payload = ""; |
| 865 |
buf = buf.slice(i + 2); |
| 866 |
block.split("\n").forEach(function (l) { |
| 867 |
if (l.indexOf("event:") === 0) kind = l.slice(6).trim(); |
| 868 |
else if (l.indexOf("data:") === 0) payload += l.slice(5).trim(); |
| 869 |
}); |
| 870 |
if (!payload) continue; |
| 871 |
var v; |
| 872 |
try { v = JSON.parse(payload); } catch (_) { continue; } |
| c43e4f63 Andy McCall ↶ |
873 |
if (kind === "part") { text += v; show(untitled(text)); } |
| 874 |
else if (kind === "title") { |
| 875 |
if (titleField && (!titleField.value.trim() || titleField.value === titleField.defaultValue)) titleField.value = v; |
| 876 |
} |
| 119fd17d Andy McCall ↶ |
877 |
else if (kind === "done") { show(v); end("Drafted by " + btn.value + "; nothing is saved until you save the proposal.", true); return; } |
| 878 |
else if (kind === "error") { end(v, false); return; } |
| 879 |
} |
| 880 |
return pump(); |
| 881 |
}); |
| 882 |
} |
| 883 |
return pump(); |
| 884 |
}) |
| 885 |
.catch(function (err) { end(btn.value + " did not answer: " + err.message + ".", false); }) |
| 886 |
.then(function () { buttons.forEach(function (b) { b.disabled = false; }); }); |
| 887 |
}); |
| 888 |
}); |
| a7aa76ac Andy McCall |
889 |
|
| 890 |
|
| 891 |
|
| 892 |
|
| 893 |
|
| 894 |
document.addEventListener("click", function (e) { |
| 895 |
var el = e.target.closest && e.target.closest("[data-confirm]"); |
| 896 |
if (el && el.tagName !== "FORM" && !window.confirm(el.getAttribute("data-confirm"))) { |
| 897 |
e.preventDefault(); |
| 898 |
e.stopImmediatePropagation(); |
| 899 |
} |
| 900 |
}, true); |
| 901 |
document.addEventListener("submit", function (e) { |
| 902 |
var f = e.target; |
| 903 |
if (f.hasAttribute && f.hasAttribute("data-confirm") && !window.confirm(f.getAttribute("data-confirm"))) e.preventDefault(); |
| 904 |
}, true); |
| 905 |
document.addEventListener("change", function (e) { |
| 906 |
var el = e.target; |
| 907 |
if (el.hasAttribute && el.hasAttribute("data-autosubmit") && el.form) el.form.submit(); |
| 908 |
}); |
| 909 |
function selectAll(e) { |
| 910 |
var el = e.target; |
| 911 |
if (el.hasAttribute && el.hasAttribute("data-select") && el.select) el.select(); |
| 912 |
} |
| 913 |
document.addEventListener("focusin", selectAll); |
| 914 |
document.addEventListener("click", selectAll); |
| 915 |
|
| 916 |
|
| 917 |
(function () { |
| 918 |
var sel = document.querySelector("[data-mail-service]"); |
| 919 |
if (!sel) return; |
| 920 |
var show = function () { |
| 921 |
document.querySelectorAll(".mail-panel [data-for]").forEach(function (el) { |
| 922 |
el.hidden = el.getAttribute("data-for").split(" ").indexOf(sel.value) < 0; |
| 923 |
}); |
| 924 |
}; |
| 925 |
sel.addEventListener("change", show); |
| 926 |
show(); |
| 927 |
})(); |
| d366306d Andy McCall ↶ |
928 |
|
| 929 |
|
| 930 |
|
| 931 |
|
| 932 |
(function () { |
| 933 |
var list = document.querySelector("[data-drop-files]"); |
| 934 |
var add = document.querySelector("[data-drop-add]"); |
| 935 |
if (!list || !add) return; |
| 936 |
function wire(row) { |
| 937 |
var rm = row.querySelector("[data-drop-remove]"); |
| 938 |
if (!rm) return; |
| 939 |
rm.hidden = false; |
| 940 |
rm.addEventListener("click", function () { |
| 941 |
if (list.querySelectorAll("[data-drop-file]").length > 1) row.remove(); |
| 942 |
else row.querySelectorAll("input, textarea").forEach(function (f) { f.value = ""; }); |
| 943 |
}); |
| 944 |
} |
| 945 |
list.querySelectorAll("[data-drop-file]").forEach(wire); |
| 946 |
add.hidden = false; |
| 947 |
add.addEventListener("click", function () { |
| 948 |
var rows = list.querySelectorAll("[data-drop-file]"); |
| 949 |
var row = rows[rows.length - 1].cloneNode(true); |
| 950 |
row.querySelectorAll("input, textarea").forEach(function (f) { f.value = ""; f.textContent = ""; }); |
| 951 |
list.appendChild(row); |
| 952 |
wire(row); |
| 953 |
row.querySelector("input").focus(); |
| 954 |
}); |
| 955 |
})(); |
| 956 |
|
| 957 |
|
| 958 |
|
| 959 |
|
| 960 |
|
| 961 |
(function () { |
| 962 |
var nav = document.querySelector("[data-settings-anchors]"); |
| 963 |
var hash = location.hash.slice(1); |
| 964 |
if (!nav || !/^[a-z-]+$/.test(hash)) return; |
| 965 |
var moved = { "history-scan": "push-protection", "flow-priority": "runs", "flow-supersede": "runs", "agent-gates": "gates" }; |
| 966 |
var link = nav.querySelector('a[data-slug="' + (moved[hash] || hash) + '"]'); |
| 967 |
if (link && link.getAttribute("aria-current") !== "page") location.replace(link.getAttribute("href") + "#" + hash); |
| 968 |
})(); |
| 119fd17d Andy McCall ↶ |
969 |
})(); |