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,1259 @@
1
+ /**
2
+ * File Viewer Styles
3
+ * Code viewing, line numbers, file header, images, binary files, markdown, and syntax highlighting
4
+ */
5
+
6
+ /* ========================================
7
+ File Header
8
+ ======================================== */
9
+
10
+ .file-header {
11
+ align-items: center;
12
+ backdrop-filter: blur(10px);
13
+ background: linear-gradient(135deg, var(--bg-card) 0%, var(--bg-elevated) 100%);
14
+ border: 1px solid var(--border-subtle);
15
+ border-radius: var(--radius-xl);
16
+ box-shadow: var(--shadow-md);
17
+ display: flex;
18
+ flex-wrap: wrap;
19
+ gap: var(--space-lg);
20
+ justify-content: space-between;
21
+ margin-bottom: var(--space-xl);
22
+ overflow: visible;
23
+ padding: 20px 28px;
24
+ position: relative;
25
+ transition: all var(--transition-base);
26
+ }
27
+
28
+ .file-header::before {
29
+ background: linear-gradient(90deg, transparent 0%, var(--link-color) 50%, transparent 100%);
30
+ border-radius: var(--radius-xl) var(--radius-xl) 0 0;
31
+ content: '';
32
+ height: 2px;
33
+ left: 0;
34
+ opacity: 0;
35
+ position: absolute;
36
+ right: 0;
37
+ top: 0;
38
+ transition: opacity var(--transition-base);
39
+ }
40
+
41
+ .file-header:hover {
42
+ border-color: var(--border-primary);
43
+ box-shadow: var(--shadow-xl);
44
+ transform: translateY(-2px);
45
+ }
46
+
47
+ .file-header:hover::before {
48
+ opacity: 1;
49
+ }
50
+
51
+ .file-header-main {
52
+ display: flex;
53
+ flex: 1;
54
+ flex-direction: column;
55
+ gap: 8px;
56
+ min-width: 0;
57
+ }
58
+
59
+ .file-path-info {
60
+ align-items: center;
61
+ display: flex;
62
+ font-size: 14px;
63
+ gap: 8px;
64
+ }
65
+
66
+ .file-path-text {
67
+ color: var(--link-color);
68
+ font-weight: 500;
69
+ word-break: break-all;
70
+ }
71
+
72
+ .file-path-copy-btn {
73
+ align-items: center;
74
+ background: transparent;
75
+ border: none;
76
+ border-radius: var(--radius-sm);
77
+ color: var(--text-secondary);
78
+ cursor: pointer;
79
+ display: inline-flex;
80
+ flex-shrink: 0;
81
+ height: 24px;
82
+ justify-content: center;
83
+ opacity: 0.7;
84
+ padding: 5px;
85
+ transition: all var(--transition-base);
86
+ width: 24px;
87
+ }
88
+
89
+ .file-path-copy-btn:hover {
90
+ background-color: var(--hover-bg);
91
+ color: var(--link-color);
92
+ opacity: 1;
93
+ transform: scale(1.1);
94
+ }
95
+
96
+ .file-path-copy-btn:active {
97
+ transform: scale(0.95);
98
+ }
99
+
100
+ .file-stats {
101
+ align-items: center;
102
+ color: var(--text-secondary);
103
+ display: flex;
104
+ font-size: 12px;
105
+ gap: 4px;
106
+ }
107
+
108
+ .file-stat {
109
+ color: var(--text-secondary);
110
+ }
111
+
112
+ .file-stat-separator {
113
+ color: var(--text-secondary);
114
+ opacity: 0.5;
115
+ }
116
+
117
+ /* ========================================
118
+ File Header Actions
119
+ ======================================== */
120
+
121
+ .file-header-actions {
122
+ align-items: center;
123
+ display: flex;
124
+ flex-shrink: 0;
125
+ flex-wrap: wrap;
126
+ gap: 8px;
127
+ }
128
+
129
+ .file-action-group {
130
+ background-color: var(--bg-primary);
131
+ border: 1px solid var(--border-primary);
132
+ border-radius: var(--radius-md);
133
+ box-shadow: var(--shadow-sm);
134
+ display: inline-flex;
135
+ overflow: hidden;
136
+ transition: all var(--transition-base);
137
+ }
138
+
139
+ .file-action-group:hover {
140
+ border-color: var(--border-secondary);
141
+ box-shadow: var(--shadow-md);
142
+ }
143
+
144
+ .file-action-btn {
145
+ align-items: center;
146
+ background: transparent;
147
+ border: none;
148
+ border-right: 1px solid var(--border-primary);
149
+ color: var(--text-secondary);
150
+ cursor: pointer;
151
+ display: inline-flex;
152
+ font-size: 12px;
153
+ font-weight: 500;
154
+ gap: 6px;
155
+ justify-content: center;
156
+ padding: 7px 14px;
157
+ position: relative;
158
+ text-decoration: none;
159
+ transition: all var(--transition-base);
160
+ white-space: nowrap;
161
+ }
162
+
163
+ .file-action-btn:last-child {
164
+ border-right: none;
165
+ }
166
+
167
+ .file-action-btn:hover {
168
+ background: linear-gradient(180deg, var(--hover-bg) 0%, var(--bg-tertiary) 100%);
169
+ color: var(--text-primary);
170
+ transform: translateY(-1px);
171
+ }
172
+
173
+ .file-action-btn:active {
174
+ background: var(--hover-bg-strong);
175
+ transform: translateY(0);
176
+ }
177
+
178
+ .file-action-btn .file-action-label {
179
+ color: inherit;
180
+ }
181
+
182
+ .file-action-icon {
183
+ fill: currentColor;
184
+ flex-shrink: 0;
185
+ }
186
+
187
+ .copy-raw-btn {
188
+ padding: 6px;
189
+ }
190
+
191
+ .file-action-btn:first-child {
192
+ border-radius: 6px 0 0 6px;
193
+ }
194
+
195
+ .file-action-btn:last-child {
196
+ border-radius: 0 6px 6px 0;
197
+ }
198
+
199
+ .file-action-group:has(.file-action-btn:only-child) .file-action-btn {
200
+ border-radius: 6px;
201
+ border-right: none;
202
+ }
203
+
204
+ /* ========================================
205
+ File Content Container
206
+ ======================================== */
207
+
208
+ .file-content {
209
+ backdrop-filter: blur(10px);
210
+ background: var(--bg-card);
211
+ border: 1px solid var(--border-subtle);
212
+ border-radius: var(--radius-xl);
213
+ box-shadow: var(--shadow-lg);
214
+ overflow: auto;
215
+ position: relative;
216
+ transition: all var(--transition-base);
217
+ }
218
+
219
+ .file-content::before {
220
+ background: linear-gradient(90deg, transparent 0%, var(--link-color) 50%, transparent 100%);
221
+ content: '';
222
+ height: 1px;
223
+ left: 0;
224
+ opacity: 0.3;
225
+ position: absolute;
226
+ right: 0;
227
+ top: 0;
228
+ }
229
+
230
+ .file-content:hover {
231
+ border-color: var(--border-primary);
232
+ box-shadow: var(--shadow-xl);
233
+ transform: translateY(-1px);
234
+ }
235
+
236
+ .file-content pre {
237
+ background-color: var(--bg-primary);
238
+ font-size: 13px;
239
+ line-height: 22px;
240
+ margin: 0;
241
+ overflow-x: auto;
242
+ padding: 16px 0;
243
+ }
244
+
245
+ .file-content code {
246
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
247
+ font-size: 12px;
248
+ font-weight: 400;
249
+ }
250
+
251
+ /* ========================================
252
+ Line Numbers
253
+ ======================================== */
254
+
255
+ .with-line-numbers {
256
+ counter-reset: line;
257
+ display: block;
258
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
259
+ font-weight: 400;
260
+ }
261
+
262
+ .line-container {
263
+ border-left: 2px solid transparent;
264
+ display: block;
265
+ line-height: 20px;
266
+ min-height: 20px;
267
+ padding: 0;
268
+ position: relative;
269
+ transition: all var(--transition-base);
270
+ }
271
+
272
+ .line-container:hover {
273
+ background-color: rgba(110, 118, 129, 0.08);
274
+ border-left-color: var(--border-primary);
275
+ }
276
+
277
+ .line-container.selected {
278
+ background: linear-gradient(90deg, rgba(255, 251, 221, 0.4) 0%, rgba(255, 251, 221, 0.2) 100%);
279
+ border-left-color: rgba(255, 235, 59, 0.6);
280
+ }
281
+
282
+ [data-theme="dark"] .line-container.selected {
283
+ background: linear-gradient(90deg, rgba(187, 128, 9, 0.2) 0%, rgba(187, 128, 9, 0.1) 100%);
284
+ border-left-color: rgba(255, 235, 59, 0.5);
285
+ }
286
+
287
+ .line-number {
288
+ -webkit-user-select: none;
289
+ background: transparent;
290
+ border-right: 1px solid var(--border-primary);
291
+ color: var(--text-secondary);
292
+ cursor: pointer;
293
+ display: inline-block;
294
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
295
+ font-size: 12px;
296
+ font-weight: 400;
297
+ line-height: 20px;
298
+ margin-right: 0;
299
+ opacity: 0.7;
300
+ padding: 0 10px;
301
+ text-align: right;
302
+ text-decoration: none;
303
+ transition: all var(--transition-base);
304
+ user-select: none;
305
+ width: 56px;
306
+ }
307
+
308
+ .line-number:hover {
309
+ background: rgba(88, 166, 255, 0.08);
310
+ border-right-color: var(--link-color);
311
+ color: var(--link-color);
312
+ opacity: 1;
313
+ text-decoration: none;
314
+ }
315
+
316
+ .line-content {
317
+ display: inline;
318
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
319
+ font-size: 12px;
320
+ font-weight: 400;
321
+ letter-spacing: normal;
322
+ line-height: 20px;
323
+ padding: 0 10px;
324
+ white-space: pre;
325
+ }
326
+
327
+ /* Line highlight flash animation */
328
+ .line-highlight-flash {
329
+ animation: lineFlash 2s ease-out;
330
+ }
331
+
332
+ @keyframes lineFlash {
333
+ 0% {
334
+ background: rgba(96, 165, 250, 0.3);
335
+ }
336
+ 100% {
337
+ background: transparent;
338
+ }
339
+ }
340
+
341
+ [data-theme="light"] .line-highlight-flash {
342
+ animation: lineFlashLight 2s ease-out;
343
+ }
344
+
345
+ @keyframes lineFlashLight {
346
+ 0% {
347
+ background: rgba(37, 99, 235, 0.2);
348
+ }
349
+ 100% {
350
+ background: transparent;
351
+ }
352
+ }
353
+
354
+ /* ========================================
355
+ Image Viewing
356
+ ======================================== */
357
+
358
+ .image-container {
359
+ background-color: var(--bg-primary);
360
+ border-radius: 6px;
361
+ padding: 20px;
362
+ text-align: center;
363
+ }
364
+
365
+ .image-display {
366
+ background: var(--bg-secondary);
367
+ border-radius: 6px;
368
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
369
+ height: auto;
370
+ max-height: 80vh;
371
+ max-width: 100%;
372
+ }
373
+
374
+ [data-theme="light"] .image-display {
375
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06);
376
+ }
377
+
378
+ .image-info {
379
+ border-top: 1px solid var(--border-primary);
380
+ margin-top: 16px;
381
+ padding-top: 16px;
382
+ }
383
+
384
+ .image-filename {
385
+ color: var(--text-primary);
386
+ font-size: 14px;
387
+ font-weight: 600;
388
+ }
389
+
390
+ /* ========================================
391
+ Binary File Viewing
392
+ ======================================== */
393
+
394
+ .binary-file-container {
395
+ background-color: var(--bg-primary);
396
+ border: 1px solid var(--border-primary);
397
+ border-radius: 6px;
398
+ padding: 40px 20px;
399
+ text-align: center;
400
+ }
401
+
402
+ .binary-file-info h3 {
403
+ color: var(--text-primary);
404
+ font-size: 18px;
405
+ font-weight: 600;
406
+ margin-bottom: 12px;
407
+ }
408
+
409
+ .binary-file-info p {
410
+ color: var(--text-secondary);
411
+ font-size: 14px;
412
+ margin-bottom: 20px;
413
+ }
414
+
415
+ .binary-file-info .btn {
416
+ align-items: center;
417
+ border: 1px solid transparent;
418
+ border-radius: 6px;
419
+ cursor: pointer;
420
+ display: inline-flex;
421
+ font-size: 14px;
422
+ font-weight: 500;
423
+ gap: 8px;
424
+ padding: 8px 16px;
425
+ text-decoration: none;
426
+ }
427
+
428
+ .binary-file-info .btn-primary {
429
+ background-color: var(--link-color);
430
+ color: white;
431
+ }
432
+
433
+ .binary-file-info .btn-primary:hover {
434
+ opacity: 0.9;
435
+ }
436
+
437
+ /* ========================================
438
+ README Section
439
+ ======================================== */
440
+
441
+ .readme-section {
442
+ background: var(--bg-primary);
443
+ border: 1px solid var(--border-primary);
444
+ border-radius: 8px;
445
+ margin-top: 32px;
446
+ overflow: hidden;
447
+ }
448
+
449
+ .readme-header {
450
+ background: var(--bg-secondary);
451
+ border-bottom: 1px solid var(--border-primary);
452
+ padding: 12px 16px;
453
+ }
454
+
455
+ .readme-header h2 {
456
+ align-items: center;
457
+ color: var(--text-accent);
458
+ display: flex;
459
+ font-size: 14px;
460
+ font-weight: 600;
461
+ margin: 0;
462
+ }
463
+
464
+ .readme-icon {
465
+ fill: currentColor;
466
+ height: 16px;
467
+ margin-right: 8px;
468
+ width: 16px;
469
+ }
470
+
471
+ .readme-content {
472
+ max-height: none;
473
+ overflow-y: visible;
474
+ padding: 32px;
475
+ }
476
+
477
+ .readme-content .markdown {
478
+ padding: 0;
479
+ }
480
+
481
+ /* ========================================
482
+ Markdown Rendering
483
+ ======================================== */
484
+
485
+ .markdown {
486
+ font-size: 16px;
487
+ line-height: 1.6;
488
+ max-width: 100%;
489
+ padding: 32px;
490
+ }
491
+
492
+ .markdown h1 {
493
+ border-bottom: 1px solid var(--border-primary);
494
+ color: var(--text-accent);
495
+ font-size: 2rem;
496
+ font-weight: 600;
497
+ line-height: 1.25;
498
+ margin: 0 0 24px 0;
499
+ padding-bottom: 12px;
500
+ }
501
+
502
+ .markdown h2 {
503
+ border-bottom: 1px solid var(--border-secondary);
504
+ color: var(--text-accent);
505
+ font-size: 1.5rem;
506
+ font-weight: 600;
507
+ line-height: 1.25;
508
+ margin: 32px 0 16px 0;
509
+ padding-bottom: 8px;
510
+ }
511
+
512
+ .markdown h3 {
513
+ border: none;
514
+ color: var(--text-accent);
515
+ font-size: 1.25rem;
516
+ font-weight: 600;
517
+ line-height: 1.25;
518
+ margin: 24px 0 16px 0;
519
+ }
520
+
521
+ .markdown h4 {
522
+ border: none;
523
+ color: var(--text-accent);
524
+ font-size: 1rem;
525
+ font-weight: 600;
526
+ line-height: 1.25;
527
+ margin: 24px 0 16px 0;
528
+ }
529
+
530
+ .markdown h5,
531
+ .markdown h6 {
532
+ border: none;
533
+ color: var(--text-accent);
534
+ font-size: 0.875rem;
535
+ font-weight: 600;
536
+ line-height: 1.25;
537
+ margin: 20px 0 12px 0;
538
+ }
539
+
540
+ .markdown p {
541
+ color: var(--text-primary);
542
+ font-size: 16px;
543
+ line-height: 1.6;
544
+ margin-bottom: 16px;
545
+ }
546
+
547
+ .markdown ul,
548
+ .markdown ol {
549
+ list-style: none;
550
+ margin-bottom: 16px;
551
+ padding-left: 0;
552
+ }
553
+
554
+ .markdown li {
555
+ color: var(--text-primary);
556
+ font-size: 16px;
557
+ line-height: 1.6;
558
+ margin-bottom: 8px;
559
+ padding-left: 24px;
560
+ position: relative;
561
+ }
562
+
563
+ .markdown ul li:before {
564
+ color: var(--text-secondary);
565
+ content: "\2022";
566
+ font-size: 18px;
567
+ left: 0;
568
+ position: absolute;
569
+ top: 0;
570
+ }
571
+
572
+ .markdown ol {
573
+ counter-reset: item;
574
+ }
575
+
576
+ .markdown ol li {
577
+ counter-increment: item;
578
+ padding-left: 32px;
579
+ }
580
+
581
+ .markdown ol li:before {
582
+ color: var(--text-secondary);
583
+ content: counter(item) ".";
584
+ font-weight: 600;
585
+ left: 0;
586
+ position: absolute;
587
+ top: 0;
588
+ }
589
+
590
+ .markdown li strong {
591
+ color: var(--text-accent);
592
+ font-weight: 600;
593
+ }
594
+
595
+ .markdown code {
596
+ background-color: var(--bg-secondary);
597
+ border: 1px solid var(--border-primary);
598
+ border-radius: 6px;
599
+ color: var(--text-accent);
600
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
601
+ font-size: 85%;
602
+ padding: 3px 6px;
603
+ }
604
+
605
+ .markdown pre {
606
+ background-color: var(--bg-primary);
607
+ border: 1px solid var(--border-primary);
608
+ border-radius: 6px;
609
+ margin: 16px 0;
610
+ overflow-x: auto;
611
+ padding: 16px;
612
+ }
613
+
614
+ .markdown pre code {
615
+ background: none;
616
+ border: none;
617
+ color: var(--text-primary);
618
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
619
+ font-size: 12px;
620
+ line-height: 20px;
621
+ padding: 0;
622
+ }
623
+
624
+ .markdown blockquote {
625
+ border-left: 4px solid var(--border-primary);
626
+ color: var(--text-secondary);
627
+ font-style: italic;
628
+ margin: 16px 0;
629
+ padding-left: 16px;
630
+ }
631
+
632
+ .markdown a {
633
+ color: var(--link-color);
634
+ text-decoration: none;
635
+ }
636
+
637
+ .markdown a:hover {
638
+ text-decoration: underline;
639
+ }
640
+
641
+ .markdown table {
642
+ border-collapse: collapse;
643
+ margin-bottom: 16px;
644
+ width: 100%;
645
+ }
646
+
647
+ .markdown table th,
648
+ .markdown table td {
649
+ border: 1px solid var(--border-primary);
650
+ padding: 8px 12px;
651
+ text-align: left;
652
+ }
653
+
654
+ .markdown table th {
655
+ background-color: var(--bg-secondary);
656
+ color: var(--text-accent);
657
+ font-weight: 600;
658
+ }
659
+
660
+ .markdown hr {
661
+ border: none;
662
+ border-top: 1px solid var(--border-primary);
663
+ margin: 24px 0;
664
+ }
665
+
666
+ /* ========================================
667
+ Syntax Highlighting (highlight.js)
668
+ Uses CSS variables for theme support
669
+ ======================================== */
670
+
671
+ /* Base hljs container */
672
+ .hljs {
673
+ background: var(--bg-primary);
674
+ color: var(--text-primary);
675
+ display: block;
676
+ overflow-x: auto;
677
+ padding: 0;
678
+ }
679
+
680
+ /* Comments */
681
+ .hljs-comment,
682
+ .hljs-quote {
683
+ color: var(--hljs-comment);
684
+ font-style: italic;
685
+ }
686
+
687
+ /* Keywords */
688
+ .hljs-doctag,
689
+ .hljs-keyword,
690
+ .hljs-formula {
691
+ color: var(--hljs-keyword);
692
+ }
693
+
694
+ .hljs-section,
695
+ .hljs-name,
696
+ .hljs-selector-tag,
697
+ .hljs-deletion,
698
+ .hljs-subst {
699
+ color: var(--hljs-keyword);
700
+ }
701
+
702
+ /* Literals/Numbers */
703
+ .hljs-literal {
704
+ color: var(--hljs-number);
705
+ }
706
+
707
+ .hljs-attr,
708
+ .hljs-variable,
709
+ .hljs-template-variable,
710
+ .hljs-type,
711
+ .hljs-selector-class,
712
+ .hljs-selector-attr,
713
+ .hljs-selector-pseudo,
714
+ .hljs-number {
715
+ color: var(--hljs-number);
716
+ }
717
+
718
+ .hljs-symbol,
719
+ .hljs-bullet,
720
+ .hljs-link,
721
+ .hljs-meta,
722
+ .hljs-selector-id,
723
+ .hljs-title {
724
+ color: var(--hljs-number);
725
+ }
726
+
727
+ /* Strings */
728
+ .hljs-string,
729
+ .hljs-regexp,
730
+ .hljs-addition,
731
+ .hljs-attribute,
732
+ .hljs-meta-string {
733
+ color: var(--hljs-string);
734
+ }
735
+
736
+ /* Built-ins/Classes */
737
+ .hljs-built_in,
738
+ .hljs-class .hljs-title {
739
+ color: var(--hljs-builtin);
740
+ }
741
+
742
+ .hljs-title.class_ {
743
+ color: var(--hljs-builtin);
744
+ }
745
+
746
+ /* Functions */
747
+ .hljs-function,
748
+ .hljs-params {
749
+ color: var(--hljs-function);
750
+ }
751
+
752
+ .hljs-title.function_ {
753
+ color: var(--hljs-function);
754
+ }
755
+
756
+ /* Tags (HTML/XML) */
757
+ .hljs-tag {
758
+ color: var(--hljs-tag);
759
+ }
760
+
761
+ /* Properties */
762
+ .hljs-property {
763
+ color: var(--hljs-number);
764
+ }
765
+
766
+ /* Text styles */
767
+ .hljs-emphasis {
768
+ font-style: italic;
769
+ }
770
+
771
+ .hljs-strong {
772
+ font-weight: bold;
773
+ }
774
+
775
+ .hljs-link {
776
+ text-decoration: underline;
777
+ }
778
+
779
+ /* ========================================
780
+ Diff Viewer
781
+ ======================================== */
782
+
783
+ .diff-container {
784
+ background: var(--bg-primary);
785
+ display: flex;
786
+ height: 100%;
787
+ margin: 0;
788
+ overflow-x: auto;
789
+ overflow-y: visible;
790
+ padding: 0;
791
+ width: 100%;
792
+ }
793
+
794
+ .diff-content {
795
+ display: block;
796
+ min-width: 100%;
797
+ padding: 0;
798
+ }
799
+
800
+ .raw-diff-container {
801
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
802
+ font-size: 12px;
803
+ font-weight: 400;
804
+ line-height: 20px;
805
+ min-width: max-content;
806
+ }
807
+
808
+ .diff-side {
809
+ border-right: 1px solid var(--border-primary);
810
+ display: flex;
811
+ flex: 1;
812
+ flex-direction: column;
813
+ }
814
+
815
+ .diff-side:last-child {
816
+ border-right: none;
817
+ }
818
+
819
+ .diff-side-header {
820
+ background: var(--bg-secondary);
821
+ border-bottom: 1px solid var(--border-primary);
822
+ color: var(--text-secondary);
823
+ font-size: 12px;
824
+ font-weight: 600;
825
+ padding: 8px 16px;
826
+ }
827
+
828
+ .diff-side-content {
829
+ flex: 1;
830
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
831
+ font-size: 12px;
832
+ font-weight: 400;
833
+ line-height: 20px;
834
+ overflow: auto;
835
+ }
836
+
837
+ .diff-line {
838
+ align-items: stretch;
839
+ color: var(--text-primary);
840
+ display: flex;
841
+ line-height: 20px;
842
+ min-height: 20px;
843
+ transition: background-color 0.1s ease;
844
+ white-space: pre;
845
+ }
846
+
847
+ .diff-line:hover {
848
+ background-color: var(--hover-bg);
849
+ }
850
+
851
+ .diff-line-number {
852
+ background: var(--bg-secondary);
853
+ border-right: 1px solid var(--border-primary);
854
+ color: var(--text-secondary);
855
+ display: inline-block;
856
+ flex-shrink: 0;
857
+ font-variant-numeric: tabular-nums;
858
+ max-width: 50px;
859
+ min-width: 50px;
860
+ padding: 0 8px;
861
+ text-align: right;
862
+ user-select: none;
863
+ }
864
+
865
+ .diff-line-number.old {
866
+ border-right: none;
867
+ }
868
+
869
+ .diff-line-number.new {
870
+ border-right: 1px solid var(--border-primary);
871
+ }
872
+
873
+ .diff-line-number:empty::before {
874
+ content: '\00a0';
875
+ }
876
+
877
+ .diff-line-content {
878
+ flex: 1;
879
+ min-width: 0;
880
+ overflow-x: auto;
881
+ padding: 0 10px;
882
+ white-space: pre;
883
+ }
884
+
885
+ .diff-line-added {
886
+ background: rgba(46, 160, 67, 0.15);
887
+ }
888
+
889
+ .diff-line-added .diff-line-number {
890
+ background: rgba(46, 160, 67, 0.1);
891
+ }
892
+
893
+ .diff-line-removed {
894
+ background: rgba(248, 81, 73, 0.15);
895
+ }
896
+
897
+ .diff-line-removed .diff-line-number {
898
+ background: rgba(248, 81, 73, 0.1);
899
+ }
900
+
901
+ .diff-line-context {
902
+ background: var(--bg-primary);
903
+ }
904
+
905
+ .diff-line-hunk {
906
+ background: rgba(88, 166, 255, 0.1);
907
+ color: #58a6ff;
908
+ font-weight: 600;
909
+ }
910
+
911
+ .diff-line-hunk .diff-line-number {
912
+ background: rgba(88, 166, 255, 0.05);
913
+ }
914
+
915
+ .diff-line-header {
916
+ background: var(--bg-secondary);
917
+ color: var(--text-secondary);
918
+ font-weight: 500;
919
+ opacity: 0.9;
920
+ }
921
+
922
+ .diff-line-header .diff-line-number {
923
+ background: var(--bg-secondary);
924
+ }
925
+
926
+ [data-theme="light"] .diff-line-added {
927
+ background: rgba(46, 160, 67, 0.1);
928
+ }
929
+
930
+ [data-theme="light"] .diff-line-added .diff-line-number {
931
+ background: rgba(46, 160, 67, 0.08);
932
+ }
933
+
934
+ [data-theme="light"] .diff-line-removed {
935
+ background: rgba(248, 81, 73, 0.1);
936
+ }
937
+
938
+ [data-theme="light"] .diff-line-removed .diff-line-number {
939
+ background: rgba(248, 81, 73, 0.08);
940
+ }
941
+
942
+ [data-theme="light"] .diff-line-hunk {
943
+ background: rgba(9, 105, 218, 0.1);
944
+ color: #0969da;
945
+ }
946
+
947
+ [data-theme="light"] .diff-line-hunk .diff-line-number {
948
+ background: rgba(9, 105, 218, 0.05);
949
+ }
950
+
951
+ .diff-stats {
952
+ align-items: center;
953
+ display: flex;
954
+ font-size: 12px;
955
+ gap: 16px;
956
+ }
957
+
958
+ .diff-stat {
959
+ align-items: center;
960
+ display: flex;
961
+ gap: 4px;
962
+ }
963
+
964
+ .diff-stat-added {
965
+ color: #28a745;
966
+ }
967
+
968
+ .diff-stat-removed {
969
+ color: #dc3545;
970
+ }
971
+
972
+ .no-changes {
973
+ color: var(--text-secondary);
974
+ font-style: italic;
975
+ padding: 40px;
976
+ text-align: center;
977
+ }
978
+
979
+ /* ========================================
980
+ Octicons
981
+ ======================================== */
982
+
983
+ .octicon-file,
984
+ .octicon-directory,
985
+ .octicon-breadcrumb,
986
+ .octicon-separator,
987
+ .octicon-home,
988
+ .octicon-branch,
989
+ .octicon-small,
990
+ .octicon-chevron,
991
+ .octicon-copy {
992
+ fill: currentColor;
993
+ height: 16px;
994
+ vertical-align: text-bottom;
995
+ width: 16px;
996
+ }
997
+
998
+ .octicon-directory {
999
+ color: #7dd3fc;
1000
+ fill: #7dd3fc;
1001
+ }
1002
+
1003
+ [data-theme="light"] .octicon-directory {
1004
+ color: #54adf5;
1005
+ fill: #54adf5;
1006
+ }
1007
+
1008
+ .octicon-branch {
1009
+ fill: var(--text-secondary);
1010
+ height: 16px;
1011
+ width: 16px;
1012
+ }
1013
+
1014
+ .octicon-small {
1015
+ fill: var(--text-secondary);
1016
+ height: 14px;
1017
+ width: 14px;
1018
+ }
1019
+
1020
+ .octicon-chevron {
1021
+ fill: var(--text-secondary);
1022
+ height: 12px;
1023
+ width: 12px;
1024
+ }
1025
+
1026
+ .octicon-home {
1027
+ margin-right: 8px;
1028
+ }
1029
+
1030
+ .octicon-separator {
1031
+ height: 12px;
1032
+ margin: 0 4px;
1033
+ opacity: 0.7;
1034
+ width: 12px;
1035
+ }
1036
+
1037
+ /* ========================================
1038
+ Text Colors
1039
+ ======================================== */
1040
+
1041
+ .text-yellow {
1042
+ color: #f9c513;
1043
+ fill: #f9c513;
1044
+ }
1045
+
1046
+ .text-blue {
1047
+ color: #0969da;
1048
+ fill: #0969da;
1049
+ }
1050
+
1051
+ .text-green {
1052
+ color: #1a7f37;
1053
+ fill: #1a7f37;
1054
+ }
1055
+
1056
+ .text-red {
1057
+ color: #cf222e;
1058
+ fill: #cf222e;
1059
+ }
1060
+
1061
+ .text-orange {
1062
+ color: #fb8500;
1063
+ fill: #fb8500;
1064
+ }
1065
+
1066
+ .text-purple {
1067
+ color: #8250df;
1068
+ fill: #8250df;
1069
+ }
1070
+
1071
+ .text-gray {
1072
+ color: var(--text-secondary);
1073
+ fill: var(--text-secondary);
1074
+ }
1075
+
1076
+ [data-theme="light"] .text-yellow {
1077
+ color: #dbab09;
1078
+ fill: #dbab09;
1079
+ }
1080
+
1081
+ [data-theme="light"] .text-blue {
1082
+ color: #0550ae;
1083
+ fill: #0550ae;
1084
+ }
1085
+
1086
+ [data-theme="light"] .text-green {
1087
+ color: #116329;
1088
+ fill: #116329;
1089
+ }
1090
+
1091
+ [data-theme="light"] .text-red {
1092
+ color: #82071e;
1093
+ fill: #82071e;
1094
+ }
1095
+
1096
+ [data-theme="light"] .text-orange {
1097
+ color: #bc4c00;
1098
+ fill: #bc4c00;
1099
+ }
1100
+
1101
+ [data-theme="light"] .text-purple {
1102
+ color: #6f42c1;
1103
+ fill: #6f42c1;
1104
+ }
1105
+
1106
+ /* ========================================
1107
+ Git Status Colors
1108
+ ======================================== */
1109
+
1110
+ .git-status {
1111
+ border-radius: 4px;
1112
+ display: inline;
1113
+ line-height: inherit;
1114
+ margin-left: 8px;
1115
+ opacity: 0.8;
1116
+ padding: 0;
1117
+ vertical-align: middle;
1118
+ }
1119
+
1120
+ .git-status-icon {
1121
+ display: inline;
1122
+ fill: currentColor;
1123
+ height: 10px;
1124
+ vertical-align: middle;
1125
+ width: 10px;
1126
+ }
1127
+
1128
+ .git-status-M {
1129
+ color: #d29922;
1130
+ }
1131
+
1132
+ .git-status-A {
1133
+ color: #2ea043;
1134
+ }
1135
+
1136
+ .git-status-D {
1137
+ color: #f85149;
1138
+ }
1139
+
1140
+ .git-status-R {
1141
+ color: #1f6feb;
1142
+ }
1143
+
1144
+ .git-status-\?\? {
1145
+ color: #a371f7;
1146
+ }
1147
+
1148
+ .git-status-MM,
1149
+ .git-status-AM,
1150
+ .git-status-AD {
1151
+ color: #db6d28;
1152
+ }
1153
+
1154
+ .git-status-untracked {
1155
+ color: #7c3aed !important;
1156
+ }
1157
+
1158
+ [data-theme="light"] .git-status-M {
1159
+ color: #bf8700;
1160
+ }
1161
+
1162
+ [data-theme="light"] .git-status-A {
1163
+ color: #1a7f37;
1164
+ }
1165
+
1166
+ [data-theme="light"] .git-status-D {
1167
+ color: #cf222e;
1168
+ }
1169
+
1170
+ [data-theme="light"] .git-status-R {
1171
+ color: #0969da;
1172
+ }
1173
+
1174
+ [data-theme="light"] .git-status-MM,
1175
+ [data-theme="light"] .git-status-AM,
1176
+ [data-theme="light"] .git-status-AD {
1177
+ color: #9a6700;
1178
+ }
1179
+
1180
+ [data-theme="light"] .git-status-untracked {
1181
+ color: #8b5cf6 !important;
1182
+ }
1183
+
1184
+ .file-table .col-icon .git-status {
1185
+ font-size: 12px;
1186
+ }
1187
+
1188
+ /* Git status colored icons in file rows */
1189
+ [data-theme="dark"] .file-row--added .icon .octicon-directory,
1190
+ [data-theme="dark"] .file-row--added .icon .octicon-file {
1191
+ color: #2ea043;
1192
+ fill: #2ea043;
1193
+ }
1194
+
1195
+ [data-theme="dark"] .file-row--deleted .icon .octicon-directory,
1196
+ [data-theme="dark"] .file-row--deleted .icon .octicon-file {
1197
+ color: #f85149;
1198
+ fill: #f85149;
1199
+ }
1200
+
1201
+ [data-theme="dark"] .file-row--modified .icon .octicon-directory,
1202
+ [data-theme="dark"] .file-row--modified .icon .octicon-file {
1203
+ color: #d29922;
1204
+ fill: #d29922;
1205
+ }
1206
+
1207
+ [data-theme="dark"] .file-row--renamed .icon .octicon-directory,
1208
+ [data-theme="dark"] .file-row--renamed .icon .octicon-file {
1209
+ color: #1f6feb;
1210
+ fill: #1f6feb;
1211
+ }
1212
+
1213
+ [data-theme="dark"] .file-row--untracked .icon .octicon-directory,
1214
+ [data-theme="dark"] .file-row--untracked .icon .octicon-file {
1215
+ color: #a371f7;
1216
+ fill: #a371f7;
1217
+ }
1218
+
1219
+ [data-theme="dark"] .file-row--mixed .icon .octicon-directory,
1220
+ [data-theme="dark"] .file-row--mixed .icon .octicon-file {
1221
+ color: #db6d28;
1222
+ fill: #db6d28;
1223
+ }
1224
+
1225
+ [data-theme="light"] .file-row--added .icon .octicon-directory,
1226
+ [data-theme="light"] .file-row--added .icon .octicon-file {
1227
+ color: #1a7f37;
1228
+ fill: #1a7f37;
1229
+ }
1230
+
1231
+ [data-theme="light"] .file-row--deleted .icon .octicon-directory,
1232
+ [data-theme="light"] .file-row--deleted .icon .octicon-file {
1233
+ color: #cf222e;
1234
+ fill: #cf222e;
1235
+ }
1236
+
1237
+ [data-theme="light"] .file-row--modified .icon .octicon-directory,
1238
+ [data-theme="light"] .file-row--modified .icon .octicon-file {
1239
+ color: #bf8700;
1240
+ fill: #bf8700;
1241
+ }
1242
+
1243
+ [data-theme="light"] .file-row--renamed .icon .octicon-directory,
1244
+ [data-theme="light"] .file-row--renamed .icon .octicon-file {
1245
+ color: #0969da;
1246
+ fill: #0969da;
1247
+ }
1248
+
1249
+ [data-theme="light"] .file-row--untracked .icon .octicon-directory,
1250
+ [data-theme="light"] .file-row--untracked .icon .octicon-file {
1251
+ color: #8250df;
1252
+ fill: #8250df;
1253
+ }
1254
+
1255
+ [data-theme="light"] .file-row--mixed .icon .octicon-directory,
1256
+ [data-theme="light"] .file-row--mixed .icon .octicon-file {
1257
+ color: #9a6700;
1258
+ fill: #9a6700;
1259
+ }