@youtyan/code-viewer 0.9.0 → 0.9.2
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/README.md +18 -2
- package/dist/code-viewer.js +1098 -681
- package/package.json +1 -1
- package/web/app.js +94 -69
- package/web/index.html +1 -1
- package/web/style.css +18 -0
package/package.json
CHANGED
package/web/app.js
CHANGED
|
@@ -247,6 +247,22 @@ ${lines.join(`
|
|
|
247
247
|
};
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
// web-src/core/changed-paths.ts
|
|
251
|
+
function changedPathCoversPath(changed, path) {
|
|
252
|
+
return path === changed || path.startsWith(`${changed}/`);
|
|
253
|
+
}
|
|
254
|
+
function changedPathsCoverPath(changedPaths, path) {
|
|
255
|
+
if (!changedPaths)
|
|
256
|
+
return true;
|
|
257
|
+
if (changedPaths.has(path))
|
|
258
|
+
return true;
|
|
259
|
+
for (const changed of changedPaths) {
|
|
260
|
+
if (changedPathCoversPath(changed, path))
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
|
|
250
266
|
// web-src/core/expand-logic.ts
|
|
251
267
|
function initExpandState(prevHunkEndNew, hunkNewStart) {
|
|
252
268
|
return {
|
|
@@ -23348,7 +23364,14 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
23348
23364
|
const span = document.createElement("span");
|
|
23349
23365
|
span.className = `badge ${ch}`;
|
|
23350
23366
|
span.textContent = ch;
|
|
23351
|
-
span.title = {
|
|
23367
|
+
span.title = {
|
|
23368
|
+
M: "modified",
|
|
23369
|
+
A: "added",
|
|
23370
|
+
D: "deleted",
|
|
23371
|
+
R: "renamed",
|
|
23372
|
+
U: "untracked",
|
|
23373
|
+
I: "ignored"
|
|
23374
|
+
}[ch] || ch;
|
|
23352
23375
|
return span;
|
|
23353
23376
|
}
|
|
23354
23377
|
function setFileViewed(path, viewed) {
|
|
@@ -23690,7 +23713,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
23690
23713
|
function invalidateLoadedCard(card, file, changedPaths, measuredHeight) {
|
|
23691
23714
|
if (!card.classList.contains("loaded") && !card.classList.contains("loading"))
|
|
23692
23715
|
return false;
|
|
23693
|
-
if (changedPaths
|
|
23716
|
+
if (!changedPathsCoverPath(changedPaths, file.path))
|
|
23694
23717
|
return false;
|
|
23695
23718
|
card.dataset.reqId = String(++CLIENT_REQ_SEQ);
|
|
23696
23719
|
card.style.minHeight = `${measuredHeight ?? card.offsetHeight}px`;
|
|
@@ -23780,13 +23803,12 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
23780
23803
|
const pathsUnknown = !changedPaths;
|
|
23781
23804
|
const contentMayNeedReload = !listSame || pathsUnknown || (changedPaths ? newFiles.some((file) => {
|
|
23782
23805
|
const key = fileKey(file);
|
|
23783
|
-
return prevCardSignatures.get(key) !== newCardSigs.get(key) || changedPaths
|
|
23806
|
+
return prevCardSignatures.get(key) !== newCardSigs.get(key) || changedPathsCoverPath(changedPaths, file.path);
|
|
23784
23807
|
}) : false);
|
|
23785
23808
|
if (contentMayNeedReload)
|
|
23786
23809
|
resetLoadScheduling();
|
|
23787
23810
|
let invalidatedCards = 0;
|
|
23788
23811
|
if (listSame && domIntact) {
|
|
23789
|
-
const pathsUnknown2 = !changedPaths;
|
|
23790
23812
|
const cardsByKey = collectDiffCardsByKey(target);
|
|
23791
23813
|
const measuredHeights = new Map;
|
|
23792
23814
|
for (const f2 of newFiles) {
|
|
@@ -23801,7 +23823,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
23801
23823
|
const oldSig = prevCardSignatures.get(key);
|
|
23802
23824
|
const newSig = newCardSigs.get(key) ?? computeCardSignature(f2);
|
|
23803
23825
|
const sigChanged = oldSig !== newSig;
|
|
23804
|
-
const pathHint =
|
|
23826
|
+
const pathHint = changedPathsCoverPath(changedPaths, f2.path);
|
|
23805
23827
|
if (!sigChanged && !pathHint) {
|
|
23806
23828
|
continue;
|
|
23807
23829
|
}
|
|
@@ -26425,7 +26447,11 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
26425
26447
|
},
|
|
26426
26448
|
{
|
|
26427
26449
|
kind: "paragraph",
|
|
26428
|
-
text: 'Symlinks show a distinct icon and a "→ target" label so they are never mistaken for a regular file or folder, and clicking one navigates to its resolved target. A broken symlink is visually flagged and disabled.
|
|
26450
|
+
text: 'Symlinks show a distinct icon and a "→ target" label so they are never mistaken for a regular file or folder, and clicking one navigates to its resolved target. A broken symlink is visually flagged and disabled.'
|
|
26451
|
+
},
|
|
26452
|
+
{
|
|
26453
|
+
kind: "paragraph",
|
|
26454
|
+
text: "Files with pending git changes show a status badge in the tree instead of the regular type icon: M (modified), A (added — staged for commit), D (deleted), R (renamed), U (untracked — in the worktree but not under version control yet), and I (ignored by a .gitignore rule). U and A stay separate so a file you have never run git add on does not look like one that is already staged. A wholly untracked or ignored directory is badged as a whole and keeps its folder icon, so it stays recognizable while collapsed; its contents inherit the badge unless an ignore rule names a file specifically."
|
|
26429
26455
|
}
|
|
26430
26456
|
]
|
|
26431
26457
|
},
|
|
@@ -27116,7 +27142,11 @@ code-viewer query agent-help`
|
|
|
27116
27142
|
},
|
|
27117
27143
|
{
|
|
27118
27144
|
kind: "paragraph",
|
|
27119
|
-
text: "シンボリックリンクは専用アイコンと「→
|
|
27145
|
+
text: "シンボリックリンクは専用アイコンと「→ リンク先」ラベルで表示されるため通常のファイル/フォルダと区別でき、クリックするとリンク先に遷移します。リンク切れのシンボリックリンクは無効化されたことが分かる表示になります。"
|
|
27146
|
+
},
|
|
27147
|
+
{
|
|
27148
|
+
kind: "paragraph",
|
|
27149
|
+
text: "git の状態があるファイルは、通常の種類アイコンの代わりにステータスバッジがツリーに表示されます。M(変更)、A(追加 — コミット予定としてステージ済み)、D(削除)、R(リネーム)、U(未追跡 — ワークツリーにあるがまだバージョン管理下にない)、I(.gitignore の対象) の 6 種類です。U と A を分けているのは、git add をまだ一度もしていないファイルが、既にステージ済みのファイルと同じ見た目にならないようにするためです。丸ごと未追跡・無視のディレクトリにはディレクトリ単位でバッジが付き、フォルダアイコンは残るので折りたたんだままでも判別できます。配下のファイルはそのバッジを引き継ぎますが、無視ルールが個別に名指ししているファイルはそちらが優先されます。"
|
|
27120
27150
|
}
|
|
27121
27151
|
]
|
|
27122
27152
|
},
|
|
@@ -31235,6 +31265,43 @@ code-viewer query agent-help`
|
|
|
31235
31265
|
function toggleSidebarHidden() {
|
|
31236
31266
|
applySidebarHidden(!STATE.sidebarHidden);
|
|
31237
31267
|
}
|
|
31268
|
+
function applyDirEntryToNode(node, entry) {
|
|
31269
|
+
node.explicit = true;
|
|
31270
|
+
if (entry.children_omitted === true) {
|
|
31271
|
+
node.children_omitted = true;
|
|
31272
|
+
node.children_omitted_reason = entry.children_omitted_reason;
|
|
31273
|
+
}
|
|
31274
|
+
if (entry.is_symlink) {
|
|
31275
|
+
node.is_symlink = true;
|
|
31276
|
+
node.symlink_target = entry.symlink_target;
|
|
31277
|
+
node.resolved_path = entry.resolved_path;
|
|
31278
|
+
}
|
|
31279
|
+
if (entry.status)
|
|
31280
|
+
node.status = entry.status;
|
|
31281
|
+
}
|
|
31282
|
+
function createTreeDirLabel(dir) {
|
|
31283
|
+
const label = document.createElement("span");
|
|
31284
|
+
label.className = "dir-label";
|
|
31285
|
+
const dn = document.createElement("span");
|
|
31286
|
+
dn.className = "dir-name";
|
|
31287
|
+
dn.textContent = dir.name;
|
|
31288
|
+
dn.title = dir.path;
|
|
31289
|
+
label.appendChild(dn);
|
|
31290
|
+
if (dir.status)
|
|
31291
|
+
label.appendChild(fileBadge(dir.status));
|
|
31292
|
+
if (dir.children_omitted) {
|
|
31293
|
+
const omitted = document.createElement("span");
|
|
31294
|
+
omitted.className = "dir-omitted " + (dir.children_omitted_reason === "heavy" ? "dir-omitted-heavy" : "dir-omitted-internal");
|
|
31295
|
+
const badge = omittedDirectoryBadge(dir.children_omitted_reason);
|
|
31296
|
+
omitted.textContent = badge.label;
|
|
31297
|
+
omitted.title = badge.title;
|
|
31298
|
+
label.appendChild(omitted);
|
|
31299
|
+
}
|
|
31300
|
+
const dirSymlinkLabel = symlinkTargetLabel(dir);
|
|
31301
|
+
if (dirSymlinkLabel)
|
|
31302
|
+
label.appendChild(dirSymlinkLabel);
|
|
31303
|
+
return label;
|
|
31304
|
+
}
|
|
31238
31305
|
function buildTree(files) {
|
|
31239
31306
|
const root = {
|
|
31240
31307
|
name: "",
|
|
@@ -31266,16 +31333,7 @@ code-viewer query agent-help`
|
|
|
31266
31333
|
node.minOrder = f2.order;
|
|
31267
31334
|
}
|
|
31268
31335
|
if (f2.type === "tree") {
|
|
31269
|
-
node
|
|
31270
|
-
if (f2.children_omitted === true) {
|
|
31271
|
-
node.children_omitted = true;
|
|
31272
|
-
node.children_omitted_reason = f2.children_omitted_reason;
|
|
31273
|
-
}
|
|
31274
|
-
if (f2.is_symlink) {
|
|
31275
|
-
node.is_symlink = true;
|
|
31276
|
-
node.symlink_target = f2.symlink_target;
|
|
31277
|
-
node.resolved_path = f2.resolved_path;
|
|
31278
|
-
}
|
|
31336
|
+
applyDirEntryToNode(node, f2);
|
|
31279
31337
|
continue;
|
|
31280
31338
|
}
|
|
31281
31339
|
node.files.push(f2);
|
|
@@ -31345,25 +31403,7 @@ code-viewer query agent-help`
|
|
|
31345
31403
|
const dirIcon = document.createElement("span");
|
|
31346
31404
|
dirIcon.className = "dir-icon";
|
|
31347
31405
|
li.appendChild(dirIcon);
|
|
31348
|
-
|
|
31349
|
-
label.className = "dir-label";
|
|
31350
|
-
const dn = document.createElement("span");
|
|
31351
|
-
dn.className = "dir-name";
|
|
31352
|
-
dn.textContent = dir.name;
|
|
31353
|
-
dn.title = dir.path;
|
|
31354
|
-
label.appendChild(dn);
|
|
31355
|
-
if (dir.children_omitted) {
|
|
31356
|
-
const omitted = document.createElement("span");
|
|
31357
|
-
omitted.className = "dir-omitted " + (dir.children_omitted_reason === "heavy" ? "dir-omitted-heavy" : "dir-omitted-internal");
|
|
31358
|
-
const badge = omittedDirectoryBadge(dir.children_omitted_reason);
|
|
31359
|
-
omitted.textContent = badge.label;
|
|
31360
|
-
omitted.title = badge.title;
|
|
31361
|
-
label.appendChild(omitted);
|
|
31362
|
-
}
|
|
31363
|
-
const dirSymlinkLabel = symlinkTargetLabel(dir);
|
|
31364
|
-
if (dirSymlinkLabel)
|
|
31365
|
-
label.appendChild(dirSymlinkLabel);
|
|
31366
|
-
li.appendChild(label);
|
|
31406
|
+
li.appendChild(createTreeDirLabel(dir));
|
|
31367
31407
|
li.appendChild(createOpenPathButton(dir.path, "directory", openDirectoryInOsTitle()));
|
|
31368
31408
|
const collapsed = STATE.collapsedDirs.has(dir.path);
|
|
31369
31409
|
if (collapsed)
|
|
@@ -31460,16 +31500,7 @@ code-viewer query agent-help`
|
|
|
31460
31500
|
node.minOrder = Math.min(node.minOrder, order);
|
|
31461
31501
|
}
|
|
31462
31502
|
if (entry.type === "tree") {
|
|
31463
|
-
node
|
|
31464
|
-
if (entry.children_omitted === true) {
|
|
31465
|
-
node.children_omitted = true;
|
|
31466
|
-
node.children_omitted_reason = entry.children_omitted_reason;
|
|
31467
|
-
}
|
|
31468
|
-
if (entry.is_symlink) {
|
|
31469
|
-
node.is_symlink = true;
|
|
31470
|
-
node.symlink_target = entry.symlink_target;
|
|
31471
|
-
node.resolved_path = entry.resolved_path;
|
|
31472
|
-
}
|
|
31503
|
+
applyDirEntryToNode(node, entry);
|
|
31473
31504
|
return;
|
|
31474
31505
|
}
|
|
31475
31506
|
if (!node.files.some((file) => file.path === entry.path))
|
|
@@ -31553,25 +31584,7 @@ code-viewer query agent-help`
|
|
|
31553
31584
|
const dirIcon = document.createElement("span");
|
|
31554
31585
|
dirIcon.className = "dir-icon";
|
|
31555
31586
|
li.appendChild(dirIcon);
|
|
31556
|
-
|
|
31557
|
-
label.className = "dir-label";
|
|
31558
|
-
const dn = document.createElement("span");
|
|
31559
|
-
dn.className = "dir-name";
|
|
31560
|
-
dn.textContent = dir.name;
|
|
31561
|
-
dn.title = dir.path;
|
|
31562
|
-
label.appendChild(dn);
|
|
31563
|
-
if (dir.children_omitted) {
|
|
31564
|
-
const omitted = document.createElement("span");
|
|
31565
|
-
omitted.className = "dir-omitted " + (dir.children_omitted_reason === "heavy" ? "dir-omitted-heavy" : "dir-omitted-internal");
|
|
31566
|
-
const badge = omittedDirectoryBadge(dir.children_omitted_reason);
|
|
31567
|
-
omitted.textContent = badge.label;
|
|
31568
|
-
omitted.title = badge.title;
|
|
31569
|
-
label.appendChild(omitted);
|
|
31570
|
-
}
|
|
31571
|
-
const dirSymlinkLabel = symlinkTargetLabel(dir);
|
|
31572
|
-
if (dirSymlinkLabel)
|
|
31573
|
-
label.appendChild(dirSymlinkLabel);
|
|
31574
|
-
li.appendChild(label);
|
|
31587
|
+
li.appendChild(createTreeDirLabel(dir));
|
|
31575
31588
|
li.appendChild(createOpenPathButton(dir.path, "directory", openDirectoryInOsTitle()));
|
|
31576
31589
|
const updateIcon = () => {
|
|
31577
31590
|
setFolderIcon(dirIcon, li.classList.contains("collapsed"));
|
|
@@ -33209,10 +33222,17 @@ code-viewer query agent-help`
|
|
|
33209
33222
|
row.className = nonBrowsableCommit ? `gdp-repo-row ${entry.type} gdp-repo-row-gitlink` : entry.is_symlink ? `gdp-repo-row ${entry.type} symlink-row${brokenSymlink ? " symlink-broken-row gdp-row-disabled" : ""}` : `gdp-repo-row ${entry.type}`;
|
|
33210
33223
|
if (deletedEntry)
|
|
33211
33224
|
row.classList.add("gdp-row-disabled");
|
|
33212
|
-
const
|
|
33225
|
+
const directoryRow = entry.type === "tree";
|
|
33226
|
+
const icon = entry.status && !directoryRow ? fileBadge(entry.status) : repoEntryTypeIcon(entry, browsable, nonBrowsableCommit);
|
|
33213
33227
|
const name = document.createElement("span");
|
|
33214
33228
|
name.className = "name";
|
|
33215
33229
|
name.textContent = entry.name;
|
|
33230
|
+
let nameCell = name;
|
|
33231
|
+
if (directoryRow && entry.status) {
|
|
33232
|
+
nameCell = document.createElement("span");
|
|
33233
|
+
nameCell.className = "name-cell";
|
|
33234
|
+
nameCell.append(name, fileBadge(entry.status));
|
|
33235
|
+
}
|
|
33216
33236
|
if (nonBrowsableCommit) {
|
|
33217
33237
|
row.title = commitEntryMeta(entry.submodule).title;
|
|
33218
33238
|
row.setAttribute("aria-disabled", "true");
|
|
@@ -33221,7 +33241,7 @@ code-viewer query agent-help`
|
|
|
33221
33241
|
}
|
|
33222
33242
|
const metaBlock = createRepoEntryMeta(entry, browsable);
|
|
33223
33243
|
const size = createRepoEntrySize(entry);
|
|
33224
|
-
row.append(icon,
|
|
33244
|
+
row.append(icon, nameCell, metaBlock, size);
|
|
33225
33245
|
row.addEventListener("click", () => {
|
|
33226
33246
|
if (brokenSymlink || deletedEntry)
|
|
33227
33247
|
return;
|
|
@@ -36588,6 +36608,11 @@ code-viewer query agent-help`
|
|
|
36588
36608
|
SERVER_SCOPE_WATCH_LIMIT_MIN = settings.scope.watch_limit_min;
|
|
36589
36609
|
if (typeof settings.scope.watch_limit_max === "number")
|
|
36590
36610
|
SERVER_SCOPE_WATCH_LIMIT_MAX = settings.scope.watch_limit_max;
|
|
36611
|
+
if (typeof settings.scope.watch_recursive === "boolean") {
|
|
36612
|
+
const watchSection = document.querySelector("#watch-settings-section");
|
|
36613
|
+
if (watchSection)
|
|
36614
|
+
watchSection.hidden = settings.scope.watch_recursive;
|
|
36615
|
+
}
|
|
36591
36616
|
return settings;
|
|
36592
36617
|
} catch {
|
|
36593
36618
|
return null;
|
|
@@ -40074,7 +40099,7 @@ code-viewer query agent-help`
|
|
|
40074
40099
|
return;
|
|
40075
40100
|
if (isBlobOrBlameFileRoute(route)) {
|
|
40076
40101
|
const viewingPath = route.path;
|
|
40077
|
-
if (
|
|
40102
|
+
if (viewingPath && !changedPathsCoverPath(paths, viewingPath))
|
|
40078
40103
|
return;
|
|
40079
40104
|
dispatchFileRoute(route, { refresh: true });
|
|
40080
40105
|
return;
|
|
@@ -40122,7 +40147,7 @@ code-viewer query agent-help`
|
|
|
40122
40147
|
const route = STATE.route;
|
|
40123
40148
|
if (isBlobOrBlameFileRoute(route)) {
|
|
40124
40149
|
const viewingPath = route.path;
|
|
40125
|
-
if (
|
|
40150
|
+
if (viewingPath && !changedPathsCoverPath(paths, viewingPath))
|
|
40126
40151
|
return;
|
|
40127
40152
|
}
|
|
40128
40153
|
if (STATE.autoUpdate) {
|
package/web/index.html
CHANGED
|
@@ -191,7 +191,7 @@
|
|
|
191
191
|
</label>
|
|
192
192
|
<p id="datastore-s3-tooltip-help" class="scope-settings-help"></p>
|
|
193
193
|
</div>
|
|
194
|
-
<div class="scope-settings-section">
|
|
194
|
+
<div id="watch-settings-section" class="scope-settings-section">
|
|
195
195
|
<strong id="watch-section-title" class="scope-settings-section-title">File change watcher</strong>
|
|
196
196
|
<label for="scope-watch-limit">Maximum directories to watch</label>
|
|
197
197
|
<div class="scope-watch-limit-row">
|
package/web/style.css
CHANGED
|
@@ -2721,11 +2721,19 @@ body.gdp-help-page #content {
|
|
|
2721
2721
|
.badge.A { background: #ccffd866; color: var(--success); }
|
|
2722
2722
|
.badge.D { background: #ffd7d566; color: var(--danger); }
|
|
2723
2723
|
.badge.R { background: #d8b9ff66; color: var(--done); }
|
|
2724
|
+
/* Outside version control. U (untracked) takes the accent hue so it reads as
|
|
2725
|
+
"not in git yet" rather than as one more shade of the staged-green A it
|
|
2726
|
+
used to be collapsed into. I (ignored) stays deliberately colorless: an
|
|
2727
|
+
ignored file is present but irrelevant to the repository. */
|
|
2728
|
+
.badge.U { background: var(--accent-subtle); color: var(--accent); }
|
|
2729
|
+
.badge.I { background: var(--bg-emph); color: var(--fg-muted); }
|
|
2724
2730
|
|
|
2725
2731
|
[data-theme="dark"] .badge.M { background: rgba(210,153,34,0.20); color: var(--attn); }
|
|
2726
2732
|
[data-theme="dark"] .badge.A { background: rgba(46,160,67,0.20); color: var(--success); }
|
|
2727
2733
|
[data-theme="dark"] .badge.D { background: rgba(248,81,73,0.20); color: var(--danger); }
|
|
2728
2734
|
[data-theme="dark"] .badge.R { background: rgba(163,113,247,0.20); color: var(--done); }
|
|
2735
|
+
[data-theme="dark"] .badge.U { background: rgba(56,139,253,0.20); color: var(--accent); }
|
|
2736
|
+
[data-theme="dark"] .badge.I { background: rgba(145,152,161,0.15); color: var(--fg-muted); }
|
|
2729
2737
|
|
|
2730
2738
|
/* Sidebar row marker for files worth a second look before diving in:
|
|
2731
2739
|
heavy diffs, binary/media files, or Git commit entries. Same semantics as
|
|
@@ -4792,6 +4800,16 @@ body.gdp-file-detail-page #empty {
|
|
|
4792
4800
|
white-space: nowrap;
|
|
4793
4801
|
font-weight: 500;
|
|
4794
4802
|
}
|
|
4803
|
+
/* Holds the name plus a directory's status badge inside the single name
|
|
4804
|
+
column of the row grid - same shape as the sidebar's .dir-label, which
|
|
4805
|
+
pairs a directory name with its badges. */
|
|
4806
|
+
.gdp-repo-row .name-cell {
|
|
4807
|
+
min-width: 0;
|
|
4808
|
+
display: flex;
|
|
4809
|
+
align-items: center;
|
|
4810
|
+
gap: 6px;
|
|
4811
|
+
overflow: hidden;
|
|
4812
|
+
}
|
|
4795
4813
|
.gdp-repo-row .kind {
|
|
4796
4814
|
justify-self: end;
|
|
4797
4815
|
color: var(--fg-muted);
|