@youtyan/code-viewer 0.1.19 → 0.1.21
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/dist/code-viewer.js +18 -7
- package/package.json +2 -2
- package/web/app.js +189 -142
- package/web/style.css +23 -10
package/dist/code-viewer.js
CHANGED
|
@@ -342,24 +342,35 @@ function refs(cwd) {
|
|
|
342
342
|
"git",
|
|
343
343
|
"for-each-ref",
|
|
344
344
|
"--sort=-committerdate",
|
|
345
|
-
"--format=%(refname:short)",
|
|
345
|
+
"--format=%(refname)%09%(refname:short)%09%(committerdate:iso-strict)",
|
|
346
346
|
"refs/heads",
|
|
347
347
|
"refs/remotes"
|
|
348
348
|
], cwd);
|
|
349
349
|
if (branches.code === 0) {
|
|
350
|
-
|
|
351
|
-
`)
|
|
350
|
+
for (const line of branches.stdout.split(`
|
|
351
|
+
`)) {
|
|
352
|
+
const [fullName, name, when] = line.split("\t");
|
|
353
|
+
if (!fullName || !name || fullName.startsWith("refs/remotes/") && fullName.endsWith("/HEAD"))
|
|
354
|
+
continue;
|
|
355
|
+
out.branches.push({ name, when });
|
|
356
|
+
}
|
|
352
357
|
}
|
|
353
358
|
const tags = run([
|
|
354
359
|
"git",
|
|
355
360
|
"for-each-ref",
|
|
356
361
|
"--sort=-creatordate",
|
|
357
|
-
"--format=%(refname:short)",
|
|
362
|
+
"--format=%(refname:short)%09%(creatordate:iso-strict)",
|
|
358
363
|
"refs/tags"
|
|
359
364
|
], cwd);
|
|
360
|
-
if (tags.code === 0)
|
|
361
|
-
|
|
362
|
-
`)
|
|
365
|
+
if (tags.code === 0) {
|
|
366
|
+
for (const line of tags.stdout.split(`
|
|
367
|
+
`)) {
|
|
368
|
+
const [name, when] = line.split("\t");
|
|
369
|
+
if (!name)
|
|
370
|
+
continue;
|
|
371
|
+
out.tags.push({ name, when });
|
|
372
|
+
}
|
|
373
|
+
}
|
|
363
374
|
out.commits = refCommits(cwd, "", DEFAULT_REF_COMMIT_LIMIT);
|
|
364
375
|
out.current = currentBranch(cwd) || "";
|
|
365
376
|
return out;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@youtyan/code-viewer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.21",
|
|
4
4
|
"description": "Local browser-based code and git diff viewer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"preview": "bun run web-src/server/dev.ts",
|
|
38
38
|
"preview:raw": "bun run web-src/server/preview.ts",
|
|
39
39
|
"test": "bun test",
|
|
40
|
-
"lint": "biome lint web-src
|
|
40
|
+
"lint": "biome lint web-src package.json biome.jsonc",
|
|
41
41
|
"verify": "bun run check && bun run lint && bun run check:format && bun run build && bun run check:bundle && bun run test && node --check web/app.js && node --check web/mermaid.js && node --check web/shiki.js && node --check dist/code-viewer.js && node dist/code-viewer.js --help && node scripts/node-smoke.mjs",
|
|
42
42
|
"pack:dry": "npm pack --dry-run",
|
|
43
43
|
"prepack": "bun run build",
|
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) ?
|
|
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 +=
|
|
317
|
+
source += `[${body}]`;
|
|
318
318
|
i = close;
|
|
319
319
|
}
|
|
320
320
|
} else {
|
|
@@ -6092,7 +6092,7 @@
|
|
|
6092
6092
|
|
|
6093
6093
|
// web-src/routes.ts
|
|
6094
6094
|
function assertNever(value) {
|
|
6095
|
-
throw new Error(
|
|
6095
|
+
throw new Error(`unhandled route: ${JSON.stringify(value)}`);
|
|
6096
6096
|
}
|
|
6097
6097
|
function parseLegacyRange(value, fallback) {
|
|
6098
6098
|
const raw = value || "";
|
|
@@ -6120,7 +6120,7 @@
|
|
|
6120
6120
|
return Number.isInteger(line) && line > 0 ? line : undefined;
|
|
6121
6121
|
}
|
|
6122
6122
|
function formatLineTarget(line) {
|
|
6123
|
-
return typeof line === "number" ? String(line) : line.start
|
|
6123
|
+
return typeof line === "number" ? String(line) : `${line.start}-${line.end}`;
|
|
6124
6124
|
}
|
|
6125
6125
|
function parseRoute(pathname, search, fallbackRange) {
|
|
6126
6126
|
const params = new URLSearchParams(search);
|
|
@@ -6194,15 +6194,15 @@
|
|
|
6194
6194
|
if (route.path)
|
|
6195
6195
|
params.set("path", route.path);
|
|
6196
6196
|
const qs = params.toString();
|
|
6197
|
-
return
|
|
6197
|
+
return `/${qs ? `?${qs}` : ""}`;
|
|
6198
6198
|
}
|
|
6199
6199
|
case "file":
|
|
6200
6200
|
if (route.view === "blob") {
|
|
6201
|
-
return "/file?path=" + encodeURIComponent(route.path) + "&target=" + encodeURIComponent(route.ref || "worktree") + (route.line ?
|
|
6201
|
+
return "/file?path=" + encodeURIComponent(route.path) + "&target=" + encodeURIComponent(route.ref || "worktree") + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "");
|
|
6202
6202
|
}
|
|
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 ?
|
|
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))}` : "");
|
|
6204
6204
|
case "diff":
|
|
6205
|
-
return "/todif?from=" + encodeURIComponent(route.range.from || "") + "&to=" + encodeURIComponent(route.range.to || "worktree") + (route.path ?
|
|
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))}` : "");
|
|
6206
6206
|
case "help": {
|
|
6207
6207
|
const params = new URLSearchParams;
|
|
6208
6208
|
if (route.lang && route.lang !== "en")
|
|
@@ -6210,7 +6210,7 @@
|
|
|
6210
6210
|
if (route.section && route.section !== "keybindings")
|
|
6211
6211
|
params.set("section", route.section);
|
|
6212
6212
|
const qs = params.toString();
|
|
6213
|
-
return
|
|
6213
|
+
return `/help${qs ? `?${qs}` : ""}`;
|
|
6214
6214
|
}
|
|
6215
6215
|
case "unknown":
|
|
6216
6216
|
return "/todif?from=" + encodeURIComponent(route.range.from || "") + "&to=" + encodeURIComponent(route.range.to || "worktree");
|
|
@@ -6331,7 +6331,7 @@
|
|
|
6331
6331
|
});
|
|
6332
6332
|
} catch {}
|
|
6333
6333
|
}
|
|
6334
|
-
return
|
|
6334
|
+
return `<pre><code>${md.utils.escapeHtml(code2)}</code></pre>`;
|
|
6335
6335
|
}
|
|
6336
6336
|
});
|
|
6337
6337
|
md.use(b, {
|
|
@@ -6431,7 +6431,10 @@
|
|
|
6431
6431
|
const frontmatter = splitYamlFrontmatter(textValue);
|
|
6432
6432
|
if (!frontmatter)
|
|
6433
6433
|
return md.render(textValue);
|
|
6434
|
-
return '<div class="gdp-markdown-frontmatter" data-gdp-frontmatter="yaml">' + md.render(
|
|
6434
|
+
return '<div class="gdp-markdown-frontmatter" data-gdp-frontmatter="yaml">' + md.render(`\`\`\`yaml
|
|
6435
|
+
${frontmatter.yaml}
|
|
6436
|
+
\`\`\`
|
|
6437
|
+
`) + "</div>" + md.render(frontmatter.body);
|
|
6435
6438
|
}
|
|
6436
6439
|
function splitYamlFrontmatter(textValue) {
|
|
6437
6440
|
if (!textValue.startsWith(`---
|
|
@@ -6443,7 +6446,7 @@
|
|
|
6443
6446
|
` : `
|
|
6444
6447
|
`;
|
|
6445
6448
|
const start = 3 + newline2.length;
|
|
6446
|
-
const closing = textValue.indexOf(newline2
|
|
6449
|
+
const closing = textValue.indexOf(`${newline2}---${newline2}`, start);
|
|
6447
6450
|
if (closing < 0)
|
|
6448
6451
|
return null;
|
|
6449
6452
|
return {
|
|
@@ -6492,9 +6495,9 @@
|
|
|
6492
6495
|
const list2 = document.createElement("ul");
|
|
6493
6496
|
entries.forEach((entry) => {
|
|
6494
6497
|
const item = document.createElement("li");
|
|
6495
|
-
item.className =
|
|
6498
|
+
item.className = `level-${entry.level}`;
|
|
6496
6499
|
const link2 = document.createElement("a");
|
|
6497
|
-
link2.href =
|
|
6500
|
+
link2.href = `#${encodeURIComponent(entry.id)}`;
|
|
6498
6501
|
link2.dataset.target = entry.id;
|
|
6499
6502
|
link2.textContent = entry.text;
|
|
6500
6503
|
item.appendChild(link2);
|
|
@@ -6525,7 +6528,7 @@
|
|
|
6525
6528
|
return;
|
|
6526
6529
|
const entries = Array.from(toc.querySelectorAll("a[data-target]")).map((link2) => ({
|
|
6527
6530
|
link: link2,
|
|
6528
|
-
target: root.querySelector(
|
|
6531
|
+
target: root.querySelector(`#${CSS.escape(link2.dataset.target || "")}`)
|
|
6529
6532
|
})).filter((entry) => !!entry.target);
|
|
6530
6533
|
if (!entries.length)
|
|
6531
6534
|
return;
|
|
@@ -6533,12 +6536,12 @@
|
|
|
6533
6536
|
const link2 = e2.target?.closest("a[data-target]");
|
|
6534
6537
|
if (!link2)
|
|
6535
6538
|
return;
|
|
6536
|
-
const section = root.querySelector(
|
|
6539
|
+
const section = root.querySelector(`#${CSS.escape(link2.dataset.target || "")}`);
|
|
6537
6540
|
if (!section)
|
|
6538
6541
|
return;
|
|
6539
6542
|
e2.preventDefault();
|
|
6540
6543
|
section.scrollIntoView({ block: "start", behavior: "smooth" });
|
|
6541
|
-
history.replaceState(history.state, "",
|
|
6544
|
+
history.replaceState(history.state, "", `#${encodeURIComponent(section.id)}`);
|
|
6542
6545
|
});
|
|
6543
6546
|
const controller = new AbortController;
|
|
6544
6547
|
const scrollRoot = document.scrollingElement || document.documentElement;
|
|
@@ -6564,7 +6567,9 @@
|
|
|
6564
6567
|
if (window.innerHeight + scrollRoot.scrollTop >= scrollRoot.scrollHeight - 4) {
|
|
6565
6568
|
active = entries[entries.length - 1];
|
|
6566
6569
|
}
|
|
6567
|
-
entries.forEach((entry) =>
|
|
6570
|
+
entries.forEach((entry) => {
|
|
6571
|
+
entry.link.classList.toggle("active", entry === active);
|
|
6572
|
+
});
|
|
6568
6573
|
keepTocLinkVisible(toc, active.link);
|
|
6569
6574
|
};
|
|
6570
6575
|
const schedule = () => {
|
|
@@ -6698,7 +6703,7 @@
|
|
|
6698
6703
|
let tx = 0;
|
|
6699
6704
|
let ty = 0;
|
|
6700
6705
|
const apply = () => {
|
|
6701
|
-
svg.style.transform =
|
|
6706
|
+
svg.style.transform = `translate(${tx}px, ${ty}px) scale(${scale})`;
|
|
6702
6707
|
};
|
|
6703
6708
|
const fit = () => {
|
|
6704
6709
|
const vw = Math.max(1, window.innerWidth - 128);
|
|
@@ -6798,7 +6803,7 @@
|
|
|
6798
6803
|
try {
|
|
6799
6804
|
const box = svg.getBBox();
|
|
6800
6805
|
if (box.width > 0 && box.height > 0) {
|
|
6801
|
-
svg.setAttribute("viewBox", box.x
|
|
6806
|
+
svg.setAttribute("viewBox", `${box.x} ${box.y} ${box.width} ${box.height}`);
|
|
6802
6807
|
svg.setAttribute("width", String(box.width));
|
|
6803
6808
|
svg.setAttribute("height", String(box.height));
|
|
6804
6809
|
return { width: box.width, height: box.height };
|
|
@@ -7040,7 +7045,7 @@
|
|
|
7040
7045
|
return Array.from(document.querySelectorAll("#content .gdp-source-virtual-scroller, #content .gdp-source-table")).some((item) => item.offsetParent !== null);
|
|
7041
7046
|
}
|
|
7042
7047
|
function sourceCursorKey(target) {
|
|
7043
|
-
return target.ref
|
|
7048
|
+
return `${target.ref}\x00${target.path}`;
|
|
7044
7049
|
}
|
|
7045
7050
|
function sourceCursorMatches(target, line) {
|
|
7046
7051
|
return !!SOURCE_CURSOR && sourceTargetsEqual(SOURCE_CURSOR.target, target) && SOURCE_CURSOR.line === line;
|
|
@@ -7095,7 +7100,7 @@
|
|
|
7095
7100
|
syncSourceCursorRows(cursor.target);
|
|
7096
7101
|
return;
|
|
7097
7102
|
}
|
|
7098
|
-
document.querySelector(
|
|
7103
|
+
document.querySelector(`#content [data-line="${cursor.line}"]`)?.scrollIntoView({ block: edge });
|
|
7099
7104
|
}
|
|
7100
7105
|
function moveSourceCursor(direction, unit, edge) {
|
|
7101
7106
|
if (!hasVisibleSourceCodeSurface())
|
|
@@ -7175,7 +7180,7 @@
|
|
|
7175
7180
|
const tabs = document.querySelector("#content .gdp-source-tabs");
|
|
7176
7181
|
if (!tabs)
|
|
7177
7182
|
return false;
|
|
7178
|
-
const button = tabs.querySelector(
|
|
7183
|
+
const button = tabs.querySelector(`button[data-source-tab="${tab}"]`);
|
|
7179
7184
|
if (!button || button.hidden || button.disabled)
|
|
7180
7185
|
return false;
|
|
7181
7186
|
button.click();
|
|
@@ -7205,7 +7210,7 @@
|
|
|
7205
7210
|
if (!project)
|
|
7206
7211
|
return;
|
|
7207
7212
|
PROJECT_NAME = project;
|
|
7208
|
-
document.title = project
|
|
7213
|
+
document.title = `${project} - code viewer`;
|
|
7209
7214
|
}
|
|
7210
7215
|
function savedScopeOmitDirs() {
|
|
7211
7216
|
const raw = localStorage.getItem(scopeOmitDirsStorageKey());
|
|
@@ -7248,7 +7253,7 @@
|
|
|
7248
7253
|
requestAnimationFrame(() => {
|
|
7249
7254
|
const head = document.querySelector(".sb-head");
|
|
7250
7255
|
if (head)
|
|
7251
|
-
document.documentElement.style.setProperty("--sidebar-head-h", Math.ceil(head.getBoundingClientRect().height)
|
|
7256
|
+
document.documentElement.style.setProperty("--sidebar-head-h", `${Math.ceil(head.getBoundingClientRect().height)}px`);
|
|
7252
7257
|
});
|
|
7253
7258
|
}
|
|
7254
7259
|
function observeSidebarHeaderHeight() {
|
|
@@ -7293,7 +7298,7 @@
|
|
|
7293
7298
|
layout: localStorage.getItem("gdp:layout") || "side-by-side",
|
|
7294
7299
|
theme: localStorage.getItem("gdp:theme") || (matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"),
|
|
7295
7300
|
sbView: localStorage.getItem("gdp:sbview") || "tree",
|
|
7296
|
-
sbWidth: parseInt(localStorage.getItem("gdp:sbwidth")) || 308,
|
|
7301
|
+
sbWidth: parseInt(localStorage.getItem("gdp:sbwidth") ?? "", 10) || 308,
|
|
7297
7302
|
sidebarHidden: localStorage.getItem("gdp:sidebar-hidden") === "1",
|
|
7298
7303
|
collapsedDirs: new Set(JSON.parse(localStorage.getItem("gdp:collapsed-dirs") || "[]")),
|
|
7299
7304
|
ignoreWs: igRaw === null ? true : igRaw === "1",
|
|
@@ -7321,7 +7326,7 @@
|
|
|
7321
7326
|
$("#hljs-dark").disabled = STATE.theme !== "dark";
|
|
7322
7327
|
}
|
|
7323
7328
|
function getHljs() {
|
|
7324
|
-
const hljsRef = window.hljs || window.Diff2HtmlUI
|
|
7329
|
+
const hljsRef = window.hljs || window.Diff2HtmlUI?.hljs;
|
|
7325
7330
|
if (!hljsRef)
|
|
7326
7331
|
return null;
|
|
7327
7332
|
if (!highlightConfigured && typeof hljsRef.configure === "function") {
|
|
@@ -7502,7 +7507,7 @@
|
|
|
7502
7507
|
function fileBadge(status) {
|
|
7503
7508
|
const ch = (status || "M")[0].toUpperCase();
|
|
7504
7509
|
const span = document.createElement("span");
|
|
7505
|
-
span.className =
|
|
7510
|
+
span.className = `badge ${ch}`;
|
|
7506
7511
|
span.textContent = ch;
|
|
7507
7512
|
span.title = { M: "modified", A: "added", D: "deleted", R: "renamed" }[ch] || ch;
|
|
7508
7513
|
return span;
|
|
@@ -7542,7 +7547,7 @@
|
|
|
7542
7547
|
}
|
|
7543
7548
|
function iconSvg(className, paths) {
|
|
7544
7549
|
const pathList = Array.isArray(paths) ? paths : [paths];
|
|
7545
|
-
return '<svg class="octicon ' + className + '" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true">' + pathList.map((path) =>
|
|
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>";
|
|
7546
7551
|
}
|
|
7547
7552
|
function setUnfoldButtonState(button, expanded) {
|
|
7548
7553
|
if (!button)
|
|
@@ -7672,7 +7677,7 @@
|
|
|
7672
7677
|
const dirPartCount = f2.type === "tree" ? parts.length : parts.length - 1;
|
|
7673
7678
|
for (let i2 = 0;i2 < dirPartCount; i2++) {
|
|
7674
7679
|
const p2 = parts[i2];
|
|
7675
|
-
acc = acc ? acc
|
|
7680
|
+
acc = acc ? `${acc}/${p2}` : p2;
|
|
7676
7681
|
if (!node.dirs[p2]) {
|
|
7677
7682
|
node.dirs[p2] = {
|
|
7678
7683
|
name: p2,
|
|
@@ -7700,13 +7705,15 @@
|
|
|
7700
7705
|
const ks = Object.keys(node.dirs);
|
|
7701
7706
|
while (ks.length === 1 && node.files.length === 0 && !node.explicit && node !== root) {
|
|
7702
7707
|
const only = node.dirs[ks[0]];
|
|
7703
|
-
node.name = node.name ? node.name
|
|
7708
|
+
node.name = node.name ? `${node.name}/${only.name}` : only.name;
|
|
7704
7709
|
node.dirs = only.dirs;
|
|
7705
7710
|
node.files = only.files;
|
|
7706
7711
|
node.path = only.path;
|
|
7707
7712
|
node.minOrder = Math.min(node.minOrder, only.minOrder);
|
|
7708
7713
|
ks.length = 0;
|
|
7709
|
-
Object.keys(node.dirs).forEach((k) =>
|
|
7714
|
+
Object.keys(node.dirs).forEach((k) => {
|
|
7715
|
+
ks.push(k);
|
|
7716
|
+
});
|
|
7710
7717
|
}
|
|
7711
7718
|
Object.values(node.dirs).forEach(compress);
|
|
7712
7719
|
}
|
|
@@ -7741,7 +7748,7 @@
|
|
|
7741
7748
|
li.classList.add(dir.children_omitted_reason === "heavy" ? "children-omitted-heavy" : "children-omitted-internal");
|
|
7742
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";
|
|
7743
7750
|
}
|
|
7744
|
-
li.style.setProperty("--lvl-pad", 12 + depth * 14
|
|
7751
|
+
li.style.setProperty("--lvl-pad", `${12 + depth * 14}px`);
|
|
7745
7752
|
const chev = document.createElement("span");
|
|
7746
7753
|
if (dir.children_omitted) {
|
|
7747
7754
|
chev.className = "chev-spacer";
|
|
@@ -7820,7 +7827,7 @@
|
|
|
7820
7827
|
li.tabIndex = -1;
|
|
7821
7828
|
li.dataset.path = f2.path;
|
|
7822
7829
|
li.classList.toggle("viewed", !onFileClick && STATE.viewedFiles.has(f2.path));
|
|
7823
|
-
li.style.setProperty("--lvl-pad", 12 + depth * 14
|
|
7830
|
+
li.style.setProperty("--lvl-pad", `${12 + depth * 14}px`);
|
|
7824
7831
|
const spacer = document.createElement("span");
|
|
7825
7832
|
spacer.className = "chev-spacer";
|
|
7826
7833
|
li.appendChild(spacer);
|
|
@@ -7901,7 +7908,7 @@
|
|
|
7901
7908
|
} else {
|
|
7902
7909
|
renderFlat(files, ul, onFileClick);
|
|
7903
7910
|
}
|
|
7904
|
-
$("#totals").textContent = files.length ? files.length
|
|
7911
|
+
$("#totals").textContent = files.length ? `${files.length} file${files.length === 1 ? "" : "s"}` : "";
|
|
7905
7912
|
$$(".sb-view-seg button").forEach((b2) => {
|
|
7906
7913
|
b2.classList.toggle("active", b2.dataset.view === STATE.sbView);
|
|
7907
7914
|
});
|
|
@@ -7939,7 +7946,7 @@
|
|
|
7939
7946
|
}
|
|
7940
7947
|
function createRefSelectorInput(options) {
|
|
7941
7948
|
const wrap = document.createElement("div");
|
|
7942
|
-
wrap.className =
|
|
7949
|
+
wrap.className = `ref-selector${options.extraClass ? ` ${options.extraClass}` : ""}`;
|
|
7943
7950
|
wrap.dataset.refSelector = "";
|
|
7944
7951
|
if (options.wrapperId)
|
|
7945
7952
|
wrap.id = options.wrapperId;
|
|
@@ -7990,7 +7997,7 @@
|
|
|
7990
7997
|
if (meta.branch) {
|
|
7991
7998
|
const b2 = document.createElement("span");
|
|
7992
7999
|
b2.className = "ref";
|
|
7993
|
-
b2.textContent =
|
|
8000
|
+
b2.textContent = `⎇ ${meta.branch}`;
|
|
7994
8001
|
el.appendChild(b2);
|
|
7995
8002
|
}
|
|
7996
8003
|
if (meta.totals) {
|
|
@@ -8002,13 +8009,13 @@
|
|
|
8002
8009
|
const u2 = document.createElement("span");
|
|
8003
8010
|
u2.className = "updated-at";
|
|
8004
8011
|
u2.title = "last updated";
|
|
8005
|
-
u2.textContent =
|
|
8012
|
+
u2.textContent = `updated ${new Date().toLocaleTimeString([], { hour12: false })}`;
|
|
8006
8013
|
el.appendChild(u2);
|
|
8007
8014
|
}
|
|
8008
8015
|
let SUPPRESS_SPY_UNTIL = 0;
|
|
8009
8016
|
function prefetchByPath(path) {
|
|
8010
8017
|
const card = document.querySelector(diffCardSelector(path));
|
|
8011
|
-
if (!card
|
|
8018
|
+
if (!card?.classList.contains("pending"))
|
|
8012
8019
|
return;
|
|
8013
8020
|
const f2 = STATE.files.find((x) => x.path === path);
|
|
8014
8021
|
if (!f2)
|
|
@@ -8083,7 +8090,7 @@
|
|
|
8083
8090
|
for (const dir of sidebarAncestorDirs(path)) {
|
|
8084
8091
|
if (STATE.collapsedDirs.delete(dir))
|
|
8085
8092
|
changed = true;
|
|
8086
|
-
const row = document.querySelector(
|
|
8093
|
+
const row = document.querySelector(`#filelist .tree-dir[data-dirpath="${CSS.escape(dir)}"]`);
|
|
8087
8094
|
row?.classList.remove("collapsed");
|
|
8088
8095
|
const icon = row?.querySelector(".dir-icon");
|
|
8089
8096
|
if (icon)
|
|
@@ -8144,7 +8151,7 @@
|
|
|
8144
8151
|
function updateTreeDirVisibility(dirMatches, filterActive = false) {
|
|
8145
8152
|
$$("#filelist .tree-dir").forEach((dir) => {
|
|
8146
8153
|
const childUl = dir.nextElementSibling;
|
|
8147
|
-
if (!childUl
|
|
8154
|
+
if (!childUl?.classList.contains("tree-children"))
|
|
8148
8155
|
return;
|
|
8149
8156
|
const anyVisible = !!childUl.querySelector(".tree-file:not(.hidden):not(.hidden-by-tests)");
|
|
8150
8157
|
const explicitVisible = dir.dataset.explicit === "true" && !filterActive;
|
|
@@ -8293,8 +8300,12 @@
|
|
|
8293
8300
|
});
|
|
8294
8301
|
}
|
|
8295
8302
|
function removeStandaloneSource() {
|
|
8296
|
-
document.querySelectorAll(".gdp-standalone-source").forEach((el) =>
|
|
8297
|
-
|
|
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
|
+
});
|
|
8298
8309
|
}
|
|
8299
8310
|
function renderHelpPage() {
|
|
8300
8311
|
cancelActiveSourceLoad("navigation");
|
|
@@ -8441,7 +8452,7 @@
|
|
|
8441
8452
|
delete old.dataset.manualRendered;
|
|
8442
8453
|
delete old.dataset.manualLoad;
|
|
8443
8454
|
delete old.dataset.manualMode;
|
|
8444
|
-
old.style.minHeight =
|
|
8455
|
+
old.style.minHeight = `${f2.estimated_height_px || 80}px`;
|
|
8445
8456
|
old._diffData = null;
|
|
8446
8457
|
old._file = null;
|
|
8447
8458
|
} else {
|
|
@@ -8456,7 +8467,9 @@
|
|
|
8456
8467
|
ordered.push(createPlaceholder(f2));
|
|
8457
8468
|
}
|
|
8458
8469
|
});
|
|
8459
|
-
oldByKey.forEach((c2) =>
|
|
8470
|
+
oldByKey.forEach((c2) => {
|
|
8471
|
+
c2.remove();
|
|
8472
|
+
});
|
|
8460
8473
|
target.replaceChildren(...ordered);
|
|
8461
8474
|
for (let i2 = LOAD_QUEUE.length - 1;i2 >= 0; i2--) {
|
|
8462
8475
|
if (!LOAD_QUEUE[i2].card.isConnected)
|
|
@@ -8531,7 +8544,9 @@
|
|
|
8531
8544
|
return;
|
|
8532
8545
|
const form = new FormData;
|
|
8533
8546
|
form.set("dir", path);
|
|
8534
|
-
list2.forEach((file) =>
|
|
8547
|
+
list2.forEach((file) => {
|
|
8548
|
+
form.append("files", file, file.name);
|
|
8549
|
+
});
|
|
8535
8550
|
const res = await fetch("/_upload_files", {
|
|
8536
8551
|
method: "POST",
|
|
8537
8552
|
headers: { "X-Code-Viewer-Action": "1" },
|
|
@@ -8547,7 +8562,7 @@
|
|
|
8547
8562
|
dropPanel.className = "gdp-upload-panel";
|
|
8548
8563
|
const copy = document.createElement("div");
|
|
8549
8564
|
copy.className = "gdp-upload-copy";
|
|
8550
|
-
copy.textContent =
|
|
8565
|
+
copy.textContent = `Drop files into ${path || PROJECT_NAME || "repository"}`;
|
|
8551
8566
|
const input = document.createElement("input");
|
|
8552
8567
|
input.type = "file";
|
|
8553
8568
|
input.multiple = true;
|
|
@@ -8563,7 +8578,7 @@
|
|
|
8563
8578
|
};
|
|
8564
8579
|
input.addEventListener("change", async () => {
|
|
8565
8580
|
try {
|
|
8566
|
-
if (input.files
|
|
8581
|
+
if (input.files?.length)
|
|
8567
8582
|
await uploadFiles(path, input.files);
|
|
8568
8583
|
} catch {
|
|
8569
8584
|
fail();
|
|
@@ -8581,7 +8596,7 @@
|
|
|
8581
8596
|
dropPanel.classList.remove("dragging");
|
|
8582
8597
|
try {
|
|
8583
8598
|
const files = event.dataTransfer?.files;
|
|
8584
|
-
if (files
|
|
8599
|
+
if (files?.length)
|
|
8585
8600
|
await uploadFiles(path, files);
|
|
8586
8601
|
} catch {
|
|
8587
8602
|
fail();
|
|
@@ -8723,7 +8738,7 @@
|
|
|
8723
8738
|
meta.entries.forEach((entry) => {
|
|
8724
8739
|
const row = document.createElement("button");
|
|
8725
8740
|
row.type = "button";
|
|
8726
|
-
row.className =
|
|
8741
|
+
row.className = `gdp-repo-row ${entry.type}`;
|
|
8727
8742
|
const icon = document.createElement("span");
|
|
8728
8743
|
icon.className = entry.type === "tree" ? "dir-icon" : "d2h-icon-wrapper";
|
|
8729
8744
|
if (entry.type === "tree")
|
|
@@ -8763,7 +8778,7 @@
|
|
|
8763
8778
|
listWrapper.appendChild(list2);
|
|
8764
8779
|
listCard.appendChild(listWrapper);
|
|
8765
8780
|
shell.appendChild(listCard);
|
|
8766
|
-
if (meta.readme
|
|
8781
|
+
if (meta.readme?.text) {
|
|
8767
8782
|
const readme = document.createElement("section");
|
|
8768
8783
|
readme.className = "gdp-file-shell loaded gdp-repo-readme";
|
|
8769
8784
|
const wrapper = document.createElement("div");
|
|
@@ -8824,7 +8839,7 @@
|
|
|
8824
8839
|
params.set("recursive", "1");
|
|
8825
8840
|
appendScopeOmitDirsParam(params);
|
|
8826
8841
|
REPO_SIDEBAR_LOAD_REF = normalizedRef;
|
|
8827
|
-
const load2 = trackLoad(fetch(
|
|
8842
|
+
const load2 = trackLoad(fetch(`/_tree?${params.toString()}`).then((r2) => {
|
|
8828
8843
|
if (!r2.ok)
|
|
8829
8844
|
throw new Error("failed to load repository tree");
|
|
8830
8845
|
return r2.json();
|
|
@@ -8883,7 +8898,7 @@
|
|
|
8883
8898
|
card.dataset.status = f2.status || "M";
|
|
8884
8899
|
card.classList.toggle("viewed", STATE.viewedFiles.has(f2.path));
|
|
8885
8900
|
if (f2.estimated_height_px) {
|
|
8886
|
-
card.style.minHeight = f2.estimated_height_px
|
|
8901
|
+
card.style.minHeight = `${f2.estimated_height_px}px`;
|
|
8887
8902
|
}
|
|
8888
8903
|
const head = document.createElement("div");
|
|
8889
8904
|
head.className = "gdp-shell-header";
|
|
@@ -8910,7 +8925,9 @@
|
|
|
8910
8925
|
enqueueLoad(f2, card, 0);
|
|
8911
8926
|
});
|
|
8912
8927
|
}, { rootMargin: "1200px 0px 1600px 0px" });
|
|
8913
|
-
document.querySelectorAll(".gdp-file-shell.pending").forEach((c2) =>
|
|
8928
|
+
document.querySelectorAll(".gdp-file-shell.pending").forEach((c2) => {
|
|
8929
|
+
lazyObserver.observe(c2);
|
|
8930
|
+
});
|
|
8914
8931
|
}
|
|
8915
8932
|
window.addEventListener("scroll", () => enqueueInitialLoads(), {
|
|
8916
8933
|
passive: true
|
|
@@ -8981,12 +8998,14 @@
|
|
|
8981
8998
|
if (indicator)
|
|
8982
8999
|
indicator.hidden = true;
|
|
8983
9000
|
const body = card.querySelector(".gdp-shell-body");
|
|
9001
|
+
if (!body)
|
|
9002
|
+
return;
|
|
8984
9003
|
body.innerHTML = "";
|
|
8985
9004
|
const wrap = document.createElement("div");
|
|
8986
9005
|
wrap.className = "gdp-manual-load";
|
|
8987
9006
|
const note = document.createElement("div");
|
|
8988
9007
|
note.className = "gdp-manual-note";
|
|
8989
|
-
note.textContent = manualLoadReason(file)
|
|
9008
|
+
note.textContent = `${manualLoadReason(file)} - click to load diff`;
|
|
8990
9009
|
const previewBtn = document.createElement("button");
|
|
8991
9010
|
previewBtn.className = "gdp-show-full";
|
|
8992
9011
|
previewBtn.textContent = "Load preview";
|
|
@@ -9091,6 +9110,8 @@
|
|
|
9091
9110
|
card.classList.remove("loading");
|
|
9092
9111
|
card.classList.add("error");
|
|
9093
9112
|
const body = card.querySelector(".gdp-shell-body");
|
|
9113
|
+
if (!body)
|
|
9114
|
+
return;
|
|
9094
9115
|
body.innerHTML = '<div class="gdp-error">failed to load — <button class="retry">retry</button></div>';
|
|
9095
9116
|
const btn = body.querySelector(".retry");
|
|
9096
9117
|
if (btn)
|
|
@@ -9107,8 +9128,10 @@
|
|
|
9107
9128
|
if (head)
|
|
9108
9129
|
head.style.display = "none";
|
|
9109
9130
|
const body = card.querySelector(".gdp-shell-body");
|
|
9131
|
+
if (!body)
|
|
9132
|
+
return;
|
|
9110
9133
|
body.innerHTML = "";
|
|
9111
|
-
if (!data.diff
|
|
9134
|
+
if (!data.diff?.trim()) {
|
|
9112
9135
|
body.innerHTML = '<div class="gdp-info">No content</div>';
|
|
9113
9136
|
return;
|
|
9114
9137
|
}
|
|
@@ -9200,7 +9223,9 @@
|
|
|
9200
9223
|
const parsed = group.find((g) => g.hunk) || group[0];
|
|
9201
9224
|
if (!parsed.hunk)
|
|
9202
9225
|
return;
|
|
9203
|
-
group.forEach((g) =>
|
|
9226
|
+
group.forEach((g) => {
|
|
9227
|
+
g.tr.classList.add("gdp-hunk-row");
|
|
9228
|
+
});
|
|
9204
9229
|
infoRows.push({
|
|
9205
9230
|
tr: parsed.tr,
|
|
9206
9231
|
info: parsed.info,
|
|
@@ -9264,7 +9289,7 @@
|
|
|
9264
9289
|
setBusy(true);
|
|
9265
9290
|
const url = "/file_range?path=" + refPath + "&ref=" + encodeURIComponent(ref) + "&start=" + start + "&end=" + end;
|
|
9266
9291
|
trackLoad(fetch(url).then((r2) => r2.json())).then((data) => {
|
|
9267
|
-
if (!data
|
|
9292
|
+
if (!data?.lines) {
|
|
9268
9293
|
setBusy(false);
|
|
9269
9294
|
return;
|
|
9270
9295
|
}
|
|
@@ -9282,7 +9307,7 @@
|
|
|
9282
9307
|
item.bottomExpandedEnd = end;
|
|
9283
9308
|
for (const sib of item.siblings || [{ tr: item.tr }]) {
|
|
9284
9309
|
const ln = sib.tr.querySelector(".d2h-code-linenumber.d2h-info, .d2h-code-side-linenumber.d2h-info");
|
|
9285
|
-
const old = ln
|
|
9310
|
+
const old = ln?.querySelector(".gdp-expand-stack");
|
|
9286
9311
|
if (old)
|
|
9287
9312
|
old.remove();
|
|
9288
9313
|
}
|
|
@@ -9299,18 +9324,18 @@
|
|
|
9299
9324
|
if (isFirst) {
|
|
9300
9325
|
buttons.push({
|
|
9301
9326
|
direction: "up",
|
|
9302
|
-
title:
|
|
9327
|
+
title: `Show ${Math.min(STEP, remainingSize)} more lines`,
|
|
9303
9328
|
onClick: () => fetchAndInsert(Math.max(remainingStart, remainingEnd - STEP + 1), remainingEnd, "after")
|
|
9304
9329
|
});
|
|
9305
9330
|
} else {
|
|
9306
9331
|
buttons.push({
|
|
9307
9332
|
direction: "up",
|
|
9308
|
-
title:
|
|
9333
|
+
title: `Show ${Math.min(STEP, remainingSize)} more lines`,
|
|
9309
9334
|
onClick: () => fetchAndInsert(remainingStart, Math.min(remainingEnd, remainingStart + STEP - 1), "before")
|
|
9310
9335
|
});
|
|
9311
9336
|
buttons.push({
|
|
9312
9337
|
direction: "down",
|
|
9313
|
-
title:
|
|
9338
|
+
title: `Show ${Math.min(STEP, remainingSize)} more lines`,
|
|
9314
9339
|
onClick: () => fetchAndInsert(Math.max(remainingStart, remainingEnd - STEP + 1), remainingEnd, "after")
|
|
9315
9340
|
});
|
|
9316
9341
|
}
|
|
@@ -9354,12 +9379,14 @@
|
|
|
9354
9379
|
const syncHeight = () => {
|
|
9355
9380
|
const stack = stackRow.querySelector(".gdp-expand-stack");
|
|
9356
9381
|
const targetH = stack ? Math.max(20, stack.getBoundingClientRect().height) : 20;
|
|
9357
|
-
rows.forEach((row) =>
|
|
9382
|
+
rows.forEach((row) => {
|
|
9383
|
+
row.style.setProperty("height", `${targetH}px`, "important");
|
|
9384
|
+
});
|
|
9358
9385
|
};
|
|
9359
9386
|
requestAnimationFrame(syncHeight);
|
|
9360
9387
|
setTimeout(syncHeight, 100);
|
|
9361
9388
|
}
|
|
9362
|
-
function
|
|
9389
|
+
function _attachTrailingExpandControls(item, file, ref, refPath) {
|
|
9363
9390
|
const STEP = 20;
|
|
9364
9391
|
let nextNewStart = nextNewLine(item.hunk);
|
|
9365
9392
|
let nextOldStart = nextOldLine(item.hunk);
|
|
@@ -9385,29 +9412,37 @@
|
|
|
9385
9412
|
if (!rows.length)
|
|
9386
9413
|
return;
|
|
9387
9414
|
const setBusy = (busy) => {
|
|
9388
|
-
rows.forEach((row) =>
|
|
9389
|
-
btn.
|
|
9390
|
-
|
|
9415
|
+
rows.forEach((row) => {
|
|
9416
|
+
row.ln.querySelectorAll(".gdp-expand-btn").forEach((btn) => {
|
|
9417
|
+
btn.disabled = busy;
|
|
9418
|
+
});
|
|
9419
|
+
});
|
|
9391
9420
|
};
|
|
9392
9421
|
const fetchAndInsert = () => {
|
|
9393
9422
|
const range = window.GdpExpandLogic.trailingClickRange(nextNewStart, STEP);
|
|
9394
9423
|
setBusy(true);
|
|
9395
9424
|
const url = "/file_range?path=" + refPath + "&ref=" + encodeURIComponent(ref) + "&start=" + range.start + "&end=" + range.end;
|
|
9396
9425
|
trackLoad(fetch(url).then((r2) => r2.json())).then((data) => {
|
|
9397
|
-
const lines = data
|
|
9426
|
+
const lines = data?.lines || [];
|
|
9398
9427
|
if (!lines.length) {
|
|
9399
|
-
rows.forEach((row) =>
|
|
9428
|
+
rows.forEach((row) => {
|
|
9429
|
+
row.tr.remove();
|
|
9430
|
+
});
|
|
9400
9431
|
return;
|
|
9401
9432
|
}
|
|
9402
9433
|
const card = item.tr.closest(".d2h-file-wrapper");
|
|
9403
|
-
rows.forEach((row) =>
|
|
9434
|
+
rows.forEach((row) => {
|
|
9435
|
+
insertContextRows(row.tr, lines, range.start, nextOldStart, "before", row.sideIndex);
|
|
9436
|
+
});
|
|
9404
9437
|
const next = window.GdpExpandLogic.applyTrailingResult({ newStart: nextNewStart, oldStart: nextOldStart }, lines.length, STEP);
|
|
9405
9438
|
nextNewStart = next.newStart;
|
|
9406
9439
|
nextOldStart = next.oldStart;
|
|
9407
9440
|
if (card)
|
|
9408
9441
|
highlightInsertedSpans(card, file);
|
|
9409
9442
|
if (next.eof) {
|
|
9410
|
-
rows.forEach((row) =>
|
|
9443
|
+
rows.forEach((row) => {
|
|
9444
|
+
row.tr.remove();
|
|
9445
|
+
});
|
|
9411
9446
|
return;
|
|
9412
9447
|
}
|
|
9413
9448
|
setBusy(false);
|
|
@@ -9441,7 +9476,7 @@
|
|
|
9441
9476
|
let lnHtml;
|
|
9442
9477
|
if (isSplit) {
|
|
9443
9478
|
const num = sideIndex === 0 ? oldStart + i2 : newStart + i2;
|
|
9444
|
-
lnHtml =
|
|
9479
|
+
lnHtml = `<td class="d2h-code-side-linenumber d2h-cntx">${num}</td>`;
|
|
9445
9480
|
} else {
|
|
9446
9481
|
lnHtml = '<td class="d2h-code-linenumber d2h-cntx"><div class="line-num1">' + (oldStart + i2) + '</div><div class="line-num2">' + (newStart + i2) + "</div></td>";
|
|
9447
9482
|
}
|
|
@@ -9489,7 +9524,7 @@
|
|
|
9489
9524
|
title.textContent = "Loading file";
|
|
9490
9525
|
const message = document.createElement("div");
|
|
9491
9526
|
message.className = "gdp-source-loading-message";
|
|
9492
|
-
message.textContent = target.path
|
|
9527
|
+
message.textContent = `${target.path} at ${target.ref}`;
|
|
9493
9528
|
content.append(title, message);
|
|
9494
9529
|
if (onCancel) {
|
|
9495
9530
|
const button = document.createElement("button");
|
|
@@ -9513,7 +9548,7 @@
|
|
|
9513
9548
|
const body = card.querySelector(".gdp-file-detail-body, .d2h-files-diff, .d2h-file-diff, .gdp-media, .gdp-source-viewer");
|
|
9514
9549
|
const view = document.createElement("div");
|
|
9515
9550
|
view.className = "gdp-source-viewer error";
|
|
9516
|
-
view.textContent = message ||
|
|
9551
|
+
view.textContent = message || `Cannot load ${target.path} at ${target.ref}`;
|
|
9517
9552
|
if (body)
|
|
9518
9553
|
body.replaceWith(view);
|
|
9519
9554
|
else
|
|
@@ -9530,7 +9565,7 @@
|
|
|
9530
9565
|
title.textContent = "Loading cancelled";
|
|
9531
9566
|
const message = document.createElement("div");
|
|
9532
9567
|
message.className = "gdp-source-loading-message";
|
|
9533
|
-
message.textContent = target.path
|
|
9568
|
+
message.textContent = `${target.path} at ${target.ref}`;
|
|
9534
9569
|
const retry = document.createElement("button");
|
|
9535
9570
|
retry.type = "button";
|
|
9536
9571
|
retry.className = "gdp-btn gdp-btn-sm";
|
|
@@ -9583,7 +9618,7 @@
|
|
|
9583
9618
|
const preview = document.createElement("div");
|
|
9584
9619
|
preview.className = "gdp-html-preview";
|
|
9585
9620
|
const frame = document.createElement("iframe");
|
|
9586
|
-
frame.title = target.path
|
|
9621
|
+
frame.title = `${target.path} preview`;
|
|
9587
9622
|
frame.srcdoc = html;
|
|
9588
9623
|
preview.appendChild(frame);
|
|
9589
9624
|
return preview;
|
|
@@ -10021,7 +10056,7 @@
|
|
|
10021
10056
|
const header = isStandalone ? null : document.createElement("div");
|
|
10022
10057
|
if (header) {
|
|
10023
10058
|
header.className = "gdp-source-meta";
|
|
10024
|
-
header.textContent = target.path
|
|
10059
|
+
header.textContent = `${target.path} @ ${target.ref}`;
|
|
10025
10060
|
}
|
|
10026
10061
|
const lang = inferLang(target.path);
|
|
10027
10062
|
const usesVirtualSource = shouldVirtualizeSource(textValue, lines) && !isVirtualSourceDisabled();
|
|
@@ -10364,7 +10399,7 @@
|
|
|
10364
10399
|
return;
|
|
10365
10400
|
matches = nextMatches;
|
|
10366
10401
|
active = matches.length ? Math.max(0, Math.min(active, matches.length - 1)) : -1;
|
|
10367
|
-
count.textContent = matches.length ? active + 1
|
|
10402
|
+
count.textContent = matches.length ? `${active + 1} / ${matches.length}` : "0 / 0";
|
|
10368
10403
|
if (active >= 0)
|
|
10369
10404
|
scroller.scrollTop = Math.max(0, (matches[active].line - 1) * VIRTUAL_SOURCE_ROW_HEIGHT - VIRTUAL_SOURCE_ROW_HEIGHT * 3);
|
|
10370
10405
|
renderFn();
|
|
@@ -10386,7 +10421,7 @@
|
|
|
10386
10421
|
if (!matches.length)
|
|
10387
10422
|
return;
|
|
10388
10423
|
active = (active + direction + matches.length) % matches.length;
|
|
10389
|
-
count.textContent = active + 1
|
|
10424
|
+
count.textContent = `${active + 1} / ${matches.length}`;
|
|
10390
10425
|
scroller.scrollTop = Math.max(0, (matches[active].line - 1) * VIRTUAL_SOURCE_ROW_HEIGHT - VIRTUAL_SOURCE_ROW_HEIGHT * 3);
|
|
10391
10426
|
renderFn();
|
|
10392
10427
|
};
|
|
@@ -10476,10 +10511,10 @@
|
|
|
10476
10511
|
scroller.className = "gdp-source-virtual-scroller";
|
|
10477
10512
|
scroller.tabIndex = 0;
|
|
10478
10513
|
scroller.setAttribute("role", "region");
|
|
10479
|
-
scroller.setAttribute("aria-label", target.path
|
|
10514
|
+
scroller.setAttribute("aria-label", `${target.path} source code`);
|
|
10480
10515
|
const spacer = document.createElement("div");
|
|
10481
10516
|
spacer.className = "gdp-source-virtual-spacer";
|
|
10482
|
-
spacer.style.height = Math.max(1, lines.length * VIRTUAL_SOURCE_ROW_HEIGHT)
|
|
10517
|
+
spacer.style.height = `${Math.max(1, lines.length * VIRTUAL_SOURCE_ROW_HEIGHT)}px`;
|
|
10483
10518
|
const windowEl = document.createElement("div");
|
|
10484
10519
|
windowEl.className = "gdp-source-virtual-window";
|
|
10485
10520
|
spacer.appendChild(windowEl);
|
|
@@ -10500,7 +10535,7 @@
|
|
|
10500
10535
|
renderedStart = start;
|
|
10501
10536
|
renderedEnd = end;
|
|
10502
10537
|
windowEl.replaceChildren();
|
|
10503
|
-
windowEl.style.transform =
|
|
10538
|
+
windowEl.style.transform = `translateY(${start * VIRTUAL_SOURCE_ROW_HEIGHT}px)`;
|
|
10504
10539
|
const fragment = document.createDocumentFragment();
|
|
10505
10540
|
for (let index = start;index < end; index++) {
|
|
10506
10541
|
const row = document.createElement("div");
|
|
@@ -10517,7 +10552,7 @@
|
|
|
10517
10552
|
const line = lines[index] ?? "";
|
|
10518
10553
|
const searchQuery = search?.query() || "";
|
|
10519
10554
|
const activeRange = search?.activeRange() || null;
|
|
10520
|
-
if (appendVirtualSourceLineCode(code2, line, searchQuery, activeRange, index + 1)) {} else if (hljsRef
|
|
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))) {
|
|
10521
10556
|
try {
|
|
10522
10557
|
code2.innerHTML = hljsRef.highlight(line, {
|
|
10523
10558
|
language: lang,
|
|
@@ -10592,7 +10627,7 @@
|
|
|
10592
10627
|
scroller.className = "gdp-source-virtual-scroller";
|
|
10593
10628
|
scroller.tabIndex = 0;
|
|
10594
10629
|
scroller.setAttribute("role", "region");
|
|
10595
|
-
scroller.setAttribute("aria-label", target.path
|
|
10630
|
+
scroller.setAttribute("aria-label", `${target.path} source code`);
|
|
10596
10631
|
const spacer = document.createElement("div");
|
|
10597
10632
|
spacer.className = "gdp-source-virtual-spacer";
|
|
10598
10633
|
const windowEl = document.createElement("div");
|
|
@@ -10606,15 +10641,17 @@
|
|
|
10606
10641
|
const targetLine = lineTargetStart(currentSourceLineTarget(target)) || 1;
|
|
10607
10642
|
let complete = initialComplete;
|
|
10608
10643
|
let totalRows = initialComplete ? Math.max(1, initialTotal) : Math.max(initialTotal || 1, initialStart + initialLines.length - 1, targetLine + VIRTUAL_SOURCE_PAGE_SIZE);
|
|
10609
|
-
initialLines.forEach((line, index) =>
|
|
10644
|
+
initialLines.forEach((line, index) => {
|
|
10645
|
+
lines.set(initialStart + index, line);
|
|
10646
|
+
});
|
|
10610
10647
|
requestedPages.add(Math.max(0, Math.floor((initialStart - 1) / VIRTUAL_SOURCE_PAGE_SIZE)));
|
|
10611
10648
|
for (let line = initialStart;line < initialStart + initialLines.length; line += VIRTUAL_SOURCE_PAGE_SIZE) {
|
|
10612
10649
|
requestedPages.add(Math.max(0, Math.floor((line - 1) / VIRTUAL_SOURCE_PAGE_SIZE)));
|
|
10613
10650
|
}
|
|
10614
10651
|
const updateTotals = () => {
|
|
10615
10652
|
SOURCE_CURSOR_TOTALS.set(sourceCursorKey(target), totalRows);
|
|
10616
|
-
summary.textContent = (complete ? totalRows.toLocaleString() : lines.size.toLocaleString()
|
|
10617
|
-
spacer.style.height = Math.max(1, totalRows * VIRTUAL_SOURCE_ROW_HEIGHT)
|
|
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`;
|
|
10618
10655
|
};
|
|
10619
10656
|
const loadPage = (line) => {
|
|
10620
10657
|
if (signal?.aborted || complete && line > totalRows)
|
|
@@ -10630,7 +10667,9 @@
|
|
|
10630
10667
|
trackLoad(fetch(buildFileRangeUrl(target, start, end), { signal }).then((res) => res.ok ? res.json() : null).then((data) => {
|
|
10631
10668
|
if (!data || signal?.aborted)
|
|
10632
10669
|
return;
|
|
10633
|
-
data.lines.forEach((lineValue, index) =>
|
|
10670
|
+
data.lines.forEach((lineValue, index) => {
|
|
10671
|
+
lines.set(data.start + index, lineValue);
|
|
10672
|
+
});
|
|
10634
10673
|
totalRows = data.complete ? Math.max(1, data.total) : Math.max(totalRows, data.total, end + VIRTUAL_SOURCE_PAGE_SIZE);
|
|
10635
10674
|
complete = data.complete === true;
|
|
10636
10675
|
updateTotals();
|
|
@@ -10662,7 +10701,7 @@
|
|
|
10662
10701
|
renderedStart = start;
|
|
10663
10702
|
renderedEnd = end;
|
|
10664
10703
|
windowEl.replaceChildren();
|
|
10665
|
-
windowEl.style.transform =
|
|
10704
|
+
windowEl.style.transform = `translateY(${start * VIRTUAL_SOURCE_ROW_HEIGHT}px)`;
|
|
10666
10705
|
const fragment = document.createDocumentFragment();
|
|
10667
10706
|
for (let index = start;index < end; index++) {
|
|
10668
10707
|
const lineNumber = index + 1;
|
|
@@ -10682,7 +10721,7 @@
|
|
|
10682
10721
|
const line = lines.get(lineNumber);
|
|
10683
10722
|
if (line == null) {
|
|
10684
10723
|
code2.textContent = "";
|
|
10685
|
-
} else if (appendVirtualSourceLineCode(code2, line, search?.query() || "", search?.activeRange() || null, lineNumber)) {} else if (hljsRef
|
|
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))) {
|
|
10686
10725
|
try {
|
|
10687
10726
|
code2.innerHTML = hljsRef.highlight(line, {
|
|
10688
10727
|
language: lang,
|
|
@@ -10782,7 +10821,7 @@
|
|
|
10782
10821
|
const header = isStandalone ? null : document.createElement("div");
|
|
10783
10822
|
if (header) {
|
|
10784
10823
|
header.className = "gdp-source-meta";
|
|
10785
|
-
header.textContent = target.path
|
|
10824
|
+
header.textContent = `${target.path} @ ${target.ref}`;
|
|
10786
10825
|
view.appendChild(header);
|
|
10787
10826
|
}
|
|
10788
10827
|
const lineTarget = lineTargetStart(currentSourceLineTarget(target)) || 1;
|
|
@@ -10823,7 +10862,7 @@
|
|
|
10823
10862
|
if (!isStandalone) {
|
|
10824
10863
|
const meta = document.createElement("div");
|
|
10825
10864
|
meta.className = "gdp-source-meta";
|
|
10826
|
-
meta.textContent = target.path
|
|
10865
|
+
meta.textContent = `${target.path} @ ${target.ref}`;
|
|
10827
10866
|
view.appendChild(meta);
|
|
10828
10867
|
}
|
|
10829
10868
|
const url = buildRawFileUrl(target);
|
|
@@ -10853,7 +10892,7 @@
|
|
|
10853
10892
|
img.alt = "";
|
|
10854
10893
|
img.addEventListener("load", () => {
|
|
10855
10894
|
const resolution = document.createElement("span");
|
|
10856
|
-
resolution.textContent = img.naturalWidth
|
|
10895
|
+
resolution.textContent = `${img.naturalWidth} x ${img.naturalHeight}`;
|
|
10857
10896
|
info.appendChild(resolution);
|
|
10858
10897
|
}, { once: true });
|
|
10859
10898
|
view.appendChild(img);
|
|
@@ -10863,7 +10902,7 @@
|
|
|
10863
10902
|
else
|
|
10864
10903
|
card.appendChild(view);
|
|
10865
10904
|
}
|
|
10866
|
-
function
|
|
10905
|
+
function _renderSourceBinary(card, target) {
|
|
10867
10906
|
const body = card.querySelector(".gdp-file-detail-body, .d2h-files-diff, .d2h-file-diff, .gdp-media, .gdp-source-viewer");
|
|
10868
10907
|
const isStandalone = card.classList.contains("gdp-standalone-source");
|
|
10869
10908
|
const view = document.createElement("div");
|
|
@@ -10876,7 +10915,7 @@
|
|
|
10876
10915
|
if (!isStandalone) {
|
|
10877
10916
|
const meta = document.createElement("div");
|
|
10878
10917
|
meta.className = "gdp-source-meta";
|
|
10879
|
-
meta.textContent = target.path
|
|
10918
|
+
meta.textContent = `${target.path} @ ${target.ref}`;
|
|
10880
10919
|
view.appendChild(meta);
|
|
10881
10920
|
}
|
|
10882
10921
|
view.appendChild(link2);
|
|
@@ -10928,7 +10967,9 @@
|
|
|
10928
10967
|
const repoTarget = repoFileTargetFromRoute();
|
|
10929
10968
|
setPageMode();
|
|
10930
10969
|
removeStandaloneSource();
|
|
10931
|
-
document.querySelectorAll(".gdp-repo-blob-layout").forEach((el) =>
|
|
10970
|
+
document.querySelectorAll(".gdp-repo-blob-layout").forEach((el) => {
|
|
10971
|
+
el.remove();
|
|
10972
|
+
});
|
|
10932
10973
|
const card = document.createElement("article");
|
|
10933
10974
|
card.className = "gdp-file-shell loaded gdp-standalone-source gdp-source-mode";
|
|
10934
10975
|
card.dataset.path = target.path;
|
|
@@ -11034,7 +11075,7 @@
|
|
|
11034
11075
|
return;
|
|
11035
11076
|
if (!response.ok) {
|
|
11036
11077
|
finishSourceLoad(req);
|
|
11037
|
-
renderSourceError(card, target,
|
|
11078
|
+
renderSourceError(card, target, `Cannot load ${target.path} at ${target.ref}`);
|
|
11038
11079
|
return;
|
|
11039
11080
|
}
|
|
11040
11081
|
const textValue = await response.text();
|
|
@@ -11056,7 +11097,7 @@
|
|
|
11056
11097
|
renderSourceCancelled(card, target);
|
|
11057
11098
|
return;
|
|
11058
11099
|
}
|
|
11059
|
-
renderSourceError(card, target,
|
|
11100
|
+
renderSourceError(card, target, `Cannot load ${target.path} at ${target.ref}`);
|
|
11060
11101
|
}
|
|
11061
11102
|
}
|
|
11062
11103
|
function scrollStandaloneSourceLine(card, line) {
|
|
@@ -11069,7 +11110,7 @@
|
|
|
11069
11110
|
virtualScroller.__gdpRenderVirtualSource?.();
|
|
11070
11111
|
return;
|
|
11071
11112
|
}
|
|
11072
|
-
const row = card.querySelector(
|
|
11113
|
+
const row = card.querySelector(`.gdp-source-table tr[data-line="${String(line)}"]`);
|
|
11073
11114
|
if (row)
|
|
11074
11115
|
row.scrollIntoView({ block: "center" });
|
|
11075
11116
|
}
|
|
@@ -11210,7 +11251,8 @@
|
|
|
11210
11251
|
}
|
|
11211
11252
|
const total = (file.additions || 0) + (file.deletions || 0);
|
|
11212
11253
|
const SEG = 5;
|
|
11213
|
-
let aSeg
|
|
11254
|
+
let aSeg;
|
|
11255
|
+
let dSeg;
|
|
11214
11256
|
if (total === 0) {
|
|
11215
11257
|
aSeg = 0;
|
|
11216
11258
|
dSeg = 0;
|
|
@@ -11267,7 +11309,7 @@
|
|
|
11267
11309
|
card.style.minHeight = "";
|
|
11268
11310
|
mountDiff(card, file, data);
|
|
11269
11311
|
applyDiffRouteFocus(card);
|
|
11270
|
-
card.style.containIntrinsicSize = Math.max(card.offsetHeight, file.estimated_height_px || 200)
|
|
11312
|
+
card.style.containIntrinsicSize = `${Math.max(card.offsetHeight, file.estimated_height_px || 200)}px`;
|
|
11271
11313
|
applyViewedToCard(card, STATE.viewedFiles.has(file.path), true);
|
|
11272
11314
|
if (data.truncated && data.mode === "preview") {
|
|
11273
11315
|
addExpandHunksUI(file, data, card);
|
|
@@ -11294,15 +11336,15 @@
|
|
|
11294
11336
|
const step = Math.min(10, remaining);
|
|
11295
11337
|
const moreBtn = document.createElement("button");
|
|
11296
11338
|
moreBtn.className = "gdp-show-full";
|
|
11297
|
-
moreBtn.textContent =
|
|
11339
|
+
moreBtn.textContent = `Show next ${step} hunk${step === 1 ? "" : "s"}`;
|
|
11298
11340
|
moreBtn.addEventListener("click", () => loadMore(rendered + step, false));
|
|
11299
11341
|
const allBtn = document.createElement("button");
|
|
11300
11342
|
allBtn.className = "gdp-show-full secondary";
|
|
11301
|
-
allBtn.textContent =
|
|
11343
|
+
allBtn.textContent = `Show all (${remaining} remaining)`;
|
|
11302
11344
|
allBtn.addEventListener("click", () => loadMore(total, true));
|
|
11303
11345
|
const note = document.createElement("span");
|
|
11304
11346
|
note.className = "gdp-hunk-note";
|
|
11305
|
-
note.textContent = rendered
|
|
11347
|
+
note.textContent = `${rendered} / ${total} hunks shown`;
|
|
11306
11348
|
wrap.appendChild(note);
|
|
11307
11349
|
wrap.appendChild(moreBtn);
|
|
11308
11350
|
wrap.appendChild(allBtn);
|
|
@@ -11350,10 +11392,10 @@
|
|
|
11350
11392
|
if (!STATE.syntaxHighlight)
|
|
11351
11393
|
return;
|
|
11352
11394
|
const hljsRef = getHljs();
|
|
11353
|
-
if (!hljsRef
|
|
11395
|
+
if (!hljsRef?.highlight)
|
|
11354
11396
|
return;
|
|
11355
11397
|
const lang = inferLang(file.path);
|
|
11356
|
-
if (!lang || !hljsRef.getLanguage
|
|
11398
|
+
if (!lang || !hljsRef.getLanguage?.(lang))
|
|
11357
11399
|
return;
|
|
11358
11400
|
const spans = card.querySelectorAll("tr.gdp-inserted-ctx .d2h-code-line-ctn:not([data-gdp-hl])");
|
|
11359
11401
|
spans.forEach((s2) => {
|
|
@@ -11381,10 +11423,10 @@
|
|
|
11381
11423
|
if (!("requestIdleCallback" in window))
|
|
11382
11424
|
return;
|
|
11383
11425
|
const hljsRef = getHljs();
|
|
11384
|
-
if (!hljsRef
|
|
11426
|
+
if (!hljsRef?.highlight)
|
|
11385
11427
|
return;
|
|
11386
11428
|
const lang = inferLang(file.path);
|
|
11387
|
-
if (!lang || !hljsRef.getLanguage
|
|
11429
|
+
if (!lang || !hljsRef.getLanguage?.(lang))
|
|
11388
11430
|
return;
|
|
11389
11431
|
const work = (deadline) => {
|
|
11390
11432
|
const spans = card.querySelectorAll(".d2h-code-line-ctn:not([data-gdp-hl])");
|
|
@@ -11446,17 +11488,17 @@
|
|
|
11446
11488
|
return AUDIO_RE.test(p2);
|
|
11447
11489
|
}
|
|
11448
11490
|
function fileURL(path, ref) {
|
|
11449
|
-
return
|
|
11491
|
+
return `/_file?path=${encodeURIComponent(path)}&ref=${ref}`;
|
|
11450
11492
|
}
|
|
11451
11493
|
function mediaTag(path, ref) {
|
|
11452
11494
|
const url = fileURL(path, ref);
|
|
11453
11495
|
if (isVideo(path)) {
|
|
11454
|
-
return
|
|
11496
|
+
return `<video src="${url}" controls preload="metadata"></video>`;
|
|
11455
11497
|
}
|
|
11456
11498
|
if (isAudio(path)) {
|
|
11457
|
-
return
|
|
11499
|
+
return `<audio src="${url}" controls preload="metadata"></audio>`;
|
|
11458
11500
|
}
|
|
11459
|
-
return
|
|
11501
|
+
return `<img src="${url}" alt="" loading="lazy">`;
|
|
11460
11502
|
}
|
|
11461
11503
|
function enhanceMediaCard(file, card) {
|
|
11462
11504
|
const path = file.path;
|
|
@@ -11470,7 +11512,8 @@
|
|
|
11470
11512
|
return;
|
|
11471
11513
|
const container = document.createElement("div");
|
|
11472
11514
|
container.className = "gdp-media";
|
|
11473
|
-
let leftHTML
|
|
11515
|
+
let leftHTML;
|
|
11516
|
+
let rightHTML;
|
|
11474
11517
|
if (file.status === "A") {
|
|
11475
11518
|
leftHTML = '<div class="media-empty">Not in HEAD</div>';
|
|
11476
11519
|
rightHTML = mediaTag(path, "worktree");
|
|
@@ -11494,7 +11537,7 @@
|
|
|
11494
11537
|
handler._raf = null;
|
|
11495
11538
|
if (performance.now() < SUPPRESS_SPY_UNTIL)
|
|
11496
11539
|
return;
|
|
11497
|
-
const topbarH = parseInt(getComputedStyle(document.documentElement).getPropertyValue("--topbar-h")) || 56;
|
|
11540
|
+
const topbarH = parseInt(getComputedStyle(document.documentElement).getPropertyValue("--topbar-h"), 10) || 56;
|
|
11498
11541
|
const scanY = topbarH + 24;
|
|
11499
11542
|
const cards = document.querySelectorAll(".gdp-file-shell");
|
|
11500
11543
|
for (const w of cards) {
|
|
@@ -11512,7 +11555,7 @@
|
|
|
11512
11555
|
markActive(best);
|
|
11513
11556
|
const recentlyTouched = performance.now() - (window.__gdpSidebarTouchedAt || 0) < 1500;
|
|
11514
11557
|
if (!recentlyTouched) {
|
|
11515
|
-
const li = document.querySelector(
|
|
11558
|
+
const li = document.querySelector(`#filelist li[data-path="${CSS.escape(best)}"]`);
|
|
11516
11559
|
if (li) {
|
|
11517
11560
|
const sb = document.querySelector("#sidebar");
|
|
11518
11561
|
if (!sb)
|
|
@@ -11536,7 +11579,7 @@
|
|
|
11536
11579
|
window.addEventListener("scroll", handler, { passive: true });
|
|
11537
11580
|
handler(new Event("scroll"));
|
|
11538
11581
|
}
|
|
11539
|
-
function
|
|
11582
|
+
function _collapseAll(force) {
|
|
11540
11583
|
STATE.collapsed = typeof force === "boolean" ? force : !STATE.collapsed;
|
|
11541
11584
|
document.querySelectorAll(".gdp-file-shell.loaded .d2h-file-wrapper").forEach((w) => {
|
|
11542
11585
|
const body = w.querySelector(".d2h-files-diff, .d2h-file-diff");
|
|
@@ -11580,7 +11623,7 @@
|
|
|
11580
11623
|
});
|
|
11581
11624
|
function applySidebarWidth(w) {
|
|
11582
11625
|
const cw = Math.max(180, Math.min(900, w));
|
|
11583
|
-
document.documentElement.style.setProperty("--sidebar-w", cw
|
|
11626
|
+
document.documentElement.style.setProperty("--sidebar-w", `${cw}px`);
|
|
11584
11627
|
STATE.sbWidth = cw;
|
|
11585
11628
|
localStorage.setItem("gdp:sbwidth", String(cw));
|
|
11586
11629
|
}
|
|
@@ -11621,14 +11664,14 @@
|
|
|
11621
11664
|
currentW = startW;
|
|
11622
11665
|
document.body.classList.add("gdp-resizing");
|
|
11623
11666
|
preview.style.display = "block";
|
|
11624
|
-
preview.style.left = startW
|
|
11667
|
+
preview.style.left = `${startW}px`;
|
|
11625
11668
|
e2.preventDefault();
|
|
11626
11669
|
});
|
|
11627
11670
|
window.addEventListener("mousemove", (e2) => {
|
|
11628
11671
|
if (!dragging)
|
|
11629
11672
|
return;
|
|
11630
11673
|
currentW = clamp(startW + (e2.clientX - startX));
|
|
11631
|
-
preview.style.left = currentW
|
|
11674
|
+
preview.style.left = `${currentW}px`;
|
|
11632
11675
|
});
|
|
11633
11676
|
window.addEventListener("mouseup", () => {
|
|
11634
11677
|
if (!dragging)
|
|
@@ -11962,7 +12005,7 @@
|
|
|
11962
12005
|
state.items.forEach((item, index) => {
|
|
11963
12006
|
const row = document.createElement("button");
|
|
11964
12007
|
row.type = "button";
|
|
11965
|
-
row.id =
|
|
12008
|
+
row.id = `gdp-palette-item-${index}`;
|
|
11966
12009
|
row.className = "gdp-palette-row";
|
|
11967
12010
|
row.setAttribute("role", "option");
|
|
11968
12011
|
row.setAttribute("aria-selected", index === state.selected ? "true" : "false");
|
|
@@ -11974,10 +12017,10 @@
|
|
|
11974
12017
|
title.textContent = item.path.split("/").pop() || item.path;
|
|
11975
12018
|
appendHighlightedPath(detail, item.displayPath, item.ranges);
|
|
11976
12019
|
if (item.old_path && item.displayPath !== item.old_path) {
|
|
11977
|
-
detail.appendChild(document.createTextNode(
|
|
12020
|
+
detail.appendChild(document.createTextNode(` ${item.old_path}`));
|
|
11978
12021
|
}
|
|
11979
12022
|
} else {
|
|
11980
|
-
title.textContent = item.path
|
|
12023
|
+
title.textContent = `${item.path}:${item.line}`;
|
|
11981
12024
|
detail.textContent = item.preview;
|
|
11982
12025
|
}
|
|
11983
12026
|
row.append(title, detail);
|
|
@@ -11995,7 +12038,7 @@
|
|
|
11995
12038
|
syncPaletteSelection(state);
|
|
11996
12039
|
}
|
|
11997
12040
|
function syncPaletteSelection(state) {
|
|
11998
|
-
state.input.setAttribute("aria-activedescendant", state.selected >= 0 ?
|
|
12041
|
+
state.input.setAttribute("aria-activedescendant", state.selected >= 0 ? `gdp-palette-item-${state.selected}` : "");
|
|
11999
12042
|
state.list.querySelectorAll(".gdp-palette-row").forEach((row, index) => {
|
|
12000
12043
|
row.setAttribute("aria-selected", index === state.selected ? "true" : "false");
|
|
12001
12044
|
if (index === state.selected)
|
|
@@ -12010,7 +12053,7 @@
|
|
|
12010
12053
|
const params = new URLSearchParams;
|
|
12011
12054
|
params.set("ref", ref);
|
|
12012
12055
|
appendScopeOmitDirsParam(params);
|
|
12013
|
-
const res = await trackLoad(fetch(
|
|
12056
|
+
const res = await trackLoad(fetch(`/_files?${params.toString()}`).then((r2) => {
|
|
12014
12057
|
if (!r2.ok)
|
|
12015
12058
|
throw new Error("failed to load files");
|
|
12016
12059
|
return r2.json();
|
|
@@ -12058,7 +12101,7 @@
|
|
|
12058
12101
|
}) : [];
|
|
12059
12102
|
state.items = limitPaletteResults(base2);
|
|
12060
12103
|
state.selected = state.items.length ? 0 : -1;
|
|
12061
|
-
state.status.textContent = source === "diff" ? state.diffSnapshot.length
|
|
12104
|
+
state.status.textContent = source === "diff" ? `${state.diffSnapshot.length} diff files` : "Type to search repository files";
|
|
12062
12105
|
renderPalette(state);
|
|
12063
12106
|
return;
|
|
12064
12107
|
}
|
|
@@ -12080,7 +12123,7 @@
|
|
|
12080
12123
|
}));
|
|
12081
12124
|
}
|
|
12082
12125
|
state.selected = state.items.length ? 0 : -1;
|
|
12083
|
-
state.status.textContent = state.items.length ? state.items.length
|
|
12126
|
+
state.status.textContent = state.items.length ? `${state.items.length} results` : "No results";
|
|
12084
12127
|
renderPalette(state);
|
|
12085
12128
|
}
|
|
12086
12129
|
function updateGrepPalette(state, query) {
|
|
@@ -12120,7 +12163,7 @@
|
|
|
12120
12163
|
}
|
|
12121
12164
|
const controller = new AbortController;
|
|
12122
12165
|
state.controller = controller;
|
|
12123
|
-
trackLoad(fetch(
|
|
12166
|
+
trackLoad(fetch(`/_grep?${params.toString()}`, {
|
|
12124
12167
|
signal: controller.signal
|
|
12125
12168
|
}).then((r2) => {
|
|
12126
12169
|
if (!r2.ok)
|
|
@@ -12378,7 +12421,7 @@
|
|
|
12378
12421
|
if (!isPlainPageKey && !isCtrlArrowKey)
|
|
12379
12422
|
return false;
|
|
12380
12423
|
const scroller = findMainScrollTarget();
|
|
12381
|
-
if (!scroller
|
|
12424
|
+
if (!scroller?.matches("#content .gdp-source-virtual-scroller"))
|
|
12382
12425
|
return false;
|
|
12383
12426
|
const pageDown = key === "pagedown" || key === "arrowdown";
|
|
12384
12427
|
const pageUp = key === "pageup" || key === "arrowup";
|
|
@@ -12436,7 +12479,7 @@
|
|
|
12436
12479
|
if (STATE.route.path)
|
|
12437
12480
|
params.set("path", STATE.route.path);
|
|
12438
12481
|
appendScopeOmitDirsParam(params);
|
|
12439
|
-
return trackLoad(fetch(
|
|
12482
|
+
return trackLoad(fetch(`/_tree?${params.toString()}`).then((r2) => {
|
|
12440
12483
|
if (!r2.ok)
|
|
12441
12484
|
throw new Error("failed to load repository tree");
|
|
12442
12485
|
return r2.json();
|
|
@@ -12465,7 +12508,7 @@
|
|
|
12465
12508
|
params.set("to", STATE.to);
|
|
12466
12509
|
if (options.force)
|
|
12467
12510
|
params.set("nocache", "1");
|
|
12468
|
-
const url =
|
|
12511
|
+
const url = `/diff.json${params.toString() ? `?${params.toString()}` : ""}`;
|
|
12469
12512
|
return trackLoad(fetch(url).then((r2) => r2.json())).then((data) => {
|
|
12470
12513
|
renderShell(data);
|
|
12471
12514
|
setStatus("live");
|
|
@@ -12523,6 +12566,8 @@
|
|
|
12523
12566
|
const popover = $("#ref-popover");
|
|
12524
12567
|
const popBody = popover.querySelector(".rp-body");
|
|
12525
12568
|
const popSearch = popover.querySelector(".rp-search");
|
|
12569
|
+
if (!popBody || !popSearch)
|
|
12570
|
+
return;
|
|
12526
12571
|
let popTarget = null;
|
|
12527
12572
|
function fetchRefs() {
|
|
12528
12573
|
return fetch("/_refs").then((r2) => r2.json()).then((refs) => {
|
|
@@ -12540,7 +12585,7 @@
|
|
|
12540
12585
|
if (commitSearchAbort)
|
|
12541
12586
|
commitSearchAbort.abort();
|
|
12542
12587
|
commitSearchAbort = new AbortController;
|
|
12543
|
-
const url =
|
|
12588
|
+
const url = `/_commits?max=100&q=${encodeURIComponent((query || "").trim())}`;
|
|
12544
12589
|
return fetch(url, { signal: commitSearchAbort.signal }).then((r2) => r2.json()).then((refs) => {
|
|
12545
12590
|
if (seq !== commitSearchSeq)
|
|
12546
12591
|
return;
|
|
@@ -12585,21 +12630,21 @@
|
|
|
12585
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>");
|
|
12586
12631
|
}
|
|
12587
12632
|
} else if (popTab === "branches") {
|
|
12588
|
-
const branches = (REFS.branches || []).filter(m);
|
|
12633
|
+
const branches = (REFS.branches || []).filter((b2) => m(b2.name));
|
|
12589
12634
|
if (!branches.length) {
|
|
12590
12635
|
html.push('<div class="rp-empty">no branches</div>');
|
|
12591
12636
|
}
|
|
12592
|
-
for (const
|
|
12593
|
-
const cur =
|
|
12594
|
-
html.push('<div class="rp-item-ref" data-val="' + escapeAttr(
|
|
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>");
|
|
12595
12640
|
}
|
|
12596
12641
|
} else if (popTab === "tags") {
|
|
12597
|
-
const tags = (REFS.tags || []).filter(m);
|
|
12642
|
+
const tags = (REFS.tags || []).filter((t2) => m(t2.name));
|
|
12598
12643
|
if (!tags.length) {
|
|
12599
12644
|
html.push('<div class="rp-empty">no tags</div>');
|
|
12600
12645
|
}
|
|
12601
|
-
for (const
|
|
12602
|
-
html.push('<div class="rp-item-ref" data-val="' + escapeAttr(
|
|
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>");
|
|
12603
12648
|
}
|
|
12604
12649
|
}
|
|
12605
12650
|
popBody.innerHTML = html.join("");
|
|
@@ -12643,8 +12688,8 @@
|
|
|
12643
12688
|
popover.hidden = false;
|
|
12644
12689
|
const r2 = input.getBoundingClientRect();
|
|
12645
12690
|
const popWidth = Math.min(560, Math.floor(window.innerWidth * 0.9));
|
|
12646
|
-
popover.style.left = Math.max(8, Math.min(r2.left, window.innerWidth - popWidth - 8))
|
|
12647
|
-
popover.style.top = r2.bottom + 4
|
|
12691
|
+
popover.style.left = `${Math.max(8, Math.min(r2.left, window.innerWidth - popWidth - 8))}px`;
|
|
12692
|
+
popover.style.top = `${r2.bottom + 4}px`;
|
|
12648
12693
|
setTimeout(() => popSearch.focus(), 0);
|
|
12649
12694
|
}
|
|
12650
12695
|
function closePopover() {
|
|
@@ -12704,7 +12749,9 @@
|
|
|
12704
12749
|
popover.querySelectorAll(".rp-tab").forEach((t2) => {
|
|
12705
12750
|
t2.addEventListener("click", () => {
|
|
12706
12751
|
popTab = t2.dataset.tab || "commits";
|
|
12707
|
-
popover.querySelectorAll(".rp-tab").forEach((b2) =>
|
|
12752
|
+
popover.querySelectorAll(".rp-tab").forEach((b2) => {
|
|
12753
|
+
b2.classList.toggle("active", b2 === t2);
|
|
12754
|
+
});
|
|
12708
12755
|
if (popTab === "commits")
|
|
12709
12756
|
scheduleCommitSearch(popSearch.value);
|
|
12710
12757
|
buildPopBody(popSearch.value);
|
package/web/style.css
CHANGED
|
@@ -686,9 +686,7 @@ body[data-code-font-size="xlarge"] { --code-font-size: 15px; }
|
|
|
686
686
|
|
|
687
687
|
/* Branch / tag / special items */
|
|
688
688
|
.rp-item-ref {
|
|
689
|
-
display:
|
|
690
|
-
align-items: center;
|
|
691
|
-
gap: 10px;
|
|
689
|
+
display: block;
|
|
692
690
|
padding: 7px 14px;
|
|
693
691
|
cursor: pointer;
|
|
694
692
|
border-left: 2px solid transparent;
|
|
@@ -699,16 +697,29 @@ body[data-code-font-size="xlarge"] { --code-font-size: 15px; }
|
|
|
699
697
|
background: var(--bg-mute);
|
|
700
698
|
border-left-color: var(--accent);
|
|
701
699
|
}
|
|
700
|
+
.rp-item-ref .row1 {
|
|
701
|
+
display: grid;
|
|
702
|
+
grid-template-columns: minmax(0, 1fr) max-content;
|
|
703
|
+
align-items: center;
|
|
704
|
+
gap: 10px;
|
|
705
|
+
}
|
|
702
706
|
.rp-item-ref .name {
|
|
703
707
|
font-family: "Monaspace Neon", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
|
|
704
|
-
|
|
708
|
+
min-width: 0;
|
|
705
709
|
overflow: hidden;
|
|
706
710
|
text-overflow: ellipsis;
|
|
707
711
|
white-space: nowrap;
|
|
708
712
|
color: var(--fg);
|
|
709
713
|
}
|
|
710
714
|
.rp-item-ref .badge {
|
|
715
|
+
width: auto;
|
|
716
|
+
height: auto;
|
|
717
|
+
display: inline-flex;
|
|
718
|
+
align-items: center;
|
|
719
|
+
justify-content: center;
|
|
720
|
+
min-height: 18px;
|
|
711
721
|
font-size: 10px;
|
|
722
|
+
line-height: 1;
|
|
712
723
|
font-weight: 600;
|
|
713
724
|
text-transform: uppercase;
|
|
714
725
|
letter-spacing: 0.06em;
|
|
@@ -716,12 +727,14 @@ body[data-code-font-size="xlarge"] { --code-font-size: 15px; }
|
|
|
716
727
|
background: var(--bg-mute);
|
|
717
728
|
padding: 2px 6px;
|
|
718
729
|
border-radius: 4px;
|
|
730
|
+
white-space: nowrap;
|
|
731
|
+
justify-self: end;
|
|
719
732
|
}
|
|
720
733
|
.rp-item-ref .badge.cur { background: var(--accent-subtle); color: var(--accent); }
|
|
721
|
-
.rp-item-ref .
|
|
734
|
+
.rp-item-ref .row2 {
|
|
722
735
|
font-size: 11px;
|
|
723
736
|
color: var(--fg-subtle);
|
|
724
|
-
|
|
737
|
+
margin-top: 2px;
|
|
725
738
|
}
|
|
726
739
|
.rp-empty {
|
|
727
740
|
padding: 36px 14px;
|
|
@@ -1361,7 +1374,7 @@ body.gdp-help-page #content {
|
|
|
1361
1374
|
opacity: 0.72;
|
|
1362
1375
|
}
|
|
1363
1376
|
#filelist.tree .tree-dir.children-omitted .dir-label {
|
|
1364
|
-
border-bottom:
|
|
1377
|
+
border-bottom: 0;
|
|
1365
1378
|
}
|
|
1366
1379
|
#filelist.tree .tree-dir.children-omitted-heavy {
|
|
1367
1380
|
cursor: pointer;
|
|
@@ -1424,9 +1437,9 @@ body.gdp-help-page #content {
|
|
|
1424
1437
|
text-transform: uppercase;
|
|
1425
1438
|
}
|
|
1426
1439
|
#filelist.tree .tree-dir .dir-omitted-heavy {
|
|
1427
|
-
color: var(--
|
|
1428
|
-
border-color: var(--
|
|
1429
|
-
background: var(--
|
|
1440
|
+
color: var(--fg-subtle);
|
|
1441
|
+
border-color: var(--border-muted);
|
|
1442
|
+
background: var(--bg-soft);
|
|
1430
1443
|
}
|
|
1431
1444
|
#filelist.tree .tree-dir .dir-omitted-internal {
|
|
1432
1445
|
color: var(--fg-subtle);
|