mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
tpl/encoding: Add noHTMLEscape option to jsonify
This commit is contained in:
parent
2ef60dbd2d
commit
09e10110a3
3 changed files with 51 additions and 11 deletions
|
@ -32,6 +32,17 @@ more copies of *indent* according to the indentation nesting.
|
|||
{{ dict "title" .Title "content" .Plain | jsonify (dict "prefix" " " "indent" " ") }}
|
||||
```
|
||||
|
||||
## Jsonify options
|
||||
|
||||
indent ("")
|
||||
: Indendation to use.
|
||||
|
||||
prefix ("")
|
||||
: Indentation prefix.
|
||||
|
||||
noHTMLEscape (false)
|
||||
: Disable escaping of problematic HTML characters inside JSON quoted strings. The default behavior is to escape &, <, and > to \u0026, \u003c, and \u003e to avoid certain safety problems that can arise when embedding JSON in HTML.
|
||||
|
||||
See also the `.PlainWords`, `.Plain`, and `.RawContent` [page variables][pagevars].
|
||||
|
||||
[pagevars]: /variables/page/
|
||||
|
|
|
@ -20,7 +20,10 @@ import (
|
|||
"errors"
|
||||
"html/template"
|
||||
|
||||
bp "github.com/gohugoio/hugo/bufferpool"
|
||||
|
||||
"github.com/gohugoio/hugo/common/maps"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
|
@ -62,22 +65,25 @@ func (ns *Namespace) Jsonify(args ...any) (template.HTML, error) {
|
|||
var (
|
||||
b []byte
|
||||
err error
|
||||
obj any
|
||||
opts jsonifyOpts
|
||||
)
|
||||
|
||||
switch len(args) {
|
||||
case 0:
|
||||
return "", nil
|
||||
case 1:
|
||||
b, err = json.Marshal(args[0])
|
||||
obj = args[0]
|
||||
case 2:
|
||||
var opts map[string]string
|
||||
|
||||
opts, err = maps.ToStringMapStringE(args[0])
|
||||
var m map[string]any
|
||||
m, err = maps.ToStringMapE(args[0])
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
b, err = json.MarshalIndent(args[1], opts["prefix"], opts["indent"])
|
||||
if err = mapstructure.WeakDecode(m, &opts); err != nil {
|
||||
break
|
||||
}
|
||||
obj = args[1]
|
||||
default:
|
||||
err = errors.New("too many arguments to jsonify")
|
||||
}
|
||||
|
@ -86,5 +92,25 @@ func (ns *Namespace) Jsonify(args ...any) (template.HTML, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
buff := bp.GetBuffer()
|
||||
defer bp.PutBuffer(buff)
|
||||
e := json.NewEncoder(buff)
|
||||
e.SetEscapeHTML(!opts.NoHTMLEscape)
|
||||
e.SetIndent(opts.Prefix, opts.Indent)
|
||||
if err = e.Encode(obj); err != nil {
|
||||
return "", err
|
||||
}
|
||||
b = buff.Bytes()
|
||||
// See https://github.com/golang/go/issues/37083
|
||||
// Hugo changed from MarshalIndent/Marshal. To make the output
|
||||
// the same, we need to trim the trailing newline.
|
||||
b = b[:len(b)-1]
|
||||
|
||||
return template.HTML(b), nil
|
||||
}
|
||||
|
||||
type jsonifyOpts struct {
|
||||
Prefix string
|
||||
Indent string
|
||||
NoHTMLEscape bool
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ func TestJsonify(t *testing.T) {
|
|||
c := qt.New(t)
|
||||
ns := New()
|
||||
|
||||
for _, test := range []struct {
|
||||
for i, test := range []struct {
|
||||
opts any
|
||||
v any
|
||||
expect any
|
||||
|
@ -91,6 +91,9 @@ func TestJsonify(t *testing.T) {
|
|||
{map[string]string{"indent": "<i>"}, []string{"a", "b"}, template.HTML("[\n<i>\"a\",\n<i>\"b\"\n]")},
|
||||
{map[string]string{"prefix": "<p>"}, []string{"a", "b"}, template.HTML("[\n<p>\"a\",\n<p>\"b\"\n<p>]")},
|
||||
{map[string]string{"prefix": "<p>", "indent": "<i>"}, []string{"a", "b"}, template.HTML("[\n<p><i>\"a\",\n<p><i>\"b\"\n<p>]")},
|
||||
{map[string]string{"indent": "<i>"}, []string{"a", "b"}, template.HTML("[\n<i>\"a\",\n<i>\"b\"\n]")},
|
||||
{map[string]any{"noHTMLEscape": false}, []string{"<a>", "<b>"}, template.HTML("[\"\\u003ca\\u003e\",\"\\u003cb\\u003e\"]")},
|
||||
{map[string]any{"noHTMLEscape": true}, []string{"<a>", "<b>"}, template.HTML("[\"<a>\",\"<b>\"]")},
|
||||
{nil, tstNoStringer{}, template.HTML("{}")},
|
||||
{nil, nil, template.HTML("null")},
|
||||
// errors
|
||||
|
@ -108,11 +111,11 @@ func TestJsonify(t *testing.T) {
|
|||
result, err := ns.Jsonify(args...)
|
||||
|
||||
if b, ok := test.expect.(bool); ok && !b {
|
||||
c.Assert(err, qt.Not(qt.IsNil))
|
||||
c.Assert(err, qt.Not(qt.IsNil), qt.Commentf("#%d", i))
|
||||
continue
|
||||
}
|
||||
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(result, qt.Equals, test.expect)
|
||||
c.Assert(result, qt.Equals, test.expect, qt.Commentf("#%d", i))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue