gh-here 3.0.3 → 3.2.0

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.
Files changed (47) hide show
  1. package/.env +0 -0
  2. package/lib/constants.js +21 -16
  3. package/lib/content-search.js +212 -0
  4. package/lib/error-handler.js +39 -28
  5. package/lib/file-utils.js +438 -287
  6. package/lib/git.js +11 -55
  7. package/lib/gitignore.js +70 -41
  8. package/lib/renderers.js +17 -33
  9. package/lib/server.js +73 -196
  10. package/lib/symbol-parser.js +600 -0
  11. package/package.json +1 -1
  12. package/public/app.js +135 -68
  13. package/public/css/components/buttons.css +423 -0
  14. package/public/css/components/forms.css +171 -0
  15. package/public/css/components/modals.css +286 -0
  16. package/public/css/components/notifications.css +36 -0
  17. package/public/css/file-table.css +318 -0
  18. package/public/css/file-tree.css +269 -0
  19. package/public/css/file-viewer.css +1259 -0
  20. package/public/css/layout.css +372 -0
  21. package/public/css/main.css +35 -0
  22. package/public/css/reset.css +64 -0
  23. package/public/css/search.css +694 -0
  24. package/public/css/symbol-outline.css +279 -0
  25. package/public/css/variables.css +135 -0
  26. package/public/js/constants.js +50 -34
  27. package/public/js/content-search-handler.js +551 -0
  28. package/public/js/file-viewer.js +437 -0
  29. package/public/js/focus-mode.js +280 -0
  30. package/public/js/inline-search.js +659 -0
  31. package/public/js/modal-manager.js +14 -28
  32. package/public/js/symbol-outline.js +454 -0
  33. package/public/js/utils.js +152 -94
  34. package/.claude/settings.local.json +0 -30
  35. package/SAMPLE.md +0 -287
  36. package/lib/validation.js +0 -77
  37. package/public/app.js.backup +0 -1902
  38. package/public/highlight.css +0 -121
  39. package/public/js/draft-manager.js +0 -36
  40. package/public/js/editor-manager.js +0 -159
  41. package/public/styles.css +0 -2727
  42. package/test.js +0 -138
  43. package/tests/draftManager.test.js +0 -241
  44. package/tests/fileTypeDetection.test.js +0 -111
  45. package/tests/httpService.test.js +0 -268
  46. package/tests/languageDetection.test.js +0 -145
  47. package/tests/pathUtils.test.js +0 -136
@@ -0,0 +1,372 @@
1
+ /**
2
+ * Layout Styles
3
+ * Header, main content area, canvas, and content wrappers
4
+ */
5
+
6
+ /* ========================================
7
+ Header
8
+ ======================================== */
9
+
10
+ header {
11
+ -webkit-backdrop-filter: blur(20px) saturate(180%);
12
+ backdrop-filter: blur(20px) saturate(180%);
13
+ background: linear-gradient(180deg, rgba(19, 23, 29, 0.95) 0%, rgba(19, 23, 29, 0.85) 100%);
14
+ border-bottom: 1px solid var(--border-subtle);
15
+ box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05) inset, var(--shadow-md);
16
+ position: sticky;
17
+ top: 0;
18
+ transition: all var(--transition-base);
19
+ z-index: 100;
20
+ }
21
+
22
+ header:hover {
23
+ box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05) inset, var(--shadow-lg);
24
+ }
25
+
26
+ [data-theme="light"] header {
27
+ background: linear-gradient(180deg, rgba(248, 250, 252, 0.95) 0%, rgba(248, 250, 252, 0.85) 100%);
28
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.05) inset, var(--shadow-md);
29
+ }
30
+
31
+ [data-theme="light"] header:hover {
32
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.05) inset, var(--shadow-lg);
33
+ }
34
+
35
+ .header-content {
36
+ align-items: center;
37
+ display: flex;
38
+ gap: var(--space-lg);
39
+ justify-content: space-between;
40
+ max-width: 100%;
41
+ padding: 12px 32px;
42
+ }
43
+
44
+ .header-left {
45
+ flex: 0 0 auto;
46
+ }
47
+
48
+ .header-left h1 {
49
+ -webkit-background-clip: text;
50
+ -webkit-text-fill-color: transparent;
51
+ background: linear-gradient(135deg, var(--text-primary) 0%, var(--text-secondary) 100%);
52
+ background-clip: text;
53
+ color: var(--text-primary);
54
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
55
+ font-size: 22px;
56
+ font-weight: 700;
57
+ letter-spacing: -0.02em;
58
+ margin: 0;
59
+ transition: all var(--transition-base);
60
+ }
61
+
62
+ .header-left h1::before {
63
+ color: var(--link-color);
64
+ content: '$';
65
+ display: inline-block;
66
+ filter: drop-shadow(0 0 4px rgba(96, 165, 250, 0.4));
67
+ font-weight: 500;
68
+ margin-right: 10px;
69
+ opacity: 1;
70
+ transform: scale(1.1);
71
+ }
72
+
73
+ .header-path {
74
+ align-items: center;
75
+ display: flex;
76
+ gap: 8px;
77
+ }
78
+
79
+ .header-right {
80
+ align-items: center;
81
+ display: flex;
82
+ gap: 8px;
83
+ margin-left: auto;
84
+ }
85
+
86
+ /* ========================================
87
+ Main Content Area
88
+ ======================================== */
89
+
90
+ main {
91
+ background: var(--bg-primary);
92
+ display: flex;
93
+ min-height: calc(100vh - 57px);
94
+ padding: 0;
95
+ }
96
+
97
+ .main-content {
98
+ margin: 0 auto;
99
+ max-width: 1400px;
100
+ padding: var(--space-xl) var(--space-2xl);
101
+ width: 100%;
102
+ }
103
+
104
+ .main-content-wrapper {
105
+ display: flex;
106
+ flex: 1;
107
+ flex-direction: column;
108
+ min-width: 0;
109
+ transition: opacity 160ms ease;
110
+ will-change: opacity;
111
+ }
112
+
113
+ .main-content-wrapper.navigating {
114
+ opacity: 0.5;
115
+ pointer-events: none;
116
+ }
117
+
118
+ .main-content-wrapper.no-sidebar {
119
+ margin: 0 auto;
120
+ max-width: 1280px;
121
+ width: 100%;
122
+ }
123
+
124
+ .main-content-wrapper.no-sidebar .repo-canvas-content {
125
+ max-width: 980px;
126
+ }
127
+
128
+ /* ========================================
129
+ Repo Canvas
130
+ ======================================== */
131
+
132
+ .repo-canvas {
133
+ background-color: var(--bg-primary);
134
+ flex: 1;
135
+ min-width: 0;
136
+ position: relative;
137
+ }
138
+
139
+ .repo-canvas-content {
140
+ margin: 0 auto;
141
+ max-width: 1400px;
142
+ padding: var(--space-2xl) var(--space-3xl);
143
+ position: relative;
144
+ z-index: 1;
145
+ }
146
+
147
+ @media (max-width: 1200px) {
148
+ .repo-canvas-content {
149
+ padding: var(--space-xl) var(--space-2xl);
150
+ }
151
+ }
152
+
153
+ @media (max-width: 768px) {
154
+ .repo-canvas-content {
155
+ padding: var(--space-lg) var(--space-md);
156
+ }
157
+ }
158
+
159
+ /* ========================================
160
+ Repo Controls Bar
161
+ ======================================== */
162
+
163
+ .repo-controls {
164
+ align-items: center;
165
+ background: var(--bg-card);
166
+ border: 1px solid var(--border-subtle);
167
+ border-radius: var(--radius-lg);
168
+ box-shadow: var(--shadow-sm);
169
+ display: flex;
170
+ gap: var(--space-md);
171
+ justify-content: space-between;
172
+ margin-bottom: var(--space-lg);
173
+ min-height: 40px;
174
+ overflow: hidden;
175
+ padding: 8px 16px;
176
+ transition: all var(--transition-base);
177
+ }
178
+
179
+ .repo-controls:hover {
180
+ border-color: var(--border-primary);
181
+ box-shadow: var(--shadow-md);
182
+ transform: translateY(-1px);
183
+ }
184
+
185
+ .repo-controls-left {
186
+ align-items: center;
187
+ display: flex;
188
+ flex-shrink: 0;
189
+ gap: 12px;
190
+ min-width: 0;
191
+ }
192
+
193
+ .repo-controls-left:empty {
194
+ display: none;
195
+ }
196
+
197
+ .repo-controls-right {
198
+ align-items: center;
199
+ display: flex;
200
+ flex-shrink: 1;
201
+ gap: 12px;
202
+ margin-left: auto;
203
+ max-width: 320px;
204
+ min-width: 0;
205
+ overflow: hidden;
206
+ }
207
+
208
+ /* ========================================
209
+ Breadcrumb Section
210
+ ======================================== */
211
+
212
+ .breadcrumb-section {
213
+ align-items: center;
214
+ color: var(--text-primary);
215
+ display: flex;
216
+ flex-wrap: wrap;
217
+ font-size: 22px;
218
+ font-weight: 700;
219
+ gap: var(--space-sm);
220
+ letter-spacing: -0.01em;
221
+ line-height: 1.4;
222
+ margin: 0 0 var(--space-lg) 0;
223
+ }
224
+
225
+ .breadcrumb-item {
226
+ align-items: center;
227
+ display: inline-flex;
228
+ }
229
+
230
+ .breadcrumb-item a {
231
+ align-items: center;
232
+ border-radius: var(--radius-md);
233
+ color: var(--link-color);
234
+ display: inline-flex;
235
+ font-weight: 600;
236
+ gap: 6px;
237
+ overflow: hidden;
238
+ padding: 6px 12px;
239
+ position: relative;
240
+ text-decoration: none;
241
+ transition: all var(--transition-base);
242
+ }
243
+
244
+ .breadcrumb-item a::before {
245
+ background: linear-gradient(135deg, rgba(96, 165, 250, 0.1) 0%, rgba(96, 165, 250, 0.05) 100%);
246
+ content: '';
247
+ inset: 0;
248
+ opacity: 0;
249
+ position: absolute;
250
+ transition: opacity var(--transition-base);
251
+ }
252
+
253
+ .breadcrumb-item a:hover {
254
+ box-shadow: var(--shadow-sm), var(--shadow-glow);
255
+ color: var(--link-hover);
256
+ text-decoration: none;
257
+ transform: translateY(-2px);
258
+ }
259
+
260
+ .breadcrumb-item a:hover::before {
261
+ opacity: 1;
262
+ }
263
+
264
+ .breadcrumb-separator {
265
+ color: var(--text-secondary);
266
+ margin: 0 4px;
267
+ opacity: 0.7;
268
+ }
269
+
270
+ /* ========================================
271
+ Directory Actions
272
+ ======================================== */
273
+
274
+ .directory-actions {
275
+ display: flex;
276
+ gap: 8px;
277
+ margin-bottom: 24px;
278
+ }
279
+
280
+ /* ========================================
281
+ Repo Name and Divider
282
+ ======================================== */
283
+
284
+ .repo-name {
285
+ color: var(--text-primary);
286
+ font-size: 20px;
287
+ font-weight: 600;
288
+ margin: 0 0 12px 0;
289
+ }
290
+
291
+ .repo-divider {
292
+ border: none;
293
+ border-top: 1px solid var(--border-primary);
294
+ margin: 0 0 12px 0;
295
+ }
296
+
297
+ /* ========================================
298
+ Focus Mode
299
+ ======================================== */
300
+
301
+ body.focus-mode {
302
+ overflow: hidden;
303
+ }
304
+
305
+ body.focus-mode header.focus-mode {
306
+ backdrop-filter: blur(8px);
307
+ opacity: 0.25;
308
+ transition: opacity var(--transition-slow);
309
+ }
310
+
311
+ body.focus-mode header.focus-mode:hover {
312
+ opacity: 0.9;
313
+ }
314
+
315
+ .main-content-wrapper.focus-mode {
316
+ animation: focusFadeIn 0.4s cubic-bezier(0.4, 0, 0.2, 1);
317
+ margin: 0 auto;
318
+ max-width: 1200px;
319
+ padding: 48px 32px;
320
+ }
321
+
322
+ @keyframes focusFadeIn {
323
+ from {
324
+ opacity: 0;
325
+ transform: translateY(10px);
326
+ }
327
+ to {
328
+ opacity: 1;
329
+ transform: translateY(0);
330
+ }
331
+ }
332
+
333
+ body.focus-mode .main-content-wrapper.focus-mode .main-content {
334
+ max-width: 100%;
335
+ }
336
+
337
+ body.focus-mode .file-content {
338
+ max-width: 100%;
339
+ }
340
+
341
+ /* ========================================
342
+ Responsive - Mobile
343
+ ======================================== */
344
+
345
+ @media (max-width: 768px) {
346
+ .main-content {
347
+ padding: 12px 16px;
348
+ }
349
+
350
+ .repo-canvas-content {
351
+ padding: 12px 16px;
352
+ }
353
+
354
+ .header-content {
355
+ padding: 8px 16px;
356
+ }
357
+
358
+ .header-left h1 {
359
+ font-size: 14px;
360
+ }
361
+
362
+ .repo-controls {
363
+ align-items: stretch;
364
+ flex-direction: column;
365
+ gap: 12px;
366
+ }
367
+
368
+ .repo-controls-right {
369
+ flex-direction: column;
370
+ gap: 8px;
371
+ }
372
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * gh-here Main Stylesheet
3
+ * Imports all component CSS files in the correct order
4
+ *
5
+ * File Structure:
6
+ * - variables.css: CSS custom properties (themes, colors, spacing)
7
+ * - reset.css: Base resets and body styles
8
+ * - layout.css: Header, main content, canvas
9
+ * - components/: Buttons, forms, modals, notifications
10
+ * - file-tree.css: Sidebar navigation
11
+ * - file-table.css: Directory listing
12
+ * - file-viewer.css: Code display, syntax, diffs
13
+ * - search.css: All search functionality
14
+ * - symbol-outline.css: Code navigation panel
15
+ */
16
+
17
+ /* Foundation */
18
+ @import url('variables.css');
19
+ @import url('reset.css');
20
+
21
+ /* Layout */
22
+ @import url('layout.css');
23
+
24
+ /* Components */
25
+ @import url('components/buttons.css');
26
+ @import url('components/forms.css');
27
+ @import url('components/modals.css');
28
+ @import url('components/notifications.css');
29
+
30
+ /* Features */
31
+ @import url('file-tree.css');
32
+ @import url('file-table.css');
33
+ @import url('file-viewer.css');
34
+ @import url('search.css');
35
+ @import url('symbol-outline.css');
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Reset and Base Styles
3
+ * Global resets, body styles, and view transitions
4
+ */
5
+
6
+ * {
7
+ box-sizing: border-box;
8
+ margin: 0;
9
+ padding: 0;
10
+ }
11
+
12
+ html {
13
+ background-color: var(--bg-primary);
14
+ color-scheme: dark;
15
+ }
16
+
17
+ html[data-theme="light"] {
18
+ background-color: var(--bg-primary);
19
+ color-scheme: light;
20
+ }
21
+
22
+ body {
23
+ -moz-osx-font-smoothing: grayscale;
24
+ -webkit-font-smoothing: antialiased;
25
+ background-color: var(--bg-primary);
26
+ color: var(--text-primary);
27
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
28
+ line-height: 1.6;
29
+ min-height: 100vh;
30
+ text-rendering: optimizeLegibility;
31
+ }
32
+
33
+ /* View Transitions API animations */
34
+ ::view-transition-old(root),
35
+ ::view-transition-new(root) {
36
+ animation-duration: 0.2s;
37
+ }
38
+
39
+ ::view-transition-old(root) {
40
+ animation-name: fade-out;
41
+ }
42
+
43
+ ::view-transition-new(root) {
44
+ animation-name: fade-in;
45
+ }
46
+
47
+ @keyframes fade-out {
48
+ to {
49
+ opacity: 0;
50
+ }
51
+ }
52
+
53
+ @keyframes fade-in {
54
+ from {
55
+ opacity: 0;
56
+ }
57
+ }
58
+
59
+ /* Reduced motion preference */
60
+ @media (prefers-reduced-motion: reduce) {
61
+ .main-content-wrapper {
62
+ transition: none;
63
+ }
64
+ }