+5
-1
cmd/legit/main.go
+5
-1
cmd/legit/main.go
···
3
3
import (
4
4
"flag"
5
5
"fmt"
6
+
"html/template"
6
7
"log"
7
8
"net/http"
9
+
"path/filepath"
8
10
9
11
"github.com/icyphox/bild/legit/config"
10
12
"github.com/icyphox/bild/legit/routes"
···
20
22
log.Fatal(err)
21
23
}
22
24
23
-
mux := routes.Handlers(c)
25
+
t := template.Must(template.ParseGlob(filepath.Join(c.Dirs.Templates, "*")))
26
+
27
+
mux := routes.Handlers(c, t)
24
28
addr := fmt.Sprintf("%s:%d", c.Server.Host, c.Server.Port)
25
29
log.Println("starting server on", addr)
26
30
log.Fatal(http.ListenAndServe(addr, mux))
+30
-24
flake.nix
+30
-24
flake.nix
···
15
15
};
16
16
};
17
17
18
-
outputs = {
19
-
self,
20
-
nixpkgs,
21
-
gitignore,
22
-
rust-overlay,
23
-
}: let
24
-
supportedSystems = ["x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin"];
25
-
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
26
-
nixpkgsFor = forAllSystems (system:
27
-
import nixpkgs {
28
-
inherit system;
29
-
overlays = [(import rust-overlay)];
30
-
});
31
-
in {
32
-
defaultPackage = forAllSystems (system: self.packages.${system}.legit);
33
-
formatter = forAllSystems (system: nixpkgsFor."${system}".alejandra);
34
-
devShells = forAllSystems (system: let
35
-
pkgs = nixpkgsFor.${system};
36
-
rust-bin = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
37
-
in {
38
-
default = pkgs.mkShell {
39
-
nativeBuildInputs = [
40
-
pkgs.go
41
-
pkgs.air
18
+
outputs =
19
+
{ self
20
+
, nixpkgs
21
+
, gitignore
22
+
, rust-overlay
23
+
,
24
+
}:
25
+
let
26
+
supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ];
27
+
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
28
+
nixpkgsFor = forAllSystems (system:
29
+
import nixpkgs {
30
+
inherit system;
31
+
overlays = [ (import rust-overlay) ];
32
+
});
33
+
in
34
+
{
35
+
defaultPackage = forAllSystems (system: self.packages.${system}.legit);
36
+
formatter = forAllSystems (system: nixpkgsFor."${system}".alejandra);
37
+
devShells = forAllSystems (system:
38
+
let
39
+
pkgs = nixpkgsFor.${system};
40
+
rust-bin = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
41
+
in
42
+
{
43
+
default = pkgs.mkShell {
44
+
nativeBuildInputs = [
45
+
pkgs.go
46
+
pkgs.air
47
+
pkgs.templ
42
48
43
49
pkgs.httpie
44
50
pkgs.bacon
+6
-4
go.mod
+6
-4
go.mod
···
1
1
module github.com/icyphox/bild
2
2
3
-
go 1.22.0
3
+
go 1.23
4
+
5
+
toolchain go1.23.4
4
6
5
7
require (
6
8
github.com/alecthomas/chroma/v2 v2.14.0
···
33
35
github.com/sergi/go-diff v1.3.1 // indirect
34
36
github.com/skeema/knownhosts v1.3.0 // indirect
35
37
github.com/xanzy/ssh-agent v0.3.3 // indirect
36
-
golang.org/x/crypto v0.28.0 // indirect
37
-
golang.org/x/net v0.30.0 // indirect
38
-
golang.org/x/sys v0.26.0 // indirect
38
+
golang.org/x/crypto v0.31.0 // indirect
39
+
golang.org/x/net v0.33.0 // indirect
40
+
golang.org/x/sys v0.28.0 // indirect
39
41
gopkg.in/warnings.v0 v0.1.2 // indirect
40
42
)
41
43
+10
-10
go.sum
+10
-10
go.sum
···
119
119
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
120
120
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
121
121
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
122
-
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
123
-
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
122
+
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
123
+
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
124
124
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
125
125
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
126
126
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
···
134
134
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
135
135
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
136
136
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
137
-
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
138
-
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
137
+
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
138
+
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
139
139
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
140
140
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
141
141
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
···
158
158
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
159
159
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
160
160
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
161
-
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
162
-
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
161
+
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
162
+
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
163
163
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
164
164
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
165
165
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
···
167
167
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
168
168
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
169
169
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
170
-
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
171
-
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
170
+
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
171
+
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
172
172
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
173
173
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
174
174
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
···
176
176
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
177
177
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
178
178
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
179
-
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
180
-
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
179
+
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
180
+
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
181
181
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
182
182
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
183
183
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+4
-2
legit/routes/handler.go
+4
-2
legit/routes/handler.go
···
1
1
package routes
2
2
3
3
import (
4
+
"html/template"
4
5
"net/http"
5
6
6
7
"github.com/go-chi/chi/v5"
···
29
30
}
30
31
}
31
32
32
-
func Handlers(c *config.Config) http.Handler {
33
+
func Handlers(c *config.Config, t *template.Template) http.Handler {
33
34
r := chi.NewRouter()
34
-
d := deps{c}
35
+
d := deps{c, t}
35
36
37
+
r.Get("/login", d.Login)
36
38
r.Get("/static/{file}", d.ServeStatic)
37
39
38
40
r.Route("/@{user}", func(r chi.Router) {
+13
-20
legit/routes/routes.go
+13
-20
legit/routes/routes.go
···
22
22
23
23
type deps struct {
24
24
c *config.Config
25
+
t *template.Template
25
26
}
26
27
27
28
func (d *deps) Index(w http.ResponseWriter, r *http.Request) {
···
73
74
return infos[j].d.Before(infos[i].d)
74
75
})
75
76
76
-
tpath := filepath.Join(d.c.Dirs.Templates, "*")
77
-
t := template.Must(template.ParseGlob(tpath))
78
-
79
77
data := make(map[string]interface{})
80
78
data["meta"] = d.c.Meta
81
79
data["info"] = infos
82
80
83
-
if err := t.ExecuteTemplate(w, "index", data); err != nil {
81
+
if err := d.t.ExecuteTemplate(w, "index", data); err != nil {
84
82
log.Println(err)
85
83
return
86
84
}
···
142
140
log.Println(err)
143
141
return
144
142
}
145
-
146
-
tpath := filepath.Join(d.c.Dirs.Templates, "*")
147
-
t := template.Must(template.ParseGlob(tpath))
148
143
149
144
if len(commits) >= 3 {
150
145
commits = commits[:3]
···
161
156
data["meta"] = d.c.Meta
162
157
data["gomod"] = isGoModule(gr)
163
158
164
-
if err := t.ExecuteTemplate(w, "repo", data); err != nil {
159
+
if err := d.t.ExecuteTemplate(w, "repo", data); err != nil {
165
160
log.Println(err)
166
161
return
167
162
}
···
327
322
return
328
323
}
329
324
330
-
tpath := filepath.Join(d.c.Dirs.Templates, "*")
331
-
t := template.Must(template.ParseGlob(tpath))
332
-
333
325
data := make(map[string]interface{})
334
326
data["commits"] = commits
335
327
data["meta"] = d.c.Meta
···
339
331
data["desc"] = getDescription(path)
340
332
data["log"] = true
341
333
342
-
if err := t.ExecuteTemplate(w, "log", data); err != nil {
334
+
if err := d.t.ExecuteTemplate(w, "log", data); err != nil {
343
335
log.Println(err)
344
336
return
345
337
}
···
367
359
return
368
360
}
369
361
370
-
tpath := filepath.Join(d.c.Dirs.Templates, "*")
371
-
t := template.Must(template.ParseGlob(tpath))
372
-
373
362
data := make(map[string]interface{})
374
363
375
364
data["commit"] = diff.Commit
···
381
370
data["ref"] = ref
382
371
data["desc"] = getDescription(path)
383
372
384
-
if err := t.ExecuteTemplate(w, "commit", data); err != nil {
373
+
if err := d.t.ExecuteTemplate(w, "commit", data); err != nil {
385
374
log.Println(err)
386
375
return
387
376
}
···
414
403
return
415
404
}
416
405
417
-
tpath := filepath.Join(d.c.Dirs.Templates, "*")
418
-
t := template.Must(template.ParseGlob(tpath))
419
-
420
406
data := make(map[string]interface{})
421
407
422
408
data["meta"] = d.c.Meta
···
426
412
data["tags"] = tags
427
413
data["desc"] = getDescription(path)
428
414
429
-
if err := t.ExecuteTemplate(w, "refs", data); err != nil {
415
+
if err := d.t.ExecuteTemplate(w, "refs", data); err != nil {
430
416
log.Println(err)
431
417
return
432
418
}
···
438
424
439
425
http.ServeFile(w, r, f)
440
426
}
427
+
428
+
func (d *deps) Login(w http.ResponseWriter, r *http.Request) {
429
+
if err := d.t.ExecuteTemplate(w, "login", nil); err != nil {
430
+
log.Println(err)
431
+
return
432
+
}
433
+
}
+29
legit/templates/login.html
+29
legit/templates/login.html
···
1
+
{{ define "login" }}
2
+
<html>
3
+
{{ template "head" . }}
4
+
5
+
<body>
6
+
<main>
7
+
<form
8
+
class="form-login"
9
+
method="post"
10
+
action="http://localhost:3000/login"
11
+
>
12
+
<p>
13
+
You will be redirected to bsky.app (or your PDS) to complete
14
+
login.
15
+
</p>
16
+
<div>
17
+
<input
18
+
type="text"
19
+
id="handle"
20
+
name="handle"
21
+
placeholder="@username.bsky.social"
22
+
/>
23
+
</div>
24
+
<button type="submit">Login</button>
25
+
</form>
26
+
</main>
27
+
</body>
28
+
</html>
29
+
{{ end }}