tpl/transform: Add transform.XMLEscape template function

Fixes #3268
This commit is contained in:
Joe Mooring 2023-11-24 15:51:27 -08:00 committed by Bjørn Erik Pedersen
parent ef12d169c8
commit b4c5df42ff
6 changed files with 105 additions and 2 deletions

View file

@ -112,6 +112,16 @@ func init() {
},
)
ns.AddMethodMapping(ctx.XMLEscape,
nil,
[][2]string{
{
`{{ transform.XMLEscape "<p>abc</p>" }}`,
`&lt;p&gt;abc&lt;/p&gt;`,
},
},
)
return ns
}

View file

@ -65,3 +65,23 @@ foo
b.AssertFileContent("public/p3/index.html", "_<h2 id=\"foo\">foo</h2>\n<p>bar</p>\n_")
b.AssertFileContent("public/p4/index.html", "_<p id=\"bar\">foo</p>\n_")
}
func TestXMLEscape(t *testing.T) {
t.Parallel()
files := `
-- config.toml --
disableKinds = ['section','sitemap','taxonomy','term']
-- content/p1.md --
---
title: p1
---
a **b** c
<!--more-->
`
b := hugolib.Test(t, files)
b.AssertFileContent("public/index.xml", `
<description>&lt;p&gt;a &lt;strong&gt;b&lt;/strong&gt; c&lt;/p&gt;</description>
`)
}

View file

@ -15,9 +15,12 @@
package transform
import (
"bytes"
"context"
"encoding/xml"
"html"
"html/template"
"strings"
"github.com/gohugoio/hugo/cache/namedmemcache"
"github.com/gohugoio/hugo/markup/converter/hooks"
@ -118,6 +121,34 @@ func (ns *Namespace) HTMLUnescape(s any) (string, error) {
return html.UnescapeString(ss), nil
}
// XMLEscape returns the given string, removing disallowed characters then
// escaping the result to its XML equivalent.
func (ns *Namespace) XMLEscape(s any) (string, error) {
ss, err := cast.ToStringE(s)
if err != nil {
return "", err
}
// https://www.w3.org/TR/xml/#NT-Char
cleaned := strings.Map(func(r rune) rune {
if r == 0x9 || r == 0xA || r == 0xD ||
(r >= 0x20 && r <= 0xD7FF) ||
(r >= 0xE000 && r <= 0xFFFD) ||
(r >= 0x10000 && r <= 0x10FFFF) {
return r
}
return -1
}, ss)
var buf bytes.Buffer
err = xml.EscapeText(&buf, []byte(cleaned))
if err != nil {
return "", err
}
return buf.String(), nil
}
// Markdownify renders s from Markdown to HTML.
func (ns *Namespace) Markdownify(ctx context.Context, s any) (template.HTML, error) {