aboutsummaryrefslogtreecommitdiff
path: root/forged
diff options
context:
space:
mode:
authorRunxi Yu <me@runxiyu.org>2025-08-18 02:09:50 +0800
committerRunxi Yu <me@runxiyu.org>2025-08-18 02:09:50 +0800
commitaa63d26cdd4284faf67f9582d34a12c8767aed15 (patch)
treebd895fd2c5a87b4cf5d943775e6a1eff730886bd /forged
parentAdd templates and static paths to the web config (diff)
downloadforge-aa63d26cdd4284faf67f9582d34a12c8767aed15.tar.gz
forge-aa63d26cdd4284faf67f9582d34a12c8767aed15.tar.zst
forge-aa63d26cdd4284faf67f9582d34a12c8767aed15.zip
Add template rendering
Diffstat (limited to 'forged')
-rw-r--r--forged/internal/incoming/web/handler.go25
-rw-r--r--forged/internal/incoming/web/handlers/group.go14
-rw-r--r--forged/internal/incoming/web/handlers/index.go17
-rw-r--r--forged/internal/incoming/web/handlers/repo/index.go18
-rw-r--r--forged/internal/incoming/web/templates/load.go31
-rw-r--r--forged/internal/incoming/web/templates/renderer.go23
6 files changed, 109 insertions, 19 deletions
diff --git a/forged/internal/incoming/web/handler.go b/forged/internal/incoming/web/handler.go
index 10f85d6..da2a2e0 100644
--- a/forged/internal/incoming/web/handler.go
+++ b/forged/internal/incoming/web/handler.go
@@ -1,11 +1,13 @@
package web
import (
+ "html/template"
"net/http"
- "path/filepath"
+ "go.lindenii.runxiyu.org/forge/forged/internal/common/misc"
handlers "go.lindenii.runxiyu.org/forge/forged/internal/incoming/web/handlers"
repoHandlers "go.lindenii.runxiyu.org/forge/forged/internal/incoming/web/handlers/repo"
+ "go.lindenii.runxiyu.org/forge/forged/internal/incoming/web/templates"
)
type handler struct {
@@ -15,18 +17,25 @@ type handler struct {
func NewHandler(cfg Config) http.Handler {
h := &handler{r: NewRouter().ReverseProxy(cfg.ReverseProxy)}
- // Static files
- staticDir := filepath.Join(cfg.Root, "static")
- staticFS := http.FileServer(http.Dir(staticDir))
+ staticFS := http.FileServer(http.Dir(cfg.StaticPath))
h.r.ANYHTTP("-/static/*rest",
http.StripPrefix("/-/static/", staticFS),
WithDirIfEmpty("rest"),
)
- // Feature handler instances
- indexHTTP := handlers.NewIndexHTTP()
- groupHTTP := handlers.NewGroupHTTP()
- repoHTTP := repoHandlers.NewHTTP()
+ funcs := template.FuncMap{
+ "path_escape": misc.PathEscape,
+ "query_escape": misc.QueryEscape,
+ "minus": misc.Minus,
+ "first_line": misc.FirstLine,
+ "dereference_error": misc.DereferenceOrZero[error],
+ }
+ t := templates.MustParseDir(cfg.TemplatesPath, funcs)
+ renderer := templates.New(t)
+
+ indexHTTP := handlers.NewIndexHTTP(renderer)
+ groupHTTP := handlers.NewGroupHTTP(renderer)
+ repoHTTP := repoHandlers.NewHTTP(renderer)
notImpl := handlers.NewNotImplementedHTTP()
// Index
diff --git a/forged/internal/incoming/web/handlers/group.go b/forged/internal/incoming/web/handlers/group.go
index 1a1cb1d..0c631c3 100644
--- a/forged/internal/incoming/web/handlers/group.go
+++ b/forged/internal/incoming/web/handlers/group.go
@@ -4,14 +4,22 @@ import (
"net/http"
"strings"
+ "go.lindenii.runxiyu.org/forge/forged/internal/incoming/web/templates"
wtypes "go.lindenii.runxiyu.org/forge/forged/internal/incoming/web/types"
)
-type GroupHTTP struct{}
+type GroupHTTP struct {
+ r templates.Renderer
+}
-func NewGroupHTTP() *GroupHTTP { return &GroupHTTP{} }
+func NewGroupHTTP(r templates.Renderer) *GroupHTTP { return &GroupHTTP{r: r} }
func (h *GroupHTTP) Index(w http.ResponseWriter, r *http.Request, _ wtypes.Vars) {
base := wtypes.Base(r)
- _, _ = w.Write([]byte("group index for: /" + strings.Join(base.GroupPath, "/") + "/"))
+ _ = h.r.Render(w, "group/index.html", struct {
+ GroupPath string
+ }{
+ GroupPath: "/" + strings.Join(base.GroupPath, "/") + "/",
+ })
}
+
diff --git a/forged/internal/incoming/web/handlers/index.go b/forged/internal/incoming/web/handlers/index.go
index 1fd2954..259ca4a 100644
--- a/forged/internal/incoming/web/handlers/index.go
+++ b/forged/internal/incoming/web/handlers/index.go
@@ -1,15 +1,26 @@
package handlers
import (
+ "log"
"net/http"
+ "go.lindenii.runxiyu.org/forge/forged/internal/incoming/web/templates"
wtypes "go.lindenii.runxiyu.org/forge/forged/internal/incoming/web/types"
)
-type IndexHTTP struct{}
+type IndexHTTP struct {
+ r templates.Renderer
+}
-func NewIndexHTTP() *IndexHTTP { return &IndexHTTP{} }
+func NewIndexHTTP(r templates.Renderer) *IndexHTTP { return &IndexHTTP{r: r} }
func (h *IndexHTTP) Index(w http.ResponseWriter, _ *http.Request, _ wtypes.Vars) {
- _, _ = w.Write([]byte("index: replace with template render"))
+ err := h.r.Render(w, "index", struct {
+ Title string
+ }{
+ Title: "Home",
+ })
+ if err != nil {
+ log.Println("failed to render index page", "error", err)
+ }
}
diff --git a/forged/internal/incoming/web/handlers/repo/index.go b/forged/internal/incoming/web/handlers/repo/index.go
index 3a6d7ea..dd1382f 100644
--- a/forged/internal/incoming/web/handlers/repo/index.go
+++ b/forged/internal/incoming/web/handlers/repo/index.go
@@ -1,20 +1,28 @@
package repo
import (
- "fmt"
"net/http"
"strings"
+ "go.lindenii.runxiyu.org/forge/forged/internal/incoming/web/templates"
wtypes "go.lindenii.runxiyu.org/forge/forged/internal/incoming/web/types"
)
-type HTTP struct{}
+type HTTP struct {
+ r templates.Renderer
+}
-func NewHTTP() *HTTP { return &HTTP{} }
+func NewHTTP(r templates.Renderer) *HTTP { return &HTTP{r: r} }
func (h *HTTP) Index(w http.ResponseWriter, r *http.Request, v wtypes.Vars) {
base := wtypes.Base(r)
repo := v["repo"]
- _, _ = w.Write([]byte(fmt.Sprintf("repo index: group=%q repo=%q",
- "/"+strings.Join(base.GroupPath, "/")+"/", repo)))
+ _ = h.r.Render(w, "repo/index.html", struct {
+ Group string
+ Repo string
+ }{
+ Group: "/" + strings.Join(base.GroupPath, "/") + "/",
+ Repo: repo,
+ })
}
+
diff --git a/forged/internal/incoming/web/templates/load.go b/forged/internal/incoming/web/templates/load.go
new file mode 100644
index 0000000..4a6fc49
--- /dev/null
+++ b/forged/internal/incoming/web/templates/load.go
@@ -0,0 +1,31 @@
+package templates
+
+import (
+ "html/template"
+ "io/fs"
+ "os"
+ "path/filepath"
+)
+
+func MustParseDir(dir string, funcs template.FuncMap) *template.Template {
+ base := template.New("").Funcs(funcs)
+
+ err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
+ if err != nil {
+ return err
+ }
+ if d.IsDir() {
+ return nil
+ }
+ b, err := os.ReadFile(path)
+ if err != nil {
+ return err
+ }
+ _, err = base.Parse(string(b))
+ return err
+ })
+ if err != nil {
+ panic(err)
+ }
+ return base
+}
diff --git a/forged/internal/incoming/web/templates/renderer.go b/forged/internal/incoming/web/templates/renderer.go
new file mode 100644
index 0000000..1e2f325
--- /dev/null
+++ b/forged/internal/incoming/web/templates/renderer.go
@@ -0,0 +1,23 @@
+package templates
+
+import (
+ "html/template"
+ "net/http"
+)
+
+type Renderer interface {
+ Render(w http.ResponseWriter, name string, data any) error
+}
+
+type tmplRenderer struct {
+ t *template.Template
+}
+
+func New(t *template.Template) Renderer {
+ return &tmplRenderer{t: t}
+}
+
+func (r *tmplRenderer) Render(w http.ResponseWriter, name string, data any) error {
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ return r.t.ExecuteTemplate(w, name, data)
+}