Mirror of https://git.jolheiser.com/ugit

Compare changes

Choose any two refs to compare.

+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
+2
.gitignore
··· 1 /ugit* 2 .ssh/ 3 .ugit/
··· 1 /ugit* 2 .ssh/ 3 .ugit/ 4 + .tsnet/ 5 + *.qcow2
-5
.helix/languages.toml
··· 1 - [[language]] 2 - name = "templ" 3 - language-id = "html" 4 - language-servers = ["templ", "vscode-html-language-server", "tailwindcss-ls"] 5 -
···
+4 -4
README.md
··· 2 <picture> 3 <img alt="ugit logo" width="250" src="./assets/ugit.svg" /> 4 </picture> 5 - <h3 align="center">ugit</h3> 6 </p> 7 8 Minimal git server 9 10 - ugit allows cloning via HTTPS/SSH, but can only be pushed to via SSH. 11 12 There are no plans to directly support issues or PR workflows, although webhooks are planned and auxillary software may be created to facilitate these things. 13 - For now, if you wish to collaborate, please send me patches at [ugit@jolheiser.com](mailto:git@jolheiser.com). 14 15 - Currently all HTML is allowed in markdown, ugit is intended to be run by/for a trusted user. 16 17 ## Getting your public SSH keys from another forge 18
··· 2 <picture> 3 <img alt="ugit logo" width="250" src="./assets/ugit.svg" /> 4 </picture> 5 + <h3 align="center">ยตgit</h3> 6 </p> 7 8 Minimal git server 9 10 + ยตgit allows cloning via HTTPS/SSH, but can only be pushed to via SSH. 11 12 There are no plans to directly support issues or PR workflows, although webhooks are planned and auxillary software may be created to facilitate these things. 13 + If you wish to collaborate, please send me patches via [git-pr](https://pr.jolheiser.com/repos/ugit). 14 15 + Currently all HTML is allowed in markdown, ยตgit is intended to be run by/for a trusted user. 16 17 ## Getting your public SSH keys from another forge 18
+1 -1
assets/ugit.svg
··· 1 <?xml version="1.0" encoding="UTF-8"?> 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> 4 <rect fill="none" x="1" y="1" rx="1" ry="1" width="22" height="22"></rect> 5 <ellipse cx="6" cy="6" rx="2" ry="2"></ellipse> 6 <ellipse cx="18" cy="6" rx="2" ry="2"></ellipse>
··· 1 <?xml version="1.0" encoding="UTF-8"?> 2 <svg viewBox="0 0 24 24" stroke="#de4c36" fill="#de4c36" stroke-width="1" xmlns="http://www.w3.org/2000/svg"> 3 + <title>ยตgit icon</title> 4 <rect fill="none" x="1" y="1" rx="1" ry="1" width="22" height="22"></rect> 5 <ellipse cx="6" cy="6" rx="2" ry="2"></ellipse> 6 <ellipse cx="18" cy="6" rx="2" ry="2"></ellipse>
+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
··· 1 package main 2 3 import ( 4 "flag" 5 "fmt" 6 "strings" 7 8 - "github.com/charmbracelet/log" 9 "github.com/peterbourgon/ff/v3" 10 - "github.com/peterbourgon/ff/v3/ffyaml" 11 ) 12 13 type cliArgs struct { 14 - RepoDir string 15 - SSH sshArgs 16 - HTTP httpArgs 17 - Meta metaArgs 18 - Profile profileArgs 19 - Log logArgs 20 } 21 22 type sshArgs struct { 23 AuthorizedKeys string 24 CloneURL string 25 Port int ··· 27 } 28 29 type httpArgs struct { 30 CloneURL string 31 Port int 32 } ··· 48 } 49 50 type logArgs struct { 51 - Level log.Level 52 JSON bool 53 } 54 55 func parseArgs(args []string) (c cliArgs, e error) { 56 fs := flag.NewFlagSet("ugitd", flag.ContinueOnError) 57 - fs.String("config", "ugit.yaml", "Path to config file") 58 59 c = cliArgs{ 60 RepoDir: ".ugit", 61 SSH: sshArgs{ 62 AuthorizedKeys: ".ssh/authorized_keys", 63 CloneURL: "ssh://localhost:8448", 64 Port: 8448, 65 HostKey: ".ssh/ugit_ed25519", 66 }, 67 HTTP: httpArgs{ 68 CloneURL: "http://localhost:8449", 69 Port: 8449, 70 }, ··· 73 Description: "Minimal git server", 74 }, 75 Log: logArgs{ 76 - Level: log.InfoLevel, 77 }, 78 } 79 80 fs.Func("log.level", "Logging level", func(s string) error { 81 - lvl, err := log.ParseLevel(s) 82 - if err != nil { 83 - return err 84 } 85 c.Log.Level = lvl 86 return nil 87 }) 88 fs.BoolVar(&c.Log.JSON, "log.json", c.Log.JSON, "Print logs in JSON(L) format") 89 fs.StringVar(&c.RepoDir, "repo-dir", c.RepoDir, "Path to directory containing repositories") 90 fs.StringVar(&c.SSH.AuthorizedKeys, "ssh.authorized-keys", c.SSH.AuthorizedKeys, "Path to authorized_keys") 91 fs.StringVar(&c.SSH.CloneURL, "ssh.clone-url", c.SSH.CloneURL, "SSH clone URL base") 92 fs.IntVar(&c.SSH.Port, "ssh.port", c.SSH.Port, "SSH port") 93 fs.StringVar(&c.SSH.HostKey, "ssh.host-key", c.SSH.HostKey, "SSH host key (created if it doesn't exist)") 94 fs.StringVar(&c.HTTP.CloneURL, "http.clone-url", c.HTTP.CloneURL, "HTTP clone URL base") 95 fs.IntVar(&c.HTTP.Port, "http.port", c.HTTP.Port, "HTTP port") 96 fs.StringVar(&c.Meta.Title, "meta.title", c.Meta.Title, "App title") ··· 109 return nil 110 }) 111 112 return c, ff.Parse(fs, args, 113 ff.WithEnvVarPrefix("UGIT"), 114 ff.WithConfigFileFlag("config"), 115 ff.WithAllowMissingConfigFile(true), 116 - ff.WithConfigFileParser(ffyaml.Parser), 117 ) 118 }
··· 1 package main 2 3 import ( 4 + _ "embed" 5 "flag" 6 "fmt" 7 + "log/slog" 8 "strings" 9 10 "github.com/peterbourgon/ff/v3" 11 + "go.jolheiser.com/ffcue" 12 ) 13 14 + //go:embed args.cue 15 + var schema string 16 + 17 type cliArgs struct { 18 + RepoDir string 19 + SSH sshArgs 20 + HTTP httpArgs 21 + Meta metaArgs 22 + Profile profileArgs 23 + Log logArgs 24 + ShowPrivate bool 25 } 26 27 type sshArgs struct { 28 + Enable bool 29 AuthorizedKeys string 30 CloneURL string 31 Port int ··· 33 } 34 35 type httpArgs struct { 36 + Enable bool 37 CloneURL string 38 Port int 39 } ··· 55 } 56 57 type logArgs struct { 58 + Level slog.Level 59 JSON bool 60 } 61 62 func parseArgs(args []string) (c cliArgs, e error) { 63 fs := flag.NewFlagSet("ugitd", flag.ContinueOnError) 64 + fs.String("config", "ugit.cue", "Path to config file") 65 66 c = cliArgs{ 67 RepoDir: ".ugit", 68 SSH: sshArgs{ 69 + Enable: true, 70 AuthorizedKeys: ".ssh/authorized_keys", 71 CloneURL: "ssh://localhost:8448", 72 Port: 8448, 73 HostKey: ".ssh/ugit_ed25519", 74 }, 75 HTTP: httpArgs{ 76 + Enable: true, 77 CloneURL: "http://localhost:8449", 78 Port: 8449, 79 }, ··· 82 Description: "Minimal git server", 83 }, 84 Log: logArgs{ 85 + Level: slog.LevelError, 86 }, 87 } 88 89 fs.Func("log.level", "Logging level", func(s string) error { 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) 102 } 103 c.Log.Level = lvl 104 return nil 105 }) 106 fs.BoolVar(&c.Log.JSON, "log.json", c.Log.JSON, "Print logs in JSON(L) format") 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") 110 fs.StringVar(&c.SSH.AuthorizedKeys, "ssh.authorized-keys", c.SSH.AuthorizedKeys, "Path to authorized_keys") 111 fs.StringVar(&c.SSH.CloneURL, "ssh.clone-url", c.SSH.CloneURL, "SSH clone URL base") 112 fs.IntVar(&c.SSH.Port, "ssh.port", c.SSH.Port, "SSH port") 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") 115 fs.StringVar(&c.HTTP.CloneURL, "http.clone-url", c.HTTP.CloneURL, "HTTP clone URL base") 116 fs.IntVar(&c.HTTP.Port, "http.port", c.HTTP.Port, "HTTP port") 117 fs.StringVar(&c.Meta.Title, "meta.title", c.Meta.Title, "App title") ··· 130 return nil 131 }) 132 133 + parser := &ffcue.ParseConfig{ 134 + Constraints: schema, 135 + } 136 return c, ff.Parse(fs, args, 137 ff.WithEnvVarPrefix("UGIT"), 138 ff.WithConfigFileFlag("config"), 139 ff.WithAllowMissingConfigFile(true), 140 + ff.WithConfigFileParser(parser.Parse), 141 ) 142 }
+43 -28
cmd/ugitd/main.go
··· 4 "errors" 5 "flag" 6 "fmt" 7 "log/slog" 8 "os" 9 "os/signal" 10 "path/filepath" 11 "strconv" 12 "strings" 13 14 - "github.com/charmbracelet/log" 15 "github.com/go-chi/chi/v5/middleware" 16 "github.com/go-chi/httplog/v2" 17 "github.com/go-git/go-git/v5/plumbing/protocol/packp" ··· 39 panic(err) 40 } 41 42 - log.SetLevel(args.Log.Level) 43 middleware.DefaultLogger = httplog.RequestLogger(httplog.NewLogger("ugit", httplog.Options{ 44 JSON: args.Log.JSON, 45 LogLevel: slog.Level(args.Log.Level), 46 - Concise: args.Log.Level != log.DebugLevel, 47 })) 48 49 - if args.Log.Level == log.DebugLevel { 50 trace.SetTarget(trace.Packet) 51 } else { 52 middleware.DefaultLogger = http.NoopLogger ··· 54 } 55 56 if args.Log.JSON { 57 - log.SetFormatter(log.JSONFormatter) 58 } 59 60 if err := requiredFS(args.RepoDir); err != nil { 61 panic(err) 62 } 63 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 { 78 panic(err) 79 } 80 - }() 81 82 httpSettings := http.Settings{ 83 Title: args.Meta.Title, ··· 89 Username: args.Profile.Username, 90 Email: args.Profile.Email, 91 }, 92 } 93 for _, link := range args.Profile.Links { 94 httpSettings.Profile.Links = append(httpSettings.Profile.Links, http.Link{ ··· 96 URL: link.URL, 97 }) 98 } 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 - }() 106 107 ch := make(chan os.Signal, 1) 108 - signal.Notify(ch, os.Kill, os.Interrupt) 109 <-ch 110 } 111 ··· 128 } 129 fp = filepath.Join(fp, "pre-receive") 130 131 fi, err := os.Create(fp) 132 if err != nil { 133 return err 134 } 135 fi.WriteString("#!/usr/bin/env bash\n") 136 fi.WriteString(fmt.Sprintf("%s pre-receive-hook\n", bin)) 137 fi.Close() 138 139 return os.Chmod(fp, 0o755)
··· 4 "errors" 5 "flag" 6 "fmt" 7 + "log" 8 "log/slog" 9 "os" 10 "os/signal" 11 "path/filepath" 12 "strconv" 13 "strings" 14 + "syscall" 15 16 "github.com/go-chi/chi/v5/middleware" 17 "github.com/go-chi/httplog/v2" 18 "github.com/go-git/go-git/v5/plumbing/protocol/packp" ··· 40 panic(err) 41 } 42 43 + slog.SetLogLoggerLevel(args.Log.Level) 44 middleware.DefaultLogger = httplog.RequestLogger(httplog.NewLogger("ugit", httplog.Options{ 45 JSON: args.Log.JSON, 46 LogLevel: slog.Level(args.Log.Level), 47 + Concise: args.Log.Level != slog.LevelDebug, 48 })) 49 50 + if args.Log.Level == slog.LevelDebug { 51 trace.SetTarget(trace.Packet) 52 } else { 53 middleware.DefaultLogger = http.NoopLogger ··· 55 } 56 57 if args.Log.JSON { 58 + logger := slog.New(slog.NewJSONHandler(os.Stderr, nil)) 59 + slog.SetDefault(logger) 60 } 61 62 if err := requiredFS(args.RepoDir); err != nil { 63 panic(err) 64 } 65 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 { 76 panic(err) 77 } 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 + } 85 86 httpSettings := http.Settings{ 87 Title: args.Meta.Title, ··· 93 Username: args.Profile.Username, 94 Email: args.Profile.Email, 95 }, 96 + ShowPrivate: args.ShowPrivate, 97 } 98 for _, link := range args.Profile.Links { 99 httpSettings.Profile.Links = append(httpSettings.Profile.Links, http.Link{ ··· 101 URL: link.URL, 102 }) 103 } 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 + } 113 114 ch := make(chan os.Signal, 1) 115 + signal.Notify(ch, syscall.SIGTERM, os.Interrupt) 116 <-ch 117 } 118 ··· 135 } 136 fp = filepath.Join(fp, "pre-receive") 137 138 + if err := os.MkdirAll(fp+".d", os.ModePerm); err != nil { 139 + return err 140 + } 141 + 142 fi, err := os.Create(fp) 143 if err != nil { 144 return err 145 } 146 fi.WriteString("#!/usr/bin/env bash\n") 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)) 152 fi.Close() 153 154 return os.Chmod(fp, 0o755)
+2
config.cue
···
··· 1 + http: port: 1 2 + ssh: port: 1
+3 -9
contrib/layout.kdl
··· 5 command "nix" 6 args "develop" 7 size "90%" 8 - start_suspended true 9 } 10 pane split_direction="vertical" { 11 pane { 12 - name "run" 13 - command "go" 14 - args "run" "./cmd/ugitd" 15 - start_suspended true 16 - } 17 - pane { 18 - name "watch" 19 command "nix" 20 - args "develop" "--command" "nu" "-c" "watch --glob *.templ ./internal/html/ {|| go generate ./...}" 21 } 22 } 23 }
··· 5 command "nix" 6 args "develop" 7 size "90%" 8 } 9 pane split_direction="vertical" { 10 pane { 11 + name "air" 12 command "nix" 13 + args "develop" "--command" "air" 14 + start_suspended true 15 } 16 } 17 }
+3 -58
flake.lock
··· 1 { 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 "nixpkgs": { 43 "locked": { 44 - "lastModified": 1719379843, 45 - "narHash": "sha256-u+D+IOAMMl70+CJ9NKB+RMrASjInuIWMHzjLWQjPZ6c=", 46 "owner": "nixos", 47 "repo": "nixpkgs", 48 - "rev": "b3f3c1b13fb08f3828442ee86630362e81136bbc", 49 "type": "github" 50 }, 51 "original": { ··· 57 }, 58 "root": { 59 "inputs": { 60 - "gomod2nix": "gomod2nix", 61 "nixpkgs": "nixpkgs", 62 "tailwind-ctp": "tailwind-ctp", 63 "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 } 80 }, 81 "tailwind-ctp": {
··· 1 { 2 "nodes": { 3 "nixpkgs": { 4 "locked": { 5 + "lastModified": 1755205935, 6 + "narHash": "sha256-EQ6qHuJWguaoBZyxdqsgJqyEdS77k+2CnlKrfFxlkRY=", 7 "owner": "nixos", 8 "repo": "nixpkgs", 9 + "rev": "c5e2e42c112de623adfd662b3e51f0805bf9ff83", 10 "type": "github" 11 }, 12 "original": { ··· 18 }, 19 "root": { 20 "inputs": { 21 "nixpkgs": "nixpkgs", 22 "tailwind-ctp": "tailwind-ctp", 23 "tailwind-ctp-lsp": "tailwind-ctp-lsp" 24 } 25 }, 26 "tailwind-ctp": {
+67 -153
flake.nix
··· 3 4 inputs = { 5 nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; 6 - gomod2nix = { 7 - url = "github:nix-community/gomod2nix"; 8 - inputs.nixpkgs.follows = "nixpkgs"; 9 - }; 10 tailwind-ctp = { 11 url = "git+https://git.jolheiser.com/tailwind-ctp"; 12 inputs.nixpkgs.follows = "nixpkgs"; ··· 17 }; 18 }; 19 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 66 ]; 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"; 117 }; 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 - }; 136 }; 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"; 169 }; 170 - }; 171 - }; 172 }; 173 - }; 174 }
··· 3 4 inputs = { 5 nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; 6 tailwind-ctp = { 7 url = "git+https://git.jolheiser.com/tailwind-ctp"; 8 inputs.nixpkgs.follows = "nixpkgs"; ··· 13 }; 14 }; 15 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" 31 ]; 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 + ]; 53 }; 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 + ]; 70 }; 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 + ''}"; 84 }; 85 + } 86 + ); 87 }; 88 }
+66 -54
go.mod
··· 1 module go.jolheiser.com/ugit 2 3 - go 1.21 4 5 - toolchain go1.21.5 6 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 13 github.com/dustin/go-humanize v1.0.1 14 - github.com/go-chi/chi/v5 v5.0.11 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 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 21 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc 22 - golang.org/x/net v0.25.0 23 ) 24 25 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 29 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect 30 - github.com/atotto/clipboard v0.1.4 // indirect 31 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 50 github.com/emirpasic/gods v1.18.1 // indirect 51 github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect 52 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect 53 github.com/go-logfmt/logfmt v0.6.0 // indirect 54 - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 55 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect 56 github.com/kevinburke/ssh_config v1.2.0 // indirect 57 github.com/lucasb-eyer/go-colorful v1.2.0 // indirect 58 github.com/mattn/go-isatty v0.0.20 // indirect 59 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 62 github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect 63 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 67 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 71 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 81 gopkg.in/warnings.v0 v0.1.2 // indirect 82 - gopkg.in/yaml.v2 v2.4.0 // indirect 83 )
··· 1 module go.jolheiser.com/ugit 2 3 + go 1.23.1 4 5 + toolchain go1.23.3 6 7 require ( 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 github.com/dustin/go-humanize v1.0.1 14 + github.com/go-chi/chi/v5 v5.2.0 15 github.com/go-chi/httplog/v2 v2.1.1 16 + github.com/go-git/go-billy/v5 v5.6.1 17 + github.com/go-git/go-git/v5 v5.13.1 18 github.com/peterbourgon/ff/v3 v3.4.0 19 + github.com/yuin/goldmark v1.7.12 20 + github.com/yuin/goldmark-emoji v1.0.4 21 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc 22 + go.jolheiser.com/ffcue v0.0.0-20250816031459-3e3e4f232e75 23 + golang.org/x/net v0.42.0 24 ) 25 26 require ( 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 34 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect 35 github.com/aymanbagabas/go-osc52/v2 v2.0.1 // 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 54 github.com/emirpasic/gods v1.18.1 // indirect 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 58 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect 59 github.com/go-logfmt/logfmt v0.6.0 // 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 63 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect 64 github.com/kevinburke/ssh_config v1.2.0 // indirect 65 github.com/lucasb-eyer/go-colorful v1.2.0 // indirect 66 + github.com/mattn/go-colorable v0.1.13 // indirect 67 github.com/mattn/go-isatty v0.0.20 // indirect 68 github.com/mattn/go-localereader v0.0.1 // 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 72 github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect 73 github.com/muesli/cancelreader v0.2.2 // 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 80 github.com/rivo/uniseg v0.4.7 // indirect 81 + github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect 82 + github.com/skeema/knownhosts v1.3.0 // indirect 83 github.com/xanzy/ssh-agent v0.3.3 // 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 91 gopkg.in/warnings.v0 v0.1.2 // indirect 92 + gopkg.in/yaml.v3 v3.0.1 // indirect 93 ) 94 + 95 + tool github.com/a-h/templ/cmd/templ
+1 -1
go.mod.sri
··· 1 - sha256-8kI94hcJupAUye6cEAmIlN+CrtYSXlgoAlmpyXArfF8=
··· 1 + sha256-DjweXB8uqEpOIBwGabLCnVL4ZOKkPcJDf6JlAS5FmKI=
+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= 3 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= 12 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= 15 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= 18 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= 19 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= 20 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= 21 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 github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= 25 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= 74 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 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 77 github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= 78 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= 81 github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= 82 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= 85 github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= 86 github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= 87 github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= 88 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= 93 github.com/go-chi/httplog/v2 v2.1.1 h1:ojojiu4PIaoeJ/qAO4GWUxJqvYUTobeo7zmuHQJAxRk= 94 github.com/go-chi/httplog/v2 v2.1.1/go.mod h1:/XXdxicJsp4BA5fapgIC3VuTD+z0Z/VzukoB3VDc1YE= 95 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= 96 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= 99 github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= 100 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= 103 github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= 104 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= 109 github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= 110 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 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= 114 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= 115 github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= ··· 121 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 122 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 123 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 124 github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= 125 github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= 126 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 127 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 128 github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= 129 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= 135 github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= 136 github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= 137 github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= 138 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= 145 github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= 146 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= 149 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 150 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 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= 154 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 github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= 158 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= 163 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= 166 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 167 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 168 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 169 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= 176 github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= 177 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 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= 187 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ= 188 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= 191 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= 207 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= 223 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 224 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 225 golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 226 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 227 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 228 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 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= 236 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= 241 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= 252 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= 261 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= 270 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 271 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 272 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= ··· 274 gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= 275 gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 276 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 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 279 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 280 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
··· 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= 7 github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= 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= 18 github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs= 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= 21 github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= 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= 26 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= 27 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= 28 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= 29 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= 30 github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= 31 github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= 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= 66 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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= 70 github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= 71 github.com/dlclark/regexp2 v1.7.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= 74 github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= 75 github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= 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= 80 github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= 81 github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= 82 github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= 83 github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= 84 + github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= 85 + github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= 86 + github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= 87 + github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= 88 + github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= 89 + github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= 90 + github.com/go-chi/chi/v5 v5.2.0 h1:Aj1EtB0qR2Rdo2dG4O94RIU35w2lvQSj6BRA4+qwFL0= 91 + github.com/go-chi/chi/v5 v5.2.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= 92 github.com/go-chi/httplog/v2 v2.1.1 h1:ojojiu4PIaoeJ/qAO4GWUxJqvYUTobeo7zmuHQJAxRk= 93 github.com/go-chi/httplog/v2 v2.1.1/go.mod h1:/XXdxicJsp4BA5fapgIC3VuTD+z0Z/VzukoB3VDc1YE= 94 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= 95 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= 96 + github.com/go-git/go-billy/v5 v5.6.1 h1:u+dcrgaguSSkbjzHwelEjc0Yj300NUevrrPphk/SoRA= 97 + github.com/go-git/go-billy/v5 v5.6.1/go.mod h1:0AsLr1z2+Uksi4NlElmMblP5rPcDZNRCD8ujZCRR2BE= 98 github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= 99 github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= 100 + github.com/go-git/go-git/v5 v5.13.1 h1:DAQ9APonnlvSWpvolXWIuV6Q6zXy2wHbN4cVlNR5Q+M= 101 + github.com/go-git/go-git/v5 v5.13.1/go.mod h1:qryJB4cSBoq3FRoBRf5A77joojuBcmPJ0qu3XXXVixc= 102 github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= 103 github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= 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= 112 github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= 113 github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= 114 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= 115 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= 116 github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= ··· 122 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 123 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 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= 129 github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= 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= 134 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 135 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 136 github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= 137 github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= 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= 144 github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= 145 github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= 146 github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= 147 github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= 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= 160 github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= 161 github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= 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= 164 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 165 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 166 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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= 171 github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 172 github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= 173 github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= 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= 178 github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 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= 181 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 182 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 183 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 184 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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= 187 github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= 188 github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= 189 github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 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= 195 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ= 196 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I= 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= 199 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 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= 206 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= 213 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 214 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 215 golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 216 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 217 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 218 golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 219 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 220 + golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 221 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 222 + golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= 223 + golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 224 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 225 + golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= 226 + golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= 227 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 228 + golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= 229 + golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= 230 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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= 233 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 234 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 235 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= ··· 237 gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= 238 gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 239 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 240 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 241 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 242 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
-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
··· 98 } 99 } 100 101 - fis := make([]FileInfo, 0) 102 for _, entry := range t.Entries { 103 fm, err := entry.Mode.ToOSFileMode() 104 if err != nil { ··· 118 sort.Slice(fis, func(i, j int) bool { 119 fi1 := fis[i] 120 fi2 := fis[j] 121 - return (fi1.IsDir && !fi2.IsDir) || fi1.Name() < fi2.Name() 122 }) 123 124 return fis, nil 125 } 126 127 // FileContent returns the content of a file in the git tree at a given ref/rev
··· 98 } 99 } 100 101 + fis := make([]FileInfo, 0, len(t.Entries)) 102 for _, entry := range t.Entries { 103 fm, err := entry.Mode.ToOSFileMode() 104 if err != nil { ··· 118 sort.Slice(fis, func(i, j int) bool { 119 fi1 := fis[i] 120 fi2 := fis[j] 121 + if fi1.IsDir != fi2.IsDir { 122 + return fi1.IsDir 123 + } 124 + return fi1.Name() < fi2.Name() 125 }) 126 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) 143 } 144 145 // FileContent returns the content of a file in the git tree at a given ref/rev
+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
··· 18 19 // Grep performs a naive "code search" via git grep 20 func (r Repo) Grep(search string) ([]GrepResult, error) { 21 - // Plain-text search only 22 - re, err := regexp.Compile(regexp.QuoteMeta(search)) 23 if err != nil { 24 return nil, err 25 }
··· 18 19 // Grep performs a naive "code search" via git grep 20 func (r Repo) Grep(search string) ([]GrepResult, error) { 21 + if strings.HasPrefix(search, "=") { 22 + search = regexp.QuoteMeta(strings.TrimPrefix(search, "=")) 23 + } 24 + re, err := regexp.Compile(search) 25 if err != nil { 26 return nil, err 27 }
+66 -4
internal/git/meta.go
··· 3 import ( 4 "encoding/json" 5 "errors" 6 "io/fs" 7 "os" 8 "path/filepath" 9 ) 10 11 // RepoMeta is the meta information a Repo can have 12 type RepoMeta struct { 13 - Description string `json:"description"` 14 - Private bool `json:"private"` 15 - Tags []string `json:"tags"` 16 } 17 18 // Update updates meta given another RepoMeta ··· 46 return json.NewEncoder(fi).Encode(r.Meta) 47 } 48 49 func ensureJSONFile(path string) error { 50 _, err := os.Stat(path) 51 if err == nil { ··· 59 return err 60 } 61 defer fi.Close() 62 - if _, err := fi.WriteString(`{"private":true}`); err != nil { 63 return err 64 } 65 return nil
··· 3 import ( 4 "encoding/json" 5 "errors" 6 + "fmt" 7 "io/fs" 8 "os" 9 "path/filepath" 10 + "slices" 11 ) 12 13 // RepoMeta is the meta information a Repo can have 14 type RepoMeta struct { 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 68 } 69 70 // Update updates meta given another RepoMeta ··· 98 return json.NewEncoder(fi).Encode(r.Meta) 99 } 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 + 111 func ensureJSONFile(path string) error { 112 _, err := os.Stat(path) 113 if err == nil { ··· 121 return err 122 } 123 defer fi.Close() 124 + if _, err := fi.Write(defaultMeta); err != nil { 125 return err 126 } 127 return nil
+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
··· 58 remove = true 59 tagValue = strings.TrimPrefix(tagValue, "-") 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 - } 70 } 71 } 72 }
··· 58 remove = true 59 tagValue = strings.TrimPrefix(tagValue, "-") 60 } 61 + tagValue = strings.ToLower(tagValue) 62 + if remove { 63 + repo.Meta.Tags.Remove(tagValue) 64 + } else { 65 + repo.Meta.Tags.Add(tagValue) 66 } 67 } 68 }
-1
internal/git/protocol_git.go
··· 58 cmd.Env = append(os.Environ(), fmt.Sprintf("UGIT_REPODIR=%s", repoDir), "GIT_PROTOCOL=version=2") 59 cmd.Stdin = ctx 60 cmd.Stdout = ctx 61 - fmt.Println(cmd.Env, cmd.String()) 62 63 return cmd.Run() 64 }
··· 58 cmd.Env = append(os.Environ(), fmt.Sprintf("UGIT_REPODIR=%s", repoDir), "GIT_PROTOCOL=version=2") 59 cmd.Stdin = ctx 60 cmd.Stdout = ctx 61 62 return cmd.Run() 63 }
+11
internal/git/repo.go
··· 57 if err := json.NewDecoder(fi).Decode(&r.Meta); err != nil { 58 return nil, err 59 } 60 61 return r, nil 62 } ··· 132 type CommitFileEntry struct { 133 Path string 134 Commit string 135 } 136 137 // Short returns the first eight characters of the SHA
··· 57 if err := json.NewDecoder(fi).Decode(&r.Meta); err != nil { 58 return nil, err 59 } 60 + if r.Meta.Tags == nil { 61 + r.Meta.Tags = make(TagSet) 62 + } 63 64 return r, nil 65 } ··· 135 type CommitFileEntry struct { 136 Path string 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 146 } 147 148 // Short returns the first eight characters of the SHA
+3 -1
internal/html/base.templ
··· 18 <meta property="og:description" content={ bc.Description }/> 19 </head> 20 <body class="latte dark:mocha bg-base/50 dark:bg-base/95 max-w-7xl mx-5 sm:mx-auto my-10"> 21 - <h2 class="text-text text-xl mb-3"><a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href="/">Home</a></h2> 22 { children... } 23 </body> 24 </html>
··· 18 <meta property="og:description" content={ bc.Description }/> 19 </head> 20 <body class="latte dark:mocha bg-base/50 dark:bg-base/95 max-w-7xl mx-5 sm:mx-auto my-10"> 21 + <h2 class="text-text text-xl mb-3"> 22 + <a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href="/">Home</a> 23 + </h2> 24 { children... } 25 </body> 26 </html>
+22 -17
internal/html/base_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.707 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 - import "context" 10 - import "io" 11 - import "bytes" 12 13 type BaseContext struct { 14 Title string ··· 16 } 17 18 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) 21 if !templ_7745c5c3_IsBuffer { 22 - templ_7745c5c3_Buffer = templ.GetBuffer() 23 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 24 } 25 ctx = templ.InitializeContext(ctx) 26 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 28 templ_7745c5c3_Var1 = templ.NopComponent 29 } 30 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>") 32 if templ_7745c5c3_Err != nil { 33 return templ_7745c5c3_Err 34 } ··· 41 if templ_7745c5c3_Err != nil { 42 return templ_7745c5c3_Err 43 } 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=\"") 45 if templ_7745c5c3_Err != nil { 46 return templ_7745c5c3_Err 47 } ··· 54 if templ_7745c5c3_Err != nil { 55 return templ_7745c5c3_Err 56 } 57 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><meta property=\"og:description\" content=\"") 58 if templ_7745c5c3_Err != nil { 59 return templ_7745c5c3_Err 60 } ··· 67 if templ_7745c5c3_Err != nil { 68 return templ_7745c5c3_Err 69 } 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>") 71 if templ_7745c5c3_Err != nil { 72 return templ_7745c5c3_Err 73 } ··· 75 if templ_7745c5c3_Err != nil { 76 return templ_7745c5c3_Err 77 } 78 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</body></html>") 79 if templ_7745c5c3_Err != nil { 80 return templ_7745c5c3_Err 81 } 82 - if !templ_7745c5c3_IsBuffer { 83 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 84 - } 85 - return templ_7745c5c3_Err 86 }) 87 }
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 + // templ: version: v0.3.924 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 11 type BaseContext struct { 12 Title string ··· 14 } 15 16 func base(bc BaseContext) templ.Component { 17 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 18 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 19 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 20 + return templ_7745c5c3_CtxErr 21 + } 22 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 23 if !templ_7745c5c3_IsBuffer { 24 + defer func() { 25 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 26 + if templ_7745c5c3_Err == nil { 27 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 28 + } 29 + }() 30 } 31 ctx = templ.InitializeContext(ctx) 32 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 34 templ_7745c5c3_Var1 = templ.NopComponent 35 } 36 ctx = templ.ClearChildren(ctx) 37 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>") 38 if templ_7745c5c3_Err != nil { 39 return templ_7745c5c3_Err 40 } ··· 47 if templ_7745c5c3_Err != nil { 48 return templ_7745c5c3_Err 49 } 50 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><link rel=\"icon\" href=\"/_/favicon.svg\"><link rel=\"stylesheet\" href=\"/_/tailwind.css\"><meta property=\"og:title\" content=\"") 51 if templ_7745c5c3_Err != nil { 52 return templ_7745c5c3_Err 53 } ··· 60 if templ_7745c5c3_Err != nil { 61 return templ_7745c5c3_Err 62 } 63 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\"><meta property=\"og:description\" content=\"") 64 if templ_7745c5c3_Err != nil { 65 return templ_7745c5c3_Err 66 } ··· 73 if templ_7745c5c3_Err != nil { 74 return templ_7745c5c3_Err 75 } 76 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\"></head><body class=\"latte dark:mocha bg-base/50 dark:bg-base/95 max-w-7xl mx-5 sm:mx-auto my-10\"><h2 class=\"text-text text-xl mb-3\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"/\">Home</a></h2>") 77 if templ_7745c5c3_Err != nil { 78 return templ_7745c5c3_Err 79 } ··· 81 if templ_7745c5c3_Err != nil { 82 return templ_7745c5c3_Err 83 } 84 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</body></html>") 85 if templ_7745c5c3_Err != nil { 86 return templ_7745c5c3_Err 87 } 88 + return nil 89 }) 90 } 91 + 92 + var _ = templruntime.GeneratedTemplate
-4
internal/html/generate.css
··· 46 47 .code>.chroma { 48 @apply text-sm p-3 rounded overflow-scroll; 49 - } 50 - 51 - .chroma .line { 52 - @apply overflow-scroll 53 }
··· 46 47 .code>.chroma { 48 @apply text-sm p-3 rounded overflow-scroll; 49 }
+6 -4
internal/html/generate.go
··· 12 13 "go.jolheiser.com/ugit/internal/html/markup" 14 15 "github.com/alecthomas/chroma/v2/styles" 16 ) 17 ··· 25 otherCSS string 26 ) 27 28 - //go:generate templ generate 29 //go:generate go run generate.go 30 func main() { 31 if err := tailwind(); err != nil { ··· 33 } 34 } 35 36 - // Generate tailwind code from templ templates and combine with other misc CSS 37 func tailwind() error { 38 fmt.Println("generating tailwind...") 39 ··· 47 } 48 49 fmt.Println("generating chroma styles...") 50 51 latte := styles.Get("catppuccin-latte") 52 - if err := markup.Formatter.WriteCSS(tmp, latte); err != nil { 53 return err 54 } 55 56 tmp.WriteString("@media (prefers-color-scheme: dark) {") 57 mocha := styles.Get("catppuccin-mocha") 58 - if err := markup.Formatter.WriteCSS(tmp, mocha); err != nil { 59 return err 60 } 61 tmp.WriteString("}")
··· 12 13 "go.jolheiser.com/ugit/internal/html/markup" 14 15 + "github.com/alecthomas/chroma/v2/formatters/html" 16 "github.com/alecthomas/chroma/v2/styles" 17 ) 18 ··· 26 otherCSS string 27 ) 28 29 + //go:generate go tool templ generate 30 //go:generate go run generate.go 31 func main() { 32 if err := tailwind(); err != nil { ··· 34 } 35 } 36 37 + // Generate tailwind code from templates and combine with other misc CSS 38 func tailwind() error { 39 fmt.Println("generating tailwind...") 40 ··· 48 } 49 50 fmt.Println("generating chroma styles...") 51 + formatter := html.New(markup.Options("")...) 52 53 latte := styles.Get("catppuccin-latte") 54 + if err := formatter.WriteCSS(tmp, latte); err != nil { 55 return err 56 } 57 58 tmp.WriteString("@media (prefers-color-scheme: dark) {") 59 mocha := styles.Get("catppuccin-mocha") 60 + if err := formatter.WriteCSS(tmp, mocha); err != nil { 61 return err 62 } 63 tmp.WriteString("}")
+28 -8
internal/html/index.templ
··· 1 package html 2 3 - import "go.jolheiser.com/ugit/internal/git" 4 - import "github.com/dustin/go-humanize" 5 - import "go.jolheiser.com/ugit/assets" 6 7 type IndexContext struct { 8 BaseContext ··· 21 URL string 22 } 23 24 - func lastCommit(repo *git.Repo, human bool) string { 25 c, err := repo.LastCommit() 26 if err != nil { 27 return "" ··· 32 return c.When.Format("01/02/2006 03:04:05 PM") 33 } 34 35 templ Index(ic IndexContext) { 36 @base(ic.BaseContext) { 37 <header> ··· 62 </div> 63 } 64 </div> 65 - <div class="grid sm:grid-cols-8 gap-2 mt-5"> 66 for _, repo := range ic.Repos { 67 <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> 69 <div class="sm:col-span-1 text-subtext0"> 70 - for _, tag := range repo.Meta.Tags { 71 <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 } 73 </div> 74 - <div class="sm:col-span-1 text-text/80 mb-4 sm:mb-0" title={ lastCommit(repo, false) }>{ lastCommit(repo, true) }</div> 75 } 76 </div> 77 </main>
··· 1 package html 2 3 + import ( 4 + "fmt" 5 + "github.com/dustin/go-humanize" 6 + "go.jolheiser.com/ugit/assets" 7 + "go.jolheiser.com/ugit/internal/git" 8 + ) 9 10 type IndexContext struct { 11 BaseContext ··· 24 URL string 25 } 26 27 + func lastCommitTime(repo *git.Repo, human bool) string { 28 c, err := repo.LastCommit() 29 if err != nil { 30 return "" ··· 35 return c.When.Format("01/02/2006 03:04:05 PM") 36 } 37 38 + func lastCommit(repo *git.Repo) *git.Commit { 39 + c, err := repo.LastCommit() 40 + if err != nil { 41 + return nil 42 + } 43 + return &c 44 + } 45 + 46 templ Index(ic IndexContext) { 47 @base(ic.BaseContext) { 48 <header> ··· 73 </div> 74 } 75 </div> 76 + <div class="grid sm:grid-cols-10 gap-2 mt-5"> 77 for _, repo := range ic.Repos { 78 + {{ commit := lastCommit(repo) }} 79 <div class="sm:col-span-2 text-blue dark:text-lavender"><a class="underline decoration-blue/50 dark:decoration-lavender/50 decoration-dashed hover:decoration-solid" href={ templ.URL("/" + repo.Name()) }>{ repo.Name() }</a></div> 80 + <div class="sm:col-span-3 text-subtext0">{ repo.Meta.Description }</div> 81 + <div class="sm:col-span-3 text-subtext0"> 82 + if commit != nil { 83 + <div title={ commit.Message }> 84 + <a class="underline text-blue dark:text-lavender decoration-blue/50 dark:decoration-lavender/50 decoration-dashed hover:decoration-solid" href={ fmt.Sprintf("/%s/commit/%s", repo.Name(), commit.SHA) }>{ commit.Short() }</a> 85 + { ": " + commit.Summary() } 86 + </div> 87 + } 88 + </div> 89 <div class="sm:col-span-1 text-subtext0"> 90 + for _, tag := range repo.Meta.Tags.Slice() { 91 <a href={ templ.SafeURL("?tag=" + tag) } class="rounded border-rosewater border-solid border pb-0.5 px-1 mr-1 mb-1 inline-block">{ tag }</a> 92 } 93 </div> 94 + <div class="sm:col-span-1 text-text/80 mb-4 sm:mb-0" title={ lastCommitTime(repo, false) }>{ lastCommitTime(repo, true) }</div> 95 } 96 </div> 97 </main>
+175 -77
internal/html/index_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.707 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 - import "context" 10 - import "io" 11 - import "bytes" 12 13 - import "go.jolheiser.com/ugit/internal/git" 14 - import "github.com/dustin/go-humanize" 15 - import "go.jolheiser.com/ugit/assets" 16 17 type IndexContext struct { 18 BaseContext ··· 31 URL string 32 } 33 34 - func lastCommit(repo *git.Repo, human bool) string { 35 c, err := repo.LastCommit() 36 if err != nil { 37 return "" ··· 42 return c.When.Format("01/02/2006 03:04:05 PM") 43 } 44 45 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) 48 if !templ_7745c5c3_IsBuffer { 49 - templ_7745c5c3_Buffer = templ.GetBuffer() 50 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 51 } 52 ctx = templ.InitializeContext(ctx) 53 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 55 templ_7745c5c3_Var1 = templ.NopComponent 56 } 57 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) 60 if !templ_7745c5c3_IsBuffer { 61 - templ_7745c5c3_Buffer = templ.GetBuffer() 62 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 63 } 64 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<header><h1 class=\"text-text text-xl font-bold\">") 65 if templ_7745c5c3_Err != nil { 66 return templ_7745c5c3_Err 67 } 68 var templ_7745c5c3_Var3 string 69 templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(ic.Title) 70 if templ_7745c5c3_Err != nil { 71 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 38, Col: 53} 72 } 73 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 74 if templ_7745c5c3_Err != nil { 75 return templ_7745c5c3_Err 76 } 77 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h1><h2 class=\"text-subtext1 text-lg\">") 78 if templ_7745c5c3_Err != nil { 79 return templ_7745c5c3_Err 80 } 81 var templ_7745c5c3_Var4 string 82 templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(ic.Description) 83 if templ_7745c5c3_Err != nil { 84 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 39, Col: 53} 85 } 86 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 87 if templ_7745c5c3_Err != nil { 88 return templ_7745c5c3_Err 89 } 90 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h2></header><main class=\"mt-5\"><div class=\"grid grid-cols-1 sm:grid-cols-8\">") 91 if templ_7745c5c3_Err != nil { 92 return templ_7745c5c3_Err 93 } 94 if ic.Profile.Username != "" { 95 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"text-mauve\">") 96 if templ_7745c5c3_Err != nil { 97 return templ_7745c5c3_Err 98 } 99 var templ_7745c5c3_Var5 string 100 templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(`@` + ic.Profile.Username) 101 if templ_7745c5c3_Err != nil { 102 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 44, Col: 56} 103 } 104 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 105 if templ_7745c5c3_Err != nil { 106 return templ_7745c5c3_Err 107 } 108 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 109 if templ_7745c5c3_Err != nil { 110 return templ_7745c5c3_Err 111 } 112 } 113 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\">") 115 if templ_7745c5c3_Err != nil { 116 return templ_7745c5c3_Err 117 } ··· 119 if templ_7745c5c3_Err != nil { 120 return templ_7745c5c3_Err 121 } 122 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><a class=\"underline decoration-mauve/50 decoration-dashed hover:decoration-solid\" href=\"") 123 if templ_7745c5c3_Err != nil { 124 return templ_7745c5c3_Err 125 } 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))) 128 if templ_7745c5c3_Err != nil { 129 return templ_7745c5c3_Err 130 } 131 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 132 if templ_7745c5c3_Err != nil { 133 return templ_7745c5c3_Err 134 } 135 var templ_7745c5c3_Var7 string 136 templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(ic.Profile.Email) 137 if templ_7745c5c3_Err != nil { 138 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 51, Col: 159} 139 } 140 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 141 if templ_7745c5c3_Err != nil { 142 return templ_7745c5c3_Err 143 } 144 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div>") 145 if templ_7745c5c3_Err != nil { 146 return templ_7745c5c3_Err 147 } 148 } 149 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"grid grid-cols-1 sm:grid-cols-8\">") 150 if templ_7745c5c3_Err != nil { 151 return templ_7745c5c3_Err 152 } 153 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\">") 155 if templ_7745c5c3_Err != nil { 156 return templ_7745c5c3_Err 157 } ··· 159 if templ_7745c5c3_Err != nil { 160 return templ_7745c5c3_Err 161 } 162 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><a class=\"underline decoration-mauve/50 decoration-dashed hover:decoration-solid\" rel=\"me\" href=\"") 163 if templ_7745c5c3_Err != nil { 164 return templ_7745c5c3_Err 165 } 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))) 168 if templ_7745c5c3_Err != nil { 169 return templ_7745c5c3_Err 170 } 171 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 172 if templ_7745c5c3_Err != nil { 173 return templ_7745c5c3_Err 174 } 175 var templ_7745c5c3_Var9 string 176 templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(link.Name) 177 if templ_7745c5c3_Err != nil { 178 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 61, Col: 141} 179 } 180 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) 181 if templ_7745c5c3_Err != nil { 182 return templ_7745c5c3_Err 183 } 184 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div>") 185 if templ_7745c5c3_Err != nil { 186 return templ_7745c5c3_Err 187 } 188 } 189 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"grid sm:grid-cols-8 gap-2 mt-5\">") 190 if templ_7745c5c3_Err != nil { 191 return templ_7745c5c3_Err 192 } 193 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=\"") 195 if templ_7745c5c3_Err != nil { 196 return templ_7745c5c3_Err 197 } 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))) 200 if templ_7745c5c3_Err != nil { 201 return templ_7745c5c3_Err 202 } 203 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 204 if templ_7745c5c3_Err != nil { 205 return templ_7745c5c3_Err 206 } 207 var templ_7745c5c3_Var11 string 208 templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Name()) 209 if templ_7745c5c3_Err != nil { 210 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 67, Col: 221} 211 } 212 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) 213 if templ_7745c5c3_Err != nil { 214 return templ_7745c5c3_Err 215 } 216 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div class=\"sm:col-span-4 text-subtext0\">") 217 if templ_7745c5c3_Err != nil { 218 return templ_7745c5c3_Err 219 } 220 var templ_7745c5c3_Var12 string 221 templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Meta.Description) 222 if templ_7745c5c3_Err != nil { 223 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 68, Col: 69} 224 } 225 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) 226 if templ_7745c5c3_Err != nil { 227 return templ_7745c5c3_Err 228 } 229 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"sm:col-span-1 text-subtext0\">") 230 if templ_7745c5c3_Err != nil { 231 return templ_7745c5c3_Err 232 } 233 - for _, tag := range repo.Meta.Tags { 234 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"") 235 if templ_7745c5c3_Err != nil { 236 return templ_7745c5c3_Err 237 } 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))) 240 if templ_7745c5c3_Err != nil { 241 return templ_7745c5c3_Err 242 } 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\">") 244 if templ_7745c5c3_Err != nil { 245 return templ_7745c5c3_Err 246 } 247 - var templ_7745c5c3_Var14 string 248 - templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(tag) 249 if templ_7745c5c3_Err != nil { 250 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 71, Col: 141} 251 } 252 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) 253 if templ_7745c5c3_Err != nil { 254 return templ_7745c5c3_Err 255 } 256 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>") 257 if templ_7745c5c3_Err != nil { 258 return templ_7745c5c3_Err 259 } 260 } 261 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"sm:col-span-1 text-text/80 mb-4 sm:mb-0\" title=\"") 262 if templ_7745c5c3_Err != nil { 263 return templ_7745c5c3_Err 264 } 265 - var templ_7745c5c3_Var15 string 266 - templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(lastCommit(repo, false)) 267 if templ_7745c5c3_Err != nil { 268 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 74, Col: 89} 269 } 270 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) 271 if templ_7745c5c3_Err != nil { 272 return templ_7745c5c3_Err 273 } 274 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 275 if templ_7745c5c3_Err != nil { 276 return templ_7745c5c3_Err 277 } 278 - var templ_7745c5c3_Var16 string 279 - templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(lastCommit(repo, true)) 280 if templ_7745c5c3_Err != nil { 281 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 74, Col: 116} 282 } 283 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) 284 if templ_7745c5c3_Err != nil { 285 return templ_7745c5c3_Err 286 } 287 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 288 if templ_7745c5c3_Err != nil { 289 return templ_7745c5c3_Err 290 } 291 } 292 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></main>") 293 if templ_7745c5c3_Err != nil { 294 return templ_7745c5c3_Err 295 } 296 - if !templ_7745c5c3_IsBuffer { 297 - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) 298 - } 299 - return templ_7745c5c3_Err 300 }) 301 templ_7745c5c3_Err = base(ic.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 302 if templ_7745c5c3_Err != nil { 303 return templ_7745c5c3_Err 304 } 305 - if !templ_7745c5c3_IsBuffer { 306 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 307 - } 308 - return templ_7745c5c3_Err 309 }) 310 }
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 + // templ: version: v0.3.924 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 11 + import ( 12 + "fmt" 13 + "github.com/dustin/go-humanize" 14 + "go.jolheiser.com/ugit/assets" 15 + "go.jolheiser.com/ugit/internal/git" 16 + ) 17 18 type IndexContext struct { 19 BaseContext ··· 32 URL string 33 } 34 35 + func lastCommitTime(repo *git.Repo, human bool) string { 36 c, err := repo.LastCommit() 37 if err != nil { 38 return "" ··· 43 return c.When.Format("01/02/2006 03:04:05 PM") 44 } 45 46 + func lastCommit(repo *git.Repo) *git.Commit { 47 + c, err := repo.LastCommit() 48 + if err != nil { 49 + return nil 50 + } 51 + return &c 52 + } 53 + 54 func Index(ic IndexContext) templ.Component { 55 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 56 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 57 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 58 + return templ_7745c5c3_CtxErr 59 + } 60 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 61 if !templ_7745c5c3_IsBuffer { 62 + defer func() { 63 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 64 + if templ_7745c5c3_Err == nil { 65 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 66 + } 67 + }() 68 } 69 ctx = templ.InitializeContext(ctx) 70 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 72 templ_7745c5c3_Var1 = templ.NopComponent 73 } 74 ctx = templ.ClearChildren(ctx) 75 + templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 76 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 77 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 78 if !templ_7745c5c3_IsBuffer { 79 + defer func() { 80 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 81 + if templ_7745c5c3_Err == nil { 82 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 83 + } 84 + }() 85 } 86 + ctx = templ.InitializeContext(ctx) 87 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<header><h1 class=\"text-text text-xl font-bold\">") 88 if templ_7745c5c3_Err != nil { 89 return templ_7745c5c3_Err 90 } 91 var templ_7745c5c3_Var3 string 92 templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(ic.Title) 93 if templ_7745c5c3_Err != nil { 94 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 49, Col: 53} 95 } 96 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 97 if templ_7745c5c3_Err != nil { 98 return templ_7745c5c3_Err 99 } 100 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</h1><h2 class=\"text-subtext1 text-lg\">") 101 if templ_7745c5c3_Err != nil { 102 return templ_7745c5c3_Err 103 } 104 var templ_7745c5c3_Var4 string 105 templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(ic.Description) 106 if templ_7745c5c3_Err != nil { 107 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 50, Col: 53} 108 } 109 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 110 if templ_7745c5c3_Err != nil { 111 return templ_7745c5c3_Err 112 } 113 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h2></header><main class=\"mt-5\"><div class=\"grid grid-cols-1 sm:grid-cols-8\">") 114 if templ_7745c5c3_Err != nil { 115 return templ_7745c5c3_Err 116 } 117 if ic.Profile.Username != "" { 118 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div class=\"text-mauve\">") 119 if templ_7745c5c3_Err != nil { 120 return templ_7745c5c3_Err 121 } 122 var templ_7745c5c3_Var5 string 123 templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(`@` + ic.Profile.Username) 124 if templ_7745c5c3_Err != nil { 125 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 55, Col: 56} 126 } 127 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 128 if templ_7745c5c3_Err != nil { 129 return templ_7745c5c3_Err 130 } 131 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div>") 132 if templ_7745c5c3_Err != nil { 133 return templ_7745c5c3_Err 134 } 135 } 136 if ic.Profile.Email != "" { 137 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"text-mauve col-span-2\"><div class=\"w-5 h-5 stroke-mauve inline-block mr-1 align-middle\">") 138 if templ_7745c5c3_Err != nil { 139 return templ_7745c5c3_Err 140 } ··· 142 if templ_7745c5c3_Err != nil { 143 return templ_7745c5c3_Err 144 } 145 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div><a class=\"underline decoration-mauve/50 decoration-dashed hover:decoration-solid\" href=\"") 146 if templ_7745c5c3_Err != nil { 147 return templ_7745c5c3_Err 148 } 149 + var templ_7745c5c3_Var6 templ.SafeURL 150 + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL("mailto:" + ic.Profile.Email)) 151 + if templ_7745c5c3_Err != nil { 152 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 62, Col: 138} 153 + } 154 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 155 if templ_7745c5c3_Err != nil { 156 return templ_7745c5c3_Err 157 } 158 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\">") 159 if templ_7745c5c3_Err != nil { 160 return templ_7745c5c3_Err 161 } 162 var templ_7745c5c3_Var7 string 163 templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(ic.Profile.Email) 164 if templ_7745c5c3_Err != nil { 165 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 62, Col: 159} 166 } 167 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 168 if templ_7745c5c3_Err != nil { 169 return templ_7745c5c3_Err 170 } 171 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</a></div>") 172 if templ_7745c5c3_Err != nil { 173 return templ_7745c5c3_Err 174 } 175 } 176 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div><div class=\"grid grid-cols-1 sm:grid-cols-8\">") 177 if templ_7745c5c3_Err != nil { 178 return templ_7745c5c3_Err 179 } 180 for _, link := range ic.Profile.Links { 181 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"text-mauve\"><div class=\"w-5 h-5 stroke-mauve inline-block mr-1 align-middle\">") 182 if templ_7745c5c3_Err != nil { 183 return templ_7745c5c3_Err 184 } ··· 186 if templ_7745c5c3_Err != nil { 187 return templ_7745c5c3_Err 188 } 189 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div><a class=\"underline decoration-mauve/50 decoration-dashed hover:decoration-solid\" rel=\"me\" href=\"") 190 if templ_7745c5c3_Err != nil { 191 return templ_7745c5c3_Err 192 } 193 + var templ_7745c5c3_Var8 templ.SafeURL 194 + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(link.URL)) 195 + if templ_7745c5c3_Err != nil { 196 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 72, Col: 127} 197 + } 198 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) 199 if templ_7745c5c3_Err != nil { 200 return templ_7745c5c3_Err 201 } 202 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\">") 203 if templ_7745c5c3_Err != nil { 204 return templ_7745c5c3_Err 205 } 206 var templ_7745c5c3_Var9 string 207 templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(link.Name) 208 if templ_7745c5c3_Err != nil { 209 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 72, Col: 141} 210 } 211 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) 212 if templ_7745c5c3_Err != nil { 213 return templ_7745c5c3_Err 214 } 215 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</a></div>") 216 if templ_7745c5c3_Err != nil { 217 return templ_7745c5c3_Err 218 } 219 } 220 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</div><div class=\"grid sm:grid-cols-10 gap-2 mt-5\">") 221 if templ_7745c5c3_Err != nil { 222 return templ_7745c5c3_Err 223 } 224 for _, repo := range ic.Repos { 225 + commit := lastCommit(repo) 226 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<div class=\"sm:col-span-2 text-blue dark:text-lavender\"><a class=\"underline decoration-blue/50 dark:decoration-lavender/50 decoration-dashed hover:decoration-solid\" href=\"") 227 if templ_7745c5c3_Err != nil { 228 return templ_7745c5c3_Err 229 } 230 + var templ_7745c5c3_Var10 templ.SafeURL 231 + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL("/" + repo.Name())) 232 + if templ_7745c5c3_Err != nil { 233 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 79, Col: 205} 234 + } 235 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) 236 if templ_7745c5c3_Err != nil { 237 return templ_7745c5c3_Err 238 } 239 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\">") 240 if templ_7745c5c3_Err != nil { 241 return templ_7745c5c3_Err 242 } 243 var templ_7745c5c3_Var11 string 244 templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Name()) 245 if templ_7745c5c3_Err != nil { 246 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 79, Col: 221} 247 } 248 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) 249 if templ_7745c5c3_Err != nil { 250 return templ_7745c5c3_Err 251 } 252 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</a></div><div class=\"sm:col-span-3 text-subtext0\">") 253 if templ_7745c5c3_Err != nil { 254 return templ_7745c5c3_Err 255 } 256 var templ_7745c5c3_Var12 string 257 templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Meta.Description) 258 if templ_7745c5c3_Err != nil { 259 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 80, Col: 69} 260 } 261 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) 262 if templ_7745c5c3_Err != nil { 263 return templ_7745c5c3_Err 264 } 265 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</div><div class=\"sm:col-span-3 text-subtext0\">") 266 if templ_7745c5c3_Err != nil { 267 return templ_7745c5c3_Err 268 } 269 + if commit != nil { 270 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<div title=\"") 271 if templ_7745c5c3_Err != nil { 272 return templ_7745c5c3_Err 273 } 274 + var templ_7745c5c3_Var13 string 275 + templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Message) 276 + if templ_7745c5c3_Err != nil { 277 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 83, Col: 34} 278 + } 279 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) 280 if templ_7745c5c3_Err != nil { 281 return templ_7745c5c3_Err 282 } 283 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "\"><a class=\"underline text-blue dark:text-lavender decoration-blue/50 dark:decoration-lavender/50 decoration-dashed hover:decoration-solid\" href=\"") 284 if templ_7745c5c3_Err != nil { 285 return templ_7745c5c3_Err 286 } 287 + var templ_7745c5c3_Var14 templ.SafeURL 288 + templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinURLErrs(fmt.Sprintf("/%s/commit/%s", repo.Name(), commit.SHA)) 289 if templ_7745c5c3_Err != nil { 290 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 84, Col: 206} 291 } 292 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) 293 if templ_7745c5c3_Err != nil { 294 return templ_7745c5c3_Err 295 } 296 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\">") 297 + if templ_7745c5c3_Err != nil { 298 + return templ_7745c5c3_Err 299 + } 300 + var templ_7745c5c3_Var15 string 301 + templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Short()) 302 + if templ_7745c5c3_Err != nil { 303 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 84, Col: 225} 304 + } 305 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) 306 + if templ_7745c5c3_Err != nil { 307 + return templ_7745c5c3_Err 308 + } 309 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</a> ") 310 + if templ_7745c5c3_Err != nil { 311 + return templ_7745c5c3_Err 312 + } 313 + var templ_7745c5c3_Var16 string 314 + templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(": " + commit.Summary()) 315 + if templ_7745c5c3_Err != nil { 316 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 85, Col: 33} 317 + } 318 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) 319 + if templ_7745c5c3_Err != nil { 320 + return templ_7745c5c3_Err 321 + } 322 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</div>") 323 if templ_7745c5c3_Err != nil { 324 return templ_7745c5c3_Err 325 } 326 } 327 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</div><div class=\"sm:col-span-1 text-subtext0\">") 328 if templ_7745c5c3_Err != nil { 329 return templ_7745c5c3_Err 330 } 331 + for _, tag := range repo.Meta.Tags.Slice() { 332 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<a href=\"") 333 + if templ_7745c5c3_Err != nil { 334 + return templ_7745c5c3_Err 335 + } 336 + var templ_7745c5c3_Var17 templ.SafeURL 337 + templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL("?tag=" + tag)) 338 + if templ_7745c5c3_Err != nil { 339 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 91, Col: 45} 340 + } 341 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) 342 + if templ_7745c5c3_Err != nil { 343 + return templ_7745c5c3_Err 344 + } 345 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "\" class=\"rounded border-rosewater border-solid border pb-0.5 px-1 mr-1 mb-1 inline-block\">") 346 + if templ_7745c5c3_Err != nil { 347 + return templ_7745c5c3_Err 348 + } 349 + var templ_7745c5c3_Var18 string 350 + templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(tag) 351 + if templ_7745c5c3_Err != nil { 352 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 91, Col: 141} 353 + } 354 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) 355 + if templ_7745c5c3_Err != nil { 356 + return templ_7745c5c3_Err 357 + } 358 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</a>") 359 + if templ_7745c5c3_Err != nil { 360 + return templ_7745c5c3_Err 361 + } 362 + } 363 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</div><div class=\"sm:col-span-1 text-text/80 mb-4 sm:mb-0\" title=\"") 364 if templ_7745c5c3_Err != nil { 365 + return templ_7745c5c3_Err 366 + } 367 + var templ_7745c5c3_Var19 string 368 + templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(lastCommitTime(repo, false)) 369 + if templ_7745c5c3_Err != nil { 370 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 94, Col: 93} 371 } 372 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) 373 if templ_7745c5c3_Err != nil { 374 return templ_7745c5c3_Err 375 } 376 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "\">") 377 if templ_7745c5c3_Err != nil { 378 return templ_7745c5c3_Err 379 } 380 + var templ_7745c5c3_Var20 string 381 + templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(lastCommitTime(repo, true)) 382 if templ_7745c5c3_Err != nil { 383 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 94, Col: 124} 384 } 385 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) 386 if templ_7745c5c3_Err != nil { 387 return templ_7745c5c3_Err 388 } 389 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "</div>") 390 if templ_7745c5c3_Err != nil { 391 return templ_7745c5c3_Err 392 } 393 } 394 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "</div></main>") 395 if templ_7745c5c3_Err != nil { 396 return templ_7745c5c3_Err 397 } 398 + return nil 399 }) 400 templ_7745c5c3_Err = base(ic.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 401 if templ_7745c5c3_Err != nil { 402 return templ_7745c5c3_Err 403 } 404 + return nil 405 }) 406 } 407 + 408 + var _ = templruntime.GeneratedTemplate
+16 -24
internal/html/markup/chroma.go
··· 2 3 import ( 4 "io" 5 6 "github.com/alecthomas/chroma/v2" 7 "github.com/alecthomas/chroma/v2/formatters/html" ··· 9 "github.com/alecthomas/chroma/v2/styles" 10 ) 11 12 - var ( 13 - // Formatter is the default formatter 14 - Formatter = html.New( 15 html.WithLineNumbers(true), 16 - html.WithLinkableLineNumbers(true, "L"), 17 html.WithClasses(true), 18 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{} 28 29 func setup(source []byte, fileName string) (chroma.Iterator, *chroma.Style, error) { 30 lexer := lexers.Match(fileName) 31 if lexer == nil { 32 lexer = lexers.Fallback 33 } 34 lexer = chroma.Coalesce(lexer) 35 ··· 46 return iter, style, nil 47 } 48 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 // Convert formats code with line numbers, links, etc. 59 - func (c code) Convert(source []byte, fileName string, writer io.Writer) error { 60 iter, style, err := setup(source, fileName) 61 if err != nil { 62 return err 63 } 64 - return Formatter.Format(writer, style, iter) 65 } 66 67 // Snippet formats code with line numbers starting at a specific line
··· 2 3 import ( 4 "io" 5 + "path/filepath" 6 7 "github.com/alecthomas/chroma/v2" 8 "github.com/alecthomas/chroma/v2/formatters/html" ··· 10 "github.com/alecthomas/chroma/v2/styles" 11 ) 12 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{ 20 html.WithLineNumbers(true), 21 + html.WithLinkableLineNumbers(true, linePrefix), 22 html.WithClasses(true), 23 html.LineNumbersInTable(true), 24 + } 25 + } 26 27 func setup(source []byte, fileName string) (chroma.Iterator, *chroma.Style, error) { 28 lexer := lexers.Match(fileName) 29 if lexer == nil { 30 lexer = lexers.Fallback 31 + if name, ok := customReg[filepath.Ext(fileName)]; ok { 32 + lexer = lexers.Get(name) 33 + } 34 } 35 lexer = chroma.Coalesce(lexer) 36 ··· 47 return iter, style, nil 48 } 49 50 // Convert formats code with line numbers, links, etc. 51 + func Convert(source []byte, fileName, linePrefix string, writer io.Writer) error { 52 iter, style, err := setup(source, fileName) 53 if err != nil { 54 return err 55 } 56 + return html.New(Options(linePrefix)...).Format(writer, style, iter) 57 } 58 59 // Snippet formats code with line numbers starting at a specific line
+1
internal/html/markup/markdown.go
··· 112 case *ast.Image: 113 link := v.Destination 114 if len(link) > 0 && !bytes.HasPrefix(link, []byte("http")) { 115 v.Destination = []byte(resolveLink(ctx.repo, ctx.ref, ctx.path, string(link)) + "?raw&pretty") 116 } 117
··· 112 case *ast.Image: 113 link := v.Destination 114 if len(link) > 0 && !bytes.HasPrefix(link, []byte("http")) { 115 + v.SetAttributeString("style", []byte("max-width:100%;")) 116 v.Destination = []byte(resolveLink(ctx.repo, ctx.ref, ctx.path, string(link)) + "?raw&pretty") 117 } 118
+4 -3
internal/html/readme.templ
··· 1 package html 2 3 type ReadmeComponentContext struct { 4 - Markdown string 5 } 6 7 templ readmeComponent(rcc ReadmeComponentContext) { 8 if rcc.Markdown != "" { 9 - <div class="bg-base dark:bg-base/50 p-5 mt-5 rounded markdown">@templ.Raw(rcc.Markdown)</div> 10 } 11 } 12 -
··· 1 package html 2 3 type ReadmeComponentContext struct { 4 + Markdown string 5 } 6 7 templ readmeComponent(rcc ReadmeComponentContext) { 8 if rcc.Markdown != "" { 9 + <div class="bg-base dark:bg-base/50 p-5 mt-5 rounded markdown"> 10 + @templ.Raw(rcc.Markdown) 11 + </div> 12 } 13 }
+19 -14
internal/html/readme_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.707 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 - import "context" 10 - import "io" 11 - import "bytes" 12 13 type ReadmeComponentContext struct { 14 Markdown string 15 } 16 17 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) 20 if !templ_7745c5c3_IsBuffer { 21 - templ_7745c5c3_Buffer = templ.GetBuffer() 22 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 23 } 24 ctx = templ.InitializeContext(ctx) 25 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 28 } 29 ctx = templ.ClearChildren(ctx) 30 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\">") 32 if templ_7745c5c3_Err != nil { 33 return templ_7745c5c3_Err 34 } ··· 36 if templ_7745c5c3_Err != nil { 37 return templ_7745c5c3_Err 38 } 39 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 40 if templ_7745c5c3_Err != nil { 41 return templ_7745c5c3_Err 42 } 43 } 44 - if !templ_7745c5c3_IsBuffer { 45 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 46 - } 47 - return templ_7745c5c3_Err 48 }) 49 }
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 + // templ: version: v0.3.924 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 11 type ReadmeComponentContext struct { 12 Markdown string 13 } 14 15 func readmeComponent(rcc ReadmeComponentContext) templ.Component { 16 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 17 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 18 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 19 + return templ_7745c5c3_CtxErr 20 + } 21 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 22 if !templ_7745c5c3_IsBuffer { 23 + defer func() { 24 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 25 + if templ_7745c5c3_Err == nil { 26 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 27 + } 28 + }() 29 } 30 ctx = templ.InitializeContext(ctx) 31 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 34 } 35 ctx = templ.ClearChildren(ctx) 36 if rcc.Markdown != "" { 37 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"bg-base dark:bg-base/50 p-5 mt-5 rounded markdown\">") 38 if templ_7745c5c3_Err != nil { 39 return templ_7745c5c3_Err 40 } ··· 42 if templ_7745c5c3_Err != nil { 43 return templ_7745c5c3_Err 44 } 45 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</div>") 46 if templ_7745c5c3_Err != nil { 47 return templ_7745c5c3_Err 48 } 49 } 50 + return nil 51 }) 52 } 53 + 54 + var _ = templruntime.GeneratedTemplate
+1 -1
internal/html/repo_breadcrumb.templ
··· 2 3 import ( 4 "fmt" 5 - "strings" 6 "path" 7 ) 8 9 type RepoBreadcrumbComponentContext struct {
··· 2 3 import ( 4 "fmt" 5 "path" 6 + "strings" 7 ) 8 9 type RepoBreadcrumbComponentContext struct {
+30 -21
internal/html/repo_breadcrumb_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.707 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 - import "context" 10 - import "io" 11 - import "bytes" 12 13 import ( 14 "fmt" ··· 47 } 48 49 func repoBreadcrumbComponent(rbcc RepoBreadcrumbComponentContext) templ.Component { 50 - return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { 51 - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) 52 if !templ_7745c5c3_IsBuffer { 53 - templ_7745c5c3_Buffer = templ.GetBuffer() 54 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 55 } 56 ctx = templ.InitializeContext(ctx) 57 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 60 } 61 ctx = templ.ClearChildren(ctx) 62 if rbcc.Path != "" { 63 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"inline-block text-text\">") 64 if templ_7745c5c3_Err != nil { 65 return templ_7745c5c3_Err 66 } 67 for _, crumb := range rbcc.crumbs() { 68 if crumb.end { 69 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<span>") 70 if templ_7745c5c3_Err != nil { 71 return templ_7745c5c3_Err 72 } ··· 79 if templ_7745c5c3_Err != nil { 80 return templ_7745c5c3_Err 81 } 82 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span>") 83 if templ_7745c5c3_Err != nil { 84 return templ_7745c5c3_Err 85 } 86 } else { 87 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 88 if templ_7745c5c3_Err != nil { 89 return templ_7745c5c3_Err 90 } 91 - var templ_7745c5c3_Var3 templ.SafeURL = templ.SafeURL(crumb.href) 92 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var3))) 93 if templ_7745c5c3_Err != nil { 94 return templ_7745c5c3_Err 95 } 96 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 97 if templ_7745c5c3_Err != nil { 98 return templ_7745c5c3_Err 99 } ··· 106 if templ_7745c5c3_Err != nil { 107 return templ_7745c5c3_Err 108 } 109 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a> ") 110 if templ_7745c5c3_Err != nil { 111 return templ_7745c5c3_Err 112 } ··· 121 } 122 } 123 } 124 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 125 if templ_7745c5c3_Err != nil { 126 return templ_7745c5c3_Err 127 } 128 } 129 - if !templ_7745c5c3_IsBuffer { 130 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 131 - } 132 - return templ_7745c5c3_Err 133 }) 134 }
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 + // templ: version: v0.3.924 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 11 import ( 12 "fmt" ··· 45 } 46 47 func repoBreadcrumbComponent(rbcc RepoBreadcrumbComponentContext) templ.Component { 48 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 49 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 50 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 51 + return templ_7745c5c3_CtxErr 52 + } 53 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 54 if !templ_7745c5c3_IsBuffer { 55 + defer func() { 56 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 57 + if templ_7745c5c3_Err == nil { 58 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 59 + } 60 + }() 61 } 62 ctx = templ.InitializeContext(ctx) 63 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 66 } 67 ctx = templ.ClearChildren(ctx) 68 if rbcc.Path != "" { 69 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"inline-block text-text\">") 70 if templ_7745c5c3_Err != nil { 71 return templ_7745c5c3_Err 72 } 73 for _, crumb := range rbcc.crumbs() { 74 if crumb.end { 75 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<span>") 76 if templ_7745c5c3_Err != nil { 77 return templ_7745c5c3_Err 78 } ··· 85 if templ_7745c5c3_Err != nil { 86 return templ_7745c5c3_Err 87 } 88 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span>") 89 if templ_7745c5c3_Err != nil { 90 return templ_7745c5c3_Err 91 } 92 } else { 93 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 94 if templ_7745c5c3_Err != nil { 95 return templ_7745c5c3_Err 96 } 97 + var templ_7745c5c3_Var3 templ.SafeURL 98 + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(crumb.href)) 99 + if templ_7745c5c3_Err != nil { 100 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_breadcrumb.templ`, Line: 46, Col: 118} 101 + } 102 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 103 if templ_7745c5c3_Err != nil { 104 return templ_7745c5c3_Err 105 } 106 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">") 107 if templ_7745c5c3_Err != nil { 108 return templ_7745c5c3_Err 109 } ··· 116 if templ_7745c5c3_Err != nil { 117 return templ_7745c5c3_Err 118 } 119 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</a> ") 120 if templ_7745c5c3_Err != nil { 121 return templ_7745c5c3_Err 122 } ··· 131 } 132 } 133 } 134 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div>") 135 if templ_7745c5c3_Err != nil { 136 return templ_7745c5c3_Err 137 } 138 } 139 + return nil 140 }) 141 } 142 + 143 + var _ = templruntime.GeneratedTemplate
+16 -8
internal/html/repo_commit.templ
··· 4 import "github.com/dustin/go-humanize" 5 import "go.jolheiser.com/ugit/internal/git" 6 7 - type RepoCommitContext struct{ 8 - BaseContext 9 - RepoHeaderComponentContext 10 - Commit git.Commit 11 } 12 13 templ RepoCommit(rcc RepoCommitContext) { ··· 25 <div>{ rcc.Commit.Author }{ " " }<a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("mailto:%s", rcc.Commit.Email)) }>{ fmt.Sprintf("<%s>", rcc.Commit.Email) }</a></div> 26 <div title={ rcc.Commit.When.Format("01/02/2006 03:04:05 PM") }>{ humanize.Time(rcc.Commit.When) }</div> 27 </div> 28 - <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> 29 for _, file := range rcc.Commit.Files { 30 - <div class="text-text mt-5"> 31 <span class="text-text/80" title={ file.Action }>{ string(file.Action[0]) }</span> 32 { " " } 33 if file.From.Path != "" { ··· 40 <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 } 42 </div> 43 - <div class="whitespace-pre code">@templ.Raw(file.Patch)</div> 44 } 45 } 46 } 47 -
··· 4 import "github.com/dustin/go-humanize" 5 import "go.jolheiser.com/ugit/internal/git" 6 7 + type RepoCommitContext struct { 8 + BaseContext 9 + RepoHeaderComponentContext 10 + Commit git.Commit 11 } 12 13 templ RepoCommit(rcc RepoCommitContext) { ··· 25 <div>{ rcc.Commit.Author }{ " " }<a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("mailto:%s", rcc.Commit.Email)) }>{ fmt.Sprintf("<%s>", rcc.Commit.Email) }</a></div> 26 <div title={ rcc.Commit.When.Format("01/02/2006 03:04:05 PM") }>{ humanize.Time(rcc.Commit.When) }</div> 27 </div> 28 + <details class="text-text mt-5"> 29 + <summary class="cursor-pointer">{ fmt.Sprintf("%d changed files, %d additions(+), %d deletions(-)", rcc.Commit.Stats.Changed, rcc.Commit.Stats.Additions, rcc.Commit.Stats.Deletions) }</summary> 30 + <div class="p-3 bg-base rounded"> 31 + for _, file := range rcc.Commit.Files { 32 + <a class="block underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ "#" + file.Path() }>{ file.Path() }</a> 33 + } 34 + </div> 35 + </details> 36 for _, file := range rcc.Commit.Files { 37 + <div class="text-text mt-5" id={ file.Path() }> 38 <span class="text-text/80" title={ file.Action }>{ string(file.Action[0]) }</span> 39 { " " } 40 if file.From.Path != "" { ··· 47 <a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.To.Commit, file.To.Path)) }>{ file.To.Path }</a> 48 } 49 </div> 50 + <div class="code"> 51 + @templ.Raw(file.Patch) 52 + </div> 53 } 54 } 55 }
+162 -81
internal/html/repo_commit_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.707 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 - import "context" 10 - import "io" 11 - import "bytes" 12 13 import "fmt" 14 import "github.com/dustin/go-humanize" ··· 21 } 22 23 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) 26 if !templ_7745c5c3_IsBuffer { 27 - templ_7745c5c3_Buffer = templ.GetBuffer() 28 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 29 } 30 ctx = templ.InitializeContext(ctx) 31 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 33 templ_7745c5c3_Var1 = templ.NopComponent 34 } 35 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) 38 if !templ_7745c5c3_IsBuffer { 39 - templ_7745c5c3_Buffer = templ.GetBuffer() 40 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 41 } 42 templ_7745c5c3_Err = repoHeaderComponent(rcc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer) 43 if templ_7745c5c3_Err != nil { 44 return templ_7745c5c3_Err 45 } 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=\"") 47 if templ_7745c5c3_Err != nil { 48 return templ_7745c5c3_Err 49 } 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))) 52 if templ_7745c5c3_Err != nil { 53 return templ_7745c5c3_Err 54 } 55 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">tree</a>") 56 if templ_7745c5c3_Err != nil { 57 return templ_7745c5c3_Err 58 } ··· 65 if templ_7745c5c3_Err != nil { 66 return templ_7745c5c3_Err 67 } 68 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 69 if templ_7745c5c3_Err != nil { 70 return templ_7745c5c3_Err 71 } 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))) 74 if templ_7745c5c3_Err != nil { 75 return templ_7745c5c3_Err 76 } 77 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">log</a>") 78 if templ_7745c5c3_Err != nil { 79 return templ_7745c5c3_Err 80 } ··· 87 if templ_7745c5c3_Err != nil { 88 return templ_7745c5c3_Err 89 } 90 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 91 if templ_7745c5c3_Err != nil { 92 return templ_7745c5c3_Err 93 } 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))) 96 if templ_7745c5c3_Err != nil { 97 return templ_7745c5c3_Err 98 } 99 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">patch</a></div><div class=\"text-text whitespace-pre mt-5 p-3 bg-base rounded\">") 100 if templ_7745c5c3_Err != nil { 101 return templ_7745c5c3_Err 102 } ··· 109 if templ_7745c5c3_Err != nil { 110 return templ_7745c5c3_Err 111 } 112 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 113 if templ_7745c5c3_Err != nil { 114 return templ_7745c5c3_Err 115 } 116 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>") 118 if templ_7745c5c3_Err != nil { 119 return templ_7745c5c3_Err 120 } ··· 127 if templ_7745c5c3_Err != nil { 128 return templ_7745c5c3_Err 129 } 130 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</code></div></details>") 131 if templ_7745c5c3_Err != nil { 132 return templ_7745c5c3_Err 133 } 134 } 135 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <div class=\"text-text mt-3\"><div>") 136 if templ_7745c5c3_Err != nil { 137 return templ_7745c5c3_Err 138 } ··· 154 if templ_7745c5c3_Err != nil { 155 return templ_7745c5c3_Err 156 } 157 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 158 if templ_7745c5c3_Err != nil { 159 return templ_7745c5c3_Err 160 } 161 - var templ_7745c5c3_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))) 163 if templ_7745c5c3_Err != nil { 164 return templ_7745c5c3_Err 165 } 166 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 167 if templ_7745c5c3_Err != nil { 168 return templ_7745c5c3_Err 169 } ··· 176 if templ_7745c5c3_Err != nil { 177 return templ_7745c5c3_Err 178 } 179 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div title=\"") 180 if templ_7745c5c3_Err != nil { 181 return templ_7745c5c3_Err 182 } ··· 189 if templ_7745c5c3_Err != nil { 190 return templ_7745c5c3_Err 191 } 192 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 193 if templ_7745c5c3_Err != nil { 194 return templ_7745c5c3_Err 195 } ··· 202 if templ_7745c5c3_Err != nil { 203 return templ_7745c5c3_Err 204 } 205 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div><div class=\"text-text mt-5\">") 206 if templ_7745c5c3_Err != nil { 207 return templ_7745c5c3_Err 208 } 209 var templ_7745c5c3_Var16 string 210 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 if templ_7745c5c3_Err != nil { 212 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 28, Col: 179} 213 } 214 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) 215 if templ_7745c5c3_Err != nil { 216 return templ_7745c5c3_Err 217 } 218 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 219 if templ_7745c5c3_Err != nil { 220 return templ_7745c5c3_Err 221 } 222 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=\"") 224 if templ_7745c5c3_Err != nil { 225 return templ_7745c5c3_Err 226 } 227 - var templ_7745c5c3_Var17 string 228 - templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(file.Action) 229 if templ_7745c5c3_Err != nil { 230 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 31, Col: 50} 231 } 232 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) 233 if templ_7745c5c3_Err != nil { 234 return templ_7745c5c3_Err 235 } 236 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 237 if templ_7745c5c3_Err != nil { 238 return templ_7745c5c3_Err 239 } 240 var templ_7745c5c3_Var18 string 241 - templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(string(file.Action[0])) 242 if templ_7745c5c3_Err != nil { 243 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 31, Col: 77} 244 } 245 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) 246 if templ_7745c5c3_Err != nil { 247 return templ_7745c5c3_Err 248 } 249 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span> ") 250 if templ_7745c5c3_Err != nil { 251 return templ_7745c5c3_Err 252 } 253 var templ_7745c5c3_Var19 string 254 - templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 255 if templ_7745c5c3_Err != nil { 256 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 32, Col: 9} 257 } 258 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) 259 if templ_7745c5c3_Err != nil { 260 return templ_7745c5c3_Err 261 } 262 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 263 if templ_7745c5c3_Err != nil { 264 return templ_7745c5c3_Err 265 } 266 if file.From.Path != "" { 267 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 268 if templ_7745c5c3_Err != nil { 269 return templ_7745c5c3_Err 270 } 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))) 273 if templ_7745c5c3_Err != nil { 274 return templ_7745c5c3_Err 275 } 276 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 277 if templ_7745c5c3_Err != nil { 278 return templ_7745c5c3_Err 279 } 280 - var templ_7745c5c3_Var21 string 281 - templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(file.From.Path) 282 if templ_7745c5c3_Err != nil { 283 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 34, Col: 227} 284 } 285 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) 286 if templ_7745c5c3_Err != nil { 287 return templ_7745c5c3_Err 288 } 289 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a> ") 290 if templ_7745c5c3_Err != nil { 291 return templ_7745c5c3_Err 292 } 293 } 294 if file.From.Path != "" && file.To.Path != "" { 295 - var templ_7745c5c3_Var22 string 296 - templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(" -> ") 297 if templ_7745c5c3_Err != nil { 298 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 37, Col: 13} 299 } 300 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) 301 if templ_7745c5c3_Err != nil { 302 return templ_7745c5c3_Err 303 } 304 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 305 if templ_7745c5c3_Err != nil { 306 return templ_7745c5c3_Err 307 } 308 } 309 if file.To.Path != "" { 310 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 311 if templ_7745c5c3_Err != nil { 312 return templ_7745c5c3_Err 313 } 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))) 316 if templ_7745c5c3_Err != nil { 317 return templ_7745c5c3_Err 318 } 319 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 320 if templ_7745c5c3_Err != nil { 321 return templ_7745c5c3_Err 322 } 323 - var templ_7745c5c3_Var24 string 324 - templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(file.To.Path) 325 if templ_7745c5c3_Err != nil { 326 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 40, Col: 221} 327 } 328 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) 329 if templ_7745c5c3_Err != nil { 330 return templ_7745c5c3_Err 331 } 332 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>") 333 if templ_7745c5c3_Err != nil { 334 return templ_7745c5c3_Err 335 } 336 } 337 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"whitespace-pre code\">") 338 if templ_7745c5c3_Err != nil { 339 return templ_7745c5c3_Err 340 } ··· 342 if templ_7745c5c3_Err != nil { 343 return templ_7745c5c3_Err 344 } 345 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 346 if templ_7745c5c3_Err != nil { 347 return templ_7745c5c3_Err 348 } 349 } 350 - if !templ_7745c5c3_IsBuffer { 351 - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) 352 - } 353 - return templ_7745c5c3_Err 354 }) 355 templ_7745c5c3_Err = base(rcc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 356 if templ_7745c5c3_Err != nil { 357 return templ_7745c5c3_Err 358 } 359 - if !templ_7745c5c3_IsBuffer { 360 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 361 - } 362 - return templ_7745c5c3_Err 363 }) 364 }
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 + // templ: version: v0.3.924 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 11 import "fmt" 12 import "github.com/dustin/go-humanize" ··· 19 } 20 21 func RepoCommit(rcc RepoCommitContext) templ.Component { 22 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 23 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 24 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 25 + return templ_7745c5c3_CtxErr 26 + } 27 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 28 if !templ_7745c5c3_IsBuffer { 29 + defer func() { 30 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 31 + if templ_7745c5c3_Err == nil { 32 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 33 + } 34 + }() 35 } 36 ctx = templ.InitializeContext(ctx) 37 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 39 templ_7745c5c3_Var1 = templ.NopComponent 40 } 41 ctx = templ.ClearChildren(ctx) 42 + templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 43 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 44 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 45 if !templ_7745c5c3_IsBuffer { 46 + defer func() { 47 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 48 + if templ_7745c5c3_Err == nil { 49 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 50 + } 51 + }() 52 } 53 + ctx = templ.InitializeContext(ctx) 54 templ_7745c5c3_Err = repoHeaderComponent(rcc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer) 55 if templ_7745c5c3_Err != nil { 56 return templ_7745c5c3_Err 57 } 58 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"text-text mt-5\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 59 if templ_7745c5c3_Err != nil { 60 return templ_7745c5c3_Err 61 } 62 + var templ_7745c5c3_Var3 templ.SafeURL 63 + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA))) 64 + if templ_7745c5c3_Err != nil { 65 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 16, Col: 213} 66 + } 67 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 68 if templ_7745c5c3_Err != nil { 69 return templ_7745c5c3_Err 70 } 71 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\">tree</a>") 72 if templ_7745c5c3_Err != nil { 73 return templ_7745c5c3_Err 74 } ··· 81 if templ_7745c5c3_Err != nil { 82 return templ_7745c5c3_Err 83 } 84 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 85 if templ_7745c5c3_Err != nil { 86 return templ_7745c5c3_Err 87 } 88 + var templ_7745c5c3_Var5 templ.SafeURL 89 + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/log/%s", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA))) 90 + if templ_7745c5c3_Err != nil { 91 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 16, Col: 412} 92 + } 93 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 94 if templ_7745c5c3_Err != nil { 95 return templ_7745c5c3_Err 96 } 97 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\">log</a>") 98 if templ_7745c5c3_Err != nil { 99 return templ_7745c5c3_Err 100 } ··· 107 if templ_7745c5c3_Err != nil { 108 return templ_7745c5c3_Err 109 } 110 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 111 if templ_7745c5c3_Err != nil { 112 return templ_7745c5c3_Err 113 } 114 + var templ_7745c5c3_Var7 templ.SafeURL 115 + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/commit/%s.patch", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA))) 116 + if templ_7745c5c3_Err != nil { 117 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 16, Col: 619} 118 + } 119 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 120 if templ_7745c5c3_Err != nil { 121 return templ_7745c5c3_Err 122 } 123 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">patch</a></div><div class=\"text-text whitespace-pre mt-5 p-3 bg-base rounded\">") 124 if templ_7745c5c3_Err != nil { 125 return templ_7745c5c3_Err 126 } ··· 133 if templ_7745c5c3_Err != nil { 134 return templ_7745c5c3_Err 135 } 136 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div>") 137 if templ_7745c5c3_Err != nil { 138 return templ_7745c5c3_Err 139 } 140 if rcc.Commit.Signature != "" { 141 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<details class=\"text-text whitespace-pre\"><summary class=\"cursor-pointer\">Signature</summary><div class=\"p-3 bg-base rounded\"><code>") 142 if templ_7745c5c3_Err != nil { 143 return templ_7745c5c3_Err 144 } ··· 151 if templ_7745c5c3_Err != nil { 152 return templ_7745c5c3_Err 153 } 154 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</code></div></details>") 155 if templ_7745c5c3_Err != nil { 156 return templ_7745c5c3_Err 157 } 158 } 159 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " <div class=\"text-text mt-3\"><div>") 160 if templ_7745c5c3_Err != nil { 161 return templ_7745c5c3_Err 162 } ··· 178 if templ_7745c5c3_Err != nil { 179 return templ_7745c5c3_Err 180 } 181 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 182 if templ_7745c5c3_Err != nil { 183 return templ_7745c5c3_Err 184 } 185 + var templ_7745c5c3_Var12 templ.SafeURL 186 + templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("mailto:%s", rcc.Commit.Email))) 187 + if templ_7745c5c3_Err != nil { 188 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 25, Col: 181} 189 + } 190 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) 191 if templ_7745c5c3_Err != nil { 192 return templ_7745c5c3_Err 193 } 194 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\">") 195 if templ_7745c5c3_Err != nil { 196 return templ_7745c5c3_Err 197 } ··· 204 if templ_7745c5c3_Err != nil { 205 return templ_7745c5c3_Err 206 } 207 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</a></div><div title=\"") 208 if templ_7745c5c3_Err != nil { 209 return templ_7745c5c3_Err 210 } ··· 217 if templ_7745c5c3_Err != nil { 218 return templ_7745c5c3_Err 219 } 220 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "\">") 221 if templ_7745c5c3_Err != nil { 222 return templ_7745c5c3_Err 223 } ··· 230 if templ_7745c5c3_Err != nil { 231 return templ_7745c5c3_Err 232 } 233 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</div></div><details class=\"text-text mt-5\"><summary class=\"cursor-pointer\">") 234 if templ_7745c5c3_Err != nil { 235 return templ_7745c5c3_Err 236 } 237 var templ_7745c5c3_Var16 string 238 templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d changed files, %d additions(+), %d deletions(-)", rcc.Commit.Stats.Changed, rcc.Commit.Stats.Additions, rcc.Commit.Stats.Deletions)) 239 if templ_7745c5c3_Err != nil { 240 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 29, Col: 184} 241 } 242 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) 243 if templ_7745c5c3_Err != nil { 244 return templ_7745c5c3_Err 245 } 246 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</summary><div class=\"p-3 bg-base rounded\">") 247 if templ_7745c5c3_Err != nil { 248 return templ_7745c5c3_Err 249 } 250 for _, file := range rcc.Commit.Files { 251 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<a class=\"block underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 252 if templ_7745c5c3_Err != nil { 253 return templ_7745c5c3_Err 254 } 255 + var templ_7745c5c3_Var17 templ.SafeURL 256 + templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinURLErrs("#" + file.Path()) 257 if templ_7745c5c3_Err != nil { 258 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 32, Col: 116} 259 } 260 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) 261 if templ_7745c5c3_Err != nil { 262 return templ_7745c5c3_Err 263 } 264 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\">") 265 if templ_7745c5c3_Err != nil { 266 return templ_7745c5c3_Err 267 } 268 var templ_7745c5c3_Var18 string 269 + templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(file.Path()) 270 if templ_7745c5c3_Err != nil { 271 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 32, Col: 132} 272 } 273 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) 274 if templ_7745c5c3_Err != nil { 275 return templ_7745c5c3_Err 276 } 277 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</a>") 278 + if templ_7745c5c3_Err != nil { 279 + return templ_7745c5c3_Err 280 + } 281 + } 282 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</div></details> ") 283 + if templ_7745c5c3_Err != nil { 284 + return templ_7745c5c3_Err 285 + } 286 + for _, file := range rcc.Commit.Files { 287 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<div class=\"text-text mt-5\" id=\"") 288 if templ_7745c5c3_Err != nil { 289 return templ_7745c5c3_Err 290 } 291 var templ_7745c5c3_Var19 string 292 + templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(file.Path()) 293 if templ_7745c5c3_Err != nil { 294 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 37, Col: 47} 295 } 296 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) 297 if templ_7745c5c3_Err != nil { 298 return templ_7745c5c3_Err 299 } 300 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\"><span class=\"text-text/80\" title=\"") 301 + if templ_7745c5c3_Err != nil { 302 + return templ_7745c5c3_Err 303 + } 304 + var templ_7745c5c3_Var20 string 305 + templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(file.Action) 306 + if templ_7745c5c3_Err != nil { 307 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 38, Col: 50} 308 + } 309 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) 310 + if templ_7745c5c3_Err != nil { 311 + return templ_7745c5c3_Err 312 + } 313 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\">") 314 + if templ_7745c5c3_Err != nil { 315 + return templ_7745c5c3_Err 316 + } 317 + var templ_7745c5c3_Var21 string 318 + templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(string(file.Action[0])) 319 + if templ_7745c5c3_Err != nil { 320 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 38, Col: 77} 321 + } 322 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) 323 + if templ_7745c5c3_Err != nil { 324 + return templ_7745c5c3_Err 325 + } 326 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</span> ") 327 + if templ_7745c5c3_Err != nil { 328 + return templ_7745c5c3_Err 329 + } 330 + var templ_7745c5c3_Var22 string 331 + templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 332 + if templ_7745c5c3_Err != nil { 333 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 39, Col: 9} 334 + } 335 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) 336 + if templ_7745c5c3_Err != nil { 337 + return templ_7745c5c3_Err 338 + } 339 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, " ") 340 if templ_7745c5c3_Err != nil { 341 return templ_7745c5c3_Err 342 } 343 if file.From.Path != "" { 344 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 345 if templ_7745c5c3_Err != nil { 346 return templ_7745c5c3_Err 347 } 348 + var templ_7745c5c3_Var23 templ.SafeURL 349 + templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.From.Commit, file.From.Path))) 350 + if templ_7745c5c3_Err != nil { 351 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 41, Col: 208} 352 + } 353 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) 354 if templ_7745c5c3_Err != nil { 355 return templ_7745c5c3_Err 356 } 357 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "\">") 358 if templ_7745c5c3_Err != nil { 359 return templ_7745c5c3_Err 360 } 361 + var templ_7745c5c3_Var24 string 362 + templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(file.From.Path) 363 if templ_7745c5c3_Err != nil { 364 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 41, Col: 227} 365 } 366 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) 367 if templ_7745c5c3_Err != nil { 368 return templ_7745c5c3_Err 369 } 370 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</a> ") 371 if templ_7745c5c3_Err != nil { 372 return templ_7745c5c3_Err 373 } 374 } 375 if file.From.Path != "" && file.To.Path != "" { 376 + var templ_7745c5c3_Var25 string 377 + templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(" -> ") 378 if templ_7745c5c3_Err != nil { 379 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 44, Col: 13} 380 } 381 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) 382 if templ_7745c5c3_Err != nil { 383 return templ_7745c5c3_Err 384 } 385 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, " ") 386 if templ_7745c5c3_Err != nil { 387 return templ_7745c5c3_Err 388 } 389 } 390 if file.To.Path != "" { 391 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 392 if templ_7745c5c3_Err != nil { 393 return templ_7745c5c3_Err 394 } 395 + var templ_7745c5c3_Var26 templ.SafeURL 396 + templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.To.Commit, file.To.Path))) 397 + if templ_7745c5c3_Err != nil { 398 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 47, Col: 204} 399 + } 400 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) 401 if templ_7745c5c3_Err != nil { 402 return templ_7745c5c3_Err 403 } 404 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "\">") 405 if templ_7745c5c3_Err != nil { 406 return templ_7745c5c3_Err 407 } 408 + var templ_7745c5c3_Var27 string 409 + templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(file.To.Path) 410 if templ_7745c5c3_Err != nil { 411 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 47, Col: 221} 412 } 413 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) 414 if templ_7745c5c3_Err != nil { 415 return templ_7745c5c3_Err 416 } 417 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "</a>") 418 if templ_7745c5c3_Err != nil { 419 return templ_7745c5c3_Err 420 } 421 } 422 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</div><div class=\"code\">") 423 if templ_7745c5c3_Err != nil { 424 return templ_7745c5c3_Err 425 } ··· 427 if templ_7745c5c3_Err != nil { 428 return templ_7745c5c3_Err 429 } 430 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</div>") 431 if templ_7745c5c3_Err != nil { 432 return templ_7745c5c3_Err 433 } 434 } 435 + return nil 436 }) 437 templ_7745c5c3_Err = base(rcc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 438 if templ_7745c5c3_Err != nil { 439 return templ_7745c5c3_Err 440 } 441 + return nil 442 }) 443 } 444 + 445 + var _ = templruntime.GeneratedTemplate
+42 -5
internal/html/repo_file.templ
··· 1 package html 2 3 type RepoFileContext struct { 4 BaseContext 5 RepoHeaderComponentContext 6 RepoBreadcrumbComponentContext 7 - Code string 8 } 9 10 templ RepoFile(rfc RepoFileContext) { ··· 14 @repoBreadcrumbComponent(rfc.RepoBreadcrumbComponentContext) 15 { " - " } 16 <a class="text-text underline decoration-text/50 decoration-dashed hover:decoration-solid" href="?raw">raw</a> 17 - <div class="code"> 18 @templ.Raw(rfc.Code) 19 </div> 20 </div> 21 } ··· 23 const lineRe = /#L(\d+)(?:-L(\d+))?/g 24 const $lineLines = document.querySelectorAll(".chroma .lntable .lnt"); 25 const $codeLines = document.querySelectorAll(".chroma .lntable .line"); 26 let start = 0; 27 let end = 0; 28 ··· 31 start = results[0][1] !== undefined ? parseInt(results[0][1]) : 0; 32 end = results[0][2] !== undefined ? parseInt(results[0][2]) : 0; 33 } 34 - if (start != 0) { 35 deactivateLines(); 36 activateLines(start, end); 37 } 38 39 for (let line of $lineLines) { ··· 45 if (event.shiftKey) { 46 end = n; 47 anchor = `#L${start}-L${end}`; 48 } else { 49 start = n; 50 end = 0; 51 anchor = `#L${start}`; 52 } 53 - history.replaceState(null, null, anchor); 54 - activateLines(start, end); 55 }); 56 } 57 58 function activateLines(start, end) { 59 if (end < start) end = start;
··· 1 package html 2 3 + import "fmt" 4 + 5 type RepoFileContext struct { 6 BaseContext 7 RepoHeaderComponentContext 8 RepoBreadcrumbComponentContext 9 + Code string 10 + Commit string 11 + Path string 12 + } 13 + 14 + func (rfc RepoFileContext) Permalink() string { 15 + return fmt.Sprintf("/%s/tree/%s/%s", rfc.RepoBreadcrumbComponentContext.Repo, rfc.Commit, rfc.Path) 16 } 17 18 templ RepoFile(rfc RepoFileContext) { ··· 22 @repoBreadcrumbComponent(rfc.RepoBreadcrumbComponentContext) 23 { " - " } 24 <a class="text-text underline decoration-text/50 decoration-dashed hover:decoration-solid" href="?raw">raw</a> 25 + { " - " } 26 + <a class="text-text underline decoration-text/50 decoration-dashed hover:decoration-solid" id="permalink" data-permalink={ rfc.Permalink() } href={ rfc.Permalink() }>permalink</a> 27 + <div class="code relative"> 28 @templ.Raw(rfc.Code) 29 + <button id="copy" class="absolute top-0 right-0 rounded bg-base hover:bg-surface0"></button> 30 </div> 31 </div> 32 } ··· 34 const lineRe = /#L(\d+)(?:-L(\d+))?/g 35 const $lineLines = document.querySelectorAll(".chroma .lntable .lnt"); 36 const $codeLines = document.querySelectorAll(".chroma .lntable .line"); 37 + const $copyButton = document.getElementById('copy'); 38 + const $permalink = document.getElementById('permalink'); 39 + const $copyIcon = "๐Ÿ“‹"; 40 + const $copiedIcon = "โœ…"; 41 + let $code = "" 42 + for (let codeLine of $codeLines) $code += codeLine.innerText; 43 let start = 0; 44 let end = 0; 45 ··· 48 start = results[0][1] !== undefined ? parseInt(results[0][1]) : 0; 49 end = results[0][2] !== undefined ? parseInt(results[0][2]) : 0; 50 } 51 + if (start !== 0) { 52 deactivateLines(); 53 activateLines(start, end); 54 + let anchor = `#${start}`; 55 + if (end !== 0) anchor += `-${end}`; 56 + if (anchor !== "") $permalink.href = $permalink.dataset.permalink + anchor; 57 + $lineLines[start-1].scrollIntoView(true); 58 } 59 60 for (let line of $lineLines) { ··· 66 if (event.shiftKey) { 67 end = n; 68 anchor = `#L${start}-L${end}`; 69 + } else if (start === n) { 70 + start = 0; 71 + end = 0; 72 } else { 73 start = n; 74 end = 0; 75 anchor = `#L${start}`; 76 } 77 + history.replaceState(null, null, window.location.pathname + anchor); 78 + $permalink.href = $permalink.dataset.permalink + anchor; 79 + if (start !== 0) activateLines(start, end); 80 }); 81 } 82 + 83 + if (navigator.clipboard && navigator.clipboard.writeText) { 84 + $copyButton.innerText = $copyIcon; 85 + $copyButton.classList.remove("hidden"); 86 + } 87 + $copyButton.addEventListener("click", () => { 88 + navigator.clipboard.writeText($code); 89 + $copyButton.innerText = $copiedIcon; 90 + setTimeout(() => { 91 + $copyButton.innerText = $copyIcon; 92 + }, 1000); 93 + }); 94 95 function activateLines(start, end) { 96 if (end < start) end = start;
+81 -26
internal/html/repo_file_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.707 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 - import "context" 10 - import "io" 11 - import "bytes" 12 13 type RepoFileContext struct { 14 BaseContext 15 RepoHeaderComponentContext 16 RepoBreadcrumbComponentContext 17 - Code string 18 } 19 20 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) 23 if !templ_7745c5c3_IsBuffer { 24 - templ_7745c5c3_Buffer = templ.GetBuffer() 25 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 26 } 27 ctx = templ.InitializeContext(ctx) 28 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 30 templ_7745c5c3_Var1 = templ.NopComponent 31 } 32 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) 35 if !templ_7745c5c3_IsBuffer { 36 - templ_7745c5c3_Buffer = templ.GetBuffer() 37 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 38 } 39 templ_7745c5c3_Err = repoHeaderComponent(rfc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer) 40 if templ_7745c5c3_Err != nil { 41 return templ_7745c5c3_Err 42 } 43 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <div class=\"mt-2 text-text\">") 44 if templ_7745c5c3_Err != nil { 45 return templ_7745c5c3_Err 46 } ··· 51 var templ_7745c5c3_Var3 string 52 templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(" - ") 53 if templ_7745c5c3_Err != nil { 54 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 15, Col: 10} 55 } 56 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 57 if templ_7745c5c3_Err != nil { 58 return templ_7745c5c3_Err 59 } 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\">") 61 if templ_7745c5c3_Err != nil { 62 return templ_7745c5c3_Err 63 } 64 - templ_7745c5c3_Err = templ.Raw(rfc.Code).Render(ctx, templ_7745c5c3_Buffer) 65 if templ_7745c5c3_Err != nil { 66 return templ_7745c5c3_Err 67 } 68 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div>") 69 if templ_7745c5c3_Err != nil { 70 return templ_7745c5c3_Err 71 } 72 - if !templ_7745c5c3_IsBuffer { 73 - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) 74 } 75 - return templ_7745c5c3_Err 76 }) 77 templ_7745c5c3_Err = base(rfc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 78 if templ_7745c5c3_Err != nil { 79 return templ_7745c5c3_Err 80 } 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>") 82 if templ_7745c5c3_Err != nil { 83 return templ_7745c5c3_Err 84 } 85 - if !templ_7745c5c3_IsBuffer { 86 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 87 - } 88 - return templ_7745c5c3_Err 89 }) 90 }
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 + // templ: version: v0.3.924 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 + 11 + import "fmt" 12 13 type RepoFileContext struct { 14 BaseContext 15 RepoHeaderComponentContext 16 RepoBreadcrumbComponentContext 17 + Code string 18 + Commit string 19 + Path string 20 + } 21 + 22 + func (rfc RepoFileContext) Permalink() string { 23 + return fmt.Sprintf("/%s/tree/%s/%s", rfc.RepoBreadcrumbComponentContext.Repo, rfc.Commit, rfc.Path) 24 } 25 26 func RepoFile(rfc RepoFileContext) templ.Component { 27 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 28 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 29 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 30 + return templ_7745c5c3_CtxErr 31 + } 32 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 33 if !templ_7745c5c3_IsBuffer { 34 + defer func() { 35 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 36 + if templ_7745c5c3_Err == nil { 37 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 38 + } 39 + }() 40 } 41 ctx = templ.InitializeContext(ctx) 42 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 44 templ_7745c5c3_Var1 = templ.NopComponent 45 } 46 ctx = templ.ClearChildren(ctx) 47 + templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 48 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 49 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 50 if !templ_7745c5c3_IsBuffer { 51 + defer func() { 52 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 53 + if templ_7745c5c3_Err == nil { 54 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 55 + } 56 + }() 57 } 58 + ctx = templ.InitializeContext(ctx) 59 templ_7745c5c3_Err = repoHeaderComponent(rfc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer) 60 if templ_7745c5c3_Err != nil { 61 return templ_7745c5c3_Err 62 } 63 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"mt-2 text-text\">") 64 if templ_7745c5c3_Err != nil { 65 return templ_7745c5c3_Err 66 } ··· 71 var templ_7745c5c3_Var3 string 72 templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(" - ") 73 if templ_7745c5c3_Err != nil { 74 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 23, Col: 10} 75 } 76 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 77 if templ_7745c5c3_Err != nil { 78 return templ_7745c5c3_Err 79 } 80 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " <a class=\"text-text underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"?raw\">raw</a> ") 81 + if templ_7745c5c3_Err != nil { 82 + return templ_7745c5c3_Err 83 + } 84 + var templ_7745c5c3_Var4 string 85 + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(" - ") 86 + if templ_7745c5c3_Err != nil { 87 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 25, Col: 10} 88 + } 89 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 90 + if templ_7745c5c3_Err != nil { 91 + return templ_7745c5c3_Err 92 + } 93 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, " <a class=\"text-text underline decoration-text/50 decoration-dashed hover:decoration-solid\" id=\"permalink\" data-permalink=\"") 94 + if templ_7745c5c3_Err != nil { 95 + return templ_7745c5c3_Err 96 + } 97 + var templ_7745c5c3_Var5 string 98 + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(rfc.Permalink()) 99 + if templ_7745c5c3_Err != nil { 100 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 26, Col: 141} 101 + } 102 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 103 + if templ_7745c5c3_Err != nil { 104 + return templ_7745c5c3_Err 105 + } 106 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" href=\"") 107 + if templ_7745c5c3_Err != nil { 108 + return templ_7745c5c3_Err 109 + } 110 + var templ_7745c5c3_Var6 templ.SafeURL 111 + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(rfc.Permalink()) 112 + if templ_7745c5c3_Err != nil { 113 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 26, Col: 166} 114 + } 115 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 116 if templ_7745c5c3_Err != nil { 117 return templ_7745c5c3_Err 118 } 119 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">permalink</a><div class=\"code relative\">") 120 if templ_7745c5c3_Err != nil { 121 return templ_7745c5c3_Err 122 } 123 + templ_7745c5c3_Err = templ.Raw(rfc.Code).Render(ctx, templ_7745c5c3_Buffer) 124 if templ_7745c5c3_Err != nil { 125 return templ_7745c5c3_Err 126 } 127 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<button id=\"copy\" class=\"absolute top-0 right-0 rounded bg-base hover:bg-surface0\"></button></div></div>") 128 + if templ_7745c5c3_Err != nil { 129 + return templ_7745c5c3_Err 130 } 131 + return nil 132 }) 133 templ_7745c5c3_Err = base(rfc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 134 if templ_7745c5c3_Err != nil { 135 return templ_7745c5c3_Err 136 } 137 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<script>\n\t\tconst lineRe = /#L(\\d+)(?:-L(\\d+))?/g\n\t\tconst $lineLines = document.querySelectorAll(\".chroma .lntable .lnt\");\n\t\tconst $codeLines = document.querySelectorAll(\".chroma .lntable .line\");\n\t\tconst $copyButton = document.getElementById('copy');\n\t\tconst $permalink = document.getElementById('permalink');\n\t\tconst $copyIcon = \"๐Ÿ“‹\";\n\t\tconst $copiedIcon = \"โœ…\";\n\t\tlet $code = \"\"\n\t\tfor (let codeLine of $codeLines) $code += codeLine.innerText;\n\t\tlet start = 0;\n\t\tlet end = 0;\n\n\t\tconst results = [...location.hash.matchAll(lineRe)];\t\t\n\t\tif (0 in results) {\n\t\t\tstart = results[0][1] !== undefined ? parseInt(results[0][1]) : 0;\n\t\t\tend = results[0][2] !== undefined ? parseInt(results[0][2]) : 0;\n\t\t}\n\t\tif (start !== 0) {\n\t\t\tdeactivateLines();\n\t\t\tactivateLines(start, end);\n\t\t\tlet anchor = `#${start}`;\n if (end !== 0) anchor += `-${end}`;\n if (anchor !== \"\") $permalink.href = $permalink.dataset.permalink + anchor;\n\t\t\t$lineLines[start-1].scrollIntoView(true);\n\t\t}\n\n\t\tfor (let line of $lineLines) {\n\t\t\tline.addEventListener(\"click\", (event) => {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tdeactivateLines();\n\t\t\t\tconst n = parseInt(line.id.substring(1));\n\t\t\t\tlet anchor = \"\";\n\t\t\t\tif (event.shiftKey) {\n\t\t\t\t\tend = n;\n\t\t\t\t\tanchor = `#L${start}-L${end}`;\n\t\t\t\t} else if (start === n) {\n\t\t\t\t\tstart = 0;\n\t\t\t\t\tend = 0;\n\t\t\t\t} else {\n\t\t\t\t\tstart = n;\n\t\t\t\t\tend = 0;\n\t\t\t\t\tanchor = `#L${start}`;\n\t\t\t\t}\n\t\t\t\thistory.replaceState(null, null, window.location.pathname + anchor);\n\t\t\t\t$permalink.href = $permalink.dataset.permalink + anchor;\n\t\t\t\tif (start !== 0) activateLines(start, end);\n\t\t\t});\n\t\t}\n\n\t\tif (navigator.clipboard && navigator.clipboard.writeText) {\n\t\t\t$copyButton.innerText = $copyIcon;\n\t\t\t$copyButton.classList.remove(\"hidden\");\n }\n\t\t$copyButton.addEventListener(\"click\", () => {\n navigator.clipboard.writeText($code);\n\t\t\t$copyButton.innerText = $copiedIcon;\n\t\t\tsetTimeout(() => {\n\t\t\t\t$copyButton.innerText = $copyIcon;\n\t\t\t}, 1000);\n });\n\n\t\tfunction activateLines(start, end) {\n\t\t\tif (end < start) end = start;\n\t\t\tfor (let idx = start - 1; idx < end; idx++) {\n\t\t\t\t$codeLines[idx].classList.add(\"active\");\n\t\t\t}\n\t\t}\n\n\t\tfunction deactivateLines() {\n\t\t\tfor (let code of $codeLines) {\n\t\t\t\tcode.classList.remove(\"active\");\n\t\t\t}\n\t\t}\n\n\t\t\n\t\t\n\t</script>") 138 if templ_7745c5c3_Err != nil { 139 return templ_7745c5c3_Err 140 } 141 + return nil 142 }) 143 } 144 + 145 + var _ = templruntime.GeneratedTemplate
+3 -4
internal/html/repo_log.templ
··· 5 import "go.jolheiser.com/ugit/internal/git" 6 7 type RepoLogContext struct { 8 - BaseContext 9 - RepoHeaderComponentContext 10 - Commits []git.Commit 11 } 12 13 templ RepoLog(rlc RepoLogContext) { ··· 36 </div> 37 } 38 } 39 -
··· 5 import "go.jolheiser.com/ugit/internal/git" 6 7 type RepoLogContext struct { 8 + BaseContext 9 + RepoHeaderComponentContext 10 + Commits []git.Commit 11 } 12 13 templ RepoLog(rlc RepoLogContext) { ··· 36 </div> 37 } 38 }
+54 -38
internal/html/repo_log_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.707 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 - import "context" 10 - import "io" 11 - import "bytes" 12 13 import "fmt" 14 import "github.com/dustin/go-humanize" ··· 21 } 22 23 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) 26 if !templ_7745c5c3_IsBuffer { 27 - templ_7745c5c3_Buffer = templ.GetBuffer() 28 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 29 } 30 ctx = templ.InitializeContext(ctx) 31 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 33 templ_7745c5c3_Var1 = templ.NopComponent 34 } 35 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) 38 if !templ_7745c5c3_IsBuffer { 39 - templ_7745c5c3_Buffer = templ.GetBuffer() 40 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 41 } 42 templ_7745c5c3_Err = repoHeaderComponent(rlc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer) 43 if templ_7745c5c3_Err != nil { 44 return templ_7745c5c3_Err 45 } 46 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <div class=\"grid sm:grid-cols-8 gap-1 text-text mt-5\">") 47 if templ_7745c5c3_Err != nil { 48 return templ_7745c5c3_Err 49 } 50 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=\"") 52 if templ_7745c5c3_Err != nil { 53 return templ_7745c5c3_Err 54 } 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))) 57 if templ_7745c5c3_Err != nil { 58 return templ_7745c5c3_Err 59 } 60 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 61 if templ_7745c5c3_Err != nil { 62 return templ_7745c5c3_Err 63 } ··· 70 if templ_7745c5c3_Err != nil { 71 return templ_7745c5c3_Err 72 } 73 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div class=\"whitespace-pre\">") 74 if templ_7745c5c3_Err != nil { 75 return templ_7745c5c3_Err 76 } 77 if commit.Details() != "" { 78 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<details><summary class=\"cursor-pointer\">") 79 if templ_7745c5c3_Err != nil { 80 return templ_7745c5c3_Err 81 } ··· 88 if templ_7745c5c3_Err != nil { 89 return templ_7745c5c3_Err 90 } 91 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</summary><div class=\"p-3 bg-base rounded\">") 92 if templ_7745c5c3_Err != nil { 93 return templ_7745c5c3_Err 94 } ··· 101 if templ_7745c5c3_Err != nil { 102 return templ_7745c5c3_Err 103 } 104 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></details>") 105 if templ_7745c5c3_Err != nil { 106 return templ_7745c5c3_Err 107 } ··· 116 return templ_7745c5c3_Err 117 } 118 } 119 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div><div class=\"sm:col-span-3 mb-4\"><div>") 120 if templ_7745c5c3_Err != nil { 121 return templ_7745c5c3_Err 122 } ··· 138 if templ_7745c5c3_Err != nil { 139 return templ_7745c5c3_Err 140 } 141 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 142 if templ_7745c5c3_Err != nil { 143 return templ_7745c5c3_Err 144 } 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))) 147 if templ_7745c5c3_Err != nil { 148 return templ_7745c5c3_Err 149 } 150 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 151 if templ_7745c5c3_Err != nil { 152 return templ_7745c5c3_Err 153 } ··· 160 if templ_7745c5c3_Err != nil { 161 return templ_7745c5c3_Err 162 } 163 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div title=\"") 164 if templ_7745c5c3_Err != nil { 165 return templ_7745c5c3_Err 166 } ··· 173 if templ_7745c5c3_Err != nil { 174 return templ_7745c5c3_Err 175 } 176 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 177 if templ_7745c5c3_Err != nil { 178 return templ_7745c5c3_Err 179 } ··· 186 if templ_7745c5c3_Err != nil { 187 return templ_7745c5c3_Err 188 } 189 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div>") 190 if templ_7745c5c3_Err != nil { 191 return templ_7745c5c3_Err 192 } 193 } 194 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 195 if templ_7745c5c3_Err != nil { 196 return templ_7745c5c3_Err 197 } 198 - if !templ_7745c5c3_IsBuffer { 199 - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) 200 - } 201 - return templ_7745c5c3_Err 202 }) 203 templ_7745c5c3_Err = base(rlc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 204 if templ_7745c5c3_Err != nil { 205 return templ_7745c5c3_Err 206 } 207 - if !templ_7745c5c3_IsBuffer { 208 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 209 - } 210 - return templ_7745c5c3_Err 211 }) 212 }
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 + // templ: version: v0.3.924 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 11 import "fmt" 12 import "github.com/dustin/go-humanize" ··· 19 } 20 21 func RepoLog(rlc RepoLogContext) templ.Component { 22 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 23 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 24 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 25 + return templ_7745c5c3_CtxErr 26 + } 27 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 28 if !templ_7745c5c3_IsBuffer { 29 + defer func() { 30 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 31 + if templ_7745c5c3_Err == nil { 32 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 33 + } 34 + }() 35 } 36 ctx = templ.InitializeContext(ctx) 37 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 39 templ_7745c5c3_Var1 = templ.NopComponent 40 } 41 ctx = templ.ClearChildren(ctx) 42 + templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 43 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 44 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 45 if !templ_7745c5c3_IsBuffer { 46 + defer func() { 47 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 48 + if templ_7745c5c3_Err == nil { 49 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 50 + } 51 + }() 52 } 53 + ctx = templ.InitializeContext(ctx) 54 templ_7745c5c3_Err = repoHeaderComponent(rlc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer) 55 if templ_7745c5c3_Err != nil { 56 return templ_7745c5c3_Err 57 } 58 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"grid sm:grid-cols-8 gap-1 text-text mt-5\">") 59 if templ_7745c5c3_Err != nil { 60 return templ_7745c5c3_Err 61 } 62 for _, commit := range rlc.Commits { 63 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"sm:col-span-5\"><div><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 64 if templ_7745c5c3_Err != nil { 65 return templ_7745c5c3_Err 66 } 67 + var templ_7745c5c3_Var3 templ.SafeURL 68 + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/commit/%s", rlc.RepoHeaderComponentContext.Name, commit.SHA))) 69 + if templ_7745c5c3_Err != nil { 70 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 19, Col: 190} 71 + } 72 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 73 if templ_7745c5c3_Err != nil { 74 return templ_7745c5c3_Err 75 } 76 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">") 77 if templ_7745c5c3_Err != nil { 78 return templ_7745c5c3_Err 79 } ··· 86 if templ_7745c5c3_Err != nil { 87 return templ_7745c5c3_Err 88 } 89 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</a></div><div class=\"whitespace-pre\">") 90 if templ_7745c5c3_Err != nil { 91 return templ_7745c5c3_Err 92 } 93 if commit.Details() != "" { 94 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<details><summary class=\"cursor-pointer\">") 95 if templ_7745c5c3_Err != nil { 96 return templ_7745c5c3_Err 97 } ··· 104 if templ_7745c5c3_Err != nil { 105 return templ_7745c5c3_Err 106 } 107 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</summary><div class=\"p-3 bg-base rounded\">") 108 if templ_7745c5c3_Err != nil { 109 return templ_7745c5c3_Err 110 } ··· 117 if templ_7745c5c3_Err != nil { 118 return templ_7745c5c3_Err 119 } 120 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div></details>") 121 if templ_7745c5c3_Err != nil { 122 return templ_7745c5c3_Err 123 } ··· 132 return templ_7745c5c3_Err 133 } 134 } 135 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div></div><div class=\"sm:col-span-3 mb-4\"><div>") 136 if templ_7745c5c3_Err != nil { 137 return templ_7745c5c3_Err 138 } ··· 154 if templ_7745c5c3_Err != nil { 155 return templ_7745c5c3_Err 156 } 157 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 158 if templ_7745c5c3_Err != nil { 159 return templ_7745c5c3_Err 160 } 161 + var templ_7745c5c3_Var10 templ.SafeURL 162 + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("mailto:%s", commit.Email))) 163 + if templ_7745c5c3_Err != nil { 164 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 32, Col: 175} 165 + } 166 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) 167 if templ_7745c5c3_Err != nil { 168 return templ_7745c5c3_Err 169 } 170 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\">") 171 if templ_7745c5c3_Err != nil { 172 return templ_7745c5c3_Err 173 } ··· 180 if templ_7745c5c3_Err != nil { 181 return templ_7745c5c3_Err 182 } 183 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</a></div><div title=\"") 184 if templ_7745c5c3_Err != nil { 185 return templ_7745c5c3_Err 186 } ··· 193 if templ_7745c5c3_Err != nil { 194 return templ_7745c5c3_Err 195 } 196 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\">") 197 if templ_7745c5c3_Err != nil { 198 return templ_7745c5c3_Err 199 } ··· 206 if templ_7745c5c3_Err != nil { 207 return templ_7745c5c3_Err 208 } 209 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div></div>") 210 if templ_7745c5c3_Err != nil { 211 return templ_7745c5c3_Err 212 } 213 } 214 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</div>") 215 if templ_7745c5c3_Err != nil { 216 return templ_7745c5c3_Err 217 } 218 + return nil 219 }) 220 templ_7745c5c3_Err = base(rlc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 221 if templ_7745c5c3_Err != nil { 222 return templ_7745c5c3_Err 223 } 224 + return nil 225 }) 226 } 227 + 228 + var _ = templruntime.GeneratedTemplate
+4 -5
internal/html/repo_refs.templ
··· 4 import "go.jolheiser.com/ugit/internal/git" 5 6 type RepoRefsContext struct { 7 - BaseContext 8 - RepoHeaderComponentContext 9 - Branches []string 10 - Tags []git.Tag 11 } 12 13 templ RepoRefs(rrc RepoRefsContext) { ··· 39 } 40 } 41 } 42 -
··· 4 import "go.jolheiser.com/ugit/internal/git" 5 6 type RepoRefsContext struct { 7 + BaseContext 8 + RepoHeaderComponentContext 9 + Branches []string 10 + Tags []git.Tag 11 } 12 13 templ RepoRefs(rrc RepoRefsContext) { ··· 39 } 40 } 41 }
+73 -49
internal/html/repo_refs_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.707 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 - import "context" 10 - import "io" 11 - import "bytes" 12 13 import "fmt" 14 import "go.jolheiser.com/ugit/internal/git" ··· 21 } 22 23 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) 26 if !templ_7745c5c3_IsBuffer { 27 - templ_7745c5c3_Buffer = templ.GetBuffer() 28 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 29 } 30 ctx = templ.InitializeContext(ctx) 31 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 33 templ_7745c5c3_Var1 = templ.NopComponent 34 } 35 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) 38 if !templ_7745c5c3_IsBuffer { 39 - templ_7745c5c3_Buffer = templ.GetBuffer() 40 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 41 } 42 templ_7745c5c3_Err = repoHeaderComponent(rrc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer) 43 if templ_7745c5c3_Err != nil { 44 return templ_7745c5c3_Err 45 } 46 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 47 if templ_7745c5c3_Err != nil { 48 return templ_7745c5c3_Err 49 } 50 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\">") 52 if templ_7745c5c3_Err != nil { 53 return templ_7745c5c3_Err 54 } 55 for _, branch := range rrc.Branches { 56 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"col-span-2 sm:col-span-1 font-bold\">") 57 if templ_7745c5c3_Err != nil { 58 return templ_7745c5c3_Err 59 } ··· 66 if templ_7745c5c3_Err != nil { 67 return templ_7745c5c3_Err 68 } 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=\"") 70 if templ_7745c5c3_Err != nil { 71 return templ_7745c5c3_Err 72 } 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))) 75 if templ_7745c5c3_Err != nil { 76 return templ_7745c5c3_Err 77 } 78 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">tree</a>") 79 if templ_7745c5c3_Err != nil { 80 return templ_7745c5c3_Err 81 } ··· 88 if templ_7745c5c3_Err != nil { 89 return templ_7745c5c3_Err 90 } 91 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 92 if templ_7745c5c3_Err != nil { 93 return templ_7745c5c3_Err 94 } 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))) 97 if templ_7745c5c3_Err != nil { 98 return templ_7745c5c3_Err 99 } 100 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">log</a></div>") 101 if templ_7745c5c3_Err != nil { 102 return templ_7745c5c3_Err 103 } 104 } 105 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 106 if templ_7745c5c3_Err != nil { 107 return templ_7745c5c3_Err 108 } 109 } 110 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 111 if templ_7745c5c3_Err != nil { 112 return templ_7745c5c3_Err 113 } 114 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\">") 116 if templ_7745c5c3_Err != nil { 117 return templ_7745c5c3_Err 118 } 119 for _, tag := range rrc.Tags { 120 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"col-span-1 font-bold\">") 121 if templ_7745c5c3_Err != nil { 122 return templ_7745c5c3_Err 123 } ··· 130 if templ_7745c5c3_Err != nil { 131 return templ_7745c5c3_Err 132 } 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=\"") 134 if templ_7745c5c3_Err != nil { 135 return templ_7745c5c3_Err 136 } 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))) 139 if templ_7745c5c3_Err != nil { 140 return templ_7745c5c3_Err 141 } 142 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">tree</a>") 143 if templ_7745c5c3_Err != nil { 144 return templ_7745c5c3_Err 145 } ··· 152 if templ_7745c5c3_Err != nil { 153 return templ_7745c5c3_Err 154 } 155 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 156 if templ_7745c5c3_Err != nil { 157 return templ_7745c5c3_Err 158 } 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))) 161 if templ_7745c5c3_Err != nil { 162 return templ_7745c5c3_Err 163 } 164 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">log</a></div>") 165 if templ_7745c5c3_Err != nil { 166 return templ_7745c5c3_Err 167 } 168 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>") 170 if templ_7745c5c3_Err != nil { 171 return templ_7745c5c3_Err 172 } ··· 179 if templ_7745c5c3_Err != nil { 180 return templ_7745c5c3_Err 181 } 182 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</code></details>") 183 if templ_7745c5c3_Err != nil { 184 return templ_7745c5c3_Err 185 } 186 } 187 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 188 if templ_7745c5c3_Err != nil { 189 return templ_7745c5c3_Err 190 } 191 if tag.Annotation != "" { 192 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"col-span-8 mb-3\">") 193 if templ_7745c5c3_Err != nil { 194 return templ_7745c5c3_Err 195 } ··· 202 if templ_7745c5c3_Err != nil { 203 return templ_7745c5c3_Err 204 } 205 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 206 if templ_7745c5c3_Err != nil { 207 return templ_7745c5c3_Err 208 } 209 } 210 } 211 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 212 if templ_7745c5c3_Err != nil { 213 return templ_7745c5c3_Err 214 } 215 } 216 - if !templ_7745c5c3_IsBuffer { 217 - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) 218 - } 219 - return templ_7745c5c3_Err 220 }) 221 templ_7745c5c3_Err = base(rrc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 222 if templ_7745c5c3_Err != nil { 223 return templ_7745c5c3_Err 224 } 225 - if !templ_7745c5c3_IsBuffer { 226 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 227 - } 228 - return templ_7745c5c3_Err 229 }) 230 }
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 + // templ: version: v0.3.924 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 11 import "fmt" 12 import "go.jolheiser.com/ugit/internal/git" ··· 19 } 20 21 func RepoRefs(rrc RepoRefsContext) templ.Component { 22 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 23 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 24 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 25 + return templ_7745c5c3_CtxErr 26 + } 27 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 28 if !templ_7745c5c3_IsBuffer { 29 + defer func() { 30 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 31 + if templ_7745c5c3_Err == nil { 32 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 33 + } 34 + }() 35 } 36 ctx = templ.InitializeContext(ctx) 37 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 39 templ_7745c5c3_Var1 = templ.NopComponent 40 } 41 ctx = templ.ClearChildren(ctx) 42 + templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 43 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 44 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 45 if !templ_7745c5c3_IsBuffer { 46 + defer func() { 47 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 48 + if templ_7745c5c3_Err == nil { 49 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 50 + } 51 + }() 52 } 53 + ctx = templ.InitializeContext(ctx) 54 templ_7745c5c3_Err = repoHeaderComponent(rrc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer) 55 if templ_7745c5c3_Err != nil { 56 return templ_7745c5c3_Err 57 } 58 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ") 59 if templ_7745c5c3_Err != nil { 60 return templ_7745c5c3_Err 61 } 62 if len(rrc.Branches) > 0 { 63 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<h3 class=\"text-text text-lg mt-5\">Branches</h3><div class=\"text-text grid grid-cols-4 sm:grid-cols-8\">") 64 if templ_7745c5c3_Err != nil { 65 return templ_7745c5c3_Err 66 } 67 for _, branch := range rrc.Branches { 68 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<div class=\"col-span-2 sm:col-span-1 font-bold\">") 69 if templ_7745c5c3_Err != nil { 70 return templ_7745c5c3_Err 71 } ··· 78 if templ_7745c5c3_Err != nil { 79 return templ_7745c5c3_Err 80 } 81 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</div><div class=\"col-span-2 sm:col-span-7\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 82 if templ_7745c5c3_Err != nil { 83 return templ_7745c5c3_Err 84 } 85 + var templ_7745c5c3_Var4 templ.SafeURL 86 + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rrc.RepoHeaderComponentContext.Name, branch))) 87 + if templ_7745c5c3_Err != nil { 88 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 21, Col: 218} 89 + } 90 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 91 if templ_7745c5c3_Err != nil { 92 return templ_7745c5c3_Err 93 } 94 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">tree</a>") 95 if templ_7745c5c3_Err != nil { 96 return templ_7745c5c3_Err 97 } ··· 104 if templ_7745c5c3_Err != nil { 105 return templ_7745c5c3_Err 106 } 107 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 108 if templ_7745c5c3_Err != nil { 109 return templ_7745c5c3_Err 110 } 111 + var templ_7745c5c3_Var6 templ.SafeURL 112 + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/log/%s", rrc.RepoHeaderComponentContext.Name, branch))) 113 + if templ_7745c5c3_Err != nil { 114 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 21, Col: 409} 115 + } 116 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 117 if templ_7745c5c3_Err != nil { 118 return templ_7745c5c3_Err 119 } 120 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\">log</a></div>") 121 if templ_7745c5c3_Err != nil { 122 return templ_7745c5c3_Err 123 } 124 } 125 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div>") 126 if templ_7745c5c3_Err != nil { 127 return templ_7745c5c3_Err 128 } 129 } 130 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " ") 131 if templ_7745c5c3_Err != nil { 132 return templ_7745c5c3_Err 133 } 134 if len(rrc.Tags) > 0 { 135 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<h3 class=\"text-text text-lg mt-5\">Tags</h3><div class=\"text-text grid grid-cols-8\">") 136 if templ_7745c5c3_Err != nil { 137 return templ_7745c5c3_Err 138 } 139 for _, tag := range rrc.Tags { 140 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"col-span-1 font-bold\">") 141 if templ_7745c5c3_Err != nil { 142 return templ_7745c5c3_Err 143 } ··· 150 if templ_7745c5c3_Err != nil { 151 return templ_7745c5c3_Err 152 } 153 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div><div class=\"col-span-7\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 154 if templ_7745c5c3_Err != nil { 155 return templ_7745c5c3_Err 156 } 157 + var templ_7745c5c3_Var8 templ.SafeURL 158 + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rrc.RepoHeaderComponentContext.Name, tag.Name))) 159 + if templ_7745c5c3_Err != nil { 160 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 30, Col: 206} 161 + } 162 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) 163 if templ_7745c5c3_Err != nil { 164 return templ_7745c5c3_Err 165 } 166 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\">tree</a>") 167 if templ_7745c5c3_Err != nil { 168 return templ_7745c5c3_Err 169 } ··· 176 if templ_7745c5c3_Err != nil { 177 return templ_7745c5c3_Err 178 } 179 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 180 if templ_7745c5c3_Err != nil { 181 return templ_7745c5c3_Err 182 } 183 + var templ_7745c5c3_Var10 templ.SafeURL 184 + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/log/%s", rrc.RepoHeaderComponentContext.Name, tag.Name))) 185 + if templ_7745c5c3_Err != nil { 186 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 30, Col: 399} 187 + } 188 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) 189 if templ_7745c5c3_Err != nil { 190 return templ_7745c5c3_Err 191 } 192 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\">log</a></div>") 193 if templ_7745c5c3_Err != nil { 194 return templ_7745c5c3_Err 195 } 196 if tag.Signature != "" { 197 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<details class=\"col-span-8 whitespace-pre\"><summary class=\"cursor-pointer\">Signature</summary><code>") 198 if templ_7745c5c3_Err != nil { 199 return templ_7745c5c3_Err 200 } ··· 207 if templ_7745c5c3_Err != nil { 208 return templ_7745c5c3_Err 209 } 210 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</code></details>") 211 if templ_7745c5c3_Err != nil { 212 return templ_7745c5c3_Err 213 } 214 } 215 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, " ") 216 if templ_7745c5c3_Err != nil { 217 return templ_7745c5c3_Err 218 } 219 if tag.Annotation != "" { 220 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<div class=\"col-span-8 mb-3\">") 221 if templ_7745c5c3_Err != nil { 222 return templ_7745c5c3_Err 223 } ··· 230 if templ_7745c5c3_Err != nil { 231 return templ_7745c5c3_Err 232 } 233 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</div>") 234 if templ_7745c5c3_Err != nil { 235 return templ_7745c5c3_Err 236 } 237 } 238 } 239 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</div>") 240 if templ_7745c5c3_Err != nil { 241 return templ_7745c5c3_Err 242 } 243 } 244 + return nil 245 }) 246 templ_7745c5c3_Err = base(rrc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 247 if templ_7745c5c3_Err != nil { 248 return templ_7745c5c3_Err 249 } 250 + return nil 251 }) 252 } 253 + 254 + var _ = templruntime.GeneratedTemplate
+6 -8
internal/html/repo_search.templ
··· 11 12 func (s SearchContext) DedupeResults() [][]git.GrepResult { 13 var ( 14 - results [][]git.GrepResult 15 - currentFile string 16 - currentResults []git.GrepResult 17 ) 18 for _, result := range s.Results { 19 if result.File == currentFile { 20 - currentResults = append(currentResults, result) 21 continue 22 } 23 - if currentFile != "" { 24 - results = append(results, currentResults) 25 - } 26 currentFile = result.File 27 - currentResults = []git.GrepResult{result} 28 } 29 30 return results
··· 11 12 func (s SearchContext) DedupeResults() [][]git.GrepResult { 13 var ( 14 + results [][]git.GrepResult 15 + currentFile string 16 ) 17 + var idx int 18 for _, result := range s.Results { 19 if result.File == currentFile { 20 + results[idx-1] = append(results[idx-1], result) 21 continue 22 } 23 + results = append(results, []git.GrepResult{result}) 24 currentFile = result.File 25 + idx++ 26 } 27 28 return results
+76 -57
internal/html/repo_search_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.707 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 - import "context" 10 - import "io" 11 - import "bytes" 12 13 import "fmt" 14 import "go.jolheiser.com/ugit/internal/git" ··· 21 22 func (s SearchContext) DedupeResults() [][]git.GrepResult { 23 var ( 24 - results [][]git.GrepResult 25 - currentFile string 26 - currentResults []git.GrepResult 27 ) 28 for _, result := range s.Results { 29 if result.File == currentFile { 30 - currentResults = append(currentResults, result) 31 continue 32 } 33 - if currentFile != "" { 34 - results = append(results, currentResults) 35 - } 36 currentFile = result.File 37 - currentResults = []git.GrepResult{result} 38 } 39 40 return results 41 } 42 43 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) 46 if !templ_7745c5c3_IsBuffer { 47 - templ_7745c5c3_Buffer = templ.GetBuffer() 48 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 49 } 50 ctx = templ.InitializeContext(ctx) 51 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 53 templ_7745c5c3_Var1 = templ.NopComponent 54 } 55 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) 58 if !templ_7745c5c3_IsBuffer { 59 - templ_7745c5c3_Buffer = templ.GetBuffer() 60 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 61 } 62 templ_7745c5c3_Err = repoHeaderComponent(sc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer) 63 if templ_7745c5c3_Err != nil { 64 return templ_7745c5c3_Err ··· 69 return templ_7745c5c3_Err 70 } 71 } 72 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 73 if templ_7745c5c3_Err != nil { 74 return templ_7745c5c3_Err 75 } 76 if len(sc.DedupeResults()) == 0 { 77 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p class=\"text-text mt-5 text-lg\">No results</p>") 78 if templ_7745c5c3_Err != nil { 79 return templ_7745c5c3_Err 80 } 81 } 82 - if !templ_7745c5c3_IsBuffer { 83 - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) 84 - } 85 - return templ_7745c5c3_Err 86 }) 87 templ_7745c5c3_Err = base(sc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 88 if templ_7745c5c3_Err != nil { 89 return templ_7745c5c3_Err 90 } 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>") 92 if templ_7745c5c3_Err != nil { 93 return templ_7745c5c3_Err 94 } 95 - if !templ_7745c5c3_IsBuffer { 96 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 97 - } 98 - return templ_7745c5c3_Err 99 }) 100 } 101 102 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) 105 if !templ_7745c5c3_IsBuffer { 106 - templ_7745c5c3_Buffer = templ.GetBuffer() 107 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 108 } 109 ctx = templ.InitializeContext(ctx) 110 templ_7745c5c3_Var3 := templ.GetChildren(ctx) ··· 112 templ_7745c5c3_Var3 = templ.NopComponent 113 } 114 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=\"") 116 if templ_7745c5c3_Err != nil { 117 return templ_7745c5c3_Err 118 } 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))) 121 if templ_7745c5c3_Err != nil { 122 return templ_7745c5c3_Err 123 } 124 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 125 if templ_7745c5c3_Err != nil { 126 return templ_7745c5c3_Err 127 } 128 var templ_7745c5c3_Var5 string 129 templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(results[0].File) 130 if templ_7745c5c3_Err != nil { 131 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 50, Col: 230} 132 } 133 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 134 if templ_7745c5c3_Err != nil { 135 return templ_7745c5c3_Err 136 } 137 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div class=\"code\">") 138 if templ_7745c5c3_Err != nil { 139 return templ_7745c5c3_Err 140 } ··· 142 if templ_7745c5c3_Err != nil { 143 return templ_7745c5c3_Err 144 } 145 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 146 if templ_7745c5c3_Err != nil { 147 return templ_7745c5c3_Err 148 } 149 if len(results) > 1 { 150 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<details class=\"text-text cursor-pointer\"><summary>") 151 if templ_7745c5c3_Err != nil { 152 return templ_7745c5c3_Err 153 } 154 var templ_7745c5c3_Var6 string 155 templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d ", len(results[1:]))) 156 if templ_7745c5c3_Err != nil { 157 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 56, Col: 50} 158 } 159 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 160 if templ_7745c5c3_Err != nil { 161 return templ_7745c5c3_Err 162 } 163 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("more</summary> ") 164 if templ_7745c5c3_Err != nil { 165 return templ_7745c5c3_Err 166 } 167 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=\"") 169 if templ_7745c5c3_Err != nil { 170 return templ_7745c5c3_Err 171 } 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))) 174 if templ_7745c5c3_Err != nil { 175 return templ_7745c5c3_Err 176 } 177 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 178 if templ_7745c5c3_Err != nil { 179 return templ_7745c5c3_Err 180 } 181 var templ_7745c5c3_Var8 string 182 templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(results[0].File) 183 if templ_7745c5c3_Err != nil { 184 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 58, Col: 230} 185 } 186 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) 187 if templ_7745c5c3_Err != nil { 188 return templ_7745c5c3_Err 189 } 190 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div class=\"code ml-5\">") 191 if templ_7745c5c3_Err != nil { 192 return templ_7745c5c3_Err 193 } ··· 195 if templ_7745c5c3_Err != nil { 196 return templ_7745c5c3_Err 197 } 198 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 199 if templ_7745c5c3_Err != nil { 200 return templ_7745c5c3_Err 201 } 202 } 203 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</details>") 204 if templ_7745c5c3_Err != nil { 205 return templ_7745c5c3_Err 206 } 207 } 208 - if !templ_7745c5c3_IsBuffer { 209 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 210 - } 211 - return templ_7745c5c3_Err 212 }) 213 }
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 + // templ: version: v0.3.924 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 11 import "fmt" 12 import "go.jolheiser.com/ugit/internal/git" ··· 19 20 func (s SearchContext) DedupeResults() [][]git.GrepResult { 21 var ( 22 + results [][]git.GrepResult 23 + currentFile string 24 ) 25 + var idx int 26 for _, result := range s.Results { 27 if result.File == currentFile { 28 + results[idx-1] = append(results[idx-1], result) 29 continue 30 } 31 + results = append(results, []git.GrepResult{result}) 32 currentFile = result.File 33 + idx++ 34 } 35 36 return results 37 } 38 39 func RepoSearch(sc SearchContext) templ.Component { 40 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 41 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 42 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 43 + return templ_7745c5c3_CtxErr 44 + } 45 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 46 if !templ_7745c5c3_IsBuffer { 47 + defer func() { 48 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 49 + if templ_7745c5c3_Err == nil { 50 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 51 + } 52 + }() 53 } 54 ctx = templ.InitializeContext(ctx) 55 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 57 templ_7745c5c3_Var1 = templ.NopComponent 58 } 59 ctx = templ.ClearChildren(ctx) 60 + templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 61 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 62 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 63 if !templ_7745c5c3_IsBuffer { 64 + defer func() { 65 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 66 + if templ_7745c5c3_Err == nil { 67 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 68 + } 69 + }() 70 } 71 + ctx = templ.InitializeContext(ctx) 72 templ_7745c5c3_Err = repoHeaderComponent(sc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer) 73 if templ_7745c5c3_Err != nil { 74 return templ_7745c5c3_Err ··· 79 return templ_7745c5c3_Err 80 } 81 } 82 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ") 83 if templ_7745c5c3_Err != nil { 84 return templ_7745c5c3_Err 85 } 86 if len(sc.DedupeResults()) == 0 { 87 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<p class=\"text-text mt-5 text-lg\">No results</p>") 88 if templ_7745c5c3_Err != nil { 89 return templ_7745c5c3_Err 90 } 91 } 92 + return nil 93 }) 94 templ_7745c5c3_Err = base(sc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 95 if templ_7745c5c3_Err != nil { 96 return templ_7745c5c3_Err 97 } 98 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<script>\n\t\tconst search = new URLSearchParams(window.location.search).get(\"q\");\n\t\tif (search !== \"\") document.querySelector(\"#search\").value = search;\n\t</script>") 99 if templ_7745c5c3_Err != nil { 100 return templ_7745c5c3_Err 101 } 102 + return nil 103 }) 104 } 105 106 func repoSearchResult(repo, ref string, results []git.GrepResult) templ.Component { 107 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 108 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 109 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 110 + return templ_7745c5c3_CtxErr 111 + } 112 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 113 if !templ_7745c5c3_IsBuffer { 114 + defer func() { 115 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 116 + if templ_7745c5c3_Err == nil { 117 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 118 + } 119 + }() 120 } 121 ctx = templ.InitializeContext(ctx) 122 templ_7745c5c3_Var3 := templ.GetChildren(ctx) ··· 124 templ_7745c5c3_Var3 = templ.NopComponent 125 } 126 ctx = templ.ClearChildren(ctx) 127 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div class=\"text-text mt-5\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 128 if templ_7745c5c3_Err != nil { 129 return templ_7745c5c3_Err 130 } 131 + var templ_7745c5c3_Var4 templ.SafeURL 132 + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, results[0].File, results[0].Line))) 133 + if templ_7745c5c3_Err != nil { 134 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 48, Col: 210} 135 + } 136 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 137 if templ_7745c5c3_Err != nil { 138 return templ_7745c5c3_Err 139 } 140 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">") 141 if templ_7745c5c3_Err != nil { 142 return templ_7745c5c3_Err 143 } 144 var templ_7745c5c3_Var5 string 145 templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(results[0].File) 146 if templ_7745c5c3_Err != nil { 147 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 48, Col: 230} 148 } 149 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 150 if templ_7745c5c3_Err != nil { 151 return templ_7745c5c3_Err 152 } 153 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</a></div><div class=\"code\">") 154 if templ_7745c5c3_Err != nil { 155 return templ_7745c5c3_Err 156 } ··· 158 if templ_7745c5c3_Err != nil { 159 return templ_7745c5c3_Err 160 } 161 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div>") 162 if templ_7745c5c3_Err != nil { 163 return templ_7745c5c3_Err 164 } 165 if len(results) > 1 { 166 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<details class=\"text-text cursor-pointer\"><summary>") 167 if templ_7745c5c3_Err != nil { 168 return templ_7745c5c3_Err 169 } 170 var templ_7745c5c3_Var6 string 171 templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d ", len(results[1:]))) 172 if templ_7745c5c3_Err != nil { 173 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 54, Col: 50} 174 } 175 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 176 if templ_7745c5c3_Err != nil { 177 return templ_7745c5c3_Err 178 } 179 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "more</summary> ") 180 if templ_7745c5c3_Err != nil { 181 return templ_7745c5c3_Err 182 } 183 for _, result := range results[1:] { 184 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<div class=\"text-text mt-5 ml-5\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 185 if templ_7745c5c3_Err != nil { 186 return templ_7745c5c3_Err 187 } 188 + var templ_7745c5c3_Var7 templ.SafeURL 189 + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, result.File, result.Line))) 190 + if templ_7745c5c3_Err != nil { 191 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 56, Col: 210} 192 + } 193 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 194 if templ_7745c5c3_Err != nil { 195 return templ_7745c5c3_Err 196 } 197 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\">") 198 if templ_7745c5c3_Err != nil { 199 return templ_7745c5c3_Err 200 } 201 var templ_7745c5c3_Var8 string 202 templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(results[0].File) 203 if templ_7745c5c3_Err != nil { 204 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 56, Col: 230} 205 } 206 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) 207 if templ_7745c5c3_Err != nil { 208 return templ_7745c5c3_Err 209 } 210 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</a></div><div class=\"code ml-5\">") 211 if templ_7745c5c3_Err != nil { 212 return templ_7745c5c3_Err 213 } ··· 215 if templ_7745c5c3_Err != nil { 216 return templ_7745c5c3_Err 217 } 218 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div>") 219 if templ_7745c5c3_Err != nil { 220 return templ_7745c5c3_Err 221 } 222 } 223 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</details>") 224 if templ_7745c5c3_Err != nil { 225 return templ_7745c5c3_Err 226 } 227 } 228 + return nil 229 }) 230 } 231 + 232 + var _ = templruntime.GeneratedTemplate
+65 -40
internal/html/repo_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.707 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 - import "context" 10 - import "io" 11 - import "bytes" 12 13 import "fmt" 14 ··· 21 } 22 23 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) 26 if !templ_7745c5c3_IsBuffer { 27 - templ_7745c5c3_Buffer = templ.GetBuffer() 28 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 29 } 30 ctx = templ.InitializeContext(ctx) 31 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 33 templ_7745c5c3_Var1 = templ.NopComponent 34 } 35 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=\"") 37 if templ_7745c5c3_Err != nil { 38 return templ_7745c5c3_Err 39 } 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))) 42 if templ_7745c5c3_Err != nil { 43 return templ_7745c5c3_Err 44 } 45 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 46 if templ_7745c5c3_Err != nil { 47 return templ_7745c5c3_Err 48 } ··· 55 if templ_7745c5c3_Err != nil { 56 return templ_7745c5c3_Err 57 } 58 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a> ") 59 if templ_7745c5c3_Err != nil { 60 return templ_7745c5c3_Err 61 } ··· 69 if templ_7745c5c3_Err != nil { 70 return templ_7745c5c3_Err 71 } 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=\"") 73 if templ_7745c5c3_Err != nil { 74 return templ_7745c5c3_Err 75 } 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))) 78 if templ_7745c5c3_Err != nil { 79 return templ_7745c5c3_Err 80 } 81 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 82 if templ_7745c5c3_Err != nil { 83 return templ_7745c5c3_Err 84 } ··· 91 if templ_7745c5c3_Err != nil { 92 return templ_7745c5c3_Err 93 } 94 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a> ") 95 if templ_7745c5c3_Err != nil { 96 return templ_7745c5c3_Err 97 } ··· 105 if templ_7745c5c3_Err != nil { 106 return templ_7745c5c3_Err 107 } 108 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 109 if templ_7745c5c3_Err != nil { 110 return templ_7745c5c3_Err 111 } 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))) 114 if templ_7745c5c3_Err != nil { 115 return templ_7745c5c3_Err 116 } 117 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">refs</a> ") 118 if templ_7745c5c3_Err != nil { 119 return templ_7745c5c3_Err 120 } ··· 127 if templ_7745c5c3_Err != nil { 128 return templ_7745c5c3_Err 129 } 130 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 131 if templ_7745c5c3_Err != nil { 132 return templ_7745c5c3_Err 133 } 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))) 136 if templ_7745c5c3_Err != nil { 137 return templ_7745c5c3_Err 138 } 139 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">log</a> ") 140 if templ_7745c5c3_Err != nil { 141 return templ_7745c5c3_Err 142 } ··· 149 if templ_7745c5c3_Err != nil { 150 return templ_7745c5c3_Err 151 } 152 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<form class=\"inline-block\" action=\"") 153 if templ_7745c5c3_Err != nil { 154 return templ_7745c5c3_Err 155 } 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))) 158 if templ_7745c5c3_Err != nil { 159 return templ_7745c5c3_Err 160 } 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>") 162 if templ_7745c5c3_Err != nil { 163 return templ_7745c5c3_Err 164 } ··· 171 if templ_7745c5c3_Err != nil { 172 return templ_7745c5c3_Err 173 } 174 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<pre class=\"text-text inline select-all bg-base dark:bg-base/50 p-1 rounded\">") 175 if templ_7745c5c3_Err != nil { 176 return templ_7745c5c3_Err 177 } ··· 184 if templ_7745c5c3_Err != nil { 185 return templ_7745c5c3_Err 186 } 187 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</pre></div><div class=\"text-subtext0 mb-1\">") 188 if templ_7745c5c3_Err != nil { 189 return templ_7745c5c3_Err 190 } 191 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\">") 193 if templ_7745c5c3_Err != nil { 194 return templ_7745c5c3_Err 195 } ··· 202 if templ_7745c5c3_Err != nil { 203 return templ_7745c5c3_Err 204 } 205 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span>") 206 if templ_7745c5c3_Err != nil { 207 return templ_7745c5c3_Err 208 } 209 } 210 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"text-text/80 mb-1\">") 211 if templ_7745c5c3_Err != nil { 212 return templ_7745c5c3_Err 213 } ··· 220 if templ_7745c5c3_Err != nil { 221 return templ_7745c5c3_Err 222 } 223 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 224 if templ_7745c5c3_Err != nil { 225 return templ_7745c5c3_Err 226 } 227 - if !templ_7745c5c3_IsBuffer { 228 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 229 - } 230 - return templ_7745c5c3_Err 231 }) 232 }
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 + // templ: version: v0.3.924 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 11 import "fmt" 12 ··· 19 } 20 21 func repoHeaderComponent(rhcc RepoHeaderComponentContext) templ.Component { 22 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 23 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 24 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 25 + return templ_7745c5c3_CtxErr 26 + } 27 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 28 if !templ_7745c5c3_IsBuffer { 29 + defer func() { 30 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 31 + if templ_7745c5c3_Err == nil { 32 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 33 + } 34 + }() 35 } 36 ctx = templ.InitializeContext(ctx) 37 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 39 templ_7745c5c3_Var1 = templ.NopComponent 40 } 41 ctx = templ.ClearChildren(ctx) 42 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"mb-1 text-text\"><a class=\"text-lg underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 43 if templ_7745c5c3_Err != nil { 44 return templ_7745c5c3_Err 45 } 46 + var templ_7745c5c3_Var2 templ.SafeURL 47 + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL("/" + rhcc.Name)) 48 + if templ_7745c5c3_Err != nil { 49 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 15, Col: 128} 50 + } 51 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) 52 if templ_7745c5c3_Err != nil { 53 return templ_7745c5c3_Err 54 } 55 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\">") 56 if templ_7745c5c3_Err != nil { 57 return templ_7745c5c3_Err 58 } ··· 65 if templ_7745c5c3_Err != nil { 66 return templ_7745c5c3_Err 67 } 68 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</a> ") 69 if templ_7745c5c3_Err != nil { 70 return templ_7745c5c3_Err 71 } ··· 79 if templ_7745c5c3_Err != nil { 80 return templ_7745c5c3_Err 81 } 82 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " <a class=\"text-text/80 text-sm underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 83 if templ_7745c5c3_Err != nil { 84 return templ_7745c5c3_Err 85 } 86 + var templ_7745c5c3_Var5 templ.SafeURL 87 + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rhcc.Name, rhcc.Ref))) 88 + if templ_7745c5c3_Err != nil { 89 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 18, Col: 175} 90 + } 91 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 92 if templ_7745c5c3_Err != nil { 93 return templ_7745c5c3_Err 94 } 95 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">") 96 if templ_7745c5c3_Err != nil { 97 return templ_7745c5c3_Err 98 } ··· 105 if templ_7745c5c3_Err != nil { 106 return templ_7745c5c3_Err 107 } 108 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</a> ") 109 if templ_7745c5c3_Err != nil { 110 return templ_7745c5c3_Err 111 } ··· 119 if templ_7745c5c3_Err != nil { 120 return templ_7745c5c3_Err 121 } 122 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, " <a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 123 if templ_7745c5c3_Err != nil { 124 return templ_7745c5c3_Err 125 } 126 + var templ_7745c5c3_Var8 templ.SafeURL 127 + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/refs", rhcc.Name))) 128 + if templ_7745c5c3_Err != nil { 129 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 21, Col: 139} 130 + } 131 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) 132 if templ_7745c5c3_Err != nil { 133 return templ_7745c5c3_Err 134 } 135 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\">refs</a> ") 136 if templ_7745c5c3_Err != nil { 137 return templ_7745c5c3_Err 138 } ··· 145 if templ_7745c5c3_Err != nil { 146 return templ_7745c5c3_Err 147 } 148 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " <a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 149 if templ_7745c5c3_Err != nil { 150 return templ_7745c5c3_Err 151 } 152 + var templ_7745c5c3_Var10 templ.SafeURL 153 + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/log/%s", rhcc.Name, rhcc.Ref))) 154 + if templ_7745c5c3_Err != nil { 155 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 23, Col: 151} 156 + } 157 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) 158 if templ_7745c5c3_Err != nil { 159 return templ_7745c5c3_Err 160 } 161 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\">log</a> ") 162 if templ_7745c5c3_Err != nil { 163 return templ_7745c5c3_Err 164 } ··· 171 if templ_7745c5c3_Err != nil { 172 return templ_7745c5c3_Err 173 } 174 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<form class=\"inline-block\" action=\"") 175 if templ_7745c5c3_Err != nil { 176 return templ_7745c5c3_Err 177 } 178 + var templ_7745c5c3_Var12 templ.SafeURL 179 + templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/search", rhcc.Name))) 180 + if templ_7745c5c3_Err != nil { 181 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 25, Col: 89} 182 + } 183 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) 184 if templ_7745c5c3_Err != nil { 185 return templ_7745c5c3_Err 186 } 187 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\" method=\"get\"><input class=\"rounded p-1 bg-mantle focus:border-lavender focus:outline-none focus:ring-0\" id=\"search\" type=\"text\" name=\"q\" placeholder=\"search\"></form>") 188 if templ_7745c5c3_Err != nil { 189 return templ_7745c5c3_Err 190 } ··· 197 if templ_7745c5c3_Err != nil { 198 return templ_7745c5c3_Err 199 } 200 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<pre class=\"text-text inline select-all bg-base dark:bg-base/50 p-1 rounded\">") 201 if templ_7745c5c3_Err != nil { 202 return templ_7745c5c3_Err 203 } ··· 210 if templ_7745c5c3_Err != nil { 211 return templ_7745c5c3_Err 212 } 213 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</pre></div><div class=\"text-subtext0 mb-1\">") 214 if templ_7745c5c3_Err != nil { 215 return templ_7745c5c3_Err 216 } 217 for _, tag := range rhcc.Tags { 218 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<span class=\"rounded border-rosewater border-solid border pb-0.5 px-1 mr-1 mb-1 inline-block\">") 219 if templ_7745c5c3_Err != nil { 220 return templ_7745c5c3_Err 221 } ··· 228 if templ_7745c5c3_Err != nil { 229 return templ_7745c5c3_Err 230 } 231 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</span>") 232 if templ_7745c5c3_Err != nil { 233 return templ_7745c5c3_Err 234 } 235 } 236 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</div><div class=\"text-text/80 mb-1\">") 237 if templ_7745c5c3_Err != nil { 238 return templ_7745c5c3_Err 239 } ··· 246 if templ_7745c5c3_Err != nil { 247 return templ_7745c5c3_Err 248 } 249 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</div>") 250 if templ_7745c5c3_Err != nil { 251 return templ_7745c5c3_Err 252 } 253 + return nil 254 }) 255 } 256 + 257 + var _ = templruntime.GeneratedTemplate
+65 -44
internal/html/repo_tree_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.707 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 - import "context" 10 - import "io" 11 - import "bytes" 12 13 import ( 14 "fmt" ··· 25 } 26 27 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) 30 if !templ_7745c5c3_IsBuffer { 31 - templ_7745c5c3_Buffer = templ.GetBuffer() 32 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 33 } 34 ctx = templ.InitializeContext(ctx) 35 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 37 templ_7745c5c3_Var1 = templ.NopComponent 38 } 39 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) 42 if !templ_7745c5c3_IsBuffer { 43 - templ_7745c5c3_Buffer = templ.GetBuffer() 44 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 45 } 46 templ_7745c5c3_Err = repoHeaderComponent(rtc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer) 47 if templ_7745c5c3_Err != nil { 48 return templ_7745c5c3_Err 49 } 50 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 51 if templ_7745c5c3_Err != nil { 52 return templ_7745c5c3_Err 53 } ··· 55 if templ_7745c5c3_Err != nil { 56 return templ_7745c5c3_Err 57 } 58 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 59 if templ_7745c5c3_Err != nil { 60 return templ_7745c5c3_Err 61 } ··· 63 if templ_7745c5c3_Err != nil { 64 return templ_7745c5c3_Err 65 } 66 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 67 if templ_7745c5c3_Err != nil { 68 return templ_7745c5c3_Err 69 } ··· 71 if templ_7745c5c3_Err != nil { 72 return templ_7745c5c3_Err 73 } 74 - if !templ_7745c5c3_IsBuffer { 75 - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) 76 - } 77 - return templ_7745c5c3_Err 78 }) 79 templ_7745c5c3_Err = base(rtc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 80 if templ_7745c5c3_Err != nil { 81 return templ_7745c5c3_Err 82 } 83 - if !templ_7745c5c3_IsBuffer { 84 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 85 - } 86 - return templ_7745c5c3_Err 87 }) 88 } 89 ··· 102 } 103 104 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) 107 if !templ_7745c5c3_IsBuffer { 108 - templ_7745c5c3_Buffer = templ.GetBuffer() 109 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 110 } 111 ctx = templ.InitializeContext(ctx) 112 templ_7745c5c3_Var3 := templ.GetChildren(ctx) ··· 114 templ_7745c5c3_Var3 = templ.NopComponent 115 } 116 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\">") 118 if templ_7745c5c3_Err != nil { 119 return templ_7745c5c3_Err 120 } 121 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=\"") 123 if templ_7745c5c3_Err != nil { 124 return templ_7745c5c3_Err 125 } 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))) 128 if templ_7745c5c3_Err != nil { 129 return templ_7745c5c3_Err 130 } 131 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">..</a></div>") 132 if templ_7745c5c3_Err != nil { 133 return templ_7745c5c3_Err 134 } 135 } 136 for _, fi := range rtcc.Tree { 137 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"sm:col-span-1 break-keep\">") 138 if templ_7745c5c3_Err != nil { 139 return templ_7745c5c3_Err 140 } ··· 147 if templ_7745c5c3_Err != nil { 148 return templ_7745c5c3_Err 149 } 150 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"sm:col-span-1 text-right\">") 151 if templ_7745c5c3_Err != nil { 152 return templ_7745c5c3_Err 153 } ··· 160 if templ_7745c5c3_Err != nil { 161 return templ_7745c5c3_Err 162 } 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=\"") 164 if templ_7745c5c3_Err != nil { 165 return templ_7745c5c3_Err 166 } 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))) 169 if templ_7745c5c3_Err != nil { 170 return templ_7745c5c3_Err 171 } 172 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 173 if templ_7745c5c3_Err != nil { 174 return templ_7745c5c3_Err 175 } ··· 182 if templ_7745c5c3_Err != nil { 183 return templ_7745c5c3_Err 184 } 185 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div>") 186 if templ_7745c5c3_Err != nil { 187 return templ_7745c5c3_Err 188 } 189 } 190 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 191 if templ_7745c5c3_Err != nil { 192 return templ_7745c5c3_Err 193 } 194 - if !templ_7745c5c3_IsBuffer { 195 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 196 - } 197 - return templ_7745c5c3_Err 198 }) 199 }
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 + // templ: version: v0.3.924 4 package html 5 6 //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 8 import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 11 import ( 12 "fmt" ··· 23 } 24 25 func RepoTree(rtc RepoTreeContext) templ.Component { 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) 32 if !templ_7745c5c3_IsBuffer { 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 + }() 39 } 40 ctx = templ.InitializeContext(ctx) 41 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 43 templ_7745c5c3_Var1 = templ.NopComponent 44 } 45 ctx = templ.ClearChildren(ctx) 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) 49 if !templ_7745c5c3_IsBuffer { 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 + }() 56 } 57 + ctx = templ.InitializeContext(ctx) 58 templ_7745c5c3_Err = repoHeaderComponent(rtc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer) 59 if templ_7745c5c3_Err != nil { 60 return templ_7745c5c3_Err 61 } 62 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ") 63 if templ_7745c5c3_Err != nil { 64 return templ_7745c5c3_Err 65 } ··· 67 if templ_7745c5c3_Err != nil { 68 return templ_7745c5c3_Err 69 } 70 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " ") 71 if templ_7745c5c3_Err != nil { 72 return templ_7745c5c3_Err 73 } ··· 75 if templ_7745c5c3_Err != nil { 76 return templ_7745c5c3_Err 77 } 78 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, " ") 79 if templ_7745c5c3_Err != nil { 80 return templ_7745c5c3_Err 81 } ··· 83 if templ_7745c5c3_Err != nil { 84 return templ_7745c5c3_Err 85 } 86 + return nil 87 }) 88 templ_7745c5c3_Err = base(rtc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 89 if templ_7745c5c3_Err != nil { 90 return templ_7745c5c3_Err 91 } 92 + return nil 93 }) 94 } 95 ··· 108 } 109 110 func repoTreeComponent(rtcc RepoTreeComponentContext) templ.Component { 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) 117 if !templ_7745c5c3_IsBuffer { 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 + }() 124 } 125 ctx = templ.InitializeContext(ctx) 126 templ_7745c5c3_Var3 := templ.GetChildren(ctx) ··· 128 templ_7745c5c3_Var3 = templ.NopComponent 129 } 130 ctx = templ.ClearChildren(ctx) 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\">") 132 if templ_7745c5c3_Err != nil { 133 return templ_7745c5c3_Err 134 } 135 if rtcc.Back != "" { 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=\"") 137 if templ_7745c5c3_Err != nil { 138 return templ_7745c5c3_Err 139 } 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)) 146 if templ_7745c5c3_Err != nil { 147 return templ_7745c5c3_Err 148 } 149 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">..</a></div>") 150 if templ_7745c5c3_Err != nil { 151 return templ_7745c5c3_Err 152 } 153 } 154 for _, fi := range rtcc.Tree { 155 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<div class=\"sm:col-span-1 break-keep\">") 156 if templ_7745c5c3_Err != nil { 157 return templ_7745c5c3_Err 158 } ··· 165 if templ_7745c5c3_Err != nil { 166 return templ_7745c5c3_Err 167 } 168 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div><div class=\"sm:col-span-1 text-right\">") 169 if templ_7745c5c3_Err != nil { 170 return templ_7745c5c3_Err 171 } ··· 178 if templ_7745c5c3_Err != nil { 179 return templ_7745c5c3_Err 180 } 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=\"") 182 if templ_7745c5c3_Err != nil { 183 return templ_7745c5c3_Err 184 } 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)) 191 if templ_7745c5c3_Err != nil { 192 return templ_7745c5c3_Err 193 } 194 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\">") 195 if templ_7745c5c3_Err != nil { 196 return templ_7745c5c3_Err 197 } ··· 204 if templ_7745c5c3_Err != nil { 205 return templ_7745c5c3_Err 206 } 207 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</a></div>") 208 if templ_7745c5c3_Err != nil { 209 return templ_7745c5c3_Err 210 } 211 } 212 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div>") 213 if templ_7745c5c3_Err != nil { 214 return templ_7745c5c3_Err 215 } 216 + return nil 217 }) 218 } 219 + 220 + var _ = templruntime.GeneratedTemplate
+1 -1
internal/html/tailwind.config.js
··· 1 /** @type {import('tailwindcss').Config} */ 2 module.exports = { 3 - content: ["./**/*.templ"], 4 plugins: [require("@catppuccin/tailwindcss")], 5 } 6
··· 1 /** @type {import('tailwindcss').Config} */ 2 module.exports = { 3 + content: ["./*.go"], 4 plugins: [require("@catppuccin/tailwindcss")], 5 } 6
+1 -1
internal/html/tailwind.go
··· 5 6 func TailwindHandler(w http.ResponseWriter, r *http.Request) { 7 w.Header().Set("Content-Type", "text/css") 8 - w.Write([]byte("/*! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:\"\"}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}.latte{--ctp-rosewater:220,138,120;--ctp-flamingo:221,120,120;--ctp-pink:234,118,203;--ctp-mauve:136,57,239;--ctp-red:210,15,57;--ctp-maroon:230,69,83;--ctp-peach:254,100,11;--ctp-yellow:223,142,29;--ctp-green:64,160,43;--ctp-teal:23,146,153;--ctp-sky:4,165,229;--ctp-sapphire:32,159,181;--ctp-blue:30,102,245;--ctp-lavender:114,135,253;--ctp-text:76,79,105;--ctp-subtext1:92,95,119;--ctp-subtext0:108,111,133;--ctp-overlay2:124,127,147;--ctp-overlay1:140,143,161;--ctp-overlay0:156,160,176;--ctp-surface2:172,176,190;--ctp-surface1:188,192,204;--ctp-surface0:204,208,218;--ctp-base:239,241,245;--ctp-mantle:230,233,239;--ctp-crust:220,224,232}*,::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))}}")) 9 }
··· 5 6 func TailwindHandler(w http.ResponseWriter, r *http.Request) { 7 w.Header().Set("Content-Type", "text/css") 8 + w.Write([]byte("/*! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:\"\"}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}.latte{--ctp-rosewater:220,138,120;--ctp-flamingo:221,120,120;--ctp-pink:234,118,203;--ctp-mauve:136,57,239;--ctp-red:210,15,57;--ctp-maroon:230,69,83;--ctp-peach:254,100,11;--ctp-yellow:223,142,29;--ctp-green:64,160,43;--ctp-teal:23,146,153;--ctp-sky:4,165,229;--ctp-sapphire:32,159,181;--ctp-blue:30,102,245;--ctp-lavender:114,135,253;--ctp-text:76,79,105;--ctp-subtext1:92,95,119;--ctp-subtext0:108,111,133;--ctp-overlay2:124,127,147;--ctp-overlay1:140,143,161;--ctp-overlay0:156,160,176;--ctp-surface2:172,176,190;--ctp-surface1:188,192,204;--ctp-surface0:204,208,218;--ctp-base:239,241,245;--ctp-mantle:230,233,239;--ctp-crust:220,224,232}.mocha{--ctp-rosewater:245,224,220;--ctp-flamingo:242,205,205;--ctp-pink:245,194,231;--ctp-mauve:203,166,247;--ctp-red:243,139,168;--ctp-maroon:235,160,172;--ctp-peach:250,179,135;--ctp-yellow:249,226,175;--ctp-green:166,227,161;--ctp-teal:148,226,213;--ctp-sky:137,220,235;--ctp-sapphire:116,199,236;--ctp-blue:137,180,250;--ctp-lavender:180,190,254;--ctp-text:205,214,244;--ctp-subtext1:186,194,222;--ctp-subtext0:166,173,200;--ctp-overlay2:147,153,178;--ctp-overlay1:127,132,156;--ctp-overlay0:108,112,134;--ctp-surface2:88,91,112;--ctp-surface1:69,71,90;--ctp-surface0:49,50,68;--ctp-base:30,30,46;--ctp-mantle:24,24,37;--ctp-crust:17,17,27}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.absolute{position:absolute}.relative{position:relative}.right-0{right:0}.start-1{inset-inline-start:.25rem}.top-0{top:0}.col-span-1{grid-column:span 1/span 1}.col-span-2{grid-column:span 2/span 2}.col-span-7{grid-column:span 7/span 7}.col-span-8{grid-column:span 8/span 8}.mx-5{margin-left:1.25rem;margin-right:1.25rem}.my-10{margin-top:2.5rem;margin-bottom:2.5rem}.mb-1{margin-bottom:.25rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-5{margin-left:1.25rem}.mr-1{margin-right:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-5{margin-top:1.25rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.grid{display:grid}.hidden{display:none}.h-5{height:1.25rem}.w-5{width:1.25rem}.max-w-7xl{max-width:80rem}.cursor-pointer{cursor:pointer}.select-all{-webkit-user-select:all;-moz-user-select:all;user-select:all}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-8{grid-template-columns:repeat(8,minmax(0,1fr))}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-y-1{row-gap:.25rem}.overflow-hidden{overflow:hidden}.text-ellipsis{text-overflow:ellipsis}.whitespace-pre{white-space:pre}.break-keep{word-break:keep-all}.rounded{border-radius:.25rem}.border{border-width:1px}.border-solid{border-style:solid}.border-rosewater{--tw-border-opacity:1;border-color:rgba(var(--ctp-rosewater),var(--tw-border-opacity))}.bg-base{--tw-bg-opacity:1;background-color:rgba(var(--ctp-base),var(--tw-bg-opacity))}.bg-base\\/50{background-color:rgba(var(--ctp-base),.5)}.bg-mantle{--tw-bg-opacity:1;background-color:rgba(var(--ctp-mantle),var(--tw-bg-opacity))}.stroke-mauve{stroke:rgb(var(--ctp-mauve))}.p-1{padding:.25rem}.p-3{padding:.75rem}.p-5{padding:1.25rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pb-0{padding-bottom:0}.pb-0\\.5{padding-bottom:.125rem}.text-right{text-align:right}.align-middle{vertical-align:middle}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-bold{font-weight:700}.text-blue{--tw-text-opacity:1;color:rgba(var(--ctp-blue),var(--tw-text-opacity))}.text-mauve{--tw-text-opacity:1;color:rgba(var(--ctp-mauve),var(--tw-text-opacity))}.text-subtext0{--tw-text-opacity:1;color:rgba(var(--ctp-subtext0),var(--tw-text-opacity))}.text-subtext1{--tw-text-opacity:1;color:rgba(var(--ctp-subtext1),var(--tw-text-opacity))}.text-text{--tw-text-opacity:1;color:rgba(var(--ctp-text),var(--tw-text-opacity))}.text-text\\/80{color:rgba(var(--ctp-text),.8)}.underline{text-decoration-line:underline}.decoration-blue\\/50{text-decoration-color:rgba(var(--ctp-blue),.5)}.decoration-mauve\\/50{text-decoration-color:rgba(var(--ctp-mauve),.5)}.decoration-text\\/50{text-decoration-color:rgba(var(--ctp-text),.5)}.decoration-dashed{text-decoration-style:dashed}.markdown *{all:revert-layer;color:rgb(var(--ctp-text))}.markdown code,.markdown pre{background-color:rgb(var(--ctp-base))}.markdown a{color:rgb(var(--ctp-blue));text-decoration-line:underline;text-decoration-style:dashed}.markdown a:hover{text-decoration-style:solid}.markdown .chroma{border-radius:.25rem;padding:.75rem}.chroma *{background-color:rgb(var(--ctp-base))!important}.chroma table{border-spacing:5px 0!important}.chroma .lnt{color:rgb(var(--ctp-subtext1))!important}.chroma .lnt:focus,.chroma .lnt:target{color:rgb(var(--ctp-subtext0))!important}.chroma .line.active,.chroma .line.active *{background:rgb(var(--ctp-surface0))!important}.code>.chroma{overflow:scroll;border-radius:.25rem;padding:.75rem;font-size:.875rem;line-height:1.25rem}.bg,.chroma{color:#4c4f69;background-color:#eff1f5}.chroma .lntd:last-child{width:100%}.chroma .ln:target,.chroma .lnt:target{color:#4c4f69;background-color:#bcc0cc}.chroma .err{color:#d20f39}.chroma .lnlinks{outline:none;text-decoration:none;color:inherit}.chroma .lntd{vertical-align:top;padding:0;margin:0;border:0}.chroma .lntable{border-spacing:0;padding:0;margin:0;border:0}.chroma .hl{background-color:#bcc0cc}.chroma .ln,.chroma .lnt{white-space:pre;-webkit-user-select:none;-moz-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#8c8fa1}.chroma .line{display:flex}.chroma .k{color:#8839ef}.chroma .kc{color:#fe640b}.chroma .kd{color:#d20f39}.chroma .kn{color:#179299}.chroma .kp,.chroma .kr{color:#8839ef}.chroma .kt{color:#d20f39}.chroma .na{color:#1e66f5}.chroma .bp,.chroma .nb{color:#04a5e5}.chroma .nc,.chroma .no{color:#df8e1d}.chroma .nd{color:#1e66f5;font-weight:700}.chroma .ni{color:#179299}.chroma .ne{color:#fe640b}.chroma .fm,.chroma .nf{color:#1e66f5}.chroma .nl{color:#04a5e5}.chroma .nn,.chroma .py{color:#fe640b}.chroma .nt{color:#8839ef}.chroma .nv,.chroma .vc,.chroma .vg,.chroma .vi,.chroma .vm{color:#dc8a78}.chroma .s{color:#40a02b}.chroma .sa{color:#d20f39}.chroma .sb,.chroma .sc{color:#40a02b}.chroma .dl{color:#1e66f5}.chroma .sd{color:#9ca0b0}.chroma .s2{color:#40a02b}.chroma .se{color:#1e66f5}.chroma .sh{color:#9ca0b0}.chroma .si,.chroma .sx{color:#40a02b}.chroma .sr{color:#179299}.chroma .s1,.chroma .ss{color:#40a02b}.chroma .il,.chroma .m,.chroma .mb,.chroma .mf,.chroma .mh,.chroma .mi,.chroma .mo{color:#fe640b}.chroma .o,.chroma .ow{color:#04a5e5;font-weight:700}.chroma .c,.chroma .c1,.chroma .ch,.chroma .cm,.chroma .cp,.chroma .cpf,.chroma .cs{color:#9ca0b0;font-style:italic}.chroma .cpf{font-weight:700}.chroma .gd{color:#d20f39;background-color:#ccd0da}.chroma .ge{font-style:italic}.chroma .gr{color:#d20f39}.chroma .gh{color:#fe640b;font-weight:700}.chroma .gi{color:#40a02b;background-color:#ccd0da}.chroma .gs,.chroma .gu{font-weight:700}.chroma .gu{color:#fe640b}.chroma .gt{color:#d20f39}.chroma .gl{text-decoration:underline}@media (prefers-color-scheme:dark){.bg,.chroma{color:#cdd6f4;background-color:#1e1e2e}.chroma .lntd:last-child{width:100%}.chroma .ln:target,.chroma .lnt:target{color:#cdd6f4;background-color:#45475a}.chroma .err{color:#f38ba8}.chroma .lnlinks{outline:none;text-decoration:none;color:inherit}.chroma .lntd{vertical-align:top;padding:0;margin:0;border:0}.chroma .lntable{border-spacing:0;padding:0;margin:0;border:0}.chroma .hl{background-color:#45475a}.chroma .ln,.chroma .lnt{white-space:pre;-webkit-user-select:none;-moz-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#7f849c}.chroma .line{display:flex}.chroma .k{color:#cba6f7}.chroma .kc{color:#fab387}.chroma .kd{color:#f38ba8}.chroma .kn{color:#94e2d5}.chroma .kp,.chroma .kr{color:#cba6f7}.chroma .kt{color:#f38ba8}.chroma .na{color:#89b4fa}.chroma .bp,.chroma .nb{color:#89dceb}.chroma .nc,.chroma .no{color:#f9e2af}.chroma .nd{color:#89b4fa;font-weight:700}.chroma .ni{color:#94e2d5}.chroma .ne{color:#fab387}.chroma .fm,.chroma .nf{color:#89b4fa}.chroma .nl{color:#89dceb}.chroma .nn,.chroma .py{color:#fab387}.chroma .nt{color:#cba6f7}.chroma .nv,.chroma .vc,.chroma .vg,.chroma .vi,.chroma .vm{color:#f5e0dc}.chroma .s{color:#a6e3a1}.chroma .sa{color:#f38ba8}.chroma .sb,.chroma .sc{color:#a6e3a1}.chroma .dl{color:#89b4fa}.chroma .sd{color:#6c7086}.chroma .s2{color:#a6e3a1}.chroma .se{color:#89b4fa}.chroma .sh{color:#6c7086}.chroma .si,.chroma .sx{color:#a6e3a1}.chroma .sr{color:#94e2d5}.chroma .s1,.chroma .ss{color:#a6e3a1}.chroma .il,.chroma .m,.chroma .mb,.chroma .mf,.chroma .mh,.chroma .mi,.chroma .mo{color:#fab387}.chroma .o,.chroma .ow{color:#89dceb;font-weight:700}.chroma .c,.chroma .c1,.chroma .ch,.chroma .cm,.chroma .cp,.chroma .cpf,.chroma .cs{color:#6c7086;font-style:italic}.chroma .cpf{font-weight:700}.chroma .gd{color:#f38ba8;background-color:#313244}.chroma .ge{font-style:italic}.chroma .gr{color:#f38ba8}.chroma .gh{color:#fab387;font-weight:700}.chroma .gi{color:#a6e3a1;background-color:#313244}.chroma .gs,.chroma .gu{font-weight:700}.chroma .gu{color:#fab387}.chroma .gt{color:#f38ba8}.chroma .gl{text-decoration:underline}.dark\\:mocha{--ctp-rosewater:245,224,220;--ctp-flamingo:242,205,205;--ctp-pink:245,194,231;--ctp-mauve:203,166,247;--ctp-red:243,139,168;--ctp-maroon:235,160,172;--ctp-peach:250,179,135;--ctp-yellow:249,226,175;--ctp-green:166,227,161;--ctp-teal:148,226,213;--ctp-sky:137,220,235;--ctp-sapphire:116,199,236;--ctp-blue:137,180,250;--ctp-lavender:180,190,254;--ctp-text:205,214,244;--ctp-subtext1:186,194,222;--ctp-subtext0:166,173,200;--ctp-overlay2:147,153,178;--ctp-overlay1:127,132,156;--ctp-overlay0:108,112,134;--ctp-surface2:88,91,112;--ctp-surface1:69,71,90;--ctp-surface0:49,50,68;--ctp-base:30,30,46;--ctp-mantle:24,24,37;--ctp-crust:17,17,27}}.hover\\:bg-surface0:hover{--tw-bg-opacity:1;background-color:rgba(var(--ctp-surface0),var(--tw-bg-opacity))}.hover\\:decoration-solid:hover{text-decoration-style:solid}.focus\\:border-lavender:focus{--tw-border-opacity:1;border-color:rgba(var(--ctp-lavender),var(--tw-border-opacity))}.focus\\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}.focus\\:ring-0:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}@media (prefers-color-scheme:dark){.dark\\:bg-base\\/50{background-color:rgba(var(--ctp-base),.5)}.dark\\:bg-base\\/95{background-color:rgba(var(--ctp-base),.95)}.dark\\:text-lavender{--tw-text-opacity:1;color:rgba(var(--ctp-lavender),var(--tw-text-opacity))}.dark\\:decoration-lavender\\/50{text-decoration-color:rgba(var(--ctp-lavender),.5)}}@media (min-width:640px){.sm\\:col-span-1{grid-column:span 1/span 1}.sm\\:col-span-2{grid-column:span 2/span 2}.sm\\:col-span-3{grid-column:span 3/span 3}.sm\\:col-span-5{grid-column:span 5/span 5}.sm\\:col-span-6{grid-column:span 6/span 6}.sm\\:col-span-7{grid-column:span 7/span 7}.sm\\:mx-auto{margin-left:auto;margin-right:auto}.sm\\:mb-0{margin-bottom:0}.sm\\:grid-cols-10{grid-template-columns:repeat(10,minmax(0,1fr))}.sm\\:grid-cols-8{grid-template-columns:repeat(8,minmax(0,1fr))}}")) 9 }
+5 -4
internal/http/http.go
··· 18 // Server is the container struct for the HTTP server 19 type Server struct { 20 port int 21 - mux *chi.Mux 22 } 23 24 // ListenAndServe simply wraps http.ListenAndServe to contain the functionality here 25 func (s Server) ListenAndServe() error { 26 - return http.ListenAndServe(fmt.Sprintf("localhost:%d", s.port), s.mux) 27 } 28 29 // Settings is the configuration for the HTTP server ··· 34 Port int 35 RepoDir string 36 Profile Profile 37 } 38 39 // Profile is the index profile ··· 101 r.Get("/tailwind.css", html.TailwindHandler) 102 }) 103 104 - return Server{mux: mux, port: settings.Port} 105 } 106 107 type repoHandler struct { ··· 125 Name: chi.URLParam(r, "repo"), 126 Ref: ref, 127 CloneURL: rh.s.CloneURL, 128 - Tags: repo.Meta.Tags, 129 } 130 } 131
··· 18 // Server is the container struct for the HTTP server 19 type Server struct { 20 port int 21 + Mux *chi.Mux 22 } 23 24 // ListenAndServe simply wraps http.ListenAndServe to contain the functionality here 25 func (s Server) ListenAndServe() error { 26 + return http.ListenAndServe(fmt.Sprintf("localhost:%d", s.port), s.Mux) 27 } 28 29 // Settings is the configuration for the HTTP server ··· 34 Port int 35 RepoDir string 36 Profile Profile 37 + ShowPrivate bool 38 } 39 40 // Profile is the index profile ··· 102 r.Get("/tailwind.css", html.TailwindHandler) 103 }) 104 105 + return Server{Mux: mux, port: settings.Port} 106 } 107 108 type repoHandler struct { ··· 126 Name: chi.URLParam(r, "repo"), 127 Ref: ref, 128 CloneURL: rh.s.CloneURL, 129 + Tags: repo.Meta.Tags.Slice(), 130 } 131 } 132
+2 -3
internal/http/httperr/httperr.go
··· 2 3 import ( 4 "errors" 5 "net/http" 6 - 7 - "github.com/charmbracelet/log" 8 ) 9 10 type httpError struct { ··· 41 status = httpErr.status 42 } 43 44 - log.Error(err) 45 http.Error(w, http.StatusText(status), status) 46 } 47 }
··· 2 3 import ( 4 "errors" 5 + "log/slog" 6 "net/http" 7 ) 8 9 type httpError struct { ··· 40 status = httpErr.status 41 } 42 43 + slog.Error("httperr Handler error", "error", err) 44 http.Error(w, http.StatusText(status), status) 45 } 46 }
+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
··· 3 import ( 4 "net/http" 5 "os" 6 - "slices" 7 "sort" 8 "strings" 9 "time" ··· 31 return httperr.Error(err) 32 } 33 if repo.Meta.Private { 34 - continue 35 } 36 - if tagFilter != "" && !slices.Contains(repo.Meta.Tags, strings.ToLower(tagFilter)) { 37 continue 38 } 39 repos = append(repos, repo)
··· 3 import ( 4 "net/http" 5 "os" 6 "sort" 7 "strings" 8 "time" ··· 30 return httperr.Error(err) 31 } 32 if repo.Meta.Private { 33 + if !rh.s.ShowPrivate { 34 + continue 35 + } 36 + repo.Meta.Tags.Add("private") 37 } 38 + 39 + if tagFilter != "" && !repo.Meta.Tags.Contains(strings.ToLower(tagFilter)) { 40 continue 41 } 42 repos = append(repos, repo)
+4 -1
internal/http/middleware.go
··· 27 return httperr.Status(err, httpErr) 28 } 29 if repo.Meta.Private { 30 - return httperr.Status(errors.New("could not get git repo"), http.StatusNotFound) 31 } 32 r = r.WithContext(context.WithValue(r.Context(), repoCtxKey, repo)) 33 next.ServeHTTP(w, r)
··· 27 return httperr.Status(err, httpErr) 28 } 29 if repo.Meta.Private { 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") 34 } 35 r = r.WithContext(context.WithValue(r.Context(), repoCtxKey, repo)) 36 next.ServeHTTP(w, r)
+12 -3
internal/http/repo.go
··· 88 } 89 90 var buf bytes.Buffer 91 - if err := markup.Code.Convert([]byte(content), filepath.Base(path), &buf); err != nil { 92 return httperr.Error(err) 93 } 94 95 if err := html.RepoFile(html.RepoFileContext{ 96 BaseContext: rh.baseContext(), 97 RepoHeaderComponentContext: rh.repoHeaderContext(repo, r), 98 RepoBreadcrumbComponentContext: rh.repoBreadcrumbContext(repo, r, path), 99 Code: buf.String(), 100 }).Render(r.Context(), w); err != nil { 101 return httperr.Error(err) 102 } ··· 158 159 for idx, p := range commit.Files { 160 var patch bytes.Buffer 161 - if err := markup.Code.Basic([]byte(p.Patch), "commit.patch", &patch); err != nil { 162 return httperr.Error(err) 163 } 164 commit.Files[idx].Patch = patch.String() ··· 206 } 207 results[idx].Content = buf.String() 208 } 209 - 210 } 211 212 if err := html.RepoSearch(html.SearchContext{
··· 88 } 89 90 var buf bytes.Buffer 91 + if err := markup.Convert([]byte(content), filepath.Base(path), "L", &buf); err != nil { 92 return httperr.Error(err) 93 } 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 + 103 if err := html.RepoFile(html.RepoFileContext{ 104 BaseContext: rh.baseContext(), 105 RepoHeaderComponentContext: rh.repoHeaderContext(repo, r), 106 RepoBreadcrumbComponentContext: rh.repoBreadcrumbContext(repo, r, path), 107 Code: buf.String(), 108 + Commit: commit, 109 + Path: path, 110 }).Render(r.Context(), w); err != nil { 111 return httperr.Error(err) 112 } ··· 168 169 for idx, p := range commit.Files { 170 var patch bytes.Buffer 171 + if err := markup.Convert([]byte(p.Patch), "commit.patch", p.Path()+"-L", &patch); err != nil { 172 return httperr.Error(err) 173 } 174 commit.Files[idx].Patch = patch.String() ··· 216 } 217 results[idx].Content = buf.String() 218 } 219 } 220 221 if err := html.RepoSearch(html.SearchContext{
-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 3 import ( 4 "fmt" 5 6 - "github.com/charmbracelet/log" 7 "github.com/charmbracelet/ssh" 8 "github.com/charmbracelet/wish" 9 "github.com/charmbracelet/wish/logging" ··· 42 func (a hooks) Fetch(_ string, _ ssh.PublicKey) {} 43 44 var ( 45 - DefaultLogger logging.Logger = log.StandardLog() 46 NoopLogger logging.Logger = noopLogger{} 47 ) 48
··· 2 3 import ( 4 "fmt" 5 + "log" 6 7 "github.com/charmbracelet/ssh" 8 "github.com/charmbracelet/wish" 9 "github.com/charmbracelet/wish/logging" ··· 42 func (a hooks) Fetch(_ string, _ ssh.PublicKey) {} 43 44 var ( 45 + DefaultLogger logging.Logger = log.Default() 46 NoopLogger logging.Logger = noopLogger{} 47 ) 48
+3 -13
internal/ssh/wish.go
··· 5 "errors" 6 "fmt" 7 "io/fs" 8 "os" 9 "path/filepath" 10 "strings" ··· 12 13 "go.jolheiser.com/ugit/internal/git" 14 15 - "github.com/charmbracelet/log" 16 "github.com/charmbracelet/ssh" 17 "github.com/charmbracelet/wish" 18 ) ··· 91 if errors.Is(err, ErrInvalidRepo) { 92 Fatal(s, ErrInvalidRepo) 93 } 94 - log.Error("unknown git error", "error", err) 95 Fatal(s, ErrSystemMalfunction) 96 } 97 gh.Fetch(repo, pk) ··· 103 if len(cmd) == 0 { 104 des, err := os.ReadDir(repoDir) 105 if err != nil && err != fs.ErrNotExist { 106 - log.Error("invalid repository", "error", err) 107 } 108 tw := tabwriter.NewWriter(s, 0, 0, 1, ' ', 0) 109 for _, de := range des { ··· 122 } 123 tw.Flush() 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 sh(s) 136 } 137 }
··· 5 "errors" 6 "fmt" 7 "io/fs" 8 + "log/slog" 9 "os" 10 "path/filepath" 11 "strings" ··· 13 14 "go.jolheiser.com/ugit/internal/git" 15 16 "github.com/charmbracelet/ssh" 17 "github.com/charmbracelet/wish" 18 ) ··· 91 if errors.Is(err, ErrInvalidRepo) { 92 Fatal(s, ErrInvalidRepo) 93 } 94 + slog.Error("unknown git error", "error", err) 95 Fatal(s, ErrSystemMalfunction) 96 } 97 gh.Fetch(repo, pk) ··· 103 if len(cmd) == 0 { 104 des, err := os.ReadDir(repoDir) 105 if err != nil && err != fs.ErrNotExist { 106 + slog.Error("invalid repository", "error", err) 107 } 108 tw := tabwriter.NewWriter(s, 0, 0, 1, ' ', 0) 109 for _, de := range des { ··· 122 } 123 tw.Flush() 124 } 125 sh(s) 126 } 127 }
+10
nix/default.nix
···
··· 1 + { 2 + pkgs ? import <nixpkgs> { }, 3 + }: 4 + let 5 + pkg = pkgs.callPackage ./pkg.nix { inherit pkgs; }; 6 + in 7 + { 8 + ugit = pkg; 9 + default = pkg; 10 + }
+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
···
··· 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
···
··· 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 + }