Skip to content

Commit 369f257

Browse files
committed
Adding ability to set html/template options
1 parent b037de6 commit 369f257

File tree

4 files changed

+88
-0
lines changed

4 files changed

+88
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ r := render.New(render.Options{
101101
UseMutexLock: true, // Overrides the default no lock implementation and uses the standard `sync.RWMutex` lock.
102102
UnEscapeHTML: true, // Replace ensure '&<>' are output correctly (JSON only).
103103
StreamingJSON: true, // Streams the JSON response via json.Encoder.
104+
HTMLTemplateOption: "missingkey=error", // Sets the option value for HTML templates. See https://pkg.go.dev/html/template#Template.Option for a list of known options.
104105
RequirePartials: true, // Return an error if a template is missing a partial used in a layout.
105106
DisableHTTPErrorRendering: true, // Disables automatic rendering of http.StatusInternalServerError when an error occurs.
106107
})
@@ -139,6 +140,7 @@ r := render.New(render.Options{
139140
IsDevelopment: false,
140141
UseMutexLock: false,
141142
UnEscapeHTML: false,
143+
HTMLTemplateOption: "",
142144
StreamingJSON: false,
143145
RequirePartials: false,
144146
DisableHTTPErrorRendering: false,

render.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ type Options struct {
9797
UseMutexLock bool
9898
// Unescape HTML characters "&<>" to their original values. Default is false.
9999
UnEscapeHTML bool
100+
// Sets the `Option` value for HTML templates. Defaults to blank ("").
101+
HTMLTemplateOption string
100102
// Streams JSON responses instead of marshalling prior to sending. Default is false.
101103
StreamingJSON bool
102104
// Require that all partials executed in the layout are implemented in all templates using the layout. Default is false.
@@ -217,6 +219,11 @@ func (r *Render) CompileTemplates() {
217219
func (r *Render) compileTemplatesFromDir() {
218220
dir := r.opt.Directory
219221
tmpTemplates := template.New(dir)
222+
223+
if len(r.opt.HTMLTemplateOption) > 0 {
224+
tmpTemplates.Option(r.opt.HTMLTemplateOption)
225+
}
226+
220227
tmpTemplates.Delims(r.opt.Delims.Left, r.opt.Delims.Right)
221228

222229
var watcher *fsnotify.Watcher
@@ -301,6 +308,11 @@ func (r *Render) compileTemplatesFromDir() {
301308
func (r *Render) compileTemplatesFromAsset() {
302309
dir := r.opt.Directory
303310
tmpTemplates := template.New(dir)
311+
312+
if len(r.opt.HTMLTemplateOption) > 0 {
313+
tmpTemplates.Option(r.opt.HTMLTemplateOption)
314+
}
315+
304316
tmpTemplates.Delims(r.opt.Delims.Left, r.opt.Delims.Right)
305317

306318
for _, path := range r.opt.AssetNames() {

render_html_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"html/template"
77
"net/http"
88
"net/http/httptest"
9+
"strings"
910
"testing"
1011
)
1112

@@ -428,3 +429,75 @@ func TestHTMLDisabledCharset(t *testing.T) {
428429
expect(t, res.Header().Get(ContentType), ContentHTML)
429430
expect(t, res.Body.String(), "<h1>Hello gophers</h1>\n")
430431
}
432+
433+
func TestHTMLTemplateOptionDefault(t *testing.T) {
434+
render := New(Options{
435+
Directory: "testdata/basic",
436+
})
437+
438+
var err error
439+
440+
// Template expects "world" key.
441+
templateData := map[string]int{"missing-key-here": 100}
442+
443+
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
444+
err = render.HTML(w, http.StatusOK, "map", templateData)
445+
})
446+
447+
res := httptest.NewRecorder()
448+
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, "/foo", nil)
449+
h.ServeHTTP(res, req)
450+
451+
expectNil(t, err)
452+
expect(t, res.Code, 200)
453+
expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8")
454+
expect(t, res.Body.String(), "<h1>Hello </h1>\n")
455+
}
456+
457+
func TestHTMLTemplateOptionZero(t *testing.T) {
458+
render := New(Options{
459+
Directory: "testdata/basic",
460+
HTMLTemplateOption: "missingkey=zero",
461+
})
462+
463+
var err error
464+
465+
// Template expects "world" key.
466+
templateData := map[string]int{"missing-key-here": 100}
467+
468+
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
469+
err = render.HTML(w, http.StatusOK, "map", templateData)
470+
})
471+
472+
res := httptest.NewRecorder()
473+
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, "/foo", nil)
474+
h.ServeHTTP(res, req)
475+
476+
expectNil(t, err)
477+
expect(t, res.Code, 200)
478+
expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8")
479+
expect(t, res.Body.String(), "<h1>Hello 0</h1>\n")
480+
}
481+
482+
func TestHTMLTemplateOptionError(t *testing.T) {
483+
render := New(Options{
484+
Directory: "testdata/basic",
485+
HTMLTemplateOption: "missingkey=error",
486+
})
487+
488+
var err error
489+
490+
// Template expects "world" key.
491+
templateData := map[string]string{"missing-key-here": "gophers"}
492+
493+
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
494+
err = render.HTML(w, http.StatusOK, "map", templateData)
495+
})
496+
497+
res := httptest.NewRecorder()
498+
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, "/foo", nil)
499+
h.ServeHTTP(res, req)
500+
501+
expectNotNil(t, err)
502+
expect(t, strings.Contains(err.Error(), "map has no entry for key"), true)
503+
}

testdata/basic/map.tmpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>Hello {{.world}}</h1>

0 commit comments

Comments
 (0)