This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

Initialize with `press`

https://tangled.org/nagee.dev/press

nagee (May 29, 2026, 9:49 PM EDT) fb15febe

+903
+24
go.mod
··· 1 + module git.nagee.dev/isthisnagee/toolbox 2 + 3 + go 1.25.3 4 + 5 + tool github.com/a-h/templ/cmd/templ 6 + 7 + require github.com/a-h/templ v0.3.1020 8 + 9 + require ( 10 + github.com/a-h/parse v0.0.0-20250122154542-74294addb73e // indirect 11 + github.com/andybalholm/brotli v1.1.0 // indirect 12 + github.com/cenkalti/backoff/v4 v4.3.0 // indirect 13 + github.com/cli/browser v1.3.0 // indirect 14 + github.com/fatih/color v1.16.0 // indirect 15 + github.com/fsnotify/fsnotify v1.7.0 // indirect 16 + github.com/mattn/go-colorable v0.1.13 // indirect 17 + github.com/mattn/go-isatty v0.0.20 // indirect 18 + github.com/natefinch/atomic v1.0.1 // indirect 19 + golang.org/x/mod v0.26.0 // indirect 20 + golang.org/x/net v0.51.0 // indirect 21 + golang.org/x/sync v0.16.0 // indirect 22 + golang.org/x/sys v0.41.0 // indirect 23 + golang.org/x/tools v0.35.0 // indirect 24 + )
+43
go.sum
··· 1 + github.com/a-h/parse v0.0.0-20250122154542-74294addb73e h1:HjVbSQHy+dnlS6C3XajZ69NYAb5jbGNfHanvm1+iYlo= 2 + github.com/a-h/parse v0.0.0-20250122154542-74294addb73e/go.mod h1:3mnrkvGpurZ4ZrTDbYU84xhwXW2TjTKShSwjRi2ihfQ= 3 + github.com/a-h/templ v0.3.1020 h1:ypAT/L5ySWEnZ6Zft/5yfoWXYYkhFNvEFOeeqecg4tw= 4 + github.com/a-h/templ v0.3.1020/go.mod h1:A2DlK61v+K+NRoGnhmYbNYVmtYHcFO5/AisMvBdDxTM= 5 + github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= 6 + github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= 7 + github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= 8 + github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= 9 + github.com/cli/browser v1.3.0 h1:LejqCrpWr+1pRqmEPDGnTZOjsMe7sehifLynZJuqJpo= 10 + github.com/cli/browser v1.3.0/go.mod h1:HH8s+fOAxjhQoBUAsKuPCbqUuxZDhQ2/aD+SzsEfBTk= 11 + github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 12 + github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 13 + github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= 14 + github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= 15 + github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= 16 + github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= 17 + github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 18 + github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 19 + github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 20 + github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 21 + github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 22 + github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 23 + github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 24 + github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A= 25 + github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM= 26 + github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 27 + github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 28 + github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 29 + github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 30 + golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= 31 + golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= 32 + golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= 33 + golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= 34 + golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= 35 + golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 36 + golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 37 + golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 38 + golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= 39 + golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= 40 + golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= 41 + golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= 42 + gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 43 + gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+77
main.go
··· 1 + package main 2 + 3 + import ( 4 + "embed" 5 + "fmt" 6 + "git.nagee.dev/isthisnagee/toolbox/src/handlers" 7 + "git.nagee.dev/isthisnagee/toolbox/src/services" 8 + "log/slog" 9 + "net/http" 10 + "os" 11 + "time" 12 + ) 13 + 14 + //go:embed static/* 15 + var staticFS embed.FS 16 + 17 + var ( 18 + version string 19 + ) 20 + 21 + func main() { 22 + for _, arg := range os.Args[1:] { 23 + if arg == "--version" || arg == "-v" { 24 + fmt.Println(version) 25 + os.Exit(0) 26 + } 27 + } 28 + 29 + // Configure logger with timestamp 30 + logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) 31 + 32 + port := os.Getenv("PORT") 33 + if port == "" { 34 + port = "8080" 35 + } 36 + 37 + ms := services.NewMath(logger) 38 + toolboxHandler := handlers.New(logger, ms) 39 + 40 + mux := http.NewServeMux() 41 + 42 + // Serve static files 43 + fileServer := http.FileServer(http.FS(staticFS)) 44 + mux.Handle("/static/", fileServer) 45 + 46 + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 47 + if r.Method == http.MethodPost { 48 + toolboxHandler.Increment(w, r) 49 + } 50 + toolboxHandler.Index(w, r) 51 + }) 52 + mux.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {}) // no favicon 53 + 54 + // Wrap with logging middleware 55 + logged := loggingMiddleware(mux, logger) 56 + 57 + logger.Info("Server started at port", port) 58 + addr := ":" + port 59 + if err := http.ListenAndServe(addr, logged); err != nil { 60 + logger.Error("could not start server: %v", err) 61 + } 62 + } 63 + 64 + func loggingMiddleware(next http.Handler, logger *slog.Logger) http.Handler { 65 + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 66 + start := time.Now() 67 + 68 + next.ServeHTTP(w, r) 69 + 70 + logger.Info( 71 + "http request", 72 + "method", r.Method, 73 + "path", r.URL.Path, 74 + "duration", time.Since(start), 75 + ) 76 + }) 77 + }
+60
mise.toml
··· 1 + [tools] 2 + go = "1.25" 3 + 4 + [vars] 5 + version = "{{ exec(command='cat version.txt') }}" 6 + ldl_flags = "-X 'main.version={{ exec(command='cat version.txt') }}'" 7 + 8 + [tasks.install] 9 + run = ["mise install"] 10 + 11 + [tasks.fmt-go] 12 + description = "Format the project" 13 + run = "go fmt" 14 + 15 + [tasks.fmt-templ] 16 + run = "go tool templ fmt ." 17 + 18 + [tasks.fmt] 19 + depends = ["fmt-go", "fmt-templ"] 20 + 21 + [tasks.templ-generate] 22 + run = "go tool templ generate ." 23 + 24 + [tasks.dev] 25 + depends = ["install", "templ-generate"] 26 + description = "Run the application" 27 + run = ''' 28 + go run \ 29 + -ldflags="{{vars.ldl_flags}}" \ 30 + main.go 31 + ''' 32 + 33 + [tasks.build] 34 + depends = ["install"] 35 + description = "Build the application" 36 + run = ''' 37 + go build \ 38 + -ldflags="{{vars.ldl_flags}}" \ 39 + -o \ 40 + main.go 41 + ''' 42 + 43 + [tasks.ci-build] 44 + depends = ["install"] 45 + description = "Build the application" 46 + run = ''' 47 + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ 48 + -ldflags="{{vars.ldl_flags}}" \ 49 + -o toolbox \ 50 + main.go 51 + ''' 52 + 53 + [tasks.ci-upload] 54 + depends = ["ci-build"] 55 + description = "Upload the binary to the bucket" 56 + run = ''' 57 + s3cmd put \ 58 + toolbox \ 59 + "s3://$DO_SPACES_BUCKET/builds/toolbox/{{vars.version}}/toolbox" 60 + '''
+59
src/handlers/default.go
··· 1 + package handlers 2 + 3 + import ( 4 + "context" 5 + "log/slog" 6 + "net/http" 7 + "strconv" 8 + 9 + "git.nagee.dev/isthisnagee/toolbox/src/models" 10 + "git.nagee.dev/isthisnagee/toolbox/src/ui" 11 + "git.nagee.dev/isthisnagee/toolbox/src/ui/templates" 12 + ) 13 + 14 + type ToolboxHandler struct { 15 + Log *slog.Logger 16 + CountService CountService 17 + } 18 + 19 + func New(log *slog.Logger, cs CountService) *ToolboxHandler { 20 + return &ToolboxHandler{ 21 + Log: log, 22 + CountService: cs, 23 + } 24 + } 25 + 26 + type CountService interface { 27 + Add(ctx context.Context, a, b int) (result models.AddResult, err error) 28 + } 29 + 30 + func (h *ToolboxHandler) Index(w http.ResponseWriter, r *http.Request) { 31 + h.Log.Info("Index page") 32 + result := models.AddResult{N: 10} 33 + uiResult := ui.ToUiAddResult(result) 34 + pageData := ui.IndexPageData{Result: uiResult} 35 + templates.IndexPage(pageData).Render(r.Context(), w) 36 + } 37 + 38 + func (h *ToolboxHandler) Increment(w http.ResponseWriter, r *http.Request) { 39 + h.Log.Info("Add method") 40 + 41 + valueStr := r.FormValue("increment") 42 + value, err := strconv.Atoi(valueStr) 43 + if err != nil { 44 + http.Error(w, "invalid increment", http.StatusBadRequest) 45 + return 46 + } 47 + 48 + result, err := h.CountService.Add(r.Context(), value, 1) 49 + if err != nil { 50 + h.Log.Error("Failed to add", err) 51 + http.Error(w, "failed to add", http.StatusInternalServerError) 52 + return 53 + } 54 + pageData := ui.IndexPageData{ 55 + Result: ui.ToUiAddResult(result), 56 + } 57 + 58 + templates.IndexPage(pageData).Render(r.Context(), w) 59 + }
+5
src/models/models.go
··· 1 + package models 2 + 3 + type AddResult struct { 4 + N int 5 + }
+20
src/services/services.go
··· 1 + package services 2 + 3 + import ( 4 + "log/slog" 5 + "context" 6 + "git.nagee.dev/isthisnagee/toolbox/src/models" 7 + ) 8 + 9 + type Math struct { 10 + Log *slog.Logger 11 + } 12 + 13 + func NewMath(log *slog.Logger) Math { 14 + return Math{Log: log} 15 + } 16 + 17 + func (ms Math) Add(ctx context.Context, a, b int) (result models.AddResult, err error) { 18 + ms.Log.Info("Adding some numbers", a, b) 19 + return models.AddResult{N: a + b}, nil 20 + }
+20
src/ui/models.go
··· 1 + package ui 2 + 3 + import ( 4 + "git.nagee.dev/isthisnagee/toolbox/src/models" 5 + ) 6 + 7 + type UiAddResult struct { 8 + N int 9 + } 10 + 11 + func ToUiAddResult(result models.AddResult) UiAddResult { 12 + return UiAddResult{ 13 + N: result.N, 14 + } 15 + } 16 + 17 + 18 + type IndexPageData struct { 19 + Result UiAddResult 20 + }
+9
src/ui/style.templ
··· 1 + package ui 2 + 3 + var cssStylesheet = templ.NewOnceHandle() 4 + 5 + templ GlobalCss() { 6 + @cssStylesheet.Once() { 7 + <link rel="stylesheet" href="/static/css/styles.css"/> 8 + } 9 + }
+60
src/ui/style_templ.go
··· 1 + // Code generated by templ - DO NOT EDIT. 2 + 3 + // templ: version: v0.3.1020 4 + package ui 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 + var cssStylesheet = templ.NewOnceHandle() 12 + 13 + func GlobalCss() templ.Component { 14 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 15 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 16 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 17 + return templ_7745c5c3_CtxErr 18 + } 19 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 20 + if !templ_7745c5c3_IsBuffer { 21 + defer func() { 22 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 23 + if templ_7745c5c3_Err == nil { 24 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 25 + } 26 + }() 27 + } 28 + ctx = templ.InitializeContext(ctx) 29 + templ_7745c5c3_Var1 := templ.GetChildren(ctx) 30 + if templ_7745c5c3_Var1 == nil { 31 + templ_7745c5c3_Var1 = templ.NopComponent 32 + } 33 + ctx = templ.ClearChildren(ctx) 34 + templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 35 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 36 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 37 + if !templ_7745c5c3_IsBuffer { 38 + defer func() { 39 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 40 + if templ_7745c5c3_Err == nil { 41 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 42 + } 43 + }() 44 + } 45 + ctx = templ.InitializeContext(ctx) 46 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<link rel=\"stylesheet\" href=\"/static/css/styles.css\">") 47 + if templ_7745c5c3_Err != nil { 48 + return templ_7745c5c3_Err 49 + } 50 + return nil 51 + }) 52 + templ_7745c5c3_Err = cssStylesheet.Once().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 53 + if templ_7745c5c3_Err != nil { 54 + return templ_7745c5c3_Err 55 + } 56 + return nil 57 + }) 58 + } 59 + 60 + var _ = templruntime.GeneratedTemplate
+18
src/ui/templates/index.templ
··· 1 + package templates 2 + 3 + import "git.nagee.dev/isthisnagee/toolbox/src/ui" 4 + 5 + templ form(result ui.UiAddResult) { 6 + <form action="/" method="POST"> 7 + <div><button type="submit" name="increment" value={ result.N }>Increment { result.N }</button></div> 8 + </form> 9 + } 10 + 11 + // TODO: Add increment button 12 + templ IndexPage(data ui.IndexPageData) { 13 + @Page("home") { 14 + <div> 15 + @form(data.Result) 16 + </div> 17 + } 18 + }
+124
src/ui/templates/index_templ.go
··· 1 + // Code generated by templ - DO NOT EDIT. 2 + 3 + // templ: version: v0.3.1020 4 + package templates 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 "git.nagee.dev/isthisnagee/toolbox/src/ui" 12 + 13 + func form(result ui.UiAddResult) templ.Component { 14 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 15 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 16 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 17 + return templ_7745c5c3_CtxErr 18 + } 19 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 20 + if !templ_7745c5c3_IsBuffer { 21 + defer func() { 22 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 23 + if templ_7745c5c3_Err == nil { 24 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 25 + } 26 + }() 27 + } 28 + ctx = templ.InitializeContext(ctx) 29 + templ_7745c5c3_Var1 := templ.GetChildren(ctx) 30 + if templ_7745c5c3_Var1 == nil { 31 + templ_7745c5c3_Var1 = templ.NopComponent 32 + } 33 + ctx = templ.ClearChildren(ctx) 34 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<form action=\"/\" method=\"POST\"><div><button type=\"submit\" name=\"increment\" value=\"") 35 + if templ_7745c5c3_Err != nil { 36 + return templ_7745c5c3_Err 37 + } 38 + var templ_7745c5c3_Var2 string 39 + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.ResolveAttributeValue(result.N) 40 + if templ_7745c5c3_Err != nil { 41 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/ui/templates/index.templ`, Line: 7, Col: 62} 42 + } 43 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var2) 44 + if templ_7745c5c3_Err != nil { 45 + return templ_7745c5c3_Err 46 + } 47 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\">Increment ") 48 + if templ_7745c5c3_Err != nil { 49 + return templ_7745c5c3_Err 50 + } 51 + var templ_7745c5c3_Var3 string 52 + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(result.N) 53 + if templ_7745c5c3_Err != nil { 54 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/ui/templates/index.templ`, Line: 7, Col: 85} 55 + } 56 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 57 + if templ_7745c5c3_Err != nil { 58 + return templ_7745c5c3_Err 59 + } 60 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</button></div></form>") 61 + if templ_7745c5c3_Err != nil { 62 + return templ_7745c5c3_Err 63 + } 64 + return nil 65 + }) 66 + } 67 + 68 + // TODO: Add increment button 69 + func IndexPage(data ui.IndexPageData) templ.Component { 70 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 71 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 72 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 73 + return templ_7745c5c3_CtxErr 74 + } 75 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 76 + if !templ_7745c5c3_IsBuffer { 77 + defer func() { 78 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 79 + if templ_7745c5c3_Err == nil { 80 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 81 + } 82 + }() 83 + } 84 + ctx = templ.InitializeContext(ctx) 85 + templ_7745c5c3_Var4 := templ.GetChildren(ctx) 86 + if templ_7745c5c3_Var4 == nil { 87 + templ_7745c5c3_Var4 = templ.NopComponent 88 + } 89 + ctx = templ.ClearChildren(ctx) 90 + templ_7745c5c3_Var5 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 91 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 92 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 93 + if !templ_7745c5c3_IsBuffer { 94 + defer func() { 95 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 96 + if templ_7745c5c3_Err == nil { 97 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 98 + } 99 + }() 100 + } 101 + ctx = templ.InitializeContext(ctx) 102 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div>") 103 + if templ_7745c5c3_Err != nil { 104 + return templ_7745c5c3_Err 105 + } 106 + templ_7745c5c3_Err = form(data.Result).Render(ctx, templ_7745c5c3_Buffer) 107 + if templ_7745c5c3_Err != nil { 108 + return templ_7745c5c3_Err 109 + } 110 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div>") 111 + if templ_7745c5c3_Err != nil { 112 + return templ_7745c5c3_Err 113 + } 114 + return nil 115 + }) 116 + templ_7745c5c3_Err = Page("home").Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer) 117 + if templ_7745c5c3_Err != nil { 118 + return templ_7745c5c3_Err 119 + } 120 + return nil 121 + }) 122 + } 123 + 124 + var _ = templruntime.GeneratedTemplate
+26
src/ui/templates/page.templ
··· 1 + package templates 2 + 3 + import "git.nagee.dev/isthisnagee/toolbox/src/ui" 4 + 5 + templ Page(title string) { 6 + <!DOCTYPE html> 7 + <html lang="en"> 8 + <head> 9 + <meta charset="UTF-8"/> 10 + <meta name="viewport" content="width=device-width, initial-scale=1.0"/> 11 + <title>{ title }</title> 12 + @ui.GlobalCss() 13 + </head> 14 + <body> 15 + <header><h1>Toolbox</h1></header> 16 + <nav data-style="classy"> 17 + <span> 18 + <a class="nav-item" href="/">home</a> 19 + </span> 20 + </nav> 21 + <main> 22 + { children... } 23 + </main> 24 + </body> 25 + </html> 26 + }
+71
src/ui/templates/page_templ.go
··· 1 + // Code generated by templ - DO NOT EDIT. 2 + 3 + // templ: version: v0.3.1020 4 + package templates 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 "git.nagee.dev/isthisnagee/toolbox/src/ui" 12 + 13 + func Page(title string) templ.Component { 14 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 15 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 16 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 17 + return templ_7745c5c3_CtxErr 18 + } 19 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 20 + if !templ_7745c5c3_IsBuffer { 21 + defer func() { 22 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 23 + if templ_7745c5c3_Err == nil { 24 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 25 + } 26 + }() 27 + } 28 + ctx = templ.InitializeContext(ctx) 29 + templ_7745c5c3_Var1 := templ.GetChildren(ctx) 30 + if templ_7745c5c3_Var1 == nil { 31 + templ_7745c5c3_Var1 = templ.NopComponent 32 + } 33 + ctx = templ.ClearChildren(ctx) 34 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>") 35 + if templ_7745c5c3_Err != nil { 36 + return templ_7745c5c3_Err 37 + } 38 + var templ_7745c5c3_Var2 string 39 + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title) 40 + if templ_7745c5c3_Err != nil { 41 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/ui/templates/page.templ`, Line: 11, Col: 17} 42 + } 43 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) 44 + if templ_7745c5c3_Err != nil { 45 + return templ_7745c5c3_Err 46 + } 47 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title>") 48 + if templ_7745c5c3_Err != nil { 49 + return templ_7745c5c3_Err 50 + } 51 + templ_7745c5c3_Err = ui.GlobalCss().Render(ctx, templ_7745c5c3_Buffer) 52 + if templ_7745c5c3_Err != nil { 53 + return templ_7745c5c3_Err 54 + } 55 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</head><body><header><h1>Toolbox</h1></header><nav data-style=\"classy\"><span><a class=\"nav-item\" href=\"/\">home</a></span></nav><main>") 56 + if templ_7745c5c3_Err != nil { 57 + return templ_7745c5c3_Err 58 + } 59 + templ_7745c5c3_Err = templ_7745c5c3_Var1.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, 4, "</main></body></html>") 64 + if templ_7745c5c3_Err != nil { 65 + return templ_7745c5c3_Err 66 + } 67 + return nil 68 + }) 69 + } 70 + 71 + var _ = templruntime.GeneratedTemplate
+286
static/css/styles.css
··· 1 + /* readable.css 1.1.0, licensed 0BSD */ 2 + /* https://codeberg.org/Freedom-to-Write/readable.css/src/branch/main/readable.css# */ 3 + 4 + /* Font family support */ 5 + html, html[data-font-family="serif"] { 6 + --font-family: serif; 7 + } 8 + html[data-font-family="sans-serif"] { 9 + --font-family: sans-serif; 10 + } 11 + html[data-font-family="monospace"] { 12 + --font-family: monospace; 13 + } 14 + 15 + /* Color scheme support */ 16 + html, html[data-theme="light"] { 17 + --background-color: snow; 18 + --color: #000; 19 + } 20 + html[data-high-contrast="on"], html[data-theme="light"][data-high-contrast="on"] { 21 + --background-color: #fff; 22 + } 23 + 24 + html[data-theme="dark"] { 25 + --background-color: #1f272d; 26 + --color: #fff; 27 + } 28 + html[data-theme="dark"][data-high-contrast="on"] { 29 + --background-color: #000; 30 + } 31 + 32 + @media (prefers-color-scheme: dark) { 33 + html { 34 + --background-color: #222830; 35 + --color: #fff; 36 + } 37 + html[data-high-contrast="on"] { 38 + --background-color: #000; 39 + } 40 + } 41 + 42 + @media (prefers-contrast: more) { 43 + :is(html, html[data-theme="light"]):not([data-high-contrast="off"]) { 44 + --background-color: #fff; 45 + } 46 + 47 + html[data-theme="dark"]:not([data-high-contrast="off"]) { 48 + --background-color: #000; 49 + } 50 + } 51 + 52 + /* Generic styles */ 53 + :root { 54 + --column-width: 67ch; 55 + --form-width: 50ch; 56 + --line-width: 0.125rem; 57 + --line-height: 1.5; 58 + 59 + --one-line: calc(var(--line-height) * 1rem); 60 + --half-line: calc(var(--one-line) * 0.5); 61 + 62 + font-family: var(--font-family); 63 + 64 + background-color: var(--background-color); 65 + color: var(--color); 66 + } 67 + 68 + a { 69 + color: inherit; 70 + } 71 + 72 + a:active { 73 + color: red; 74 + } 75 + 76 + header, footer, h1, h2 { 77 + text-align: center; 78 + } 79 + 80 + footer:not(.exclude) { 81 + border-top: var(--line-width) solid; 82 + } 83 + 84 + summary { 85 + cursor: pointer; 86 + } 87 + 88 + blockquote:not(.exclude) { 89 + padding-left: var(--one-line); 90 + border-left: var(--line-width) solid; 91 + } 92 + 93 + ul, ol { 94 + padding-left: calc(var(--line-height) * 2rem); 95 + } 96 + 97 + :is(body, article, main, figure) > :is(img, video):not(.exclude) { 98 + max-width: 100%; 99 + } 100 + 101 + figure:not(.exclude) { 102 + text-align: center; 103 + } 104 + 105 + figure:not(.exclude) > * + figcaption { 106 + margin-top: 0; 107 + font-style: italic; 108 + } 109 + 110 + article aside:not(.exclude) { 111 + border: var(--line-width) solid; 112 + padding: 0 var(--one-line); 113 + border-radius: var(--half-line); 114 + } 115 + 116 + pre { 117 + max-width: 100%; 118 + overflow: auto; 119 + } 120 + 121 + hr { 122 + color: inherit; 123 + border: 0; 124 + border-top: var(--line-width) solid; 125 + } 126 + 127 + /* Vertical Rhythm */ 128 + p, ul, ol, figcaption, nav, td, th, label { 129 + line-height: var(--line-height); 130 + } 131 + 132 + h1, h2, h3, h4, h5, h6, p, blockquote, hr, footer, header, nav, figure, figcaption, :is(ul, ol):not(li > *), :is(body, article, main) > :is(img, video, details):not(.exclude), table, article > aside, article > aside { 133 + margin: var(--one-line) 0; 134 + } 135 + 136 + /* Headings */ 137 + 138 + header h1 { 139 + font-weight: normal; 140 + } 141 + 142 + h1, h2 { 143 + line-height: calc(var(--line-height) * 2rem); 144 + } 145 + 146 + h1 { 147 + font-size: 2.5rem; 148 + } 149 + 150 + h2 { 151 + font-size: 1.75rem; 152 + } 153 + 154 + h3, h4, h5, h6 { 155 + line-height: var(--one-line); 156 + padding-top: calc(var(--line-height) * 0.75rem); 157 + margin-bottom: calc(var(--line-height) * 0.25rem); 158 + } 159 + 160 + :is(h3, h4, h5, h6) + * { 161 + margin-top: 0; 162 + } 163 + 164 + /* Navbar */ 165 + nav:not(.exclude:not([data-style]), [data-style="none"]) { /* This styling only affects the first nav element that is the direct child of the body */ 166 + text-align: center; 167 + border-width: var(--line-width) 0; 168 + border-style: solid; 169 + line-height: var(--line-height); 170 + display: flex; 171 + flex-flow: row wrap; 172 + } 173 + 174 + nav:not(.exclude:not([data-style]), [data-style="none"]) > * { 175 + flex-grow: 1; 176 + margin: calc((var(--line-height) * 0.5rem) - var(--line-width)) var(--half-line); /* Put half a line's height on both top and bottom, then remove the width of the border */ 177 + text-transform: uppercase; 178 + } 179 + 180 + nav[data-style="blockout"], 181 + nav:is([data-style="boxes"], [data-style="roundesque"]) a:is(:hover, :focus) { 182 + background-color: var(--color); 183 + color: var(--background-color); 184 + } 185 + 186 + nav[data-style="blockout"] a { 187 + text-decoration: none; 188 + } 189 + 190 + nav[data-style="blockout"] a:is(:hover, :focus) { 191 + background-color: var(--background-color); 192 + color: var(--color); 193 + } 194 + 195 + nav[data-style]:is([data-style="boxes"], [data-style="roundesque"]) { 196 + border: 0; 197 + } 198 + 199 + nav:is([data-style="boxes"], [data-style="roundesque"]) a { 200 + text-decoration: none; 201 + border: var(--line-width) solid; 202 + } 203 + 204 + nav[data-style="roundesque"] a { 205 + border-radius: calc(0.25 * var(--one-line)); 206 + } 207 + 208 + @media (prefers-reduced-motion: no-preference) { 209 + nav[data-style="classy"] span > a { 210 + text-decoration: none; 211 + display: inline-block; 212 + } 213 + 214 + nav[data-style="classy"] span > a::after { 215 + content: ''; 216 + width: 0; 217 + height: var(--line-width); 218 + display: block; 219 + background: var(--color); 220 + transition: 150ms; 221 + } 222 + 223 + nav[data-style="classy"] span > a:is(:hover, :focus)::after { 224 + width: 100%; 225 + } 226 + } 227 + 228 + /* Column */ 229 + body { 230 + margin: 0 auto; 231 + width: min(95%, var(--column-width)); 232 + } 233 + 234 + /* Justification (default off; use data-justify="on" on <html> to enable) */ 235 + /* 67ch (var(--column-width) / 95% (column max-width) === 70.526315789ch */ 236 + @media (min-width: 70.5ch) { 237 + [data-justify="on"] body { 238 + text-align: justify; 239 + text-justify: inter-character; 240 + } 241 + } 242 + 243 + /* Tables */ 244 + table:not(.exclude) { 245 + display: block; 246 + width: 100%; 247 + overflow: auto; 248 + border-collapse: collapse; 249 + } 250 + 251 + table:not(.exclude) :is(td, th) { 252 + padding: calc(var(--line-height) * 0.25rem); 253 + border: var(--line-width) solid; 254 + } 255 + 256 + table:not(.exclude) td { 257 + word-wrap: break-word; 258 + } 259 + 260 + /* Forms */ 261 + form { 262 + max-width: var(--form-width) 263 + } 264 + 265 + form:not(.exclude) :is(label:not(input:is([type="checkbox"], [type="radio"]) + label), input:not([type="checkbox"], [type="radio"]), textarea, select) { 266 + display: block; 267 + margin: var(--half-line) 0; 268 + } 269 + 270 + form:not(.exclude) :is(input:not([type="checkbox"], [type="radio"]), textarea, select), button { 271 + box-sizing: border-box; 272 + padding: var(--half-line); 273 + background: transparent; 274 + border: var(--line-width) solid; 275 + color: inherit; 276 + font: inherit; 277 + width: 100%; 278 + } 279 + 280 + button { 281 + width: initial; 282 + } 283 + 284 + form:not(.exclude) label:not(input:is([type="checkbox"], [type="radio"]) + label) { 285 + font-weight: bold; 286 + }
+1
version.txt
··· 1 + 1