From 2d613dd905bb8eeb8af57e30ddd749a0f04fbd3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Wed, 13 Sep 2017 12:32:06 +0200 Subject: [PATCH] tpl/tplimpl: Fix escaped HTML Go 1.9 multioutput issue (#3880) Fixes #3876 --- hugolib/site_output_test.go | 7 ++++ tpl/tplimpl/template.go | 6 ++-- tpl/tplimpl/template_test.go | 64 ++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 tpl/tplimpl/template_test.go diff --git a/hugolib/site_output_test.go b/hugolib/site_output_test.go index 941387e35..a8a43d625 100644 --- a/hugolib/site_output_test.go +++ b/hugolib/site_output_test.go @@ -125,6 +125,9 @@ outputs: %s # Doc {{< myShort >}} + +{{< myOtherShort >}} + ` mf := afero.NewMemMapFs() @@ -144,6 +147,7 @@ other = "Olboge" "layouts/partials/GoHugo.html", `Go Hugo Partial`, "layouts/_default/baseof.json", `START JSON:{{block "main" .}}default content{{ end }}:END JSON`, "layouts/_default/baseof.html", `START HTML:{{block "main" .}}default content{{ end }}:END HTML`, + "layouts/shortcodes/myOtherShort.html", `OtherShort: {{ "

Hi!

" | safeHTML }}`, "layouts/shortcodes/myShort.html", `ShortHTML`, "layouts/shortcodes/myShort.json", `ShortJSON`, @@ -210,6 +214,7 @@ Content: {{ .Content }} "Output/Rel: HTML/canonical|", "en: Elbow", "ShortJSON", + "OtherShort:

Hi!

", ) th.assertFileContent("public/index.html", @@ -218,6 +223,7 @@ Content: {{ .Content }} `List HTML|JSON Home|`, "en: Elbow", "ShortHTML", + "OtherShort:

Hi!

", ) th.assertFileContent("public/nn/index.html", "List HTML|JSON Nynorsk Heim|", @@ -228,6 +234,7 @@ Content: {{ .Content }} // JSON is plain text, so no need to safeHTML this and that ``, "ShortJSON", + "OtherShort:

Hi!

", ) th.assertFileContent("public/nn/index.json", "List JSON|JSON Nynorsk Heim|", diff --git a/tpl/tplimpl/template.go b/tpl/tplimpl/template.go index 06ab775c3..a8417819e 100644 --- a/tpl/tplimpl/template.go +++ b/tpl/tplimpl/template.go @@ -305,7 +305,8 @@ func (t *htmlTemplates) addTemplateIn(tt *template.Template, name, tpl string) e // We need to keep track of one ot the output format's shortcode template // without knowing the rendering context. withoutExt := strings.TrimSuffix(name, path.Ext(name)) - tt.AddParseTree(withoutExt, templ.Tree) + clone := template.Must(templ.Clone()) + tt.AddParseTree(withoutExt, clone.Tree) } return nil @@ -334,7 +335,8 @@ func (t *textTemplates) addTemplateIn(tt *texttemplate.Template, name, tpl strin // We need to keep track of one ot the output format's shortcode template // without knowing the rendering context. withoutExt := strings.TrimSuffix(name, path.Ext(name)) - tt.AddParseTree(withoutExt, templ.Tree) + clone := texttemplate.Must(templ.Clone()) + tt.AddParseTree(withoutExt, clone.Tree) } return nil diff --git a/tpl/tplimpl/template_test.go b/tpl/tplimpl/template_test.go new file mode 100644 index 000000000..b94848394 --- /dev/null +++ b/tpl/tplimpl/template_test.go @@ -0,0 +1,64 @@ +// Copyright 2017-present The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tplimpl + +import ( + "testing" + + "github.com/gohugoio/hugo/deps" + "github.com/gohugoio/hugo/hugofs" + "github.com/spf13/viper" + "github.com/stretchr/testify/require" +) + +type handler interface { + addTemplate(name, tpl string) error +} + +// #3876 +func TestHTMLEscape(t *testing.T) { + assert := require.New(t) + + data := map[string]string{ + "html": "

Hi!

", + "other": "

Hi!

", + } + v := viper.New() + fs := hugofs.NewMem(v) + + //afero.WriteFile(fs.Source, filepath.Join(workingDir, "README.txt"), []byte("Hugo Rocks!"), 0755) + + depsCfg := newDepsConfig(v) + depsCfg.Fs = fs + d, err := deps.New(depsCfg) + assert.NoError(err) + + tpl := `{{ "

Hi!

" | safeHTML }}` + + provider := DefaultTemplateProvider + provider.Update(d) + + h := d.Tmpl.(handler) + + assert.NoError(h.addTemplate("shortcodes/myShort.html", tpl)) + + s, err := d.Tmpl.Lookup("shortcodes/myShort.html").ExecuteToString(data) + assert.NoError(err) + assert.Contains(s, "

Hi!

") + + s, err = d.Tmpl.Lookup("shortcodes/myShort").ExecuteToString(data) + assert.NoError(err) + assert.Contains(s, "

Hi!

") + +}