URI: 
       Consolidate all hashing to the common/hashing package - hugo - [fork] hugo port for 9front
  HTML git clone git@git.drkhsh.at/hugo.git
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
   DIR commit e67886c038dc79755c14ec77bbeff6605953f9ef
   DIR parent d5eda13cb2e57998210b66e080dc96e95b38e5f0
  HTML Author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
       Date:   Tue, 30 Jul 2024 15:47:34 +0200
       
       Consolidate all hashing to the common/hashing package
       
       And remove now unsued hashing funcs.
       
       Diffstat:
         M common/hashing/hashing.go           |      80 +++++++++++++++++++++++++++++++
         M common/hashing/hashing_test.go      |      50 ++++++++++++++++++++++++++++----
         M common/loggers/handlersmisc.go      |       4 ++--
         M config/namespace.go                 |       4 ++--
         M helpers/general.go                  |      62 -------------------------------
         M helpers/general_test.go             |      89 -------------------------------
         M hugolib/page__meta.go               |       6 +++---
         M hugolib/page_test.go                |       6 +++---
         M hugolib/pagebundler_test.go         |       7 +++----
         M hugolib/pagesfromdata/pagesfromgot… |       3 ++-
         M hugolib/resource_chain_test.go      |       4 ++--
         D identity/identityhash.go            |      91 -------------------------------
         D identity/identityhash_test.go       |      68 -------------------------------
         M metrics/metrics.go                  |       4 ++--
         M resources/image.go                  |       9 ++++-----
         M resources/image_test.go             |       7 +++----
         M resources/images/filters_test.go    |      10 +++++-----
         M resources/internal/key.go           |       4 ++--
         M resources/resource_factories/creat… |       4 ++--
         M resources/resource_factories/creat… |       5 +++--
         R resources/testdata/golden/giphy_hu… |       0 
         R resources/testdata/golden/giphy_hu… |       0 
         R resources/testdata/golden/giphy_hu… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gohugoio… |       0 
         R resources/testdata/golden/gopher-h… |       0 
         R resources/testdata/golden/gopher-h… |       0 
         R resources/testdata/golden/gopher-h… |       0 
         R resources/testdata/golden/gopher-h… |       0 
         R resources/testdata/golden/gradient… |       0 
         R resources/testdata/golden/gradient… |       0 
         R resources/testdata/golden/gradient… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         R resources/testdata/golden/sunset_h… |       0 
         M resources/transform.go              |       4 ++--
         M source/fileInfo.go                  |       5 ++---
         M tpl/collections/reflect_helpers.go  |       4 ++--
         M tpl/data/resources.go               |       4 ++--
         M tpl/partials/partials.go            |       3 ++-
         M tpl/templates/templates.go          |       4 ++--
         M tpl/transform/unmarshal.go          |       4 ++--
       
       125 files changed, 177 insertions(+), 368 deletions(-)
       ---
   DIR diff --git a/common/hashing/hashing.go b/common/hashing/hashing.go
       @@ -15,11 +15,15 @@
        package hashing
        
        import (
       +        "crypto/md5"
                "encoding/hex"
                "io"
       +        "strconv"
                "sync"
        
                "github.com/cespare/xxhash/v2"
       +        "github.com/gohugoio/hashstructure"
       +        "github.com/gohugoio/hugo/identity"
        )
        
        // XXHashFromReader calculates the xxHash for the given reader.
       @@ -50,6 +54,82 @@ func XxHashFromStringHexEncoded(f string) string {
                return hex.EncodeToString(hash)
        }
        
       +// MD5FromStringHexEncoded returns the MD5 hash of the given string.
       +func MD5FromStringHexEncoded(f string) string {
       +        h := md5.New()
       +        h.Write([]byte(f))
       +        return hex.EncodeToString(h.Sum(nil))
       +}
       +
       +// HashString returns a hash from the given elements.
       +// It will panic if the hash cannot be calculated.
       +// Note that this hash should be used primarily for identity, not for change detection as
       +// it in the more complex values (e.g. Page) will not hash the full content.
       +func HashString(vs ...any) string {
       +        hash := HashUint64(vs...)
       +        return strconv.FormatUint(hash, 10)
       +}
       +
       +var hashOptsPool = sync.Pool{
       +        New: func() any {
       +                return &hashstructure.HashOptions{
       +                        Hasher: xxhash.New(),
       +                }
       +        },
       +}
       +
       +func getHashOpts() *hashstructure.HashOptions {
       +        return hashOptsPool.Get().(*hashstructure.HashOptions)
       +}
       +
       +func putHashOpts(opts *hashstructure.HashOptions) {
       +        opts.Hasher.Reset()
       +        hashOptsPool.Put(opts)
       +}
       +
       +// HashUint64 returns a hash from the given elements.
       +// It will panic if the hash cannot be calculated.
       +// Note that this hash should be used primarily for identity, not for change detection as
       +// it in the more complex values (e.g. Page) will not hash the full content.
       +func HashUint64(vs ...any) uint64 {
       +        var o any
       +        if len(vs) == 1 {
       +                o = toHashable(vs[0])
       +        } else {
       +                elements := make([]any, len(vs))
       +                for i, e := range vs {
       +                        elements[i] = toHashable(e)
       +                }
       +                o = elements
       +        }
       +
       +        hashOpts := getHashOpts()
       +        defer putHashOpts(hashOpts)
       +
       +        hash, err := hashstructure.Hash(o, hashOpts)
       +        if err != nil {
       +                panic(err)
       +        }
       +        return hash
       +}
       +
       +type keyer interface {
       +        Key() string
       +}
       +
       +// For structs, hashstructure.Hash only works on the exported fields,
       +// so rewrite the input slice for known identity types.
       +func toHashable(v any) any {
       +        switch t := v.(type) {
       +        case keyer:
       +                return t.Key()
       +        case identity.IdentityProvider:
       +                return t.GetIdentity()
       +        default:
       +                return v
       +        }
       +}
       +
        type xxhashReadFrom struct {
                buff []byte
                *xxhash.Digest
   DIR diff --git a/common/hashing/hashing_test.go b/common/hashing/hashing_test.go
       @@ -14,10 +14,11 @@
        package hashing
        
        import (
       +        "fmt"
       +        "math"
                "strings"
                "testing"
        
       -        "github.com/cespare/xxhash/v2"
                qt "github.com/frankban/quicktest"
        )
        
       @@ -72,8 +73,47 @@ func BenchmarkXXHashFromStringHexEncoded(b *testing.B) {
                }
        }
        
       -func xxHashFromString(f string) uint64 {
       -        h := xxhash.New()
       -        h.WriteString(f)
       -        return h.Sum64()
       +func TestHashString(t *testing.T) {
       +        c := qt.New(t)
       +
       +        c.Assert(HashString("a", "b"), qt.Equals, "3176555414984061461")
       +        c.Assert(HashString("ab"), qt.Equals, "7347350983217793633")
       +
       +        var vals []any = []any{"a", "b", tstKeyer{"c"}}
       +
       +        c.Assert(HashString(vals...), qt.Equals, "4438730547989914315")
       +        c.Assert(vals[2], qt.Equals, tstKeyer{"c"})
       +}
       +
       +type tstKeyer struct {
       +        key string
       +}
       +
       +func (t tstKeyer) Key() string {
       +        return t.key
       +}
       +
       +func (t tstKeyer) String() string {
       +        return "key: " + t.key
       +}
       +
       +func BenchmarkHashString(b *testing.B) {
       +        word := " hello "
       +
       +        var tests []string
       +
       +        for i := 1; i <= 5; i++ {
       +                sentence := strings.Repeat(word, int(math.Pow(4, float64(i))))
       +                tests = append(tests, sentence)
       +        }
       +
       +        b.ResetTimer()
       +
       +        for _, test := range tests {
       +                b.Run(fmt.Sprintf("n%d", len(test)), func(b *testing.B) {
       +                        for i := 0; i < b.N; i++ {
       +                                HashString(test)
       +                        }
       +                })
       +        }
        }
   DIR diff --git a/common/loggers/handlersmisc.go b/common/loggers/handlersmisc.go
       @@ -21,7 +21,7 @@ import (
                "sync"
        
                "github.com/bep/logg"
       -        "github.com/gohugoio/hugo/identity"
       +        "github.com/gohugoio/hugo/common/hashing"
        )
        
        // PanicOnWarningHook panics on warnings.
       @@ -85,7 +85,7 @@ func (h *logOnceHandler) HandleLog(e *logg.Entry) error {
                }
                h.mu.Lock()
                defer h.mu.Unlock()
       -        hash := identity.HashUint64(e.Level, e.Message, e.Fields)
       +        hash := hashing.HashUint64(e.Level, e.Message, e.Fields)
                if h.seen[hash] {
                        return errStop
                }
   DIR diff --git a/config/namespace.go b/config/namespace.go
       @@ -16,13 +16,13 @@ package config
        import (
                "encoding/json"
        
       -        "github.com/gohugoio/hugo/identity"
       +        "github.com/gohugoio/hugo/common/hashing"
        )
        
        func DecodeNamespace[S, C any](configSource any, buildConfig func(any) (C, any, error)) (*ConfigNamespace[S, C], error) {
                // Calculate the hash of the input (not including any defaults applied later).
                // This allows us to introduce new config options without breaking the hash.
       -        h := identity.HashString(configSource)
       +        h := hashing.HashString(configSource)
        
                // Build the config
                c, ext, err := buildConfig(configSource)
   DIR diff --git a/helpers/general.go b/helpers/general.go
       @@ -15,8 +15,6 @@ package helpers
        
        import (
                "bytes"
       -        "crypto/md5"
       -        "encoding/hex"
                "fmt"
                "io"
                "net"
       @@ -257,66 +255,6 @@ func SliceToLower(s []string) []string {
                return l
        }
        
       -// XXHashFromReader creates a xxHash hash from the given reader.
       -
       -// MD5String takes a string and returns its MD5 hash.
       -func MD5String(f string) string {
       -        h := md5.New()
       -        h.Write([]byte(f))
       -        return hex.EncodeToString(h.Sum([]byte{}))
       -}
       -
       -// MD5FromReaderFast creates a MD5 hash from the given file. It only reads parts of
       -// the file for speed, so don't use it if the files are very subtly different.
       -// It will not close the file.
       -// It will return the MD5 hash and the size of r in bytes.
       -func MD5FromReaderFast(r io.ReadSeeker) (string, int64, error) {
       -        const (
       -                // Do not change once set in stone!
       -                maxChunks = 8
       -                peekSize  = 64
       -                seek      = 2048
       -        )
       -
       -        h := md5.New()
       -        buff := make([]byte, peekSize)
       -
       -        for i := 0; i < maxChunks; i++ {
       -                if i > 0 {
       -                        _, err := r.Seek(seek, 0)
       -                        if err != nil {
       -                                if err == io.EOF {
       -                                        break
       -                                }
       -                                return "", 0, err
       -                        }
       -                }
       -
       -                _, err := io.ReadAtLeast(r, buff, peekSize)
       -                if err != nil {
       -                        if err == io.EOF || err == io.ErrUnexpectedEOF {
       -                                h.Write(buff)
       -                                break
       -                        }
       -                        return "", 0, err
       -                }
       -                h.Write(buff)
       -        }
       -
       -        size, _ := r.Seek(0, io.SeekEnd)
       -
       -        return hex.EncodeToString(h.Sum(nil)), size, nil
       -}
       -
       -// MD5FromReader creates a MD5 hash from the given reader.
       -func MD5FromReader(r io.Reader) (string, error) {
       -        h := md5.New()
       -        if _, err := io.Copy(h, r); err != nil {
       -                return "", nil
       -        }
       -        return hex.EncodeToString(h.Sum(nil)), nil
       -}
       -
        // IsWhitespace determines if the given rune is whitespace.
        func IsWhitespace(r rune) bool {
                return r == ' ' || r == '\t' || r == '\n' || r == '\r'
   DIR diff --git a/helpers/general_test.go b/helpers/general_test.go
       @@ -14,7 +14,6 @@
        package helpers_test
        
        import (
       -        "fmt"
                "reflect"
                "strings"
                "testing"
       @@ -22,7 +21,6 @@ import (
                "github.com/gohugoio/hugo/helpers"
        
                qt "github.com/frankban/quicktest"
       -        "github.com/spf13/afero"
        )
        
        func TestResolveMarkup(t *testing.T) {
       @@ -256,93 +254,6 @@ func TestUniqueStringsSorted(t *testing.T) {
                c.Assert(helpers.UniqueStringsSorted(nil), qt.IsNil)
        }
        
       -func TestFastMD5FromFile(t *testing.T) {
       -        fs := afero.NewMemMapFs()
       -
       -        if err := afero.WriteFile(fs, "small.txt", []byte("abc"), 0o777); err != nil {
       -                t.Fatal(err)
       -        }
       -
       -        if err := afero.WriteFile(fs, "small2.txt", []byte("abd"), 0o777); err != nil {
       -                t.Fatal(err)
       -        }
       -
       -        if err := afero.WriteFile(fs, "bigger.txt", []byte(strings.Repeat("a bc d e", 100)), 0o777); err != nil {
       -                t.Fatal(err)
       -        }
       -
       -        if err := afero.WriteFile(fs, "bigger2.txt", []byte(strings.Repeat("c d e f g", 100)), 0o777); err != nil {
       -                t.Fatal(err)
       -        }
       -
       -        c := qt.New(t)
       -
       -        sf1, err := fs.Open("small.txt")
       -        c.Assert(err, qt.IsNil)
       -        sf2, err := fs.Open("small2.txt")
       -        c.Assert(err, qt.IsNil)
       -
       -        bf1, err := fs.Open("bigger.txt")
       -        c.Assert(err, qt.IsNil)
       -        bf2, err := fs.Open("bigger2.txt")
       -        c.Assert(err, qt.IsNil)
       -
       -        defer sf1.Close()
       -        defer sf2.Close()
       -        defer bf1.Close()
       -        defer bf2.Close()
       -
       -        m1, _, err := helpers.MD5FromReaderFast(sf1)
       -        c.Assert(err, qt.IsNil)
       -        c.Assert(m1, qt.Equals, "e9c8989b64b71a88b4efb66ad05eea96")
       -
       -        m2, _, err := helpers.MD5FromReaderFast(sf2)
       -        c.Assert(err, qt.IsNil)
       -        c.Assert(m2, qt.Not(qt.Equals), m1)
       -
       -        m3, _, err := helpers.MD5FromReaderFast(bf1)
       -        c.Assert(err, qt.IsNil)
       -        c.Assert(m3, qt.Not(qt.Equals), m2)
       -
       -        m4, _, err := helpers.MD5FromReaderFast(bf2)
       -        c.Assert(err, qt.IsNil)
       -        c.Assert(m4, qt.Not(qt.Equals), m3)
       -
       -        m5, err := helpers.MD5FromReader(bf2)
       -        c.Assert(err, qt.IsNil)
       -        c.Assert(m5, qt.Not(qt.Equals), m4)
       -}
       -
       -func BenchmarkMD5FromFileFast(b *testing.B) {
       -        fs := afero.NewMemMapFs()
       -
       -        for _, full := range []bool{false, true} {
       -                b.Run(fmt.Sprintf("full=%t", full), func(b *testing.B) {
       -                        for i := 0; i < b.N; i++ {
       -                                b.StopTimer()
       -                                if err := afero.WriteFile(fs, "file.txt", []byte(strings.Repeat("1234567890", 2000)), 0o777); err != nil {
       -                                        b.Fatal(err)
       -                                }
       -                                f, err := fs.Open("file.txt")
       -                                if err != nil {
       -                                        b.Fatal(err)
       -                                }
       -                                b.StartTimer()
       -                                if full {
       -                                        if _, err := helpers.MD5FromReader(f); err != nil {
       -                                                b.Fatal(err)
       -                                        }
       -                                } else {
       -                                        if _, _, err := helpers.MD5FromReaderFast(f); err != nil {
       -                                                b.Fatal(err)
       -                                        }
       -                                }
       -                                f.Close()
       -                        }
       -                })
       -        }
       -}
       -
        func BenchmarkUniqueStrings(b *testing.B) {
                input := []string{"a", "b", "d", "e", "d", "h", "a", "i"}
        
   DIR diff --git a/hugolib/page__meta.go b/hugolib/page__meta.go
       @@ -22,7 +22,6 @@ import (
                "time"
        
                "github.com/gobuffalo/flect"
       -        "github.com/gohugoio/hugo/identity"
                "github.com/gohugoio/hugo/langs"
                "github.com/gohugoio/hugo/markup/converter"
                xmaps "golang.org/x/exp/maps"
       @@ -32,6 +31,7 @@ import (
                "github.com/gohugoio/hugo/source"
        
                "github.com/gohugoio/hugo/common/constants"
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/common/hugo"
                "github.com/gohugoio/hugo/common/loggers"
                "github.com/gohugoio/hugo/common/maps"
       @@ -328,7 +328,7 @@ func (ps *pageState) setMetaPost(cascade map[page.PageMatcher]maps.Params) error
                ps.m.setMetaPostCount++
                var cascadeHashPre uint64
                if ps.m.setMetaPostCount > 1 {
       -                cascadeHashPre = identity.HashUint64(ps.m.pageConfig.CascadeCompiled)
       +                cascadeHashPre = hashing.HashUint64(ps.m.pageConfig.CascadeCompiled)
                        ps.m.pageConfig.CascadeCompiled = xmaps.Clone[map[page.PageMatcher]maps.Params](ps.m.cascadeOriginal)
        
                }
       @@ -360,7 +360,7 @@ func (ps *pageState) setMetaPost(cascade map[page.PageMatcher]maps.Params) error
                }
        
                if ps.m.setMetaPostCount > 1 {
       -                ps.m.setMetaPostCascadeChanged = cascadeHashPre != identity.HashUint64(ps.m.pageConfig.CascadeCompiled)
       +                ps.m.setMetaPostCascadeChanged = cascadeHashPre != hashing.HashUint64(ps.m.pageConfig.CascadeCompiled)
                        if !ps.m.setMetaPostCascadeChanged {
        
                                // No changes, restore any value that may be changed by aggregation.
   DIR diff --git a/hugolib/page_test.go b/hugolib/page_test.go
       @@ -23,13 +23,13 @@ import (
                "time"
        
                "github.com/bep/clocks"
       -        "github.com/gohugoio/hugo/identity"
                "github.com/gohugoio/hugo/markup/asciidocext"
                "github.com/gohugoio/hugo/markup/rst"
                "github.com/gohugoio/hugo/tpl"
        
                "github.com/gohugoio/hugo/config"
        
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/common/htime"
                "github.com/gohugoio/hugo/common/loggers"
        
       @@ -2040,8 +2040,8 @@ title: "p2"
        
                b.Assert(p1, qt.Not(qt.Equals), p2)
        
       -        b.Assert(identity.HashString(p1), qt.Not(qt.Equals), identity.HashString(p2))
       -        b.Assert(identity.HashString(sites[0]), qt.Not(qt.Equals), identity.HashString(sites[1]))
       +        b.Assert(hashing.HashString(p1), qt.Not(qt.Equals), hashing.HashString(p2))
       +        b.Assert(hashing.HashString(sites[0]), qt.Not(qt.Equals), hashing.HashString(sites[1]))
        }
        
        // Issue #11243
   DIR diff --git a/hugolib/pagebundler_test.go b/hugolib/pagebundler_test.go
       @@ -19,12 +19,11 @@ import (
                "path/filepath"
                "testing"
        
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/common/loggers"
        
                "github.com/gohugoio/hugo/config"
        
       -        "github.com/gohugoio/hugo/helpers"
       -
                "github.com/gohugoio/hugo/hugofs"
        
                "github.com/gohugoio/hugo/resources/kinds"
       @@ -701,13 +700,13 @@ bundle min min key: {{ $jsonMinMin.Key }}
                                b.AssertFileContent(index, fmt.Sprintf("data content unmarshaled: v%d", i))
                                b.AssertFileContent(index, fmt.Sprintf("data assets content unmarshaled: v%d", i))
        
       -                        md5Asset := helpers.MD5String(fmt.Sprintf(`vdata: v%d`, i))
       +                        md5Asset := hashing.MD5FromStringHexEncoded(fmt.Sprintf(`vdata: v%d`, i))
                                b.AssertFileContent(index, fmt.Sprintf("assets fingerprinted: /data%d/data.%s.yaml", i, md5Asset))
        
                                // The original is not used, make sure it's not published.
                                b.Assert(b.CheckExists(fmt.Sprintf("public/data%d/data.yaml", i)), qt.Equals, false)
        
       -                        md5Bundle := helpers.MD5String(fmt.Sprintf(`data: v%d`, i))
       +                        md5Bundle := hashing.MD5FromStringHexEncoded(fmt.Sprintf(`data: v%d`, i))
                                b.AssertFileContent(index, fmt.Sprintf("bundle fingerprinted: /bundle%d/data.%s.yaml", i, md5Bundle))
        
                                b.AssertFileContent(index,
   DIR diff --git a/hugolib/pagesfromdata/pagesfromgotmpl.go b/hugolib/pagesfromdata/pagesfromgotmpl.go
       @@ -19,6 +19,7 @@ import (
                "io"
                "path/filepath"
        
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/common/maps"
                "github.com/gohugoio/hugo/common/paths"
                "github.com/gohugoio/hugo/helpers"
       @@ -219,7 +220,7 @@ type BuildState struct {
        }
        
        func (b *BuildState) hash(v any) uint64 {
       -        return identity.HashUint64(v)
       +        return hashing.HashUint64(v)
        }
        
        func (b *BuildState) checkHasChangedAndSetSourceInfo(changedPath string, v any) bool {
   DIR diff --git a/hugolib/resource_chain_test.go b/hugolib/resource_chain_test.go
       @@ -27,8 +27,8 @@ import (
        
                qt "github.com/frankban/quicktest"
        
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/common/loggers"
       -        "github.com/gohugoio/hugo/identity"
                "github.com/gohugoio/hugo/resources/resource_transformers/tocss/scss"
        )
        
       @@ -119,7 +119,7 @@ FAILED REMOTE ERROR DETAILS CONTENT: |failed to fetch remote resource: Not Imple
        |StatusCode: 501|ContentLength: 16|ContentType: text/plain; charset=utf-8|
        
        
       -`, identity.HashString(ts.URL+"/sunset.jpg", map[string]any{})))
       +`, hashing.HashString(ts.URL+"/sunset.jpg", map[string]any{})))
        
                        b.AssertFileContent("public/styles.min.a1df58687c3c9cc38bf26532f7b4b2f2c2b0315dcde212376959995c04f11fef.css", "body{background-color:#add8e6}")
                        b.AssertFileContent("public//styles2.min.1cfc52986836405d37f9998a63fd6dd8608e8c410e5e3db1daaa30f78bc273ba.css", "body{background-color:orange}")
   DIR diff --git a/identity/identityhash.go b/identity/identityhash.go
       @@ -1,91 +0,0 @@
       -// Copyright 2024 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 identity
       -
       -import (
       -        "strconv"
       -        "sync"
       -
       -        "github.com/cespare/xxhash/v2"
       -        "github.com/gohugoio/hashstructure"
       -)
       -
       -// HashString returns a hash from the given elements.
       -// It will panic if the hash cannot be calculated.
       -// Note that this hash should be used primarily for identity, not for change detection as
       -// it in the more complex values (e.g. Page) will not hash the full content.
       -func HashString(vs ...any) string {
       -        hash := HashUint64(vs...)
       -        return strconv.FormatUint(hash, 10)
       -}
       -
       -var hashOptsPool = sync.Pool{
       -        New: func() any {
       -                return &hashstructure.HashOptions{
       -                        Hasher: xxhash.New(),
       -                }
       -        },
       -}
       -
       -func getHashOpts() *hashstructure.HashOptions {
       -        return hashOptsPool.Get().(*hashstructure.HashOptions)
       -}
       -
       -func putHashOpts(opts *hashstructure.HashOptions) {
       -        opts.Hasher.Reset()
       -        hashOptsPool.Put(opts)
       -}
       -
       -// HashUint64 returns a hash from the given elements.
       -// It will panic if the hash cannot be calculated.
       -// Note that this hash should be used primarily for identity, not for change detection as
       -// it in the more complex values (e.g. Page) will not hash the full content.
       -func HashUint64(vs ...any) uint64 {
       -        var o any
       -        if len(vs) == 1 {
       -                o = toHashable(vs[0])
       -        } else {
       -                elements := make([]any, len(vs))
       -                for i, e := range vs {
       -                        elements[i] = toHashable(e)
       -                }
       -                o = elements
       -        }
       -
       -        hashOpts := getHashOpts()
       -        defer putHashOpts(hashOpts)
       -
       -        hash, err := hashstructure.Hash(o, hashOpts)
       -        if err != nil {
       -                panic(err)
       -        }
       -        return hash
       -}
       -
       -type keyer interface {
       -        Key() string
       -}
       -
       -// For structs, hashstructure.Hash only works on the exported fields,
       -// so rewrite the input slice for known identity types.
       -func toHashable(v any) any {
       -        switch t := v.(type) {
       -        case keyer:
       -                return t.Key()
       -        case IdentityProvider:
       -                return t.GetIdentity()
       -        default:
       -                return v
       -        }
       -}
   DIR diff --git a/identity/identityhash_test.go b/identity/identityhash_test.go
       @@ -1,68 +0,0 @@
       -// Copyright 2024 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 identity
       -
       -import (
       -        "fmt"
       -        "math"
       -        "strings"
       -        "testing"
       -
       -        qt "github.com/frankban/quicktest"
       -)
       -
       -func TestHashString(t *testing.T) {
       -        c := qt.New(t)
       -
       -        c.Assert(HashString("a", "b"), qt.Equals, "3176555414984061461")
       -        c.Assert(HashString("ab"), qt.Equals, "7347350983217793633")
       -
       -        var vals []any = []any{"a", "b", tstKeyer{"c"}}
       -
       -        c.Assert(HashString(vals...), qt.Equals, "4438730547989914315")
       -        c.Assert(vals[2], qt.Equals, tstKeyer{"c"})
       -}
       -
       -type tstKeyer struct {
       -        key string
       -}
       -
       -func (t tstKeyer) Key() string {
       -        return t.key
       -}
       -
       -func (t tstKeyer) String() string {
       -        return "key: " + t.key
       -}
       -
       -func BenchmarkHashString(b *testing.B) {
       -        word := " hello "
       -
       -        var tests []string
       -
       -        for i := 1; i <= 5; i++ {
       -                sentence := strings.Repeat(word, int(math.Pow(4, float64(i))))
       -                tests = append(tests, sentence)
       -        }
       -
       -        b.ResetTimer()
       -
       -        for _, test := range tests {
       -                b.Run(fmt.Sprintf("n%d", len(test)), func(b *testing.B) {
       -                        for i := 0; i < b.N; i++ {
       -                                HashString(test)
       -                        }
       -                })
       -        }
       -}
   DIR diff --git a/metrics/metrics.go b/metrics/metrics.go
       @@ -25,9 +25,9 @@ import (
                "sync"
                "time"
        
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/common/types"
                "github.com/gohugoio/hugo/compare"
       -        "github.com/gohugoio/hugo/identity"
        )
        
        // The Provider interface defines an interface for measuring metrics.
       @@ -241,7 +241,7 @@ func howSimilar(a, b any) int {
                        return 90
                }
        
       -        h1, h2 := identity.HashString(a), identity.HashString(b)
       +        h1, h2 := hashing.HashString(a), hashing.HashString(b)
                if h1 == h2 {
                        return 100
                }
   DIR diff --git a/resources/image.go b/resources/image.go
       @@ -29,9 +29,9 @@ import (
                color_extractor "github.com/marekm4/color-extractor"
        
                "github.com/gohugoio/hugo/cache/filecache"
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/common/hstrings"
                "github.com/gohugoio/hugo/common/paths"
       -        "github.com/gohugoio/hugo/identity"
        
                "github.com/disintegration/gift"
        
       @@ -40,7 +40,6 @@ import (
        
                "github.com/gohugoio/hugo/resources/resource"
        
       -        "github.com/gohugoio/hugo/helpers"
                "github.com/gohugoio/hugo/resources/images"
        
                // Blind import for image.Decode
       @@ -274,7 +273,7 @@ func (i *imageResource) Filter(filters ...any) (images.ImageResource, error) {
                }
        
                conf.Action = "filter"
       -        conf.Key = identity.HashString(gfilters)
       +        conf.Key = hashing.HashString(gfilters)
                conf.TargetFormat = targetFormat
                if conf.TargetFormat == 0 {
                        conf.TargetFormat = i.Format
       @@ -481,7 +480,7 @@ func (i *imageResource) getImageMetaCacheTargetPath() string {
                df := i.getResourcePaths()
                p1, _ := paths.FileAndExt(df.File)
                h := i.hash()
       -        idStr := identity.HashString(h, i.size(), imageMetaVersionNumber, cfgHash)
       +        idStr := hashing.HashString(h, i.size(), imageMetaVersionNumber, cfgHash)
                df.File = fmt.Sprintf("%s_%s.json", p1, idStr)
                return df.TargetPath()
        }
       @@ -504,7 +503,7 @@ func (i *imageResource) relTargetPathFromConfig(conf images.ImageConfig) interna
                // can easily be too long to read, and maybe even too long
                // for the different OSes to handle.
                if len(p1)+len(idStr)+len(p2) > md5Threshold {
       -                key = helpers.MD5String(p1 + key + p2)
       +                key = hashing.MD5FromStringHexEncoded(p1 + key + p2)
                        huIdx := strings.Index(p1, "_hu")
                        if huIdx != -1 {
                                p1 = p1[:huIdx]
   DIR diff --git a/resources/image_test.go b/resources/image_test.go
       @@ -33,14 +33,13 @@ import (
                "github.com/gohugoio/hugo/htesting"
                "github.com/gohugoio/hugo/resources/images/webp"
        
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/common/paths"
        
                "github.com/spf13/afero"
        
                "github.com/disintegration/gift"
        
       -        "github.com/gohugoio/hugo/helpers"
       -
                "github.com/gohugoio/hugo/media"
                "github.com/gohugoio/hugo/resources/images"
                "github.com/google/go-cmp/cmp"
       @@ -835,9 +834,9 @@ func assetGoldenDirs(c *qt.C, dir1, dir2 string) {
                                _, err = f2.Seek(0, 0)
                                c.Assert(err, qt.IsNil)
        
       -                        hash1, err := helpers.MD5FromReader(f1)
       +                        hash1, _, err := hashing.XXHashFromReader(f1)
                                c.Assert(err, qt.IsNil)
       -                        hash2, err := helpers.MD5FromReader(f2)
       +                        hash2, _, err := hashing.XXHashFromReader(f2)
                                c.Assert(err, qt.IsNil)
        
                                c.Assert(hash1, qt.Equals, hash2)
   DIR diff --git a/resources/images/filters_test.go b/resources/images/filters_test.go
       @@ -17,7 +17,7 @@ import (
                "testing"
        
                qt "github.com/frankban/quicktest"
       -        "github.com/gohugoio/hugo/identity"
       +        "github.com/gohugoio/hugo/common/hashing"
        )
        
        func TestFilterHash(t *testing.T) {
       @@ -25,8 +25,8 @@ func TestFilterHash(t *testing.T) {
        
                f := &Filters{}
        
       -        c.Assert(identity.HashString(f.Grayscale()), qt.Equals, identity.HashString(f.Grayscale()))
       -        c.Assert(identity.HashString(f.Grayscale()), qt.Not(qt.Equals), identity.HashString(f.Invert()))
       -        c.Assert(identity.HashString(f.Gamma(32)), qt.Not(qt.Equals), identity.HashString(f.Gamma(33)))
       -        c.Assert(identity.HashString(f.Gamma(32)), qt.Equals, identity.HashString(f.Gamma(32)))
       +        c.Assert(hashing.HashString(f.Grayscale()), qt.Equals, hashing.HashString(f.Grayscale()))
       +        c.Assert(hashing.HashString(f.Grayscale()), qt.Not(qt.Equals), hashing.HashString(f.Invert()))
       +        c.Assert(hashing.HashString(f.Gamma(32)), qt.Not(qt.Equals), hashing.HashString(f.Gamma(33)))
       +        c.Assert(hashing.HashString(f.Gamma(32)), qt.Equals, hashing.HashString(f.Gamma(32)))
        }
   DIR diff --git a/resources/internal/key.go b/resources/internal/key.go
       @@ -13,7 +13,7 @@
        
        package internal
        
       -import "github.com/gohugoio/hugo/identity"
       +import "github.com/gohugoio/hugo/common/hashing"
        
        // ResourceTransformationKey are provided by the different transformation implementations.
        // It identifies the transformation (name) and its configuration (elements).
       @@ -38,5 +38,5 @@ func (k ResourceTransformationKey) Value() string {
                        return k.Name
                }
        
       -        return k.Name + "_" + identity.HashString(k.elements...)
       +        return k.Name + "_" + hashing.HashString(k.elements...)
        }
   DIR diff --git a/resources/resource_factories/create/create.go b/resources/resource_factories/create/create.go
       @@ -26,7 +26,6 @@ import (
                "github.com/bep/logg"
                "github.com/gohugoio/httpcache"
                hhttpcache "github.com/gohugoio/hugo/cache/httpcache"
       -        "github.com/gohugoio/hugo/helpers"
                "github.com/gohugoio/hugo/hugofs/glob"
                "github.com/gohugoio/hugo/identity"
        
       @@ -34,6 +33,7 @@ import (
        
                "github.com/gohugoio/hugo/cache/dynacache"
                "github.com/gohugoio/hugo/cache/filecache"
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/common/hcontext"
                "github.com/gohugoio/hugo/common/hugio"
                "github.com/gohugoio/hugo/common/tasks"
       @@ -226,7 +226,7 @@ func (c *Client) match(name, pattern string, matchFunc func(r resource.Resource)
        // TODO(bep) see #10912; we currently emit a warning for this config scenario.
        func (c *Client) FromString(targetPath, content string) (resource.Resource, error) {
                targetPath = path.Clean(targetPath)
       -        key := dynacache.CleanKey(targetPath) + helpers.MD5String(content)
       +        key := dynacache.CleanKey(targetPath) + hashing.MD5FromStringHexEncoded(content)
                r, err := c.rs.ResourceCache.GetOrCreate(key, func() (resource.Resource, error) {
                        return c.rs.NewResource(
                                resources.ResourceSourceDescriptor{
   DIR diff --git a/resources/resource_factories/create/remote.go b/resources/resource_factories/create/remote.go
       @@ -29,6 +29,7 @@ import (
                gmaps "maps"
        
                "github.com/gohugoio/httpcache"
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/common/hugio"
                "github.com/gohugoio/hugo/common/loggers"
                "github.com/gohugoio/hugo/common/maps"
       @@ -310,10 +311,10 @@ func (c *Client) validateFromRemoteArgs(uri string, options fromRemoteOptions) e
        func remoteResourceKeys(uri string, optionsm map[string]any) (string, string) {
                var userKey string
                if key, k, found := maps.LookupEqualFold(optionsm, "key"); found {
       -                userKey = identity.HashString(key)
       +                userKey = hashing.HashString(key)
                        delete(optionsm, k)
                }
       -        optionsKey := identity.HashString(uri, optionsm)
       +        optionsKey := hashing.HashString(uri, optionsm)
                if userKey == "" {
                        userKey = optionsKey
                }
   DIR diff --git a/resources/testdata/golden/giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_100x0_resize_q75_bgffffff_box_1.jpg b/resources/testdata/golden/giphy_hu2834162883155351332_0_100x0_resize_q75_bgffffff_box_1.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_200x0_resize_box_1.gif b/resources/testdata/golden/giphy_hu2834162883155351332_0_200x0_resize_box_1.gif
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/giphy_hu3eafc418e52414ace6236bf1d31f82e1_52213_512x0_resize_box_1.gif b/resources/testdata/golden/giphy_hu2834162883155351332_0_512x0_resize_box_1.gif
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio-card_hu4d09f75255d3942fd4680641110a1a73_10820_100x0_resize_box_1.gif b/resources/testdata/golden/gohugoio-card_hu4315323919404496126_0_100x0_resize_box_1.gif
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio-card_hu4d09f75255d3942fd4680641110a1a73_10820_220x0_resize_box_1.gif b/resources/testdata/golden/gohugoio-card_hu4315323919404496126_0_220x0_resize_box_1.gif
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_100x100_fill_box_center_3.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_100x100_fill_box_center_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_200x0_resize_q50_r90_box_3.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_200x0_resize_q50_r90_box_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_200x100_resize_box_3.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_200x100_resize_box_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_300x100_fill_nearestneighbor_topleft_3.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_300x100_fill_nearestneighbor_topleft_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_300x200_fill_gaussian_smart1_3.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_300x200_fill_gaussian_smart1_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_300x200_fit_linear_3.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_300x200_fit_linear_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_400x200_fill_box_bottomleft_3.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_bottomleft_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_400x200_fill_box_center_3.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_324b4d42c8746a684068d123fad8b744.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_10145879774663310287.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_43055c40cb4a15bd8491bfc502799f43.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_10484317606894136532.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_8166ccaf22bdabb94c9bb90bffe64133.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_11093326483404439501.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_a751b6cd969d7feab12540a8bb0ca927.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_12108901413150876595.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_9a8d95423df65a9c230a4cc88056c13a.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_1368160528378247482.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_ee57777f148caaa6993972d9709fdf2d.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_15932678542579281584.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_aeaaf23afe6fb4702bd3992426d0cad3.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_16769769134069376407.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_60c098f0ca6626668d9e3ad6bfb38b5b.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_16826185614123406698.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_6575f3a3c39a30cba9d76a6045c36de6.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_16851788174025928944.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_bdde5e36f15689c1451933f92fd357b3.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_17478916973129747965.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_a38a1924befb1721a09be7d432f5f70f.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_1999930288179126795.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_9165e5559db8ba31a401327b5617c098.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_35625387183264766.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_e8ef2efdde4357a79694ea9c2be82f63.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_4355974086897058214.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_a487ef4bea3dba1e1a84be5358cfef39.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_4500301550729488566.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_d87fd348ad697a9b16399709441d9d56.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_4537007754286294453.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_d111079da5d8d143b6cae10d6fedbc24.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_6226609227946633992.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_abcdd770eaed9301cfff4bc2f96459ba.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_6663284144007557192.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_1a923841aa34545db29f46a8fc4c5b0d.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_7394663371967385838.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_4ea8f246299cc5fba9744bdf162bd57d.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_400x200_fill_box_center_3_filter_9987965893403929502.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_600x0_resize_box_3.png b/resources/testdata/golden/gohugoio24_hu7834617682594811866_0_600x0_resize_box_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_100x100_fill_box_center_3.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_100x100_fill_box_center_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_200x0_resize_q50_r90_box_3.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_200x0_resize_q50_r90_box_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_200x100_resize_box_3.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_200x100_resize_box_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_300x100_fill_nearestneighbor_topleft_3.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_300x100_fill_nearestneighbor_topleft_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_300x200_fill_gaussian_smart1_3.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_300x200_fill_gaussian_smart1_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_300x200_fit_linear_3.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_300x200_fit_linear_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_400x200_fill_box_bottomleft_3.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_bottomleft_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_400x200_fill_box_center_3.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_ae631e5252bb5d7b92bc766ad1a89069.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_10145879774663310287.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_73c19c5f80881858a85aa23cd0ca400d.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_10484317606894136532.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_d1bbfa2629bffb90118cacce3fcfb924.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_11093326483404439501.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_428e769d14483c2fcdd6f5c5138e2066.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_12108901413150876595.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_276650b97daa7ae98e79b929d7f87c19.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_1368160528378247482.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_b34412412a1cf1658e516a335b0a8dd4.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_15932678542579281584.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_f17bba59421e7a500387232295512fc0.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_16769769134069376407.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_00cd4ff18b53ecbd78e42aefe5fbf522.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_16826185614123406698.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_c5140f11378ddb13843432a5b489594a.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_16851788174025928944.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_a0505112c99af88626ac9b9a16a27acb.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_17478916973129747965.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_e4d38674b70d9ef559c5df72c9262790.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_1999930288179126795.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_2e05d39f4cb329be10e8c515494cef76.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_35625387183264766.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_398ca764abfff83bb15318068105dcb9.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_4355974086897058214.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_871826faffc414ca3746f65fc9910eed.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_4500301550729488566.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_a0ffc0f22f22e6920f3cad414d6db6ba.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_4537007754286294453.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_d17d0184674fcf0a4d770c90bed503db.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_6226609227946633992.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_3980c5868e0b6f20ec95424dfdcb1d67.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_6663284144007557192.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_eff9583d9b94ac79c60cb099846ce8f3.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_7394663371967385838.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_3ed273f49d1dc83891f5736e21fc5f44.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_400x200_fill_box_center_3_filter_9987965893403929502.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_600x0_resize_box_3.png b/resources/testdata/golden/gohugoio8_hu3730316029470468128_0_600x0_resize_box_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gopher-hero8_huaa0cd7d2cfc14ff32a57f171896f2285_13327_200x0_resize_bge3e615_box_3.png b/resources/testdata/golden/gopher-hero8_hu15519140586546988538_0_200x0_resize_bge3e615_box_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gopher-hero8_huaa0cd7d2cfc14ff32a57f171896f2285_13327_200x0_resize_q75_bge3e615_box_3.jpg b/resources/testdata/golden/gopher-hero8_hu15519140586546988538_0_200x0_resize_q75_bge3e615_box_3.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gopher-hero8_huaa0cd7d2cfc14ff32a57f171896f2285_13327_30x0_resize_box_3.png b/resources/testdata/golden/gopher-hero8_hu15519140586546988538_0_30x0_resize_box_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gopher-hero8_huaa0cd7d2cfc14ff32a57f171896f2285_13327_filter_10590793696706257122.png b/resources/testdata/golden/gopher-hero8_hu15519140586546988538_0_filter_18247526396371657121.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gradient-circle_huf3d35257a40a8d6f525263a856c5ecfd_20069_200x0_resize_bge3e615_box_3.png b/resources/testdata/golden/gradient-circle_hu6504854814255106391_0_200x0_resize_bge3e615_box_3.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gradient-circle_huf3d35257a40a8d6f525263a856c5ecfd_20069_200x0_resize_q75_bge3e615_box_3.jpg b/resources/testdata/golden/gradient-circle_hu6504854814255106391_0_200x0_resize_q75_bge3e615_box_3.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/gradient-circle_huf3d35257a40a8d6f525263a856c5ecfd_20069_filter_10590793696706257122.png b/resources/testdata/golden/gradient-circle_hu6504854814255106391_0_filter_18247526396371657121.png
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_100x100_fill_q75_box_center.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_100x100_fill_q75_box_center.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_200x0_resize_q50_r90_box.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_200x0_resize_q50_r90_box.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_200x100_resize_q75_box.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_200x100_resize_q75_box.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_300x100_fill_q75_nearestneighbor_topleft.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_300x100_fill_q75_nearestneighbor_topleft.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_300x200_fill_q75_gaussian_smart1.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_300x200_fill_q75_gaussian_smart1.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_300x200_fit_q75_linear.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_300x200_fit_q75_linear.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_400x200_fill_q75_box_bottomleft.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_bottomleft.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_400x200_fill_q75_box_center.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_3f1b1455c4a7d13c5aeb7510f9a6a581.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_10145879774663310287.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_cb45fcba865177290c89dc9f41d6ff7a.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_10484317606894136532.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_6c5c12ac79d3455ccb1993d51eec3cdf.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_11093326483404439501.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_352eb0101b7c88107520ba719432bbb2.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_12108901413150876595.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_3efc2d0f29a8e12c5a690fc6c9288854.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_1368160528378247482.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_6673ece428cb7d523234ca0d7c299542.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_15932678542579281584.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_c2d24766b49f3147f5a4137a8db592ac.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_16769769134069376407.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_7d9bc4700565266807dc476421066137.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_16826185614123406698.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_c50a17db1e6d1bd0fe31a9a3444f1587.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_16851788174025928944.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_0d1b300da7a815ed567b6dadb6f2ce5e.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_17478916973129747965.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_17fd3c558d78ce249b5f0bcbe1ddbffb.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_1999930288179126795.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_510813cc53c37e2d489d2f9fdb13f749.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_35625387183264766.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_abf356affd7d70d6bec3b3498b572191.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_4355974086897058214.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_f6d8fe32ce3e83abf130e91e33456914.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_4500301550729488566.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_de1fe6c0f40e7165355507d0f1748083.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_4537007754286294453.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_9f00027c376fe8556cc9996c47f23f78.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_6226609227946633992.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_d30c10468b33df9010d185a8fe8f0491.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_6663284144007557192.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_c36da6818db1ab630c3f87f65170003b.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_7394663371967385838.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_30fc2aab35ca0861bf396d09aebc85a4.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_400x200_fill_q75_box_center_filter_9987965893403929502.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_600x0_resize_q75_box.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_600x0_resize_q75_box.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_filter_16531506165985954191.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_filter_2739339915147920042.jpg
       Binary files differ.
   DIR diff --git a/resources/testdata/golden/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_filter_18171945436439920693.jpg b/resources/testdata/golden/sunset_hu13399802095542588467_0_filter_7649370997474087000.jpg
       Binary files differ.
   DIR diff --git a/resources/transform.go b/resources/transform.go
       @@ -24,6 +24,7 @@ import (
                "sync"
        
                "github.com/gohugoio/hugo/common/constants"
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/common/paths"
                "github.com/gohugoio/hugo/identity"
        
       @@ -36,7 +37,6 @@ import (
                "github.com/gohugoio/hugo/common/herrors"
                "github.com/gohugoio/hugo/common/hugio"
                "github.com/gohugoio/hugo/common/maps"
       -        "github.com/gohugoio/hugo/helpers"
                "github.com/gohugoio/hugo/resources/internal"
                "github.com/gohugoio/hugo/resources/resource"
        
       @@ -397,7 +397,7 @@ func (r *resourceAdapter) TransformationKey() string {
                for _, tr := range r.transformations {
                        key = key + "_" + tr.Key().Value()
                }
       -        return r.spec.ResourceCache.cleanKey(r.target.Key()) + "_" + helpers.MD5String(key)
       +        return r.spec.ResourceCache.cleanKey(r.target.Key()) + "_" + hashing.MD5FromStringHexEncoded(key)
        }
        
        func (r *resourceAdapter) getOrTransform(publish, setContent bool) error {
   DIR diff --git a/source/fileInfo.go b/source/fileInfo.go
       @@ -19,6 +19,7 @@ import (
                "time"
        
                "github.com/bep/gitmap"
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/common/hugo"
                "github.com/gohugoio/hugo/common/paths"
                "github.com/gohugoio/hugo/media"
       @@ -26,8 +27,6 @@ import (
                "github.com/gohugoio/hugo/common/hugio"
        
                "github.com/gohugoio/hugo/hugofs"
       -
       -        "github.com/gohugoio/hugo/helpers"
        )
        
        // File describes a source file.
       @@ -125,7 +124,7 @@ func (fi *File) IsZero() bool {
        // in some cases that is slightly expensive to construct.
        func (fi *File) init() {
                fi.lazyInit.Do(func() {
       -                fi.uniqueID = helpers.MD5String(filepath.ToSlash(fi.Path()))
       +                fi.uniqueID = hashing.MD5FromStringHexEncoded(filepath.ToSlash(fi.Path()))
                })
        }
        
   DIR diff --git a/tpl/collections/reflect_helpers.go b/tpl/collections/reflect_helpers.go
       @@ -18,8 +18,8 @@ import (
                "fmt"
                "reflect"
        
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/common/types"
       -        "github.com/gohugoio/hugo/identity"
        )
        
        var (
       @@ -49,7 +49,7 @@ func normalize(v reflect.Value) any {
                k := v.Kind()
                switch {
                case !v.Type().Comparable():
       -                return identity.HashUint64(v.Interface())
       +                return hashing.HashUint64(v.Interface())
                case isNumber(k):
                        f, err := numberToFloat(v)
                        if err == nil {
   DIR diff --git a/tpl/data/resources.go b/tpl/data/resources.go
       @@ -23,7 +23,7 @@ import (
                "time"
        
                "github.com/gohugoio/hugo/cache/filecache"
       -        "github.com/gohugoio/hugo/helpers"
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/spf13/afero"
        )
        
       @@ -44,7 +44,7 @@ func (ns *Namespace) getRemote(cache *filecache.Cache, unmarshal func([]byte) (b
        
                var headers bytes.Buffer
                req.Header.Write(&headers)
       -        id := helpers.MD5String(url + headers.String())
       +        id := hashing.MD5FromStringHexEncoded(url + headers.String())
                var handled bool
                var retry bool
        
   DIR diff --git a/tpl/partials/partials.go b/tpl/partials/partials.go
       @@ -25,6 +25,7 @@ import (
        
                "github.com/bep/lazycache"
        
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/identity"
        
                texttemplate "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate"
       @@ -50,7 +51,7 @@ func (k partialCacheKey) Key() string {
                if k.Variants == nil {
                        return k.Name
                }
       -        return identity.HashString(append([]any{k.Name}, k.Variants...)...)
       +        return hashing.HashString(append([]any{k.Name}, k.Variants...)...)
        }
        
        func (k partialCacheKey) templateName() string {
   DIR diff --git a/tpl/templates/templates.go b/tpl/templates/templates.go
       @@ -20,8 +20,8 @@ import (
                "strconv"
                "sync/atomic"
        
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/deps"
       -        "github.com/gohugoio/hugo/helpers"
                "github.com/gohugoio/hugo/tpl"
                "github.com/mitchellh/mapstructure"
        )
       @@ -83,7 +83,7 @@ func (ns *Namespace) DoDefer(ctx context.Context, id string, optsv any) string {
                templateName := id
                var key string
                if opts.Key != "" {
       -                key = helpers.MD5String(opts.Key)
       +                key = hashing.MD5FromStringHexEncoded(opts.Key)
                } else {
                        key = strconv.FormatUint(defferedIDCounter.Add(1), 10)
                }
   DIR diff --git a/tpl/transform/unmarshal.go b/tpl/transform/unmarshal.go
       @@ -22,11 +22,11 @@ import (
                "github.com/gohugoio/hugo/resources"
                "github.com/gohugoio/hugo/resources/resource"
        
       +        "github.com/gohugoio/hugo/common/hashing"
                "github.com/gohugoio/hugo/common/types"
        
                "github.com/mitchellh/mapstructure"
        
       -        "github.com/gohugoio/hugo/helpers"
                "github.com/gohugoio/hugo/parser/metadecoders"
        
                "github.com/spf13/cast"
       @@ -117,7 +117,7 @@ func (ns *Namespace) Unmarshal(args ...any) (any, error) {
                        return nil, errors.New("no data to transform")
                }
        
       -        key := helpers.MD5String(dataStr)
       +        key := hashing.MD5FromStringHexEncoded(dataStr)
        
                v, err := ns.cache.GetOrCreate(key, func(string) (*resources.StaleValue[any], error) {
                        f := decoder.FormatFromContentString(dataStr)