@youtyan/code-viewer 0.1.13 → 0.1.15
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 +9 -0
- package/package.json +1 -1
- package/web/app.js +451 -106
- package/web/index.html +45 -8
- package/web/style.css +405 -78
- package/web-src/server/git.ts +117 -59
- package/web-src/server/preview.ts +113 -33
- package/web-src/server/search.ts +10 -7
- package/web-src/types.ts +10 -0
package/web/app.js
CHANGED
|
@@ -6746,8 +6746,25 @@
|
|
|
6746
6746
|
];
|
|
6747
6747
|
const FILE_16_PATH = "M2 1.75C2 .784 2.784 0 3.75 0h5.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 12.25 16h-8.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 8 4.25V1.5Zm5.75.062V4.25c0 .138.112.25.25.25h2.688Z";
|
|
6748
6748
|
const OPEN_EXTERNAL_16_PATH = "M3.75 2A1.75 1.75 0 0 0 2 3.75v8.5C2 13.216 2.784 14 3.75 14h8.5A1.75 1.75 0 0 0 14 12.25v-3.5a.75.75 0 0 0-1.5 0v3.5a.25.25 0 0 1-.25.25h-8.5a.25.25 0 0 1-.25-.25v-8.5a.25.25 0 0 1 .25-.25h3.5a.75.75 0 0 0 0-1.5h-3.5Zm6.5 0a.75.75 0 0 0 0 1.5h1.19L7.72 7.22a.749.749 0 1 0 1.06 1.06l3.72-3.72v1.19a.75.75 0 0 0 1.5 0v-3A.75.75 0 0 0 13.25 2h-3Z";
|
|
6749
|
-
const
|
|
6750
|
-
const
|
|
6749
|
+
const GIT_BRANCH_16_PATH = "M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z";
|
|
6750
|
+
const TRIANGLE_DOWN_16_PATH = "m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z";
|
|
6751
|
+
const SIDEBAR_SHOW_16_PATHS = [
|
|
6752
|
+
"M6.823 7.823a.25.25 0 0 1 0 .354l-2.396 2.396A.25.25 0 0 1 4 10.396V5.604a.25.25 0 0 1 .427-.177Z",
|
|
6753
|
+
"M1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0ZM1.5 1.75v12.5c0 .138.112.25.25.25H9.5v-13H1.75a.25.25 0 0 0-.25.25ZM11 14.5h3.25a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25H11Z"
|
|
6754
|
+
];
|
|
6755
|
+
const SIDEBAR_HIDE_16_PATHS = [
|
|
6756
|
+
"m4.177 7.823 2.396-2.396A.25.25 0 0 1 7 5.604v4.792a.25.25 0 0 1-.427.177L4.177 8.177a.25.25 0 0 1 0-.354Z",
|
|
6757
|
+
"M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25H9.5v-13Zm12.5 13a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25H11v13Z"
|
|
6758
|
+
];
|
|
6759
|
+
const GEAR_16_PATH = "M8 0a8.2 8.2 0 0 1 1.7.18.75.75 0 0 1 .6.86l-.14.93c.23.1.45.21.67.34l.73-.6a.75.75 0 0 1 1.03.08c.47.37.89.78 1.23 1.23a.75.75 0 0 1 .07 1.03l-.59.73c.13.22.24.44.34.67l.93-.14a.75.75 0 0 1 .86.6c.12.55.18 1.12.18 1.7s-.06 1.15-.18 1.7a.75.75 0 0 1-.86.6l-.93-.14c-.1.23-.21.45-.34.67l.59.73a.75.75 0 0 1-.07 1.03c-.34.45-.76.86-1.23 1.23a.75.75 0 0 1-1.03.08l-.73-.6c-.22.13-.44.24-.67.34l.14.93a.75.75 0 0 1-.6.86A8.2 8.2 0 0 1 8 16a8.2 8.2 0 0 1-1.7-.18.75.75 0 0 1-.6-.86l.14-.93a5.9 5.9 0 0 1-.67-.34l-.73.6a.75.75 0 0 1-1.03-.08 8.1 8.1 0 0 1-1.23-1.23.75.75 0 0 1-.07-1.03l.59-.73a5.9 5.9 0 0 1-.34-.67l-.93.14a.75.75 0 0 1-.86-.6A8.2 8.2 0 0 1 0 8c0-.58.06-1.15.18-1.7a.75.75 0 0 1 .86-.6l.93.14c.1-.23.21-.45.34-.67l-.59-.73a.75.75 0 0 1 .07-1.03 8.1 8.1 0 0 1 1.23-1.23.75.75 0 0 1 1.03-.08l.73.6c.22-.13.44-.24.67-.34l-.14-.93a.75.75 0 0 1 .6-.86A8.2 8.2 0 0 1 8 0Zm0 5a3 3 0 1 0 0 6 3 3 0 0 0 0-6Z";
|
|
6760
|
+
const EXPAND_ALL_16_PATHS = [
|
|
6761
|
+
"M3.22 4.47a.75.75 0 0 1 1.06 0L8 8.19l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L3.22 5.53a.75.75 0 0 1 0-1.06Z",
|
|
6762
|
+
"M3.22 8.47a.75.75 0 0 1 1.06 0L8 12.19l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L3.22 9.53a.75.75 0 0 1 0-1.06Z"
|
|
6763
|
+
];
|
|
6764
|
+
const COLLAPSE_ALL_16_PATHS = [
|
|
6765
|
+
"M7.47 2.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 1 1-1.06 1.06L8 3.81 4.28 7.53a.75.75 0 0 1-1.06-1.06Z",
|
|
6766
|
+
"M7.47 6.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 1 1-1.06 1.06L8 7.81l-3.72 3.72a.75.75 0 1 1-1.06-1.06Z"
|
|
6767
|
+
];
|
|
6751
6768
|
const $ = (sel) => document.querySelector(sel);
|
|
6752
6769
|
const $$ = (sel) => Array.from(document.querySelectorAll(sel));
|
|
6753
6770
|
const diffCardSelector = (path) => '.gdp-file-shell[data-path="' + (window.CSS && CSS.escape ? CSS.escape(path) : path) + '"]';
|
|
@@ -6764,12 +6781,46 @@
|
|
|
6764
6781
|
let REPO_SIDEBAR_REF = null;
|
|
6765
6782
|
let REPO_SIDEBAR_LOAD_REF = null;
|
|
6766
6783
|
let REPO_SIDEBAR_LOAD = null;
|
|
6784
|
+
let SIDEBAR_FILES = [];
|
|
6785
|
+
let SIDEBAR_ON_FILE_CLICK;
|
|
6786
|
+
let SERVER_SCOPE_OMIT_DIRS_DEFAULT = [];
|
|
6767
6787
|
let PENDING_G_SCOPE = null;
|
|
6768
6788
|
let PENDING_G_UNTIL = 0;
|
|
6769
6789
|
let SOURCE_CURSOR = null;
|
|
6770
6790
|
const SOURCE_CURSOR_TOTALS = new Map;
|
|
6771
6791
|
const HELP_LANGUAGES = ["en", "ja"];
|
|
6772
6792
|
const HELP_SECTIONS = ["keybindings"];
|
|
6793
|
+
const SCOPE_OMIT_DIRS_STORAGE_KEY_PREFIX = "gdp:scope-omit-dirs:";
|
|
6794
|
+
const SIDEBAR_FONT_SIZE_STORAGE_KEY = "gdp:sidebar-font-size";
|
|
6795
|
+
const CODE_FONT_SIZE_STORAGE_KEY = "gdp:code-font-size";
|
|
6796
|
+
const CLIENT_SCOPE_OMIT_DIRS_DEFAULT = [
|
|
6797
|
+
"node_modules",
|
|
6798
|
+
".venv",
|
|
6799
|
+
"venv",
|
|
6800
|
+
".next",
|
|
6801
|
+
".nuxt",
|
|
6802
|
+
".svelte-kit",
|
|
6803
|
+
".astro",
|
|
6804
|
+
".vercel",
|
|
6805
|
+
"dist",
|
|
6806
|
+
"build",
|
|
6807
|
+
"out",
|
|
6808
|
+
"target",
|
|
6809
|
+
".gradle",
|
|
6810
|
+
"__pycache__",
|
|
6811
|
+
".pytest_cache",
|
|
6812
|
+
".tox",
|
|
6813
|
+
".terraform",
|
|
6814
|
+
".idea",
|
|
6815
|
+
".vscode",
|
|
6816
|
+
"vendor",
|
|
6817
|
+
".cache",
|
|
6818
|
+
"coverage",
|
|
6819
|
+
"DerivedData",
|
|
6820
|
+
"Pods",
|
|
6821
|
+
"bin",
|
|
6822
|
+
"obj"
|
|
6823
|
+
];
|
|
6773
6824
|
const HELP_CONTENT = {
|
|
6774
6825
|
en: {
|
|
6775
6826
|
languageLabel: "Language",
|
|
@@ -6940,6 +6991,90 @@
|
|
|
6940
6991
|
REPO_SIDEBAR_LOAD_REF = null;
|
|
6941
6992
|
REPO_SIDEBAR_LOAD = null;
|
|
6942
6993
|
}
|
|
6994
|
+
function normalizeScopeOmitDirs(value) {
|
|
6995
|
+
const raw = Array.isArray(value) ? value : value.split(/[\n,]+/);
|
|
6996
|
+
return [...new Set(raw.map((item) => item.trim()).filter((item) => item && item.length <= 64 && !item.includes("/") && !item.includes("\\") && item !== "." && item !== ".." && item !== ".git"))].slice(0, 100).sort((a2, b2) => a2.localeCompare(b2));
|
|
6997
|
+
}
|
|
6998
|
+
function scopeOmitDirsStorageKey() {
|
|
6999
|
+
return SCOPE_OMIT_DIRS_STORAGE_KEY_PREFIX + (PROJECT_NAME || "default");
|
|
7000
|
+
}
|
|
7001
|
+
function setProjectName(project) {
|
|
7002
|
+
if (!project)
|
|
7003
|
+
return;
|
|
7004
|
+
PROJECT_NAME = project;
|
|
7005
|
+
document.title = project + " - code viewer";
|
|
7006
|
+
}
|
|
7007
|
+
function savedScopeOmitDirs() {
|
|
7008
|
+
const raw = localStorage.getItem(scopeOmitDirsStorageKey());
|
|
7009
|
+
if (raw == null)
|
|
7010
|
+
return null;
|
|
7011
|
+
try {
|
|
7012
|
+
const parsed = JSON.parse(raw);
|
|
7013
|
+
return normalizeScopeOmitDirs(Array.isArray(parsed) ? parsed : []);
|
|
7014
|
+
} catch {
|
|
7015
|
+
return normalizeScopeOmitDirs(raw);
|
|
7016
|
+
}
|
|
7017
|
+
}
|
|
7018
|
+
function serverScopeOmitDirsDefault() {
|
|
7019
|
+
return SERVER_SCOPE_OMIT_DIRS_DEFAULT.length ? SERVER_SCOPE_OMIT_DIRS_DEFAULT : CLIENT_SCOPE_OMIT_DIRS_DEFAULT;
|
|
7020
|
+
}
|
|
7021
|
+
function effectiveScopeOmitDirs() {
|
|
7022
|
+
return savedScopeOmitDirs() ?? serverScopeOmitDirsDefault();
|
|
7023
|
+
}
|
|
7024
|
+
function appendScopeOmitDirsParam(params) {
|
|
7025
|
+
const saved = savedScopeOmitDirs();
|
|
7026
|
+
if (saved != null)
|
|
7027
|
+
params.set("omit_dirs", saved.join(","));
|
|
7028
|
+
}
|
|
7029
|
+
function normalizeViewerFontSize(value) {
|
|
7030
|
+
return value === "compact" || value === "large" || value === "xlarge" ? value : "regular";
|
|
7031
|
+
}
|
|
7032
|
+
function savedSidebarFontSize() {
|
|
7033
|
+
return normalizeViewerFontSize(localStorage.getItem(SIDEBAR_FONT_SIZE_STORAGE_KEY));
|
|
7034
|
+
}
|
|
7035
|
+
function savedCodeFontSize() {
|
|
7036
|
+
return normalizeViewerFontSize(localStorage.getItem(CODE_FONT_SIZE_STORAGE_KEY));
|
|
7037
|
+
}
|
|
7038
|
+
function applySidebarFontSize(size = savedSidebarFontSize()) {
|
|
7039
|
+
document.body.dataset.sidebarFontSize = size;
|
|
7040
|
+
}
|
|
7041
|
+
function applyCodeFontSize(size = savedCodeFontSize()) {
|
|
7042
|
+
document.body.dataset.codeFontSize = size;
|
|
7043
|
+
}
|
|
7044
|
+
function syncSidebarHeaderHeight() {
|
|
7045
|
+
requestAnimationFrame(() => {
|
|
7046
|
+
const head = document.querySelector(".sb-head");
|
|
7047
|
+
if (head)
|
|
7048
|
+
document.documentElement.style.setProperty("--sidebar-head-h", Math.ceil(head.getBoundingClientRect().height) + "px");
|
|
7049
|
+
});
|
|
7050
|
+
}
|
|
7051
|
+
function observeSidebarHeaderHeight() {
|
|
7052
|
+
const head = document.querySelector(".sb-head");
|
|
7053
|
+
if (!head || typeof ResizeObserver === "undefined") {
|
|
7054
|
+
syncSidebarHeaderHeight();
|
|
7055
|
+
return;
|
|
7056
|
+
}
|
|
7057
|
+
const observer = new ResizeObserver(syncSidebarHeaderHeight);
|
|
7058
|
+
observer.observe(head);
|
|
7059
|
+
syncSidebarHeaderHeight();
|
|
7060
|
+
}
|
|
7061
|
+
function repoFileCacheKey(ref) {
|
|
7062
|
+
const saved = savedScopeOmitDirs();
|
|
7063
|
+
return `${ref}\x00${saved ? saved.join("\x00") : "server"}`;
|
|
7064
|
+
}
|
|
7065
|
+
async function loadSettings() {
|
|
7066
|
+
try {
|
|
7067
|
+
const res = await fetch("/_settings");
|
|
7068
|
+
if (!res.ok)
|
|
7069
|
+
return null;
|
|
7070
|
+
const settings = await res.json();
|
|
7071
|
+
setProjectName(settings.project || "");
|
|
7072
|
+
SERVER_SCOPE_OMIT_DIRS_DEFAULT = normalizeScopeOmitDirs(settings.scope.omit_dirs_effective);
|
|
7073
|
+
return settings;
|
|
7074
|
+
} catch {
|
|
7075
|
+
return null;
|
|
7076
|
+
}
|
|
7077
|
+
}
|
|
6943
7078
|
function isRepoSidebarReusable(ref) {
|
|
6944
7079
|
return REPO_SIDEBAR_REF === (ref || "worktree") && isRepositorySidebarMode();
|
|
6945
7080
|
}
|
|
@@ -6956,6 +7091,7 @@
|
|
|
6956
7091
|
theme: localStorage.getItem("gdp:theme") || (matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"),
|
|
6957
7092
|
sbView: localStorage.getItem("gdp:sbview") || "tree",
|
|
6958
7093
|
sbWidth: parseInt(localStorage.getItem("gdp:sbwidth")) || 308,
|
|
7094
|
+
sidebarHidden: localStorage.getItem("gdp:sidebar-hidden") === "1",
|
|
6959
7095
|
collapsedDirs: new Set(JSON.parse(localStorage.getItem("gdp:collapsed-dirs") || "[]")),
|
|
6960
7096
|
ignoreWs: igRaw === null ? true : igRaw === "1",
|
|
6961
7097
|
from: route.range.from,
|
|
@@ -7210,15 +7346,112 @@
|
|
|
7210
7346
|
return;
|
|
7211
7347
|
button.setAttribute("aria-pressed", expanded ? "true" : "false");
|
|
7212
7348
|
button.title = expanded ? "Collapse expanded lines" : "Expand all lines";
|
|
7213
|
-
button.innerHTML = expanded ? iconSvg("octicon-fold",
|
|
7349
|
+
button.innerHTML = expanded ? iconSvg("octicon-fold", COLLAPSE_ALL_16_PATHS) : iconSvg("octicon-unfold", EXPAND_ALL_16_PATHS);
|
|
7214
7350
|
}
|
|
7215
7351
|
function setSidebarTreeActionIcons() {
|
|
7352
|
+
const settings = document.querySelector("#viewer-settings");
|
|
7353
|
+
const sidebarToggle = document.querySelector("#sidebar-toggle");
|
|
7216
7354
|
const expand = document.querySelector("#sb-expand-all");
|
|
7217
7355
|
const collapse = document.querySelector("#sb-collapse-all");
|
|
7356
|
+
if (settings)
|
|
7357
|
+
settings.innerHTML = iconSvg("octicon-gear", GEAR_16_PATH);
|
|
7358
|
+
if (sidebarToggle)
|
|
7359
|
+
sidebarToggle.innerHTML = iconSvg("octicon-sidebar", STATE.sidebarHidden ? SIDEBAR_SHOW_16_PATHS : SIDEBAR_HIDE_16_PATHS);
|
|
7218
7360
|
if (expand)
|
|
7219
|
-
expand.innerHTML = iconSvg("octicon-
|
|
7361
|
+
expand.innerHTML = iconSvg("octicon-chevron-down", EXPAND_ALL_16_PATHS);
|
|
7220
7362
|
if (collapse)
|
|
7221
|
-
collapse.innerHTML = iconSvg("octicon-
|
|
7363
|
+
collapse.innerHTML = iconSvg("octicon-chevron-up", COLLAPSE_ALL_16_PATHS);
|
|
7364
|
+
}
|
|
7365
|
+
function attachSidebarToggle(host) {
|
|
7366
|
+
const button = document.querySelector("#sidebar-toggle");
|
|
7367
|
+
if (!button || button.parentElement === host)
|
|
7368
|
+
return;
|
|
7369
|
+
host.prepend(button);
|
|
7370
|
+
}
|
|
7371
|
+
function placeSidebarToggle() {
|
|
7372
|
+
const sidebarHead = document.querySelector(".sb-head");
|
|
7373
|
+
const toolbar = document.querySelector(".gdp-repo-toolbar, .gdp-file-detail-header");
|
|
7374
|
+
const restoreHost = toolbar || document.querySelector("#topbar") || document.querySelector("#global-header");
|
|
7375
|
+
if (STATE.sidebarHidden && restoreHost)
|
|
7376
|
+
attachSidebarToggle(restoreHost);
|
|
7377
|
+
else if (sidebarHead)
|
|
7378
|
+
attachSidebarToggle(sidebarHead);
|
|
7379
|
+
}
|
|
7380
|
+
function applySidebarHidden(hidden = STATE.sidebarHidden) {
|
|
7381
|
+
STATE.sidebarHidden = hidden;
|
|
7382
|
+
document.body.classList.toggle("gdp-sidebar-hidden", hidden);
|
|
7383
|
+
localStorage.setItem("gdp:sidebar-hidden", hidden ? "1" : "0");
|
|
7384
|
+
const button = document.querySelector("#sidebar-toggle");
|
|
7385
|
+
if (button) {
|
|
7386
|
+
button.setAttribute("aria-pressed", hidden ? "true" : "false");
|
|
7387
|
+
button.title = hidden ? "show sidebar" : "hide sidebar";
|
|
7388
|
+
button.setAttribute("aria-label", hidden ? "show sidebar" : "hide sidebar");
|
|
7389
|
+
}
|
|
7390
|
+
setSidebarTreeActionIcons();
|
|
7391
|
+
placeSidebarToggle();
|
|
7392
|
+
syncSidebarHeaderHeight();
|
|
7393
|
+
}
|
|
7394
|
+
function toggleSidebarHidden() {
|
|
7395
|
+
applySidebarHidden(!STATE.sidebarHidden);
|
|
7396
|
+
}
|
|
7397
|
+
function scopeOmitSourceLabel() {
|
|
7398
|
+
return savedScopeOmitDirs() != null ? "Browser override" : "Server default";
|
|
7399
|
+
}
|
|
7400
|
+
function refreshRepositoryTreeAfterSettings() {
|
|
7401
|
+
REPO_FILE_CACHE.clear();
|
|
7402
|
+
invalidateRepoSidebar();
|
|
7403
|
+
if (STATE.route.screen === "repo") {
|
|
7404
|
+
loadRepo();
|
|
7405
|
+
return;
|
|
7406
|
+
}
|
|
7407
|
+
const target = sourceTargetFromRoute();
|
|
7408
|
+
if (target)
|
|
7409
|
+
renderRepoBlobSidebar(target.path, target.ref || "worktree");
|
|
7410
|
+
}
|
|
7411
|
+
async function openScopeSettings() {
|
|
7412
|
+
const pop = document.querySelector("#scope-settings-popover");
|
|
7413
|
+
const input = document.querySelector("#scope-omit-dirs");
|
|
7414
|
+
const sidebarFontSize = document.querySelector("#sidebar-font-size");
|
|
7415
|
+
const codeFontSize = document.querySelector("#code-font-size");
|
|
7416
|
+
const source = document.querySelector("#scope-omit-source");
|
|
7417
|
+
if (!pop || !input || !sidebarFontSize || !codeFontSize || !source)
|
|
7418
|
+
return;
|
|
7419
|
+
await loadSettings();
|
|
7420
|
+
sidebarFontSize.value = savedSidebarFontSize();
|
|
7421
|
+
codeFontSize.value = savedCodeFontSize();
|
|
7422
|
+
input.value = effectiveScopeOmitDirs().join(`
|
|
7423
|
+
`);
|
|
7424
|
+
source.textContent = 'Saved for project "' + (PROJECT_NAME || "default") + '" in this browser. Source: ' + scopeOmitSourceLabel() + ". Used by tree, Ctrl+K, and Ctrl+G. Reset removes the browser override.";
|
|
7425
|
+
pop.hidden = false;
|
|
7426
|
+
sidebarFontSize.focus();
|
|
7427
|
+
}
|
|
7428
|
+
function closeScopeSettings() {
|
|
7429
|
+
const pop = document.querySelector("#scope-settings-popover");
|
|
7430
|
+
if (pop)
|
|
7431
|
+
pop.hidden = true;
|
|
7432
|
+
}
|
|
7433
|
+
function saveScopeSettings() {
|
|
7434
|
+
const input = document.querySelector("#scope-omit-dirs");
|
|
7435
|
+
const sidebarFontSize = document.querySelector("#sidebar-font-size");
|
|
7436
|
+
const codeFontSize = document.querySelector("#code-font-size");
|
|
7437
|
+
if (!input || !sidebarFontSize || !codeFontSize)
|
|
7438
|
+
return;
|
|
7439
|
+
localStorage.setItem(SIDEBAR_FONT_SIZE_STORAGE_KEY, normalizeViewerFontSize(sidebarFontSize.value));
|
|
7440
|
+
localStorage.setItem(CODE_FONT_SIZE_STORAGE_KEY, normalizeViewerFontSize(codeFontSize.value));
|
|
7441
|
+
applySidebarFontSize();
|
|
7442
|
+
applyCodeFontSize();
|
|
7443
|
+
localStorage.setItem(scopeOmitDirsStorageKey(), JSON.stringify(normalizeScopeOmitDirs(input.value)));
|
|
7444
|
+
closeScopeSettings();
|
|
7445
|
+
refreshRepositoryTreeAfterSettings();
|
|
7446
|
+
}
|
|
7447
|
+
function resetScopeSettings() {
|
|
7448
|
+
localStorage.removeItem(SIDEBAR_FONT_SIZE_STORAGE_KEY);
|
|
7449
|
+
localStorage.removeItem(CODE_FONT_SIZE_STORAGE_KEY);
|
|
7450
|
+
applySidebarFontSize("regular");
|
|
7451
|
+
applyCodeFontSize("regular");
|
|
7452
|
+
localStorage.removeItem(scopeOmitDirsStorageKey());
|
|
7453
|
+
closeScopeSettings();
|
|
7454
|
+
refreshRepositoryTreeAfterSettings();
|
|
7222
7455
|
}
|
|
7223
7456
|
function buildTree(files) {
|
|
7224
7457
|
const root = { name: "", dirs: {}, files: [], path: "", minOrder: Infinity, explicit: true };
|
|
@@ -7239,8 +7472,10 @@
|
|
|
7239
7472
|
}
|
|
7240
7473
|
if (f2.type === "tree") {
|
|
7241
7474
|
node.explicit = true;
|
|
7242
|
-
if (f2.children_omitted === true)
|
|
7475
|
+
if (f2.children_omitted === true) {
|
|
7243
7476
|
node.children_omitted = true;
|
|
7477
|
+
node.children_omitted_reason = f2.children_omitted_reason;
|
|
7478
|
+
}
|
|
7244
7479
|
continue;
|
|
7245
7480
|
}
|
|
7246
7481
|
node.files.push(f2);
|
|
@@ -7283,12 +7518,18 @@
|
|
|
7283
7518
|
li.dataset.explicit = "true";
|
|
7284
7519
|
if (dir.children_omitted) {
|
|
7285
7520
|
li.classList.add("children-omitted");
|
|
7286
|
-
li.
|
|
7521
|
+
li.classList.add(dir.children_omitted_reason === "heavy" ? "children-omitted-heavy" : "children-omitted-internal");
|
|
7522
|
+
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";
|
|
7287
7523
|
}
|
|
7288
7524
|
li.style.setProperty("--lvl-pad", 12 + depth * 14 + "px");
|
|
7289
7525
|
const chev = document.createElement("span");
|
|
7290
|
-
|
|
7291
|
-
|
|
7526
|
+
if (dir.children_omitted) {
|
|
7527
|
+
chev.className = "chev-spacer";
|
|
7528
|
+
chev.setAttribute("aria-hidden", "true");
|
|
7529
|
+
} else {
|
|
7530
|
+
chev.className = "chev";
|
|
7531
|
+
setChevronIcon(chev);
|
|
7532
|
+
}
|
|
7292
7533
|
li.appendChild(chev);
|
|
7293
7534
|
const dirIcon = document.createElement("span");
|
|
7294
7535
|
dirIcon.className = "dir-icon";
|
|
@@ -7302,9 +7543,9 @@
|
|
|
7302
7543
|
label.appendChild(dn);
|
|
7303
7544
|
if (dir.children_omitted) {
|
|
7304
7545
|
const omitted = document.createElement("span");
|
|
7305
|
-
omitted.className = "dir-omitted";
|
|
7306
|
-
omitted.textContent = "skipped";
|
|
7307
|
-
omitted.title = "
|
|
7546
|
+
omitted.className = "dir-omitted " + (dir.children_omitted_reason === "heavy" ? "dir-omitted-heavy" : "dir-omitted-internal");
|
|
7547
|
+
omitted.textContent = dir.children_omitted_reason === "heavy" ? "skipped" : "private";
|
|
7548
|
+
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";
|
|
7308
7549
|
label.appendChild(omitted);
|
|
7309
7550
|
}
|
|
7310
7551
|
li.appendChild(label);
|
|
@@ -7329,12 +7570,22 @@
|
|
|
7329
7570
|
STATE.collapsedDirs.delete(dir.path);
|
|
7330
7571
|
localStorage.setItem("gdp:collapsed-dirs", JSON.stringify([...STATE.collapsedDirs]));
|
|
7331
7572
|
};
|
|
7332
|
-
|
|
7333
|
-
|
|
7573
|
+
if (!dir.children_omitted) {
|
|
7574
|
+
chev.addEventListener("click", toggleDir);
|
|
7575
|
+
dirIcon.addEventListener("click", toggleDir);
|
|
7576
|
+
}
|
|
7334
7577
|
if (onFileClick) {
|
|
7335
7578
|
li.addEventListener("click", (e2) => {
|
|
7336
7579
|
e2.stopPropagation();
|
|
7337
|
-
|
|
7580
|
+
if (dir.children_omitted_reason === "internal" || dir.children_omitted_reason === "truncated")
|
|
7581
|
+
return;
|
|
7582
|
+
onFileClick({
|
|
7583
|
+
path: dir.path,
|
|
7584
|
+
display_path: dir.path,
|
|
7585
|
+
type: "tree",
|
|
7586
|
+
children_omitted: dir.children_omitted,
|
|
7587
|
+
children_omitted_reason: dir.children_omitted_reason
|
|
7588
|
+
});
|
|
7338
7589
|
focusSidebarPanel();
|
|
7339
7590
|
});
|
|
7340
7591
|
} else {
|
|
@@ -7416,6 +7667,8 @@
|
|
|
7416
7667
|
ul.innerHTML = "";
|
|
7417
7668
|
ul.classList.toggle("tree", STATE.sbView === "tree");
|
|
7418
7669
|
STATE.files = files;
|
|
7670
|
+
SIDEBAR_FILES = files;
|
|
7671
|
+
SIDEBAR_ON_FILE_CLICK = onFileClick;
|
|
7419
7672
|
if (!onFileClick)
|
|
7420
7673
|
REPO_SIDEBAR_REF = null;
|
|
7421
7674
|
if (STATE.sbView === "tree") {
|
|
@@ -7458,6 +7711,49 @@
|
|
|
7458
7711
|
return;
|
|
7459
7712
|
input.value = ref || "worktree";
|
|
7460
7713
|
wrap.hidden = !(STATE.route.screen === "file" && STATE.route.view === "blob");
|
|
7714
|
+
syncSidebarHeaderHeight();
|
|
7715
|
+
}
|
|
7716
|
+
function createRefSelectorInput(options) {
|
|
7717
|
+
const wrap = document.createElement("div");
|
|
7718
|
+
wrap.className = "ref-selector" + (options.extraClass ? " " + options.extraClass : "");
|
|
7719
|
+
wrap.dataset.refSelector = "";
|
|
7720
|
+
if (options.wrapperId)
|
|
7721
|
+
wrap.id = options.wrapperId;
|
|
7722
|
+
if (options.hidden)
|
|
7723
|
+
wrap.hidden = true;
|
|
7724
|
+
const icon = document.createElement("span");
|
|
7725
|
+
icon.className = "ref-selector-icon";
|
|
7726
|
+
icon.setAttribute("aria-hidden", "true");
|
|
7727
|
+
icon.innerHTML = iconSvg("octicon-git-branch", GIT_BRANCH_16_PATH);
|
|
7728
|
+
const input = document.createElement("input");
|
|
7729
|
+
input.className = "ref-input";
|
|
7730
|
+
input.id = options.id;
|
|
7731
|
+
input.readOnly = true;
|
|
7732
|
+
input.autocomplete = "off";
|
|
7733
|
+
input.placeholder = options.placeholder;
|
|
7734
|
+
if (options.title)
|
|
7735
|
+
input.title = options.title;
|
|
7736
|
+
if (options.value != null)
|
|
7737
|
+
input.value = options.value;
|
|
7738
|
+
const caret = document.createElement("span");
|
|
7739
|
+
caret.className = "ref-selector-caret";
|
|
7740
|
+
caret.setAttribute("aria-hidden", "true");
|
|
7741
|
+
caret.innerHTML = iconSvg("octicon-triangle-down", TRIANGLE_DOWN_16_PATH);
|
|
7742
|
+
wrap.append(icon, input, caret);
|
|
7743
|
+
return { wrap, input };
|
|
7744
|
+
}
|
|
7745
|
+
function hydrateRefSelectorMounts() {
|
|
7746
|
+
document.querySelectorAll("[data-ref-selector-mount]").forEach((mount) => {
|
|
7747
|
+
const { wrap } = createRefSelectorInput({
|
|
7748
|
+
id: mount.dataset.refId || "",
|
|
7749
|
+
placeholder: mount.dataset.placeholder || "ref...",
|
|
7750
|
+
title: mount.dataset.title,
|
|
7751
|
+
wrapperId: mount.dataset.wrapperId,
|
|
7752
|
+
extraClass: mount.dataset.extraClass,
|
|
7753
|
+
hidden: mount.hidden
|
|
7754
|
+
});
|
|
7755
|
+
mount.replaceWith(wrap);
|
|
7756
|
+
});
|
|
7461
7757
|
}
|
|
7462
7758
|
function renderMeta(meta) {
|
|
7463
7759
|
const el = $("#meta");
|
|
@@ -7465,8 +7761,7 @@
|
|
|
7465
7761
|
el.textContent = "";
|
|
7466
7762
|
return;
|
|
7467
7763
|
}
|
|
7468
|
-
|
|
7469
|
-
document.title = (meta.project ? meta.project + " - " : "") + "code viewer";
|
|
7764
|
+
setProjectName(meta.project || "");
|
|
7470
7765
|
el.innerHTML = "";
|
|
7471
7766
|
if (meta.branch) {
|
|
7472
7767
|
const b2 = document.createElement("span");
|
|
@@ -7550,13 +7845,43 @@
|
|
|
7550
7845
|
card.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
7551
7846
|
}
|
|
7552
7847
|
}
|
|
7553
|
-
function
|
|
7848
|
+
function sidebarAncestorDirs(path) {
|
|
7849
|
+
const parts = path.split("/").filter(Boolean);
|
|
7850
|
+
const dirs = [];
|
|
7851
|
+
for (let i2 = 1;i2 < parts.length; i2++)
|
|
7852
|
+
dirs.push(parts.slice(0, i2).join("/"));
|
|
7853
|
+
return dirs;
|
|
7854
|
+
}
|
|
7855
|
+
function expandSidebarAncestors(path) {
|
|
7856
|
+
if (STATE.sbView !== "tree")
|
|
7857
|
+
return;
|
|
7858
|
+
let changed = false;
|
|
7859
|
+
for (const dir of sidebarAncestorDirs(path)) {
|
|
7860
|
+
if (STATE.collapsedDirs.delete(dir))
|
|
7861
|
+
changed = true;
|
|
7862
|
+
const row = document.querySelector('#filelist .tree-dir[data-dirpath="' + CSS.escape(dir) + '"]');
|
|
7863
|
+
row?.classList.remove("collapsed");
|
|
7864
|
+
const icon = row?.querySelector(".dir-icon");
|
|
7865
|
+
if (icon)
|
|
7866
|
+
setFolderIcon(icon, false);
|
|
7867
|
+
}
|
|
7868
|
+
if (changed)
|
|
7869
|
+
localStorage.setItem("gdp:collapsed-dirs", JSON.stringify([...STATE.collapsedDirs]));
|
|
7870
|
+
}
|
|
7871
|
+
function markActive(path, options = {}) {
|
|
7554
7872
|
STATE.activeFile = path;
|
|
7873
|
+
if (options.reveal && STATE.sbView === "tree")
|
|
7874
|
+
expandSidebarAncestors(path);
|
|
7555
7875
|
$$("#filelist li").forEach((li) => {
|
|
7556
7876
|
const itemPath = li.dataset.path || li.dataset.dirpath;
|
|
7557
7877
|
if (itemPath)
|
|
7558
7878
|
li.classList.toggle("active", itemPath === path);
|
|
7559
7879
|
});
|
|
7880
|
+
if (options.reveal) {
|
|
7881
|
+
const active = document.querySelector("#filelist li.active[data-path], #filelist .tree-dir.active[data-dirpath]");
|
|
7882
|
+
if (active)
|
|
7883
|
+
requestAnimationFrame(() => scrollSidebarItemIntoView(active));
|
|
7884
|
+
}
|
|
7560
7885
|
}
|
|
7561
7886
|
function applyViewedState() {
|
|
7562
7887
|
$$("#filelist li[data-path]").forEach((li) => {
|
|
@@ -7703,7 +8028,7 @@
|
|
|
7703
8028
|
syncRepoTargetInput(repoFileTargetFromRoute() || "worktree");
|
|
7704
8029
|
}
|
|
7705
8030
|
function syncHeaderMenu() {
|
|
7706
|
-
document.querySelectorAll(".app-menu-item").forEach((link2) => {
|
|
8031
|
+
document.querySelectorAll(".app-menu-item, .global-help-link").forEach((link2) => {
|
|
7707
8032
|
const fileRouteOwner = STATE.route.screen === "file" && STATE.route.view === "blob" ? "repo" : "diff";
|
|
7708
8033
|
const active = link2.dataset.route === STATE.route.screen || STATE.route.screen === "file" && link2.dataset.route === fileRouteOwner;
|
|
7709
8034
|
link2.classList.toggle("active", active);
|
|
@@ -8007,28 +8332,23 @@
|
|
|
8007
8332
|
function repoRoute(ref, path) {
|
|
8008
8333
|
return { screen: "repo", ref: ref || "worktree", path, range: currentRange() };
|
|
8009
8334
|
}
|
|
8010
|
-
function
|
|
8011
|
-
input.
|
|
8012
|
-
|
|
8335
|
+
function wireRefSelectorInput(input, onPick) {
|
|
8336
|
+
const wrap = input.closest("[data-ref-selector]");
|
|
8337
|
+
wrap?.addEventListener("click", (e2) => {
|
|
8013
8338
|
e2.stopPropagation();
|
|
8014
8339
|
openPopover(input);
|
|
8015
8340
|
});
|
|
8016
|
-
input.addEventListener("mousedown", (e2) => {
|
|
8017
|
-
if (popover.hidden) {
|
|
8018
|
-
e2.preventDefault();
|
|
8019
|
-
input.focus();
|
|
8020
|
-
}
|
|
8021
|
-
});
|
|
8022
8341
|
input.addEventListener("keydown", (e2) => {
|
|
8023
|
-
if (e2.key === "Enter") {
|
|
8342
|
+
if (e2.key === "Enter" || e2.key === " ") {
|
|
8024
8343
|
e2.preventDefault();
|
|
8025
|
-
|
|
8344
|
+
openPopover(input);
|
|
8026
8345
|
} else if (e2.key === "Escape") {
|
|
8027
8346
|
closePopover();
|
|
8028
8347
|
input.blur();
|
|
8029
8348
|
}
|
|
8030
8349
|
});
|
|
8031
|
-
|
|
8350
|
+
if (onPick)
|
|
8351
|
+
input.addEventListener("change", () => onPick(input.value || "worktree"));
|
|
8032
8352
|
}
|
|
8033
8353
|
function createRepoBreadcrumb(target, path) {
|
|
8034
8354
|
const nav = document.createElement("nav");
|
|
@@ -8063,7 +8383,7 @@
|
|
|
8063
8383
|
return nav;
|
|
8064
8384
|
}
|
|
8065
8385
|
async function renderRepo(meta) {
|
|
8066
|
-
|
|
8386
|
+
setProjectName(meta.project || "");
|
|
8067
8387
|
setPageMode();
|
|
8068
8388
|
removeStandaloneSource();
|
|
8069
8389
|
$("#empty").classList.add("hidden");
|
|
@@ -8076,21 +8396,19 @@
|
|
|
8076
8396
|
const target = $("#diff");
|
|
8077
8397
|
const shell = document.createElement("section");
|
|
8078
8398
|
shell.className = "gdp-repo-shell";
|
|
8079
|
-
const targetPicker =
|
|
8080
|
-
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
|
|
8084
|
-
|
|
8085
|
-
targetPicker
|
|
8086
|
-
targetPicker.title = "repository ref";
|
|
8087
|
-
wireRepoTargetPicker(targetPicker, (ref) => {
|
|
8399
|
+
const { wrap: targetPickerWrap, input: targetPicker } = createRefSelectorInput({
|
|
8400
|
+
id: "repo-ref",
|
|
8401
|
+
placeholder: "ref...",
|
|
8402
|
+
title: "repository ref",
|
|
8403
|
+
value: meta.ref || "worktree"
|
|
8404
|
+
});
|
|
8405
|
+
wireRefSelectorInput(targetPicker, (ref) => {
|
|
8088
8406
|
setRoute(repoRoute(ref, ""));
|
|
8089
8407
|
loadRepo();
|
|
8090
8408
|
});
|
|
8091
8409
|
const toolbar = document.createElement("div");
|
|
8092
8410
|
toolbar.className = "gdp-file-detail-header gdp-repo-toolbar";
|
|
8093
|
-
toolbar.append(createRepoBreadcrumb(meta.ref, meta.path || ""), createOpenPathButton(meta.path || "", "directory", "open this folder in OS")
|
|
8411
|
+
toolbar.append(targetPickerWrap, createRepoBreadcrumb(meta.ref, meta.path || ""), createOpenPathButton(meta.path || "", "directory", "open this folder in OS"));
|
|
8094
8412
|
shell.appendChild(toolbar);
|
|
8095
8413
|
const listCard = document.createElement("section");
|
|
8096
8414
|
listCard.className = "gdp-file-shell loaded gdp-repo-list-shell";
|
|
@@ -8209,6 +8527,7 @@
|
|
|
8209
8527
|
shell.appendChild(readme);
|
|
8210
8528
|
}
|
|
8211
8529
|
target.appendChild(shell);
|
|
8530
|
+
placeSidebarToggle();
|
|
8212
8531
|
}
|
|
8213
8532
|
function renderRepoBlobSidebar(currentPath, ref) {
|
|
8214
8533
|
syncRepoTargetInput(ref);
|
|
@@ -8225,6 +8544,7 @@
|
|
|
8225
8544
|
const params = new URLSearchParams;
|
|
8226
8545
|
params.set("ref", normalizedRef);
|
|
8227
8546
|
params.set("recursive", "1");
|
|
8547
|
+
appendScopeOmitDirsParam(params);
|
|
8228
8548
|
REPO_SIDEBAR_LOAD_REF = normalizedRef;
|
|
8229
8549
|
const load2 = trackLoad(fetch("/_tree?" + params.toString()).then((r2) => {
|
|
8230
8550
|
if (!r2.ok)
|
|
@@ -8239,7 +8559,8 @@
|
|
|
8239
8559
|
path: entry.path,
|
|
8240
8560
|
display_path: entry.path,
|
|
8241
8561
|
type: entry.type,
|
|
8242
|
-
children_omitted: entry.children_omitted
|
|
8562
|
+
children_omitted: entry.children_omitted,
|
|
8563
|
+
children_omitted_reason: entry.children_omitted_reason
|
|
8243
8564
|
}));
|
|
8244
8565
|
renderSidebar(files, (file) => {
|
|
8245
8566
|
if (file.type === "tree") {
|
|
@@ -8266,7 +8587,7 @@
|
|
|
8266
8587
|
return load2;
|
|
8267
8588
|
}
|
|
8268
8589
|
function activateRepoSidebarPath(currentPath) {
|
|
8269
|
-
markActive(currentPath);
|
|
8590
|
+
markActive(currentPath, { reveal: true });
|
|
8270
8591
|
applyFilter();
|
|
8271
8592
|
}
|
|
8272
8593
|
function createPlaceholder(f2) {
|
|
@@ -8308,7 +8629,10 @@
|
|
|
8308
8629
|
document.querySelectorAll(".gdp-file-shell.pending").forEach((c2) => lazyObserver.observe(c2));
|
|
8309
8630
|
}
|
|
8310
8631
|
window.addEventListener("scroll", () => enqueueInitialLoads(), { passive: true });
|
|
8311
|
-
window.addEventListener("resize", () =>
|
|
8632
|
+
window.addEventListener("resize", () => {
|
|
8633
|
+
enqueueInitialLoads();
|
|
8634
|
+
syncSidebarHeaderHeight();
|
|
8635
|
+
}, { passive: true });
|
|
8312
8636
|
document.addEventListener("visibilitychange", () => {
|
|
8313
8637
|
if (!document.hidden)
|
|
8314
8638
|
enqueueInitialLoads();
|
|
@@ -9213,6 +9537,8 @@
|
|
|
9213
9537
|
function sourceDisplayKind(path) {
|
|
9214
9538
|
if (isVideo(path))
|
|
9215
9539
|
return "video";
|
|
9540
|
+
if (isAudio(path))
|
|
9541
|
+
return "audio";
|
|
9216
9542
|
if (isImage(path))
|
|
9217
9543
|
return "image";
|
|
9218
9544
|
if (/\.pdf$/i.test(path))
|
|
@@ -9259,10 +9585,28 @@
|
|
|
9259
9585
|
return "MP4 video";
|
|
9260
9586
|
if (ext === "webm")
|
|
9261
9587
|
return "WebM video";
|
|
9588
|
+
if (ext === "mp3")
|
|
9589
|
+
return "MP3 audio";
|
|
9590
|
+
if (ext === "wav")
|
|
9591
|
+
return "WAV audio";
|
|
9592
|
+
if (ext === "ogg")
|
|
9593
|
+
return "Ogg audio";
|
|
9594
|
+
if (ext === "flac")
|
|
9595
|
+
return "FLAC audio";
|
|
9596
|
+
if (ext === "m4a")
|
|
9597
|
+
return "M4A audio";
|
|
9598
|
+
if (ext === "aac")
|
|
9599
|
+
return "AAC audio";
|
|
9600
|
+
if (ext === "opus")
|
|
9601
|
+
return "Opus audio";
|
|
9602
|
+
if (ext === "mid" || ext === "midi")
|
|
9603
|
+
return "MIDI file";
|
|
9262
9604
|
if (mime?.startsWith("image/"))
|
|
9263
9605
|
return "Image";
|
|
9264
9606
|
if (mime?.startsWith("video/"))
|
|
9265
9607
|
return "Video";
|
|
9608
|
+
if (mime?.startsWith("audio/"))
|
|
9609
|
+
return "Audio";
|
|
9266
9610
|
if (mime === "application/pdf")
|
|
9267
9611
|
return "PDF document";
|
|
9268
9612
|
if (fallback === "unsupported file")
|
|
@@ -9734,6 +10078,12 @@
|
|
|
9734
10078
|
video.controls = true;
|
|
9735
10079
|
video.preload = "metadata";
|
|
9736
10080
|
view.appendChild(video);
|
|
10081
|
+
} else if (mediaKind === "audio") {
|
|
10082
|
+
const audio = document.createElement("audio");
|
|
10083
|
+
audio.src = url;
|
|
10084
|
+
audio.controls = true;
|
|
10085
|
+
audio.preload = "metadata";
|
|
10086
|
+
view.appendChild(audio);
|
|
9737
10087
|
} else if (mediaKind === "pdf") {
|
|
9738
10088
|
const frame = document.createElement("iframe");
|
|
9739
10089
|
frame.src = url;
|
|
@@ -9888,6 +10238,7 @@
|
|
|
9888
10238
|
} else {
|
|
9889
10239
|
root.prepend(card);
|
|
9890
10240
|
}
|
|
10241
|
+
placeSidebarToggle();
|
|
9891
10242
|
const controller = new AbortController;
|
|
9892
10243
|
ACTIVE_SOURCE_LOAD = { controller, req, target, card };
|
|
9893
10244
|
renderSourceLoading(card, target, () => cancelActiveSourceLoad("user"));
|
|
@@ -9900,7 +10251,7 @@
|
|
|
9900
10251
|
renderSourceUnsupported(card, target);
|
|
9901
10252
|
return;
|
|
9902
10253
|
}
|
|
9903
|
-
if (displayKind === "image" || displayKind === "video" || displayKind === "pdf") {
|
|
10254
|
+
if (displayKind === "image" || displayKind === "video" || displayKind === "audio" || displayKind === "pdf") {
|
|
9904
10255
|
if (req !== SOURCE_REQ_SEQ || !sourceTargetsEqual(sourceTargetFromRoute(), target))
|
|
9905
10256
|
return;
|
|
9906
10257
|
finishSourceLoad(req);
|
|
@@ -10296,9 +10647,10 @@
|
|
|
10296
10647
|
b2.addEventListener("scroll", () => mirror(b2, a2), { passive: true });
|
|
10297
10648
|
});
|
|
10298
10649
|
}
|
|
10299
|
-
const MEDIA_RE = /\.(png|jpe?g|gif|webp|svg|avif|bmp|ico|mp4|webm|mov)(\?.*)?$/i;
|
|
10650
|
+
const MEDIA_RE = /\.(png|jpe?g|gif|webp|svg|avif|bmp|ico|mp4|webm|mov|mp3|wav|ogg|flac|m4a|aac|opus)(\?.*)?$/i;
|
|
10300
10651
|
const IMAGE_RE = /\.(png|jpe?g|gif|webp|svg|avif|bmp|ico)(\?.*)?$/i;
|
|
10301
10652
|
const VIDEO_RE = /\.(mp4|webm|mov)$/i;
|
|
10653
|
+
const AUDIO_RE = /\.(mp3|wav|ogg|flac|m4a|aac|opus)$/i;
|
|
10302
10654
|
function isMedia(p2) {
|
|
10303
10655
|
return MEDIA_RE.test(p2);
|
|
10304
10656
|
}
|
|
@@ -10308,6 +10660,9 @@
|
|
|
10308
10660
|
function isVideo(p2) {
|
|
10309
10661
|
return VIDEO_RE.test(p2);
|
|
10310
10662
|
}
|
|
10663
|
+
function isAudio(p2) {
|
|
10664
|
+
return AUDIO_RE.test(p2);
|
|
10665
|
+
}
|
|
10311
10666
|
function fileURL(path, ref) {
|
|
10312
10667
|
return "/_file?path=" + encodeURIComponent(path) + "&ref=" + ref;
|
|
10313
10668
|
}
|
|
@@ -10316,6 +10671,9 @@
|
|
|
10316
10671
|
if (isVideo(path)) {
|
|
10317
10672
|
return '<video src="' + url + '" controls preload="metadata"></video>';
|
|
10318
10673
|
}
|
|
10674
|
+
if (isAudio(path)) {
|
|
10675
|
+
return '<audio src="' + url + '" controls preload="metadata"></audio>';
|
|
10676
|
+
}
|
|
10319
10677
|
return '<img src="' + url + '" alt="" loading="lazy">';
|
|
10320
10678
|
}
|
|
10321
10679
|
function enhanceMediaCard(file, card) {
|
|
@@ -10404,17 +10762,31 @@
|
|
|
10404
10762
|
body.style.display = STATE.collapsed ? "none" : "";
|
|
10405
10763
|
});
|
|
10406
10764
|
}
|
|
10765
|
+
applySidebarFontSize();
|
|
10766
|
+
applyCodeFontSize();
|
|
10767
|
+
applySidebarHidden();
|
|
10768
|
+
observeSidebarHeaderHeight();
|
|
10769
|
+
hydrateRefSelectorMounts();
|
|
10407
10770
|
setSidebarTreeActionIcons();
|
|
10408
10771
|
$$(".sb-view-seg button").forEach((b2) => {
|
|
10409
10772
|
b2.addEventListener("click", () => {
|
|
10410
10773
|
STATE.sbView = b2.dataset.view || "tree";
|
|
10411
10774
|
localStorage.setItem("gdp:sbview", STATE.sbView);
|
|
10412
|
-
if (
|
|
10413
|
-
renderSidebar(
|
|
10775
|
+
if (SIDEBAR_FILES.length)
|
|
10776
|
+
renderSidebar(SIDEBAR_FILES, SIDEBAR_ON_FILE_CLICK);
|
|
10414
10777
|
});
|
|
10415
10778
|
});
|
|
10416
10779
|
$("#sb-expand-all").addEventListener("click", () => setAllSidebarDirsCollapsed(false));
|
|
10417
10780
|
$("#sb-collapse-all").addEventListener("click", () => setAllSidebarDirsCollapsed(true));
|
|
10781
|
+
$("#sidebar-toggle")?.addEventListener("click", toggleSidebarHidden);
|
|
10782
|
+
$("#viewer-settings")?.addEventListener("click", openScopeSettings);
|
|
10783
|
+
$("#scope-settings-close")?.addEventListener("click", closeScopeSettings);
|
|
10784
|
+
$("#scope-omit-save")?.addEventListener("click", saveScopeSettings);
|
|
10785
|
+
$("#scope-omit-reset")?.addEventListener("click", resetScopeSettings);
|
|
10786
|
+
$("#scope-settings-popover")?.addEventListener("keydown", (e2) => {
|
|
10787
|
+
if (e2.key === "Escape")
|
|
10788
|
+
closeScopeSettings();
|
|
10789
|
+
});
|
|
10418
10790
|
prepareKeyboardPanels();
|
|
10419
10791
|
const contentPanel = document.querySelector("#content");
|
|
10420
10792
|
contentPanel?.addEventListener("focusin", () => setPanelFocusScope("main"));
|
|
@@ -10849,17 +11221,19 @@
|
|
|
10849
11221
|
});
|
|
10850
11222
|
}
|
|
10851
11223
|
async function repoPaletteFiles(ref) {
|
|
10852
|
-
const
|
|
11224
|
+
const cacheKey = repoFileCacheKey(ref);
|
|
11225
|
+
const cached = REPO_FILE_CACHE.get(cacheKey);
|
|
10853
11226
|
if (cached && cached.generation === SERVER_GENERATION)
|
|
10854
11227
|
return cached;
|
|
10855
11228
|
const params = new URLSearchParams;
|
|
10856
11229
|
params.set("ref", ref);
|
|
11230
|
+
appendScopeOmitDirsParam(params);
|
|
10857
11231
|
const res = await trackLoad(fetch("/_files?" + params.toString()).then((r2) => {
|
|
10858
11232
|
if (!r2.ok)
|
|
10859
11233
|
throw new Error("failed to load files");
|
|
10860
11234
|
return r2.json();
|
|
10861
11235
|
}));
|
|
10862
|
-
REPO_FILE_CACHE.set(
|
|
11236
|
+
REPO_FILE_CACHE.set(cacheKey, res);
|
|
10863
11237
|
return res;
|
|
10864
11238
|
}
|
|
10865
11239
|
function diffFilePaletteItems(state, query) {
|
|
@@ -10947,6 +11321,7 @@
|
|
|
10947
11321
|
params.set("max", "200");
|
|
10948
11322
|
if (state.grepRegex)
|
|
10949
11323
|
params.set("regex", "1");
|
|
11324
|
+
appendScopeOmitDirsParam(params);
|
|
10950
11325
|
if (source === "diff") {
|
|
10951
11326
|
for (const file of state.diffSnapshot)
|
|
10952
11327
|
params.append("path", file.path);
|
|
@@ -11065,6 +11440,8 @@
|
|
|
11065
11440
|
return true;
|
|
11066
11441
|
}
|
|
11067
11442
|
if (action === "focus-sidebar") {
|
|
11443
|
+
if (STATE.sidebarHidden)
|
|
11444
|
+
applySidebarHidden(false);
|
|
11068
11445
|
focusSidebarPanel();
|
|
11069
11446
|
return true;
|
|
11070
11447
|
}
|
|
@@ -11194,6 +11571,7 @@
|
|
|
11194
11571
|
params.set("ref", STATE.route.ref || "worktree");
|
|
11195
11572
|
if (STATE.route.path)
|
|
11196
11573
|
params.set("path", STATE.route.path);
|
|
11574
|
+
appendScopeOmitDirsParam(params);
|
|
11197
11575
|
return trackLoad(fetch("/_tree?" + params.toString()).then((r2) => {
|
|
11198
11576
|
if (!r2.ok)
|
|
11199
11577
|
throw new Error("failed to load repository tree");
|
|
@@ -11229,16 +11607,18 @@
|
|
|
11229
11607
|
setStatus("live");
|
|
11230
11608
|
}).catch(() => setStatus("error"));
|
|
11231
11609
|
}
|
|
11232
|
-
|
|
11233
|
-
|
|
11234
|
-
|
|
11235
|
-
|
|
11236
|
-
|
|
11237
|
-
|
|
11238
|
-
|
|
11239
|
-
|
|
11240
|
-
|
|
11241
|
-
|
|
11610
|
+
loadSettings().finally(() => {
|
|
11611
|
+
if (STATE.route.screen === "help") {
|
|
11612
|
+
setStatus("live");
|
|
11613
|
+
renderHelpPage();
|
|
11614
|
+
} else if (STATE.route.screen === "repo")
|
|
11615
|
+
loadRepo();
|
|
11616
|
+
else if (STATE.route.screen === "file" && STATE.route.view === "blob") {
|
|
11617
|
+
setStatus("live");
|
|
11618
|
+
applySourceRouteToShell();
|
|
11619
|
+
} else
|
|
11620
|
+
load();
|
|
11621
|
+
});
|
|
11242
11622
|
function syncRefInputs() {
|
|
11243
11623
|
const fi = $("#ref-from"), ti = $("#ref-to");
|
|
11244
11624
|
if (fi)
|
|
@@ -11357,40 +11737,21 @@
|
|
|
11357
11737
|
popover.hidden = true;
|
|
11358
11738
|
popTarget = null;
|
|
11359
11739
|
}
|
|
11360
|
-
|
|
11361
|
-
|
|
11362
|
-
|
|
11363
|
-
|
|
11364
|
-
|
|
11365
|
-
|
|
11366
|
-
|
|
11367
|
-
}
|
|
11368
|
-
});
|
|
11369
|
-
el.addEventListener("click", (e2) => {
|
|
11370
|
-
e2.stopPropagation();
|
|
11371
|
-
openPopover(el);
|
|
11372
|
-
});
|
|
11373
|
-
el.addEventListener("keydown", (e2) => {
|
|
11374
|
-
if (e2.key === "Enter") {
|
|
11375
|
-
e2.preventDefault();
|
|
11376
|
-
closePopover();
|
|
11377
|
-
} else if (e2.key === "Escape") {
|
|
11378
|
-
closePopover();
|
|
11379
|
-
el.blur();
|
|
11380
|
-
}
|
|
11381
|
-
});
|
|
11740
|
+
const refFromInput = $("#ref-from");
|
|
11741
|
+
const refToInput = $("#ref-to");
|
|
11742
|
+
wireRefSelectorInput(refFromInput, () => {
|
|
11743
|
+
const otherEmpty = !refToInput.value;
|
|
11744
|
+
setRange(refFromInput.value, refToInput.value);
|
|
11745
|
+
if (otherEmpty)
|
|
11746
|
+
setTimeout(() => openPopover(refToInput), 0);
|
|
11382
11747
|
});
|
|
11383
|
-
|
|
11748
|
+
wireRefSelectorInput(refToInput, () => setRange(refFromInput.value, refToInput.value));
|
|
11749
|
+
wireRefSelectorInput($("#repo-target"), (ref) => {
|
|
11384
11750
|
if (STATE.route.screen !== "file")
|
|
11385
11751
|
return;
|
|
11386
11752
|
setRoute({ screen: "file", path: STATE.route.path, ref, view: "blob", range: currentRange() });
|
|
11387
11753
|
renderStandaloneSource({ path: STATE.route.path, ref });
|
|
11388
11754
|
});
|
|
11389
|
-
document.addEventListener("focusin", (e2) => {
|
|
11390
|
-
const el = e2.target;
|
|
11391
|
-
if (el instanceof HTMLInputElement && (el.id === "repo-ref" || el.id === "repo-target"))
|
|
11392
|
-
openPopover(el);
|
|
11393
|
-
});
|
|
11394
11755
|
popSearch.addEventListener("input", () => buildPopBody(popSearch.value));
|
|
11395
11756
|
popSearch.addEventListener("keydown", (e2) => {
|
|
11396
11757
|
if (e2.key === "Escape") {
|
|
@@ -11407,24 +11768,8 @@
|
|
|
11407
11768
|
return;
|
|
11408
11769
|
const pickedTarget = popTarget;
|
|
11409
11770
|
pickedTarget.value = val;
|
|
11410
|
-
if (pickedTarget.id === "repo-ref") {
|
|
11411
|
-
closePopover();
|
|
11412
|
-
pickedTarget.dispatchEvent(new Event("change"));
|
|
11413
|
-
return;
|
|
11414
|
-
}
|
|
11415
|
-
if (pickedTarget.id === "repo-target") {
|
|
11416
|
-
closePopover();
|
|
11417
|
-
pickedTarget.dispatchEvent(new Event("change"));
|
|
11418
|
-
return;
|
|
11419
|
-
}
|
|
11420
|
-
const targetWasFrom = pickedTarget.id === "ref-from";
|
|
11421
|
-
const otherEmpty = !$("#ref-to").value;
|
|
11422
11771
|
closePopover();
|
|
11423
|
-
|
|
11424
|
-
if (targetWasFrom && otherEmpty) {
|
|
11425
|
-
const ti = $("#ref-to");
|
|
11426
|
-
setTimeout(() => ti.focus(), 0);
|
|
11427
|
-
}
|
|
11772
|
+
pickedTarget.dispatchEvent(new Event("change"));
|
|
11428
11773
|
}
|
|
11429
11774
|
popBody.addEventListener("click", (e2) => {
|
|
11430
11775
|
const item = e2.target.closest(".rp-item-commit, .rp-item-ref");
|