yaml parser and languages WIP
- commit
- cd54f111ea1e71e7751233b588477a9fc2ad54bd
- author
- bnema · · 2023-09-02 05:12 UTC
- parent
- df8fa86
- signature
- unsigned
7 files · +181 -42
M cmd/main.go +89 -29
| @@ -3,57 +3,60 @@ package main | |||
| 3 | 3 | import ( | |
| 4 | 4 | "fmt" | |
| 5 | 5 | "html/template" | |
| 6 | + | "io/fs" | |
| 6 | 7 | "net/http" | |
| 7 | - | "strings" | |
| 8 | + | "os" | |
| 8 | 9 | ||
| 9 | 10 | "github.com/labstack/echo/v4" | |
| 11 | + | "github.com/labstack/echo/v4/middleware" | |
| 12 | + | "github.com/rs/zerolog" | |
| 10 | 13 | "gogs.bnema.dev/gordon-echo/internal/ui" | |
| 11 | 14 | "gogs.bnema.dev/gordon-echo/pkg/utils" | |
| 12 | 15 | ) | |
| 13 | 16 | ||
| 14 | - | const trailedAdminPath = "/admin/" | |
| 17 | + | // getRenderer returns a new renderer for the given template | |
| 18 | + | func getRenderer(filename string, fs fs.FS) (*utils.Renderer, error) { | |
| 19 | + | tmpl, err := template.New(filename).ParseFS(fs, filename) | |
| 20 | + | if err != nil { | |
| 21 | + | return nil, err | |
| 22 | + | } | |
| 23 | + | return &utils.Renderer{ | |
| 24 | + | Template: tmpl, | |
| 25 | + | }, nil | |
| 26 | + | } | |
| 15 | 27 | ||
| 16 | 28 | // bindStaticAdminUI serves the static admin UI | |
| 17 | 29 | func bindStaticAdminUI(e *echo.Echo) error { | |
| 18 | - | tmpl, err := template.New("index").ParseFS(ui.PublicFS, "index.html") | |
| 30 | + | // Load static website data from YAML | |
| 31 | + | staticData, err := utils.LoadDataFromYAML() | |
| 19 | 32 | if err != nil { | |
| 20 | - | return fmt.Errorf("failed to parse index.html: %w", err) | |
| 33 | + | return err | |
| 21 | 34 | } | |
| 22 | 35 | ||
| 23 | - | renderer := &utils.Renderer{ | |
| 24 | - | Template: tmpl, | |
| 25 | - | ParseError: err, | |
| 26 | - | } | |
| 36 | + | // Main handler for /admin | |
| 37 | + | e.GET("/admin/:lang", func(c echo.Context) error { | |
| 38 | + | lang := c.Param("lang") | |
| 27 | 39 | ||
| 28 | - | // redirect to trailing slash to ensure that relative urls will still work properly | |
| 29 | - | e.GET( | |
| 30 | - | strings.TrimRight(trailedAdminPath, "/"), | |
| 31 | - | func(c echo.Context) error { | |
| 32 | - | return c.Redirect(http.StatusTemporaryRedirect, strings.TrimLeft(trailedAdminPath, "/")) | |
| 33 | - | }, | |
| 34 | - | ) | |
| 35 | - | ||
| 36 | - | // Main handler for /admin/ | |
| 37 | - | e.GET(trailedAdminPath, func(c echo.Context) error { | |
| 38 | - | data := map[string]interface{}{ | |
| 39 | - | "website": map[string]interface{}{ | |
| 40 | - | "title": "Hello, World!", | |
| 41 | - | }, | |
| 40 | + | switch lang { | |
| 41 | + | case "fr": | |
| 42 | + | staticData.CurrentLang = staticData.FR | |
| 43 | + | default: // default to English if no match | |
| 44 | + | staticData.CurrentLang = staticData.EN | |
| 45 | + | } | |
| 46 | + | ||
| 47 | + | renderer, err := getRenderer("index.html", ui.PublicFS) | |
| 48 | + | if err != nil { | |
| 49 | + | return err | |
| 42 | 50 | } | |
| 43 | 51 | ||
| 44 | - | html, err := renderer.Render(data) | |
| 52 | + | html, err := renderer.Render(staticData) | |
| 45 | 53 | if err != nil { | |
| 46 | 54 | return c.String(http.StatusInternalServerError, fmt.Sprintf("Failed to render template: %v", err)) | |
| 47 | 55 | } | |
| 48 | 56 | ||
| 49 | 57 | return c.HTML(http.StatusOK, html) | |
| 50 | 58 | }) | |
| 51 | - | // serves static files from the /ui/dist directory | |
| 52 | - | // (similar to echo.StaticFS but with gzip middleware enabled) | |
| 53 | - | e.GET( | |
| 54 | - | trailedAdminPath+"*", | |
| 55 | - | echo.StaticDirectoryHandler(ui.PublicFS, false), | |
| 56 | - | ) | |
| 59 | + | ||
| 57 | 60 | e.GET("/htmx", func(c echo.Context) error { | |
| 58 | 61 | fragment := c.Request().Header.Get("X-Fragment") | |
| 59 | 62 | ||
| @@ -70,14 +73,71 @@ func bindStaticAdminUI(e *echo.Echo) error { | |||
| 70 | 73 | // Handle other fragments or default behavior | |
| 71 | 74 | return c.String(http.StatusBadRequest, "Invalid fragment") | |
| 72 | 75 | }) | |
| 76 | + | ||
| 77 | + | // !!! IMPORTANT !!! This must be the last route (except for the 404 route) | |
| 78 | + | e.GET("/*", func(c echo.Context) error { | |
| 79 | + | // Set cache headers | |
| 80 | + | c.Response().Header().Set("Cache-Control", "public, max-age=86400") | |
| 81 | + | ||
| 82 | + | // Proceed with serving the file | |
| 83 | + | return echo.StaticDirectoryHandler(ui.PublicFS, false)(c) | |
| 84 | + | }) | |
| 85 | + | ||
| 86 | + | // // 404 handler | |
| 87 | + | // e.HTTPErrorHandler = func(err error, c echo.Context) { | |
| 88 | + | // if he, ok := err.(*echo.HTTPError); ok { | |
| 89 | + | // if he.Code == http.StatusNotFound { | |
| 90 | + | // // 404.html | |
| 91 | + | // renderer, err := getRenderer("404.html", ui.TemplateFS) | |
| 92 | + | // if err != nil { | |
| 93 | + | // c.String(http.StatusInternalServerError, fmt.Sprintf("Failed to render template: %v", err)) | |
| 94 | + | // } | |
| 95 | + | ||
| 96 | + | // data := map[string]interface{}{ | |
| 97 | + | // "website": map[string]interface{}{ | |
| 98 | + | // "title": "Page Not Found", | |
| 99 | + | // }, | |
| 100 | + | // } | |
| 101 | + | ||
| 102 | + | // html, err := renderer.Render(data) | |
| 103 | + | // if err != nil { | |
| 104 | + | // c.String(http.StatusInternalServerError, fmt.Sprintf("Failed to render template: %v", err)) | |
| 105 | + | // } | |
| 106 | + | ||
| 107 | + | // c.HTML(http.StatusNotFound, html) | |
| 108 | + | // return | |
| 109 | + | // } | |
| 110 | + | // } | |
| 111 | + | ||
| 112 | + | // e.DefaultHTTPErrorHandler(err, c) | |
| 113 | + | // } | |
| 114 | + | ||
| 73 | 115 | return nil | |
| 116 | + | ||
| 74 | 117 | } | |
| 75 | 118 | ||
| 76 | 119 | func main() { | |
| 120 | + | logger := zerolog.New(os.Stdout) | |
| 77 | 121 | e := echo.New() | |
| 78 | 122 | ||
| 123 | + | e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ | |
| 124 | + | LogURI: true, | |
| 125 | + | LogStatus: true, | |
| 126 | + | LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error { | |
| 127 | + | logger.Info(). | |
| 128 | + | Str("URI", v.URI). | |
| 129 | + | Int("status", v.Status). | |
| 130 | + | Msg("request") | |
| 131 | + | ||
| 132 | + | return nil | |
| 133 | + | }, | |
| 134 | + | })) | |
| 135 | + | ||
| 79 | 136 | // use func bindStaticAdminUI to serve the static admin UI | |
| 80 | 137 | bindStaticAdminUI(e) | |
| 138 | + | if err := bindStaticAdminUI(e); err != nil { | |
| 139 | + | e.Logger.Fatal(err) | |
| 140 | + | } | |
| 81 | 141 | ||
| 82 | 142 | e.Logger.Fatal(e.Start(":1323")) | |
| 83 | 143 | ||
| @@ -3,57 +3,60 @@ package main | |||||
| 3 | import ( | 3 | import ( | ||
| 4 | "fmt" | 4 | "fmt" | ||
| 5 | "html/template" | 5 | "html/template" | ||
| 6 | + | "io/fs" | |||
| 6 | "net/http" | 7 | "net/http" | ||
| 7 | - | "strings" | 8 | + | "os" |
| 8 | 9 | ||||
| 9 | "github.com/labstack/echo/v4" | 10 | "github.com/labstack/echo/v4" | ||
| 11 | + | "github.com/labstack/echo/v4/middleware" | |||
| 12 | + | "github.com/rs/zerolog" | |||
| 10 | "gogs.bnema.dev/gordon-echo/internal/ui" | 13 | "gogs.bnema.dev/gordon-echo/internal/ui" | ||
| 11 | "gogs.bnema.dev/gordon-echo/pkg/utils" | 14 | "gogs.bnema.dev/gordon-echo/pkg/utils" | ||
| 12 | ) | 15 | ) | ||
| 13 | 16 | ||||
| 14 | - | const trailedAdminPath = "/admin/" | 17 | + | // getRenderer returns a new renderer for the given template |
| 18 | + | func getRenderer(filename string, fs fs.FS) (*utils.Renderer, error) { | |||
| 19 | + | tmpl, err := template.New(filename).ParseFS(fs, filename) | |||
| 20 | + | if err != nil { | |||
| 21 | + | return nil, err | |||
| 22 | + | } | |||
| 23 | + | return &utils.Renderer{ | |||
| 24 | + | Template: tmpl, | |||
| 25 | + | }, nil | |||
| 26 | + | } | |||
| 15 | 27 | ||||
| 16 | // bindStaticAdminUI serves the static admin UI | 28 | // bindStaticAdminUI serves the static admin UI | ||
| 17 | func bindStaticAdminUI(e *echo.Echo) error { | 29 | func bindStaticAdminUI(e *echo.Echo) error { | ||
| 18 | - | tmpl, err := template.New("index").ParseFS(ui.PublicFS, "index.html") | 30 | + | // Load static website data from YAML |
| 31 | + | staticData, err := utils.LoadDataFromYAML() | |||
| 19 | if err != nil { | 32 | if err != nil { | ||
| 20 | - | return fmt.Errorf("failed to parse index.html: %w", err) | 33 | + | return err |
| 21 | } | 34 | } | ||
| 22 | 35 | ||||
| 23 | - | renderer := &utils.Renderer{ | 36 | + | // Main handler for /admin |
| 24 | - | Template: tmpl, | 37 | + | e.GET("/admin/:lang", func(c echo.Context) error { |
| 25 | - | ParseError: err, | 38 | + | lang := c.Param("lang") |
| 26 | - | } | |||
| 27 | 39 | ||||
| 28 | - | // redirect to trailing slash to ensure that relative urls will still work properly | 40 | + | switch lang { |
| 29 | - | e.GET( | 41 | + | case "fr": |
| 30 | - | strings.TrimRight(trailedAdminPath, "/"), | 42 | + | staticData.CurrentLang = staticData.FR |
| 31 | - | func(c echo.Context) error { | 43 | + | default: // default to English if no match |
| 32 | - | return c.Redirect(http.StatusTemporaryRedirect, strings.TrimLeft(trailedAdminPath, "/")) | 44 | + | staticData.CurrentLang = staticData.EN |
| 33 | - | }, | 45 | + | } |
| 34 | - | ) | 46 | + | |
| 35 | - | 47 | + | renderer, err := getRenderer("index.html", ui.PublicFS) | |
| 36 | - | // Main handler for /admin/ | 48 | + | if err != nil { |
| 37 | - | e.GET(trailedAdminPath, func(c echo.Context) error { | 49 | + | return err |
| 38 | - | data := map[string]interface{}{ | |||
| 39 | - | "website": map[string]interface{}{ | |||
| 40 | - | "title": "Hello, World!", | |||
| 41 | - | }, | |||
| 42 | } | 50 | } | ||
| 43 | 51 | ||||
| 44 | - | html, err := renderer.Render(data) | 52 | + | html, err := renderer.Render(staticData) |
| 45 | if err != nil { | 53 | if err != nil { | ||
| 46 | return c.String(http.StatusInternalServerError, fmt.Sprintf("Failed to render template: %v", err)) | 54 | return c.String(http.StatusInternalServerError, fmt.Sprintf("Failed to render template: %v", err)) | ||
| 47 | } | 55 | } | ||
| 48 | 56 | ||||
| 49 | return c.HTML(http.StatusOK, html) | 57 | return c.HTML(http.StatusOK, html) | ||
| 50 | }) | 58 | }) | ||
| 51 | - | // serves static files from the /ui/dist directory | 59 | + | |
| 52 | - | // (similar to echo.StaticFS but with gzip middleware enabled) | |||
| 53 | - | e.GET( | |||
| 54 | - | trailedAdminPath+"*", | |||
| 55 | - | echo.StaticDirectoryHandler(ui.PublicFS, false), | |||
| 56 | - | ) | |||
| 57 | e.GET("/htmx", func(c echo.Context) error { | 60 | e.GET("/htmx", func(c echo.Context) error { | ||
| 58 | fragment := c.Request().Header.Get("X-Fragment") | 61 | fragment := c.Request().Header.Get("X-Fragment") | ||
| 59 | 62 | ||||
| @@ -70,14 +73,71 @@ func bindStaticAdminUI(e *echo.Echo) error { | |||||
| 70 | // Handle other fragments or default behavior | 73 | // Handle other fragments or default behavior | ||
| 71 | return c.String(http.StatusBadRequest, "Invalid fragment") | 74 | return c.String(http.StatusBadRequest, "Invalid fragment") | ||
| 72 | }) | 75 | }) | ||
| 76 | + | ||||
| 77 | + | // !!! IMPORTANT !!! This must be the last route (except for the 404 route) | |||
| 78 | + | e.GET("/*", func(c echo.Context) error { | |||
| 79 | + | // Set cache headers | |||
| 80 | + | c.Response().Header().Set("Cache-Control", "public, max-age=86400") | |||
| 81 | + | ||||
| 82 | + | // Proceed with serving the file | |||
| 83 | + | return echo.StaticDirectoryHandler(ui.PublicFS, false)(c) | |||
| 84 | + | }) | |||
| 85 | + | ||||
| 86 | + | // // 404 handler | |||
| 87 | + | // e.HTTPErrorHandler = func(err error, c echo.Context) { | |||
| 88 | + | // if he, ok := err.(*echo.HTTPError); ok { | |||
| 89 | + | // if he.Code == http.StatusNotFound { | |||
| 90 | + | // // 404.html | |||
| 91 | + | // renderer, err := getRenderer("404.html", ui.TemplateFS) | |||
| 92 | + | // if err != nil { | |||
| 93 | + | // c.String(http.StatusInternalServerError, fmt.Sprintf("Failed to render template: %v", err)) | |||
| 94 | + | // } | |||
| 95 | + | ||||
| 96 | + | // data := map[string]interface{}{ | |||
| 97 | + | // "website": map[string]interface{}{ | |||
| 98 | + | // "title": "Page Not Found", | |||
| 99 | + | // }, | |||
| 100 | + | // } | |||
| 101 | + | ||||
| 102 | + | // html, err := renderer.Render(data) | |||
| 103 | + | // if err != nil { | |||
| 104 | + | // c.String(http.StatusInternalServerError, fmt.Sprintf("Failed to render template: %v", err)) | |||
| 105 | + | // } | |||
| 106 | + | ||||
| 107 | + | // c.HTML(http.StatusNotFound, html) | |||
| 108 | + | // return | |||
| 109 | + | // } | |||
| 110 | + | // } | |||
| 111 | + | ||||
| 112 | + | // e.DefaultHTTPErrorHandler(err, c) | |||
| 113 | + | // } | |||
| 114 | + | ||||
| 73 | return nil | 115 | return nil | ||
| 116 | + | ||||
| 74 | } | 117 | } | ||
| 75 | 118 | ||||
| 76 | func main() { | 119 | func main() { | ||
| 120 | + | logger := zerolog.New(os.Stdout) | |||
| 77 | e := echo.New() | 121 | e := echo.New() | ||
| 78 | 122 | ||||
| 123 | + | e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ | |||
| 124 | + | LogURI: true, | |||
| 125 | + | LogStatus: true, | |||
| 126 | + | LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error { | |||
| 127 | + | logger.Info(). | |||
| 128 | + | Str("URI", v.URI). | |||
| 129 | + | Int("status", v.Status). | |||
| 130 | + | Msg("request") | |||
| 131 | + | ||||
| 132 | + | return nil | |||
| 133 | + | }, | |||
| 134 | + | })) | |||
| 135 | + | ||||
| 79 | // use func bindStaticAdminUI to serve the static admin UI | 136 | // use func bindStaticAdminUI to serve the static admin UI | ||
| 80 | bindStaticAdminUI(e) | 137 | bindStaticAdminUI(e) | ||
| 138 | + | if err := bindStaticAdminUI(e); err != nil { | |||
| 139 | + | e.Logger.Fatal(err) | |||
| 140 | + | } | |||
| 81 | 141 | ||||
| 82 | e.Logger.Fatal(e.Start(":1323")) | 142 | e.Logger.Fatal(e.Start(":1323")) | ||
| 83 | 143 | ||||
M go.mod +10 -4
| @@ -2,19 +2,25 @@ module gogs.bnema.dev/gordon-echo | |||
| 2 | 2 | ||
| 3 | 3 | go 1.21.0 | |
| 4 | 4 | ||
| 5 | - | require github.com/labstack/echo/v4 v4.11.1 | |
| 5 | + | require ( | |
| 6 | + | github.com/PuerkitoBio/goquery v1.8.1 | |
| 7 | + | github.com/labstack/echo/v4 v4.11.1 | |
| 8 | + | ) | |
| 6 | 9 | ||
| 7 | 10 | require ( | |
| 8 | - | github.com/PuerkitoBio/goquery v1.8.1 // indirect | |
| 9 | 11 | github.com/andybalholm/cascadia v1.3.1 // indirect | |
| 10 | - | github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect | |
| 12 | + | github.com/golang-jwt/jwt v3.2.2+incompatible // indirect | |
| 13 | + | github.com/google/safehtml v0.1.0 // indirect | |
| 14 | + | golang.org/x/time v0.3.0 // indirect | |
| 15 | + | gopkg.in/yaml.v3 v3.0.1 // indirect | |
| 11 | 16 | ) | |
| 12 | 17 | ||
| 13 | 18 | require ( | |
| 14 | - | github.com/labstack/echo v3.3.10+incompatible | |
| 19 | + | github.com/go-chi/chi v1.5.4 | |
| 15 | 20 | github.com/labstack/gommon v0.4.0 // indirect | |
| 16 | 21 | github.com/mattn/go-colorable v0.1.13 // indirect | |
| 17 | 22 | github.com/mattn/go-isatty v0.0.19 // indirect | |
| 23 | + | github.com/rs/zerolog v1.30.0 | |
| 18 | 24 | github.com/valyala/bytebufferpool v1.0.0 // indirect | |
| 19 | 25 | github.com/valyala/fasttemplate v1.2.2 // indirect | |
| 20 | 26 | golang.org/x/crypto v0.11.0 // indirect | |
| @@ -2,19 +2,25 @@ module gogs.bnema.dev/gordon-echo | |||||
| 2 | 2 | ||||
| 3 | go 1.21.0 | 3 | go 1.21.0 | ||
| 4 | 4 | ||||
| 5 | - | require github.com/labstack/echo/v4 v4.11.1 | 5 | + | require ( |
| 6 | + | github.com/PuerkitoBio/goquery v1.8.1 | |||
| 7 | + | github.com/labstack/echo/v4 v4.11.1 | |||
| 8 | + | ) | |||
| 6 | 9 | ||||
| 7 | require ( | 10 | require ( | ||
| 8 | - | github.com/PuerkitoBio/goquery v1.8.1 // indirect | |||
| 9 | github.com/andybalholm/cascadia v1.3.1 // indirect | 11 | github.com/andybalholm/cascadia v1.3.1 // indirect | ||
| 10 | - | github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect | 12 | + | github.com/golang-jwt/jwt v3.2.2+incompatible // indirect |
| 13 | + | github.com/google/safehtml v0.1.0 // indirect | |||
| 14 | + | golang.org/x/time v0.3.0 // indirect | |||
| 15 | + | gopkg.in/yaml.v3 v3.0.1 // indirect | |||
| 11 | ) | 16 | ) | ||
| 12 | 17 | ||||
| 13 | require ( | 18 | require ( | ||
| 14 | - | github.com/labstack/echo v3.3.10+incompatible | 19 | + | github.com/go-chi/chi v1.5.4 |
| 15 | github.com/labstack/gommon v0.4.0 // indirect | 20 | github.com/labstack/gommon v0.4.0 // indirect | ||
| 16 | github.com/mattn/go-colorable v0.1.13 // indirect | 21 | github.com/mattn/go-colorable v0.1.13 // indirect | ||
| 17 | github.com/mattn/go-isatty v0.0.19 // indirect | 22 | github.com/mattn/go-isatty v0.0.19 // indirect | ||
| 23 | + | github.com/rs/zerolog v1.30.0 | |||
| 18 | github.com/valyala/bytebufferpool v1.0.0 // indirect | 24 | github.com/valyala/bytebufferpool v1.0.0 // indirect | ||
| 19 | github.com/valyala/fasttemplate v1.2.2 // indirect | 25 | github.com/valyala/fasttemplate v1.2.2 // indirect | ||
| 20 | golang.org/x/crypto v0.11.0 // indirect | 26 | golang.org/x/crypto v0.11.0 // indirect | ||
M go.sum +21 -4
| @@ -2,26 +2,39 @@ github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAc | |||
| 2 | 2 | github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= | |
| 3 | 3 | github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= | |
| 4 | 4 | github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= | |
| 5 | + | github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= | |
| 5 | 6 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |
| 7 | + | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | |
| 6 | 8 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |
| 7 | - | github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= | |
| 8 | - | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= | |
| 9 | - | github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg= | |
| 10 | - | github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= | |
| 9 | + | github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs= | |
| 10 | + | github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg= | |
| 11 | + | github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= | |
| 12 | + | github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= | |
| 13 | + | github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= | |
| 14 | + | github.com/google/safehtml v0.1.0 h1:EwLKo8qawTKfsi0orxcQAZzu07cICaBeFMegAU9eaT8= | |
| 15 | + | github.com/google/safehtml v0.1.0/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU= | |
| 11 | 16 | github.com/labstack/echo/v4 v4.11.1 h1:dEpLU2FLg4UVmvCGPuk/APjlH6GDpbEPti61srUUUs4= | |
| 12 | 17 | github.com/labstack/echo/v4 v4.11.1/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ= | |
| 13 | 18 | github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= | |
| 14 | 19 | github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= | |
| 15 | 20 | github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= | |
| 21 | + | github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= | |
| 16 | 22 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= | |
| 17 | 23 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= | |
| 18 | 24 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= | |
| 19 | 25 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= | |
| 20 | 26 | github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= | |
| 21 | 27 | github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= | |
| 28 | + | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | |
| 29 | + | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | |
| 22 | 30 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | |
| 31 | + | github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= | |
| 32 | + | github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= | |
| 33 | + | github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= | |
| 23 | 34 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | |
| 24 | 35 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | |
| 36 | + | github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= | |
| 37 | + | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | |
| 25 | 38 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= | |
| 26 | 39 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= | |
| 27 | 40 | github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= | |
| @@ -66,6 +79,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | |||
| 66 | 79 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= | |
| 67 | 80 | golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= | |
| 68 | 81 | golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= | |
| 82 | + | golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= | |
| 83 | + | golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | |
| 69 | 84 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |
| 70 | 85 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | |
| 71 | 86 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= | |
| @@ -73,3 +88,5 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T | |||
| 73 | 88 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |
| 74 | 89 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | |
| 75 | 90 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | |
| 91 | + | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | |
| 92 | + | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | |
| @@ -2,26 +2,39 @@ github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAc | |||||
| 2 | github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= | 2 | github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= | ||
| 3 | github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= | 3 | github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= | ||
| 4 | github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= | 4 | github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= | ||
| 5 | + | github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= | |||
| 5 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | 6 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
| 7 | + | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | |||
| 6 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | 8 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
| 7 | - | github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= | 9 | + | github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs= |
| 8 | - | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= | 10 | + | github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg= |
| 9 | - | github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg= | 11 | + | github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= |
| 10 | - | github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= | 12 | + | github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= |
| 13 | + | github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= | |||
| 14 | + | github.com/google/safehtml v0.1.0 h1:EwLKo8qawTKfsi0orxcQAZzu07cICaBeFMegAU9eaT8= | |||
| 15 | + | github.com/google/safehtml v0.1.0/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU= | |||
| 11 | github.com/labstack/echo/v4 v4.11.1 h1:dEpLU2FLg4UVmvCGPuk/APjlH6GDpbEPti61srUUUs4= | 16 | github.com/labstack/echo/v4 v4.11.1 h1:dEpLU2FLg4UVmvCGPuk/APjlH6GDpbEPti61srUUUs4= | ||
| 12 | github.com/labstack/echo/v4 v4.11.1/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ= | 17 | github.com/labstack/echo/v4 v4.11.1/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ= | ||
| 13 | github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= | 18 | github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= | ||
| 14 | github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= | 19 | github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= | ||
| 15 | github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= | 20 | github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= | ||
| 21 | + | github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= | |||
| 16 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= | 22 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= | ||
| 17 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= | 23 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= | ||
| 18 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= | 24 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= | ||
| 19 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= | 25 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= | ||
| 20 | github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= | 26 | github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= | ||
| 21 | github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= | 27 | github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= | ||
| 28 | + | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | |||
| 29 | + | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | |||
| 22 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | 30 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
| 31 | + | github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= | |||
| 32 | + | github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= | |||
| 33 | + | github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= | |||
| 23 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | 34 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
| 24 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | 35 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
| 36 | + | github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= | |||
| 37 | + | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | |||
| 25 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= | 38 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= | ||
| 26 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= | 39 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= | ||
| 27 | github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= | 40 | github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= | ||
| @@ -66,6 +79,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | |||||
| 66 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= | 79 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= | ||
| 67 | golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= | 80 | golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= | ||
| 68 | golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= | 81 | golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= | ||
| 82 | + | golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= | |||
| 83 | + | golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | |||
| 69 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | 84 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
| 70 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | 85 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||
| 71 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= | 86 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= | ||
| @@ -73,3 +88,5 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T | |||||
| 73 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | 88 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
| 74 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | 89 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
| 75 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | 90 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
| 91 | + | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | |||
| 92 | + | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | |||
A internal/ui/public/assets/imgs/gordon-mascot.png +0 -0 binary file: no text diff
binary file: no text diff
A internal/ui/templates/strings.yaml +9 -0
| @@ -0,0 +1,9 @@ | |||
| 1 | + | en: | |
| 2 | + | website: | |
| 3 | + | title: Admin Dashboard | |
| 4 | + | user: John Doe | |
| 5 | + | ||
| 6 | + | fr: | |
| 7 | + | website: | |
| 8 | + | title: Tableau de bord administrateur | |
| 9 | + | user: Jean Dupont⏎̸ | |
| @@ -0,0 +1,9 @@ | |||||
| 1 | + | en: | |||
| 2 | + | website: | |||
| 3 | + | title: Admin Dashboard | |||
| 4 | + | user: John Doe | |||
| 5 | + | ||||
| 6 | + | fr: | |||
| 7 | + | website: | |||
| 8 | + | title: Tableau de bord administrateur | |||
| 9 | + | user: Jean Dupont⏎̸ | |||
A pkg/utils/parser.go +49 -0
| @@ -0,0 +1,49 @@ | |||
| 1 | + | package utils | |
| 2 | + | ||
| 3 | + | import ( | |
| 4 | + | "fmt" | |
| 5 | + | "io" | |
| 6 | + | ||
| 7 | + | "gogs.bnema.dev/gordon-echo/internal/ui" | |
| 8 | + | "gopkg.in/yaml.v3" | |
| 9 | + | ) | |
| 10 | + | ||
| 11 | + | type Data struct { | |
| 12 | + | EN StaticData `yaml:"en"` | |
| 13 | + | FR StaticData `yaml:"fr"` | |
| 14 | + | CurrentLang StaticData `yaml:"-"` | |
| 15 | + | Website struct { | |
| 16 | + | Title string `yaml:"title"` | |
| 17 | + | User string `yaml:"user"` | |
| 18 | + | } `yaml:"website"` | |
| 19 | + | } | |
| 20 | + | ||
| 21 | + | type StaticData struct { | |
| 22 | + | Title string `yaml:"title"` | |
| 23 | + | User string `yaml:"user"` | |
| 24 | + | } | |
| 25 | + | ||
| 26 | + | // LoadDataFromYAML loads the data from the given YAML file | |
| 27 | + | func LoadDataFromYAML() (Data, error) { | |
| 28 | + | var data Data | |
| 29 | + | ||
| 30 | + | // Open the YAML file inside the ui/components directory | |
| 31 | + | file, err := ui.TemplateFS.Open("strings.yaml") | |
| 32 | + | if err != nil { | |
| 33 | + | return data, fmt.Errorf("failed to open strings.yaml: %w", err) | |
| 34 | + | } | |
| 35 | + | defer file.Close() | |
| 36 | + | ||
| 37 | + | // Read the content of the file | |
| 38 | + | content, err := io.ReadAll(file) | |
| 39 | + | if err != nil { | |
| 40 | + | return data, fmt.Errorf("failed to read strings.yaml: %w", err) | |
| 41 | + | } | |
| 42 | + | ||
| 43 | + | // Unmarshal the YAML content into the Data struct | |
| 44 | + | if err := yaml.Unmarshal(content, &data); err != nil { | |
| 45 | + | return data, fmt.Errorf("failed to unmarshal strings.yaml: %w", err) | |
| 46 | + | } | |
| 47 | + | ||
| 48 | + | return data, nil | |
| 49 | + | } | |
| @@ -0,0 +1,49 @@ | |||||
| 1 | + | package utils | |||
| 2 | + | ||||
| 3 | + | import ( | |||
| 4 | + | "fmt" | |||
| 5 | + | "io" | |||
| 6 | + | ||||
| 7 | + | "gogs.bnema.dev/gordon-echo/internal/ui" | |||
| 8 | + | "gopkg.in/yaml.v3" | |||
| 9 | + | ) | |||
| 10 | + | ||||
| 11 | + | type Data struct { | |||
| 12 | + | EN StaticData `yaml:"en"` | |||
| 13 | + | FR StaticData `yaml:"fr"` | |||
| 14 | + | CurrentLang StaticData `yaml:"-"` | |||
| 15 | + | Website struct { | |||
| 16 | + | Title string `yaml:"title"` | |||
| 17 | + | User string `yaml:"user"` | |||
| 18 | + | } `yaml:"website"` | |||
| 19 | + | } | |||
| 20 | + | ||||
| 21 | + | type StaticData struct { | |||
| 22 | + | Title string `yaml:"title"` | |||
| 23 | + | User string `yaml:"user"` | |||
| 24 | + | } | |||
| 25 | + | ||||
| 26 | + | // LoadDataFromYAML loads the data from the given YAML file | |||
| 27 | + | func LoadDataFromYAML() (Data, error) { | |||
| 28 | + | var data Data | |||
| 29 | + | ||||
| 30 | + | // Open the YAML file inside the ui/components directory | |||
| 31 | + | file, err := ui.TemplateFS.Open("strings.yaml") | |||
| 32 | + | if err != nil { | |||
| 33 | + | return data, fmt.Errorf("failed to open strings.yaml: %w", err) | |||
| 34 | + | } | |||
| 35 | + | defer file.Close() | |||
| 36 | + | ||||
| 37 | + | // Read the content of the file | |||
| 38 | + | content, err := io.ReadAll(file) | |||
| 39 | + | if err != nil { | |||
| 40 | + | return data, fmt.Errorf("failed to read strings.yaml: %w", err) | |||
| 41 | + | } | |||
| 42 | + | ||||
| 43 | + | // Unmarshal the YAML content into the Data struct | |||
| 44 | + | if err := yaml.Unmarshal(content, &data); err != nil { | |||
| 45 | + | return data, fmt.Errorf("failed to unmarshal strings.yaml: %w", err) | |||
| 46 | + | } | |||
| 47 | + | ||||
| 48 | + | return data, nil | |||
| 49 | + | } | |||
M pkg/utils/render.go +3 -5
| @@ -11,9 +11,8 @@ type Renderer struct { | |||
| 11 | 11 | ParseError error | |
| 12 | 12 | } | |
| 13 | 13 | ||
| 14 | - | // Render executes the template with the specified data as the dot object | |
| 15 | - | // and returns the result as plain string. | |
| 16 | - | func (r *Renderer) Render(data any) (string, error) { | |
| 14 | + | // Render function renders the template with the given data | |
| 15 | + | func (r *Renderer) Render(data interface{}) (string, error) { | |
| 17 | 16 | if r.ParseError != nil { | |
| 18 | 17 | return "", r.ParseError | |
| 19 | 18 | } | |
| @@ -23,10 +22,9 @@ func (r *Renderer) Render(data any) (string, error) { | |||
| 23 | 22 | } | |
| 24 | 23 | ||
| 25 | 24 | buf := new(bytes.Buffer) | |
| 26 | - | ||
| 27 | 25 | err := r.Template.Execute(buf, data) | |
| 28 | 26 | if err != nil { | |
| 29 | - | return "", errors.New("failed to execute template: " + err.Error()) | |
| 27 | + | return "", err | |
| 30 | 28 | } | |
| 31 | 29 | ||
| 32 | 30 | return buf.String(), nil | |
| @@ -11,9 +11,8 @@ type Renderer struct { | |||||
| 11 | ParseError error | 11 | ParseError error | ||
| 12 | } | 12 | } | ||
| 13 | 13 | ||||
| 14 | - | // Render executes the template with the specified data as the dot object | 14 | + | // Render function renders the template with the given data |
| 15 | - | // and returns the result as plain string. | 15 | + | func (r *Renderer) Render(data interface{}) (string, error) { |
| 16 | - | func (r *Renderer) Render(data any) (string, error) { | |||
| 17 | if r.ParseError != nil { | 16 | if r.ParseError != nil { | ||
| 18 | return "", r.ParseError | 17 | return "", r.ParseError | ||
| 19 | } | 18 | } | ||
| @@ -23,10 +22,9 @@ func (r *Renderer) Render(data any) (string, error) { | |||||
| 23 | } | 22 | } | ||
| 24 | 23 | ||||
| 25 | buf := new(bytes.Buffer) | 24 | buf := new(bytes.Buffer) | ||
| 26 | - | ||||
| 27 | err := r.Template.Execute(buf, data) | 25 | err := r.Template.Execute(buf, data) | ||
| 28 | if err != nil { | 26 | if err != nil { | ||
| 29 | - | return "", errors.New("failed to execute template: " + err.Error()) | 27 | + | return "", err |
| 30 | } | 28 | } | ||
| 31 | 29 | ||||
| 32 | return buf.String(), nil | 30 | return buf.String(), nil | ||