+3
-2
README.md
+3
-2
README.md
···
9
10
ยตgit allows cloning via HTTPS/SSH, but can only be pushed to via SSH.
11
12
-
There are no plans to directly support issues or PR workflows, although webhooks are planned and auxillary software may be created to facilitate these things.
13
-
If you wish to collaborate, please send me patches via [git-pr](https://pr.jolheiser.com/repos/ugit).
14
15
Currently all HTML is allowed in markdown, ยตgit is intended to be run by/for a trusted user.
16
···
9
10
ยตgit allows cloning via HTTPS/SSH, but can only be pushed to via SSH.
11
12
+
There are no plans to directly support issues or PR workflows.
13
+
If you wish to collaborate, please send me patches via [github](https://github.com/jolheiser/ugit) or [tangled](https://tangled.org/@jolheiser.com/ugit).
14
+
For issue/bug-tracking, I recommend [git-bug](https://github.com/git-bug/git-bug).
15
16
Currently all HTML is allowed in markdown, ยตgit is intended to be run by/for a trusted user.
17
-2
cmd/ugitd/args.go
-2
cmd/ugitd/args.go
···
18
Profile profileArgs
19
Log logArgs
20
ShowPrivate bool
21
-
TUI bool
22
}
23
24
type sshArgs struct {
···
115
fs.StringVar(&c.Meta.Description, "meta.description", c.Meta.Description, "App description")
116
fs.StringVar(&c.Profile.Username, "profile.username", c.Profile.Username, "Username for index page")
117
fs.StringVar(&c.Profile.Email, "profile.email", c.Profile.Email, "Email for index page")
118
-
fs.BoolVar(&c.TUI, "tui", c.TUI, "Run the TUI interface directly")
119
fs.Func("profile.links", "Link(s) for index page", func(s string) error {
120
parts := strings.SplitN(s, ",", 2)
121
if len(parts) != 2 {
···
18
Profile profileArgs
19
Log logArgs
20
ShowPrivate bool
21
}
22
23
type sshArgs struct {
···
114
fs.StringVar(&c.Meta.Description, "meta.description", c.Meta.Description, "App description")
115
fs.StringVar(&c.Profile.Username, "profile.username", c.Profile.Username, "Username for index page")
116
fs.StringVar(&c.Profile.Email, "profile.email", c.Profile.Email, "Email for index page")
117
fs.Func("profile.links", "Link(s) for index page", func(s string) error {
118
parts := strings.SplitN(s, ",", 2)
119
if len(parts) != 2 {
+5
-14
cmd/ugitd/main.go
+5
-14
cmd/ugitd/main.go
···
20
"go.jolheiser.com/ugit/internal/git"
21
"go.jolheiser.com/ugit/internal/http"
22
"go.jolheiser.com/ugit/internal/ssh"
23
-
"go.jolheiser.com/ugit/internal/tui"
24
)
25
26
func main() {
···
39
args.RepoDir, err = filepath.Abs(args.RepoDir)
40
if err != nil {
41
panic(err)
42
-
}
43
-
44
-
// Run TUI mode if requested
45
-
if args.TUI {
46
-
if err := tui.Run(args.RepoDir); err != nil {
47
-
panic(err)
48
-
}
49
-
return
50
}
51
52
slog.SetLogLoggerLevel(args.Log.Level)
···
152
if err != nil {
153
return err
154
}
155
-
fi.WriteString("#!/usr/bin/env bash\n")
156
-
fi.WriteString(fmt.Sprintf("%s pre-receive-hook\n", bin))
157
-
fi.WriteString(fmt.Sprintf(`for hook in %s.d/*; do
158
test -x "${hook}" && test -f "${hook}" || continue
159
"${hook}"
160
-
done`, fp))
161
fi.Close()
162
163
return os.Chmod(fp, 0o755)
···
171
172
opts := make([]*packp.Option, 0)
173
if pushCount, err := strconv.Atoi(os.Getenv("GIT_PUSH_OPTION_COUNT")); err == nil {
174
-
for idx := 0; idx < pushCount; idx++ {
175
opt := os.Getenv(fmt.Sprintf("GIT_PUSH_OPTION_%d", idx))
176
kv := strings.SplitN(opt, "=", 2)
177
if len(kv) == 2 {
···
20
"go.jolheiser.com/ugit/internal/git"
21
"go.jolheiser.com/ugit/internal/http"
22
"go.jolheiser.com/ugit/internal/ssh"
23
)
24
25
func main() {
···
38
args.RepoDir, err = filepath.Abs(args.RepoDir)
39
if err != nil {
40
panic(err)
41
}
42
43
slog.SetLogLoggerLevel(args.Log.Level)
···
143
if err != nil {
144
return err
145
}
146
+
fmt.Fprintln(fi, "#!/usr/bin/env bash")
147
+
fmt.Fprintf(fi, "%s pre-receive-hook\n", bin)
148
+
fmt.Fprintf(fi, `for hook in %s.d/*; do
149
test -x "${hook}" && test -f "${hook}" || continue
150
"${hook}"
151
+
done`, fp)
152
fi.Close()
153
154
return os.Chmod(fp, 0o755)
···
162
163
opts := make([]*packp.Option, 0)
164
if pushCount, err := strconv.Atoi(os.Getenv("GIT_PUSH_OPTION_COUNT")); err == nil {
165
+
for idx := range pushCount {
166
opt := os.Getenv(fmt.Sprintf("GIT_PUSH_OPTION_%d", idx))
167
kv := strings.SplitN(opt, "=", 2)
168
if len(kv) == 2 {
+7
-7
flake.lock
+7
-7
flake.lock
···
2
"nodes": {
3
"nixpkgs": {
4
"locked": {
5
-
"lastModified": 1736241350,
6
-
"narHash": "sha256-CHd7yhaDigUuJyDeX0SADbTM9FXfiWaeNyY34FL1wQU=",
7
"owner": "nixos",
8
"repo": "nixpkgs",
9
-
"rev": "8c9fd3e564728e90829ee7dbac6edc972971cd0f",
10
"type": "github"
11
},
12
"original": {
···
30
]
31
},
32
"locked": {
33
-
"lastModified": 1695841587,
34
-
"narHash": "sha256-fgiZd5AV+hi8Ne0bJ8SyAx5nppseW4aXJQEIDSr0VNA=",
35
"ref": "refs/heads/main",
36
-
"rev": "afca060674b20e0ccecde2d6fe88c887790219a5",
37
-
"revCount": 1,
38
"type": "git",
39
"url": "https://git.jolheiser.com/tailwind-ctp"
40
},
···
2
"nodes": {
3
"nixpkgs": {
4
"locked": {
5
+
"lastModified": 1755205935,
6
+
"narHash": "sha256-EQ6qHuJWguaoBZyxdqsgJqyEdS77k+2CnlKrfFxlkRY=",
7
"owner": "nixos",
8
"repo": "nixpkgs",
9
+
"rev": "c5e2e42c112de623adfd662b3e51f0805bf9ff83",
10
"type": "github"
11
},
12
"original": {
···
30
]
31
},
32
"locked": {
33
+
"lastModified": 1753803577,
34
+
"narHash": "sha256-sE5IgsHacXmfsWJjVVPvb7Aa6oHElt+nfP6+3Pqa414=",
35
"ref": "refs/heads/main",
36
+
"rev": "4ce9431cbb4e9e5dceadfbc413fbd34e7305fe8e",
37
+
"revCount": 3,
38
"type": "git",
39
"url": "https://git.jolheiser.com/tailwind-ctp"
40
},
+4
-4
flake.nix
+4
-4
flake.nix
···
34
tctpl = forAllSystems (system: tailwind-ctp-lsp.packages.${system}.default);
35
in
36
{
37
-
packages = forAllSystems (system: import ./nix { pkgs = import nixpkgs { inherit system; }; });
38
devShells = forAllSystems (
39
system:
40
let
41
-
pkgs = import nixpkgs { inherit system; };
42
in
43
{
44
default = pkgs.mkShell {
···
47
gopls
48
air
49
tctp.${system}
50
-
tctpl.${system}
51
-
vscode-langservers-extracted
52
];
53
};
54
}
···
34
tctpl = forAllSystems (system: tailwind-ctp-lsp.packages.${system}.default);
35
in
36
{
37
+
packages = forAllSystems (system: import ./nix { pkgs = nixpkgs.legacyPackages.${system}; });
38
devShells = forAllSystems (
39
system:
40
let
41
+
pkgs = nixpkgs.legacyPackages.${system};
42
in
43
{
44
default = pkgs.mkShell {
···
47
gopls
48
air
49
tctp.${system}
50
+
#tctpl.${system}
51
+
#vscode-langservers-extracted
52
];
53
};
54
}
+64
-48
go.mod
+64
-48
go.mod
···
1
module go.jolheiser.com/ugit
2
3
-
go 1.23.1
4
-
5
-
toolchain go1.23.3
6
7
require (
8
github.com/alecthomas/assert/v2 v2.11.0
9
-
github.com/alecthomas/chroma/v2 v2.15.0
10
-
github.com/charmbracelet/bubbles v0.21.0
11
-
github.com/charmbracelet/bubbletea v1.3.5
12
-
github.com/charmbracelet/lipgloss v1.1.0
13
-
github.com/charmbracelet/ssh v0.0.0-20241211182756-4fe22b0f1b7c
14
-
github.com/charmbracelet/wish v1.4.4
15
github.com/dustin/go-humanize v1.0.1
16
-
github.com/go-chi/chi/v5 v5.2.0
17
github.com/go-chi/httplog/v2 v2.1.1
18
-
github.com/go-git/go-billy/v5 v5.6.1
19
-
github.com/go-git/go-git/v5 v5.13.1
20
github.com/peterbourgon/ff/v3 v3.4.0
21
-
github.com/yuin/goldmark v1.7.8
22
-
github.com/yuin/goldmark-emoji v1.0.4
23
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
24
-
golang.org/x/net v0.34.0
25
-
maragu.dev/gomponents v1.0.0
26
)
27
28
require (
29
-
dario.cat/mergo v1.0.1 // indirect
30
github.com/Microsoft/go-winio v0.6.2 // indirect
31
-
github.com/ProtonMail/go-crypto v1.1.4 // indirect
32
-
github.com/alecthomas/repr v0.4.0 // indirect
33
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
34
-
github.com/atotto/clipboard v0.1.4 // indirect
35
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
36
-
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
37
-
github.com/charmbracelet/keygen v0.5.1 // indirect
38
-
github.com/charmbracelet/log v0.4.0 // indirect
39
-
github.com/charmbracelet/x/ansi v0.8.0 // indirect
40
-
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
41
-
github.com/charmbracelet/x/conpty v0.1.0 // indirect
42
-
github.com/charmbracelet/x/errors v0.0.0-20250107110353-48b574af22a5 // indirect
43
-
github.com/charmbracelet/x/input v0.2.0 // indirect
44
github.com/charmbracelet/x/term v0.2.1 // indirect
45
-
github.com/charmbracelet/x/termios v0.1.0 // indirect
46
-
github.com/cloudflare/circl v1.5.0 // indirect
47
github.com/creack/pty v1.1.24 // indirect
48
-
github.com/cyphar/filepath-securejoin v0.3.6 // indirect
49
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
50
-
github.com/dlclark/regexp2 v1.11.4 // indirect
51
github.com/emirpasic/gods v1.18.1 // indirect
52
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
53
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
54
-
github.com/go-logfmt/logfmt v0.6.0 // indirect
55
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
56
github.com/hexops/gotextdiff v1.0.3 // indirect
57
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
58
-
github.com/kevinburke/ssh_config v1.2.0 // indirect
59
-
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
60
github.com/mattn/go-isatty v0.0.20 // indirect
61
github.com/mattn/go-localereader v0.0.1 // indirect
62
-
github.com/mattn/go-runewidth v0.0.16 // indirect
63
-
github.com/mmcloughlin/avo v0.6.0 // indirect
64
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
65
github.com/muesli/cancelreader v0.2.2 // indirect
66
github.com/muesli/termenv v0.16.0 // indirect
67
-
github.com/pjbgf/sha1cd v0.3.1 // indirect
68
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
69
github.com/rivo/uniseg v0.4.7 // indirect
70
-
github.com/sahilm/fuzzy v0.1.1 // indirect
71
-
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
72
-
github.com/skeema/knownhosts v1.3.0 // indirect
73
github.com/xanzy/ssh-agent v0.3.3 // indirect
74
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
75
-
golang.org/x/crypto v0.32.0 // indirect
76
-
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
77
-
golang.org/x/mod v0.22.0 // indirect
78
-
golang.org/x/sync v0.13.0 // indirect
79
-
golang.org/x/sys v0.32.0 // indirect
80
-
golang.org/x/text v0.21.0 // indirect
81
-
golang.org/x/tools v0.29.0 // indirect
82
gopkg.in/warnings.v0 v0.1.2 // indirect
83
gopkg.in/yaml.v2 v2.4.0 // indirect
84
)
···
1
module go.jolheiser.com/ugit
2
3
+
go 1.24.0
4
5
require (
6
+
github.com/a-h/templ v0.3.960
7
github.com/alecthomas/assert/v2 v2.11.0
8
+
github.com/alecthomas/chroma/v2 v2.20.0
9
+
github.com/charmbracelet/ssh v0.0.0-20250826160808-ebfa259c7309
10
+
github.com/charmbracelet/wish v1.4.7
11
github.com/dustin/go-humanize v1.0.1
12
+
github.com/go-chi/chi/v5 v5.2.3
13
github.com/go-chi/httplog/v2 v2.1.1
14
+
github.com/go-git/go-billy/v5 v5.6.2
15
+
github.com/go-git/go-git/v5 v5.16.3
16
github.com/peterbourgon/ff/v3 v3.4.0
17
+
github.com/yuin/goldmark v1.7.13
18
+
github.com/yuin/goldmark-emoji v1.0.6
19
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
20
+
golang.org/x/net v0.46.0
21
)
22
23
require (
24
+
dario.cat/mergo v1.0.2 // indirect
25
github.com/Microsoft/go-winio v0.6.2 // indirect
26
+
github.com/ProtonMail/go-crypto v1.3.0 // indirect
27
+
github.com/a-h/parse v0.0.0-20250122154542-74294addb73e // indirect
28
+
github.com/alecthomas/repr v0.5.1 // indirect
29
+
github.com/andybalholm/brotli v1.1.0 // indirect
30
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
31
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
32
+
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
33
+
github.com/charmbracelet/bubbletea v1.3.10 // indirect
34
+
github.com/charmbracelet/colorprofile v0.3.2 // indirect
35
+
github.com/charmbracelet/keygen v0.5.4 // indirect
36
+
github.com/charmbracelet/lipgloss v1.1.0 // indirect
37
+
github.com/charmbracelet/log v0.4.2 // indirect
38
+
github.com/charmbracelet/x/ansi v0.10.2 // indirect
39
+
github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
40
+
github.com/charmbracelet/x/conpty v0.1.1 // indirect
41
+
github.com/charmbracelet/x/errors v0.0.0-20251030181443-0cf22f8402df // indirect
42
github.com/charmbracelet/x/term v0.2.1 // indirect
43
+
github.com/charmbracelet/x/termios v0.1.1 // indirect
44
+
github.com/cli/browser v1.3.0 // indirect
45
+
github.com/clipperhouse/stringish v0.1.1 // indirect
46
+
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
47
+
github.com/cloudflare/circl v1.6.1 // indirect
48
github.com/creack/pty v1.1.24 // indirect
49
+
github.com/cyphar/filepath-securejoin v0.5.0 // indirect
50
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
51
+
github.com/dlclark/regexp2 v1.11.5 // indirect
52
github.com/emirpasic/gods v1.18.1 // indirect
53
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
54
+
github.com/fatih/color v1.16.0 // indirect
55
+
github.com/fsnotify/fsnotify v1.7.0 // indirect
56
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
57
+
github.com/go-logfmt/logfmt v0.6.1 // indirect
58
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
59
github.com/hexops/gotextdiff v1.0.3 // indirect
60
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
61
+
github.com/kevinburke/ssh_config v1.4.0 // indirect
62
+
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
63
+
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
64
+
github.com/mattn/go-colorable v0.1.13 // indirect
65
github.com/mattn/go-isatty v0.0.20 // indirect
66
github.com/mattn/go-localereader v0.0.1 // indirect
67
+
github.com/mattn/go-runewidth v0.0.19 // indirect
68
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
69
github.com/muesli/cancelreader v0.2.2 // indirect
70
github.com/muesli/termenv v0.16.0 // indirect
71
+
github.com/natefinch/atomic v1.0.1 // indirect
72
+
github.com/pjbgf/sha1cd v0.5.0 // indirect
73
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
74
github.com/rivo/uniseg v0.4.7 // indirect
75
+
github.com/sergi/go-diff v1.4.0 // indirect
76
+
github.com/skeema/knownhosts v1.3.2 // indirect
77
github.com/xanzy/ssh-agent v0.3.3 // indirect
78
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
79
+
golang.org/x/crypto v0.43.0 // indirect
80
+
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
81
+
golang.org/x/mod v0.29.0 // indirect
82
+
golang.org/x/sync v0.17.0 // indirect
83
+
golang.org/x/sys v0.37.0 // indirect
84
+
golang.org/x/text v0.30.0 // indirect
85
+
golang.org/x/tools v0.38.0 // indirect
86
gopkg.in/warnings.v0 v0.1.2 // indirect
87
gopkg.in/yaml.v2 v2.4.0 // indirect
88
)
89
+
90
+
tool (
91
+
github.com/a-h/templ/cmd/templ
92
+
go.jolheiser.com/ugit/assets
93
+
go.jolheiser.com/ugit/cmd/ugitd
94
+
go.jolheiser.com/ugit/internal/git
95
+
go.jolheiser.com/ugit/internal/html
96
+
go.jolheiser.com/ugit/internal/html/markup
97
+
go.jolheiser.com/ugit/internal/http
98
+
go.jolheiser.com/ugit/internal/http/httperr
99
+
go.jolheiser.com/ugit/internal/ssh
100
+
)
+1
-1
go.mod.sri
+1
-1
go.mod.sri
+110
-104
go.sum
+110
-104
go.sum
···
1
-
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
2
-
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
3
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
4
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
5
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
6
-
github.com/ProtonMail/go-crypto v1.1.4 h1:G5U5asvD5N/6/36oIw3k2bOfBn5XVcZrb7PBjzzKKoE=
7
-
github.com/ProtonMail/go-crypto v1.1.4/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
8
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
9
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
10
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
11
-
github.com/alecthomas/chroma/v2 v2.15.0 h1:LxXTQHFoYrstG2nnV9y2X5O94sOBzf0CIUpSTbpxvMc=
12
-
github.com/alecthomas/chroma/v2 v2.15.0/go.mod h1:gUhVLrPDXPtp/f+L1jo9xepo9gL4eLwRuGAunSZMkio=
13
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
14
-
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
15
-
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
16
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
17
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
18
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
19
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
20
-
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
21
-
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
22
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
23
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
24
-
github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
25
-
github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
26
-
github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs=
27
-
github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg=
28
-
github.com/charmbracelet/bubbletea v1.3.5 h1:JAMNLTbqMOhSwoELIr0qyP4VidFq72/6E9j7HHmRKQc=
29
-
github.com/charmbracelet/bubbletea v1.3.5/go.mod h1:TkCnmH+aBd4LrXhXcqrKiYwRs7qyQx5rBgH5fVY3v54=
30
-
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
31
-
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
32
-
github.com/charmbracelet/keygen v0.5.1 h1:zBkkYPtmKDVTw+cwUyY6ZwGDhRxXkEp0Oxs9sqMLqxI=
33
-
github.com/charmbracelet/keygen v0.5.1/go.mod h1:zznJVmK/GWB6dAtjluqn2qsttiCBhA5MZSiwb80fcHw=
34
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
35
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
36
-
github.com/charmbracelet/log v0.4.0 h1:G9bQAcx8rWA2T3pWvx7YtPTPwgqpk7D68BX21IRW8ZM=
37
-
github.com/charmbracelet/log v0.4.0/go.mod h1:63bXt/djrizTec0l11H20t8FDSvA4CRZJ1KH22MdptM=
38
-
github.com/charmbracelet/ssh v0.0.0-20241211182756-4fe22b0f1b7c h1:treQxMBdI2PaD4eOYfFux8stfCkUxhuUxaqGcxKqVpI=
39
-
github.com/charmbracelet/ssh v0.0.0-20241211182756-4fe22b0f1b7c/go.mod h1:CY1xbl2z+ZeBmNWItKZyxx0zgDgnhmR57+DTsHOobJ4=
40
-
github.com/charmbracelet/wish v1.4.4 h1:wtfoAMkf8Db9zi+9Lme2f7XKMxL6BqfgDWbqcTUHLaU=
41
-
github.com/charmbracelet/wish v1.4.4/go.mod h1:XB8v51UxIFMRlUod9lLaAgOsj/wpe+qW9HjsoYIiNMo=
42
-
github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE=
43
-
github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q=
44
-
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
45
-
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
46
-
github.com/charmbracelet/x/conpty v0.1.0 h1:4zc8KaIcbiL4mghEON8D72agYtSeIgq8FSThSPQIb+U=
47
-
github.com/charmbracelet/x/conpty v0.1.0/go.mod h1:rMFsDJoDwVmiYM10aD4bH2XiRgwI7NYJtQgl5yskjEQ=
48
-
github.com/charmbracelet/x/errors v0.0.0-20250107110353-48b574af22a5 h1:Hx72S6S4jAfrrWE3pv9IbudVdUV4htBgkOX800o17Bk=
49
-
github.com/charmbracelet/x/errors v0.0.0-20250107110353-48b574af22a5/go.mod h1:2P0UgXMEa6TsToMSuFqKFQR+fZTO9CNGUNokkPatT/0=
50
-
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ=
51
-
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
52
-
github.com/charmbracelet/x/input v0.2.0 h1:1Sv+y/flcqUfUH2PXNIDKDIdT2G8smOnGOgawqhwy8A=
53
-
github.com/charmbracelet/x/input v0.2.0/go.mod h1:KUSFIS6uQymtnr5lHVSOK9j8RvwTD4YHnWnzJUYnd/M=
54
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
55
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
56
-
github.com/charmbracelet/x/termios v0.1.0 h1:y4rjAHeFksBAfGbkRDmVinMg7x7DELIGAFbdNvxg97k=
57
-
github.com/charmbracelet/x/termios v0.1.0/go.mod h1:H/EVv/KRnrYjz+fCYa9bsKdqF3S8ouDK0AZEbG7r+/U=
58
-
github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys=
59
-
github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
60
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
61
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
62
-
github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM=
63
-
github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
64
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
65
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
66
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
67
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
68
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
69
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
70
-
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
71
-
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
72
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
73
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
74
-
github.com/elazarl/goproxy v1.2.3 h1:xwIyKHbaP5yfT6O9KIeYJR5549MXRQkoQMRXGztz8YQ=
75
-
github.com/elazarl/goproxy v1.2.3/go.mod h1:YfEbZtqP4AetfO6d40vWchF3znWX7C7Vd6ZMfdL8z64=
76
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
77
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
78
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
79
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
80
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
81
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
82
-
github.com/go-chi/chi/v5 v5.2.0 h1:Aj1EtB0qR2Rdo2dG4O94RIU35w2lvQSj6BRA4+qwFL0=
83
-
github.com/go-chi/chi/v5 v5.2.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
84
github.com/go-chi/httplog/v2 v2.1.1 h1:ojojiu4PIaoeJ/qAO4GWUxJqvYUTobeo7zmuHQJAxRk=
85
github.com/go-chi/httplog/v2 v2.1.1/go.mod h1:/XXdxicJsp4BA5fapgIC3VuTD+z0Z/VzukoB3VDc1YE=
86
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
87
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
88
-
github.com/go-git/go-billy/v5 v5.6.1 h1:u+dcrgaguSSkbjzHwelEjc0Yj300NUevrrPphk/SoRA=
89
-
github.com/go-git/go-billy/v5 v5.6.1/go.mod h1:0AsLr1z2+Uksi4NlElmMblP5rPcDZNRCD8ujZCRR2BE=
90
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
91
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
92
-
github.com/go-git/go-git/v5 v5.13.1 h1:DAQ9APonnlvSWpvolXWIuV6Q6zXy2wHbN4cVlNR5Q+M=
93
-
github.com/go-git/go-git/v5 v5.13.1/go.mod h1:qryJB4cSBoq3FRoBRf5A77joojuBcmPJ0qu3XXXVixc=
94
-
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
95
-
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
96
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
97
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
98
-
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
99
-
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
100
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
101
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
102
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
103
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
104
-
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
105
-
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
106
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
107
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
108
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
···
110
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
111
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
112
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
113
-
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
114
-
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
115
-
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
116
-
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
117
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
118
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
119
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
120
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
121
-
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
122
-
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
123
-
github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY=
124
-
github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8=
125
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
126
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
127
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
128
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
129
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
130
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
131
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
132
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
133
github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc=
134
github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ=
135
-
github.com/pjbgf/sha1cd v0.3.1 h1:Dh2GYdpJnO84lIw0LJwTFXjcNbasP/bklicSznyAaPI=
136
-
github.com/pjbgf/sha1cd v0.3.1/go.mod h1:Y8t7jSB/dEI/lQE04A1HVKteqjj9bX5O4+Cex0TCu8s=
137
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
138
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
139
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
140
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
141
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
142
-
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
143
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
144
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
145
-
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
146
-
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
147
-
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
148
-
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
149
-
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
150
-
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
151
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
152
-
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
153
-
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
154
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
155
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
156
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
···
162
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
163
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
164
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
165
-
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
166
-
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
167
-
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
168
-
github.com/yuin/goldmark-emoji v1.0.4 h1:vCwMkPZSNefSUnOW2ZKRUjBSD5Ok3W78IXhGxxAEF90=
169
-
github.com/yuin/goldmark-emoji v1.0.4/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U=
170
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
171
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
172
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
173
-
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
174
-
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
175
-
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
176
-
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
177
-
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
178
-
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
179
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
180
-
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
181
-
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
182
-
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
183
-
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
184
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
185
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
186
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
···
188
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
189
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
190
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
191
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
192
-
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
193
-
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
194
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
195
-
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
196
-
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
197
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
198
-
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
199
-
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
200
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
201
-
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
202
-
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
203
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
204
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
205
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
···
212
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
213
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
214
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
215
-
maragu.dev/gomponents v1.0.0 h1:eeLScjq4PqP1l+r5z/GC+xXZhLHXa6RWUWGW7gSfLh4=
216
-
maragu.dev/gomponents v1.0.0/go.mod h1:oEDahza2gZoXDoDHhw8jBNgH+3UR5ni7Ur648HORydM=
···
1
+
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
2
+
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
3
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
4
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
5
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
6
+
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
7
+
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
8
+
github.com/a-h/parse v0.0.0-20250122154542-74294addb73e h1:HjVbSQHy+dnlS6C3XajZ69NYAb5jbGNfHanvm1+iYlo=
9
+
github.com/a-h/parse v0.0.0-20250122154542-74294addb73e/go.mod h1:3mnrkvGpurZ4ZrTDbYU84xhwXW2TjTKShSwjRi2ihfQ=
10
+
github.com/a-h/templ v0.3.960 h1:trshEpGa8clF5cdI39iY4ZrZG8Z/QixyzEyUnA7feTM=
11
+
github.com/a-h/templ v0.3.960/go.mod h1:oCZcnKRf5jjsGpf2yELzQfodLphd2mwecwG4Crk5HBo=
12
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
13
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
14
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
15
+
github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw=
16
+
github.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA=
17
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
18
+
github.com/alecthomas/repr v0.5.1 h1:E3G4t2QbHTSNpPKBgMTln5KLkZHLOcU7r37J4pXBuIg=
19
+
github.com/alecthomas/repr v0.5.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
20
+
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
21
+
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
22
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
23
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
24
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
25
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
26
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
27
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
28
+
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
29
+
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
30
+
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
31
+
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
32
+
github.com/charmbracelet/colorprofile v0.3.2 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI=
33
+
github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI=
34
+
github.com/charmbracelet/keygen v0.5.4 h1:XQYgf6UEaTGgQSSmiPpIQ78WfseNQp4Pz8N/c1OsrdA=
35
+
github.com/charmbracelet/keygen v0.5.4/go.mod h1:t4oBRr41bvK7FaJsAaAQhhkUuHslzFXVjOBwA55CZNM=
36
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
37
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
38
+
github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig=
39
+
github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
40
+
github.com/charmbracelet/ssh v0.0.0-20250826160808-ebfa259c7309 h1:dCVbCRRtg9+tsfiTXTp0WupDlHruAXyp+YoxGVofHHc=
41
+
github.com/charmbracelet/ssh v0.0.0-20250826160808-ebfa259c7309/go.mod h1:R9cISUs5kAH4Cq/rguNbSwcR+slE5Dfm8FEs//uoIGE=
42
+
github.com/charmbracelet/wish v1.4.7 h1:O+jdLac3s6GaqkOHHSwezejNK04vl6VjO1A+hl8J8Yc=
43
+
github.com/charmbracelet/wish v1.4.7/go.mod h1:OBZ8vC62JC5cvbxJLh+bIWtG7Ctmct+ewziuUWK+G14=
44
+
github.com/charmbracelet/x/ansi v0.10.2 h1:ith2ArZS0CJG30cIUfID1LXN7ZFXRCww6RUvAPA+Pzw=
45
+
github.com/charmbracelet/x/ansi v0.10.2/go.mod h1:HbLdJjQH4UH4AqA2HpRWuWNluRE6zxJH/yteYEYCFa8=
46
+
github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k=
47
+
github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
48
+
github.com/charmbracelet/x/conpty v0.1.1 h1:s1bUxjoi7EpqiXysVtC+a8RrvPPNcNvAjfi4jxsAuEs=
49
+
github.com/charmbracelet/x/conpty v0.1.1/go.mod h1:OmtR77VODEFbiTzGE9G1XiRJAga6011PIm4u5fTNZpk=
50
+
github.com/charmbracelet/x/errors v0.0.0-20251030181443-0cf22f8402df h1:6zTS1yAzaSDINNXDQRtayOHL4Zde4LVmnbjRPdxV84g=
51
+
github.com/charmbracelet/x/errors v0.0.0-20251030181443-0cf22f8402df/go.mod h1:O2BTD/aMVQDmrvqroIO3fB6zXUuU07ZpVt21QTmZjRg=
52
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
53
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
54
+
github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY=
55
+
github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo=
56
+
github.com/cli/browser v1.3.0 h1:LejqCrpWr+1pRqmEPDGnTZOjsMe7sehifLynZJuqJpo=
57
+
github.com/cli/browser v1.3.0/go.mod h1:HH8s+fOAxjhQoBUAsKuPCbqUuxZDhQ2/aD+SzsEfBTk=
58
+
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
59
+
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
60
+
github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
61
+
github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
62
+
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
63
+
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
64
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
65
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
66
+
github.com/cyphar/filepath-securejoin v0.5.0 h1:hIAhkRBMQ8nIeuVwcAoymp7MY4oherZdAxD+m0u9zaw=
67
+
github.com/cyphar/filepath-securejoin v0.5.0/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
68
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
69
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
70
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
71
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
72
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
73
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
74
+
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
75
+
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
76
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
77
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
78
+
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
79
+
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
80
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
81
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
82
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
83
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
84
+
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
85
+
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
86
+
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
87
+
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
88
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
89
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
90
+
github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=
91
+
github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
92
github.com/go-chi/httplog/v2 v2.1.1 h1:ojojiu4PIaoeJ/qAO4GWUxJqvYUTobeo7zmuHQJAxRk=
93
github.com/go-chi/httplog/v2 v2.1.1/go.mod h1:/XXdxicJsp4BA5fapgIC3VuTD+z0Z/VzukoB3VDc1YE=
94
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
95
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
96
+
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
97
+
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
98
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
99
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
100
+
github.com/go-git/go-git/v5 v5.16.3 h1:Z8BtvxZ09bYm/yYNgPKCzgWtaRqDTgIKRgIRHBfU6Z8=
101
+
github.com/go-git/go-git/v5 v5.16.3/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
102
+
github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE=
103
+
github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk=
104
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
105
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
106
+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
107
+
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
108
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
109
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
110
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
111
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
112
+
github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ=
113
+
github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
114
+
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
115
+
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
116
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
117
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
118
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
···
120
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
121
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
122
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
123
+
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
124
+
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
125
+
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
126
+
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
127
+
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
128
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
129
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
130
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
131
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
132
+
github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
133
+
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
134
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
135
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
136
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
137
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
138
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
139
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
140
+
github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A=
141
+
github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM=
142
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
143
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
144
github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc=
145
github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ=
146
+
github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0=
147
+
github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM=
148
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
149
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
150
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
151
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
152
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
153
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
154
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
155
+
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
156
+
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
157
+
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
158
+
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
159
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
160
+
github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg=
161
+
github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow=
162
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
163
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
164
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
···
170
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
171
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
172
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
173
+
github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA=
174
+
github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
175
+
github.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9HTHs=
176
+
github.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA=
177
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
178
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
179
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
180
+
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
181
+
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
182
+
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
183
+
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
184
+
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
185
+
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
186
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
187
+
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
188
+
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
189
+
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
190
+
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
191
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
192
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
193
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
···
195
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
196
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
197
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
198
+
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
199
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
200
+
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
201
+
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
202
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
203
+
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
204
+
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
205
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
206
+
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
207
+
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
208
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
209
+
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
210
+
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
211
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
212
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
213
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
···
220
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
221
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
222
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+2
-2
internal/git/grep.go
+2
-2
internal/git/grep.go
+4
-3
internal/git/meta.go
+4
-3
internal/git/meta.go
-61
internal/git/repo_utils.go
-61
internal/git/repo_utils.go
···
1
-
package git
2
-
3
-
import (
4
-
"errors"
5
-
"io/fs"
6
-
"os"
7
-
"path/filepath"
8
-
"strings"
9
-
)
10
-
11
-
// ListRepos returns all directory entries in the given directory
12
-
func ListRepos(dir string) ([]fs.DirEntry, error) {
13
-
entries, err := os.ReadDir(dir)
14
-
if err != nil {
15
-
if errors.Is(err, fs.ErrNotExist) {
16
-
return []fs.DirEntry{}, nil
17
-
}
18
-
return nil, err
19
-
}
20
-
return entries, nil
21
-
}
22
-
23
-
// DeleteRepo deletes a git repository from the filesystem
24
-
func DeleteRepo(repoPath string) error {
25
-
return os.RemoveAll(repoPath)
26
-
}
27
-
28
-
// RenameRepo renames a git repository
29
-
func RenameRepo(repoDir, oldName, newName string) error {
30
-
if !filepath.IsAbs(repoDir) {
31
-
return errors.New("repository directory must be an absolute path")
32
-
}
33
-
34
-
if !filepath.IsAbs(oldName) && !filepath.IsAbs(newName) {
35
-
oldPath := filepath.Join(repoDir, oldName)
36
-
if !strings.HasSuffix(oldPath, ".git") {
37
-
oldPath += ".git"
38
-
}
39
-
40
-
newPath := filepath.Join(repoDir, newName)
41
-
if !strings.HasSuffix(newPath, ".git") {
42
-
newPath += ".git"
43
-
}
44
-
45
-
return os.Rename(oldPath, newPath)
46
-
}
47
-
48
-
return errors.New("repository names should not be absolute paths")
49
-
}
50
-
51
-
// RepoPathExists checks if a path exists
52
-
func RepoPathExists(path string) (bool, error) {
53
-
_, err := os.Stat(path)
54
-
if err == nil {
55
-
return true, nil
56
-
}
57
-
if errors.Is(err, fs.ErrNotExist) {
58
-
return false, nil
59
-
}
60
-
return false, err
61
-
}
···
-38
internal/html/base.go
-38
internal/html/base.go
···
1
-
package html
2
-
3
-
import (
4
-
. "maragu.dev/gomponents"
5
-
. "maragu.dev/gomponents/components"
6
-
. "maragu.dev/gomponents/html"
7
-
)
8
-
9
-
type BaseContext struct {
10
-
Title string
11
-
Description string
12
-
}
13
-
14
-
func base(bc BaseContext, children ...Node) Node {
15
-
return HTML5(HTML5Props{
16
-
Title: bc.Title,
17
-
Description: bc.Description,
18
-
Head: []Node{
19
-
Link(Rel("icon"), Href("/_/favicon.svg")),
20
-
Link(Rel("stylesheet"), Href("/_/tailwind.css")),
21
-
ogp("title", bc.Title),
22
-
ogp("description", bc.Description),
23
-
Meta(Name("forge"), Content("ugit")),
24
-
Meta(Name("keywords"), Content("git,forge,ugit")),
25
-
},
26
-
Body: []Node{
27
-
Class("latte dark:mocha bg-base/50 dark:bg-base/95 max-w-7xl mx-5 sm:mx-auto my-10"),
28
-
H2(Class("text-text text-xl mb-3"),
29
-
A(Class("text-text text-xl mb-3"), Href("/"), Text("Home")),
30
-
),
31
-
Group(children),
32
-
},
33
-
})
34
-
}
35
-
36
-
func ogp(property, content string) Node {
37
-
return El("meta", Attr("property", "og:"+property), Attr("content", content))
38
-
}
···
+27
internal/html/base.templ
+27
internal/html/base.templ
···
···
1
+
package html
2
+
3
+
type BaseContext struct {
4
+
Title string
5
+
Description string
6
+
}
7
+
8
+
templ base(bc BaseContext) {
9
+
<!DOCTYPE html>
10
+
<html>
11
+
<head>
12
+
<meta charset="UTF-8"/>
13
+
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
14
+
<title>{ bc.Title }</title>
15
+
<link rel="icon" href="/_/favicon.svg"/>
16
+
<link rel="stylesheet" href="/_/tailwind.css"/>
17
+
<meta property="og:title" content={ bc.Title }/>
18
+
<meta property="og:description" content={ bc.Description }/>
19
+
</head>
20
+
<body class="latte dark:mocha bg-base/50 dark:bg-base/95 max-w-7xl mx-5 sm:mx-auto my-10">
21
+
<h2 class="text-text text-xl mb-3">
22
+
<a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href="/">Home</a>
23
+
</h2>
24
+
{ children... }
25
+
</body>
26
+
</html>
27
+
}
+92
internal/html/base_templ.go
+92
internal/html/base_templ.go
···
···
1
+
// Code generated by templ - DO NOT EDIT.
2
+
3
+
// templ: version: v0.3.924
4
+
package html
5
+
6
+
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
+
8
+
import "github.com/a-h/templ"
9
+
import templruntime "github.com/a-h/templ/runtime"
10
+
11
+
type BaseContext struct {
12
+
Title string
13
+
Description string
14
+
}
15
+
16
+
func base(bc BaseContext) templ.Component {
17
+
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
18
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
19
+
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
20
+
return templ_7745c5c3_CtxErr
21
+
}
22
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
23
+
if !templ_7745c5c3_IsBuffer {
24
+
defer func() {
25
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
26
+
if templ_7745c5c3_Err == nil {
27
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
28
+
}
29
+
}()
30
+
}
31
+
ctx = templ.InitializeContext(ctx)
32
+
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
33
+
if templ_7745c5c3_Var1 == nil {
34
+
templ_7745c5c3_Var1 = templ.NopComponent
35
+
}
36
+
ctx = templ.ClearChildren(ctx)
37
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>")
38
+
if templ_7745c5c3_Err != nil {
39
+
return templ_7745c5c3_Err
40
+
}
41
+
var templ_7745c5c3_Var2 string
42
+
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(bc.Title)
43
+
if templ_7745c5c3_Err != nil {
44
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `base.templ`, Line: 14, Col: 20}
45
+
}
46
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
47
+
if templ_7745c5c3_Err != nil {
48
+
return templ_7745c5c3_Err
49
+
}
50
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><link rel=\"icon\" href=\"/_/favicon.svg\"><link rel=\"stylesheet\" href=\"/_/tailwind.css\"><meta property=\"og:title\" content=\"")
51
+
if templ_7745c5c3_Err != nil {
52
+
return templ_7745c5c3_Err
53
+
}
54
+
var templ_7745c5c3_Var3 string
55
+
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(bc.Title)
56
+
if templ_7745c5c3_Err != nil {
57
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `base.templ`, Line: 17, Col: 47}
58
+
}
59
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
60
+
if templ_7745c5c3_Err != nil {
61
+
return templ_7745c5c3_Err
62
+
}
63
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\"><meta property=\"og:description\" content=\"")
64
+
if templ_7745c5c3_Err != nil {
65
+
return templ_7745c5c3_Err
66
+
}
67
+
var templ_7745c5c3_Var4 string
68
+
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(bc.Description)
69
+
if templ_7745c5c3_Err != nil {
70
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `base.templ`, Line: 18, Col: 59}
71
+
}
72
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
73
+
if templ_7745c5c3_Err != nil {
74
+
return templ_7745c5c3_Err
75
+
}
76
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\"></head><body class=\"latte dark:mocha bg-base/50 dark:bg-base/95 max-w-7xl mx-5 sm:mx-auto my-10\"><h2 class=\"text-text text-xl mb-3\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"/\">Home</a></h2>")
77
+
if templ_7745c5c3_Err != nil {
78
+
return templ_7745c5c3_Err
79
+
}
80
+
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
81
+
if templ_7745c5c3_Err != nil {
82
+
return templ_7745c5c3_Err
83
+
}
84
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</body></html>")
85
+
if templ_7745c5c3_Err != nil {
86
+
return templ_7745c5c3_Err
87
+
}
88
+
return nil
89
+
})
90
+
}
91
+
92
+
var _ = templruntime.GeneratedTemplate
+2
-1
internal/html/generate.go
+2
-1
internal/html/generate.go
···
26
otherCSS string
27
)
28
29
//go:generate go run generate.go
30
func main() {
31
if err := tailwind(); err != nil {
···
72
defer styles.Close()
73
74
var buf bytes.Buffer
75
-
cmd := exec.Command("tailwind-ctp", "-i", tmp.Name(), "--minify")
76
cmd.Stdout = &buf
77
if err := cmd.Run(); err != nil {
78
return err
···
26
otherCSS string
27
)
28
29
+
//go:generate go tool templ generate
30
//go:generate go run generate.go
31
func main() {
32
if err := tailwind(); err != nil {
···
73
defer styles.Close()
74
75
var buf bytes.Buffer
76
+
cmd := exec.Command("tailwind-ctp_3", "-i", tmp.Name(), "--minify")
77
cmd.Stdout = &buf
78
if err := cmd.Run(); err != nil {
79
return err
-105
internal/html/index.go
-105
internal/html/index.go
···
1
-
package html
2
-
3
-
import (
4
-
"fmt"
5
-
6
-
"github.com/dustin/go-humanize"
7
-
"go.jolheiser.com/ugit/assets"
8
-
"go.jolheiser.com/ugit/internal/git"
9
-
. "maragu.dev/gomponents"
10
-
. "maragu.dev/gomponents/html"
11
-
)
12
-
13
-
type IndexContext struct {
14
-
BaseContext
15
-
Profile IndexProfile
16
-
Repos []*git.Repo
17
-
}
18
-
19
-
type IndexProfile struct {
20
-
Username string
21
-
Email string
22
-
Links []IndexLink
23
-
}
24
-
25
-
type IndexLink struct {
26
-
Name string
27
-
URL string
28
-
}
29
-
30
-
func lastCommitTime(repo *git.Repo, human bool) string {
31
-
c, err := repo.LastCommit()
32
-
if err != nil {
33
-
return ""
34
-
}
35
-
if human {
36
-
return humanize.Time(c.When)
37
-
}
38
-
return c.When.Format("01/02/2006 03:04:05 PM")
39
-
}
40
-
41
-
func lastCommit(repo *git.Repo) *git.Commit {
42
-
c, err := repo.LastCommit()
43
-
if err != nil {
44
-
return nil
45
-
}
46
-
return &c
47
-
}
48
-
49
-
func IndexTemplate(ic IndexContext) Node {
50
-
return base(ic.BaseContext, []Node{
51
-
Header(
52
-
H1(Class("text-text text-xl font-bold"), Text(ic.Title)),
53
-
H2(Class("text-subtext1 text-lg"), Text(ic.Description)),
54
-
),
55
-
Main(Class("mt-5"),
56
-
Div(Class("grid grid-cols-1 sm:grid-cols-8"),
57
-
If(ic.Profile.Username != "",
58
-
Div(Class("text-mauve"), Text("@"+ic.Profile.Username)),
59
-
),
60
-
If(ic.Profile.Email != "", Group([]Node{
61
-
Div(Class("text-mauve col-span-2"),
62
-
Div(Class("w-5 h-5 stroke-mauve inline-block mr-1 align-middle"), Raw(string(assets.EmailIcon))),
63
-
A(Class("underline decoration-mauve/50 decoration-dashed hover:decoration-solid"), Href("mailto:"+ic.Profile.Email), Text(ic.Profile.Email)),
64
-
),
65
-
}),
66
-
),
67
-
),
68
-
Div(Class("grid grid-cols-1 sm:grid-cols-8"),
69
-
Map(ic.Profile.Links, func(link IndexLink) Node {
70
-
return Div(Class("text-mauve"),
71
-
Div(Class("w-5 h-5 stroke-mauve inline-block mr-1 align-middle"),
72
-
Raw(string(assets.LinkIcon)),
73
-
),
74
-
A(Class("underline decoration-mauve/50 decoration-dashed hover:decoration-solid"), Rel("me"), Href(link.URL), Text(link.Name)),
75
-
)
76
-
}),
77
-
),
78
-
Div(Class("grid sm:grid-cols-10 gap-2 mt-5"),
79
-
Map(ic.Repos, func(repo *git.Repo) Node {
80
-
commit := lastCommit(repo)
81
-
return Group([]Node{
82
-
Div(Class("sm:col-span-2 text-blue dark:text-lavender"),
83
-
A(Class("underline decoration-blue/50 dark:decoration-lavender/50 decoration-dashed hover:decoration-solid"), Href("/"+repo.Name()), Text(repo.Name())),
84
-
),
85
-
Div(Class("sm:col-span-3 text-subtext0"), Text(repo.Meta.Description)),
86
-
Div(Class("sm:col-span-3 text-subtext0"),
87
-
If(commit != nil,
88
-
Div(Title(commit.Message),
89
-
A(Class("underline text-blue dark:text-lavender decoration-blue/50 dark:decoration-lavender/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/commit/%s", repo.Name(), commit.SHA)), Text(commit.Short())),
90
-
Text(": "+commit.Summary()),
91
-
),
92
-
),
93
-
),
94
-
Div(Class("sm:col-span-1 text-subtext0"),
95
-
Map(repo.Meta.Tags.Slice(), func(tag string) Node {
96
-
return A(Class("rounded border-rosewater border-solid border pb-0.5 px-1 mr-1 mb-1 inline-block"), Href("?tag="+tag), Text(tag))
97
-
}),
98
-
),
99
-
Div(Class("sm:col-span-1 text-text/80 mb-4 sm:mb-0"), Title(lastCommitTime(repo, false)), Text(lastCommitTime(repo, true))),
100
-
})
101
-
}),
102
-
),
103
-
),
104
-
}...)
105
-
}
···
+99
internal/html/index.templ
+99
internal/html/index.templ
···
···
1
+
package html
2
+
3
+
import (
4
+
"fmt"
5
+
"github.com/dustin/go-humanize"
6
+
"go.jolheiser.com/ugit/assets"
7
+
"go.jolheiser.com/ugit/internal/git"
8
+
)
9
+
10
+
type IndexContext struct {
11
+
BaseContext
12
+
Profile IndexProfile
13
+
Repos []*git.Repo
14
+
}
15
+
16
+
type IndexProfile struct {
17
+
Username string
18
+
Email string
19
+
Links []IndexLink
20
+
}
21
+
22
+
type IndexLink struct {
23
+
Name string
24
+
URL string
25
+
}
26
+
27
+
func lastCommitTime(repo *git.Repo, human bool) string {
28
+
c, err := repo.LastCommit()
29
+
if err != nil {
30
+
return ""
31
+
}
32
+
if human {
33
+
return humanize.Time(c.When)
34
+
}
35
+
return c.When.Format("01/02/2006 03:04:05 PM")
36
+
}
37
+
38
+
func lastCommit(repo *git.Repo) *git.Commit {
39
+
c, err := repo.LastCommit()
40
+
if err != nil {
41
+
return nil
42
+
}
43
+
return &c
44
+
}
45
+
46
+
templ Index(ic IndexContext) {
47
+
@base(ic.BaseContext) {
48
+
<header>
49
+
<h1 class="text-text text-xl font-bold">{ ic.Title }</h1>
50
+
<h2 class="text-subtext1 text-lg">{ ic.Description }</h2>
51
+
</header>
52
+
<main class="mt-5">
53
+
<div class="grid grid-cols-1 sm:grid-cols-8">
54
+
if ic.Profile.Username != "" {
55
+
<div class="text-mauve">{ `@` + ic.Profile.Username }</div>
56
+
}
57
+
if ic.Profile.Email != "" {
58
+
<div class="text-mauve col-span-2">
59
+
<div class="w-5 h-5 stroke-mauve inline-block mr-1 align-middle">
60
+
@templ.Raw(string(assets.EmailIcon))
61
+
</div>
62
+
<a class="underline decoration-mauve/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL("mailto:" + ic.Profile.Email) }>{ ic.Profile.Email }</a>
63
+
</div>
64
+
}
65
+
</div>
66
+
<div class="grid grid-cols-1 sm:grid-cols-8">
67
+
for _, link := range ic.Profile.Links {
68
+
<div class="text-mauve">
69
+
<div class="w-5 h-5 stroke-mauve inline-block mr-1 align-middle">
70
+
@templ.Raw(string(assets.LinkIcon))
71
+
</div>
72
+
<a class="underline decoration-mauve/50 decoration-dashed hover:decoration-solid" rel="me" href={ templ.SafeURL(link.URL) }>{ link.Name }</a>
73
+
</div>
74
+
}
75
+
</div>
76
+
<div class="grid sm:grid-cols-10 gap-2 mt-5">
77
+
for _, repo := range ic.Repos {
78
+
{{ commit := lastCommit(repo) }}
79
+
<div class="sm:col-span-2 text-blue dark:text-lavender"><a class="underline decoration-blue/50 dark:decoration-lavender/50 decoration-dashed hover:decoration-solid" href={ templ.URL("/" + repo.Name()) }>{ repo.Name() }</a></div>
80
+
<div class="sm:col-span-3 text-subtext0">{ repo.Meta.Description }</div>
81
+
<div class="sm:col-span-3 text-subtext0">
82
+
if commit != nil {
83
+
<div title={ commit.Message }>
84
+
<a class="underline text-blue dark:text-lavender decoration-blue/50 dark:decoration-lavender/50 decoration-dashed hover:decoration-solid" href={ fmt.Sprintf("/%s/commit/%s", repo.Name(), commit.SHA) }>{ commit.Short() }</a>
85
+
{ ": " + commit.Summary() }
86
+
</div>
87
+
}
88
+
</div>
89
+
<div class="sm:col-span-1 text-subtext0">
90
+
for _, tag := range repo.Meta.Tags.Slice() {
91
+
<a href={ templ.SafeURL("?tag=" + tag) } class="rounded border-rosewater border-solid border pb-0.5 px-1 mr-1 mb-1 inline-block">{ tag }</a>
92
+
}
93
+
</div>
94
+
<div class="sm:col-span-1 text-text/80 mb-4 sm:mb-0" title={ lastCommitTime(repo, false) }>{ lastCommitTime(repo, true) }</div>
95
+
}
96
+
</div>
97
+
</main>
98
+
}
99
+
}
+408
internal/html/index_templ.go
+408
internal/html/index_templ.go
···
···
1
+
// Code generated by templ - DO NOT EDIT.
2
+
3
+
// templ: version: v0.3.924
4
+
package html
5
+
6
+
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
+
8
+
import "github.com/a-h/templ"
9
+
import templruntime "github.com/a-h/templ/runtime"
10
+
11
+
import (
12
+
"fmt"
13
+
"github.com/dustin/go-humanize"
14
+
"go.jolheiser.com/ugit/assets"
15
+
"go.jolheiser.com/ugit/internal/git"
16
+
)
17
+
18
+
type IndexContext struct {
19
+
BaseContext
20
+
Profile IndexProfile
21
+
Repos []*git.Repo
22
+
}
23
+
24
+
type IndexProfile struct {
25
+
Username string
26
+
Email string
27
+
Links []IndexLink
28
+
}
29
+
30
+
type IndexLink struct {
31
+
Name string
32
+
URL string
33
+
}
34
+
35
+
func lastCommitTime(repo *git.Repo, human bool) string {
36
+
c, err := repo.LastCommit()
37
+
if err != nil {
38
+
return ""
39
+
}
40
+
if human {
41
+
return humanize.Time(c.When)
42
+
}
43
+
return c.When.Format("01/02/2006 03:04:05 PM")
44
+
}
45
+
46
+
func lastCommit(repo *git.Repo) *git.Commit {
47
+
c, err := repo.LastCommit()
48
+
if err != nil {
49
+
return nil
50
+
}
51
+
return &c
52
+
}
53
+
54
+
func Index(ic IndexContext) templ.Component {
55
+
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
56
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
57
+
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
58
+
return templ_7745c5c3_CtxErr
59
+
}
60
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
61
+
if !templ_7745c5c3_IsBuffer {
62
+
defer func() {
63
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
64
+
if templ_7745c5c3_Err == nil {
65
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
66
+
}
67
+
}()
68
+
}
69
+
ctx = templ.InitializeContext(ctx)
70
+
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
71
+
if templ_7745c5c3_Var1 == nil {
72
+
templ_7745c5c3_Var1 = templ.NopComponent
73
+
}
74
+
ctx = templ.ClearChildren(ctx)
75
+
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
76
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
77
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
78
+
if !templ_7745c5c3_IsBuffer {
79
+
defer func() {
80
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
81
+
if templ_7745c5c3_Err == nil {
82
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
83
+
}
84
+
}()
85
+
}
86
+
ctx = templ.InitializeContext(ctx)
87
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<header><h1 class=\"text-text text-xl font-bold\">")
88
+
if templ_7745c5c3_Err != nil {
89
+
return templ_7745c5c3_Err
90
+
}
91
+
var templ_7745c5c3_Var3 string
92
+
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(ic.Title)
93
+
if templ_7745c5c3_Err != nil {
94
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 49, Col: 53}
95
+
}
96
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
97
+
if templ_7745c5c3_Err != nil {
98
+
return templ_7745c5c3_Err
99
+
}
100
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</h1><h2 class=\"text-subtext1 text-lg\">")
101
+
if templ_7745c5c3_Err != nil {
102
+
return templ_7745c5c3_Err
103
+
}
104
+
var templ_7745c5c3_Var4 string
105
+
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(ic.Description)
106
+
if templ_7745c5c3_Err != nil {
107
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 50, Col: 53}
108
+
}
109
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
110
+
if templ_7745c5c3_Err != nil {
111
+
return templ_7745c5c3_Err
112
+
}
113
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h2></header><main class=\"mt-5\"><div class=\"grid grid-cols-1 sm:grid-cols-8\">")
114
+
if templ_7745c5c3_Err != nil {
115
+
return templ_7745c5c3_Err
116
+
}
117
+
if ic.Profile.Username != "" {
118
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div class=\"text-mauve\">")
119
+
if templ_7745c5c3_Err != nil {
120
+
return templ_7745c5c3_Err
121
+
}
122
+
var templ_7745c5c3_Var5 string
123
+
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(`@` + ic.Profile.Username)
124
+
if templ_7745c5c3_Err != nil {
125
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 55, Col: 56}
126
+
}
127
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
128
+
if templ_7745c5c3_Err != nil {
129
+
return templ_7745c5c3_Err
130
+
}
131
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div>")
132
+
if templ_7745c5c3_Err != nil {
133
+
return templ_7745c5c3_Err
134
+
}
135
+
}
136
+
if ic.Profile.Email != "" {
137
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"text-mauve col-span-2\"><div class=\"w-5 h-5 stroke-mauve inline-block mr-1 align-middle\">")
138
+
if templ_7745c5c3_Err != nil {
139
+
return templ_7745c5c3_Err
140
+
}
141
+
templ_7745c5c3_Err = templ.Raw(string(assets.EmailIcon)).Render(ctx, templ_7745c5c3_Buffer)
142
+
if templ_7745c5c3_Err != nil {
143
+
return templ_7745c5c3_Err
144
+
}
145
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div><a class=\"underline decoration-mauve/50 decoration-dashed hover:decoration-solid\" href=\"")
146
+
if templ_7745c5c3_Err != nil {
147
+
return templ_7745c5c3_Err
148
+
}
149
+
var templ_7745c5c3_Var6 templ.SafeURL
150
+
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL("mailto:" + ic.Profile.Email))
151
+
if templ_7745c5c3_Err != nil {
152
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 62, Col: 138}
153
+
}
154
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
155
+
if templ_7745c5c3_Err != nil {
156
+
return templ_7745c5c3_Err
157
+
}
158
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\">")
159
+
if templ_7745c5c3_Err != nil {
160
+
return templ_7745c5c3_Err
161
+
}
162
+
var templ_7745c5c3_Var7 string
163
+
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(ic.Profile.Email)
164
+
if templ_7745c5c3_Err != nil {
165
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 62, Col: 159}
166
+
}
167
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
168
+
if templ_7745c5c3_Err != nil {
169
+
return templ_7745c5c3_Err
170
+
}
171
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</a></div>")
172
+
if templ_7745c5c3_Err != nil {
173
+
return templ_7745c5c3_Err
174
+
}
175
+
}
176
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div><div class=\"grid grid-cols-1 sm:grid-cols-8\">")
177
+
if templ_7745c5c3_Err != nil {
178
+
return templ_7745c5c3_Err
179
+
}
180
+
for _, link := range ic.Profile.Links {
181
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"text-mauve\"><div class=\"w-5 h-5 stroke-mauve inline-block mr-1 align-middle\">")
182
+
if templ_7745c5c3_Err != nil {
183
+
return templ_7745c5c3_Err
184
+
}
185
+
templ_7745c5c3_Err = templ.Raw(string(assets.LinkIcon)).Render(ctx, templ_7745c5c3_Buffer)
186
+
if templ_7745c5c3_Err != nil {
187
+
return templ_7745c5c3_Err
188
+
}
189
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div><a class=\"underline decoration-mauve/50 decoration-dashed hover:decoration-solid\" rel=\"me\" href=\"")
190
+
if templ_7745c5c3_Err != nil {
191
+
return templ_7745c5c3_Err
192
+
}
193
+
var templ_7745c5c3_Var8 templ.SafeURL
194
+
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(link.URL))
195
+
if templ_7745c5c3_Err != nil {
196
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 72, Col: 127}
197
+
}
198
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
199
+
if templ_7745c5c3_Err != nil {
200
+
return templ_7745c5c3_Err
201
+
}
202
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\">")
203
+
if templ_7745c5c3_Err != nil {
204
+
return templ_7745c5c3_Err
205
+
}
206
+
var templ_7745c5c3_Var9 string
207
+
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(link.Name)
208
+
if templ_7745c5c3_Err != nil {
209
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 72, Col: 141}
210
+
}
211
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
212
+
if templ_7745c5c3_Err != nil {
213
+
return templ_7745c5c3_Err
214
+
}
215
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</a></div>")
216
+
if templ_7745c5c3_Err != nil {
217
+
return templ_7745c5c3_Err
218
+
}
219
+
}
220
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</div><div class=\"grid sm:grid-cols-10 gap-2 mt-5\">")
221
+
if templ_7745c5c3_Err != nil {
222
+
return templ_7745c5c3_Err
223
+
}
224
+
for _, repo := range ic.Repos {
225
+
commit := lastCommit(repo)
226
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<div class=\"sm:col-span-2 text-blue dark:text-lavender\"><a class=\"underline decoration-blue/50 dark:decoration-lavender/50 decoration-dashed hover:decoration-solid\" href=\"")
227
+
if templ_7745c5c3_Err != nil {
228
+
return templ_7745c5c3_Err
229
+
}
230
+
var templ_7745c5c3_Var10 templ.SafeURL
231
+
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL("/" + repo.Name()))
232
+
if templ_7745c5c3_Err != nil {
233
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 79, Col: 205}
234
+
}
235
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
236
+
if templ_7745c5c3_Err != nil {
237
+
return templ_7745c5c3_Err
238
+
}
239
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\">")
240
+
if templ_7745c5c3_Err != nil {
241
+
return templ_7745c5c3_Err
242
+
}
243
+
var templ_7745c5c3_Var11 string
244
+
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Name())
245
+
if templ_7745c5c3_Err != nil {
246
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 79, Col: 221}
247
+
}
248
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
249
+
if templ_7745c5c3_Err != nil {
250
+
return templ_7745c5c3_Err
251
+
}
252
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</a></div><div class=\"sm:col-span-3 text-subtext0\">")
253
+
if templ_7745c5c3_Err != nil {
254
+
return templ_7745c5c3_Err
255
+
}
256
+
var templ_7745c5c3_Var12 string
257
+
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Meta.Description)
258
+
if templ_7745c5c3_Err != nil {
259
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 80, Col: 69}
260
+
}
261
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
262
+
if templ_7745c5c3_Err != nil {
263
+
return templ_7745c5c3_Err
264
+
}
265
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</div><div class=\"sm:col-span-3 text-subtext0\">")
266
+
if templ_7745c5c3_Err != nil {
267
+
return templ_7745c5c3_Err
268
+
}
269
+
if commit != nil {
270
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<div title=\"")
271
+
if templ_7745c5c3_Err != nil {
272
+
return templ_7745c5c3_Err
273
+
}
274
+
var templ_7745c5c3_Var13 string
275
+
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Message)
276
+
if templ_7745c5c3_Err != nil {
277
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 83, Col: 34}
278
+
}
279
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
280
+
if templ_7745c5c3_Err != nil {
281
+
return templ_7745c5c3_Err
282
+
}
283
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "\"><a class=\"underline text-blue dark:text-lavender decoration-blue/50 dark:decoration-lavender/50 decoration-dashed hover:decoration-solid\" href=\"")
284
+
if templ_7745c5c3_Err != nil {
285
+
return templ_7745c5c3_Err
286
+
}
287
+
var templ_7745c5c3_Var14 templ.SafeURL
288
+
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinURLErrs(fmt.Sprintf("/%s/commit/%s", repo.Name(), commit.SHA))
289
+
if templ_7745c5c3_Err != nil {
290
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 84, Col: 206}
291
+
}
292
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
293
+
if templ_7745c5c3_Err != nil {
294
+
return templ_7745c5c3_Err
295
+
}
296
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\">")
297
+
if templ_7745c5c3_Err != nil {
298
+
return templ_7745c5c3_Err
299
+
}
300
+
var templ_7745c5c3_Var15 string
301
+
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Short())
302
+
if templ_7745c5c3_Err != nil {
303
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 84, Col: 225}
304
+
}
305
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
306
+
if templ_7745c5c3_Err != nil {
307
+
return templ_7745c5c3_Err
308
+
}
309
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</a> ")
310
+
if templ_7745c5c3_Err != nil {
311
+
return templ_7745c5c3_Err
312
+
}
313
+
var templ_7745c5c3_Var16 string
314
+
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(": " + commit.Summary())
315
+
if templ_7745c5c3_Err != nil {
316
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 85, Col: 33}
317
+
}
318
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
319
+
if templ_7745c5c3_Err != nil {
320
+
return templ_7745c5c3_Err
321
+
}
322
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</div>")
323
+
if templ_7745c5c3_Err != nil {
324
+
return templ_7745c5c3_Err
325
+
}
326
+
}
327
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</div><div class=\"sm:col-span-1 text-subtext0\">")
328
+
if templ_7745c5c3_Err != nil {
329
+
return templ_7745c5c3_Err
330
+
}
331
+
for _, tag := range repo.Meta.Tags.Slice() {
332
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<a href=\"")
333
+
if templ_7745c5c3_Err != nil {
334
+
return templ_7745c5c3_Err
335
+
}
336
+
var templ_7745c5c3_Var17 templ.SafeURL
337
+
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL("?tag=" + tag))
338
+
if templ_7745c5c3_Err != nil {
339
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 91, Col: 45}
340
+
}
341
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
342
+
if templ_7745c5c3_Err != nil {
343
+
return templ_7745c5c3_Err
344
+
}
345
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "\" class=\"rounded border-rosewater border-solid border pb-0.5 px-1 mr-1 mb-1 inline-block\">")
346
+
if templ_7745c5c3_Err != nil {
347
+
return templ_7745c5c3_Err
348
+
}
349
+
var templ_7745c5c3_Var18 string
350
+
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(tag)
351
+
if templ_7745c5c3_Err != nil {
352
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 91, Col: 141}
353
+
}
354
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
355
+
if templ_7745c5c3_Err != nil {
356
+
return templ_7745c5c3_Err
357
+
}
358
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</a>")
359
+
if templ_7745c5c3_Err != nil {
360
+
return templ_7745c5c3_Err
361
+
}
362
+
}
363
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</div><div class=\"sm:col-span-1 text-text/80 mb-4 sm:mb-0\" title=\"")
364
+
if templ_7745c5c3_Err != nil {
365
+
return templ_7745c5c3_Err
366
+
}
367
+
var templ_7745c5c3_Var19 string
368
+
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(lastCommitTime(repo, false))
369
+
if templ_7745c5c3_Err != nil {
370
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 94, Col: 93}
371
+
}
372
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
373
+
if templ_7745c5c3_Err != nil {
374
+
return templ_7745c5c3_Err
375
+
}
376
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "\">")
377
+
if templ_7745c5c3_Err != nil {
378
+
return templ_7745c5c3_Err
379
+
}
380
+
var templ_7745c5c3_Var20 string
381
+
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(lastCommitTime(repo, true))
382
+
if templ_7745c5c3_Err != nil {
383
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 94, Col: 124}
384
+
}
385
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
386
+
if templ_7745c5c3_Err != nil {
387
+
return templ_7745c5c3_Err
388
+
}
389
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "</div>")
390
+
if templ_7745c5c3_Err != nil {
391
+
return templ_7745c5c3_Err
392
+
}
393
+
}
394
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "</div></main>")
395
+
if templ_7745c5c3_Err != nil {
396
+
return templ_7745c5c3_Err
397
+
}
398
+
return nil
399
+
})
400
+
templ_7745c5c3_Err = base(ic.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
401
+
if templ_7745c5c3_Err != nil {
402
+
return templ_7745c5c3_Err
403
+
}
404
+
return nil
405
+
})
406
+
}
407
+
408
+
var _ = templruntime.GeneratedTemplate
-17
internal/html/readme.go
-17
internal/html/readme.go
···
1
-
package html
2
-
3
-
import (
4
-
. "maragu.dev/gomponents"
5
-
. "maragu.dev/gomponents/html"
6
-
)
7
-
8
-
type ReadmeComponentContext struct {
9
-
Markdown string
10
-
}
11
-
12
-
func readmeComponent(rcc ReadmeComponentContext) Node {
13
-
if rcc.Markdown == "" {
14
-
return nil
15
-
}
16
-
return Div(Class("bg-base dark:bg-base/50 p-5 mt-5 rounded markdown"), Raw(rcc.Markdown))
17
-
}
···
+13
internal/html/readme.templ
+13
internal/html/readme.templ
···
···
1
+
package html
2
+
3
+
type ReadmeComponentContext struct {
4
+
Markdown string
5
+
}
6
+
7
+
templ readmeComponent(rcc ReadmeComponentContext) {
8
+
if rcc.Markdown != "" {
9
+
<div class="bg-base dark:bg-base/50 p-5 mt-5 rounded markdown">
10
+
@templ.Raw(rcc.Markdown)
11
+
</div>
12
+
}
13
+
}
+54
internal/html/readme_templ.go
+54
internal/html/readme_templ.go
···
···
1
+
// Code generated by templ - DO NOT EDIT.
2
+
3
+
// templ: version: v0.3.924
4
+
package html
5
+
6
+
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
+
8
+
import "github.com/a-h/templ"
9
+
import templruntime "github.com/a-h/templ/runtime"
10
+
11
+
type ReadmeComponentContext struct {
12
+
Markdown string
13
+
}
14
+
15
+
func readmeComponent(rcc ReadmeComponentContext) templ.Component {
16
+
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
17
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
18
+
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
19
+
return templ_7745c5c3_CtxErr
20
+
}
21
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
22
+
if !templ_7745c5c3_IsBuffer {
23
+
defer func() {
24
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
25
+
if templ_7745c5c3_Err == nil {
26
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
27
+
}
28
+
}()
29
+
}
30
+
ctx = templ.InitializeContext(ctx)
31
+
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
32
+
if templ_7745c5c3_Var1 == nil {
33
+
templ_7745c5c3_Var1 = templ.NopComponent
34
+
}
35
+
ctx = templ.ClearChildren(ctx)
36
+
if rcc.Markdown != "" {
37
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"bg-base dark:bg-base/50 p-5 mt-5 rounded markdown\">")
38
+
if templ_7745c5c3_Err != nil {
39
+
return templ_7745c5c3_Err
40
+
}
41
+
templ_7745c5c3_Err = templ.Raw(rcc.Markdown).Render(ctx, templ_7745c5c3_Buffer)
42
+
if templ_7745c5c3_Err != nil {
43
+
return templ_7745c5c3_Err
44
+
}
45
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</div>")
46
+
if templ_7745c5c3_Err != nil {
47
+
return templ_7745c5c3_Err
48
+
}
49
+
}
50
+
return nil
51
+
})
52
+
}
53
+
54
+
var _ = templruntime.GeneratedTemplate
-44
internal/html/repo.go
-44
internal/html/repo.go
···
1
-
package html
2
-
3
-
import (
4
-
"fmt"
5
-
6
-
. "maragu.dev/gomponents"
7
-
. "maragu.dev/gomponents/html"
8
-
)
9
-
10
-
type RepoHeaderComponentContext struct {
11
-
Name string
12
-
Ref string
13
-
Description string
14
-
CloneURL string
15
-
Tags []string
16
-
}
17
-
18
-
func repoHeaderComponent(rhcc RepoHeaderComponentContext) Node {
19
-
return Group([]Node{
20
-
Div(Class("mb-1 text-text"),
21
-
A(Class("text-lg underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href("/"+rhcc.Name), Text(rhcc.Name)),
22
-
If(rhcc.Ref != "", Group([]Node{
23
-
Text(" "),
24
-
A(Class("text-text/80 text-sm underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/tree/%s/", rhcc.Name, rhcc.Ref)), Text("@"+rhcc.Ref)),
25
-
})),
26
-
Text(" - "),
27
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/refs", rhcc.Name)), Text("refs")),
28
-
Text(" - "),
29
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/log/%s", rhcc.Name, rhcc.Ref)), Text("log")),
30
-
Text(" - "),
31
-
Form(Class("inline-block"), Action(fmt.Sprintf("/%s/search", rhcc.Name)), Method("get"),
32
-
Input(Class("rounded p-1 bg-mantle focus:border-lavender focus:outline-none focus:ring-0"), ID("search"), Type("text"), Name("q"), Placeholder("search")),
33
-
),
34
-
Text(" - "),
35
-
Pre(Class("text-text inline select-all bg-base dark:bg-base/50 p-1 rounded"), Textf("%s/%s.git", rhcc.CloneURL, rhcc.Name)),
36
-
),
37
-
Div(Class("text-subtext0 mb-1"),
38
-
Map(rhcc.Tags, func(tag string) Node {
39
-
return Span(Class("rounded border-rosewater border-solid border pb-0.5 px-1 mr-1 mb-1 inline-block"), Text(tag))
40
-
}),
41
-
),
42
-
Div(Class("text-text/80 mb-1"), Text(rhcc.Description)),
43
-
})
44
-
}
···
+35
internal/html/repo.templ
+35
internal/html/repo.templ
···
···
1
+
package html
2
+
3
+
import "fmt"
4
+
5
+
type RepoHeaderComponentContext struct {
6
+
Name string
7
+
Ref string
8
+
Description string
9
+
CloneURL string
10
+
Tags []string
11
+
}
12
+
13
+
templ repoHeaderComponent(rhcc RepoHeaderComponentContext) {
14
+
<div class="mb-1 text-text">
15
+
<a class="text-lg underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL("/" + rhcc.Name) }>{ rhcc.Name }</a>
16
+
if rhcc.Ref != "" {
17
+
{ " " }
18
+
<a class="text-text/80 text-sm underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rhcc.Name, rhcc.Ref)) }>{ "@" + rhcc.Ref }</a>
19
+
}
20
+
{ " - " }
21
+
<a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/refs", rhcc.Name)) }>refs</a>
22
+
{ " - " }
23
+
<a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/log/%s", rhcc.Name, rhcc.Ref)) }>log</a>
24
+
{ " - " }
25
+
<form class="inline-block" action={ templ.SafeURL(fmt.Sprintf("/%s/search", rhcc.Name)) } method="get"><input class="rounded p-1 bg-mantle focus:border-lavender focus:outline-none focus:ring-0" id="search" type="text" name="q" placeholder="search"/></form>
26
+
{ " - " }
27
+
<pre class="text-text inline select-all bg-base dark:bg-base/50 p-1 rounded">{ fmt.Sprintf("%s/%s.git", rhcc.CloneURL, rhcc.Name) }</pre>
28
+
</div>
29
+
<div class="text-subtext0 mb-1">
30
+
for _, tag := range rhcc.Tags {
31
+
<span class="rounded border-rosewater border-solid border pb-0.5 px-1 mr-1 mb-1 inline-block">{ tag }</span>
32
+
}
33
+
</div>
34
+
<div class="text-text/80 mb-1">{ rhcc.Description }</div>
35
+
}
-72
internal/html/repo_commit.go
-72
internal/html/repo_commit.go
···
1
-
package html
2
-
3
-
import (
4
-
"fmt"
5
-
6
-
"github.com/dustin/go-humanize"
7
-
"go.jolheiser.com/ugit/internal/git"
8
-
. "maragu.dev/gomponents"
9
-
. "maragu.dev/gomponents/html"
10
-
)
11
-
12
-
type RepoCommitContext struct {
13
-
BaseContext
14
-
RepoHeaderComponentContext
15
-
Commit git.Commit
16
-
}
17
-
18
-
func RepoCommitTemplate(rcc RepoCommitContext) Node {
19
-
return base(rcc.BaseContext, []Node{
20
-
repoHeaderComponent(rcc.RepoHeaderComponentContext),
21
-
Div(Class("text-text mt-5"),
22
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/tree/%s/", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA)), Text("tree")),
23
-
Text(" "),
24
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/log/%s", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA)), Text("log")),
25
-
Text(" "),
26
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/commit/%s.patch", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA)), Text("patch")),
27
-
),
28
-
Div(Class("text-text whitespace-pre mt-5 p-3 bg-base rounded"), Text(rcc.Commit.Message)),
29
-
If(rcc.Commit.Signature != "",
30
-
Details(Class("text-text whitespace-pre"),
31
-
Summary(Class("cursor-pointer"), Text("Signature")),
32
-
Div(Class("p-3 bg-base rounded"),
33
-
Code(Text(rcc.Commit.Signature)),
34
-
),
35
-
),
36
-
),
37
-
Div(Class("text-text mt-3"),
38
-
Div(
39
-
Text(rcc.Commit.Author),
40
-
Text(" "),
41
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("mailto:%s", rcc.Commit.Email)), Text(fmt.Sprintf("<%s>", rcc.Commit.Email))),
42
-
),
43
-
Div(Title(rcc.Commit.When.Format("01/02/2006 03:04:05 PM")), Text(humanize.Time(rcc.Commit.When))),
44
-
),
45
-
Details(Class("text-text mt-5"),
46
-
Summary(Class("cursor-pointer"), Textf("%d changed files, %d additions(+), %d deletions(-)", rcc.Commit.Stats.Changed, rcc.Commit.Stats.Additions, rcc.Commit.Stats.Deletions)),
47
-
Div(Class("p-3 bg-base rounded"),
48
-
Map(rcc.Commit.Files, func(file git.CommitFile) Node {
49
-
return A(Class("block underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href("#"+file.Path()), Text(file.Path()))
50
-
}),
51
-
),
52
-
),
53
-
Map(rcc.Commit.Files, func(file git.CommitFile) Node {
54
-
return Group([]Node{
55
-
Div(Class("text-text mt-5"), ID(file.Path()),
56
-
Span(Class("text-text/80"), Title(file.Action), Text(string(file.Action[0]))),
57
-
Text(" "),
58
-
If(file.From.Path != "",
59
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.From.Commit, file.From.Path)), Text(file.From.Path)),
60
-
),
61
-
If(file.From.Path != "" && file.To.Path != "", Text(" โ ")),
62
-
If(file.To.Path != "",
63
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.To.Commit, file.To.Path)), Text(file.To.Path)),
64
-
),
65
-
),
66
-
Div(Class("code"),
67
-
Raw(file.Patch),
68
-
),
69
-
})
70
-
}),
71
-
}...)
72
-
}
···
+55
internal/html/repo_commit.templ
+55
internal/html/repo_commit.templ
···
···
1
+
package html
2
+
3
+
import "fmt"
4
+
import "github.com/dustin/go-humanize"
5
+
import "go.jolheiser.com/ugit/internal/git"
6
+
7
+
type RepoCommitContext struct {
8
+
BaseContext
9
+
RepoHeaderComponentContext
10
+
Commit git.Commit
11
+
}
12
+
13
+
templ RepoCommit(rcc RepoCommitContext) {
14
+
@base(rcc.BaseContext) {
15
+
@repoHeaderComponent(rcc.RepoHeaderComponentContext)
16
+
<div class="text-text mt-5"><a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA)) }>tree</a>{ " " }<a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/log/%s", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA)) }>log</a>{ " " }<a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/commit/%s.patch", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA)) }>patch</a></div>
17
+
<div class="text-text whitespace-pre mt-5 p-3 bg-base rounded">{ rcc.Commit.Message }</div>
18
+
if rcc.Commit.Signature != "" {
19
+
<details class="text-text whitespace-pre">
20
+
<summary class="cursor-pointer">Signature</summary>
21
+
<div class="p-3 bg-base rounded"><code>{ rcc.Commit.Signature }</code></div>
22
+
</details>
23
+
}
24
+
<div class="text-text mt-3">
25
+
<div>{ rcc.Commit.Author }{ " " }<a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("mailto:%s", rcc.Commit.Email)) }>{ fmt.Sprintf("<%s>", rcc.Commit.Email) }</a></div>
26
+
<div title={ rcc.Commit.When.Format("01/02/2006 03:04:05 PM") }>{ humanize.Time(rcc.Commit.When) }</div>
27
+
</div>
28
+
<details class="text-text mt-5">
29
+
<summary class="cursor-pointer">{ fmt.Sprintf("%d changed files, %d additions(+), %d deletions(-)", rcc.Commit.Stats.Changed, rcc.Commit.Stats.Additions, rcc.Commit.Stats.Deletions) }</summary>
30
+
<div class="p-3 bg-base rounded">
31
+
for _, file := range rcc.Commit.Files {
32
+
<a class="block underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ "#" + file.Path() }>{ file.Path() }</a>
33
+
}
34
+
</div>
35
+
</details>
36
+
for _, file := range rcc.Commit.Files {
37
+
<div class="text-text mt-5" id={ file.Path() }>
38
+
<span class="text-text/80" title={ file.Action }>{ string(file.Action[0]) }</span>
39
+
{ " " }
40
+
if file.From.Path != "" {
41
+
<a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.From.Commit, file.From.Path)) }>{ file.From.Path }</a>
42
+
}
43
+
if file.From.Path != "" && file.To.Path != "" {
44
+
{ " -> " }
45
+
}
46
+
if file.To.Path != "" {
47
+
<a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.To.Commit, file.To.Path)) }>{ file.To.Path }</a>
48
+
}
49
+
</div>
50
+
<div class="code">
51
+
@templ.Raw(file.Patch)
52
+
</div>
53
+
}
54
+
}
55
+
}
+445
internal/html/repo_commit_templ.go
+445
internal/html/repo_commit_templ.go
···
···
1
+
// Code generated by templ - DO NOT EDIT.
2
+
3
+
// templ: version: v0.3.924
4
+
package html
5
+
6
+
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
+
8
+
import "github.com/a-h/templ"
9
+
import templruntime "github.com/a-h/templ/runtime"
10
+
11
+
import "fmt"
12
+
import "github.com/dustin/go-humanize"
13
+
import "go.jolheiser.com/ugit/internal/git"
14
+
15
+
type RepoCommitContext struct {
16
+
BaseContext
17
+
RepoHeaderComponentContext
18
+
Commit git.Commit
19
+
}
20
+
21
+
func RepoCommit(rcc RepoCommitContext) templ.Component {
22
+
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
23
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
24
+
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
25
+
return templ_7745c5c3_CtxErr
26
+
}
27
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
28
+
if !templ_7745c5c3_IsBuffer {
29
+
defer func() {
30
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
31
+
if templ_7745c5c3_Err == nil {
32
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
33
+
}
34
+
}()
35
+
}
36
+
ctx = templ.InitializeContext(ctx)
37
+
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
38
+
if templ_7745c5c3_Var1 == nil {
39
+
templ_7745c5c3_Var1 = templ.NopComponent
40
+
}
41
+
ctx = templ.ClearChildren(ctx)
42
+
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
43
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
44
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
45
+
if !templ_7745c5c3_IsBuffer {
46
+
defer func() {
47
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
48
+
if templ_7745c5c3_Err == nil {
49
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
50
+
}
51
+
}()
52
+
}
53
+
ctx = templ.InitializeContext(ctx)
54
+
templ_7745c5c3_Err = repoHeaderComponent(rcc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer)
55
+
if templ_7745c5c3_Err != nil {
56
+
return templ_7745c5c3_Err
57
+
}
58
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"text-text mt-5\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
59
+
if templ_7745c5c3_Err != nil {
60
+
return templ_7745c5c3_Err
61
+
}
62
+
var templ_7745c5c3_Var3 templ.SafeURL
63
+
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA)))
64
+
if templ_7745c5c3_Err != nil {
65
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 16, Col: 213}
66
+
}
67
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
68
+
if templ_7745c5c3_Err != nil {
69
+
return templ_7745c5c3_Err
70
+
}
71
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\">tree</a>")
72
+
if templ_7745c5c3_Err != nil {
73
+
return templ_7745c5c3_Err
74
+
}
75
+
var templ_7745c5c3_Var4 string
76
+
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(" ")
77
+
if templ_7745c5c3_Err != nil {
78
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 16, Col: 229}
79
+
}
80
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
81
+
if templ_7745c5c3_Err != nil {
82
+
return templ_7745c5c3_Err
83
+
}
84
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
85
+
if templ_7745c5c3_Err != nil {
86
+
return templ_7745c5c3_Err
87
+
}
88
+
var templ_7745c5c3_Var5 templ.SafeURL
89
+
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/log/%s", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA)))
90
+
if templ_7745c5c3_Err != nil {
91
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 16, Col: 412}
92
+
}
93
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
94
+
if templ_7745c5c3_Err != nil {
95
+
return templ_7745c5c3_Err
96
+
}
97
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\">log</a>")
98
+
if templ_7745c5c3_Err != nil {
99
+
return templ_7745c5c3_Err
100
+
}
101
+
var templ_7745c5c3_Var6 string
102
+
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(" ")
103
+
if templ_7745c5c3_Err != nil {
104
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 16, Col: 427}
105
+
}
106
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
107
+
if templ_7745c5c3_Err != nil {
108
+
return templ_7745c5c3_Err
109
+
}
110
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
111
+
if templ_7745c5c3_Err != nil {
112
+
return templ_7745c5c3_Err
113
+
}
114
+
var templ_7745c5c3_Var7 templ.SafeURL
115
+
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/commit/%s.patch", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA)))
116
+
if templ_7745c5c3_Err != nil {
117
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 16, Col: 619}
118
+
}
119
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
120
+
if templ_7745c5c3_Err != nil {
121
+
return templ_7745c5c3_Err
122
+
}
123
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">patch</a></div><div class=\"text-text whitespace-pre mt-5 p-3 bg-base rounded\">")
124
+
if templ_7745c5c3_Err != nil {
125
+
return templ_7745c5c3_Err
126
+
}
127
+
var templ_7745c5c3_Var8 string
128
+
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(rcc.Commit.Message)
129
+
if templ_7745c5c3_Err != nil {
130
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 17, Col: 85}
131
+
}
132
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
133
+
if templ_7745c5c3_Err != nil {
134
+
return templ_7745c5c3_Err
135
+
}
136
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div>")
137
+
if templ_7745c5c3_Err != nil {
138
+
return templ_7745c5c3_Err
139
+
}
140
+
if rcc.Commit.Signature != "" {
141
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<details class=\"text-text whitespace-pre\"><summary class=\"cursor-pointer\">Signature</summary><div class=\"p-3 bg-base rounded\"><code>")
142
+
if templ_7745c5c3_Err != nil {
143
+
return templ_7745c5c3_Err
144
+
}
145
+
var templ_7745c5c3_Var9 string
146
+
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(rcc.Commit.Signature)
147
+
if templ_7745c5c3_Err != nil {
148
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 21, Col: 65}
149
+
}
150
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
151
+
if templ_7745c5c3_Err != nil {
152
+
return templ_7745c5c3_Err
153
+
}
154
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</code></div></details>")
155
+
if templ_7745c5c3_Err != nil {
156
+
return templ_7745c5c3_Err
157
+
}
158
+
}
159
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " <div class=\"text-text mt-3\"><div>")
160
+
if templ_7745c5c3_Err != nil {
161
+
return templ_7745c5c3_Err
162
+
}
163
+
var templ_7745c5c3_Var10 string
164
+
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(rcc.Commit.Author)
165
+
if templ_7745c5c3_Err != nil {
166
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 25, Col: 27}
167
+
}
168
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
169
+
if templ_7745c5c3_Err != nil {
170
+
return templ_7745c5c3_Err
171
+
}
172
+
var templ_7745c5c3_Var11 string
173
+
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(" ")
174
+
if templ_7745c5c3_Err != nil {
175
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 25, Col: 34}
176
+
}
177
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
178
+
if templ_7745c5c3_Err != nil {
179
+
return templ_7745c5c3_Err
180
+
}
181
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
182
+
if templ_7745c5c3_Err != nil {
183
+
return templ_7745c5c3_Err
184
+
}
185
+
var templ_7745c5c3_Var12 templ.SafeURL
186
+
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("mailto:%s", rcc.Commit.Email)))
187
+
if templ_7745c5c3_Err != nil {
188
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 25, Col: 181}
189
+
}
190
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
191
+
if templ_7745c5c3_Err != nil {
192
+
return templ_7745c5c3_Err
193
+
}
194
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\">")
195
+
if templ_7745c5c3_Err != nil {
196
+
return templ_7745c5c3_Err
197
+
}
198
+
var templ_7745c5c3_Var13 string
199
+
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("<%s>", rcc.Commit.Email))
200
+
if templ_7745c5c3_Err != nil {
201
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 25, Col: 223}
202
+
}
203
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
204
+
if templ_7745c5c3_Err != nil {
205
+
return templ_7745c5c3_Err
206
+
}
207
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</a></div><div title=\"")
208
+
if templ_7745c5c3_Err != nil {
209
+
return templ_7745c5c3_Err
210
+
}
211
+
var templ_7745c5c3_Var14 string
212
+
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(rcc.Commit.When.Format("01/02/2006 03:04:05 PM"))
213
+
if templ_7745c5c3_Err != nil {
214
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 26, Col: 64}
215
+
}
216
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
217
+
if templ_7745c5c3_Err != nil {
218
+
return templ_7745c5c3_Err
219
+
}
220
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "\">")
221
+
if templ_7745c5c3_Err != nil {
222
+
return templ_7745c5c3_Err
223
+
}
224
+
var templ_7745c5c3_Var15 string
225
+
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(humanize.Time(rcc.Commit.When))
226
+
if templ_7745c5c3_Err != nil {
227
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 26, Col: 99}
228
+
}
229
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
230
+
if templ_7745c5c3_Err != nil {
231
+
return templ_7745c5c3_Err
232
+
}
233
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</div></div><details class=\"text-text mt-5\"><summary class=\"cursor-pointer\">")
234
+
if templ_7745c5c3_Err != nil {
235
+
return templ_7745c5c3_Err
236
+
}
237
+
var templ_7745c5c3_Var16 string
238
+
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d changed files, %d additions(+), %d deletions(-)", rcc.Commit.Stats.Changed, rcc.Commit.Stats.Additions, rcc.Commit.Stats.Deletions))
239
+
if templ_7745c5c3_Err != nil {
240
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 29, Col: 184}
241
+
}
242
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
243
+
if templ_7745c5c3_Err != nil {
244
+
return templ_7745c5c3_Err
245
+
}
246
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</summary><div class=\"p-3 bg-base rounded\">")
247
+
if templ_7745c5c3_Err != nil {
248
+
return templ_7745c5c3_Err
249
+
}
250
+
for _, file := range rcc.Commit.Files {
251
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<a class=\"block underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
252
+
if templ_7745c5c3_Err != nil {
253
+
return templ_7745c5c3_Err
254
+
}
255
+
var templ_7745c5c3_Var17 templ.SafeURL
256
+
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinURLErrs("#" + file.Path())
257
+
if templ_7745c5c3_Err != nil {
258
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 32, Col: 116}
259
+
}
260
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
261
+
if templ_7745c5c3_Err != nil {
262
+
return templ_7745c5c3_Err
263
+
}
264
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\">")
265
+
if templ_7745c5c3_Err != nil {
266
+
return templ_7745c5c3_Err
267
+
}
268
+
var templ_7745c5c3_Var18 string
269
+
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(file.Path())
270
+
if templ_7745c5c3_Err != nil {
271
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 32, Col: 132}
272
+
}
273
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
274
+
if templ_7745c5c3_Err != nil {
275
+
return templ_7745c5c3_Err
276
+
}
277
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</a>")
278
+
if templ_7745c5c3_Err != nil {
279
+
return templ_7745c5c3_Err
280
+
}
281
+
}
282
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</div></details> ")
283
+
if templ_7745c5c3_Err != nil {
284
+
return templ_7745c5c3_Err
285
+
}
286
+
for _, file := range rcc.Commit.Files {
287
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<div class=\"text-text mt-5\" id=\"")
288
+
if templ_7745c5c3_Err != nil {
289
+
return templ_7745c5c3_Err
290
+
}
291
+
var templ_7745c5c3_Var19 string
292
+
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(file.Path())
293
+
if templ_7745c5c3_Err != nil {
294
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 37, Col: 47}
295
+
}
296
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
297
+
if templ_7745c5c3_Err != nil {
298
+
return templ_7745c5c3_Err
299
+
}
300
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\"><span class=\"text-text/80\" title=\"")
301
+
if templ_7745c5c3_Err != nil {
302
+
return templ_7745c5c3_Err
303
+
}
304
+
var templ_7745c5c3_Var20 string
305
+
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(file.Action)
306
+
if templ_7745c5c3_Err != nil {
307
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 38, Col: 50}
308
+
}
309
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
310
+
if templ_7745c5c3_Err != nil {
311
+
return templ_7745c5c3_Err
312
+
}
313
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\">")
314
+
if templ_7745c5c3_Err != nil {
315
+
return templ_7745c5c3_Err
316
+
}
317
+
var templ_7745c5c3_Var21 string
318
+
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(string(file.Action[0]))
319
+
if templ_7745c5c3_Err != nil {
320
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 38, Col: 77}
321
+
}
322
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
323
+
if templ_7745c5c3_Err != nil {
324
+
return templ_7745c5c3_Err
325
+
}
326
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</span> ")
327
+
if templ_7745c5c3_Err != nil {
328
+
return templ_7745c5c3_Err
329
+
}
330
+
var templ_7745c5c3_Var22 string
331
+
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(" ")
332
+
if templ_7745c5c3_Err != nil {
333
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 39, Col: 9}
334
+
}
335
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
336
+
if templ_7745c5c3_Err != nil {
337
+
return templ_7745c5c3_Err
338
+
}
339
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, " ")
340
+
if templ_7745c5c3_Err != nil {
341
+
return templ_7745c5c3_Err
342
+
}
343
+
if file.From.Path != "" {
344
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
345
+
if templ_7745c5c3_Err != nil {
346
+
return templ_7745c5c3_Err
347
+
}
348
+
var templ_7745c5c3_Var23 templ.SafeURL
349
+
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.From.Commit, file.From.Path)))
350
+
if templ_7745c5c3_Err != nil {
351
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 41, Col: 208}
352
+
}
353
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
354
+
if templ_7745c5c3_Err != nil {
355
+
return templ_7745c5c3_Err
356
+
}
357
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "\">")
358
+
if templ_7745c5c3_Err != nil {
359
+
return templ_7745c5c3_Err
360
+
}
361
+
var templ_7745c5c3_Var24 string
362
+
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(file.From.Path)
363
+
if templ_7745c5c3_Err != nil {
364
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 41, Col: 227}
365
+
}
366
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
367
+
if templ_7745c5c3_Err != nil {
368
+
return templ_7745c5c3_Err
369
+
}
370
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</a> ")
371
+
if templ_7745c5c3_Err != nil {
372
+
return templ_7745c5c3_Err
373
+
}
374
+
}
375
+
if file.From.Path != "" && file.To.Path != "" {
376
+
var templ_7745c5c3_Var25 string
377
+
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(" -> ")
378
+
if templ_7745c5c3_Err != nil {
379
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 44, Col: 13}
380
+
}
381
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
382
+
if templ_7745c5c3_Err != nil {
383
+
return templ_7745c5c3_Err
384
+
}
385
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, " ")
386
+
if templ_7745c5c3_Err != nil {
387
+
return templ_7745c5c3_Err
388
+
}
389
+
}
390
+
if file.To.Path != "" {
391
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
392
+
if templ_7745c5c3_Err != nil {
393
+
return templ_7745c5c3_Err
394
+
}
395
+
var templ_7745c5c3_Var26 templ.SafeURL
396
+
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.To.Commit, file.To.Path)))
397
+
if templ_7745c5c3_Err != nil {
398
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 47, Col: 204}
399
+
}
400
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
401
+
if templ_7745c5c3_Err != nil {
402
+
return templ_7745c5c3_Err
403
+
}
404
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "\">")
405
+
if templ_7745c5c3_Err != nil {
406
+
return templ_7745c5c3_Err
407
+
}
408
+
var templ_7745c5c3_Var27 string
409
+
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(file.To.Path)
410
+
if templ_7745c5c3_Err != nil {
411
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 47, Col: 221}
412
+
}
413
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
414
+
if templ_7745c5c3_Err != nil {
415
+
return templ_7745c5c3_Err
416
+
}
417
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "</a>")
418
+
if templ_7745c5c3_Err != nil {
419
+
return templ_7745c5c3_Err
420
+
}
421
+
}
422
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</div><div class=\"code\">")
423
+
if templ_7745c5c3_Err != nil {
424
+
return templ_7745c5c3_Err
425
+
}
426
+
templ_7745c5c3_Err = templ.Raw(file.Patch).Render(ctx, templ_7745c5c3_Buffer)
427
+
if templ_7745c5c3_Err != nil {
428
+
return templ_7745c5c3_Err
429
+
}
430
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</div>")
431
+
if templ_7745c5c3_Err != nil {
432
+
return templ_7745c5c3_Err
433
+
}
434
+
}
435
+
return nil
436
+
})
437
+
templ_7745c5c3_Err = base(rcc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
438
+
if templ_7745c5c3_Err != nil {
439
+
return templ_7745c5c3_Err
440
+
}
441
+
return nil
442
+
})
443
+
}
444
+
445
+
var _ = templruntime.GeneratedTemplate
-40
internal/html/repo_file.go
-40
internal/html/repo_file.go
···
1
-
package html
2
-
3
-
import (
4
-
_ "embed"
5
-
"fmt"
6
-
7
-
. "maragu.dev/gomponents"
8
-
. "maragu.dev/gomponents/html"
9
-
)
10
-
11
-
type RepoFileContext struct {
12
-
BaseContext
13
-
RepoHeaderComponentContext
14
-
RepoBreadcrumbComponentContext
15
-
Code string
16
-
Commit string
17
-
Path string
18
-
}
19
-
20
-
//go:embed repo_file.js
21
-
var repoFileJS string
22
-
23
-
func RepoFileTemplate(rfc RepoFileContext) Node {
24
-
permalink := fmt.Sprintf("/%s/tree/%s/%s", rfc.RepoBreadcrumbComponentContext.Repo, rfc.Commit, rfc.Path)
25
-
return base(rfc.BaseContext, []Node{
26
-
repoHeaderComponent(rfc.RepoHeaderComponentContext),
27
-
Div(Class("mt-2 text-text"),
28
-
repoBreadcrumbComponent(rfc.RepoBreadcrumbComponentContext),
29
-
Text(" - "),
30
-
A(Class("text-text underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href("?raw"), Text("raw")),
31
-
Text(" - "),
32
-
A(Class("text-text underline decoration-text/50 decoration-dashed hover:decoration-solid"), ID("permalink"), Data("permalink", permalink), Href(permalink), Text("permalink")),
33
-
Div(Class("code relative"),
34
-
Raw(rfc.Code),
35
-
Button(ID("copy"), Class("absolute top-0 right-0 rounded bg-base hover:bg-surface0")),
36
-
),
37
-
),
38
-
Script(Raw(repoFileJS)),
39
-
}...)
40
-
}
···
-70
internal/html/repo_file.js
-70
internal/html/repo_file.js
···
1
-
const lineRe = /#L(\d+)(?:-L(\d+))?/g
2
-
const $lineLines = document.querySelectorAll(".chroma .lntable .lnt");
3
-
const $codeLines = document.querySelectorAll(".chroma .lntable .line");
4
-
const $copyButton = document.getElementById('copy');
5
-
const $permalink = document.getElementById('permalink');
6
-
const $copyIcon = "๐";
7
-
const $copiedIcon = "โ
";
8
-
let $code = ""
9
-
for (let codeLine of $codeLines) $code += codeLine.innerText;
10
-
let start = 0;
11
-
let end = 0;
12
-
const results = [...location.hash.matchAll(lineRe)];
13
-
if (0 in results) {
14
-
start = results[0][1] !== undefined ? parseInt(results[0][1]) : 0;
15
-
end = results[0][2] !== undefined ? parseInt(results[0][2]) : 0;
16
-
}
17
-
if (start !== 0) {
18
-
deactivateLines();
19
-
activateLines(start, end);
20
-
let anchor = `#${start}`;
21
-
if (end !== 0) anchor += `-${end}`;
22
-
if (anchor !== "") $permalink.href = $permalink.dataset.permalink + anchor;
23
-
$lineLines[start - 1].scrollIntoView(true);
24
-
}
25
-
for (let line of $lineLines) {
26
-
line.addEventListener("click", (event) => {
27
-
event.preventDefault();
28
-
deactivateLines();
29
-
const n = parseInt(line.id.substring(1));
30
-
let anchor = "";
31
-
if (event.shiftKey) {
32
-
end = n;
33
-
anchor = `#L${start}-L${end}`;
34
-
} else if (start === n) {
35
-
start = 0;
36
-
end = 0;
37
-
} else {
38
-
start = n;
39
-
end = 0;
40
-
anchor = `#L${start}`;
41
-
}
42
-
history.replaceState(null, null, window.location.pathname + anchor);
43
-
$permalink.href = $permalink.dataset.permalink + anchor;
44
-
if (start !== 0) activateLines(start, end);
45
-
});
46
-
}
47
-
if (navigator.clipboard && navigator.clipboard.writeText) {
48
-
$copyButton.innerText = $copyIcon;
49
-
$copyButton.classList.remove("hidden");
50
-
}
51
-
$copyButton.addEventListener("click", () => {
52
-
navigator.clipboard.writeText($code);
53
-
$copyButton.innerText = $copiedIcon;
54
-
setTimeout(() => {
55
-
$copyButton.innerText = $copyIcon;
56
-
}, 1000);
57
-
});
58
-
59
-
function activateLines(start, end) {
60
-
if (end < start) end = start;
61
-
for (let idx = start - 1; idx < end; idx++) {
62
-
$codeLines[idx].classList.add("active");
63
-
}
64
-
}
65
-
66
-
function deactivateLines() {
67
-
for (let code of $codeLines) {
68
-
code.classList.remove("active");
69
-
}
70
-
}
···
+111
internal/html/repo_file.templ
+111
internal/html/repo_file.templ
···
···
1
+
package html
2
+
3
+
import "fmt"
4
+
5
+
type RepoFileContext struct {
6
+
BaseContext
7
+
RepoHeaderComponentContext
8
+
RepoBreadcrumbComponentContext
9
+
Code string
10
+
Commit string
11
+
Path string
12
+
}
13
+
14
+
func (rfc RepoFileContext) Permalink() string {
15
+
return fmt.Sprintf("/%s/tree/%s/%s", rfc.RepoBreadcrumbComponentContext.Repo, rfc.Commit, rfc.Path)
16
+
}
17
+
18
+
templ RepoFile(rfc RepoFileContext) {
19
+
@base(rfc.BaseContext) {
20
+
@repoHeaderComponent(rfc.RepoHeaderComponentContext)
21
+
<div class="mt-2 text-text">
22
+
@repoBreadcrumbComponent(rfc.RepoBreadcrumbComponentContext)
23
+
{ " - " }
24
+
<a class="text-text underline decoration-text/50 decoration-dashed hover:decoration-solid" href="?raw">raw</a>
25
+
{ " - " }
26
+
<a class="text-text underline decoration-text/50 decoration-dashed hover:decoration-solid" id="permalink" data-permalink={ rfc.Permalink() } href={ rfc.Permalink() }>permalink</a>
27
+
<div class="code relative">
28
+
@templ.Raw(rfc.Code)
29
+
<button id="copy" class="absolute top-0 right-0 rounded bg-base hover:bg-surface0"></button>
30
+
</div>
31
+
</div>
32
+
}
33
+
<script>
34
+
const lineRe = /#L(\d+)(?:-L(\d+))?/g
35
+
const $lineLines = document.querySelectorAll(".chroma .lntable .lnt");
36
+
const $codeLines = document.querySelectorAll(".chroma .lntable .line");
37
+
const $copyButton = document.getElementById('copy');
38
+
const $permalink = document.getElementById('permalink');
39
+
const $copyIcon = "๐";
40
+
const $copiedIcon = "โ
";
41
+
let $code = ""
42
+
for (let codeLine of $codeLines) $code += codeLine.innerText;
43
+
let start = 0;
44
+
let end = 0;
45
+
46
+
const results = [...location.hash.matchAll(lineRe)];
47
+
if (0 in results) {
48
+
start = results[0][1] !== undefined ? parseInt(results[0][1]) : 0;
49
+
end = results[0][2] !== undefined ? parseInt(results[0][2]) : 0;
50
+
}
51
+
if (start !== 0) {
52
+
deactivateLines();
53
+
activateLines(start, end);
54
+
let anchor = `#${start}`;
55
+
if (end !== 0) anchor += `-${end}`;
56
+
if (anchor !== "") $permalink.href = $permalink.dataset.permalink + anchor;
57
+
$lineLines[start-1].scrollIntoView(true);
58
+
}
59
+
60
+
for (let line of $lineLines) {
61
+
line.addEventListener("click", (event) => {
62
+
event.preventDefault();
63
+
deactivateLines();
64
+
const n = parseInt(line.id.substring(1));
65
+
let anchor = "";
66
+
if (event.shiftKey) {
67
+
end = n;
68
+
anchor = `#L${start}-L${end}`;
69
+
} else if (start === n) {
70
+
start = 0;
71
+
end = 0;
72
+
} else {
73
+
start = n;
74
+
end = 0;
75
+
anchor = `#L${start}`;
76
+
}
77
+
history.replaceState(null, null, window.location.pathname + anchor);
78
+
$permalink.href = $permalink.dataset.permalink + anchor;
79
+
if (start !== 0) activateLines(start, end);
80
+
});
81
+
}
82
+
83
+
if (navigator.clipboard && navigator.clipboard.writeText) {
84
+
$copyButton.innerText = $copyIcon;
85
+
$copyButton.classList.remove("hidden");
86
+
}
87
+
$copyButton.addEventListener("click", () => {
88
+
navigator.clipboard.writeText($code);
89
+
$copyButton.innerText = $copiedIcon;
90
+
setTimeout(() => {
91
+
$copyButton.innerText = $copyIcon;
92
+
}, 1000);
93
+
});
94
+
95
+
function activateLines(start, end) {
96
+
if (end < start) end = start;
97
+
for (let idx = start - 1; idx < end; idx++) {
98
+
$codeLines[idx].classList.add("active");
99
+
}
100
+
}
101
+
102
+
function deactivateLines() {
103
+
for (let code of $codeLines) {
104
+
code.classList.remove("active");
105
+
}
106
+
}
107
+
108
+
109
+
110
+
</script>
111
+
}
+145
internal/html/repo_file_templ.go
+145
internal/html/repo_file_templ.go
···
···
1
+
// Code generated by templ - DO NOT EDIT.
2
+
3
+
// templ: version: v0.3.924
4
+
package html
5
+
6
+
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
+
8
+
import "github.com/a-h/templ"
9
+
import templruntime "github.com/a-h/templ/runtime"
10
+
11
+
import "fmt"
12
+
13
+
type RepoFileContext struct {
14
+
BaseContext
15
+
RepoHeaderComponentContext
16
+
RepoBreadcrumbComponentContext
17
+
Code string
18
+
Commit string
19
+
Path string
20
+
}
21
+
22
+
func (rfc RepoFileContext) Permalink() string {
23
+
return fmt.Sprintf("/%s/tree/%s/%s", rfc.RepoBreadcrumbComponentContext.Repo, rfc.Commit, rfc.Path)
24
+
}
25
+
26
+
func RepoFile(rfc RepoFileContext) templ.Component {
27
+
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
28
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
29
+
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
30
+
return templ_7745c5c3_CtxErr
31
+
}
32
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
33
+
if !templ_7745c5c3_IsBuffer {
34
+
defer func() {
35
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
36
+
if templ_7745c5c3_Err == nil {
37
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
38
+
}
39
+
}()
40
+
}
41
+
ctx = templ.InitializeContext(ctx)
42
+
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
43
+
if templ_7745c5c3_Var1 == nil {
44
+
templ_7745c5c3_Var1 = templ.NopComponent
45
+
}
46
+
ctx = templ.ClearChildren(ctx)
47
+
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
48
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
49
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
50
+
if !templ_7745c5c3_IsBuffer {
51
+
defer func() {
52
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
53
+
if templ_7745c5c3_Err == nil {
54
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
55
+
}
56
+
}()
57
+
}
58
+
ctx = templ.InitializeContext(ctx)
59
+
templ_7745c5c3_Err = repoHeaderComponent(rfc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer)
60
+
if templ_7745c5c3_Err != nil {
61
+
return templ_7745c5c3_Err
62
+
}
63
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"mt-2 text-text\">")
64
+
if templ_7745c5c3_Err != nil {
65
+
return templ_7745c5c3_Err
66
+
}
67
+
templ_7745c5c3_Err = repoBreadcrumbComponent(rfc.RepoBreadcrumbComponentContext).Render(ctx, templ_7745c5c3_Buffer)
68
+
if templ_7745c5c3_Err != nil {
69
+
return templ_7745c5c3_Err
70
+
}
71
+
var templ_7745c5c3_Var3 string
72
+
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(" - ")
73
+
if templ_7745c5c3_Err != nil {
74
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 23, Col: 10}
75
+
}
76
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
77
+
if templ_7745c5c3_Err != nil {
78
+
return templ_7745c5c3_Err
79
+
}
80
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " <a class=\"text-text underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"?raw\">raw</a> ")
81
+
if templ_7745c5c3_Err != nil {
82
+
return templ_7745c5c3_Err
83
+
}
84
+
var templ_7745c5c3_Var4 string
85
+
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(" - ")
86
+
if templ_7745c5c3_Err != nil {
87
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 25, Col: 10}
88
+
}
89
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
90
+
if templ_7745c5c3_Err != nil {
91
+
return templ_7745c5c3_Err
92
+
}
93
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, " <a class=\"text-text underline decoration-text/50 decoration-dashed hover:decoration-solid\" id=\"permalink\" data-permalink=\"")
94
+
if templ_7745c5c3_Err != nil {
95
+
return templ_7745c5c3_Err
96
+
}
97
+
var templ_7745c5c3_Var5 string
98
+
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(rfc.Permalink())
99
+
if templ_7745c5c3_Err != nil {
100
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 26, Col: 141}
101
+
}
102
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
103
+
if templ_7745c5c3_Err != nil {
104
+
return templ_7745c5c3_Err
105
+
}
106
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" href=\"")
107
+
if templ_7745c5c3_Err != nil {
108
+
return templ_7745c5c3_Err
109
+
}
110
+
var templ_7745c5c3_Var6 templ.SafeURL
111
+
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(rfc.Permalink())
112
+
if templ_7745c5c3_Err != nil {
113
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 26, Col: 166}
114
+
}
115
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
116
+
if templ_7745c5c3_Err != nil {
117
+
return templ_7745c5c3_Err
118
+
}
119
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">permalink</a><div class=\"code relative\">")
120
+
if templ_7745c5c3_Err != nil {
121
+
return templ_7745c5c3_Err
122
+
}
123
+
templ_7745c5c3_Err = templ.Raw(rfc.Code).Render(ctx, templ_7745c5c3_Buffer)
124
+
if templ_7745c5c3_Err != nil {
125
+
return templ_7745c5c3_Err
126
+
}
127
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<button id=\"copy\" class=\"absolute top-0 right-0 rounded bg-base hover:bg-surface0\"></button></div></div>")
128
+
if templ_7745c5c3_Err != nil {
129
+
return templ_7745c5c3_Err
130
+
}
131
+
return nil
132
+
})
133
+
templ_7745c5c3_Err = base(rfc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
134
+
if templ_7745c5c3_Err != nil {
135
+
return templ_7745c5c3_Err
136
+
}
137
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<script>\n\t\tconst lineRe = /#L(\\d+)(?:-L(\\d+))?/g\n\t\tconst $lineLines = document.querySelectorAll(\".chroma .lntable .lnt\");\n\t\tconst $codeLines = document.querySelectorAll(\".chroma .lntable .line\");\n\t\tconst $copyButton = document.getElementById('copy');\n\t\tconst $permalink = document.getElementById('permalink');\n\t\tconst $copyIcon = \"๐\";\n\t\tconst $copiedIcon = \"โ
\";\n\t\tlet $code = \"\"\n\t\tfor (let codeLine of $codeLines) $code += codeLine.innerText;\n\t\tlet start = 0;\n\t\tlet end = 0;\n\n\t\tconst results = [...location.hash.matchAll(lineRe)];\t\t\n\t\tif (0 in results) {\n\t\t\tstart = results[0][1] !== undefined ? parseInt(results[0][1]) : 0;\n\t\t\tend = results[0][2] !== undefined ? parseInt(results[0][2]) : 0;\n\t\t}\n\t\tif (start !== 0) {\n\t\t\tdeactivateLines();\n\t\t\tactivateLines(start, end);\n\t\t\tlet anchor = `#${start}`;\n if (end !== 0) anchor += `-${end}`;\n if (anchor !== \"\") $permalink.href = $permalink.dataset.permalink + anchor;\n\t\t\t$lineLines[start-1].scrollIntoView(true);\n\t\t}\n\n\t\tfor (let line of $lineLines) {\n\t\t\tline.addEventListener(\"click\", (event) => {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tdeactivateLines();\n\t\t\t\tconst n = parseInt(line.id.substring(1));\n\t\t\t\tlet anchor = \"\";\n\t\t\t\tif (event.shiftKey) {\n\t\t\t\t\tend = n;\n\t\t\t\t\tanchor = `#L${start}-L${end}`;\n\t\t\t\t} else if (start === n) {\n\t\t\t\t\tstart = 0;\n\t\t\t\t\tend = 0;\n\t\t\t\t} else {\n\t\t\t\t\tstart = n;\n\t\t\t\t\tend = 0;\n\t\t\t\t\tanchor = `#L${start}`;\n\t\t\t\t}\n\t\t\t\thistory.replaceState(null, null, window.location.pathname + anchor);\n\t\t\t\t$permalink.href = $permalink.dataset.permalink + anchor;\n\t\t\t\tif (start !== 0) activateLines(start, end);\n\t\t\t});\n\t\t}\n\n\t\tif (navigator.clipboard && navigator.clipboard.writeText) {\n\t\t\t$copyButton.innerText = $copyIcon;\n\t\t\t$copyButton.classList.remove(\"hidden\");\n }\n\t\t$copyButton.addEventListener(\"click\", () => {\n navigator.clipboard.writeText($code);\n\t\t\t$copyButton.innerText = $copiedIcon;\n\t\t\tsetTimeout(() => {\n\t\t\t\t$copyButton.innerText = $copyIcon;\n\t\t\t}, 1000);\n });\n\n\t\tfunction activateLines(start, end) {\n\t\t\tif (end < start) end = start;\n\t\t\tfor (let idx = start - 1; idx < end; idx++) {\n\t\t\t\t$codeLines[idx].classList.add(\"active\");\n\t\t\t}\n\t\t}\n\n\t\tfunction deactivateLines() {\n\t\t\tfor (let code of $codeLines) {\n\t\t\t\tcode.classList.remove(\"active\");\n\t\t\t}\n\t\t}\n\n\t\t\n\t\t\n\t</script>")
138
+
if templ_7745c5c3_Err != nil {
139
+
return templ_7745c5c3_Err
140
+
}
141
+
return nil
142
+
})
143
+
}
144
+
145
+
var _ = templruntime.GeneratedTemplate
-52
internal/html/repo_log.go
-52
internal/html/repo_log.go
···
1
-
package html
2
-
3
-
import (
4
-
"fmt"
5
-
6
-
"github.com/dustin/go-humanize"
7
-
"go.jolheiser.com/ugit/internal/git"
8
-
. "maragu.dev/gomponents"
9
-
. "maragu.dev/gomponents/html"
10
-
)
11
-
12
-
type RepoLogContext struct {
13
-
BaseContext
14
-
RepoHeaderComponentContext
15
-
Commits []git.Commit
16
-
}
17
-
18
-
func RepoLogTemplate(rlc RepoLogContext) Node {
19
-
return base(rlc.BaseContext, []Node{
20
-
repoHeaderComponent(rlc.RepoHeaderComponentContext),
21
-
Div(Class("grid sm:grid-cols-8 gap-1 text-text mt-5"),
22
-
Map(rlc.Commits, func(commit git.Commit) Node {
23
-
return Group([]Node{
24
-
Div(Class("sm:col-span-5"),
25
-
Div(
26
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/commit/%s", rlc.RepoHeaderComponentContext.Name, commit.SHA)), Text(commit.Short())),
27
-
),
28
-
Div(Class("whitespace-pre"),
29
-
If(commit.Details() != "",
30
-
Details(
31
-
Summary(Class("cursor-pointer"), Text(commit.Summary())),
32
-
Div(Class("p-3 bg-base rounded"), Text(commit.Details())),
33
-
),
34
-
),
35
-
If(commit.Details() == "",
36
-
Text(commit.Message),
37
-
),
38
-
),
39
-
),
40
-
Div(Class("sm:col-span-3 mb-4"),
41
-
Div(
42
-
Text(commit.Author),
43
-
Text(" "),
44
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("mailto:%s", commit.Email)), Textf("<%s>", commit.Email)),
45
-
),
46
-
Div(Title(commit.When.Format("01/02/2006 03:04:05 PM")), Text(humanize.Time(commit.When))),
47
-
),
48
-
})
49
-
}),
50
-
),
51
-
}...)
52
-
}
···
+38
internal/html/repo_log.templ
+38
internal/html/repo_log.templ
···
···
1
+
package html
2
+
3
+
import "fmt"
4
+
import "github.com/dustin/go-humanize"
5
+
import "go.jolheiser.com/ugit/internal/git"
6
+
7
+
type RepoLogContext struct {
8
+
BaseContext
9
+
RepoHeaderComponentContext
10
+
Commits []git.Commit
11
+
}
12
+
13
+
templ RepoLog(rlc RepoLogContext) {
14
+
@base(rlc.BaseContext) {
15
+
@repoHeaderComponent(rlc.RepoHeaderComponentContext)
16
+
<div class="grid sm:grid-cols-8 gap-1 text-text mt-5">
17
+
for _, commit := range rlc.Commits {
18
+
<div class="sm:col-span-5">
19
+
<div><a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/commit/%s", rlc.RepoHeaderComponentContext.Name, commit.SHA)) }>{ commit.Short() }</a></div>
20
+
<div class="whitespace-pre">
21
+
if commit.Details() != "" {
22
+
<details>
23
+
<summary class="cursor-pointer">{ commit.Summary() }</summary>
24
+
<div class="p-3 bg-base rounded">{ commit.Details() }</div>
25
+
</details>
26
+
} else {
27
+
{ commit.Message }
28
+
}
29
+
</div>
30
+
</div>
31
+
<div class="sm:col-span-3 mb-4">
32
+
<div>{ commit.Author }{ " " }<a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("mailto:%s", commit.Email)) }>{ fmt.Sprintf("<%s>", commit.Email) }</a></div>
33
+
<div title={ commit.When.Format("01/02/2006 03:04:05 PM") }>{ humanize.Time(commit.When) }</div>
34
+
</div>
35
+
}
36
+
</div>
37
+
}
38
+
}
+228
internal/html/repo_log_templ.go
+228
internal/html/repo_log_templ.go
···
···
1
+
// Code generated by templ - DO NOT EDIT.
2
+
3
+
// templ: version: v0.3.924
4
+
package html
5
+
6
+
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
+
8
+
import "github.com/a-h/templ"
9
+
import templruntime "github.com/a-h/templ/runtime"
10
+
11
+
import "fmt"
12
+
import "github.com/dustin/go-humanize"
13
+
import "go.jolheiser.com/ugit/internal/git"
14
+
15
+
type RepoLogContext struct {
16
+
BaseContext
17
+
RepoHeaderComponentContext
18
+
Commits []git.Commit
19
+
}
20
+
21
+
func RepoLog(rlc RepoLogContext) templ.Component {
22
+
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
23
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
24
+
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
25
+
return templ_7745c5c3_CtxErr
26
+
}
27
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
28
+
if !templ_7745c5c3_IsBuffer {
29
+
defer func() {
30
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
31
+
if templ_7745c5c3_Err == nil {
32
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
33
+
}
34
+
}()
35
+
}
36
+
ctx = templ.InitializeContext(ctx)
37
+
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
38
+
if templ_7745c5c3_Var1 == nil {
39
+
templ_7745c5c3_Var1 = templ.NopComponent
40
+
}
41
+
ctx = templ.ClearChildren(ctx)
42
+
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
43
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
44
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
45
+
if !templ_7745c5c3_IsBuffer {
46
+
defer func() {
47
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
48
+
if templ_7745c5c3_Err == nil {
49
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
50
+
}
51
+
}()
52
+
}
53
+
ctx = templ.InitializeContext(ctx)
54
+
templ_7745c5c3_Err = repoHeaderComponent(rlc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer)
55
+
if templ_7745c5c3_Err != nil {
56
+
return templ_7745c5c3_Err
57
+
}
58
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"grid sm:grid-cols-8 gap-1 text-text mt-5\">")
59
+
if templ_7745c5c3_Err != nil {
60
+
return templ_7745c5c3_Err
61
+
}
62
+
for _, commit := range rlc.Commits {
63
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"sm:col-span-5\"><div><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
64
+
if templ_7745c5c3_Err != nil {
65
+
return templ_7745c5c3_Err
66
+
}
67
+
var templ_7745c5c3_Var3 templ.SafeURL
68
+
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/commit/%s", rlc.RepoHeaderComponentContext.Name, commit.SHA)))
69
+
if templ_7745c5c3_Err != nil {
70
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 19, Col: 190}
71
+
}
72
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
73
+
if templ_7745c5c3_Err != nil {
74
+
return templ_7745c5c3_Err
75
+
}
76
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">")
77
+
if templ_7745c5c3_Err != nil {
78
+
return templ_7745c5c3_Err
79
+
}
80
+
var templ_7745c5c3_Var4 string
81
+
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Short())
82
+
if templ_7745c5c3_Err != nil {
83
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 19, Col: 209}
84
+
}
85
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
86
+
if templ_7745c5c3_Err != nil {
87
+
return templ_7745c5c3_Err
88
+
}
89
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</a></div><div class=\"whitespace-pre\">")
90
+
if templ_7745c5c3_Err != nil {
91
+
return templ_7745c5c3_Err
92
+
}
93
+
if commit.Details() != "" {
94
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<details><summary class=\"cursor-pointer\">")
95
+
if templ_7745c5c3_Err != nil {
96
+
return templ_7745c5c3_Err
97
+
}
98
+
var templ_7745c5c3_Var5 string
99
+
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Summary())
100
+
if templ_7745c5c3_Err != nil {
101
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 23, Col: 58}
102
+
}
103
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
104
+
if templ_7745c5c3_Err != nil {
105
+
return templ_7745c5c3_Err
106
+
}
107
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</summary><div class=\"p-3 bg-base rounded\">")
108
+
if templ_7745c5c3_Err != nil {
109
+
return templ_7745c5c3_Err
110
+
}
111
+
var templ_7745c5c3_Var6 string
112
+
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Details())
113
+
if templ_7745c5c3_Err != nil {
114
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 24, Col: 59}
115
+
}
116
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
117
+
if templ_7745c5c3_Err != nil {
118
+
return templ_7745c5c3_Err
119
+
}
120
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div></details>")
121
+
if templ_7745c5c3_Err != nil {
122
+
return templ_7745c5c3_Err
123
+
}
124
+
} else {
125
+
var templ_7745c5c3_Var7 string
126
+
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Message)
127
+
if templ_7745c5c3_Err != nil {
128
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 27, Col: 23}
129
+
}
130
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
131
+
if templ_7745c5c3_Err != nil {
132
+
return templ_7745c5c3_Err
133
+
}
134
+
}
135
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div></div><div class=\"sm:col-span-3 mb-4\"><div>")
136
+
if templ_7745c5c3_Err != nil {
137
+
return templ_7745c5c3_Err
138
+
}
139
+
var templ_7745c5c3_Var8 string
140
+
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Author)
141
+
if templ_7745c5c3_Err != nil {
142
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 32, Col: 25}
143
+
}
144
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
145
+
if templ_7745c5c3_Err != nil {
146
+
return templ_7745c5c3_Err
147
+
}
148
+
var templ_7745c5c3_Var9 string
149
+
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(" ")
150
+
if templ_7745c5c3_Err != nil {
151
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 32, Col: 32}
152
+
}
153
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
154
+
if templ_7745c5c3_Err != nil {
155
+
return templ_7745c5c3_Err
156
+
}
157
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
158
+
if templ_7745c5c3_Err != nil {
159
+
return templ_7745c5c3_Err
160
+
}
161
+
var templ_7745c5c3_Var10 templ.SafeURL
162
+
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("mailto:%s", commit.Email)))
163
+
if templ_7745c5c3_Err != nil {
164
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 32, Col: 175}
165
+
}
166
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
167
+
if templ_7745c5c3_Err != nil {
168
+
return templ_7745c5c3_Err
169
+
}
170
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\">")
171
+
if templ_7745c5c3_Err != nil {
172
+
return templ_7745c5c3_Err
173
+
}
174
+
var templ_7745c5c3_Var11 string
175
+
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("<%s>", commit.Email))
176
+
if templ_7745c5c3_Err != nil {
177
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 32, Col: 213}
178
+
}
179
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
180
+
if templ_7745c5c3_Err != nil {
181
+
return templ_7745c5c3_Err
182
+
}
183
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</a></div><div title=\"")
184
+
if templ_7745c5c3_Err != nil {
185
+
return templ_7745c5c3_Err
186
+
}
187
+
var templ_7745c5c3_Var12 string
188
+
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(commit.When.Format("01/02/2006 03:04:05 PM"))
189
+
if templ_7745c5c3_Err != nil {
190
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 33, Col: 62}
191
+
}
192
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
193
+
if templ_7745c5c3_Err != nil {
194
+
return templ_7745c5c3_Err
195
+
}
196
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\">")
197
+
if templ_7745c5c3_Err != nil {
198
+
return templ_7745c5c3_Err
199
+
}
200
+
var templ_7745c5c3_Var13 string
201
+
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(humanize.Time(commit.When))
202
+
if templ_7745c5c3_Err != nil {
203
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 33, Col: 93}
204
+
}
205
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
206
+
if templ_7745c5c3_Err != nil {
207
+
return templ_7745c5c3_Err
208
+
}
209
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div></div>")
210
+
if templ_7745c5c3_Err != nil {
211
+
return templ_7745c5c3_Err
212
+
}
213
+
}
214
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</div>")
215
+
if templ_7745c5c3_Err != nil {
216
+
return templ_7745c5c3_Err
217
+
}
218
+
return nil
219
+
})
220
+
templ_7745c5c3_Err = base(rlc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
221
+
if templ_7745c5c3_Err != nil {
222
+
return templ_7745c5c3_Err
223
+
}
224
+
return nil
225
+
})
226
+
}
227
+
228
+
var _ = templruntime.GeneratedTemplate
-61
internal/html/repo_refs.go
-61
internal/html/repo_refs.go
···
1
-
package html
2
-
3
-
import (
4
-
"fmt"
5
-
6
-
"go.jolheiser.com/ugit/internal/git"
7
-
. "maragu.dev/gomponents"
8
-
. "maragu.dev/gomponents/html"
9
-
)
10
-
11
-
type RepoRefsContext struct {
12
-
BaseContext
13
-
RepoHeaderComponentContext
14
-
Branches []string
15
-
Tags []git.Tag
16
-
}
17
-
18
-
func RepoRefsTemplate(rrc RepoRefsContext) Node {
19
-
return base(rrc.BaseContext, []Node{
20
-
repoHeaderComponent(rrc.RepoHeaderComponentContext),
21
-
If(len(rrc.Branches) > 0, Group([]Node{
22
-
H3(Class("text-text text-lg mt-5"), Text("Branches")),
23
-
Div(Class("text-text grid grid-cols-4 sm:grid-cols-8"),
24
-
Map(rrc.Branches, func(branch string) Node {
25
-
return Group([]Node{
26
-
Div(Class("col-span-2 sm:col-span-1 font-bold"), Text(branch)),
27
-
Div(Class("col-span-2 sm:col-span-7"),
28
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/tree/%s/", rrc.RepoHeaderComponentContext.Name, branch)), Text("tree")),
29
-
Text(" "),
30
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/log/%s", rrc.RepoHeaderComponentContext.Name, branch)), Text("log")),
31
-
),
32
-
})
33
-
}),
34
-
),
35
-
})),
36
-
If(len(rrc.Tags) > 0, Group([]Node{
37
-
H3(Class("text-text text-lg mt-5"), Text("Tags")),
38
-
Div(Class("text-text grid grid-cols-8"),
39
-
Map(rrc.Tags, func(tag git.Tag) Node {
40
-
return Group([]Node{
41
-
Div(Class("col-span-1 font-bold"), Text(tag.Name)),
42
-
Div(Class("col-span-7"),
43
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/tree/%s/", rrc.RepoHeaderComponentContext.Name, tag.Name)), Text("tree")),
44
-
Text(" "),
45
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/log/%s", rrc.RepoHeaderComponentContext.Name, tag.Name)), Text("log")),
46
-
),
47
-
If(tag.Signature != "",
48
-
Details(Class("col-span-8 whitespace-pre"),
49
-
Summary(Class("cursor-pointer"), Text("Signature")),
50
-
Code(Text(tag.Signature)),
51
-
),
52
-
),
53
-
If(tag.Annotation != "",
54
-
Div(Class("col-span-8 mb-3"), Text(tag.Annotation)),
55
-
),
56
-
})
57
-
}),
58
-
),
59
-
})),
60
-
}...)
61
-
}
···
+41
internal/html/repo_refs.templ
+41
internal/html/repo_refs.templ
···
···
1
+
package html
2
+
3
+
import "fmt"
4
+
import "go.jolheiser.com/ugit/internal/git"
5
+
6
+
type RepoRefsContext struct {
7
+
BaseContext
8
+
RepoHeaderComponentContext
9
+
Branches []string
10
+
Tags []git.Tag
11
+
}
12
+
13
+
templ RepoRefs(rrc RepoRefsContext) {
14
+
@base(rrc.BaseContext) {
15
+
@repoHeaderComponent(rrc.RepoHeaderComponentContext)
16
+
if len(rrc.Branches) > 0 {
17
+
<h3 class="text-text text-lg mt-5">Branches</h3>
18
+
<div class="text-text grid grid-cols-4 sm:grid-cols-8">
19
+
for _, branch := range rrc.Branches {
20
+
<div class="col-span-2 sm:col-span-1 font-bold">{ branch }</div>
21
+
<div class="col-span-2 sm:col-span-7"><a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rrc.RepoHeaderComponentContext.Name, branch)) }>tree</a>{ " " }<a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/log/%s", rrc.RepoHeaderComponentContext.Name, branch)) }>log</a></div>
22
+
}
23
+
</div>
24
+
}
25
+
if len(rrc.Tags) > 0 {
26
+
<h3 class="text-text text-lg mt-5">Tags</h3>
27
+
<div class="text-text grid grid-cols-8">
28
+
for _, tag := range rrc.Tags {
29
+
<div class="col-span-1 font-bold">{ tag.Name }</div>
30
+
<div class="col-span-7"><a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rrc.RepoHeaderComponentContext.Name, tag.Name)) }>tree</a>{ " " }<a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/log/%s", rrc.RepoHeaderComponentContext.Name, tag.Name)) }>log</a></div>
31
+
if tag.Signature != "" {
32
+
<details class="col-span-8 whitespace-pre"><summary class="cursor-pointer">Signature</summary><code>{ tag.Signature }</code></details>
33
+
}
34
+
if tag.Annotation != "" {
35
+
<div class="col-span-8 mb-3">{ tag.Annotation }</div>
36
+
}
37
+
}
38
+
</div>
39
+
}
40
+
}
41
+
}
+254
internal/html/repo_refs_templ.go
+254
internal/html/repo_refs_templ.go
···
···
1
+
// Code generated by templ - DO NOT EDIT.
2
+
3
+
// templ: version: v0.3.924
4
+
package html
5
+
6
+
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
+
8
+
import "github.com/a-h/templ"
9
+
import templruntime "github.com/a-h/templ/runtime"
10
+
11
+
import "fmt"
12
+
import "go.jolheiser.com/ugit/internal/git"
13
+
14
+
type RepoRefsContext struct {
15
+
BaseContext
16
+
RepoHeaderComponentContext
17
+
Branches []string
18
+
Tags []git.Tag
19
+
}
20
+
21
+
func RepoRefs(rrc RepoRefsContext) templ.Component {
22
+
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
23
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
24
+
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
25
+
return templ_7745c5c3_CtxErr
26
+
}
27
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
28
+
if !templ_7745c5c3_IsBuffer {
29
+
defer func() {
30
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
31
+
if templ_7745c5c3_Err == nil {
32
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
33
+
}
34
+
}()
35
+
}
36
+
ctx = templ.InitializeContext(ctx)
37
+
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
38
+
if templ_7745c5c3_Var1 == nil {
39
+
templ_7745c5c3_Var1 = templ.NopComponent
40
+
}
41
+
ctx = templ.ClearChildren(ctx)
42
+
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
43
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
44
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
45
+
if !templ_7745c5c3_IsBuffer {
46
+
defer func() {
47
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
48
+
if templ_7745c5c3_Err == nil {
49
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
50
+
}
51
+
}()
52
+
}
53
+
ctx = templ.InitializeContext(ctx)
54
+
templ_7745c5c3_Err = repoHeaderComponent(rrc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer)
55
+
if templ_7745c5c3_Err != nil {
56
+
return templ_7745c5c3_Err
57
+
}
58
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ")
59
+
if templ_7745c5c3_Err != nil {
60
+
return templ_7745c5c3_Err
61
+
}
62
+
if len(rrc.Branches) > 0 {
63
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<h3 class=\"text-text text-lg mt-5\">Branches</h3><div class=\"text-text grid grid-cols-4 sm:grid-cols-8\">")
64
+
if templ_7745c5c3_Err != nil {
65
+
return templ_7745c5c3_Err
66
+
}
67
+
for _, branch := range rrc.Branches {
68
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<div class=\"col-span-2 sm:col-span-1 font-bold\">")
69
+
if templ_7745c5c3_Err != nil {
70
+
return templ_7745c5c3_Err
71
+
}
72
+
var templ_7745c5c3_Var3 string
73
+
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(branch)
74
+
if templ_7745c5c3_Err != nil {
75
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 20, Col: 61}
76
+
}
77
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
78
+
if templ_7745c5c3_Err != nil {
79
+
return templ_7745c5c3_Err
80
+
}
81
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</div><div class=\"col-span-2 sm:col-span-7\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
82
+
if templ_7745c5c3_Err != nil {
83
+
return templ_7745c5c3_Err
84
+
}
85
+
var templ_7745c5c3_Var4 templ.SafeURL
86
+
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rrc.RepoHeaderComponentContext.Name, branch)))
87
+
if templ_7745c5c3_Err != nil {
88
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 21, Col: 218}
89
+
}
90
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
91
+
if templ_7745c5c3_Err != nil {
92
+
return templ_7745c5c3_Err
93
+
}
94
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">tree</a>")
95
+
if templ_7745c5c3_Err != nil {
96
+
return templ_7745c5c3_Err
97
+
}
98
+
var templ_7745c5c3_Var5 string
99
+
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(" ")
100
+
if templ_7745c5c3_Err != nil {
101
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 21, Col: 234}
102
+
}
103
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
104
+
if templ_7745c5c3_Err != nil {
105
+
return templ_7745c5c3_Err
106
+
}
107
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
108
+
if templ_7745c5c3_Err != nil {
109
+
return templ_7745c5c3_Err
110
+
}
111
+
var templ_7745c5c3_Var6 templ.SafeURL
112
+
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/log/%s", rrc.RepoHeaderComponentContext.Name, branch)))
113
+
if templ_7745c5c3_Err != nil {
114
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 21, Col: 409}
115
+
}
116
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
117
+
if templ_7745c5c3_Err != nil {
118
+
return templ_7745c5c3_Err
119
+
}
120
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\">log</a></div>")
121
+
if templ_7745c5c3_Err != nil {
122
+
return templ_7745c5c3_Err
123
+
}
124
+
}
125
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div>")
126
+
if templ_7745c5c3_Err != nil {
127
+
return templ_7745c5c3_Err
128
+
}
129
+
}
130
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " ")
131
+
if templ_7745c5c3_Err != nil {
132
+
return templ_7745c5c3_Err
133
+
}
134
+
if len(rrc.Tags) > 0 {
135
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<h3 class=\"text-text text-lg mt-5\">Tags</h3><div class=\"text-text grid grid-cols-8\">")
136
+
if templ_7745c5c3_Err != nil {
137
+
return templ_7745c5c3_Err
138
+
}
139
+
for _, tag := range rrc.Tags {
140
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"col-span-1 font-bold\">")
141
+
if templ_7745c5c3_Err != nil {
142
+
return templ_7745c5c3_Err
143
+
}
144
+
var templ_7745c5c3_Var7 string
145
+
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(tag.Name)
146
+
if templ_7745c5c3_Err != nil {
147
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 29, Col: 49}
148
+
}
149
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
150
+
if templ_7745c5c3_Err != nil {
151
+
return templ_7745c5c3_Err
152
+
}
153
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div><div class=\"col-span-7\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
154
+
if templ_7745c5c3_Err != nil {
155
+
return templ_7745c5c3_Err
156
+
}
157
+
var templ_7745c5c3_Var8 templ.SafeURL
158
+
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rrc.RepoHeaderComponentContext.Name, tag.Name)))
159
+
if templ_7745c5c3_Err != nil {
160
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 30, Col: 206}
161
+
}
162
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
163
+
if templ_7745c5c3_Err != nil {
164
+
return templ_7745c5c3_Err
165
+
}
166
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\">tree</a>")
167
+
if templ_7745c5c3_Err != nil {
168
+
return templ_7745c5c3_Err
169
+
}
170
+
var templ_7745c5c3_Var9 string
171
+
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(" ")
172
+
if templ_7745c5c3_Err != nil {
173
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 30, Col: 222}
174
+
}
175
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
176
+
if templ_7745c5c3_Err != nil {
177
+
return templ_7745c5c3_Err
178
+
}
179
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
180
+
if templ_7745c5c3_Err != nil {
181
+
return templ_7745c5c3_Err
182
+
}
183
+
var templ_7745c5c3_Var10 templ.SafeURL
184
+
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/log/%s", rrc.RepoHeaderComponentContext.Name, tag.Name)))
185
+
if templ_7745c5c3_Err != nil {
186
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 30, Col: 399}
187
+
}
188
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
189
+
if templ_7745c5c3_Err != nil {
190
+
return templ_7745c5c3_Err
191
+
}
192
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\">log</a></div>")
193
+
if templ_7745c5c3_Err != nil {
194
+
return templ_7745c5c3_Err
195
+
}
196
+
if tag.Signature != "" {
197
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<details class=\"col-span-8 whitespace-pre\"><summary class=\"cursor-pointer\">Signature</summary><code>")
198
+
if templ_7745c5c3_Err != nil {
199
+
return templ_7745c5c3_Err
200
+
}
201
+
var templ_7745c5c3_Var11 string
202
+
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(tag.Signature)
203
+
if templ_7745c5c3_Err != nil {
204
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 32, Col: 121}
205
+
}
206
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
207
+
if templ_7745c5c3_Err != nil {
208
+
return templ_7745c5c3_Err
209
+
}
210
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</code></details>")
211
+
if templ_7745c5c3_Err != nil {
212
+
return templ_7745c5c3_Err
213
+
}
214
+
}
215
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, " ")
216
+
if templ_7745c5c3_Err != nil {
217
+
return templ_7745c5c3_Err
218
+
}
219
+
if tag.Annotation != "" {
220
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<div class=\"col-span-8 mb-3\">")
221
+
if templ_7745c5c3_Err != nil {
222
+
return templ_7745c5c3_Err
223
+
}
224
+
var templ_7745c5c3_Var12 string
225
+
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(tag.Annotation)
226
+
if templ_7745c5c3_Err != nil {
227
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 35, Col: 51}
228
+
}
229
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
230
+
if templ_7745c5c3_Err != nil {
231
+
return templ_7745c5c3_Err
232
+
}
233
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</div>")
234
+
if templ_7745c5c3_Err != nil {
235
+
return templ_7745c5c3_Err
236
+
}
237
+
}
238
+
}
239
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</div>")
240
+
if templ_7745c5c3_Err != nil {
241
+
return templ_7745c5c3_Err
242
+
}
243
+
}
244
+
return nil
245
+
})
246
+
templ_7745c5c3_Err = base(rrc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
247
+
if templ_7745c5c3_Err != nil {
248
+
return templ_7745c5c3_Err
249
+
}
250
+
return nil
251
+
})
252
+
}
253
+
254
+
var _ = templruntime.GeneratedTemplate
-78
internal/html/repo_search.go
-78
internal/html/repo_search.go
···
1
-
package html
2
-
3
-
import (
4
-
_ "embed"
5
-
"fmt"
6
-
7
-
"go.jolheiser.com/ugit/internal/git"
8
-
. "maragu.dev/gomponents"
9
-
. "maragu.dev/gomponents/html"
10
-
)
11
-
12
-
type SearchContext struct {
13
-
BaseContext
14
-
RepoHeaderComponentContext
15
-
Results []git.GrepResult
16
-
}
17
-
18
-
func (s SearchContext) DedupeResults() [][]git.GrepResult {
19
-
var (
20
-
results [][]git.GrepResult
21
-
currentFile string
22
-
)
23
-
var idx int
24
-
for _, result := range s.Results {
25
-
if result.File == currentFile {
26
-
results[idx-1] = append(results[idx-1], result)
27
-
continue
28
-
}
29
-
results = append(results, []git.GrepResult{result})
30
-
currentFile = result.File
31
-
idx++
32
-
}
33
-
34
-
return results
35
-
}
36
-
37
-
//go:embed repo_search.js
38
-
var repoSearchJS string
39
-
40
-
func repoSearchResult(repo, ref string, results []git.GrepResult) Node {
41
-
return Group([]Node{
42
-
Div(Class("text-text mt-5"),
43
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, results[0].File, results[0].Line)), Text(results[0].File)),
44
-
),
45
-
Div(Class("code"),
46
-
Raw(results[0].Content),
47
-
),
48
-
If(len(results) > 1,
49
-
Details(Class("text-text cursor-pointer"),
50
-
Summary(Textf("%d more", len(results[1:]))),
51
-
Map(results[1:], func(result git.GrepResult) Node {
52
-
return Group([]Node{
53
-
Div(Class("text-text mt-5 ml-5"),
54
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, result.File, result.Line)), Text(results[0].File)),
55
-
),
56
-
Div(Class("code ml-5"),
57
-
Raw(result.Content),
58
-
),
59
-
})
60
-
}),
61
-
),
62
-
),
63
-
})
64
-
}
65
-
66
-
func RepoSearchTemplate(sc SearchContext) Node {
67
-
dedupeResults := sc.DedupeResults()
68
-
return base(sc.BaseContext, []Node{
69
-
repoHeaderComponent(sc.RepoHeaderComponentContext),
70
-
Map(dedupeResults, func(results []git.GrepResult) Node {
71
-
return repoSearchResult(sc.RepoHeaderComponentContext.Name, sc.RepoHeaderComponentContext.Ref, results)
72
-
}),
73
-
If(len(dedupeResults) == 0,
74
-
P(Class("text-text mt-5 text-lg"), Text("No results")),
75
-
),
76
-
Script(Raw(repoSearchJS)),
77
-
}...)
78
-
}
···
-2
internal/html/repo_search.js
-2
internal/html/repo_search.js
+63
internal/html/repo_search.templ
+63
internal/html/repo_search.templ
···
···
1
+
package html
2
+
3
+
import "fmt"
4
+
import "go.jolheiser.com/ugit/internal/git"
5
+
6
+
type SearchContext struct {
7
+
BaseContext
8
+
RepoHeaderComponentContext
9
+
Results []git.GrepResult
10
+
}
11
+
12
+
func (s SearchContext) DedupeResults() [][]git.GrepResult {
13
+
var (
14
+
results [][]git.GrepResult
15
+
currentFile string
16
+
)
17
+
var idx int
18
+
for _, result := range s.Results {
19
+
if result.File == currentFile {
20
+
results[idx-1] = append(results[idx-1], result)
21
+
continue
22
+
}
23
+
results = append(results, []git.GrepResult{result})
24
+
currentFile = result.File
25
+
idx++
26
+
}
27
+
28
+
return results
29
+
}
30
+
31
+
templ RepoSearch(sc SearchContext) {
32
+
@base(sc.BaseContext) {
33
+
@repoHeaderComponent(sc.RepoHeaderComponentContext)
34
+
for _, results := range sc.DedupeResults() {
35
+
@repoSearchResult(sc.RepoHeaderComponentContext.Name, sc.RepoHeaderComponentContext.Ref, results)
36
+
}
37
+
if len(sc.DedupeResults()) == 0 {
38
+
<p class="text-text mt-5 text-lg">No results</p>
39
+
}
40
+
}
41
+
<script>
42
+
const search = new URLSearchParams(window.location.search).get("q");
43
+
if (search !== "") document.querySelector("#search").value = search;
44
+
</script>
45
+
}
46
+
47
+
templ repoSearchResult(repo, ref string, results []git.GrepResult) {
48
+
<div class="text-text mt-5"><a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, results[0].File, results[0].Line)) }>{ results[0].File }</a></div>
49
+
<div class="code">
50
+
@templ.Raw(results[0].Content)
51
+
</div>
52
+
if len(results) > 1 {
53
+
<details class="text-text cursor-pointer">
54
+
<summary>{ fmt.Sprintf("%d ", len(results[1:])) }more</summary>
55
+
for _, result := range results[1:] {
56
+
<div class="text-text mt-5 ml-5"><a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, result.File, result.Line)) }>{ results[0].File }</a></div>
57
+
<div class="code ml-5">
58
+
@templ.Raw(result.Content)
59
+
</div>
60
+
}
61
+
</details>
62
+
}
63
+
}
+232
internal/html/repo_search_templ.go
+232
internal/html/repo_search_templ.go
···
···
1
+
// Code generated by templ - DO NOT EDIT.
2
+
3
+
// templ: version: v0.3.924
4
+
package html
5
+
6
+
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
+
8
+
import "github.com/a-h/templ"
9
+
import templruntime "github.com/a-h/templ/runtime"
10
+
11
+
import "fmt"
12
+
import "go.jolheiser.com/ugit/internal/git"
13
+
14
+
type SearchContext struct {
15
+
BaseContext
16
+
RepoHeaderComponentContext
17
+
Results []git.GrepResult
18
+
}
19
+
20
+
func (s SearchContext) DedupeResults() [][]git.GrepResult {
21
+
var (
22
+
results [][]git.GrepResult
23
+
currentFile string
24
+
)
25
+
var idx int
26
+
for _, result := range s.Results {
27
+
if result.File == currentFile {
28
+
results[idx-1] = append(results[idx-1], result)
29
+
continue
30
+
}
31
+
results = append(results, []git.GrepResult{result})
32
+
currentFile = result.File
33
+
idx++
34
+
}
35
+
36
+
return results
37
+
}
38
+
39
+
func RepoSearch(sc SearchContext) templ.Component {
40
+
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
41
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
42
+
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
43
+
return templ_7745c5c3_CtxErr
44
+
}
45
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
46
+
if !templ_7745c5c3_IsBuffer {
47
+
defer func() {
48
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
49
+
if templ_7745c5c3_Err == nil {
50
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
51
+
}
52
+
}()
53
+
}
54
+
ctx = templ.InitializeContext(ctx)
55
+
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
56
+
if templ_7745c5c3_Var1 == nil {
57
+
templ_7745c5c3_Var1 = templ.NopComponent
58
+
}
59
+
ctx = templ.ClearChildren(ctx)
60
+
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
61
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
62
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
63
+
if !templ_7745c5c3_IsBuffer {
64
+
defer func() {
65
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
66
+
if templ_7745c5c3_Err == nil {
67
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
68
+
}
69
+
}()
70
+
}
71
+
ctx = templ.InitializeContext(ctx)
72
+
templ_7745c5c3_Err = repoHeaderComponent(sc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer)
73
+
if templ_7745c5c3_Err != nil {
74
+
return templ_7745c5c3_Err
75
+
}
76
+
for _, results := range sc.DedupeResults() {
77
+
templ_7745c5c3_Err = repoSearchResult(sc.RepoHeaderComponentContext.Name, sc.RepoHeaderComponentContext.Ref, results).Render(ctx, templ_7745c5c3_Buffer)
78
+
if templ_7745c5c3_Err != nil {
79
+
return templ_7745c5c3_Err
80
+
}
81
+
}
82
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ")
83
+
if templ_7745c5c3_Err != nil {
84
+
return templ_7745c5c3_Err
85
+
}
86
+
if len(sc.DedupeResults()) == 0 {
87
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<p class=\"text-text mt-5 text-lg\">No results</p>")
88
+
if templ_7745c5c3_Err != nil {
89
+
return templ_7745c5c3_Err
90
+
}
91
+
}
92
+
return nil
93
+
})
94
+
templ_7745c5c3_Err = base(sc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
95
+
if templ_7745c5c3_Err != nil {
96
+
return templ_7745c5c3_Err
97
+
}
98
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<script>\n\t\tconst search = new URLSearchParams(window.location.search).get(\"q\");\n\t\tif (search !== \"\") document.querySelector(\"#search\").value = search;\n\t</script>")
99
+
if templ_7745c5c3_Err != nil {
100
+
return templ_7745c5c3_Err
101
+
}
102
+
return nil
103
+
})
104
+
}
105
+
106
+
func repoSearchResult(repo, ref string, results []git.GrepResult) templ.Component {
107
+
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
108
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
109
+
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
110
+
return templ_7745c5c3_CtxErr
111
+
}
112
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
113
+
if !templ_7745c5c3_IsBuffer {
114
+
defer func() {
115
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
116
+
if templ_7745c5c3_Err == nil {
117
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
118
+
}
119
+
}()
120
+
}
121
+
ctx = templ.InitializeContext(ctx)
122
+
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
123
+
if templ_7745c5c3_Var3 == nil {
124
+
templ_7745c5c3_Var3 = templ.NopComponent
125
+
}
126
+
ctx = templ.ClearChildren(ctx)
127
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div class=\"text-text mt-5\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
128
+
if templ_7745c5c3_Err != nil {
129
+
return templ_7745c5c3_Err
130
+
}
131
+
var templ_7745c5c3_Var4 templ.SafeURL
132
+
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, results[0].File, results[0].Line)))
133
+
if templ_7745c5c3_Err != nil {
134
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 48, Col: 210}
135
+
}
136
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
137
+
if templ_7745c5c3_Err != nil {
138
+
return templ_7745c5c3_Err
139
+
}
140
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">")
141
+
if templ_7745c5c3_Err != nil {
142
+
return templ_7745c5c3_Err
143
+
}
144
+
var templ_7745c5c3_Var5 string
145
+
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(results[0].File)
146
+
if templ_7745c5c3_Err != nil {
147
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 48, Col: 230}
148
+
}
149
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
150
+
if templ_7745c5c3_Err != nil {
151
+
return templ_7745c5c3_Err
152
+
}
153
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</a></div><div class=\"code\">")
154
+
if templ_7745c5c3_Err != nil {
155
+
return templ_7745c5c3_Err
156
+
}
157
+
templ_7745c5c3_Err = templ.Raw(results[0].Content).Render(ctx, templ_7745c5c3_Buffer)
158
+
if templ_7745c5c3_Err != nil {
159
+
return templ_7745c5c3_Err
160
+
}
161
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div>")
162
+
if templ_7745c5c3_Err != nil {
163
+
return templ_7745c5c3_Err
164
+
}
165
+
if len(results) > 1 {
166
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<details class=\"text-text cursor-pointer\"><summary>")
167
+
if templ_7745c5c3_Err != nil {
168
+
return templ_7745c5c3_Err
169
+
}
170
+
var templ_7745c5c3_Var6 string
171
+
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d ", len(results[1:])))
172
+
if templ_7745c5c3_Err != nil {
173
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 54, Col: 50}
174
+
}
175
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
176
+
if templ_7745c5c3_Err != nil {
177
+
return templ_7745c5c3_Err
178
+
}
179
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "more</summary> ")
180
+
if templ_7745c5c3_Err != nil {
181
+
return templ_7745c5c3_Err
182
+
}
183
+
for _, result := range results[1:] {
184
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<div class=\"text-text mt-5 ml-5\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
185
+
if templ_7745c5c3_Err != nil {
186
+
return templ_7745c5c3_Err
187
+
}
188
+
var templ_7745c5c3_Var7 templ.SafeURL
189
+
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, result.File, result.Line)))
190
+
if templ_7745c5c3_Err != nil {
191
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 56, Col: 210}
192
+
}
193
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
194
+
if templ_7745c5c3_Err != nil {
195
+
return templ_7745c5c3_Err
196
+
}
197
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\">")
198
+
if templ_7745c5c3_Err != nil {
199
+
return templ_7745c5c3_Err
200
+
}
201
+
var templ_7745c5c3_Var8 string
202
+
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(results[0].File)
203
+
if templ_7745c5c3_Err != nil {
204
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 56, Col: 230}
205
+
}
206
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
207
+
if templ_7745c5c3_Err != nil {
208
+
return templ_7745c5c3_Err
209
+
}
210
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</a></div><div class=\"code ml-5\">")
211
+
if templ_7745c5c3_Err != nil {
212
+
return templ_7745c5c3_Err
213
+
}
214
+
templ_7745c5c3_Err = templ.Raw(result.Content).Render(ctx, templ_7745c5c3_Buffer)
215
+
if templ_7745c5c3_Err != nil {
216
+
return templ_7745c5c3_Err
217
+
}
218
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div>")
219
+
if templ_7745c5c3_Err != nil {
220
+
return templ_7745c5c3_Err
221
+
}
222
+
}
223
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</details>")
224
+
if templ_7745c5c3_Err != nil {
225
+
return templ_7745c5c3_Err
226
+
}
227
+
}
228
+
return nil
229
+
})
230
+
}
231
+
232
+
var _ = templruntime.GeneratedTemplate
+257
internal/html/repo_templ.go
+257
internal/html/repo_templ.go
···
···
1
+
// Code generated by templ - DO NOT EDIT.
2
+
3
+
// templ: version: v0.3.924
4
+
package html
5
+
6
+
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
+
8
+
import "github.com/a-h/templ"
9
+
import templruntime "github.com/a-h/templ/runtime"
10
+
11
+
import "fmt"
12
+
13
+
type RepoHeaderComponentContext struct {
14
+
Name string
15
+
Ref string
16
+
Description string
17
+
CloneURL string
18
+
Tags []string
19
+
}
20
+
21
+
func repoHeaderComponent(rhcc RepoHeaderComponentContext) templ.Component {
22
+
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
23
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
24
+
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
25
+
return templ_7745c5c3_CtxErr
26
+
}
27
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
28
+
if !templ_7745c5c3_IsBuffer {
29
+
defer func() {
30
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
31
+
if templ_7745c5c3_Err == nil {
32
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
33
+
}
34
+
}()
35
+
}
36
+
ctx = templ.InitializeContext(ctx)
37
+
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
38
+
if templ_7745c5c3_Var1 == nil {
39
+
templ_7745c5c3_Var1 = templ.NopComponent
40
+
}
41
+
ctx = templ.ClearChildren(ctx)
42
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"mb-1 text-text\"><a class=\"text-lg underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
43
+
if templ_7745c5c3_Err != nil {
44
+
return templ_7745c5c3_Err
45
+
}
46
+
var templ_7745c5c3_Var2 templ.SafeURL
47
+
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL("/" + rhcc.Name))
48
+
if templ_7745c5c3_Err != nil {
49
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 15, Col: 128}
50
+
}
51
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
52
+
if templ_7745c5c3_Err != nil {
53
+
return templ_7745c5c3_Err
54
+
}
55
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\">")
56
+
if templ_7745c5c3_Err != nil {
57
+
return templ_7745c5c3_Err
58
+
}
59
+
var templ_7745c5c3_Var3 string
60
+
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(rhcc.Name)
61
+
if templ_7745c5c3_Err != nil {
62
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 15, Col: 142}
63
+
}
64
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
65
+
if templ_7745c5c3_Err != nil {
66
+
return templ_7745c5c3_Err
67
+
}
68
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</a> ")
69
+
if templ_7745c5c3_Err != nil {
70
+
return templ_7745c5c3_Err
71
+
}
72
+
if rhcc.Ref != "" {
73
+
var templ_7745c5c3_Var4 string
74
+
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(" ")
75
+
if templ_7745c5c3_Err != nil {
76
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 17, Col: 8}
77
+
}
78
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
79
+
if templ_7745c5c3_Err != nil {
80
+
return templ_7745c5c3_Err
81
+
}
82
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " <a class=\"text-text/80 text-sm underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
83
+
if templ_7745c5c3_Err != nil {
84
+
return templ_7745c5c3_Err
85
+
}
86
+
var templ_7745c5c3_Var5 templ.SafeURL
87
+
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rhcc.Name, rhcc.Ref)))
88
+
if templ_7745c5c3_Err != nil {
89
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 18, Col: 175}
90
+
}
91
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
92
+
if templ_7745c5c3_Err != nil {
93
+
return templ_7745c5c3_Err
94
+
}
95
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">")
96
+
if templ_7745c5c3_Err != nil {
97
+
return templ_7745c5c3_Err
98
+
}
99
+
var templ_7745c5c3_Var6 string
100
+
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs("@" + rhcc.Ref)
101
+
if templ_7745c5c3_Err != nil {
102
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 18, Col: 194}
103
+
}
104
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
105
+
if templ_7745c5c3_Err != nil {
106
+
return templ_7745c5c3_Err
107
+
}
108
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</a> ")
109
+
if templ_7745c5c3_Err != nil {
110
+
return templ_7745c5c3_Err
111
+
}
112
+
}
113
+
var templ_7745c5c3_Var7 string
114
+
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(" - ")
115
+
if templ_7745c5c3_Err != nil {
116
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 20, Col: 9}
117
+
}
118
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
119
+
if templ_7745c5c3_Err != nil {
120
+
return templ_7745c5c3_Err
121
+
}
122
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, " <a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
123
+
if templ_7745c5c3_Err != nil {
124
+
return templ_7745c5c3_Err
125
+
}
126
+
var templ_7745c5c3_Var8 templ.SafeURL
127
+
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/refs", rhcc.Name)))
128
+
if templ_7745c5c3_Err != nil {
129
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 21, Col: 139}
130
+
}
131
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
132
+
if templ_7745c5c3_Err != nil {
133
+
return templ_7745c5c3_Err
134
+
}
135
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\">refs</a> ")
136
+
if templ_7745c5c3_Err != nil {
137
+
return templ_7745c5c3_Err
138
+
}
139
+
var templ_7745c5c3_Var9 string
140
+
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(" - ")
141
+
if templ_7745c5c3_Err != nil {
142
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 22, Col: 9}
143
+
}
144
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
145
+
if templ_7745c5c3_Err != nil {
146
+
return templ_7745c5c3_Err
147
+
}
148
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " <a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
149
+
if templ_7745c5c3_Err != nil {
150
+
return templ_7745c5c3_Err
151
+
}
152
+
var templ_7745c5c3_Var10 templ.SafeURL
153
+
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/log/%s", rhcc.Name, rhcc.Ref)))
154
+
if templ_7745c5c3_Err != nil {
155
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 23, Col: 151}
156
+
}
157
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
158
+
if templ_7745c5c3_Err != nil {
159
+
return templ_7745c5c3_Err
160
+
}
161
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\">log</a> ")
162
+
if templ_7745c5c3_Err != nil {
163
+
return templ_7745c5c3_Err
164
+
}
165
+
var templ_7745c5c3_Var11 string
166
+
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(" - ")
167
+
if templ_7745c5c3_Err != nil {
168
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 24, Col: 9}
169
+
}
170
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
171
+
if templ_7745c5c3_Err != nil {
172
+
return templ_7745c5c3_Err
173
+
}
174
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<form class=\"inline-block\" action=\"")
175
+
if templ_7745c5c3_Err != nil {
176
+
return templ_7745c5c3_Err
177
+
}
178
+
var templ_7745c5c3_Var12 templ.SafeURL
179
+
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/search", rhcc.Name)))
180
+
if templ_7745c5c3_Err != nil {
181
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 25, Col: 89}
182
+
}
183
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
184
+
if templ_7745c5c3_Err != nil {
185
+
return templ_7745c5c3_Err
186
+
}
187
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\" method=\"get\"><input class=\"rounded p-1 bg-mantle focus:border-lavender focus:outline-none focus:ring-0\" id=\"search\" type=\"text\" name=\"q\" placeholder=\"search\"></form>")
188
+
if templ_7745c5c3_Err != nil {
189
+
return templ_7745c5c3_Err
190
+
}
191
+
var templ_7745c5c3_Var13 string
192
+
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(" - ")
193
+
if templ_7745c5c3_Err != nil {
194
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 26, Col: 9}
195
+
}
196
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
197
+
if templ_7745c5c3_Err != nil {
198
+
return templ_7745c5c3_Err
199
+
}
200
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<pre class=\"text-text inline select-all bg-base dark:bg-base/50 p-1 rounded\">")
201
+
if templ_7745c5c3_Err != nil {
202
+
return templ_7745c5c3_Err
203
+
}
204
+
var templ_7745c5c3_Var14 string
205
+
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%s/%s.git", rhcc.CloneURL, rhcc.Name))
206
+
if templ_7745c5c3_Err != nil {
207
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 27, Col: 131}
208
+
}
209
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
210
+
if templ_7745c5c3_Err != nil {
211
+
return templ_7745c5c3_Err
212
+
}
213
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</pre></div><div class=\"text-subtext0 mb-1\">")
214
+
if templ_7745c5c3_Err != nil {
215
+
return templ_7745c5c3_Err
216
+
}
217
+
for _, tag := range rhcc.Tags {
218
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<span class=\"rounded border-rosewater border-solid border pb-0.5 px-1 mr-1 mb-1 inline-block\">")
219
+
if templ_7745c5c3_Err != nil {
220
+
return templ_7745c5c3_Err
221
+
}
222
+
var templ_7745c5c3_Var15 string
223
+
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(tag)
224
+
if templ_7745c5c3_Err != nil {
225
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 31, Col: 102}
226
+
}
227
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
228
+
if templ_7745c5c3_Err != nil {
229
+
return templ_7745c5c3_Err
230
+
}
231
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</span>")
232
+
if templ_7745c5c3_Err != nil {
233
+
return templ_7745c5c3_Err
234
+
}
235
+
}
236
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</div><div class=\"text-text/80 mb-1\">")
237
+
if templ_7745c5c3_Err != nil {
238
+
return templ_7745c5c3_Err
239
+
}
240
+
var templ_7745c5c3_Var16 string
241
+
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(rhcc.Description)
242
+
if templ_7745c5c3_Err != nil {
243
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 34, Col: 50}
244
+
}
245
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
246
+
if templ_7745c5c3_Err != nil {
247
+
return templ_7745c5c3_Err
248
+
}
249
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</div>")
250
+
if templ_7745c5c3_Err != nil {
251
+
return templ_7745c5c3_Err
252
+
}
253
+
return nil
254
+
})
255
+
}
256
+
257
+
var _ = templruntime.GeneratedTemplate
-61
internal/html/repo_tree.go
-61
internal/html/repo_tree.go
···
1
-
package html
2
-
3
-
import (
4
-
"fmt"
5
-
6
-
"go.jolheiser.com/ugit/internal/git"
7
-
. "maragu.dev/gomponents"
8
-
. "maragu.dev/gomponents/html"
9
-
)
10
-
11
-
type RepoTreeContext struct {
12
-
BaseContext
13
-
RepoHeaderComponentContext
14
-
RepoBreadcrumbComponentContext
15
-
RepoTreeComponentContext
16
-
ReadmeComponentContext
17
-
Description string
18
-
}
19
-
20
-
type RepoTreeComponentContext struct {
21
-
Repo string
22
-
Ref string
23
-
Tree []git.FileInfo
24
-
Back string
25
-
}
26
-
27
-
func slashDir(name string, isDir bool) string {
28
-
if isDir {
29
-
return name + "/"
30
-
}
31
-
return name
32
-
}
33
-
34
-
func repoTreeComponent(rtcc RepoTreeComponentContext) Node {
35
-
return Div(Class("grid grid-cols-3 sm:grid-cols-8 text-text py-5 rounded px-5 gap-x-3 gap-y-1 bg-base dark:bg-base/50"),
36
-
If(rtcc.Back != "", Group([]Node{
37
-
Div(Class("col-span-2")),
38
-
Div(Class("sm:col-span-6"),
39
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/tree/%s/%s", rtcc.Repo, rtcc.Ref, rtcc.Back)), Text("..")),
40
-
),
41
-
})),
42
-
Map(rtcc.Tree, func(fi git.FileInfo) Node {
43
-
return Group([]Node{
44
-
Div(Class("sm:col-span-1 break-keep"), Text(fi.Mode)),
45
-
Div(Class("sm:col-span-1 text-right"), Text(fi.Size)),
46
-
Div(Class("sm:col-span-6 overflow-hidden text-ellipsis"),
47
-
A(Class("underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href(fmt.Sprintf("/%s/tree/%s/%s", rtcc.Repo, rtcc.Ref, fi.Path)), Text(slashDir(fi.Name(), fi.IsDir))),
48
-
),
49
-
})
50
-
}),
51
-
)
52
-
}
53
-
54
-
func RepoTreeTemplate(rtc RepoTreeContext) Node {
55
-
return base(rtc.BaseContext, []Node{
56
-
repoHeaderComponent(rtc.RepoHeaderComponentContext),
57
-
repoBreadcrumbComponent(rtc.RepoBreadcrumbComponentContext),
58
-
repoTreeComponent(rtc.RepoTreeComponentContext),
59
-
readmeComponent(rtc.ReadmeComponentContext),
60
-
}...)
61
-
}
···
+51
internal/html/repo_tree.templ
+51
internal/html/repo_tree.templ
···
···
1
+
package html
2
+
3
+
import (
4
+
"fmt"
5
+
"go.jolheiser.com/ugit/internal/git"
6
+
)
7
+
8
+
type RepoTreeContext struct {
9
+
BaseContext
10
+
RepoHeaderComponentContext
11
+
RepoBreadcrumbComponentContext
12
+
RepoTreeComponentContext
13
+
ReadmeComponentContext
14
+
}
15
+
16
+
templ RepoTree(rtc RepoTreeContext) {
17
+
@base(rtc.BaseContext) {
18
+
@repoHeaderComponent(rtc.RepoHeaderComponentContext)
19
+
@repoBreadcrumbComponent(rtc.RepoBreadcrumbComponentContext)
20
+
@repoTreeComponent(rtc.RepoTreeComponentContext)
21
+
@readmeComponent(rtc.ReadmeComponentContext)
22
+
}
23
+
}
24
+
25
+
type RepoTreeComponentContext struct {
26
+
Repo string
27
+
Ref string
28
+
Tree []git.FileInfo
29
+
Back string
30
+
}
31
+
32
+
func slashDir(name string, isDir bool) string {
33
+
if isDir {
34
+
return name + "/"
35
+
}
36
+
return name
37
+
}
38
+
39
+
templ repoTreeComponent(rtcc RepoTreeComponentContext) {
40
+
<div class="grid grid-cols-3 sm:grid-cols-8 text-text py-5 rounded px-5 gap-x-3 gap-y-1 bg-base dark:bg-base/50">
41
+
if rtcc.Back != "" {
42
+
<div class="col-span-2"></div>
43
+
<div class="sm:col-span-6"><a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rtcc.Repo, rtcc.Ref, rtcc.Back)) }>..</a></div>
44
+
}
45
+
for _, fi := range rtcc.Tree {
46
+
<div class="sm:col-span-1 break-keep">{ fi.Mode }</div>
47
+
<div class="sm:col-span-1 text-right">{ fi.Size }</div>
48
+
<div class="sm:col-span-6 overflow-hidden text-ellipsis"><a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rtcc.Repo, rtcc.Ref, fi.Path)) }>{ slashDir(fi.Name(), fi.IsDir) }</a></div>
49
+
}
50
+
</div>
51
+
}
+219
internal/html/repo_tree_templ.go
+219
internal/html/repo_tree_templ.go
···
···
1
+
// Code generated by templ - DO NOT EDIT.
2
+
3
+
// templ: version: v0.3.924
4
+
package html
5
+
6
+
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
+
8
+
import "github.com/a-h/templ"
9
+
import templruntime "github.com/a-h/templ/runtime"
10
+
11
+
import (
12
+
"fmt"
13
+
"go.jolheiser.com/ugit/internal/git"
14
+
)
15
+
16
+
type RepoTreeContext struct {
17
+
BaseContext
18
+
RepoHeaderComponentContext
19
+
RepoBreadcrumbComponentContext
20
+
RepoTreeComponentContext
21
+
ReadmeComponentContext
22
+
}
23
+
24
+
func RepoTree(rtc RepoTreeContext) templ.Component {
25
+
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
26
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
27
+
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
28
+
return templ_7745c5c3_CtxErr
29
+
}
30
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
31
+
if !templ_7745c5c3_IsBuffer {
32
+
defer func() {
33
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
34
+
if templ_7745c5c3_Err == nil {
35
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
36
+
}
37
+
}()
38
+
}
39
+
ctx = templ.InitializeContext(ctx)
40
+
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
41
+
if templ_7745c5c3_Var1 == nil {
42
+
templ_7745c5c3_Var1 = templ.NopComponent
43
+
}
44
+
ctx = templ.ClearChildren(ctx)
45
+
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
46
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
47
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
48
+
if !templ_7745c5c3_IsBuffer {
49
+
defer func() {
50
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
51
+
if templ_7745c5c3_Err == nil {
52
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
53
+
}
54
+
}()
55
+
}
56
+
ctx = templ.InitializeContext(ctx)
57
+
templ_7745c5c3_Err = repoHeaderComponent(rtc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer)
58
+
if templ_7745c5c3_Err != nil {
59
+
return templ_7745c5c3_Err
60
+
}
61
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ")
62
+
if templ_7745c5c3_Err != nil {
63
+
return templ_7745c5c3_Err
64
+
}
65
+
templ_7745c5c3_Err = repoBreadcrumbComponent(rtc.RepoBreadcrumbComponentContext).Render(ctx, templ_7745c5c3_Buffer)
66
+
if templ_7745c5c3_Err != nil {
67
+
return templ_7745c5c3_Err
68
+
}
69
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " ")
70
+
if templ_7745c5c3_Err != nil {
71
+
return templ_7745c5c3_Err
72
+
}
73
+
templ_7745c5c3_Err = repoTreeComponent(rtc.RepoTreeComponentContext).Render(ctx, templ_7745c5c3_Buffer)
74
+
if templ_7745c5c3_Err != nil {
75
+
return templ_7745c5c3_Err
76
+
}
77
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, " ")
78
+
if templ_7745c5c3_Err != nil {
79
+
return templ_7745c5c3_Err
80
+
}
81
+
templ_7745c5c3_Err = readmeComponent(rtc.ReadmeComponentContext).Render(ctx, templ_7745c5c3_Buffer)
82
+
if templ_7745c5c3_Err != nil {
83
+
return templ_7745c5c3_Err
84
+
}
85
+
return nil
86
+
})
87
+
templ_7745c5c3_Err = base(rtc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
88
+
if templ_7745c5c3_Err != nil {
89
+
return templ_7745c5c3_Err
90
+
}
91
+
return nil
92
+
})
93
+
}
94
+
95
+
type RepoTreeComponentContext struct {
96
+
Repo string
97
+
Ref string
98
+
Tree []git.FileInfo
99
+
Back string
100
+
}
101
+
102
+
func slashDir(name string, isDir bool) string {
103
+
if isDir {
104
+
return name + "/"
105
+
}
106
+
return name
107
+
}
108
+
109
+
func repoTreeComponent(rtcc RepoTreeComponentContext) templ.Component {
110
+
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
111
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
112
+
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
113
+
return templ_7745c5c3_CtxErr
114
+
}
115
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
116
+
if !templ_7745c5c3_IsBuffer {
117
+
defer func() {
118
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
119
+
if templ_7745c5c3_Err == nil {
120
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
121
+
}
122
+
}()
123
+
}
124
+
ctx = templ.InitializeContext(ctx)
125
+
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
126
+
if templ_7745c5c3_Var3 == nil {
127
+
templ_7745c5c3_Var3 = templ.NopComponent
128
+
}
129
+
ctx = templ.ClearChildren(ctx)
130
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div class=\"grid grid-cols-3 sm:grid-cols-8 text-text py-5 rounded px-5 gap-x-3 gap-y-1 bg-base dark:bg-base/50\">")
131
+
if templ_7745c5c3_Err != nil {
132
+
return templ_7745c5c3_Err
133
+
}
134
+
if rtcc.Back != "" {
135
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<div class=\"col-span-2\"></div><div class=\"sm:col-span-6\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
136
+
if templ_7745c5c3_Err != nil {
137
+
return templ_7745c5c3_Err
138
+
}
139
+
var templ_7745c5c3_Var4 templ.SafeURL
140
+
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rtcc.Repo, rtcc.Ref, rtcc.Back)))
141
+
if templ_7745c5c3_Err != nil {
142
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_tree.templ`, Line: 43, Col: 194}
143
+
}
144
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
145
+
if templ_7745c5c3_Err != nil {
146
+
return templ_7745c5c3_Err
147
+
}
148
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">..</a></div>")
149
+
if templ_7745c5c3_Err != nil {
150
+
return templ_7745c5c3_Err
151
+
}
152
+
}
153
+
for _, fi := range rtcc.Tree {
154
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<div class=\"sm:col-span-1 break-keep\">")
155
+
if templ_7745c5c3_Err != nil {
156
+
return templ_7745c5c3_Err
157
+
}
158
+
var templ_7745c5c3_Var5 string
159
+
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(fi.Mode)
160
+
if templ_7745c5c3_Err != nil {
161
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_tree.templ`, Line: 46, Col: 50}
162
+
}
163
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
164
+
if templ_7745c5c3_Err != nil {
165
+
return templ_7745c5c3_Err
166
+
}
167
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div><div class=\"sm:col-span-1 text-right\">")
168
+
if templ_7745c5c3_Err != nil {
169
+
return templ_7745c5c3_Err
170
+
}
171
+
var templ_7745c5c3_Var6 string
172
+
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fi.Size)
173
+
if templ_7745c5c3_Err != nil {
174
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_tree.templ`, Line: 47, Col: 50}
175
+
}
176
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
177
+
if templ_7745c5c3_Err != nil {
178
+
return templ_7745c5c3_Err
179
+
}
180
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div><div class=\"sm:col-span-6 overflow-hidden text-ellipsis\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
181
+
if templ_7745c5c3_Err != nil {
182
+
return templ_7745c5c3_Err
183
+
}
184
+
var templ_7745c5c3_Var7 templ.SafeURL
185
+
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rtcc.Repo, rtcc.Ref, fi.Path)))
186
+
if templ_7745c5c3_Err != nil {
187
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_tree.templ`, Line: 48, Col: 222}
188
+
}
189
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
190
+
if templ_7745c5c3_Err != nil {
191
+
return templ_7745c5c3_Err
192
+
}
193
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\">")
194
+
if templ_7745c5c3_Err != nil {
195
+
return templ_7745c5c3_Err
196
+
}
197
+
var templ_7745c5c3_Var8 string
198
+
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(slashDir(fi.Name(), fi.IsDir))
199
+
if templ_7745c5c3_Err != nil {
200
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_tree.templ`, Line: 48, Col: 256}
201
+
}
202
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
203
+
if templ_7745c5c3_Err != nil {
204
+
return templ_7745c5c3_Err
205
+
}
206
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</a></div>")
207
+
if templ_7745c5c3_Err != nil {
208
+
return templ_7745c5c3_Err
209
+
}
210
+
}
211
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div>")
212
+
if templ_7745c5c3_Err != nil {
213
+
return templ_7745c5c3_Err
214
+
}
215
+
return nil
216
+
})
217
+
}
218
+
219
+
var _ = templruntime.GeneratedTemplate
+1
-1
internal/html/tailwind.go
+1
-1
internal/html/tailwind.go
···
5
6
func TailwindHandler(w http.ResponseWriter, r *http.Request) {
7
w.Header().Set("Content-Type", "text/css")
8
-
w.Write([]byte("/*! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:\"\"}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}.latte{--ctp-rosewater:220,138,120;--ctp-flamingo:221,120,120;--ctp-pink:234,118,203;--ctp-mauve:136,57,239;--ctp-red:210,15,57;--ctp-maroon:230,69,83;--ctp-peach:254,100,11;--ctp-yellow:223,142,29;--ctp-green:64,160,43;--ctp-teal:23,146,153;--ctp-sky:4,165,229;--ctp-sapphire:32,159,181;--ctp-blue:30,102,245;--ctp-lavender:114,135,253;--ctp-text:76,79,105;--ctp-subtext1:92,95,119;--ctp-subtext0:108,111,133;--ctp-overlay2:124,127,147;--ctp-overlay1:140,143,161;--ctp-overlay0:156,160,176;--ctp-surface2:172,176,190;--ctp-surface1:188,192,204;--ctp-surface0:204,208,218;--ctp-base:239,241,245;--ctp-mantle:230,233,239;--ctp-crust:220,224,232}.mocha{--ctp-rosewater:245,224,220;--ctp-flamingo:242,205,205;--ctp-pink:245,194,231;--ctp-mauve:203,166,247;--ctp-red:243,139,168;--ctp-maroon:235,160,172;--ctp-peach:250,179,135;--ctp-yellow:249,226,175;--ctp-green:166,227,161;--ctp-teal:148,226,213;--ctp-sky:137,220,235;--ctp-sapphire:116,199,236;--ctp-blue:137,180,250;--ctp-lavender:180,190,254;--ctp-text:205,214,244;--ctp-subtext1:186,194,222;--ctp-subtext0:166,173,200;--ctp-overlay2:147,153,178;--ctp-overlay1:127,132,156;--ctp-overlay0:108,112,134;--ctp-surface2:88,91,112;--ctp-surface1:69,71,90;--ctp-surface0:49,50,68;--ctp-base:30,30,46;--ctp-mantle:24,24,37;--ctp-crust:17,17,27}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.absolute{position:absolute}.relative{position:relative}.right-0{right:0}.top-0{top:0}.col-span-1{grid-column:span 1/span 1}.col-span-2{grid-column:span 2/span 2}.col-span-7{grid-column:span 7/span 7}.col-span-8{grid-column:span 8/span 8}.mx-5{margin-left:1.25rem;margin-right:1.25rem}.my-10{margin-top:2.5rem;margin-bottom:2.5rem}.mb-1{margin-bottom:.25rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-5{margin-left:1.25rem}.mr-1{margin-right:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-5{margin-top:1.25rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.grid{display:grid}.h-5{height:1.25rem}.w-5{width:1.25rem}.max-w-7xl{max-width:80rem}.cursor-pointer{cursor:pointer}.select-all{-webkit-user-select:all;-moz-user-select:all;user-select:all}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-8{grid-template-columns:repeat(8,minmax(0,1fr))}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-y-1{row-gap:.25rem}.overflow-hidden{overflow:hidden}.text-ellipsis{text-overflow:ellipsis}.whitespace-pre{white-space:pre}.break-keep{word-break:keep-all}.rounded{border-radius:.25rem}.border{border-width:1px}.border-solid{border-style:solid}.border-rosewater{--tw-border-opacity:1;border-color:rgba(var(--ctp-rosewater),var(--tw-border-opacity))}.bg-base{--tw-bg-opacity:1;background-color:rgba(var(--ctp-base),var(--tw-bg-opacity))}.bg-base\\/50{background-color:rgba(var(--ctp-base),.5)}.bg-mantle{--tw-bg-opacity:1;background-color:rgba(var(--ctp-mantle),var(--tw-bg-opacity))}.stroke-mauve{stroke:rgb(var(--ctp-mauve))}.p-1{padding:.25rem}.p-3{padding:.75rem}.p-5{padding:1.25rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pb-0{padding-bottom:0}.pb-0\\.5{padding-bottom:.125rem}.text-right{text-align:right}.align-middle{vertical-align:middle}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-bold{font-weight:700}.text-blue{--tw-text-opacity:1;color:rgba(var(--ctp-blue),var(--tw-text-opacity))}.text-mauve{--tw-text-opacity:1;color:rgba(var(--ctp-mauve),var(--tw-text-opacity))}.text-subtext0{--tw-text-opacity:1;color:rgba(var(--ctp-subtext0),var(--tw-text-opacity))}.text-subtext1{--tw-text-opacity:1;color:rgba(var(--ctp-subtext1),var(--tw-text-opacity))}.text-text{--tw-text-opacity:1;color:rgba(var(--ctp-text),var(--tw-text-opacity))}.text-text\\/80{color:rgba(var(--ctp-text),.8)}.underline{text-decoration-line:underline}.decoration-blue\\/50{text-decoration-color:rgba(var(--ctp-blue),.5)}.decoration-mauve\\/50{text-decoration-color:rgba(var(--ctp-mauve),.5)}.decoration-text\\/50{text-decoration-color:rgba(var(--ctp-text),.5)}.decoration-dashed{text-decoration-style:dashed}.markdown *{all:revert-layer;color:rgb(var(--ctp-text))}.markdown code,.markdown pre{background-color:rgb(var(--ctp-base))}.markdown a{color:rgb(var(--ctp-blue));text-decoration-line:underline;text-decoration-style:dashed}.markdown a:hover{text-decoration-style:solid}.markdown .chroma{border-radius:.25rem;padding:.75rem}.chroma *{background-color:rgb(var(--ctp-base))!important}.chroma table{border-spacing:5px 0!important}.chroma .lnt{color:rgb(var(--ctp-subtext1))!important}.chroma .lnt:focus,.chroma .lnt:target{color:rgb(var(--ctp-subtext0))!important}.chroma .line.active,.chroma .line.active *{background:rgb(var(--ctp-surface0))!important}.code>.chroma{overflow:scroll;border-radius:.25rem;padding:.75rem;font-size:.875rem;line-height:1.25rem}.bg,.chroma{color:#4c4f69;background-color:#eff1f5}.chroma .lntd:last-child{width:100%}.chroma .ln:target,.chroma .lnt:target{color:#4c4f69;background-color:#bcc0cc}.chroma .err{color:#d20f39}.chroma .lnlinks{outline:none;text-decoration:none;color:inherit}.chroma .lntd{vertical-align:top;padding:0;margin:0;border:0}.chroma .lntable{border-spacing:0;padding:0;margin:0;border:0}.chroma .hl{background-color:#bcc0cc}.chroma .ln,.chroma .lnt{white-space:pre;-webkit-user-select:none;-moz-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#8c8fa1}.chroma .line{display:flex}.chroma .k{color:#8839ef}.chroma .kc{color:#fe640b}.chroma .kd{color:#d20f39}.chroma .kn{color:#179299}.chroma .kp,.chroma .kr{color:#8839ef}.chroma .kt{color:#d20f39}.chroma .na{color:#1e66f5}.chroma .bp,.chroma .nb{color:#04a5e5}.chroma .nc,.chroma .no{color:#df8e1d}.chroma .nd{color:#1e66f5;font-weight:700}.chroma .ni{color:#179299}.chroma .ne{color:#fe640b}.chroma .fm,.chroma .nf{color:#1e66f5}.chroma .nl{color:#04a5e5}.chroma .nn,.chroma .py{color:#fe640b}.chroma .nt{color:#8839ef}.chroma .nv,.chroma .vc,.chroma .vg,.chroma .vi,.chroma .vm{color:#dc8a78}.chroma .s{color:#40a02b}.chroma .sa{color:#d20f39}.chroma .sb,.chroma .sc{color:#40a02b}.chroma .dl{color:#1e66f5}.chroma .sd{color:#9ca0b0}.chroma .s2{color:#40a02b}.chroma .se{color:#1e66f5}.chroma .sh{color:#9ca0b0}.chroma .si,.chroma .sx{color:#40a02b}.chroma .sr{color:#179299}.chroma .s1,.chroma .ss{color:#40a02b}.chroma .il,.chroma .m,.chroma .mb,.chroma .mf,.chroma .mh,.chroma .mi,.chroma .mo{color:#fe640b}.chroma .o,.chroma .ow{color:#04a5e5;font-weight:700}.chroma .c,.chroma .c1,.chroma .ch,.chroma .cm,.chroma .cp,.chroma .cpf,.chroma .cs{color:#9ca0b0;font-style:italic}.chroma .cpf{font-weight:700}.chroma .gd{color:#d20f39;background-color:#ccd0da}.chroma .ge{font-style:italic}.chroma .gr{color:#d20f39}.chroma .gh{color:#fe640b;font-weight:700}.chroma .gi{color:#40a02b;background-color:#ccd0da}.chroma .gs,.chroma .gu{font-weight:700}.chroma .gu{color:#fe640b}.chroma .gt{color:#d20f39}.chroma .gl{text-decoration:underline}@media (prefers-color-scheme:dark){.bg,.chroma{color:#cdd6f4;background-color:#1e1e2e}.chroma .lntd:last-child{width:100%}.chroma .ln:target,.chroma .lnt:target{color:#cdd6f4;background-color:#45475a}.chroma .err{color:#f38ba8}.chroma .lnlinks{outline:none;text-decoration:none;color:inherit}.chroma .lntd{vertical-align:top;padding:0;margin:0;border:0}.chroma .lntable{border-spacing:0;padding:0;margin:0;border:0}.chroma .hl{background-color:#45475a}.chroma .ln,.chroma .lnt{white-space:pre;-webkit-user-select:none;-moz-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#7f849c}.chroma .line{display:flex}.chroma .k{color:#cba6f7}.chroma .kc{color:#fab387}.chroma .kd{color:#f38ba8}.chroma .kn{color:#94e2d5}.chroma .kp,.chroma .kr{color:#cba6f7}.chroma .kt{color:#f38ba8}.chroma .na{color:#89b4fa}.chroma .bp,.chroma .nb{color:#89dceb}.chroma .nc,.chroma .no{color:#f9e2af}.chroma .nd{color:#89b4fa;font-weight:700}.chroma .ni{color:#94e2d5}.chroma .ne{color:#fab387}.chroma .fm,.chroma .nf{color:#89b4fa}.chroma .nl{color:#89dceb}.chroma .nn,.chroma .py{color:#fab387}.chroma .nt{color:#cba6f7}.chroma .nv,.chroma .vc,.chroma .vg,.chroma .vi,.chroma .vm{color:#f5e0dc}.chroma .s{color:#a6e3a1}.chroma .sa{color:#f38ba8}.chroma .sb,.chroma .sc{color:#a6e3a1}.chroma .dl{color:#89b4fa}.chroma .sd{color:#6c7086}.chroma .s2{color:#a6e3a1}.chroma .se{color:#89b4fa}.chroma .sh{color:#6c7086}.chroma .si,.chroma .sx{color:#a6e3a1}.chroma .sr{color:#94e2d5}.chroma .s1,.chroma .ss{color:#a6e3a1}.chroma .il,.chroma .m,.chroma .mb,.chroma .mf,.chroma .mh,.chroma .mi,.chroma .mo{color:#fab387}.chroma .o,.chroma .ow{color:#89dceb;font-weight:700}.chroma .c,.chroma .c1,.chroma .ch,.chroma .cm,.chroma .cp,.chroma .cpf,.chroma .cs{color:#6c7086;font-style:italic}.chroma .cpf{font-weight:700}.chroma .gd{color:#f38ba8;background-color:#313244}.chroma .ge{font-style:italic}.chroma .gr{color:#f38ba8}.chroma .gh{color:#fab387;font-weight:700}.chroma .gi{color:#a6e3a1;background-color:#313244}.chroma .gs,.chroma .gu{font-weight:700}.chroma .gu{color:#fab387}.chroma .gt{color:#f38ba8}.chroma .gl{text-decoration:underline}.dark\\:mocha{--ctp-rosewater:245,224,220;--ctp-flamingo:242,205,205;--ctp-pink:245,194,231;--ctp-mauve:203,166,247;--ctp-red:243,139,168;--ctp-maroon:235,160,172;--ctp-peach:250,179,135;--ctp-yellow:249,226,175;--ctp-green:166,227,161;--ctp-teal:148,226,213;--ctp-sky:137,220,235;--ctp-sapphire:116,199,236;--ctp-blue:137,180,250;--ctp-lavender:180,190,254;--ctp-text:205,214,244;--ctp-subtext1:186,194,222;--ctp-subtext0:166,173,200;--ctp-overlay2:147,153,178;--ctp-overlay1:127,132,156;--ctp-overlay0:108,112,134;--ctp-surface2:88,91,112;--ctp-surface1:69,71,90;--ctp-surface0:49,50,68;--ctp-base:30,30,46;--ctp-mantle:24,24,37;--ctp-crust:17,17,27}}.hover\\:bg-surface0:hover{--tw-bg-opacity:1;background-color:rgba(var(--ctp-surface0),var(--tw-bg-opacity))}.hover\\:decoration-solid:hover{text-decoration-style:solid}.focus\\:border-lavender:focus{--tw-border-opacity:1;border-color:rgba(var(--ctp-lavender),var(--tw-border-opacity))}.focus\\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}.focus\\:ring-0:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}@media (prefers-color-scheme:dark){.dark\\:bg-base\\/50{background-color:rgba(var(--ctp-base),.5)}.dark\\:bg-base\\/95{background-color:rgba(var(--ctp-base),.95)}.dark\\:text-lavender{--tw-text-opacity:1;color:rgba(var(--ctp-lavender),var(--tw-text-opacity))}.dark\\:decoration-lavender\\/50{text-decoration-color:rgba(var(--ctp-lavender),.5)}}@media (min-width:640px){.sm\\:col-span-1{grid-column:span 1/span 1}.sm\\:col-span-2{grid-column:span 2/span 2}.sm\\:col-span-3{grid-column:span 3/span 3}.sm\\:col-span-5{grid-column:span 5/span 5}.sm\\:col-span-6{grid-column:span 6/span 6}.sm\\:col-span-7{grid-column:span 7/span 7}.sm\\:mx-auto{margin-left:auto;margin-right:auto}.sm\\:mb-0{margin-bottom:0}.sm\\:grid-cols-10{grid-template-columns:repeat(10,minmax(0,1fr))}.sm\\:grid-cols-8{grid-template-columns:repeat(8,minmax(0,1fr))}}"))
9
}
···
5
6
func TailwindHandler(w http.ResponseWriter, r *http.Request) {
7
w.Header().Set("Content-Type", "text/css")
8
+
w.Write([]byte("/*! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:\"\"}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}.latte{--ctp-rosewater:220,138,120;--ctp-flamingo:221,120,120;--ctp-pink:234,118,203;--ctp-mauve:136,57,239;--ctp-red:210,15,57;--ctp-maroon:230,69,83;--ctp-peach:254,100,11;--ctp-yellow:223,142,29;--ctp-green:64,160,43;--ctp-teal:23,146,153;--ctp-sky:4,165,229;--ctp-sapphire:32,159,181;--ctp-blue:30,102,245;--ctp-lavender:114,135,253;--ctp-text:76,79,105;--ctp-subtext1:92,95,119;--ctp-subtext0:108,111,133;--ctp-overlay2:124,127,147;--ctp-overlay1:140,143,161;--ctp-overlay0:156,160,176;--ctp-surface2:172,176,190;--ctp-surface1:188,192,204;--ctp-surface0:204,208,218;--ctp-base:239,241,245;--ctp-mantle:230,233,239;--ctp-crust:220,224,232}.mocha{--ctp-rosewater:245,224,220;--ctp-flamingo:242,205,205;--ctp-pink:245,194,231;--ctp-mauve:203,166,247;--ctp-red:243,139,168;--ctp-maroon:235,160,172;--ctp-peach:250,179,135;--ctp-yellow:249,226,175;--ctp-green:166,227,161;--ctp-teal:148,226,213;--ctp-sky:137,220,235;--ctp-sapphire:116,199,236;--ctp-blue:137,180,250;--ctp-lavender:180,190,254;--ctp-text:205,214,244;--ctp-subtext1:186,194,222;--ctp-subtext0:166,173,200;--ctp-overlay2:147,153,178;--ctp-overlay1:127,132,156;--ctp-overlay0:108,112,134;--ctp-surface2:88,91,112;--ctp-surface1:69,71,90;--ctp-surface0:49,50,68;--ctp-base:30,30,46;--ctp-mantle:24,24,37;--ctp-crust:17,17,27}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.absolute{position:absolute}.relative{position:relative}.right-0{right:0}.start-1{inset-inline-start:.25rem}.top-0{top:0}.col-span-1{grid-column:span 1/span 1}.col-span-2{grid-column:span 2/span 2}.col-span-7{grid-column:span 7/span 7}.col-span-8{grid-column:span 8/span 8}.mx-5{margin-left:1.25rem;margin-right:1.25rem}.my-10{margin-top:2.5rem;margin-bottom:2.5rem}.mb-1{margin-bottom:.25rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-5{margin-left:1.25rem}.mr-1{margin-right:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-5{margin-top:1.25rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.grid{display:grid}.hidden{display:none}.h-5{height:1.25rem}.w-5{width:1.25rem}.max-w-7xl{max-width:80rem}.cursor-pointer{cursor:pointer}.select-all{-webkit-user-select:all;-moz-user-select:all;user-select:all}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-8{grid-template-columns:repeat(8,minmax(0,1fr))}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-y-1{row-gap:.25rem}.overflow-hidden{overflow:hidden}.text-ellipsis{text-overflow:ellipsis}.whitespace-pre{white-space:pre}.break-keep{word-break:keep-all}.rounded{border-radius:.25rem}.border{border-width:1px}.border-solid{border-style:solid}.border-rosewater{--tw-border-opacity:1;border-color:rgba(var(--ctp-rosewater),var(--tw-border-opacity))}.bg-base{--tw-bg-opacity:1;background-color:rgba(var(--ctp-base),var(--tw-bg-opacity))}.bg-base\\/50{background-color:rgba(var(--ctp-base),.5)}.bg-mantle{--tw-bg-opacity:1;background-color:rgba(var(--ctp-mantle),var(--tw-bg-opacity))}.stroke-mauve{stroke:rgb(var(--ctp-mauve))}.p-1{padding:.25rem}.p-3{padding:.75rem}.p-5{padding:1.25rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pb-0{padding-bottom:0}.pb-0\\.5{padding-bottom:.125rem}.text-right{text-align:right}.align-middle{vertical-align:middle}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-bold{font-weight:700}.text-blue{--tw-text-opacity:1;color:rgba(var(--ctp-blue),var(--tw-text-opacity))}.text-mauve{--tw-text-opacity:1;color:rgba(var(--ctp-mauve),var(--tw-text-opacity))}.text-subtext0{--tw-text-opacity:1;color:rgba(var(--ctp-subtext0),var(--tw-text-opacity))}.text-subtext1{--tw-text-opacity:1;color:rgba(var(--ctp-subtext1),var(--tw-text-opacity))}.text-text{--tw-text-opacity:1;color:rgba(var(--ctp-text),var(--tw-text-opacity))}.text-text\\/80{color:rgba(var(--ctp-text),.8)}.underline{text-decoration-line:underline}.decoration-blue\\/50{text-decoration-color:rgba(var(--ctp-blue),.5)}.decoration-mauve\\/50{text-decoration-color:rgba(var(--ctp-mauve),.5)}.decoration-text\\/50{text-decoration-color:rgba(var(--ctp-text),.5)}.decoration-dashed{text-decoration-style:dashed}.markdown *{all:revert-layer;color:rgb(var(--ctp-text))}.markdown code,.markdown pre{background-color:rgb(var(--ctp-base))}.markdown a{color:rgb(var(--ctp-blue));text-decoration-line:underline;text-decoration-style:dashed}.markdown a:hover{text-decoration-style:solid}.markdown .chroma{border-radius:.25rem;padding:.75rem}.chroma *{background-color:rgb(var(--ctp-base))!important}.chroma table{border-spacing:5px 0!important}.chroma .lnt{color:rgb(var(--ctp-subtext1))!important}.chroma .lnt:focus,.chroma .lnt:target{color:rgb(var(--ctp-subtext0))!important}.chroma .line.active,.chroma .line.active *{background:rgb(var(--ctp-surface0))!important}.code>.chroma{overflow:scroll;border-radius:.25rem;padding:.75rem;font-size:.875rem;line-height:1.25rem}.bg,.chroma{color:#4c4f69;background-color:#eff1f5}.chroma .lntd:last-child{width:100%}.chroma .ln:target,.chroma .lnt:target{color:#4c4f69;background-color:#bcc0cc}.chroma .err{color:#d20f39}.chroma .lnlinks{outline:none;text-decoration:none;color:inherit}.chroma .lntd{vertical-align:top;padding:0;margin:0;border:0}.chroma .lntable{border-spacing:0;padding:0;margin:0;border:0}.chroma .hl{background-color:#bcc0cc}.chroma .ln,.chroma .lnt{white-space:pre;-webkit-user-select:none;-moz-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#8c8fa1}.chroma .line{display:flex}.chroma .k{color:#8839ef}.chroma .kc{color:#fe640b}.chroma .kd{color:#d20f39}.chroma .kn{color:#179299}.chroma .kp,.chroma .kr{color:#8839ef}.chroma .kt{color:#d20f39}.chroma .na{color:#1e66f5}.chroma .bp,.chroma .nb{color:#04a5e5}.chroma .nc,.chroma .no{color:#df8e1d}.chroma .nd{color:#1e66f5;font-weight:700}.chroma .ni{color:#179299}.chroma .ne{color:#fe640b}.chroma .fm,.chroma .nf{color:#1e66f5}.chroma .nl{color:#04a5e5}.chroma .nn,.chroma .py{color:#fe640b}.chroma .nt{color:#8839ef}.chroma .nv,.chroma .vc,.chroma .vg,.chroma .vi,.chroma .vm{color:#dc8a78}.chroma .s{color:#40a02b}.chroma .sa{color:#d20f39}.chroma .sb,.chroma .sc{color:#40a02b}.chroma .dl{color:#1e66f5}.chroma .sd{color:#9ca0b0}.chroma .s2{color:#40a02b}.chroma .se{color:#1e66f5}.chroma .sh{color:#9ca0b0}.chroma .si,.chroma .sx{color:#40a02b}.chroma .sr{color:#179299}.chroma .s1,.chroma .ss{color:#40a02b}.chroma .il,.chroma .m,.chroma .mb,.chroma .mf,.chroma .mh,.chroma .mi,.chroma .mo{color:#fe640b}.chroma .o,.chroma .ow{color:#04a5e5;font-weight:700}.chroma .c,.chroma .c1,.chroma .ch,.chroma .cm,.chroma .cp,.chroma .cpf,.chroma .cs{color:#9ca0b0;font-style:italic}.chroma .cpf{font-weight:700}.chroma .gd{color:#d20f39;background-color:#ccd0da}.chroma .ge{font-style:italic}.chroma .gr{color:#d20f39}.chroma .gh{color:#fe640b;font-weight:700}.chroma .gi{color:#40a02b;background-color:#ccd0da}.chroma .gs,.chroma .gu{font-weight:700}.chroma .gu{color:#fe640b}.chroma .gt{color:#d20f39}.chroma .gl{text-decoration:underline}@media (prefers-color-scheme:dark){.bg,.chroma{color:#cdd6f4;background-color:#1e1e2e}.chroma .lntd:last-child{width:100%}.chroma .ln:target,.chroma .lnt:target{color:#cdd6f4;background-color:#45475a}.chroma .err{color:#f38ba8}.chroma .lnlinks{outline:none;text-decoration:none;color:inherit}.chroma .lntd{vertical-align:top;padding:0;margin:0;border:0}.chroma .lntable{border-spacing:0;padding:0;margin:0;border:0}.chroma .hl{background-color:#45475a}.chroma .ln,.chroma .lnt{white-space:pre;-webkit-user-select:none;-moz-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#7f849c}.chroma .line{display:flex}.chroma .k{color:#cba6f7}.chroma .kc{color:#fab387}.chroma .kd{color:#f38ba8}.chroma .kn{color:#94e2d5}.chroma .kp,.chroma .kr{color:#cba6f7}.chroma .kt{color:#f38ba8}.chroma .na{color:#89b4fa}.chroma .bp,.chroma .nb{color:#89dceb}.chroma .nc,.chroma .no{color:#f9e2af}.chroma .nd{color:#89b4fa;font-weight:700}.chroma .ni{color:#94e2d5}.chroma .ne{color:#fab387}.chroma .fm,.chroma .nf{color:#89b4fa}.chroma .nl{color:#89dceb}.chroma .nn,.chroma .py{color:#fab387}.chroma .nt{color:#cba6f7}.chroma .nv,.chroma .vc,.chroma .vg,.chroma .vi,.chroma .vm{color:#f5e0dc}.chroma .s{color:#a6e3a1}.chroma .sa{color:#f38ba8}.chroma .sb,.chroma .sc{color:#a6e3a1}.chroma .dl{color:#89b4fa}.chroma .sd{color:#6c7086}.chroma .s2{color:#a6e3a1}.chroma .se{color:#89b4fa}.chroma .sh{color:#6c7086}.chroma .si,.chroma .sx{color:#a6e3a1}.chroma .sr{color:#94e2d5}.chroma .s1,.chroma .ss{color:#a6e3a1}.chroma .il,.chroma .m,.chroma .mb,.chroma .mf,.chroma .mh,.chroma .mi,.chroma .mo{color:#fab387}.chroma .o,.chroma .ow{color:#89dceb;font-weight:700}.chroma .c,.chroma .c1,.chroma .ch,.chroma .cm,.chroma .cp,.chroma .cpf,.chroma .cs{color:#6c7086;font-style:italic}.chroma .cpf{font-weight:700}.chroma .gd{color:#f38ba8;background-color:#313244}.chroma .ge{font-style:italic}.chroma .gr{color:#f38ba8}.chroma .gh{color:#fab387;font-weight:700}.chroma .gi{color:#a6e3a1;background-color:#313244}.chroma .gs,.chroma .gu{font-weight:700}.chroma .gu{color:#fab387}.chroma .gt{color:#f38ba8}.chroma .gl{text-decoration:underline}.dark\\:mocha{--ctp-rosewater:245,224,220;--ctp-flamingo:242,205,205;--ctp-pink:245,194,231;--ctp-mauve:203,166,247;--ctp-red:243,139,168;--ctp-maroon:235,160,172;--ctp-peach:250,179,135;--ctp-yellow:249,226,175;--ctp-green:166,227,161;--ctp-teal:148,226,213;--ctp-sky:137,220,235;--ctp-sapphire:116,199,236;--ctp-blue:137,180,250;--ctp-lavender:180,190,254;--ctp-text:205,214,244;--ctp-subtext1:186,194,222;--ctp-subtext0:166,173,200;--ctp-overlay2:147,153,178;--ctp-overlay1:127,132,156;--ctp-overlay0:108,112,134;--ctp-surface2:88,91,112;--ctp-surface1:69,71,90;--ctp-surface0:49,50,68;--ctp-base:30,30,46;--ctp-mantle:24,24,37;--ctp-crust:17,17,27}}.hover\\:bg-surface0:hover{--tw-bg-opacity:1;background-color:rgba(var(--ctp-surface0),var(--tw-bg-opacity))}.hover\\:decoration-solid:hover{text-decoration-style:solid}.focus\\:border-lavender:focus{--tw-border-opacity:1;border-color:rgba(var(--ctp-lavender),var(--tw-border-opacity))}.focus\\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}.focus\\:ring-0:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}@media (prefers-color-scheme:dark){.dark\\:bg-base\\/50{background-color:rgba(var(--ctp-base),.5)}.dark\\:bg-base\\/95{background-color:rgba(var(--ctp-base),.95)}.dark\\:text-lavender{--tw-text-opacity:1;color:rgba(var(--ctp-lavender),var(--tw-text-opacity))}.dark\\:decoration-lavender\\/50{text-decoration-color:rgba(var(--ctp-lavender),.5)}}@media (min-width:640px){.sm\\:col-span-1{grid-column:span 1/span 1}.sm\\:col-span-2{grid-column:span 2/span 2}.sm\\:col-span-3{grid-column:span 3/span 3}.sm\\:col-span-5{grid-column:span 5/span 5}.sm\\:col-span-6{grid-column:span 6/span 6}.sm\\:col-span-7{grid-column:span 7/span 7}.sm\\:mx-auto{margin-left:auto;margin-right:auto}.sm\\:mb-0{margin-bottom:0}.sm\\:grid-cols-10{grid-template-columns:repeat(10,minmax(0,1fr))}.sm\\:grid-cols-8{grid-template-columns:repeat(8,minmax(0,1fr))}}"))
9
}
+7
internal/http/http.go
+7
internal/http/http.go
···
116
}
117
}
118
119
+
func (rh repoHandler) repoBaseContext(repo *git.Repo) html.BaseContext {
120
+
return html.BaseContext{
121
+
Title: repo.Name(),
122
+
Description: repo.Meta.Description,
123
+
}
124
+
}
125
+
126
func (rh repoHandler) repoHeaderContext(repo *git.Repo, r *http.Request) html.RepoHeaderComponentContext {
127
ref := chi.URLParam(r, "ref")
128
if ref == "" {
+2
-2
internal/http/index.go
+2
-2
internal/http/index.go
+18
-19
internal/http/repo.go
+18
-19
internal/http/repo.go
···
47
if path != "" {
48
back = filepath.Dir(path)
49
}
50
-
if err := html.RepoTreeTemplate(html.RepoTreeContext{
51
-
Description: repo.Meta.Description,
52
-
BaseContext: rh.baseContext(),
53
RepoHeaderComponentContext: rh.repoHeaderContext(repo, r),
54
RepoBreadcrumbComponentContext: rh.repoBreadcrumbContext(repo, r, path),
55
RepoTreeComponentContext: html.RepoTreeComponentContext{
···
61
ReadmeComponentContext: html.ReadmeComponentContext{
62
Markdown: readmeContent,
63
},
64
-
}).Render(w); err != nil {
65
return httperr.Error(err)
66
}
67
···
100
}
101
}
102
103
-
if err := html.RepoFileTemplate(html.RepoFileContext{
104
-
BaseContext: rh.baseContext(),
105
RepoHeaderComponentContext: rh.repoHeaderContext(repo, r),
106
RepoBreadcrumbComponentContext: rh.repoBreadcrumbContext(repo, r, path),
107
Code: buf.String(),
108
Commit: commit,
109
Path: path,
110
-
}).Render(w); err != nil {
111
return httperr.Error(err)
112
}
113
···
127
return httperr.Error(err)
128
}
129
130
-
if err := html.RepoRefsTemplate(html.RepoRefsContext{
131
-
BaseContext: rh.baseContext(),
132
RepoHeaderComponentContext: rh.repoHeaderContext(repo, r),
133
Branches: branches,
134
Tags: tags,
135
-
}).Render(w); err != nil {
136
return httperr.Error(err)
137
}
138
···
147
return httperr.Error(err)
148
}
149
150
-
if err := html.RepoLogTemplate(html.RepoLogContext{
151
-
BaseContext: rh.baseContext(),
152
RepoHeaderComponentContext: rh.repoHeaderContext(repo, r),
153
Commits: commits,
154
-
}).Render(w); err != nil {
155
return httperr.Error(err)
156
}
157
···
174
commit.Files[idx].Patch = patch.String()
175
}
176
177
-
if err := html.RepoCommitTemplate(html.RepoCommitContext{
178
-
BaseContext: rh.baseContext(),
179
RepoHeaderComponentContext: rh.repoHeaderContext(repo, r),
180
Commit: commit,
181
-
}).Render(w); err != nil {
182
return httperr.Error(err)
183
}
184
···
218
}
219
}
220
221
-
if err := html.RepoSearchTemplate(html.SearchContext{
222
-
BaseContext: rh.baseContext(),
223
RepoHeaderComponentContext: rh.repoHeaderContext(repo, r),
224
Results: results,
225
-
}).Render(w); err != nil {
226
return httperr.Error(err)
227
}
228
···
47
if path != "" {
48
back = filepath.Dir(path)
49
}
50
+
if err := html.RepoTree(html.RepoTreeContext{
51
+
BaseContext: rh.repoBaseContext(repo),
52
RepoHeaderComponentContext: rh.repoHeaderContext(repo, r),
53
RepoBreadcrumbComponentContext: rh.repoBreadcrumbContext(repo, r, path),
54
RepoTreeComponentContext: html.RepoTreeComponentContext{
···
60
ReadmeComponentContext: html.ReadmeComponentContext{
61
Markdown: readmeContent,
62
},
63
+
}).Render(r.Context(), w); err != nil {
64
return httperr.Error(err)
65
}
66
···
99
}
100
}
101
102
+
if err := html.RepoFile(html.RepoFileContext{
103
+
BaseContext: rh.repoBaseContext(repo),
104
RepoHeaderComponentContext: rh.repoHeaderContext(repo, r),
105
RepoBreadcrumbComponentContext: rh.repoBreadcrumbContext(repo, r, path),
106
Code: buf.String(),
107
Commit: commit,
108
Path: path,
109
+
}).Render(r.Context(), w); err != nil {
110
return httperr.Error(err)
111
}
112
···
126
return httperr.Error(err)
127
}
128
129
+
if err := html.RepoRefs(html.RepoRefsContext{
130
+
BaseContext: rh.repoBaseContext(repo),
131
RepoHeaderComponentContext: rh.repoHeaderContext(repo, r),
132
Branches: branches,
133
Tags: tags,
134
+
}).Render(r.Context(), w); err != nil {
135
return httperr.Error(err)
136
}
137
···
146
return httperr.Error(err)
147
}
148
149
+
if err := html.RepoLog(html.RepoLogContext{
150
+
BaseContext: rh.repoBaseContext(repo),
151
RepoHeaderComponentContext: rh.repoHeaderContext(repo, r),
152
Commits: commits,
153
+
}).Render(r.Context(), w); err != nil {
154
return httperr.Error(err)
155
}
156
···
173
commit.Files[idx].Patch = patch.String()
174
}
175
176
+
if err := html.RepoCommit(html.RepoCommitContext{
177
+
BaseContext: rh.repoBaseContext(repo),
178
RepoHeaderComponentContext: rh.repoHeaderContext(repo, r),
179
Commit: commit,
180
+
}).Render(r.Context(), w); err != nil {
181
return httperr.Error(err)
182
}
183
···
217
}
218
}
219
220
+
if err := html.RepoSearch(html.SearchContext{
221
+
BaseContext: rh.repoBaseContext(repo),
222
RepoHeaderComponentContext: rh.repoHeaderContext(repo, r),
223
Results: results,
224
+
}).Render(r.Context(), w); err != nil {
225
return httperr.Error(err)
226
}
227
+1
-1
internal/ssh/ssh.go
+1
-1
internal/ssh/ssh.go
+19
-26
internal/ssh/wish.go
+19
-26
internal/ssh/wish.go
···
12
"text/tabwriter"
13
14
"go.jolheiser.com/ugit/internal/git"
15
-
"go.jolheiser.com/ugit/internal/tui"
16
17
"github.com/charmbracelet/ssh"
18
"github.com/charmbracelet/wish"
···
100
}
101
}
102
103
-
// No args, start TUI
104
if len(cmd) == 0 {
105
-
if err := tui.Start(s, repoDir); err != nil {
106
-
slog.Error("failed to start TUI", "error", err)
107
-
108
-
// Fall back to simple list on TUI error
109
-
des, err := os.ReadDir(repoDir)
110
-
if err != nil && err != fs.ErrNotExist {
111
-
slog.Error("invalid repository", "error", err)
112
}
113
-
tw := tabwriter.NewWriter(s, 0, 0, 1, ' ', 0)
114
-
for _, de := range des {
115
-
if filepath.Ext(de.Name()) != ".git" {
116
-
continue
117
-
}
118
-
repo, err := git.NewRepo(repoDir, de.Name())
119
-
visibility := "โ"
120
-
if err == nil {
121
-
visibility = "๐"
122
-
if repo.Meta.Private {
123
-
visibility = "๐"
124
-
}
125
}
126
-
fmt.Fprintf(tw, "%[1]s\t%[3]s\t%[2]s/%[1]s.git\n", strings.TrimSuffix(de.Name(), ".git"), cloneURL, visibility)
127
}
128
-
tw.Flush()
129
}
130
-
return
131
}
132
sh(s)
133
}
···
175
}
176
177
// Fatal prints to the session's STDOUT as a git response and exit 1.
178
-
func Fatal(s ssh.Session, v ...interface{}) {
179
msg := fmt.Sprint(v...)
180
// hex length includes 4 byte length prefix and ending newline
181
pktLine := fmt.Sprintf("%04x%s\n", len(msg)+5, msg)
182
_, _ = wish.WriteString(s, pktLine)
183
s.Exit(1) // nolint: errcheck
184
-
}
···
12
"text/tabwriter"
13
14
"go.jolheiser.com/ugit/internal/git"
15
16
"github.com/charmbracelet/ssh"
17
"github.com/charmbracelet/wish"
···
99
}
100
}
101
102
+
// Repo list
103
if len(cmd) == 0 {
104
+
des, err := os.ReadDir(repoDir)
105
+
if err != nil && err != fs.ErrNotExist {
106
+
slog.Error("invalid repository", "error", err)
107
+
}
108
+
tw := tabwriter.NewWriter(s, 0, 0, 1, ' ', 0)
109
+
for _, de := range des {
110
+
if filepath.Ext(de.Name()) != ".git" {
111
+
continue
112
}
113
+
repo, err := git.NewRepo(repoDir, de.Name())
114
+
visibility := "โ"
115
+
if err == nil {
116
+
visibility = "๐"
117
+
if repo.Meta.Private {
118
+
visibility = "๐"
119
}
120
}
121
+
fmt.Fprintf(tw, "%[1]s\t%[3]s\t%[2]s/%[1]s.git\n", strings.TrimSuffix(de.Name(), ".git"), cloneURL, visibility)
122
}
123
+
tw.Flush()
124
}
125
sh(s)
126
}
···
168
}
169
170
// Fatal prints to the session's STDOUT as a git response and exit 1.
171
+
func Fatal(s ssh.Session, v ...any) {
172
msg := fmt.Sprint(v...)
173
// hex length includes 4 byte length prefix and ending newline
174
pktLine := fmt.Sprintf("%04x%s\n", len(msg)+5, msg)
175
_, _ = wish.WriteString(s, pktLine)
176
s.Exit(1) // nolint: errcheck
177
+
}
-230
internal/tui/form.go
-230
internal/tui/form.go
···
1
-
package tui
2
-
3
-
import (
4
-
"fmt"
5
-
"strings"
6
-
7
-
"github.com/charmbracelet/bubbles/textinput"
8
-
tea "github.com/charmbracelet/bubbletea"
9
-
"github.com/charmbracelet/lipgloss"
10
-
"go.jolheiser.com/ugit/internal/git"
11
-
)
12
-
13
-
type repoForm struct {
14
-
inputs []textinput.Model
15
-
isPrivate bool
16
-
focusIndex int
17
-
width int
18
-
height int
19
-
done bool
20
-
save bool
21
-
selectedRepo *git.Repo
22
-
}
23
-
24
-
// newRepoForm creates a new repository editing form
25
-
func newRepoForm() repoForm {
26
-
var inputs []textinput.Model
27
-
28
-
nameInput := textinput.New()
29
-
nameInput.Placeholder = "Repository name"
30
-
nameInput.Focus()
31
-
nameInput.Width = 50
32
-
inputs = append(inputs, nameInput)
33
-
34
-
descInput := textinput.New()
35
-
descInput.Placeholder = "Repository description"
36
-
descInput.Width = 50
37
-
inputs = append(inputs, descInput)
38
-
39
-
tagsInput := textinput.New()
40
-
tagsInput.Placeholder = "Tags (comma separated)"
41
-
tagsInput.Width = 50
42
-
inputs = append(inputs, tagsInput)
43
-
44
-
return repoForm{
45
-
inputs: inputs,
46
-
focusIndex: 0,
47
-
}
48
-
}
49
-
50
-
// setValues sets the form values from the selected repo
51
-
func (f *repoForm) setValues(repo *git.Repo) {
52
-
f.inputs[0].SetValue(repo.Name())
53
-
f.inputs[1].SetValue(repo.Meta.Description)
54
-
f.inputs[2].SetValue(strings.Join(repo.Meta.Tags.Slice(), ", "))
55
-
f.isPrivate = repo.Meta.Private
56
-
57
-
f.inputs[0].Focus()
58
-
f.focusIndex = 0
59
-
}
60
-
61
-
// setSize sets the form dimensions
62
-
func (f *repoForm) setSize(width, height int) {
63
-
f.width = width
64
-
f.height = height
65
-
66
-
for i := range f.inputs {
67
-
f.inputs[i].Width = width - 10
68
-
}
69
-
}
70
-
71
-
// isPrivateToggleFocused returns true if the private toggle is focused
72
-
func (f *repoForm) isPrivateToggleFocused() bool {
73
-
return f.focusIndex == len(f.inputs)
74
-
}
75
-
76
-
// isSaveButtonFocused returns true if the save button is focused
77
-
func (f *repoForm) isSaveButtonFocused() bool {
78
-
return f.focusIndex == len(f.inputs)+1
79
-
}
80
-
81
-
// isCancelButtonFocused returns true if the cancel button is focused
82
-
func (f *repoForm) isCancelButtonFocused() bool {
83
-
return f.focusIndex == len(f.inputs)+2
84
-
}
85
-
86
-
// Update handles form updates
87
-
func (f repoForm) Update(msg tea.Msg) (repoForm, tea.Cmd) {
88
-
var cmds []tea.Cmd
89
-
90
-
switch msg := msg.(type) {
91
-
case tea.KeyMsg:
92
-
switch msg.String() {
93
-
case "tab", "shift+tab", "up", "down":
94
-
if msg.String() == "up" || msg.String() == "shift+tab" {
95
-
f.focusIndex--
96
-
if f.focusIndex < 0 {
97
-
f.focusIndex = len(f.inputs) + 3 - 1
98
-
}
99
-
} else {
100
-
f.focusIndex++
101
-
if f.focusIndex >= len(f.inputs)+3 {
102
-
f.focusIndex = 0
103
-
}
104
-
}
105
-
106
-
for i := range f.inputs {
107
-
if i == f.focusIndex {
108
-
cmds = append(cmds, f.inputs[i].Focus())
109
-
} else {
110
-
f.inputs[i].Blur()
111
-
}
112
-
}
113
-
114
-
case "enter":
115
-
if f.isSaveButtonFocused() {
116
-
f.done = true
117
-
f.save = true
118
-
return f, nil
119
-
}
120
-
121
-
if f.isCancelButtonFocused() {
122
-
f.done = true
123
-
f.save = false
124
-
return f, nil
125
-
}
126
-
127
-
case "esc":
128
-
f.done = true
129
-
f.save = false
130
-
return f, nil
131
-
132
-
case " ":
133
-
if f.isPrivateToggleFocused() {
134
-
f.isPrivate = !f.isPrivate
135
-
}
136
-
137
-
if f.isSaveButtonFocused() {
138
-
f.done = true
139
-
f.save = true
140
-
return f, nil
141
-
}
142
-
143
-
if f.isCancelButtonFocused() {
144
-
f.done = true
145
-
f.save = false
146
-
return f, nil
147
-
}
148
-
}
149
-
}
150
-
151
-
for i := range f.inputs {
152
-
if i == f.focusIndex {
153
-
var cmd tea.Cmd
154
-
f.inputs[i], cmd = f.inputs[i].Update(msg)
155
-
cmds = append(cmds, cmd)
156
-
}
157
-
}
158
-
159
-
return f, tea.Batch(cmds...)
160
-
}
161
-
162
-
// View renders the form
163
-
func (f repoForm) View() string {
164
-
var b strings.Builder
165
-
166
-
formStyle := lipgloss.NewStyle().
167
-
BorderStyle(lipgloss.RoundedBorder()).
168
-
BorderForeground(lipgloss.Color("170")).
169
-
Padding(1, 2)
170
-
171
-
titleStyle := lipgloss.NewStyle().
172
-
Bold(true).
173
-
Foreground(lipgloss.Color("170")).
174
-
MarginBottom(1)
175
-
176
-
b.WriteString(titleStyle.Render("Edit Repository"))
177
-
b.WriteString("\n\n")
178
-
179
-
b.WriteString("Repository Name:\n")
180
-
b.WriteString(f.inputs[0].View())
181
-
b.WriteString("\n\n")
182
-
183
-
b.WriteString("Description:\n")
184
-
b.WriteString(f.inputs[1].View())
185
-
b.WriteString("\n\n")
186
-
187
-
b.WriteString("Tags (comma separated):\n")
188
-
b.WriteString(f.inputs[2].View())
189
-
b.WriteString("\n\n")
190
-
191
-
toggleStyle := lipgloss.NewStyle()
192
-
if f.isPrivateToggleFocused() {
193
-
toggleStyle = toggleStyle.Foreground(lipgloss.Color("170")).Bold(true)
194
-
}
195
-
196
-
visibility := "Public ๐"
197
-
if f.isPrivate {
198
-
visibility = "Private ๐"
199
-
}
200
-
201
-
b.WriteString(toggleStyle.Render(fmt.Sprintf("[%s] %s", visibility, "Toggle with Space")))
202
-
b.WriteString("\n\n")
203
-
204
-
buttonStyle := lipgloss.NewStyle().
205
-
Padding(0, 3).
206
-
MarginRight(1)
207
-
208
-
focusedButtonStyle := buttonStyle.Copy().
209
-
Foreground(lipgloss.Color("0")).
210
-
Background(lipgloss.Color("170")).
211
-
Bold(true)
212
-
213
-
saveButton := buttonStyle.Render("[ Save ]")
214
-
cancelButton := buttonStyle.Render("[ Cancel ]")
215
-
216
-
if f.isSaveButtonFocused() {
217
-
saveButton = focusedButtonStyle.Render("[ Save ]")
218
-
}
219
-
220
-
if f.isCancelButtonFocused() {
221
-
cancelButton = focusedButtonStyle.Render("[ Cancel ]")
222
-
}
223
-
224
-
b.WriteString(saveButton + cancelButton)
225
-
b.WriteString("\n\n")
226
-
227
-
b.WriteString("\nTab: Next โข Shift+Tab: Previous โข Enter: Select โข Esc: Cancel")
228
-
229
-
return formStyle.Width(f.width - 4).Render(b.String())
230
-
}
···
-65
internal/tui/keymap.go
-65
internal/tui/keymap.go
···
1
-
package tui
2
-
3
-
import (
4
-
"github.com/charmbracelet/bubbles/key"
5
-
)
6
-
7
-
// keyMap defines the keybindings for the TUI
8
-
type keyMap struct {
9
-
Up key.Binding
10
-
Down key.Binding
11
-
Edit key.Binding
12
-
Delete key.Binding
13
-
Help key.Binding
14
-
Quit key.Binding
15
-
Confirm key.Binding
16
-
Cancel key.Binding
17
-
}
18
-
19
-
// ShortHelp returns keybindings to be shown in the mini help view.
20
-
func (k keyMap) ShortHelp() []key.Binding {
21
-
return []key.Binding{k.Help, k.Edit, k.Delete, k.Quit}
22
-
}
23
-
24
-
// FullHelp returns keybindings for the expanded help view.
25
-
func (k keyMap) FullHelp() [][]key.Binding {
26
-
return [][]key.Binding{
27
-
{k.Up, k.Down, k.Edit},
28
-
{k.Delete, k.Help, k.Quit},
29
-
}
30
-
}
31
-
32
-
var keys = keyMap{
33
-
Up: key.NewBinding(
34
-
key.WithKeys("up", "k"),
35
-
key.WithHelp("โ/k", "up"),
36
-
),
37
-
Down: key.NewBinding(
38
-
key.WithKeys("down", "j"),
39
-
key.WithHelp("โ/j", "down"),
40
-
),
41
-
Edit: key.NewBinding(
42
-
key.WithKeys("e"),
43
-
key.WithHelp("e", "edit"),
44
-
),
45
-
Delete: key.NewBinding(
46
-
key.WithKeys("d"),
47
-
key.WithHelp("d", "delete"),
48
-
),
49
-
Help: key.NewBinding(
50
-
key.WithKeys("?"),
51
-
key.WithHelp("?", "help"),
52
-
),
53
-
Quit: key.NewBinding(
54
-
key.WithKeys("q", "ctrl+c"),
55
-
key.WithHelp("q", "quit"),
56
-
),
57
-
Confirm: key.NewBinding(
58
-
key.WithKeys("y"),
59
-
key.WithHelp("y", "confirm"),
60
-
),
61
-
Cancel: key.NewBinding(
62
-
key.WithKeys("n", "esc"),
63
-
key.WithHelp("n", "cancel"),
64
-
),
65
-
}
···
-50
internal/tui/main.go
-50
internal/tui/main.go
···
1
-
package tui
2
-
3
-
import (
4
-
"fmt"
5
-
6
-
"github.com/charmbracelet/bubbles/help"
7
-
"github.com/charmbracelet/bubbles/list"
8
-
tea "github.com/charmbracelet/bubbletea"
9
-
"github.com/charmbracelet/lipgloss"
10
-
)
11
-
12
-
// Run runs the TUI standalone, useful for development or local usage
13
-
func Run(repoDir string) error {
14
-
model := Model{
15
-
repoDir: repoDir,
16
-
help: help.New(),
17
-
keys: keys,
18
-
activeView: ViewList,
19
-
repoForm: newRepoForm(),
20
-
}
21
-
22
-
repos, err := loadRepos(repoDir)
23
-
if err != nil {
24
-
return fmt.Errorf("failed to load repos: %w", err)
25
-
}
26
-
model.repos = repos
27
-
28
-
items := make([]list.Item, len(repos))
29
-
for i, repo := range repos {
30
-
items[i] = repoItem{repo: repo}
31
-
}
32
-
33
-
delegate := list.NewDefaultDelegate()
34
-
delegate.Styles.SelectedTitle = delegate.Styles.SelectedTitle.Foreground(lipgloss.Color("170"))
35
-
delegate.Styles.SelectedDesc = delegate.Styles.SelectedDesc.Foreground(lipgloss.Color("244"))
36
-
37
-
repoList := list.New(items, delegate, 0, 0)
38
-
repoList.Title = "Git Repositories"
39
-
repoList.SetShowStatusBar(true)
40
-
repoList.SetFilteringEnabled(true)
41
-
repoList.Styles.Title = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("170")).Padding(0, 0, 0, 2)
42
-
repoList.StatusMessageLifetime = 3
43
-
44
-
model.repoList = repoList
45
-
46
-
p := tea.NewProgram(model, tea.WithAltScreen(), tea.WithMouseCellMotion())
47
-
48
-
_, err = p.Run()
49
-
return err
50
-
}
···
-72
internal/tui/repo_item.go
-72
internal/tui/repo_item.go
···
1
-
package tui
2
-
3
-
import (
4
-
"strings"
5
-
6
-
"go.jolheiser.com/ugit/internal/git"
7
-
)
8
-
9
-
// repoItem represents a repository item in the list
10
-
type repoItem struct {
11
-
repo *git.Repo
12
-
}
13
-
14
-
// Title returns the title for the list item
15
-
func (r repoItem) Title() string {
16
-
return r.repo.Name()
17
-
}
18
-
19
-
// Description returns the description for the list item
20
-
func (r repoItem) Description() string {
21
-
var builder strings.Builder
22
-
23
-
if r.repo.Meta.Private {
24
-
builder.WriteString("๐")
25
-
} else {
26
-
builder.WriteString("๐")
27
-
}
28
-
29
-
builder.WriteString(" โข ")
30
-
31
-
if r.repo.Meta.Description != "" {
32
-
builder.WriteString(r.repo.Meta.Description)
33
-
} else {
34
-
builder.WriteString("No description")
35
-
}
36
-
37
-
builder.WriteString(" โข ")
38
-
39
-
builder.WriteString("[")
40
-
if len(r.repo.Meta.Tags) > 0 {
41
-
builder.WriteString(strings.Join(r.repo.Meta.Tags.Slice(), ", "))
42
-
}
43
-
builder.WriteString("]")
44
-
45
-
builder.WriteString(" โข ")
46
-
47
-
lastCommit, err := r.repo.LastCommit()
48
-
if err == nil {
49
-
builder.WriteString(lastCommit.Short())
50
-
} else {
51
-
builder.WriteString("deadbeef")
52
-
}
53
-
54
-
return builder.String()
55
-
}
56
-
57
-
// FilterValue returns the value to use for filtering
58
-
func (r repoItem) FilterValue() string {
59
-
var builder strings.Builder
60
-
builder.WriteString(r.repo.Name())
61
-
builder.WriteString(" ")
62
-
builder.WriteString(r.repo.Meta.Description)
63
-
64
-
if len(r.repo.Meta.Tags) > 0 {
65
-
for _, tag := range r.repo.Meta.Tags.Slice() {
66
-
builder.WriteString(" ")
67
-
builder.WriteString(tag)
68
-
}
69
-
}
70
-
71
-
return strings.ToLower(builder.String())
72
-
}
···
-321
internal/tui/tui.go
-321
internal/tui/tui.go
···
1
-
package tui
2
-
3
-
import (
4
-
"fmt"
5
-
"log/slog"
6
-
"path/filepath"
7
-
"strings"
8
-
9
-
"github.com/charmbracelet/bubbles/help"
10
-
"github.com/charmbracelet/bubbles/key"
11
-
"github.com/charmbracelet/bubbles/list"
12
-
"github.com/charmbracelet/bubbles/textinput"
13
-
tea "github.com/charmbracelet/bubbletea"
14
-
"github.com/charmbracelet/lipgloss"
15
-
"github.com/charmbracelet/ssh"
16
-
"go.jolheiser.com/ugit/internal/git"
17
-
)
18
-
19
-
// Model is the main TUI model
20
-
type Model struct {
21
-
repoList list.Model
22
-
repos []*git.Repo
23
-
repoDir string
24
-
width int
25
-
height int
26
-
help help.Model
27
-
keys keyMap
28
-
activeView View
29
-
repoForm repoForm
30
-
session ssh.Session
31
-
}
32
-
33
-
// View represents the current active view in the TUI
34
-
type View int
35
-
36
-
const (
37
-
ViewList View = iota
38
-
ViewForm
39
-
ViewConfirmDelete
40
-
)
41
-
42
-
// New creates a new TUI model
43
-
func New(s ssh.Session, repoDir string) (*Model, error) {
44
-
repos, err := loadRepos(repoDir)
45
-
if err != nil {
46
-
return nil, fmt.Errorf("failed to load repos: %w", err)
47
-
}
48
-
49
-
items := make([]list.Item, len(repos))
50
-
for i, repo := range repos {
51
-
items[i] = repoItem{repo: repo}
52
-
}
53
-
54
-
delegate := list.NewDefaultDelegate()
55
-
delegate.Styles.SelectedTitle = delegate.Styles.SelectedTitle.Foreground(lipgloss.Color("170"))
56
-
delegate.Styles.SelectedDesc = delegate.Styles.SelectedDesc.Foreground(lipgloss.Color("244"))
57
-
58
-
repoList := list.New(items, delegate, 0, 0)
59
-
repoList.Title = "Git Repositories"
60
-
repoList.SetShowStatusBar(true)
61
-
repoList.SetFilteringEnabled(true)
62
-
repoList.Styles.Title = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("170")).Padding(0, 0, 0, 2)
63
-
repoList.StatusMessageLifetime = 3
64
-
65
-
repoList.FilterInput.Placeholder = "Type to filter repositories..."
66
-
repoList.FilterInput.PromptStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("170"))
67
-
repoList.FilterInput.TextStyle = lipgloss.NewStyle()
68
-
69
-
help := help.New()
70
-
71
-
repoForm := newRepoForm()
72
-
73
-
return &Model{
74
-
repoList: repoList,
75
-
repos: repos,
76
-
repoDir: repoDir,
77
-
help: help,
78
-
keys: keys,
79
-
activeView: ViewList,
80
-
repoForm: repoForm,
81
-
session: s,
82
-
}, nil
83
-
}
84
-
85
-
// loadRepos loads all git repositories from the given directory
86
-
func loadRepos(repoDir string) ([]*git.Repo, error) {
87
-
entries, err := git.ListRepos(repoDir)
88
-
if err != nil {
89
-
return nil, err
90
-
}
91
-
92
-
repos := make([]*git.Repo, 0, len(entries))
93
-
for _, entry := range entries {
94
-
if !strings.HasSuffix(entry.Name(), ".git") {
95
-
continue
96
-
}
97
-
repo, err := git.NewRepo(repoDir, entry.Name())
98
-
if err != nil {
99
-
slog.Error("error loading repo", "name", entry.Name(), "error", err)
100
-
continue
101
-
}
102
-
repos = append(repos, repo)
103
-
}
104
-
105
-
return repos, nil
106
-
}
107
-
108
-
// Init initializes the model
109
-
func (m Model) Init() tea.Cmd {
110
-
return nil
111
-
}
112
-
113
-
// Update handles all the messages and updates the model accordingly
114
-
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
115
-
var cmds []tea.Cmd
116
-
117
-
switch msg := msg.(type) {
118
-
case tea.KeyMsg:
119
-
switch {
120
-
case key.Matches(msg, m.keys.Quit):
121
-
return m, tea.Quit
122
-
case key.Matches(msg, m.keys.Help):
123
-
m.help.ShowAll = !m.help.ShowAll
124
-
}
125
-
126
-
switch m.activeView {
127
-
case ViewList:
128
-
var cmd tea.Cmd
129
-
m.repoList, cmd = m.repoList.Update(msg)
130
-
cmds = append(cmds, cmd)
131
-
132
-
if m.repoList.FilterState() == list.Filtering {
133
-
break
134
-
}
135
-
136
-
switch {
137
-
case key.Matches(msg, m.keys.Edit):
138
-
if len(m.repos) == 0 {
139
-
m.repoList.NewStatusMessage("No repositories to edit")
140
-
break
141
-
}
142
-
143
-
selectedItem := m.repoList.SelectedItem().(repoItem)
144
-
m.repoForm.selectedRepo = selectedItem.repo
145
-
146
-
m.repoForm.setValues(selectedItem.repo)
147
-
m.activeView = ViewForm
148
-
return m, textinput.Blink
149
-
150
-
case key.Matches(msg, m.keys.Delete):
151
-
if len(m.repos) == 0 {
152
-
m.repoList.NewStatusMessage("No repositories to delete")
153
-
break
154
-
}
155
-
156
-
m.activeView = ViewConfirmDelete
157
-
}
158
-
159
-
case ViewForm:
160
-
var cmd tea.Cmd
161
-
m.repoForm, cmd = m.repoForm.Update(msg)
162
-
cmds = append(cmds, cmd)
163
-
164
-
if m.repoForm.done {
165
-
if m.repoForm.save {
166
-
selectedRepo := m.repoForm.selectedRepo
167
-
repoDir := filepath.Dir(selectedRepo.Path())
168
-
oldName := selectedRepo.Name()
169
-
newName := m.repoForm.inputs[0].Value()
170
-
171
-
var renamed bool
172
-
if oldName != newName {
173
-
if err := git.RenameRepo(repoDir, oldName, newName); err != nil {
174
-
m.repoList.NewStatusMessage(fmt.Sprintf("Error renaming repo: %s", err))
175
-
} else {
176
-
m.repoList.NewStatusMessage(fmt.Sprintf("Repository renamed from %s to %s", oldName, newName))
177
-
renamed = true
178
-
}
179
-
}
180
-
181
-
if renamed {
182
-
if newRepo, err := git.NewRepo(repoDir, newName+".git"); err == nil {
183
-
selectedRepo = newRepo
184
-
} else {
185
-
m.repoList.NewStatusMessage(fmt.Sprintf("Error loading renamed repo: %s", err))
186
-
}
187
-
}
188
-
189
-
selectedRepo.Meta.Description = m.repoForm.inputs[1].Value()
190
-
selectedRepo.Meta.Private = m.repoForm.isPrivate
191
-
192
-
tags := make(git.TagSet)
193
-
for _, tag := range strings.Split(m.repoForm.inputs[2].Value(), ",") {
194
-
tag = strings.TrimSpace(tag)
195
-
if tag != "" {
196
-
tags.Add(tag)
197
-
}
198
-
}
199
-
selectedRepo.Meta.Tags = tags
200
-
201
-
if err := selectedRepo.SaveMeta(); err != nil {
202
-
m.repoList.NewStatusMessage(fmt.Sprintf("Error saving repo metadata: %s", err))
203
-
} else if !renamed {
204
-
m.repoList.NewStatusMessage("Repository updated successfully")
205
-
}
206
-
}
207
-
208
-
m.repoForm.done = false
209
-
m.repoForm.save = false
210
-
m.activeView = ViewList
211
-
212
-
if repos, err := loadRepos(m.repoDir); err == nil {
213
-
m.repos = repos
214
-
items := make([]list.Item, len(repos))
215
-
for i, repo := range repos {
216
-
items[i] = repoItem{repo: repo}
217
-
}
218
-
m.repoList.SetItems(items)
219
-
}
220
-
}
221
-
222
-
case ViewConfirmDelete:
223
-
switch {
224
-
case key.Matches(msg, m.keys.Confirm):
225
-
selectedItem := m.repoList.SelectedItem().(repoItem)
226
-
repo := selectedItem.repo
227
-
228
-
if err := git.DeleteRepo(repo.Path()); err != nil {
229
-
m.repoList.NewStatusMessage(fmt.Sprintf("Error deleting repo: %s", err))
230
-
} else {
231
-
m.repoList.NewStatusMessage(fmt.Sprintf("Repository %s deleted", repo.Name()))
232
-
233
-
if repos, err := loadRepos(m.repoDir); err == nil {
234
-
m.repos = repos
235
-
items := make([]list.Item, len(repos))
236
-
for i, repo := range repos {
237
-
items[i] = repoItem{repo: repo}
238
-
}
239
-
m.repoList.SetItems(items)
240
-
}
241
-
}
242
-
m.activeView = ViewList
243
-
244
-
case key.Matches(msg, m.keys.Cancel):
245
-
m.activeView = ViewList
246
-
}
247
-
}
248
-
249
-
case tea.WindowSizeMsg:
250
-
m.width = msg.Width
251
-
m.height = msg.Height
252
-
253
-
headerHeight := 3
254
-
footerHeight := 2
255
-
256
-
m.repoList.SetSize(msg.Width, msg.Height-headerHeight-footerHeight)
257
-
m.repoForm.setSize(msg.Width, msg.Height)
258
-
259
-
m.help.Width = msg.Width
260
-
}
261
-
262
-
return m, tea.Batch(cmds...)
263
-
}
264
-
265
-
// View renders the current UI
266
-
func (m Model) View() string {
267
-
switch m.activeView {
268
-
case ViewList:
269
-
return fmt.Sprintf("%s\n%s", m.repoList.View(), m.help.View(m.keys))
270
-
271
-
case ViewForm:
272
-
return m.repoForm.View()
273
-
274
-
case ViewConfirmDelete:
275
-
selectedItem := m.repoList.SelectedItem().(repoItem)
276
-
repo := selectedItem.repo
277
-
278
-
confirmStyle := lipgloss.NewStyle().
279
-
BorderStyle(lipgloss.RoundedBorder()).
280
-
BorderForeground(lipgloss.Color("170")).
281
-
Padding(1, 2).
282
-
Width(m.width - 4).
283
-
Align(lipgloss.Center)
284
-
285
-
confirmText := fmt.Sprintf(
286
-
"Are you sure you want to delete repository '%s'?\n\nThis action cannot be undone!\n\nPress y to confirm or n to cancel.",
287
-
repo.Name(),
288
-
)
289
-
290
-
return confirmStyle.Render(confirmText)
291
-
}
292
-
293
-
return ""
294
-
}
295
-
296
-
// Start runs the TUI
297
-
func Start(s ssh.Session, repoDir string) error {
298
-
model, err := New(s, repoDir)
299
-
if err != nil {
300
-
return err
301
-
}
302
-
303
-
// Get terminal dimensions from SSH session if available
304
-
pty, _, isPty := s.Pty()
305
-
if isPty && pty.Window.Width > 0 && pty.Window.Height > 0 {
306
-
// Initialize with correct size
307
-
model.width = pty.Window.Width
308
-
model.height = pty.Window.Height
309
-
310
-
headerHeight := 3
311
-
footerHeight := 2
312
-
model.repoList.SetSize(pty.Window.Width, pty.Window.Height-headerHeight-footerHeight)
313
-
model.repoForm.setSize(pty.Window.Width, pty.Window.Height)
314
-
model.help.Width = pty.Window.Width
315
-
}
316
-
317
-
p := tea.NewProgram(model, tea.WithAltScreen(), tea.WithMouseCellMotion(), tea.WithInput(s), tea.WithOutput(s))
318
-
319
-
_, err = p.Run()
320
-
return err
321
-
}
···