@@ -7,15 +7,18 @@ import (
77 "bytes"
88 "context"
99 "fmt"
10+ "html/template"
11+ "io"
12+ "net/http"
13+ "path/filepath"
1014 "regexp"
1115 "strconv"
1216 "strings"
17+ "sync/atomic"
1318
1419 "code.gitea.io/gitea/modules/log"
1520 "code.gitea.io/gitea/modules/setting"
1621 "code.gitea.io/gitea/modules/watcher"
17-
18- "github.com/unrolled/render"
1922)
2023
2124var (
@@ -27,14 +30,50 @@ var (
2730 expectedEndError = regexp .MustCompile (`^template: (.*):([0-9]+): expected end; found (.*)` )
2831)
2932
30- // HTMLRenderer returns the current html renderer for the context or creates and stores one within the context for future use
31- func HTMLRenderer (ctx context.Context ) (context.Context , * render.Render ) {
32- rendererInterface := ctx .Value (rendererKey )
33- if rendererInterface != nil {
34- renderer , ok := rendererInterface .(* render.Render )
35- if ok {
36- return ctx , renderer
33+ type HTMLRender struct {
34+ templates atomic.Pointer [template.Template ]
35+ }
36+
37+ func (h * HTMLRender ) HTML (w io.Writer , status int , name string , data interface {}) error {
38+ if respWriter , ok := w .(http.ResponseWriter ); ok {
39+ if respWriter .Header ().Get ("Content-Type" ) == "" {
40+ respWriter .Header ().Set ("Content-Type" , "text/html; charset=utf-8" )
41+ }
42+ respWriter .WriteHeader (status )
43+ }
44+ return h .templates .Load ().ExecuteTemplate (w , name , data )
45+ }
46+
47+ func (h * HTMLRender ) TemplateLookup (t string ) * template.Template {
48+ return h .templates .Load ().Lookup (t )
49+ }
50+
51+ func (h * HTMLRender ) CompileTemplates () error {
52+ dirPrefix := "templates/"
53+ tmpls := template .New ("" )
54+ for _ , path := range GetTemplateAssetNames () {
55+ name := path [len (dirPrefix ):]
56+ name = strings .TrimSuffix (name , ".tmpl" )
57+ tmpl := tmpls .New (filepath .ToSlash (name ))
58+ for _ , fm := range NewFuncMap () {
59+ tmpl .Funcs (fm )
60+ }
61+ buf , err := GetAsset (path )
62+ if err != nil {
63+ return err
3764 }
65+ if _ , err = tmpl .Parse (string (buf )); err != nil {
66+ return err
67+ }
68+ }
69+ h .templates .Store (tmpls )
70+ return nil
71+ }
72+
73+ // HTMLRenderer returns the current html renderer for the context or creates and stores one within the context for future use
74+ func HTMLRenderer (ctx context.Context ) (context.Context , * HTMLRender ) {
75+ if renderer , ok := ctx .Value (rendererKey ).(* HTMLRender ); ok {
76+ return ctx , renderer
3877 }
3978
4079 rendererType := "static"
@@ -43,53 +82,24 @@ func HTMLRenderer(ctx context.Context) (context.Context, *render.Render) {
4382 }
4483 log .Log (1 , log .DEBUG , "Creating " + rendererType + " HTML Renderer" )
4584
46- compilingTemplates := true
47- defer func () {
48- if ! compilingTemplates {
49- return
50- }
51-
52- panicked := recover ()
53- if panicked == nil {
54- return
55- }
56-
57- // OK try to handle the panic...
58- err , ok := panicked .(error )
59- if ok {
60- handlePanicError (err )
61- }
62- log .Fatal ("PANIC: Unable to compile templates!\n %v\n \n Stacktrace:\n %s" , panicked , log .Stack (2 ))
63- }()
64-
65- renderer := render .New (render.Options {
66- Extensions : []string {".tmpl" },
67- Directory : "templates" ,
68- Funcs : NewFuncMap (),
69- Asset : GetAsset ,
70- AssetNames : GetTemplateAssetNames ,
71- UseMutexLock : ! setting .IsProd ,
72- IsDevelopment : false ,
73- DisableHTTPErrorRendering : true ,
74- })
75- compilingTemplates = false
85+ renderer := & HTMLRender {}
86+ if err := renderer .CompileTemplates (); err != nil {
87+ handleFatalError (err )
88+ }
7689 if ! setting .IsProd {
7790 watcher .CreateWatcher (ctx , "HTML Templates" , & watcher.CreateWatcherOpts {
7891 PathsCallback : walkTemplateFiles ,
7992 BetweenCallback : func () {
80- defer func () {
81- if err := recover (); err != nil {
82- log .Error ("PANIC: %v\n %s" , err , log .Stack (2 ))
83- }
84- }()
85- renderer .CompileTemplates ()
93+ if err := renderer .CompileTemplates (); err != nil {
94+ log .Error ("Template error: %v\n %s" , err , log .Stack (2 ))
95+ }
8696 },
8797 })
8898 }
8999 return context .WithValue (ctx , rendererKey , renderer ), renderer
90100}
91101
92- func handlePanicError (err error ) {
102+ func handleFatalError (err error ) {
93103 wrapFatal (handleNotDefinedPanicError (err ))
94104 wrapFatal (handleUnexpected (err ))
95105 wrapFatal (handleExpectedEnd (err ))
0 commit comments