detached dbe8671

fix(web): serve a favicon and keep tree, refs and README code within narrow screens

commit
dbe8671c353d80720b097270e462827579e28037
author
brice · · 2026-10-10 14:16 UTC
parent
c83fe67
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
37 files · +209 -153
M cmd/ermite/testdata/web/blob-binary.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>data.bin · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>data.bin · files · example.test</title>7 <title>data.bin · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/blob-code.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>main.go · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>main.go · files · example.test</title>7 <title>main.go · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/blob-empty.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>empty.txt · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>empty.txt · files · example.test</title>7 <title>empty.txt · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/blob-image.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>pic.png · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>pic.png · files · example.test</title>7 <title>pic.png · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/blob-markdown.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>docs/guide.md · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>docs/guide.md · files · example.test</title>7 <title>docs/guide.md · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/blob-svg.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>logo.svg · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>logo.svg · files · example.test</title>7 <title>logo.svg · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/blob-text.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>notes.txt · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>notes.txt · files · example.test</title>7 <title>notes.txt · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/blob-too-large.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>big.txt · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>big.txt · files · example.test</title>7 <title>big.txt · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/blob-trojan.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>evil.go · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>evil.go · files · example.test</title>7 <title>evil.go · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/commit-big.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>SHA7 add a very large file · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>SHA7 add a very large file · diffs · example.test</title>7 <title>SHA7 add a very large file · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/commit-binary.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>SHA7 change a binary file · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>SHA7 change a binary file · diffs · example.test</title>7 <title>SHA7 change a binary file · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/commit-merge.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>SHA7 merge the side branch · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>SHA7 merge the side branch · diffs · example.test</title>7 <title>SHA7 merge the side branch · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/commit-modify-split.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>SHA7 modify a file and make a script executable · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>SHA7 modify a file and make a script executable · diffs · example.test</title>7 <title>SHA7 modify a file and make a script executable · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/commit-modify.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>SHA7 modify a file and make a script executable · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>SHA7 modify a file and make a script executable · diffs · example.test</title>7 <title>SHA7 modify a file and make a script executable · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/commit-rename.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>SHA7 rename a file and delete another · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>SHA7 rename a file and delete another · diffs · example.test</title>7 <title>SHA7 rename a file and delete another · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/commit-root.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>SHA7 root: the first files · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>SHA7 root: the first files · diffs · example.test</title>7 <title>SHA7 root: the first files · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/commit-trojan.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>SHA7 add evil.go · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>SHA7 add evil.go · diffs · example.test</title>7 <title>SHA7 add evil.go · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/commits-page2.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>commits · long · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>commits · long · example.test</title>7 <title>commits · long · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/commits-path.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>history of a.txt · long · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>history of a.txt · long · example.test</title>7 <title>history of a.txt · long · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/commits-root.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>commits · long · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>commits · long · example.test</title>7 <title>commits · long · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/commits-small.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>commits · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>commits · diffs · example.test</title>7 <title>commits · diffs · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/empty.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>quiet · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>quiet · example.test</title>7 <title>quiet · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/home.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>example.test</title>7 <title>example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/not-found-page.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>404 · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>404 · example.test</title>7 <title>404 · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/not-found.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>404 · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>404 · example.test</title>7 <title>404 · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/refs.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>refs · demo · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>refs · demo · example.test</title>7 <title>refs · demo · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/summary.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>demo · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>demo · example.test</title>7 <title>demo · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/tree-nested.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>src/lib · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>src/lib · files · example.test</title>7 <title>src/lib · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/tree-root.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>tree · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>tree · files · example.test</title>7 <title>tree · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/tree-slash-ref.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>x · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>x · files · example.test</title>7 <title>x · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M cmd/ermite/testdata/web/tree-subdir.html +1 -0
@@ -5,6 +5,7 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <meta name="color-scheme" content="light dark">
77 <title>docs · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
89 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
910 <script src="/-/static/js/htmx.min.HASH.js" defer>
1011 </script>
@@ -5,6 +5,7 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1">5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <meta name="color-scheme" content="light dark">6 <meta name="color-scheme" content="light dark">
7 <title>docs · files · example.test</title>7 <title>docs · files · example.test</title>
8+<link rel="icon" type="image/svg+xml" href="/-/static/img/icon.HASH.svg">
8 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">9 <link rel="stylesheet" href="/-/static/css/ermite.HASH.css">
9 <script src="/-/static/js/htmx.min.HASH.js" defer>10 <script src="/-/static/js/htmx.min.HASH.js" defer>
10 </script>11 </script>
M internal/adapters/web/assets.go +7 -1
@@ -22,7 +22,7 @@ const StaticPrefix = "/-/static/"
2222 // Assets are the URLs of the assets a page loads. Their names carry a hash of
2323 // the content, so they can be cached for ever.
2424 type Assets struct {
25- CSS, HTMX, Live, SSE, App string
25+ CSS, HTMX, Live, SSE, App, Icon string
2626 }
2727
2828 // asset is one embedded file under its content-hashed name.
@@ -84,6 +84,12 @@ func loadAssets() (*assetSet, error) {
8484 }
8585 sc.set(&s.urls, put("js", sc.file, b, "text/javascript; charset=utf-8"))
8686 }
87+
88+ icon, err := staticFS.ReadFile("static/icon.svg")
89+ if err != nil {
90+ return nil, err
91+ }
92+ s.urls.Icon = put("img", "icon.svg", icon, "image/svg+xml")
8793 return s, nil
8894 }
8995
@@ -22,7 +22,7 @@ const StaticPrefix = "/-/static/"
22 // Assets are the URLs of the assets a page loads. Their names carry a hash of22 // Assets are the URLs of the assets a page loads. Their names carry a hash of
23 // the content, so they can be cached for ever.23 // the content, so they can be cached for ever.
24 type Assets struct {24 type Assets struct {
25- CSS, HTMX, Live, SSE, App string25+ CSS, HTMX, Live, SSE, App, Icon string
26 }26 }
27 27
28 // asset is one embedded file under its content-hashed name.28 // asset is one embedded file under its content-hashed name.
@@ -84,6 +84,12 @@ func loadAssets() (*assetSet, error) {
84 }84 }
85 sc.set(&s.urls, put("js", sc.file, b, "text/javascript; charset=utf-8"))85 sc.set(&s.urls, put("js", sc.file, b, "text/javascript; charset=utf-8"))
86 }86 }
87+
88+ icon, err := staticFS.ReadFile("static/icon.svg")
89+ if err != nil {
90+ return nil, err
91+ }
92+ s.urls.Icon = put("img", "icon.svg", icon, "image/svg+xml")
87 return s, nil93 return s, nil
88 }94 }
89 95
M internal/adapters/web/shell.templ +1 -0
@@ -12,6 +12,7 @@ templ Shell(l Layout, rail templ.Component) {
1212 <meta name="viewport" content="width=device-width, initial-scale=1"/>
1313 <meta name="color-scheme" content="light dark"/>
1414 <title>{ l.Title }</title>
15+ <link rel="icon" type="image/svg+xml" href={ templ.SafeURL(l.Assets.Icon) }/>
1516 <link rel="stylesheet" href={ templ.SafeURL(l.Assets.CSS) }/>
1617 <script src={ l.Assets.HTMX } defer></script>
1718 <script src={ l.Assets.Live } defer></script>
@@ -12,6 +12,7 @@ templ Shell(l Layout, rail templ.Component) {
12 <meta name="viewport" content="width=device-width, initial-scale=1"/>12 <meta name="viewport" content="width=device-width, initial-scale=1"/>
13 <meta name="color-scheme" content="light dark"/>13 <meta name="color-scheme" content="light dark"/>
14 <title>{ l.Title }</title>14 <title>{ l.Title }</title>
15+ <link rel="icon" type="image/svg+xml" href={ templ.SafeURL(l.Assets.Icon) }/>
15 <link rel="stylesheet" href={ templ.SafeURL(l.Assets.CSS) }/>16 <link rel="stylesheet" href={ templ.SafeURL(l.Assets.CSS) }/>
16 <script src={ l.Assets.HTMX } defer></script>17 <script src={ l.Assets.HTMX } defer></script>
17 <script src={ l.Assets.Live } defer></script>18 <script src={ l.Assets.Live } defer></script>
M internal/adapters/web/shell_templ.go +164 -151
@@ -46,38 +46,38 @@ func Shell(l Layout, rail templ.Component) templ.Component {
4646 if templ_7745c5c3_Err != nil {
4747 return templ_7745c5c3_Err
4848 }
49- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><link rel=\"stylesheet\" href=\"")
49+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><link rel=\"icon\" type=\"image/svg+xml\" href=\"")
5050 if templ_7745c5c3_Err != nil {
5151 return templ_7745c5c3_Err
5252 }
5353 var templ_7745c5c3_Var3 templ.SafeURL
54- templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(l.Assets.CSS))
54+ templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(l.Assets.Icon))
5555 if templ_7745c5c3_Err != nil {
56- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 15, Col: 60}
56+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 15, Col: 76}
5757 }
5858 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
5959 if templ_7745c5c3_Err != nil {
6060 return templ_7745c5c3_Err
6161 }
62- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\"><script src=\"")
62+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\"><link rel=\"stylesheet\" href=\"")
6363 if templ_7745c5c3_Err != nil {
6464 return templ_7745c5c3_Err
6565 }
66- var templ_7745c5c3_Var4 string
67- templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.HTMX)
66+ var templ_7745c5c3_Var4 templ.SafeURL
67+ templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(l.Assets.CSS))
6868 if templ_7745c5c3_Err != nil {
69- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 16, Col: 30}
69+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 16, Col: 60}
7070 }
71- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
71+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
7272 if templ_7745c5c3_Err != nil {
7373 return templ_7745c5c3_Err
7474 }
75- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" defer></script><script src=\"")
75+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\"><script src=\"")
7676 if templ_7745c5c3_Err != nil {
7777 return templ_7745c5c3_Err
7878 }
7979 var templ_7745c5c3_Var5 string
80- templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.Live)
80+ templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.HTMX)
8181 if templ_7745c5c3_Err != nil {
8282 return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 17, Col: 30}
8383 }
@@ -90,9 +90,9 @@ func Shell(l Layout, rail templ.Component) templ.Component {
9090 return templ_7745c5c3_Err
9191 }
9292 var templ_7745c5c3_Var6 string
93- templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.SSE)
93+ templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.Live)
9494 if templ_7745c5c3_Err != nil {
95- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 18, Col: 29}
95+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 18, Col: 30}
9696 }
9797 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var6)
9898 if templ_7745c5c3_Err != nil {
@@ -103,7 +103,7 @@ func Shell(l Layout, rail templ.Component) templ.Component {
103103 return templ_7745c5c3_Err
104104 }
105105 var templ_7745c5c3_Var7 string
106- templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.App)
106+ templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.SSE)
107107 if templ_7745c5c3_Err != nil {
108108 return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 19, Col: 29}
109109 }
@@ -111,33 +111,46 @@ func Shell(l Layout, rail templ.Component) templ.Component {
111111 if templ_7745c5c3_Err != nil {
112112 return templ_7745c5c3_Err
113113 }
114- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\" defer></script></head><body data-ref=\"")
114+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\" defer></script><script src=\"")
115115 if templ_7745c5c3_Err != nil {
116116 return templ_7745c5c3_Err
117117 }
118118 var templ_7745c5c3_Var8 string
119- templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.RefPath)
119+ templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.App)
120120 if templ_7745c5c3_Err != nil {
121- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 21, Col: 28}
121+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 20, Col: 29}
122122 }
123123 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var8)
124124 if templ_7745c5c3_Err != nil {
125125 return templ_7745c5c3_Err
126126 }
127- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" data-sha=\"")
127+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" defer></script></head><body data-ref=\"")
128128 if templ_7745c5c3_Err != nil {
129129 return templ_7745c5c3_Err
130130 }
131131 var templ_7745c5c3_Var9 string
132- templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.SHA)
132+ templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.RefPath)
133133 if templ_7745c5c3_Err != nil {
134- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 21, Col: 47}
134+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 22, Col: 28}
135135 }
136136 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9)
137137 if templ_7745c5c3_Err != nil {
138138 return templ_7745c5c3_Err
139139 }
140- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\" data-sel=\"\"><a class=\"skip\" href=\"#main\">skip to content</a>")
140+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\" data-sha=\"")
141+ if templ_7745c5c3_Err != nil {
142+ return templ_7745c5c3_Err
143+ }
144+ var templ_7745c5c3_Var10 string
145+ templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.SHA)
146+ if templ_7745c5c3_Err != nil {
147+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 22, Col: 47}
148+ }
149+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var10)
150+ if templ_7745c5c3_Err != nil {
151+ return templ_7745c5c3_Err
152+ }
153+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\" data-sel=\"\"><a class=\"skip\" href=\"#main\">skip to content</a>")
141154 if templ_7745c5c3_Err != nil {
142155 return templ_7745c5c3_Err
143156 }
@@ -145,25 +158,25 @@ func Shell(l Layout, rail templ.Component) templ.Component {
145158 if templ_7745c5c3_Err != nil {
146159 return templ_7745c5c3_Err
147160 }
148- var templ_7745c5c3_Var10 = []any{"work", templ.KV("has-rail", l.HasRail), templ.KV("read", l.Read)}
149- templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...)
161+ var templ_7745c5c3_Var11 = []any{"work", templ.KV("has-rail", l.HasRail), templ.KV("read", l.Read)}
162+ templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var11...)
150163 if templ_7745c5c3_Err != nil {
151164 return templ_7745c5c3_Err
152165 }
153- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<div class=\"")
166+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"")
154167 if templ_7745c5c3_Err != nil {
155168 return templ_7745c5c3_Err
156169 }
157- var templ_7745c5c3_Var11 string
158- templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var10).String())
170+ var templ_7745c5c3_Var12 string
171+ templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var11).String())
159172 if templ_7745c5c3_Err != nil {
160173 return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 1, Col: 0}
161174 }
162- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var11)
175+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var12)
163176 if templ_7745c5c3_Err != nil {
164177 return templ_7745c5c3_Err
165178 }
166- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\"><main id=\"main\" tabindex=\"-1\" data-y=\"0\" hx-on:scroll=\"this.dataset.y = Math.round(this.scrollTop / 60)\">")
179+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\"><main id=\"main\" tabindex=\"-1\" data-y=\"0\" hx-on:scroll=\"this.dataset.y = Math.round(this.scrollTop / 60)\">")
167180 if templ_7745c5c3_Err != nil {
168181 return templ_7745c5c3_Err
169182 }
@@ -171,25 +184,25 @@ func Shell(l Layout, rail templ.Component) templ.Component {
171184 if templ_7745c5c3_Err != nil {
172185 return templ_7745c5c3_Err
173186 }
174- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</main>")
187+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</main>")
175188 if templ_7745c5c3_Err != nil {
176189 return templ_7745c5c3_Err
177190 }
178191 if l.HasRail && rail != nil {
179- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<aside class=\"rail\" aria-label=\"Context\"><details class=\"rail-d\" open data-init=\"\" hx-live=\"if (!data.init) { data.init = '1'; this.open = matchMedia('(min-width: 1100px)').matches }\"><summary>")
192+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<aside class=\"rail\" aria-label=\"Context\"><details class=\"rail-d\" open data-init=\"\" hx-live=\"if (!data.init) { data.init = '1'; this.open = matchMedia('(min-width: 1100px)').matches }\"><summary>")
180193 if templ_7745c5c3_Err != nil {
181194 return templ_7745c5c3_Err
182195 }
183- var templ_7745c5c3_Var12 string
184- templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(l.RailSum)
196+ var templ_7745c5c3_Var13 string
197+ templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(l.RailSum)
185198 if templ_7745c5c3_Err != nil {
186- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 31, Col: 27}
199+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 32, Col: 27}
187200 }
188- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
201+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
189202 if templ_7745c5c3_Err != nil {
190203 return templ_7745c5c3_Err
191204 }
192- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</summary>")
205+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</summary>")
193206 if templ_7745c5c3_Err != nil {
194207 return templ_7745c5c3_Err
195208 }
@@ -197,12 +210,12 @@ func Shell(l Layout, rail templ.Component) templ.Component {
197210 if templ_7745c5c3_Err != nil {
198211 return templ_7745c5c3_Err
199212 }
200- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</details></aside>")
213+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</details></aside>")
201214 if templ_7745c5c3_Err != nil {
202215 return templ_7745c5c3_Err
203216 }
204217 }
205- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</div>")
218+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</div>")
206219 if templ_7745c5c3_Err != nil {
207220 return templ_7745c5c3_Err
208221 }
@@ -226,7 +239,7 @@ func Shell(l Layout, rail templ.Component) templ.Component {
226239 if templ_7745c5c3_Err != nil {
227240 return templ_7745c5c3_Err
228241 }
229- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</body></html>")
242+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</body></html>")
230243 if templ_7745c5c3_Err != nil {
231244 return templ_7745c5c3_Err
232245 }
@@ -252,222 +265,222 @@ func Topbar(l Layout) templ.Component {
252265 }()
253266 }
254267 ctx = templ.InitializeContext(ctx)
255- templ_7745c5c3_Var13 := templ.GetChildren(ctx)
256- if templ_7745c5c3_Var13 == nil {
257- templ_7745c5c3_Var13 = templ.NopComponent
268+ templ_7745c5c3_Var14 := templ.GetChildren(ctx)
269+ if templ_7745c5c3_Var14 == nil {
270+ templ_7745c5c3_Var14 = templ.NopComponent
258271 }
259272 ctx = templ.ClearChildren(ctx)
260- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<header class=\"bar top\"><a class=\"blk\" href=\"/\" data-g=\"h\" title=\"home (g h)\">")
273+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<header class=\"bar top\"><a class=\"blk\" href=\"/\" data-g=\"h\" title=\"home (g h)\">")
261274 if templ_7745c5c3_Err != nil {
262275 return templ_7745c5c3_Err
263276 }
264- var templ_7745c5c3_Var14 string
265- templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(l.Instance)
277+ var templ_7745c5c3_Var15 string
278+ templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(l.Instance)
266279 if templ_7745c5c3_Err != nil {
267- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 50, Col: 68}
280+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 51, Col: 68}
268281 }
269- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
282+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
270283 if templ_7745c5c3_Err != nil {
271284 return templ_7745c5c3_Err
272285 }
273- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</a><span class=\"fade\" aria-hidden=\"true\"></span><nav class=\"crumbs\" aria-label=\"Path\"><ol>")
286+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</a><span class=\"fade\" aria-hidden=\"true\"></span><nav class=\"crumbs\" aria-label=\"Path\"><ol>")
274287 if templ_7745c5c3_Err != nil {
275288 return templ_7745c5c3_Err
276289 }
277290 for _, c := range l.Crumbs {
278- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<li>")
291+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<li>")
279292 if templ_7745c5c3_Err != nil {
280293 return templ_7745c5c3_Err
281294 }
282295 if c.Href != "" {
283- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<a href=\"")
296+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<a href=\"")
284297 if templ_7745c5c3_Err != nil {
285298 return templ_7745c5c3_Err
286299 }
287- var templ_7745c5c3_Var15 templ.SafeURL
288- templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(c.Href))
300+ var templ_7745c5c3_Var16 templ.SafeURL
301+ templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(c.Href))
289302 if templ_7745c5c3_Err != nil {
290- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 57, Col: 36}
303+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 58, Col: 36}
291304 }
292- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
305+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
293306 if templ_7745c5c3_Err != nil {
294307 return templ_7745c5c3_Err
295308 }
296- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\"")
309+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\"")
297310 if templ_7745c5c3_Err != nil {
298311 return templ_7745c5c3_Err
299312 }
300313 if c.Current {
301- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, " aria-current=\"page\"")
314+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, " aria-current=\"page\"")
302315 if templ_7745c5c3_Err != nil {
303316 return templ_7745c5c3_Err
304317 }
305318 }
306- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, ">")
319+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, ">")
307320 if templ_7745c5c3_Err != nil {
308321 return templ_7745c5c3_Err
309322 }
310- var templ_7745c5c3_Var16 string
311- templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(c.Label)
323+ var templ_7745c5c3_Var17 string
324+ templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(c.Label)
312325 if templ_7745c5c3_Err != nil {
313- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 61, Col: 17}
326+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 62, Col: 17}
314327 }
315- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
328+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
316329 if templ_7745c5c3_Err != nil {
317330 return templ_7745c5c3_Err
318331 }
319- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</a>")
332+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</a>")
320333 if templ_7745c5c3_Err != nil {
321334 return templ_7745c5c3_Err
322335 }
323336 } else {
324- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<span aria-current=\"page\">")
337+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "<span aria-current=\"page\">")
325338 if templ_7745c5c3_Err != nil {
326339 return templ_7745c5c3_Err
327340 }
328- var templ_7745c5c3_Var17 string
329- templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(c.Label)
341+ var templ_7745c5c3_Var18 string
342+ templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(c.Label)
330343 if templ_7745c5c3_Err != nil {
331- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 63, Col: 42}
344+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 64, Col: 42}
332345 }
333- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
346+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
334347 if templ_7745c5c3_Err != nil {
335348 return templ_7745c5c3_Err
336349 }
337- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</span>")
350+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</span>")
338351 if templ_7745c5c3_Err != nil {
339352 return templ_7745c5c3_Err
340353 }
341354 }
342- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</li>")
355+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</li>")
343356 if templ_7745c5c3_Err != nil {
344357 return templ_7745c5c3_Err
345358 }
346359 }
347- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</ol></nav>")
360+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "</ol></nav>")
348361 if templ_7745c5c3_Err != nil {
349362 return templ_7745c5c3_Err
350363 }
351364 if len(l.Sections) > 0 {
352- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<nav class=\"secs\" aria-label=\"Sections\"><ul>")
365+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<nav class=\"secs\" aria-label=\"Sections\"><ul>")
353366 if templ_7745c5c3_Err != nil {
354367 return templ_7745c5c3_Err
355368 }
356369 for _, s := range l.Sections {
357- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<li><a href=\"")
370+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "<li><a href=\"")
358371 if templ_7745c5c3_Err != nil {
359372 return templ_7745c5c3_Err
360373 }
361- var templ_7745c5c3_Var18 templ.SafeURL
362- templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(s.Href))
374+ var templ_7745c5c3_Var19 templ.SafeURL
375+ templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(s.Href))
363376 if templ_7745c5c3_Err != nil {
364- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 75, Col: 36}
377+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 76, Col: 36}
365378 }
366- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
379+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
367380 if templ_7745c5c3_Err != nil {
368381 return templ_7745c5c3_Err
369382 }
370- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\" data-key=\"")
383+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "\" data-key=\"")
371384 if templ_7745c5c3_Err != nil {
372385 return templ_7745c5c3_Err
373386 }
374- var templ_7745c5c3_Var19 string
375- templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.ResolveAttributeValue(s.Key)
387+ var templ_7745c5c3_Var20 string
388+ templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.ResolveAttributeValue(s.Key)
376389 if templ_7745c5c3_Err != nil {
377- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 76, Col: 24}
390+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 77, Col: 24}
378391 }
379- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var19)
392+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var20)
380393 if templ_7745c5c3_Err != nil {
381394 return templ_7745c5c3_Err
382395 }
383- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "\" aria-keyshortcuts=\"")
396+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "\" aria-keyshortcuts=\"")
384397 if templ_7745c5c3_Err != nil {
385398 return templ_7745c5c3_Err
386399 }
387- var templ_7745c5c3_Var20 string
388- templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.ResolveAttributeValue("g " + s.Key)
400+ var templ_7745c5c3_Var21 string
401+ templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.ResolveAttributeValue("g " + s.Key)
389402 if templ_7745c5c3_Err != nil {
390- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 77, Col: 40}
403+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 78, Col: 40}
391404 }
392- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var20)
405+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var21)
393406 if templ_7745c5c3_Err != nil {
394407 return templ_7745c5c3_Err
395408 }
396- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "\"")
409+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "\"")
397410 if templ_7745c5c3_Err != nil {
398411 return templ_7745c5c3_Err
399412 }
400413 if s.Current {
401- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, " aria-current=\"page\"")
414+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, " aria-current=\"page\"")
402415 if templ_7745c5c3_Err != nil {
403416 return templ_7745c5c3_Err
404417 }
405418 }
406- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, ">")
419+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, ">")
407420 if templ_7745c5c3_Err != nil {
408421 return templ_7745c5c3_Err
409422 }
410- var templ_7745c5c3_Var21 string
411- templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(s.Key)
423+ var templ_7745c5c3_Var22 string
424+ templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(s.Key)
412425 if templ_7745c5c3_Err != nil {
413- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 81, Col: 15}
426+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 82, Col: 15}
414427 }
415- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
428+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
416429 if templ_7745c5c3_Err != nil {
417430 return templ_7745c5c3_Err
418431 }
419- var templ_7745c5c3_Var22 string
420- templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(s.Post)
432+ var templ_7745c5c3_Var23 string
433+ templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(s.Post)
421434 if templ_7745c5c3_Err != nil {
422- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 81, Col: 25}
435+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 82, Col: 25}
423436 }
424- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
437+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
425438 if templ_7745c5c3_Err != nil {
426439 return templ_7745c5c3_Err
427440 }
428- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "</a></li>")
441+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "</a></li>")
429442 if templ_7745c5c3_Err != nil {
430443 return templ_7745c5c3_Err
431444 }
432445 }
433- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "</ul></nav>")
446+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</ul></nav>")
434447 if templ_7745c5c3_Err != nil {
435448 return templ_7745c5c3_Err
436449 }
437450 }
438451 if l.Ref != "" {
439- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "<button type=\"button\" class=\"ref\" aria-haspopup=\"dialog\" aria-controls=\"panel-refs\" aria-keyshortcuts=\"b\" title=\"switch ref (b)\" hx-on:click=\"document.body.dispatchEvent(new CustomEvent('k-refs'))\">")
452+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<button type=\"button\" class=\"ref\" aria-haspopup=\"dialog\" aria-controls=\"panel-refs\" aria-keyshortcuts=\"b\" title=\"switch ref (b)\" hx-on:click=\"document.body.dispatchEvent(new CustomEvent('k-refs'))\">")
440453 if templ_7745c5c3_Err != nil {
441454 return templ_7745c5c3_Err
442455 }
443- var templ_7745c5c3_Var23 string
444- templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(l.Ref)
456+ var templ_7745c5c3_Var24 string
457+ templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(l.Ref)
445458 if templ_7745c5c3_Err != nil {
446- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 96, Col: 11}
459+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 97, Col: 11}
447460 }
448- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
461+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
449462 if templ_7745c5c3_Err != nil {
450463 return templ_7745c5c3_Err
451464 }
452- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<span class=\"sha\">")
465+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "<span class=\"sha\">")
453466 if templ_7745c5c3_Err != nil {
454467 return templ_7745c5c3_Err
455468 }
456- var templ_7745c5c3_Var24 string
457- templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs("@" + l.Short)
469+ var templ_7745c5c3_Var25 string
470+ templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs("@" + l.Short)
458471 if templ_7745c5c3_Err != nil {
459- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 96, Col: 46}
472+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 97, Col: 46}
460473 }
461- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
474+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
462475 if templ_7745c5c3_Err != nil {
463476 return templ_7745c5c3_Err
464477 }
465- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</span></button>")
478+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</span></button>")
466479 if templ_7745c5c3_Err != nil {
467480 return templ_7745c5c3_Err
468481 }
469482 }
470- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</header>")
483+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</header>")
471484 if templ_7745c5c3_Err != nil {
472485 return templ_7745c5c3_Err
473486 }
@@ -494,61 +507,61 @@ func Statusbar(l Layout) templ.Component {
494507 }()
495508 }
496509 ctx = templ.InitializeContext(ctx)
497- templ_7745c5c3_Var25 := templ.GetChildren(ctx)
498- if templ_7745c5c3_Var25 == nil {
499- templ_7745c5c3_Var25 = templ.NopComponent
510+ templ_7745c5c3_Var26 := templ.GetChildren(ctx)
511+ if templ_7745c5c3_Var26 == nil {
512+ templ_7745c5c3_Var26 = templ.NopComponent
500513 }
501514 ctx = templ.ClearChildren(ctx)
502- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "<footer class=\"bar status\" aria-label=\"Status\"><span class=\"mode\">")
515+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "<footer class=\"bar status\" aria-label=\"Status\"><span class=\"mode\">")
503516 if templ_7745c5c3_Err != nil {
504517 return templ_7745c5c3_Err
505518 }
506- var templ_7745c5c3_Var26 string
507- templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(l.Status.Mode)
519+ var templ_7745c5c3_Var27 string
520+ templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(l.Status.Mode)
508521 if templ_7745c5c3_Err != nil {
509- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 106, Col: 36}
522+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 107, Col: 36}
510523 }
511- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
524+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
512525 if templ_7745c5c3_Err != nil {
513526 return templ_7745c5c3_Err
514527 }
515- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "</span> <span class=\"st-ctx\">")
528+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "</span> <span class=\"st-ctx\">")
516529 if templ_7745c5c3_Err != nil {
517530 return templ_7745c5c3_Err
518531 }
519- var templ_7745c5c3_Var27 string
520- templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(l.Status.Context)
532+ var templ_7745c5c3_Var28 string
533+ templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(l.Status.Context)
521534 if templ_7745c5c3_Err != nil {
522- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 107, Col: 41}
535+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 108, Col: 41}
523536 }
524- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
537+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
525538 if templ_7745c5c3_Err != nil {
526539 return templ_7745c5c3_Err
527540 }
528- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "</span> <button type=\"button\" class=\"st-cmd\" aria-haspopup=\"dialog\" aria-controls=\"panel-cmd\" aria-keyshortcuts=\":\" hx-on:click=\"document.body.dispatchEvent(new CustomEvent('k-cmd'))\"><span class=\"hi\">:</span> go to…</button> ")
541+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "</span> <button type=\"button\" class=\"st-cmd\" aria-haspopup=\"dialog\" aria-controls=\"panel-cmd\" aria-keyshortcuts=\":\" hx-on:click=\"document.body.dispatchEvent(new CustomEvent('k-cmd'))\"><span class=\"hi\">:</span> go to…</button> ")
529542 if templ_7745c5c3_Err != nil {
530543 return templ_7745c5c3_Err
531544 }
532545 if l.Status.Blob {
533- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "<span class=\"st-sel\" :text=\"document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : 'click a line number · shift-click extends'\">click a line number · shift-click extends</span> ")
546+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "<span class=\"st-sel\" :text=\"document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : 'click a line number · shift-click extends'\">click a line number · shift-click extends</span> ")
534547 if templ_7745c5c3_Err != nil {
535548 return templ_7745c5c3_Err
536549 }
537550 }
538- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "<span class=\"st-flash\" aria-live=\"polite\" :text=\"document.body.dataset.flash || ''\"></span> <span class=\"st-hints\">")
551+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "<span class=\"st-flash\" aria-live=\"polite\" :text=\"document.body.dataset.flash || ''\"></span> <span class=\"st-hints\">")
539552 if templ_7745c5c3_Err != nil {
540553 return templ_7745c5c3_Err
541554 }
542- var templ_7745c5c3_Var28 string
543- templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(l.Status.Hints)
555+ var templ_7745c5c3_Var29 string
556+ templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(l.Status.Hints)
544557 if templ_7745c5c3_Err != nil {
545- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 120, Col: 41}
558+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 121, Col: 41}
546559 }
547- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
560+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
548561 if templ_7745c5c3_Err != nil {
549562 return templ_7745c5c3_Err
550563 }
551- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "</span>")
564+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "</span>")
552565 if templ_7745c5c3_Err != nil {
553566 return templ_7745c5c3_Err
554567 }
@@ -561,25 +574,25 @@ func Statusbar(l Layout) templ.Component {
561574 return templ_7745c5c3_Err
562575 }
563576 if l.Status.Cursor {
564- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "<span class=\"st-pos num\" title=\"cursor position\" :text=\"(() => { let all = q('[data-rows] > :not([hidden])').arr(); let i = all.findIndex(r => r.hasAttribute('data-cursor')); return (i + 1) + '/' + all.length })()\">")
577+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "<span class=\"st-pos num\" title=\"cursor position\" :text=\"(() => { let all = q('[data-rows] > :not([hidden])').arr(); let i = all.findIndex(r => r.hasAttribute('data-cursor')); return (i + 1) + '/' + all.length })()\">")
565578 if templ_7745c5c3_Err != nil {
566579 return templ_7745c5c3_Err
567580 }
568- var templ_7745c5c3_Var29 string
569- templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(cursorText(l.Status.Count))
581+ var templ_7745c5c3_Var30 string
582+ templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(cursorText(l.Status.Count))
570583 if templ_7745c5c3_Err != nil {
571- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 128, Col: 32}
584+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 129, Col: 32}
572585 }
573- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
586+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
574587 if templ_7745c5c3_Err != nil {
575588 return templ_7745c5c3_Err
576589 }
577- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "</span>")
590+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "</span>")
578591 if templ_7745c5c3_Err != nil {
579592 return templ_7745c5c3_Err
580593 }
581594 }
582- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "</footer>")
595+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "</footer>")
583596 if templ_7745c5c3_Err != nil {
584597 return templ_7745c5c3_Err
585598 }
@@ -605,38 +618,38 @@ func Footer(l Layout) templ.Component {
605618 }()
606619 }
607620 ctx = templ.InitializeContext(ctx)
608- templ_7745c5c3_Var30 := templ.GetChildren(ctx)
609- if templ_7745c5c3_Var30 == nil {
610- templ_7745c5c3_Var30 = templ.NopComponent
621+ templ_7745c5c3_Var31 := templ.GetChildren(ctx)
622+ if templ_7745c5c3_Var31 == nil {
623+ templ_7745c5c3_Var31 = templ.NopComponent
611624 }
612625 ctx = templ.ClearChildren(ctx)
613- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "<span class=\"st-src\"><span class=\"st-ver\">ermite ")
626+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "<span class=\"st-src\"><span class=\"st-ver\">ermite ")
614627 if templ_7745c5c3_Err != nil {
615628 return templ_7745c5c3_Err
616629 }
617- var templ_7745c5c3_Var31 string
618- templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(l.Version)
630+ var templ_7745c5c3_Var32 string
631+ templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(l.Version)
619632 if templ_7745c5c3_Err != nil {
620- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 136, Col: 61}
633+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 137, Col: 61}
621634 }
622- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31))
635+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32))
623636 if templ_7745c5c3_Err != nil {
624637 return templ_7745c5c3_Err
625638 }
626- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, " · </span><a href=\"")
639+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, " · </span><a href=\"")
627640 if templ_7745c5c3_Err != nil {
628641 return templ_7745c5c3_Err
629642 }
630- var templ_7745c5c3_Var32 templ.SafeURL
631- templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(l.SourceURL))
643+ var templ_7745c5c3_Var33 templ.SafeURL
644+ templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(l.SourceURL))
632645 if templ_7745c5c3_Err != nil {
633- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 136, Col: 110}
646+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 137, Col: 110}
634647 }
635- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32))
648+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33))
636649 if templ_7745c5c3_Err != nil {
637650 return templ_7745c5c3_Err
638651 }
639- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "\" rel=\"noopener\" title=\"source of this version (AGPL-3.0-or-later)\">source</a></span>")
652+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "\" rel=\"noopener\" title=\"source of this version (AGPL-3.0-or-later)\">source</a></span>")
640653 if templ_7745c5c3_Err != nil {
641654 return templ_7745c5c3_Err
642655 }
@@ -46,38 +46,38 @@ func Shell(l Layout, rail templ.Component) templ.Component {
46 if templ_7745c5c3_Err != nil {46 if templ_7745c5c3_Err != nil {
47 return templ_7745c5c3_Err47 return templ_7745c5c3_Err
48 }48 }
49- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><link rel=\"stylesheet\" href=\"")49+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><link rel=\"icon\" type=\"image/svg+xml\" href=\"")
50 if templ_7745c5c3_Err != nil {50 if templ_7745c5c3_Err != nil {
51 return templ_7745c5c3_Err51 return templ_7745c5c3_Err
52 }52 }
53 var templ_7745c5c3_Var3 templ.SafeURL53 var templ_7745c5c3_Var3 templ.SafeURL
54- templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(l.Assets.CSS))54+ templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(l.Assets.Icon))
55 if templ_7745c5c3_Err != nil {55 if templ_7745c5c3_Err != nil {
56- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 15, Col: 60}56+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 15, Col: 76}
57 }57 }
58 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))58 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
59 if templ_7745c5c3_Err != nil {59 if templ_7745c5c3_Err != nil {
60 return templ_7745c5c3_Err60 return templ_7745c5c3_Err
61 }61 }
62- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\"><script src=\"")62+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\"><link rel=\"stylesheet\" href=\"")
63 if templ_7745c5c3_Err != nil {63 if templ_7745c5c3_Err != nil {
64 return templ_7745c5c3_Err64 return templ_7745c5c3_Err
65 }65 }
66- var templ_7745c5c3_Var4 string66+ var templ_7745c5c3_Var4 templ.SafeURL
67- templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.HTMX)67+ templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(l.Assets.CSS))
68 if templ_7745c5c3_Err != nil {68 if templ_7745c5c3_Err != nil {
69- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 16, Col: 30}69+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 16, Col: 60}
70 }70 }
71- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)71+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
72 if templ_7745c5c3_Err != nil {72 if templ_7745c5c3_Err != nil {
73 return templ_7745c5c3_Err73 return templ_7745c5c3_Err
74 }74 }
75- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" defer></script><script src=\"")75+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\"><script src=\"")
76 if templ_7745c5c3_Err != nil {76 if templ_7745c5c3_Err != nil {
77 return templ_7745c5c3_Err77 return templ_7745c5c3_Err
78 }78 }
79 var templ_7745c5c3_Var5 string79 var templ_7745c5c3_Var5 string
80- templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.Live)80+ templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.HTMX)
81 if templ_7745c5c3_Err != nil {81 if templ_7745c5c3_Err != nil {
82 return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 17, Col: 30}82 return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 17, Col: 30}
83 }83 }
@@ -90,9 +90,9 @@ func Shell(l Layout, rail templ.Component) templ.Component {
90 return templ_7745c5c3_Err90 return templ_7745c5c3_Err
91 }91 }
92 var templ_7745c5c3_Var6 string92 var templ_7745c5c3_Var6 string
93- templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.SSE)93+ templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.Live)
94 if templ_7745c5c3_Err != nil {94 if templ_7745c5c3_Err != nil {
95- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 18, Col: 29}95+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 18, Col: 30}
96 }96 }
97 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var6)97 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var6)
98 if templ_7745c5c3_Err != nil {98 if templ_7745c5c3_Err != nil {
@@ -103,7 +103,7 @@ func Shell(l Layout, rail templ.Component) templ.Component {
103 return templ_7745c5c3_Err103 return templ_7745c5c3_Err
104 }104 }
105 var templ_7745c5c3_Var7 string105 var templ_7745c5c3_Var7 string
106- templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.App)106+ templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.SSE)
107 if templ_7745c5c3_Err != nil {107 if templ_7745c5c3_Err != nil {
108 return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 19, Col: 29}108 return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 19, Col: 29}
109 }109 }
@@ -111,33 +111,46 @@ func Shell(l Layout, rail templ.Component) templ.Component {
111 if templ_7745c5c3_Err != nil {111 if templ_7745c5c3_Err != nil {
112 return templ_7745c5c3_Err112 return templ_7745c5c3_Err
113 }113 }
114- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\" defer></script></head><body data-ref=\"")114+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\" defer></script><script src=\"")
115 if templ_7745c5c3_Err != nil {115 if templ_7745c5c3_Err != nil {
116 return templ_7745c5c3_Err116 return templ_7745c5c3_Err
117 }117 }
118 var templ_7745c5c3_Var8 string118 var templ_7745c5c3_Var8 string
119- templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.RefPath)119+ templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.Assets.App)
120 if templ_7745c5c3_Err != nil {120 if templ_7745c5c3_Err != nil {
121- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 21, Col: 28}121+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 20, Col: 29}
122 }122 }
123 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var8)123 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var8)
124 if templ_7745c5c3_Err != nil {124 if templ_7745c5c3_Err != nil {
125 return templ_7745c5c3_Err125 return templ_7745c5c3_Err
126 }126 }
127- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" data-sha=\"")127+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" defer></script></head><body data-ref=\"")
128 if templ_7745c5c3_Err != nil {128 if templ_7745c5c3_Err != nil {
129 return templ_7745c5c3_Err129 return templ_7745c5c3_Err
130 }130 }
131 var templ_7745c5c3_Var9 string131 var templ_7745c5c3_Var9 string
132- templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.SHA)132+ templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.RefPath)
133 if templ_7745c5c3_Err != nil {133 if templ_7745c5c3_Err != nil {
134- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 21, Col: 47}134+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 22, Col: 28}
135 }135 }
136 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9)136 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9)
137 if templ_7745c5c3_Err != nil {137 if templ_7745c5c3_Err != nil {
138 return templ_7745c5c3_Err138 return templ_7745c5c3_Err
139 }139 }
140- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\" data-sel=\"\"><a class=\"skip\" href=\"#main\">skip to content</a>")140+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\" data-sha=\"")
141+ if templ_7745c5c3_Err != nil {
142+ return templ_7745c5c3_Err
143+ }
144+ var templ_7745c5c3_Var10 string
145+ templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.ResolveAttributeValue(l.SHA)
146+ if templ_7745c5c3_Err != nil {
147+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 22, Col: 47}
148+ }
149+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var10)
150+ if templ_7745c5c3_Err != nil {
151+ return templ_7745c5c3_Err
152+ }
153+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\" data-sel=\"\"><a class=\"skip\" href=\"#main\">skip to content</a>")
141 if templ_7745c5c3_Err != nil {154 if templ_7745c5c3_Err != nil {
142 return templ_7745c5c3_Err155 return templ_7745c5c3_Err
143 }156 }
@@ -145,25 +158,25 @@ func Shell(l Layout, rail templ.Component) templ.Component {
145 if templ_7745c5c3_Err != nil {158 if templ_7745c5c3_Err != nil {
146 return templ_7745c5c3_Err159 return templ_7745c5c3_Err
147 }160 }
148- var templ_7745c5c3_Var10 = []any{"work", templ.KV("has-rail", l.HasRail), templ.KV("read", l.Read)}161+ var templ_7745c5c3_Var11 = []any{"work", templ.KV("has-rail", l.HasRail), templ.KV("read", l.Read)}
149- templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...)162+ templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var11...)
150 if templ_7745c5c3_Err != nil {163 if templ_7745c5c3_Err != nil {
151 return templ_7745c5c3_Err164 return templ_7745c5c3_Err
152 }165 }
153- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<div class=\"")166+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"")
154 if templ_7745c5c3_Err != nil {167 if templ_7745c5c3_Err != nil {
155 return templ_7745c5c3_Err168 return templ_7745c5c3_Err
156 }169 }
157- var templ_7745c5c3_Var11 string170+ var templ_7745c5c3_Var12 string
158- templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var10).String())171+ templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var11).String())
159 if templ_7745c5c3_Err != nil {172 if templ_7745c5c3_Err != nil {
160 return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 1, Col: 0}173 return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 1, Col: 0}
161 }174 }
162- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var11)175+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var12)
163 if templ_7745c5c3_Err != nil {176 if templ_7745c5c3_Err != nil {
164 return templ_7745c5c3_Err177 return templ_7745c5c3_Err
165 }178 }
166- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\"><main id=\"main\" tabindex=\"-1\" data-y=\"0\" hx-on:scroll=\"this.dataset.y = Math.round(this.scrollTop / 60)\">")179+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\"><main id=\"main\" tabindex=\"-1\" data-y=\"0\" hx-on:scroll=\"this.dataset.y = Math.round(this.scrollTop / 60)\">")
167 if templ_7745c5c3_Err != nil {180 if templ_7745c5c3_Err != nil {
168 return templ_7745c5c3_Err181 return templ_7745c5c3_Err
169 }182 }
@@ -171,25 +184,25 @@ func Shell(l Layout, rail templ.Component) templ.Component {
171 if templ_7745c5c3_Err != nil {184 if templ_7745c5c3_Err != nil {
172 return templ_7745c5c3_Err185 return templ_7745c5c3_Err
173 }186 }
174- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</main>")187+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</main>")
175 if templ_7745c5c3_Err != nil {188 if templ_7745c5c3_Err != nil {
176 return templ_7745c5c3_Err189 return templ_7745c5c3_Err
177 }190 }
178 if l.HasRail && rail != nil {191 if l.HasRail && rail != nil {
179- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<aside class=\"rail\" aria-label=\"Context\"><details class=\"rail-d\" open data-init=\"\" hx-live=\"if (!data.init) { data.init = '1'; this.open = matchMedia('(min-width: 1100px)').matches }\"><summary>")192+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<aside class=\"rail\" aria-label=\"Context\"><details class=\"rail-d\" open data-init=\"\" hx-live=\"if (!data.init) { data.init = '1'; this.open = matchMedia('(min-width: 1100px)').matches }\"><summary>")
180 if templ_7745c5c3_Err != nil {193 if templ_7745c5c3_Err != nil {
181 return templ_7745c5c3_Err194 return templ_7745c5c3_Err
182 }195 }
183- var templ_7745c5c3_Var12 string196+ var templ_7745c5c3_Var13 string
184- templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(l.RailSum)197+ templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(l.RailSum)
185 if templ_7745c5c3_Err != nil {198 if templ_7745c5c3_Err != nil {
186- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 31, Col: 27}199+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 32, Col: 27}
187 }200 }
188- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))201+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
189 if templ_7745c5c3_Err != nil {202 if templ_7745c5c3_Err != nil {
190 return templ_7745c5c3_Err203 return templ_7745c5c3_Err
191 }204 }
192- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</summary>")205+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</summary>")
193 if templ_7745c5c3_Err != nil {206 if templ_7745c5c3_Err != nil {
194 return templ_7745c5c3_Err207 return templ_7745c5c3_Err
195 }208 }
@@ -197,12 +210,12 @@ func Shell(l Layout, rail templ.Component) templ.Component {
197 if templ_7745c5c3_Err != nil {210 if templ_7745c5c3_Err != nil {
198 return templ_7745c5c3_Err211 return templ_7745c5c3_Err
199 }212 }
200- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</details></aside>")213+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</details></aside>")
201 if templ_7745c5c3_Err != nil {214 if templ_7745c5c3_Err != nil {
202 return templ_7745c5c3_Err215 return templ_7745c5c3_Err
203 }216 }
204 }217 }
205- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</div>")218+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</div>")
206 if templ_7745c5c3_Err != nil {219 if templ_7745c5c3_Err != nil {
207 return templ_7745c5c3_Err220 return templ_7745c5c3_Err
208 }221 }
@@ -226,7 +239,7 @@ func Shell(l Layout, rail templ.Component) templ.Component {
226 if templ_7745c5c3_Err != nil {239 if templ_7745c5c3_Err != nil {
227 return templ_7745c5c3_Err240 return templ_7745c5c3_Err
228 }241 }
229- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</body></html>")242+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</body></html>")
230 if templ_7745c5c3_Err != nil {243 if templ_7745c5c3_Err != nil {
231 return templ_7745c5c3_Err244 return templ_7745c5c3_Err
232 }245 }
@@ -252,222 +265,222 @@ func Topbar(l Layout) templ.Component {
252 }()265 }()
253 }266 }
254 ctx = templ.InitializeContext(ctx)267 ctx = templ.InitializeContext(ctx)
255- templ_7745c5c3_Var13 := templ.GetChildren(ctx)268+ templ_7745c5c3_Var14 := templ.GetChildren(ctx)
256- if templ_7745c5c3_Var13 == nil {269+ if templ_7745c5c3_Var14 == nil {
257- templ_7745c5c3_Var13 = templ.NopComponent270+ templ_7745c5c3_Var14 = templ.NopComponent
258 }271 }
259 ctx = templ.ClearChildren(ctx)272 ctx = templ.ClearChildren(ctx)
260- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<header class=\"bar top\"><a class=\"blk\" href=\"/\" data-g=\"h\" title=\"home (g h)\">")273+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<header class=\"bar top\"><a class=\"blk\" href=\"/\" data-g=\"h\" title=\"home (g h)\">")
261 if templ_7745c5c3_Err != nil {274 if templ_7745c5c3_Err != nil {
262 return templ_7745c5c3_Err275 return templ_7745c5c3_Err
263 }276 }
264- var templ_7745c5c3_Var14 string277+ var templ_7745c5c3_Var15 string
265- templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(l.Instance)278+ templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(l.Instance)
266 if templ_7745c5c3_Err != nil {279 if templ_7745c5c3_Err != nil {
267- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 50, Col: 68}280+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 51, Col: 68}
268 }281 }
269- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))282+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
270 if templ_7745c5c3_Err != nil {283 if templ_7745c5c3_Err != nil {
271 return templ_7745c5c3_Err284 return templ_7745c5c3_Err
272 }285 }
273- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</a><span class=\"fade\" aria-hidden=\"true\"></span><nav class=\"crumbs\" aria-label=\"Path\"><ol>")286+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</a><span class=\"fade\" aria-hidden=\"true\"></span><nav class=\"crumbs\" aria-label=\"Path\"><ol>")
274 if templ_7745c5c3_Err != nil {287 if templ_7745c5c3_Err != nil {
275 return templ_7745c5c3_Err288 return templ_7745c5c3_Err
276 }289 }
277 for _, c := range l.Crumbs {290 for _, c := range l.Crumbs {
278- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<li>")291+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<li>")
279 if templ_7745c5c3_Err != nil {292 if templ_7745c5c3_Err != nil {
280 return templ_7745c5c3_Err293 return templ_7745c5c3_Err
281 }294 }
282 if c.Href != "" {295 if c.Href != "" {
283- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<a href=\"")296+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<a href=\"")
284 if templ_7745c5c3_Err != nil {297 if templ_7745c5c3_Err != nil {
285 return templ_7745c5c3_Err298 return templ_7745c5c3_Err
286 }299 }
287- var templ_7745c5c3_Var15 templ.SafeURL300+ var templ_7745c5c3_Var16 templ.SafeURL
288- templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(c.Href))301+ templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(c.Href))
289 if templ_7745c5c3_Err != nil {302 if templ_7745c5c3_Err != nil {
290- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 57, Col: 36}303+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 58, Col: 36}
291 }304 }
292- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))305+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
293 if templ_7745c5c3_Err != nil {306 if templ_7745c5c3_Err != nil {
294 return templ_7745c5c3_Err307 return templ_7745c5c3_Err
295 }308 }
296- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\"")309+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\"")
297 if templ_7745c5c3_Err != nil {310 if templ_7745c5c3_Err != nil {
298 return templ_7745c5c3_Err311 return templ_7745c5c3_Err
299 }312 }
300 if c.Current {313 if c.Current {
301- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, " aria-current=\"page\"")314+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, " aria-current=\"page\"")
302 if templ_7745c5c3_Err != nil {315 if templ_7745c5c3_Err != nil {
303 return templ_7745c5c3_Err316 return templ_7745c5c3_Err
304 }317 }
305 }318 }
306- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, ">")319+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, ">")
307 if templ_7745c5c3_Err != nil {320 if templ_7745c5c3_Err != nil {
308 return templ_7745c5c3_Err321 return templ_7745c5c3_Err
309 }322 }
310- var templ_7745c5c3_Var16 string323+ var templ_7745c5c3_Var17 string
311- templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(c.Label)324+ templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(c.Label)
312 if templ_7745c5c3_Err != nil {325 if templ_7745c5c3_Err != nil {
313- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 61, Col: 17}326+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 62, Col: 17}
314 }327 }
315- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))328+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
316 if templ_7745c5c3_Err != nil {329 if templ_7745c5c3_Err != nil {
317 return templ_7745c5c3_Err330 return templ_7745c5c3_Err
318 }331 }
319- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</a>")332+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</a>")
320 if templ_7745c5c3_Err != nil {333 if templ_7745c5c3_Err != nil {
321 return templ_7745c5c3_Err334 return templ_7745c5c3_Err
322 }335 }
323 } else {336 } else {
324- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<span aria-current=\"page\">")337+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "<span aria-current=\"page\">")
325 if templ_7745c5c3_Err != nil {338 if templ_7745c5c3_Err != nil {
326 return templ_7745c5c3_Err339 return templ_7745c5c3_Err
327 }340 }
328- var templ_7745c5c3_Var17 string341+ var templ_7745c5c3_Var18 string
329- templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(c.Label)342+ templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(c.Label)
330 if templ_7745c5c3_Err != nil {343 if templ_7745c5c3_Err != nil {
331- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 63, Col: 42}344+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 64, Col: 42}
332 }345 }
333- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))346+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
334 if templ_7745c5c3_Err != nil {347 if templ_7745c5c3_Err != nil {
335 return templ_7745c5c3_Err348 return templ_7745c5c3_Err
336 }349 }
337- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</span>")350+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</span>")
338 if templ_7745c5c3_Err != nil {351 if templ_7745c5c3_Err != nil {
339 return templ_7745c5c3_Err352 return templ_7745c5c3_Err
340 }353 }
341 }354 }
342- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</li>")355+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</li>")
343 if templ_7745c5c3_Err != nil {356 if templ_7745c5c3_Err != nil {
344 return templ_7745c5c3_Err357 return templ_7745c5c3_Err
345 }358 }
346 }359 }
347- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</ol></nav>")360+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "</ol></nav>")
348 if templ_7745c5c3_Err != nil {361 if templ_7745c5c3_Err != nil {
349 return templ_7745c5c3_Err362 return templ_7745c5c3_Err
350 }363 }
351 if len(l.Sections) > 0 {364 if len(l.Sections) > 0 {
352- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<nav class=\"secs\" aria-label=\"Sections\"><ul>")365+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<nav class=\"secs\" aria-label=\"Sections\"><ul>")
353 if templ_7745c5c3_Err != nil {366 if templ_7745c5c3_Err != nil {
354 return templ_7745c5c3_Err367 return templ_7745c5c3_Err
355 }368 }
356 for _, s := range l.Sections {369 for _, s := range l.Sections {
357- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<li><a href=\"")370+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "<li><a href=\"")
358 if templ_7745c5c3_Err != nil {371 if templ_7745c5c3_Err != nil {
359 return templ_7745c5c3_Err372 return templ_7745c5c3_Err
360 }373 }
361- var templ_7745c5c3_Var18 templ.SafeURL374+ var templ_7745c5c3_Var19 templ.SafeURL
362- templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(s.Href))375+ templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(s.Href))
363 if templ_7745c5c3_Err != nil {376 if templ_7745c5c3_Err != nil {
364- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 75, Col: 36}377+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 76, Col: 36}
365 }378 }
366- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))379+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
367 if templ_7745c5c3_Err != nil {380 if templ_7745c5c3_Err != nil {
368 return templ_7745c5c3_Err381 return templ_7745c5c3_Err
369 }382 }
370- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\" data-key=\"")383+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "\" data-key=\"")
371 if templ_7745c5c3_Err != nil {384 if templ_7745c5c3_Err != nil {
372 return templ_7745c5c3_Err385 return templ_7745c5c3_Err
373 }386 }
374- var templ_7745c5c3_Var19 string387+ var templ_7745c5c3_Var20 string
375- templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.ResolveAttributeValue(s.Key)388+ templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.ResolveAttributeValue(s.Key)
376 if templ_7745c5c3_Err != nil {389 if templ_7745c5c3_Err != nil {
377- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 76, Col: 24}390+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 77, Col: 24}
378 }391 }
379- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var19)392+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var20)
380 if templ_7745c5c3_Err != nil {393 if templ_7745c5c3_Err != nil {
381 return templ_7745c5c3_Err394 return templ_7745c5c3_Err
382 }395 }
383- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "\" aria-keyshortcuts=\"")396+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "\" aria-keyshortcuts=\"")
384 if templ_7745c5c3_Err != nil {397 if templ_7745c5c3_Err != nil {
385 return templ_7745c5c3_Err398 return templ_7745c5c3_Err
386 }399 }
387- var templ_7745c5c3_Var20 string400+ var templ_7745c5c3_Var21 string
388- templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.ResolveAttributeValue("g " + s.Key)401+ templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.ResolveAttributeValue("g " + s.Key)
389 if templ_7745c5c3_Err != nil {402 if templ_7745c5c3_Err != nil {
390- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 77, Col: 40}403+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 78, Col: 40}
391 }404 }
392- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var20)405+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var21)
393 if templ_7745c5c3_Err != nil {406 if templ_7745c5c3_Err != nil {
394 return templ_7745c5c3_Err407 return templ_7745c5c3_Err
395 }408 }
396- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "\"")409+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "\"")
397 if templ_7745c5c3_Err != nil {410 if templ_7745c5c3_Err != nil {
398 return templ_7745c5c3_Err411 return templ_7745c5c3_Err
399 }412 }
400 if s.Current {413 if s.Current {
401- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, " aria-current=\"page\"")414+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, " aria-current=\"page\"")
402 if templ_7745c5c3_Err != nil {415 if templ_7745c5c3_Err != nil {
403 return templ_7745c5c3_Err416 return templ_7745c5c3_Err
404 }417 }
405 }418 }
406- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, ">")419+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, ">")
407 if templ_7745c5c3_Err != nil {420 if templ_7745c5c3_Err != nil {
408 return templ_7745c5c3_Err421 return templ_7745c5c3_Err
409 }422 }
410- var templ_7745c5c3_Var21 string423+ var templ_7745c5c3_Var22 string
411- templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(s.Key)424+ templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(s.Key)
412 if templ_7745c5c3_Err != nil {425 if templ_7745c5c3_Err != nil {
413- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 81, Col: 15}426+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 82, Col: 15}
414 }427 }
415- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))428+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
416 if templ_7745c5c3_Err != nil {429 if templ_7745c5c3_Err != nil {
417 return templ_7745c5c3_Err430 return templ_7745c5c3_Err
418 }431 }
419- var templ_7745c5c3_Var22 string432+ var templ_7745c5c3_Var23 string
420- templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(s.Post)433+ templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(s.Post)
421 if templ_7745c5c3_Err != nil {434 if templ_7745c5c3_Err != nil {
422- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 81, Col: 25}435+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 82, Col: 25}
423 }436 }
424- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))437+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
425 if templ_7745c5c3_Err != nil {438 if templ_7745c5c3_Err != nil {
426 return templ_7745c5c3_Err439 return templ_7745c5c3_Err
427 }440 }
428- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "</a></li>")441+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "</a></li>")
429 if templ_7745c5c3_Err != nil {442 if templ_7745c5c3_Err != nil {
430 return templ_7745c5c3_Err443 return templ_7745c5c3_Err
431 }444 }
432 }445 }
433- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "</ul></nav>")446+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</ul></nav>")
434 if templ_7745c5c3_Err != nil {447 if templ_7745c5c3_Err != nil {
435 return templ_7745c5c3_Err448 return templ_7745c5c3_Err
436 }449 }
437 }450 }
438 if l.Ref != "" {451 if l.Ref != "" {
439- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "<button type=\"button\" class=\"ref\" aria-haspopup=\"dialog\" aria-controls=\"panel-refs\" aria-keyshortcuts=\"b\" title=\"switch ref (b)\" hx-on:click=\"document.body.dispatchEvent(new CustomEvent('k-refs'))\">")452+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<button type=\"button\" class=\"ref\" aria-haspopup=\"dialog\" aria-controls=\"panel-refs\" aria-keyshortcuts=\"b\" title=\"switch ref (b)\" hx-on:click=\"document.body.dispatchEvent(new CustomEvent('k-refs'))\">")
440 if templ_7745c5c3_Err != nil {453 if templ_7745c5c3_Err != nil {
441 return templ_7745c5c3_Err454 return templ_7745c5c3_Err
442 }455 }
443- var templ_7745c5c3_Var23 string456+ var templ_7745c5c3_Var24 string
444- templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(l.Ref)457+ templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(l.Ref)
445 if templ_7745c5c3_Err != nil {458 if templ_7745c5c3_Err != nil {
446- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 96, Col: 11}459+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 97, Col: 11}
447 }460 }
448- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))461+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
449 if templ_7745c5c3_Err != nil {462 if templ_7745c5c3_Err != nil {
450 return templ_7745c5c3_Err463 return templ_7745c5c3_Err
451 }464 }
452- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<span class=\"sha\">")465+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "<span class=\"sha\">")
453 if templ_7745c5c3_Err != nil {466 if templ_7745c5c3_Err != nil {
454 return templ_7745c5c3_Err467 return templ_7745c5c3_Err
455 }468 }
456- var templ_7745c5c3_Var24 string469+ var templ_7745c5c3_Var25 string
457- templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs("@" + l.Short)470+ templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs("@" + l.Short)
458 if templ_7745c5c3_Err != nil {471 if templ_7745c5c3_Err != nil {
459- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 96, Col: 46}472+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 97, Col: 46}
460 }473 }
461- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))474+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
462 if templ_7745c5c3_Err != nil {475 if templ_7745c5c3_Err != nil {
463 return templ_7745c5c3_Err476 return templ_7745c5c3_Err
464 }477 }
465- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</span></button>")478+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</span></button>")
466 if templ_7745c5c3_Err != nil {479 if templ_7745c5c3_Err != nil {
467 return templ_7745c5c3_Err480 return templ_7745c5c3_Err
468 }481 }
469 }482 }
470- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</header>")483+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</header>")
471 if templ_7745c5c3_Err != nil {484 if templ_7745c5c3_Err != nil {
472 return templ_7745c5c3_Err485 return templ_7745c5c3_Err
473 }486 }
@@ -494,61 +507,61 @@ func Statusbar(l Layout) templ.Component {
494 }()507 }()
495 }508 }
496 ctx = templ.InitializeContext(ctx)509 ctx = templ.InitializeContext(ctx)
497- templ_7745c5c3_Var25 := templ.GetChildren(ctx)510+ templ_7745c5c3_Var26 := templ.GetChildren(ctx)
498- if templ_7745c5c3_Var25 == nil {511+ if templ_7745c5c3_Var26 == nil {
499- templ_7745c5c3_Var25 = templ.NopComponent512+ templ_7745c5c3_Var26 = templ.NopComponent
500 }513 }
501 ctx = templ.ClearChildren(ctx)514 ctx = templ.ClearChildren(ctx)
502- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "<footer class=\"bar status\" aria-label=\"Status\"><span class=\"mode\">")515+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "<footer class=\"bar status\" aria-label=\"Status\"><span class=\"mode\">")
503 if templ_7745c5c3_Err != nil {516 if templ_7745c5c3_Err != nil {
504 return templ_7745c5c3_Err517 return templ_7745c5c3_Err
505 }518 }
506- var templ_7745c5c3_Var26 string519+ var templ_7745c5c3_Var27 string
507- templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(l.Status.Mode)520+ templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(l.Status.Mode)
508 if templ_7745c5c3_Err != nil {521 if templ_7745c5c3_Err != nil {
509- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 106, Col: 36}522+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 107, Col: 36}
510 }523 }
511- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))524+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
512 if templ_7745c5c3_Err != nil {525 if templ_7745c5c3_Err != nil {
513 return templ_7745c5c3_Err526 return templ_7745c5c3_Err
514 }527 }
515- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "</span> <span class=\"st-ctx\">")528+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "</span> <span class=\"st-ctx\">")
516 if templ_7745c5c3_Err != nil {529 if templ_7745c5c3_Err != nil {
517 return templ_7745c5c3_Err530 return templ_7745c5c3_Err
518 }531 }
519- var templ_7745c5c3_Var27 string532+ var templ_7745c5c3_Var28 string
520- templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(l.Status.Context)533+ templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(l.Status.Context)
521 if templ_7745c5c3_Err != nil {534 if templ_7745c5c3_Err != nil {
522- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 107, Col: 41}535+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 108, Col: 41}
523 }536 }
524- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))537+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
525 if templ_7745c5c3_Err != nil {538 if templ_7745c5c3_Err != nil {
526 return templ_7745c5c3_Err539 return templ_7745c5c3_Err
527 }540 }
528- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "</span> <button type=\"button\" class=\"st-cmd\" aria-haspopup=\"dialog\" aria-controls=\"panel-cmd\" aria-keyshortcuts=\":\" hx-on:click=\"document.body.dispatchEvent(new CustomEvent('k-cmd'))\"><span class=\"hi\">:</span> go to…</button> ")541+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "</span> <button type=\"button\" class=\"st-cmd\" aria-haspopup=\"dialog\" aria-controls=\"panel-cmd\" aria-keyshortcuts=\":\" hx-on:click=\"document.body.dispatchEvent(new CustomEvent('k-cmd'))\"><span class=\"hi\">:</span> go to…</button> ")
529 if templ_7745c5c3_Err != nil {542 if templ_7745c5c3_Err != nil {
530 return templ_7745c5c3_Err543 return templ_7745c5c3_Err
531 }544 }
532 if l.Status.Blob {545 if l.Status.Blob {
533- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "<span class=\"st-sel\" :text=\"document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : 'click a line number · shift-click extends'\">click a line number · shift-click extends</span> ")546+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "<span class=\"st-sel\" :text=\"document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : 'click a line number · shift-click extends'\">click a line number · shift-click extends</span> ")
534 if templ_7745c5c3_Err != nil {547 if templ_7745c5c3_Err != nil {
535 return templ_7745c5c3_Err548 return templ_7745c5c3_Err
536 }549 }
537 }550 }
538- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "<span class=\"st-flash\" aria-live=\"polite\" :text=\"document.body.dataset.flash || ''\"></span> <span class=\"st-hints\">")551+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "<span class=\"st-flash\" aria-live=\"polite\" :text=\"document.body.dataset.flash || ''\"></span> <span class=\"st-hints\">")
539 if templ_7745c5c3_Err != nil {552 if templ_7745c5c3_Err != nil {
540 return templ_7745c5c3_Err553 return templ_7745c5c3_Err
541 }554 }
542- var templ_7745c5c3_Var28 string555+ var templ_7745c5c3_Var29 string
543- templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(l.Status.Hints)556+ templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(l.Status.Hints)
544 if templ_7745c5c3_Err != nil {557 if templ_7745c5c3_Err != nil {
545- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 120, Col: 41}558+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 121, Col: 41}
546 }559 }
547- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))560+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
548 if templ_7745c5c3_Err != nil {561 if templ_7745c5c3_Err != nil {
549 return templ_7745c5c3_Err562 return templ_7745c5c3_Err
550 }563 }
551- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "</span>")564+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "</span>")
552 if templ_7745c5c3_Err != nil {565 if templ_7745c5c3_Err != nil {
553 return templ_7745c5c3_Err566 return templ_7745c5c3_Err
554 }567 }
@@ -561,25 +574,25 @@ func Statusbar(l Layout) templ.Component {
561 return templ_7745c5c3_Err574 return templ_7745c5c3_Err
562 }575 }
563 if l.Status.Cursor {576 if l.Status.Cursor {
564- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "<span class=\"st-pos num\" title=\"cursor position\" :text=\"(() => { let all = q('[data-rows] > :not([hidden])').arr(); let i = all.findIndex(r => r.hasAttribute('data-cursor')); return (i + 1) + '/' + all.length })()\">")577+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "<span class=\"st-pos num\" title=\"cursor position\" :text=\"(() => { let all = q('[data-rows] > :not([hidden])').arr(); let i = all.findIndex(r => r.hasAttribute('data-cursor')); return (i + 1) + '/' + all.length })()\">")
565 if templ_7745c5c3_Err != nil {578 if templ_7745c5c3_Err != nil {
566 return templ_7745c5c3_Err579 return templ_7745c5c3_Err
567 }580 }
568- var templ_7745c5c3_Var29 string581+ var templ_7745c5c3_Var30 string
569- templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(cursorText(l.Status.Count))582+ templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(cursorText(l.Status.Count))
570 if templ_7745c5c3_Err != nil {583 if templ_7745c5c3_Err != nil {
571- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 128, Col: 32}584+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 129, Col: 32}
572 }585 }
573- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))586+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
574 if templ_7745c5c3_Err != nil {587 if templ_7745c5c3_Err != nil {
575 return templ_7745c5c3_Err588 return templ_7745c5c3_Err
576 }589 }
577- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "</span>")590+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "</span>")
578 if templ_7745c5c3_Err != nil {591 if templ_7745c5c3_Err != nil {
579 return templ_7745c5c3_Err592 return templ_7745c5c3_Err
580 }593 }
581 }594 }
582- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "</footer>")595+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "</footer>")
583 if templ_7745c5c3_Err != nil {596 if templ_7745c5c3_Err != nil {
584 return templ_7745c5c3_Err597 return templ_7745c5c3_Err
585 }598 }
@@ -605,38 +618,38 @@ func Footer(l Layout) templ.Component {
605 }()618 }()
606 }619 }
607 ctx = templ.InitializeContext(ctx)620 ctx = templ.InitializeContext(ctx)
608- templ_7745c5c3_Var30 := templ.GetChildren(ctx)621+ templ_7745c5c3_Var31 := templ.GetChildren(ctx)
609- if templ_7745c5c3_Var30 == nil {622+ if templ_7745c5c3_Var31 == nil {
610- templ_7745c5c3_Var30 = templ.NopComponent623+ templ_7745c5c3_Var31 = templ.NopComponent
611 }624 }
612 ctx = templ.ClearChildren(ctx)625 ctx = templ.ClearChildren(ctx)
613- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "<span class=\"st-src\"><span class=\"st-ver\">ermite ")626+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "<span class=\"st-src\"><span class=\"st-ver\">ermite ")
614 if templ_7745c5c3_Err != nil {627 if templ_7745c5c3_Err != nil {
615 return templ_7745c5c3_Err628 return templ_7745c5c3_Err
616 }629 }
617- var templ_7745c5c3_Var31 string630+ var templ_7745c5c3_Var32 string
618- templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(l.Version)631+ templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(l.Version)
619 if templ_7745c5c3_Err != nil {632 if templ_7745c5c3_Err != nil {
620- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 136, Col: 61}633+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 137, Col: 61}
621 }634 }
622- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31))635+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32))
623 if templ_7745c5c3_Err != nil {636 if templ_7745c5c3_Err != nil {
624 return templ_7745c5c3_Err637 return templ_7745c5c3_Err
625 }638 }
626- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, " · </span><a href=\"")639+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, " · </span><a href=\"")
627 if templ_7745c5c3_Err != nil {640 if templ_7745c5c3_Err != nil {
628 return templ_7745c5c3_Err641 return templ_7745c5c3_Err
629 }642 }
630- var templ_7745c5c3_Var32 templ.SafeURL643+ var templ_7745c5c3_Var33 templ.SafeURL
631- templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(l.SourceURL))644+ templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(l.SourceURL))
632 if templ_7745c5c3_Err != nil {645 if templ_7745c5c3_Err != nil {
633- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 136, Col: 110}646+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/shell.templ`, Line: 137, Col: 110}
634 }647 }
635- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32))648+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33))
636 if templ_7745c5c3_Err != nil {649 if templ_7745c5c3_Err != nil {
637 return templ_7745c5c3_Err650 return templ_7745c5c3_Err
638 }651 }
639- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "\" rel=\"noopener\" title=\"source of this version (AGPL-3.0-or-later)\">source</a></span>")652+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "\" rel=\"noopener\" title=\"source of this version (AGPL-3.0-or-later)\">source</a></span>")
640 if templ_7745c5c3_Err != nil {653 if templ_7745c5c3_Err != nil {
641 return templ_7745c5c3_Err654 return templ_7745c5c3_Err
642 }655 }
M internal/adapters/web/static/css/40-summary.css +1 -1
@@ -27,7 +27,7 @@
2727 & ol { list-style: decimal; }
2828 & li > ul, & li > ol, & li > p { margin-top: 0; }
2929 & pre { padding: 0 1ch; border-left: 1px solid var(--ink-mute); overflow-x: auto; font-size: var(--fs-code); line-height: var(--lh-code); }
30- & :not(pre) > code { border-bottom: 1px dotted var(--ink-mute); }
30+ & :not(pre) > code { border-bottom: 1px dotted var(--ink-mute); overflow-wrap: anywhere; }
3131 & blockquote { padding-left: 2ch; border-left: 1px solid var(--rule); color: var(--ink-dim); }
3232 & table { border-collapse: collapse; display: block; overflow-x: auto; }
3333 & th, & td { padding: 0 2ch 0 0; white-space: nowrap; vertical-align: top; }
@@ -27,7 +27,7 @@
27 & ol { list-style: decimal; }27 & ol { list-style: decimal; }
28 & li > ul, & li > ol, & li > p { margin-top: 0; }28 & li > ul, & li > ol, & li > p { margin-top: 0; }
29 & pre { padding: 0 1ch; border-left: 1px solid var(--ink-mute); overflow-x: auto; font-size: var(--fs-code); line-height: var(--lh-code); }29 & pre { padding: 0 1ch; border-left: 1px solid var(--ink-mute); overflow-x: auto; font-size: var(--fs-code); line-height: var(--lh-code); }
30- & :not(pre) > code { border-bottom: 1px dotted var(--ink-mute); }30+ & :not(pre) > code { border-bottom: 1px dotted var(--ink-mute); overflow-wrap: anywhere; }
31 & blockquote { padding-left: 2ch; border-left: 1px solid var(--rule); color: var(--ink-dim); }31 & blockquote { padding-left: 2ch; border-left: 1px solid var(--rule); color: var(--ink-dim); }
32 & table { border-collapse: collapse; display: block; overflow-x: auto; }32 & table { border-collapse: collapse; display: block; overflow-x: auto; }
33 & th, & td { padding: 0 2ch 0 0; white-space: nowrap; vertical-align: top; }33 & th, & td { padding: 0 2ch 0 0; white-space: nowrap; vertical-align: top; }
M internal/adapters/web/static/css/50-code.css +4 -0
@@ -111,6 +111,10 @@
111111 }
112112 .rail p + p { margin-top: 0; }
113113 .rail section > p { overflow-wrap: anywhere; }
114+ @media (max-width: 700px) {
115+ /* the name takes what the fixed columns leave */
116+ .list.tree .c-name, .list.refs .c-name { width: auto; }
117+ }
114118 }
115119
116120 @layer components {
@@ -111,6 +111,10 @@
111 }111 }
112 .rail p + p { margin-top: 0; }112 .rail p + p { margin-top: 0; }
113 .rail section > p { overflow-wrap: anywhere; }113 .rail section > p { overflow-wrap: anywhere; }
114+ @media (max-width: 700px) {
115+ /* the name takes what the fixed columns leave */
116+ .list.tree .c-name, .list.refs .c-name { width: auto; }
117+ }
114 }118 }
115 119
116 @layer components {120 @layer components {
A internal/adapters/web/static/icon.svg +1 -0
@@ -0,0 +1,1 @@
1+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><rect width="16" height="16" fill="#161616"/><path d="M4 4h8M4 8h6M4 12h8M4 4v8" stroke="#d0d0d0" stroke-width="2" fill="none"/></svg>
@@ -0,0 +1,1 @@
1+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><rect width="16" height="16" fill="#161616"/><path d="M4 4h8M4 8h6M4 12h8M4 4v8" stroke="#d0d0d0" stroke-width="2" fill="none"/></svg>

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 2

Tags 45

↑↓ moveenter openesc close