@youtyan/code-viewer 0.1.12 → 0.1.13
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 +720 -62
- package/web/index.html +1 -0
- package/web/style.css +189 -0
- package/web-src/routes.ts +16 -1
package/web/index.html
CHANGED
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
<nav class="app-menu" aria-label="Views">
|
|
27
27
|
<a class="app-menu-item active" data-route="repo" href="/">Repository</a>
|
|
28
28
|
<a class="app-menu-item active" data-route="diff" href="/todif?from=HEAD&to=worktree">Diff Viewer</a>
|
|
29
|
+
<a class="app-menu-item" data-route="help" href="/help">Help</a>
|
|
29
30
|
</nav>
|
|
30
31
|
<div class="global-actions">
|
|
31
32
|
<button id="theme" title="toggle theme">🌗</button>
|
package/web/style.css
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
--accent-emph: #0550ae;
|
|
23
23
|
--accent-subtle: #ddf4ff;
|
|
24
24
|
--accent-muted: #54aeff66;
|
|
25
|
+
--scope-accent: #bf8700;
|
|
25
26
|
/* success / danger / attention / done */
|
|
26
27
|
--success: #1a7f37;
|
|
27
28
|
--success-emph: #1f883d;
|
|
@@ -70,6 +71,7 @@
|
|
|
70
71
|
--accent-emph: #1f6feb;
|
|
71
72
|
--accent-subtle: rgba(56,139,253,0.10);
|
|
72
73
|
--accent-muted: rgba(56,139,253,0.40);
|
|
74
|
+
--scope-accent: #d29922;
|
|
73
75
|
--success: #3fb950;
|
|
74
76
|
--success-emph: #238636;
|
|
75
77
|
--success-subtle: rgba(46,160,67,0.15);
|
|
@@ -804,6 +806,18 @@ html, body {
|
|
|
804
806
|
padding: 0 0 32px;
|
|
805
807
|
z-index: 30;
|
|
806
808
|
}
|
|
809
|
+
body[data-focus-scope="sidebar"] #sidebar {
|
|
810
|
+
background: color-mix(in oklab, var(--bg-soft) 97%, var(--scope-accent) 3%);
|
|
811
|
+
outline: 1px solid color-mix(in oklab, var(--scope-accent) 58%, transparent);
|
|
812
|
+
outline-offset: -1px;
|
|
813
|
+
box-shadow: inset -3px 0 0 var(--scope-accent);
|
|
814
|
+
}
|
|
815
|
+
body[data-focus-scope="main"] #content {
|
|
816
|
+
background: color-mix(in oklab, var(--bg) 98%, var(--scope-accent) 2%);
|
|
817
|
+
outline: 1px solid color-mix(in oklab, var(--scope-accent) 58%, transparent);
|
|
818
|
+
outline-offset: -1px;
|
|
819
|
+
box-shadow: inset 3px 0 0 var(--scope-accent);
|
|
820
|
+
}
|
|
807
821
|
.sb-head {
|
|
808
822
|
display: flex; justify-content: space-between; align-items: center;
|
|
809
823
|
padding: 14px 16px 10px;
|
|
@@ -926,6 +940,140 @@ body.gdp-resizing #sidebar-resizer {
|
|
|
926
940
|
body.gdp-resizing { cursor: col-resize !important; user-select: none; }
|
|
927
941
|
body.gdp-resizing * { user-select: none !important; }
|
|
928
942
|
|
|
943
|
+
body.gdp-help-page #topbar,
|
|
944
|
+
body.gdp-help-page #sidebar,
|
|
945
|
+
body.gdp-help-page #sidebar-resizer {
|
|
946
|
+
display: none;
|
|
947
|
+
}
|
|
948
|
+
body.gdp-help-page #content {
|
|
949
|
+
margin-left: 0;
|
|
950
|
+
padding-top: calc(var(--global-header-h) + 28px);
|
|
951
|
+
}
|
|
952
|
+
.gdp-help-shell {
|
|
953
|
+
width: 100%;
|
|
954
|
+
max-width: none;
|
|
955
|
+
margin: 0;
|
|
956
|
+
}
|
|
957
|
+
.gdp-help-header {
|
|
958
|
+
display: flex;
|
|
959
|
+
align-items: center;
|
|
960
|
+
justify-content: space-between;
|
|
961
|
+
gap: 16px;
|
|
962
|
+
margin-bottom: 22px;
|
|
963
|
+
}
|
|
964
|
+
.gdp-help-header h1 {
|
|
965
|
+
margin: 0;
|
|
966
|
+
font-size: 28px;
|
|
967
|
+
}
|
|
968
|
+
.gdp-help-language {
|
|
969
|
+
appearance: none;
|
|
970
|
+
min-width: 92px;
|
|
971
|
+
height: 34px;
|
|
972
|
+
border: 1px solid var(--border);
|
|
973
|
+
border-radius: 6px;
|
|
974
|
+
background:
|
|
975
|
+
linear-gradient(45deg, transparent 50%, var(--fg-muted) 50%) right 15px center / 5px 5px no-repeat,
|
|
976
|
+
linear-gradient(135deg, var(--fg-muted) 50%, transparent 50%) right 10px center / 5px 5px no-repeat,
|
|
977
|
+
var(--bg);
|
|
978
|
+
color: var(--fg);
|
|
979
|
+
padding: 0 34px 0 12px;
|
|
980
|
+
font: inherit;
|
|
981
|
+
font-size: 13px;
|
|
982
|
+
line-height: 32px;
|
|
983
|
+
cursor: pointer;
|
|
984
|
+
}
|
|
985
|
+
.gdp-help-language:hover {
|
|
986
|
+
border-color: var(--border-strong);
|
|
987
|
+
}
|
|
988
|
+
.gdp-help-language:focus {
|
|
989
|
+
border-color: var(--accent);
|
|
990
|
+
outline: none;
|
|
991
|
+
box-shadow: 0 0 0 3px var(--accent-muted);
|
|
992
|
+
}
|
|
993
|
+
.gdp-help-layout {
|
|
994
|
+
display: grid;
|
|
995
|
+
grid-template-columns: 220px minmax(0, 1fr);
|
|
996
|
+
gap: 28px;
|
|
997
|
+
align-items: start;
|
|
998
|
+
}
|
|
999
|
+
.gdp-help-nav {
|
|
1000
|
+
position: sticky;
|
|
1001
|
+
top: calc(var(--global-header-h) + 20px);
|
|
1002
|
+
display: grid;
|
|
1003
|
+
gap: 4px;
|
|
1004
|
+
padding-right: 16px;
|
|
1005
|
+
border-right: 1px solid var(--border-muted);
|
|
1006
|
+
}
|
|
1007
|
+
.gdp-help-nav button {
|
|
1008
|
+
appearance: none;
|
|
1009
|
+
border: 0;
|
|
1010
|
+
border-left: 3px solid transparent;
|
|
1011
|
+
border-radius: 0 6px 6px 0;
|
|
1012
|
+
background: transparent;
|
|
1013
|
+
color: var(--fg-muted);
|
|
1014
|
+
padding: 8px 10px;
|
|
1015
|
+
text-align: left;
|
|
1016
|
+
font: inherit;
|
|
1017
|
+
cursor: pointer;
|
|
1018
|
+
}
|
|
1019
|
+
.gdp-help-nav button:hover {
|
|
1020
|
+
background: var(--bg-mute);
|
|
1021
|
+
color: var(--fg);
|
|
1022
|
+
}
|
|
1023
|
+
.gdp-help-nav button.active {
|
|
1024
|
+
border-left-color: var(--accent);
|
|
1025
|
+
background: var(--accent-subtle);
|
|
1026
|
+
color: var(--accent-emph);
|
|
1027
|
+
font-weight: 700;
|
|
1028
|
+
}
|
|
1029
|
+
.gdp-help-content h2 {
|
|
1030
|
+
margin: 0 0 8px;
|
|
1031
|
+
font-size: 24px;
|
|
1032
|
+
}
|
|
1033
|
+
.gdp-help-content > p {
|
|
1034
|
+
margin: 0 0 24px;
|
|
1035
|
+
color: var(--fg-muted);
|
|
1036
|
+
}
|
|
1037
|
+
.gdp-help-group {
|
|
1038
|
+
margin: 0 0 28px;
|
|
1039
|
+
}
|
|
1040
|
+
.gdp-help-group h3 {
|
|
1041
|
+
margin: 0 0 10px;
|
|
1042
|
+
font-size: 16px;
|
|
1043
|
+
}
|
|
1044
|
+
.gdp-help-group table {
|
|
1045
|
+
width: 100%;
|
|
1046
|
+
border-collapse: collapse;
|
|
1047
|
+
border-top: 1px solid var(--border-muted);
|
|
1048
|
+
}
|
|
1049
|
+
.gdp-help-group th,
|
|
1050
|
+
.gdp-help-group td {
|
|
1051
|
+
padding: 11px 8px;
|
|
1052
|
+
border-bottom: 1px solid var(--border-muted);
|
|
1053
|
+
vertical-align: top;
|
|
1054
|
+
}
|
|
1055
|
+
.gdp-help-group th {
|
|
1056
|
+
width: 230px;
|
|
1057
|
+
color: var(--fg);
|
|
1058
|
+
font-weight: 600;
|
|
1059
|
+
text-align: left;
|
|
1060
|
+
}
|
|
1061
|
+
.gdp-help-group td {
|
|
1062
|
+
color: var(--fg-muted);
|
|
1063
|
+
}
|
|
1064
|
+
.gdp-help-group kbd {
|
|
1065
|
+
display: inline-block;
|
|
1066
|
+
min-width: 24px;
|
|
1067
|
+
padding: 2px 6px;
|
|
1068
|
+
border: 1px solid var(--border);
|
|
1069
|
+
border-bottom-color: var(--border-strong);
|
|
1070
|
+
border-radius: 5px;
|
|
1071
|
+
background: var(--bg-soft);
|
|
1072
|
+
color: var(--fg);
|
|
1073
|
+
font: 12px "Monaspace Neon", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
|
|
1074
|
+
text-align: center;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
929
1077
|
/* ===== Tree view ===== */
|
|
930
1078
|
#filelist.tree {
|
|
931
1079
|
padding: 4px 0 0;
|
|
@@ -1519,6 +1667,8 @@ table.d2h-diff-table tr.gdp-diff-line-target > td:first-child {
|
|
|
1519
1667
|
}
|
|
1520
1668
|
.gdp-copy-path.copied { color: var(--success); }
|
|
1521
1669
|
.gdp-copy-path.failed { color: var(--danger); }
|
|
1670
|
+
.gdp-copy-source.copied { color: var(--success); }
|
|
1671
|
+
.gdp-copy-source.failed { color: var(--danger); }
|
|
1522
1672
|
.gdp-open-path.opened { color: var(--success); }
|
|
1523
1673
|
.gdp-open-path.failed { color: var(--danger); }
|
|
1524
1674
|
.gdp-file-unfold[aria-pressed="true"] {
|
|
@@ -1738,6 +1888,23 @@ table.d2h-diff-table tr.gdp-diff-line-target > td:first-child {
|
|
|
1738
1888
|
color: var(--fg);
|
|
1739
1889
|
border-bottom-color: var(--blob-tab-active);
|
|
1740
1890
|
}
|
|
1891
|
+
.gdp-source-tabs .gdp-copy-source {
|
|
1892
|
+
margin-left: auto;
|
|
1893
|
+
align-self: center;
|
|
1894
|
+
width: 28px;
|
|
1895
|
+
height: 28px;
|
|
1896
|
+
padding: 0;
|
|
1897
|
+
border: 1px solid transparent;
|
|
1898
|
+
border-radius: 6px;
|
|
1899
|
+
}
|
|
1900
|
+
.gdp-source-virtual-copy {
|
|
1901
|
+
flex: 0 0 auto;
|
|
1902
|
+
width: 28px;
|
|
1903
|
+
height: 28px;
|
|
1904
|
+
padding: 0;
|
|
1905
|
+
border: 1px solid transparent;
|
|
1906
|
+
border-radius: 6px;
|
|
1907
|
+
}
|
|
1741
1908
|
.gdp-source-viewer > [hidden],
|
|
1742
1909
|
.gdp-markdown-layout[hidden],
|
|
1743
1910
|
.gdp-source-table[hidden] {
|
|
@@ -1754,6 +1921,25 @@ table.d2h-diff-table tr.gdp-diff-line-target > td:first-child {
|
|
|
1754
1921
|
.gdp-source-table tr.gdp-source-line-target {
|
|
1755
1922
|
background: var(--line-hit-bg);
|
|
1756
1923
|
}
|
|
1924
|
+
.gdp-source-table tr.gdp-source-cursor .gdp-source-line-number,
|
|
1925
|
+
.gdp-source-virtual-row.gdp-source-cursor .gdp-source-virtual-line-number {
|
|
1926
|
+
color: var(--fg);
|
|
1927
|
+
box-shadow: inset 3px 0 0 var(--scope-accent), inset -1px 0 0 var(--border-muted);
|
|
1928
|
+
}
|
|
1929
|
+
.gdp-source-table tr.gdp-source-cursor .gdp-source-line-code,
|
|
1930
|
+
.gdp-source-virtual-row.gdp-source-cursor .gdp-source-virtual-line-code {
|
|
1931
|
+
background: color-mix(in oklab, var(--bg) 90%, var(--scope-accent) 10%) !important;
|
|
1932
|
+
}
|
|
1933
|
+
.gdp-source-table tr.gdp-source-cursor .gdp-source-line-code::before,
|
|
1934
|
+
.gdp-source-virtual-row.gdp-source-cursor .gdp-source-virtual-line-code::before {
|
|
1935
|
+
content: "";
|
|
1936
|
+
display: inline-block;
|
|
1937
|
+
width: 2px;
|
|
1938
|
+
height: 1.05em;
|
|
1939
|
+
margin: 0 8px 0 -8px;
|
|
1940
|
+
vertical-align: -0.16em;
|
|
1941
|
+
background: var(--scope-accent);
|
|
1942
|
+
}
|
|
1757
1943
|
.gdp-source-table tr.gdp-source-line-target .gdp-source-line-number,
|
|
1758
1944
|
.gdp-source-table tr.gdp-source-line-target .gdp-source-line-code,
|
|
1759
1945
|
.gdp-source-virtual-row.gdp-source-line-target {
|
|
@@ -1907,6 +2093,9 @@ table.d2h-diff-table tr.gdp-diff-line-target > td:first-child {
|
|
|
1907
2093
|
border-color: var(--accent);
|
|
1908
2094
|
color: var(--accent);
|
|
1909
2095
|
}
|
|
2096
|
+
.gdp-source-virtual-copy:hover {
|
|
2097
|
+
border-color: var(--border);
|
|
2098
|
+
}
|
|
1910
2099
|
.gdp-source-virtual-scroller {
|
|
1911
2100
|
position: relative;
|
|
1912
2101
|
overflow: auto;
|
package/web-src/routes.ts
CHANGED
|
@@ -19,9 +19,10 @@ export type AppRoute =
|
|
|
19
19
|
| { screen: 'repo'; ref: string; path: string; range: DiffRange }
|
|
20
20
|
| { screen: 'diff'; range: DiffRange; path?: string; line?: SourceLineTarget }
|
|
21
21
|
| { screen: 'file'; path: string; ref: string; range: DiffRange; view?: 'blob' | 'detail'; line?: SourceLineTarget }
|
|
22
|
+
| { screen: 'help'; range: DiffRange; lang: string; section: string }
|
|
22
23
|
| { screen: 'unknown'; reason: 'unknown-pathname' | 'missing-path'; rawPathname: string; rawSearch: string; range: DiffRange };
|
|
23
24
|
|
|
24
|
-
export const SPA_PATHS = ['/todif', '/todiff', '/file'] as const;
|
|
25
|
+
export const SPA_PATHS = ['/todif', '/todiff', '/file', '/help'] as const;
|
|
25
26
|
export const APP_ENTRY_PATHS = ['/', '/index.html'] as const;
|
|
26
27
|
|
|
27
28
|
export function assertNever(value: never): never {
|
|
@@ -89,6 +90,13 @@ export function parseRoute(pathname: string, search: string, fallbackRange: Diff
|
|
|
89
90
|
if (!path) return { screen: 'unknown', reason: 'missing-path', rawPathname: pathname, rawSearch: search, range };
|
|
90
91
|
return { screen: 'file', path, ref, range, view: target ? 'blob' : 'detail', ...(line ? { line } : {}) };
|
|
91
92
|
}
|
|
93
|
+
case '/help':
|
|
94
|
+
return {
|
|
95
|
+
screen: 'help',
|
|
96
|
+
range,
|
|
97
|
+
lang: params.get('lang') || 'en',
|
|
98
|
+
section: params.get('section') || 'keybindings',
|
|
99
|
+
};
|
|
92
100
|
default:
|
|
93
101
|
return { screen: 'unknown', reason: 'unknown-pathname', rawPathname: pathname, rawSearch: search, range };
|
|
94
102
|
}
|
|
@@ -119,6 +127,13 @@ export function buildRoute(route: AppRoute): string {
|
|
|
119
127
|
'&to=' + encodeURIComponent(route.range.to || 'worktree') +
|
|
120
128
|
(route.path ? '&path=' + encodeURIComponent(route.path) : '') +
|
|
121
129
|
(route.line ? '&line=' + encodeURIComponent(formatLineTarget(route.line)) : '');
|
|
130
|
+
case 'help': {
|
|
131
|
+
const params = new URLSearchParams();
|
|
132
|
+
if (route.lang && route.lang !== 'en') params.set('lang', route.lang);
|
|
133
|
+
if (route.section && route.section !== 'keybindings') params.set('section', route.section);
|
|
134
|
+
const qs = params.toString();
|
|
135
|
+
return '/help' + (qs ? '?' + qs : '');
|
|
136
|
+
}
|
|
122
137
|
case 'unknown':
|
|
123
138
|
return '/todif?from=' + encodeURIComponent(route.range.from || '') +
|
|
124
139
|
'&to=' + encodeURIComponent(route.range.to || 'worktree');
|