repoview 0.3.1 → 0.4.1
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/package.json +1 -1
- package/public/app.css +42 -1
- package/public/app.js +59 -4
- package/src/server.js +13 -3
- package/src/views.js +13 -0
package/package.json
CHANGED
package/public/app.css
CHANGED
|
@@ -564,6 +564,36 @@ a {
|
|
|
564
564
|
text-size-adjust: 100%;
|
|
565
565
|
}
|
|
566
566
|
|
|
567
|
+
.diff-actions {
|
|
568
|
+
display: flex;
|
|
569
|
+
gap: 8px;
|
|
570
|
+
padding: 10px 14px;
|
|
571
|
+
position: sticky;
|
|
572
|
+
top: 0;
|
|
573
|
+
z-index: 5;
|
|
574
|
+
background: var(--panel);
|
|
575
|
+
border-bottom: 1px solid var(--border);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
.btn-sm {
|
|
579
|
+
font-weight: 600;
|
|
580
|
+
font-size: 12px;
|
|
581
|
+
padding: 3px 8px;
|
|
582
|
+
border-radius: 4px;
|
|
583
|
+
border: 1px solid var(--border);
|
|
584
|
+
background: var(--btn);
|
|
585
|
+
color: var(--text);
|
|
586
|
+
cursor: pointer;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
.btn-sm:hover {
|
|
590
|
+
background: var(--btnHover);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
.diff-truncated {
|
|
594
|
+
margin: 12px 14px;
|
|
595
|
+
}
|
|
596
|
+
|
|
567
597
|
.diff-empty {
|
|
568
598
|
margin: 12px;
|
|
569
599
|
}
|
|
@@ -701,6 +731,16 @@ a {
|
|
|
701
731
|
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
702
732
|
font-size: 13px;
|
|
703
733
|
font-weight: 600;
|
|
734
|
+
white-space: normal;
|
|
735
|
+
word-break: break-all;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
.diff-file-link {
|
|
739
|
+
color: var(--accent);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
.diff-file-link:hover {
|
|
743
|
+
text-decoration: underline;
|
|
704
744
|
}
|
|
705
745
|
|
|
706
746
|
.d2h-file-header .d2h-tag {
|
|
@@ -763,7 +803,8 @@ a {
|
|
|
763
803
|
transform: rotate(-90deg);
|
|
764
804
|
}
|
|
765
805
|
|
|
766
|
-
|
|
806
|
+
/* Diffs start hidden; JS adds .expanded to show them */
|
|
807
|
+
.d2h-file-diff:not(.expanded) {
|
|
767
808
|
display: none;
|
|
768
809
|
}
|
|
769
810
|
|
package/public/app.js
CHANGED
|
@@ -184,17 +184,50 @@ function initDiffCollapse() {
|
|
|
184
184
|
const wrappers = document.querySelectorAll(".d2h-file-wrapper");
|
|
185
185
|
if (!wrappers.length) return;
|
|
186
186
|
|
|
187
|
+
// Diffs are hidden by CSS by default (.d2h-file-diff:not(.expanded)).
|
|
188
|
+
// Only expand when there are few files — avoids layout/paint cost for large diffs.
|
|
189
|
+
const shouldExpand = wrappers.length <= 8;
|
|
190
|
+
|
|
191
|
+
// Add expand/collapse all buttons
|
|
192
|
+
const diffWrap = document.querySelector(".diff-wrap");
|
|
193
|
+
if (diffWrap && wrappers.length > 1) {
|
|
194
|
+
const bar = document.createElement("div");
|
|
195
|
+
bar.className = "diff-actions";
|
|
196
|
+
bar.innerHTML = `<button type="button" class="btn btn-sm" id="expand-all">Expand all</button>
|
|
197
|
+
<button type="button" class="btn btn-sm" id="collapse-all">Collapse all</button>`;
|
|
198
|
+
diffWrap.insertBefore(bar, diffWrap.firstChild);
|
|
199
|
+
}
|
|
200
|
+
|
|
187
201
|
for (const wrapper of wrappers) {
|
|
188
202
|
const header = wrapper.querySelector(".d2h-file-header");
|
|
189
203
|
const diff = wrapper.querySelector(".d2h-file-diff");
|
|
190
204
|
if (!header || !diff) continue;
|
|
191
205
|
|
|
206
|
+
const fileNameEl = header.querySelector(".d2h-file-name");
|
|
207
|
+
if (fileNameEl && !fileNameEl.querySelector("a")) {
|
|
208
|
+
const rawName = fileNameEl.textContent.trim();
|
|
209
|
+
const name = rawName.includes(" → ") ? rawName.split(" → ").pop() : rawName;
|
|
210
|
+
const link = document.createElement("a");
|
|
211
|
+
link.className = "diff-file-link";
|
|
212
|
+
link.href = `/blob/${encodeURI(name)}`;
|
|
213
|
+
link.textContent = rawName;
|
|
214
|
+
fileNameEl.textContent = "";
|
|
215
|
+
fileNameEl.appendChild(link);
|
|
216
|
+
}
|
|
217
|
+
|
|
192
218
|
const toggle = document.createElement("button");
|
|
193
219
|
toggle.className = "diff-toggle";
|
|
194
220
|
toggle.type = "button";
|
|
195
|
-
toggle.setAttribute("aria-expanded", "true");
|
|
196
221
|
toggle.setAttribute("aria-label", "Toggle file diff");
|
|
197
|
-
|
|
222
|
+
|
|
223
|
+
if (shouldExpand) {
|
|
224
|
+
toggle.setAttribute("aria-expanded", "true");
|
|
225
|
+
toggle.textContent = "\u25BE";
|
|
226
|
+
diff.classList.add("expanded");
|
|
227
|
+
} else {
|
|
228
|
+
toggle.setAttribute("aria-expanded", "false");
|
|
229
|
+
toggle.textContent = "\u25B8";
|
|
230
|
+
}
|
|
198
231
|
header.appendChild(toggle);
|
|
199
232
|
|
|
200
233
|
header.addEventListener("click", (e) => {
|
|
@@ -202,9 +235,31 @@ function initDiffCollapse() {
|
|
|
202
235
|
const expanded = toggle.getAttribute("aria-expanded") === "true";
|
|
203
236
|
toggle.setAttribute("aria-expanded", String(!expanded));
|
|
204
237
|
toggle.textContent = expanded ? "\u25B8" : "\u25BE";
|
|
205
|
-
diff.
|
|
238
|
+
diff.classList.toggle("expanded");
|
|
206
239
|
});
|
|
207
240
|
}
|
|
241
|
+
|
|
242
|
+
document.getElementById("expand-all")?.addEventListener("click", () => {
|
|
243
|
+
for (const wrapper of wrappers) {
|
|
244
|
+
const toggle = wrapper.querySelector(".diff-toggle");
|
|
245
|
+
const diff = wrapper.querySelector(".d2h-file-diff");
|
|
246
|
+
if (!toggle || !diff) continue;
|
|
247
|
+
toggle.setAttribute("aria-expanded", "true");
|
|
248
|
+
toggle.textContent = "\u25BE";
|
|
249
|
+
diff.classList.add("expanded");
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
document.getElementById("collapse-all")?.addEventListener("click", () => {
|
|
254
|
+
for (const wrapper of wrappers) {
|
|
255
|
+
const toggle = wrapper.querySelector(".diff-toggle");
|
|
256
|
+
const diff = wrapper.querySelector(".d2h-file-diff");
|
|
257
|
+
if (!toggle || !diff) continue;
|
|
258
|
+
toggle.setAttribute("aria-expanded", "false");
|
|
259
|
+
toggle.textContent = "\u25B8";
|
|
260
|
+
diff.classList.remove("expanded");
|
|
261
|
+
}
|
|
262
|
+
});
|
|
208
263
|
}
|
|
209
264
|
|
|
210
265
|
function initBaseSelector() {
|
|
@@ -222,7 +277,7 @@ function initBaseSelector() {
|
|
|
222
277
|
}
|
|
223
278
|
|
|
224
279
|
window.addEventListener("load", () => {
|
|
225
|
-
preserveQueryParamsOnInternalLinks(["ignored", "watch", "base"]);
|
|
280
|
+
preserveQueryParamsOnInternalLinks(["ignored", "watch", "base", "show_all"]);
|
|
226
281
|
renderMath();
|
|
227
282
|
renderMermaid();
|
|
228
283
|
initTimezoneToggle();
|
package/src/server.js
CHANGED
|
@@ -143,8 +143,7 @@ async function getGitDiffRaw(repoRootReal, base) {
|
|
|
143
143
|
async function getGitInfo(repoRootReal) {
|
|
144
144
|
const gitDir = path.join(repoRootReal, ".git");
|
|
145
145
|
try {
|
|
146
|
-
|
|
147
|
-
if (!stat.isDirectory()) return { branch: null, commit: null };
|
|
146
|
+
await fs.stat(gitDir);
|
|
148
147
|
} catch {
|
|
149
148
|
return { branch: null, commit: null };
|
|
150
149
|
}
|
|
@@ -387,6 +386,7 @@ export async function startServer({ repoRoot, host, port, watch }) {
|
|
|
387
386
|
if (req.query.watch === "0") query.set("watch", "0");
|
|
388
387
|
if (req.query.ignored === "1") query.set("ignored", "1");
|
|
389
388
|
if (base !== "HEAD") query.set("base", base);
|
|
389
|
+
if (req.query.show_all === "1") query.set("show_all", "1");
|
|
390
390
|
const querySuffix = query.toString() ? `?${query.toString()}` : "";
|
|
391
391
|
|
|
392
392
|
const [branches, tags, diffResult] = await Promise.all([
|
|
@@ -395,9 +395,17 @@ export async function startServer({ repoRoot, host, port, watch }) {
|
|
|
395
395
|
getGitDiffRaw(repoRootReal, base),
|
|
396
396
|
]);
|
|
397
397
|
|
|
398
|
+
const MAX_DIFF_FILES = 30;
|
|
398
399
|
let diffHtml = "";
|
|
400
|
+
let fileCount = 0;
|
|
401
|
+
const showAll = req.query.show_all === "1";
|
|
399
402
|
if (!diffResult.tooLarge && diffResult.raw) {
|
|
400
|
-
|
|
403
|
+
const parsed = diff2html.parse(diffResult.raw);
|
|
404
|
+
fileCount = parsed.length;
|
|
405
|
+
const toRender = (!showAll && parsed.length > MAX_DIFF_FILES)
|
|
406
|
+
? parsed.slice(0, MAX_DIFF_FILES)
|
|
407
|
+
: parsed;
|
|
408
|
+
diffHtml = diff2html.html(toRender, {
|
|
401
409
|
outputFormat: "line-by-line",
|
|
402
410
|
drawFileList: true,
|
|
403
411
|
});
|
|
@@ -416,6 +424,8 @@ export async function startServer({ repoRoot, host, port, watch }) {
|
|
|
416
424
|
diffHtml,
|
|
417
425
|
tooLarge: diffResult.tooLarge,
|
|
418
426
|
empty: !diffResult.raw,
|
|
427
|
+
fileCount,
|
|
428
|
+
showAll,
|
|
419
429
|
}),
|
|
420
430
|
);
|
|
421
431
|
} catch (e) {
|
package/src/views.js
CHANGED
|
@@ -293,6 +293,8 @@ export function renderDiffPage({
|
|
|
293
293
|
diffHtml,
|
|
294
294
|
tooLarge,
|
|
295
295
|
empty,
|
|
296
|
+
fileCount,
|
|
297
|
+
showAll,
|
|
296
298
|
}) {
|
|
297
299
|
const branchOptions = branches
|
|
298
300
|
.map((b) => {
|
|
@@ -323,6 +325,16 @@ export function renderDiffPage({
|
|
|
323
325
|
content = diffHtml;
|
|
324
326
|
}
|
|
325
327
|
|
|
328
|
+
const MAX_DIFF_FILES = 30;
|
|
329
|
+
let truncatedMsg = "";
|
|
330
|
+
if (fileCount > MAX_DIFF_FILES && !showAll) {
|
|
331
|
+
const hidden = fileCount - MAX_DIFF_FILES;
|
|
332
|
+
const showAllQuery = new URLSearchParams(querySuffix ? querySuffix.slice(1) : "");
|
|
333
|
+
showAllQuery.set("show_all", "1");
|
|
334
|
+
const showAllHref = `/diff?${showAllQuery.toString()}`;
|
|
335
|
+
truncatedMsg = `<div class="diff-truncated note">${hidden} more file${hidden === 1 ? "" : "s"} not shown. <a class="link" href="${showAllHref}">Show all ${fileCount} files</a></div>`;
|
|
336
|
+
}
|
|
337
|
+
|
|
326
338
|
const body = `<section class="panel">
|
|
327
339
|
<div class="panel-title">
|
|
328
340
|
<span>Compare working tree against</span>
|
|
@@ -332,6 +344,7 @@ export function renderDiffPage({
|
|
|
332
344
|
</div>
|
|
333
345
|
<div class="diff-wrap">
|
|
334
346
|
${content}
|
|
347
|
+
${truncatedMsg}
|
|
335
348
|
</div>
|
|
336
349
|
</section>`;
|
|
337
350
|
|