You’d like to use pongo2/v4 with gin and embed templates with go:embed.
I’m using cobra for my cli parsing and commands.
So
1 2 3 4 |
mkdir -p ~/go/src/git.icod.de/dalu/ui cd ~/go/src/git.icod.de/dalu/ui cobra init --pkg-name git.icod.de/dalu/ui cobra add ui |
edit cmd/ui.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
package cmd import ( "errors" "fmt" "io/fs" "os" "strings" "<your pkg path>/ui" "code.icod.de/dalu/ginpongo2/v5" "github.com/flosch/pongo2/v5" "github.com/gin-gonic/gin" "github.com/spf13/cobra" ) const ( prefixTCP = "tcp:" prefixUNIX = "unix:" ) var ( uiDebug bool uiAddr string ) // uiCmd represents the ui command var uiCmd = &cobra.Command{ Use: "ui", Short: "serves the management ui over http", RunE: func(cmd *cobra.Command, args []string) error { if !uiDebug { gin.SetMode(gin.ReleaseMode) } r := gin.Default() r.SecureJsonPrefix(")]}',\n") r.MaxMultipartMemory = 8 << 20 if uiDebug { fmt.Println("debug mode") fl, e := pongo2.NewLocalFileSystemLoader("ui/templates/") if e != nil { return e } hr := ginpongo2.New(true, fl) r.HTMLRender = hr } else { fmt.Println("release mode") subFS, e := fs.Sub(ui.Templates, "templates") if e != nil { return e } fl := pongo2.NewFSLoader(subFS) hr := ginpongo2.New(false, fl) r.HTMLRender = hr } // Static r.Static("/assets/", "./assets/") r.GET("/", func(cx *gin.Context) { ctx := make(pongo2.Context) type Data struct { Target string Message string } ctx["data"] = &Data{ Target: "World", Message: "It's a great day to be alive", } cx.HTML(200, "index", ctx) }) // serve if strings.HasPrefix(uiAddr, prefixTCP) { addr := strings.TrimPrefix(uiAddr, prefixTCP) fmt.Println("listening on", addr) return r.Run(addr) } else if strings.HasPrefix(uiAddr, prefixUNIX) { addr := strings.TrimPrefix(uiAddr, prefixUNIX) if _, e := os.Stat(addr); errors.Is(e, os.ErrNotExist) { fmt.Println("listening on", addr) return r.RunUnix(addr) } else { if e := os.Remove(addr); e != nil { return e } else { fmt.Println("listening on", addr) return r.RunUnix(addr) } } } else { return nil } }, } func init() { rootCmd.AddCommand(uiCmd) uiCmd.Flags().BoolVar(&uiDebug, "debug", false, "enable dev mode") uiCmd.Flags().StringVar( &uiAddr, "addr", "tcp:localhost:8080", "either tcp: or unix: e.g. tcp:localhost:3030 unix:/tmp/listen.sock", ) } |
ui/templates.go
1 2 3 4 5 6 |
package ui import "embed" //go:embed templates/* var Templates embed.FS |
ui/templates/base.html.twig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> {%- block meta %}{% endblock -%} <title>{{ title }}</title> {%- block js %}{% endblock -%} {%- block css %}{% endblock -%} </head> <body> {%- block body %}{% endblock -%} {%- block jsbottom %}{% endblock -%} </body> </html> |
ui/templates/layout.html.twig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
{% extends "base.html.twig" %} {%- block css %} <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous"> {% endblock -%} {%- block js %} <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script> {% endblock -%} {%- block body %} <div class="container"> <div class="row"> <div class="col-2"> {%- block left -%}{% endblock -%} </div> <div class="col-8"> {%- block middle -%}{% endblock -%} </div> <div class="col-2"> {%- block right -%}{% endblock -%} </div> </div> </div> {% endblock -%} |
ui/templates/index.html.twig
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{% extends "layout.html.twig" %} {%- block middle %} <div class="px-4 py-5 my-5 text-center"> <h1 class="display-5 fw-bold">Hello {{data.Target}}</h1> <div class="col-lg-6 mx-auto"> <p class="lead mb-4">{{data.Message}}</p> <div class="d-grid gap-2 d-sm-flex justify-content-sm-center"> <button type="button" class="btn btn-primary btn-lg px-4 gap-3">You got it</button> <button type="button" class="btn btn-outline-secondary btn-lg px-4">Huh?</button> </div> </div> </div> {% endblock -%} |
and finally run
1 |
go mod tidy |
to download packages
Any questions -> leave a comment