diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/context/context.go | 3 | ||||
-rw-r--r-- | modules/templates/htmlrenderer.go | 102 | ||||
-rw-r--r-- | modules/test/context_tests.go | 3 |
3 files changed, 58 insertions, 50 deletions
diff --git a/modules/context/context.go b/modules/context/context.go index 1eff1459a1..04f8a9bd3d 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -42,14 +42,13 @@ import ( "gitea.com/go-chi/session" chi "github.com/go-chi/chi/v5" "github.com/minio/sha256-simd" - "github.com/unrolled/render" "golang.org/x/crypto/pbkdf2" ) // Render represents a template render type Render interface { TemplateLookup(tmpl string) *template.Template - HTML(w io.Writer, status int, name string, binding interface{}, htmlOpt ...render.HTMLOptions) error + HTML(w io.Writer, status int, name string, data interface{}) error } // Context represents context of a request. diff --git a/modules/templates/htmlrenderer.go b/modules/templates/htmlrenderer.go index 96dc010796..fd985edc64 100644 --- a/modules/templates/htmlrenderer.go +++ b/modules/templates/htmlrenderer.go @@ -7,15 +7,18 @@ import ( "bytes" "context" "fmt" + "html/template" + "io" + "net/http" + "path/filepath" "regexp" "strconv" "strings" + "sync/atomic" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/watcher" - - "github.com/unrolled/render" ) var ( @@ -27,14 +30,50 @@ var ( expectedEndError = regexp.MustCompile(`^template: (.*):([0-9]+): expected end; found (.*)`) ) -// HTMLRenderer returns the current html renderer for the context or creates and stores one within the context for future use -func HTMLRenderer(ctx context.Context) (context.Context, *render.Render) { - rendererInterface := ctx.Value(rendererKey) - if rendererInterface != nil { - renderer, ok := rendererInterface.(*render.Render) - if ok { - return ctx, renderer +type HTMLRender struct { + templates atomic.Pointer[template.Template] +} + +func (h *HTMLRender) HTML(w io.Writer, status int, name string, data interface{}) error { + if respWriter, ok := w.(http.ResponseWriter); ok { + if respWriter.Header().Get("Content-Type") == "" { + respWriter.Header().Set("Content-Type", "text/html; charset=utf-8") + } + respWriter.WriteHeader(status) + } + return h.templates.Load().ExecuteTemplate(w, name, data) +} + +func (h *HTMLRender) TemplateLookup(t string) *template.Template { + return h.templates.Load().Lookup(t) +} + +func (h *HTMLRender) CompileTemplates() error { + dirPrefix := "templates/" + tmpls := template.New("") + for _, path := range GetTemplateAssetNames() { + name := path[len(dirPrefix):] + name = strings.TrimSuffix(name, ".tmpl") + tmpl := tmpls.New(filepath.ToSlash(name)) + for _, fm := range NewFuncMap() { + tmpl.Funcs(fm) + } + buf, err := GetAsset(path) + if err != nil { + return err } + if _, err = tmpl.Parse(string(buf)); err != nil { + return err + } + } + h.templates.Store(tmpls) + return nil +} + +// HTMLRenderer returns the current html renderer for the context or creates and stores one within the context for future use +func HTMLRenderer(ctx context.Context) (context.Context, *HTMLRender) { + if renderer, ok := ctx.Value(rendererKey).(*HTMLRender); ok { + return ctx, renderer } rendererType := "static" @@ -43,53 +82,24 @@ func HTMLRenderer(ctx context.Context) (context.Context, *render.Render) { } log.Log(1, log.DEBUG, "Creating "+rendererType+" HTML Renderer") - compilingTemplates := true - defer func() { - if !compilingTemplates { - return - } - - panicked := recover() - if panicked == nil { - return - } - - // OK try to handle the panic... - err, ok := panicked.(error) - if ok { - handlePanicError(err) - } - log.Fatal("PANIC: Unable to compile templates!\n%v\n\nStacktrace:\n%s", panicked, log.Stack(2)) - }() - - renderer := render.New(render.Options{ - Extensions: []string{".tmpl"}, - Directory: "templates", - Funcs: NewFuncMap(), - Asset: GetAsset, - AssetNames: GetTemplateAssetNames, - UseMutexLock: !setting.IsProd, - IsDevelopment: false, - DisableHTTPErrorRendering: true, - }) - compilingTemplates = false + renderer := &HTMLRender{} + if err := renderer.CompileTemplates(); err != nil { + handleFatalError(err) + } if !setting.IsProd { watcher.CreateWatcher(ctx, "HTML Templates", &watcher.CreateWatcherOpts{ PathsCallback: walkTemplateFiles, BetweenCallback: func() { - defer func() { - if err := recover(); err != nil { - log.Error("PANIC: %v\n%s", err, log.Stack(2)) - } - }() - renderer.CompileTemplates() + if err := renderer.CompileTemplates(); err != nil { + log.Error("Template error: %v\n%s", err, log.Stack(2)) + } }, }) } return context.WithValue(ctx, rendererKey, renderer), renderer } -func handlePanicError(err error) { +func handleFatalError(err error) { wrapFatal(handleNotDefinedPanicError(err)) wrapFatal(handleUnexpected(err)) wrapFatal(handleExpectedEnd(err)) diff --git a/modules/test/context_tests.go b/modules/test/context_tests.go index 6c434c201b..5e66049535 100644 --- a/modules/test/context_tests.go +++ b/modules/test/context_tests.go @@ -22,7 +22,6 @@ import ( chi "github.com/go-chi/chi/v5" "github.com/stretchr/testify/assert" - "github.com/unrolled/render" ) // MockContext mock context for unit tests @@ -138,7 +137,7 @@ func (tr *mockRender) TemplateLookup(tmpl string) *template.Template { return nil } -func (tr *mockRender) HTML(w io.Writer, status int, _ string, _ interface{}, _ ...render.HTMLOptions) error { +func (tr *mockRender) HTML(w io.Writer, status int, _ string, _ interface{}) error { if resp, ok := w.(http.ResponseWriter); ok { resp.WriteHeader(status) } |