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

Compare changes

Choose any two refs to compare.

+2833 -1566
+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
+51 -10
cmd/ugitd/args.go
··· 1 package main 2 3 import ( 4 "flag" 5 "fmt" 6 "strings" 7 8 "github.com/peterbourgon/ff/v3" 9 - "go.jolheiser.com/ffdhall" 10 ) 11 12 type cliArgs struct { 13 - Debug bool 14 - RepoDir string 15 - SSH sshArgs 16 - HTTP httpArgs 17 - Meta metaArgs 18 - Profile profileArgs 19 } 20 21 type sshArgs struct { 22 AuthorizedKeys string 23 CloneURL string 24 Port int ··· 26 } 27 28 type httpArgs struct { 29 CloneURL string 30 Port int 31 } ··· 46 URL string 47 } 48 49 func parseArgs(args []string) (c cliArgs, e error) { 50 fs := flag.NewFlagSet("ugitd", flag.ContinueOnError) 51 - fs.String("config", "ugit.dhall", "Path to config file") 52 53 c = cliArgs{ 54 RepoDir: ".ugit", 55 SSH: sshArgs{ 56 AuthorizedKeys: ".ssh/authorized_keys", 57 CloneURL: "ssh://localhost:8448", 58 Port: 8448, 59 HostKey: ".ssh/ugit_ed25519", 60 }, 61 HTTP: httpArgs{ 62 CloneURL: "http://localhost:8449", 63 Port: 8449, 64 }, ··· 66 Title: "ugit", 67 Description: "Minimal git server", 68 }, 69 } 70 71 - fs.BoolVar(&c.Debug, "debug", c.Debug, "Debug logging") 72 fs.StringVar(&c.RepoDir, "repo-dir", c.RepoDir, "Path to directory containing repositories") 73 fs.StringVar(&c.SSH.AuthorizedKeys, "ssh.authorized-keys", c.SSH.AuthorizedKeys, "Path to authorized_keys") 74 fs.StringVar(&c.SSH.CloneURL, "ssh.clone-url", c.SSH.CloneURL, "SSH clone URL base") 75 fs.IntVar(&c.SSH.Port, "ssh.port", c.SSH.Port, "SSH port") 76 fs.StringVar(&c.SSH.HostKey, "ssh.host-key", c.SSH.HostKey, "SSH host key (created if it doesn't exist)") 77 fs.StringVar(&c.HTTP.CloneURL, "http.clone-url", c.HTTP.CloneURL, "HTTP clone URL base") 78 fs.IntVar(&c.HTTP.Port, "http.port", c.HTTP.Port, "HTTP port") 79 fs.StringVar(&c.Meta.Title, "meta.title", c.Meta.Title, "App title") ··· 92 return nil 93 }) 94 95 return c, ff.Parse(fs, args, 96 ff.WithEnvVarPrefix("UGIT"), 97 ff.WithConfigFileFlag("config"), 98 ff.WithAllowMissingConfigFile(true), 99 - ff.WithConfigFileParser(ffdhall.DhallParser), 100 ) 101 }
··· 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 } ··· 54 URL string 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 }, ··· 81 Title: "ugit", 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 }
+55 -30
cmd/ugitd/main.go
··· 4 "errors" 5 "flag" 6 "fmt" 7 "os" 8 "os/signal" 9 "path/filepath" 10 "strconv" 11 "strings" 12 13 "github.com/go-git/go-git/v5/plumbing/protocol/packp" 14 "go.jolheiser.com/ugit/internal/git" 15 - 16 "go.jolheiser.com/ugit/internal/http" 17 "go.jolheiser.com/ugit/internal/ssh" 18 - 19 - "github.com/charmbracelet/log" 20 - "github.com/go-chi/chi/v5/middleware" 21 - "github.com/go-git/go-git/v5/utils/trace" 22 ) 23 24 func main() { ··· 39 panic(err) 40 } 41 42 - if args.Debug { 43 trace.SetTarget(trace.Packet) 44 - log.SetLevel(log.DebugLevel) 45 } else { 46 middleware.DefaultLogger = http.NoopLogger 47 ssh.DefaultLogger = ssh.NoopLogger 48 } 49 50 if err := requiredFS(args.RepoDir); err != nil { 51 panic(err) 52 } 53 54 - sshSettings := ssh.Settings{ 55 - AuthorizedKeys: args.SSH.AuthorizedKeys, 56 - CloneURL: args.SSH.CloneURL, 57 - Port: args.SSH.Port, 58 - HostKey: args.SSH.HostKey, 59 - RepoDir: args.RepoDir, 60 - } 61 - sshSrv, err := ssh.New(sshSettings) 62 - if err != nil { 63 - panic(err) 64 - } 65 - go func() { 66 - fmt.Printf("SSH listening on ssh://localhost:%d\n", sshSettings.Port) 67 - if err := sshSrv.ListenAndServe(); err != nil { 68 panic(err) 69 } 70 - }() 71 72 httpSettings := http.Settings{ 73 Title: args.Meta.Title, ··· 79 Username: args.Profile.Username, 80 Email: args.Profile.Email, 81 }, 82 } 83 for _, link := range args.Profile.Links { 84 httpSettings.Profile.Links = append(httpSettings.Profile.Links, http.Link{ ··· 86 URL: link.URL, 87 }) 88 } 89 - httpSrv := http.New(httpSettings) 90 - go func() { 91 - fmt.Printf("HTTP listening on http://localhost:%d\n", httpSettings.Port) 92 - if err := httpSrv.ListenAndServe(); err != nil { 93 - panic(err) 94 - } 95 - }() 96 97 ch := make(chan os.Signal, 1) 98 - signal.Notify(ch, os.Kill, os.Interrupt) 99 <-ch 100 } 101 ··· 118 } 119 fp = filepath.Join(fp, "pre-receive") 120 121 fi, err := os.Create(fp) 122 if err != nil { 123 return err 124 } 125 fi.WriteString("#!/usr/bin/env bash\n") 126 fi.WriteString(fmt.Sprintf("%s pre-receive-hook\n", bin)) 127 fi.Close() 128 129 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" 19 + "github.com/go-git/go-git/v5/utils/trace" 20 "go.jolheiser.com/ugit/internal/git" 21 "go.jolheiser.com/ugit/internal/http" 22 "go.jolheiser.com/ugit/internal/ssh" 23 ) 24 25 func main() { ··· 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 54 ssh.DefaultLogger = ssh.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
+1 -1
contrib/dev.nu
··· 14 mkdir .ugit 15 for $repo in $repos { 16 git clone --bare $"($base_url)/($repo).git" $".ugit/($repo).git" 17 - {"private": false, "description": $repo} | save $".ugit/($repo).git/ugit.json" 18 } 19 }
··· 14 mkdir .ugit 15 for $repo in $repos { 16 git clone --bare $"($base_url)/($repo).git" $".ugit/($repo).git" 17 + {"private": false, "description": $repo, "tags": ["git", "dev", "mirror", "archive"]} | save $".ugit/($repo).git/ugit.json" 18 } 19 }
+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": 1704161960, 45 - "narHash": "sha256-QGua89Pmq+FBAro8NriTuoO/wNaUtugt29/qqA8zeeM=", 46 "owner": "nixos", 47 "repo": "nixpkgs", 48 - "rev": "63143ac2c9186be6d9da6035fa22620018c85932", 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 -158
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 - debug = mkOption { 132 - type = types.bool; 133 - default = false; 134 - }; 135 - 136 - openFirewall = mkOption { 137 - type = types.bool; 138 - default = false; 139 - }; 140 - }; 141 }; 142 - config = lib.mkIf cfg.enable { 143 - users.users."${cfg.user}" = { 144 - home = "/var/lib/ugit"; 145 - createHome = true; 146 - group = "${cfg.group}"; 147 - isSystemUser = true; 148 - isNormalUser = false; 149 - description = "user for ugit service"; 150 - }; 151 - users.groups."${cfg.group}" = {}; 152 - networking.firewall = lib.mkIf cfg.openFirewall { 153 - allowedTCPPorts = [8448 8449]; 154 - }; 155 - 156 - systemd.services.ugit = { 157 - enable = true; 158 - script = let 159 - authorizedKeysPath = 160 - if (builtins.length cfg.authorizedKeys) > 0 161 - then authorizedKeysFile 162 - else cfg.authorizedKeysFile; 163 - args = ["--config=${configFile}" "--repo-dir=${cfg.repoDir}" "--ssh.authorized-keys=${authorizedKeysPath}" "--ssh.host-key=${cfg.hostKeyFile}"] ++ lib.optionals cfg.debug ["--debug"]; 164 - in "${cfg.package}/bin/ugitd ${builtins.concatStringsSep " " args}"; 165 - wantedBy = ["multi-user.target"]; 166 - after = ["network.target"]; 167 - path = [cfg.package pkgs.git pkgs.bash]; 168 - serviceConfig = { 169 - User = cfg.user; 170 - Group = cfg.group; 171 - Restart = "always"; 172 - RestartSec = "15"; 173 - WorkingDirectory = "/var/lib/ugit"; 174 }; 175 - }; 176 - }; 177 }; 178 - }; 179 }
··· 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 }
+70 -47
go.mod
··· 1 module go.jolheiser.com/ugit 2 3 - go 1.22.3 4 5 require ( 6 - github.com/a-h/templ v0.2.543 7 - github.com/alecthomas/chroma/v2 v2.12.0 8 - github.com/charmbracelet/log v0.3.1 9 - github.com/charmbracelet/ssh v0.0.0-20240201134204-3f297de25560 10 - github.com/charmbracelet/wish v1.3.0 11 github.com/dustin/go-humanize v1.0.1 12 - github.com/go-chi/chi/v5 v5.0.11 13 - github.com/go-git/go-billy/v5 v5.5.0 14 - github.com/go-git/go-git/v5 v5.11.0 15 github.com/peterbourgon/ff/v3 v3.4.0 16 - github.com/yuin/goldmark v1.6.0 17 - github.com/yuin/goldmark-emoji v1.0.2 18 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc 19 - golang.org/x/net v0.20.0 20 ) 21 22 require ( 23 - dario.cat/mergo v1.0.0 // indirect 24 - github.com/Microsoft/go-winio v0.6.1 // indirect 25 - github.com/ProtonMail/go-crypto v1.0.0 // indirect 26 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect 27 github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect 28 - github.com/charmbracelet/bubbletea v0.25.0 // indirect 29 - github.com/charmbracelet/keygen v0.5.0 // indirect 30 - github.com/charmbracelet/lipgloss v0.9.1 // indirect 31 - github.com/charmbracelet/x/errors v0.0.0-20240130180102-bafe6fbaee60 // indirect 32 - github.com/charmbracelet/x/exp/term v0.0.0-20240130180102-bafe6fbaee60 // indirect 33 - github.com/cloudflare/circl v1.3.7 // indirect 34 - github.com/containerd/console v1.0.4-0.20230706203907-8f6c4e4faef5 // indirect 35 - github.com/creack/pty v1.1.21 // indirect 36 - github.com/cyphar/filepath-securejoin v0.2.4 // indirect 37 - github.com/dlclark/regexp2 v1.10.0 // indirect 38 github.com/emirpasic/gods v1.18.1 // indirect 39 - github.com/fxamacker/cbor/v2 v2.2.1-0.20200511212021-28e39be4a84f // indirect 40 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect 41 github.com/go-logfmt/logfmt v0.6.0 // indirect 42 - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 43 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect 44 github.com/kevinburke/ssh_config v1.2.0 // indirect 45 github.com/lucasb-eyer/go-colorful v1.2.0 // indirect 46 github.com/mattn/go-isatty v0.0.20 // indirect 47 github.com/mattn/go-localereader v0.0.1 // indirect 48 - github.com/mattn/go-runewidth v0.0.15 // indirect 49 github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect 50 github.com/muesli/cancelreader v0.2.2 // indirect 51 - github.com/muesli/reflow v0.3.0 // indirect 52 - github.com/muesli/termenv v0.15.2 // indirect 53 - github.com/philandstuff/dhall-golang/v6 v6.0.2 // indirect 54 - github.com/pjbgf/sha1cd v0.3.0 // indirect 55 - github.com/rivo/uniseg v0.4.6 // indirect 56 - github.com/sergi/go-diff v1.3.1 // indirect 57 - github.com/skeema/knownhosts v1.2.1 // indirect 58 - github.com/u-root/u-root v0.12.0 // indirect 59 - github.com/x448/float16 v0.8.4 // indirect 60 github.com/xanzy/ssh-agent v0.3.3 // indirect 61 - go.jolheiser.com/ffdhall v0.0.1 // indirect 62 - golang.org/x/crypto v0.18.0 // indirect 63 - golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect 64 - golang.org/x/mod v0.14.0 // indirect 65 - golang.org/x/sync v0.6.0 // indirect 66 - golang.org/x/sys v0.16.0 // indirect 67 - golang.org/x/term v0.16.0 // indirect 68 - golang.org/x/text v0.14.0 // indirect 69 - golang.org/x/tools v0.17.0 // indirect 70 gopkg.in/warnings.v0 v0.1.2 // indirect 71 - gopkg.in/yaml.v2 v2.4.0 // indirect 72 )
··· 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=
+158 -178
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/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 4 github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= 5 - github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= 6 - github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= 7 - github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= 8 - github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= 9 - github.com/a-h/templ v0.2.543 h1:8YyLvyUtf0/IE2nIwZ62Z/m2o2NqwhnMynzOL78Lzbk= 10 - github.com/a-h/templ v0.2.543/go.mod h1:jP908DQCwI08IrnTalhzSEH9WJqG/Q94+EODQcJGFUA= 11 - github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink= 12 - github.com/alecthomas/assert/v2 v2.2.1/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= 13 github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs= 14 - github.com/alecthomas/chroma/v2 v2.12.0 h1:Wh8qLEgMMsN7mgyG8/qIpegky2Hvzr4By6gEF7cmWgw= 15 - github.com/alecthomas/chroma/v2 v2.12.0/go.mod h1:4TQu7gdfuPjSh76j78ietmqh9LiurGF0EpseFXdKMBw= 16 github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= 17 - github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= 18 - github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= 19 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= 20 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= 21 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= 22 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= 23 github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= 24 github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= 25 - github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= 26 - github.com/charmbracelet/bubbletea v0.25.0 h1:bAfwk7jRz7FKFl9RzlIULPkStffg5k6pNt5dywy4TcM= 27 - github.com/charmbracelet/bubbletea v0.25.0/go.mod h1:EN3QDR1T5ZdWmdfDzYcqOCAps45+QIJbLOBxmVNWNNg= 28 - github.com/charmbracelet/keygen v0.5.0 h1:XY0fsoYiCSM9axkrU+2ziE6u6YjJulo/b9Dghnw6MZc= 29 - github.com/charmbracelet/keygen v0.5.0/go.mod h1:DfvCgLHxZ9rJxdK0DGw3C/LkV4SgdGbnliHcObV3L+8= 30 - github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg= 31 - github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I= 32 - github.com/charmbracelet/log v0.3.1 h1:TjuY4OBNbxmHWSwO3tosgqs5I3biyY8sQPny/eCMTYw= 33 - github.com/charmbracelet/log v0.3.1/go.mod h1:OR4E1hutLsax3ZKpXbgUqPtTjQfrh1pG3zwHGWuuq8g= 34 - github.com/charmbracelet/ssh v0.0.0-20240201134204-3f297de25560 h1:kUYiDRF04AsyJvWi4HrklXXSU7+S7qjExusfDnYbVGg= 35 - github.com/charmbracelet/ssh v0.0.0-20240201134204-3f297de25560/go.mod h1:IHy7o73i1MrQ5lmyJjjJ0g7y4+V+g69cm+Y7JCiZWPo= 36 - github.com/charmbracelet/wish v1.3.0 h1:SYV5TIlzDb6WaxjkkYXxv2WZsTu/QZGwfGVc0UB5M48= 37 - github.com/charmbracelet/wish v1.3.0/go.mod h1:1U/bI7zX+IE26ThD5gxtLgeRzctVhSrTpjucPqw4Pos= 38 - github.com/charmbracelet/x/errors v0.0.0-20240130180102-bafe6fbaee60 h1:u0XFhTN81zvoGwyQWOYjjkrimEQj5L2DPECCX5cBsRw= 39 - github.com/charmbracelet/x/errors v0.0.0-20240130180102-bafe6fbaee60/go.mod h1:2P0UgXMEa6TsToMSuFqKFQR+fZTO9CNGUNokkPatT/0= 40 - github.com/charmbracelet/x/exp/term v0.0.0-20240130180102-bafe6fbaee60 h1:IV19YKUZVf6ATrhiPSCirZ4Bs7EsenYwOWcUHngV+q0= 41 - github.com/charmbracelet/x/exp/term v0.0.0-20240130180102-bafe6fbaee60/go.mod h1:kOOxxyxgAFQVcR5yQJWTuLjzt5dR2pcgwy3WaLEudjE= 42 - github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= 43 - github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= 44 - github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= 45 - github.com/containerd/console v1.0.4-0.20230706203907-8f6c4e4faef5 h1:Ig+OPkE3XQrrl+SKsOqAjlkrBN/zrr+Qpw7rCuDjRCE= 46 - github.com/containerd/console v1.0.4-0.20230706203907-8f6c4e4faef5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= 47 - github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 48 - github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0= 49 - github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= 50 - github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= 51 - github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= 52 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 53 - github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 54 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 55 github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= 56 github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= 57 - github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0= 58 - github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= 59 github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= 60 github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= 61 - github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= 62 - github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= 63 github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= 64 github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= 65 - github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 66 - github.com/fxamacker/cbor/v2 v2.2.1-0.20200511212021-28e39be4a84f h1:lvGFo/tDOSQ4FKu0d2694s8XyOfAL6FLR9DCD5BIUW4= 67 - github.com/fxamacker/cbor/v2 v2.2.1-0.20200511212021-28e39be4a84f/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= 68 - github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= 69 - github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= 70 - github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA= 71 - github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= 72 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= 73 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= 74 - github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= 75 - github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= 76 github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= 77 github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= 78 - github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= 79 - github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= 80 github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= 81 github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= 82 - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= 83 - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 84 - github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 85 - github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 86 - github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 87 github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= 88 github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= 89 - github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 90 - github.com/hugelgupf/vmtest v0.0.0-20240102225328-693afabdd27f h1:ov45/OzrJG8EKbGjn7jJZQJTN7Z1t73sFYNIRd64YlI= 91 - github.com/hugelgupf/vmtest v0.0.0-20240102225328-693afabdd27f/go.mod h1:JoDrYMZpDPYo6uH9/f6Peqms3zNNWT2XiGgioMOIGuI= 92 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= 93 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= 94 github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= ··· 100 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 101 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 102 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 103 - github.com/leanovate/gopter v0.2.5-0.20190402064358-634a59d12406/go.mod h1:gNcbPWNEWRe4lm+bycKqxUYoH5uoVje5SkOJ3uoLer8= 104 github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= 105 github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= 106 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 107 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 108 github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= 109 github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= 110 - github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= 111 - github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= 112 - github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 113 github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= 114 github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= 115 github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= 116 github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= 117 - github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= 118 - github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= 119 - github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= 120 - github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= 121 - github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 122 - github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 123 - github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 124 - github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= 125 - github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= 126 github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= 127 github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= 128 - github.com/philandstuff/dhall-golang/v6 v6.0.2 h1:jv8fi4ZYiFe6uGrprx6dY7L3xPcgmEqWZo3s8ABCzkw= 129 - github.com/philandstuff/dhall-golang/v6 v6.0.2/go.mod h1:XRoxjsqZM2y7KPFhjV7CSVdWpV5CwuTzGjAY/v+1SUU= 130 - github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= 131 - github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= 132 - github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 133 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 134 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 135 - github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 136 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 137 - github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 138 github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 139 - github.com/rivo/uniseg v0.4.6 h1:Sovz9sDSwbOz9tgUy8JpT+KgCkPYJEN/oYzlJiYTNLg= 140 - github.com/rivo/uniseg v0.4.6/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= 141 - github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= 142 - github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= 143 - github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 144 - github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= 145 - github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= 146 - github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 147 github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 148 - github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= 149 - github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= 150 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 151 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 152 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 153 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 154 - github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 155 - github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 156 - github.com/u-root/gobusybox/src v0.0.0-20231228173702-b69f654846aa h1:unMPGGK/CRzfg923allsikmvk2l7beBeFPUNC4RVX/8= 157 - github.com/u-root/gobusybox/src v0.0.0-20231228173702-b69f654846aa/go.mod h1:Zj4Tt22fJVn/nz/y6Ergm1SahR9dio1Zm/D2/S0TmXM= 158 - github.com/u-root/u-root v0.12.0 h1:K0AuBFriwr0w/PGS3HawiAw89e3+MU7ks80GpghAsNs= 159 - github.com/u-root/u-root v0.12.0/go.mod h1:FYjTOh4IkIZHhjsd17lb8nYW6udgXdJhG1c0r6u0arI= 160 - github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= 161 - github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= 162 - github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= 163 github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= 164 github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= 165 - github.com/yuin/goldmark v1.3.7/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 166 - github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 167 github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 168 - github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68= 169 - github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 170 - github.com/yuin/goldmark-emoji v1.0.2 h1:c/RgTShNgHTtc6xdz2KKI74jJr6rWi7FPgnP9GAsO5s= 171 - github.com/yuin/goldmark-emoji v1.0.2/go.mod h1:RhP/RWpexdp+KHs7ghKnifRoIs/Bq4nDS7tRbCkOwKY= 172 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ= 173 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I= 174 - go.jolheiser.com/ffdhall v0.0.1 h1:HOTMUTXvUItpitv/xKEVN5stYhpSXTPlShNiERBfutA= 175 - go.jolheiser.com/ffdhall v0.0.1/go.mod h1:7VdNxVDYnHUa0WEqTms9cHqnOnyh41Mal2vot+P4O48= 176 - golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 177 - golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 178 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 179 - golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= 180 - golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= 181 - golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= 182 - golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= 183 - golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= 184 - golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= 185 - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 186 - golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 187 - golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= 188 - golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 189 - golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 190 - golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 191 - golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 192 - golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 193 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 194 - golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 195 - golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= 196 - golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 197 - golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= 198 - golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= 199 - golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= 200 - golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 201 - golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 202 - golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 203 - golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 204 - golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 205 - golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= 206 - golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 207 - golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 208 - golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 209 - golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 210 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 211 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 212 golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 213 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 214 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 215 - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 216 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 217 - golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 218 - golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 219 - golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 220 - golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 221 - golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 222 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 223 - golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= 224 - golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 225 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 226 - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 227 - golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= 228 - golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 229 - golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= 230 - golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= 231 - golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= 232 - golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 233 - golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 234 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 235 - golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 236 - golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 237 - golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 238 - golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 239 - golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 240 - golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 241 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 242 - golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 243 - golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 244 - golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 245 - golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= 246 - golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= 247 - golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 248 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 249 - gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 250 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 251 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 252 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 253 - gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 254 - gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 255 gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= 256 gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 257 - gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 258 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 259 - gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 260 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 261 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 262 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= 236 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 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 }
+64 -1
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 } 16 17 // Update updates meta given another RepoMeta ··· 45 return json.NewEncoder(fi).Encode(r.Meta) 46 } 47 48 func ensureJSONFile(path string) error { 49 _, err := os.Stat(path) 50 if err == nil { ··· 58 return err 59 } 60 defer fi.Close() 61 - if _, err := fi.WriteString(`{"private":true}`); err != nil { 62 return err 63 } 64 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 + }
+15
internal/git/protocol.go
··· 50 } 51 changed = repo.Meta.Private != private 52 repo.Meta.Private = private 53 } 54 } 55 if changed {
··· 50 } 51 changed = repo.Meta.Private != private 52 repo.Meta.Private = private 53 + case "tags": 54 + tagValues := strings.Split(opt.Value, ",") 55 + for _, tagValue := range tagValues { 56 + var remove bool 57 + if strings.HasPrefix(tagValue, "-") { 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 } 69 } 70 if changed {
-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>
+31 -25
internal/html/base_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.501 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 } 35 var templ_7745c5c3_Var2 string 36 templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(bc.Title) 37 if templ_7745c5c3_Err != nil { 38 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `base.templ`, Line: 13, Col: 20} 39 } 40 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) 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 } 48 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(bc.Title)) 49 if templ_7745c5c3_Err != nil { 50 - return templ_7745c5c3_Err 51 } 52 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><meta property=\"og:description\" content=\"") 53 if templ_7745c5c3_Err != nil { 54 return templ_7745c5c3_Err 55 } 56 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(bc.Description)) 57 if templ_7745c5c3_Err != nil { 58 return templ_7745c5c3_Err 59 } 60 - _, 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=\"/\">") 61 if templ_7745c5c3_Err != nil { 62 - return templ_7745c5c3_Err 63 } 64 - templ_7745c5c3_Var3 := `Home` 65 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3) 66 if templ_7745c5c3_Err != nil { 67 return templ_7745c5c3_Err 68 } 69 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></h2>") 70 if templ_7745c5c3_Err != nil { 71 return templ_7745c5c3_Err 72 } ··· 74 if templ_7745c5c3_Err != nil { 75 return templ_7745c5c3_Err 76 } 77 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</body></html>") 78 if templ_7745c5c3_Err != nil { 79 return templ_7745c5c3_Err 80 } 81 - if !templ_7745c5c3_IsBuffer { 82 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 83 - } 84 - return templ_7745c5c3_Err 85 }) 86 }
··· 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 } 41 var templ_7745c5c3_Var2 string 42 templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(bc.Title) 43 if templ_7745c5c3_Err != nil { 44 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `base.templ`, Line: 14, Col: 20} 45 } 46 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) 47 if templ_7745c5c3_Err != nil { 48 return templ_7745c5c3_Err 49 } 50 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><link rel=\"icon\" href=\"/_/favicon.svg\"><link rel=\"stylesheet\" href=\"/_/tailwind.css\"><meta property=\"og:title\" content=\"") 51 if templ_7745c5c3_Err != nil { 52 return templ_7745c5c3_Err 53 } 54 + var templ_7745c5c3_Var3 string 55 + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(bc.Title) 56 if templ_7745c5c3_Err != nil { 57 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `base.templ`, Line: 17, Col: 47} 58 } 59 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 60 if templ_7745c5c3_Err != nil { 61 return templ_7745c5c3_Err 62 } 63 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\"><meta property=\"og:description\" content=\"") 64 if templ_7745c5c3_Err != nil { 65 return templ_7745c5c3_Err 66 } 67 + var templ_7745c5c3_Var4 string 68 + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(bc.Description) 69 if templ_7745c5c3_Err != nil { 70 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `base.templ`, Line: 18, Col: 59} 71 } 72 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 73 if templ_7745c5c3_Err != nil { 74 return templ_7745c5c3_Err 75 } 76 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\"></head><body class=\"latte dark:mocha bg-base/50 dark:bg-base/95 max-w-7xl mx-5 sm:mx-auto my-10\"><h2 class=\"text-text text-xl mb-3\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"/\">Home</a></h2>") 77 if templ_7745c5c3_Err != nil { 78 return templ_7745c5c3_Err 79 } ··· 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("}")
+43 -15
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 9 Profile IndexProfile 10 - Repos []*git.Repo 11 } 12 13 type IndexProfile struct { 14 Username string 15 - Email string 16 - Links []IndexLink 17 } 18 19 type IndexLink struct { 20 Name string 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> ··· 45 } 46 if ic.Profile.Email != "" { 47 <div class="text-mauve col-span-2"> 48 - <div class="w-5 h-5 stroke-mauve inline-block mr-1 align-middle">@templ.Raw(string(assets.EmailIcon))</div> 49 <a class="underline decoration-mauve/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL("mailto:" + ic.Profile.Email) }>{ ic.Profile.Email }</a> 50 </div> 51 } ··· 53 <div class="grid grid-cols-1 sm:grid-cols-8"> 54 for _, link := range ic.Profile.Links { 55 <div class="text-mauve"> 56 - <div class="w-5 h-5 stroke-mauve inline-block mr-1 align-middle">@templ.Raw(string(assets.LinkIcon))</div> 57 <a class="underline decoration-mauve/50 decoration-dashed hover:decoration-solid" rel="me" href={ templ.SafeURL(link.URL) }>{ link.Name }</a> 58 </div> 59 } 60 </div> 61 - <div class="grid sm:grid-cols-8 gap-1 mt-5"> 62 for _, repo := range ic.Repos { 63 - <div class="sm:col-span-1 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> 64 - <div class="sm:col-span-5 text-subtext0">{ repo.Meta.Description }</div> 65 - <div class="sm:col-span-2 text-text/80 mb-4 sm:mb-0" title={ lastCommit(repo, false) }>{ lastCommit(repo, true) }</div> 66 } 67 </div> 68 </main> 69 } 70 } 71 -
··· 1 package html 2 3 + import ( 4 + "fmt" 5 + "github.com/dustin/go-humanize" 6 + "go.jolheiser.com/ugit/assets" 7 + "go.jolheiser.com/ugit/internal/git" 8 + ) 9 10 type IndexContext struct { 11 BaseContext 12 Profile IndexProfile 13 + Repos []*git.Repo 14 } 15 16 type IndexProfile struct { 17 Username string 18 + Email string 19 + Links []IndexLink 20 } 21 22 type IndexLink struct { 23 Name string 24 + URL string 25 } 26 27 + func lastCommitTime(repo *git.Repo, human bool) string { 28 c, err := repo.LastCommit() 29 if err != nil { 30 return "" ··· 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> ··· 56 } 57 if ic.Profile.Email != "" { 58 <div class="text-mauve col-span-2"> 59 + <div class="w-5 h-5 stroke-mauve inline-block mr-1 align-middle"> 60 + @templ.Raw(string(assets.EmailIcon)) 61 + </div> 62 <a class="underline decoration-mauve/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL("mailto:" + ic.Profile.Email) }>{ ic.Profile.Email }</a> 63 </div> 64 } ··· 66 <div class="grid grid-cols-1 sm:grid-cols-8"> 67 for _, link := range ic.Profile.Links { 68 <div class="text-mauve"> 69 + <div class="w-5 h-5 stroke-mauve inline-block mr-1 align-middle"> 70 + @templ.Raw(string(assets.LinkIcon)) 71 + </div> 72 <a class="underline decoration-mauve/50 decoration-dashed hover:decoration-solid" rel="me" href={ templ.SafeURL(link.URL) }>{ link.Name }</a> 73 </div> 74 } 75 </div> 76 + <div class="grid sm:grid-cols-10 gap-2 mt-5"> 77 for _, repo := range ic.Repos { 78 + {{ commit := lastCommit(repo) }} 79 + <div class="sm:col-span-2 text-blue dark:text-lavender"><a class="underline decoration-blue/50 dark:decoration-lavender/50 decoration-dashed hover:decoration-solid" href={ templ.URL("/" + repo.Name()) }>{ repo.Name() }</a></div> 80 + <div class="sm:col-span-3 text-subtext0">{ repo.Meta.Description }</div> 81 + <div class="sm:col-span-3 text-subtext0"> 82 + if commit != nil { 83 + <div title={ commit.Message }> 84 + <a class="underline text-blue dark:text-lavender decoration-blue/50 dark:decoration-lavender/50 decoration-dashed hover:decoration-solid" href={ fmt.Sprintf("/%s/commit/%s", repo.Name(), commit.SHA) }>{ commit.Short() }</a> 85 + { ": " + commit.Summary() } 86 + </div> 87 + } 88 + </div> 89 + <div class="sm:col-span-1 text-subtext0"> 90 + for _, tag := range repo.Meta.Tags.Slice() { 91 + <a href={ templ.SafeURL("?tag=" + tag) } class="rounded border-rosewater border-solid border pb-0.5 px-1 mr-1 mb-1 inline-block">{ tag }</a> 92 + } 93 + </div> 94 + <div class="sm:col-span-1 text-text/80 mb-4 sm:mb-0" title={ lastCommitTime(repo, false) }>{ lastCommitTime(repo, true) }</div> 95 } 96 </div> 97 </main> 98 } 99 }
+199 -64
internal/html/index_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.501 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: 37, 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: 38, 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: 43, 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: 48, 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: 56, 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-1 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-1 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: 62, 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-5 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: 63, 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-2 text-text/80 mb-4 sm:mb-0\" title=\"") 230 if templ_7745c5c3_Err != nil { 231 return templ_7745c5c3_Err 232 } 233 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(lastCommit(repo, false))) 234 if templ_7745c5c3_Err != nil { 235 return templ_7745c5c3_Err 236 } 237 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 238 if templ_7745c5c3_Err != nil { 239 return templ_7745c5c3_Err 240 } 241 - var templ_7745c5c3_Var13 string 242 - templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(lastCommit(repo, true)) 243 if templ_7745c5c3_Err != nil { 244 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 64, Col: 116} 245 } 246 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) 247 if templ_7745c5c3_Err != nil { 248 return templ_7745c5c3_Err 249 } 250 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 251 if templ_7745c5c3_Err != nil { 252 return templ_7745c5c3_Err 253 } 254 } 255 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></main>") 256 if templ_7745c5c3_Err != nil { 257 return templ_7745c5c3_Err 258 } 259 - if !templ_7745c5c3_IsBuffer { 260 - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) 261 - } 262 - return templ_7745c5c3_Err 263 }) 264 templ_7745c5c3_Err = base(ic.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 265 if templ_7745c5c3_Err != nil { 266 return templ_7745c5c3_Err 267 } 268 - if !templ_7745c5c3_IsBuffer { 269 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 270 - } 271 - return templ_7745c5c3_Err 272 }) 273 }
··· 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.501 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
+6
internal/html/repo.templ
··· 7 Ref string 8 Description string 9 CloneURL string 10 } 11 12 templ repoHeaderComponent(rhcc RepoHeaderComponentContext) { ··· 24 <form class="inline-block" action={ templ.SafeURL(fmt.Sprintf("/%s/search", rhcc.Name)) } method="get"><input class="rounded p-1 bg-mantle focus:border-lavender focus:outline-none focus:ring-0" id="search" type="text" name="q" placeholder="search"/></form> 25 { " - " } 26 <pre class="text-text inline select-all bg-base dark:bg-base/50 p-1 rounded">{ fmt.Sprintf("%s/%s.git", rhcc.CloneURL, rhcc.Name) }</pre> 27 </div> 28 <div class="text-text/80 mb-1">{ rhcc.Description }</div> 29 }
··· 7 Ref string 8 Description string 9 CloneURL string 10 + Tags []string 11 } 12 13 templ repoHeaderComponent(rhcc RepoHeaderComponentContext) { ··· 25 <form class="inline-block" action={ templ.SafeURL(fmt.Sprintf("/%s/search", rhcc.Name)) } method="get"><input class="rounded p-1 bg-mantle focus:border-lavender focus:outline-none focus:ring-0" id="search" type="text" name="q" placeholder="search"/></form> 26 { " - " } 27 <pre class="text-text inline select-all bg-base dark:bg-base/50 p-1 rounded">{ fmt.Sprintf("%s/%s.git", rhcc.CloneURL, rhcc.Name) }</pre> 28 + </div> 29 + <div class="text-subtext0 mb-1"> 30 + for _, tag := range rhcc.Tags { 31 + <span class="rounded border-rosewater border-solid border pb-0.5 px-1 mr-1 mb-1 inline-block">{ tag }</span> 32 + } 33 </div> 34 <div class="text-text/80 mb-1">{ rhcc.Description }</div> 35 }
+52
internal/html/repo_breadcrumb.templ
···
··· 1 + package html 2 + 3 + import ( 4 + "fmt" 5 + "path" 6 + "strings" 7 + ) 8 + 9 + type RepoBreadcrumbComponentContext struct { 10 + Repo string 11 + Ref string 12 + Path string 13 + } 14 + 15 + type breadcrumb struct { 16 + label string 17 + href string 18 + end bool 19 + } 20 + 21 + func (r RepoBreadcrumbComponentContext) crumbs() []breadcrumb { 22 + parts := strings.Split(r.Path, "/") 23 + breadcrumbs := []breadcrumb{ 24 + { 25 + label: r.Repo, 26 + href: fmt.Sprintf("/%s/tree/%s/", r.Repo, r.Ref), 27 + }, 28 + } 29 + for idx, part := range parts { 30 + breadcrumbs = append(breadcrumbs, breadcrumb{ 31 + label: part, 32 + href: path.Join(breadcrumbs[idx].href, part), 33 + }) 34 + } 35 + breadcrumbs[len(breadcrumbs)-1].end = true 36 + return breadcrumbs 37 + } 38 + 39 + templ repoBreadcrumbComponent(rbcc RepoBreadcrumbComponentContext) { 40 + if rbcc.Path != "" { 41 + <div class="inline-block text-text"> 42 + for _, crumb := range rbcc.crumbs() { 43 + if crumb.end { 44 + <span>{ crumb.label }</span> 45 + } else { 46 + <a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(crumb.href) }>{ crumb.label }</a> 47 + { " / " } 48 + } 49 + } 50 + </div> 51 + } 52 + }
+143
internal/html/repo_breadcrumb_templ.go
···
··· 1 + // Code generated by templ - DO NOT EDIT. 2 + 3 + // templ: version: v0.3.924 4 + package html 5 + 6 + //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 + 8 + import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 + 11 + import ( 12 + "fmt" 13 + "path" 14 + "strings" 15 + ) 16 + 17 + type RepoBreadcrumbComponentContext struct { 18 + Repo string 19 + Ref string 20 + Path string 21 + } 22 + 23 + type breadcrumb struct { 24 + label string 25 + href string 26 + end bool 27 + } 28 + 29 + func (r RepoBreadcrumbComponentContext) crumbs() []breadcrumb { 30 + parts := strings.Split(r.Path, "/") 31 + breadcrumbs := []breadcrumb{ 32 + { 33 + label: r.Repo, 34 + href: fmt.Sprintf("/%s/tree/%s/", r.Repo, r.Ref), 35 + }, 36 + } 37 + for idx, part := range parts { 38 + breadcrumbs = append(breadcrumbs, breadcrumb{ 39 + label: part, 40 + href: path.Join(breadcrumbs[idx].href, part), 41 + }) 42 + } 43 + breadcrumbs[len(breadcrumbs)-1].end = true 44 + return breadcrumbs 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) 64 + if templ_7745c5c3_Var1 == nil { 65 + templ_7745c5c3_Var1 = templ.NopComponent 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 + } 79 + var templ_7745c5c3_Var2 string 80 + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(crumb.label) 81 + if templ_7745c5c3_Err != nil { 82 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_breadcrumb.templ`, Line: 44, Col: 24} 83 + } 84 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) 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 + } 110 + var templ_7745c5c3_Var4 string 111 + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(crumb.label) 112 + if templ_7745c5c3_Err != nil { 113 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_breadcrumb.templ`, Line: 46, Col: 134} 114 + } 115 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 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 + } 123 + var templ_7745c5c3_Var5 string 124 + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(" / ") 125 + if templ_7745c5c3_Err != nil { 126 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_breadcrumb.templ`, Line: 47, Col: 12} 127 + } 128 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 129 + if templ_7745c5c3_Err != nil { 130 + return templ_7745c5c3_Err 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 }
+203 -144
internal/html/repo_commit_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.501 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("\">") 56 if templ_7745c5c3_Err != nil { 57 return templ_7745c5c3_Err 58 } 59 - templ_7745c5c3_Var4 := `tree` 60 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4) 61 if templ_7745c5c3_Err != nil { 62 return templ_7745c5c3_Err 63 } 64 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>") 65 - if templ_7745c5c3_Err != nil { 66 - return templ_7745c5c3_Err 67 - } 68 - var templ_7745c5c3_Var5 string 69 - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 70 if templ_7745c5c3_Err != nil { 71 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 15, Col: 229} 72 } 73 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 74 if templ_7745c5c3_Err != nil { 75 return templ_7745c5c3_Err 76 } 77 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 78 if templ_7745c5c3_Err != nil { 79 return templ_7745c5c3_Err 80 } 81 - var templ_7745c5c3_Var6 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/log/%s", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA)) 82 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var6))) 83 if templ_7745c5c3_Err != nil { 84 - return templ_7745c5c3_Err 85 } 86 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 87 if templ_7745c5c3_Err != nil { 88 return templ_7745c5c3_Err 89 } 90 - templ_7745c5c3_Var7 := `log` 91 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var7) 92 if templ_7745c5c3_Err != nil { 93 return templ_7745c5c3_Err 94 } 95 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>") 96 if templ_7745c5c3_Err != nil { 97 - return templ_7745c5c3_Err 98 - } 99 - var templ_7745c5c3_Var8 string 100 - templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 101 - if templ_7745c5c3_Err != nil { 102 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 15, Col: 427} 103 - } 104 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) 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_Var9 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/commit/%s.patch", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA)) 113 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var9))) 114 if templ_7745c5c3_Err != nil { 115 return templ_7745c5c3_Err 116 } 117 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 118 if templ_7745c5c3_Err != nil { 119 - return templ_7745c5c3_Err 120 } 121 - templ_7745c5c3_Var10 := `patch` 122 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var10) 123 if templ_7745c5c3_Err != nil { 124 return templ_7745c5c3_Err 125 } 126 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div class=\"text-text whitespace-pre mt-5 p-3 bg-base rounded\">") 127 if templ_7745c5c3_Err != nil { 128 return templ_7745c5c3_Err 129 } 130 - var templ_7745c5c3_Var11 string 131 - templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(rcc.Commit.Message) 132 if templ_7745c5c3_Err != nil { 133 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 16, Col: 85} 134 } 135 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) 136 if templ_7745c5c3_Err != nil { 137 return templ_7745c5c3_Err 138 } 139 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 140 if templ_7745c5c3_Err != nil { 141 return templ_7745c5c3_Err 142 } 143 if rcc.Commit.Signature != "" { 144 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<details class=\"text-text whitespace-pre\"><summary class=\"cursor-pointer\">") 145 if templ_7745c5c3_Err != nil { 146 return templ_7745c5c3_Err 147 } 148 - templ_7745c5c3_Var12 := `Signature` 149 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var12) 150 if templ_7745c5c3_Err != nil { 151 - return templ_7745c5c3_Err 152 } 153 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</summary><div class=\"p-3 bg-base rounded\"><code>") 154 if templ_7745c5c3_Err != nil { 155 return templ_7745c5c3_Err 156 } 157 - var templ_7745c5c3_Var13 string 158 - templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(rcc.Commit.Signature) 159 - if templ_7745c5c3_Err != nil { 160 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 20, Col: 65} 161 - } 162 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) 163 - if templ_7745c5c3_Err != nil { 164 - return templ_7745c5c3_Err 165 - } 166 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</code></div></details>") 167 if templ_7745c5c3_Err != nil { 168 return templ_7745c5c3_Err 169 } 170 } 171 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <div class=\"text-text mt-3\"><div>") 172 if templ_7745c5c3_Err != nil { 173 return templ_7745c5c3_Err 174 } 175 - var templ_7745c5c3_Var14 string 176 - templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(rcc.Commit.Author) 177 if templ_7745c5c3_Err != nil { 178 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 24, Col: 27} 179 } 180 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) 181 if templ_7745c5c3_Err != nil { 182 return templ_7745c5c3_Err 183 } 184 - var templ_7745c5c3_Var15 string 185 - templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 186 if templ_7745c5c3_Err != nil { 187 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 24, Col: 34} 188 } 189 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) 190 if templ_7745c5c3_Err != nil { 191 return templ_7745c5c3_Err 192 } 193 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 194 if templ_7745c5c3_Err != nil { 195 return templ_7745c5c3_Err 196 } 197 - var templ_7745c5c3_Var16 templ.SafeURL = templ.SafeURL(fmt.Sprintf("mailto:%s", rcc.Commit.Email)) 198 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var16))) 199 if templ_7745c5c3_Err != nil { 200 return templ_7745c5c3_Err 201 } 202 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 203 if templ_7745c5c3_Err != nil { 204 return templ_7745c5c3_Err 205 } 206 - var templ_7745c5c3_Var17 string 207 - templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("<%s>", rcc.Commit.Email)) 208 if templ_7745c5c3_Err != nil { 209 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 24, Col: 223} 210 } 211 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) 212 if templ_7745c5c3_Err != nil { 213 return templ_7745c5c3_Err 214 } 215 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div title=\"") 216 if templ_7745c5c3_Err != nil { 217 return templ_7745c5c3_Err 218 } 219 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(rcc.Commit.When.Format("01/02/2006 03:04:05 PM"))) 220 if templ_7745c5c3_Err != nil { 221 return templ_7745c5c3_Err 222 } 223 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 224 if templ_7745c5c3_Err != nil { 225 return templ_7745c5c3_Err 226 } 227 - var templ_7745c5c3_Var18 string 228 - templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(humanize.Time(rcc.Commit.When)) 229 if templ_7745c5c3_Err != nil { 230 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 25, Col: 99} 231 } 232 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) 233 if templ_7745c5c3_Err != nil { 234 return templ_7745c5c3_Err 235 } 236 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div><div class=\"text-text mt-5\">") 237 if templ_7745c5c3_Err != nil { 238 return templ_7745c5c3_Err 239 } 240 - var templ_7745c5c3_Var19 string 241 - templ_7745c5c3_Var19, 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)) 242 if templ_7745c5c3_Err != nil { 243 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 27, Col: 179} 244 } 245 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) 246 if templ_7745c5c3_Err != nil { 247 return templ_7745c5c3_Err 248 } 249 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 250 if templ_7745c5c3_Err != nil { 251 return templ_7745c5c3_Err 252 } 253 for _, file := range rcc.Commit.Files { 254 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"text-text mt-5\"><span class=\"text-text/80\" title=\"") 255 if templ_7745c5c3_Err != nil { 256 return templ_7745c5c3_Err 257 } 258 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(file.Action)) 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 var templ_7745c5c3_Var20 string 267 - templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(string(file.Action[0])) 268 if templ_7745c5c3_Err != nil { 269 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 30, Col: 77} 270 } 271 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) 272 if templ_7745c5c3_Err != nil { 273 return templ_7745c5c3_Err 274 } 275 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span> ") 276 if templ_7745c5c3_Err != nil { 277 return templ_7745c5c3_Err 278 } 279 var templ_7745c5c3_Var21 string 280 - templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 281 if templ_7745c5c3_Err != nil { 282 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 31, Col: 9} 283 } 284 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) 285 if templ_7745c5c3_Err != nil { 286 return templ_7745c5c3_Err 287 } 288 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 289 if templ_7745c5c3_Err != nil { 290 return templ_7745c5c3_Err 291 } 292 if file.From.Path != "" { 293 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 294 if templ_7745c5c3_Err != nil { 295 return templ_7745c5c3_Err 296 } 297 - var templ_7745c5c3_Var22 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.From.Commit, file.From.Path)) 298 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var22))) 299 if templ_7745c5c3_Err != nil { 300 return templ_7745c5c3_Err 301 } 302 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 303 if templ_7745c5c3_Err != nil { 304 return templ_7745c5c3_Err 305 } 306 - var templ_7745c5c3_Var23 string 307 - templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(file.From.Path) 308 if templ_7745c5c3_Err != nil { 309 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 33, Col: 227} 310 } 311 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) 312 if templ_7745c5c3_Err != nil { 313 return templ_7745c5c3_Err 314 } 315 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>") 316 if templ_7745c5c3_Err != nil { 317 return templ_7745c5c3_Err 318 } 319 } 320 if file.From.Path != "" && file.To.Path != "" { 321 - var templ_7745c5c3_Var24 string 322 - templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(" -> ") 323 if templ_7745c5c3_Err != nil { 324 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 36, Col: 13} 325 } 326 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) 327 if templ_7745c5c3_Err != nil { 328 return templ_7745c5c3_Err 329 } 330 } 331 if file.To.Path != "" { 332 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 333 if templ_7745c5c3_Err != nil { 334 return templ_7745c5c3_Err 335 } 336 - var templ_7745c5c3_Var25 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.To.Commit, file.To.Path)) 337 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var25))) 338 if templ_7745c5c3_Err != nil { 339 return templ_7745c5c3_Err 340 } 341 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 342 if templ_7745c5c3_Err != nil { 343 return templ_7745c5c3_Err 344 } 345 - var templ_7745c5c3_Var26 string 346 - templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(file.To.Path) 347 if templ_7745c5c3_Err != nil { 348 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 39, Col: 221} 349 } 350 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) 351 if templ_7745c5c3_Err != nil { 352 return templ_7745c5c3_Err 353 } 354 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>") 355 if templ_7745c5c3_Err != nil { 356 return templ_7745c5c3_Err 357 } 358 } 359 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"whitespace-pre code\">") 360 if templ_7745c5c3_Err != nil { 361 return templ_7745c5c3_Err 362 } ··· 364 if templ_7745c5c3_Err != nil { 365 return templ_7745c5c3_Err 366 } 367 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 368 if templ_7745c5c3_Err != nil { 369 return templ_7745c5c3_Err 370 } 371 } 372 - if !templ_7745c5c3_IsBuffer { 373 - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) 374 - } 375 - return templ_7745c5c3_Err 376 }) 377 templ_7745c5c3_Err = base(rcc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 378 if templ_7745c5c3_Err != nil { 379 return templ_7745c5c3_Err 380 } 381 - if !templ_7745c5c3_IsBuffer { 382 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 383 - } 384 - return templ_7745c5c3_Err 385 }) 386 }
··· 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 } 75 + var templ_7745c5c3_Var4 string 76 + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 77 if templ_7745c5c3_Err != nil { 78 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 16, Col: 229} 79 } 80 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 81 if templ_7745c5c3_Err != nil { 82 return templ_7745c5c3_Err 83 } 84 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 85 if templ_7745c5c3_Err != nil { 86 return templ_7745c5c3_Err 87 } 88 + var templ_7745c5c3_Var5 templ.SafeURL 89 + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/log/%s", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA))) 90 if templ_7745c5c3_Err != nil { 91 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 16, Col: 412} 92 } 93 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 94 if templ_7745c5c3_Err != nil { 95 return templ_7745c5c3_Err 96 } 97 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\">log</a>") 98 if templ_7745c5c3_Err != nil { 99 return templ_7745c5c3_Err 100 } 101 + var templ_7745c5c3_Var6 string 102 + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 103 if templ_7745c5c3_Err != nil { 104 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 16, Col: 427} 105 } 106 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 107 if templ_7745c5c3_Err != nil { 108 return templ_7745c5c3_Err 109 } 110 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 111 if templ_7745c5c3_Err != nil { 112 return templ_7745c5c3_Err 113 } 114 + var templ_7745c5c3_Var7 templ.SafeURL 115 + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/commit/%s.patch", rcc.RepoHeaderComponentContext.Name, rcc.Commit.SHA))) 116 if templ_7745c5c3_Err != nil { 117 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 16, Col: 619} 118 } 119 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 120 if templ_7745c5c3_Err != nil { 121 return templ_7745c5c3_Err 122 } 123 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">patch</a></div><div class=\"text-text whitespace-pre mt-5 p-3 bg-base rounded\">") 124 if templ_7745c5c3_Err != nil { 125 return templ_7745c5c3_Err 126 } 127 + var templ_7745c5c3_Var8 string 128 + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(rcc.Commit.Message) 129 if templ_7745c5c3_Err != nil { 130 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 17, Col: 85} 131 } 132 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) 133 if templ_7745c5c3_Err != nil { 134 return templ_7745c5c3_Err 135 } 136 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div>") 137 if templ_7745c5c3_Err != nil { 138 return templ_7745c5c3_Err 139 } 140 if rcc.Commit.Signature != "" { 141 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<details class=\"text-text whitespace-pre\"><summary class=\"cursor-pointer\">Signature</summary><div class=\"p-3 bg-base rounded\"><code>") 142 if templ_7745c5c3_Err != nil { 143 return templ_7745c5c3_Err 144 } 145 + var templ_7745c5c3_Var9 string 146 + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(rcc.Commit.Signature) 147 if templ_7745c5c3_Err != nil { 148 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 21, Col: 65} 149 } 150 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) 151 if templ_7745c5c3_Err != nil { 152 return templ_7745c5c3_Err 153 } 154 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</code></div></details>") 155 if templ_7745c5c3_Err != nil { 156 return templ_7745c5c3_Err 157 } 158 } 159 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " <div class=\"text-text mt-3\"><div>") 160 if templ_7745c5c3_Err != nil { 161 return templ_7745c5c3_Err 162 } 163 + var templ_7745c5c3_Var10 string 164 + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(rcc.Commit.Author) 165 if templ_7745c5c3_Err != nil { 166 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 25, Col: 27} 167 } 168 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) 169 if templ_7745c5c3_Err != nil { 170 return templ_7745c5c3_Err 171 } 172 + var templ_7745c5c3_Var11 string 173 + templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 174 if templ_7745c5c3_Err != nil { 175 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 25, Col: 34} 176 } 177 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) 178 if templ_7745c5c3_Err != nil { 179 return templ_7745c5c3_Err 180 } 181 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 182 if templ_7745c5c3_Err != nil { 183 return templ_7745c5c3_Err 184 } 185 + var templ_7745c5c3_Var12 templ.SafeURL 186 + templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("mailto:%s", rcc.Commit.Email))) 187 + if templ_7745c5c3_Err != nil { 188 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 25, Col: 181} 189 + } 190 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) 191 if templ_7745c5c3_Err != nil { 192 return templ_7745c5c3_Err 193 } 194 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\">") 195 if templ_7745c5c3_Err != nil { 196 return templ_7745c5c3_Err 197 } 198 + var templ_7745c5c3_Var13 string 199 + templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("<%s>", rcc.Commit.Email)) 200 if templ_7745c5c3_Err != nil { 201 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 25, Col: 223} 202 } 203 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) 204 if templ_7745c5c3_Err != nil { 205 return templ_7745c5c3_Err 206 } 207 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</a></div><div title=\"") 208 if templ_7745c5c3_Err != nil { 209 return templ_7745c5c3_Err 210 } 211 + var templ_7745c5c3_Var14 string 212 + templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(rcc.Commit.When.Format("01/02/2006 03:04:05 PM")) 213 + if templ_7745c5c3_Err != nil { 214 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 26, Col: 64} 215 + } 216 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) 217 if templ_7745c5c3_Err != nil { 218 return templ_7745c5c3_Err 219 } 220 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "\">") 221 if templ_7745c5c3_Err != nil { 222 return templ_7745c5c3_Err 223 } 224 + var templ_7745c5c3_Var15 string 225 + templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(humanize.Time(rcc.Commit.When)) 226 if templ_7745c5c3_Err != nil { 227 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 26, Col: 99} 228 } 229 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) 230 if templ_7745c5c3_Err != nil { 231 return templ_7745c5c3_Err 232 } 233 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</div></div><details class=\"text-text mt-5\"><summary class=\"cursor-pointer\">") 234 if templ_7745c5c3_Err != nil { 235 return templ_7745c5c3_Err 236 } 237 + var templ_7745c5c3_Var16 string 238 + templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d changed files, %d additions(+), %d deletions(-)", rcc.Commit.Stats.Changed, rcc.Commit.Stats.Additions, rcc.Commit.Stats.Deletions)) 239 if templ_7745c5c3_Err != nil { 240 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 29, Col: 184} 241 + } 242 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) 243 + if templ_7745c5c3_Err != nil { 244 + return templ_7745c5c3_Err 245 } 246 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</summary><div class=\"p-3 bg-base rounded\">") 247 if templ_7745c5c3_Err != nil { 248 return templ_7745c5c3_Err 249 } 250 + for _, file := range rcc.Commit.Files { 251 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<a class=\"block underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 252 + if templ_7745c5c3_Err != nil { 253 + return templ_7745c5c3_Err 254 + } 255 + var templ_7745c5c3_Var17 templ.SafeURL 256 + templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinURLErrs("#" + file.Path()) 257 + if templ_7745c5c3_Err != nil { 258 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 32, Col: 116} 259 + } 260 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) 261 + if templ_7745c5c3_Err != nil { 262 + return templ_7745c5c3_Err 263 + } 264 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\">") 265 + if templ_7745c5c3_Err != nil { 266 + return templ_7745c5c3_Err 267 + } 268 + var templ_7745c5c3_Var18 string 269 + templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(file.Path()) 270 + if templ_7745c5c3_Err != nil { 271 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 32, Col: 132} 272 + } 273 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) 274 + if templ_7745c5c3_Err != nil { 275 + return templ_7745c5c3_Err 276 + } 277 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</a>") 278 + if templ_7745c5c3_Err != nil { 279 + return templ_7745c5c3_Err 280 + } 281 + } 282 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</div></details> ") 283 if templ_7745c5c3_Err != nil { 284 return templ_7745c5c3_Err 285 } 286 for _, file := range rcc.Commit.Files { 287 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<div class=\"text-text mt-5\" id=\"") 288 if templ_7745c5c3_Err != nil { 289 return templ_7745c5c3_Err 290 } 291 + var templ_7745c5c3_Var19 string 292 + templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(file.Path()) 293 + if templ_7745c5c3_Err != nil { 294 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 37, Col: 47} 295 + } 296 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) 297 if templ_7745c5c3_Err != nil { 298 return templ_7745c5c3_Err 299 } 300 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\"><span class=\"text-text/80\" title=\"") 301 if templ_7745c5c3_Err != nil { 302 return templ_7745c5c3_Err 303 } 304 var templ_7745c5c3_Var20 string 305 + templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(file.Action) 306 if templ_7745c5c3_Err != nil { 307 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 38, Col: 50} 308 } 309 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) 310 if templ_7745c5c3_Err != nil { 311 return templ_7745c5c3_Err 312 } 313 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\">") 314 if templ_7745c5c3_Err != nil { 315 return templ_7745c5c3_Err 316 } 317 var templ_7745c5c3_Var21 string 318 + templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(string(file.Action[0])) 319 if templ_7745c5c3_Err != nil { 320 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 38, Col: 77} 321 } 322 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) 323 if templ_7745c5c3_Err != nil { 324 return templ_7745c5c3_Err 325 } 326 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</span> ") 327 + if templ_7745c5c3_Err != nil { 328 + return templ_7745c5c3_Err 329 + } 330 + var templ_7745c5c3_Var22 string 331 + templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 332 + if templ_7745c5c3_Err != nil { 333 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 39, Col: 9} 334 + } 335 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) 336 + if templ_7745c5c3_Err != nil { 337 + return templ_7745c5c3_Err 338 + } 339 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, " ") 340 if templ_7745c5c3_Err != nil { 341 return templ_7745c5c3_Err 342 } 343 if file.From.Path != "" { 344 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 345 if templ_7745c5c3_Err != nil { 346 return templ_7745c5c3_Err 347 } 348 + var templ_7745c5c3_Var23 templ.SafeURL 349 + templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.From.Commit, file.From.Path))) 350 + if templ_7745c5c3_Err != nil { 351 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 41, Col: 208} 352 + } 353 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) 354 if templ_7745c5c3_Err != nil { 355 return templ_7745c5c3_Err 356 } 357 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "\">") 358 if templ_7745c5c3_Err != nil { 359 return templ_7745c5c3_Err 360 } 361 + var templ_7745c5c3_Var24 string 362 + templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(file.From.Path) 363 if templ_7745c5c3_Err != nil { 364 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 41, Col: 227} 365 } 366 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) 367 if templ_7745c5c3_Err != nil { 368 return templ_7745c5c3_Err 369 } 370 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</a> ") 371 if templ_7745c5c3_Err != nil { 372 return templ_7745c5c3_Err 373 } 374 } 375 if file.From.Path != "" && file.To.Path != "" { 376 + var templ_7745c5c3_Var25 string 377 + templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(" -> ") 378 if templ_7745c5c3_Err != nil { 379 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 44, Col: 13} 380 } 381 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) 382 + if templ_7745c5c3_Err != nil { 383 + return templ_7745c5c3_Err 384 + } 385 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, " ") 386 if templ_7745c5c3_Err != nil { 387 return templ_7745c5c3_Err 388 } 389 } 390 if file.To.Path != "" { 391 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 392 if templ_7745c5c3_Err != nil { 393 return templ_7745c5c3_Err 394 } 395 + var templ_7745c5c3_Var26 templ.SafeURL 396 + templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.To.Commit, file.To.Path))) 397 + if templ_7745c5c3_Err != nil { 398 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 47, Col: 204} 399 + } 400 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) 401 if templ_7745c5c3_Err != nil { 402 return templ_7745c5c3_Err 403 } 404 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "\">") 405 if templ_7745c5c3_Err != nil { 406 return templ_7745c5c3_Err 407 } 408 + var templ_7745c5c3_Var27 string 409 + templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(file.To.Path) 410 if templ_7745c5c3_Err != nil { 411 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 47, Col: 221} 412 } 413 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) 414 if templ_7745c5c3_Err != nil { 415 return templ_7745c5c3_Err 416 } 417 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "</a>") 418 if templ_7745c5c3_Err != nil { 419 return templ_7745c5c3_Err 420 } 421 } 422 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</div><div class=\"code\">") 423 if templ_7745c5c3_Err != nil { 424 return templ_7745c5c3_Err 425 } ··· 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
+48 -9
internal/html/repo_file.templ
··· 1 package html 2 3 type RepoFileContext struct { 4 - BaseContext 5 RepoHeaderComponentContext 6 - Code string 7 - Path string 8 } 9 10 templ RepoFile(rfc RepoFileContext) { 11 @base(rfc.BaseContext) { 12 @repoHeaderComponent(rfc.RepoHeaderComponentContext) 13 <div class="mt-2 text-text"> 14 - <span>{ rfc.Path }{ " - " }</span> 15 <a class="text-text underline decoration-text/50 decoration-dashed hover:decoration-solid" href="?raw">raw</a> 16 - <div class="code">@templ.Raw(rfc.Code)</div> 17 </div> 18 } 19 <script> 20 const lineRe = /#L(\d+)(?:-L(\d+))?/g 21 const $lineLines = document.querySelectorAll(".chroma .lntable .lnt"); 22 const $codeLines = document.querySelectorAll(".chroma .lntable .line"); 23 let start = 0; 24 let end = 0; 25 ··· 28 start = results[0][1] !== undefined ? parseInt(results[0][1]) : 0; 29 end = results[0][2] !== undefined ? parseInt(results[0][2]) : 0; 30 } 31 - if (start != 0) { 32 deactivateLines(); 33 activateLines(start, end); 34 } 35 36 for (let line of $lineLines) { ··· 42 if (event.shiftKey) { 43 end = n; 44 anchor = `#L${start}-L${end}`; 45 } else { 46 start = n; 47 end = 0; 48 anchor = `#L${start}`; 49 } 50 - history.pushState(null, null, anchor); 51 - activateLines(start, end); 52 }); 53 } 54 55 function activateLines(start, end) { 56 if (end < start) end = start; ··· 69 70 </script> 71 } 72 -
··· 1 package html 2 3 + import "fmt" 4 + 5 type RepoFileContext struct { 6 + BaseContext 7 RepoHeaderComponentContext 8 + RepoBreadcrumbComponentContext 9 + Code string 10 + Commit string 11 + Path string 12 + } 13 + 14 + func (rfc RepoFileContext) Permalink() string { 15 + return fmt.Sprintf("/%s/tree/%s/%s", rfc.RepoBreadcrumbComponentContext.Repo, rfc.Commit, rfc.Path) 16 } 17 18 templ RepoFile(rfc RepoFileContext) { 19 @base(rfc.BaseContext) { 20 @repoHeaderComponent(rfc.RepoHeaderComponentContext) 21 <div class="mt-2 text-text"> 22 + @repoBreadcrumbComponent(rfc.RepoBreadcrumbComponentContext) 23 + { " - " } 24 <a class="text-text underline decoration-text/50 decoration-dashed hover:decoration-solid" href="?raw">raw</a> 25 + { " - " } 26 + <a class="text-text underline decoration-text/50 decoration-dashed hover:decoration-solid" id="permalink" data-permalink={ rfc.Permalink() } href={ rfc.Permalink() }>permalink</a> 27 + <div class="code relative"> 28 + @templ.Raw(rfc.Code) 29 + <button id="copy" class="absolute top-0 right-0 rounded bg-base hover:bg-surface0"></button> 30 + </div> 31 </div> 32 } 33 <script> 34 const lineRe = /#L(\d+)(?:-L(\d+))?/g 35 const $lineLines = document.querySelectorAll(".chroma .lntable .lnt"); 36 const $codeLines = document.querySelectorAll(".chroma .lntable .line"); 37 + const $copyButton = document.getElementById('copy'); 38 + const $permalink = document.getElementById('permalink'); 39 + const $copyIcon = "๐Ÿ“‹"; 40 + const $copiedIcon = "โœ…"; 41 + let $code = "" 42 + for (let codeLine of $codeLines) $code += codeLine.innerText; 43 let start = 0; 44 let end = 0; 45 ··· 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; ··· 109 110 </script> 111 }
+73 -92
internal/html/repo_file_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.501 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 - Code string 17 - Path 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\"><span>") 44 if templ_7745c5c3_Err != nil { 45 return templ_7745c5c3_Err 46 } 47 var templ_7745c5c3_Var3 string 48 - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(rfc.Path) 49 if templ_7745c5c3_Err != nil { 50 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 13, Col: 19} 51 } 52 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 53 if templ_7745c5c3_Err != nil { 54 return templ_7745c5c3_Err 55 } 56 var templ_7745c5c3_Var4 string 57 templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(" - ") 58 if templ_7745c5c3_Err != nil { 59 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 13, Col: 28} 60 } 61 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 62 if templ_7745c5c3_Err != nil { 63 return templ_7745c5c3_Err 64 } 65 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span> <a class=\"text-text underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"?raw\">") 66 if templ_7745c5c3_Err != nil { 67 return templ_7745c5c3_Err 68 } 69 - templ_7745c5c3_Var5 := `raw` 70 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var5) 71 if templ_7745c5c3_Err != nil { 72 return templ_7745c5c3_Err 73 } 74 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a><div class=\"code\">") 75 if templ_7745c5c3_Err != nil { 76 return templ_7745c5c3_Err 77 } ··· 79 if templ_7745c5c3_Err != nil { 80 return templ_7745c5c3_Err 81 } 82 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div>") 83 if templ_7745c5c3_Err != nil { 84 return templ_7745c5c3_Err 85 } 86 - if !templ_7745c5c3_IsBuffer { 87 - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) 88 - } 89 - return templ_7745c5c3_Err 90 }) 91 templ_7745c5c3_Err = base(rfc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 92 if templ_7745c5c3_Err != nil { 93 return templ_7745c5c3_Err 94 } 95 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<script>") 96 - if templ_7745c5c3_Err != nil { 97 - return templ_7745c5c3_Err 98 - } 99 - templ_7745c5c3_Var6 := ` 100 - const lineRe = /#L(\d+)(?:-L(\d+))?/g 101 - const $lineLines = document.querySelectorAll(".chroma .lntable .lnt"); 102 - const $codeLines = document.querySelectorAll(".chroma .lntable .line"); 103 - let start = 0; 104 - let end = 0; 105 - 106 - const results = [...location.hash.matchAll(lineRe)]; 107 - if (0 in results) { 108 - start = results[0][1] !== undefined ? parseInt(results[0][1]) : 0; 109 - end = results[0][2] !== undefined ? parseInt(results[0][2]) : 0; 110 - } 111 - if (start != 0) { 112 - deactivateLines(); 113 - activateLines(start, end); 114 - } 115 - 116 - for (let line of $lineLines) { 117 - line.addEventListener("click", (event) => { 118 - event.preventDefault(); 119 - deactivateLines(); 120 - const n = parseInt(line.id.substring(1)); 121 - let anchor = ""; 122 - if (event.shiftKey) { 123 - end = n; 124 - anchor = ` + "`" + `#L${start}-L${end}` + "`" + `; 125 - } else { 126 - start = n; 127 - end = 0; 128 - anchor = ` + "`" + `#L${start}` + "`" + `; 129 - } 130 - history.pushState(null, null, anchor); 131 - activateLines(start, end); 132 - }); 133 - } 134 - 135 - function activateLines(start, end) { 136 - if (end < start) end = start; 137 - for (let idx = start - 1; idx < end; idx++) { 138 - $codeLines[idx].classList.add("active"); 139 - } 140 - } 141 - 142 - function deactivateLines() { 143 - for (let code of $codeLines) { 144 - code.classList.remove("active"); 145 - } 146 - } 147 - 148 - 149 - 150 - ` 151 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var6) 152 if templ_7745c5c3_Err != nil { 153 return templ_7745c5c3_Err 154 } 155 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</script>") 156 - if templ_7745c5c3_Err != nil { 157 - return templ_7745c5c3_Err 158 - } 159 - if !templ_7745c5c3_IsBuffer { 160 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 161 - } 162 - return templ_7745c5c3_Err 163 }) 164 }
··· 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 + } 67 + templ_7745c5c3_Err = repoBreadcrumbComponent(rfc.RepoBreadcrumbComponentContext).Render(ctx, templ_7745c5c3_Buffer) 68 if templ_7745c5c3_Err != nil { 69 return templ_7745c5c3_Err 70 } 71 var templ_7745c5c3_Var3 string 72 + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(" - ") 73 if templ_7745c5c3_Err != nil { 74 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 23, Col: 10} 75 } 76 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 77 if templ_7745c5c3_Err != nil { 78 return templ_7745c5c3_Err 79 } 80 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " <a class=\"text-text underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"?raw\">raw</a> ") 81 + if templ_7745c5c3_Err != nil { 82 + return templ_7745c5c3_Err 83 + } 84 var templ_7745c5c3_Var4 string 85 templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(" - ") 86 if templ_7745c5c3_Err != nil { 87 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 25, Col: 10} 88 } 89 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 90 if templ_7745c5c3_Err != nil { 91 return templ_7745c5c3_Err 92 } 93 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, " <a class=\"text-text underline decoration-text/50 decoration-dashed hover:decoration-solid\" id=\"permalink\" data-permalink=\"") 94 if templ_7745c5c3_Err != nil { 95 return templ_7745c5c3_Err 96 } 97 + var templ_7745c5c3_Var5 string 98 + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(rfc.Permalink()) 99 + if templ_7745c5c3_Err != nil { 100 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 26, Col: 141} 101 + } 102 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 103 + if templ_7745c5c3_Err != nil { 104 + return templ_7745c5c3_Err 105 + } 106 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" href=\"") 107 + if templ_7745c5c3_Err != nil { 108 + return templ_7745c5c3_Err 109 + } 110 + var templ_7745c5c3_Var6 templ.SafeURL 111 + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(rfc.Permalink()) 112 + if templ_7745c5c3_Err != nil { 113 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_file.templ`, Line: 26, Col: 166} 114 + } 115 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 116 if templ_7745c5c3_Err != nil { 117 return templ_7745c5c3_Err 118 } 119 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">permalink</a><div class=\"code relative\">") 120 if templ_7745c5c3_Err != nil { 121 return templ_7745c5c3_Err 122 } ··· 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 }
+71 -50
internal/html/repo_log_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.501 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 } 64 var templ_7745c5c3_Var4 string 65 templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Short()) 66 if templ_7745c5c3_Err != nil { 67 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 18, Col: 209} 68 } 69 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 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 } 82 var templ_7745c5c3_Var5 string 83 templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Summary()) 84 if templ_7745c5c3_Err != nil { 85 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 22, Col: 58} 86 } 87 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 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 } 95 var templ_7745c5c3_Var6 string 96 templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Details()) 97 if templ_7745c5c3_Err != nil { 98 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 23, Col: 59} 99 } 100 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 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 } ··· 109 var templ_7745c5c3_Var7 string 110 templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Message) 111 if templ_7745c5c3_Err != nil { 112 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 26, Col: 23} 113 } 114 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 115 if templ_7745c5c3_Err != nil { 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 } 123 var templ_7745c5c3_Var8 string 124 templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Author) 125 if templ_7745c5c3_Err != nil { 126 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 31, Col: 25} 127 } 128 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) 129 if templ_7745c5c3_Err != nil { ··· 132 var templ_7745c5c3_Var9 string 133 templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 134 if templ_7745c5c3_Err != nil { 135 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 31, Col: 32} 136 } 137 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) 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 } 154 var templ_7745c5c3_Var11 string 155 templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("<%s>", commit.Email)) 156 if templ_7745c5c3_Err != nil { 157 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 31, Col: 213} 158 } 159 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) 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 } 167 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(commit.When.Format("01/02/2006 03:04:05 PM"))) 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_Var12 string 176 - templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(humanize.Time(commit.When)) 177 if templ_7745c5c3_Err != nil { 178 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 32, Col: 93} 179 } 180 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) 181 if templ_7745c5c3_Err != nil { 182 return templ_7745c5c3_Err 183 } 184 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div>") 185 if templ_7745c5c3_Err != nil { 186 return templ_7745c5c3_Err 187 } 188 } 189 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 190 if templ_7745c5c3_Err != nil { 191 return templ_7745c5c3_Err 192 } 193 - if !templ_7745c5c3_IsBuffer { 194 - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) 195 - } 196 - return templ_7745c5c3_Err 197 }) 198 templ_7745c5c3_Err = base(rlc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 199 if templ_7745c5c3_Err != nil { 200 return templ_7745c5c3_Err 201 } 202 - if !templ_7745c5c3_IsBuffer { 203 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 204 - } 205 - return templ_7745c5c3_Err 206 }) 207 }
··· 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 } 80 var templ_7745c5c3_Var4 string 81 templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Short()) 82 if templ_7745c5c3_Err != nil { 83 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 19, Col: 209} 84 } 85 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 86 if templ_7745c5c3_Err != nil { 87 return templ_7745c5c3_Err 88 } 89 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</a></div><div class=\"whitespace-pre\">") 90 if templ_7745c5c3_Err != nil { 91 return templ_7745c5c3_Err 92 } 93 if commit.Details() != "" { 94 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<details><summary class=\"cursor-pointer\">") 95 if templ_7745c5c3_Err != nil { 96 return templ_7745c5c3_Err 97 } 98 var templ_7745c5c3_Var5 string 99 templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Summary()) 100 if templ_7745c5c3_Err != nil { 101 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 23, Col: 58} 102 } 103 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 104 if templ_7745c5c3_Err != nil { 105 return templ_7745c5c3_Err 106 } 107 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</summary><div class=\"p-3 bg-base rounded\">") 108 if templ_7745c5c3_Err != nil { 109 return templ_7745c5c3_Err 110 } 111 var templ_7745c5c3_Var6 string 112 templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Details()) 113 if templ_7745c5c3_Err != nil { 114 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 24, Col: 59} 115 } 116 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 117 if templ_7745c5c3_Err != nil { 118 return templ_7745c5c3_Err 119 } 120 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div></details>") 121 if templ_7745c5c3_Err != nil { 122 return templ_7745c5c3_Err 123 } ··· 125 var templ_7745c5c3_Var7 string 126 templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Message) 127 if templ_7745c5c3_Err != nil { 128 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 27, Col: 23} 129 } 130 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 131 if templ_7745c5c3_Err != nil { 132 return templ_7745c5c3_Err 133 } 134 } 135 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div></div><div class=\"sm:col-span-3 mb-4\"><div>") 136 if templ_7745c5c3_Err != nil { 137 return templ_7745c5c3_Err 138 } 139 var templ_7745c5c3_Var8 string 140 templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Author) 141 if templ_7745c5c3_Err != nil { 142 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 32, Col: 25} 143 } 144 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) 145 if templ_7745c5c3_Err != nil { ··· 148 var templ_7745c5c3_Var9 string 149 templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 150 if templ_7745c5c3_Err != nil { 151 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 32, Col: 32} 152 } 153 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) 154 if templ_7745c5c3_Err != nil { 155 return templ_7745c5c3_Err 156 } 157 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 158 if templ_7745c5c3_Err != nil { 159 return templ_7745c5c3_Err 160 } 161 + var templ_7745c5c3_Var10 templ.SafeURL 162 + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("mailto:%s", commit.Email))) 163 + if templ_7745c5c3_Err != nil { 164 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 32, Col: 175} 165 + } 166 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) 167 if templ_7745c5c3_Err != nil { 168 return templ_7745c5c3_Err 169 } 170 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\">") 171 if templ_7745c5c3_Err != nil { 172 return templ_7745c5c3_Err 173 } 174 var templ_7745c5c3_Var11 string 175 templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("<%s>", commit.Email)) 176 if templ_7745c5c3_Err != nil { 177 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 32, Col: 213} 178 } 179 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) 180 if templ_7745c5c3_Err != nil { 181 return templ_7745c5c3_Err 182 } 183 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</a></div><div title=\"") 184 if templ_7745c5c3_Err != nil { 185 return templ_7745c5c3_Err 186 } 187 + var templ_7745c5c3_Var12 string 188 + templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(commit.When.Format("01/02/2006 03:04:05 PM")) 189 + if templ_7745c5c3_Err != nil { 190 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 33, Col: 62} 191 + } 192 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) 193 if templ_7745c5c3_Err != nil { 194 return templ_7745c5c3_Err 195 } 196 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\">") 197 if templ_7745c5c3_Err != nil { 198 return templ_7745c5c3_Err 199 } 200 + var templ_7745c5c3_Var13 string 201 + templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(humanize.Time(commit.When)) 202 if templ_7745c5c3_Err != nil { 203 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_log.templ`, Line: 33, Col: 93} 204 } 205 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) 206 if templ_7745c5c3_Err != nil { 207 return templ_7745c5c3_Err 208 } 209 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div></div>") 210 if templ_7745c5c3_Err != nil { 211 return templ_7745c5c3_Err 212 } 213 } 214 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</div>") 215 if templ_7745c5c3_Err != nil { 216 return templ_7745c5c3_Err 217 } 218 + return nil 219 }) 220 templ_7745c5c3_Err = base(rlc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 221 if templ_7745c5c3_Err != nil { 222 return templ_7745c5c3_Err 223 } 224 + return nil 225 }) 226 } 227 + 228 + var _ = templruntime.GeneratedTemplate
+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 }
+89 -128
internal/html/repo_refs_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.501 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\">") 52 - if templ_7745c5c3_Err != nil { 53 - return templ_7745c5c3_Err 54 - } 55 - templ_7745c5c3_Var3 := `Branches` 56 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3) 57 - if templ_7745c5c3_Err != nil { 58 - return templ_7745c5c3_Err 59 - } 60 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h3><div class=\"text-text grid grid-cols-4 sm:grid-cols-8\">") 61 if templ_7745c5c3_Err != nil { 62 return templ_7745c5c3_Err 63 } 64 for _, branch := range rrc.Branches { 65 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"col-span-2 sm:col-span-1 font-bold\">") 66 if templ_7745c5c3_Err != nil { 67 return templ_7745c5c3_Err 68 } 69 - var templ_7745c5c3_Var4 string 70 - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(branch) 71 if templ_7745c5c3_Err != nil { 72 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 19, Col: 61} 73 } 74 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 75 if templ_7745c5c3_Err != nil { 76 return templ_7745c5c3_Err 77 } 78 - _, 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=\"") 79 if templ_7745c5c3_Err != nil { 80 return templ_7745c5c3_Err 81 } 82 - var templ_7745c5c3_Var5 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rrc.RepoHeaderComponentContext.Name, branch)) 83 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var5))) 84 if templ_7745c5c3_Err != nil { 85 - return templ_7745c5c3_Err 86 } 87 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 88 if templ_7745c5c3_Err != nil { 89 return templ_7745c5c3_Err 90 } 91 - templ_7745c5c3_Var6 := `tree` 92 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var6) 93 - if templ_7745c5c3_Err != nil { 94 - return templ_7745c5c3_Err 95 - } 96 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>") 97 if templ_7745c5c3_Err != nil { 98 return templ_7745c5c3_Err 99 } 100 - var templ_7745c5c3_Var7 string 101 - templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 102 - if templ_7745c5c3_Err != nil { 103 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 20, Col: 234} 104 - } 105 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 106 if templ_7745c5c3_Err != nil { 107 - return templ_7745c5c3_Err 108 } 109 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 110 if templ_7745c5c3_Err != nil { 111 return templ_7745c5c3_Err 112 } 113 - var templ_7745c5c3_Var8 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/log/%s", rrc.RepoHeaderComponentContext.Name, branch)) 114 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var8))) 115 if templ_7745c5c3_Err != nil { 116 return templ_7745c5c3_Err 117 } 118 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 119 if templ_7745c5c3_Err != nil { 120 - return templ_7745c5c3_Err 121 } 122 - templ_7745c5c3_Var9 := `log` 123 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9) 124 if templ_7745c5c3_Err != nil { 125 return templ_7745c5c3_Err 126 } 127 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div>") 128 if templ_7745c5c3_Err != nil { 129 return templ_7745c5c3_Err 130 } 131 } 132 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 133 if templ_7745c5c3_Err != nil { 134 return templ_7745c5c3_Err 135 } 136 } 137 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 138 if templ_7745c5c3_Err != nil { 139 return templ_7745c5c3_Err 140 } 141 if len(rrc.Tags) > 0 { 142 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h3 class=\"text-text text-lg mt-5\">") 143 - if templ_7745c5c3_Err != nil { 144 - return templ_7745c5c3_Err 145 - } 146 - templ_7745c5c3_Var10 := `Tags` 147 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var10) 148 - if templ_7745c5c3_Err != nil { 149 - return templ_7745c5c3_Err 150 - } 151 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h3><div class=\"text-text grid grid-cols-8\">") 152 if templ_7745c5c3_Err != nil { 153 return templ_7745c5c3_Err 154 } 155 for _, tag := range rrc.Tags { 156 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"col-span-1 font-bold\">") 157 if templ_7745c5c3_Err != nil { 158 return templ_7745c5c3_Err 159 } 160 - var templ_7745c5c3_Var11 string 161 - templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(tag.Name) 162 if templ_7745c5c3_Err != nil { 163 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 28, Col: 49} 164 } 165 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) 166 if templ_7745c5c3_Err != nil { 167 return templ_7745c5c3_Err 168 } 169 - _, 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=\"") 170 if templ_7745c5c3_Err != nil { 171 return templ_7745c5c3_Err 172 } 173 - var templ_7745c5c3_Var12 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rrc.RepoHeaderComponentContext.Name, tag.Name)) 174 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var12))) 175 - if templ_7745c5c3_Err != nil { 176 - return templ_7745c5c3_Err 177 - } 178 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 179 if templ_7745c5c3_Err != nil { 180 - return templ_7745c5c3_Err 181 } 182 - templ_7745c5c3_Var13 := `tree` 183 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var13) 184 if templ_7745c5c3_Err != nil { 185 return templ_7745c5c3_Err 186 } 187 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>") 188 if templ_7745c5c3_Err != nil { 189 return templ_7745c5c3_Err 190 } 191 - var templ_7745c5c3_Var14 string 192 - templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 193 if templ_7745c5c3_Err != nil { 194 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 29, Col: 222} 195 } 196 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) 197 if templ_7745c5c3_Err != nil { 198 return templ_7745c5c3_Err 199 } 200 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 201 if templ_7745c5c3_Err != nil { 202 return templ_7745c5c3_Err 203 } 204 - var templ_7745c5c3_Var15 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/log/%s", rrc.RepoHeaderComponentContext.Name, tag.Name)) 205 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var15))) 206 if templ_7745c5c3_Err != nil { 207 - return templ_7745c5c3_Err 208 - } 209 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 210 - if templ_7745c5c3_Err != nil { 211 - return templ_7745c5c3_Err 212 } 213 - templ_7745c5c3_Var16 := `log` 214 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var16) 215 if templ_7745c5c3_Err != nil { 216 return templ_7745c5c3_Err 217 } 218 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div>") 219 if templ_7745c5c3_Err != nil { 220 return templ_7745c5c3_Err 221 } 222 if tag.Signature != "" { 223 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<details class=\"col-span-8 whitespace-pre\"><summary class=\"cursor-pointer\">") 224 if templ_7745c5c3_Err != nil { 225 return templ_7745c5c3_Err 226 } 227 - templ_7745c5c3_Var17 := `Signature` 228 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var17) 229 if templ_7745c5c3_Err != nil { 230 - return templ_7745c5c3_Err 231 } 232 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</summary><code>") 233 if templ_7745c5c3_Err != nil { 234 return templ_7745c5c3_Err 235 } 236 - var templ_7745c5c3_Var18 string 237 - templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(tag.Signature) 238 - if templ_7745c5c3_Err != nil { 239 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 31, Col: 121} 240 - } 241 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) 242 - if templ_7745c5c3_Err != nil { 243 - return templ_7745c5c3_Err 244 - } 245 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</code></details>") 246 if templ_7745c5c3_Err != nil { 247 return templ_7745c5c3_Err 248 } 249 } 250 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 251 if templ_7745c5c3_Err != nil { 252 return templ_7745c5c3_Err 253 } 254 if tag.Annotation != "" { 255 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"col-span-8 mb-3\">") 256 if templ_7745c5c3_Err != nil { 257 return templ_7745c5c3_Err 258 } 259 - var templ_7745c5c3_Var19 string 260 - templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(tag.Annotation) 261 if templ_7745c5c3_Err != nil { 262 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 34, Col: 51} 263 } 264 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) 265 if templ_7745c5c3_Err != nil { 266 return templ_7745c5c3_Err 267 } 268 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 269 if templ_7745c5c3_Err != nil { 270 return templ_7745c5c3_Err 271 } 272 } 273 } 274 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 275 if templ_7745c5c3_Err != nil { 276 return templ_7745c5c3_Err 277 } 278 } 279 - if !templ_7745c5c3_IsBuffer { 280 - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) 281 - } 282 - return templ_7745c5c3_Err 283 }) 284 templ_7745c5c3_Err = base(rrc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 285 if templ_7745c5c3_Err != nil { 286 return templ_7745c5c3_Err 287 } 288 - if !templ_7745c5c3_IsBuffer { 289 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 290 - } 291 - return templ_7745c5c3_Err 292 }) 293 }
··· 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 } 72 + var templ_7745c5c3_Var3 string 73 + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(branch) 74 if templ_7745c5c3_Err != nil { 75 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 20, Col: 61} 76 } 77 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 78 if templ_7745c5c3_Err != nil { 79 return templ_7745c5c3_Err 80 } 81 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</div><div class=\"col-span-2 sm:col-span-7\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 82 if templ_7745c5c3_Err != nil { 83 return templ_7745c5c3_Err 84 } 85 + var templ_7745c5c3_Var4 templ.SafeURL 86 + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rrc.RepoHeaderComponentContext.Name, branch))) 87 if templ_7745c5c3_Err != nil { 88 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 21, Col: 218} 89 } 90 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 91 if templ_7745c5c3_Err != nil { 92 return templ_7745c5c3_Err 93 } 94 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">tree</a>") 95 if templ_7745c5c3_Err != nil { 96 return templ_7745c5c3_Err 97 } 98 + var templ_7745c5c3_Var5 string 99 + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 100 if templ_7745c5c3_Err != nil { 101 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 21, Col: 234} 102 } 103 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 104 if templ_7745c5c3_Err != nil { 105 return templ_7745c5c3_Err 106 } 107 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 108 if templ_7745c5c3_Err != nil { 109 return templ_7745c5c3_Err 110 } 111 + var templ_7745c5c3_Var6 templ.SafeURL 112 + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/log/%s", rrc.RepoHeaderComponentContext.Name, branch))) 113 if templ_7745c5c3_Err != nil { 114 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 21, Col: 409} 115 } 116 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 117 if templ_7745c5c3_Err != nil { 118 return templ_7745c5c3_Err 119 } 120 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\">log</a></div>") 121 if templ_7745c5c3_Err != nil { 122 return templ_7745c5c3_Err 123 } 124 } 125 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div>") 126 if templ_7745c5c3_Err != nil { 127 return templ_7745c5c3_Err 128 } 129 } 130 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " ") 131 if templ_7745c5c3_Err != nil { 132 return templ_7745c5c3_Err 133 } 134 if len(rrc.Tags) > 0 { 135 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<h3 class=\"text-text text-lg mt-5\">Tags</h3><div class=\"text-text grid grid-cols-8\">") 136 if templ_7745c5c3_Err != nil { 137 return templ_7745c5c3_Err 138 } 139 for _, tag := range rrc.Tags { 140 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"col-span-1 font-bold\">") 141 if templ_7745c5c3_Err != nil { 142 return templ_7745c5c3_Err 143 } 144 + var templ_7745c5c3_Var7 string 145 + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(tag.Name) 146 if templ_7745c5c3_Err != nil { 147 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 29, Col: 49} 148 } 149 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 150 if templ_7745c5c3_Err != nil { 151 return templ_7745c5c3_Err 152 } 153 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div><div class=\"col-span-7\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 154 if templ_7745c5c3_Err != nil { 155 return templ_7745c5c3_Err 156 } 157 + var templ_7745c5c3_Var8 templ.SafeURL 158 + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rrc.RepoHeaderComponentContext.Name, tag.Name))) 159 if templ_7745c5c3_Err != nil { 160 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 30, Col: 206} 161 } 162 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) 163 if templ_7745c5c3_Err != nil { 164 return templ_7745c5c3_Err 165 } 166 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\">tree</a>") 167 if templ_7745c5c3_Err != nil { 168 return templ_7745c5c3_Err 169 } 170 + var templ_7745c5c3_Var9 string 171 + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 172 if templ_7745c5c3_Err != nil { 173 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 30, Col: 222} 174 } 175 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) 176 if templ_7745c5c3_Err != nil { 177 return templ_7745c5c3_Err 178 } 179 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 180 if templ_7745c5c3_Err != nil { 181 return templ_7745c5c3_Err 182 } 183 + var templ_7745c5c3_Var10 templ.SafeURL 184 + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/log/%s", rrc.RepoHeaderComponentContext.Name, tag.Name))) 185 if templ_7745c5c3_Err != nil { 186 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 30, Col: 399} 187 } 188 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) 189 if templ_7745c5c3_Err != nil { 190 return templ_7745c5c3_Err 191 } 192 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\">log</a></div>") 193 if templ_7745c5c3_Err != nil { 194 return templ_7745c5c3_Err 195 } 196 if tag.Signature != "" { 197 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<details class=\"col-span-8 whitespace-pre\"><summary class=\"cursor-pointer\">Signature</summary><code>") 198 if templ_7745c5c3_Err != nil { 199 return templ_7745c5c3_Err 200 } 201 + var templ_7745c5c3_Var11 string 202 + templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(tag.Signature) 203 if templ_7745c5c3_Err != nil { 204 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 32, Col: 121} 205 } 206 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) 207 if templ_7745c5c3_Err != nil { 208 return templ_7745c5c3_Err 209 } 210 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</code></details>") 211 if templ_7745c5c3_Err != nil { 212 return templ_7745c5c3_Err 213 } 214 } 215 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, " ") 216 if templ_7745c5c3_Err != nil { 217 return templ_7745c5c3_Err 218 } 219 if tag.Annotation != "" { 220 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<div class=\"col-span-8 mb-3\">") 221 if templ_7745c5c3_Err != nil { 222 return templ_7745c5c3_Err 223 } 224 + var templ_7745c5c3_Var12 string 225 + templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(tag.Annotation) 226 if templ_7745c5c3_Err != nil { 227 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_refs.templ`, Line: 35, Col: 51} 228 } 229 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) 230 if templ_7745c5c3_Err != nil { 231 return templ_7745c5c3_Err 232 } 233 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</div>") 234 if templ_7745c5c3_Err != nil { 235 return templ_7745c5c3_Err 236 } 237 } 238 } 239 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</div>") 240 if templ_7745c5c3_Err != nil { 241 return templ_7745c5c3_Err 242 } 243 } 244 + return nil 245 }) 246 templ_7745c5c3_Err = base(rrc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 247 if templ_7745c5c3_Err != nil { 248 return templ_7745c5c3_Err 249 } 250 + return nil 251 }) 252 } 253 + 254 + var _ = templruntime.GeneratedTemplate
+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
+88 -99
internal/html/repo_search_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.501 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 65 } 66 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 67 - if templ_7745c5c3_Err != nil { 68 - return templ_7745c5c3_Err 69 - } 70 for _, results := range sc.DedupeResults() { 71 templ_7745c5c3_Err = repoSearchResult(sc.RepoHeaderComponentContext.Name, sc.RepoHeaderComponentContext.Ref, results).Render(ctx, templ_7745c5c3_Buffer) 72 if templ_7745c5c3_Err != nil { 73 return templ_7745c5c3_Err 74 } 75 } 76 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 77 if templ_7745c5c3_Err != nil { 78 return templ_7745c5c3_Err 79 } 80 if len(sc.DedupeResults()) == 0 { 81 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p class=\"text-text mt-5 text-lg\">") 82 - if templ_7745c5c3_Err != nil { 83 - return templ_7745c5c3_Err 84 - } 85 - templ_7745c5c3_Var3 := `No results` 86 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3) 87 - if templ_7745c5c3_Err != nil { 88 - return templ_7745c5c3_Err 89 - } 90 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p>") 91 if templ_7745c5c3_Err != nil { 92 return templ_7745c5c3_Err 93 } 94 } 95 - if !templ_7745c5c3_IsBuffer { 96 - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) 97 - } 98 - return templ_7745c5c3_Err 99 }) 100 templ_7745c5c3_Err = base(sc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 101 if templ_7745c5c3_Err != nil { 102 return templ_7745c5c3_Err 103 } 104 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<script>") 105 - if templ_7745c5c3_Err != nil { 106 - return templ_7745c5c3_Err 107 - } 108 - templ_7745c5c3_Var4 := ` 109 - const search = new URLSearchParams(window.location.search).get("q"); 110 - if (search !== "") document.querySelector("#search").value = search; 111 - ` 112 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4) 113 if templ_7745c5c3_Err != nil { 114 return templ_7745c5c3_Err 115 } 116 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</script>") 117 - if templ_7745c5c3_Err != nil { 118 - return templ_7745c5c3_Err 119 - } 120 - if !templ_7745c5c3_IsBuffer { 121 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 122 - } 123 - return templ_7745c5c3_Err 124 }) 125 } 126 127 func repoSearchResult(repo, ref string, results []git.GrepResult) templ.Component { 128 - return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { 129 - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) 130 if !templ_7745c5c3_IsBuffer { 131 - templ_7745c5c3_Buffer = templ.GetBuffer() 132 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 133 } 134 ctx = templ.InitializeContext(ctx) 135 - templ_7745c5c3_Var5 := templ.GetChildren(ctx) 136 - if templ_7745c5c3_Var5 == nil { 137 - templ_7745c5c3_Var5 = templ.NopComponent 138 } 139 ctx = templ.ClearChildren(ctx) 140 - _, 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=\"") 141 if templ_7745c5c3_Err != nil { 142 return templ_7745c5c3_Err 143 } 144 - var templ_7745c5c3_Var6 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, results[0].File, results[0].Line)) 145 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var6))) 146 if templ_7745c5c3_Err != nil { 147 return templ_7745c5c3_Err 148 } 149 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 150 if templ_7745c5c3_Err != nil { 151 return templ_7745c5c3_Err 152 } 153 - var templ_7745c5c3_Var7 string 154 - templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(results[0].File) 155 if templ_7745c5c3_Err != nil { 156 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 49, Col: 230} 157 } 158 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 159 if templ_7745c5c3_Err != nil { 160 return templ_7745c5c3_Err 161 } 162 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div class=\"code\">") 163 if templ_7745c5c3_Err != nil { 164 return templ_7745c5c3_Err 165 } ··· 167 if templ_7745c5c3_Err != nil { 168 return templ_7745c5c3_Err 169 } 170 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 171 if templ_7745c5c3_Err != nil { 172 return templ_7745c5c3_Err 173 } 174 if len(results) > 1 { 175 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<details class=\"text-text cursor-pointer\"><summary>") 176 if templ_7745c5c3_Err != nil { 177 return templ_7745c5c3_Err 178 } 179 - var templ_7745c5c3_Var8 string 180 - templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d ", len(results[1:]))) 181 if templ_7745c5c3_Err != nil { 182 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 55, Col: 50} 183 } 184 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) 185 if templ_7745c5c3_Err != nil { 186 return templ_7745c5c3_Err 187 } 188 - templ_7745c5c3_Var9 := `more` 189 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9) 190 - if templ_7745c5c3_Err != nil { 191 - return templ_7745c5c3_Err 192 - } 193 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</summary> ") 194 if templ_7745c5c3_Err != nil { 195 return templ_7745c5c3_Err 196 } 197 for _, result := range results[1:] { 198 - _, 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=\"") 199 if templ_7745c5c3_Err != nil { 200 return templ_7745c5c3_Err 201 } 202 - var templ_7745c5c3_Var10 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, result.File, result.Line)) 203 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var10))) 204 if templ_7745c5c3_Err != nil { 205 return templ_7745c5c3_Err 206 } 207 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 208 if templ_7745c5c3_Err != nil { 209 return templ_7745c5c3_Err 210 } 211 - var templ_7745c5c3_Var11 string 212 - templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(results[0].File) 213 if templ_7745c5c3_Err != nil { 214 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 57, Col: 230} 215 } 216 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) 217 if templ_7745c5c3_Err != nil { 218 return templ_7745c5c3_Err 219 } 220 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></div><div class=\"code ml-5\">") 221 if templ_7745c5c3_Err != nil { 222 return templ_7745c5c3_Err 223 } ··· 225 if templ_7745c5c3_Err != nil { 226 return templ_7745c5c3_Err 227 } 228 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 229 if templ_7745c5c3_Err != nil { 230 return templ_7745c5c3_Err 231 } 232 } 233 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</details>") 234 if templ_7745c5c3_Err != nil { 235 return templ_7745c5c3_Err 236 } 237 } 238 - if !templ_7745c5c3_IsBuffer { 239 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 240 - } 241 - return templ_7745c5c3_Err 242 }) 243 }
··· 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 75 } 76 for _, results := range sc.DedupeResults() { 77 templ_7745c5c3_Err = repoSearchResult(sc.RepoHeaderComponentContext.Name, sc.RepoHeaderComponentContext.Ref, results).Render(ctx, templ_7745c5c3_Buffer) 78 if templ_7745c5c3_Err != nil { 79 return templ_7745c5c3_Err 80 } 81 } 82 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ") 83 if templ_7745c5c3_Err != nil { 84 return templ_7745c5c3_Err 85 } 86 if len(sc.DedupeResults()) == 0 { 87 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<p class=\"text-text mt-5 text-lg\">No results</p>") 88 if templ_7745c5c3_Err != nil { 89 return templ_7745c5c3_Err 90 } 91 } 92 + return nil 93 }) 94 templ_7745c5c3_Err = base(sc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 95 if templ_7745c5c3_Err != nil { 96 return templ_7745c5c3_Err 97 } 98 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<script>\n\t\tconst search = new URLSearchParams(window.location.search).get(\"q\");\n\t\tif (search !== \"\") document.querySelector(\"#search\").value = search;\n\t</script>") 99 if templ_7745c5c3_Err != nil { 100 return templ_7745c5c3_Err 101 } 102 + return nil 103 }) 104 } 105 106 func repoSearchResult(repo, ref string, results []git.GrepResult) templ.Component { 107 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 108 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 109 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 110 + return templ_7745c5c3_CtxErr 111 + } 112 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 113 if !templ_7745c5c3_IsBuffer { 114 + defer func() { 115 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 116 + if templ_7745c5c3_Err == nil { 117 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 118 + } 119 + }() 120 } 121 ctx = templ.InitializeContext(ctx) 122 + templ_7745c5c3_Var3 := templ.GetChildren(ctx) 123 + if templ_7745c5c3_Var3 == nil { 124 + templ_7745c5c3_Var3 = templ.NopComponent 125 } 126 ctx = templ.ClearChildren(ctx) 127 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div class=\"text-text mt-5\"><a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 128 if templ_7745c5c3_Err != nil { 129 return templ_7745c5c3_Err 130 } 131 + var templ_7745c5c3_Var4 templ.SafeURL 132 + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, results[0].File, results[0].Line))) 133 + if templ_7745c5c3_Err != nil { 134 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 48, Col: 210} 135 + } 136 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 137 if templ_7745c5c3_Err != nil { 138 return templ_7745c5c3_Err 139 } 140 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">") 141 if templ_7745c5c3_Err != nil { 142 return templ_7745c5c3_Err 143 } 144 + var templ_7745c5c3_Var5 string 145 + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(results[0].File) 146 if templ_7745c5c3_Err != nil { 147 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 48, Col: 230} 148 } 149 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 150 if templ_7745c5c3_Err != nil { 151 return templ_7745c5c3_Err 152 } 153 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</a></div><div class=\"code\">") 154 if templ_7745c5c3_Err != nil { 155 return templ_7745c5c3_Err 156 } ··· 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
+103 -72
internal/html/repo_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.501 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 ··· 17 Ref string 18 Description string 19 CloneURL string 20 } 21 22 func repoHeaderComponent(rhcc RepoHeaderComponentContext) templ.Component { 23 - return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { 24 - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) 25 if !templ_7745c5c3_IsBuffer { 26 - templ_7745c5c3_Buffer = templ.GetBuffer() 27 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 28 } 29 ctx = templ.InitializeContext(ctx) 30 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 32 templ_7745c5c3_Var1 = templ.NopComponent 33 } 34 ctx = templ.ClearChildren(ctx) 35 - _, 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=\"") 36 if templ_7745c5c3_Err != nil { 37 return templ_7745c5c3_Err 38 } 39 - var templ_7745c5c3_Var2 templ.SafeURL = templ.SafeURL("/" + rhcc.Name) 40 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var2))) 41 if templ_7745c5c3_Err != nil { 42 return templ_7745c5c3_Err 43 } 44 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 45 if templ_7745c5c3_Err != nil { 46 return templ_7745c5c3_Err 47 } 48 var templ_7745c5c3_Var3 string 49 templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(rhcc.Name) 50 if templ_7745c5c3_Err != nil { 51 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 13, Col: 142} 52 } 53 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 54 if templ_7745c5c3_Err != nil { 55 return templ_7745c5c3_Err 56 } 57 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a> ") 58 if templ_7745c5c3_Err != nil { 59 return templ_7745c5c3_Err 60 } ··· 62 var templ_7745c5c3_Var4 string 63 templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 64 if templ_7745c5c3_Err != nil { 65 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 15, Col: 8} 66 } 67 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 68 if templ_7745c5c3_Err != nil { 69 return templ_7745c5c3_Err 70 } 71 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <a class=\"text-text/80 text-sm underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 72 if templ_7745c5c3_Err != nil { 73 return templ_7745c5c3_Err 74 } 75 - var templ_7745c5c3_Var5 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rhcc.Name, rhcc.Ref)) 76 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var5))) 77 if templ_7745c5c3_Err != nil { 78 return templ_7745c5c3_Err 79 } 80 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 81 if templ_7745c5c3_Err != nil { 82 return templ_7745c5c3_Err 83 } 84 var templ_7745c5c3_Var6 string 85 templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs("@" + rhcc.Ref) 86 if templ_7745c5c3_Err != nil { 87 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 16, Col: 194} 88 } 89 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 90 if templ_7745c5c3_Err != nil { 91 return templ_7745c5c3_Err 92 } 93 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>") 94 if templ_7745c5c3_Err != nil { 95 return templ_7745c5c3_Err 96 } ··· 98 var templ_7745c5c3_Var7 string 99 templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(" - ") 100 if templ_7745c5c3_Err != nil { 101 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 18, Col: 9} 102 } 103 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 104 if templ_7745c5c3_Err != nil { 105 return templ_7745c5c3_Err 106 } 107 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <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_Var8 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/refs", rhcc.Name)) 112 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var8))) 113 if templ_7745c5c3_Err != nil { 114 return templ_7745c5c3_Err 115 } 116 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 117 if templ_7745c5c3_Err != nil { 118 return templ_7745c5c3_Err 119 } 120 - templ_7745c5c3_Var9 := `refs` 121 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9) 122 if templ_7745c5c3_Err != nil { 123 return templ_7745c5c3_Err 124 } 125 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a> ") 126 if templ_7745c5c3_Err != nil { 127 return templ_7745c5c3_Err 128 } 129 - var templ_7745c5c3_Var10 string 130 - templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(" - ") 131 if templ_7745c5c3_Err != nil { 132 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 20, Col: 9} 133 } 134 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) 135 if templ_7745c5c3_Err != nil { 136 return templ_7745c5c3_Err 137 } 138 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 139 if templ_7745c5c3_Err != nil { 140 return templ_7745c5c3_Err 141 } 142 - var templ_7745c5c3_Var11 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/log/%s", rhcc.Name, rhcc.Ref)) 143 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var11))) 144 if templ_7745c5c3_Err != nil { 145 return templ_7745c5c3_Err 146 } 147 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 148 if templ_7745c5c3_Err != nil { 149 return templ_7745c5c3_Err 150 } 151 - templ_7745c5c3_Var12 := `log` 152 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var12) 153 if templ_7745c5c3_Err != nil { 154 return templ_7745c5c3_Err 155 } 156 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a> ") 157 if templ_7745c5c3_Err != nil { 158 return templ_7745c5c3_Err 159 } 160 var templ_7745c5c3_Var13 string 161 templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(" - ") 162 if templ_7745c5c3_Err != nil { 163 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 22, Col: 9} 164 } 165 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) 166 if templ_7745c5c3_Err != nil { 167 return templ_7745c5c3_Err 168 } 169 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<form class=\"inline-block\" action=\"") 170 if templ_7745c5c3_Err != nil { 171 return templ_7745c5c3_Err 172 } 173 - var templ_7745c5c3_Var14 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/search", rhcc.Name)) 174 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var14))) 175 if templ_7745c5c3_Err != nil { 176 - return templ_7745c5c3_Err 177 } 178 - _, 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>") 179 if templ_7745c5c3_Err != nil { 180 return templ_7745c5c3_Err 181 } 182 - var templ_7745c5c3_Var15 string 183 - templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(" - ") 184 if templ_7745c5c3_Err != nil { 185 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 24, Col: 9} 186 } 187 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) 188 - if templ_7745c5c3_Err != nil { 189 - return templ_7745c5c3_Err 190 } 191 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<pre class=\"text-text inline select-all bg-base dark:bg-base/50 p-1 rounded\">") 192 if templ_7745c5c3_Err != nil { 193 return templ_7745c5c3_Err 194 } 195 var templ_7745c5c3_Var16 string 196 - templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%s/%s.git", rhcc.CloneURL, rhcc.Name)) 197 if templ_7745c5c3_Err != nil { 198 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 25, Col: 131} 199 } 200 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) 201 if templ_7745c5c3_Err != nil { 202 return templ_7745c5c3_Err 203 } 204 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</pre></div><div class=\"text-text/80 mb-1\">") 205 if templ_7745c5c3_Err != nil { 206 return templ_7745c5c3_Err 207 } 208 - var templ_7745c5c3_Var17 string 209 - templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(rhcc.Description) 210 - if templ_7745c5c3_Err != nil { 211 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 27, Col: 50} 212 - } 213 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) 214 - if templ_7745c5c3_Err != nil { 215 - return templ_7745c5c3_Err 216 - } 217 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 218 - if templ_7745c5c3_Err != nil { 219 - return templ_7745c5c3_Err 220 - } 221 - if !templ_7745c5c3_IsBuffer { 222 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 223 - } 224 - return templ_7745c5c3_Err 225 }) 226 }
··· 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 ··· 15 Ref string 16 Description string 17 CloneURL string 18 + Tags []string 19 } 20 21 func repoHeaderComponent(rhcc RepoHeaderComponentContext) templ.Component { 22 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 23 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 24 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 25 + return templ_7745c5c3_CtxErr 26 + } 27 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 28 if !templ_7745c5c3_IsBuffer { 29 + defer func() { 30 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 31 + if templ_7745c5c3_Err == nil { 32 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 33 + } 34 + }() 35 } 36 ctx = templ.InitializeContext(ctx) 37 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 39 templ_7745c5c3_Var1 = templ.NopComponent 40 } 41 ctx = templ.ClearChildren(ctx) 42 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"mb-1 text-text\"><a class=\"text-lg underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 43 if templ_7745c5c3_Err != nil { 44 return templ_7745c5c3_Err 45 } 46 + var templ_7745c5c3_Var2 templ.SafeURL 47 + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL("/" + rhcc.Name)) 48 + if templ_7745c5c3_Err != nil { 49 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 15, Col: 128} 50 + } 51 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) 52 if templ_7745c5c3_Err != nil { 53 return templ_7745c5c3_Err 54 } 55 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\">") 56 if templ_7745c5c3_Err != nil { 57 return templ_7745c5c3_Err 58 } 59 var templ_7745c5c3_Var3 string 60 templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(rhcc.Name) 61 if templ_7745c5c3_Err != nil { 62 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 15, Col: 142} 63 } 64 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 65 if templ_7745c5c3_Err != nil { 66 return templ_7745c5c3_Err 67 } 68 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</a> ") 69 if templ_7745c5c3_Err != nil { 70 return templ_7745c5c3_Err 71 } ··· 73 var templ_7745c5c3_Var4 string 74 templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(" ") 75 if templ_7745c5c3_Err != nil { 76 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 17, Col: 8} 77 } 78 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 79 if templ_7745c5c3_Err != nil { 80 return templ_7745c5c3_Err 81 } 82 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " <a class=\"text-text/80 text-sm underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 83 if templ_7745c5c3_Err != nil { 84 return templ_7745c5c3_Err 85 } 86 + var templ_7745c5c3_Var5 templ.SafeURL 87 + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/tree/%s/", rhcc.Name, rhcc.Ref))) 88 + if templ_7745c5c3_Err != nil { 89 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 18, Col: 175} 90 + } 91 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 92 if templ_7745c5c3_Err != nil { 93 return templ_7745c5c3_Err 94 } 95 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">") 96 if templ_7745c5c3_Err != nil { 97 return templ_7745c5c3_Err 98 } 99 var templ_7745c5c3_Var6 string 100 templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs("@" + rhcc.Ref) 101 if templ_7745c5c3_Err != nil { 102 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 18, Col: 194} 103 } 104 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 105 if templ_7745c5c3_Err != nil { 106 return templ_7745c5c3_Err 107 } 108 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</a> ") 109 if templ_7745c5c3_Err != nil { 110 return templ_7745c5c3_Err 111 } ··· 113 var templ_7745c5c3_Var7 string 114 templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(" - ") 115 if templ_7745c5c3_Err != nil { 116 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 20, Col: 9} 117 } 118 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 119 if templ_7745c5c3_Err != nil { 120 return templ_7745c5c3_Err 121 } 122 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, " <a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 123 if templ_7745c5c3_Err != nil { 124 return templ_7745c5c3_Err 125 } 126 + var templ_7745c5c3_Var8 templ.SafeURL 127 + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/refs", rhcc.Name))) 128 + if templ_7745c5c3_Err != nil { 129 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 21, Col: 139} 130 + } 131 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) 132 if templ_7745c5c3_Err != nil { 133 return templ_7745c5c3_Err 134 } 135 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\">refs</a> ") 136 if templ_7745c5c3_Err != nil { 137 return templ_7745c5c3_Err 138 } 139 + var templ_7745c5c3_Var9 string 140 + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(" - ") 141 + if templ_7745c5c3_Err != nil { 142 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 22, Col: 9} 143 + } 144 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) 145 if templ_7745c5c3_Err != nil { 146 return templ_7745c5c3_Err 147 } 148 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " <a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"") 149 if templ_7745c5c3_Err != nil { 150 return templ_7745c5c3_Err 151 } 152 + var templ_7745c5c3_Var10 templ.SafeURL 153 + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/log/%s", rhcc.Name, rhcc.Ref))) 154 if templ_7745c5c3_Err != nil { 155 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 23, Col: 151} 156 } 157 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) 158 if templ_7745c5c3_Err != nil { 159 return templ_7745c5c3_Err 160 } 161 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\">log</a> ") 162 if templ_7745c5c3_Err != nil { 163 return templ_7745c5c3_Err 164 } 165 + var templ_7745c5c3_Var11 string 166 + templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(" - ") 167 + if templ_7745c5c3_Err != nil { 168 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 24, Col: 9} 169 + } 170 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) 171 if templ_7745c5c3_Err != nil { 172 return templ_7745c5c3_Err 173 } 174 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<form class=\"inline-block\" action=\"") 175 if templ_7745c5c3_Err != nil { 176 return templ_7745c5c3_Err 177 } 178 + var templ_7745c5c3_Var12 templ.SafeURL 179 + templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/%s/search", rhcc.Name))) 180 + if templ_7745c5c3_Err != nil { 181 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 25, Col: 89} 182 + } 183 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) 184 if templ_7745c5c3_Err != nil { 185 return templ_7745c5c3_Err 186 } 187 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\" method=\"get\"><input class=\"rounded p-1 bg-mantle focus:border-lavender focus:outline-none focus:ring-0\" id=\"search\" type=\"text\" name=\"q\" placeholder=\"search\"></form>") 188 if templ_7745c5c3_Err != nil { 189 return templ_7745c5c3_Err 190 } 191 var templ_7745c5c3_Var13 string 192 templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(" - ") 193 if templ_7745c5c3_Err != nil { 194 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 26, Col: 9} 195 } 196 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) 197 if templ_7745c5c3_Err != nil { 198 return templ_7745c5c3_Err 199 } 200 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<pre class=\"text-text inline select-all bg-base dark:bg-base/50 p-1 rounded\">") 201 if templ_7745c5c3_Err != nil { 202 return templ_7745c5c3_Err 203 } 204 + var templ_7745c5c3_Var14 string 205 + templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%s/%s.git", rhcc.CloneURL, rhcc.Name)) 206 if templ_7745c5c3_Err != nil { 207 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 27, Col: 131} 208 } 209 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) 210 if templ_7745c5c3_Err != nil { 211 return templ_7745c5c3_Err 212 } 213 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</pre></div><div class=\"text-subtext0 mb-1\">") 214 if templ_7745c5c3_Err != nil { 215 + return templ_7745c5c3_Err 216 } 217 + for _, tag := range rhcc.Tags { 218 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<span class=\"rounded border-rosewater border-solid border pb-0.5 px-1 mr-1 mb-1 inline-block\">") 219 + if templ_7745c5c3_Err != nil { 220 + return templ_7745c5c3_Err 221 + } 222 + var templ_7745c5c3_Var15 string 223 + templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(tag) 224 + if templ_7745c5c3_Err != nil { 225 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 31, Col: 102} 226 + } 227 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) 228 + if templ_7745c5c3_Err != nil { 229 + return templ_7745c5c3_Err 230 + } 231 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</span>") 232 + if templ_7745c5c3_Err != nil { 233 + return templ_7745c5c3_Err 234 + } 235 } 236 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</div><div class=\"text-text/80 mb-1\">") 237 if templ_7745c5c3_Err != nil { 238 return templ_7745c5c3_Err 239 } 240 var templ_7745c5c3_Var16 string 241 + templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(rhcc.Description) 242 if templ_7745c5c3_Err != nil { 243 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 34, Col: 50} 244 } 245 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) 246 if templ_7745c5c3_Err != nil { 247 return templ_7745c5c3_Err 248 } 249 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</div>") 250 if templ_7745c5c3_Err != nil { 251 return templ_7745c5c3_Err 252 } 253 + return nil 254 }) 255 } 256 + 257 + var _ = templruntime.GeneratedTemplate
+16 -15
internal/html/repo_tree.templ
··· 1 package html 2 3 import ( 4 - "fmt" 5 - "go.jolheiser.com/ugit/internal/git" 6 ) 7 8 type RepoTreeContext struct { 9 - BaseContext 10 RepoHeaderComponentContext 11 - RepoTreeComponentContext 12 - ReadmeComponentContext 13 - Description string 14 } 15 16 templ RepoTree(rtc RepoTreeContext) { 17 @base(rtc.BaseContext) { 18 @repoHeaderComponent(rtc.RepoHeaderComponentContext) 19 @repoTreeComponent(rtc.RepoTreeComponentContext) 20 @readmeComponent(rtc.ReadmeComponentContext) 21 } 22 } 23 24 type RepoTreeComponentContext struct { 25 - Repo string 26 - Ref string 27 - Tree []git.FileInfo 28 - Back string 29 } 30 31 func slashDir(name string, isDir bool) string { 32 - if isDir { 33 - return name + "/" 34 - } 35 - return name 36 } 37 38 templ repoTreeComponent(rtcc RepoTreeComponentContext) { ··· 48 } 49 </div> 50 } 51 -
··· 1 package html 2 3 import ( 4 + "fmt" 5 + "go.jolheiser.com/ugit/internal/git" 6 ) 7 8 type RepoTreeContext struct { 9 + BaseContext 10 RepoHeaderComponentContext 11 + RepoBreadcrumbComponentContext 12 + RepoTreeComponentContext 13 + ReadmeComponentContext 14 + Description string 15 } 16 17 templ RepoTree(rtc RepoTreeContext) { 18 @base(rtc.BaseContext) { 19 @repoHeaderComponent(rtc.RepoHeaderComponentContext) 20 + @repoBreadcrumbComponent(rtc.RepoBreadcrumbComponentContext) 21 @repoTreeComponent(rtc.RepoTreeComponentContext) 22 @readmeComponent(rtc.ReadmeComponentContext) 23 } 24 } 25 26 type RepoTreeComponentContext struct { 27 + Repo string 28 + Ref string 29 + Tree []git.FileInfo 30 + Back string 31 } 32 33 func slashDir(name string, isDir bool) string { 34 + if isDir { 35 + return name + "/" 36 + } 37 + return name 38 } 39 40 templ repoTreeComponent(rtcc RepoTreeComponentContext) { ··· 50 } 51 </div> 52 }
+83 -62
internal/html/repo_tree_templ.go
··· 1 // Code generated by templ - DO NOT EDIT. 2 3 - // templ: version: v0.2.501 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" ··· 18 type RepoTreeContext struct { 19 BaseContext 20 RepoHeaderComponentContext 21 RepoTreeComponentContext 22 ReadmeComponentContext 23 Description string 24 } 25 26 func RepoTree(rtc RepoTreeContext) templ.Component { 27 - return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { 28 - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) 29 if !templ_7745c5c3_IsBuffer { 30 - templ_7745c5c3_Buffer = templ.GetBuffer() 31 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 32 } 33 ctx = templ.InitializeContext(ctx) 34 templ_7745c5c3_Var1 := templ.GetChildren(ctx) ··· 36 templ_7745c5c3_Var1 = templ.NopComponent 37 } 38 ctx = templ.ClearChildren(ctx) 39 - templ_7745c5c3_Var2 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { 40 - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) 41 if !templ_7745c5c3_IsBuffer { 42 - templ_7745c5c3_Buffer = templ.GetBuffer() 43 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 44 } 45 templ_7745c5c3_Err = repoHeaderComponent(rtc.RepoHeaderComponentContext).Render(ctx, templ_7745c5c3_Buffer) 46 if templ_7745c5c3_Err != nil { 47 return templ_7745c5c3_Err 48 } 49 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 50 if templ_7745c5c3_Err != nil { 51 return templ_7745c5c3_Err 52 } ··· 54 if templ_7745c5c3_Err != nil { 55 return templ_7745c5c3_Err 56 } 57 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") 58 if templ_7745c5c3_Err != nil { 59 return templ_7745c5c3_Err 60 } ··· 62 if templ_7745c5c3_Err != nil { 63 return templ_7745c5c3_Err 64 } 65 - if !templ_7745c5c3_IsBuffer { 66 - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) 67 - } 68 - return templ_7745c5c3_Err 69 }) 70 templ_7745c5c3_Err = base(rtc.BaseContext).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 71 if templ_7745c5c3_Err != nil { 72 return templ_7745c5c3_Err 73 } 74 - if !templ_7745c5c3_IsBuffer { 75 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) 76 - } 77 - return templ_7745c5c3_Err 78 }) 79 } 80 ··· 93 } 94 95 func repoTreeComponent(rtcc RepoTreeComponentContext) templ.Component { 96 - return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { 97 - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) 98 if !templ_7745c5c3_IsBuffer { 99 - templ_7745c5c3_Buffer = templ.GetBuffer() 100 - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) 101 } 102 ctx = templ.InitializeContext(ctx) 103 templ_7745c5c3_Var3 := templ.GetChildren(ctx) ··· 105 templ_7745c5c3_Var3 = templ.NopComponent 106 } 107 ctx = templ.ClearChildren(ctx) 108 - _, 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\">") 109 if templ_7745c5c3_Err != nil { 110 return templ_7745c5c3_Err 111 } 112 if rtcc.Back != "" { 113 - _, 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=\"") 114 - if templ_7745c5c3_Err != nil { 115 - return templ_7745c5c3_Err 116 - } 117 - var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rtcc.Repo, rtcc.Ref, rtcc.Back)) 118 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4))) 119 if templ_7745c5c3_Err != nil { 120 return templ_7745c5c3_Err 121 } 122 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 123 if templ_7745c5c3_Err != nil { 124 - return templ_7745c5c3_Err 125 } 126 - templ_7745c5c3_Var5 := `..` 127 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var5) 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 } 141 - var templ_7745c5c3_Var6 string 142 - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fi.Mode) 143 if templ_7745c5c3_Err != nil { 144 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_tree.templ`, Line: 44, Col: 50} 145 } 146 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 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 } 154 - var templ_7745c5c3_Var7 string 155 - templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fi.Size) 156 if templ_7745c5c3_Err != nil { 157 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_tree.templ`, Line: 45, Col: 50} 158 } 159 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 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_Var8 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_Var8))) 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 } 176 - var templ_7745c5c3_Var9 string 177 - templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(slashDir(fi.Name(), fi.IsDir)) 178 if templ_7745c5c3_Err != nil { 179 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_tree.templ`, Line: 46, Col: 256} 180 } 181 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) 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" ··· 16 type RepoTreeContext struct { 17 BaseContext 18 RepoHeaderComponentContext 19 + RepoBreadcrumbComponentContext 20 RepoTreeComponentContext 21 ReadmeComponentContext 22 Description string 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 + } 66 + templ_7745c5c3_Err = repoBreadcrumbComponent(rtc.RepoBreadcrumbComponentContext).Render(ctx, templ_7745c5c3_Buffer) 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 } 159 + var templ_7745c5c3_Var5 string 160 + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(fi.Mode) 161 if templ_7745c5c3_Err != nil { 162 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_tree.templ`, Line: 47, Col: 50} 163 } 164 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 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 } 172 + var templ_7745c5c3_Var6 string 173 + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fi.Size) 174 if templ_7745c5c3_Err != nil { 175 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_tree.templ`, Line: 48, Col: 50} 176 } 177 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 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 } 198 + var templ_7745c5c3_Var8 string 199 + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(slashDir(fi.Name(), fi.IsDir)) 200 if templ_7745c5c3_Err != nil { 201 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_tree.templ`, Line: 49, Col: 256} 202 } 203 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) 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-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}.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-5{padding-left:1.25rem;padding-right:1.25rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.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-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 }
+17 -3
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 } 129 } 130
··· 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 + 133 + func (rh repoHandler) repoBreadcrumbContext(repo *git.Repo, r *http.Request, path string) html.RepoBreadcrumbComponentContext { 134 + ref := chi.URLParam(r, "ref") 135 + if ref == "" { 136 + ref, _ = repo.DefaultBranch() 137 + } 138 + return html.RepoBreadcrumbComponentContext{ 139 + Repo: chi.URLParam(r, "repo"), 140 + Ref: ref, 141 + Path: path, 142 } 143 } 144
+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 + }
+12 -2
internal/http/index.go
··· 18 return httperr.Error(err) 19 } 20 21 repos := make([]*git.Repo, 0, len(repoPaths)) 22 for _, repoName := range repoPaths { 23 if !strings.HasSuffix(repoName.Name(), ".git") { ··· 27 if err != nil { 28 return httperr.Error(err) 29 } 30 - if !repo.Meta.Private { 31 - repos = append(repos, repo) 32 } 33 } 34 sort.Slice(repos, func(i, j int) bool { 35 var when1, when2 time.Time
··· 18 return httperr.Error(err) 19 } 20 21 + tagFilter := r.URL.Query().Get("tag") 22 + 23 repos := make([]*git.Repo, 0, len(repoPaths)) 24 for _, repoName := range repoPaths { 25 if !strings.HasSuffix(repoName.Name(), ".git") { ··· 29 if err != nil { 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) 43 } 44 sort.Slice(repos, func(i, j int) bool { 45 var when1, when2 time.Time
+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)
+20 -10
internal/http/repo.go
··· 48 back = filepath.Dir(path) 49 } 50 if err := html.RepoTree(html.RepoTreeContext{ 51 - Description: repo.Meta.Description, 52 - BaseContext: rh.baseContext(), 53 - RepoHeaderComponentContext: rh.repoHeaderContext(repo, r), 54 RepoTreeComponentContext: html.RepoTreeComponentContext{ 55 Repo: repo.Name(), 56 Ref: ref, ··· 87 } 88 89 var buf bytes.Buffer 90 - if err := markup.Code.Convert([]byte(content), filepath.Base(path), &buf); err != nil { 91 return httperr.Error(err) 92 } 93 94 if err := html.RepoFile(html.RepoFileContext{ 95 - BaseContext: rh.baseContext(), 96 - RepoHeaderComponentContext: rh.repoHeaderContext(repo, r), 97 - Code: buf.String(), 98 - Path: path, 99 }).Render(r.Context(), w); err != nil { 100 return httperr.Error(err) 101 } ··· 157 158 for idx, p := range commit.Files { 159 var patch bytes.Buffer 160 - if err := markup.Code.Basic([]byte(p.Patch), "commit.patch", &patch); err != nil { 161 return httperr.Error(err) 162 } 163 commit.Files[idx].Patch = patch.String() ··· 205 } 206 results[idx].Content = buf.String() 207 } 208 - 209 } 210 211 if err := html.RepoSearch(html.SearchContext{
··· 48 back = filepath.Dir(path) 49 } 50 if err := html.RepoTree(html.RepoTreeContext{ 51 + Description: repo.Meta.Description, 52 + BaseContext: rh.baseContext(), 53 + RepoHeaderComponentContext: rh.repoHeaderContext(repo, r), 54 + RepoBreadcrumbComponentContext: rh.repoBreadcrumbContext(repo, r, path), 55 RepoTreeComponentContext: html.RepoTreeComponentContext{ 56 Repo: repo.Name(), 57 Ref: ref, ··· 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{
+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
+18 -5
internal/ssh/wish.go
··· 5 "errors" 6 "fmt" 7 "io/fs" 8 "os" 9 "path/filepath" 10 "strings" 11 12 "go.jolheiser.com/ugit/internal/git" 13 14 - "github.com/charmbracelet/log" 15 "github.com/charmbracelet/ssh" 16 "github.com/charmbracelet/wish" 17 ) ··· 90 if errors.Is(err, ErrInvalidRepo) { 91 Fatal(s, ErrInvalidRepo) 92 } 93 - log.Error("unknown git error", "error", err) 94 Fatal(s, ErrSystemMalfunction) 95 } 96 gh.Fetch(repo, pk) ··· 102 if len(cmd) == 0 { 103 des, err := os.ReadDir(repoDir) 104 if err != nil && err != fs.ErrNotExist { 105 - log.Error("invalid repository", "error", err) 106 } 107 for _, de := range des { 108 - fmt.Fprintln(s, de.Name()) 109 - fmt.Fprintf(s, "\tgit clone %s/%s\n", cloneURL, de.Name()) 110 } 111 } 112 sh(s) 113 }
··· 5 "errors" 6 "fmt" 7 "io/fs" 8 + "log/slog" 9 "os" 10 "path/filepath" 11 "strings" 12 + "text/tabwriter" 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 { 110 + if filepath.Ext(de.Name()) != ".git" { 111 + continue 112 + } 113 + repo, err := git.NewRepo(repoDir, de.Name()) 114 + visibility := "โ“" 115 + if err == nil { 116 + visibility = "๐Ÿ”“" 117 + if repo.Meta.Private { 118 + visibility = "๐Ÿ”’" 119 + } 120 + } 121 + fmt.Fprintf(tw, "%[1]s\t%[3]s\t%[2]s/%[1]s.git\n", strings.TrimSuffix(de.Name(), ".git"), cloneURL, visibility) 122 } 123 + tw.Flush() 124 } 125 sh(s) 126 }
+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 + }