cerrado @ 358d4691f44fbee5f388b68458f41f4038464a0b

feat: Adapt scss to support dark mode
  1diff --git a/scss/main.scss b/scss/main.scss
  2index e0fecf162da0f98f0f1ef6e3405d05c9664fdf81..a98c0a2e43b6cfb15bafd82109dd1a64f4295ec2 100644
  3--- a/scss/main.scss
  4+++ b/scss/main.scss
  5@@ -12,7 +12,7 @@
  6 // basic functionality
  7 @import "bootstrap/scss/_functions.scss";
  8 @import "bootstrap/scss/_variables.scss";
  9-@import "bootstrap/scss/_variables-dark.scss";
 10+//@import "bootstrap/scss/_variables-dark.scss";
 11 @import "bootstrap/scss/_maps.scss";
 12 @import "bootstrap/scss/_mixins.scss";
 13 @import "bootstrap/scss/_utilities.scss";
 14@@ -27,6 +27,7 @@ @import "bootstrap/scss/_navbar.scss";
 15 @import "bootstrap/scss/_grid.scss";
 16 @import "bootstrap/scss/_forms.scss";
 17 @import "bootstrap/scss/_buttons.scss";
 18+@import "bootstrap/scss/mixins/_color-mode.scss";
 19 @import "tree.scss";
 20 
 21 // overwrite to reduce the ammount of css generated by loading all utilities
 22@@ -80,6 +81,12 @@     font-size: $base-font-size;
 23     margin: 0;
 24 }
 25 
 26+@include color-mode(dark) {
 27+    body {
 28+        background: #212529;
 29+    }
 30+}
 31+
 32 // prevert wierd input overflowing 100%
 33 input {
 34     width: 100%;
 35@@ -116,6 +123,12 @@     margin: 0.5rem 0;
 36     background: #f8f9fa;
 37 }
 38 
 39+@include color-mode(dark) {
 40+    .event {
 41+        background: #131618;
 42+    }
 43+}
 44+
 45 .event-commit {
 46     background: #dadada;
 47     padding: 5px;
 48@@ -132,6 +145,13 @@     text-align: end;
 49 
 50     @include media-breakpoint-down(xl) {
 51         text-align: start;
 52+    }
 53+}
 54+
 55+
 56+@include color-mode(dark) {
 57+    .event-commit {
 58+        background: #000;
 59     }
 60 }
 61 
 62diff --git a/scss/tree.scss b/scss/tree.scss
 63index 05828dc61747425bebb694e5ce3743b975e94aa7..58258bd921e2dc2f06d0339233fdbbf957f54952 100644
 64--- a/scss/tree.scss
 65+++ b/scss/tree.scss
 66@@ -53,6 +53,20 @@     .size {
 67         color: $gray-700;
 68     }
 69 
 70+    @media(prefers-color-scheme: dark) {
 71+        .name.blob a {
 72+            color: inherit;
 73+        }
 74+
 75+        .mode,
 76+        .commit,
 77+        .commit a,
 78+        .date,
 79+        .size {
 80+            color: inherit;
 81+        }
 82+    }
 83+
 84     .name.blob {
 85         text-overflow: ellipsis;
 86         white-space: nowrap;
 87@@ -85,7 +99,392 @@
 88             // Striped rows
 89             &:nth-child(10n+#{$i}) {
 90                 background: rgba(0, 0, 0, .05);
 91+
 92+                @media(prefers-color-scheme: dark) {
 93+                    background: lighten($gray-900, 5);
 94+                }
 95             }
 96         }
 97     }
 98 }
 99+
100+.code-view {
101+    display: grid;
102+    grid-template-columns: auto auto auto 1fr;
103+    grid-template-rows: auto;
104+
105+    .blame-user {
106+        grid-column-start: 1;
107+        grid-row-start: 1;
108+        background: #ddd;
109+
110+        @media(prefers-color-scheme: dark) {
111+            background: $gray-900;
112+        }
113+
114+        .hunk {
115+            padding-left: 0.5rem;
116+        }
117+    }
118+
119+    .blame-time {
120+        grid-column-start: 2;
121+        grid-row-start: 1;
122+        background: #ddd;
123+        border-right: 1px solid #444;
124+        text-align: right;
125+
126+        @media(prefers-color-scheme: dark) {
127+            background: $gray-900;
128+        }
129+
130+        .hunk {
131+            padding-right: 0.5rem;
132+        }
133+    }
134+
135+    .hunk:nth-child(2n) {
136+        background: #eee;
137+
138+        @media(prefers-color-scheme: dark) {
139+            background: lighten($gray-900, 5);
140+        }
141+    }
142+
143+    .lines {
144+        grid-column-start: 3;
145+        grid-row-start: 1;
146+        text-align: right;
147+        padding-left: 0.5rem;
148+        padding-right: 0.5rem;
149+
150+        background: #eee;
151+        border-right: 1px solid #444;
152+
153+        @media(prefers-color-scheme: dark) {
154+            background: lighten($gray-900, 5);
155+        }
156+
157+        a:target::before,
158+        a.selected::before {
159+            display: block;
160+            content: "";
161+            // +6px to connect multiple selected lines
162+            height: calc(1rem + 6px);
163+            width: 100%;
164+            z-index: -1;
165+            position: absolute;
166+            left: 0;
167+            background: lighten($blue, 35);
168+
169+            @media(prefers-color-scheme: dark) {
170+                background: $black;
171+            }
172+        }
173+    }
174+
175+    .highlight {
176+        grid-column-start: 4;
177+        grid-row-start: 1;
178+        padding-left: 1rem;
179+        background: transparent;
180+        overflow-x: hidden;
181+
182+        pre {
183+            background: transparent;
184+        }
185+    }
186+
187+    .ruler {
188+        background: transparent;
189+        grid-column-start: 4;
190+        grid-row-start: 1;
191+        display: block;
192+        padding-left: calc(1rem + 4px);
193+        height: 100%;
194+        pointer-events: none;
195+        overflow-x: hidden;
196+
197+        pre {
198+            background: transparent;
199+        }
200+
201+        &>span {
202+            height: 100%;
203+            display: inline-block;
204+            border-right: 1px solid $gray-200;
205+
206+            @media(prefers-color-scheme: dark) {
207+                border-right: 1px solid #343a40;
208+            }
209+        }
210+    }
211+}
212+
213+.ref {
214+    border-width: 1px;
215+    border-style: solid;
216+    padding: 0.1rem 0.2rem;
217+
218+    &.branch {
219+        border-color: darken($info, 20);
220+        background: $info;
221+        color: $white !important;
222+    }
223+
224+    &.tag {
225+        border-color: darken($primary, 20);
226+        background: $primary;
227+        color: $white;
228+    }
229+
230+    &.tag.annotated {
231+        border-color: darken($success, 20);
232+        background: $success;
233+        color: $white;
234+    }
235+}
236+
237+.diff {
238+    .lineno {
239+        text-decoration: none;
240+    }
241+
242+    .text-success {
243+        color: color_adjust_contrast_AERT(darken($success, 10), white) !important;
244+    }
245+
246+    .text-danger {
247+        color: color_adjust_contrast_AERT(darken($danger, 10), white) !important;
248+    }
249+
250+    pre {
251+        background: transparent;
252+    }
253+
254+    @media(prefers-color-scheme: dark) {
255+        $success-dark: #2bb34b;
256+        $danger-dark: #ff3e3e;
257+
258+        .text-success {
259+            color: $success-dark !important;
260+        }
261+
262+        .text-danger {
263+            color: $danger-dark !important;
264+        }
265+    }
266+}
267+
268+img {
269+    max-width: 100%;
270+}
271+
272+.prepare-patchset {
273+    legend {
274+        font-weight: bold;
275+    }
276+
277+    label {
278+        margin-right: 1rem;
279+        cursor: pointer;
280+    }
281+
282+    details {
283+        display: inline;
284+        color: $gray-600;
285+
286+        &[open] {
287+            display: block;
288+            color: $black;
289+
290+            summary {
291+                color: $black;
292+            }
293+        }
294+
295+        ul {
296+            list-style: none;
297+            padding-left: 0;
298+        }
299+
300+        li {
301+            margin-top: 1rem;
302+        }
303+
304+        @media(prefers-color-scheme: dark) {
305+            color: $gray-500;
306+
307+            &[open] {
308+                color: $gray-100;
309+
310+                summary {
311+                    color: $gray-100;
312+                }
313+            }
314+        }
315+    }
316+
317+    .event-list {
318+        display: flex;
319+        flex-direction: column;
320+
321+        &.reverse {
322+            flex-direction: column-reverse;
323+        }
324+
325+        input[type="radio"] {
326+            display: none;
327+        }
328+
329+        &>.commit-diff {
330+            margin-top: 1rem;
331+            order: -2;
332+        }
333+
334+        &>.form-controls {
335+            order: -1;
336+            margin-top: 1rem;
337+            align-self: flex-end;
338+
339+            &.last {
340+                order: -3;
341+            }
342+        }
343+
344+        &>details {
345+            order: 0;
346+        }
347+
348+        &>.event {
349+            order: 1;
350+            display: block;
351+            margin: 0.25rem 0;
352+
353+            // Because the order is reversed
354+            &:last-child {
355+                margin: 0.25rem 0;
356+            }
357+
358+            &:first-child {
359+                margin: 0;
360+            }
361+        }
362+
363+        input[type="radio"]:checked~.event {
364+            background: lighten($info, 50) !important;
365+        }
366+
367+        input[type="radio"]:checked+.event {
368+            background: lighten($info, 45) !important;
369+        }
370+
371+        @media(prefers-color-scheme: dark) {
372+            input[type="radio"]:checked~.event {
373+                background: #131a3c !important;
374+            }
375+
376+            input[type="radio"]:checked+.event {
377+                background: #003038 !important;
378+            }
379+        }
380+    }
381+}
382+
383+.markdown-nav {
384+    padding-left: 0;
385+    padding-right: 0;
386+
387+    .nav-tabs {
388+        padding-left: 0;
389+        margin-bottom: 0;
390+        border-left: 1rem #ddd solid;
391+    }
392+}
393+
394+.blob-nav {
395+    display: inline-block;
396+    padding-left: 0;
397+    padding-right: 0;
398+
399+    .nav-item:hover {
400+        background: #fff;
401+    }
402+
403+    @media(prefers-color-scheme: dark) {
404+        .nav-item:hover {
405+            background: inherit;
406+        }
407+    }
408+
409+    .nav-tabs {
410+        padding-left: 0;
411+        margin-bottom: -3px;
412+        border-bottom: 3px transparent solid;
413+
414+        .nav-link {
415+            padding: 0 0.5rem;
416+
417+            &:hover {
418+                color: black;
419+            }
420+
421+            &.active {
422+                border-bottom: 3px #fff solid;
423+                background: #fff;
424+            }
425+
426+            @media(prefers-color-scheme: dark) {
427+                color: $gray-400;
428+
429+                &.active,
430+                &:hover {
431+                    border-bottom: 3px $gray-900 solid;
432+                    background: $gray-900;
433+                    color: $white;
434+                }
435+            }
436+        }
437+    }
438+}
439+
440+.tree-header {
441+    display: flex;
442+
443+    .breadcrumb {
444+        flex-grow: 1;
445+        width: 100%;
446+    }
447+
448+    .commit-info {
449+        margin-left: 1rem;
450+        white-space: nowrap;
451+        text-overflow: ellipsis;
452+        overflow: hidden;
453+        min-width: 0;
454+    }
455+}
456+
457+dl {
458+    dd {
459+        text-overflow: ellipsis;
460+        overflow-x: hidden;
461+    }
462+}
463+
464+@include media-breakpoint-up(md) {
465+    .blob {
466+        padding-left: 2rem;
467+
468+        .commit {
469+            float: right;
470+        }
471+    }
472+}
473+
474+.code-viewport {
475+    display: flex;
476+    flex: 1 0 auto;
477+    padding-left: 0;
478+    padding-right: 0;
479+}
480diff --git a/templates/base.qtpl b/templates/base.qtpl
481index db9deeed4f226872ce7a32728f8c5d9db0898b5f..b3df94a5b8b51f047b1403ddea94a376122fd844 100644
482--- a/templates/base.qtpl
483+++ b/templates/base.qtpl
484@@ -54,12 +54,13 @@
485 Page prints a page implementing Page interface.
486 {% func PageTemplate(p Page, ctx context.Context) %}
487 <!DOCTYPE html>
488-<html lang="en">
489+<html lang="en" data-bs-theme="light">
490   <head>
491     <meta charset="utf-8">
492     <link rel="icon" href="data:,">
493     <title>{%= p.Title(ctx) %}</title> 
494     <link rel="stylesheet" href="/static/main{%s Slug %}.css">
495+    <html data-bs-theme="dark">
496     <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
497     <meta name="viewport" content="width=device-width, initial-scale=1" />
498   </head>
499@@ -70,5 +71,8 @@       {%= p.Content(ctx) %}
500     </div>
501   </body>
502   {%= p.Script(ctx) %}
503+  <script>
504+  function a(){const e=window.matchMedia("(prefers-color-scheme: dark)").matches;document.documentElement.setAttribute("data-bs-theme",e?"dark":"light")}a(),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",a);
505+  </script>
506 </html>
507 {% endfunc %}
508diff --git a/templates/base.qtpl.go b/templates/base.qtpl.go
509index 796538ee9e81af6a386f75a825c5c8c13bbd27e6..dce4cbcf1c80f70254c7a2dc5bcbc3794414fc2d 100644
510--- a/templates/base.qtpl.go
511+++ b/templates/base.qtpl.go
512@@ -98,7 +98,7 @@ func StreamPageTemplate(qw422016 *qt422016.Writer, p Page, ctx context.Context) {
513 //line templates/base.qtpl:55
514 	qw422016.N().S(`
515 <!DOCTYPE html>
516-<html lang="en">
517+<html lang="en" data-bs-theme="light">
518   <head>
519     <meta charset="utf-8">
520     <link rel="icon" href="data:,">
521@@ -112,55 +112,59 @@ //line templates/base.qtpl:62
522 	qw422016.E().S(Slug)
523 //line templates/base.qtpl:62
524 	qw422016.N().S(`.css">
525+    <html data-bs-theme="dark">
526     <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
527     <meta name="viewport" content="width=device-width, initial-scale=1" />
528   </head>
529   <body>
530     `)
531-//line templates/base.qtpl:67
532+//line templates/base.qtpl:68
533 	p.StreamNavbar(qw422016, ctx)
534-//line templates/base.qtpl:67
535+//line templates/base.qtpl:68
536 	qw422016.N().S(`
537     <div class="container">
538       `)
539-//line templates/base.qtpl:69
540+//line templates/base.qtpl:70
541 	p.StreamContent(qw422016, ctx)
542-//line templates/base.qtpl:69
543+//line templates/base.qtpl:70
544 	qw422016.N().S(`
545     </div>
546   </body>
547   `)
548-//line templates/base.qtpl:72
549+//line templates/base.qtpl:73
550 	p.StreamScript(qw422016, ctx)
551-//line templates/base.qtpl:72
552+//line templates/base.qtpl:73
553 	qw422016.N().S(`
554+  <script>
555+  function a(){const e=window.matchMedia("(prefers-color-scheme: dark)").matches;document.documentElement.setAttribute("data-bs-theme",e?"dark":"light")}a(),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",a);
556+  </script>
557 </html>
558 `)
559-//line templates/base.qtpl:74
560+//line templates/base.qtpl:78
561 }
562 
563-//line templates/base.qtpl:74
564+//line templates/base.qtpl:78
565 func WritePageTemplate(qq422016 qtio422016.Writer, p Page, ctx context.Context) {
566-//line templates/base.qtpl:74
567+//line templates/base.qtpl:78
568 	qw422016 := qt422016.AcquireWriter(qq422016)
569-//line templates/base.qtpl:74
570+//line templates/base.qtpl:78
571 	StreamPageTemplate(qw422016, p, ctx)
572-//line templates/base.qtpl:74
573+//line templates/base.qtpl:78
574 	qt422016.ReleaseWriter(qw422016)
575-//line templates/base.qtpl:74
576+//line templates/base.qtpl:78
577 }
578 
579-//line templates/base.qtpl:74
580+//line templates/base.qtpl:78
581 func PageTemplate(p Page, ctx context.Context) string {
582-//line templates/base.qtpl:74
583+//line templates/base.qtpl:78
584 	qb422016 := qt422016.AcquireByteBuffer()
585-//line templates/base.qtpl:74
586+//line templates/base.qtpl:78
587 	WritePageTemplate(qb422016, p, ctx)
588-//line templates/base.qtpl:74
589+//line templates/base.qtpl:78
590 	qs422016 := string(qb422016.B)
591-//line templates/base.qtpl:74
592+//line templates/base.qtpl:78
593 	qt422016.ReleaseByteBuffer(qb422016)
594-//line templates/base.qtpl:74
595+//line templates/base.qtpl:78
596 	return qs422016
597-//line templates/base.qtpl:74
598+//line templates/base.qtpl:78
599 }