mirror of
https://github.com/gohugoio/hugo.git
synced 2026-08-24 07:18:54 +00:00
@@ -16,6 +16,7 @@ package encoding
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"html/template"
|
||||
@@ -56,6 +57,28 @@ func (ns *Namespace) Base64Encode(content any) (string, error) {
|
||||
return base64.StdEncoding.EncodeToString([]byte(conv)), nil
|
||||
}
|
||||
|
||||
// HexDecode returns the hex decoding of the given content.
|
||||
func (ns *Namespace) HexDecode(content any) (string, error) {
|
||||
conv, err := cast.ToStringE(content)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
b, err := hex.DecodeString(conv)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
// HexEncode returns the hex encoding of the given content.
|
||||
func (ns *Namespace) HexEncode(content any) (string, error) {
|
||||
conv, err := cast.ToStringE(content)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return hex.EncodeToString([]byte(conv)), nil
|
||||
}
|
||||
|
||||
// Jsonify encodes a given object to JSON. To pretty print the JSON, pass a map
|
||||
// or dictionary of options as the first value in args. Supported options are
|
||||
// "prefix" and "indent". Each JSON element in the output will begin on a new
|
||||
|
||||
@@ -77,6 +77,60 @@ func TestBase64Encode(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHexDecode(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := qt.New(t)
|
||||
|
||||
ns := New()
|
||||
|
||||
for _, test := range []struct {
|
||||
v any
|
||||
expect any
|
||||
}{
|
||||
{"616263313233213f242a2628292d3d407e", "abc123!?$*&()-=@~"},
|
||||
// errors
|
||||
{t, false},
|
||||
} {
|
||||
|
||||
result, err := ns.HexDecode(test.v)
|
||||
|
||||
if b, ok := test.expect.(bool); ok && !b {
|
||||
c.Assert(err, qt.Not(qt.IsNil))
|
||||
continue
|
||||
}
|
||||
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(result, qt.Equals, test.expect)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHexEncode(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := qt.New(t)
|
||||
|
||||
ns := New()
|
||||
|
||||
for _, test := range []struct {
|
||||
v any
|
||||
expect any
|
||||
}{
|
||||
{"abc123!?$*&()-=@~", "616263313233213f242a2628292d3d407e"},
|
||||
// errors
|
||||
{t, false},
|
||||
} {
|
||||
|
||||
result, err := ns.HexEncode(test.v)
|
||||
|
||||
if b, ok := test.expect.(bool); ok && !b {
|
||||
c.Assert(err, qt.Not(qt.IsNil))
|
||||
continue
|
||||
}
|
||||
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(result, qt.Equals, test.expect)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJsonify(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := qt.New(t)
|
||||
|
||||
@@ -46,6 +46,20 @@ func init() {
|
||||
},
|
||||
)
|
||||
|
||||
ns.AddMethodMapping(ctx.HexDecode,
|
||||
nil,
|
||||
[][2]string{
|
||||
{`{{ "48656c6c6f20776f726c64" | encoding.HexDecode }}`, `Hello world`},
|
||||
},
|
||||
)
|
||||
|
||||
ns.AddMethodMapping(ctx.HexEncode,
|
||||
nil,
|
||||
[][2]string{
|
||||
{`{{ "Hello world" | encoding.HexEncode }}`, `48656c6c6f20776f726c64`},
|
||||
},
|
||||
)
|
||||
|
||||
ns.AddMethodMapping(ctx.Jsonify,
|
||||
[]string{"jsonify"},
|
||||
[][2]string{
|
||||
|
||||
@@ -453,3 +453,49 @@ Home. {{ partial "a" }}:Done.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecoratorFingerprintScript(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
baseURL = "https://example.org/"
|
||||
[outputs]
|
||||
home = ["html", "headers"]
|
||||
[mediaTypes]
|
||||
[mediaTypes."text/netlify"]
|
||||
delimiter = ""
|
||||
[outputFormats]
|
||||
[outputFormats.headers]
|
||||
baseName = "_headers"
|
||||
isPlainText = true
|
||||
mediatype = "text/netlify"
|
||||
notAlternative = true
|
||||
-- layouts/_partials/script.html --
|
||||
{{ $s := (templates.Inner .) }}
|
||||
{{ $r := resources.FromString ($s | xxhash) $s | fingerprint }}
|
||||
{{ $hash := $s | crypto.SHA256 | encoding.HexDecode | encoding.Base64Encode }}
|
||||
{{ $sri := (printf "sha256-%s" $hash) }}
|
||||
{{ if ne $sri $r.Data.Integrity }}
|
||||
{{ errorf "SRI hash mismatch: %s != %s" $sri $r.Data.Integrity }}
|
||||
{{ end }}
|
||||
{{ hugo.Store.SetInMap "srihashes" $sri true }}
|
||||
<script>{{ $s | safeJS }}</script>
|
||||
-- layouts/home.html --
|
||||
Home.
|
||||
{{ with partial "script.html" . }}
|
||||
console.log("Hello world");
|
||||
{{ end }}
|
||||
{{ with partial "script.html" . }}
|
||||
console.log("Hugo rocks!");
|
||||
{{ end }}
|
||||
-- layouts/home.headers --
|
||||
{{ $hashes := hugo.Store.Get "srihashes" -}}
|
||||
Content-Security-Policy: script-src 'self'{{ range $k, $v := $hashes }} '{{ $k }}'{{ end }};
|
||||
`
|
||||
|
||||
b := hugolib.Test(t, files)
|
||||
|
||||
b.AssertFileContentExact("public/index.html", "<script>\nconsole.log(\"Hello world\");\n</script>")
|
||||
b.AssertFileContentExact("public/_headers", "Content-Security-Policy: script-src 'self' 'sha256-t6z9j4/CagmaDDbn6nHbntzt8PRk8HZ1TwrgdYuZjbE=' 'sha256-wVbS8f78ttoSSGU80KghGoPcTO8DXqT0Uc/87a7zMdk=';")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user