@youtyan/code-viewer 0.1.18 → 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/web/app.js CHANGED
@@ -274,7 +274,7 @@
274
274
  const basename = lowerPath.slice(baseStart);
275
275
  if (basename.startsWith(q))
276
276
  score += 30;
277
- if (basename === q || basename.startsWith(q + "."))
277
+ if (basename === q || basename.startsWith(`${q}.`))
278
278
  score += 25;
279
279
  if (lowerPath.endsWith(q))
280
280
  score += 15;
@@ -290,7 +290,7 @@
290
290
  return /[*?]/.test(query.trim());
291
291
  }
292
292
  function escapeRegexChar(ch) {
293
- return /[\\^$+?.()|{}]/.test(ch) ? "\\" + ch : ch;
293
+ return /[\\^$+?.()|{}]/.test(ch) ? `\\${ch}` : ch;
294
294
  }
295
295
  function globToRegExp(query) {
296
296
  const pattern = query.trim();
@@ -314,7 +314,7 @@
314
314
  source += "\\[";
315
315
  } else {
316
316
  const body = pattern.slice(i + 1, close).replace(/\\/g, "\\\\");
317
- source += "[" + body + "]";
317
+ source += `[${body}]`;
318
318
  i = close;
319
319
  }
320
320
  } else {
@@ -359,22 +359,58 @@
359
359
  if (isGlobPathQuery(query)) {
360
360
  return items.map((item) => {
361
361
  const match = globMatchPath(query, item.path);
362
- return match ? { item, score: match.score, ranges: match.ranges, mode: "glob" } : null;
362
+ return match ? {
363
+ item,
364
+ score: match.score,
365
+ ranges: match.ranges,
366
+ mode: "glob"
367
+ } : null;
363
368
  }).filter((item) => item !== null).sort((a, b) => b.score - a.score || a.item.path.localeCompare(b.item.path));
364
369
  }
365
- return rankFuzzyPaths(query, items).map((item) => ({ ...item, mode: "fuzzy" }));
370
+ return rankFuzzyPaths(query, items).map((item) => ({
371
+ ...item,
372
+ mode: "fuzzy"
373
+ }));
366
374
  }
367
375
 
368
376
  // web-src/keymap.ts
369
377
  var DEFAULT_KEY_BINDINGS = [
370
- { action: "open-file-palette", key: "k", ctrl: true, allowEditable: true, allowPaletteOpen: true },
371
- { action: "open-file-palette", key: "k", meta: true, allowEditable: true, allowPaletteOpen: true },
372
- { action: "open-grep-palette", key: "g", ctrl: true, allowEditable: true, allowPaletteOpen: true },
373
- { action: "open-grep-palette", key: "g", meta: true, allowEditable: true, allowPaletteOpen: true },
378
+ {
379
+ action: "open-file-palette",
380
+ key: "k",
381
+ ctrl: true,
382
+ allowEditable: true,
383
+ allowPaletteOpen: true
384
+ },
385
+ {
386
+ action: "open-file-palette",
387
+ key: "k",
388
+ meta: true,
389
+ allowEditable: true,
390
+ allowPaletteOpen: true
391
+ },
392
+ {
393
+ action: "open-grep-palette",
394
+ key: "g",
395
+ ctrl: true,
396
+ allowEditable: true,
397
+ allowPaletteOpen: true
398
+ },
399
+ {
400
+ action: "open-grep-palette",
401
+ key: "g",
402
+ meta: true,
403
+ allowEditable: true,
404
+ allowPaletteOpen: true
405
+ },
374
406
  { action: "focus-file-filter", key: "/" },
375
407
  { action: "focus-sidebar", key: "h", ctrl: true },
376
408
  { action: "focus-main", key: "l", ctrl: true },
377
- { action: "cancel-source-load", key: "escape", requires: { lightboxClosed: true } },
409
+ {
410
+ action: "cancel-source-load",
411
+ key: "escape",
412
+ requires: { lightboxClosed: true }
413
+ },
378
414
  { action: "open-sidebar-item", key: "enter", scope: "sidebar" },
379
415
  { action: "open-sidebar-item", key: "enter", scope: "global" },
380
416
  { action: "sidebar-next", key: "j", scope: "sidebar" },
@@ -399,12 +435,37 @@
399
435
  { action: "scroll-main-page-up", key: "pageup", scope: "global" },
400
436
  { action: "scroll-main-page-down", key: "pagedown", scope: "sidebar" },
401
437
  { action: "scroll-main-page-up", key: "pageup", scope: "sidebar" },
402
- { action: "scroll-main-page-down", key: "arrowdown", scope: "main", ctrl: true },
438
+ {
439
+ action: "scroll-main-page-down",
440
+ key: "arrowdown",
441
+ scope: "main",
442
+ ctrl: true
443
+ },
403
444
  { action: "scroll-main-page-up", key: "arrowup", scope: "main", ctrl: true },
404
- { action: "scroll-main-page-down", key: "arrowdown", scope: "global", ctrl: true },
405
- { action: "scroll-main-page-up", key: "arrowup", scope: "global", ctrl: true },
406
- { action: "scroll-main-page-down", key: "arrowdown", scope: "sidebar", ctrl: true },
407
- { action: "scroll-main-page-up", key: "arrowup", scope: "sidebar", ctrl: true },
445
+ {
446
+ action: "scroll-main-page-down",
447
+ key: "arrowdown",
448
+ scope: "global",
449
+ ctrl: true
450
+ },
451
+ {
452
+ action: "scroll-main-page-up",
453
+ key: "arrowup",
454
+ scope: "global",
455
+ ctrl: true
456
+ },
457
+ {
458
+ action: "scroll-main-page-down",
459
+ key: "arrowdown",
460
+ scope: "sidebar",
461
+ ctrl: true
462
+ },
463
+ {
464
+ action: "scroll-main-page-up",
465
+ key: "arrowup",
466
+ scope: "sidebar",
467
+ ctrl: true
468
+ },
408
469
  { action: "tab-preview", key: "p", scope: "main", pendingG: true },
409
470
  { action: "tab-code", key: "c", scope: "main", pendingG: true },
410
471
  { action: "goto-top", key: "g", pendingG: true },
@@ -6031,7 +6092,7 @@
6031
6092
 
6032
6093
  // web-src/routes.ts
6033
6094
  function assertNever(value) {
6034
- throw new Error("unhandled route: " + JSON.stringify(value));
6095
+ throw new Error(`unhandled route: ${JSON.stringify(value)}`);
6035
6096
  }
6036
6097
  function parseLegacyRange(value, fallback) {
6037
6098
  const raw = value || "";
@@ -6059,7 +6120,7 @@
6059
6120
  return Number.isInteger(line) && line > 0 ? line : undefined;
6060
6121
  }
6061
6122
  function formatLineTarget(line) {
6062
- return typeof line === "number" ? String(line) : line.start + "-" + line.end;
6123
+ return typeof line === "number" ? String(line) : `${line.start}-${line.end}`;
6063
6124
  }
6064
6125
  function parseRoute(pathname, search, fallbackRange) {
6065
6126
  const params = new URLSearchParams(search);
@@ -6091,8 +6152,21 @@
6091
6152
  const ref = target || params.get("ref") || "worktree";
6092
6153
  const line = parseLineTarget(params.get("line"));
6093
6154
  if (!path)
6094
- return { screen: "unknown", reason: "missing-path", rawPathname: pathname, rawSearch: search, range };
6095
- return { screen: "file", path, ref, range, view: target ? "blob" : "detail", ...line ? { line } : {} };
6155
+ return {
6156
+ screen: "unknown",
6157
+ reason: "missing-path",
6158
+ rawPathname: pathname,
6159
+ rawSearch: search,
6160
+ range
6161
+ };
6162
+ return {
6163
+ screen: "file",
6164
+ path,
6165
+ ref,
6166
+ range,
6167
+ view: target ? "blob" : "detail",
6168
+ ...line ? { line } : {}
6169
+ };
6096
6170
  }
6097
6171
  case "/help":
6098
6172
  return {
@@ -6102,7 +6176,13 @@
6102
6176
  section: params.get("section") || "keybindings"
6103
6177
  };
6104
6178
  default:
6105
- return { screen: "unknown", reason: "unknown-pathname", rawPathname: pathname, rawSearch: search, range };
6179
+ return {
6180
+ screen: "unknown",
6181
+ reason: "unknown-pathname",
6182
+ rawPathname: pathname,
6183
+ rawSearch: search,
6184
+ range
6185
+ };
6106
6186
  }
6107
6187
  }
6108
6188
  function buildRoute(route) {
@@ -6114,15 +6194,15 @@
6114
6194
  if (route.path)
6115
6195
  params.set("path", route.path);
6116
6196
  const qs = params.toString();
6117
- return "/" + (qs ? "?" + qs : "");
6197
+ return `/${qs ? `?${qs}` : ""}`;
6118
6198
  }
6119
6199
  case "file":
6120
6200
  if (route.view === "blob") {
6121
- return "/file?path=" + encodeURIComponent(route.path) + "&target=" + encodeURIComponent(route.ref || "worktree") + (route.line ? "&line=" + encodeURIComponent(formatLineTarget(route.line)) : "");
6201
+ return "/file?path=" + encodeURIComponent(route.path) + "&target=" + encodeURIComponent(route.ref || "worktree") + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "");
6122
6202
  }
6123
- return "/file?path=" + encodeURIComponent(route.path) + "&ref=" + encodeURIComponent(route.ref || "worktree") + "&from=" + encodeURIComponent(route.range.from || "") + "&to=" + encodeURIComponent(route.range.to || "worktree") + (route.line ? "&line=" + encodeURIComponent(formatLineTarget(route.line)) : "");
6203
+ return "/file?path=" + encodeURIComponent(route.path) + "&ref=" + encodeURIComponent(route.ref || "worktree") + "&from=" + encodeURIComponent(route.range.from || "") + "&to=" + encodeURIComponent(route.range.to || "worktree") + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "");
6124
6204
  case "diff":
6125
- return "/todif?from=" + encodeURIComponent(route.range.from || "") + "&to=" + encodeURIComponent(route.range.to || "worktree") + (route.path ? "&path=" + encodeURIComponent(route.path) : "") + (route.line ? "&line=" + encodeURIComponent(formatLineTarget(route.line)) : "");
6205
+ return "/todif?from=" + encodeURIComponent(route.range.from || "") + "&to=" + encodeURIComponent(route.range.to || "worktree") + (route.path ? `&path=${encodeURIComponent(route.path)}` : "") + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "");
6126
6206
  case "help": {
6127
6207
  const params = new URLSearchParams;
6128
6208
  if (route.lang && route.lang !== "en")
@@ -6130,7 +6210,7 @@
6130
6210
  if (route.section && route.section !== "keybindings")
6131
6211
  params.set("section", route.section);
6132
6212
  const qs = params.toString();
6133
- return "/help" + (qs ? "?" + qs : "");
6213
+ return `/help${qs ? `?${qs}` : ""}`;
6134
6214
  }
6135
6215
  case "unknown":
6136
6216
  return "/todif?from=" + encodeURIComponent(route.range.from || "") + "&to=" + encodeURIComponent(route.range.to || "worktree");
@@ -6218,7 +6298,10 @@
6218
6298
  }
6219
6299
  function resolveRepoRelative(currentPath, requestedPath) {
6220
6300
  const base2 = currentPath.split("/").slice(0, -1);
6221
- const parts = [...requestedPath.startsWith("/") ? [] : base2, ...requestedPath.split("/")].filter((part) => part && part !== ".");
6301
+ const parts = [
6302
+ ...requestedPath.startsWith("/") ? [] : base2,
6303
+ ...requestedPath.split("/")
6304
+ ].filter((part) => part && part !== ".");
6222
6305
  const resolved = [];
6223
6306
  for (const part of parts) {
6224
6307
  if (part === "..") {
@@ -6248,7 +6331,7 @@
6248
6331
  });
6249
6332
  } catch {}
6250
6333
  }
6251
- return "<pre><code>" + md.utils.escapeHtml(code2) + "</code></pre>";
6334
+ return `<pre><code>${md.utils.escapeHtml(code2)}</code></pre>`;
6252
6335
  }
6253
6336
  });
6254
6337
  md.use(b, {
@@ -6348,7 +6431,10 @@
6348
6431
  const frontmatter = splitYamlFrontmatter(textValue);
6349
6432
  if (!frontmatter)
6350
6433
  return md.render(textValue);
6351
- return '<div class="gdp-markdown-frontmatter" data-gdp-frontmatter="yaml">' + md.render("```yaml\n" + frontmatter.yaml + "\n```\n") + "</div>" + md.render(frontmatter.body);
6434
+ return '<div class="gdp-markdown-frontmatter" data-gdp-frontmatter="yaml">' + md.render(`\`\`\`yaml
6435
+ ${frontmatter.yaml}
6436
+ \`\`\`
6437
+ `) + "</div>" + md.render(frontmatter.body);
6352
6438
  }
6353
6439
  function splitYamlFrontmatter(textValue) {
6354
6440
  if (!textValue.startsWith(`---
@@ -6360,7 +6446,7 @@
6360
6446
  ` : `
6361
6447
  `;
6362
6448
  const start = 3 + newline2.length;
6363
- const closing = textValue.indexOf(newline2 + "---" + newline2, start);
6449
+ const closing = textValue.indexOf(`${newline2}---${newline2}`, start);
6364
6450
  if (closing < 0)
6365
6451
  return null;
6366
6452
  return {
@@ -6409,9 +6495,9 @@
6409
6495
  const list2 = document.createElement("ul");
6410
6496
  entries.forEach((entry) => {
6411
6497
  const item = document.createElement("li");
6412
- item.className = "level-" + entry.level;
6498
+ item.className = `level-${entry.level}`;
6413
6499
  const link2 = document.createElement("a");
6414
- link2.href = "#" + encodeURIComponent(entry.id);
6500
+ link2.href = `#${encodeURIComponent(entry.id)}`;
6415
6501
  link2.dataset.target = entry.id;
6416
6502
  link2.textContent = entry.text;
6417
6503
  item.appendChild(link2);
@@ -6440,19 +6526,22 @@
6440
6526
  const toc = root.querySelector(".gdp-markdown-toc");
6441
6527
  if (!toc)
6442
6528
  return;
6443
- const entries = Array.from(toc.querySelectorAll("a[data-target]")).map((link2) => ({ link: link2, target: root.querySelector("#" + CSS.escape(link2.dataset.target || "")) })).filter((entry) => !!entry.target);
6529
+ const entries = Array.from(toc.querySelectorAll("a[data-target]")).map((link2) => ({
6530
+ link: link2,
6531
+ target: root.querySelector(`#${CSS.escape(link2.dataset.target || "")}`)
6532
+ })).filter((entry) => !!entry.target);
6444
6533
  if (!entries.length)
6445
6534
  return;
6446
6535
  toc.addEventListener("click", (e2) => {
6447
6536
  const link2 = e2.target?.closest("a[data-target]");
6448
6537
  if (!link2)
6449
6538
  return;
6450
- const section = root.querySelector("#" + CSS.escape(link2.dataset.target || ""));
6539
+ const section = root.querySelector(`#${CSS.escape(link2.dataset.target || "")}`);
6451
6540
  if (!section)
6452
6541
  return;
6453
6542
  e2.preventDefault();
6454
6543
  section.scrollIntoView({ block: "start", behavior: "smooth" });
6455
- history.replaceState(history.state, "", "#" + encodeURIComponent(section.id));
6544
+ history.replaceState(history.state, "", `#${encodeURIComponent(section.id)}`);
6456
6545
  });
6457
6546
  const controller = new AbortController;
6458
6547
  const scrollRoot = document.scrollingElement || document.documentElement;
@@ -6478,14 +6567,19 @@
6478
6567
  if (window.innerHeight + scrollRoot.scrollTop >= scrollRoot.scrollHeight - 4) {
6479
6568
  active = entries[entries.length - 1];
6480
6569
  }
6481
- entries.forEach((entry) => entry.link.classList.toggle("active", entry === active));
6570
+ entries.forEach((entry) => {
6571
+ entry.link.classList.toggle("active", entry === active);
6572
+ });
6482
6573
  keepTocLinkVisible(toc, active.link);
6483
6574
  };
6484
6575
  const schedule = () => {
6485
6576
  if (!raf)
6486
6577
  raf = requestAnimationFrame(update);
6487
6578
  };
6488
- window.addEventListener("scroll", schedule, { passive: true, signal: controller.signal });
6579
+ window.addEventListener("scroll", schedule, {
6580
+ passive: true,
6581
+ signal: controller.signal
6582
+ });
6489
6583
  window.addEventListener("resize", schedule, { signal: controller.signal });
6490
6584
  setTimeout(() => {
6491
6585
  if (!root.isConnected)
@@ -6537,7 +6631,11 @@
6537
6631
  const typed = mod;
6538
6632
  const mermaid = typed.default;
6539
6633
  if (!mermaidInitialized) {
6540
- mermaid.initialize({ startOnLoad: false, securityLevel: "strict", theme: "default" });
6634
+ mermaid.initialize({
6635
+ startOnLoad: false,
6636
+ securityLevel: "strict",
6637
+ theme: "default"
6638
+ });
6541
6639
  mermaidInitialized = true;
6542
6640
  }
6543
6641
  return mermaid;
@@ -6605,7 +6703,7 @@
6605
6703
  let tx = 0;
6606
6704
  let ty = 0;
6607
6705
  const apply = () => {
6608
- svg.style.transform = "translate(" + tx + "px, " + ty + "px) scale(" + scale + ")";
6706
+ svg.style.transform = `translate(${tx}px, ${ty}px) scale(${scale})`;
6609
6707
  };
6610
6708
  const fit = () => {
6611
6709
  const vw = Math.max(1, window.innerWidth - 128);
@@ -6705,7 +6803,7 @@
6705
6803
  try {
6706
6804
  const box = svg.getBBox();
6707
6805
  if (box.width > 0 && box.height > 0) {
6708
- svg.setAttribute("viewBox", box.x + " " + box.y + " " + box.width + " " + box.height);
6806
+ svg.setAttribute("viewBox", `${box.x} ${box.y} ${box.width} ${box.height}`);
6709
6807
  svg.setAttribute("width", String(box.width));
6710
6808
  svg.setAttribute("height", String(box.height));
6711
6809
  return { width: box.width, height: box.height };
@@ -6947,7 +7045,7 @@
6947
7045
  return Array.from(document.querySelectorAll("#content .gdp-source-virtual-scroller, #content .gdp-source-table")).some((item) => item.offsetParent !== null);
6948
7046
  }
6949
7047
  function sourceCursorKey(target) {
6950
- return target.ref + "\x00" + target.path;
7048
+ return `${target.ref}\x00${target.path}`;
6951
7049
  }
6952
7050
  function sourceCursorMatches(target, line) {
6953
7051
  return !!SOURCE_CURSOR && sourceTargetsEqual(SOURCE_CURSOR.target, target) && SOURCE_CURSOR.line === line;
@@ -7002,7 +7100,7 @@
7002
7100
  syncSourceCursorRows(cursor.target);
7003
7101
  return;
7004
7102
  }
7005
- document.querySelector('#content [data-line="' + cursor.line + '"]')?.scrollIntoView({ block: edge });
7103
+ document.querySelector(`#content [data-line="${cursor.line}"]`)?.scrollIntoView({ block: edge });
7006
7104
  }
7007
7105
  function moveSourceCursor(direction, unit, edge) {
7008
7106
  if (!hasVisibleSourceCodeSurface())
@@ -7082,7 +7180,7 @@
7082
7180
  const tabs = document.querySelector("#content .gdp-source-tabs");
7083
7181
  if (!tabs)
7084
7182
  return false;
7085
- const button = tabs.querySelector('button[data-source-tab="' + tab + '"]');
7183
+ const button = tabs.querySelector(`button[data-source-tab="${tab}"]`);
7086
7184
  if (!button || button.hidden || button.disabled)
7087
7185
  return false;
7088
7186
  button.click();
@@ -7112,7 +7210,7 @@
7112
7210
  if (!project)
7113
7211
  return;
7114
7212
  PROJECT_NAME = project;
7115
- document.title = project + " - code viewer";
7213
+ document.title = `${project} - code viewer`;
7116
7214
  }
7117
7215
  function savedScopeOmitDirs() {
7118
7216
  const raw = localStorage.getItem(scopeOmitDirsStorageKey());
@@ -7155,7 +7253,7 @@
7155
7253
  requestAnimationFrame(() => {
7156
7254
  const head = document.querySelector(".sb-head");
7157
7255
  if (head)
7158
- document.documentElement.style.setProperty("--sidebar-head-h", Math.ceil(head.getBoundingClientRect().height) + "px");
7256
+ document.documentElement.style.setProperty("--sidebar-head-h", `${Math.ceil(head.getBoundingClientRect().height)}px`);
7159
7257
  });
7160
7258
  }
7161
7259
  function observeSidebarHeaderHeight() {
@@ -7200,7 +7298,7 @@
7200
7298
  layout: localStorage.getItem("gdp:layout") || "side-by-side",
7201
7299
  theme: localStorage.getItem("gdp:theme") || (matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"),
7202
7300
  sbView: localStorage.getItem("gdp:sbview") || "tree",
7203
- sbWidth: parseInt(localStorage.getItem("gdp:sbwidth")) || 308,
7301
+ sbWidth: parseInt(localStorage.getItem("gdp:sbwidth") ?? "", 10) || 308,
7204
7302
  sidebarHidden: localStorage.getItem("gdp:sidebar-hidden") === "1",
7205
7303
  collapsedDirs: new Set(JSON.parse(localStorage.getItem("gdp:collapsed-dirs") || "[]")),
7206
7304
  ignoreWs: igRaw === null ? true : igRaw === "1",
@@ -7228,7 +7326,7 @@
7228
7326
  $("#hljs-dark").disabled = STATE.theme !== "dark";
7229
7327
  }
7230
7328
  function getHljs() {
7231
- const hljsRef = window.hljs || window.Diff2HtmlUI && window.Diff2HtmlUI.hljs;
7329
+ const hljsRef = window.hljs || window.Diff2HtmlUI?.hljs;
7232
7330
  if (!hljsRef)
7233
7331
  return null;
7234
7332
  if (!highlightConfigured && typeof hljsRef.configure === "function") {
@@ -7409,7 +7507,7 @@
7409
7507
  function fileBadge(status) {
7410
7508
  const ch = (status || "M")[0].toUpperCase();
7411
7509
  const span = document.createElement("span");
7412
- span.className = "badge " + ch;
7510
+ span.className = `badge ${ch}`;
7413
7511
  span.textContent = ch;
7414
7512
  span.title = { M: "modified", A: "added", D: "deleted", R: "renamed" }[ch] || ch;
7415
7513
  return span;
@@ -7449,7 +7547,7 @@
7449
7547
  }
7450
7548
  function iconSvg(className, paths) {
7451
7549
  const pathList = Array.isArray(paths) ? paths : [paths];
7452
- return '<svg class="octicon ' + className + '" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true">' + pathList.map((path) => '<path fill="currentColor" d="' + path + '"></path>').join("") + "</svg>";
7550
+ return '<svg class="octicon ' + className + '" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true">' + pathList.map((path) => `<path fill="currentColor" d="${path}"></path>`).join("") + "</svg>";
7453
7551
  }
7454
7552
  function setUnfoldButtonState(button, expanded) {
7455
7553
  if (!button)
@@ -7579,7 +7677,7 @@
7579
7677
  const dirPartCount = f2.type === "tree" ? parts.length : parts.length - 1;
7580
7678
  for (let i2 = 0;i2 < dirPartCount; i2++) {
7581
7679
  const p2 = parts[i2];
7582
- acc = acc ? acc + "/" + p2 : p2;
7680
+ acc = acc ? `${acc}/${p2}` : p2;
7583
7681
  if (!node.dirs[p2]) {
7584
7682
  node.dirs[p2] = {
7585
7683
  name: p2,
@@ -7607,13 +7705,15 @@
7607
7705
  const ks = Object.keys(node.dirs);
7608
7706
  while (ks.length === 1 && node.files.length === 0 && !node.explicit && node !== root) {
7609
7707
  const only = node.dirs[ks[0]];
7610
- node.name = node.name ? node.name + "/" + only.name : only.name;
7708
+ node.name = node.name ? `${node.name}/${only.name}` : only.name;
7611
7709
  node.dirs = only.dirs;
7612
7710
  node.files = only.files;
7613
7711
  node.path = only.path;
7614
7712
  node.minOrder = Math.min(node.minOrder, only.minOrder);
7615
7713
  ks.length = 0;
7616
- Object.keys(node.dirs).forEach((k) => ks.push(k));
7714
+ Object.keys(node.dirs).forEach((k) => {
7715
+ ks.push(k);
7716
+ });
7617
7717
  }
7618
7718
  Object.values(node.dirs).forEach(compress);
7619
7719
  }
@@ -7648,7 +7748,7 @@
7648
7748
  li.classList.add(dir.children_omitted_reason === "heavy" ? "children-omitted-heavy" : "children-omitted-internal");
7649
7749
  li.title = dir.children_omitted_reason === "heavy" ? "Large generated/vendor directory: open the detail pane to browse its contents" : "Internal Git metadata is not browsed";
7650
7750
  }
7651
- li.style.setProperty("--lvl-pad", 12 + depth * 14 + "px");
7751
+ li.style.setProperty("--lvl-pad", `${12 + depth * 14}px`);
7652
7752
  const chev = document.createElement("span");
7653
7753
  if (dir.children_omitted) {
7654
7754
  chev.className = "chev-spacer";
@@ -7727,7 +7827,7 @@
7727
7827
  li.tabIndex = -1;
7728
7828
  li.dataset.path = f2.path;
7729
7829
  li.classList.toggle("viewed", !onFileClick && STATE.viewedFiles.has(f2.path));
7730
- li.style.setProperty("--lvl-pad", 12 + depth * 14 + "px");
7830
+ li.style.setProperty("--lvl-pad", `${12 + depth * 14}px`);
7731
7831
  const spacer = document.createElement("span");
7732
7832
  spacer.className = "chev-spacer";
7733
7833
  li.appendChild(spacer);
@@ -7808,7 +7908,7 @@
7808
7908
  } else {
7809
7909
  renderFlat(files, ul, onFileClick);
7810
7910
  }
7811
- $("#totals").textContent = files.length ? files.length + " file" + (files.length === 1 ? "" : "s") : "";
7911
+ $("#totals").textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"}` : "";
7812
7912
  $$(".sb-view-seg button").forEach((b2) => {
7813
7913
  b2.classList.toggle("active", b2.dataset.view === STATE.sbView);
7814
7914
  });
@@ -7846,7 +7946,7 @@
7846
7946
  }
7847
7947
  function createRefSelectorInput(options) {
7848
7948
  const wrap = document.createElement("div");
7849
- wrap.className = "ref-selector" + (options.extraClass ? " " + options.extraClass : "");
7949
+ wrap.className = `ref-selector${options.extraClass ? ` ${options.extraClass}` : ""}`;
7850
7950
  wrap.dataset.refSelector = "";
7851
7951
  if (options.wrapperId)
7852
7952
  wrap.id = options.wrapperId;
@@ -7897,7 +7997,7 @@
7897
7997
  if (meta.branch) {
7898
7998
  const b2 = document.createElement("span");
7899
7999
  b2.className = "ref";
7900
- b2.textContent = "⎇ " + meta.branch;
8000
+ b2.textContent = `⎇ ${meta.branch}`;
7901
8001
  el.appendChild(b2);
7902
8002
  }
7903
8003
  if (meta.totals) {
@@ -7909,13 +8009,13 @@
7909
8009
  const u2 = document.createElement("span");
7910
8010
  u2.className = "updated-at";
7911
8011
  u2.title = "last updated";
7912
- u2.textContent = "updated " + new Date().toLocaleTimeString([], { hour12: false });
8012
+ u2.textContent = `updated ${new Date().toLocaleTimeString([], { hour12: false })}`;
7913
8013
  el.appendChild(u2);
7914
8014
  }
7915
8015
  let SUPPRESS_SPY_UNTIL = 0;
7916
8016
  function prefetchByPath(path) {
7917
8017
  const card = document.querySelector(diffCardSelector(path));
7918
- if (!card || !card.classList.contains("pending"))
8018
+ if (!card?.classList.contains("pending"))
7919
8019
  return;
7920
8020
  const f2 = STATE.files.find((x) => x.path === path);
7921
8021
  if (!f2)
@@ -7990,7 +8090,7 @@
7990
8090
  for (const dir of sidebarAncestorDirs(path)) {
7991
8091
  if (STATE.collapsedDirs.delete(dir))
7992
8092
  changed = true;
7993
- const row = document.querySelector('#filelist .tree-dir[data-dirpath="' + CSS.escape(dir) + '"]');
8093
+ const row = document.querySelector(`#filelist .tree-dir[data-dirpath="${CSS.escape(dir)}"]`);
7994
8094
  row?.classList.remove("collapsed");
7995
8095
  const icon = row?.querySelector(".dir-icon");
7996
8096
  if (icon)
@@ -8051,7 +8151,7 @@
8051
8151
  function updateTreeDirVisibility(dirMatches, filterActive = false) {
8052
8152
  $$("#filelist .tree-dir").forEach((dir) => {
8053
8153
  const childUl = dir.nextElementSibling;
8054
- if (!childUl || !childUl.classList.contains("tree-children"))
8154
+ if (!childUl?.classList.contains("tree-children"))
8055
8155
  return;
8056
8156
  const anyVisible = !!childUl.querySelector(".tree-file:not(.hidden):not(.hidden-by-tests)");
8057
8157
  const explicitVisible = dir.dataset.explicit === "true" && !filterActive;
@@ -8200,8 +8300,12 @@
8200
8300
  });
8201
8301
  }
8202
8302
  function removeStandaloneSource() {
8203
- document.querySelectorAll(".gdp-standalone-source").forEach((el) => el.remove());
8204
- document.querySelectorAll(".gdp-repo-blob-layout").forEach((el) => el.remove());
8303
+ document.querySelectorAll(".gdp-standalone-source").forEach((el) => {
8304
+ el.remove();
8305
+ });
8306
+ document.querySelectorAll(".gdp-repo-blob-layout").forEach((el) => {
8307
+ el.remove();
8308
+ });
8205
8309
  }
8206
8310
  function renderHelpPage() {
8207
8311
  cancelActiveSourceLoad("navigation");
@@ -8348,7 +8452,7 @@
8348
8452
  delete old.dataset.manualRendered;
8349
8453
  delete old.dataset.manualLoad;
8350
8454
  delete old.dataset.manualMode;
8351
- old.style.minHeight = (f2.estimated_height_px || 80) + "px";
8455
+ old.style.minHeight = `${f2.estimated_height_px || 80}px`;
8352
8456
  old._diffData = null;
8353
8457
  old._file = null;
8354
8458
  } else {
@@ -8363,7 +8467,9 @@
8363
8467
  ordered.push(createPlaceholder(f2));
8364
8468
  }
8365
8469
  });
8366
- oldByKey.forEach((c2) => c2.remove());
8470
+ oldByKey.forEach((c2) => {
8471
+ c2.remove();
8472
+ });
8367
8473
  target.replaceChildren(...ordered);
8368
8474
  for (let i2 = LOAD_QUEUE.length - 1;i2 >= 0; i2--) {
8369
8475
  if (!LOAD_QUEUE[i2].card.isConnected)
@@ -8438,7 +8544,9 @@
8438
8544
  return;
8439
8545
  const form = new FormData;
8440
8546
  form.set("dir", path);
8441
- list2.forEach((file) => form.append("files", file, file.name));
8547
+ list2.forEach((file) => {
8548
+ form.append("files", file, file.name);
8549
+ });
8442
8550
  const res = await fetch("/_upload_files", {
8443
8551
  method: "POST",
8444
8552
  headers: { "X-Code-Viewer-Action": "1" },
@@ -8454,7 +8562,7 @@
8454
8562
  dropPanel.className = "gdp-upload-panel";
8455
8563
  const copy = document.createElement("div");
8456
8564
  copy.className = "gdp-upload-copy";
8457
- copy.textContent = "Drop files into " + (path || PROJECT_NAME || "repository");
8565
+ copy.textContent = `Drop files into ${path || PROJECT_NAME || "repository"}`;
8458
8566
  const input = document.createElement("input");
8459
8567
  input.type = "file";
8460
8568
  input.multiple = true;
@@ -8470,7 +8578,7 @@
8470
8578
  };
8471
8579
  input.addEventListener("change", async () => {
8472
8580
  try {
8473
- if (input.files && input.files.length)
8581
+ if (input.files?.length)
8474
8582
  await uploadFiles(path, input.files);
8475
8583
  } catch {
8476
8584
  fail();
@@ -8488,7 +8596,7 @@
8488
8596
  dropPanel.classList.remove("dragging");
8489
8597
  try {
8490
8598
  const files = event.dataTransfer?.files;
8491
- if (files && files.length)
8599
+ if (files?.length)
8492
8600
  await uploadFiles(path, files);
8493
8601
  } catch {
8494
8602
  fail();
@@ -8630,7 +8738,7 @@
8630
8738
  meta.entries.forEach((entry) => {
8631
8739
  const row = document.createElement("button");
8632
8740
  row.type = "button";
8633
- row.className = "gdp-repo-row " + entry.type;
8741
+ row.className = `gdp-repo-row ${entry.type}`;
8634
8742
  const icon = document.createElement("span");
8635
8743
  icon.className = entry.type === "tree" ? "dir-icon" : "d2h-icon-wrapper";
8636
8744
  if (entry.type === "tree")
@@ -8670,7 +8778,7 @@
8670
8778
  listWrapper.appendChild(list2);
8671
8779
  listCard.appendChild(listWrapper);
8672
8780
  shell.appendChild(listCard);
8673
- if (meta.readme && meta.readme.text) {
8781
+ if (meta.readme?.text) {
8674
8782
  const readme = document.createElement("section");
8675
8783
  readme.className = "gdp-file-shell loaded gdp-repo-readme";
8676
8784
  const wrapper = document.createElement("div");
@@ -8731,7 +8839,7 @@
8731
8839
  params.set("recursive", "1");
8732
8840
  appendScopeOmitDirsParam(params);
8733
8841
  REPO_SIDEBAR_LOAD_REF = normalizedRef;
8734
- const load2 = trackLoad(fetch("/_tree?" + params.toString()).then((r2) => {
8842
+ const load2 = trackLoad(fetch(`/_tree?${params.toString()}`).then((r2) => {
8735
8843
  if (!r2.ok)
8736
8844
  throw new Error("failed to load repository tree");
8737
8845
  return r2.json();
@@ -8790,7 +8898,7 @@
8790
8898
  card.dataset.status = f2.status || "M";
8791
8899
  card.classList.toggle("viewed", STATE.viewedFiles.has(f2.path));
8792
8900
  if (f2.estimated_height_px) {
8793
- card.style.minHeight = f2.estimated_height_px + "px";
8901
+ card.style.minHeight = `${f2.estimated_height_px}px`;
8794
8902
  }
8795
8903
  const head = document.createElement("div");
8796
8904
  head.className = "gdp-shell-header";
@@ -8817,7 +8925,9 @@
8817
8925
  enqueueLoad(f2, card, 0);
8818
8926
  });
8819
8927
  }, { rootMargin: "1200px 0px 1600px 0px" });
8820
- document.querySelectorAll(".gdp-file-shell.pending").forEach((c2) => lazyObserver.observe(c2));
8928
+ document.querySelectorAll(".gdp-file-shell.pending").forEach((c2) => {
8929
+ lazyObserver.observe(c2);
8930
+ });
8821
8931
  }
8822
8932
  window.addEventListener("scroll", () => enqueueInitialLoads(), {
8823
8933
  passive: true
@@ -8888,12 +8998,14 @@
8888
8998
  if (indicator)
8889
8999
  indicator.hidden = true;
8890
9000
  const body = card.querySelector(".gdp-shell-body");
9001
+ if (!body)
9002
+ return;
8891
9003
  body.innerHTML = "";
8892
9004
  const wrap = document.createElement("div");
8893
9005
  wrap.className = "gdp-manual-load";
8894
9006
  const note = document.createElement("div");
8895
9007
  note.className = "gdp-manual-note";
8896
- note.textContent = manualLoadReason(file) + " - click to load diff";
9008
+ note.textContent = `${manualLoadReason(file)} - click to load diff`;
8897
9009
  const previewBtn = document.createElement("button");
8898
9010
  previewBtn.className = "gdp-show-full";
8899
9011
  previewBtn.textContent = "Load preview";
@@ -8998,6 +9110,8 @@
8998
9110
  card.classList.remove("loading");
8999
9111
  card.classList.add("error");
9000
9112
  const body = card.querySelector(".gdp-shell-body");
9113
+ if (!body)
9114
+ return;
9001
9115
  body.innerHTML = '<div class="gdp-error">failed to load — <button class="retry">retry</button></div>';
9002
9116
  const btn = body.querySelector(".retry");
9003
9117
  if (btn)
@@ -9014,8 +9128,10 @@
9014
9128
  if (head)
9015
9129
  head.style.display = "none";
9016
9130
  const body = card.querySelector(".gdp-shell-body");
9131
+ if (!body)
9132
+ return;
9017
9133
  body.innerHTML = "";
9018
- if (!data.diff || !data.diff.trim()) {
9134
+ if (!data.diff?.trim()) {
9019
9135
  body.innerHTML = '<div class="gdp-info">No content</div>';
9020
9136
  return;
9021
9137
  }
@@ -9107,7 +9223,9 @@
9107
9223
  const parsed = group.find((g) => g.hunk) || group[0];
9108
9224
  if (!parsed.hunk)
9109
9225
  return;
9110
- group.forEach((g) => g.tr.classList.add("gdp-hunk-row"));
9226
+ group.forEach((g) => {
9227
+ g.tr.classList.add("gdp-hunk-row");
9228
+ });
9111
9229
  infoRows.push({
9112
9230
  tr: parsed.tr,
9113
9231
  info: parsed.info,
@@ -9171,7 +9289,7 @@
9171
9289
  setBusy(true);
9172
9290
  const url = "/file_range?path=" + refPath + "&ref=" + encodeURIComponent(ref) + "&start=" + start + "&end=" + end;
9173
9291
  trackLoad(fetch(url).then((r2) => r2.json())).then((data) => {
9174
- if (!data || !data.lines) {
9292
+ if (!data?.lines) {
9175
9293
  setBusy(false);
9176
9294
  return;
9177
9295
  }
@@ -9189,7 +9307,7 @@
9189
9307
  item.bottomExpandedEnd = end;
9190
9308
  for (const sib of item.siblings || [{ tr: item.tr }]) {
9191
9309
  const ln = sib.tr.querySelector(".d2h-code-linenumber.d2h-info, .d2h-code-side-linenumber.d2h-info");
9192
- const old = ln && ln.querySelector(".gdp-expand-stack");
9310
+ const old = ln?.querySelector(".gdp-expand-stack");
9193
9311
  if (old)
9194
9312
  old.remove();
9195
9313
  }
@@ -9206,18 +9324,18 @@
9206
9324
  if (isFirst) {
9207
9325
  buttons.push({
9208
9326
  direction: "up",
9209
- title: "Show " + Math.min(STEP, remainingSize) + " more lines",
9327
+ title: `Show ${Math.min(STEP, remainingSize)} more lines`,
9210
9328
  onClick: () => fetchAndInsert(Math.max(remainingStart, remainingEnd - STEP + 1), remainingEnd, "after")
9211
9329
  });
9212
9330
  } else {
9213
9331
  buttons.push({
9214
9332
  direction: "up",
9215
- title: "Show " + Math.min(STEP, remainingSize) + " more lines",
9333
+ title: `Show ${Math.min(STEP, remainingSize)} more lines`,
9216
9334
  onClick: () => fetchAndInsert(remainingStart, Math.min(remainingEnd, remainingStart + STEP - 1), "before")
9217
9335
  });
9218
9336
  buttons.push({
9219
9337
  direction: "down",
9220
- title: "Show " + Math.min(STEP, remainingSize) + " more lines",
9338
+ title: `Show ${Math.min(STEP, remainingSize)} more lines`,
9221
9339
  onClick: () => fetchAndInsert(Math.max(remainingStart, remainingEnd - STEP + 1), remainingEnd, "after")
9222
9340
  });
9223
9341
  }
@@ -9261,12 +9379,14 @@
9261
9379
  const syncHeight = () => {
9262
9380
  const stack = stackRow.querySelector(".gdp-expand-stack");
9263
9381
  const targetH = stack ? Math.max(20, stack.getBoundingClientRect().height) : 20;
9264
- rows.forEach((row) => row.style.setProperty("height", targetH + "px", "important"));
9382
+ rows.forEach((row) => {
9383
+ row.style.setProperty("height", `${targetH}px`, "important");
9384
+ });
9265
9385
  };
9266
9386
  requestAnimationFrame(syncHeight);
9267
9387
  setTimeout(syncHeight, 100);
9268
9388
  }
9269
- function attachTrailingExpandControls(item, file, ref, refPath) {
9389
+ function _attachTrailingExpandControls(item, file, ref, refPath) {
9270
9390
  const STEP = 20;
9271
9391
  let nextNewStart = nextNewLine(item.hunk);
9272
9392
  let nextOldStart = nextOldLine(item.hunk);
@@ -9292,29 +9412,37 @@
9292
9412
  if (!rows.length)
9293
9413
  return;
9294
9414
  const setBusy = (busy) => {
9295
- rows.forEach((row) => row.ln.querySelectorAll(".gdp-expand-btn").forEach((btn) => {
9296
- btn.disabled = busy;
9297
- }));
9415
+ rows.forEach((row) => {
9416
+ row.ln.querySelectorAll(".gdp-expand-btn").forEach((btn) => {
9417
+ btn.disabled = busy;
9418
+ });
9419
+ });
9298
9420
  };
9299
9421
  const fetchAndInsert = () => {
9300
9422
  const range = window.GdpExpandLogic.trailingClickRange(nextNewStart, STEP);
9301
9423
  setBusy(true);
9302
9424
  const url = "/file_range?path=" + refPath + "&ref=" + encodeURIComponent(ref) + "&start=" + range.start + "&end=" + range.end;
9303
9425
  trackLoad(fetch(url).then((r2) => r2.json())).then((data) => {
9304
- const lines = data && data.lines || [];
9426
+ const lines = data?.lines || [];
9305
9427
  if (!lines.length) {
9306
- rows.forEach((row) => row.tr.remove());
9428
+ rows.forEach((row) => {
9429
+ row.tr.remove();
9430
+ });
9307
9431
  return;
9308
9432
  }
9309
9433
  const card = item.tr.closest(".d2h-file-wrapper");
9310
- rows.forEach((row) => insertContextRows(row.tr, lines, range.start, nextOldStart, "before", row.sideIndex));
9434
+ rows.forEach((row) => {
9435
+ insertContextRows(row.tr, lines, range.start, nextOldStart, "before", row.sideIndex);
9436
+ });
9311
9437
  const next = window.GdpExpandLogic.applyTrailingResult({ newStart: nextNewStart, oldStart: nextOldStart }, lines.length, STEP);
9312
9438
  nextNewStart = next.newStart;
9313
9439
  nextOldStart = next.oldStart;
9314
9440
  if (card)
9315
9441
  highlightInsertedSpans(card, file);
9316
9442
  if (next.eof) {
9317
- rows.forEach((row) => row.tr.remove());
9443
+ rows.forEach((row) => {
9444
+ row.tr.remove();
9445
+ });
9318
9446
  return;
9319
9447
  }
9320
9448
  setBusy(false);
@@ -9348,7 +9476,7 @@
9348
9476
  let lnHtml;
9349
9477
  if (isSplit) {
9350
9478
  const num = sideIndex === 0 ? oldStart + i2 : newStart + i2;
9351
- lnHtml = '<td class="d2h-code-side-linenumber d2h-cntx">' + num + "</td>";
9479
+ lnHtml = `<td class="d2h-code-side-linenumber d2h-cntx">${num}</td>`;
9352
9480
  } else {
9353
9481
  lnHtml = '<td class="d2h-code-linenumber d2h-cntx"><div class="line-num1">' + (oldStart + i2) + '</div><div class="line-num2">' + (newStart + i2) + "</div></td>";
9354
9482
  }
@@ -9396,7 +9524,7 @@
9396
9524
  title.textContent = "Loading file";
9397
9525
  const message = document.createElement("div");
9398
9526
  message.className = "gdp-source-loading-message";
9399
- message.textContent = target.path + " at " + target.ref;
9527
+ message.textContent = `${target.path} at ${target.ref}`;
9400
9528
  content.append(title, message);
9401
9529
  if (onCancel) {
9402
9530
  const button = document.createElement("button");
@@ -9420,7 +9548,7 @@
9420
9548
  const body = card.querySelector(".gdp-file-detail-body, .d2h-files-diff, .d2h-file-diff, .gdp-media, .gdp-source-viewer");
9421
9549
  const view = document.createElement("div");
9422
9550
  view.className = "gdp-source-viewer error";
9423
- view.textContent = message || "Cannot load " + target.path + " at " + target.ref;
9551
+ view.textContent = message || `Cannot load ${target.path} at ${target.ref}`;
9424
9552
  if (body)
9425
9553
  body.replaceWith(view);
9426
9554
  else
@@ -9437,7 +9565,7 @@
9437
9565
  title.textContent = "Loading cancelled";
9438
9566
  const message = document.createElement("div");
9439
9567
  message.className = "gdp-source-loading-message";
9440
- message.textContent = target.path + " at " + target.ref;
9568
+ message.textContent = `${target.path} at ${target.ref}`;
9441
9569
  const retry = document.createElement("button");
9442
9570
  retry.type = "button";
9443
9571
  retry.className = "gdp-btn gdp-btn-sm";
@@ -9490,7 +9618,7 @@
9490
9618
  const preview = document.createElement("div");
9491
9619
  preview.className = "gdp-html-preview";
9492
9620
  const frame = document.createElement("iframe");
9493
- frame.title = target.path + " preview";
9621
+ frame.title = `${target.path} preview`;
9494
9622
  frame.srcdoc = html;
9495
9623
  preview.appendChild(frame);
9496
9624
  return preview;
@@ -9928,7 +10056,7 @@
9928
10056
  const header = isStandalone ? null : document.createElement("div");
9929
10057
  if (header) {
9930
10058
  header.className = "gdp-source-meta";
9931
- header.textContent = target.path + " @ " + target.ref;
10059
+ header.textContent = `${target.path} @ ${target.ref}`;
9932
10060
  }
9933
10061
  const lang = inferLang(target.path);
9934
10062
  const usesVirtualSource = shouldVirtualizeSource(textValue, lines) && !isVirtualSourceDisabled();
@@ -10271,7 +10399,7 @@
10271
10399
  return;
10272
10400
  matches = nextMatches;
10273
10401
  active = matches.length ? Math.max(0, Math.min(active, matches.length - 1)) : -1;
10274
- count.textContent = matches.length ? active + 1 + " / " + matches.length : "0 / 0";
10402
+ count.textContent = matches.length ? `${active + 1} / ${matches.length}` : "0 / 0";
10275
10403
  if (active >= 0)
10276
10404
  scroller.scrollTop = Math.max(0, (matches[active].line - 1) * VIRTUAL_SOURCE_ROW_HEIGHT - VIRTUAL_SOURCE_ROW_HEIGHT * 3);
10277
10405
  renderFn();
@@ -10293,7 +10421,7 @@
10293
10421
  if (!matches.length)
10294
10422
  return;
10295
10423
  active = (active + direction + matches.length) % matches.length;
10296
- count.textContent = active + 1 + " / " + matches.length;
10424
+ count.textContent = `${active + 1} / ${matches.length}`;
10297
10425
  scroller.scrollTop = Math.max(0, (matches[active].line - 1) * VIRTUAL_SOURCE_ROW_HEIGHT - VIRTUAL_SOURCE_ROW_HEIGHT * 3);
10298
10426
  renderFn();
10299
10427
  };
@@ -10383,10 +10511,10 @@
10383
10511
  scroller.className = "gdp-source-virtual-scroller";
10384
10512
  scroller.tabIndex = 0;
10385
10513
  scroller.setAttribute("role", "region");
10386
- scroller.setAttribute("aria-label", target.path + " source code");
10514
+ scroller.setAttribute("aria-label", `${target.path} source code`);
10387
10515
  const spacer = document.createElement("div");
10388
10516
  spacer.className = "gdp-source-virtual-spacer";
10389
- spacer.style.height = Math.max(1, lines.length * VIRTUAL_SOURCE_ROW_HEIGHT) + "px";
10517
+ spacer.style.height = `${Math.max(1, lines.length * VIRTUAL_SOURCE_ROW_HEIGHT)}px`;
10390
10518
  const windowEl = document.createElement("div");
10391
10519
  windowEl.className = "gdp-source-virtual-window";
10392
10520
  spacer.appendChild(windowEl);
@@ -10407,7 +10535,7 @@
10407
10535
  renderedStart = start;
10408
10536
  renderedEnd = end;
10409
10537
  windowEl.replaceChildren();
10410
- windowEl.style.transform = "translateY(" + start * VIRTUAL_SOURCE_ROW_HEIGHT + "px)";
10538
+ windowEl.style.transform = `translateY(${start * VIRTUAL_SOURCE_ROW_HEIGHT}px)`;
10411
10539
  const fragment = document.createDocumentFragment();
10412
10540
  for (let index = start;index < end; index++) {
10413
10541
  const row = document.createElement("div");
@@ -10424,7 +10552,7 @@
10424
10552
  const line = lines[index] ?? "";
10425
10553
  const searchQuery = search?.query() || "";
10426
10554
  const activeRange = search?.activeRange() || null;
10427
- if (appendVirtualSourceLineCode(code2, line, searchQuery, activeRange, index + 1)) {} else if (hljsRef && hljsRef.highlight && lang && line.length <= VIRTUAL_SOURCE_HIGHLIGHT_MAX_LINE_LENGTH && (!hljsRef.getLanguage || hljsRef.getLanguage(lang))) {
10555
+ if (appendVirtualSourceLineCode(code2, line, searchQuery, activeRange, index + 1)) {} else if (hljsRef?.highlight && lang && line.length <= VIRTUAL_SOURCE_HIGHLIGHT_MAX_LINE_LENGTH && (!hljsRef.getLanguage || hljsRef.getLanguage(lang))) {
10428
10556
  try {
10429
10557
  code2.innerHTML = hljsRef.highlight(line, {
10430
10558
  language: lang,
@@ -10499,7 +10627,7 @@
10499
10627
  scroller.className = "gdp-source-virtual-scroller";
10500
10628
  scroller.tabIndex = 0;
10501
10629
  scroller.setAttribute("role", "region");
10502
- scroller.setAttribute("aria-label", target.path + " source code");
10630
+ scroller.setAttribute("aria-label", `${target.path} source code`);
10503
10631
  const spacer = document.createElement("div");
10504
10632
  spacer.className = "gdp-source-virtual-spacer";
10505
10633
  const windowEl = document.createElement("div");
@@ -10513,15 +10641,17 @@
10513
10641
  const targetLine = lineTargetStart(currentSourceLineTarget(target)) || 1;
10514
10642
  let complete = initialComplete;
10515
10643
  let totalRows = initialComplete ? Math.max(1, initialTotal) : Math.max(initialTotal || 1, initialStart + initialLines.length - 1, targetLine + VIRTUAL_SOURCE_PAGE_SIZE);
10516
- initialLines.forEach((line, index) => lines.set(initialStart + index, line));
10644
+ initialLines.forEach((line, index) => {
10645
+ lines.set(initialStart + index, line);
10646
+ });
10517
10647
  requestedPages.add(Math.max(0, Math.floor((initialStart - 1) / VIRTUAL_SOURCE_PAGE_SIZE)));
10518
10648
  for (let line = initialStart;line < initialStart + initialLines.length; line += VIRTUAL_SOURCE_PAGE_SIZE) {
10519
10649
  requestedPages.add(Math.max(0, Math.floor((line - 1) / VIRTUAL_SOURCE_PAGE_SIZE)));
10520
10650
  }
10521
10651
  const updateTotals = () => {
10522
10652
  SOURCE_CURSOR_TOTALS.set(sourceCursorKey(target), totalRows);
10523
- summary.textContent = (complete ? totalRows.toLocaleString() : lines.size.toLocaleString() + "+") + " lines loaded from " + formatBytes(size) + ". More rows load as you scroll.";
10524
- spacer.style.height = Math.max(1, totalRows * VIRTUAL_SOURCE_ROW_HEIGHT) + "px";
10653
+ summary.textContent = (complete ? totalRows.toLocaleString() : `${lines.size.toLocaleString()}+`) + " lines loaded from " + formatBytes(size) + ". More rows load as you scroll.";
10654
+ spacer.style.height = `${Math.max(1, totalRows * VIRTUAL_SOURCE_ROW_HEIGHT)}px`;
10525
10655
  };
10526
10656
  const loadPage = (line) => {
10527
10657
  if (signal?.aborted || complete && line > totalRows)
@@ -10537,7 +10667,9 @@
10537
10667
  trackLoad(fetch(buildFileRangeUrl(target, start, end), { signal }).then((res) => res.ok ? res.json() : null).then((data) => {
10538
10668
  if (!data || signal?.aborted)
10539
10669
  return;
10540
- data.lines.forEach((lineValue, index) => lines.set(data.start + index, lineValue));
10670
+ data.lines.forEach((lineValue, index) => {
10671
+ lines.set(data.start + index, lineValue);
10672
+ });
10541
10673
  totalRows = data.complete ? Math.max(1, data.total) : Math.max(totalRows, data.total, end + VIRTUAL_SOURCE_PAGE_SIZE);
10542
10674
  complete = data.complete === true;
10543
10675
  updateTotals();
@@ -10569,7 +10701,7 @@
10569
10701
  renderedStart = start;
10570
10702
  renderedEnd = end;
10571
10703
  windowEl.replaceChildren();
10572
- windowEl.style.transform = "translateY(" + start * VIRTUAL_SOURCE_ROW_HEIGHT + "px)";
10704
+ windowEl.style.transform = `translateY(${start * VIRTUAL_SOURCE_ROW_HEIGHT}px)`;
10573
10705
  const fragment = document.createDocumentFragment();
10574
10706
  for (let index = start;index < end; index++) {
10575
10707
  const lineNumber = index + 1;
@@ -10589,7 +10721,7 @@
10589
10721
  const line = lines.get(lineNumber);
10590
10722
  if (line == null) {
10591
10723
  code2.textContent = "";
10592
- } else if (appendVirtualSourceLineCode(code2, line, search?.query() || "", search?.activeRange() || null, lineNumber)) {} else if (hljsRef && hljsRef.highlight && lang && line.length <= VIRTUAL_SOURCE_HIGHLIGHT_MAX_LINE_LENGTH && (!hljsRef.getLanguage || hljsRef.getLanguage(lang))) {
10724
+ } else if (appendVirtualSourceLineCode(code2, line, search?.query() || "", search?.activeRange() || null, lineNumber)) {} else if (hljsRef?.highlight && lang && line.length <= VIRTUAL_SOURCE_HIGHLIGHT_MAX_LINE_LENGTH && (!hljsRef.getLanguage || hljsRef.getLanguage(lang))) {
10593
10725
  try {
10594
10726
  code2.innerHTML = hljsRef.highlight(line, {
10595
10727
  language: lang,
@@ -10689,7 +10821,7 @@
10689
10821
  const header = isStandalone ? null : document.createElement("div");
10690
10822
  if (header) {
10691
10823
  header.className = "gdp-source-meta";
10692
- header.textContent = target.path + " @ " + target.ref;
10824
+ header.textContent = `${target.path} @ ${target.ref}`;
10693
10825
  view.appendChild(header);
10694
10826
  }
10695
10827
  const lineTarget = lineTargetStart(currentSourceLineTarget(target)) || 1;
@@ -10730,7 +10862,7 @@
10730
10862
  if (!isStandalone) {
10731
10863
  const meta = document.createElement("div");
10732
10864
  meta.className = "gdp-source-meta";
10733
- meta.textContent = target.path + " @ " + target.ref;
10865
+ meta.textContent = `${target.path} @ ${target.ref}`;
10734
10866
  view.appendChild(meta);
10735
10867
  }
10736
10868
  const url = buildRawFileUrl(target);
@@ -10760,7 +10892,7 @@
10760
10892
  img.alt = "";
10761
10893
  img.addEventListener("load", () => {
10762
10894
  const resolution = document.createElement("span");
10763
- resolution.textContent = img.naturalWidth + " x " + img.naturalHeight;
10895
+ resolution.textContent = `${img.naturalWidth} x ${img.naturalHeight}`;
10764
10896
  info.appendChild(resolution);
10765
10897
  }, { once: true });
10766
10898
  view.appendChild(img);
@@ -10770,7 +10902,7 @@
10770
10902
  else
10771
10903
  card.appendChild(view);
10772
10904
  }
10773
- function renderSourceBinary(card, target) {
10905
+ function _renderSourceBinary(card, target) {
10774
10906
  const body = card.querySelector(".gdp-file-detail-body, .d2h-files-diff, .d2h-file-diff, .gdp-media, .gdp-source-viewer");
10775
10907
  const isStandalone = card.classList.contains("gdp-standalone-source");
10776
10908
  const view = document.createElement("div");
@@ -10783,7 +10915,7 @@
10783
10915
  if (!isStandalone) {
10784
10916
  const meta = document.createElement("div");
10785
10917
  meta.className = "gdp-source-meta";
10786
- meta.textContent = target.path + " @ " + target.ref;
10918
+ meta.textContent = `${target.path} @ ${target.ref}`;
10787
10919
  view.appendChild(meta);
10788
10920
  }
10789
10921
  view.appendChild(link2);
@@ -10835,7 +10967,9 @@
10835
10967
  const repoTarget = repoFileTargetFromRoute();
10836
10968
  setPageMode();
10837
10969
  removeStandaloneSource();
10838
- document.querySelectorAll(".gdp-repo-blob-layout").forEach((el) => el.remove());
10970
+ document.querySelectorAll(".gdp-repo-blob-layout").forEach((el) => {
10971
+ el.remove();
10972
+ });
10839
10973
  const card = document.createElement("article");
10840
10974
  card.className = "gdp-file-shell loaded gdp-standalone-source gdp-source-mode";
10841
10975
  card.dataset.path = target.path;
@@ -10941,7 +11075,7 @@
10941
11075
  return;
10942
11076
  if (!response.ok) {
10943
11077
  finishSourceLoad(req);
10944
- renderSourceError(card, target, "Cannot load " + target.path + " at " + target.ref);
11078
+ renderSourceError(card, target, `Cannot load ${target.path} at ${target.ref}`);
10945
11079
  return;
10946
11080
  }
10947
11081
  const textValue = await response.text();
@@ -10963,7 +11097,7 @@
10963
11097
  renderSourceCancelled(card, target);
10964
11098
  return;
10965
11099
  }
10966
- renderSourceError(card, target, "Cannot load " + target.path + " at " + target.ref);
11100
+ renderSourceError(card, target, `Cannot load ${target.path} at ${target.ref}`);
10967
11101
  }
10968
11102
  }
10969
11103
  function scrollStandaloneSourceLine(card, line) {
@@ -10976,7 +11110,7 @@
10976
11110
  virtualScroller.__gdpRenderVirtualSource?.();
10977
11111
  return;
10978
11112
  }
10979
- const row = card.querySelector('.gdp-source-table tr[data-line="' + String(line) + '"]');
11113
+ const row = card.querySelector(`.gdp-source-table tr[data-line="${String(line)}"]`);
10980
11114
  if (row)
10981
11115
  row.scrollIntoView({ block: "center" });
10982
11116
  }
@@ -11117,7 +11251,8 @@
11117
11251
  }
11118
11252
  const total = (file.additions || 0) + (file.deletions || 0);
11119
11253
  const SEG = 5;
11120
- let aSeg, dSeg;
11254
+ let aSeg;
11255
+ let dSeg;
11121
11256
  if (total === 0) {
11122
11257
  aSeg = 0;
11123
11258
  dSeg = 0;
@@ -11174,7 +11309,7 @@
11174
11309
  card.style.minHeight = "";
11175
11310
  mountDiff(card, file, data);
11176
11311
  applyDiffRouteFocus(card);
11177
- card.style.containIntrinsicSize = Math.max(card.offsetHeight, file.estimated_height_px || 200) + "px";
11312
+ card.style.containIntrinsicSize = `${Math.max(card.offsetHeight, file.estimated_height_px || 200)}px`;
11178
11313
  applyViewedToCard(card, STATE.viewedFiles.has(file.path), true);
11179
11314
  if (data.truncated && data.mode === "preview") {
11180
11315
  addExpandHunksUI(file, data, card);
@@ -11201,15 +11336,15 @@
11201
11336
  const step = Math.min(10, remaining);
11202
11337
  const moreBtn = document.createElement("button");
11203
11338
  moreBtn.className = "gdp-show-full";
11204
- moreBtn.textContent = "Show next " + step + " hunk" + (step === 1 ? "" : "s");
11339
+ moreBtn.textContent = `Show next ${step} hunk${step === 1 ? "" : "s"}`;
11205
11340
  moreBtn.addEventListener("click", () => loadMore(rendered + step, false));
11206
11341
  const allBtn = document.createElement("button");
11207
11342
  allBtn.className = "gdp-show-full secondary";
11208
- allBtn.textContent = "Show all (" + remaining + " remaining)";
11343
+ allBtn.textContent = `Show all (${remaining} remaining)`;
11209
11344
  allBtn.addEventListener("click", () => loadMore(total, true));
11210
11345
  const note = document.createElement("span");
11211
11346
  note.className = "gdp-hunk-note";
11212
- note.textContent = rendered + " / " + total + " hunks shown";
11347
+ note.textContent = `${rendered} / ${total} hunks shown`;
11213
11348
  wrap.appendChild(note);
11214
11349
  wrap.appendChild(moreBtn);
11215
11350
  wrap.appendChild(allBtn);
@@ -11257,10 +11392,10 @@
11257
11392
  if (!STATE.syntaxHighlight)
11258
11393
  return;
11259
11394
  const hljsRef = getHljs();
11260
- if (!hljsRef || !hljsRef.highlight)
11395
+ if (!hljsRef?.highlight)
11261
11396
  return;
11262
11397
  const lang = inferLang(file.path);
11263
- if (!lang || !hljsRef.getLanguage || !hljsRef.getLanguage(lang))
11398
+ if (!lang || !hljsRef.getLanguage?.(lang))
11264
11399
  return;
11265
11400
  const spans = card.querySelectorAll("tr.gdp-inserted-ctx .d2h-code-line-ctn:not([data-gdp-hl])");
11266
11401
  spans.forEach((s2) => {
@@ -11288,10 +11423,10 @@
11288
11423
  if (!("requestIdleCallback" in window))
11289
11424
  return;
11290
11425
  const hljsRef = getHljs();
11291
- if (!hljsRef || !hljsRef.highlight)
11426
+ if (!hljsRef?.highlight)
11292
11427
  return;
11293
11428
  const lang = inferLang(file.path);
11294
- if (!lang || !hljsRef.getLanguage || !hljsRef.getLanguage(lang))
11429
+ if (!lang || !hljsRef.getLanguage?.(lang))
11295
11430
  return;
11296
11431
  const work = (deadline) => {
11297
11432
  const spans = card.querySelectorAll(".d2h-code-line-ctn:not([data-gdp-hl])");
@@ -11353,17 +11488,17 @@
11353
11488
  return AUDIO_RE.test(p2);
11354
11489
  }
11355
11490
  function fileURL(path, ref) {
11356
- return "/_file?path=" + encodeURIComponent(path) + "&ref=" + ref;
11491
+ return `/_file?path=${encodeURIComponent(path)}&ref=${ref}`;
11357
11492
  }
11358
11493
  function mediaTag(path, ref) {
11359
11494
  const url = fileURL(path, ref);
11360
11495
  if (isVideo(path)) {
11361
- return '<video src="' + url + '" controls preload="metadata"></video>';
11496
+ return `<video src="${url}" controls preload="metadata"></video>`;
11362
11497
  }
11363
11498
  if (isAudio(path)) {
11364
- return '<audio src="' + url + '" controls preload="metadata"></audio>';
11499
+ return `<audio src="${url}" controls preload="metadata"></audio>`;
11365
11500
  }
11366
- return '<img src="' + url + '" alt="" loading="lazy">';
11501
+ return `<img src="${url}" alt="" loading="lazy">`;
11367
11502
  }
11368
11503
  function enhanceMediaCard(file, card) {
11369
11504
  const path = file.path;
@@ -11377,7 +11512,8 @@
11377
11512
  return;
11378
11513
  const container = document.createElement("div");
11379
11514
  container.className = "gdp-media";
11380
- let leftHTML, rightHTML;
11515
+ let leftHTML;
11516
+ let rightHTML;
11381
11517
  if (file.status === "A") {
11382
11518
  leftHTML = '<div class="media-empty">Not in HEAD</div>';
11383
11519
  rightHTML = mediaTag(path, "worktree");
@@ -11401,7 +11537,7 @@
11401
11537
  handler._raf = null;
11402
11538
  if (performance.now() < SUPPRESS_SPY_UNTIL)
11403
11539
  return;
11404
- const topbarH = parseInt(getComputedStyle(document.documentElement).getPropertyValue("--topbar-h")) || 56;
11540
+ const topbarH = parseInt(getComputedStyle(document.documentElement).getPropertyValue("--topbar-h"), 10) || 56;
11405
11541
  const scanY = topbarH + 24;
11406
11542
  const cards = document.querySelectorAll(".gdp-file-shell");
11407
11543
  for (const w of cards) {
@@ -11419,7 +11555,7 @@
11419
11555
  markActive(best);
11420
11556
  const recentlyTouched = performance.now() - (window.__gdpSidebarTouchedAt || 0) < 1500;
11421
11557
  if (!recentlyTouched) {
11422
- const li = document.querySelector('#filelist li[data-path="' + CSS.escape(best) + '"]');
11558
+ const li = document.querySelector(`#filelist li[data-path="${CSS.escape(best)}"]`);
11423
11559
  if (li) {
11424
11560
  const sb = document.querySelector("#sidebar");
11425
11561
  if (!sb)
@@ -11443,7 +11579,7 @@
11443
11579
  window.addEventListener("scroll", handler, { passive: true });
11444
11580
  handler(new Event("scroll"));
11445
11581
  }
11446
- function collapseAll(force) {
11582
+ function _collapseAll(force) {
11447
11583
  STATE.collapsed = typeof force === "boolean" ? force : !STATE.collapsed;
11448
11584
  document.querySelectorAll(".gdp-file-shell.loaded .d2h-file-wrapper").forEach((w) => {
11449
11585
  const body = w.querySelector(".d2h-files-diff, .d2h-file-diff");
@@ -11487,7 +11623,7 @@
11487
11623
  });
11488
11624
  function applySidebarWidth(w) {
11489
11625
  const cw = Math.max(180, Math.min(900, w));
11490
- document.documentElement.style.setProperty("--sidebar-w", cw + "px");
11626
+ document.documentElement.style.setProperty("--sidebar-w", `${cw}px`);
11491
11627
  STATE.sbWidth = cw;
11492
11628
  localStorage.setItem("gdp:sbwidth", String(cw));
11493
11629
  }
@@ -11528,14 +11664,14 @@
11528
11664
  currentW = startW;
11529
11665
  document.body.classList.add("gdp-resizing");
11530
11666
  preview.style.display = "block";
11531
- preview.style.left = startW + "px";
11667
+ preview.style.left = `${startW}px`;
11532
11668
  e2.preventDefault();
11533
11669
  });
11534
11670
  window.addEventListener("mousemove", (e2) => {
11535
11671
  if (!dragging)
11536
11672
  return;
11537
11673
  currentW = clamp(startW + (e2.clientX - startX));
11538
- preview.style.left = currentW + "px";
11674
+ preview.style.left = `${currentW}px`;
11539
11675
  });
11540
11676
  window.addEventListener("mouseup", () => {
11541
11677
  if (!dragging)
@@ -11869,7 +12005,7 @@
11869
12005
  state.items.forEach((item, index) => {
11870
12006
  const row = document.createElement("button");
11871
12007
  row.type = "button";
11872
- row.id = "gdp-palette-item-" + index;
12008
+ row.id = `gdp-palette-item-${index}`;
11873
12009
  row.className = "gdp-palette-row";
11874
12010
  row.setAttribute("role", "option");
11875
12011
  row.setAttribute("aria-selected", index === state.selected ? "true" : "false");
@@ -11881,10 +12017,10 @@
11881
12017
  title.textContent = item.path.split("/").pop() || item.path;
11882
12018
  appendHighlightedPath(detail, item.displayPath, item.ranges);
11883
12019
  if (item.old_path && item.displayPath !== item.old_path) {
11884
- detail.appendChild(document.createTextNode(" " + item.old_path));
12020
+ detail.appendChild(document.createTextNode(` ${item.old_path}`));
11885
12021
  }
11886
12022
  } else {
11887
- title.textContent = item.path + ":" + item.line;
12023
+ title.textContent = `${item.path}:${item.line}`;
11888
12024
  detail.textContent = item.preview;
11889
12025
  }
11890
12026
  row.append(title, detail);
@@ -11902,7 +12038,7 @@
11902
12038
  syncPaletteSelection(state);
11903
12039
  }
11904
12040
  function syncPaletteSelection(state) {
11905
- state.input.setAttribute("aria-activedescendant", state.selected >= 0 ? "gdp-palette-item-" + state.selected : "");
12041
+ state.input.setAttribute("aria-activedescendant", state.selected >= 0 ? `gdp-palette-item-${state.selected}` : "");
11906
12042
  state.list.querySelectorAll(".gdp-palette-row").forEach((row, index) => {
11907
12043
  row.setAttribute("aria-selected", index === state.selected ? "true" : "false");
11908
12044
  if (index === state.selected)
@@ -11917,7 +12053,7 @@
11917
12053
  const params = new URLSearchParams;
11918
12054
  params.set("ref", ref);
11919
12055
  appendScopeOmitDirsParam(params);
11920
- const res = await trackLoad(fetch("/_files?" + params.toString()).then((r2) => {
12056
+ const res = await trackLoad(fetch(`/_files?${params.toString()}`).then((r2) => {
11921
12057
  if (!r2.ok)
11922
12058
  throw new Error("failed to load files");
11923
12059
  return r2.json();
@@ -11965,7 +12101,7 @@
11965
12101
  }) : [];
11966
12102
  state.items = limitPaletteResults(base2);
11967
12103
  state.selected = state.items.length ? 0 : -1;
11968
- state.status.textContent = source === "diff" ? state.diffSnapshot.length + " diff files" : "Type to search repository files";
12104
+ state.status.textContent = source === "diff" ? `${state.diffSnapshot.length} diff files` : "Type to search repository files";
11969
12105
  renderPalette(state);
11970
12106
  return;
11971
12107
  }
@@ -11987,7 +12123,7 @@
11987
12123
  }));
11988
12124
  }
11989
12125
  state.selected = state.items.length ? 0 : -1;
11990
- state.status.textContent = state.items.length ? state.items.length + " results" : "No results";
12126
+ state.status.textContent = state.items.length ? `${state.items.length} results` : "No results";
11991
12127
  renderPalette(state);
11992
12128
  }
11993
12129
  function updateGrepPalette(state, query) {
@@ -12027,7 +12163,7 @@
12027
12163
  }
12028
12164
  const controller = new AbortController;
12029
12165
  state.controller = controller;
12030
- trackLoad(fetch("/_grep?" + params.toString(), {
12166
+ trackLoad(fetch(`/_grep?${params.toString()}`, {
12031
12167
  signal: controller.signal
12032
12168
  }).then((r2) => {
12033
12169
  if (!r2.ok)
@@ -12285,7 +12421,7 @@
12285
12421
  if (!isPlainPageKey && !isCtrlArrowKey)
12286
12422
  return false;
12287
12423
  const scroller = findMainScrollTarget();
12288
- if (!scroller || !scroller.matches("#content .gdp-source-virtual-scroller"))
12424
+ if (!scroller?.matches("#content .gdp-source-virtual-scroller"))
12289
12425
  return false;
12290
12426
  const pageDown = key === "pagedown" || key === "arrowdown";
12291
12427
  const pageUp = key === "pageup" || key === "arrowup";
@@ -12343,7 +12479,7 @@
12343
12479
  if (STATE.route.path)
12344
12480
  params.set("path", STATE.route.path);
12345
12481
  appendScopeOmitDirsParam(params);
12346
- return trackLoad(fetch("/_tree?" + params.toString()).then((r2) => {
12482
+ return trackLoad(fetch(`/_tree?${params.toString()}`).then((r2) => {
12347
12483
  if (!r2.ok)
12348
12484
  throw new Error("failed to load repository tree");
12349
12485
  return r2.json();
@@ -12372,7 +12508,7 @@
12372
12508
  params.set("to", STATE.to);
12373
12509
  if (options.force)
12374
12510
  params.set("nocache", "1");
12375
- const url = "/diff.json" + (params.toString() ? "?" + params.toString() : "");
12511
+ const url = `/diff.json${params.toString() ? `?${params.toString()}` : ""}`;
12376
12512
  return trackLoad(fetch(url).then((r2) => r2.json())).then((data) => {
12377
12513
  renderShell(data);
12378
12514
  setStatus("live");
@@ -12430,6 +12566,8 @@
12430
12566
  const popover = $("#ref-popover");
12431
12567
  const popBody = popover.querySelector(".rp-body");
12432
12568
  const popSearch = popover.querySelector(".rp-search");
12569
+ if (!popBody || !popSearch)
12570
+ return;
12433
12571
  let popTarget = null;
12434
12572
  function fetchRefs() {
12435
12573
  return fetch("/_refs").then((r2) => r2.json()).then((refs) => {
@@ -12438,37 +12576,75 @@
12438
12576
  }
12439
12577
  fetchRefs();
12440
12578
  let popTab = "commits";
12579
+ let commitSearchTimer = null;
12580
+ let commitSearchSeq = 0;
12581
+ let commitSearchAbort = null;
12582
+ let commitSearchLoading = false;
12583
+ function fetchCommitRefs(query) {
12584
+ const seq = ++commitSearchSeq;
12585
+ if (commitSearchAbort)
12586
+ commitSearchAbort.abort();
12587
+ commitSearchAbort = new AbortController;
12588
+ const url = `/_commits?max=100&q=${encodeURIComponent((query || "").trim())}`;
12589
+ return fetch(url, { signal: commitSearchAbort.signal }).then((r2) => r2.json()).then((refs) => {
12590
+ if (seq !== commitSearchSeq)
12591
+ return;
12592
+ commitSearchLoading = false;
12593
+ REFS.commits = refs.commits || [];
12594
+ if (!popover.hidden && popTab === "commits") {
12595
+ buildPopBody(popSearch.value);
12596
+ }
12597
+ }).catch(() => {
12598
+ if (seq === commitSearchSeq)
12599
+ commitSearchLoading = false;
12600
+ });
12601
+ }
12602
+ function scheduleCommitSearch(query) {
12603
+ if (commitSearchTimer)
12604
+ clearTimeout(commitSearchTimer);
12605
+ commitSearchLoading = true;
12606
+ commitSearchTimer = setTimeout(() => {
12607
+ commitSearchTimer = null;
12608
+ fetchCommitRefs(query);
12609
+ }, 150);
12610
+ }
12441
12611
  function buildPopBody(query) {
12442
12612
  const q = (query || "").toLowerCase().trim();
12443
12613
  const m = (s2) => !q || String(s2).toLowerCase().includes(q);
12444
12614
  const html = [];
12445
12615
  if (popTab === "commits") {
12446
- const commits = (REFS.commits || []).filter((c2) => m(c2));
12616
+ if (commitSearchLoading) {
12617
+ html.push('<div class="rp-empty">loading commits...</div>');
12618
+ popBody.innerHTML = html.join("");
12619
+ highlightCurrentInPopover();
12620
+ return;
12621
+ }
12622
+ const commits = (REFS.commits || []).filter((commit) => m(`${commit.sha} ${commit.subject} ${commit.author}`));
12447
12623
  if (!commits.length) {
12448
12624
  html.push('<div class="rp-empty">no commits</div>');
12449
12625
  }
12450
- for (const c2 of commits) {
12451
- const [sha, subject, author, when] = c2.split("\t");
12452
- if (!sha)
12626
+ for (const commit of commits) {
12627
+ if (!commit.sha)
12453
12628
  continue;
12454
- html.push('<div class="rp-item-commit" data-val="' + escapeAttr(sha) + '"><div class="row1"><span class="sha">' + escapeHtml2(sha) + '</span><span class="subject" title="' + escapeAttr(subject || "") + '">' + escapeHtml2(subject || "") + '</span></div><div class="row2"><span class="author">' + escapeHtml2(author || "") + '</span><span class="when">' + escapeHtml2(when || "") + "</span></div></div>");
12629
+ const shortSha = commit.sha.slice(0, 7);
12630
+ html.push('<div class="rp-item-commit" data-val="' + escapeAttr(commit.sha) + '"><div class="row1"><span class="sha">' + escapeHtml2(shortSha) + '</span><span class="subject" title="' + escapeAttr(commit.subject || "") + '">' + escapeHtml2(commit.subject || "") + '</span></div><div class="row2"><span class="author">' + escapeHtml2(commit.author || "") + '</span><span class="when">' + escapeHtml2(commit.when || "") + "</span></div></div>");
12455
12631
  }
12456
12632
  } else if (popTab === "branches") {
12457
- const branches = (REFS.branches || []).filter(m);
12633
+ const branches = (REFS.branches || []).filter((b2) => m(b2.name));
12458
12634
  if (!branches.length) {
12459
12635
  html.push('<div class="rp-empty">no branches</div>');
12460
12636
  }
12461
- for (const b2 of branches) {
12462
- const cur = b2 === REFS.current;
12463
- html.push('<div class="rp-item-ref" data-val="' + escapeAttr(b2) + '"><span class="name">' + escapeHtml2(b2) + "</span>" + (cur ? '<span class="badge cur">current</span>' : '<span class="badge">branch</span>') + "</div>");
12637
+ for (const branch of branches) {
12638
+ const cur = branch.name === REFS.current;
12639
+ html.push('<div class="rp-item-ref" data-val="' + escapeAttr(branch.name) + '"><div class="row1"><span class="name">' + escapeHtml2(branch.name) + "</span>" + (cur ? '<span class="badge cur">current</span>' : '<span class="badge">branch</span>') + "</div>" + (branch.when ? '<div class="row2"><span class="when">' + escapeHtml2(branch.when) + "</span></div>" : "") + "</div>");
12464
12640
  }
12465
12641
  } else if (popTab === "tags") {
12466
- const tags = (REFS.tags || []).filter(m);
12642
+ const tags = (REFS.tags || []).filter((t2) => m(t2.name));
12467
12643
  if (!tags.length) {
12468
12644
  html.push('<div class="rp-empty">no tags</div>');
12469
12645
  }
12470
- for (const t2 of tags) {
12471
- html.push('<div class="rp-item-ref" data-val="' + escapeAttr(t2) + '"><span class="name">' + escapeHtml2(t2) + '</span><span class="badge">tag</span></div>');
12646
+ for (const tag of tags) {
12647
+ html.push('<div class="rp-item-ref" data-val="' + escapeAttr(tag.name) + '"><div class="row1"><span class="name">' + escapeHtml2(tag.name) + '</span><span class="badge">tag</span></div>' + (tag.when ? '<div class="row2"><span class="when">' + escapeHtml2(tag.when) + "</span></div>" : "") + "</div>");
12472
12648
  }
12473
12649
  }
12474
12650
  popBody.innerHTML = html.join("");
@@ -12502,6 +12678,8 @@
12502
12678
  function openPopover(input) {
12503
12679
  popTarget = input;
12504
12680
  popSearch.value = "";
12681
+ if (popTab === "commits")
12682
+ scheduleCommitSearch("");
12505
12683
  buildPopBody("");
12506
12684
  const cur = (input.value || "").trim();
12507
12685
  popover.querySelectorAll(".rp-chip").forEach((c2) => {
@@ -12510,8 +12688,8 @@
12510
12688
  popover.hidden = false;
12511
12689
  const r2 = input.getBoundingClientRect();
12512
12690
  const popWidth = Math.min(560, Math.floor(window.innerWidth * 0.9));
12513
- popover.style.left = Math.max(8, Math.min(r2.left, window.innerWidth - popWidth - 8)) + "px";
12514
- popover.style.top = r2.bottom + 4 + "px";
12691
+ popover.style.left = `${Math.max(8, Math.min(r2.left, window.innerWidth - popWidth - 8))}px`;
12692
+ popover.style.top = `${r2.bottom + 4}px`;
12515
12693
  setTimeout(() => popSearch.focus(), 0);
12516
12694
  }
12517
12695
  function closePopover() {
@@ -12539,13 +12717,17 @@
12539
12717
  });
12540
12718
  renderStandaloneSource({ path: STATE.route.path, ref });
12541
12719
  });
12542
- popSearch.addEventListener("input", () => buildPopBody(popSearch.value));
12720
+ popSearch.addEventListener("input", () => {
12721
+ if (popTab === "commits")
12722
+ scheduleCommitSearch(popSearch.value);
12723
+ buildPopBody(popSearch.value);
12724
+ });
12543
12725
  popSearch.addEventListener("keydown", (e2) => {
12544
12726
  if (e2.key === "Escape") {
12545
12727
  closePopover();
12546
12728
  }
12547
12729
  if (e2.key === "Enter") {
12548
- const first = popBody.querySelector(".rp-item");
12730
+ const first = popBody.querySelector(".rp-item-commit, .rp-item-ref");
12549
12731
  if (first)
12550
12732
  first.click();
12551
12733
  }
@@ -12567,7 +12749,11 @@
12567
12749
  popover.querySelectorAll(".rp-tab").forEach((t2) => {
12568
12750
  t2.addEventListener("click", () => {
12569
12751
  popTab = t2.dataset.tab || "commits";
12570
- popover.querySelectorAll(".rp-tab").forEach((b2) => b2.classList.toggle("active", b2 === t2));
12752
+ popover.querySelectorAll(".rp-tab").forEach((b2) => {
12753
+ b2.classList.toggle("active", b2 === t2);
12754
+ });
12755
+ if (popTab === "commits")
12756
+ scheduleCommitSearch(popSearch.value);
12571
12757
  buildPopBody(popSearch.value);
12572
12758
  });
12573
12759
  });