+24
.air.toml
+24
.air.toml
···
1
+
root = "."
2
+
testdata_dir = "testdata"
3
+
tmp_dir = "tmp"
4
+
5
+
[build]
6
+
bin = "./ugitd"
7
+
cmd = "go build ./cmd/ugitd"
8
+
delay = 1000
9
+
exclude_file = ["internal/html/tailwind.go"]
10
+
exclude_regex = ["_test.go"]
11
+
exclude_unchanged = true
12
+
include_ext = ["go"]
13
+
pre_cmd = ["go generate ./..."]
14
+
15
+
[misc]
16
+
clean_on_exit = true
17
+
18
+
[proxy]
19
+
app_port = 8449
20
+
enabled = true
21
+
proxy_port = 8450
22
+
23
+
[screen]
24
+
clear_on_rebuild = true
-5
.helix/languages.toml
-5
.helix/languages.toml
+4
-4
README.md
+4
-4
README.md
···
2
2
<picture>
3
3
<img alt="ugit logo" width="250" src="./assets/ugit.svg" />
4
4
</picture>
5
-
<h3 align="center">ugit</h3>
5
+
<h3 align="center">ยตgit</h3>
6
6
</p>
7
7
8
8
Minimal git server
9
9
10
-
ugit allows cloning via HTTPS/SSH, but can only be pushed to via SSH.
10
+
ยตgit allows cloning via HTTPS/SSH, but can only be pushed to via SSH.
11
11
12
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
-
For now, if you wish to collaborate, please send me patches at [ugit@jolheiser.com](mailto:git@jolheiser.com).
13
+
If you wish to collaborate, please send me patches via [git-pr](https://pr.jolheiser.com/repos/ugit).
14
14
15
-
Currently all HTML is allowed in markdown, ugit is intended to be run by/for a trusted user.
15
+
Currently all HTML is allowed in markdown, ยตgit is intended to be run by/for a trusted user.
16
16
17
17
## Getting your public SSH keys from another forge
18
18
+1
-1
assets/ugit.svg
+1
-1
assets/ugit.svg
···
1
1
<?xml version="1.0" encoding="UTF-8"?>
2
2
<svg viewBox="0 0 24 24" stroke="#de4c36" fill="#de4c36" stroke-width="1" xmlns="http://www.w3.org/2000/svg">
3
-
<title>ugit icon</title>
3
+
<title>ยตgit icon</title>
4
4
<rect fill="none" x="1" y="1" rx="1" ry="1" width="22" height="22"></rect>
5
5
<ellipse cx="6" cy="6" rx="2" ry="2"></ellipse>
6
6
<ellipse cx="18" cy="6" rx="2" ry="2"></ellipse>
+69
cmd/ugitd/args.cue
+69
cmd/ugitd/args.cue
···
1
+
import "strings"
2
+
3
+
// Schema
4
+
#Port: int & >0 & <65536
5
+
#Link: string & strings.Contains(",")
6
+
7
+
#Config: {
8
+
"repo-dir": string
9
+
"show-private": bool
10
+
ssh: {
11
+
enable: bool
12
+
"authorized-keys": string
13
+
"clone-url": string
14
+
port: #Port
15
+
"host-key": string
16
+
}
17
+
http: {
18
+
enable: bool
19
+
"clone-url": string
20
+
port: #Port
21
+
}
22
+
meta: {
23
+
title: string
24
+
description: string
25
+
}
26
+
profile?: {
27
+
username?: string
28
+
email?: string
29
+
links?: [...#Link]
30
+
}
31
+
log: {
32
+
json: bool
33
+
level: "debug" | "info" | "warn" | "warning" | "error"
34
+
}
35
+
36
+
// Constraints
37
+
if ssh.port == http.port {
38
+
error("ssh.port and http.port cannot be the same")
39
+
}
40
+
}
41
+
42
+
// Defaults
43
+
#Config: {
44
+
"repo-dir": ".ugit"
45
+
"show-private": false
46
+
ssh: {
47
+
enable: true
48
+
"authorized-keys": ".ssh/authorized_keys"
49
+
"clone-url": "ssh://localhost:8448"
50
+
port: 8448
51
+
"host-key": ".ssh/ugit_ed25519"
52
+
}
53
+
http: {
54
+
enable: true
55
+
"clone-url": "http://localhost:8449"
56
+
port: 8449
57
+
}
58
+
meta: {
59
+
title: "uGit"
60
+
description: "Minimal git server"
61
+
}
62
+
log: {
63
+
json: false
64
+
level: "info"
65
+
}
66
+
}
67
+
68
+
// Apply schema
69
+
#Config
+39
-15
cmd/ugitd/args.go
+39
-15
cmd/ugitd/args.go
···
1
1
package main
2
2
3
3
import (
4
+
_ "embed"
4
5
"flag"
5
6
"fmt"
7
+
"log/slog"
6
8
"strings"
7
9
8
-
"github.com/charmbracelet/log"
9
10
"github.com/peterbourgon/ff/v3"
10
-
"github.com/peterbourgon/ff/v3/ffyaml"
11
+
"go.jolheiser.com/ffcue"
11
12
)
12
13
14
+
//go:embed args.cue
15
+
var schema string
16
+
13
17
type cliArgs struct {
14
-
RepoDir string
15
-
SSH sshArgs
16
-
HTTP httpArgs
17
-
Meta metaArgs
18
-
Profile profileArgs
19
-
Log logArgs
18
+
RepoDir string
19
+
SSH sshArgs
20
+
HTTP httpArgs
21
+
Meta metaArgs
22
+
Profile profileArgs
23
+
Log logArgs
24
+
ShowPrivate bool
20
25
}
21
26
22
27
type sshArgs struct {
28
+
Enable bool
23
29
AuthorizedKeys string
24
30
CloneURL string
25
31
Port int
···
27
33
}
28
34
29
35
type httpArgs struct {
36
+
Enable bool
30
37
CloneURL string
31
38
Port int
32
39
}
···
48
55
}
49
56
50
57
type logArgs struct {
51
-
Level log.Level
58
+
Level slog.Level
52
59
JSON bool
53
60
}
54
61
55
62
func parseArgs(args []string) (c cliArgs, e error) {
56
63
fs := flag.NewFlagSet("ugitd", flag.ContinueOnError)
57
-
fs.String("config", "ugit.yaml", "Path to config file")
64
+
fs.String("config", "ugit.cue", "Path to config file")
58
65
59
66
c = cliArgs{
60
67
RepoDir: ".ugit",
61
68
SSH: sshArgs{
69
+
Enable: true,
62
70
AuthorizedKeys: ".ssh/authorized_keys",
63
71
CloneURL: "ssh://localhost:8448",
64
72
Port: 8448,
65
73
HostKey: ".ssh/ugit_ed25519",
66
74
},
67
75
HTTP: httpArgs{
76
+
Enable: true,
68
77
CloneURL: "http://localhost:8449",
69
78
Port: 8449,
70
79
},
···
73
82
Description: "Minimal git server",
74
83
},
75
84
Log: logArgs{
76
-
Level: log.InfoLevel,
85
+
Level: slog.LevelError,
77
86
},
78
87
}
79
88
80
89
fs.Func("log.level", "Logging level", func(s string) error {
81
-
lvl, err := log.ParseLevel(s)
82
-
if err != nil {
83
-
return err
90
+
var lvl slog.Level
91
+
switch strings.ToLower(s) {
92
+
case "debug":
93
+
lvl = slog.LevelDebug
94
+
case "info":
95
+
lvl = slog.LevelInfo
96
+
case "warn", "warning":
97
+
lvl = slog.LevelWarn
98
+
case "error":
99
+
lvl = slog.LevelError
100
+
default:
101
+
return fmt.Errorf("unknown log level %q: options are [debug, info, warn, error]", s)
84
102
}
85
103
c.Log.Level = lvl
86
104
return nil
87
105
})
88
106
fs.BoolVar(&c.Log.JSON, "log.json", c.Log.JSON, "Print logs in JSON(L) format")
89
107
fs.StringVar(&c.RepoDir, "repo-dir", c.RepoDir, "Path to directory containing repositories")
108
+
fs.BoolVar(&c.ShowPrivate, "show-private", c.ShowPrivate, "Show private repos in web interface")
109
+
fs.BoolVar(&c.SSH.Enable, "ssh.enable", c.SSH.Enable, "Enable SSH server")
90
110
fs.StringVar(&c.SSH.AuthorizedKeys, "ssh.authorized-keys", c.SSH.AuthorizedKeys, "Path to authorized_keys")
91
111
fs.StringVar(&c.SSH.CloneURL, "ssh.clone-url", c.SSH.CloneURL, "SSH clone URL base")
92
112
fs.IntVar(&c.SSH.Port, "ssh.port", c.SSH.Port, "SSH port")
93
113
fs.StringVar(&c.SSH.HostKey, "ssh.host-key", c.SSH.HostKey, "SSH host key (created if it doesn't exist)")
114
+
fs.BoolVar(&c.HTTP.Enable, "http.enable", c.HTTP.Enable, "Enable HTTP server")
94
115
fs.StringVar(&c.HTTP.CloneURL, "http.clone-url", c.HTTP.CloneURL, "HTTP clone URL base")
95
116
fs.IntVar(&c.HTTP.Port, "http.port", c.HTTP.Port, "HTTP port")
96
117
fs.StringVar(&c.Meta.Title, "meta.title", c.Meta.Title, "App title")
···
109
130
return nil
110
131
})
111
132
133
+
parser := &ffcue.ParseConfig{
134
+
Constraints: schema,
135
+
}
112
136
return c, ff.Parse(fs, args,
113
137
ff.WithEnvVarPrefix("UGIT"),
114
138
ff.WithConfigFileFlag("config"),
115
139
ff.WithAllowMissingConfigFile(true),
116
-
ff.WithConfigFileParser(ffyaml.Parser),
140
+
ff.WithConfigFileParser(parser.Parse),
117
141
)
118
142
}
+43
-28
cmd/ugitd/main.go
+43
-28
cmd/ugitd/main.go
···
4
4
"errors"
5
5
"flag"
6
6
"fmt"
7
+
"log"
7
8
"log/slog"
8
9
"os"
9
10
"os/signal"
10
11
"path/filepath"
11
12
"strconv"
12
13
"strings"
14
+
"syscall"
13
15
14
-
"github.com/charmbracelet/log"
15
16
"github.com/go-chi/chi/v5/middleware"
16
17
"github.com/go-chi/httplog/v2"
17
18
"github.com/go-git/go-git/v5/plumbing/protocol/packp"
···
39
40
panic(err)
40
41
}
41
42
42
-
log.SetLevel(args.Log.Level)
43
+
slog.SetLogLoggerLevel(args.Log.Level)
43
44
middleware.DefaultLogger = httplog.RequestLogger(httplog.NewLogger("ugit", httplog.Options{
44
45
JSON: args.Log.JSON,
45
46
LogLevel: slog.Level(args.Log.Level),
46
-
Concise: args.Log.Level != log.DebugLevel,
47
+
Concise: args.Log.Level != slog.LevelDebug,
47
48
}))
48
49
49
-
if args.Log.Level == log.DebugLevel {
50
+
if args.Log.Level == slog.LevelDebug {
50
51
trace.SetTarget(trace.Packet)
51
52
} else {
52
53
middleware.DefaultLogger = http.NoopLogger
···
54
55
}
55
56
56
57
if args.Log.JSON {
57
-
log.SetFormatter(log.JSONFormatter)
58
+
logger := slog.New(slog.NewJSONHandler(os.Stderr, nil))
59
+
slog.SetDefault(logger)
58
60
}
59
61
60
62
if err := requiredFS(args.RepoDir); err != nil {
61
63
panic(err)
62
64
}
63
65
64
-
sshSettings := ssh.Settings{
65
-
AuthorizedKeys: args.SSH.AuthorizedKeys,
66
-
CloneURL: args.SSH.CloneURL,
67
-
Port: args.SSH.Port,
68
-
HostKey: args.SSH.HostKey,
69
-
RepoDir: args.RepoDir,
70
-
}
71
-
sshSrv, err := ssh.New(sshSettings)
72
-
if err != nil {
73
-
panic(err)
74
-
}
75
-
go func() {
76
-
log.Debugf("SSH listening on ssh://localhost:%d\n", sshSettings.Port)
77
-
if err := sshSrv.ListenAndServe(); err != nil {
66
+
if args.SSH.Enable {
67
+
sshSettings := ssh.Settings{
68
+
AuthorizedKeys: args.SSH.AuthorizedKeys,
69
+
CloneURL: args.SSH.CloneURL,
70
+
Port: args.SSH.Port,
71
+
HostKey: args.SSH.HostKey,
72
+
RepoDir: args.RepoDir,
73
+
}
74
+
sshSrv, err := ssh.New(sshSettings)
75
+
if err != nil {
78
76
panic(err)
79
77
}
80
-
}()
78
+
go func() {
79
+
log.Printf("SSH listening on ssh://localhost:%d\n", sshSettings.Port)
80
+
if err := sshSrv.ListenAndServe(); err != nil {
81
+
panic(err)
82
+
}
83
+
}()
84
+
}
81
85
82
86
httpSettings := http.Settings{
83
87
Title: args.Meta.Title,
···
89
93
Username: args.Profile.Username,
90
94
Email: args.Profile.Email,
91
95
},
96
+
ShowPrivate: args.ShowPrivate,
92
97
}
93
98
for _, link := range args.Profile.Links {
94
99
httpSettings.Profile.Links = append(httpSettings.Profile.Links, http.Link{
···
96
101
URL: link.URL,
97
102
})
98
103
}
99
-
httpSrv := http.New(httpSettings)
100
-
go func() {
101
-
log.Debugf("HTTP listening on http://localhost:%d\n", httpSettings.Port)
102
-
if err := httpSrv.ListenAndServe(); err != nil {
103
-
panic(err)
104
-
}
105
-
}()
104
+
if args.HTTP.Enable {
105
+
httpSrv := http.New(httpSettings)
106
+
go func() {
107
+
log.Printf("HTTP listening on http://localhost:%d\n", httpSettings.Port)
108
+
if err := httpSrv.ListenAndServe(); err != nil {
109
+
panic(err)
110
+
}
111
+
}()
112
+
}
106
113
107
114
ch := make(chan os.Signal, 1)
108
-
signal.Notify(ch, os.Kill, os.Interrupt)
115
+
signal.Notify(ch, syscall.SIGTERM, os.Interrupt)
109
116
<-ch
110
117
}
111
118
···
128
135
}
129
136
fp = filepath.Join(fp, "pre-receive")
130
137
138
+
if err := os.MkdirAll(fp+".d", os.ModePerm); err != nil {
139
+
return err
140
+
}
141
+
131
142
fi, err := os.Create(fp)
132
143
if err != nil {
133
144
return err
134
145
}
135
146
fi.WriteString("#!/usr/bin/env bash\n")
136
147
fi.WriteString(fmt.Sprintf("%s pre-receive-hook\n", bin))
148
+
fi.WriteString(fmt.Sprintf(`for hook in %s.d/*; do
149
+
test -x "${hook}" && test -f "${hook}" || continue
150
+
"${hook}"
151
+
done`, fp))
137
152
fi.Close()
138
153
139
154
return os.Chmod(fp, 0o755)
+3
-9
contrib/layout.kdl
+3
-9
contrib/layout.kdl
···
5
5
command "nix"
6
6
args "develop"
7
7
size "90%"
8
-
start_suspended true
9
8
}
10
9
pane split_direction="vertical" {
11
10
pane {
12
-
name "run"
13
-
command "go"
14
-
args "run" "./cmd/ugitd"
15
-
start_suspended true
16
-
}
17
-
pane {
18
-
name "watch"
11
+
name "air"
19
12
command "nix"
20
-
args "develop" "--command" "nu" "-c" "watch --glob *.templ ./internal/html/ {|| go generate ./...}"
13
+
args "develop" "--command" "air"
14
+
start_suspended true
21
15
}
22
16
}
23
17
}
+3
-58
flake.lock
+3
-58
flake.lock
···
1
1
{
2
2
"nodes": {
3
-
"flake-utils": {
4
-
"inputs": {
5
-
"systems": "systems"
6
-
},
7
-
"locked": {
8
-
"lastModified": 1694529238,
9
-
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
10
-
"owner": "numtide",
11
-
"repo": "flake-utils",
12
-
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
13
-
"type": "github"
14
-
},
15
-
"original": {
16
-
"owner": "numtide",
17
-
"repo": "flake-utils",
18
-
"type": "github"
19
-
}
20
-
},
21
-
"gomod2nix": {
22
-
"inputs": {
23
-
"flake-utils": "flake-utils",
24
-
"nixpkgs": [
25
-
"nixpkgs"
26
-
]
27
-
},
28
-
"locked": {
29
-
"lastModified": 1717050755,
30
-
"narHash": "sha256-C9IEHABulv2zEDFA+Bf0E1nmfN4y6MIUe5eM2RCrDC0=",
31
-
"owner": "nix-community",
32
-
"repo": "gomod2nix",
33
-
"rev": "31b6d2e40b36456e792cd6cf50d5a8ddd2fa59a1",
34
-
"type": "github"
35
-
},
36
-
"original": {
37
-
"owner": "nix-community",
38
-
"repo": "gomod2nix",
39
-
"type": "github"
40
-
}
41
-
},
42
3
"nixpkgs": {
43
4
"locked": {
44
-
"lastModified": 1719379843,
45
-
"narHash": "sha256-u+D+IOAMMl70+CJ9NKB+RMrASjInuIWMHzjLWQjPZ6c=",
5
+
"lastModified": 1755205935,
6
+
"narHash": "sha256-EQ6qHuJWguaoBZyxdqsgJqyEdS77k+2CnlKrfFxlkRY=",
46
7
"owner": "nixos",
47
8
"repo": "nixpkgs",
48
-
"rev": "b3f3c1b13fb08f3828442ee86630362e81136bbc",
9
+
"rev": "c5e2e42c112de623adfd662b3e51f0805bf9ff83",
49
10
"type": "github"
50
11
},
51
12
"original": {
···
57
18
},
58
19
"root": {
59
20
"inputs": {
60
-
"gomod2nix": "gomod2nix",
61
21
"nixpkgs": "nixpkgs",
62
22
"tailwind-ctp": "tailwind-ctp",
63
23
"tailwind-ctp-lsp": "tailwind-ctp-lsp"
64
-
}
65
-
},
66
-
"systems": {
67
-
"locked": {
68
-
"lastModified": 1681028828,
69
-
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
70
-
"owner": "nix-systems",
71
-
"repo": "default",
72
-
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
73
-
"type": "github"
74
-
},
75
-
"original": {
76
-
"owner": "nix-systems",
77
-
"repo": "default",
78
-
"type": "github"
79
24
}
80
25
},
81
26
"tailwind-ctp": {
+67
-153
flake.nix
+67
-153
flake.nix
···
3
3
4
4
inputs = {
5
5
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
6
-
gomod2nix = {
7
-
url = "github:nix-community/gomod2nix";
8
-
inputs.nixpkgs.follows = "nixpkgs";
9
-
};
10
6
tailwind-ctp = {
11
7
url = "git+https://git.jolheiser.com/tailwind-ctp";
12
8
inputs.nixpkgs.follows = "nixpkgs";
···
17
13
};
18
14
};
19
15
20
-
outputs = {
21
-
self,
22
-
nixpkgs,
23
-
gomod2nix,
24
-
tailwind-ctp,
25
-
tailwind-ctp-lsp,
26
-
} @ inputs: let
27
-
system = "x86_64-linux";
28
-
pkgs = nixpkgs.legacyPackages.${system};
29
-
tailwind-ctp = inputs.tailwind-ctp.packages.${system}.default;
30
-
tailwind-ctp-lsp = inputs.tailwind-ctp-lsp.packages.${system}.default;
31
-
ugit = gomod2nix.legacyPackages.${system}.buildGoApplication rec {
32
-
name = "ugitd";
33
-
src = pkgs.nix-gitignore.gitignoreSource [] (builtins.path {
34
-
inherit name;
35
-
path = ./.;
36
-
});
37
-
pwd = ./.;
38
-
subPackages = ["cmd/ugitd"];
39
-
CGO_ENABLED = 0;
40
-
flags = [
41
-
"-trimpath"
42
-
];
43
-
ldflags = [
44
-
"-s"
45
-
"-w"
46
-
"-extldflags -static"
47
-
];
48
-
meta = with pkgs.lib; {
49
-
description = "Minimal git server";
50
-
homepage = "https://git.jolheiser.com/ugit";
51
-
maintainers = with maintainers; [jolheiser];
52
-
mainProgram = "ugitd";
53
-
};
54
-
};
55
-
in {
56
-
packages.${system}.default = ugit;
57
-
devShells.${system}.default = pkgs.mkShell {
58
-
nativeBuildInputs = with pkgs; [
59
-
go
60
-
gopls
61
-
gomod2nix.legacyPackages.${system}.gomod2nix
62
-
templ
63
-
tailwind-ctp
64
-
tailwind-ctp-lsp
65
-
vscode-langservers-extracted
16
+
outputs =
17
+
{
18
+
self,
19
+
nixpkgs,
20
+
tailwind-ctp,
21
+
tailwind-ctp-lsp,
22
+
}:
23
+
let
24
+
systems = [
25
+
"x86_64-linux"
26
+
"i686-linux"
27
+
"x86_64-darwin"
28
+
"aarch64-linux"
29
+
"armv6l-linux"
30
+
"armv7l-linux"
66
31
];
67
-
};
68
-
nixosModules.default = {
69
-
pkgs,
70
-
lib,
71
-
config,
72
-
...
73
-
}: let
74
-
cfg = config.services.ugit;
75
-
yamlFormat = pkgs.formats.yaml {};
76
-
configFile = pkgs.writeText "ugit.yaml" (builtins.readFile (yamlFormat.generate "ugit-yaml" cfg.config));
77
-
authorizedKeysFile = pkgs.writeText "ugit_keys" (builtins.concatStringsSep "\n" cfg.authorizedKeys);
78
-
in {
79
-
options = with lib; {
80
-
services.ugit = {
81
-
enable = mkEnableOption "Enable ugit";
82
-
83
-
package = mkOption {
84
-
type = types.package;
85
-
description = "ugit package to use";
86
-
default = ugit;
87
-
};
88
-
89
-
repoDir = mkOption {
90
-
type = types.str;
91
-
description = "where ugit stores repositories";
92
-
default = "/var/lib/ugit/repos";
93
-
};
94
-
95
-
authorizedKeys = mkOption {
96
-
type = types.listOf types.str;
97
-
description = "list of keys to use for authorized_keys";
98
-
default = [];
99
-
};
100
-
101
-
authorizedKeysFile = mkOption {
102
-
type = types.str;
103
-
description = "path to authorized_keys file ugit uses for auth";
104
-
default = "/var/lib/ugit/authorized_keys";
105
-
};
106
-
107
-
hostKeyFile = mkOption {
108
-
type = types.str;
109
-
description = "path to host key file (will be created if it doesn't exist)";
110
-
default = "/var/lib/ugit/ugit_ed25519";
111
-
};
112
-
113
-
config = mkOption {
114
-
type = types.attrs;
115
-
default = {};
116
-
description = "config.yaml contents";
32
+
forAllSystems = f: nixpkgs.lib.genAttrs systems f;
33
+
tctp = forAllSystems (system: tailwind-ctp.packages.${system}.default);
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 {
45
+
nativeBuildInputs = with pkgs; [
46
+
go
47
+
gopls
48
+
air
49
+
tctp.${system}
50
+
#tctpl.${system}
51
+
#vscode-langservers-extracted
52
+
];
117
53
};
118
-
119
-
user = mkOption {
120
-
type = types.str;
121
-
default = "ugit";
122
-
description = "User account under which ugit runs";
123
-
};
124
-
125
-
group = mkOption {
126
-
type = types.str;
127
-
default = "ugit";
128
-
description = "Group account under which ugit runs";
129
-
};
130
-
131
-
openFirewall = mkOption {
132
-
type = types.bool;
133
-
default = false;
134
-
};
135
-
};
54
+
}
55
+
);
56
+
nixosModules.default = import ./nix/module.nix;
57
+
nixosConfigurations.ugitVM = nixpkgs.lib.nixosSystem {
58
+
system = "x86_64-linux";
59
+
modules = [
60
+
./nix/vm.nix
61
+
{
62
+
virtualisation.vmVariant.virtualisation = {
63
+
cores = 2;
64
+
memorySize = 2048;
65
+
graphics = false;
66
+
};
67
+
system.stateVersion = "23.11";
68
+
}
69
+
];
136
70
};
137
-
config = lib.mkIf cfg.enable {
138
-
users.users."${cfg.user}" = {
139
-
home = "/var/lib/ugit";
140
-
createHome = true;
141
-
group = "${cfg.group}";
142
-
isSystemUser = true;
143
-
isNormalUser = false;
144
-
description = "user for ugit service";
145
-
};
146
-
users.groups."${cfg.group}" = {};
147
-
networking.firewall = lib.mkIf cfg.openFirewall {
148
-
allowedTCPPorts = [8448 8449];
149
-
};
150
-
151
-
systemd.services.ugit = {
152
-
enable = true;
153
-
script = let
154
-
authorizedKeysPath =
155
-
if (builtins.length cfg.authorizedKeys) > 0
156
-
then authorizedKeysFile
157
-
else cfg.authorizedKeysFile;
158
-
args = ["--config=${configFile}" "--repo-dir=${cfg.repoDir}" "--ssh.authorized-keys=${authorizedKeysPath}" "--ssh.host-key=${cfg.hostKeyFile}"];
159
-
in "${cfg.package}/bin/ugitd ${builtins.concatStringsSep " " args}";
160
-
wantedBy = ["multi-user.target"];
161
-
after = ["network.target"];
162
-
path = [cfg.package pkgs.git pkgs.bash];
163
-
serviceConfig = {
164
-
User = cfg.user;
165
-
Group = cfg.group;
166
-
Restart = "always";
167
-
RestartSec = "15";
168
-
WorkingDirectory = "/var/lib/ugit";
71
+
apps = forAllSystems (
72
+
system:
73
+
let
74
+
pkgs = import nixpkgs { inherit system; };
75
+
in
76
+
{
77
+
vm = {
78
+
type = "app";
79
+
program = "${pkgs.writeShellScript "vm" ''
80
+
nixos-rebuild build-vm --flake .#ugitVM
81
+
./result/bin/run-nixos-vm
82
+
rm nixos.qcow2
83
+
''}";
169
84
};
170
-
};
171
-
};
85
+
}
86
+
);
172
87
};
173
-
};
174
88
}
+66
-54
go.mod
+66
-54
go.mod
···
1
1
module go.jolheiser.com/ugit
2
2
3
-
go 1.21
3
+
go 1.23.1
4
4
5
-
toolchain go1.21.5
5
+
toolchain go1.23.3
6
6
7
7
require (
8
-
github.com/a-h/templ v0.2.543
9
-
github.com/alecthomas/chroma/v2 v2.12.0
10
-
github.com/charmbracelet/log v0.3.1
11
-
github.com/charmbracelet/ssh v0.0.0-20240201134204-3f297de25560
12
-
github.com/charmbracelet/wish v1.3.0
8
+
github.com/a-h/templ v0.3.924
9
+
github.com/alecthomas/assert/v2 v2.11.0
10
+
github.com/alecthomas/chroma/v2 v2.15.0
11
+
github.com/charmbracelet/ssh v0.0.0-20241211182756-4fe22b0f1b7c
12
+
github.com/charmbracelet/wish v1.4.4
13
13
github.com/dustin/go-humanize v1.0.1
14
-
github.com/go-chi/chi/v5 v5.0.11
14
+
github.com/go-chi/chi/v5 v5.2.0
15
15
github.com/go-chi/httplog/v2 v2.1.1
16
-
github.com/go-git/go-billy/v5 v5.5.0
17
-
github.com/go-git/go-git/v5 v5.11.0
16
+
github.com/go-git/go-billy/v5 v5.6.1
17
+
github.com/go-git/go-git/v5 v5.13.1
18
18
github.com/peterbourgon/ff/v3 v3.4.0
19
-
github.com/yuin/goldmark v1.6.0
20
-
github.com/yuin/goldmark-emoji v1.0.2
19
+
github.com/yuin/goldmark v1.7.12
20
+
github.com/yuin/goldmark-emoji v1.0.4
21
21
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
22
-
golang.org/x/net v0.25.0
22
+
go.jolheiser.com/ffcue v0.0.0-20250816031459-3e3e4f232e75
23
+
golang.org/x/net v0.42.0
23
24
)
24
25
25
26
require (
26
-
dario.cat/mergo v1.0.0 // indirect
27
-
github.com/Microsoft/go-winio v0.6.1 // indirect
28
-
github.com/ProtonMail/go-crypto v1.0.0 // indirect
27
+
cuelang.org/go v0.14.1 // indirect
28
+
dario.cat/mergo v1.0.1 // indirect
29
+
github.com/Microsoft/go-winio v0.6.2 // indirect
30
+
github.com/ProtonMail/go-crypto v1.1.4 // indirect
31
+
github.com/a-h/parse v0.0.0-20250122154542-74294addb73e // indirect
32
+
github.com/alecthomas/repr v0.4.0 // indirect
33
+
github.com/andybalholm/brotli v1.1.0 // indirect
29
34
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
30
-
github.com/atotto/clipboard v0.1.4 // indirect
31
35
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
32
-
github.com/catppuccin/go v0.2.0 // indirect
33
-
github.com/charmbracelet/bubbles v0.18.0 // indirect
34
-
github.com/charmbracelet/bubbletea v0.26.4 // indirect
35
-
github.com/charmbracelet/huh v0.5.1 // indirect
36
-
github.com/charmbracelet/keygen v0.5.0 // indirect
37
-
github.com/charmbracelet/lipgloss v0.11.0 // indirect
38
-
github.com/charmbracelet/x/ansi v0.1.2 // indirect
39
-
github.com/charmbracelet/x/errors v0.0.0-20240130180102-bafe6fbaee60 // indirect
40
-
github.com/charmbracelet/x/exp/strings v0.0.0-20240617190524-788ec55faed1 // indirect
41
-
github.com/charmbracelet/x/exp/term v0.0.0-20240524151031-ff83003bf67a // indirect
42
-
github.com/charmbracelet/x/input v0.1.2 // indirect
43
-
github.com/charmbracelet/x/term v0.1.1 // indirect
44
-
github.com/charmbracelet/x/windows v0.1.2 // indirect
45
-
github.com/cloudflare/circl v1.3.7 // indirect
46
-
github.com/containerd/console v1.0.4-0.20230706203907-8f6c4e4faef5 // indirect
47
-
github.com/creack/pty v1.1.21 // indirect
48
-
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
49
-
github.com/dlclark/regexp2 v1.10.0 // indirect
36
+
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
37
+
github.com/charmbracelet/bubbletea v1.2.4 // indirect
38
+
github.com/charmbracelet/keygen v0.5.1 // indirect
39
+
github.com/charmbracelet/lipgloss v1.0.0 // indirect
40
+
github.com/charmbracelet/log v0.4.0 // indirect
41
+
github.com/charmbracelet/x/ansi v0.6.0 // indirect
42
+
github.com/charmbracelet/x/conpty v0.1.0 // indirect
43
+
github.com/charmbracelet/x/errors v0.0.0-20250107110353-48b574af22a5 // indirect
44
+
github.com/charmbracelet/x/term v0.2.1 // indirect
45
+
github.com/charmbracelet/x/termios v0.1.0 // indirect
46
+
github.com/cli/browser v1.3.0 // indirect
47
+
github.com/cloudflare/circl v1.5.0 // indirect
48
+
github.com/cockroachdb/apd/v3 v3.2.1 // indirect
49
+
github.com/creack/pty v1.1.24 // indirect
50
+
github.com/cyphar/filepath-securejoin v0.3.6 // indirect
51
+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
52
+
github.com/dlclark/regexp2 v1.11.4 // indirect
53
+
github.com/emicklei/proto v1.14.2 // indirect
50
54
github.com/emirpasic/gods v1.18.1 // indirect
51
55
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
56
+
github.com/fatih/color v1.16.0 // indirect
57
+
github.com/fsnotify/fsnotify v1.7.0 // indirect
52
58
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
53
59
github.com/go-logfmt/logfmt v0.6.0 // indirect
54
-
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
60
+
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
61
+
github.com/google/uuid v1.6.0 // indirect
62
+
github.com/hexops/gotextdiff v1.0.3 // indirect
55
63
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
56
64
github.com/kevinburke/ssh_config v1.2.0 // indirect
57
65
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
66
+
github.com/mattn/go-colorable v0.1.13 // indirect
58
67
github.com/mattn/go-isatty v0.0.20 // indirect
59
68
github.com/mattn/go-localereader v0.0.1 // indirect
60
-
github.com/mattn/go-runewidth v0.0.15 // indirect
61
-
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
69
+
github.com/mattn/go-runewidth v0.0.16 // indirect
70
+
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
71
+
github.com/mmcloughlin/avo v0.6.0 // indirect
62
72
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
63
73
github.com/muesli/cancelreader v0.2.2 // indirect
64
-
github.com/muesli/reflow v0.3.0 // indirect
65
-
github.com/muesli/termenv v0.15.2 // indirect
66
-
github.com/pjbgf/sha1cd v0.3.0 // indirect
74
+
github.com/muesli/termenv v0.15.3-0.20240509142007-81b8f94111d5 // indirect
75
+
github.com/natefinch/atomic v1.0.1 // indirect
76
+
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
77
+
github.com/pjbgf/sha1cd v0.3.1 // indirect
78
+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
79
+
github.com/protocolbuffers/txtpbfmt v0.0.0-20250627152318-f293424e46b5 // indirect
67
80
github.com/rivo/uniseg v0.4.7 // indirect
68
-
github.com/sergi/go-diff v1.3.1 // indirect
69
-
github.com/skeema/knownhosts v1.2.1 // indirect
70
-
github.com/u-root/u-root v0.12.0 // indirect
81
+
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
82
+
github.com/skeema/knownhosts v1.3.0 // indirect
71
83
github.com/xanzy/ssh-agent v0.3.3 // indirect
72
-
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
73
-
golang.org/x/crypto v0.23.0 // indirect
74
-
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
75
-
golang.org/x/mod v0.17.0 // indirect
76
-
golang.org/x/sync v0.7.0 // indirect
77
-
golang.org/x/sys v0.21.0 // indirect
78
-
golang.org/x/term v0.20.0 // indirect
79
-
golang.org/x/text v0.16.0 // indirect
80
-
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
84
+
golang.org/x/crypto v0.40.0 // indirect
85
+
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
86
+
golang.org/x/mod v0.26.0 // indirect
87
+
golang.org/x/sync v0.16.0 // indirect
88
+
golang.org/x/sys v0.34.0 // indirect
89
+
golang.org/x/text v0.27.0 // indirect
90
+
golang.org/x/tools v0.35.0 // indirect
81
91
gopkg.in/warnings.v0 v0.1.2 // indirect
82
-
gopkg.in/yaml.v2 v2.4.0 // indirect
92
+
gopkg.in/yaml.v3 v3.0.1 // indirect
83
93
)
94
+
95
+
tool github.com/a-h/templ/cmd/templ
+1
-1
go.mod.sri
+1
-1
go.mod.sri
+151
-189
go.sum
+151
-189
go.sum
···
1
-
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
2
-
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
1
+
cuelabs.dev/go/oci/ociregistry v0.0.0-20250715075730-49cab49c8e9d h1:lX0EawyoAu4kgMJJfy7MmNkIHioBcdBGFRSKDZ+CWo0=
2
+
cuelabs.dev/go/oci/ociregistry v0.0.0-20250715075730-49cab49c8e9d/go.mod h1:4WWeZNxUO1vRoZWAHIG0KZOd6dA25ypyWuwD3ti0Tdc=
3
+
cuelang.org/go v0.14.1 h1:kxFAHr7bvrCikbtVps2chPIARazVdnRmlz65dAzKyWg=
4
+
cuelang.org/go v0.14.1/go.mod h1:aSP9UZUM5m2izHAHUvqtq0wTlWn5oLjuv2iBMQZBLLs=
5
+
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
6
+
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
3
7
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
4
-
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
5
-
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
6
-
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
7
-
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
8
-
github.com/a-h/templ v0.2.543 h1:8YyLvyUtf0/IE2nIwZ62Z/m2o2NqwhnMynzOL78Lzbk=
9
-
github.com/a-h/templ v0.2.543/go.mod h1:jP908DQCwI08IrnTalhzSEH9WJqG/Q94+EODQcJGFUA=
10
-
github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink=
11
-
github.com/alecthomas/assert/v2 v2.2.1/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ=
8
+
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
9
+
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
10
+
github.com/ProtonMail/go-crypto v1.1.4 h1:G5U5asvD5N/6/36oIw3k2bOfBn5XVcZrb7PBjzzKKoE=
11
+
github.com/ProtonMail/go-crypto v1.1.4/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
12
+
github.com/a-h/parse v0.0.0-20250122154542-74294addb73e h1:HjVbSQHy+dnlS6C3XajZ69NYAb5jbGNfHanvm1+iYlo=
13
+
github.com/a-h/parse v0.0.0-20250122154542-74294addb73e/go.mod h1:3mnrkvGpurZ4ZrTDbYU84xhwXW2TjTKShSwjRi2ihfQ=
14
+
github.com/a-h/templ v0.3.924 h1:t5gZqTneXqvehpNZsgtnlOscnBboNh9aASBH2MgV/0k=
15
+
github.com/a-h/templ v0.3.924/go.mod h1:FFAu4dI//ESmEN7PQkJ7E7QfnSEMdcnu7QrAY8Dn334=
16
+
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
17
+
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
12
18
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
13
-
github.com/alecthomas/chroma/v2 v2.12.0 h1:Wh8qLEgMMsN7mgyG8/qIpegky2Hvzr4By6gEF7cmWgw=
14
-
github.com/alecthomas/chroma/v2 v2.12.0/go.mod h1:4TQu7gdfuPjSh76j78ietmqh9LiurGF0EpseFXdKMBw=
19
+
github.com/alecthomas/chroma/v2 v2.15.0 h1:LxXTQHFoYrstG2nnV9y2X5O94sOBzf0CIUpSTbpxvMc=
20
+
github.com/alecthomas/chroma/v2 v2.15.0/go.mod h1:gUhVLrPDXPtp/f+L1jo9xepo9gL4eLwRuGAunSZMkio=
15
21
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
16
-
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
17
-
github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
22
+
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
23
+
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
24
+
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
25
+
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
18
26
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
19
27
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
20
28
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
21
29
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
22
-
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
23
-
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
24
30
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
25
31
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
26
-
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
27
-
github.com/catppuccin/go v0.2.0 h1:ktBeIrIP42b/8FGiScP9sgrWOss3lw0Z5SktRoithGA=
28
-
github.com/catppuccin/go v0.2.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc=
29
-
github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0=
30
-
github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw=
31
-
github.com/charmbracelet/bubbletea v0.25.0 h1:bAfwk7jRz7FKFl9RzlIULPkStffg5k6pNt5dywy4TcM=
32
-
github.com/charmbracelet/bubbletea v0.25.0/go.mod h1:EN3QDR1T5ZdWmdfDzYcqOCAps45+QIJbLOBxmVNWNNg=
33
-
github.com/charmbracelet/bubbletea v0.26.4 h1:2gDkkzLZaTjMl/dQBpNVtnvcCxsh/FCkimep7FC9c40=
34
-
github.com/charmbracelet/bubbletea v0.26.4/go.mod h1:P+r+RRA5qtI1DOHNFn0otoNwB4rn+zNAzSj/EXz6xU0=
35
-
github.com/charmbracelet/huh v0.5.1 h1:t5j6g9sMjAE2a9AQuc4lNL7pf/0X4WdHiiMGkL8v/aM=
36
-
github.com/charmbracelet/huh v0.5.1/go.mod h1:gs7b2brpzXkY0PBWUqJrlzvOowTCL0vNAR6OTItc+kA=
37
-
github.com/charmbracelet/keygen v0.5.0 h1:XY0fsoYiCSM9axkrU+2ziE6u6YjJulo/b9Dghnw6MZc=
38
-
github.com/charmbracelet/keygen v0.5.0/go.mod h1:DfvCgLHxZ9rJxdK0DGw3C/LkV4SgdGbnliHcObV3L+8=
39
-
github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg=
40
-
github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I=
41
-
github.com/charmbracelet/lipgloss v0.11.0 h1:UoAcbQ6Qml8hDwSWs0Y1cB5TEQuZkDPH/ZqwWWYTG4g=
42
-
github.com/charmbracelet/lipgloss v0.11.0/go.mod h1:1UdRTH9gYgpcdNN5oBtjbu/IzNKtzVtb7sqN1t9LNn8=
43
-
github.com/charmbracelet/log v0.3.1 h1:TjuY4OBNbxmHWSwO3tosgqs5I3biyY8sQPny/eCMTYw=
44
-
github.com/charmbracelet/log v0.3.1/go.mod h1:OR4E1hutLsax3ZKpXbgUqPtTjQfrh1pG3zwHGWuuq8g=
45
-
github.com/charmbracelet/ssh v0.0.0-20240201134204-3f297de25560 h1:kUYiDRF04AsyJvWi4HrklXXSU7+S7qjExusfDnYbVGg=
46
-
github.com/charmbracelet/ssh v0.0.0-20240201134204-3f297de25560/go.mod h1:IHy7o73i1MrQ5lmyJjjJ0g7y4+V+g69cm+Y7JCiZWPo=
47
-
github.com/charmbracelet/wish v1.3.0 h1:SYV5TIlzDb6WaxjkkYXxv2WZsTu/QZGwfGVc0UB5M48=
48
-
github.com/charmbracelet/wish v1.3.0/go.mod h1:1U/bI7zX+IE26ThD5gxtLgeRzctVhSrTpjucPqw4Pos=
49
-
github.com/charmbracelet/x/ansi v0.1.2 h1:6+LR39uG8DE6zAmbu023YlqjJHkYXDF1z36ZwzO4xZY=
50
-
github.com/charmbracelet/x/ansi v0.1.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
51
-
github.com/charmbracelet/x/errors v0.0.0-20240130180102-bafe6fbaee60 h1:u0XFhTN81zvoGwyQWOYjjkrimEQj5L2DPECCX5cBsRw=
52
-
github.com/charmbracelet/x/errors v0.0.0-20240130180102-bafe6fbaee60/go.mod h1:2P0UgXMEa6TsToMSuFqKFQR+fZTO9CNGUNokkPatT/0=
53
-
github.com/charmbracelet/x/exp/strings v0.0.0-20240617190524-788ec55faed1 h1:VZIQzjwFE0EamzG2v8HfemeisB8X02Tl0BZBnJ0PeU8=
54
-
github.com/charmbracelet/x/exp/strings v0.0.0-20240617190524-788ec55faed1/go.mod h1:pBhA0ybfXv6hDjQUZ7hk1lVxBiUbupdw5R31yPUViVQ=
55
-
github.com/charmbracelet/x/exp/term v0.0.0-20240130180102-bafe6fbaee60 h1:IV19YKUZVf6ATrhiPSCirZ4Bs7EsenYwOWcUHngV+q0=
56
-
github.com/charmbracelet/x/exp/term v0.0.0-20240130180102-bafe6fbaee60/go.mod h1:kOOxxyxgAFQVcR5yQJWTuLjzt5dR2pcgwy3WaLEudjE=
57
-
github.com/charmbracelet/x/exp/term v0.0.0-20240524151031-ff83003bf67a h1:k/s6UoOSVynWiw7PlclyGO2VdVs5ZLbMIHiGp4shFZE=
58
-
github.com/charmbracelet/x/exp/term v0.0.0-20240524151031-ff83003bf67a/go.mod h1:YBotIGhfoWhHDlnUpJMkjebGV2pdGRCn1Y4/Nk/vVcU=
59
-
github.com/charmbracelet/x/input v0.1.2 h1:QJAZr33eOhDowkkEQ24rsJy4Llxlm+fRDf/cQrmqJa0=
60
-
github.com/charmbracelet/x/input v0.1.2/go.mod h1:LGBim0maUY4Pitjn/4fHnuXb4KirU3DODsyuHuXdOyA=
61
-
github.com/charmbracelet/x/term v0.1.1 h1:3cosVAiPOig+EV4X9U+3LDgtwwAoEzJjNdwbXDjF6yI=
62
-
github.com/charmbracelet/x/term v0.1.1/go.mod h1:wB1fHt5ECsu3mXYusyzcngVWWlu1KKUmmLhfgr/Flxw=
63
-
github.com/charmbracelet/x/windows v0.1.2 h1:Iumiwq2G+BRmgoayww/qfcvof7W/3uLoelhxojXlRWg=
64
-
github.com/charmbracelet/x/windows v0.1.2/go.mod h1:GLEO/l+lizvFDBPLIOk+49gdX49L9YWMB5t+DZd0jkQ=
65
-
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
66
-
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
67
-
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
68
-
github.com/containerd/console v1.0.4-0.20230706203907-8f6c4e4faef5 h1:Ig+OPkE3XQrrl+SKsOqAjlkrBN/zrr+Qpw7rCuDjRCE=
69
-
github.com/containerd/console v1.0.4-0.20230706203907-8f6c4e4faef5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
70
-
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
71
-
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
72
-
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
73
-
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
32
+
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
33
+
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
34
+
github.com/charmbracelet/bubbletea v1.2.4 h1:KN8aCViA0eps9SCOThb2/XPIlea3ANJLUkv3KnQRNCE=
35
+
github.com/charmbracelet/bubbletea v1.2.4/go.mod h1:Qr6fVQw+wX7JkWWkVyXYk/ZUQ92a6XNekLXa3rR18MM=
36
+
github.com/charmbracelet/keygen v0.5.1 h1:zBkkYPtmKDVTw+cwUyY6ZwGDhRxXkEp0Oxs9sqMLqxI=
37
+
github.com/charmbracelet/keygen v0.5.1/go.mod h1:zznJVmK/GWB6dAtjluqn2qsttiCBhA5MZSiwb80fcHw=
38
+
github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg=
39
+
github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo=
40
+
github.com/charmbracelet/log v0.4.0 h1:G9bQAcx8rWA2T3pWvx7YtPTPwgqpk7D68BX21IRW8ZM=
41
+
github.com/charmbracelet/log v0.4.0/go.mod h1:63bXt/djrizTec0l11H20t8FDSvA4CRZJ1KH22MdptM=
42
+
github.com/charmbracelet/ssh v0.0.0-20241211182756-4fe22b0f1b7c h1:treQxMBdI2PaD4eOYfFux8stfCkUxhuUxaqGcxKqVpI=
43
+
github.com/charmbracelet/ssh v0.0.0-20241211182756-4fe22b0f1b7c/go.mod h1:CY1xbl2z+ZeBmNWItKZyxx0zgDgnhmR57+DTsHOobJ4=
44
+
github.com/charmbracelet/wish v1.4.4 h1:wtfoAMkf8Db9zi+9Lme2f7XKMxL6BqfgDWbqcTUHLaU=
45
+
github.com/charmbracelet/wish v1.4.4/go.mod h1:XB8v51UxIFMRlUod9lLaAgOsj/wpe+qW9HjsoYIiNMo=
46
+
github.com/charmbracelet/x/ansi v0.6.0 h1:qOznutrb93gx9oMiGf7caF7bqqubh6YIM0SWKyA08pA=
47
+
github.com/charmbracelet/x/ansi v0.6.0/go.mod h1:KBUFw1la39nl0dLl10l5ORDAqGXaeurTQmwyyVKse/Q=
48
+
github.com/charmbracelet/x/conpty v0.1.0 h1:4zc8KaIcbiL4mghEON8D72agYtSeIgq8FSThSPQIb+U=
49
+
github.com/charmbracelet/x/conpty v0.1.0/go.mod h1:rMFsDJoDwVmiYM10aD4bH2XiRgwI7NYJtQgl5yskjEQ=
50
+
github.com/charmbracelet/x/errors v0.0.0-20250107110353-48b574af22a5 h1:Hx72S6S4jAfrrWE3pv9IbudVdUV4htBgkOX800o17Bk=
51
+
github.com/charmbracelet/x/errors v0.0.0-20250107110353-48b574af22a5/go.mod h1:2P0UgXMEa6TsToMSuFqKFQR+fZTO9CNGUNokkPatT/0=
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.0 h1:y4rjAHeFksBAfGbkRDmVinMg7x7DELIGAFbdNvxg97k=
55
+
github.com/charmbracelet/x/termios v0.1.0/go.mod h1:H/EVv/KRnrYjz+fCYa9bsKdqF3S8ouDK0AZEbG7r+/U=
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/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/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg=
61
+
github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc=
62
+
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
63
+
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
64
+
github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM=
65
+
github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
74
66
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
75
-
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
76
67
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
68
+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
69
+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
77
70
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
78
71
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
79
-
github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
80
-
github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
72
+
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
73
+
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
81
74
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
82
75
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
83
-
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
84
-
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
76
+
github.com/elazarl/goproxy v1.2.3 h1:xwIyKHbaP5yfT6O9KIeYJR5549MXRQkoQMRXGztz8YQ=
77
+
github.com/elazarl/goproxy v1.2.3/go.mod h1:YfEbZtqP4AetfO6d40vWchF3znWX7C7Vd6ZMfdL8z64=
78
+
github.com/emicklei/proto v1.14.2 h1:wJPxPy2Xifja9cEMrcA/g08art5+7CGJNFNk35iXC1I=
79
+
github.com/emicklei/proto v1.14.2/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A=
85
80
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
86
81
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
87
82
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
88
83
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
89
-
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
90
-
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
91
-
github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA=
92
-
github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
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.0 h1:Aj1EtB0qR2Rdo2dG4O94RIU35w2lvQSj6BRA4+qwFL0=
91
+
github.com/go-chi/chi/v5 v5.2.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
93
92
github.com/go-chi/httplog/v2 v2.1.1 h1:ojojiu4PIaoeJ/qAO4GWUxJqvYUTobeo7zmuHQJAxRk=
94
93
github.com/go-chi/httplog/v2 v2.1.1/go.mod h1:/XXdxicJsp4BA5fapgIC3VuTD+z0Z/VzukoB3VDc1YE=
95
94
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
96
95
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
97
-
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
98
-
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
96
+
github.com/go-git/go-billy/v5 v5.6.1 h1:u+dcrgaguSSkbjzHwelEjc0Yj300NUevrrPphk/SoRA=
97
+
github.com/go-git/go-billy/v5 v5.6.1/go.mod h1:0AsLr1z2+Uksi4NlElmMblP5rPcDZNRCD8ujZCRR2BE=
99
98
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
100
99
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
101
-
github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
102
-
github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
100
+
github.com/go-git/go-git/v5 v5.13.1 h1:DAQ9APonnlvSWpvolXWIuV6Q6zXy2wHbN4cVlNR5Q+M=
101
+
github.com/go-git/go-git/v5 v5.13.1/go.mod h1:qryJB4cSBoq3FRoBRf5A77joojuBcmPJ0qu3XXXVixc=
103
102
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
104
103
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
105
-
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
106
-
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
107
-
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
108
-
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
104
+
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
105
+
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
106
+
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
107
+
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
108
+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
109
+
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
110
+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
111
+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
109
112
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
110
113
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
111
-
github.com/hugelgupf/vmtest v0.0.0-20240102225328-693afabdd27f h1:ov45/OzrJG8EKbGjn7jJZQJTN7Z1t73sFYNIRd64YlI=
112
-
github.com/hugelgupf/vmtest v0.0.0-20240102225328-693afabdd27f/go.mod h1:JoDrYMZpDPYo6uH9/f6Peqms3zNNWT2XiGgioMOIGuI=
113
114
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
114
115
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
115
116
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
···
121
122
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
122
123
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
123
124
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
125
+
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
126
+
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
127
+
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
128
+
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
124
129
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
125
130
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
131
+
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
132
+
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
133
+
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
126
134
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
127
135
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
128
136
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
129
137
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
130
-
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
131
-
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
132
-
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
133
-
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
134
-
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
138
+
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
139
+
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
140
+
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
141
+
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
142
+
github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY=
143
+
github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8=
135
144
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
136
145
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
137
146
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
138
147
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
139
-
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
140
-
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
141
-
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
142
-
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
143
-
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
144
-
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
148
+
github.com/muesli/termenv v0.15.3-0.20240509142007-81b8f94111d5 h1:NiONcKK0EV5gUZcnCiPMORaZA0eBDc+Fgepl9xl4lZ8=
149
+
github.com/muesli/termenv v0.15.3-0.20240509142007-81b8f94111d5/go.mod h1:hxSnBBYLK21Vtq/PHd0S2FYCxBXzBua8ov5s1RobyRQ=
150
+
github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A=
151
+
github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM=
152
+
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
153
+
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
154
+
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
155
+
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
156
+
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
157
+
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
158
+
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
159
+
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
145
160
github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc=
146
161
github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ=
147
-
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
148
-
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
162
+
github.com/pjbgf/sha1cd v0.3.1 h1:Dh2GYdpJnO84lIw0LJwTFXjcNbasP/bklicSznyAaPI=
163
+
github.com/pjbgf/sha1cd v0.3.1/go.mod h1:Y8t7jSB/dEI/lQE04A1HVKteqjj9bX5O4+Cex0TCu8s=
149
164
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
150
165
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
151
-
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
152
166
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
153
-
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
167
+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
168
+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
169
+
github.com/protocolbuffers/txtpbfmt v0.0.0-20250627152318-f293424e46b5 h1:WWs1ZFnGobK5ZXNu+N9If+8PDNVB9xAqrib/stUXsV4=
170
+
github.com/protocolbuffers/txtpbfmt v0.0.0-20250627152318-f293424e46b5/go.mod h1:BnHogPTyzYAReeQLZrOxyxzS739DaTNtTvohVdbENmA=
154
171
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
155
-
github.com/rivo/uniseg v0.4.6 h1:Sovz9sDSwbOz9tgUy8JpT+KgCkPYJEN/oYzlJiYTNLg=
156
-
github.com/rivo/uniseg v0.4.6/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
157
172
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
158
173
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
159
-
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
160
-
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
161
-
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
162
-
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
174
+
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
175
+
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
176
+
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
177
+
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
163
178
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
164
-
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
165
-
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
179
+
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
180
+
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
166
181
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
167
182
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
168
183
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
169
184
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
170
-
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
171
-
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
172
-
github.com/u-root/gobusybox/src v0.0.0-20231228173702-b69f654846aa h1:unMPGGK/CRzfg923allsikmvk2l7beBeFPUNC4RVX/8=
173
-
github.com/u-root/gobusybox/src v0.0.0-20231228173702-b69f654846aa/go.mod h1:Zj4Tt22fJVn/nz/y6Ergm1SahR9dio1Zm/D2/S0TmXM=
174
-
github.com/u-root/u-root v0.12.0 h1:K0AuBFriwr0w/PGS3HawiAw89e3+MU7ks80GpghAsNs=
175
-
github.com/u-root/u-root v0.12.0/go.mod h1:FYjTOh4IkIZHhjsd17lb8nYW6udgXdJhG1c0r6u0arI=
185
+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
186
+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
176
187
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
177
188
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
178
-
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
179
-
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
180
-
github.com/yuin/goldmark v1.3.7/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
181
-
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
182
189
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
183
-
github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
184
-
github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
185
-
github.com/yuin/goldmark-emoji v1.0.2 h1:c/RgTShNgHTtc6xdz2KKI74jJr6rWi7FPgnP9GAsO5s=
186
-
github.com/yuin/goldmark-emoji v1.0.2/go.mod h1:RhP/RWpexdp+KHs7ghKnifRoIs/Bq4nDS7tRbCkOwKY=
190
+
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
191
+
github.com/yuin/goldmark v1.7.12 h1:YwGP/rrea2/CnCtUHgjuolG/PnMxdQtPMO5PvaE2/nY=
192
+
github.com/yuin/goldmark v1.7.12/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
193
+
github.com/yuin/goldmark-emoji v1.0.4 h1:vCwMkPZSNefSUnOW2ZKRUjBSD5Ok3W78IXhGxxAEF90=
194
+
github.com/yuin/goldmark-emoji v1.0.4/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U=
187
195
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
188
196
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
189
-
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
190
-
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
197
+
go.jolheiser.com/ffcue v0.0.0-20250816031459-3e3e4f232e75 h1:hu2LcTy2bvgmfEDuaDCfpWIzWN1pHAKfUkAnpgjZYco=
198
+
go.jolheiser.com/ffcue v0.0.0-20250816031459-3e3e4f232e75/go.mod h1:IrDGUkvU3xl27+Seb20ZE/H2dzG95m/xmu0Z/B3crUE=
191
199
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
192
-
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
193
-
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
194
-
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
195
-
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
196
-
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
197
-
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
198
-
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
199
-
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
200
-
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
201
-
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
202
-
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
203
-
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
204
-
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
205
-
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
206
-
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
200
+
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
201
+
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
202
+
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
203
+
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
204
+
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
205
+
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
207
206
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
208
-
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
209
-
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
210
-
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
211
-
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
212
-
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
213
-
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
214
-
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
215
-
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
216
-
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
217
-
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
218
-
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
219
-
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
220
-
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
221
-
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
222
-
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
207
+
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
208
+
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
209
+
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
210
+
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
211
+
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
212
+
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
223
213
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
224
214
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
225
215
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
226
216
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
227
217
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
228
218
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
229
-
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
230
219
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
231
-
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
232
-
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
233
-
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
234
-
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
235
-
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
220
+
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
236
221
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
237
-
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
238
-
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
239
-
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
240
-
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
222
+
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
223
+
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
241
224
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
242
-
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
243
-
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
244
-
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
245
-
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
246
-
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
247
-
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
248
-
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
249
-
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
250
-
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
251
-
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
225
+
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
226
+
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
252
227
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
253
-
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
254
-
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
255
-
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
256
-
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
257
-
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
258
-
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
259
-
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
260
-
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
228
+
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
229
+
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
261
230
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
262
-
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
263
-
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
264
-
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
265
-
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
266
-
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
267
-
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
268
-
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
269
-
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
231
+
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
232
+
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
270
233
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
271
234
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
272
235
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
···
274
237
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
275
238
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
276
239
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
277
-
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
278
240
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
279
241
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
280
242
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
-180
gomod2nix.toml
-180
gomod2nix.toml
···
1
-
schema = 3
2
-
3
-
[mod]
4
-
[mod."dario.cat/mergo"]
5
-
version = "v1.0.0"
6
-
hash = "sha256-jlpc8dDj+DmiOU4gEawBu8poJJj9My0s9Mvuk9oS8ww="
7
-
[mod."github.com/Microsoft/go-winio"]
8
-
version = "v0.6.1"
9
-
hash = "sha256-BL0BVaHtmPKQts/711W59AbHXjGKqFS4ZTal0RYnR9I="
10
-
[mod."github.com/ProtonMail/go-crypto"]
11
-
version = "v1.0.0"
12
-
hash = "sha256-Gflazvyv+457FpUTtPafJ+SdolYSalpsU0tragTxNi8="
13
-
[mod."github.com/a-h/templ"]
14
-
version = "v0.2.543"
15
-
hash = "sha256-1BvIj9UPZJp8SOXMPIGdHyZLIvjORHg2UY3pRZJM01s="
16
-
[mod."github.com/alecthomas/chroma/v2"]
17
-
version = "v2.12.0"
18
-
hash = "sha256-w3gKGPwsoayknuU4ifPaF0JOMNqnKjIEutbIkR9c2Ag="
19
-
[mod."github.com/anmitsu/go-shlex"]
20
-
version = "v0.0.0-20200514113438-38f4b401e2be"
21
-
hash = "sha256-L3Ak4X2z7WXq7vMKuiHCOJ29nlpajUQ08Sfb9T0yP54="
22
-
[mod."github.com/aymanbagabas/go-osc52/v2"]
23
-
version = "v2.0.1"
24
-
hash = "sha256-6Bp0jBZ6npvsYcKZGHHIUSVSTAMEyieweAX2YAKDjjg="
25
-
[mod."github.com/charmbracelet/bubbletea"]
26
-
version = "v0.25.0"
27
-
hash = "sha256-A0WjFRFAUhwO3m7uvCOeefPPIM8ReU+xTtIRxG0aH+Y="
28
-
[mod."github.com/charmbracelet/keygen"]
29
-
version = "v0.5.0"
30
-
hash = "sha256-JFD2SdFL7tq3oVhnBEgiBTrJvjqdUtIuodAJuSFcJoA="
31
-
[mod."github.com/charmbracelet/lipgloss"]
32
-
version = "v0.9.1"
33
-
hash = "sha256-AHbabOymgDRIXsMBgJHS25/GgBWT54oGbd15EBWKeZc="
34
-
[mod."github.com/charmbracelet/log"]
35
-
version = "v0.3.1"
36
-
hash = "sha256-Er60POPID2eNrRZnBHxoI4yHn0mIKnXYftGKSslbXx0="
37
-
[mod."github.com/charmbracelet/ssh"]
38
-
version = "v0.0.0-20240201134204-3f297de25560"
39
-
hash = "sha256-r4h4bym47rs3C2us+sCgVfwAl4TCbm3bDCTsXKYREz8="
40
-
[mod."github.com/charmbracelet/wish"]
41
-
version = "v1.3.0"
42
-
hash = "sha256-3Uq1PDu5DMoWgJykFx/roGk20x8jdb7o5JFPpmEtX/c="
43
-
[mod."github.com/charmbracelet/x/errors"]
44
-
version = "v0.0.0-20240130180102-bafe6fbaee60"
45
-
hash = "sha256-GO8hf0lhVtl00C+xoTzvBtPU2cO0PymSLc2szBRUNtE="
46
-
[mod."github.com/charmbracelet/x/exp/term"]
47
-
version = "v0.0.0-20240130180102-bafe6fbaee60"
48
-
hash = "sha256-hEj/Gj1U1ahk5EFVZVAL52yrdBNO47yXykpiehJICbc="
49
-
[mod."github.com/cloudflare/circl"]
50
-
version = "v1.3.7"
51
-
hash = "sha256-AkOpcZ+evLxLJStvvr01+TLeWDqcLxY3e/AhGggzh40="
52
-
[mod."github.com/containerd/console"]
53
-
version = "v1.0.4-0.20230706203907-8f6c4e4faef5"
54
-
hash = "sha256-mxRERsgS6TmI5I0UYblhzl2FZlbtkJhUkfF1x6mZINw="
55
-
[mod."github.com/creack/pty"]
56
-
version = "v1.1.21"
57
-
hash = "sha256-pjGw6wQlrVhN65XaIxZueNJqnXThGu00u24rKOLzxS0="
58
-
[mod."github.com/cyphar/filepath-securejoin"]
59
-
version = "v0.2.4"
60
-
hash = "sha256-heCD0xMxlwnHCHcRBgTjVexHOLyWI2zRW3E8NFKoLzk="
61
-
[mod."github.com/dlclark/regexp2"]
62
-
version = "v1.10.0"
63
-
hash = "sha256-Jxzj/O/Q9tIWBOOgCkCibhrgJBzzfVIxYDsabt7O8ow="
64
-
[mod."github.com/dustin/go-humanize"]
65
-
version = "v1.0.1"
66
-
hash = "sha256-yuvxYYngpfVkUg9yAmG99IUVmADTQA0tMbBXe0Fq0Mc="
67
-
[mod."github.com/emirpasic/gods"]
68
-
version = "v1.18.1"
69
-
hash = "sha256-hGDKddjLj+5dn2woHtXKUdd49/3xdsqnhx7VEdCu1m4="
70
-
[mod."github.com/go-chi/chi/v5"]
71
-
version = "v5.0.11"
72
-
hash = "sha256-95LKg/OVzhik2HUz6cirHH3eAT4qbHSg52bSvkc+XOY="
73
-
[mod."github.com/go-git/gcfg"]
74
-
version = "v1.5.1-0.20230307220236-3a3c6141e376"
75
-
hash = "sha256-f4k0gSYuo0/q3WOoTxl2eFaj7WZpdz29ih6CKc8Ude8="
76
-
[mod."github.com/go-git/go-billy/v5"]
77
-
version = "v5.5.0"
78
-
hash = "sha256-4XUoD2bOCMCdu83egb/y8kY/Fm0s1rWgPMtiahh38OQ="
79
-
[mod."github.com/go-git/go-git/v5"]
80
-
version = "v5.11.0"
81
-
hash = "sha256-2yUM/FlV+nYxacVynJCnDZeMub4Iu8JL2WBHmlnwOkE="
82
-
[mod."github.com/go-logfmt/logfmt"]
83
-
version = "v0.6.0"
84
-
hash = "sha256-RtIG2qARd5sT10WQ7F3LR8YJhS8exs+KiuUiVf75bWg="
85
-
[mod."github.com/golang/groupcache"]
86
-
version = "v0.0.0-20210331224755-41bb18bfe9da"
87
-
hash = "sha256-7Gs7CS9gEYZkbu5P4hqPGBpeGZWC64VDwraSKFF+VR0="
88
-
[mod."github.com/jbenet/go-context"]
89
-
version = "v0.0.0-20150711004518-d14ea06fba99"
90
-
hash = "sha256-VANNCWNNpARH/ILQV9sCQsBWgyL2iFT+4AHZREpxIWE="
91
-
[mod."github.com/kevinburke/ssh_config"]
92
-
version = "v1.2.0"
93
-
hash = "sha256-Ta7ZOmyX8gG5tzWbY2oES70EJPfI90U7CIJS9EAce0s="
94
-
[mod."github.com/lucasb-eyer/go-colorful"]
95
-
version = "v1.2.0"
96
-
hash = "sha256-Gg9dDJFCTaHrKHRR1SrJgZ8fWieJkybljybkI9x0gyE="
97
-
[mod."github.com/mattn/go-isatty"]
98
-
version = "v0.0.20"
99
-
hash = "sha256-qhw9hWtU5wnyFyuMbKx+7RB8ckQaFQ8D+8GKPkN3HHQ="
100
-
[mod."github.com/mattn/go-localereader"]
101
-
version = "v0.0.1"
102
-
hash = "sha256-JlWckeGaWG+bXK8l8WEdZqmSiTwCA8b1qbmBKa/Fj3E="
103
-
[mod."github.com/mattn/go-runewidth"]
104
-
version = "v0.0.15"
105
-
hash = "sha256-WP39EU2UrQbByYfnwrkBDoKN7xzXsBssDq3pNryBGm0="
106
-
[mod."github.com/muesli/ansi"]
107
-
version = "v0.0.0-20230316100256-276c6243b2f6"
108
-
hash = "sha256-qRKn0Bh2yvP0QxeEMeZe11Vz0BPFIkVcleKsPeybKMs="
109
-
[mod."github.com/muesli/cancelreader"]
110
-
version = "v0.2.2"
111
-
hash = "sha256-uEPpzwRJBJsQWBw6M71FDfgJuR7n55d/7IV8MO+rpwQ="
112
-
[mod."github.com/muesli/reflow"]
113
-
version = "v0.3.0"
114
-
hash = "sha256-Pou2ybE9SFSZG6YfZLVV1Eyfm+X4FuVpDPLxhpn47Cc="
115
-
[mod."github.com/muesli/termenv"]
116
-
version = "v0.15.2"
117
-
hash = "sha256-Eum/SpyytcNIchANPkG4bYGBgcezLgej7j/+6IhqoMU="
118
-
[mod."github.com/peterbourgon/ff/v3"]
119
-
version = "v3.4.0"
120
-
hash = "sha256-rmRl4GSmc2atnMbw6hTs6jwxW5lO4ivYuF2VN3jacZM="
121
-
[mod."github.com/pjbgf/sha1cd"]
122
-
version = "v0.3.0"
123
-
hash = "sha256-kX9BdLh2dxtGNaDvc24NORO+C0AZ7JzbrXrtecCdB7w="
124
-
[mod."github.com/rivo/uniseg"]
125
-
version = "v0.4.6"
126
-
hash = "sha256-zGfzO8FWj03POzo47SzrK1B4yLMKJ7iic6ium76ZLzI="
127
-
[mod."github.com/sergi/go-diff"]
128
-
version = "v1.3.1"
129
-
hash = "sha256-XLA/BLIPuUU76yikXqIeRSXr7T7A3Uz6I27+mDxGj7w="
130
-
[mod."github.com/skeema/knownhosts"]
131
-
version = "v1.2.1"
132
-
hash = "sha256-u0jB6ahTdGa+SvcIvPNRLnbSHvgmW9X/ThRq0nWQrJs="
133
-
[mod."github.com/u-root/u-root"]
134
-
version = "v0.12.0"
135
-
hash = "sha256-B9Qoq1S0l0W6twET54uxiWjh2ulxN/zMLAeWJX4cXW0="
136
-
[mod."github.com/xanzy/ssh-agent"]
137
-
version = "v0.3.3"
138
-
hash = "sha256-l3pGB6IdzcPA/HLk93sSN6NM2pKPy+bVOoacR5RC2+c="
139
-
[mod."github.com/yuin/goldmark"]
140
-
version = "v1.6.0"
141
-
hash = "sha256-0PeGjGxxM7lUSx2dn8yPUBpilPQzEN9nkgf3s+5zGTY="
142
-
[mod."github.com/yuin/goldmark-emoji"]
143
-
version = "v1.0.2"
144
-
hash = "sha256-RvzhNXlF98fu9SD/Rve9JMtR4bcRh7rN56Twhh/kmt4="
145
-
[mod."github.com/yuin/goldmark-highlighting/v2"]
146
-
version = "v2.0.0-20230729083705-37449abec8cc"
147
-
hash = "sha256-HpiwU7jIeDUAg2zOpTIiviQir8dpRPuXYh2nqFFccpg="
148
-
[mod."golang.org/x/crypto"]
149
-
version = "v0.18.0"
150
-
hash = "sha256-BuMVUxOIyfLo8MOhqYt+uQ8NDN6P2KdblKyfPxINzQ4="
151
-
[mod."golang.org/x/exp"]
152
-
version = "v0.0.0-20240119083558-1b970713d09a"
153
-
hash = "sha256-JQ3JLywTjgboNhs12blhOkS3ty7m8sUa/zaWv1k/X28="
154
-
[mod."golang.org/x/mod"]
155
-
version = "v0.14.0"
156
-
hash = "sha256-sx3hWp5l99DBfIrn821ohfoBwvaITSHMWbzPvX0btLM="
157
-
[mod."golang.org/x/net"]
158
-
version = "v0.20.0"
159
-
hash = "sha256-PCttIsWSBQd6fDXL49jepszUAMLnAGAKR//5EDO3XDk="
160
-
[mod."golang.org/x/sync"]
161
-
version = "v0.6.0"
162
-
hash = "sha256-LLims/wjDZtIqlYCVHREewcUOX4hwRwplEuZKPOJ/HI="
163
-
[mod."golang.org/x/sys"]
164
-
version = "v0.16.0"
165
-
hash = "sha256-ZkGclbp2S7NQYhbuGji6XokCn2Qi1BJy8dwyAOTV8sY="
166
-
[mod."golang.org/x/term"]
167
-
version = "v0.16.0"
168
-
hash = "sha256-9qlHcsCI1sa7ZI4Q+fJbOp3mG5Y+uV16e+pGmG+MQe0="
169
-
[mod."golang.org/x/text"]
170
-
version = "v0.14.0"
171
-
hash = "sha256-yh3B0tom1RfzQBf1RNmfdNWF1PtiqxV41jW1GVS6JAg="
172
-
[mod."golang.org/x/tools"]
173
-
version = "v0.17.0"
174
-
hash = "sha256-CxuHfKKtUkn3VjA7D9WQjzvV1EUbyI/xMNhb5CxO6IQ="
175
-
[mod."gopkg.in/warnings.v0"]
176
-
version = "v0.1.2"
177
-
hash = "sha256-ATVL9yEmgYbkJ1DkltDGRn/auGAjqGOfjQyBYyUo8s8="
178
-
[mod."gopkg.in/yaml.v2"]
179
-
version = "v2.4.0"
180
-
hash = "sha256-uVEGglIedjOIGZzHW4YwN1VoRSTK8o0eGZqzd+TNdd0="
+20
-2
internal/git/git.go
+20
-2
internal/git/git.go
···
98
98
}
99
99
}
100
100
101
-
fis := make([]FileInfo, 0)
101
+
fis := make([]FileInfo, 0, len(t.Entries))
102
102
for _, entry := range t.Entries {
103
103
fm, err := entry.Mode.ToOSFileMode()
104
104
if err != nil {
···
118
118
sort.Slice(fis, func(i, j int) bool {
119
119
fi1 := fis[i]
120
120
fi2 := fis[j]
121
-
return (fi1.IsDir && !fi2.IsDir) || fi1.Name() < fi2.Name()
121
+
if fi1.IsDir != fi2.IsDir {
122
+
return fi1.IsDir
123
+
}
124
+
return fi1.Name() < fi2.Name()
122
125
})
123
126
124
127
return fis, nil
128
+
}
129
+
130
+
// GetCommitFromRef returns the commit object for a given ref
131
+
func (r Repo) GetCommitFromRef(ref string) (*object.Commit, error) {
132
+
g, err := r.Git()
133
+
if err != nil {
134
+
return nil, err
135
+
}
136
+
137
+
hash, err := g.ResolveRevision(plumbing.Revision(ref))
138
+
if err != nil {
139
+
return nil, err
140
+
}
141
+
142
+
return g.CommitObject(*hash)
125
143
}
126
144
127
145
// FileContent returns the content of a file in the git tree at a given ref/rev
+276
internal/git/git_test.go
+276
internal/git/git_test.go
···
1
+
package git_test
2
+
3
+
import (
4
+
"path/filepath"
5
+
"testing"
6
+
"time"
7
+
8
+
"github.com/alecthomas/assert/v2"
9
+
"github.com/go-git/go-git/v5/plumbing/protocol/packp"
10
+
"go.jolheiser.com/ugit/internal/git"
11
+
)
12
+
13
+
func TestEnsureRepo(t *testing.T) {
14
+
tmp := t.TempDir()
15
+
16
+
ok, err := git.PathExists(filepath.Join(tmp, "test"))
17
+
assert.False(t, ok, "repo should not exist yet")
18
+
assert.NoError(t, err, "PathExists should not error when repo doesn't exist")
19
+
20
+
err = git.EnsureRepo(tmp, "test")
21
+
assert.NoError(t, err, "repo should be created")
22
+
23
+
ok, err = git.PathExists(filepath.Join(tmp, "test"))
24
+
assert.True(t, ok, "repo should exist")
25
+
assert.NoError(t, err, "EnsureRepo should not error when path exists")
26
+
27
+
err = git.EnsureRepo(tmp, "test")
28
+
assert.NoError(t, err, "repo should already exist")
29
+
}
30
+
31
+
func TestRepo(t *testing.T) {
32
+
tmp := t.TempDir()
33
+
err := git.EnsureRepo(tmp, "test.git")
34
+
assert.NoError(t, err, "should create repo")
35
+
36
+
repo, err := git.NewRepo(tmp, "test")
37
+
assert.NoError(t, err, "should init new repo")
38
+
assert.True(t, repo.Meta.Private, "repo should default to private")
39
+
40
+
repo.Meta.Private = false
41
+
err = repo.SaveMeta()
42
+
assert.NoError(t, err, "should save repo meta")
43
+
44
+
repo, err = git.NewRepo(tmp, "test")
45
+
assert.NoError(t, err, "should not error when getting existing repo")
46
+
assert.False(t, repo.Meta.Private, "repo should be public after saving meta")
47
+
}
48
+
49
+
func TestPathExists(t *testing.T) {
50
+
tmp := t.TempDir()
51
+
exists, err := git.PathExists(tmp)
52
+
assert.NoError(t, err)
53
+
assert.True(t, exists)
54
+
55
+
doesNotExist := filepath.Join(tmp, "does-not-exist")
56
+
exists, err = git.PathExists(doesNotExist)
57
+
assert.NoError(t, err)
58
+
assert.False(t, exists)
59
+
}
60
+
61
+
func TestRepoMetaUpdate(t *testing.T) {
62
+
original := git.RepoMeta{
63
+
Description: "Original description",
64
+
Private: true,
65
+
Tags: git.TagSet{"tag1": struct{}{}, "tag2": struct{}{}},
66
+
}
67
+
68
+
update := git.RepoMeta{
69
+
Description: "Updated description",
70
+
Private: false,
71
+
Tags: git.TagSet{"tag3": struct{}{}},
72
+
}
73
+
74
+
err := original.Update(update)
75
+
assert.NoError(t, err)
76
+
77
+
assert.Equal(t, "Updated description", original.Description)
78
+
assert.False(t, original.Private)
79
+
assert.Equal(t, []string{"tag1", "tag2", "tag3"}, original.Tags.Slice())
80
+
}
81
+
82
+
func TestFileInfoName(t *testing.T) {
83
+
testCases := []struct {
84
+
path string
85
+
expected string
86
+
}{
87
+
{path: "file.txt", expected: "file.txt"},
88
+
{path: "dir/file.txt", expected: "file.txt"},
89
+
{path: "nested/path/to/file.go", expected: "file.go"},
90
+
{path: "README.md", expected: "README.md"},
91
+
}
92
+
93
+
for _, tc := range testCases {
94
+
t.Run(tc.path, func(t *testing.T) {
95
+
fi := git.FileInfo{Path: tc.path}
96
+
assert.Equal(t, tc.expected, fi.Name())
97
+
})
98
+
}
99
+
}
100
+
101
+
func TestCommitSummaryAndDetails(t *testing.T) {
102
+
testCases := []struct {
103
+
message string
104
+
expectedSummary string
105
+
expectedDetails string
106
+
}{
107
+
{
108
+
message: "Simple commit message",
109
+
expectedSummary: "Simple commit message",
110
+
expectedDetails: "",
111
+
},
112
+
{
113
+
message: "Add feature X\n\nThis commit adds feature X\nWith multiple details\nAcross multiple lines",
114
+
expectedSummary: "Add feature X",
115
+
expectedDetails: "\nThis commit adds feature X\nWith multiple details\nAcross multiple lines",
116
+
},
117
+
{
118
+
message: "Fix bug\n\nDetailed explanation",
119
+
expectedSummary: "Fix bug",
120
+
expectedDetails: "\nDetailed explanation",
121
+
},
122
+
}
123
+
124
+
for _, tc := range testCases {
125
+
t.Run(tc.message, func(t *testing.T) {
126
+
commit := git.Commit{
127
+
SHA: "abcdef1234567890",
128
+
Message: tc.message,
129
+
Signature: "",
130
+
Author: "Test User",
131
+
Email: "test@example.com",
132
+
When: time.Now(),
133
+
}
134
+
135
+
assert.Equal(t, tc.expectedSummary, commit.Summary())
136
+
assert.Equal(t, tc.expectedDetails, commit.Details())
137
+
})
138
+
}
139
+
}
140
+
141
+
func TestCommitShort(t *testing.T) {
142
+
commit := git.Commit{
143
+
SHA: "abcdef1234567890abcdef1234567890",
144
+
}
145
+
146
+
assert.Equal(t, "abcdef12", commit.Short())
147
+
}
148
+
149
+
func TestCommitFilePath(t *testing.T) {
150
+
testCases := []struct {
151
+
name string
152
+
fromPath string
153
+
toPath string
154
+
expected string
155
+
}{
156
+
{
157
+
name: "to path preferred",
158
+
fromPath: "old/path.txt",
159
+
toPath: "new/path.txt",
160
+
expected: "new/path.txt",
161
+
},
162
+
{
163
+
name: "fallback to from path",
164
+
fromPath: "deleted/file.txt",
165
+
toPath: "",
166
+
expected: "deleted/file.txt",
167
+
},
168
+
{
169
+
name: "both paths empty",
170
+
fromPath: "",
171
+
toPath: "",
172
+
expected: "",
173
+
},
174
+
}
175
+
176
+
for _, tc := range testCases {
177
+
t.Run(tc.name, func(t *testing.T) {
178
+
cf := git.CommitFile{
179
+
From: git.CommitFileEntry{Path: tc.fromPath},
180
+
To: git.CommitFileEntry{Path: tc.toPath},
181
+
}
182
+
assert.Equal(t, tc.expected, cf.Path())
183
+
})
184
+
}
185
+
}
186
+
187
+
func TestRepoName(t *testing.T) {
188
+
tmp := t.TempDir()
189
+
190
+
repoName := "testrepo"
191
+
err := git.EnsureRepo(tmp, repoName+".git")
192
+
assert.NoError(t, err)
193
+
194
+
repo, err := git.NewRepo(tmp, repoName)
195
+
assert.NoError(t, err)
196
+
assert.Equal(t, repoName, repo.Name())
197
+
198
+
repoName2 := "test-repo-with-hyphens"
199
+
err = git.EnsureRepo(tmp, repoName2+".git")
200
+
assert.NoError(t, err)
201
+
202
+
repo2, err := git.NewRepo(tmp, repoName2)
203
+
assert.NoError(t, err)
204
+
assert.Equal(t, repoName2, repo2.Name())
205
+
}
206
+
207
+
func TestHandlePushOptions(t *testing.T) {
208
+
tmp := t.TempDir()
209
+
err := git.EnsureRepo(tmp, "test.git")
210
+
assert.NoError(t, err)
211
+
212
+
repo, err := git.NewRepo(tmp, "test")
213
+
assert.NoError(t, err)
214
+
215
+
opts := []*packp.Option{
216
+
{Key: "description", Value: "New description"},
217
+
}
218
+
err = git.HandlePushOptions(repo, opts)
219
+
assert.NoError(t, err)
220
+
assert.Equal(t, "New description", repo.Meta.Description)
221
+
222
+
opts = []*packp.Option{
223
+
{Key: "private", Value: "false"},
224
+
}
225
+
err = git.HandlePushOptions(repo, opts)
226
+
assert.NoError(t, err)
227
+
assert.False(t, repo.Meta.Private)
228
+
229
+
repo.Meta.Private = true
230
+
opts = []*packp.Option{
231
+
{Key: "private", Value: "invalid"},
232
+
}
233
+
err = git.HandlePushOptions(repo, opts)
234
+
assert.NoError(t, err)
235
+
assert.True(t, repo.Meta.Private)
236
+
237
+
opts = []*packp.Option{
238
+
{Key: "tags", Value: "tag1,tag2"},
239
+
}
240
+
err = git.HandlePushOptions(repo, opts)
241
+
assert.NoError(t, err)
242
+
243
+
opts = []*packp.Option{
244
+
{Key: "description", Value: "Combined update"},
245
+
{Key: "private", Value: "true"},
246
+
}
247
+
err = git.HandlePushOptions(repo, opts)
248
+
assert.NoError(t, err)
249
+
assert.Equal(t, "Combined update", repo.Meta.Description)
250
+
assert.True(t, repo.Meta.Private)
251
+
}
252
+
253
+
func TestRepoPath(t *testing.T) {
254
+
tmp := t.TempDir()
255
+
err := git.EnsureRepo(tmp, "test.git")
256
+
assert.NoError(t, err)
257
+
258
+
repo, err := git.NewRepo(tmp, "test")
259
+
assert.NoError(t, err)
260
+
261
+
expected := filepath.Join(tmp, "test.git")
262
+
assert.Equal(t, expected, repo.Path())
263
+
}
264
+
265
+
func TestEnsureJSONFile(t *testing.T) {
266
+
tmp := t.TempDir()
267
+
err := git.EnsureRepo(tmp, "test.git")
268
+
assert.NoError(t, err)
269
+
270
+
repo, err := git.NewRepo(tmp, "test")
271
+
assert.NoError(t, err)
272
+
273
+
assert.True(t, repo.Meta.Private, "default repo should be private")
274
+
assert.Equal(t, "", repo.Meta.Description, "default description should be empty")
275
+
assert.Equal(t, 0, len(repo.Meta.Tags), "default tags should be empty")
276
+
}
+4
-2
internal/git/grep.go
+4
-2
internal/git/grep.go
···
18
18
19
19
// Grep performs a naive "code search" via git grep
20
20
func (r Repo) Grep(search string) ([]GrepResult, error) {
21
-
// Plain-text search only
22
-
re, err := regexp.Compile(regexp.QuoteMeta(search))
21
+
if strings.HasPrefix(search, "=") {
22
+
search = regexp.QuoteMeta(strings.TrimPrefix(search, "="))
23
+
}
24
+
re, err := regexp.Compile(search)
23
25
if err != nil {
24
26
return nil, err
25
27
}
+66
-4
internal/git/meta.go
+66
-4
internal/git/meta.go
···
3
3
import (
4
4
"encoding/json"
5
5
"errors"
6
+
"fmt"
6
7
"io/fs"
7
8
"os"
8
9
"path/filepath"
10
+
"slices"
9
11
)
10
12
11
13
// RepoMeta is the meta information a Repo can have
12
14
type RepoMeta struct {
13
-
Description string `json:"description"`
14
-
Private bool `json:"private"`
15
-
Tags []string `json:"tags"`
15
+
Description string `json:"description"`
16
+
Private bool `json:"private"`
17
+
Tags TagSet `json:"tags"`
18
+
}
19
+
20
+
// TagSet is a Set of tags
21
+
type TagSet map[string]struct{}
22
+
23
+
// Add adds a tag to the set
24
+
func (t TagSet) Add(tag string) {
25
+
t[tag] = struct{}{}
26
+
}
27
+
28
+
// Remove removes a tag from the set
29
+
func (t TagSet) Remove(tag string) {
30
+
delete(t, tag)
31
+
}
32
+
33
+
// Contains checks if a tag is in the set
34
+
func (t TagSet) Contains(tag string) bool {
35
+
_, ok := t[tag]
36
+
return ok
37
+
}
38
+
39
+
// Slice returns the set as a (sorted) slice
40
+
func (t TagSet) Slice() []string {
41
+
s := make([]string, 0, len(t))
42
+
for k := range t {
43
+
s = append(s, k)
44
+
}
45
+
slices.Sort(s)
46
+
return s
47
+
}
48
+
49
+
// MarshalJSON implements [json.Marshaler]
50
+
func (t TagSet) MarshalJSON() ([]byte, error) {
51
+
return json.Marshal(t.Slice())
52
+
}
53
+
54
+
// UnmarshalJSON implements [json.Unmarshaler]
55
+
func (t *TagSet) UnmarshalJSON(b []byte) error {
56
+
if *t == nil {
57
+
ts := make(TagSet)
58
+
t = &ts
59
+
}
60
+
var s []string
61
+
if err := json.Unmarshal(b, &s); err != nil {
62
+
return err
63
+
}
64
+
for _, ss := range s {
65
+
t.Add(ss)
66
+
}
67
+
return nil
16
68
}
17
69
18
70
// Update updates meta given another RepoMeta
···
46
98
return json.NewEncoder(fi).Encode(r.Meta)
47
99
}
48
100
101
+
var defaultMeta = func() []byte {
102
+
b, err := json.Marshal(RepoMeta{
103
+
Private: true,
104
+
})
105
+
if err != nil {
106
+
panic(fmt.Sprintf("could not init default meta: %v", err))
107
+
}
108
+
return b
109
+
}()
110
+
49
111
func ensureJSONFile(path string) error {
50
112
_, err := os.Stat(path)
51
113
if err == nil {
···
59
121
return err
60
122
}
61
123
defer fi.Close()
62
-
if _, err := fi.WriteString(`{"private":true}`); err != nil {
124
+
if _, err := fi.Write(defaultMeta); err != nil {
63
125
return err
64
126
}
65
127
return nil
+53
internal/git/meta_test.go
+53
internal/git/meta_test.go
···
1
+
package git
2
+
3
+
import (
4
+
"encoding/json"
5
+
"testing"
6
+
7
+
"github.com/alecthomas/assert/v2"
8
+
)
9
+
10
+
func TestTagSet(t *testing.T) {
11
+
set := make(TagSet)
12
+
assert.Equal(t, 0, len(set))
13
+
assert.Equal(t, 0, len(set.Slice()))
14
+
15
+
set.Add("foo")
16
+
assert.Equal(t, 1, len(set))
17
+
assert.Equal(t, 1, len(set.Slice()))
18
+
assert.True(t, set.Contains("foo"))
19
+
20
+
set.Add("bar")
21
+
assert.Equal(t, 2, len(set))
22
+
assert.Equal(t, 2, len(set.Slice()))
23
+
assert.True(t, set.Contains("foo"))
24
+
assert.True(t, set.Contains("bar"))
25
+
26
+
set.Add("bar")
27
+
assert.Equal(t, 2, len(set))
28
+
assert.Equal(t, 2, len(set.Slice()))
29
+
assert.True(t, set.Contains("foo"))
30
+
assert.True(t, set.Contains("bar"))
31
+
32
+
set.Remove("foo")
33
+
assert.Equal(t, 1, len(set))
34
+
assert.Equal(t, 1, len(set.Slice()))
35
+
assert.False(t, set.Contains("foo"))
36
+
assert.True(t, set.Contains("bar"))
37
+
38
+
set.Add("foo")
39
+
set.Add("baz")
40
+
j, err := json.Marshal(set)
41
+
assert.NoError(t, err)
42
+
assert.Equal(t, `["bar","baz","foo"]`, string(j))
43
+
44
+
set = make(TagSet)
45
+
b := []byte(`["foo","bar","baz"]`)
46
+
err = json.Unmarshal(b, &set)
47
+
assert.NoError(t, err)
48
+
assert.Equal(t, 3, len(set))
49
+
assert.Equal(t, 3, len(set.Slice()))
50
+
assert.True(t, set.Contains("foo"))
51
+
assert.True(t, set.Contains("bar"))
52
+
assert.True(t, set.Contains("baz"))
53
+
}
+5
-9
internal/git/protocol.go
+5
-9
internal/git/protocol.go
···
58
58
remove = true
59
59
tagValue = strings.TrimPrefix(tagValue, "-")
60
60
}
61
-
for idx, tag := range repo.Meta.Tags {
62
-
if strings.EqualFold(tag, tagValue) {
63
-
if remove {
64
-
repo.Meta.Tags = append(repo.Meta.Tags[:idx], repo.Meta.Tags[idx+1:]...)
65
-
} else {
66
-
repo.Meta.Tags = append(repo.Meta.Tags, strings.ToLower(tagValue))
67
-
}
68
-
break
69
-
}
61
+
tagValue = strings.ToLower(tagValue)
62
+
if remove {
63
+
repo.Meta.Tags.Remove(tagValue)
64
+
} else {
65
+
repo.Meta.Tags.Add(tagValue)
70
66
}
71
67
}
72
68
}
-1
internal/git/protocol_git.go
-1
internal/git/protocol_git.go
+11
internal/git/repo.go
+11
internal/git/repo.go
···
57
57
if err := json.NewDecoder(fi).Decode(&r.Meta); err != nil {
58
58
return nil, err
59
59
}
60
+
if r.Meta.Tags == nil {
61
+
r.Meta.Tags = make(TagSet)
62
+
}
60
63
61
64
return r, nil
62
65
}
···
132
135
type CommitFileEntry struct {
133
136
Path string
134
137
Commit string
138
+
}
139
+
140
+
// Path returns either the To or From path, in order of preference
141
+
func (c CommitFile) Path() string {
142
+
if c.To.Path != "" {
143
+
return c.To.Path
144
+
}
145
+
return c.From.Path
135
146
}
136
147
137
148
// Short returns the first eight characters of the SHA
+3
-1
internal/html/base.templ
+3
-1
internal/html/base.templ
···
18
18
<meta property="og:description" content={ bc.Description }/>
19
19
</head>
20
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"><a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href="/">Home</a></h2>
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>
22
24
{ children... }
23
25
</body>
24
26
</html>
+22
-17
internal/html/base_templ.go
+22
-17
internal/html/base_templ.go
···
1
1
// Code generated by templ - DO NOT EDIT.
2
2
3
-
// templ: version: v0.2.707
3
+
// templ: version: v0.3.924
4
4
package html
5
5
6
6
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
7
8
8
import "github.com/a-h/templ"
9
-
import "context"
10
-
import "io"
11
-
import "bytes"
9
+
import templruntime "github.com/a-h/templ/runtime"
12
10
13
11
type BaseContext struct {
14
12
Title string
···
16
14
}
17
15
18
16
func base(bc BaseContext) templ.Component {
19
-
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
20
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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)
21
23
if !templ_7745c5c3_IsBuffer {
22
-
templ_7745c5c3_Buffer = templ.GetBuffer()
23
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
24
30
}
25
31
ctx = templ.InitializeContext(ctx)
26
32
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
···
28
34
templ_7745c5c3_Var1 = templ.NopComponent
29
35
}
30
36
ctx = templ.ClearChildren(ctx)
31
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html><html><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>")
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>")
32
38
if templ_7745c5c3_Err != nil {
33
39
return templ_7745c5c3_Err
34
40
}
···
41
47
if templ_7745c5c3_Err != nil {
42
48
return templ_7745c5c3_Err
43
49
}
44
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</title><link rel=\"icon\" href=\"/_/favicon.svg\"><link rel=\"stylesheet\" href=\"/_/tailwind.css\"><meta property=\"og:title\" content=\"")
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=\"")
45
51
if templ_7745c5c3_Err != nil {
46
52
return templ_7745c5c3_Err
47
53
}
···
54
60
if templ_7745c5c3_Err != nil {
55
61
return templ_7745c5c3_Err
56
62
}
57
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><meta property=\"og:description\" content=\"")
63
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\"><meta property=\"og:description\" content=\"")
58
64
if templ_7745c5c3_Err != nil {
59
65
return templ_7745c5c3_Err
60
66
}
···
67
73
if templ_7745c5c3_Err != nil {
68
74
return templ_7745c5c3_Err
69
75
}
70
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"></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>")
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>")
71
77
if templ_7745c5c3_Err != nil {
72
78
return templ_7745c5c3_Err
73
79
}
···
75
81
if templ_7745c5c3_Err != nil {
76
82
return templ_7745c5c3_Err
77
83
}
78
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</body></html>")
84
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</body></html>")
79
85
if templ_7745c5c3_Err != nil {
80
86
return templ_7745c5c3_Err
81
87
}
82
-
if !templ_7745c5c3_IsBuffer {
83
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
84
-
}
85
-
return templ_7745c5c3_Err
88
+
return nil
86
89
})
87
90
}
91
+
92
+
var _ = templruntime.GeneratedTemplate
-4
internal/html/generate.css
-4
internal/html/generate.css
+6
-4
internal/html/generate.go
+6
-4
internal/html/generate.go
···
12
12
13
13
"go.jolheiser.com/ugit/internal/html/markup"
14
14
15
+
"github.com/alecthomas/chroma/v2/formatters/html"
15
16
"github.com/alecthomas/chroma/v2/styles"
16
17
)
17
18
···
25
26
otherCSS string
26
27
)
27
28
28
-
//go:generate templ generate
29
+
//go:generate go tool templ generate
29
30
//go:generate go run generate.go
30
31
func main() {
31
32
if err := tailwind(); err != nil {
···
33
34
}
34
35
}
35
36
36
-
// Generate tailwind code from templ templates and combine with other misc CSS
37
+
// Generate tailwind code from templates and combine with other misc CSS
37
38
func tailwind() error {
38
39
fmt.Println("generating tailwind...")
39
40
···
47
48
}
48
49
49
50
fmt.Println("generating chroma styles...")
51
+
formatter := html.New(markup.Options("")...)
50
52
51
53
latte := styles.Get("catppuccin-latte")
52
-
if err := markup.Formatter.WriteCSS(tmp, latte); err != nil {
54
+
if err := formatter.WriteCSS(tmp, latte); err != nil {
53
55
return err
54
56
}
55
57
56
58
tmp.WriteString("@media (prefers-color-scheme: dark) {")
57
59
mocha := styles.Get("catppuccin-mocha")
58
-
if err := markup.Formatter.WriteCSS(tmp, mocha); err != nil {
60
+
if err := formatter.WriteCSS(tmp, mocha); err != nil {
59
61
return err
60
62
}
61
63
tmp.WriteString("}")
+28
-8
internal/html/index.templ
+28
-8
internal/html/index.templ
···
1
1
package html
2
2
3
-
import "go.jolheiser.com/ugit/internal/git"
4
-
import "github.com/dustin/go-humanize"
5
-
import "go.jolheiser.com/ugit/assets"
3
+
import (
4
+
"fmt"
5
+
"github.com/dustin/go-humanize"
6
+
"go.jolheiser.com/ugit/assets"
7
+
"go.jolheiser.com/ugit/internal/git"
8
+
)
6
9
7
10
type IndexContext struct {
8
11
BaseContext
···
21
24
URL string
22
25
}
23
26
24
-
func lastCommit(repo *git.Repo, human bool) string {
27
+
func lastCommitTime(repo *git.Repo, human bool) string {
25
28
c, err := repo.LastCommit()
26
29
if err != nil {
27
30
return ""
···
32
35
return c.When.Format("01/02/2006 03:04:05 PM")
33
36
}
34
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
+
35
46
templ Index(ic IndexContext) {
36
47
@base(ic.BaseContext) {
37
48
<header>
···
62
73
</div>
63
74
}
64
75
</div>
65
-
<div class="grid sm:grid-cols-8 gap-2 mt-5">
76
+
<div class="grid sm:grid-cols-10 gap-2 mt-5">
66
77
for _, repo := range ic.Repos {
78
+
{{ commit := lastCommit(repo) }}
67
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>
68
-
<div class="sm:col-span-4 text-subtext0">{ repo.Meta.Description }</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>
69
89
<div class="sm:col-span-1 text-subtext0">
70
-
for _, tag := range repo.Meta.Tags {
90
+
for _, tag := range repo.Meta.Tags.Slice() {
71
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>
72
92
}
73
93
</div>
74
-
<div class="sm:col-span-1 text-text/80 mb-4 sm:mb-0" title={ lastCommit(repo, false) }>{ lastCommit(repo, true) }</div>
94
+
<div class="sm:col-span-1 text-text/80 mb-4 sm:mb-0" title={ lastCommitTime(repo, false) }>{ lastCommitTime(repo, true) }</div>
75
95
}
76
96
</div>
77
97
</main>
+175
-77
internal/html/index_templ.go
+175
-77
internal/html/index_templ.go
···
1
1
// Code generated by templ - DO NOT EDIT.
2
2
3
-
// templ: version: v0.2.707
3
+
// templ: version: v0.3.924
4
4
package html
5
5
6
6
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
7
8
8
import "github.com/a-h/templ"
9
-
import "context"
10
-
import "io"
11
-
import "bytes"
9
+
import templruntime "github.com/a-h/templ/runtime"
12
10
13
-
import "go.jolheiser.com/ugit/internal/git"
14
-
import "github.com/dustin/go-humanize"
15
-
import "go.jolheiser.com/ugit/assets"
11
+
import (
12
+
"fmt"
13
+
"github.com/dustin/go-humanize"
14
+
"go.jolheiser.com/ugit/assets"
15
+
"go.jolheiser.com/ugit/internal/git"
16
+
)
16
17
17
18
type IndexContext struct {
18
19
BaseContext
···
31
32
URL string
32
33
}
33
34
34
-
func lastCommit(repo *git.Repo, human bool) string {
35
+
func lastCommitTime(repo *git.Repo, human bool) string {
35
36
c, err := repo.LastCommit()
36
37
if err != nil {
37
38
return ""
···
42
43
return c.When.Format("01/02/2006 03:04:05 PM")
43
44
}
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
+
45
54
func Index(ic IndexContext) templ.Component {
46
-
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
47
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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)
48
61
if !templ_7745c5c3_IsBuffer {
49
-
templ_7745c5c3_Buffer = templ.GetBuffer()
50
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
51
68
}
52
69
ctx = templ.InitializeContext(ctx)
53
70
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
···
55
72
templ_7745c5c3_Var1 = templ.NopComponent
56
73
}
57
74
ctx = templ.ClearChildren(ctx)
58
-
templ_7745c5c3_Var2 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
59
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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)
60
78
if !templ_7745c5c3_IsBuffer {
61
-
templ_7745c5c3_Buffer = templ.GetBuffer()
62
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
63
85
}
64
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<header><h1 class=\"text-text text-xl font-bold\">")
86
+
ctx = templ.InitializeContext(ctx)
87
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<header><h1 class=\"text-text text-xl font-bold\">")
65
88
if templ_7745c5c3_Err != nil {
66
89
return templ_7745c5c3_Err
67
90
}
68
91
var templ_7745c5c3_Var3 string
69
92
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(ic.Title)
70
93
if templ_7745c5c3_Err != nil {
71
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 38, Col: 53}
94
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 49, Col: 53}
72
95
}
73
96
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
74
97
if templ_7745c5c3_Err != nil {
75
98
return templ_7745c5c3_Err
76
99
}
77
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h1><h2 class=\"text-subtext1 text-lg\">")
100
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</h1><h2 class=\"text-subtext1 text-lg\">")
78
101
if templ_7745c5c3_Err != nil {
79
102
return templ_7745c5c3_Err
80
103
}
81
104
var templ_7745c5c3_Var4 string
82
105
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(ic.Description)
83
106
if templ_7745c5c3_Err != nil {
84
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 39, Col: 53}
107
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 50, Col: 53}
85
108
}
86
109
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
87
110
if templ_7745c5c3_Err != nil {
88
111
return templ_7745c5c3_Err
89
112
}
90
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h2></header><main class=\"mt-5\"><div class=\"grid grid-cols-1 sm:grid-cols-8\">")
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\">")
91
114
if templ_7745c5c3_Err != nil {
92
115
return templ_7745c5c3_Err
93
116
}
94
117
if ic.Profile.Username != "" {
95
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"text-mauve\">")
118
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div class=\"text-mauve\">")
96
119
if templ_7745c5c3_Err != nil {
97
120
return templ_7745c5c3_Err
98
121
}
99
122
var templ_7745c5c3_Var5 string
100
123
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(`@` + ic.Profile.Username)
101
124
if templ_7745c5c3_Err != nil {
102
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 44, Col: 56}
125
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 55, Col: 56}
103
126
}
104
127
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
105
128
if templ_7745c5c3_Err != nil {
106
129
return templ_7745c5c3_Err
107
130
}
108
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
131
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div>")
109
132
if templ_7745c5c3_Err != nil {
110
133
return templ_7745c5c3_Err
111
134
}
112
135
}
113
136
if ic.Profile.Email != "" {
114
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"text-mauve col-span-2\"><div class=\"w-5 h-5 stroke-mauve inline-block mr-1 align-middle\">")
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\">")
115
138
if templ_7745c5c3_Err != nil {
116
139
return templ_7745c5c3_Err
117
140
}
···
119
142
if templ_7745c5c3_Err != nil {
120
143
return templ_7745c5c3_Err
121
144
}
122
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><a class=\"underline decoration-mauve/50 decoration-dashed hover:decoration-solid\" href=\"")
145
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div><a class=\"underline decoration-mauve/50 decoration-dashed hover:decoration-solid\" href=\"")
123
146
if templ_7745c5c3_Err != nil {
124
147
return templ_7745c5c3_Err
125
148
}
126
-
var templ_7745c5c3_Var6 templ.SafeURL = templ.SafeURL("mailto:" + ic.Profile.Email)
127
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var6)))
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))
128
155
if templ_7745c5c3_Err != nil {
129
156
return templ_7745c5c3_Err
130
157
}
131
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
158
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\">")
132
159
if templ_7745c5c3_Err != nil {
133
160
return templ_7745c5c3_Err
134
161
}
135
162
var templ_7745c5c3_Var7 string
136
163
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(ic.Profile.Email)
137
164
if templ_7745c5c3_Err != nil {
138
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 51, Col: 159}
165
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 62, Col: 159}
139
166
}
140
167
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
141
168
if templ_7745c5c3_Err != nil {
142
169
return templ_7745c5c3_Err
143
170
}
144
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div>")
171
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</a></div>")
145
172
if templ_7745c5c3_Err != nil {
146
173
return templ_7745c5c3_Err
147
174
}
148
175
}
149
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"grid grid-cols-1 sm:grid-cols-8\">")
176
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div><div class=\"grid grid-cols-1 sm:grid-cols-8\">")
150
177
if templ_7745c5c3_Err != nil {
151
178
return templ_7745c5c3_Err
152
179
}
153
180
for _, link := range ic.Profile.Links {
154
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"text-mauve\"><div class=\"w-5 h-5 stroke-mauve inline-block mr-1 align-middle\">")
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\">")
155
182
if templ_7745c5c3_Err != nil {
156
183
return templ_7745c5c3_Err
157
184
}
···
159
186
if templ_7745c5c3_Err != nil {
160
187
return templ_7745c5c3_Err
161
188
}
162
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><a class=\"underline decoration-mauve/50 decoration-dashed hover:decoration-solid\" rel=\"me\" href=\"")
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=\"")
163
190
if templ_7745c5c3_Err != nil {
164
191
return templ_7745c5c3_Err
165
192
}
166
-
var templ_7745c5c3_Var8 templ.SafeURL = templ.SafeURL(link.URL)
167
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var8)))
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))
168
199
if templ_7745c5c3_Err != nil {
169
200
return templ_7745c5c3_Err
170
201
}
171
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
202
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\">")
172
203
if templ_7745c5c3_Err != nil {
173
204
return templ_7745c5c3_Err
174
205
}
175
206
var templ_7745c5c3_Var9 string
176
207
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(link.Name)
177
208
if templ_7745c5c3_Err != nil {
178
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 61, Col: 141}
209
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 72, Col: 141}
179
210
}
180
211
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
181
212
if templ_7745c5c3_Err != nil {
182
213
return templ_7745c5c3_Err
183
214
}
184
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div>")
215
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</a></div>")
185
216
if templ_7745c5c3_Err != nil {
186
217
return templ_7745c5c3_Err
187
218
}
188
219
}
189
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"grid sm:grid-cols-8 gap-2 mt-5\">")
220
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</div><div class=\"grid sm:grid-cols-10 gap-2 mt-5\">")
190
221
if templ_7745c5c3_Err != nil {
191
222
return templ_7745c5c3_Err
192
223
}
193
224
for _, repo := range ic.Repos {
194
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<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=\"")
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=\"")
195
227
if templ_7745c5c3_Err != nil {
196
228
return templ_7745c5c3_Err
197
229
}
198
-
var templ_7745c5c3_Var10 templ.SafeURL = templ.URL("/" + repo.Name())
199
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var10)))
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))
200
236
if templ_7745c5c3_Err != nil {
201
237
return templ_7745c5c3_Err
202
238
}
203
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
239
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\">")
204
240
if templ_7745c5c3_Err != nil {
205
241
return templ_7745c5c3_Err
206
242
}
207
243
var templ_7745c5c3_Var11 string
208
244
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Name())
209
245
if templ_7745c5c3_Err != nil {
210
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 67, Col: 221}
246
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 79, Col: 221}
211
247
}
212
248
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
213
249
if templ_7745c5c3_Err != nil {
214
250
return templ_7745c5c3_Err
215
251
}
216
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div class=\"sm:col-span-4 text-subtext0\">")
252
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</a></div><div class=\"sm:col-span-3 text-subtext0\">")
217
253
if templ_7745c5c3_Err != nil {
218
254
return templ_7745c5c3_Err
219
255
}
220
256
var templ_7745c5c3_Var12 string
221
257
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Meta.Description)
222
258
if templ_7745c5c3_Err != nil {
223
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 68, Col: 69}
259
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 80, Col: 69}
224
260
}
225
261
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
226
262
if templ_7745c5c3_Err != nil {
227
263
return templ_7745c5c3_Err
228
264
}
229
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"sm:col-span-1 text-subtext0\">")
265
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</div><div class=\"sm:col-span-3 text-subtext0\">")
230
266
if templ_7745c5c3_Err != nil {
231
267
return templ_7745c5c3_Err
232
268
}
233
-
for _, tag := range repo.Meta.Tags {
234
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"")
269
+
if commit != nil {
270
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<div title=\"")
235
271
if templ_7745c5c3_Err != nil {
236
272
return templ_7745c5c3_Err
237
273
}
238
-
var templ_7745c5c3_Var13 templ.SafeURL = templ.SafeURL("?tag=" + tag)
239
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var13)))
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))
240
280
if templ_7745c5c3_Err != nil {
241
281
return templ_7745c5c3_Err
242
282
}
243
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"rounded border-rosewater border-solid border pb-0.5 px-1 mr-1 mb-1 inline-block\">")
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=\"")
244
284
if templ_7745c5c3_Err != nil {
245
285
return templ_7745c5c3_Err
246
286
}
247
-
var templ_7745c5c3_Var14 string
248
-
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(tag)
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))
249
289
if templ_7745c5c3_Err != nil {
250
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 71, Col: 141}
290
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 84, Col: 206}
251
291
}
252
292
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
253
293
if templ_7745c5c3_Err != nil {
254
294
return templ_7745c5c3_Err
255
295
}
256
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>")
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>")
257
323
if templ_7745c5c3_Err != nil {
258
324
return templ_7745c5c3_Err
259
325
}
260
326
}
261
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"sm:col-span-1 text-text/80 mb-4 sm:mb-0\" title=\"")
327
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</div><div class=\"sm:col-span-1 text-subtext0\">")
262
328
if templ_7745c5c3_Err != nil {
263
329
return templ_7745c5c3_Err
264
330
}
265
-
var templ_7745c5c3_Var15 string
266
-
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(lastCommit(repo, false))
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=\"")
267
364
if templ_7745c5c3_Err != nil {
268
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 74, Col: 89}
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}
269
371
}
270
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
372
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
271
373
if templ_7745c5c3_Err != nil {
272
374
return templ_7745c5c3_Err
273
375
}
274
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
376
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "\">")
275
377
if templ_7745c5c3_Err != nil {
276
378
return templ_7745c5c3_Err
277
379
}
278
-
var templ_7745c5c3_Var16 string
279
-
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(lastCommit(repo, true))
380
+
var templ_7745c5c3_Var20 string
381
+
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(lastCommitTime(repo, true))
280
382
if templ_7745c5c3_Err != nil {
281
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 74, Col: 116}
383
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 94, Col: 124}
282
384
}
283
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
385
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
284
386
if templ_7745c5c3_Err != nil {
285
387
return templ_7745c5c3_Err
286
388
}
287
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
389
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "</div>")
288
390
if templ_7745c5c3_Err != nil {
289
391
return templ_7745c5c3_Err
290
392
}
291
393
}
292
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></main>")
394
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "</div></main>")
293
395
if templ_7745c5c3_Err != nil {
294
396
return templ_7745c5c3_Err
295
397
}
296
-
if !templ_7745c5c3_IsBuffer {
297
-
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
298
-
}
299
-
return templ_7745c5c3_Err
398
+
return nil
300
399
})
301
400
templ_7745c5c3_Err = base(ic.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
302
401
if templ_7745c5c3_Err != nil {
303
402
return templ_7745c5c3_Err
304
403
}
305
-
if !templ_7745c5c3_IsBuffer {
306
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
307
-
}
308
-
return templ_7745c5c3_Err
404
+
return nil
309
405
})
310
406
}
407
+
408
+
var _ = templruntime.GeneratedTemplate
+16
-24
internal/html/markup/chroma.go
+16
-24
internal/html/markup/chroma.go
···
2
2
3
3
import (
4
4
"io"
5
+
"path/filepath"
5
6
6
7
"github.com/alecthomas/chroma/v2"
7
8
"github.com/alecthomas/chroma/v2/formatters/html"
···
9
10
"github.com/alecthomas/chroma/v2/styles"
10
11
)
11
12
12
-
var (
13
-
// Formatter is the default formatter
14
-
Formatter = html.New(
13
+
var customReg = map[string]string{
14
+
".hujson": "json",
15
+
}
16
+
17
+
// Options are the default set of formatting options
18
+
func Options(linePrefix string) []html.Option {
19
+
return []html.Option{
15
20
html.WithLineNumbers(true),
16
-
html.WithLinkableLineNumbers(true, "L"),
21
+
html.WithLinkableLineNumbers(true, linePrefix),
17
22
html.WithClasses(true),
18
23
html.LineNumbersInTable(true),
19
-
)
20
-
basicFormatter = html.New(
21
-
html.WithClasses(true),
22
-
)
23
-
// Code is the entrypoint for formatting
24
-
Code = code{}
25
-
)
26
-
27
-
type code struct{}
24
+
}
25
+
}
28
26
29
27
func setup(source []byte, fileName string) (chroma.Iterator, *chroma.Style, error) {
30
28
lexer := lexers.Match(fileName)
31
29
if lexer == nil {
32
30
lexer = lexers.Fallback
31
+
if name, ok := customReg[filepath.Ext(fileName)]; ok {
32
+
lexer = lexers.Get(name)
33
+
}
33
34
}
34
35
lexer = chroma.Coalesce(lexer)
35
36
···
46
47
return iter, style, nil
47
48
}
48
49
49
-
// Basic formats code without any extras
50
-
func (c code) Basic(source []byte, fileName string, writer io.Writer) error {
51
-
iter, style, err := setup(source, fileName)
52
-
if err != nil {
53
-
return err
54
-
}
55
-
return basicFormatter.Format(writer, style, iter)
56
-
}
57
-
58
50
// Convert formats code with line numbers, links, etc.
59
-
func (c code) Convert(source []byte, fileName string, writer io.Writer) error {
51
+
func Convert(source []byte, fileName, linePrefix string, writer io.Writer) error {
60
52
iter, style, err := setup(source, fileName)
61
53
if err != nil {
62
54
return err
63
55
}
64
-
return Formatter.Format(writer, style, iter)
56
+
return html.New(Options(linePrefix)...).Format(writer, style, iter)
65
57
}
66
58
67
59
// Snippet formats code with line numbers starting at a specific line
+1
internal/html/markup/markdown.go
+1
internal/html/markup/markdown.go
···
112
112
case *ast.Image:
113
113
link := v.Destination
114
114
if len(link) > 0 && !bytes.HasPrefix(link, []byte("http")) {
115
+
v.SetAttributeString("style", []byte("max-width:100%;"))
115
116
v.Destination = []byte(resolveLink(ctx.repo, ctx.ref, ctx.path, string(link)) + "?raw&pretty")
116
117
}
117
118
+4
-3
internal/html/readme.templ
+4
-3
internal/html/readme.templ
···
1
1
package html
2
2
3
3
type ReadmeComponentContext struct {
4
-
Markdown string
4
+
Markdown string
5
5
}
6
6
7
7
templ readmeComponent(rcc ReadmeComponentContext) {
8
8
if rcc.Markdown != "" {
9
-
<div class="bg-base dark:bg-base/50 p-5 mt-5 rounded markdown">@templ.Raw(rcc.Markdown)</div>
9
+
<div class="bg-base dark:bg-base/50 p-5 mt-5 rounded markdown">
10
+
@templ.Raw(rcc.Markdown)
11
+
</div>
10
12
}
11
13
}
12
-
+19
-14
internal/html/readme_templ.go
+19
-14
internal/html/readme_templ.go
···
1
1
// Code generated by templ - DO NOT EDIT.
2
2
3
-
// templ: version: v0.2.707
3
+
// templ: version: v0.3.924
4
4
package html
5
5
6
6
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
7
8
8
import "github.com/a-h/templ"
9
-
import "context"
10
-
import "io"
11
-
import "bytes"
9
+
import templruntime "github.com/a-h/templ/runtime"
12
10
13
11
type ReadmeComponentContext struct {
14
12
Markdown string
15
13
}
16
14
17
15
func readmeComponent(rcc ReadmeComponentContext) templ.Component {
18
-
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
19
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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)
20
22
if !templ_7745c5c3_IsBuffer {
21
-
templ_7745c5c3_Buffer = templ.GetBuffer()
22
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
23
29
}
24
30
ctx = templ.InitializeContext(ctx)
25
31
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
···
28
34
}
29
35
ctx = templ.ClearChildren(ctx)
30
36
if rcc.Markdown != "" {
31
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"bg-base dark:bg-base/50 p-5 mt-5 rounded 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\">")
32
38
if templ_7745c5c3_Err != nil {
33
39
return templ_7745c5c3_Err
34
40
}
···
36
42
if templ_7745c5c3_Err != nil {
37
43
return templ_7745c5c3_Err
38
44
}
39
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
45
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</div>")
40
46
if templ_7745c5c3_Err != nil {
41
47
return templ_7745c5c3_Err
42
48
}
43
49
}
44
-
if !templ_7745c5c3_IsBuffer {
45
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
46
-
}
47
-
return templ_7745c5c3_Err
50
+
return nil
48
51
})
49
52
}
53
+
54
+
var _ = templruntime.GeneratedTemplate
+16
-8
internal/html/repo_commit.templ
+16
-8
internal/html/repo_commit.templ
···
4
4
import "github.com/dustin/go-humanize"
5
5
import "go.jolheiser.com/ugit/internal/git"
6
6
7
-
type RepoCommitContext struct{
8
-
BaseContext
9
-
RepoHeaderComponentContext
10
-
Commit git.Commit
7
+
type RepoCommitContext struct {
8
+
BaseContext
9
+
RepoHeaderComponentContext
10
+
Commit git.Commit
11
11
}
12
12
13
13
templ RepoCommit(rcc RepoCommitContext) {
···
25
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
26
<div title={ rcc.Commit.When.Format("01/02/2006 03:04:05 PM") }>{ humanize.Time(rcc.Commit.When) }</div>
27
27
</div>
28
-
<div class="text-text mt-5">{ fmt.Sprintf("%d changed files, %d additions(+), %d deletions(-)", rcc.Commit.Stats.Changed, rcc.Commit.Stats.Additions, rcc.Commit.Stats.Deletions) }</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>
29
36
for _, file := range rcc.Commit.Files {
30
-
<div class="text-text mt-5">
37
+
<div class="text-text mt-5" id={ file.Path() }>
31
38
<span class="text-text/80" title={ file.Action }>{ string(file.Action[0]) }</span>
32
39
{ " " }
33
40
if file.From.Path != "" {
···
40
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>
41
48
}
42
49
</div>
43
-
<div class="whitespace-pre code">@templ.Raw(file.Patch)</div>
50
+
<div class="code">
51
+
@templ.Raw(file.Patch)
52
+
</div>
44
53
}
45
54
}
46
55
}
47
-
+162
-81
internal/html/repo_commit_templ.go
+162
-81
internal/html/repo_commit_templ.go
···
1
1
// Code generated by templ - DO NOT EDIT.
2
2
3
-
// templ: version: v0.2.707
3
+
// templ: version: v0.3.924
4
4
package html
5
5
6
6
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
7
8
8
import "github.com/a-h/templ"
9
-
import "context"
10
-
import "io"
11
-
import "bytes"
9
+
import templruntime "github.com/a-h/templ/runtime"
12
10
13
11
import "fmt"
14
12
import "github.com/dustin/go-humanize"
···
21
19
}
22
20
23
21
func RepoCommit(rcc RepoCommitContext) templ.Component {
24
-
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
25
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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)
26
28
if !templ_7745c5c3_IsBuffer {
27
-
templ_7745c5c3_Buffer = templ.GetBuffer()
28
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
29
35
}
30
36
ctx = templ.InitializeContext(ctx)
31
37
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
···
33
39
templ_7745c5c3_Var1 = templ.NopComponent
34
40
}
35
41
ctx = templ.ClearChildren(ctx)
36
-
templ_7745c5c3_Var2 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
37
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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)
38
45
if !templ_7745c5c3_IsBuffer {
39
-
templ_7745c5c3_Buffer = templ.GetBuffer()
40
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
41
52
}
53
+
ctx = templ.InitializeContext(ctx)
42
54
templ_7745c5c3_Err = repoHeaderComponent(rcc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer)
43
55
if templ_7745c5c3_Err != nil {
44
56
return templ_7745c5c3_Err
45
57
}
46
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <div class=\"text-text mt-5\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
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=\"")
47
59
if templ_7745c5c3_Err != nil {
48
60
return templ_7745c5c3_Err
49
61
}
50
-
var templ_7745c5c3_Var3 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA))
51
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var3)))
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))
52
68
if templ_7745c5c3_Err != nil {
53
69
return templ_7745c5c3_Err
54
70
}
55
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">tree</a>")
71
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\">tree</a>")
56
72
if templ_7745c5c3_Err != nil {
57
73
return templ_7745c5c3_Err
58
74
}
···
65
81
if templ_7745c5c3_Err != nil {
66
82
return templ_7745c5c3_Err
67
83
}
68
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
84
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
69
85
if templ_7745c5c3_Err != nil {
70
86
return templ_7745c5c3_Err
71
87
}
72
-
var templ_7745c5c3_Var5 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/log/%s", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA))
73
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var5)))
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))
74
94
if templ_7745c5c3_Err != nil {
75
95
return templ_7745c5c3_Err
76
96
}
77
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">log</a>")
97
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\">log</a>")
78
98
if templ_7745c5c3_Err != nil {
79
99
return templ_7745c5c3_Err
80
100
}
···
87
107
if templ_7745c5c3_Err != nil {
88
108
return templ_7745c5c3_Err
89
109
}
90
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
110
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
91
111
if templ_7745c5c3_Err != nil {
92
112
return templ_7745c5c3_Err
93
113
}
94
-
var templ_7745c5c3_Var7 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/commit/%s.patch", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA))
95
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var7)))
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))
96
120
if templ_7745c5c3_Err != nil {
97
121
return templ_7745c5c3_Err
98
122
}
99
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">patch</a></div><div class=\"text-text whitespace-pre mt-5 p-3 bg-base rounded\">")
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\">")
100
124
if templ_7745c5c3_Err != nil {
101
125
return templ_7745c5c3_Err
102
126
}
···
109
133
if templ_7745c5c3_Err != nil {
110
134
return templ_7745c5c3_Err
111
135
}
112
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
136
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div>")
113
137
if templ_7745c5c3_Err != nil {
114
138
return templ_7745c5c3_Err
115
139
}
116
140
if rcc.Commit.Signature != "" {
117
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<details class=\"text-text whitespace-pre\"><summary class=\"cursor-pointer\">Signature</summary><div class=\"p-3 bg-base rounded\"><code>")
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>")
118
142
if templ_7745c5c3_Err != nil {
119
143
return templ_7745c5c3_Err
120
144
}
···
127
151
if templ_7745c5c3_Err != nil {
128
152
return templ_7745c5c3_Err
129
153
}
130
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</code></div></details>")
154
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</code></div></details>")
131
155
if templ_7745c5c3_Err != nil {
132
156
return templ_7745c5c3_Err
133
157
}
134
158
}
135
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <div class=\"text-text mt-3\"><div>")
159
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " <div class=\"text-text mt-3\"><div>")
136
160
if templ_7745c5c3_Err != nil {
137
161
return templ_7745c5c3_Err
138
162
}
···
154
178
if templ_7745c5c3_Err != nil {
155
179
return templ_7745c5c3_Err
156
180
}
157
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
181
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
158
182
if templ_7745c5c3_Err != nil {
159
183
return templ_7745c5c3_Err
160
184
}
161
-
var templ_7745c5c3_Var12 templ.SafeURL = templ.SafeURL(fmt.Sprintf("mailto:%s", rcc.Commit.Email))
162
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var12)))
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))
163
191
if templ_7745c5c3_Err != nil {
164
192
return templ_7745c5c3_Err
165
193
}
166
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
194
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\">")
167
195
if templ_7745c5c3_Err != nil {
168
196
return templ_7745c5c3_Err
169
197
}
···
176
204
if templ_7745c5c3_Err != nil {
177
205
return templ_7745c5c3_Err
178
206
}
179
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div title=\"")
207
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</a></div><div title=\"")
180
208
if templ_7745c5c3_Err != nil {
181
209
return templ_7745c5c3_Err
182
210
}
···
189
217
if templ_7745c5c3_Err != nil {
190
218
return templ_7745c5c3_Err
191
219
}
192
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
220
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "\">")
193
221
if templ_7745c5c3_Err != nil {
194
222
return templ_7745c5c3_Err
195
223
}
···
202
230
if templ_7745c5c3_Err != nil {
203
231
return templ_7745c5c3_Err
204
232
}
205
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div><div class=\"text-text mt-5\">")
233
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</div></div><details class=\"text-text mt-5\"><summary class=\"cursor-pointer\">")
206
234
if templ_7745c5c3_Err != nil {
207
235
return templ_7745c5c3_Err
208
236
}
209
237
var templ_7745c5c3_Var16 string
210
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))
211
239
if templ_7745c5c3_Err != nil {
212
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 28, Col: 179}
240
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 29, Col: 184}
213
241
}
214
242
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
215
243
if templ_7745c5c3_Err != nil {
216
244
return templ_7745c5c3_Err
217
245
}
218
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
246
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</summary><div class=\"p-3 bg-base rounded\">")
219
247
if templ_7745c5c3_Err != nil {
220
248
return templ_7745c5c3_Err
221
249
}
222
250
for _, file := range rcc.Commit.Files {
223
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"text-text mt-5\"><span class=\"text-text/80\" title=\"")
251
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<a class=\"block underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
224
252
if templ_7745c5c3_Err != nil {
225
253
return templ_7745c5c3_Err
226
254
}
227
-
var templ_7745c5c3_Var17 string
228
-
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(file.Action)
255
+
var templ_7745c5c3_Var17 templ.SafeURL
256
+
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinURLErrs("#" + file.Path())
229
257
if templ_7745c5c3_Err != nil {
230
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 31, Col: 50}
258
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 32, Col: 116}
231
259
}
232
260
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
233
261
if templ_7745c5c3_Err != nil {
234
262
return templ_7745c5c3_Err
235
263
}
236
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
264
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\">")
237
265
if templ_7745c5c3_Err != nil {
238
266
return templ_7745c5c3_Err
239
267
}
240
268
var templ_7745c5c3_Var18 string
241
-
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(string(file.Action[0]))
269
+
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(file.Path())
242
270
if templ_7745c5c3_Err != nil {
243
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 31, Col: 77}
271
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 32, Col: 132}
244
272
}
245
273
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
246
274
if templ_7745c5c3_Err != nil {
247
275
return templ_7745c5c3_Err
248
276
}
249
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span> ")
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=\"")
250
288
if templ_7745c5c3_Err != nil {
251
289
return templ_7745c5c3_Err
252
290
}
253
291
var templ_7745c5c3_Var19 string
254
-
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(" ")
292
+
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(file.Path())
255
293
if templ_7745c5c3_Err != nil {
256
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 32, Col: 9}
294
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 37, Col: 47}
257
295
}
258
296
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
259
297
if templ_7745c5c3_Err != nil {
260
298
return templ_7745c5c3_Err
261
299
}
262
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
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, " ")
263
340
if templ_7745c5c3_Err != nil {
264
341
return templ_7745c5c3_Err
265
342
}
266
343
if file.From.Path != "" {
267
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
344
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
268
345
if templ_7745c5c3_Err != nil {
269
346
return templ_7745c5c3_Err
270
347
}
271
-
var templ_7745c5c3_Var20 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.From.Commit, file.From.Path))
272
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var20)))
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))
273
354
if templ_7745c5c3_Err != nil {
274
355
return templ_7745c5c3_Err
275
356
}
276
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
357
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "\">")
277
358
if templ_7745c5c3_Err != nil {
278
359
return templ_7745c5c3_Err
279
360
}
280
-
var templ_7745c5c3_Var21 string
281
-
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(file.From.Path)
361
+
var templ_7745c5c3_Var24 string
362
+
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(file.From.Path)
282
363
if templ_7745c5c3_Err != nil {
283
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 34, Col: 227}
364
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 41, Col: 227}
284
365
}
285
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
366
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
286
367
if templ_7745c5c3_Err != nil {
287
368
return templ_7745c5c3_Err
288
369
}
289
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a> ")
370
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</a> ")
290
371
if templ_7745c5c3_Err != nil {
291
372
return templ_7745c5c3_Err
292
373
}
293
374
}
294
375
if file.From.Path != "" && file.To.Path != "" {
295
-
var templ_7745c5c3_Var22 string
296
-
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(" -> ")
376
+
var templ_7745c5c3_Var25 string
377
+
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(" -> ")
297
378
if templ_7745c5c3_Err != nil {
298
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 37, Col: 13}
379
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 44, Col: 13}
299
380
}
300
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
381
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
301
382
if templ_7745c5c3_Err != nil {
302
383
return templ_7745c5c3_Err
303
384
}
304
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
385
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, " ")
305
386
if templ_7745c5c3_Err != nil {
306
387
return templ_7745c5c3_Err
307
388
}
308
389
}
309
390
if file.To.Path != "" {
310
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
391
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
311
392
if templ_7745c5c3_Err != nil {
312
393
return templ_7745c5c3_Err
313
394
}
314
-
var templ_7745c5c3_Var23 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.To.Commit, file.To.Path))
315
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var23)))
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))
316
401
if templ_7745c5c3_Err != nil {
317
402
return templ_7745c5c3_Err
318
403
}
319
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
404
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "\">")
320
405
if templ_7745c5c3_Err != nil {
321
406
return templ_7745c5c3_Err
322
407
}
323
-
var templ_7745c5c3_Var24 string
324
-
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(file.To.Path)
408
+
var templ_7745c5c3_Var27 string
409
+
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(file.To.Path)
325
410
if templ_7745c5c3_Err != nil {
326
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 40, Col: 221}
411
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 47, Col: 221}
327
412
}
328
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
413
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
329
414
if templ_7745c5c3_Err != nil {
330
415
return templ_7745c5c3_Err
331
416
}
332
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>")
417
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "</a>")
333
418
if templ_7745c5c3_Err != nil {
334
419
return templ_7745c5c3_Err
335
420
}
336
421
}
337
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"whitespace-pre code\">")
422
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</div><div class=\"code\">")
338
423
if templ_7745c5c3_Err != nil {
339
424
return templ_7745c5c3_Err
340
425
}
···
342
427
if templ_7745c5c3_Err != nil {
343
428
return templ_7745c5c3_Err
344
429
}
345
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
430
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</div>")
346
431
if templ_7745c5c3_Err != nil {
347
432
return templ_7745c5c3_Err
348
433
}
349
434
}
350
-
if !templ_7745c5c3_IsBuffer {
351
-
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
352
-
}
353
-
return templ_7745c5c3_Err
435
+
return nil
354
436
})
355
437
templ_7745c5c3_Err = base(rcc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
356
438
if templ_7745c5c3_Err != nil {
357
439
return templ_7745c5c3_Err
358
440
}
359
-
if !templ_7745c5c3_IsBuffer {
360
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
361
-
}
362
-
return templ_7745c5c3_Err
441
+
return nil
363
442
})
364
443
}
444
+
445
+
var _ = templruntime.GeneratedTemplate
+42
-5
internal/html/repo_file.templ
+42
-5
internal/html/repo_file.templ
···
1
1
package html
2
2
3
+
import "fmt"
4
+
3
5
type RepoFileContext struct {
4
6
BaseContext
5
7
RepoHeaderComponentContext
6
8
RepoBreadcrumbComponentContext
7
-
Code string
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)
8
16
}
9
17
10
18
templ RepoFile(rfc RepoFileContext) {
···
14
22
@repoBreadcrumbComponent(rfc.RepoBreadcrumbComponentContext)
15
23
{ " - " }
16
24
<a class="text-text underline decoration-text/50 decoration-dashed hover:decoration-solid" href="?raw">raw</a>
17
-
<div class="code">
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">
18
28
@templ.Raw(rfc.Code)
29
+
<button id="copy" class="absolute top-0 right-0 rounded bg-base hover:bg-surface0"></button>
19
30
</div>
20
31
</div>
21
32
}
···
23
34
const lineRe = /#L(\d+)(?:-L(\d+))?/g
24
35
const $lineLines = document.querySelectorAll(".chroma .lntable .lnt");
25
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;
26
43
let start = 0;
27
44
let end = 0;
28
45
···
31
48
start = results[0][1] !== undefined ? parseInt(results[0][1]) : 0;
32
49
end = results[0][2] !== undefined ? parseInt(results[0][2]) : 0;
33
50
}
34
-
if (start != 0) {
51
+
if (start !== 0) {
35
52
deactivateLines();
36
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);
37
58
}
38
59
39
60
for (let line of $lineLines) {
···
45
66
if (event.shiftKey) {
46
67
end = n;
47
68
anchor = `#L${start}-L${end}`;
69
+
} else if (start === n) {
70
+
start = 0;
71
+
end = 0;
48
72
} else {
49
73
start = n;
50
74
end = 0;
51
75
anchor = `#L${start}`;
52
76
}
53
-
history.replaceState(null, null, anchor);
54
-
activateLines(start, end);
77
+
history.replaceState(null, null, window.location.pathname + anchor);
78
+
$permalink.href = $permalink.dataset.permalink + anchor;
79
+
if (start !== 0) activateLines(start, end);
55
80
});
56
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
+
});
57
94
58
95
function activateLines(start, end) {
59
96
if (end < start) end = start;
+81
-26
internal/html/repo_file_templ.go
+81
-26
internal/html/repo_file_templ.go
···
1
1
// Code generated by templ - DO NOT EDIT.
2
2
3
-
// templ: version: v0.2.707
3
+
// templ: version: v0.3.924
4
4
package html
5
5
6
6
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
7
8
8
import "github.com/a-h/templ"
9
-
import "context"
10
-
import "io"
11
-
import "bytes"
9
+
import templruntime "github.com/a-h/templ/runtime"
10
+
11
+
import "fmt"
12
12
13
13
type RepoFileContext struct {
14
14
BaseContext
15
15
RepoHeaderComponentContext
16
16
RepoBreadcrumbComponentContext
17
-
Code string
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)
18
24
}
19
25
20
26
func RepoFile(rfc RepoFileContext) templ.Component {
21
-
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
22
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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)
23
33
if !templ_7745c5c3_IsBuffer {
24
-
templ_7745c5c3_Buffer = templ.GetBuffer()
25
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
26
40
}
27
41
ctx = templ.InitializeContext(ctx)
28
42
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
···
30
44
templ_7745c5c3_Var1 = templ.NopComponent
31
45
}
32
46
ctx = templ.ClearChildren(ctx)
33
-
templ_7745c5c3_Var2 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
34
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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)
35
50
if !templ_7745c5c3_IsBuffer {
36
-
templ_7745c5c3_Buffer = templ.GetBuffer()
37
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
38
57
}
58
+
ctx = templ.InitializeContext(ctx)
39
59
templ_7745c5c3_Err = repoHeaderComponent(rfc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer)
40
60
if templ_7745c5c3_Err != nil {
41
61
return templ_7745c5c3_Err
42
62
}
43
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <div class=\"mt-2 text-text\">")
63
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"mt-2 text-text\">")
44
64
if templ_7745c5c3_Err != nil {
45
65
return templ_7745c5c3_Err
46
66
}
···
51
71
var templ_7745c5c3_Var3 string
52
72
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(" - ")
53
73
if templ_7745c5c3_Err != nil {
54
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 15, Col: 10}
74
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 23, Col: 10}
55
75
}
56
76
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
57
77
if templ_7745c5c3_Err != nil {
58
78
return templ_7745c5c3_Err
59
79
}
60
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <a class=\"text-text underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"?raw\">raw</a><div class=\"code\">")
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))
61
116
if templ_7745c5c3_Err != nil {
62
117
return templ_7745c5c3_Err
63
118
}
64
-
templ_7745c5c3_Err = templ.Raw(rfc.Code).Render(ctx, templ_7745c5c3_Buffer)
119
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">permalink</a><div class=\"code relative\">")
65
120
if templ_7745c5c3_Err != nil {
66
121
return templ_7745c5c3_Err
67
122
}
68
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div>")
123
+
templ_7745c5c3_Err = templ.Raw(rfc.Code).Render(ctx, templ_7745c5c3_Buffer)
69
124
if templ_7745c5c3_Err != nil {
70
125
return templ_7745c5c3_Err
71
126
}
72
-
if !templ_7745c5c3_IsBuffer {
73
-
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
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
74
130
}
75
-
return templ_7745c5c3_Err
131
+
return nil
76
132
})
77
133
templ_7745c5c3_Err = base(rfc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
78
134
if templ_7745c5c3_Err != nil {
79
135
return templ_7745c5c3_Err
80
136
}
81
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<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\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}\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 {\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, anchor);\n\t\t\t\tactivateLines(start, end);\n\t\t\t});\n\t\t}\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>")
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>")
82
138
if templ_7745c5c3_Err != nil {
83
139
return templ_7745c5c3_Err
84
140
}
85
-
if !templ_7745c5c3_IsBuffer {
86
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
87
-
}
88
-
return templ_7745c5c3_Err
141
+
return nil
89
142
})
90
143
}
144
+
145
+
var _ = templruntime.GeneratedTemplate
+3
-4
internal/html/repo_log.templ
+3
-4
internal/html/repo_log.templ
···
5
5
import "go.jolheiser.com/ugit/internal/git"
6
6
7
7
type RepoLogContext struct {
8
-
BaseContext
9
-
RepoHeaderComponentContext
10
-
Commits []git.Commit
8
+
BaseContext
9
+
RepoHeaderComponentContext
10
+
Commits []git.Commit
11
11
}
12
12
13
13
templ RepoLog(rlc RepoLogContext) {
···
36
36
</div>
37
37
}
38
38
}
39
-
+54
-38
internal/html/repo_log_templ.go
+54
-38
internal/html/repo_log_templ.go
···
1
1
// Code generated by templ - DO NOT EDIT.
2
2
3
-
// templ: version: v0.2.707
3
+
// templ: version: v0.3.924
4
4
package html
5
5
6
6
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
7
8
8
import "github.com/a-h/templ"
9
-
import "context"
10
-
import "io"
11
-
import "bytes"
9
+
import templruntime "github.com/a-h/templ/runtime"
12
10
13
11
import "fmt"
14
12
import "github.com/dustin/go-humanize"
···
21
19
}
22
20
23
21
func RepoLog(rlc RepoLogContext) templ.Component {
24
-
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
25
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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)
26
28
if !templ_7745c5c3_IsBuffer {
27
-
templ_7745c5c3_Buffer = templ.GetBuffer()
28
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
29
35
}
30
36
ctx = templ.InitializeContext(ctx)
31
37
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
···
33
39
templ_7745c5c3_Var1 = templ.NopComponent
34
40
}
35
41
ctx = templ.ClearChildren(ctx)
36
-
templ_7745c5c3_Var2 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
37
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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)
38
45
if !templ_7745c5c3_IsBuffer {
39
-
templ_7745c5c3_Buffer = templ.GetBuffer()
40
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
41
52
}
53
+
ctx = templ.InitializeContext(ctx)
42
54
templ_7745c5c3_Err = repoHeaderComponent(rlc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer)
43
55
if templ_7745c5c3_Err != nil {
44
56
return templ_7745c5c3_Err
45
57
}
46
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <div class=\"grid sm:grid-cols-8 gap-1 text-text mt-5\">")
58
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"grid sm:grid-cols-8 gap-1 text-text mt-5\">")
47
59
if templ_7745c5c3_Err != nil {
48
60
return templ_7745c5c3_Err
49
61
}
50
62
for _, commit := range rlc.Commits {
51
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"sm:col-span-5\"><div><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
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=\"")
52
64
if templ_7745c5c3_Err != nil {
53
65
return templ_7745c5c3_Err
54
66
}
55
-
var templ_7745c5c3_Var3 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/commit/%s", rlc.RepoHeaderComponentContext.Name, commit.SHA))
56
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var3)))
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))
57
73
if templ_7745c5c3_Err != nil {
58
74
return templ_7745c5c3_Err
59
75
}
60
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
76
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">")
61
77
if templ_7745c5c3_Err != nil {
62
78
return templ_7745c5c3_Err
63
79
}
···
70
86
if templ_7745c5c3_Err != nil {
71
87
return templ_7745c5c3_Err
72
88
}
73
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div class=\"whitespace-pre\">")
89
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</a></div><div class=\"whitespace-pre\">")
74
90
if templ_7745c5c3_Err != nil {
75
91
return templ_7745c5c3_Err
76
92
}
77
93
if commit.Details() != "" {
78
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<details><summary class=\"cursor-pointer\">")
94
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<details><summary class=\"cursor-pointer\">")
79
95
if templ_7745c5c3_Err != nil {
80
96
return templ_7745c5c3_Err
81
97
}
···
88
104
if templ_7745c5c3_Err != nil {
89
105
return templ_7745c5c3_Err
90
106
}
91
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</summary><div class=\"p-3 bg-base rounded\">")
107
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</summary><div class=\"p-3 bg-base rounded\">")
92
108
if templ_7745c5c3_Err != nil {
93
109
return templ_7745c5c3_Err
94
110
}
···
101
117
if templ_7745c5c3_Err != nil {
102
118
return templ_7745c5c3_Err
103
119
}
104
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></details>")
120
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div></details>")
105
121
if templ_7745c5c3_Err != nil {
106
122
return templ_7745c5c3_Err
107
123
}
···
116
132
return templ_7745c5c3_Err
117
133
}
118
134
}
119
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div><div class=\"sm:col-span-3 mb-4\"><div>")
135
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div></div><div class=\"sm:col-span-3 mb-4\"><div>")
120
136
if templ_7745c5c3_Err != nil {
121
137
return templ_7745c5c3_Err
122
138
}
···
138
154
if templ_7745c5c3_Err != nil {
139
155
return templ_7745c5c3_Err
140
156
}
141
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
157
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
142
158
if templ_7745c5c3_Err != nil {
143
159
return templ_7745c5c3_Err
144
160
}
145
-
var templ_7745c5c3_Var10 templ.SafeURL = templ.SafeURL(fmt.Sprintf("mailto:%s", commit.Email))
146
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var10)))
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))
147
167
if templ_7745c5c3_Err != nil {
148
168
return templ_7745c5c3_Err
149
169
}
150
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
170
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\">")
151
171
if templ_7745c5c3_Err != nil {
152
172
return templ_7745c5c3_Err
153
173
}
···
160
180
if templ_7745c5c3_Err != nil {
161
181
return templ_7745c5c3_Err
162
182
}
163
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div title=\"")
183
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</a></div><div title=\"")
164
184
if templ_7745c5c3_Err != nil {
165
185
return templ_7745c5c3_Err
166
186
}
···
173
193
if templ_7745c5c3_Err != nil {
174
194
return templ_7745c5c3_Err
175
195
}
176
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
196
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\">")
177
197
if templ_7745c5c3_Err != nil {
178
198
return templ_7745c5c3_Err
179
199
}
···
186
206
if templ_7745c5c3_Err != nil {
187
207
return templ_7745c5c3_Err
188
208
}
189
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div>")
209
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div></div>")
190
210
if templ_7745c5c3_Err != nil {
191
211
return templ_7745c5c3_Err
192
212
}
193
213
}
194
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
214
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</div>")
195
215
if templ_7745c5c3_Err != nil {
196
216
return templ_7745c5c3_Err
197
217
}
198
-
if !templ_7745c5c3_IsBuffer {
199
-
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
200
-
}
201
-
return templ_7745c5c3_Err
218
+
return nil
202
219
})
203
220
templ_7745c5c3_Err = base(rlc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
204
221
if templ_7745c5c3_Err != nil {
205
222
return templ_7745c5c3_Err
206
223
}
207
-
if !templ_7745c5c3_IsBuffer {
208
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
209
-
}
210
-
return templ_7745c5c3_Err
224
+
return nil
211
225
})
212
226
}
227
+
228
+
var _ = templruntime.GeneratedTemplate
+4
-5
internal/html/repo_refs.templ
+4
-5
internal/html/repo_refs.templ
···
4
4
import "go.jolheiser.com/ugit/internal/git"
5
5
6
6
type RepoRefsContext struct {
7
-
BaseContext
8
-
RepoHeaderComponentContext
9
-
Branches []string
10
-
Tags []git.Tag
7
+
BaseContext
8
+
RepoHeaderComponentContext
9
+
Branches []string
10
+
Tags []git.Tag
11
11
}
12
12
13
13
templ RepoRefs(rrc RepoRefsContext) {
···
39
39
}
40
40
}
41
41
}
42
-
+73
-49
internal/html/repo_refs_templ.go
+73
-49
internal/html/repo_refs_templ.go
···
1
1
// Code generated by templ - DO NOT EDIT.
2
2
3
-
// templ: version: v0.2.707
3
+
// templ: version: v0.3.924
4
4
package html
5
5
6
6
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
7
8
8
import "github.com/a-h/templ"
9
-
import "context"
10
-
import "io"
11
-
import "bytes"
9
+
import templruntime "github.com/a-h/templ/runtime"
12
10
13
11
import "fmt"
14
12
import "go.jolheiser.com/ugit/internal/git"
···
21
19
}
22
20
23
21
func RepoRefs(rrc RepoRefsContext) templ.Component {
24
-
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
25
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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)
26
28
if !templ_7745c5c3_IsBuffer {
27
-
templ_7745c5c3_Buffer = templ.GetBuffer()
28
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
29
35
}
30
36
ctx = templ.InitializeContext(ctx)
31
37
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
···
33
39
templ_7745c5c3_Var1 = templ.NopComponent
34
40
}
35
41
ctx = templ.ClearChildren(ctx)
36
-
templ_7745c5c3_Var2 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
37
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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)
38
45
if !templ_7745c5c3_IsBuffer {
39
-
templ_7745c5c3_Buffer = templ.GetBuffer()
40
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
41
52
}
53
+
ctx = templ.InitializeContext(ctx)
42
54
templ_7745c5c3_Err = repoHeaderComponent(rrc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer)
43
55
if templ_7745c5c3_Err != nil {
44
56
return templ_7745c5c3_Err
45
57
}
46
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
58
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ")
47
59
if templ_7745c5c3_Err != nil {
48
60
return templ_7745c5c3_Err
49
61
}
50
62
if len(rrc.Branches) > 0 {
51
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h3 class=\"text-text text-lg mt-5\">Branches</h3><div class=\"text-text grid grid-cols-4 sm:grid-cols-8\">")
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\">")
52
64
if templ_7745c5c3_Err != nil {
53
65
return templ_7745c5c3_Err
54
66
}
55
67
for _, branch := range rrc.Branches {
56
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"col-span-2 sm:col-span-1 font-bold\">")
68
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<div class=\"col-span-2 sm:col-span-1 font-bold\">")
57
69
if templ_7745c5c3_Err != nil {
58
70
return templ_7745c5c3_Err
59
71
}
···
66
78
if templ_7745c5c3_Err != nil {
67
79
return templ_7745c5c3_Err
68
80
}
69
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"col-span-2 sm:col-span-7\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
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=\"")
70
82
if templ_7745c5c3_Err != nil {
71
83
return templ_7745c5c3_Err
72
84
}
73
-
var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rrc.RepoHeaderComponentContext.Name, branch))
74
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
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))
75
91
if templ_7745c5c3_Err != nil {
76
92
return templ_7745c5c3_Err
77
93
}
78
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">tree</a>")
94
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">tree</a>")
79
95
if templ_7745c5c3_Err != nil {
80
96
return templ_7745c5c3_Err
81
97
}
···
88
104
if templ_7745c5c3_Err != nil {
89
105
return templ_7745c5c3_Err
90
106
}
91
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
107
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
92
108
if templ_7745c5c3_Err != nil {
93
109
return templ_7745c5c3_Err
94
110
}
95
-
var templ_7745c5c3_Var6 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/log/%s", rrc.RepoHeaderComponentContext.Name, branch))
96
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var6)))
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))
97
117
if templ_7745c5c3_Err != nil {
98
118
return templ_7745c5c3_Err
99
119
}
100
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">log</a></div>")
120
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\">log</a></div>")
101
121
if templ_7745c5c3_Err != nil {
102
122
return templ_7745c5c3_Err
103
123
}
104
124
}
105
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
125
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div>")
106
126
if templ_7745c5c3_Err != nil {
107
127
return templ_7745c5c3_Err
108
128
}
109
129
}
110
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
130
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " ")
111
131
if templ_7745c5c3_Err != nil {
112
132
return templ_7745c5c3_Err
113
133
}
114
134
if len(rrc.Tags) > 0 {
115
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h3 class=\"text-text text-lg mt-5\">Tags</h3><div class=\"text-text grid grid-cols-8\">")
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\">")
116
136
if templ_7745c5c3_Err != nil {
117
137
return templ_7745c5c3_Err
118
138
}
119
139
for _, tag := range rrc.Tags {
120
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"col-span-1 font-bold\">")
140
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"col-span-1 font-bold\">")
121
141
if templ_7745c5c3_Err != nil {
122
142
return templ_7745c5c3_Err
123
143
}
···
130
150
if templ_7745c5c3_Err != nil {
131
151
return templ_7745c5c3_Err
132
152
}
133
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"col-span-7\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
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=\"")
134
154
if templ_7745c5c3_Err != nil {
135
155
return templ_7745c5c3_Err
136
156
}
137
-
var templ_7745c5c3_Var8 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rrc.RepoHeaderComponentContext.Name, tag.Name))
138
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var8)))
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))
139
163
if templ_7745c5c3_Err != nil {
140
164
return templ_7745c5c3_Err
141
165
}
142
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">tree</a>")
166
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\">tree</a>")
143
167
if templ_7745c5c3_Err != nil {
144
168
return templ_7745c5c3_Err
145
169
}
···
152
176
if templ_7745c5c3_Err != nil {
153
177
return templ_7745c5c3_Err
154
178
}
155
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
179
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
156
180
if templ_7745c5c3_Err != nil {
157
181
return templ_7745c5c3_Err
158
182
}
159
-
var templ_7745c5c3_Var10 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/log/%s", rrc.RepoHeaderComponentContext.Name, tag.Name))
160
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var10)))
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))
161
189
if templ_7745c5c3_Err != nil {
162
190
return templ_7745c5c3_Err
163
191
}
164
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">log</a></div>")
192
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\">log</a></div>")
165
193
if templ_7745c5c3_Err != nil {
166
194
return templ_7745c5c3_Err
167
195
}
168
196
if tag.Signature != "" {
169
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<details class=\"col-span-8 whitespace-pre\"><summary class=\"cursor-pointer\">Signature</summary><code>")
197
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<details class=\"col-span-8 whitespace-pre\"><summary class=\"cursor-pointer\">Signature</summary><code>")
170
198
if templ_7745c5c3_Err != nil {
171
199
return templ_7745c5c3_Err
172
200
}
···
179
207
if templ_7745c5c3_Err != nil {
180
208
return templ_7745c5c3_Err
181
209
}
182
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</code></details>")
210
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</code></details>")
183
211
if templ_7745c5c3_Err != nil {
184
212
return templ_7745c5c3_Err
185
213
}
186
214
}
187
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
215
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, " ")
188
216
if templ_7745c5c3_Err != nil {
189
217
return templ_7745c5c3_Err
190
218
}
191
219
if tag.Annotation != "" {
192
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"col-span-8 mb-3\">")
220
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<div class=\"col-span-8 mb-3\">")
193
221
if templ_7745c5c3_Err != nil {
194
222
return templ_7745c5c3_Err
195
223
}
···
202
230
if templ_7745c5c3_Err != nil {
203
231
return templ_7745c5c3_Err
204
232
}
205
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
233
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</div>")
206
234
if templ_7745c5c3_Err != nil {
207
235
return templ_7745c5c3_Err
208
236
}
209
237
}
210
238
}
211
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
239
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</div>")
212
240
if templ_7745c5c3_Err != nil {
213
241
return templ_7745c5c3_Err
214
242
}
215
243
}
216
-
if !templ_7745c5c3_IsBuffer {
217
-
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
218
-
}
219
-
return templ_7745c5c3_Err
244
+
return nil
220
245
})
221
246
templ_7745c5c3_Err = base(rrc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
222
247
if templ_7745c5c3_Err != nil {
223
248
return templ_7745c5c3_Err
224
249
}
225
-
if !templ_7745c5c3_IsBuffer {
226
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
227
-
}
228
-
return templ_7745c5c3_Err
250
+
return nil
229
251
})
230
252
}
253
+
254
+
var _ = templruntime.GeneratedTemplate
+6
-8
internal/html/repo_search.templ
+6
-8
internal/html/repo_search.templ
···
11
11
12
12
func (s SearchContext) DedupeResults() [][]git.GrepResult {
13
13
var (
14
-
results [][]git.GrepResult
15
-
currentFile string
16
-
currentResults []git.GrepResult
14
+
results [][]git.GrepResult
15
+
currentFile string
17
16
)
17
+
var idx int
18
18
for _, result := range s.Results {
19
19
if result.File == currentFile {
20
-
currentResults = append(currentResults, result)
20
+
results[idx-1] = append(results[idx-1], result)
21
21
continue
22
22
}
23
-
if currentFile != "" {
24
-
results = append(results, currentResults)
25
-
}
23
+
results = append(results, []git.GrepResult{result})
26
24
currentFile = result.File
27
-
currentResults = []git.GrepResult{result}
25
+
idx++
28
26
}
29
27
30
28
return results
+76
-57
internal/html/repo_search_templ.go
+76
-57
internal/html/repo_search_templ.go
···
1
1
// Code generated by templ - DO NOT EDIT.
2
2
3
-
// templ: version: v0.2.707
3
+
// templ: version: v0.3.924
4
4
package html
5
5
6
6
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
7
8
8
import "github.com/a-h/templ"
9
-
import "context"
10
-
import "io"
11
-
import "bytes"
9
+
import templruntime "github.com/a-h/templ/runtime"
12
10
13
11
import "fmt"
14
12
import "go.jolheiser.com/ugit/internal/git"
···
21
19
22
20
func (s SearchContext) DedupeResults() [][]git.GrepResult {
23
21
var (
24
-
results [][]git.GrepResult
25
-
currentFile string
26
-
currentResults []git.GrepResult
22
+
results [][]git.GrepResult
23
+
currentFile string
27
24
)
25
+
var idx int
28
26
for _, result := range s.Results {
29
27
if result.File == currentFile {
30
-
currentResults = append(currentResults, result)
28
+
results[idx-1] = append(results[idx-1], result)
31
29
continue
32
30
}
33
-
if currentFile != "" {
34
-
results = append(results, currentResults)
35
-
}
31
+
results = append(results, []git.GrepResult{result})
36
32
currentFile = result.File
37
-
currentResults = []git.GrepResult{result}
33
+
idx++
38
34
}
39
35
40
36
return results
41
37
}
42
38
43
39
func RepoSearch(sc SearchContext) templ.Component {
44
-
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
45
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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
46
if !templ_7745c5c3_IsBuffer {
47
-
templ_7745c5c3_Buffer = templ.GetBuffer()
48
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
49
53
}
50
54
ctx = templ.InitializeContext(ctx)
51
55
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
···
53
57
templ_7745c5c3_Var1 = templ.NopComponent
54
58
}
55
59
ctx = templ.ClearChildren(ctx)
56
-
templ_7745c5c3_Var2 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
57
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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)
58
63
if !templ_7745c5c3_IsBuffer {
59
-
templ_7745c5c3_Buffer = templ.GetBuffer()
60
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
61
70
}
71
+
ctx = templ.InitializeContext(ctx)
62
72
templ_7745c5c3_Err = repoHeaderComponent(sc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer)
63
73
if templ_7745c5c3_Err != nil {
64
74
return templ_7745c5c3_Err
···
69
79
return templ_7745c5c3_Err
70
80
}
71
81
}
72
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
82
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ")
73
83
if templ_7745c5c3_Err != nil {
74
84
return templ_7745c5c3_Err
75
85
}
76
86
if len(sc.DedupeResults()) == 0 {
77
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p class=\"text-text mt-5 text-lg\">No results</p>")
87
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<p class=\"text-text mt-5 text-lg\">No results</p>")
78
88
if templ_7745c5c3_Err != nil {
79
89
return templ_7745c5c3_Err
80
90
}
81
91
}
82
-
if !templ_7745c5c3_IsBuffer {
83
-
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
84
-
}
85
-
return templ_7745c5c3_Err
92
+
return nil
86
93
})
87
94
templ_7745c5c3_Err = base(sc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
88
95
if templ_7745c5c3_Err != nil {
89
96
return templ_7745c5c3_Err
90
97
}
91
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<script>\n\t\tconst search = new URLSearchParams(window.location.search).get(\"q\");\n\t\tif (search !== \"\") document.querySelector(\"#search\").value = search;\n\t</script>")
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>")
92
99
if templ_7745c5c3_Err != nil {
93
100
return templ_7745c5c3_Err
94
101
}
95
-
if !templ_7745c5c3_IsBuffer {
96
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
97
-
}
98
-
return templ_7745c5c3_Err
102
+
return nil
99
103
})
100
104
}
101
105
102
106
func repoSearchResult(repo, ref string, results []git.GrepResult) templ.Component {
103
-
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
104
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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)
105
113
if !templ_7745c5c3_IsBuffer {
106
-
templ_7745c5c3_Buffer = templ.GetBuffer()
107
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
108
120
}
109
121
ctx = templ.InitializeContext(ctx)
110
122
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
···
112
124
templ_7745c5c3_Var3 = templ.NopComponent
113
125
}
114
126
ctx = templ.ClearChildren(ctx)
115
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"text-text mt-5\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
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=\"")
116
128
if templ_7745c5c3_Err != nil {
117
129
return templ_7745c5c3_Err
118
130
}
119
-
var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, results[0].File, results[0].Line))
120
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
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))
121
137
if templ_7745c5c3_Err != nil {
122
138
return templ_7745c5c3_Err
123
139
}
124
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
140
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">")
125
141
if templ_7745c5c3_Err != nil {
126
142
return templ_7745c5c3_Err
127
143
}
128
144
var templ_7745c5c3_Var5 string
129
145
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(results[0].File)
130
146
if templ_7745c5c3_Err != nil {
131
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 50, Col: 230}
147
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 48, Col: 230}
132
148
}
133
149
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
134
150
if templ_7745c5c3_Err != nil {
135
151
return templ_7745c5c3_Err
136
152
}
137
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div class=\"code\">")
153
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</a></div><div class=\"code\">")
138
154
if templ_7745c5c3_Err != nil {
139
155
return templ_7745c5c3_Err
140
156
}
···
142
158
if templ_7745c5c3_Err != nil {
143
159
return templ_7745c5c3_Err
144
160
}
145
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
161
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div>")
146
162
if templ_7745c5c3_Err != nil {
147
163
return templ_7745c5c3_Err
148
164
}
149
165
if len(results) > 1 {
150
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<details class=\"text-text cursor-pointer\"><summary>")
166
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<details class=\"text-text cursor-pointer\"><summary>")
151
167
if templ_7745c5c3_Err != nil {
152
168
return templ_7745c5c3_Err
153
169
}
154
170
var templ_7745c5c3_Var6 string
155
171
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d ", len(results[1:])))
156
172
if templ_7745c5c3_Err != nil {
157
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 56, Col: 50}
173
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 54, Col: 50}
158
174
}
159
175
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
160
176
if templ_7745c5c3_Err != nil {
161
177
return templ_7745c5c3_Err
162
178
}
163
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("more</summary> ")
179
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "more</summary> ")
164
180
if templ_7745c5c3_Err != nil {
165
181
return templ_7745c5c3_Err
166
182
}
167
183
for _, result := range results[1:] {
168
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"text-text mt-5 ml-5\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
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=\"")
169
185
if templ_7745c5c3_Err != nil {
170
186
return templ_7745c5c3_Err
171
187
}
172
-
var templ_7745c5c3_Var7 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, result.File, result.Line))
173
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var7)))
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))
174
194
if templ_7745c5c3_Err != nil {
175
195
return templ_7745c5c3_Err
176
196
}
177
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
197
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\">")
178
198
if templ_7745c5c3_Err != nil {
179
199
return templ_7745c5c3_Err
180
200
}
181
201
var templ_7745c5c3_Var8 string
182
202
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(results[0].File)
183
203
if templ_7745c5c3_Err != nil {
184
-
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 58, Col: 230}
204
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 56, Col: 230}
185
205
}
186
206
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
187
207
if templ_7745c5c3_Err != nil {
188
208
return templ_7745c5c3_Err
189
209
}
190
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div class=\"code ml-5\">")
210
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</a></div><div class=\"code ml-5\">")
191
211
if templ_7745c5c3_Err != nil {
192
212
return templ_7745c5c3_Err
193
213
}
···
195
215
if templ_7745c5c3_Err != nil {
196
216
return templ_7745c5c3_Err
197
217
}
198
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
218
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div>")
199
219
if templ_7745c5c3_Err != nil {
200
220
return templ_7745c5c3_Err
201
221
}
202
222
}
203
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</details>")
223
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</details>")
204
224
if templ_7745c5c3_Err != nil {
205
225
return templ_7745c5c3_Err
206
226
}
207
227
}
208
-
if !templ_7745c5c3_IsBuffer {
209
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
210
-
}
211
-
return templ_7745c5c3_Err
228
+
return nil
212
229
})
213
230
}
231
+
232
+
var _ = templruntime.GeneratedTemplate
+65
-40
internal/html/repo_templ.go
+65
-40
internal/html/repo_templ.go
···
1
1
// Code generated by templ - DO NOT EDIT.
2
2
3
-
// templ: version: v0.2.707
3
+
// templ: version: v0.3.924
4
4
package html
5
5
6
6
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
7
8
8
import "github.com/a-h/templ"
9
-
import "context"
10
-
import "io"
11
-
import "bytes"
9
+
import templruntime "github.com/a-h/templ/runtime"
12
10
13
11
import "fmt"
14
12
···
21
19
}
22
20
23
21
func repoHeaderComponent(rhcc RepoHeaderComponentContext) templ.Component {
24
-
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
25
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
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)
26
28
if !templ_7745c5c3_IsBuffer {
27
-
templ_7745c5c3_Buffer = templ.GetBuffer()
28
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
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
+
}()
29
35
}
30
36
ctx = templ.InitializeContext(ctx)
31
37
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
···
33
39
templ_7745c5c3_Var1 = templ.NopComponent
34
40
}
35
41
ctx = templ.ClearChildren(ctx)
36
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"mb-1 text-text\"><a class=\"text-lg underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
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=\"")
37
43
if templ_7745c5c3_Err != nil {
38
44
return templ_7745c5c3_Err
39
45
}
40
-
var templ_7745c5c3_Var2 templ.SafeURL = templ.SafeURL("/" + rhcc.Name)
41
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var2)))
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))
42
52
if templ_7745c5c3_Err != nil {
43
53
return templ_7745c5c3_Err
44
54
}
45
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
55
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\">")
46
56
if templ_7745c5c3_Err != nil {
47
57
return templ_7745c5c3_Err
48
58
}
···
55
65
if templ_7745c5c3_Err != nil {
56
66
return templ_7745c5c3_Err
57
67
}
58
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a> ")
68
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</a> ")
59
69
if templ_7745c5c3_Err != nil {
60
70
return templ_7745c5c3_Err
61
71
}
···
69
79
if templ_7745c5c3_Err != nil {
70
80
return templ_7745c5c3_Err
71
81
}
72
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <a class=\"text-text/80 text-sm underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
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=\"")
73
83
if templ_7745c5c3_Err != nil {
74
84
return templ_7745c5c3_Err
75
85
}
76
-
var templ_7745c5c3_Var5 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rhcc.Name, rhcc.Ref))
77
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var5)))
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))
78
92
if templ_7745c5c3_Err != nil {
79
93
return templ_7745c5c3_Err
80
94
}
81
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
95
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">")
82
96
if templ_7745c5c3_Err != nil {
83
97
return templ_7745c5c3_Err
84
98
}
···
91
105
if templ_7745c5c3_Err != nil {
92
106
return templ_7745c5c3_Err
93
107
}
94
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a> ")
108
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</a> ")
95
109
if templ_7745c5c3_Err != nil {
96
110
return templ_7745c5c3_Err
97
111
}
···
105
119
if templ_7745c5c3_Err != nil {
106
120
return templ_7745c5c3_Err
107
121
}
108
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
122
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, " <a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
109
123
if templ_7745c5c3_Err != nil {
110
124
return templ_7745c5c3_Err
111
125
}
112
-
var templ_7745c5c3_Var8 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/refs", rhcc.Name))
113
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var8)))
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))
114
132
if templ_7745c5c3_Err != nil {
115
133
return templ_7745c5c3_Err
116
134
}
117
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">refs</a> ")
135
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\">refs</a> ")
118
136
if templ_7745c5c3_Err != nil {
119
137
return templ_7745c5c3_Err
120
138
}
···
127
145
if templ_7745c5c3_Err != nil {
128
146
return templ_7745c5c3_Err
129
147
}
130
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
148
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " <a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
131
149
if templ_7745c5c3_Err != nil {
132
150
return templ_7745c5c3_Err
133
151
}
134
-
var templ_7745c5c3_Var10 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/log/%s", rhcc.Name, rhcc.Ref))
135
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var10)))
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))
136
158
if templ_7745c5c3_Err != nil {
137
159
return templ_7745c5c3_Err
138
160
}
139
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">log</a> ")
161
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\">log</a> ")
140
162
if templ_7745c5c3_Err != nil {
141
163
return templ_7745c5c3_Err
142
164
}
···
149
171
if templ_7745c5c3_Err != nil {
150
172
return templ_7745c5c3_Err
151
173
}
152
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<form class=\"inline-block\" action=\"")
174
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<form class=\"inline-block\" action=\"")
153
175
if templ_7745c5c3_Err != nil {
154
176
return templ_7745c5c3_Err
155
177
}
156
-
var templ_7745c5c3_Var12 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/search", rhcc.Name))
157
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var12)))
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))
158
184
if templ_7745c5c3_Err != nil {
159
185
return templ_7745c5c3_Err
160
186
}
161
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" 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>")
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>")
162
188
if templ_7745c5c3_Err != nil {
163
189
return templ_7745c5c3_Err
164
190
}
···
171
197
if templ_7745c5c3_Err != nil {
172
198
return templ_7745c5c3_Err
173
199
}
174
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<pre class=\"text-text inline select-all bg-base dark:bg-base/50 p-1 rounded\">")
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\">")
175
201
if templ_7745c5c3_Err != nil {
176
202
return templ_7745c5c3_Err
177
203
}
···
184
210
if templ_7745c5c3_Err != nil {
185
211
return templ_7745c5c3_Err
186
212
}
187
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</pre></div><div class=\"text-subtext0 mb-1\">")
213
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</pre></div><div class=\"text-subtext0 mb-1\">")
188
214
if templ_7745c5c3_Err != nil {
189
215
return templ_7745c5c3_Err
190
216
}
191
217
for _, tag := range rhcc.Tags {
192
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<span class=\"rounded border-rosewater border-solid border pb-0.5 px-1 mr-1 mb-1 inline-block\">")
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\">")
193
219
if templ_7745c5c3_Err != nil {
194
220
return templ_7745c5c3_Err
195
221
}
···
202
228
if templ_7745c5c3_Err != nil {
203
229
return templ_7745c5c3_Err
204
230
}
205
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span>")
231
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</span>")
206
232
if templ_7745c5c3_Err != nil {
207
233
return templ_7745c5c3_Err
208
234
}
209
235
}
210
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"text-text/80 mb-1\">")
236
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</div><div class=\"text-text/80 mb-1\">")
211
237
if templ_7745c5c3_Err != nil {
212
238
return templ_7745c5c3_Err
213
239
}
···
220
246
if templ_7745c5c3_Err != nil {
221
247
return templ_7745c5c3_Err
222
248
}
223
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
249
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</div>")
224
250
if templ_7745c5c3_Err != nil {
225
251
return templ_7745c5c3_Err
226
252
}
227
-
if !templ_7745c5c3_IsBuffer {
228
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
229
-
}
230
-
return templ_7745c5c3_Err
253
+
return nil
231
254
})
232
255
}
256
+
257
+
var _ = templruntime.GeneratedTemplate
+65
-44
internal/html/repo_tree_templ.go
+65
-44
internal/html/repo_tree_templ.go
···
1
1
// Code generated by templ - DO NOT EDIT.
2
2
3
-
// templ: version: v0.2.707
3
+
// templ: version: v0.3.924
4
4
package html
5
5
6
6
//lint:file-ignore SA4006 This context is only used if a nested component is present.
7
7
8
8
import "github.com/a-h/templ"
9
-
import "context"
10
-
import "io"
11
-
import "bytes"
9
+
import templruntime "github.com/a-h/templ/runtime"
12
10
13
11
import (
14
12
"fmt"
···
25
23
}
26
24
27
25
func RepoTree(rtc RepoTreeContext) templ.Component {
28
-
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
29
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
26
+
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
27
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
28
+
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
29
+
return templ_7745c5c3_CtxErr
30
+
}
31
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
30
32
if !templ_7745c5c3_IsBuffer {
31
-
templ_7745c5c3_Buffer = templ.GetBuffer()
32
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
33
+
defer func() {
34
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
35
+
if templ_7745c5c3_Err == nil {
36
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
37
+
}
38
+
}()
33
39
}
34
40
ctx = templ.InitializeContext(ctx)
35
41
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
···
37
43
templ_7745c5c3_Var1 = templ.NopComponent
38
44
}
39
45
ctx = templ.ClearChildren(ctx)
40
-
templ_7745c5c3_Var2 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
41
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
46
+
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
47
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
48
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
42
49
if !templ_7745c5c3_IsBuffer {
43
-
templ_7745c5c3_Buffer = templ.GetBuffer()
44
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
50
+
defer func() {
51
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
52
+
if templ_7745c5c3_Err == nil {
53
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
54
+
}
55
+
}()
45
56
}
57
+
ctx = templ.InitializeContext(ctx)
46
58
templ_7745c5c3_Err = repoHeaderComponent(rtc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer)
47
59
if templ_7745c5c3_Err != nil {
48
60
return templ_7745c5c3_Err
49
61
}
50
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
62
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ")
51
63
if templ_7745c5c3_Err != nil {
52
64
return templ_7745c5c3_Err
53
65
}
···
55
67
if templ_7745c5c3_Err != nil {
56
68
return templ_7745c5c3_Err
57
69
}
58
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
70
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " ")
59
71
if templ_7745c5c3_Err != nil {
60
72
return templ_7745c5c3_Err
61
73
}
···
63
75
if templ_7745c5c3_Err != nil {
64
76
return templ_7745c5c3_Err
65
77
}
66
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
78
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, " ")
67
79
if templ_7745c5c3_Err != nil {
68
80
return templ_7745c5c3_Err
69
81
}
···
71
83
if templ_7745c5c3_Err != nil {
72
84
return templ_7745c5c3_Err
73
85
}
74
-
if !templ_7745c5c3_IsBuffer {
75
-
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
76
-
}
77
-
return templ_7745c5c3_Err
86
+
return nil
78
87
})
79
88
templ_7745c5c3_Err = base(rtc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
80
89
if templ_7745c5c3_Err != nil {
81
90
return templ_7745c5c3_Err
82
91
}
83
-
if !templ_7745c5c3_IsBuffer {
84
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
85
-
}
86
-
return templ_7745c5c3_Err
92
+
return nil
87
93
})
88
94
}
89
95
···
102
108
}
103
109
104
110
func repoTreeComponent(rtcc RepoTreeComponentContext) templ.Component {
105
-
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
106
-
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
111
+
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
112
+
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
113
+
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
114
+
return templ_7745c5c3_CtxErr
115
+
}
116
+
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
107
117
if !templ_7745c5c3_IsBuffer {
108
-
templ_7745c5c3_Buffer = templ.GetBuffer()
109
-
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
118
+
defer func() {
119
+
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
120
+
if templ_7745c5c3_Err == nil {
121
+
templ_7745c5c3_Err = templ_7745c5c3_BufErr
122
+
}
123
+
}()
110
124
}
111
125
ctx = templ.InitializeContext(ctx)
112
126
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
···
114
128
templ_7745c5c3_Var3 = templ.NopComponent
115
129
}
116
130
ctx = templ.ClearChildren(ctx)
117
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<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
+
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\">")
118
132
if templ_7745c5c3_Err != nil {
119
133
return templ_7745c5c3_Err
120
134
}
121
135
if rtcc.Back != "" {
122
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<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
+
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=\"")
123
137
if templ_7745c5c3_Err != nil {
124
138
return templ_7745c5c3_Err
125
139
}
126
-
var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rtcc.Repo, rtcc.Ref, rtcc.Back))
127
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
140
+
var templ_7745c5c3_Var4 templ.SafeURL
141
+
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rtcc.Repo, rtcc.Ref, rtcc.Back)))
142
+
if templ_7745c5c3_Err != nil {
143
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_tree.templ`, Line: 44, Col: 194}
144
+
}
145
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
128
146
if templ_7745c5c3_Err != nil {
129
147
return templ_7745c5c3_Err
130
148
}
131
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">..</a></div>")
149
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">..</a></div>")
132
150
if templ_7745c5c3_Err != nil {
133
151
return templ_7745c5c3_Err
134
152
}
135
153
}
136
154
for _, fi := range rtcc.Tree {
137
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"sm:col-span-1 break-keep\">")
155
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<div class=\"sm:col-span-1 break-keep\">")
138
156
if templ_7745c5c3_Err != nil {
139
157
return templ_7745c5c3_Err
140
158
}
···
147
165
if templ_7745c5c3_Err != nil {
148
166
return templ_7745c5c3_Err
149
167
}
150
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"sm:col-span-1 text-right\">")
168
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div><div class=\"sm:col-span-1 text-right\">")
151
169
if templ_7745c5c3_Err != nil {
152
170
return templ_7745c5c3_Err
153
171
}
···
160
178
if templ_7745c5c3_Err != nil {
161
179
return templ_7745c5c3_Err
162
180
}
163
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"sm:col-span-6 overflow-hidden text-ellipsis\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
181
+
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=\"")
164
182
if templ_7745c5c3_Err != nil {
165
183
return templ_7745c5c3_Err
166
184
}
167
-
var templ_7745c5c3_Var7 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rtcc.Repo, rtcc.Ref, fi.Path))
168
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var7)))
185
+
var templ_7745c5c3_Var7 templ.SafeURL
186
+
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rtcc.Repo, rtcc.Ref, fi.Path)))
187
+
if templ_7745c5c3_Err != nil {
188
+
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_tree.templ`, Line: 49, Col: 222}
189
+
}
190
+
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
169
191
if templ_7745c5c3_Err != nil {
170
192
return templ_7745c5c3_Err
171
193
}
172
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
194
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\">")
173
195
if templ_7745c5c3_Err != nil {
174
196
return templ_7745c5c3_Err
175
197
}
···
182
204
if templ_7745c5c3_Err != nil {
183
205
return templ_7745c5c3_Err
184
206
}
185
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div>")
207
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</a></div>")
186
208
if templ_7745c5c3_Err != nil {
187
209
return templ_7745c5c3_Err
188
210
}
189
211
}
190
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
212
+
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div>")
191
213
if templ_7745c5c3_Err != nil {
192
214
return templ_7745c5c3_Err
193
215
}
194
-
if !templ_7745c5c3_IsBuffer {
195
-
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
196
-
}
197
-
return templ_7745c5c3_Err
216
+
return nil
198
217
})
199
218
}
219
+
220
+
var _ = templruntime.GeneratedTemplate
+1
-1
internal/html/tailwind.config.js
+1
-1
internal/html/tailwind.config.js
+1
-1
internal/html/tailwind.go
+1
-1
internal/html/tailwind.go
···
5
5
6
6
func TailwindHandler(w http.ResponseWriter, r *http.Request) {
7
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}*,::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: }.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}.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}.chroma .line{overflow:scroll}.bg,.chroma{color:#4c4f69;background-color:#eff1f5}.chroma .lntd:last-child{width:100%}.chroma .ln:target,.chroma .lnt:target{color:#bcc0cc;background-color:#eff1f5}.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{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:#45475a;background-color:#1e1e2e}.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{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\\: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-4{grid-column:span 4/span 4}.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-8{grid-template-columns:repeat(8,minmax(0,1fr))}}"))
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
9
}
+5
-4
internal/http/http.go
+5
-4
internal/http/http.go
···
18
18
// Server is the container struct for the HTTP server
19
19
type Server struct {
20
20
port int
21
-
mux *chi.Mux
21
+
Mux *chi.Mux
22
22
}
23
23
24
24
// ListenAndServe simply wraps http.ListenAndServe to contain the functionality here
25
25
func (s Server) ListenAndServe() error {
26
-
return http.ListenAndServe(fmt.Sprintf("localhost:%d", s.port), s.mux)
26
+
return http.ListenAndServe(fmt.Sprintf("localhost:%d", s.port), s.Mux)
27
27
}
28
28
29
29
// Settings is the configuration for the HTTP server
···
34
34
Port int
35
35
RepoDir string
36
36
Profile Profile
37
+
ShowPrivate bool
37
38
}
38
39
39
40
// Profile is the index profile
···
101
102
r.Get("/tailwind.css", html.TailwindHandler)
102
103
})
103
104
104
-
return Server{mux: mux, port: settings.Port}
105
+
return Server{Mux: mux, port: settings.Port}
105
106
}
106
107
107
108
type repoHandler struct {
···
125
126
Name: chi.URLParam(r, "repo"),
126
127
Ref: ref,
127
128
CloneURL: rh.s.CloneURL,
128
-
Tags: repo.Meta.Tags,
129
+
Tags: repo.Meta.Tags.Slice(),
129
130
}
130
131
}
131
132
+2
-3
internal/http/httperr/httperr.go
+2
-3
internal/http/httperr/httperr.go
···
2
2
3
3
import (
4
4
"errors"
5
+
"log/slog"
5
6
"net/http"
6
-
7
-
"github.com/charmbracelet/log"
8
7
)
9
8
10
9
type httpError struct {
···
41
40
status = httpErr.status
42
41
}
43
42
44
-
log.Error(err)
43
+
slog.Error("httperr Handler error", "error", err)
45
44
http.Error(w, http.StatusText(status), status)
46
45
}
47
46
}
+122
internal/http/httperr/httperr_test.go
+122
internal/http/httperr/httperr_test.go
···
1
+
package httperr_test
2
+
3
+
import (
4
+
"errors"
5
+
"net/http"
6
+
"net/http/httptest"
7
+
"testing"
8
+
9
+
"github.com/alecthomas/assert/v2"
10
+
"go.jolheiser.com/ugit/internal/http/httperr"
11
+
)
12
+
13
+
func successHandler(w http.ResponseWriter, r *http.Request) error {
14
+
w.WriteHeader(http.StatusOK)
15
+
return nil
16
+
}
17
+
18
+
func errorHandler(w http.ResponseWriter, r *http.Request) error {
19
+
return errors.New("test error")
20
+
}
21
+
22
+
func statusErrorHandler(status int) func(w http.ResponseWriter, r *http.Request) error {
23
+
return func(w http.ResponseWriter, r *http.Request) error {
24
+
return httperr.Status(errors.New("test error"), status)
25
+
}
26
+
}
27
+
28
+
func TestHandler_Success(t *testing.T) {
29
+
handler := httperr.Handler(successHandler)
30
+
31
+
req := httptest.NewRequest("GET", "/", nil)
32
+
recorder := httptest.NewRecorder()
33
+
34
+
handler.ServeHTTP(recorder, req)
35
+
36
+
assert.Equal(t, http.StatusOK, recorder.Code)
37
+
}
38
+
39
+
func TestHandler_Error(t *testing.T) {
40
+
handler := httperr.Handler(errorHandler)
41
+
42
+
req := httptest.NewRequest("GET", "/", nil)
43
+
recorder := httptest.NewRecorder()
44
+
45
+
handler.ServeHTTP(recorder, req)
46
+
47
+
assert.Equal(t, http.StatusInternalServerError, recorder.Code)
48
+
}
49
+
50
+
func TestHandler_StatusError(t *testing.T) {
51
+
testCases := []struct {
52
+
name string
53
+
status int
54
+
expectedStatus int
55
+
}{
56
+
{
57
+
name: "not found",
58
+
status: http.StatusNotFound,
59
+
expectedStatus: http.StatusNotFound,
60
+
},
61
+
{
62
+
name: "bad request",
63
+
status: http.StatusBadRequest,
64
+
expectedStatus: http.StatusBadRequest,
65
+
},
66
+
{
67
+
name: "unauthorized",
68
+
status: http.StatusUnauthorized,
69
+
expectedStatus: http.StatusUnauthorized,
70
+
},
71
+
}
72
+
73
+
for _, tc := range testCases {
74
+
t.Run(tc.name, func(t *testing.T) {
75
+
handler := httperr.Handler(statusErrorHandler(tc.status))
76
+
77
+
req := httptest.NewRequest("GET", "/", nil)
78
+
recorder := httptest.NewRecorder()
79
+
80
+
handler.ServeHTTP(recorder, req)
81
+
82
+
assert.Equal(t, tc.expectedStatus, recorder.Code)
83
+
})
84
+
}
85
+
}
86
+
87
+
type unwrapper interface {
88
+
Unwrap() error
89
+
}
90
+
91
+
func TestError(t *testing.T) {
92
+
originalErr := errors.New("original error")
93
+
httpErr := httperr.Error(originalErr)
94
+
95
+
assert.Equal(t, originalErr.Error(), httpErr.Error())
96
+
97
+
unwrapper, ok := any(httpErr).(unwrapper)
98
+
assert.True(t, ok)
99
+
assert.Equal(t, originalErr, unwrapper.Unwrap())
100
+
}
101
+
102
+
func TestStatus(t *testing.T) {
103
+
originalErr := errors.New("original error")
104
+
httpErr := httperr.Status(originalErr, http.StatusNotFound)
105
+
106
+
assert.Equal(t, originalErr.Error(), httpErr.Error())
107
+
108
+
unwrapper, ok := any(httpErr).(unwrapper)
109
+
assert.True(t, ok)
110
+
assert.Equal(t, originalErr, unwrapper.Unwrap())
111
+
112
+
handler := httperr.Handler(func(w http.ResponseWriter, r *http.Request) error {
113
+
return httpErr
114
+
})
115
+
116
+
req := httptest.NewRequest("GET", "/", nil)
117
+
recorder := httptest.NewRecorder()
118
+
119
+
handler.ServeHTTP(recorder, req)
120
+
121
+
assert.Equal(t, http.StatusNotFound, recorder.Code)
122
+
}
+6
-3
internal/http/index.go
+6
-3
internal/http/index.go
···
3
3
import (
4
4
"net/http"
5
5
"os"
6
-
"slices"
7
6
"sort"
8
7
"strings"
9
8
"time"
···
31
30
return httperr.Error(err)
32
31
}
33
32
if repo.Meta.Private {
34
-
continue
33
+
if !rh.s.ShowPrivate {
34
+
continue
35
+
}
36
+
repo.Meta.Tags.Add("private")
35
37
}
36
-
if tagFilter != "" && !slices.Contains(repo.Meta.Tags, strings.ToLower(tagFilter)) {
38
+
39
+
if tagFilter != "" && !repo.Meta.Tags.Contains(strings.ToLower(tagFilter)) {
37
40
continue
38
41
}
39
42
repos = append(repos, repo)
+4
-1
internal/http/middleware.go
+4
-1
internal/http/middleware.go
···
27
27
return httperr.Status(err, httpErr)
28
28
}
29
29
if repo.Meta.Private {
30
-
return httperr.Status(errors.New("could not get git repo"), http.StatusNotFound)
30
+
if !rh.s.ShowPrivate {
31
+
return httperr.Status(errors.New("could not get git repo"), http.StatusNotFound)
32
+
}
33
+
repo.Meta.Tags.Add("private")
31
34
}
32
35
r = r.WithContext(context.WithValue(r.Context(), repoCtxKey, repo))
33
36
next.ServeHTTP(w, r)
+12
-3
internal/http/repo.go
+12
-3
internal/http/repo.go
···
88
88
}
89
89
90
90
var buf bytes.Buffer
91
-
if err := markup.Code.Convert([]byte(content), filepath.Base(path), &buf); err != nil {
91
+
if err := markup.Convert([]byte(content), filepath.Base(path), "L", &buf); err != nil {
92
92
return httperr.Error(err)
93
93
}
94
94
95
+
commit := ref
96
+
if len(ref) < 40 {
97
+
commitObj, err := repo.GetCommitFromRef(ref)
98
+
if err == nil {
99
+
commit = commitObj.Hash.String()
100
+
}
101
+
}
102
+
95
103
if err := html.RepoFile(html.RepoFileContext{
96
104
BaseContext: rh.baseContext(),
97
105
RepoHeaderComponentContext: rh.repoHeaderContext(repo, r),
98
106
RepoBreadcrumbComponentContext: rh.repoBreadcrumbContext(repo, r, path),
99
107
Code: buf.String(),
108
+
Commit: commit,
109
+
Path: path,
100
110
}).Render(r.Context(), w); err != nil {
101
111
return httperr.Error(err)
102
112
}
···
158
168
159
169
for idx, p := range commit.Files {
160
170
var patch bytes.Buffer
161
-
if err := markup.Code.Basic([]byte(p.Patch), "commit.patch", &patch); err != nil {
171
+
if err := markup.Convert([]byte(p.Patch), "commit.patch", p.Path()+"-L", &patch); err != nil {
162
172
return httperr.Error(err)
163
173
}
164
174
commit.Files[idx].Patch = patch.String()
···
206
216
}
207
217
results[idx].Content = buf.String()
208
218
}
209
-
210
219
}
211
220
212
221
if err := html.RepoSearch(html.SearchContext{
-37
internal/ssh/form.go
-37
internal/ssh/form.go
···
1
-
package ssh
2
-
3
-
import (
4
-
"strings"
5
-
6
-
"github.com/charmbracelet/huh"
7
-
"go.jolheiser.com/ugit/internal/git"
8
-
)
9
-
10
-
type stringSliceAccessor []string
11
-
12
-
func (s stringSliceAccessor) Get() string {
13
-
return strings.Join(s, "\n")
14
-
}
15
-
16
-
func (s stringSliceAccessor) Set(value string) {
17
-
s = strings.Split(value, "\n")
18
-
}
19
-
20
-
func newForm(meta git.RepoMeta) *huh.Form {
21
-
return huh.NewForm(
22
-
huh.NewGroup(
23
-
huh.NewText().
24
-
Title("Description").
25
-
Value(&meta.Description),
26
-
huh.NewConfirm().
27
-
Title("Visibility").
28
-
Affirmative("Public").
29
-
Negative("Private").
30
-
Value(&meta.Private),
31
-
huh.NewText().
32
-
Title("Tags").
33
-
Description("One per line").
34
-
Accessor(stringSliceAccessor(meta.Tags)),
35
-
),
36
-
)
37
-
}
+2
-2
internal/ssh/ssh.go
+2
-2
internal/ssh/ssh.go
···
2
2
3
3
import (
4
4
"fmt"
5
+
"log"
5
6
6
-
"github.com/charmbracelet/log"
7
7
"github.com/charmbracelet/ssh"
8
8
"github.com/charmbracelet/wish"
9
9
"github.com/charmbracelet/wish/logging"
···
42
42
func (a hooks) Fetch(_ string, _ ssh.PublicKey) {}
43
43
44
44
var (
45
-
DefaultLogger logging.Logger = log.StandardLog()
45
+
DefaultLogger logging.Logger = log.Default()
46
46
NoopLogger logging.Logger = noopLogger{}
47
47
)
48
48
+3
-13
internal/ssh/wish.go
+3
-13
internal/ssh/wish.go
···
5
5
"errors"
6
6
"fmt"
7
7
"io/fs"
8
+
"log/slog"
8
9
"os"
9
10
"path/filepath"
10
11
"strings"
···
12
13
13
14
"go.jolheiser.com/ugit/internal/git"
14
15
15
-
"github.com/charmbracelet/log"
16
16
"github.com/charmbracelet/ssh"
17
17
"github.com/charmbracelet/wish"
18
18
)
···
91
91
if errors.Is(err, ErrInvalidRepo) {
92
92
Fatal(s, ErrInvalidRepo)
93
93
}
94
-
log.Error("unknown git error", "error", err)
94
+
slog.Error("unknown git error", "error", err)
95
95
Fatal(s, ErrSystemMalfunction)
96
96
}
97
97
gh.Fetch(repo, pk)
···
103
103
if len(cmd) == 0 {
104
104
des, err := os.ReadDir(repoDir)
105
105
if err != nil && err != fs.ErrNotExist {
106
-
log.Error("invalid repository", "error", err)
106
+
slog.Error("invalid repository", "error", err)
107
107
}
108
108
tw := tabwriter.NewWriter(s, 0, 0, 1, ' ', 0)
109
109
for _, de := range des {
···
122
122
}
123
123
tw.Flush()
124
124
}
125
-
126
-
// Edit repo
127
-
if len(cmd) == 1 {
128
-
repo, err := git.NewRepo(cmd[0])
129
-
if err != nil {
130
-
Fatal(s, ErrInvalidRepo)
131
-
}
132
-
133
-
}
134
-
135
125
sh(s)
136
126
}
137
127
}
+10
nix/default.nix
+10
nix/default.nix
+228
nix/module.nix
+228
nix/module.nix
···
1
+
{
2
+
pkgs,
3
+
lib,
4
+
config,
5
+
...
6
+
}:
7
+
let
8
+
cfg = config.services.ugit;
9
+
pkg = pkgs.callPackage ./pkg.nix { inherit pkgs; };
10
+
yamlFormat = pkgs.formats.yaml { };
11
+
instanceOptions =
12
+
{ name, config, ... }:
13
+
let
14
+
inherit (lib) mkEnableOption mkOption types;
15
+
baseDir = "/var/lib/ugit-${name}";
16
+
in
17
+
{
18
+
options = {
19
+
enable = mkEnableOption "Enable ugit";
20
+
21
+
package = mkOption {
22
+
type = types.package;
23
+
description = "ugit package to use";
24
+
default = pkg;
25
+
};
26
+
27
+
homeDir = mkOption {
28
+
type = types.str;
29
+
description = "ugit home directory";
30
+
default = baseDir;
31
+
};
32
+
33
+
repoDir = mkOption {
34
+
type = types.str;
35
+
description = "where ugit stores repositories";
36
+
default = "${baseDir}/repos";
37
+
};
38
+
39
+
authorizedKeys = mkOption {
40
+
type = types.listOf types.str;
41
+
description = "list of keys to use for authorized_keys";
42
+
default = [ ];
43
+
};
44
+
45
+
authorizedKeysFile = mkOption {
46
+
type = types.str;
47
+
description = "path to authorized_keys file ugit uses for auth";
48
+
default = "${baseDir}/authorized_keys";
49
+
};
50
+
51
+
hostKeyFile = mkOption {
52
+
type = types.str;
53
+
description = "path to host key file (will be created if it doesn't exist)";
54
+
default = "${baseDir}/ugit_ed25519";
55
+
};
56
+
57
+
config = mkOption {
58
+
type = types.attrs;
59
+
default = { };
60
+
description = "config.yaml contents";
61
+
};
62
+
63
+
user = mkOption {
64
+
type = types.str;
65
+
default = "ugit-${name}";
66
+
description = "User account under which ugit runs";
67
+
};
68
+
69
+
group = mkOption {
70
+
type = types.str;
71
+
default = "ugit-${name}";
72
+
description = "Group account under which ugit runs";
73
+
};
74
+
75
+
hooks = mkOption {
76
+
type = types.listOf (
77
+
types.submodule {
78
+
options = {
79
+
name = mkOption {
80
+
type = types.str;
81
+
description = "Hook name";
82
+
};
83
+
content = mkOption {
84
+
type = types.str;
85
+
description = "Hook contents";
86
+
};
87
+
};
88
+
}
89
+
);
90
+
description = "A list of pre-receive hooks to run";
91
+
default = [ ];
92
+
};
93
+
};
94
+
};
95
+
in
96
+
{
97
+
options = {
98
+
services.ugit = lib.mkOption {
99
+
type = lib.types.attrsOf (lib.types.submodule instanceOptions);
100
+
default = { };
101
+
description = "Attribute set of ugit instances";
102
+
};
103
+
};
104
+
config = lib.mkIf (cfg != { }) {
105
+
users.users = lib.mapAttrs' (
106
+
name: instanceCfg:
107
+
lib.nameValuePair instanceCfg.user {
108
+
home = instanceCfg.homeDir;
109
+
createHome = true;
110
+
group = instanceCfg.group;
111
+
isSystemUser = true;
112
+
isNormalUser = false;
113
+
description = "user for ugit ${name} service";
114
+
}
115
+
) (lib.filterAttrs (name: instanceCfg: instanceCfg.enable) cfg);
116
+
117
+
users.groups = lib.mapAttrs' (name: instanceCfg: lib.nameValuePair instanceCfg.group { }) (
118
+
lib.filterAttrs (name: instanceCfg: instanceCfg.enable) cfg
119
+
);
120
+
121
+
systemd.services = lib.foldl' (
122
+
acc: name:
123
+
let
124
+
instanceCfg = cfg.${name};
125
+
in
126
+
lib.recursiveUpdate acc (
127
+
lib.optionalAttrs instanceCfg.enable {
128
+
"ugit-${name}" = {
129
+
enable = true;
130
+
description = "ugit instance ${name}";
131
+
wantedBy = [ "multi-user.target" ];
132
+
after = [ "network.target" ];
133
+
path = [
134
+
instanceCfg.package
135
+
pkgs.git
136
+
pkgs.bash
137
+
];
138
+
serviceConfig = {
139
+
User = instanceCfg.user;
140
+
Group = instanceCfg.group;
141
+
Restart = "always";
142
+
RestartSec = "15";
143
+
WorkingDirectory = instanceCfg.homeDir;
144
+
ReadWritePaths = [ instanceCfg.homeDir ];
145
+
CapabilityBoundingSet = "";
146
+
NoNewPrivileges = true;
147
+
ProtectSystem = "strict";
148
+
ProtectHome = true;
149
+
PrivateTmp = true;
150
+
PrivateDevices = true;
151
+
PrivateUsers = true;
152
+
ProtectHostname = true;
153
+
ProtectClock = true;
154
+
ProtectKernelTunables = true;
155
+
ProtectKernelModules = true;
156
+
ProtectKernelLogs = true;
157
+
ProtectControlGroups = true;
158
+
RestrictAddressFamilies = [
159
+
"AF_UNIX"
160
+
"AF_INET"
161
+
"AF_INET6"
162
+
];
163
+
RestrictNamespaces = true;
164
+
LockPersonality = true;
165
+
MemoryDenyWriteExecute = true;
166
+
RestrictRealtime = true;
167
+
RestrictSUIDSGID = true;
168
+
RemoveIPC = true;
169
+
PrivateMounts = true;
170
+
SystemCallArchitectures = "native";
171
+
ExecStart =
172
+
let
173
+
configFile = pkgs.writeText "ugit-${name}.yaml" (
174
+
builtins.readFile (yamlFormat.generate "ugit-${name}-yaml" instanceCfg.config)
175
+
);
176
+
authorizedKeysFile = pkgs.writeText "ugit_${name}_keys" (
177
+
builtins.concatStringsSep "\n" instanceCfg.authorizedKeys
178
+
);
179
+
180
+
authorizedKeysPath =
181
+
if (builtins.length instanceCfg.authorizedKeys) > 0 then
182
+
authorizedKeysFile
183
+
else
184
+
instanceCfg.authorizedKeysFile;
185
+
args = [
186
+
"--config=${configFile}"
187
+
"--repo-dir=${instanceCfg.repoDir}"
188
+
"--ssh.authorized-keys=${authorizedKeysPath}"
189
+
"--ssh.host-key=${instanceCfg.hostKeyFile}"
190
+
];
191
+
in
192
+
"${instanceCfg.package}/bin/ugitd ${builtins.concatStringsSep " " args}";
193
+
};
194
+
};
195
+
196
+
"ugit-${name}-hooks" = {
197
+
description = "Setup hooks for ugit instance ${name}";
198
+
wantedBy = [ "multi-user.target" ];
199
+
after = [ "ugit-${name}.service" ];
200
+
requires = [ "ugit-${name}.service" ];
201
+
serviceConfig = {
202
+
Type = "oneshot";
203
+
RemainAfterExit = true;
204
+
User = instanceCfg.user;
205
+
Group = instanceCfg.group;
206
+
ExecStart =
207
+
let
208
+
hookDir = "${instanceCfg.repoDir}/hooks/pre-receive.d";
209
+
mkHookScript =
210
+
hook:
211
+
let
212
+
script = pkgs.writeShellScript "ugit-${name}-${hook.name}" hook.content;
213
+
in
214
+
''
215
+
mkdir -p ${hookDir}
216
+
ln -sf ${script} ${hookDir}/${hook.name}
217
+
'';
218
+
in
219
+
pkgs.writeShellScript "ugit-${name}-hooks-setup" ''
220
+
${builtins.concatStringsSep "\n" (map mkHookScript instanceCfg.hooks)}
221
+
'';
222
+
};
223
+
};
224
+
}
225
+
)
226
+
) { } (builtins.attrNames cfg);
227
+
};
228
+
}
+32
nix/pkg.nix
+32
nix/pkg.nix
···
1
+
{
2
+
pkgs ? import <nixpkgs> { },
3
+
}:
4
+
let
5
+
name = "ugitd";
6
+
in
7
+
pkgs.buildGoModule {
8
+
pname = name;
9
+
version = "main";
10
+
src = pkgs.nix-gitignore.gitignoreSource [ ] (
11
+
builtins.path {
12
+
inherit name;
13
+
path = ../.;
14
+
}
15
+
);
16
+
subPackages = [
17
+
"cmd/ugitd"
18
+
];
19
+
vendorHash = pkgs.lib.fileContents ../go.mod.sri;
20
+
env.CGO_ENABLED = 0;
21
+
flags = [ "-trimpath" ];
22
+
ldflags = [
23
+
"-s"
24
+
"-w"
25
+
"-extldflags -static"
26
+
];
27
+
meta = {
28
+
description = "Minimal git server";
29
+
homepage = "https://git.jolheiser.com/ugit";
30
+
mainProgram = "ugitd";
31
+
};
32
+
}
+84
nix/vm.nix
+84
nix/vm.nix
···
1
+
{ pkgs, ... }:
2
+
let
3
+
privKey = ''
4
+
-----BEGIN OPENSSH PRIVATE KEY-----
5
+
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
6
+
QyNTUxOQAAACBIpmLtcHhECei1ls6s0kKUehjpRCP9yel/c5YCIb5DpQAAAIgAYtkzAGLZ
7
+
MwAAAAtzc2gtZWQyNTUxOQAAACBIpmLtcHhECei1ls6s0kKUehjpRCP9yel/c5YCIb5DpQ
8
+
AAAEDFY3M69VfnFbyE67r3l4lDcf5eht5qgNemE9xtMhRkBkimYu1weEQJ6LWWzqzSQpR6
9
+
GOlEI/3J6X9zlgIhvkOlAAAAAAECAwQF
10
+
-----END OPENSSH PRIVATE KEY-----
11
+
'';
12
+
pubKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEimYu1weEQJ6LWWzqzSQpR6GOlEI/3J6X9zlgIhvkOl";
13
+
sshConfig = ''
14
+
Host ugit
15
+
HostName localhost
16
+
Port 8448
17
+
User ugit
18
+
IdentityFile ~/.ssh/vm
19
+
IdentitiesOnly yes
20
+
'';
21
+
in
22
+
{
23
+
imports = [ ./module.nix ];
24
+
environment.systemPackages = with pkgs; [ git ];
25
+
services.getty.autologinUser = "root";
26
+
services.openssh.enable = true;
27
+
services.ugit.vm = {
28
+
enable = true;
29
+
authorizedKeys = [ pubKey ];
30
+
hooks = [
31
+
{
32
+
name = "pre-receive";
33
+
content = ''
34
+
echo "Pre-receive hook executed"
35
+
'';
36
+
}
37
+
];
38
+
};
39
+
systemd.services."setup-vm" = {
40
+
wantedBy = [ "multi-user.target" ];
41
+
after = [ "ugit-vm.service" ];
42
+
path = with pkgs; [
43
+
git
44
+
];
45
+
serviceConfig = {
46
+
Type = "oneshot";
47
+
RemainAfterExit = true;
48
+
User = "root";
49
+
Group = "root";
50
+
ExecStart =
51
+
let
52
+
privSSH = pkgs.writeText "vm-privkey" privKey;
53
+
sshConfigFile = pkgs.writeText "vm-sshconfig" sshConfig;
54
+
in
55
+
pkgs.writeShellScript "setup-vm-script" ''
56
+
# Hack to let ugit start up and generate its SSH keypair
57
+
sleep 3
58
+
59
+
# Set up git
60
+
git config --global user.name "NixUser"
61
+
git config --global user.email "nixuser@example.com"
62
+
git config --global init.defaultBranch main
63
+
git config --global push.autoSetupRemote true
64
+
65
+
# Set up SSH files
66
+
mkdir ~/.ssh
67
+
ln -sf ${sshConfigFile} ~/.ssh/config
68
+
cp ${privSSH} ~/.ssh/vm
69
+
chmod 600 ~/.ssh/vm
70
+
echo "[localhost]:8448 $(cat /var/lib/ugit-vm/ugit_ed25519.pub)" > ~/.ssh/known_hosts
71
+
72
+
# Stage some git activity
73
+
mkdir ~/repo
74
+
cd ~/repo
75
+
git init
76
+
git remote add origin ugit:repo.git
77
+
touch README.md
78
+
git add README.md
79
+
git commit -m "Test"
80
+
'';
81
+
};
82
+
};
83
+
84
+
}