@youtyan/code-viewer 0.1.21 → 0.1.22
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/web/app.js +620 -44
- package/web/style.css +38 -9
package/package.json
CHANGED
package/web/app.js
CHANGED
|
@@ -243,10 +243,43 @@
|
|
|
243
243
|
}
|
|
244
244
|
return ranges;
|
|
245
245
|
}
|
|
246
|
-
function
|
|
246
|
+
function basenameMatchTier(loweredQuery, loweredBasename) {
|
|
247
|
+
if (loweredBasename === loweredQuery)
|
|
248
|
+
return 4;
|
|
249
|
+
if (loweredBasename.startsWith(`${loweredQuery}.`))
|
|
250
|
+
return 3;
|
|
251
|
+
if (loweredBasename.startsWith(loweredQuery))
|
|
252
|
+
return 2;
|
|
253
|
+
if (loweredBasename.includes(loweredQuery))
|
|
254
|
+
return 1;
|
|
255
|
+
return 0;
|
|
256
|
+
}
|
|
257
|
+
function pathMatchTier(loweredQuery, loweredPath, loweredBasename) {
|
|
258
|
+
if (loweredQuery.includes("/") && (loweredPath === loweredQuery || loweredPath.endsWith(`/${loweredQuery}`)))
|
|
259
|
+
return 4;
|
|
260
|
+
return basenameMatchTier(loweredQuery, loweredBasename);
|
|
261
|
+
}
|
|
262
|
+
function contiguousPathRange(loweredQuery, loweredPath, baseStart) {
|
|
263
|
+
const loweredBasename = loweredPath.slice(baseStart);
|
|
264
|
+
const basenameMatchStart = loweredBasename.indexOf(loweredQuery);
|
|
265
|
+
if (basenameMatchStart >= 0) {
|
|
266
|
+
const start = baseStart + basenameMatchStart;
|
|
267
|
+
return { start, end: start + loweredQuery.length };
|
|
268
|
+
}
|
|
269
|
+
if (loweredQuery.includes("/")) {
|
|
270
|
+
const pathMatchStart = loweredPath.endsWith(`/${loweredQuery}`) ? loweredPath.length - loweredQuery.length : loweredPath === loweredQuery ? 0 : -1;
|
|
271
|
+
if (pathMatchStart >= 0)
|
|
272
|
+
return {
|
|
273
|
+
start: pathMatchStart,
|
|
274
|
+
end: pathMatchStart + loweredQuery.length
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
function computeFuzzyMatch(query, path) {
|
|
247
280
|
const q = query.trim().toLowerCase();
|
|
248
281
|
if (!q)
|
|
249
|
-
return { score: 0, ranges: [] };
|
|
282
|
+
return { score: 0, ranges: [], tier: 0 };
|
|
250
283
|
const lowerPath = path.toLowerCase();
|
|
251
284
|
const baseStart = basenameStart(path);
|
|
252
285
|
const indices = [];
|
|
@@ -267,24 +300,28 @@
|
|
|
267
300
|
score += 12;
|
|
268
301
|
from = index + 1;
|
|
269
302
|
}
|
|
270
|
-
const first = indices[0]
|
|
303
|
+
const first = indices[0];
|
|
271
304
|
score -= Math.min(first, 40);
|
|
272
305
|
if (indices[0] >= baseStart)
|
|
273
306
|
score += 20;
|
|
274
307
|
const basename = lowerPath.slice(baseStart);
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
score
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
308
|
+
const tier = pathMatchTier(q, lowerPath, basename);
|
|
309
|
+
const contiguousRange = contiguousPathRange(q, lowerPath, baseStart);
|
|
310
|
+
return {
|
|
311
|
+
score,
|
|
312
|
+
ranges: contiguousRange ? [contiguousRange] : toRanges(indices),
|
|
313
|
+
tier
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
function fuzzyMatchPath(query, path) {
|
|
317
|
+
const match = computeFuzzyMatch(query, path);
|
|
318
|
+
return match ? { score: match.score, ranges: match.ranges } : null;
|
|
282
319
|
}
|
|
283
320
|
function rankFuzzyPaths(query, items) {
|
|
284
321
|
return items.map((item) => {
|
|
285
|
-
const match =
|
|
286
|
-
return match ? { item, score: match.score, ranges: match.ranges } : null;
|
|
287
|
-
}).filter((item) => item !== null).sort((a, b) => b.score - a.score || a.item.path.localeCompare(b.item.path));
|
|
322
|
+
const match = computeFuzzyMatch(query, item.path);
|
|
323
|
+
return match ? { item, score: match.score, ranges: match.ranges, tier: match.tier } : null;
|
|
324
|
+
}).filter((item) => item !== null).sort((a, b) => b.tier - a.tier || b.score - a.score || a.item.path.localeCompare(b.item.path)).map(({ item, score, ranges }) => ({ item, score, ranges }));
|
|
288
325
|
}
|
|
289
326
|
function isGlobPathQuery(query) {
|
|
290
327
|
return /[*?]/.test(query.trim());
|
|
@@ -6884,7 +6921,11 @@ ${frontmatter.yaml}
|
|
|
6884
6921
|
const VIRTUAL_SOURCE_SIZE_THRESHOLD = 1024 * 1024;
|
|
6885
6922
|
const VIRTUAL_SOURCE_PAGE_SIZE = 2000;
|
|
6886
6923
|
const VIRTUAL_SOURCE_ROW_HEIGHT = 20;
|
|
6924
|
+
const VIRTUAL_SIDEBAR_THRESHOLD = 3000;
|
|
6925
|
+
const VIRTUAL_SIDEBAR_ROW_HEIGHT = 29;
|
|
6926
|
+
const VIRTUAL_SIDEBAR_OVERSCAN = 16;
|
|
6887
6927
|
const VIRTUAL_SOURCE_HIGHLIGHT_MAX_LINE_LENGTH = 2000;
|
|
6928
|
+
const TEST_RE = /(^|[/_.])(test|spec|__tests__)([/_.]|$)/i;
|
|
6888
6929
|
let highlightLoadPromise = null;
|
|
6889
6930
|
let sourceShikiLoadPromise = null;
|
|
6890
6931
|
let highlightConfigured = false;
|
|
@@ -6894,6 +6935,12 @@ ${frontmatter.yaml}
|
|
|
6894
6935
|
let REPO_SIDEBAR_LOAD = null;
|
|
6895
6936
|
let SIDEBAR_FILES = [];
|
|
6896
6937
|
let SIDEBAR_ON_FILE_CLICK;
|
|
6938
|
+
let SIDEBAR_TREE_ROOT = null;
|
|
6939
|
+
let SIDEBAR_TREE_ROWS = [];
|
|
6940
|
+
let SIDEBAR_VISIBLE_ROWS = [];
|
|
6941
|
+
let SIDEBAR_ROW_BY_PATH = new Map;
|
|
6942
|
+
let SIDEBAR_VIRTUAL_ACTIVE_PATH = "";
|
|
6943
|
+
const SIDEBAR_TREE_ITEMS_CACHE = new WeakMap;
|
|
6897
6944
|
let SERVER_SCOPE_OMIT_DIRS_DEFAULT = [];
|
|
6898
6945
|
let PENDING_G_SCOPE = null;
|
|
6899
6946
|
let PENDING_G_UNTIL = 0;
|
|
@@ -7584,6 +7631,22 @@ ${frontmatter.yaml}
|
|
|
7584
7631
|
attachSidebarToggle(restoreHost);
|
|
7585
7632
|
else if (sidebarHead)
|
|
7586
7633
|
attachSidebarToggle(sidebarHead);
|
|
7634
|
+
placeSidebarFilter();
|
|
7635
|
+
}
|
|
7636
|
+
function placeSidebarFilter() {
|
|
7637
|
+
const sidebarHead = document.querySelector(".sb-head");
|
|
7638
|
+
const filter = document.querySelector(".sb-filter-wrap");
|
|
7639
|
+
const list2 = document.querySelector("#filelist");
|
|
7640
|
+
if (!sidebarHead || !filter || !list2)
|
|
7641
|
+
return;
|
|
7642
|
+
const repoSidebar = isRepositorySidebarMode();
|
|
7643
|
+
if (repoSidebar && filter.parentElement !== sidebarHead) {
|
|
7644
|
+
sidebarHead.appendChild(filter);
|
|
7645
|
+
return;
|
|
7646
|
+
}
|
|
7647
|
+
if (!repoSidebar && filter.parentElement === sidebarHead) {
|
|
7648
|
+
sidebarHead.after(filter);
|
|
7649
|
+
}
|
|
7587
7650
|
}
|
|
7588
7651
|
function applySidebarHidden(hidden = STATE.sidebarHidden) {
|
|
7589
7652
|
STATE.sidebarHidden = hidden;
|
|
@@ -7859,6 +7922,301 @@ ${frontmatter.yaml}
|
|
|
7859
7922
|
}
|
|
7860
7923
|
}
|
|
7861
7924
|
}
|
|
7925
|
+
function treeNodeItems(node) {
|
|
7926
|
+
const cached = SIDEBAR_TREE_ITEMS_CACHE.get(node);
|
|
7927
|
+
if (cached)
|
|
7928
|
+
return cached;
|
|
7929
|
+
const items = [];
|
|
7930
|
+
for (const k of Object.keys(node.dirs)) {
|
|
7931
|
+
const d2 = node.dirs[k];
|
|
7932
|
+
items.push({ kind: "dir", sortKey: d2.minOrder, dir: d2 });
|
|
7933
|
+
}
|
|
7934
|
+
for (const f2 of node.files) {
|
|
7935
|
+
items.push({
|
|
7936
|
+
kind: "file",
|
|
7937
|
+
sortKey: f2.order != null ? f2.order : Infinity,
|
|
7938
|
+
file: f2
|
|
7939
|
+
});
|
|
7940
|
+
}
|
|
7941
|
+
items.sort((a2, b2) => a2.sortKey - b2.sortKey);
|
|
7942
|
+
SIDEBAR_TREE_ITEMS_CACHE.set(node, items);
|
|
7943
|
+
return items;
|
|
7944
|
+
}
|
|
7945
|
+
function createTreeDirRow(dir, depth, onFileClick) {
|
|
7946
|
+
const li = document.createElement("li");
|
|
7947
|
+
li.className = "tree-dir";
|
|
7948
|
+
li.tabIndex = -1;
|
|
7949
|
+
li.dataset.dirpath = dir.path;
|
|
7950
|
+
if (dir.explicit)
|
|
7951
|
+
li.dataset.explicit = "true";
|
|
7952
|
+
if (dir.children_omitted) {
|
|
7953
|
+
li.classList.add("children-omitted");
|
|
7954
|
+
li.classList.add(dir.children_omitted_reason === "heavy" ? "children-omitted-heavy" : "children-omitted-internal");
|
|
7955
|
+
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";
|
|
7956
|
+
}
|
|
7957
|
+
li.style.setProperty("--lvl-pad", `${12 + depth * 14}px`);
|
|
7958
|
+
const chev = document.createElement("span");
|
|
7959
|
+
if (dir.children_omitted) {
|
|
7960
|
+
chev.className = "chev-spacer";
|
|
7961
|
+
chev.setAttribute("aria-hidden", "true");
|
|
7962
|
+
} else {
|
|
7963
|
+
chev.className = "chev";
|
|
7964
|
+
setChevronIcon(chev);
|
|
7965
|
+
}
|
|
7966
|
+
li.appendChild(chev);
|
|
7967
|
+
const dirIcon = document.createElement("span");
|
|
7968
|
+
dirIcon.className = "dir-icon";
|
|
7969
|
+
li.appendChild(dirIcon);
|
|
7970
|
+
const label = document.createElement("span");
|
|
7971
|
+
label.className = "dir-label";
|
|
7972
|
+
const dn = document.createElement("span");
|
|
7973
|
+
dn.className = "dir-name";
|
|
7974
|
+
dn.textContent = dir.name;
|
|
7975
|
+
dn.title = dir.path;
|
|
7976
|
+
label.appendChild(dn);
|
|
7977
|
+
if (dir.children_omitted) {
|
|
7978
|
+
const omitted = document.createElement("span");
|
|
7979
|
+
omitted.className = "dir-omitted " + (dir.children_omitted_reason === "heavy" ? "dir-omitted-heavy" : "dir-omitted-internal");
|
|
7980
|
+
omitted.textContent = dir.children_omitted_reason === "heavy" ? "skipped" : "private";
|
|
7981
|
+
omitted.title = dir.children_omitted_reason === "heavy" ? "Tree expansion is skipped, but the directory detail can be opened" : "This directory cannot be opened from the browser";
|
|
7982
|
+
label.appendChild(omitted);
|
|
7983
|
+
}
|
|
7984
|
+
li.appendChild(label);
|
|
7985
|
+
li.appendChild(createOpenPathButton(dir.path, "directory", "open this folder in OS"));
|
|
7986
|
+
const updateIcon = () => {
|
|
7987
|
+
setFolderIcon(dirIcon, li.classList.contains("collapsed"));
|
|
7988
|
+
};
|
|
7989
|
+
const toggleDir = (e2) => {
|
|
7990
|
+
e2.stopPropagation();
|
|
7991
|
+
li.classList.toggle("collapsed");
|
|
7992
|
+
updateIcon();
|
|
7993
|
+
if (li.classList.contains("collapsed"))
|
|
7994
|
+
STATE.collapsedDirs.add(dir.path);
|
|
7995
|
+
else
|
|
7996
|
+
STATE.collapsedDirs.delete(dir.path);
|
|
7997
|
+
localStorage.setItem("gdp:collapsed-dirs", JSON.stringify([...STATE.collapsedDirs]));
|
|
7998
|
+
rerenderVirtualSidebar();
|
|
7999
|
+
};
|
|
8000
|
+
li.classList.toggle("collapsed", STATE.collapsedDirs.has(dir.path));
|
|
8001
|
+
updateIcon();
|
|
8002
|
+
if (!dir.children_omitted) {
|
|
8003
|
+
chev.addEventListener("click", toggleDir);
|
|
8004
|
+
dirIcon.addEventListener("click", toggleDir);
|
|
8005
|
+
}
|
|
8006
|
+
if (onFileClick) {
|
|
8007
|
+
li.addEventListener("click", (e2) => {
|
|
8008
|
+
e2.stopPropagation();
|
|
8009
|
+
if (dir.children_omitted_reason === "internal" || dir.children_omitted_reason === "truncated")
|
|
8010
|
+
return;
|
|
8011
|
+
onFileClick({
|
|
8012
|
+
path: dir.path,
|
|
8013
|
+
display_path: dir.path,
|
|
8014
|
+
type: "tree",
|
|
8015
|
+
children_omitted: dir.children_omitted,
|
|
8016
|
+
children_omitted_reason: dir.children_omitted_reason
|
|
8017
|
+
});
|
|
8018
|
+
scheduleMainSurfaceFocus();
|
|
8019
|
+
});
|
|
8020
|
+
} else {
|
|
8021
|
+
li.addEventListener("click", toggleDir);
|
|
8022
|
+
}
|
|
8023
|
+
return li;
|
|
8024
|
+
}
|
|
8025
|
+
function createTreeFileRow(f2, depth, onFileClick) {
|
|
8026
|
+
const li = document.createElement("li");
|
|
8027
|
+
li.className = "tree-file";
|
|
8028
|
+
li.tabIndex = -1;
|
|
8029
|
+
li.dataset.path = f2.path;
|
|
8030
|
+
li.classList.toggle("viewed", !onFileClick && STATE.viewedFiles.has(f2.path));
|
|
8031
|
+
li.classList.toggle("hidden-by-tests", STATE.hideTests && TEST_RE.test(f2.path || ""));
|
|
8032
|
+
li.style.setProperty("--lvl-pad", `${12 + depth * 14}px`);
|
|
8033
|
+
const spacer = document.createElement("span");
|
|
8034
|
+
spacer.className = "chev-spacer";
|
|
8035
|
+
li.appendChild(spacer);
|
|
8036
|
+
if (f2.status) {
|
|
8037
|
+
li.appendChild(fileBadge(f2.status));
|
|
8038
|
+
} else {
|
|
8039
|
+
const icon = document.createElement("span");
|
|
8040
|
+
icon.className = "d2h-icon-wrapper";
|
|
8041
|
+
icon.innerHTML = fileEntryIcon();
|
|
8042
|
+
li.appendChild(icon);
|
|
8043
|
+
}
|
|
8044
|
+
const name = document.createElement("span");
|
|
8045
|
+
name.className = "name";
|
|
8046
|
+
name.textContent = f2.path.split("/").pop();
|
|
8047
|
+
name.title = f2.path;
|
|
8048
|
+
li.appendChild(name);
|
|
8049
|
+
li.addEventListener("click", () => {
|
|
8050
|
+
if (onFileClick)
|
|
8051
|
+
onFileClick(f2);
|
|
8052
|
+
else
|
|
8053
|
+
scrollToFile(f2.path);
|
|
8054
|
+
scheduleMainSurfaceFocus();
|
|
8055
|
+
});
|
|
8056
|
+
if (!onFileClick)
|
|
8057
|
+
li.addEventListener("mouseenter", () => prefetchByPath(f2.path), {
|
|
8058
|
+
passive: true
|
|
8059
|
+
});
|
|
8060
|
+
return li;
|
|
8061
|
+
}
|
|
8062
|
+
function buildSidebarTreeRows(root) {
|
|
8063
|
+
const rows = [];
|
|
8064
|
+
const byPath = new Map;
|
|
8065
|
+
const walk = (node, depth) => {
|
|
8066
|
+
for (const item of treeNodeItems(node)) {
|
|
8067
|
+
if (item.kind === "dir") {
|
|
8068
|
+
const row = {
|
|
8069
|
+
kind: "dir",
|
|
8070
|
+
path: item.dir.path,
|
|
8071
|
+
name: item.dir.name,
|
|
8072
|
+
depth,
|
|
8073
|
+
dir: item.dir
|
|
8074
|
+
};
|
|
8075
|
+
rows.push(row);
|
|
8076
|
+
byPath.set(row.path, row);
|
|
8077
|
+
walk(item.dir, depth + 1);
|
|
8078
|
+
} else {
|
|
8079
|
+
const row = {
|
|
8080
|
+
kind: "file",
|
|
8081
|
+
path: item.file.path,
|
|
8082
|
+
name: item.file.path.split("/").pop() || item.file.path,
|
|
8083
|
+
depth,
|
|
8084
|
+
file: item.file
|
|
8085
|
+
};
|
|
8086
|
+
rows.push(row);
|
|
8087
|
+
byPath.set(row.path, row);
|
|
8088
|
+
}
|
|
8089
|
+
}
|
|
8090
|
+
};
|
|
8091
|
+
walk(root, 0);
|
|
8092
|
+
SIDEBAR_TREE_ROWS = rows;
|
|
8093
|
+
SIDEBAR_ROW_BY_PATH = byPath;
|
|
8094
|
+
}
|
|
8095
|
+
function computeVirtualSidebarVisibleRows() {
|
|
8096
|
+
if (!SIDEBAR_TREE_ROOT) {
|
|
8097
|
+
SIDEBAR_VISIBLE_ROWS = [];
|
|
8098
|
+
return;
|
|
8099
|
+
}
|
|
8100
|
+
const input = $("#sb-filter");
|
|
8101
|
+
const filter = compileFileFilter(input.value);
|
|
8102
|
+
const invalid = filter.kind === "invalid";
|
|
8103
|
+
input.toggleAttribute("aria-invalid", invalid);
|
|
8104
|
+
input.title = invalid ? filter.error || "invalid regular expression" : "";
|
|
8105
|
+
const filterActive = filter.kind !== "empty" && !invalid;
|
|
8106
|
+
const matches = invalid ? () => true : filter.match;
|
|
8107
|
+
const walk = (node, depth) => {
|
|
8108
|
+
let subtreeVisible = false;
|
|
8109
|
+
const rows = [];
|
|
8110
|
+
for (const item of treeNodeItems(node)) {
|
|
8111
|
+
if (item.kind === "dir") {
|
|
8112
|
+
const dirMatches = filterActive && matches(item.dir.path);
|
|
8113
|
+
const expanded = !item.dir.children_omitted && (filterActive || !STATE.collapsedDirs.has(item.dir.path));
|
|
8114
|
+
const child = walk(item.dir, depth + 1);
|
|
8115
|
+
const visible = item.dir.explicit && !filterActive ? true : dirMatches || child.visible;
|
|
8116
|
+
if (visible) {
|
|
8117
|
+
rows.push({
|
|
8118
|
+
kind: "dir",
|
|
8119
|
+
path: item.dir.path,
|
|
8120
|
+
name: item.dir.name,
|
|
8121
|
+
depth,
|
|
8122
|
+
dir: item.dir
|
|
8123
|
+
});
|
|
8124
|
+
if (expanded)
|
|
8125
|
+
rows.push(...child.rows);
|
|
8126
|
+
}
|
|
8127
|
+
subtreeVisible = subtreeVisible || visible;
|
|
8128
|
+
} else {
|
|
8129
|
+
const testHidden = STATE.hideTests && TEST_RE.test(item.file.path || "");
|
|
8130
|
+
const visible = !testHidden && matches(item.file.path || "");
|
|
8131
|
+
if (visible) {
|
|
8132
|
+
rows.push({
|
|
8133
|
+
kind: "file",
|
|
8134
|
+
path: item.file.path,
|
|
8135
|
+
name: item.file.path.split("/").pop() || item.file.path,
|
|
8136
|
+
depth,
|
|
8137
|
+
file: item.file
|
|
8138
|
+
});
|
|
8139
|
+
}
|
|
8140
|
+
subtreeVisible = subtreeVisible || visible;
|
|
8141
|
+
}
|
|
8142
|
+
}
|
|
8143
|
+
return { visible: subtreeVisible, rows };
|
|
8144
|
+
};
|
|
8145
|
+
SIDEBAR_VISIBLE_ROWS = walk(SIDEBAR_TREE_ROOT, 0).rows;
|
|
8146
|
+
}
|
|
8147
|
+
function sidebarVirtualRange() {
|
|
8148
|
+
const sidebar = document.querySelector("#sidebar");
|
|
8149
|
+
const scrollTop = sidebar?.scrollTop || 0;
|
|
8150
|
+
const height = sidebar?.clientHeight || window.innerHeight;
|
|
8151
|
+
const start = Math.max(0, Math.floor(scrollTop / VIRTUAL_SIDEBAR_ROW_HEIGHT) - VIRTUAL_SIDEBAR_OVERSCAN);
|
|
8152
|
+
const end = Math.min(SIDEBAR_VISIBLE_ROWS.length, Math.ceil((scrollTop + height) / VIRTUAL_SIDEBAR_ROW_HEIGHT) + VIRTUAL_SIDEBAR_OVERSCAN);
|
|
8153
|
+
return { start, end };
|
|
8154
|
+
}
|
|
8155
|
+
function renderVirtualSidebarWindow() {
|
|
8156
|
+
const ul = $("#filelist");
|
|
8157
|
+
if (!ul.classList.contains("tree-virtual"))
|
|
8158
|
+
return;
|
|
8159
|
+
const { start, end } = sidebarVirtualRange();
|
|
8160
|
+
const fragment = document.createDocumentFragment();
|
|
8161
|
+
for (let i2 = start;i2 < end; i2++) {
|
|
8162
|
+
const row = SIDEBAR_VISIBLE_ROWS[i2];
|
|
8163
|
+
const li = row.kind === "dir" && row.dir ? createTreeDirRow(row.dir, row.depth, SIDEBAR_ON_FILE_CLICK) : row.file ? createTreeFileRow(row.file, row.depth, SIDEBAR_ON_FILE_CLICK) : null;
|
|
8164
|
+
if (!li)
|
|
8165
|
+
continue;
|
|
8166
|
+
li.classList.toggle("active", row.path === SIDEBAR_VIRTUAL_ACTIVE_PATH);
|
|
8167
|
+
li.style.position = "absolute";
|
|
8168
|
+
li.style.top = `${i2 * VIRTUAL_SIDEBAR_ROW_HEIGHT}px`;
|
|
8169
|
+
li.style.left = "0";
|
|
8170
|
+
li.style.right = "0";
|
|
8171
|
+
fragment.appendChild(li);
|
|
8172
|
+
}
|
|
8173
|
+
ul.replaceChildren(fragment);
|
|
8174
|
+
ul.style.height = `${SIDEBAR_VISIBLE_ROWS.length * VIRTUAL_SIDEBAR_ROW_HEIGHT}px`;
|
|
8175
|
+
}
|
|
8176
|
+
function scrollVirtualSidebarPathIntoView(path) {
|
|
8177
|
+
const index = SIDEBAR_VISIBLE_ROWS.findIndex((row) => row.path === path);
|
|
8178
|
+
if (index < 0)
|
|
8179
|
+
return;
|
|
8180
|
+
const sidebar = document.querySelector("#sidebar");
|
|
8181
|
+
if (!sidebar)
|
|
8182
|
+
return;
|
|
8183
|
+
const ul = $("#filelist");
|
|
8184
|
+
const top = index * VIRTUAL_SIDEBAR_ROW_HEIGHT;
|
|
8185
|
+
const bottom = top + VIRTUAL_SIDEBAR_ROW_HEIGHT;
|
|
8186
|
+
const sidebarRect = sidebar.getBoundingClientRect();
|
|
8187
|
+
const stickyBottom = Math.max(sidebarRect.top, document.querySelector(".sb-head")?.getBoundingClientRect().bottom || sidebarRect.top, document.querySelector(".sb-filter-wrap")?.getBoundingClientRect().bottom || sidebarRect.top);
|
|
8188
|
+
const topPadding = Math.max(8, stickyBottom - sidebarRect.top + 8);
|
|
8189
|
+
const bottomPadding = 14;
|
|
8190
|
+
const listTop = ul.offsetTop;
|
|
8191
|
+
const maxHeight = Number.parseFloat(getComputedStyle(sidebar).maxHeight);
|
|
8192
|
+
const visibleHeight = Number.isFinite(maxHeight) && maxHeight > 0 ? Math.min(sidebar.clientHeight, maxHeight) : sidebar.clientHeight;
|
|
8193
|
+
const visibleTop = sidebar.scrollTop + topPadding - listTop;
|
|
8194
|
+
const visibleBottom = sidebar.scrollTop + visibleHeight - bottomPadding - listTop;
|
|
8195
|
+
if (top < visibleTop)
|
|
8196
|
+
sidebar.scrollTop = Math.max(0, top + listTop - topPadding);
|
|
8197
|
+
else if (bottom > visibleBottom)
|
|
8198
|
+
sidebar.scrollTop = bottom + listTop - visibleHeight + bottomPadding;
|
|
8199
|
+
renderVirtualSidebarWindow();
|
|
8200
|
+
}
|
|
8201
|
+
function rerenderVirtualSidebar() {
|
|
8202
|
+
const ul = document.querySelector("#filelist");
|
|
8203
|
+
if (!ul?.classList.contains("tree-virtual"))
|
|
8204
|
+
return;
|
|
8205
|
+
computeVirtualSidebarVisibleRows();
|
|
8206
|
+
renderVirtualSidebarWindow();
|
|
8207
|
+
}
|
|
8208
|
+
function renderVirtualTreeSidebar(root) {
|
|
8209
|
+
const ul = $("#filelist");
|
|
8210
|
+
SIDEBAR_TREE_ROOT = root;
|
|
8211
|
+
buildSidebarTreeRows(root);
|
|
8212
|
+
ul.classList.add("tree-virtual");
|
|
8213
|
+
ul.style.position = "relative";
|
|
8214
|
+
computeVirtualSidebarVisibleRows();
|
|
8215
|
+
renderVirtualSidebarWindow();
|
|
8216
|
+
document.querySelector("#sidebar")?.addEventListener("scroll", renderVirtualSidebarWindow, {
|
|
8217
|
+
passive: true
|
|
8218
|
+
});
|
|
8219
|
+
}
|
|
7862
8220
|
function renderFlat(files, ul, onFileClick) {
|
|
7863
8221
|
files.forEach((f2, i2) => {
|
|
7864
8222
|
const li = document.createElement("li");
|
|
@@ -7897,6 +8255,13 @@ ${frontmatter.yaml}
|
|
|
7897
8255
|
const ul = $("#filelist");
|
|
7898
8256
|
ul.innerHTML = "";
|
|
7899
8257
|
ul.classList.toggle("tree", STATE.sbView === "tree");
|
|
8258
|
+
ul.classList.remove("tree-virtual");
|
|
8259
|
+
ul.style.removeProperty("height");
|
|
8260
|
+
ul.style.removeProperty("position");
|
|
8261
|
+
SIDEBAR_TREE_ROOT = null;
|
|
8262
|
+
SIDEBAR_TREE_ROWS = [];
|
|
8263
|
+
SIDEBAR_VISIBLE_ROWS = [];
|
|
8264
|
+
SIDEBAR_ROW_BY_PATH = new Map;
|
|
7900
8265
|
STATE.files = files;
|
|
7901
8266
|
SIDEBAR_FILES = files;
|
|
7902
8267
|
SIDEBAR_ON_FILE_CLICK = onFileClick;
|
|
@@ -7904,7 +8269,10 @@ ${frontmatter.yaml}
|
|
|
7904
8269
|
REPO_SIDEBAR_REF = null;
|
|
7905
8270
|
if (STATE.sbView === "tree") {
|
|
7906
8271
|
const root = buildTree(files);
|
|
7907
|
-
|
|
8272
|
+
if (onFileClick && files.length >= VIRTUAL_SIDEBAR_THRESHOLD)
|
|
8273
|
+
renderVirtualTreeSidebar(root);
|
|
8274
|
+
else
|
|
8275
|
+
renderTreeNode(root, 0, ul, onFileClick);
|
|
7908
8276
|
} else {
|
|
7909
8277
|
renderFlat(files, ul, onFileClick);
|
|
7910
8278
|
}
|
|
@@ -7922,6 +8290,17 @@ ${frontmatter.yaml}
|
|
|
7922
8290
|
function setAllSidebarDirsCollapsed(collapsed) {
|
|
7923
8291
|
if (!collapsed)
|
|
7924
8292
|
STATE.collapsedDirs.clear();
|
|
8293
|
+
if ($("#filelist").classList.contains("tree-virtual")) {
|
|
8294
|
+
if (collapsed) {
|
|
8295
|
+
for (const row of SIDEBAR_TREE_ROWS) {
|
|
8296
|
+
if (row.kind === "dir")
|
|
8297
|
+
STATE.collapsedDirs.add(row.path);
|
|
8298
|
+
}
|
|
8299
|
+
}
|
|
8300
|
+
localStorage.setItem("gdp:collapsed-dirs", JSON.stringify([...STATE.collapsedDirs]));
|
|
8301
|
+
rerenderVirtualSidebar();
|
|
8302
|
+
return;
|
|
8303
|
+
}
|
|
7925
8304
|
$$("#filelist .tree-dir[data-dirpath]").forEach((li) => {
|
|
7926
8305
|
const path = li.dataset.dirpath || "";
|
|
7927
8306
|
if (!path)
|
|
@@ -8098,29 +8477,32 @@ ${frontmatter.yaml}
|
|
|
8098
8477
|
}
|
|
8099
8478
|
if (changed)
|
|
8100
8479
|
localStorage.setItem("gdp:collapsed-dirs", JSON.stringify([...STATE.collapsedDirs]));
|
|
8480
|
+
rerenderVirtualSidebar();
|
|
8101
8481
|
}
|
|
8102
8482
|
function markActive(path, options = {}) {
|
|
8103
8483
|
STATE.activeFile = path;
|
|
8484
|
+
SIDEBAR_VIRTUAL_ACTIVE_PATH = path;
|
|
8104
8485
|
if (options.reveal && STATE.sbView === "tree")
|
|
8105
8486
|
expandSidebarAncestors(path);
|
|
8106
|
-
|
|
8107
|
-
|
|
8108
|
-
|
|
8109
|
-
|
|
8110
|
-
|
|
8487
|
+
setActiveSidebarItem(sidebarItemByPath(path));
|
|
8488
|
+
if ($("#filelist").classList.contains("tree-virtual")) {
|
|
8489
|
+
renderVirtualSidebarWindow();
|
|
8490
|
+
scrollVirtualSidebarPathIntoView(path);
|
|
8491
|
+
return;
|
|
8492
|
+
}
|
|
8111
8493
|
if (options.reveal) {
|
|
8112
|
-
const active =
|
|
8494
|
+
const active = activeSidebarItem();
|
|
8113
8495
|
if (active)
|
|
8114
8496
|
requestAnimationFrame(() => scrollSidebarItemIntoView(active));
|
|
8115
8497
|
}
|
|
8116
8498
|
}
|
|
8117
8499
|
function applyViewedState() {
|
|
8500
|
+
if (isRepositorySidebarMode())
|
|
8501
|
+
return;
|
|
8118
8502
|
$$("#filelist li[data-path]").forEach((li) => {
|
|
8119
8503
|
const path = li.dataset.path || "";
|
|
8120
|
-
li.classList.toggle("viewed",
|
|
8504
|
+
li.classList.toggle("viewed", STATE.viewedFiles.has(path));
|
|
8121
8505
|
});
|
|
8122
|
-
if (isRepositorySidebarMode())
|
|
8123
|
-
return;
|
|
8124
8506
|
$$(".gdp-file-shell[data-path]").forEach((card) => {
|
|
8125
8507
|
const path = card.dataset.path || "";
|
|
8126
8508
|
const viewed = STATE.viewedFiles.has(path);
|
|
@@ -8129,11 +8511,16 @@ ${frontmatter.yaml}
|
|
|
8129
8511
|
}
|
|
8130
8512
|
function applyFilter() {
|
|
8131
8513
|
const input = $("#sb-filter");
|
|
8514
|
+
if ($("#filelist").classList.contains("tree-virtual")) {
|
|
8515
|
+
rerenderVirtualSidebar();
|
|
8516
|
+
return;
|
|
8517
|
+
}
|
|
8132
8518
|
const filter = compileFileFilter(input.value);
|
|
8133
8519
|
const invalid = filter.kind === "invalid";
|
|
8134
8520
|
input.toggleAttribute("aria-invalid", invalid);
|
|
8135
8521
|
input.title = invalid ? filter.error || "invalid regular expression" : "";
|
|
8136
8522
|
const matches = invalid ? () => true : filter.match;
|
|
8523
|
+
const filterActive = filter.kind !== "empty" && !invalid;
|
|
8137
8524
|
$$("#filelist li[data-path]").forEach((li) => {
|
|
8138
8525
|
const match2 = matches(li.dataset.path || "");
|
|
8139
8526
|
li.classList.toggle("hidden", !match2);
|
|
@@ -8144,21 +8531,51 @@ ${frontmatter.yaml}
|
|
|
8144
8531
|
card.classList.toggle("hidden-by-filter", !match2);
|
|
8145
8532
|
});
|
|
8146
8533
|
}
|
|
8147
|
-
updateTreeDirVisibility(matches,
|
|
8148
|
-
if (typeof applyViewedState === "function")
|
|
8534
|
+
updateTreeDirVisibility(matches, filterActive);
|
|
8535
|
+
if (!isRepositorySidebarMode() && typeof applyViewedState === "function")
|
|
8149
8536
|
applyViewedState();
|
|
8150
8537
|
}
|
|
8151
8538
|
function updateTreeDirVisibility(dirMatches, filterActive = false) {
|
|
8152
|
-
$$("#filelist .tree-dir")
|
|
8539
|
+
const dirs = $$("#filelist .tree-dir");
|
|
8540
|
+
for (let i2 = dirs.length - 1;i2 >= 0; i2--) {
|
|
8541
|
+
const dir = dirs[i2];
|
|
8153
8542
|
const childUl = dir.nextElementSibling;
|
|
8154
8543
|
if (!childUl?.classList.contains("tree-children"))
|
|
8155
|
-
|
|
8156
|
-
|
|
8544
|
+
continue;
|
|
8545
|
+
let anyVisible = false;
|
|
8546
|
+
for (const child of childUl.children) {
|
|
8547
|
+
if (!(child instanceof HTMLElement))
|
|
8548
|
+
continue;
|
|
8549
|
+
if (child.classList.contains("tree-file") && !child.classList.contains("hidden") && !child.classList.contains("hidden-by-tests")) {
|
|
8550
|
+
anyVisible = true;
|
|
8551
|
+
break;
|
|
8552
|
+
}
|
|
8553
|
+
if (child.classList.contains("tree-dir") && !child.classList.contains("hidden") && !child.classList.contains("hidden-by-tests")) {
|
|
8554
|
+
anyVisible = true;
|
|
8555
|
+
break;
|
|
8556
|
+
}
|
|
8557
|
+
}
|
|
8157
8558
|
const explicitVisible = dir.dataset.explicit === "true" && !filterActive;
|
|
8158
8559
|
const selfMatches = filterActive && !!dirMatches && dirMatches(dir.dataset.dirpath || "");
|
|
8159
8560
|
dir.classList.toggle("hidden", !anyVisible && !explicitVisible && !selfMatches);
|
|
8561
|
+
}
|
|
8562
|
+
}
|
|
8563
|
+
let SIDEBAR_FILTER_RAF = 0;
|
|
8564
|
+
function scheduleApplyFilter() {
|
|
8565
|
+
if (SIDEBAR_FILTER_RAF)
|
|
8566
|
+
cancelAnimationFrame(SIDEBAR_FILTER_RAF);
|
|
8567
|
+
SIDEBAR_FILTER_RAF = requestAnimationFrame(() => {
|
|
8568
|
+
SIDEBAR_FILTER_RAF = 0;
|
|
8569
|
+
applyFilter();
|
|
8160
8570
|
});
|
|
8161
8571
|
}
|
|
8572
|
+
function flushSidebarFilter() {
|
|
8573
|
+
if (!SIDEBAR_FILTER_RAF)
|
|
8574
|
+
return;
|
|
8575
|
+
cancelAnimationFrame(SIDEBAR_FILTER_RAF);
|
|
8576
|
+
SIDEBAR_FILTER_RAF = 0;
|
|
8577
|
+
applyFilter();
|
|
8578
|
+
}
|
|
8162
8579
|
let SERVER_GENERATION = 0;
|
|
8163
8580
|
let CLIENT_REQ_SEQ = 0;
|
|
8164
8581
|
const LOAD_QUEUE = [];
|
|
@@ -11705,8 +12122,97 @@ ${frontmatter.yaml}
|
|
|
11705
12122
|
}
|
|
11706
12123
|
return true;
|
|
11707
12124
|
}
|
|
12125
|
+
const SIDEBAR_ITEM_SELECTOR = "#filelist li[data-path], #filelist .tree-dir[data-dirpath]";
|
|
12126
|
+
const ACTIVE_SIDEBAR_ITEM_SELECTOR = "#filelist li.active[data-path], #filelist .tree-dir.active[data-dirpath]";
|
|
12127
|
+
function sidebarItemPath(item) {
|
|
12128
|
+
return item.dataset.path || item.dataset.dirpath || "";
|
|
12129
|
+
}
|
|
12130
|
+
function activeSidebarItem() {
|
|
12131
|
+
return document.querySelector(ACTIVE_SIDEBAR_ITEM_SELECTOR);
|
|
12132
|
+
}
|
|
12133
|
+
function sidebarItemByPath(path) {
|
|
12134
|
+
if (isVirtualSidebarActive() && SIDEBAR_ROW_BY_PATH.has(path)) {
|
|
12135
|
+
return document.querySelector(`#filelist li[data-path="${CSS.escape(path)}"], #filelist .tree-dir[data-dirpath="${CSS.escape(path)}"]`) || null;
|
|
12136
|
+
}
|
|
12137
|
+
const escaped = CSS.escape(path);
|
|
12138
|
+
return document.querySelector(`#filelist li[data-path="${escaped}"], #filelist .tree-dir[data-dirpath="${escaped}"]`);
|
|
12139
|
+
}
|
|
12140
|
+
function setActiveSidebarItem(target) {
|
|
12141
|
+
document.querySelectorAll(ACTIVE_SIDEBAR_ITEM_SELECTOR).forEach((item) => {
|
|
12142
|
+
if (item !== target)
|
|
12143
|
+
item.classList.remove("active");
|
|
12144
|
+
});
|
|
12145
|
+
target?.classList.add("active");
|
|
12146
|
+
}
|
|
11708
12147
|
function visibleSidebarItems() {
|
|
11709
|
-
return $$(
|
|
12148
|
+
return $$(SIDEBAR_ITEM_SELECTOR).filter(isSidebarRowVisible);
|
|
12149
|
+
}
|
|
12150
|
+
function isVirtualSidebarActive() {
|
|
12151
|
+
return $("#filelist").classList.contains("tree-virtual");
|
|
12152
|
+
}
|
|
12153
|
+
function virtualSidebarActiveIndex() {
|
|
12154
|
+
const activePath = SIDEBAR_VIRTUAL_ACTIVE_PATH || STATE.activeFile || "";
|
|
12155
|
+
return SIDEBAR_VISIBLE_ROWS.findIndex((row) => row.path === activePath);
|
|
12156
|
+
}
|
|
12157
|
+
function selectVirtualSidebarIndex(index, options) {
|
|
12158
|
+
if (!SIDEBAR_VISIBLE_ROWS.length)
|
|
12159
|
+
return null;
|
|
12160
|
+
const safeIndex = Math.max(0, Math.min(SIDEBAR_VISIBLE_ROWS.length - 1, index));
|
|
12161
|
+
const row = SIDEBAR_VISIBLE_ROWS[safeIndex];
|
|
12162
|
+
if (!row)
|
|
12163
|
+
return null;
|
|
12164
|
+
markActive(row.path);
|
|
12165
|
+
scrollVirtualSidebarPathIntoView(row.path);
|
|
12166
|
+
if (options?.open) {
|
|
12167
|
+
if (row.kind === "dir" && row.dir && SIDEBAR_ON_FILE_CLICK) {
|
|
12168
|
+
SIDEBAR_ON_FILE_CLICK({
|
|
12169
|
+
path: row.dir.path,
|
|
12170
|
+
display_path: row.dir.path,
|
|
12171
|
+
type: "tree",
|
|
12172
|
+
children_omitted: row.dir.children_omitted,
|
|
12173
|
+
children_omitted_reason: row.dir.children_omitted_reason
|
|
12174
|
+
});
|
|
12175
|
+
} else if (row.file && SIDEBAR_ON_FILE_CLICK) {
|
|
12176
|
+
SIDEBAR_ON_FILE_CLICK(row.file);
|
|
12177
|
+
}
|
|
12178
|
+
}
|
|
12179
|
+
return row;
|
|
12180
|
+
}
|
|
12181
|
+
function visibleSidebarItemFrom(current, direction) {
|
|
12182
|
+
const root = document.querySelector("#filelist");
|
|
12183
|
+
if (!current.isConnected)
|
|
12184
|
+
return null;
|
|
12185
|
+
if (!root)
|
|
12186
|
+
return null;
|
|
12187
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {
|
|
12188
|
+
acceptNode(node) {
|
|
12189
|
+
if (!(node instanceof HTMLElement))
|
|
12190
|
+
return NodeFilter.FILTER_SKIP;
|
|
12191
|
+
if (node.classList.contains("tree-children")) {
|
|
12192
|
+
const dir = node.previousElementSibling;
|
|
12193
|
+
if (dir?.classList.contains("collapsed") || dir?.classList.contains("hidden") || dir?.classList.contains("hidden-by-tests"))
|
|
12194
|
+
return NodeFilter.FILTER_REJECT;
|
|
12195
|
+
}
|
|
12196
|
+
if (!node.matches(SIDEBAR_ITEM_SELECTOR))
|
|
12197
|
+
return NodeFilter.FILTER_SKIP;
|
|
12198
|
+
return isSidebarRowVisible(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
|
|
12199
|
+
}
|
|
12200
|
+
});
|
|
12201
|
+
walker.currentNode = current;
|
|
12202
|
+
const next = direction === 1 ? walker.nextNode() : walker.previousNode();
|
|
12203
|
+
return next instanceof HTMLElement ? next : null;
|
|
12204
|
+
}
|
|
12205
|
+
function adjacentVisibleSidebarItem(direction) {
|
|
12206
|
+
const active = activeSidebarItem();
|
|
12207
|
+
if (!active) {
|
|
12208
|
+
const items = visibleSidebarItems();
|
|
12209
|
+
return direction === 1 ? items[0] || null : items[items.length - 1] || null;
|
|
12210
|
+
}
|
|
12211
|
+
if (!isSidebarRowVisible(active)) {
|
|
12212
|
+
const items = visibleSidebarItems();
|
|
12213
|
+
return direction === 1 ? items[0] || null : items[items.length - 1] || null;
|
|
12214
|
+
}
|
|
12215
|
+
return visibleSidebarItemFrom(active, direction) || active;
|
|
11710
12216
|
}
|
|
11711
12217
|
function scrollSidebarItemIntoView(item, block2 = "nearest") {
|
|
11712
12218
|
const sidebar = document.querySelector("#sidebar");
|
|
@@ -11738,6 +12244,14 @@ ${frontmatter.yaml}
|
|
|
11738
12244
|
return document.body.classList.contains("gdp-repo-page") || document.body.classList.contains("gdp-repo-blob-page");
|
|
11739
12245
|
}
|
|
11740
12246
|
function moveActiveSidebarItem(direction) {
|
|
12247
|
+
if (isVirtualSidebarActive()) {
|
|
12248
|
+
const current2 = virtualSidebarActiveIndex();
|
|
12249
|
+
const start = current2 < 0 ? direction === 1 ? 0 : SIDEBAR_VISIBLE_ROWS.length - 1 : current2 + direction;
|
|
12250
|
+
const row = selectVirtualSidebarIndex(start);
|
|
12251
|
+
if (row?.file)
|
|
12252
|
+
prefetchByPath(row.file.path);
|
|
12253
|
+
return;
|
|
12254
|
+
}
|
|
11741
12255
|
const items = visibleSidebarItems();
|
|
11742
12256
|
if (!items.length)
|
|
11743
12257
|
return;
|
|
@@ -11754,6 +12268,16 @@ ${frontmatter.yaml}
|
|
|
11754
12268
|
prefetchByPath(target.dataset.path);
|
|
11755
12269
|
}
|
|
11756
12270
|
function moveActiveSidebarPage(direction) {
|
|
12271
|
+
if (isVirtualSidebarActive()) {
|
|
12272
|
+
const sidebar2 = document.querySelector("#sidebar");
|
|
12273
|
+
const halfPageRows2 = Math.max(1, Math.floor((sidebar2?.clientHeight || window.innerHeight) / 2 / VIRTUAL_SIDEBAR_ROW_HEIGHT));
|
|
12274
|
+
const current2 = virtualSidebarActiveIndex();
|
|
12275
|
+
const start2 = current2 < 0 ? 0 : current2;
|
|
12276
|
+
const row = selectVirtualSidebarIndex(start2 + direction * halfPageRows2);
|
|
12277
|
+
if (row?.file)
|
|
12278
|
+
prefetchByPath(row.file.path);
|
|
12279
|
+
return;
|
|
12280
|
+
}
|
|
11757
12281
|
const items = visibleSidebarItems();
|
|
11758
12282
|
if (!items.length)
|
|
11759
12283
|
return;
|
|
@@ -11776,6 +12300,12 @@ ${frontmatter.yaml}
|
|
|
11776
12300
|
prefetchByPath(target.dataset.path);
|
|
11777
12301
|
}
|
|
11778
12302
|
function moveActiveSidebarToEdge(edge) {
|
|
12303
|
+
if (isVirtualSidebarActive()) {
|
|
12304
|
+
const row = selectVirtualSidebarIndex(edge === "top" ? 0 : SIDEBAR_VISIBLE_ROWS.length - 1);
|
|
12305
|
+
if (row?.file)
|
|
12306
|
+
prefetchByPath(row.file.path);
|
|
12307
|
+
return;
|
|
12308
|
+
}
|
|
11779
12309
|
const items = visibleSidebarItems();
|
|
11780
12310
|
const repoSidebar = isRepositorySidebarMode();
|
|
11781
12311
|
const target = edge === "top" ? items[0] : items[items.length - 1];
|
|
@@ -11791,6 +12321,21 @@ ${frontmatter.yaml}
|
|
|
11791
12321
|
prefetchByPath(target.dataset.path);
|
|
11792
12322
|
}
|
|
11793
12323
|
function setActiveSidebarDirectoryCollapsed(collapsed) {
|
|
12324
|
+
if (isVirtualSidebarActive()) {
|
|
12325
|
+
const row = SIDEBAR_VISIBLE_ROWS[virtualSidebarActiveIndex()];
|
|
12326
|
+
if (row?.kind !== "dir" || !row.dir || row.dir.children_omitted)
|
|
12327
|
+
return;
|
|
12328
|
+
if (STATE.collapsedDirs.has(row.path) === collapsed)
|
|
12329
|
+
return;
|
|
12330
|
+
if (collapsed)
|
|
12331
|
+
STATE.collapsedDirs.add(row.path);
|
|
12332
|
+
else
|
|
12333
|
+
STATE.collapsedDirs.delete(row.path);
|
|
12334
|
+
localStorage.setItem("gdp:collapsed-dirs", JSON.stringify([...STATE.collapsedDirs]));
|
|
12335
|
+
rerenderVirtualSidebar();
|
|
12336
|
+
scrollVirtualSidebarPathIntoView(row.path);
|
|
12337
|
+
return;
|
|
12338
|
+
}
|
|
11794
12339
|
const active = document.querySelector("#filelist .tree-dir.active[data-dirpath]");
|
|
11795
12340
|
if (!active)
|
|
11796
12341
|
return;
|
|
@@ -11801,6 +12346,13 @@ ${frontmatter.yaml}
|
|
|
11801
12346
|
control.click();
|
|
11802
12347
|
}
|
|
11803
12348
|
function toggleActiveSidebarDirectoryCollapsed() {
|
|
12349
|
+
if (isVirtualSidebarActive()) {
|
|
12350
|
+
const row = SIDEBAR_VISIBLE_ROWS[virtualSidebarActiveIndex()];
|
|
12351
|
+
if (row?.kind !== "dir" || !row.dir || row.dir.children_omitted)
|
|
12352
|
+
return;
|
|
12353
|
+
setActiveSidebarDirectoryCollapsed(!STATE.collapsedDirs.has(row.path));
|
|
12354
|
+
return;
|
|
12355
|
+
}
|
|
11804
12356
|
const active = document.querySelector("#filelist .tree-dir.active[data-dirpath]");
|
|
11805
12357
|
if (!active)
|
|
11806
12358
|
return;
|
|
@@ -11809,11 +12361,23 @@ ${frontmatter.yaml}
|
|
|
11809
12361
|
control.click();
|
|
11810
12362
|
}
|
|
11811
12363
|
function openActiveSidebarItem() {
|
|
12364
|
+
if (isVirtualSidebarActive()) {
|
|
12365
|
+
const index = virtualSidebarActiveIndex();
|
|
12366
|
+
if (index >= 0)
|
|
12367
|
+
selectVirtualSidebarIndex(index, { open: true });
|
|
12368
|
+
return;
|
|
12369
|
+
}
|
|
11812
12370
|
const active = document.querySelector("#filelist li.active[data-path], #filelist .tree-dir.active[data-dirpath]");
|
|
11813
12371
|
if (active && isSidebarRowVisible(active))
|
|
11814
12372
|
active.click();
|
|
11815
12373
|
}
|
|
11816
12374
|
function jumpToActiveOrFirstFilteredItem() {
|
|
12375
|
+
if (isVirtualSidebarActive()) {
|
|
12376
|
+
const current = virtualSidebarActiveIndex();
|
|
12377
|
+
selectVirtualSidebarIndex(current >= 0 ? current : 0, { open: true });
|
|
12378
|
+
$("#sb-filter").blur();
|
|
12379
|
+
return;
|
|
12380
|
+
}
|
|
11817
12381
|
const items = visibleSidebarItems();
|
|
11818
12382
|
const active = items.find((li) => li.classList.contains("active"));
|
|
11819
12383
|
const target = active || items[0];
|
|
@@ -11824,17 +12388,20 @@ ${frontmatter.yaml}
|
|
|
11824
12388
|
}
|
|
11825
12389
|
const sbFilter = $("#sb-filter");
|
|
11826
12390
|
if (sbFilter) {
|
|
11827
|
-
sbFilter.addEventListener("input", () =>
|
|
12391
|
+
sbFilter.addEventListener("input", () => scheduleApplyFilter());
|
|
11828
12392
|
sbFilter.addEventListener("keydown", (e2) => {
|
|
11829
12393
|
if (e2.key === "Enter") {
|
|
11830
12394
|
e2.preventDefault();
|
|
12395
|
+
flushSidebarFilter();
|
|
11831
12396
|
jumpToActiveOrFirstFilteredItem();
|
|
11832
12397
|
} else if (e2.key === "ArrowDown" || e2.key === "ArrowUp") {
|
|
11833
12398
|
e2.preventDefault();
|
|
12399
|
+
flushSidebarFilter();
|
|
11834
12400
|
moveActiveSidebarItem(e2.key === "ArrowDown" ? 1 : -1);
|
|
11835
12401
|
} else if (e2.key === "Escape") {
|
|
11836
12402
|
if (sbFilter.value) {
|
|
11837
12403
|
sbFilter.value = "";
|
|
12404
|
+
flushSidebarFilter();
|
|
11838
12405
|
applyFilter();
|
|
11839
12406
|
} else {
|
|
11840
12407
|
sbFilter.blur();
|
|
@@ -12322,16 +12889,24 @@ ${frontmatter.yaml}
|
|
|
12322
12889
|
}
|
|
12323
12890
|
if (action === "sidebar-next" || action === "sidebar-previous") {
|
|
12324
12891
|
const repoSidebar = isRepositorySidebarMode();
|
|
12325
|
-
const
|
|
12326
|
-
|
|
12892
|
+
const direction = action === "sidebar-next" ? 1 : -1;
|
|
12893
|
+
const diffItems = repoSidebar ? [] : $$("#filelist li[data-path]:not(.hidden):not(.hidden-by-tests)");
|
|
12894
|
+
let diffIndex = diffItems.findIndex((li) => li.classList.contains("active"));
|
|
12895
|
+
if (!repoSidebar)
|
|
12896
|
+
diffIndex = diffIndex < 0 ? 0 : Math.max(0, Math.min(diffItems.length - 1, diffIndex + direction));
|
|
12897
|
+
const target = repoSidebar ? isVirtualSidebarActive() ? null : adjacentVisibleSidebarItem(direction) : diffItems[diffIndex];
|
|
12898
|
+
if (repoSidebar && isVirtualSidebarActive()) {
|
|
12899
|
+
const current = virtualSidebarActiveIndex();
|
|
12900
|
+
const start = current < 0 ? direction === 1 ? 0 : SIDEBAR_VISIBLE_ROWS.length - 1 : current + direction;
|
|
12901
|
+
const row = selectVirtualSidebarIndex(start);
|
|
12902
|
+
const next = row ? SIDEBAR_VISIBLE_ROWS[Math.max(0, Math.min(SIDEBAR_VISIBLE_ROWS.length - 1, SIDEBAR_VISIBLE_ROWS.indexOf(row) + direction))] : null;
|
|
12903
|
+
if (!repeated && next?.file)
|
|
12904
|
+
prefetchByPath(next.file.path);
|
|
12327
12905
|
return true;
|
|
12328
|
-
|
|
12329
|
-
if (
|
|
12330
|
-
|
|
12331
|
-
|
|
12332
|
-
idx = action === "sidebar-next" ? Math.min(items.length - 1, idx + 1) : Math.max(0, idx - 1);
|
|
12333
|
-
const target = items[idx];
|
|
12334
|
-
const path = target?.dataset.path || target?.dataset.dirpath;
|
|
12906
|
+
}
|
|
12907
|
+
if (!target)
|
|
12908
|
+
return true;
|
|
12909
|
+
const path = sidebarItemPath(target);
|
|
12335
12910
|
if (!repoSidebar && target) {
|
|
12336
12911
|
target.click();
|
|
12337
12912
|
scrollSidebarItemIntoView(target);
|
|
@@ -12339,9 +12914,8 @@ ${frontmatter.yaml}
|
|
|
12339
12914
|
markActive(path);
|
|
12340
12915
|
scrollSidebarItemIntoView(target);
|
|
12341
12916
|
}
|
|
12342
|
-
const
|
|
12343
|
-
|
|
12344
|
-
if (nextItem && nextItem !== target && nextItem.dataset.path)
|
|
12917
|
+
const nextItem = repoSidebar ? visibleSidebarItemFrom(target, direction) : diffItems[Math.max(0, Math.min(diffItems.length - 1, diffIndex + direction))];
|
|
12918
|
+
if (!repeated && nextItem && nextItem !== target && nextItem.dataset.path)
|
|
12345
12919
|
prefetchByPath(nextItem.dataset.path);
|
|
12346
12920
|
return true;
|
|
12347
12921
|
}
|
|
@@ -12846,7 +13420,6 @@ ${frontmatter.yaml}
|
|
|
12846
13420
|
if (e2.key === "gdp:syntax-highlight")
|
|
12847
13421
|
setSyntaxHighlight(e2.newValue !== "0");
|
|
12848
13422
|
});
|
|
12849
|
-
const TEST_RE = /(^|[/_.])(test|spec|__tests__)([/_.]|$)/i;
|
|
12850
13423
|
function applyHideTests() {
|
|
12851
13424
|
const btn = $("#hide-tests");
|
|
12852
13425
|
if (btn)
|
|
@@ -12859,7 +13432,10 @@ ${frontmatter.yaml}
|
|
|
12859
13432
|
const isTest = TEST_RE.test(li.dataset.path || "");
|
|
12860
13433
|
li.classList.toggle("hidden-by-tests", STATE.hideTests && isTest);
|
|
12861
13434
|
});
|
|
12862
|
-
|
|
13435
|
+
if (isVirtualSidebarActive())
|
|
13436
|
+
rerenderVirtualSidebar();
|
|
13437
|
+
else
|
|
13438
|
+
updateTreeDirVisibility();
|
|
12863
13439
|
if (typeof applyViewedState === "function")
|
|
12864
13440
|
applyViewedState();
|
|
12865
13441
|
}
|
package/web/style.css
CHANGED
|
@@ -1352,6 +1352,16 @@ body.gdp-help-page #content {
|
|
|
1352
1352
|
#filelist.tree {
|
|
1353
1353
|
padding: 4px 0 0;
|
|
1354
1354
|
}
|
|
1355
|
+
#filelist.tree.tree-virtual {
|
|
1356
|
+
padding: 0;
|
|
1357
|
+
}
|
|
1358
|
+
#filelist.tree.tree-virtual .tree-dir,
|
|
1359
|
+
#filelist.tree.tree-virtual .tree-file {
|
|
1360
|
+
height: 29px;
|
|
1361
|
+
min-height: 29px;
|
|
1362
|
+
overflow: hidden;
|
|
1363
|
+
box-sizing: border-box;
|
|
1364
|
+
}
|
|
1355
1365
|
#filelist.tree .tree-dir {
|
|
1356
1366
|
display: grid;
|
|
1357
1367
|
grid-template-columns: 16px 16px minmax(0, 1fr) 22px;
|
|
@@ -2958,26 +2968,33 @@ body.gdp-file-detail-page.gdp-repo-blob-page #sidebar-resizer {
|
|
|
2958
2968
|
body.gdp-repo-page #sidebar-resizer {
|
|
2959
2969
|
display: block;
|
|
2960
2970
|
}
|
|
2961
|
-
body.gdp-file-detail-page.gdp-repo-blob-page .sb-title,
|
|
2962
|
-
body.gdp-file-detail-page.gdp-repo-blob-page #totals,
|
|
2963
|
-
body.gdp-repo-page .sb-title,
|
|
2964
|
-
body.gdp-repo-page #totals {
|
|
2965
|
-
display: none;
|
|
2966
|
-
}
|
|
2967
2971
|
body.gdp-repo-page .sb-head,
|
|
2968
2972
|
body.gdp-file-detail-page.gdp-repo-blob-page .sb-head {
|
|
2969
2973
|
display: grid;
|
|
2970
2974
|
grid-template:
|
|
2971
|
-
"toggle
|
|
2972
|
-
|
|
2973
|
-
|
|
2975
|
+
"toggle title totals ." auto
|
|
2976
|
+
"ref ref ref ref" auto
|
|
2977
|
+
"actions actions . view" auto
|
|
2978
|
+
"filter filter filter filter" auto
|
|
2979
|
+
/ 28px auto minmax(0, 1fr) auto;
|
|
2980
|
+
justify-content: stretch;
|
|
2974
2981
|
align-items: center;
|
|
2975
2982
|
gap: 8px;
|
|
2983
|
+
top: var(--global-header-h);
|
|
2984
|
+
z-index: 5;
|
|
2976
2985
|
}
|
|
2977
2986
|
body.gdp-repo-page .sb-head > #sidebar-toggle,
|
|
2978
2987
|
body.gdp-file-detail-page.gdp-repo-blob-page .sb-head > #sidebar-toggle {
|
|
2979
2988
|
grid-area: toggle;
|
|
2980
2989
|
}
|
|
2990
|
+
body.gdp-repo-page .sb-title,
|
|
2991
|
+
body.gdp-file-detail-page.gdp-repo-blob-page .sb-title {
|
|
2992
|
+
grid-area: title;
|
|
2993
|
+
}
|
|
2994
|
+
body.gdp-repo-page #totals,
|
|
2995
|
+
body.gdp-file-detail-page.gdp-repo-blob-page #totals {
|
|
2996
|
+
grid-area: totals;
|
|
2997
|
+
}
|
|
2981
2998
|
body.gdp-repo-page #repo-target-wrap,
|
|
2982
2999
|
body.gdp-file-detail-page.gdp-repo-blob-page #repo-target-wrap {
|
|
2983
3000
|
grid-area: ref;
|
|
@@ -2986,10 +3003,22 @@ body.gdp-file-detail-page.gdp-repo-blob-page #repo-target-wrap {
|
|
|
2986
3003
|
body.gdp-repo-page .sb-actions,
|
|
2987
3004
|
body.gdp-file-detail-page.gdp-repo-blob-page .sb-actions {
|
|
2988
3005
|
grid-area: actions;
|
|
3006
|
+
margin-left: 0;
|
|
3007
|
+
justify-self: start;
|
|
2989
3008
|
}
|
|
2990
3009
|
body.gdp-repo-page .sb-view-seg,
|
|
2991
3010
|
body.gdp-file-detail-page.gdp-repo-blob-page .sb-view-seg {
|
|
2992
3011
|
grid-area: view;
|
|
3012
|
+
margin-left: auto;
|
|
3013
|
+
}
|
|
3014
|
+
body.gdp-repo-page .sb-filter-wrap,
|
|
3015
|
+
body.gdp-file-detail-page.gdp-repo-blob-page .sb-filter-wrap {
|
|
3016
|
+
grid-area: filter;
|
|
3017
|
+
position: static;
|
|
3018
|
+
width: 100%;
|
|
3019
|
+
margin: 0;
|
|
3020
|
+
padding: 6px 0 0;
|
|
3021
|
+
border-bottom: 0;
|
|
2993
3022
|
}
|
|
2994
3023
|
body.gdp-file-detail-page {
|
|
2995
3024
|
--chrome-h: var(--global-header-h);
|