diff options
Diffstat (limited to 'tpl/transform/transform.go')
-rw-r--r-- | tpl/transform/transform.go | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/tpl/transform/transform.go b/tpl/transform/transform.go index d943b0b57..178db84e4 100644 --- a/tpl/transform/transform.go +++ b/tpl/transform/transform.go @@ -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) { |