]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Rename common/maps to common/hmaps (#14384)
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Fri, 16 Jan 2026 10:47:46 +0000 (11:47 +0100)
committerGitHub <noreply@github.com>
Fri, 16 Jan 2026 10:47:46 +0000 (11:47 +0100)
Go's stdlid now has a maps package, which is very useful. We have been using imports on the form `xmaps "maps"`, but auto import tools doesn't handle this, which is annoying.

I have been thinking about this for some time, but have been holding back because of all the import changes. However, now is a good time to do this, with very little unmerged code.

115 files changed:
cache/filecache/filecache_config.go
commands/config.go
commands/hugobuilder.go
commands/import.go
common/hexec/exec.go
common/hmaps/cache.go [new file with mode: 0644]
common/hmaps/cache_test.go [new file with mode: 0644]
common/hmaps/map.go [new file with mode: 0644]
common/hmaps/map_test.go [new file with mode: 0644]
common/hmaps/maps.go [new file with mode: 0644]
common/hmaps/maps_test.go [new file with mode: 0644]
common/hmaps/ordered.go [new file with mode: 0644]
common/hmaps/ordered_test.go [new file with mode: 0644]
common/hmaps/orderedintset.go [new file with mode: 0644]
common/hmaps/orderedintset_test.go [new file with mode: 0644]
common/hmaps/params.go [new file with mode: 0644]
common/hmaps/params_test.go [new file with mode: 0644]
common/hreflect/helpers.go
common/maps/cache.go [deleted file]
common/maps/cache_test.go [deleted file]
common/maps/map.go [deleted file]
common/maps/map_test.go [deleted file]
common/maps/maps.go [deleted file]
common/maps/maps_test.go [deleted file]
common/maps/ordered.go [deleted file]
common/maps/ordered_test.go [deleted file]
common/maps/orderedintset.go [deleted file]
common/maps/orderedintset_test.go [deleted file]
common/maps/params.go [deleted file]
common/maps/params_test.go [deleted file]
common/paths/pathparser.go
config/allconfig/allconfig.go
config/allconfig/alldecoders.go
config/allconfig/docshelper.go
config/allconfig/load.go
config/configLoader.go
config/configProvider.go
config/defaultConfigProvider.go
config/defaultConfigProvider_test.go
config/namespace_test.go
config/testconfig/testconfig.go
deps/deps.go
hugofs/hglob/glob.go
hugofs/rootmapping_fs_test.go
hugolib/config_test.go
hugolib/content_map_page.go
hugolib/content_map_page_assembler.go
hugolib/doctree/support.go
hugolib/hugo_sites.go
hugolib/integrationtest_builder.go
hugolib/page__content.go
hugolib/page__meta.go
hugolib/page__per_output.go
hugolib/pagesfromdata/pagesfromgotmpl.go
hugolib/segments/segments.go
hugolib/site.go
hugolib/sitesmatrix/vectorstores.go
hugolib/sitesmatrix/vectorstores_test.go
internal/js/api.go
internal/js/esbuild/batch.go
internal/js/esbuild/options.go
internal/js/esbuild/resolve.go
internal/warpc/warpc.go
langs/language.go
markup/goldmark/convert_test.go
markup/markup_config/config.go
media/config.go
minifiers/config.go
modules/collect.go
modules/npm/package_builder.go
navigation/menu.go
navigation/pagemenus.go
output/config.go
parser/metadecoders/decoder.go
related/inverted_index.go
resources/images/config.go
resources/images/filters.go
resources/page/page_matcher.go
resources/page/page_matcher_test.go
resources/page/page_nop.go
resources/page/pagemeta/page_frontmatter.go
resources/page/permalinks.go
resources/page/site.go
resources/page/testhelpers_test.go
resources/postpub/postpub.go
resources/resource.go
resources/resource/params.go
resources/resource/resource_helpers.go
resources/resource/resources.go
resources/resource/resourcetypes.go
resources/resource_factories/create/remote.go
resources/resource_metadata.go
resources/transform.go
tpl/collections/collections.go
tpl/collections/collections_test.go
tpl/collections/index.go
tpl/collections/index_test.go
tpl/collections/merge.go
tpl/collections/merge_test.go
tpl/collections/querify.go
tpl/collections/querify_test.go
tpl/collections/sort.go
tpl/collections/sort_test.go
tpl/collections/where.go
tpl/collections/where_test.go
tpl/css/css.go
tpl/data/data.go
tpl/data/data_test.go
tpl/encoding/encoding.go
tpl/internal/resourcehelpers/helpers.go
tpl/openapi/openapi3/openapi3.go
tpl/resources/resources.go
tpl/tplimpl/template_funcs.go
tpl/tplimpl/templatestore.go
tpl/tplimpl/templatetransform.go

index d5298117470721b13e73e9ca9701f5f269c53827..b4e4efdc2451911b28b77c05ed9528dc4359a0b2 100644 (file)
@@ -22,7 +22,7 @@ import (
        "strings"
        "time"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/config"
 
        "github.com/mitchellh/mapstructure"
@@ -154,7 +154,7 @@ func DecodeConfig(fs afero.Fs, bcfg config.BaseConfig, m map[string]any) (Config
        _, isOsFs := fs.(*afero.OsFs)
 
        for k, v := range m {
-               if _, ok := v.(maps.Params); !ok {
+               if _, ok := v.(hmaps.Params); !ok {
                        continue
                }
                cc := defaultCacheConfig
index a44378b75b0f0cc768c95e3bdeb4cba10393583b..ce00c2239991a77f7d62258b027784082ac6f195 100644 (file)
@@ -23,7 +23,7 @@ import (
        "time"
 
        "github.com/bep/simplecobra"
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/config/allconfig"
        "github.com/gohugoio/hugo/hugolib/sitesmatrix"
        "github.com/gohugoio/hugo/modules"
@@ -95,7 +95,7 @@ func (c *configCommand) Run(ctx context.Context, cd *simplecobra.Commandeer, arg
                if err := json.Unmarshal(buf.Bytes(), &m); err != nil {
                        return err
                }
-               maps.ConvertFloat64WithNoDecimalsToInt(m)
+               hmaps.ConvertFloat64WithNoDecimalsToInt(m)
                switch format {
                case "yaml":
                        return parser.InterfaceToConfig(m, metadecoders.YAML, os.Stdout)
index bc8eeb588bea63ec58541c41d970ef7efb89929b..038b9ad94780638f1321a8ff1e1287c8bc09d1c2 100644 (file)
@@ -31,11 +31,11 @@ import (
        "github.com/bep/simplecobra"
        "github.com/fsnotify/fsnotify"
        "github.com/gohugoio/hugo/common/herrors"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hstrings"
        "github.com/gohugoio/hugo/common/htime"
        "github.com/gohugoio/hugo/common/hugo"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/common/terminal"
        "github.com/gohugoio/hugo/common/types"
@@ -1077,7 +1077,7 @@ func (c *hugoBuilder) loadConfig(cd *simplecobra.Commandeer, running bool) error
        }
        cfg.Set("environment", c.r.environment)
 
-       cfg.Set("internal", maps.Params{
+       cfg.Set("internal", hmaps.Params{
                "running":        running,
                "watch":          watch,
                "verbose":        c.r.isVerbose(),
index 9da2b39e503e6cbed144b45744df2a48c50fd879..163f3b4d4c37aca8edf40282ac808e68757c1b5b 100644 (file)
@@ -29,9 +29,9 @@ import (
        "unicode"
 
        "github.com/bep/simplecobra"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/htime"
        "github.com/gohugoio/hugo/common/hugio"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/helpers"
        "github.com/gohugoio/hugo/hugofs"
        "github.com/gohugoio/hugo/parser"
@@ -190,7 +190,7 @@ func (c *importCommand) createSiteFromJekyll(jekyllRoot, targetDir string, jekyl
 }
 
 func (c *importCommand) convertJekyllContent(m any, content string) (string, error) {
-       metadata, _ := maps.ToStringMapE(m)
+       metadata, _ := hmaps.ToStringMapE(m)
 
        lines := strings.Split(content, "\n")
        var resultLines []string
@@ -246,7 +246,7 @@ func (c *importCommand) convertJekyllContent(m any, content string) (string, err
 }
 
 func (c *importCommand) convertJekyllMetaData(m any, postName string, postDate time.Time, draft bool) (any, error) {
-       metadata, err := maps.ToStringMapE(m)
+       metadata, err := hmaps.ToStringMapE(m)
        if err != nil {
                return nil, err
        }
index c3a6ebf571e80e8d734b9b41359922e266cd06b9..79d48a48392ddbee841536513092aa2a705ffd1a 100644 (file)
@@ -27,8 +27,8 @@ import (
        "sync"
 
        "github.com/bep/logg"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/config"
        "github.com/gohugoio/hugo/config/security"
 )
@@ -102,7 +102,7 @@ func New(cfg security.Config, workingDir string, log loggers.Logger) *Exec {
                workingDir:        workingDir,
                infol:             log.InfoCommand("exec"),
                baseEnviron:       baseEnviron,
-               newNPXRunnerCache: maps.NewCache[string, func(arg ...any) (Runner, error)](),
+               newNPXRunnerCache: hmaps.NewCache[string, func(arg ...any) (Runner, error)](),
        }
 }
 
@@ -121,7 +121,7 @@ type Exec struct {
        // os.Environ filtered by the Exec.OsEnviron whitelist filter.
        baseEnviron []string
 
-       newNPXRunnerCache *maps.Cache[string, func(arg ...any) (Runner, error)]
+       newNPXRunnerCache *hmaps.Cache[string, func(arg ...any) (Runner, error)]
        npxInit           sync.Once
        npxAvailable      bool
 }
diff --git a/common/hmaps/cache.go b/common/hmaps/cache.go
new file mode 100644 (file)
index 0000000..b67f1bc
--- /dev/null
@@ -0,0 +1,218 @@
+// Copyright 2026 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 hmaps
+
+import (
+       "sync"
+)
+
+// Cache is a simple thread safe cache backed by a map.
+type Cache[K comparable, T any] struct {
+       m                  map[K]T
+       opts               CacheOptions
+       hasBeenInitialized bool
+       sync.RWMutex
+}
+
+// CacheOptions are the options for the Cache.
+type CacheOptions struct {
+       // If set, the cache will not grow beyond this size.
+       Size uint64
+}
+
+var defaultCacheOptions = CacheOptions{}
+
+// NewCache creates a new Cache with default options.
+func NewCache[K comparable, T any]() *Cache[K, T] {
+       return &Cache[K, T]{m: make(map[K]T), opts: defaultCacheOptions}
+}
+
+// NewCacheWithOptions creates a new Cache with the given options.
+func NewCacheWithOptions[K comparable, T any](opts CacheOptions) *Cache[K, T] {
+       return &Cache[K, T]{m: make(map[K]T), opts: opts}
+}
+
+// Delete deletes the given key from the cache.
+// If c is nil, this method is a no-op.
+func (c *Cache[K, T]) Get(key K) (T, bool) {
+       if c == nil {
+               var zero T
+               return zero, false
+       }
+       c.RLock()
+       v, found := c.get(key)
+       c.RUnlock()
+       return v, found
+}
+
+func (c *Cache[K, T]) get(key K) (T, bool) {
+       v, found := c.m[key]
+       return v, found
+}
+
+// GetOrCreate gets the value for the given key if it exists, or creates it if not.
+func (c *Cache[K, T]) GetOrCreate(key K, create func() (T, error)) (T, error) {
+       c.RLock()
+       v, found := c.m[key]
+       c.RUnlock()
+       if found {
+               return v, nil
+       }
+       c.Lock()
+       defer c.Unlock()
+       v, found = c.m[key]
+       if found {
+               return v, nil
+       }
+       v, err := create()
+       if err != nil {
+               return v, err
+       }
+       c.clearIfNeeded()
+       c.m[key] = v
+       return v, nil
+}
+
+// Contains returns whether the given key exists in the cache.
+func (c *Cache[K, T]) Contains(key K) bool {
+       c.RLock()
+       _, found := c.m[key]
+       c.RUnlock()
+       return found
+}
+
+// InitAndGet initializes the cache if not already done and returns the value for the given key.
+// The init state will be reset on Reset or Drain.
+func (c *Cache[K, T]) InitAndGet(key K, init func(get func(key K) (T, bool), set func(key K, value T)) error) (T, error) {
+       var v T
+       c.RLock()
+       if !c.hasBeenInitialized {
+               c.RUnlock()
+               if err := func() error {
+                       c.Lock()
+                       defer c.Unlock()
+                       // Double check in case another goroutine has initialized it in the meantime.
+                       if !c.hasBeenInitialized {
+                               err := init(c.get, c.set)
+                               if err != nil {
+                                       return err
+                               }
+                               c.hasBeenInitialized = true
+                       }
+                       return nil
+               }(); err != nil {
+                       return v, err
+               }
+               // Reacquire the read lock.
+               c.RLock()
+       }
+
+       v = c.m[key]
+       c.RUnlock()
+
+       return v, nil
+}
+
+// Set sets the given key to the given value.
+func (c *Cache[K, T]) Set(key K, value T) {
+       c.Lock()
+       c.set(key, value)
+       c.Unlock()
+}
+
+// SetIfAbsent sets the given key to the given value if the key does not already exist in the cache.
+func (c *Cache[K, T]) SetIfAbsent(key K, value T) {
+       c.RLock()
+       if _, found := c.get(key); !found {
+               c.RUnlock()
+               c.Set(key, value)
+       } else {
+               c.RUnlock()
+       }
+}
+
+func (c *Cache[K, T]) clearIfNeeded() {
+       if c.opts.Size > 0 && uint64(len(c.m)) >= c.opts.Size {
+               // clear the map
+               clear(c.m)
+       }
+}
+
+func (c *Cache[K, T]) set(key K, value T) {
+       c.clearIfNeeded()
+       c.m[key] = value
+}
+
+// ForEeach calls the given function for each key/value pair in the cache.
+// If the function returns false, the iteration stops.
+func (c *Cache[K, T]) ForEeach(f func(K, T) bool) {
+       c.RLock()
+       defer c.RUnlock()
+       for k, v := range c.m {
+               if !f(k, v) {
+                       return
+               }
+       }
+}
+
+func (c *Cache[K, T]) Drain() map[K]T {
+       c.Lock()
+       m := c.m
+       c.m = make(map[K]T)
+       c.hasBeenInitialized = false
+       c.Unlock()
+       return m
+}
+
+func (c *Cache[K, T]) Len() int {
+       c.RLock()
+       defer c.RUnlock()
+       return len(c.m)
+}
+
+func (c *Cache[K, T]) Reset() {
+       c.Lock()
+       clear(c.m)
+       c.hasBeenInitialized = false
+       c.Unlock()
+}
+
+// SliceCache is a simple thread safe cache backed by a map.
+type SliceCache[T any] struct {
+       m map[string][]T
+       sync.RWMutex
+}
+
+func NewSliceCache[T any]() *SliceCache[T] {
+       return &SliceCache[T]{m: make(map[string][]T)}
+}
+
+func (c *SliceCache[T]) Get(key string) ([]T, bool) {
+       c.RLock()
+       v, found := c.m[key]
+       c.RUnlock()
+       return v, found
+}
+
+func (c *SliceCache[T]) Append(key string, values ...T) {
+       c.Lock()
+       c.m[key] = append(c.m[key], values...)
+       c.Unlock()
+}
+
+func (c *SliceCache[T]) Reset() {
+       c.Lock()
+       c.m = make(map[string][]T)
+       c.Unlock()
+}
diff --git a/common/hmaps/cache_test.go b/common/hmaps/cache_test.go
new file mode 100644 (file)
index 0000000..c6555d2
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright 2026 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 hmaps
+
+import (
+       "testing"
+
+       qt "github.com/frankban/quicktest"
+)
+
+func TestCacheSize(t *testing.T) {
+       c := qt.New(t)
+
+       cache := NewCacheWithOptions[string, string](CacheOptions{Size: 10})
+
+       for i := range 30 {
+               cache.Set(string(rune('a'+i)), "value")
+       }
+
+       c.Assert(len(cache.m), qt.Equals, 10)
+
+       for i := 20; i < 50; i++ {
+               cache.GetOrCreate(string(rune('a'+i)), func() (string, error) {
+                       return "value", nil
+               })
+       }
+
+       c.Assert(len(cache.m), qt.Equals, 10)
+
+       for i := 100; i < 200; i++ {
+               cache.SetIfAbsent(string(rune('a'+i)), "value")
+       }
+
+       c.Assert(len(cache.m), qt.Equals, 10)
+
+       cache.InitAndGet("foo", func(
+               get func(key string) (string, bool), set func(key string, value string),
+       ) error {
+               for i := 50; i < 100; i++ {
+                       set(string(rune('a'+i)), "value")
+               }
+               return nil
+       })
+
+       c.Assert(len(cache.m), qt.Equals, 10)
+}
diff --git a/common/hmaps/map.go b/common/hmaps/map.go
new file mode 100644 (file)
index 0000000..8bb1cfa
--- /dev/null
@@ -0,0 +1,129 @@
+// Copyright 2026 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 hmaps
+
+import (
+       "iter"
+       "sync"
+)
+
+func NewMap[K comparable, T any]() *Map[K, T] {
+       return &Map[K, T]{
+               m: make(map[K]T),
+       }
+}
+
+// Map is a thread safe map backed by a Go map.
+type Map[K comparable, T any] struct {
+       m  map[K]T
+       mu sync.RWMutex
+}
+
+// Get gets the value for the given key.
+// It returns the zero value of T if the key is not found.
+func (m *Map[K, T]) Get(key K) T {
+       v, _ := m.Lookup(key)
+       return v
+}
+
+// Lookup looks up the given key in the map.
+// It returns the value and a boolean indicating whether the key was found.
+func (m *Map[K, T]) Lookup(key K) (T, bool) {
+       m.mu.RLock()
+       v, found := m.m[key]
+       m.mu.RUnlock()
+       return v, found
+}
+
+// GetOrCreate gets the value for the given key if it exists, or creates it if not.
+func (m *Map[K, T]) GetOrCreate(key K, create func() (T, error)) (T, error) {
+       v, found := m.Lookup(key)
+       if found {
+               return v, nil
+       }
+       m.mu.Lock()
+       defer m.mu.Unlock()
+       v, found = m.m[key]
+       if found {
+               return v, nil
+       }
+       v, err := create()
+       if err != nil {
+               return v, err
+       }
+       m.m[key] = v
+       return v, nil
+}
+
+// Set sets the given key to the given value.
+func (m *Map[K, T]) Set(key K, value T) {
+       m.mu.Lock()
+       m.m[key] = value
+       m.mu.Unlock()
+}
+
+// Delete deletes the given key from the map.
+// It returns true if the key was found and deleted, false otherwise.
+func (m *Map[K, T]) Delete(key K) bool {
+       m.mu.Lock()
+       defer m.mu.Unlock()
+       if _, found := m.m[key]; found {
+               delete(m.m, key)
+               return true
+       }
+       return false
+}
+
+// WithWriteLock executes the given function with a write lock on the map.
+func (m *Map[K, T]) WithWriteLock(f func(m map[K]T) error) error {
+       m.mu.Lock()
+       defer m.mu.Unlock()
+       return f(m.m)
+}
+
+// SetIfAbsent sets the given key to the given value if the key does not already exist in the map.
+// It returns true if the value was set, false otherwise.
+func (m *Map[K, T]) SetIfAbsent(key K, value T) bool {
+       m.mu.RLock()
+       if _, found := m.m[key]; !found {
+               m.mu.RUnlock()
+               return m.doSetIfAbsent(key, value)
+       }
+       m.mu.RUnlock()
+       return false
+}
+
+func (m *Map[K, T]) doSetIfAbsent(key K, value T) bool {
+       m.mu.Lock()
+       defer m.mu.Unlock()
+       if _, found := m.m[key]; !found {
+               m.m[key] = value
+               return true
+       }
+       return false
+}
+
+// All returns an iterator over all key/value pairs in the map.
+// A read lock is held during the iteration.
+func (m *Map[K, T]) All() iter.Seq2[K, T] {
+       return func(yield func(K, T) bool) {
+               m.mu.RLock()
+               defer m.mu.RUnlock()
+               for k, v := range m.m {
+                       if !yield(k, v) {
+                               return
+                       }
+               }
+       }
+}
diff --git a/common/hmaps/map_test.go b/common/hmaps/map_test.go
new file mode 100644 (file)
index 0000000..7791bc6
--- /dev/null
@@ -0,0 +1,72 @@
+// Copyright 2026 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 hmaps
+
+import (
+       "testing"
+
+       qt "github.com/frankban/quicktest"
+)
+
+func TestMap(t *testing.T) {
+       c := qt.New(t)
+
+       m := NewMap[string, int]()
+
+       m.Set("b", 42)
+       v, found := m.Lookup("b")
+       c.Assert(found, qt.Equals, true)
+       c.Assert(v, qt.Equals, 42)
+       v = m.Get("b")
+       c.Assert(v, qt.Equals, 42)
+       v, found = m.Lookup("c")
+       c.Assert(found, qt.Equals, false)
+       c.Assert(v, qt.Equals, 0)
+       v = m.Get("c")
+       c.Assert(v, qt.Equals, 0)
+       v, err := m.GetOrCreate("d", func() (int, error) {
+               return 100, nil
+       })
+       c.Assert(err, qt.IsNil)
+       c.Assert(v, qt.Equals, 100)
+       v, found = m.Lookup("d")
+       c.Assert(found, qt.Equals, true)
+       c.Assert(v, qt.Equals, 100)
+
+       v, err = m.GetOrCreate("d", func() (int, error) {
+               return 200, nil
+       })
+       c.Assert(err, qt.IsNil)
+       c.Assert(v, qt.Equals, 100)
+
+       wasSet := m.SetIfAbsent("e", 300)
+       c.Assert(wasSet, qt.Equals, true)
+       v, found = m.Lookup("e")
+       c.Assert(found, qt.Equals, true)
+       c.Assert(v, qt.Equals, 300)
+
+       wasSet = m.SetIfAbsent("e", 400)
+       c.Assert(wasSet, qt.Equals, false)
+       v, found = m.Lookup("e")
+       c.Assert(found, qt.Equals, true)
+       c.Assert(v, qt.Equals, 300)
+
+       m.WithWriteLock(func(m map[string]int) error {
+               m["f"] = 500
+               return nil
+       })
+       v, found = m.Lookup("f")
+       c.Assert(found, qt.Equals, true)
+       c.Assert(v, qt.Equals, 500)
+}
diff --git a/common/hmaps/maps.go b/common/hmaps/maps.go
new file mode 100644 (file)
index 0000000..36d0103
--- /dev/null
@@ -0,0 +1,238 @@
+// Copyright 2026 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 hmaps
+
+import (
+       "fmt"
+       "strings"
+
+       "github.com/gohugoio/hugo/common/types"
+
+       "github.com/gobwas/glob"
+       "github.com/spf13/cast"
+)
+
+// ToStringMapE converts in to map[string]interface{}.
+func ToStringMapE(in any) (map[string]any, error) {
+       switch vv := in.(type) {
+       case Params:
+               return vv, nil
+       case map[string]string:
+               m := map[string]any{}
+               for k, v := range vv {
+                       m[k] = v
+               }
+               return m, nil
+
+       default:
+               return cast.ToStringMapE(in)
+       }
+}
+
+// ToParamsAndPrepare converts in to Params and prepares it for use.
+// If in is nil, an empty map is returned.
+// See PrepareParams.
+func ToParamsAndPrepare(in any) (Params, error) {
+       if types.IsNil(in) {
+               return Params{}, nil
+       }
+       m, err := ToStringMapE(in)
+       if err != nil {
+               return nil, err
+       }
+       PrepareParams(m)
+       return m, nil
+}
+
+// MustToParamsAndPrepare calls ToParamsAndPrepare and panics if it fails.
+func MustToParamsAndPrepare(in any) Params {
+       p, err := ToParamsAndPrepare(in)
+       if err != nil {
+               panic(fmt.Sprintf("cannot convert %T to maps.Params: %s", in, err))
+       }
+       return p
+}
+
+// ToStringMap converts in to map[string]interface{}.
+func ToStringMap(in any) map[string]any {
+       m, _ := ToStringMapE(in)
+       return m
+}
+
+// ToStringMapStringE converts in to map[string]string.
+func ToStringMapStringE(in any) (map[string]string, error) {
+       m, err := ToStringMapE(in)
+       if err != nil {
+               return nil, err
+       }
+       return cast.ToStringMapStringE(m)
+}
+
+// ToStringMapString converts in to map[string]string.
+func ToStringMapString(in any) map[string]string {
+       m, _ := ToStringMapStringE(in)
+       return m
+}
+
+// ToStringMapBool converts in to bool.
+func ToStringMapBool(in any) map[string]bool {
+       m, _ := ToStringMapE(in)
+       return cast.ToStringMapBool(m)
+}
+
+// ToSliceStringMap converts in to []map[string]interface{}.
+func ToSliceStringMap(in any) ([]map[string]any, error) {
+       switch v := in.(type) {
+       case []map[string]any:
+               return v, nil
+       case Params:
+               return []map[string]any{v}, nil
+       case map[string]any:
+               return []map[string]any{v}, nil
+       case []any:
+               var s []map[string]any
+               for _, entry := range v {
+                       if vv, ok := entry.(map[string]any); ok {
+                               s = append(s, vv)
+                       }
+               }
+               return s, nil
+       default:
+               return nil, fmt.Errorf("unable to cast %#v of type %T to []map[string]interface{}", in, in)
+       }
+}
+
+// LookupEqualFold finds key in m with case insensitive equality checks.
+func LookupEqualFold[T any | string](m map[string]T, key string) (T, string, bool) {
+       if v, found := m[key]; found {
+               return v, key, true
+       }
+       for k, v := range m {
+               if strings.EqualFold(k, key) {
+                       return v, k, true
+               }
+       }
+       var s T
+       return s, "", false
+}
+
+// MergeShallow merges src into dst, but only if the key does not already exist in dst.
+// The keys are compared case insensitively.
+func MergeShallow(dst, src map[string]any) {
+       for k, v := range src {
+               found := false
+               for dk := range dst {
+                       if strings.EqualFold(dk, k) {
+                               found = true
+                               break
+                       }
+               }
+               if !found {
+                       dst[k] = v
+               }
+       }
+}
+
+type keyRename struct {
+       pattern glob.Glob
+       newKey  string
+}
+
+// KeyRenamer supports renaming of keys in a map.
+type KeyRenamer struct {
+       renames []keyRename
+}
+
+// NewKeyRenamer creates a new KeyRenamer given a list of pattern and new key
+// value pairs.
+func NewKeyRenamer(patternKeys ...string) (KeyRenamer, error) {
+       var renames []keyRename
+       for i := 0; i < len(patternKeys); i += 2 {
+               g, err := glob.Compile(strings.ToLower(patternKeys[i]), '/')
+               if err != nil {
+                       return KeyRenamer{}, err
+               }
+               renames = append(renames, keyRename{pattern: g, newKey: patternKeys[i+1]})
+       }
+
+       return KeyRenamer{renames: renames}, nil
+}
+
+func (r KeyRenamer) getNewKey(keyPath string) string {
+       for _, matcher := range r.renames {
+               if matcher.pattern.Match(keyPath) {
+                       return matcher.newKey
+               }
+       }
+
+       return ""
+}
+
+// Rename renames the keys in the given map according
+// to the patterns in the current KeyRenamer.
+func (r KeyRenamer) Rename(m map[string]any) {
+       r.renamePath("", m)
+}
+
+func (KeyRenamer) keyPath(k1, k2 string) string {
+       k1, k2 = strings.ToLower(k1), strings.ToLower(k2)
+       if k1 == "" {
+               return k2
+       }
+       return k1 + "/" + k2
+}
+
+func (r KeyRenamer) renamePath(parentKeyPath string, m map[string]any) {
+       for k, v := range m {
+               keyPath := r.keyPath(parentKeyPath, k)
+               switch vv := v.(type) {
+               case map[any]any:
+                       r.renamePath(keyPath, cast.ToStringMap(vv))
+               case map[string]any:
+                       r.renamePath(keyPath, vv)
+               }
+
+               newKey := r.getNewKey(keyPath)
+
+               if newKey != "" {
+                       delete(m, k)
+                       m[newKey] = v
+               }
+       }
+}
+
+// ConvertFloat64WithNoDecimalsToInt converts float64 values with no decimals to int recursively.
+func ConvertFloat64WithNoDecimalsToInt(m map[string]any) {
+       for k, v := range m {
+               switch vv := v.(type) {
+               case float64:
+                       if v == float64(int64(vv)) {
+                               m[k] = int64(vv)
+                       }
+               case map[string]any:
+                       ConvertFloat64WithNoDecimalsToInt(vv)
+               case []any:
+                       for i, vvv := range vv {
+                               switch vvvv := vvv.(type) {
+                               case float64:
+                                       if vvv == float64(int64(vvvv)) {
+                                               vv[i] = int64(vvvv)
+                                       }
+                               case map[string]any:
+                                       ConvertFloat64WithNoDecimalsToInt(vvvv)
+                               }
+                       }
+               }
+       }
+}
diff --git a/common/hmaps/maps_test.go b/common/hmaps/maps_test.go
new file mode 100644 (file)
index 0000000..a017e6f
--- /dev/null
@@ -0,0 +1,201 @@
+// Copyright 2026 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 hmaps
+
+import (
+       "fmt"
+       "reflect"
+       "testing"
+
+       qt "github.com/frankban/quicktest"
+)
+
+func TestPrepareParams(t *testing.T) {
+       tests := []struct {
+               input    Params
+               expected Params
+       }{
+               {
+                       map[string]any{
+                               "abC": 32,
+                       },
+                       Params{
+                               "abc": 32,
+                       },
+               },
+               {
+                       map[string]any{
+                               "abC": 32,
+                               "deF": map[any]any{
+                                       23: "A value",
+                                       24: map[string]any{
+                                               "AbCDe": "A value",
+                                               "eFgHi": "Another value",
+                                       },
+                               },
+                               "gHi": map[string]any{
+                                       "J": 25,
+                               },
+                               "jKl": map[string]string{
+                                       "M": "26",
+                               },
+                       },
+                       Params{
+                               "abc": 32,
+                               "def": Params{
+                                       "23": "A value",
+                                       "24": Params{
+                                               "abcde": "A value",
+                                               "efghi": "Another value",
+                                       },
+                               },
+                               "ghi": Params{
+                                       "j": 25,
+                               },
+                               "jkl": Params{
+                                       "m": "26",
+                               },
+                       },
+               },
+       }
+
+       for i, test := range tests {
+               t.Run(fmt.Sprint(i), func(t *testing.T) {
+                       // PrepareParams modifies input.
+                       prepareClone := PrepareParamsClone(test.input)
+                       PrepareParams(test.input)
+                       if !reflect.DeepEqual(test.expected, test.input) {
+                               t.Errorf("[%d] Expected\n%#v, got\n%#v\n", i, test.expected, test.input)
+                       }
+                       if !reflect.DeepEqual(test.expected, prepareClone) {
+                               t.Errorf("[%d] Expected\n%#v, got\n%#v\n", i, test.expected, prepareClone)
+                       }
+               })
+       }
+}
+
+func TestToSliceStringMap(t *testing.T) {
+       c := qt.New(t)
+
+       tests := []struct {
+               input    any
+               expected []map[string]any
+       }{
+               {
+                       input: []map[string]any{
+                               {"abc": 123},
+                       },
+                       expected: []map[string]any{
+                               {"abc": 123},
+                       },
+               }, {
+                       input: []any{
+                               map[string]any{
+                                       "def": 456,
+                               },
+                       },
+                       expected: []map[string]any{
+                               {"def": 456},
+                       },
+               },
+       }
+
+       for _, test := range tests {
+               v, err := ToSliceStringMap(test.input)
+               c.Assert(err, qt.IsNil)
+               c.Assert(v, qt.DeepEquals, test.expected)
+       }
+}
+
+func TestToParamsAndPrepare(t *testing.T) {
+       c := qt.New(t)
+       _, err := ToParamsAndPrepare(map[string]any{"A": "av"})
+       c.Assert(err, qt.IsNil)
+
+       params, err := ToParamsAndPrepare(nil)
+       c.Assert(err, qt.IsNil)
+       c.Assert(params, qt.DeepEquals, Params{})
+}
+
+func TestRenameKeys(t *testing.T) {
+       c := qt.New(t)
+
+       m := map[string]any{
+               "a":    32,
+               "ren1": "m1",
+               "ren2": "m1_2",
+               "sub": map[string]any{
+                       "subsub": map[string]any{
+                               "REN1": "m2",
+                               "ren2": "m2_2",
+                       },
+               },
+               "no": map[string]any{
+                       "ren1": "m2",
+                       "ren2": "m2_2",
+               },
+       }
+
+       expected := map[string]any{
+               "a":    32,
+               "new1": "m1",
+               "new2": "m1_2",
+               "sub": map[string]any{
+                       "subsub": map[string]any{
+                               "new1": "m2",
+                               "ren2": "m2_2",
+                       },
+               },
+               "no": map[string]any{
+                       "ren1": "m2",
+                       "ren2": "m2_2",
+               },
+       }
+
+       renamer, err := NewKeyRenamer(
+               "{ren1,sub/*/ren1}", "new1",
+               "{Ren2,sub/ren2}", "new2",
+       )
+       c.Assert(err, qt.IsNil)
+
+       renamer.Rename(m)
+
+       if !reflect.DeepEqual(expected, m) {
+               t.Errorf("Expected\n%#v, got\n%#v\n", expected, m)
+       }
+}
+
+func TestLookupEqualFold(t *testing.T) {
+       c := qt.New(t)
+
+       m1 := map[string]any{
+               "a": "av",
+               "B": "bv",
+       }
+
+       v, k, found := LookupEqualFold(m1, "b")
+       c.Assert(found, qt.IsTrue)
+       c.Assert(v, qt.Equals, "bv")
+       c.Assert(k, qt.Equals, "B")
+
+       m2 := map[string]string{
+               "a": "av",
+               "B": "bv",
+       }
+
+       v, k, found = LookupEqualFold(m2, "b")
+       c.Assert(found, qt.IsTrue)
+       c.Assert(k, qt.Equals, "B")
+       c.Assert(v, qt.Equals, "bv")
+}
diff --git a/common/hmaps/ordered.go b/common/hmaps/ordered.go
new file mode 100644 (file)
index 0000000..b1a567b
--- /dev/null
@@ -0,0 +1,144 @@
+// Copyright 2026 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 hmaps
+
+import (
+       "slices"
+
+       "github.com/gohugoio/hugo/common/hashing"
+)
+
+// Ordered is a map that can be iterated in the order of insertion.
+// Note that insertion order is not affected if a key is re-inserted into the map.
+// In a nil map, all operations are no-ops.
+// This is not thread safe.
+type Ordered[K comparable, T any] struct {
+       // The keys in the order they were added.
+       keys []K
+       // The values.
+       values map[K]T
+}
+
+// NewOrdered creates a new Ordered map.
+func NewOrdered[K comparable, T any]() *Ordered[K, T] {
+       return &Ordered[K, T]{values: make(map[K]T)}
+}
+
+// Set sets the value for the given key.
+// Note that insertion order is not affected if a key is re-inserted into the map.
+func (m *Ordered[K, T]) Set(key K, value T) {
+       if m == nil {
+               return
+       }
+       // Check if key already exists.
+       if _, found := m.values[key]; !found {
+               m.keys = append(m.keys, key)
+       }
+       m.values[key] = value
+}
+
+// Get gets the value for the given key.
+func (m *Ordered[K, T]) Get(key K) (T, bool) {
+       if m == nil {
+               var v T
+               return v, false
+       }
+       value, found := m.values[key]
+       return value, found
+}
+
+// Has returns whether the given key exists in the map.
+func (m *Ordered[K, T]) Has(key K) bool {
+       if m == nil {
+               return false
+       }
+       _, found := m.values[key]
+       return found
+}
+
+// Delete deletes the value for the given key.
+func (m *Ordered[K, T]) Delete(key K) {
+       if m == nil {
+               return
+       }
+       delete(m.values, key)
+       for i, k := range m.keys {
+               if k == key {
+                       m.keys = slices.Delete(m.keys, i, i+1)
+                       break
+               }
+       }
+}
+
+// Clone creates a shallow copy of the map.
+func (m *Ordered[K, T]) Clone() *Ordered[K, T] {
+       if m == nil {
+               return nil
+       }
+       clone := NewOrdered[K, T]()
+       for _, k := range m.keys {
+               clone.Set(k, m.values[k])
+       }
+       return clone
+}
+
+// Keys returns the keys in the order they were added.
+func (m *Ordered[K, T]) Keys() []K {
+       if m == nil {
+               return nil
+       }
+       return m.keys
+}
+
+// Values returns the values in the order they were added.
+func (m *Ordered[K, T]) Values() []T {
+       if m == nil {
+               return nil
+       }
+       var values []T
+       for _, k := range m.keys {
+               values = append(values, m.values[k])
+       }
+       return values
+}
+
+// Len returns the number of items in the map.
+func (m *Ordered[K, T]) Len() int {
+       if m == nil {
+               return 0
+       }
+       return len(m.keys)
+}
+
+// Range calls f sequentially for each key and value present in the map.
+// If f returns false, range stops the iteration.
+// TODO(bep) replace with iter.Seq2 when we bump go Go 1.24.
+func (m *Ordered[K, T]) Range(f func(key K, value T) bool) {
+       if m == nil {
+               return
+       }
+       for _, k := range m.keys {
+               if !f(k, m.values[k]) {
+                       return
+               }
+       }
+}
+
+// Hash calculates a hash from the values.
+func (m *Ordered[K, T]) Hash() (uint64, error) {
+       if m == nil {
+               return 0, nil
+       }
+       return hashing.Hash(m.values)
+}
diff --git a/common/hmaps/ordered_test.go b/common/hmaps/ordered_test.go
new file mode 100644 (file)
index 0000000..c04fe0a
--- /dev/null
@@ -0,0 +1,99 @@
+// Copyright 2026 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 hmaps
+
+import (
+       "testing"
+
+       qt "github.com/frankban/quicktest"
+)
+
+func TestOrdered(t *testing.T) {
+       c := qt.New(t)
+
+       m := NewOrdered[string, int]()
+       m.Set("a", 1)
+       m.Set("b", 2)
+       m.Set("c", 3)
+
+       c.Assert(m.Keys(), qt.DeepEquals, []string{"a", "b", "c"})
+       c.Assert(m.Values(), qt.DeepEquals, []int{1, 2, 3})
+
+       v, found := m.Get("b")
+       c.Assert(found, qt.Equals, true)
+       c.Assert(v, qt.Equals, 2)
+
+       m.Set("b", 22)
+       c.Assert(m.Keys(), qt.DeepEquals, []string{"a", "b", "c"})
+       c.Assert(m.Values(), qt.DeepEquals, []int{1, 22, 3})
+
+       m.Delete("b")
+
+       c.Assert(m.Keys(), qt.DeepEquals, []string{"a", "c"})
+       c.Assert(m.Values(), qt.DeepEquals, []int{1, 3})
+}
+
+func TestOrderedHash(t *testing.T) {
+       c := qt.New(t)
+
+       m := NewOrdered[string, int]()
+       m.Set("a", 1)
+       m.Set("b", 2)
+       m.Set("c", 3)
+
+       h1, err := m.Hash()
+       c.Assert(err, qt.IsNil)
+
+       m.Set("d", 4)
+
+       h2, err := m.Hash()
+       c.Assert(err, qt.IsNil)
+
+       c.Assert(h1, qt.Not(qt.Equals), h2)
+
+       m = NewOrdered[string, int]()
+       m.Set("b", 2)
+       m.Set("a", 1)
+       m.Set("c", 3)
+
+       h3, err := m.Hash()
+       c.Assert(err, qt.IsNil)
+       // Order does not matter.
+       c.Assert(h1, qt.Equals, h3)
+}
+
+func TestOrderedNil(t *testing.T) {
+       c := qt.New(t)
+
+       var m *Ordered[string, int]
+
+       m.Set("a", 1)
+       c.Assert(m.Keys(), qt.IsNil)
+       c.Assert(m.Values(), qt.IsNil)
+       v, found := m.Get("a")
+       c.Assert(found, qt.Equals, false)
+       c.Assert(v, qt.Equals, 0)
+       m.Delete("a")
+       var b bool
+       m.Range(func(k string, v int) bool {
+               b = true
+               return true
+       })
+       c.Assert(b, qt.Equals, false)
+       c.Assert(m.Len(), qt.Equals, 0)
+       c.Assert(m.Clone(), qt.IsNil)
+       h, err := m.Hash()
+       c.Assert(err, qt.IsNil)
+       c.Assert(h, qt.Equals, uint64(0))
+}
diff --git a/common/hmaps/orderedintset.go b/common/hmaps/orderedintset.go
new file mode 100644 (file)
index 0000000..659d30f
--- /dev/null
@@ -0,0 +1,154 @@
+// Copyright 2026 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 hmaps
+
+import (
+       "fmt"
+       "slices"
+
+       "github.com/bits-and-blooms/bitset"
+)
+
+type OrderedIntSet struct {
+       keys   []int
+       values *bitset.BitSet
+}
+
+// NewOrderedIntSet creates a new OrderedIntSet.
+// Note that this is backed by https://github.com/bits-and-blooms/bitset
+func NewOrderedIntSet(vals ...int) *OrderedIntSet {
+       m := &OrderedIntSet{
+               keys:   make([]int, 0, len(vals)),
+               values: bitset.New(uint(len(vals))),
+       }
+       for _, v := range vals {
+               m.Set(v)
+       }
+       return m
+}
+
+// Set sets the value for the given key.
+// Note that insertion order is not affected if a key is re-inserted into the set.
+func (m *OrderedIntSet) Set(key int) {
+       if m == nil {
+               panic("nil OrderedIntSet")
+       }
+       keyu := uint(key)
+       if m.values.Test(keyu) {
+               return
+       }
+       m.values.Set(keyu)
+       m.keys = append(m.keys, key)
+}
+
+// SetFrom sets the values from another OrderedIntSet.
+func (m *OrderedIntSet) SetFrom(other *OrderedIntSet) {
+       if m == nil || other == nil {
+               return
+       }
+       for _, key := range other.keys {
+               m.Set(key)
+       }
+}
+
+func (m *OrderedIntSet) Clone() *OrderedIntSet {
+       if m == nil {
+               return nil
+       }
+       newSet := &OrderedIntSet{
+               keys:   slices.Clone(m.keys),
+               values: m.values.Clone(),
+       }
+       return newSet
+}
+
+// Next returns the next key in the set possibly including the given key.
+// It returns -1 if the key is not found or if there are no keys greater than the given key.
+func (m *OrderedIntSet) Next(i int) int {
+       n, ok := m.values.NextSet(uint(i))
+       if !ok {
+               return -1
+       }
+       return int(n)
+}
+
+// The reason we don't use iter.Seq is https://github.com/golang/go/issues/69015
+// This is 70% faster than using iter.Seq2[int, int] for the keys.
+// It returns false if the iteration was stopped early.
+func (m *OrderedIntSet) ForEachKey(yield func(int) bool) bool {
+       if m == nil {
+               return true
+       }
+       for _, key := range m.keys {
+               if !yield(key) {
+                       return false
+               }
+       }
+       return true
+}
+
+func (m *OrderedIntSet) Has(key int) bool {
+       if m == nil {
+               return false
+       }
+       return m.values.Test(uint(key))
+}
+
+func (m *OrderedIntSet) Len() int {
+       if m == nil {
+               return 0
+       }
+       return len(m.keys)
+}
+
+// KeysSorted returns the keys in sorted order.
+func (m *OrderedIntSet) KeysSorted() []int {
+       if m == nil {
+               return nil
+       }
+       keys := slices.Clone(m.keys)
+       slices.Sort(keys)
+       return m.keys
+}
+
+func (m *OrderedIntSet) String() string {
+       if m == nil {
+               return "[]"
+       }
+       return fmt.Sprintf("%v", m.keys)
+}
+
+func (m *OrderedIntSet) Values() *bitset.BitSet {
+       if m == nil {
+               return nil
+       }
+       return m.values
+}
+
+func (m *OrderedIntSet) IsSuperSet(other *OrderedIntSet) bool {
+       if m == nil || other == nil {
+               return false
+       }
+       return m.values.IsSuperSet(other.values)
+}
+
+// Words returns the bitset as array of 64-bit words, giving direct access to the internal representation.
+// It is not a copy, so changes to the returned slice will affect the bitset.
+// It is meant for advanced users.
+func (m *OrderedIntSet) Words() []uint64 {
+       if m == nil {
+               return nil
+       }
+       return m.values.Words()
+}
diff --git a/common/hmaps/orderedintset_test.go b/common/hmaps/orderedintset_test.go
new file mode 100644 (file)
index 0000000..8bce69b
--- /dev/null
@@ -0,0 +1,117 @@
+// Copyright 2026 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 hmaps
+
+import (
+       "testing"
+
+       qt "github.com/frankban/quicktest"
+)
+
+func TestOrderedIntSet(t *testing.T) {
+       c := qt.New(t)
+
+       m := NewOrderedIntSet(2, 1, 3, 7)
+
+       c.Assert(m.Len(), qt.Equals, 4)
+       c.Assert(m.Has(1), qt.Equals, true)
+       c.Assert(m.Has(4), qt.Equals, false)
+       c.Assert(m.String(), qt.Equals, "[2 1 3 7]")
+       m.Set(4)
+       c.Assert(m.Len(), qt.Equals, 5)
+       c.Assert(m.Has(4), qt.Equals, true)
+       c.Assert(m.Next(0), qt.Equals, 1)
+       c.Assert(m.Next(1), qt.Equals, 1)
+       c.Assert(m.Next(2), qt.Equals, 2)
+       c.Assert(m.Next(3), qt.Equals, 3)
+       c.Assert(m.Next(4), qt.Equals, 4)
+       c.Assert(m.Next(7), qt.Equals, 7)
+       c.Assert(m.Next(8), qt.Equals, -1)
+       c.Assert(m.String(), qt.Equals, "[2 1 3 7 4]")
+
+       var nilset *OrderedIntSet
+       c.Assert(nilset.Len(), qt.Equals, 0)
+       c.Assert(nilset.Has(1), qt.Equals, false)
+       c.Assert(nilset.String(), qt.Equals, "[]")
+
+       var collected []int
+       m.ForEachKey(func(key int) bool {
+               collected = append(collected, key)
+               return true
+       })
+       c.Assert(collected, qt.DeepEquals, []int{2, 1, 3, 7, 4})
+}
+
+func BenchmarkOrderedIntSet(b *testing.B) {
+       smallSet := NewOrderedIntSet()
+       for i := range 8 {
+               smallSet.Set(i)
+       }
+       mediumSet := NewOrderedIntSet()
+       for i := range 64 {
+               mediumSet.Set(i)
+       }
+       largeSet := NewOrderedIntSet()
+       for i := range 1024 {
+               largeSet.Set(i)
+       }
+
+       b.Run("New", func(b *testing.B) {
+               for b.Loop() {
+                       NewOrderedIntSet(1, 2, 3, 4, 5, 6, 7, 8)
+               }
+       })
+
+       b.Run("Has small", func(b *testing.B) {
+               for i := 0; b.Loop(); i++ {
+                       smallSet.Has(i % 32)
+               }
+       })
+
+       b.Run("Has medium", func(b *testing.B) {
+               for i := 0; b.Loop(); i++ {
+                       mediumSet.Has(i % 32)
+               }
+       })
+
+       b.Run("Next", func(b *testing.B) {
+               for i := 0; b.Loop(); i++ {
+                       mediumSet.Next(i % 32)
+               }
+       })
+
+       b.Run("ForEachKey small", func(b *testing.B) {
+               for b.Loop() {
+                       smallSet.ForEachKey(func(key int) bool {
+                               return true
+                       })
+               }
+       })
+
+       b.Run("ForEachKey medium", func(b *testing.B) {
+               for b.Loop() {
+                       mediumSet.ForEachKey(func(key int) bool {
+                               return true
+                       })
+               }
+       })
+
+       b.Run("ForEachKey large", func(b *testing.B) {
+               for b.Loop() {
+                       largeSet.ForEachKey(func(key int) bool {
+                               return true
+                       })
+               }
+       })
+}
diff --git a/common/hmaps/params.go b/common/hmaps/params.go
new file mode 100644 (file)
index 0000000..a67a45c
--- /dev/null
@@ -0,0 +1,473 @@
+// Copyright 2026 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 hmaps
+
+import (
+       "errors"
+       "fmt"
+       "strings"
+
+       "github.com/spf13/cast"
+)
+
+// Params is a map where all keys are lower case.
+type Params map[string]any
+
+// KeyParams is an utility struct for the WalkParams method.
+type KeyParams struct {
+       Key    string
+       Params Params
+}
+
+// GetNested does a lower case and nested search in this map.
+// It will return nil if none found.
+// Make all of these methods internal somehow.
+func (p Params) GetNested(indices ...string) any {
+       v, _, _ := getNested(p, indices)
+       return v
+}
+
+// SetParams overwrites values in dst with values in src for common or new keys.
+// This is done recursively.
+func SetParams(dst, src Params) {
+       setParams(dst, src, 0)
+}
+
+func setParams(dst, src Params, depth int) {
+       const maxDepth = 1000
+       if depth > maxDepth {
+               panic(errors.New("max depth exceeded"))
+       }
+       for k, v := range src {
+               vv, found := dst[k]
+               if !found {
+                       dst[k] = v
+               } else {
+                       switch vvv := vv.(type) {
+                       case Params:
+                               if pv, ok := v.(Params); ok {
+                                       setParams(vvv, pv, depth+1)
+                               } else {
+                                       dst[k] = v
+                               }
+                       default:
+                               dst[k] = v
+                       }
+               }
+       }
+}
+
+// IsZero returns true if p is considered empty.
+func (p Params) IsZero() bool {
+       if len(p) == 0 {
+               return true
+       }
+
+       if len(p) > 1 {
+               return false
+       }
+
+       for k := range p {
+               return k == MergeStrategyKey
+       }
+
+       return false
+}
+
+// MergeParamsWithStrategy transfers values from src to dst for new keys using the merge strategy given.
+// This is done recursively.
+func MergeParamsWithStrategy(strategy string, dst, src Params) {
+       dst.merge(ParamsMergeStrategy(strategy), src)
+}
+
+// MergeParams transfers values from src to dst for new keys using the merge encoded in dst.
+// This is done recursively.
+func MergeParams(dst, src Params) {
+       ms, _ := dst.GetMergeStrategy()
+       dst.merge(ms, src)
+}
+
+func (p Params) merge(ps ParamsMergeStrategy, pp Params) {
+       ns, found := p.GetMergeStrategy()
+
+       ms := ns
+       if !found && ps != "" {
+               ms = ps
+       }
+
+       noUpdate := ms == ParamsMergeStrategyNone
+       noUpdate = noUpdate || (ps != "" && ps == ParamsMergeStrategyShallow)
+
+       for k, v := range pp {
+               if k == MergeStrategyKey {
+                       continue
+               }
+               vv, found := p[k]
+
+               if found {
+                       // Key matches, if both sides are Params, we try to merge.
+                       if vvv, ok := vv.(Params); ok {
+                               if pv, ok := v.(Params); ok {
+                                       vvv.merge(ms, pv)
+                               }
+                       }
+               } else if !noUpdate {
+                       p[k] = v
+               }
+
+       }
+}
+
+// For internal use.
+func (p Params) GetMergeStrategy() (ParamsMergeStrategy, bool) {
+       if v, found := p[MergeStrategyKey]; found {
+               if s, ok := v.(ParamsMergeStrategy); ok {
+                       return s, true
+               }
+       }
+       return ParamsMergeStrategyShallow, false
+}
+
+// For internal use.
+func (p Params) DeleteMergeStrategy() bool {
+       if _, found := p[MergeStrategyKey]; found {
+               delete(p, MergeStrategyKey)
+               return true
+       }
+       return false
+}
+
+// For internal use.
+func (p Params) SetMergeStrategy(s ParamsMergeStrategy) {
+       switch s {
+       case ParamsMergeStrategyDeep, ParamsMergeStrategyNone, ParamsMergeStrategyShallow:
+       default:
+               panic(fmt.Sprintf("invalid merge strategy %q", s))
+       }
+       p[MergeStrategyKey] = s
+}
+
+func getNested(m map[string]any, indices []string) (any, string, map[string]any) {
+       if len(indices) == 0 {
+               return nil, "", nil
+       }
+
+       first := indices[0]
+       v, found := m[strings.ToLower(cast.ToString(first))]
+       if !found {
+               if len(indices) == 1 {
+                       return nil, first, m
+               }
+               return nil, "", nil
+
+       }
+
+       if len(indices) == 1 {
+               return v, first, m
+       }
+
+       switch m2 := v.(type) {
+       case Params:
+               return getNested(m2, indices[1:])
+       case map[string]any:
+               return getNested(m2, indices[1:])
+       default:
+               return nil, "", nil
+       }
+}
+
+// CreateNestedParamsFromSegements creates empty nested maps for the given keySegments in the target map.
+func CreateNestedParamsFromSegements(target Params, keySegments ...string) Params {
+       if len(keySegments) == 0 {
+               return target
+       }
+
+       m := target
+       for i, key := range keySegments {
+               v, found := m[key]
+               if !found {
+                       nm := Params{}
+                       m[key] = nm
+                       m = nm
+                       if i == len(keySegments)-1 {
+                               return nm
+                       }
+                       continue
+               }
+               m = v.(Params)
+       }
+
+       return m
+}
+
+// CreateNestedParamsSepString creates empty nested maps for the given keyStr in the target map
+// It returns the last map created.
+func CreateNestedParamsSepString(keyStr, separator string, target Params) Params {
+       keySegments := strings.Split(keyStr, separator)
+       return CreateNestedParamsFromSegements(target, keySegments...)
+}
+
+// SetNestedParamIfNotSet sets the value for the given keyStr in the target map if it does not exist.
+// It assumes that all but the last key in keyStr is a Params map or should be one.
+func SetNestedParamIfNotSet(keyStr, separator string, value any, target Params) Params {
+       keySegments := strings.Split(keyStr, separator)
+       if len(keySegments) == 0 {
+               return target
+       }
+       base := keySegments[:len(keySegments)-1]
+       last := keySegments[len(keySegments)-1]
+
+       m := CreateNestedParamsFromSegements(target, base...)
+
+       if _, ok := m[last]; !ok {
+               m[last] = value
+       }
+
+       return target
+}
+
+// GetNestedParam gets the first match of the keyStr in the candidates given.
+// It will first try the exact match and then try to find it as a nested map value,
+// using the given separator, e.g. "mymap.name".
+// It assumes that all the maps given have lower cased keys.
+func GetNestedParam(keyStr, separator string, candidates ...Params) (any, error) {
+       keyStr = strings.ToLower(keyStr)
+
+       // Try exact match first
+       for _, m := range candidates {
+               if v, ok := m[keyStr]; ok {
+                       return v, nil
+               }
+       }
+
+       keySegments := strings.Split(keyStr, separator)
+       for _, m := range candidates {
+               if v := m.GetNested(keySegments...); v != nil {
+                       return v, nil
+               }
+       }
+
+       return nil, nil
+}
+
+func GetNestedParamFn(keyStr, separator string, lookupFn func(key string) any) (any, string, map[string]any, error) {
+       keySegments := strings.Split(keyStr, separator)
+       if len(keySegments) == 0 {
+               return nil, "", nil, nil
+       }
+
+       first := lookupFn(keySegments[0])
+       if first == nil {
+               return nil, "", nil, nil
+       }
+
+       if len(keySegments) == 1 {
+               return first, keySegments[0], nil, nil
+       }
+
+       switch m := first.(type) {
+       case map[string]any:
+               v, key, owner := getNested(m, keySegments[1:])
+               return v, key, owner, nil
+       case Params:
+               v, key, owner := getNested(m, keySegments[1:])
+               return v, key, owner, nil
+       }
+
+       return nil, "", nil, nil
+}
+
+// ParamsMergeStrategy tells what strategy to use in Params.Merge.
+type ParamsMergeStrategy string
+
+const (
+       // Do not merge.
+       ParamsMergeStrategyNone ParamsMergeStrategy = "none"
+       // Only add new keys.
+       ParamsMergeStrategyShallow ParamsMergeStrategy = "shallow"
+       // Add new keys, merge existing.
+       ParamsMergeStrategyDeep ParamsMergeStrategy = "deep"
+
+       MergeStrategyKey = "_merge"
+)
+
+// CleanConfigStringMapString removes any processing instructions from m,
+// m will never be modified.
+func CleanConfigStringMapString(m map[string]string) map[string]string {
+       if len(m) == 0 {
+               return m
+       }
+       if _, found := m[MergeStrategyKey]; !found {
+               return m
+       }
+       // Create a new map and copy all the keys except the merge strategy key.
+       m2 := make(map[string]string, len(m)-1)
+       for k, v := range m {
+               if k != MergeStrategyKey {
+                       m2[k] = v
+               }
+       }
+       return m2
+}
+
+// CleanConfigStringMap is the same as CleanConfigStringMapString but for
+// map[string]any.
+func CleanConfigStringMap(m map[string]any) map[string]any {
+       return doCleanConfigStringMap(m, 0)
+}
+
+func doCleanConfigStringMap(m map[string]any, depth int) map[string]any {
+       if len(m) == 0 {
+               return m
+       }
+       const maxDepth = 1000
+       if depth > maxDepth {
+               panic(errors.New("max depth exceeded"))
+       }
+       if _, found := m[MergeStrategyKey]; !found {
+               return m
+       }
+       // Create a new map and copy all the keys except the merge strategy key.
+       m2 := make(map[string]any, len(m)-1)
+       for k, v := range m {
+               if k != MergeStrategyKey {
+                       m2[k] = v
+               }
+               switch v2 := v.(type) {
+               case map[string]any:
+                       m2[k] = doCleanConfigStringMap(v2, depth+1)
+               case Params:
+                       var p Params = doCleanConfigStringMap(v2, depth+1)
+                       m2[k] = p
+               case map[string]string:
+                       m2[k] = CleanConfigStringMapString(v2)
+               }
+
+       }
+       return m2
+}
+
+func toMergeStrategy(v any) ParamsMergeStrategy {
+       s := ParamsMergeStrategy(cast.ToString(v))
+       switch s {
+       case ParamsMergeStrategyDeep, ParamsMergeStrategyNone, ParamsMergeStrategyShallow:
+               return s
+       default:
+               return ParamsMergeStrategyDeep
+       }
+}
+
+// PrepareParams
+// * makes all the keys in the given map lower cased and will do so recursively.
+// * This will modify the map given.
+// * Any nested map[interface{}]interface{}, map[string]interface{},map[string]string  will be converted to Params.
+// * Any _merge value will be converted to proper type and value.
+func PrepareParams(m Params) {
+       for k, v := range m {
+               var retyped bool
+               lKey := strings.ToLower(k)
+               if lKey == MergeStrategyKey {
+                       v = toMergeStrategy(v)
+                       retyped = true
+               } else {
+                       switch vv := v.(type) {
+                       case map[any]any:
+                               var p Params = cast.ToStringMap(v)
+                               v = p
+                               PrepareParams(p)
+                               retyped = true
+                       case map[string]any:
+                               var p Params = v.(map[string]any)
+                               v = p
+                               PrepareParams(p)
+                               retyped = true
+                       case map[string]string:
+                               p := make(Params)
+                               for k, v := range vv {
+                                       p[k] = v
+                               }
+                               v = p
+                               PrepareParams(p)
+                               retyped = true
+                       }
+               }
+
+               if retyped || k != lKey {
+                       delete(m, k)
+                       m[lKey] = v
+               }
+       }
+}
+
+// CloneParamsDeep does a deep clone of the given Params,
+// meaning that any nested Params will be cloned as well.
+func CloneParamsDeep(m Params) Params {
+       return cloneParamsDeep(m, 0)
+}
+
+func cloneParamsDeep(m Params, depth int) Params {
+       const maxDepth = 1000
+       if depth > maxDepth {
+               panic(errors.New("max depth exceeded"))
+       }
+       m2 := make(Params)
+       for k, v := range m {
+               switch vv := v.(type) {
+               case Params:
+                       m2[k] = cloneParamsDeep(vv, depth+1)
+               default:
+                       m2[k] = v
+               }
+       }
+       return m2
+}
+
+// PrepareParamsClone is like PrepareParams, but it does not modify the input.
+func PrepareParamsClone(m Params) Params {
+       m2 := make(Params)
+       for k, v := range m {
+               var retyped bool
+               lKey := strings.ToLower(k)
+               if lKey == MergeStrategyKey {
+                       v = toMergeStrategy(v)
+                       retyped = true
+               } else {
+                       switch vv := v.(type) {
+                       case map[any]any:
+                               var p Params = cast.ToStringMap(v)
+                               v = PrepareParamsClone(p)
+                               retyped = true
+                       case map[string]any:
+                               var p Params = v.(map[string]any)
+                               v = PrepareParamsClone(p)
+                               retyped = true
+                       case map[string]string:
+                               p := make(Params)
+                               for k, v := range vv {
+                                       p[k] = v
+                               }
+                               v = p
+                               PrepareParams(p)
+                               retyped = true
+                       }
+               }
+
+               if retyped || k != lKey {
+                       m2[lKey] = v
+               } else {
+                       m2[k] = v
+               }
+       }
+       return m2
+}
diff --git a/common/hmaps/params_test.go b/common/hmaps/params_test.go
new file mode 100644 (file)
index 0000000..9202a84
--- /dev/null
@@ -0,0 +1,201 @@
+// Copyright 2026 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 hmaps
+
+import (
+       "testing"
+
+       qt "github.com/frankban/quicktest"
+)
+
+func TestGetNestedParam(t *testing.T) {
+       m := map[string]any{
+               "string":          "value",
+               "first":           1,
+               "with_underscore": 2,
+               "nested": map[string]any{
+                       "color": "blue",
+                       "nestednested": map[string]any{
+                               "color": "green",
+                       },
+               },
+       }
+
+       c := qt.New(t)
+
+       must := func(keyStr, separator string, candidates ...Params) any {
+               v, err := GetNestedParam(keyStr, separator, candidates...)
+               c.Assert(err, qt.IsNil)
+               return v
+       }
+
+       c.Assert(must("first", "_", m), qt.Equals, 1)
+       c.Assert(must("First", "_", m), qt.Equals, 1)
+       c.Assert(must("with_underscore", "_", m), qt.Equals, 2)
+       c.Assert(must("nested_color", "_", m), qt.Equals, "blue")
+       c.Assert(must("nested.nestednested.color", ".", m), qt.Equals, "green")
+       c.Assert(must("string.name", ".", m), qt.IsNil)
+       c.Assert(must("nested.foo", ".", m), qt.IsNil)
+}
+
+// https://github.com/gohugoio/hugo/issues/7903
+func TestGetNestedParamFnNestedNewKey(t *testing.T) {
+       c := qt.New(t)
+
+       nested := map[string]any{
+               "color": "blue",
+       }
+       m := map[string]any{
+               "nested": nested,
+       }
+
+       existing, nestedKey, owner, err := GetNestedParamFn("nested.new", ".", func(key string) any {
+               return m[key]
+       })
+
+       c.Assert(err, qt.IsNil)
+       c.Assert(existing, qt.IsNil)
+       c.Assert(nestedKey, qt.Equals, "new")
+       c.Assert(owner, qt.DeepEquals, nested)
+}
+
+func TestParamsSetAndMerge(t *testing.T) {
+       c := qt.New(t)
+
+       createParamsPair := func() (Params, Params) {
+               p1 := Params{"a": "av", "c": "cv", "nested": Params{"al2": "al2v", "cl2": "cl2v"}}
+               p2 := Params{"b": "bv", "a": "abv", "nested": Params{"bl2": "bl2v", "al2": "al2bv"}, MergeStrategyKey: ParamsMergeStrategyDeep}
+               return p1, p2
+       }
+
+       p1, p2 := createParamsPair()
+
+       SetParams(p1, p2)
+
+       c.Assert(p1, qt.DeepEquals, Params{
+               "a": "abv",
+               "c": "cv",
+               "nested": Params{
+                       "al2": "al2bv",
+                       "cl2": "cl2v",
+                       "bl2": "bl2v",
+               },
+               "b":              "bv",
+               MergeStrategyKey: ParamsMergeStrategyDeep,
+       })
+
+       p1, p2 = createParamsPair()
+
+       MergeParamsWithStrategy("", p1, p2)
+
+       // Default is to do a shallow merge.
+       c.Assert(p1, qt.DeepEquals, Params{
+               "c": "cv",
+               "nested": Params{
+                       "al2": "al2v",
+                       "cl2": "cl2v",
+               },
+               "b": "bv",
+               "a": "av",
+       })
+
+       p1, p2 = createParamsPair()
+       p1.SetMergeStrategy(ParamsMergeStrategyNone)
+       MergeParamsWithStrategy("", p1, p2)
+       p1.DeleteMergeStrategy()
+
+       c.Assert(p1, qt.DeepEquals, Params{
+               "a": "av",
+               "c": "cv",
+               "nested": Params{
+                       "al2": "al2v",
+                       "cl2": "cl2v",
+               },
+       })
+
+       p1, p2 = createParamsPair()
+       p1.SetMergeStrategy(ParamsMergeStrategyShallow)
+       MergeParamsWithStrategy("", p1, p2)
+       p1.DeleteMergeStrategy()
+
+       c.Assert(p1, qt.DeepEquals, Params{
+               "a": "av",
+               "c": "cv",
+               "nested": Params{
+                       "al2": "al2v",
+                       "cl2": "cl2v",
+               },
+               "b": "bv",
+       })
+
+       p1, p2 = createParamsPair()
+       p1.SetMergeStrategy(ParamsMergeStrategyDeep)
+       MergeParamsWithStrategy("", p1, p2)
+       p1.DeleteMergeStrategy()
+
+       c.Assert(p1, qt.DeepEquals, Params{
+               "nested": Params{
+                       "al2": "al2v",
+                       "cl2": "cl2v",
+                       "bl2": "bl2v",
+               },
+               "b": "bv",
+               "a": "av",
+               "c": "cv",
+       })
+}
+
+func TestParamsIsZero(t *testing.T) {
+       c := qt.New(t)
+
+       var nilParams Params
+
+       c.Assert(Params{}.IsZero(), qt.IsTrue)
+       c.Assert(nilParams.IsZero(), qt.IsTrue)
+       c.Assert(Params{"foo": "bar"}.IsZero(), qt.IsFalse)
+       c.Assert(Params{"_merge": "foo", "foo": "bar"}.IsZero(), qt.IsFalse)
+       c.Assert(Params{"_merge": "foo"}.IsZero(), qt.IsTrue)
+}
+
+func TestSetNestedParamIfNotSet(t *testing.T) {
+       c := qt.New(t)
+
+       m := Params{}
+
+       SetNestedParamIfNotSet("a.b.c", ".", "value", m)
+       c.Assert(m, qt.DeepEquals, Params{
+               "a": Params{
+                       "b": Params{
+                               "c": "value",
+                       },
+               },
+       })
+
+       m = Params{
+               "a": Params{
+                       "b": Params{
+                               "c": "existingValue",
+                       },
+               },
+       }
+
+       SetNestedParamIfNotSet("a.b.c", ".", "value", m)
+       c.Assert(m, qt.DeepEquals, Params{
+               "a": Params{
+                       "b": Params{
+                               "c": "existingValue",
+                       },
+               },
+       })
+}
index 4b70167d53352549acbd96410fda1e4fe259acc3..0a9200007f19dd3814c8ba6add193799f23db4ca 100644 (file)
@@ -20,8 +20,8 @@ import (
        "sync"
        "time"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/htime"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/types"
 )
 
@@ -355,7 +355,7 @@ func IsNil(v reflect.Value) bool {
 
 var contextInterface = reflect.TypeOf((*context.Context)(nil)).Elem()
 
-var isContextCache = maps.NewCache[reflect.Type, bool]()
+var isContextCache = hmaps.NewCache[reflect.Type, bool]()
 
 type k string
 
diff --git a/common/maps/cache.go b/common/maps/cache.go
deleted file mode 100644 (file)
index cf1307f..0000000
+++ /dev/null
@@ -1,218 +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 maps
-
-import (
-       "sync"
-)
-
-// Cache is a simple thread safe cache backed by a map.
-type Cache[K comparable, T any] struct {
-       m                  map[K]T
-       opts               CacheOptions
-       hasBeenInitialized bool
-       sync.RWMutex
-}
-
-// CacheOptions are the options for the Cache.
-type CacheOptions struct {
-       // If set, the cache will not grow beyond this size.
-       Size uint64
-}
-
-var defaultCacheOptions = CacheOptions{}
-
-// NewCache creates a new Cache with default options.
-func NewCache[K comparable, T any]() *Cache[K, T] {
-       return &Cache[K, T]{m: make(map[K]T), opts: defaultCacheOptions}
-}
-
-// NewCacheWithOptions creates a new Cache with the given options.
-func NewCacheWithOptions[K comparable, T any](opts CacheOptions) *Cache[K, T] {
-       return &Cache[K, T]{m: make(map[K]T), opts: opts}
-}
-
-// Delete deletes the given key from the cache.
-// If c is nil, this method is a no-op.
-func (c *Cache[K, T]) Get(key K) (T, bool) {
-       if c == nil {
-               var zero T
-               return zero, false
-       }
-       c.RLock()
-       v, found := c.get(key)
-       c.RUnlock()
-       return v, found
-}
-
-func (c *Cache[K, T]) get(key K) (T, bool) {
-       v, found := c.m[key]
-       return v, found
-}
-
-// GetOrCreate gets the value for the given key if it exists, or creates it if not.
-func (c *Cache[K, T]) GetOrCreate(key K, create func() (T, error)) (T, error) {
-       c.RLock()
-       v, found := c.m[key]
-       c.RUnlock()
-       if found {
-               return v, nil
-       }
-       c.Lock()
-       defer c.Unlock()
-       v, found = c.m[key]
-       if found {
-               return v, nil
-       }
-       v, err := create()
-       if err != nil {
-               return v, err
-       }
-       c.clearIfNeeded()
-       c.m[key] = v
-       return v, nil
-}
-
-// Contains returns whether the given key exists in the cache.
-func (c *Cache[K, T]) Contains(key K) bool {
-       c.RLock()
-       _, found := c.m[key]
-       c.RUnlock()
-       return found
-}
-
-// InitAndGet initializes the cache if not already done and returns the value for the given key.
-// The init state will be reset on Reset or Drain.
-func (c *Cache[K, T]) InitAndGet(key K, init func(get func(key K) (T, bool), set func(key K, value T)) error) (T, error) {
-       var v T
-       c.RLock()
-       if !c.hasBeenInitialized {
-               c.RUnlock()
-               if err := func() error {
-                       c.Lock()
-                       defer c.Unlock()
-                       // Double check in case another goroutine has initialized it in the meantime.
-                       if !c.hasBeenInitialized {
-                               err := init(c.get, c.set)
-                               if err != nil {
-                                       return err
-                               }
-                               c.hasBeenInitialized = true
-                       }
-                       return nil
-               }(); err != nil {
-                       return v, err
-               }
-               // Reacquire the read lock.
-               c.RLock()
-       }
-
-       v = c.m[key]
-       c.RUnlock()
-
-       return v, nil
-}
-
-// Set sets the given key to the given value.
-func (c *Cache[K, T]) Set(key K, value T) {
-       c.Lock()
-       c.set(key, value)
-       c.Unlock()
-}
-
-// SetIfAbsent sets the given key to the given value if the key does not already exist in the cache.
-func (c *Cache[K, T]) SetIfAbsent(key K, value T) {
-       c.RLock()
-       if _, found := c.get(key); !found {
-               c.RUnlock()
-               c.Set(key, value)
-       } else {
-               c.RUnlock()
-       }
-}
-
-func (c *Cache[K, T]) clearIfNeeded() {
-       if c.opts.Size > 0 && uint64(len(c.m)) >= c.opts.Size {
-               // clear the map
-               clear(c.m)
-       }
-}
-
-func (c *Cache[K, T]) set(key K, value T) {
-       c.clearIfNeeded()
-       c.m[key] = value
-}
-
-// ForEeach calls the given function for each key/value pair in the cache.
-// If the function returns false, the iteration stops.
-func (c *Cache[K, T]) ForEeach(f func(K, T) bool) {
-       c.RLock()
-       defer c.RUnlock()
-       for k, v := range c.m {
-               if !f(k, v) {
-                       return
-               }
-       }
-}
-
-func (c *Cache[K, T]) Drain() map[K]T {
-       c.Lock()
-       m := c.m
-       c.m = make(map[K]T)
-       c.hasBeenInitialized = false
-       c.Unlock()
-       return m
-}
-
-func (c *Cache[K, T]) Len() int {
-       c.RLock()
-       defer c.RUnlock()
-       return len(c.m)
-}
-
-func (c *Cache[K, T]) Reset() {
-       c.Lock()
-       clear(c.m)
-       c.hasBeenInitialized = false
-       c.Unlock()
-}
-
-// SliceCache is a simple thread safe cache backed by a map.
-type SliceCache[T any] struct {
-       m map[string][]T
-       sync.RWMutex
-}
-
-func NewSliceCache[T any]() *SliceCache[T] {
-       return &SliceCache[T]{m: make(map[string][]T)}
-}
-
-func (c *SliceCache[T]) Get(key string) ([]T, bool) {
-       c.RLock()
-       v, found := c.m[key]
-       c.RUnlock()
-       return v, found
-}
-
-func (c *SliceCache[T]) Append(key string, values ...T) {
-       c.Lock()
-       c.m[key] = append(c.m[key], values...)
-       c.Unlock()
-}
-
-func (c *SliceCache[T]) Reset() {
-       c.Lock()
-       c.m = make(map[string][]T)
-       c.Unlock()
-}
diff --git a/common/maps/cache_test.go b/common/maps/cache_test.go
deleted file mode 100644 (file)
index 239c56f..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2025 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 maps
-
-import (
-       "testing"
-
-       qt "github.com/frankban/quicktest"
-)
-
-func TestCacheSize(t *testing.T) {
-       c := qt.New(t)
-
-       cache := NewCacheWithOptions[string, string](CacheOptions{Size: 10})
-
-       for i := range 30 {
-               cache.Set(string(rune('a'+i)), "value")
-       }
-
-       c.Assert(len(cache.m), qt.Equals, 10)
-
-       for i := 20; i < 50; i++ {
-               cache.GetOrCreate(string(rune('a'+i)), func() (string, error) {
-                       return "value", nil
-               })
-       }
-
-       c.Assert(len(cache.m), qt.Equals, 10)
-
-       for i := 100; i < 200; i++ {
-               cache.SetIfAbsent(string(rune('a'+i)), "value")
-       }
-
-       c.Assert(len(cache.m), qt.Equals, 10)
-
-       cache.InitAndGet("foo", func(
-               get func(key string) (string, bool), set func(key string, value string),
-       ) error {
-               for i := 50; i < 100; i++ {
-                       set(string(rune('a'+i)), "value")
-               }
-               return nil
-       })
-
-       c.Assert(len(cache.m), qt.Equals, 10)
-}
diff --git a/common/maps/map.go b/common/maps/map.go
deleted file mode 100644 (file)
index 2050dac..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2025 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 maps
-
-import (
-       "iter"
-       "sync"
-)
-
-func NewMap[K comparable, T any]() *Map[K, T] {
-       return &Map[K, T]{
-               m: make(map[K]T),
-       }
-}
-
-// Map is a thread safe map backed by a Go map.
-type Map[K comparable, T any] struct {
-       m  map[K]T
-       mu sync.RWMutex
-}
-
-// Get gets the value for the given key.
-// It returns the zero value of T if the key is not found.
-func (m *Map[K, T]) Get(key K) T {
-       v, _ := m.Lookup(key)
-       return v
-}
-
-// Lookup looks up the given key in the map.
-// It returns the value and a boolean indicating whether the key was found.
-func (m *Map[K, T]) Lookup(key K) (T, bool) {
-       m.mu.RLock()
-       v, found := m.m[key]
-       m.mu.RUnlock()
-       return v, found
-}
-
-// GetOrCreate gets the value for the given key if it exists, or creates it if not.
-func (m *Map[K, T]) GetOrCreate(key K, create func() (T, error)) (T, error) {
-       v, found := m.Lookup(key)
-       if found {
-               return v, nil
-       }
-       m.mu.Lock()
-       defer m.mu.Unlock()
-       v, found = m.m[key]
-       if found {
-               return v, nil
-       }
-       v, err := create()
-       if err != nil {
-               return v, err
-       }
-       m.m[key] = v
-       return v, nil
-}
-
-// Set sets the given key to the given value.
-func (m *Map[K, T]) Set(key K, value T) {
-       m.mu.Lock()
-       m.m[key] = value
-       m.mu.Unlock()
-}
-
-// Delete deletes the given key from the map.
-// It returns true if the key was found and deleted, false otherwise.
-func (m *Map[K, T]) Delete(key K) bool {
-       m.mu.Lock()
-       defer m.mu.Unlock()
-       if _, found := m.m[key]; found {
-               delete(m.m, key)
-               return true
-       }
-       return false
-}
-
-// WithWriteLock executes the given function with a write lock on the map.
-func (m *Map[K, T]) WithWriteLock(f func(m map[K]T) error) error {
-       m.mu.Lock()
-       defer m.mu.Unlock()
-       return f(m.m)
-}
-
-// SetIfAbsent sets the given key to the given value if the key does not already exist in the map.
-// It returns true if the value was set, false otherwise.
-func (m *Map[K, T]) SetIfAbsent(key K, value T) bool {
-       m.mu.RLock()
-       if _, found := m.m[key]; !found {
-               m.mu.RUnlock()
-               return m.doSetIfAbsent(key, value)
-       }
-       m.mu.RUnlock()
-       return false
-}
-
-func (m *Map[K, T]) doSetIfAbsent(key K, value T) bool {
-       m.mu.Lock()
-       defer m.mu.Unlock()
-       if _, found := m.m[key]; !found {
-               m.m[key] = value
-               return true
-       }
-       return false
-}
-
-// All returns an iterator over all key/value pairs in the map.
-// A read lock is held during the iteration.
-func (m *Map[K, T]) All() iter.Seq2[K, T] {
-       return func(yield func(K, T) bool) {
-               m.mu.RLock()
-               defer m.mu.RUnlock()
-               for k, v := range m.m {
-                       if !yield(k, v) {
-                               return
-                       }
-               }
-       }
-}
diff --git a/common/maps/map_test.go b/common/maps/map_test.go
deleted file mode 100644 (file)
index de5e980..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2025 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 maps
-
-import (
-       "testing"
-
-       qt "github.com/frankban/quicktest"
-)
-
-func TestMap(t *testing.T) {
-       c := qt.New(t)
-
-       m := NewMap[string, int]()
-
-       m.Set("b", 42)
-       v, found := m.Lookup("b")
-       c.Assert(found, qt.Equals, true)
-       c.Assert(v, qt.Equals, 42)
-       v = m.Get("b")
-       c.Assert(v, qt.Equals, 42)
-       v, found = m.Lookup("c")
-       c.Assert(found, qt.Equals, false)
-       c.Assert(v, qt.Equals, 0)
-       v = m.Get("c")
-       c.Assert(v, qt.Equals, 0)
-       v, err := m.GetOrCreate("d", func() (int, error) {
-               return 100, nil
-       })
-       c.Assert(err, qt.IsNil)
-       c.Assert(v, qt.Equals, 100)
-       v, found = m.Lookup("d")
-       c.Assert(found, qt.Equals, true)
-       c.Assert(v, qt.Equals, 100)
-
-       v, err = m.GetOrCreate("d", func() (int, error) {
-               return 200, nil
-       })
-       c.Assert(err, qt.IsNil)
-       c.Assert(v, qt.Equals, 100)
-
-       wasSet := m.SetIfAbsent("e", 300)
-       c.Assert(wasSet, qt.Equals, true)
-       v, found = m.Lookup("e")
-       c.Assert(found, qt.Equals, true)
-       c.Assert(v, qt.Equals, 300)
-
-       wasSet = m.SetIfAbsent("e", 400)
-       c.Assert(wasSet, qt.Equals, false)
-       v, found = m.Lookup("e")
-       c.Assert(found, qt.Equals, true)
-       c.Assert(v, qt.Equals, 300)
-
-       m.WithWriteLock(func(m map[string]int) error {
-               m["f"] = 500
-               return nil
-       })
-       v, found = m.Lookup("f")
-       c.Assert(found, qt.Equals, true)
-       c.Assert(v, qt.Equals, 500)
-}
diff --git a/common/maps/maps.go b/common/maps/maps.go
deleted file mode 100644 (file)
index 5b3a08b..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright 2018 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 maps
-
-import (
-       "fmt"
-       "strings"
-
-       "github.com/gohugoio/hugo/common/types"
-
-       "github.com/gobwas/glob"
-       "github.com/spf13/cast"
-)
-
-// ToStringMapE converts in to map[string]interface{}.
-func ToStringMapE(in any) (map[string]any, error) {
-       switch vv := in.(type) {
-       case Params:
-               return vv, nil
-       case map[string]string:
-               m := map[string]any{}
-               for k, v := range vv {
-                       m[k] = v
-               }
-               return m, nil
-
-       default:
-               return cast.ToStringMapE(in)
-       }
-}
-
-// ToParamsAndPrepare converts in to Params and prepares it for use.
-// If in is nil, an empty map is returned.
-// See PrepareParams.
-func ToParamsAndPrepare(in any) (Params, error) {
-       if types.IsNil(in) {
-               return Params{}, nil
-       }
-       m, err := ToStringMapE(in)
-       if err != nil {
-               return nil, err
-       }
-       PrepareParams(m)
-       return m, nil
-}
-
-// MustToParamsAndPrepare calls ToParamsAndPrepare and panics if it fails.
-func MustToParamsAndPrepare(in any) Params {
-       p, err := ToParamsAndPrepare(in)
-       if err != nil {
-               panic(fmt.Sprintf("cannot convert %T to maps.Params: %s", in, err))
-       }
-       return p
-}
-
-// ToStringMap converts in to map[string]interface{}.
-func ToStringMap(in any) map[string]any {
-       m, _ := ToStringMapE(in)
-       return m
-}
-
-// ToStringMapStringE converts in to map[string]string.
-func ToStringMapStringE(in any) (map[string]string, error) {
-       m, err := ToStringMapE(in)
-       if err != nil {
-               return nil, err
-       }
-       return cast.ToStringMapStringE(m)
-}
-
-// ToStringMapString converts in to map[string]string.
-func ToStringMapString(in any) map[string]string {
-       m, _ := ToStringMapStringE(in)
-       return m
-}
-
-// ToStringMapBool converts in to bool.
-func ToStringMapBool(in any) map[string]bool {
-       m, _ := ToStringMapE(in)
-       return cast.ToStringMapBool(m)
-}
-
-// ToSliceStringMap converts in to []map[string]interface{}.
-func ToSliceStringMap(in any) ([]map[string]any, error) {
-       switch v := in.(type) {
-       case []map[string]any:
-               return v, nil
-       case Params:
-               return []map[string]any{v}, nil
-       case map[string]any:
-               return []map[string]any{v}, nil
-       case []any:
-               var s []map[string]any
-               for _, entry := range v {
-                       if vv, ok := entry.(map[string]any); ok {
-                               s = append(s, vv)
-                       }
-               }
-               return s, nil
-       default:
-               return nil, fmt.Errorf("unable to cast %#v of type %T to []map[string]interface{}", in, in)
-       }
-}
-
-// LookupEqualFold finds key in m with case insensitive equality checks.
-func LookupEqualFold[T any | string](m map[string]T, key string) (T, string, bool) {
-       if v, found := m[key]; found {
-               return v, key, true
-       }
-       for k, v := range m {
-               if strings.EqualFold(k, key) {
-                       return v, k, true
-               }
-       }
-       var s T
-       return s, "", false
-}
-
-// MergeShallow merges src into dst, but only if the key does not already exist in dst.
-// The keys are compared case insensitively.
-func MergeShallow(dst, src map[string]any) {
-       for k, v := range src {
-               found := false
-               for dk := range dst {
-                       if strings.EqualFold(dk, k) {
-                               found = true
-                               break
-                       }
-               }
-               if !found {
-                       dst[k] = v
-               }
-       }
-}
-
-type keyRename struct {
-       pattern glob.Glob
-       newKey  string
-}
-
-// KeyRenamer supports renaming of keys in a map.
-type KeyRenamer struct {
-       renames []keyRename
-}
-
-// NewKeyRenamer creates a new KeyRenamer given a list of pattern and new key
-// value pairs.
-func NewKeyRenamer(patternKeys ...string) (KeyRenamer, error) {
-       var renames []keyRename
-       for i := 0; i < len(patternKeys); i += 2 {
-               g, err := glob.Compile(strings.ToLower(patternKeys[i]), '/')
-               if err != nil {
-                       return KeyRenamer{}, err
-               }
-               renames = append(renames, keyRename{pattern: g, newKey: patternKeys[i+1]})
-       }
-
-       return KeyRenamer{renames: renames}, nil
-}
-
-func (r KeyRenamer) getNewKey(keyPath string) string {
-       for _, matcher := range r.renames {
-               if matcher.pattern.Match(keyPath) {
-                       return matcher.newKey
-               }
-       }
-
-       return ""
-}
-
-// Rename renames the keys in the given map according
-// to the patterns in the current KeyRenamer.
-func (r KeyRenamer) Rename(m map[string]any) {
-       r.renamePath("", m)
-}
-
-func (KeyRenamer) keyPath(k1, k2 string) string {
-       k1, k2 = strings.ToLower(k1), strings.ToLower(k2)
-       if k1 == "" {
-               return k2
-       }
-       return k1 + "/" + k2
-}
-
-func (r KeyRenamer) renamePath(parentKeyPath string, m map[string]any) {
-       for k, v := range m {
-               keyPath := r.keyPath(parentKeyPath, k)
-               switch vv := v.(type) {
-               case map[any]any:
-                       r.renamePath(keyPath, cast.ToStringMap(vv))
-               case map[string]any:
-                       r.renamePath(keyPath, vv)
-               }
-
-               newKey := r.getNewKey(keyPath)
-
-               if newKey != "" {
-                       delete(m, k)
-                       m[newKey] = v
-               }
-       }
-}
-
-// ConvertFloat64WithNoDecimalsToInt converts float64 values with no decimals to int recursively.
-func ConvertFloat64WithNoDecimalsToInt(m map[string]any) {
-       for k, v := range m {
-               switch vv := v.(type) {
-               case float64:
-                       if v == float64(int64(vv)) {
-                               m[k] = int64(vv)
-                       }
-               case map[string]any:
-                       ConvertFloat64WithNoDecimalsToInt(vv)
-               case []any:
-                       for i, vvv := range vv {
-                               switch vvvv := vvv.(type) {
-                               case float64:
-                                       if vvv == float64(int64(vvvv)) {
-                                               vv[i] = int64(vvvv)
-                                       }
-                               case map[string]any:
-                                       ConvertFloat64WithNoDecimalsToInt(vvvv)
-                               }
-                       }
-               }
-       }
-}
diff --git a/common/maps/maps_test.go b/common/maps/maps_test.go
deleted file mode 100644 (file)
index 40c8ac8..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2018 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 maps
-
-import (
-       "fmt"
-       "reflect"
-       "testing"
-
-       qt "github.com/frankban/quicktest"
-)
-
-func TestPrepareParams(t *testing.T) {
-       tests := []struct {
-               input    Params
-               expected Params
-       }{
-               {
-                       map[string]any{
-                               "abC": 32,
-                       },
-                       Params{
-                               "abc": 32,
-                       },
-               },
-               {
-                       map[string]any{
-                               "abC": 32,
-                               "deF": map[any]any{
-                                       23: "A value",
-                                       24: map[string]any{
-                                               "AbCDe": "A value",
-                                               "eFgHi": "Another value",
-                                       },
-                               },
-                               "gHi": map[string]any{
-                                       "J": 25,
-                               },
-                               "jKl": map[string]string{
-                                       "M": "26",
-                               },
-                       },
-                       Params{
-                               "abc": 32,
-                               "def": Params{
-                                       "23": "A value",
-                                       "24": Params{
-                                               "abcde": "A value",
-                                               "efghi": "Another value",
-                                       },
-                               },
-                               "ghi": Params{
-                                       "j": 25,
-                               },
-                               "jkl": Params{
-                                       "m": "26",
-                               },
-                       },
-               },
-       }
-
-       for i, test := range tests {
-               t.Run(fmt.Sprint(i), func(t *testing.T) {
-                       // PrepareParams modifies input.
-                       prepareClone := PrepareParamsClone(test.input)
-                       PrepareParams(test.input)
-                       if !reflect.DeepEqual(test.expected, test.input) {
-                               t.Errorf("[%d] Expected\n%#v, got\n%#v\n", i, test.expected, test.input)
-                       }
-                       if !reflect.DeepEqual(test.expected, prepareClone) {
-                               t.Errorf("[%d] Expected\n%#v, got\n%#v\n", i, test.expected, prepareClone)
-                       }
-               })
-       }
-}
-
-func TestToSliceStringMap(t *testing.T) {
-       c := qt.New(t)
-
-       tests := []struct {
-               input    any
-               expected []map[string]any
-       }{
-               {
-                       input: []map[string]any{
-                               {"abc": 123},
-                       },
-                       expected: []map[string]any{
-                               {"abc": 123},
-                       },
-               }, {
-                       input: []any{
-                               map[string]any{
-                                       "def": 456,
-                               },
-                       },
-                       expected: []map[string]any{
-                               {"def": 456},
-                       },
-               },
-       }
-
-       for _, test := range tests {
-               v, err := ToSliceStringMap(test.input)
-               c.Assert(err, qt.IsNil)
-               c.Assert(v, qt.DeepEquals, test.expected)
-       }
-}
-
-func TestToParamsAndPrepare(t *testing.T) {
-       c := qt.New(t)
-       _, err := ToParamsAndPrepare(map[string]any{"A": "av"})
-       c.Assert(err, qt.IsNil)
-
-       params, err := ToParamsAndPrepare(nil)
-       c.Assert(err, qt.IsNil)
-       c.Assert(params, qt.DeepEquals, Params{})
-}
-
-func TestRenameKeys(t *testing.T) {
-       c := qt.New(t)
-
-       m := map[string]any{
-               "a":    32,
-               "ren1": "m1",
-               "ren2": "m1_2",
-               "sub": map[string]any{
-                       "subsub": map[string]any{
-                               "REN1": "m2",
-                               "ren2": "m2_2",
-                       },
-               },
-               "no": map[string]any{
-                       "ren1": "m2",
-                       "ren2": "m2_2",
-               },
-       }
-
-       expected := map[string]any{
-               "a":    32,
-               "new1": "m1",
-               "new2": "m1_2",
-               "sub": map[string]any{
-                       "subsub": map[string]any{
-                               "new1": "m2",
-                               "ren2": "m2_2",
-                       },
-               },
-               "no": map[string]any{
-                       "ren1": "m2",
-                       "ren2": "m2_2",
-               },
-       }
-
-       renamer, err := NewKeyRenamer(
-               "{ren1,sub/*/ren1}", "new1",
-               "{Ren2,sub/ren2}", "new2",
-       )
-       c.Assert(err, qt.IsNil)
-
-       renamer.Rename(m)
-
-       if !reflect.DeepEqual(expected, m) {
-               t.Errorf("Expected\n%#v, got\n%#v\n", expected, m)
-       }
-}
-
-func TestLookupEqualFold(t *testing.T) {
-       c := qt.New(t)
-
-       m1 := map[string]any{
-               "a": "av",
-               "B": "bv",
-       }
-
-       v, k, found := LookupEqualFold(m1, "b")
-       c.Assert(found, qt.IsTrue)
-       c.Assert(v, qt.Equals, "bv")
-       c.Assert(k, qt.Equals, "B")
-
-       m2 := map[string]string{
-               "a": "av",
-               "B": "bv",
-       }
-
-       v, k, found = LookupEqualFold(m2, "b")
-       c.Assert(found, qt.IsTrue)
-       c.Assert(k, qt.Equals, "B")
-       c.Assert(v, qt.Equals, "bv")
-}
diff --git a/common/maps/ordered.go b/common/maps/ordered.go
deleted file mode 100644 (file)
index 0da9d23..0000000
+++ /dev/null
@@ -1,144 +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 maps
-
-import (
-       "slices"
-
-       "github.com/gohugoio/hugo/common/hashing"
-)
-
-// Ordered is a map that can be iterated in the order of insertion.
-// Note that insertion order is not affected if a key is re-inserted into the map.
-// In a nil map, all operations are no-ops.
-// This is not thread safe.
-type Ordered[K comparable, T any] struct {
-       // The keys in the order they were added.
-       keys []K
-       // The values.
-       values map[K]T
-}
-
-// NewOrdered creates a new Ordered map.
-func NewOrdered[K comparable, T any]() *Ordered[K, T] {
-       return &Ordered[K, T]{values: make(map[K]T)}
-}
-
-// Set sets the value for the given key.
-// Note that insertion order is not affected if a key is re-inserted into the map.
-func (m *Ordered[K, T]) Set(key K, value T) {
-       if m == nil {
-               return
-       }
-       // Check if key already exists.
-       if _, found := m.values[key]; !found {
-               m.keys = append(m.keys, key)
-       }
-       m.values[key] = value
-}
-
-// Get gets the value for the given key.
-func (m *Ordered[K, T]) Get(key K) (T, bool) {
-       if m == nil {
-               var v T
-               return v, false
-       }
-       value, found := m.values[key]
-       return value, found
-}
-
-// Has returns whether the given key exists in the map.
-func (m *Ordered[K, T]) Has(key K) bool {
-       if m == nil {
-               return false
-       }
-       _, found := m.values[key]
-       return found
-}
-
-// Delete deletes the value for the given key.
-func (m *Ordered[K, T]) Delete(key K) {
-       if m == nil {
-               return
-       }
-       delete(m.values, key)
-       for i, k := range m.keys {
-               if k == key {
-                       m.keys = slices.Delete(m.keys, i, i+1)
-                       break
-               }
-       }
-}
-
-// Clone creates a shallow copy of the map.
-func (m *Ordered[K, T]) Clone() *Ordered[K, T] {
-       if m == nil {
-               return nil
-       }
-       clone := NewOrdered[K, T]()
-       for _, k := range m.keys {
-               clone.Set(k, m.values[k])
-       }
-       return clone
-}
-
-// Keys returns the keys in the order they were added.
-func (m *Ordered[K, T]) Keys() []K {
-       if m == nil {
-               return nil
-       }
-       return m.keys
-}
-
-// Values returns the values in the order they were added.
-func (m *Ordered[K, T]) Values() []T {
-       if m == nil {
-               return nil
-       }
-       var values []T
-       for _, k := range m.keys {
-               values = append(values, m.values[k])
-       }
-       return values
-}
-
-// Len returns the number of items in the map.
-func (m *Ordered[K, T]) Len() int {
-       if m == nil {
-               return 0
-       }
-       return len(m.keys)
-}
-
-// Range calls f sequentially for each key and value present in the map.
-// If f returns false, range stops the iteration.
-// TODO(bep) replace with iter.Seq2 when we bump go Go 1.24.
-func (m *Ordered[K, T]) Range(f func(key K, value T) bool) {
-       if m == nil {
-               return
-       }
-       for _, k := range m.keys {
-               if !f(k, m.values[k]) {
-                       return
-               }
-       }
-}
-
-// Hash calculates a hash from the values.
-func (m *Ordered[K, T]) Hash() (uint64, error) {
-       if m == nil {
-               return 0, nil
-       }
-       return hashing.Hash(m.values)
-}
diff --git a/common/maps/ordered_test.go b/common/maps/ordered_test.go
deleted file mode 100644 (file)
index 65a8278..0000000
+++ /dev/null
@@ -1,99 +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 maps
-
-import (
-       "testing"
-
-       qt "github.com/frankban/quicktest"
-)
-
-func TestOrdered(t *testing.T) {
-       c := qt.New(t)
-
-       m := NewOrdered[string, int]()
-       m.Set("a", 1)
-       m.Set("b", 2)
-       m.Set("c", 3)
-
-       c.Assert(m.Keys(), qt.DeepEquals, []string{"a", "b", "c"})
-       c.Assert(m.Values(), qt.DeepEquals, []int{1, 2, 3})
-
-       v, found := m.Get("b")
-       c.Assert(found, qt.Equals, true)
-       c.Assert(v, qt.Equals, 2)
-
-       m.Set("b", 22)
-       c.Assert(m.Keys(), qt.DeepEquals, []string{"a", "b", "c"})
-       c.Assert(m.Values(), qt.DeepEquals, []int{1, 22, 3})
-
-       m.Delete("b")
-
-       c.Assert(m.Keys(), qt.DeepEquals, []string{"a", "c"})
-       c.Assert(m.Values(), qt.DeepEquals, []int{1, 3})
-}
-
-func TestOrderedHash(t *testing.T) {
-       c := qt.New(t)
-
-       m := NewOrdered[string, int]()
-       m.Set("a", 1)
-       m.Set("b", 2)
-       m.Set("c", 3)
-
-       h1, err := m.Hash()
-       c.Assert(err, qt.IsNil)
-
-       m.Set("d", 4)
-
-       h2, err := m.Hash()
-       c.Assert(err, qt.IsNil)
-
-       c.Assert(h1, qt.Not(qt.Equals), h2)
-
-       m = NewOrdered[string, int]()
-       m.Set("b", 2)
-       m.Set("a", 1)
-       m.Set("c", 3)
-
-       h3, err := m.Hash()
-       c.Assert(err, qt.IsNil)
-       // Order does not matter.
-       c.Assert(h1, qt.Equals, h3)
-}
-
-func TestOrderedNil(t *testing.T) {
-       c := qt.New(t)
-
-       var m *Ordered[string, int]
-
-       m.Set("a", 1)
-       c.Assert(m.Keys(), qt.IsNil)
-       c.Assert(m.Values(), qt.IsNil)
-       v, found := m.Get("a")
-       c.Assert(found, qt.Equals, false)
-       c.Assert(v, qt.Equals, 0)
-       m.Delete("a")
-       var b bool
-       m.Range(func(k string, v int) bool {
-               b = true
-               return true
-       })
-       c.Assert(b, qt.Equals, false)
-       c.Assert(m.Len(), qt.Equals, 0)
-       c.Assert(m.Clone(), qt.IsNil)
-       h, err := m.Hash()
-       c.Assert(err, qt.IsNil)
-       c.Assert(h, qt.Equals, uint64(0))
-}
diff --git a/common/maps/orderedintset.go b/common/maps/orderedintset.go
deleted file mode 100644 (file)
index ed9babb..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2025 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 maps
-
-import (
-       "fmt"
-       "slices"
-
-       "github.com/bits-and-blooms/bitset"
-)
-
-type OrderedIntSet struct {
-       keys   []int
-       values *bitset.BitSet
-}
-
-// NewOrderedIntSet creates a new OrderedIntSet.
-// Note that this is backed by https://github.com/bits-and-blooms/bitset
-func NewOrderedIntSet(vals ...int) *OrderedIntSet {
-       m := &OrderedIntSet{
-               keys:   make([]int, 0, len(vals)),
-               values: bitset.New(uint(len(vals))),
-       }
-       for _, v := range vals {
-               m.Set(v)
-       }
-       return m
-}
-
-// Set sets the value for the given key.
-// Note that insertion order is not affected if a key is re-inserted into the set.
-func (m *OrderedIntSet) Set(key int) {
-       if m == nil {
-               panic("nil OrderedIntSet")
-       }
-       keyu := uint(key)
-       if m.values.Test(keyu) {
-               return
-       }
-       m.values.Set(keyu)
-       m.keys = append(m.keys, key)
-}
-
-// SetFrom sets the values from another OrderedIntSet.
-func (m *OrderedIntSet) SetFrom(other *OrderedIntSet) {
-       if m == nil || other == nil {
-               return
-       }
-       for _, key := range other.keys {
-               m.Set(key)
-       }
-}
-
-func (m *OrderedIntSet) Clone() *OrderedIntSet {
-       if m == nil {
-               return nil
-       }
-       newSet := &OrderedIntSet{
-               keys:   slices.Clone(m.keys),
-               values: m.values.Clone(),
-       }
-       return newSet
-}
-
-// Next returns the next key in the set possibly including the given key.
-// It returns -1 if the key is not found or if there are no keys greater than the given key.
-func (m *OrderedIntSet) Next(i int) int {
-       n, ok := m.values.NextSet(uint(i))
-       if !ok {
-               return -1
-       }
-       return int(n)
-}
-
-// The reason we don't use iter.Seq is https://github.com/golang/go/issues/69015
-// This is 70% faster than using iter.Seq2[int, int] for the keys.
-// It returns false if the iteration was stopped early.
-func (m *OrderedIntSet) ForEachKey(yield func(int) bool) bool {
-       if m == nil {
-               return true
-       }
-       for _, key := range m.keys {
-               if !yield(key) {
-                       return false
-               }
-       }
-       return true
-}
-
-func (m *OrderedIntSet) Has(key int) bool {
-       if m == nil {
-               return false
-       }
-       return m.values.Test(uint(key))
-}
-
-func (m *OrderedIntSet) Len() int {
-       if m == nil {
-               return 0
-       }
-       return len(m.keys)
-}
-
-// KeysSorted returns the keys in sorted order.
-func (m *OrderedIntSet) KeysSorted() []int {
-       if m == nil {
-               return nil
-       }
-       keys := slices.Clone(m.keys)
-       slices.Sort(keys)
-       return m.keys
-}
-
-func (m *OrderedIntSet) String() string {
-       if m == nil {
-               return "[]"
-       }
-       return fmt.Sprintf("%v", m.keys)
-}
-
-func (m *OrderedIntSet) Values() *bitset.BitSet {
-       if m == nil {
-               return nil
-       }
-       return m.values
-}
-
-func (m *OrderedIntSet) IsSuperSet(other *OrderedIntSet) bool {
-       if m == nil || other == nil {
-               return false
-       }
-       return m.values.IsSuperSet(other.values)
-}
-
-// Words returns the bitset as array of 64-bit words, giving direct access to the internal representation.
-// It is not a copy, so changes to the returned slice will affect the bitset.
-// It is meant for advanced users.
-func (m *OrderedIntSet) Words() []uint64 {
-       if m == nil {
-               return nil
-       }
-       return m.values.Words()
-}
diff --git a/common/maps/orderedintset_test.go b/common/maps/orderedintset_test.go
deleted file mode 100644 (file)
index 2aab630..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2025 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 maps
-
-import (
-       "testing"
-
-       qt "github.com/frankban/quicktest"
-)
-
-func TestOrderedIntSet(t *testing.T) {
-       c := qt.New(t)
-
-       m := NewOrderedIntSet(2, 1, 3, 7)
-
-       c.Assert(m.Len(), qt.Equals, 4)
-       c.Assert(m.Has(1), qt.Equals, true)
-       c.Assert(m.Has(4), qt.Equals, false)
-       c.Assert(m.String(), qt.Equals, "[2 1 3 7]")
-       m.Set(4)
-       c.Assert(m.Len(), qt.Equals, 5)
-       c.Assert(m.Has(4), qt.Equals, true)
-       c.Assert(m.Next(0), qt.Equals, 1)
-       c.Assert(m.Next(1), qt.Equals, 1)
-       c.Assert(m.Next(2), qt.Equals, 2)
-       c.Assert(m.Next(3), qt.Equals, 3)
-       c.Assert(m.Next(4), qt.Equals, 4)
-       c.Assert(m.Next(7), qt.Equals, 7)
-       c.Assert(m.Next(8), qt.Equals, -1)
-       c.Assert(m.String(), qt.Equals, "[2 1 3 7 4]")
-
-       var nilset *OrderedIntSet
-       c.Assert(nilset.Len(), qt.Equals, 0)
-       c.Assert(nilset.Has(1), qt.Equals, false)
-       c.Assert(nilset.String(), qt.Equals, "[]")
-
-       var collected []int
-       m.ForEachKey(func(key int) bool {
-               collected = append(collected, key)
-               return true
-       })
-       c.Assert(collected, qt.DeepEquals, []int{2, 1, 3, 7, 4})
-}
-
-func BenchmarkOrderedIntSet(b *testing.B) {
-       smallSet := NewOrderedIntSet()
-       for i := range 8 {
-               smallSet.Set(i)
-       }
-       mediumSet := NewOrderedIntSet()
-       for i := range 64 {
-               mediumSet.Set(i)
-       }
-       largeSet := NewOrderedIntSet()
-       for i := range 1024 {
-               largeSet.Set(i)
-       }
-
-       b.Run("New", func(b *testing.B) {
-               for b.Loop() {
-                       NewOrderedIntSet(1, 2, 3, 4, 5, 6, 7, 8)
-               }
-       })
-
-       b.Run("Has small", func(b *testing.B) {
-               for i := 0; b.Loop(); i++ {
-                       smallSet.Has(i % 32)
-               }
-       })
-
-       b.Run("Has medium", func(b *testing.B) {
-               for i := 0; b.Loop(); i++ {
-                       mediumSet.Has(i % 32)
-               }
-       })
-
-       b.Run("Next", func(b *testing.B) {
-               for i := 0; b.Loop(); i++ {
-                       mediumSet.Next(i % 32)
-               }
-       })
-
-       b.Run("ForEachKey small", func(b *testing.B) {
-               for b.Loop() {
-                       smallSet.ForEachKey(func(key int) bool {
-                               return true
-                       })
-               }
-       })
-
-       b.Run("ForEachKey medium", func(b *testing.B) {
-               for b.Loop() {
-                       mediumSet.ForEachKey(func(key int) bool {
-                               return true
-                       })
-               }
-       })
-
-       b.Run("ForEachKey large", func(b *testing.B) {
-               for b.Loop() {
-                       largeSet.ForEachKey(func(key int) bool {
-                               return true
-                       })
-               }
-       })
-}
diff --git a/common/maps/params.go b/common/maps/params.go
deleted file mode 100644 (file)
index e69d13a..0000000
+++ /dev/null
@@ -1,473 +0,0 @@
-// Copyright 2019 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 maps
-
-import (
-       "errors"
-       "fmt"
-       "strings"
-
-       "github.com/spf13/cast"
-)
-
-// Params is a map where all keys are lower case.
-type Params map[string]any
-
-// KeyParams is an utility struct for the WalkParams method.
-type KeyParams struct {
-       Key    string
-       Params Params
-}
-
-// GetNested does a lower case and nested search in this map.
-// It will return nil if none found.
-// Make all of these methods internal somehow.
-func (p Params) GetNested(indices ...string) any {
-       v, _, _ := getNested(p, indices)
-       return v
-}
-
-// SetParams overwrites values in dst with values in src for common or new keys.
-// This is done recursively.
-func SetParams(dst, src Params) {
-       setParams(dst, src, 0)
-}
-
-func setParams(dst, src Params, depth int) {
-       const maxDepth = 1000
-       if depth > maxDepth {
-               panic(errors.New("max depth exceeded"))
-       }
-       for k, v := range src {
-               vv, found := dst[k]
-               if !found {
-                       dst[k] = v
-               } else {
-                       switch vvv := vv.(type) {
-                       case Params:
-                               if pv, ok := v.(Params); ok {
-                                       setParams(vvv, pv, depth+1)
-                               } else {
-                                       dst[k] = v
-                               }
-                       default:
-                               dst[k] = v
-                       }
-               }
-       }
-}
-
-// IsZero returns true if p is considered empty.
-func (p Params) IsZero() bool {
-       if len(p) == 0 {
-               return true
-       }
-
-       if len(p) > 1 {
-               return false
-       }
-
-       for k := range p {
-               return k == MergeStrategyKey
-       }
-
-       return false
-}
-
-// MergeParamsWithStrategy transfers values from src to dst for new keys using the merge strategy given.
-// This is done recursively.
-func MergeParamsWithStrategy(strategy string, dst, src Params) {
-       dst.merge(ParamsMergeStrategy(strategy), src)
-}
-
-// MergeParams transfers values from src to dst for new keys using the merge encoded in dst.
-// This is done recursively.
-func MergeParams(dst, src Params) {
-       ms, _ := dst.GetMergeStrategy()
-       dst.merge(ms, src)
-}
-
-func (p Params) merge(ps ParamsMergeStrategy, pp Params) {
-       ns, found := p.GetMergeStrategy()
-
-       ms := ns
-       if !found && ps != "" {
-               ms = ps
-       }
-
-       noUpdate := ms == ParamsMergeStrategyNone
-       noUpdate = noUpdate || (ps != "" && ps == ParamsMergeStrategyShallow)
-
-       for k, v := range pp {
-               if k == MergeStrategyKey {
-                       continue
-               }
-               vv, found := p[k]
-
-               if found {
-                       // Key matches, if both sides are Params, we try to merge.
-                       if vvv, ok := vv.(Params); ok {
-                               if pv, ok := v.(Params); ok {
-                                       vvv.merge(ms, pv)
-                               }
-                       }
-               } else if !noUpdate {
-                       p[k] = v
-               }
-
-       }
-}
-
-// For internal use.
-func (p Params) GetMergeStrategy() (ParamsMergeStrategy, bool) {
-       if v, found := p[MergeStrategyKey]; found {
-               if s, ok := v.(ParamsMergeStrategy); ok {
-                       return s, true
-               }
-       }
-       return ParamsMergeStrategyShallow, false
-}
-
-// For internal use.
-func (p Params) DeleteMergeStrategy() bool {
-       if _, found := p[MergeStrategyKey]; found {
-               delete(p, MergeStrategyKey)
-               return true
-       }
-       return false
-}
-
-// For internal use.
-func (p Params) SetMergeStrategy(s ParamsMergeStrategy) {
-       switch s {
-       case ParamsMergeStrategyDeep, ParamsMergeStrategyNone, ParamsMergeStrategyShallow:
-       default:
-               panic(fmt.Sprintf("invalid merge strategy %q", s))
-       }
-       p[MergeStrategyKey] = s
-}
-
-func getNested(m map[string]any, indices []string) (any, string, map[string]any) {
-       if len(indices) == 0 {
-               return nil, "", nil
-       }
-
-       first := indices[0]
-       v, found := m[strings.ToLower(cast.ToString(first))]
-       if !found {
-               if len(indices) == 1 {
-                       return nil, first, m
-               }
-               return nil, "", nil
-
-       }
-
-       if len(indices) == 1 {
-               return v, first, m
-       }
-
-       switch m2 := v.(type) {
-       case Params:
-               return getNested(m2, indices[1:])
-       case map[string]any:
-               return getNested(m2, indices[1:])
-       default:
-               return nil, "", nil
-       }
-}
-
-// CreateNestedParamsFromSegements creates empty nested maps for the given keySegments in the target map.
-func CreateNestedParamsFromSegements(target Params, keySegments ...string) Params {
-       if len(keySegments) == 0 {
-               return target
-       }
-
-       m := target
-       for i, key := range keySegments {
-               v, found := m[key]
-               if !found {
-                       nm := Params{}
-                       m[key] = nm
-                       m = nm
-                       if i == len(keySegments)-1 {
-                               return nm
-                       }
-                       continue
-               }
-               m = v.(Params)
-       }
-
-       return m
-}
-
-// CreateNestedParamsSepString creates empty nested maps for the given keyStr in the target map
-// It returns the last map created.
-func CreateNestedParamsSepString(keyStr, separator string, target Params) Params {
-       keySegments := strings.Split(keyStr, separator)
-       return CreateNestedParamsFromSegements(target, keySegments...)
-}
-
-// SetNestedParamIfNotSet sets the value for the given keyStr in the target map if it does not exist.
-// It assumes that all but the last key in keyStr is a Params map or should be one.
-func SetNestedParamIfNotSet(keyStr, separator string, value any, target Params) Params {
-       keySegments := strings.Split(keyStr, separator)
-       if len(keySegments) == 0 {
-               return target
-       }
-       base := keySegments[:len(keySegments)-1]
-       last := keySegments[len(keySegments)-1]
-
-       m := CreateNestedParamsFromSegements(target, base...)
-
-       if _, ok := m[last]; !ok {
-               m[last] = value
-       }
-
-       return target
-}
-
-// GetNestedParam gets the first match of the keyStr in the candidates given.
-// It will first try the exact match and then try to find it as a nested map value,
-// using the given separator, e.g. "mymap.name".
-// It assumes that all the maps given have lower cased keys.
-func GetNestedParam(keyStr, separator string, candidates ...Params) (any, error) {
-       keyStr = strings.ToLower(keyStr)
-
-       // Try exact match first
-       for _, m := range candidates {
-               if v, ok := m[keyStr]; ok {
-                       return v, nil
-               }
-       }
-
-       keySegments := strings.Split(keyStr, separator)
-       for _, m := range candidates {
-               if v := m.GetNested(keySegments...); v != nil {
-                       return v, nil
-               }
-       }
-
-       return nil, nil
-}
-
-func GetNestedParamFn(keyStr, separator string, lookupFn func(key string) any) (any, string, map[string]any, error) {
-       keySegments := strings.Split(keyStr, separator)
-       if len(keySegments) == 0 {
-               return nil, "", nil, nil
-       }
-
-       first := lookupFn(keySegments[0])
-       if first == nil {
-               return nil, "", nil, nil
-       }
-
-       if len(keySegments) == 1 {
-               return first, keySegments[0], nil, nil
-       }
-
-       switch m := first.(type) {
-       case map[string]any:
-               v, key, owner := getNested(m, keySegments[1:])
-               return v, key, owner, nil
-       case Params:
-               v, key, owner := getNested(m, keySegments[1:])
-               return v, key, owner, nil
-       }
-
-       return nil, "", nil, nil
-}
-
-// ParamsMergeStrategy tells what strategy to use in Params.Merge.
-type ParamsMergeStrategy string
-
-const (
-       // Do not merge.
-       ParamsMergeStrategyNone ParamsMergeStrategy = "none"
-       // Only add new keys.
-       ParamsMergeStrategyShallow ParamsMergeStrategy = "shallow"
-       // Add new keys, merge existing.
-       ParamsMergeStrategyDeep ParamsMergeStrategy = "deep"
-
-       MergeStrategyKey = "_merge"
-)
-
-// CleanConfigStringMapString removes any processing instructions from m,
-// m will never be modified.
-func CleanConfigStringMapString(m map[string]string) map[string]string {
-       if len(m) == 0 {
-               return m
-       }
-       if _, found := m[MergeStrategyKey]; !found {
-               return m
-       }
-       // Create a new map and copy all the keys except the merge strategy key.
-       m2 := make(map[string]string, len(m)-1)
-       for k, v := range m {
-               if k != MergeStrategyKey {
-                       m2[k] = v
-               }
-       }
-       return m2
-}
-
-// CleanConfigStringMap is the same as CleanConfigStringMapString but for
-// map[string]any.
-func CleanConfigStringMap(m map[string]any) map[string]any {
-       return doCleanConfigStringMap(m, 0)
-}
-
-func doCleanConfigStringMap(m map[string]any, depth int) map[string]any {
-       if len(m) == 0 {
-               return m
-       }
-       const maxDepth = 1000
-       if depth > maxDepth {
-               panic(errors.New("max depth exceeded"))
-       }
-       if _, found := m[MergeStrategyKey]; !found {
-               return m
-       }
-       // Create a new map and copy all the keys except the merge strategy key.
-       m2 := make(map[string]any, len(m)-1)
-       for k, v := range m {
-               if k != MergeStrategyKey {
-                       m2[k] = v
-               }
-               switch v2 := v.(type) {
-               case map[string]any:
-                       m2[k] = doCleanConfigStringMap(v2, depth+1)
-               case Params:
-                       var p Params = doCleanConfigStringMap(v2, depth+1)
-                       m2[k] = p
-               case map[string]string:
-                       m2[k] = CleanConfigStringMapString(v2)
-               }
-
-       }
-       return m2
-}
-
-func toMergeStrategy(v any) ParamsMergeStrategy {
-       s := ParamsMergeStrategy(cast.ToString(v))
-       switch s {
-       case ParamsMergeStrategyDeep, ParamsMergeStrategyNone, ParamsMergeStrategyShallow:
-               return s
-       default:
-               return ParamsMergeStrategyDeep
-       }
-}
-
-// PrepareParams
-// * makes all the keys in the given map lower cased and will do so recursively.
-// * This will modify the map given.
-// * Any nested map[interface{}]interface{}, map[string]interface{},map[string]string  will be converted to Params.
-// * Any _merge value will be converted to proper type and value.
-func PrepareParams(m Params) {
-       for k, v := range m {
-               var retyped bool
-               lKey := strings.ToLower(k)
-               if lKey == MergeStrategyKey {
-                       v = toMergeStrategy(v)
-                       retyped = true
-               } else {
-                       switch vv := v.(type) {
-                       case map[any]any:
-                               var p Params = cast.ToStringMap(v)
-                               v = p
-                               PrepareParams(p)
-                               retyped = true
-                       case map[string]any:
-                               var p Params = v.(map[string]any)
-                               v = p
-                               PrepareParams(p)
-                               retyped = true
-                       case map[string]string:
-                               p := make(Params)
-                               for k, v := range vv {
-                                       p[k] = v
-                               }
-                               v = p
-                               PrepareParams(p)
-                               retyped = true
-                       }
-               }
-
-               if retyped || k != lKey {
-                       delete(m, k)
-                       m[lKey] = v
-               }
-       }
-}
-
-// CloneParamsDeep does a deep clone of the given Params,
-// meaning that any nested Params will be cloned as well.
-func CloneParamsDeep(m Params) Params {
-       return cloneParamsDeep(m, 0)
-}
-
-func cloneParamsDeep(m Params, depth int) Params {
-       const maxDepth = 1000
-       if depth > maxDepth {
-               panic(errors.New("max depth exceeded"))
-       }
-       m2 := make(Params)
-       for k, v := range m {
-               switch vv := v.(type) {
-               case Params:
-                       m2[k] = cloneParamsDeep(vv, depth+1)
-               default:
-                       m2[k] = v
-               }
-       }
-       return m2
-}
-
-// PrepareParamsClone is like PrepareParams, but it does not modify the input.
-func PrepareParamsClone(m Params) Params {
-       m2 := make(Params)
-       for k, v := range m {
-               var retyped bool
-               lKey := strings.ToLower(k)
-               if lKey == MergeStrategyKey {
-                       v = toMergeStrategy(v)
-                       retyped = true
-               } else {
-                       switch vv := v.(type) {
-                       case map[any]any:
-                               var p Params = cast.ToStringMap(v)
-                               v = PrepareParamsClone(p)
-                               retyped = true
-                       case map[string]any:
-                               var p Params = v.(map[string]any)
-                               v = PrepareParamsClone(p)
-                               retyped = true
-                       case map[string]string:
-                               p := make(Params)
-                               for k, v := range vv {
-                                       p[k] = v
-                               }
-                               v = p
-                               PrepareParams(p)
-                               retyped = true
-                       }
-               }
-
-               if retyped || k != lKey {
-                       m2[lKey] = v
-               } else {
-                       m2[k] = v
-               }
-       }
-       return m2
-}
diff --git a/common/maps/params_test.go b/common/maps/params_test.go
deleted file mode 100644 (file)
index 4e27eae..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2019 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 maps
-
-import (
-       "testing"
-
-       qt "github.com/frankban/quicktest"
-)
-
-func TestGetNestedParam(t *testing.T) {
-       m := map[string]any{
-               "string":          "value",
-               "first":           1,
-               "with_underscore": 2,
-               "nested": map[string]any{
-                       "color": "blue",
-                       "nestednested": map[string]any{
-                               "color": "green",
-                       },
-               },
-       }
-
-       c := qt.New(t)
-
-       must := func(keyStr, separator string, candidates ...Params) any {
-               v, err := GetNestedParam(keyStr, separator, candidates...)
-               c.Assert(err, qt.IsNil)
-               return v
-       }
-
-       c.Assert(must("first", "_", m), qt.Equals, 1)
-       c.Assert(must("First", "_", m), qt.Equals, 1)
-       c.Assert(must("with_underscore", "_", m), qt.Equals, 2)
-       c.Assert(must("nested_color", "_", m), qt.Equals, "blue")
-       c.Assert(must("nested.nestednested.color", ".", m), qt.Equals, "green")
-       c.Assert(must("string.name", ".", m), qt.IsNil)
-       c.Assert(must("nested.foo", ".", m), qt.IsNil)
-}
-
-// https://github.com/gohugoio/hugo/issues/7903
-func TestGetNestedParamFnNestedNewKey(t *testing.T) {
-       c := qt.New(t)
-
-       nested := map[string]any{
-               "color": "blue",
-       }
-       m := map[string]any{
-               "nested": nested,
-       }
-
-       existing, nestedKey, owner, err := GetNestedParamFn("nested.new", ".", func(key string) any {
-               return m[key]
-       })
-
-       c.Assert(err, qt.IsNil)
-       c.Assert(existing, qt.IsNil)
-       c.Assert(nestedKey, qt.Equals, "new")
-       c.Assert(owner, qt.DeepEquals, nested)
-}
-
-func TestParamsSetAndMerge(t *testing.T) {
-       c := qt.New(t)
-
-       createParamsPair := func() (Params, Params) {
-               p1 := Params{"a": "av", "c": "cv", "nested": Params{"al2": "al2v", "cl2": "cl2v"}}
-               p2 := Params{"b": "bv", "a": "abv", "nested": Params{"bl2": "bl2v", "al2": "al2bv"}, MergeStrategyKey: ParamsMergeStrategyDeep}
-               return p1, p2
-       }
-
-       p1, p2 := createParamsPair()
-
-       SetParams(p1, p2)
-
-       c.Assert(p1, qt.DeepEquals, Params{
-               "a": "abv",
-               "c": "cv",
-               "nested": Params{
-                       "al2": "al2bv",
-                       "cl2": "cl2v",
-                       "bl2": "bl2v",
-               },
-               "b":              "bv",
-               MergeStrategyKey: ParamsMergeStrategyDeep,
-       })
-
-       p1, p2 = createParamsPair()
-
-       MergeParamsWithStrategy("", p1, p2)
-
-       // Default is to do a shallow merge.
-       c.Assert(p1, qt.DeepEquals, Params{
-               "c": "cv",
-               "nested": Params{
-                       "al2": "al2v",
-                       "cl2": "cl2v",
-               },
-               "b": "bv",
-               "a": "av",
-       })
-
-       p1, p2 = createParamsPair()
-       p1.SetMergeStrategy(ParamsMergeStrategyNone)
-       MergeParamsWithStrategy("", p1, p2)
-       p1.DeleteMergeStrategy()
-
-       c.Assert(p1, qt.DeepEquals, Params{
-               "a": "av",
-               "c": "cv",
-               "nested": Params{
-                       "al2": "al2v",
-                       "cl2": "cl2v",
-               },
-       })
-
-       p1, p2 = createParamsPair()
-       p1.SetMergeStrategy(ParamsMergeStrategyShallow)
-       MergeParamsWithStrategy("", p1, p2)
-       p1.DeleteMergeStrategy()
-
-       c.Assert(p1, qt.DeepEquals, Params{
-               "a": "av",
-               "c": "cv",
-               "nested": Params{
-                       "al2": "al2v",
-                       "cl2": "cl2v",
-               },
-               "b": "bv",
-       })
-
-       p1, p2 = createParamsPair()
-       p1.SetMergeStrategy(ParamsMergeStrategyDeep)
-       MergeParamsWithStrategy("", p1, p2)
-       p1.DeleteMergeStrategy()
-
-       c.Assert(p1, qt.DeepEquals, Params{
-               "nested": Params{
-                       "al2": "al2v",
-                       "cl2": "cl2v",
-                       "bl2": "bl2v",
-               },
-               "b": "bv",
-               "a": "av",
-               "c": "cv",
-       })
-}
-
-func TestParamsIsZero(t *testing.T) {
-       c := qt.New(t)
-
-       var nilParams Params
-
-       c.Assert(Params{}.IsZero(), qt.IsTrue)
-       c.Assert(nilParams.IsZero(), qt.IsTrue)
-       c.Assert(Params{"foo": "bar"}.IsZero(), qt.IsFalse)
-       c.Assert(Params{"_merge": "foo", "foo": "bar"}.IsZero(), qt.IsFalse)
-       c.Assert(Params{"_merge": "foo"}.IsZero(), qt.IsTrue)
-}
-
-func TestSetNestedParamIfNotSet(t *testing.T) {
-       c := qt.New(t)
-
-       m := Params{}
-
-       SetNestedParamIfNotSet("a.b.c", ".", "value", m)
-       c.Assert(m, qt.DeepEquals, Params{
-               "a": Params{
-                       "b": Params{
-                               "c": "value",
-                       },
-               },
-       })
-
-       m = Params{
-               "a": Params{
-                       "b": Params{
-                               "c": "existingValue",
-                       },
-               },
-       }
-
-       SetNestedParamIfNotSet("a.b.c", ".", "value", m)
-       c.Assert(m, qt.DeepEquals, Params{
-               "a": Params{
-                       "b": Params{
-                               "c": "existingValue",
-                       },
-               },
-       })
-}
index 8029b6cdaebb931421eaa071fdea7562825e562b..fbba141b86645c5057c30c6d399ac6da7ade3599 100644 (file)
@@ -21,7 +21,7 @@ import (
        "strings"
        "sync"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/types"
        "github.com/gohugoio/hugo/hugofs/files"
        "github.com/gohugoio/hugo/hugolib/sitesmatrix"
@@ -54,12 +54,12 @@ type PathParser struct {
 
        // Below gets created on demand.
        initOnce         sync.Once
-       sitesMatrixCache *maps.Cache[string, sitesmatrix.VectorStore] // Maps language index to sites matrix vector store.
+       sitesMatrixCache *hmaps.Cache[string, sitesmatrix.VectorStore] // Maps language index to sites matrix vector store.
 }
 
 func (pp *PathParser) init() {
        pp.initOnce.Do(func() {
-               pp.sitesMatrixCache = maps.NewCache[string, sitesmatrix.VectorStore]()
+               pp.sitesMatrixCache = hmaps.NewCache[string, sitesmatrix.VectorStore]()
        })
 }
 
index 118f57d695c1a4e284fd590dad641cb17fd1fe9c..ddfa70572c4de615aaf4c5f777df2c62ad5520c2 100644 (file)
@@ -29,10 +29,10 @@ import (
 
        "github.com/gohugoio/hugo/cache/filecache"
        "github.com/gohugoio/hugo/cache/httpcache"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hstrings"
        "github.com/gohugoio/hugo/common/hugo"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/common/urls"
        "github.com/gohugoio/hugo/config"
@@ -212,7 +212,7 @@ type Config struct {
 
        // User provided parameters.
        // <docsmeta>{"refs": ["config:languages:params"] }</docsmeta>
-       Params maps.Params `mapstructure:"-"`
+       Params hmaps.Params `mapstructure:"-"`
 
        // UglyURLs configuration. Either a boolean or a sections map.
        UglyURLs any `mapstructure:"-"`
@@ -1023,7 +1023,7 @@ func fromLoadConfigResult(fs afero.Fs, logger loggers.Logger, res config.LoadCon
                if lang == "" {
                        lang = "en"
                }
-               res.Cfg.Set("languages", maps.Params{lang: maps.Params{}})
+               res.Cfg.Set("languages", hmaps.Params{lang: hmaps.Params{}})
        }
        bcfg := res.BaseConfig
        cfg := res.Cfg
@@ -1050,11 +1050,11 @@ func fromLoadConfigResult(fs afero.Fs, logger loggers.Logger, res config.LoadCon
                var differentRootKeys []string
                switch x := v.(type) {
                case nil:
-               case maps.Params:
+               case hmaps.Params:
                        _, found := x["params"]
                        if !found {
-                               x["params"] = maps.Params{
-                                       maps.MergeStrategyKey: maps.ParamsMergeStrategyDeep,
+                               x["params"] = hmaps.Params{
+                                       hmaps.MergeStrategyKey: hmaps.ParamsMergeStrategyDeep,
                                }
                        }
                        for kk, vv := range x {
@@ -1066,16 +1066,16 @@ func fromLoadConfigResult(fs afero.Fs, logger loggers.Logger, res config.LoadCon
                                        isMultihost = true
                                }
 
-                               if p, ok := vv.(maps.Params); ok {
+                               if p, ok := vv.(hmaps.Params); ok {
                                        // With the introduction of YAML anchor and alias support, language config entries
                                        // may be contain shared references.
                                        // This also break potential cycles.
-                                       vv = maps.CloneParamsDeep(p)
+                                       vv = hmaps.CloneParamsDeep(p)
                                }
 
                                if kk == "cascade" {
                                        // If not set, add the current language to make sure it does not get applied to other languages.
-                                       page.AddLangToCascadeTargetMap(k, vv.(maps.Params))
+                                       page.AddLangToCascadeTargetMap(k, vv.(hmaps.Params))
                                        // Always clone cascade config to get the sites matrix right.
                                        differentRootKeys = append(differentRootKeys, kk)
                                }
@@ -1086,14 +1086,14 @@ func fromLoadConfigResult(fs afero.Fs, logger loggers.Logger, res config.LoadCon
                                        // This overrides a root key and potentially needs a merge.
                                        if !reflect.DeepEqual(rootv, vv) {
                                                switch vvv := vv.(type) {
-                                               case maps.Params:
+                                               case hmaps.Params:
                                                        differentRootKeys = append(differentRootKeys, kk)
 
                                                        // Use the language value as base.
                                                        // Note that this is already cloned above.
                                                        mergedConfigEntry := vvv
                                                        // Merge in the root value.
-                                                       maps.MergeParams(mergedConfigEntry, rootv.(maps.Params))
+                                                       hmaps.MergeParams(mergedConfigEntry, rootv.(hmaps.Params))
 
                                                        mergedConfig.Set(kk, mergedConfigEntry)
                                                default:
@@ -1103,7 +1103,7 @@ func fromLoadConfigResult(fs afero.Fs, logger loggers.Logger, res config.LoadCon
                                        }
                                } else {
                                        switch vv.(type) {
-                                       case maps.Params:
+                                       case hmaps.Params:
                                                differentRootKeys = append(differentRootKeys, kk)
                                        default:
                                                // Apply new values to the root.
@@ -1139,7 +1139,7 @@ func fromLoadConfigResult(fs afero.Fs, logger loggers.Logger, res config.LoadCon
                        }
 
                        langConfigMap[k] = clone
-               case maps.ParamsMergeStrategy:
+               case hmaps.ParamsMergeStrategy:
 
                default:
                        panic(fmt.Sprintf("unknown type in languages config: %T", v))
index 81e31aa6e86dc5eef84cf344cf437efab20ceccf..b7c55258ddaccb56eb53e82b55ecc27d423adc4c 100644 (file)
@@ -22,9 +22,9 @@ import (
        "github.com/gohugoio/hugo/langs"
 
        "github.com/gohugoio/hugo/cache/httpcache"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hstrings"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/types"
        "github.com/gohugoio/hugo/config"
        "github.com/gohugoio/hugo/config/privacy"
@@ -196,7 +196,7 @@ var allDecoderSetups = map[string]decodeWeight{
                key: "outputs",
                decode: func(d decodeWeight, p decodeConfig) error {
                        defaults := createDefaultOutputFormats(p.c.OutputFormats.Config)
-                       m := maps.CleanConfigStringMap(p.p.GetStringMap("outputs"))
+                       m := hmaps.CleanConfigStringMap(p.p.GetStringMap("outputs"))
                        p.c.Outputs = make(map[string][]string)
                        for k, v := range m {
                                s := types.ToStringSlicePreserveString(v)
@@ -225,13 +225,13 @@ var allDecoderSetups = map[string]decodeWeight{
        "languages": {
                key: "languages",
                decode: func(d decodeWeight, p decodeConfig) error {
-                       m := maps.CleanConfigStringMap(p.p.GetStringMap(d.key))
+                       m := hmaps.CleanConfigStringMap(p.p.GetStringMap(d.key))
                        if len(m) == 1 {
                                // In v0.112.4 we moved this to the language config, but it's very commmon for mono language sites to have this at the top level.
-                               var first maps.Params
+                               var first hmaps.Params
                                var ok bool
                                for _, v := range m {
-                                       first, ok = v.(maps.Params)
+                                       first, ok = v.(hmaps.Params)
                                        if ok {
                                                break
                                        }
@@ -266,7 +266,7 @@ var allDecoderSetups = map[string]decodeWeight{
                key: "versions",
                decode: func(d decodeWeight, p decodeConfig) error {
                        var err error
-                       m := maps.CleanConfigStringMap(p.p.GetStringMap(d.key))
+                       m := hmaps.CleanConfigStringMap(p.p.GetStringMap(d.key))
                        p.c.Versions, err = versions.DecodeConfig(p.c.RootConfig.DefaultContentVersion, m)
                        return err
                },
@@ -278,7 +278,7 @@ var allDecoderSetups = map[string]decodeWeight{
                                err                error
                                defaultContentRole string
                        )
-                       m := maps.CleanConfigStringMap(p.p.GetStringMap(d.key))
+                       m := hmaps.CleanConfigStringMap(p.p.GetStringMap(d.key))
                        p.c.Roles, defaultContentRole, err = roles.DecodeConfig(p.c.RootConfig.DefaultContentRole, m)
                        p.c.RootConfig.DefaultContentRole = defaultContentRole
 
@@ -289,7 +289,7 @@ var allDecoderSetups = map[string]decodeWeight{
        "params": {
                key: "params",
                decode: func(d decodeWeight, p decodeConfig) error {
-                       p.c.Params = maps.CleanConfigStringMap(p.p.GetStringMap("params"))
+                       p.c.Params = hmaps.CleanConfigStringMap(p.p.GetStringMap("params"))
                        if p.c.Params == nil {
                                p.c.Params = make(map[string]any)
                        }
@@ -335,7 +335,7 @@ var allDecoderSetups = map[string]decodeWeight{
                key: "taxonomies",
                decode: func(d decodeWeight, p decodeConfig) error {
                        if p.p.IsSet(d.key) {
-                               p.c.Taxonomies = maps.CleanConfigStringMapString(p.p.GetStringMapString(d.key))
+                               p.c.Taxonomies = hmaps.CleanConfigStringMapString(p.p.GetStringMapString(d.key))
                        }
                        return nil
                },
@@ -447,7 +447,7 @@ var allDecoderSetups = map[string]decodeWeight{
        "author": {
                key: "author",
                decode: func(d decodeWeight, p decodeConfig) error {
-                       p.c.Author = maps.CleanConfigStringMap(p.p.GetStringMap(d.key))
+                       p.c.Author = hmaps.CleanConfigStringMap(p.p.GetStringMap(d.key))
                        return nil
                },
                internalOrDeprecated: true,
@@ -455,7 +455,7 @@ var allDecoderSetups = map[string]decodeWeight{
        "social": {
                key: "social",
                decode: func(d decodeWeight, p decodeConfig) error {
-                       p.c.Social = maps.CleanConfigStringMapString(p.p.GetStringMapString(d.key))
+                       p.c.Social = hmaps.CleanConfigStringMapString(p.p.GetStringMapString(d.key))
                        return nil
                },
                internalOrDeprecated: true,
@@ -469,8 +469,8 @@ var allDecoderSetups = map[string]decodeWeight{
                                p.c.UglyURLs = vv
                        case string:
                                p.c.UglyURLs = vv == "true"
-                       case maps.Params:
-                               p.c.UglyURLs = cast.ToStringMapBool(maps.CleanConfigStringMap(vv))
+                       case hmaps.Params:
+                               p.c.UglyURLs = cast.ToStringMapBool(hmaps.CleanConfigStringMap(vv))
                        default:
                                p.c.UglyURLs = cast.ToStringMapBool(v)
                        }
index 1a5fb6153a013bfd056c50c08e2e347ee6fae834..deaf4b9e028cd699a95576272ea2e563486a58b3 100644 (file)
@@ -14,7 +14,7 @@
 package allconfig
 
 import (
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/config"
        "github.com/gohugoio/hugo/docshelper"
 )
@@ -27,12 +27,12 @@ func init() {
                        if v.internalOrDeprecated {
                                continue
                        }
-                       cfg.Set(configRoot, make(maps.Params))
+                       cfg.Set(configRoot, make(hmaps.Params))
                }
-               lang := maps.Params{
-                       "en": maps.Params{
-                               "menus":  maps.Params{},
-                               "params": maps.Params{},
+               lang := hmaps.Params{
+                       "en": hmaps.Params{
+                               "menus":  hmaps.Params{},
+                               "params": hmaps.Params{},
                        },
                }
                cfg.Set("languages", lang)
index ec6b71e05ed1f7eff7946d4c0374aa055073c457..1aa6a1281aaad85f5ee01a86daa2ae8e8921b2d1 100644 (file)
@@ -25,9 +25,9 @@ import (
        "github.com/gobwas/glob"
        "github.com/gohugoio/hugo/common/herrors"
        "github.com/gohugoio/hugo/common/hexec"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hugo"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/common/types"
        "github.com/gohugoio/hugo/config"
@@ -166,7 +166,7 @@ func (l configLoader) applyConfigAliases() error {
 }
 
 func (l configLoader) applyDefaultConfig() error {
-       defaultSettings := maps.Params{
+       defaultSettings := hmaps.Params{
                // These dirs are used early/before we build the config struct.
                "themesDir": "themes",
                "configDir": "config",
@@ -186,7 +186,7 @@ func (l configLoader) normalizeCfg(cfg config.Provider) error {
        } else if b, ok := cfg.Get("minify").(bool); ok {
                hugo.Deprecate("site config minify", "Use minify.minifyOutput instead.", "v0.150.0")
                if b {
-                       cfg.Set("minify", maps.Params{"minifyOutput": true})
+                       cfg.Set("minify", hmaps.Params{"minifyOutput": true})
                }
        }
 
@@ -240,7 +240,7 @@ func (l configLoader) applyOsEnvOverrides(environ []string) error {
        }
 
        for _, env := range hugoEnv {
-               existing, nestedKey, owner, err := maps.GetNestedParamFn(env.Key, delim, l.cfg.Get)
+               existing, nestedKey, owner, err := hmaps.GetNestedParamFn(env.Key, delim, l.cfg.Get)
                if err != nil {
                        return err
                }
@@ -547,7 +547,7 @@ func (l configLoader) loadConfig(configName string) (string, error) {
 }
 
 func (l configLoader) deleteMergeStrategies() (err error) {
-       l.cfg.WalkParams(func(params ...maps.KeyParams) bool {
+       l.cfg.WalkParams(func(params ...hmaps.KeyParams) bool {
                params[len(params)-1].Params.DeleteMergeStrategy()
                return false
        })
index 7b86334927a47ffd5f55ae3ee64f69a83ab2729f..49fc27fc6c97492d6ebc7f92330cad1696260d56 100644 (file)
@@ -20,11 +20,11 @@ import (
        "strings"
 
        "github.com/gohugoio/hugo/common/herrors"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/parser"
 
        "github.com/gohugoio/hugo/common/paths"
 
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/parser/metadecoders"
        "github.com/spf13/afero"
 )
@@ -222,11 +222,11 @@ func LoadConfigFromDir(sourceFs afero.Fs, configDir, environment string) (Provid
        return cfg, dirnames, nil
 }
 
-var keyAliases maps.KeyRenamer
+var keyAliases hmaps.KeyRenamer
 
 func init() {
        var err error
-       keyAliases, err = maps.NewKeyRenamer(
+       keyAliases, err = hmaps.NewKeyRenamer(
                // Before 0.53 we used singular for "menu".
                "{menu,languages/*/menu}", "menus",
        )
index 4e6878c1f8ed0ab0051edc79f85ff0443d147015..69efc595cd3520e601ad36017ea43a56b18a0eb9 100644 (file)
@@ -16,7 +16,7 @@ package config
 import (
        "time"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/common/types"
        "github.com/gohugoio/hugo/common/urls"
@@ -96,7 +96,7 @@ type Provider interface {
        GetString(key string) string
        GetInt(key string) int
        GetBool(key string) bool
-       GetParams(key string) maps.Params
+       GetParams(key string) hmaps.Params
        GetStringMap(key string) map[string]any
        GetStringMapString(key string) map[string]string
        GetStringSlice(key string) []string
@@ -104,9 +104,9 @@ type Provider interface {
        Set(key string, value any)
        Keys() []string
        Merge(key string, value any)
-       SetDefaults(params maps.Params)
+       SetDefaults(params hmaps.Params)
        SetDefaultMergeStrategy()
-       WalkParams(walkFn func(params ...maps.KeyParams) bool)
+       WalkParams(walkFn func(params ...hmaps.KeyParams) bool)
        IsSet(key string) bool
 }
 
index 8e0a294eb7f3959d615d3a75999cc66f262316c6..7e1e0adb0c59d3f12b3d3d8d0acbbbded974b0aa 100644 (file)
@@ -20,21 +20,20 @@ import (
        "strings"
        "sync"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/spf13/cast"
-
-       "github.com/gohugoio/hugo/common/maps"
 )
 
-// New creates a Provider backed by an empty maps.Params.
+// New creates a Provider backed by an empty hmaps.Params.
 func New() Provider {
        return &defaultConfigProvider{
-               root: make(maps.Params),
+               root: make(hmaps.Params),
        }
 }
 
 // NewFrom creates a Provider backed by params.
-func NewFrom(params maps.Params) Provider {
-       maps.PrepareParams(params)
+func NewFrom(params hmaps.Params) Provider {
+       hmaps.PrepareParams(params)
        return &defaultConfigProvider{
                root: params,
        }
@@ -44,7 +43,7 @@ func NewFrom(params maps.Params) Provider {
 // All methods are thread safe.
 type defaultConfigProvider struct {
        mu   sync.RWMutex
-       root maps.Params
+       root hmaps.Params
 
        keyCache sync.Map
 }
@@ -90,22 +89,22 @@ func (c *defaultConfigProvider) GetString(k string) string {
        return cast.ToString(v)
 }
 
-func (c *defaultConfigProvider) GetParams(k string) maps.Params {
+func (c *defaultConfigProvider) GetParams(k string) hmaps.Params {
        v := c.Get(k)
        if v == nil {
                return nil
        }
-       return v.(maps.Params)
+       return v.(hmaps.Params)
 }
 
 func (c *defaultConfigProvider) GetStringMap(k string) map[string]any {
        v := c.Get(k)
-       return maps.ToStringMap(v)
+       return hmaps.ToStringMap(v)
 }
 
 func (c *defaultConfigProvider) GetStringMapString(k string) map[string]string {
        v := c.Get(k)
-       return maps.ToStringMapString(v)
+       return hmaps.ToStringMapString(v)
 }
 
 func (c *defaultConfigProvider) GetStringSlice(k string) []string {
@@ -120,9 +119,9 @@ func (c *defaultConfigProvider) Set(k string, v any) {
        k = strings.ToLower(k)
 
        if k == "" {
-               if p, err := maps.ToParamsAndPrepare(v); err == nil {
+               if p, err := hmaps.ToParamsAndPrepare(v); err == nil {
                        // Set the values directly in root.
-                       maps.SetParams(c.root, p)
+                       hmaps.SetParams(c.root, p)
                } else {
                        c.root[k] = v
                }
@@ -132,7 +131,7 @@ func (c *defaultConfigProvider) Set(k string, v any) {
 
        switch vv := v.(type) {
        case map[string]any, map[any]any, map[string]string:
-               p := maps.MustToParamsAndPrepare(vv)
+               p := hmaps.MustToParamsAndPrepare(vv)
                v = p
        }
 
@@ -142,9 +141,9 @@ func (c *defaultConfigProvider) Set(k string, v any) {
        }
 
        if existing, found := m[key]; found {
-               if p1, ok := existing.(maps.Params); ok {
-                       if p2, ok := v.(maps.Params); ok {
-                               maps.SetParams(p1, p2)
+               if p1, ok := existing.(hmaps.Params); ok {
+                       if p2, ok := v.(hmaps.Params); ok {
+                               hmaps.SetParams(p1, p2)
                                return
                        }
                }
@@ -154,8 +153,8 @@ func (c *defaultConfigProvider) Set(k string, v any) {
 }
 
 // SetDefaults will set values from params if not already set.
-func (c *defaultConfigProvider) SetDefaults(params maps.Params) {
-       maps.PrepareParams(params)
+func (c *defaultConfigProvider) SetDefaults(params hmaps.Params) {
+       hmaps.PrepareParams(params)
        for k, v := range params {
                if _, found := c.root[k]; !found {
                        c.root[k] = v
@@ -170,28 +169,28 @@ func (c *defaultConfigProvider) Merge(k string, v any) {
 
        if k == "" {
                rs, f := c.root.GetMergeStrategy()
-               if f && rs == maps.ParamsMergeStrategyNone {
+               if f && rs == hmaps.ParamsMergeStrategyNone {
                        // The user has set a "no merge" strategy on this,
                        // nothing more to do.
                        return
                }
 
-               if p, err := maps.ToParamsAndPrepare(v); err == nil {
+               if p, err := hmaps.ToParamsAndPrepare(v); err == nil {
                        // As there may be keys in p not in root, we need to handle
                        // those as a special case.
                        var keysToDelete []string
                        for kk, vv := range p {
-                               if pp, ok := vv.(maps.Params); ok {
+                               if pp, ok := vv.(hmaps.Params); ok {
                                        if pppi, ok := c.root[kk]; ok {
-                                               ppp := pppi.(maps.Params)
-                                               maps.MergeParamsWithStrategy("", ppp, pp)
+                                               ppp := pppi.(hmaps.Params)
+                                               hmaps.MergeParamsWithStrategy("", ppp, pp)
                                        } else {
                                                // We need to use the default merge strategy for
                                                // this key.
-                                               np := make(maps.Params)
-                                               strategy := c.determineMergeStrategy(maps.KeyParams{Key: "", Params: c.root}, maps.KeyParams{Key: kk, Params: np})
+                                               np := make(hmaps.Params)
+                                               strategy := c.determineMergeStrategy(hmaps.KeyParams{Key: "", Params: c.root}, hmaps.KeyParams{Key: kk, Params: np})
                                                np.SetMergeStrategy(strategy)
-                                               maps.MergeParamsWithStrategy("", np, pp)
+                                               hmaps.MergeParamsWithStrategy("", np, pp)
                                                c.root[kk] = np
                                                if np.IsZero() {
                                                        // Just keep it until merge is done.
@@ -201,7 +200,7 @@ func (c *defaultConfigProvider) Merge(k string, v any) {
                                }
                        }
                        // Merge the rest.
-                       maps.MergeParams(c.root, p)
+                       hmaps.MergeParams(c.root, p)
                        for _, k := range keysToDelete {
                                delete(c.root, k)
                        }
@@ -214,7 +213,7 @@ func (c *defaultConfigProvider) Merge(k string, v any) {
 
        switch vv := v.(type) {
        case map[string]any, map[any]any, map[string]string:
-               p := maps.MustToParamsAndPrepare(vv)
+               p := hmaps.MustToParamsAndPrepare(vv)
                v = p
        }
 
@@ -224,9 +223,9 @@ func (c *defaultConfigProvider) Merge(k string, v any) {
        }
 
        if existing, found := m[key]; found {
-               if p1, ok := existing.(maps.Params); ok {
-                       if p2, ok := v.(maps.Params); ok {
-                               maps.MergeParamsWithStrategy("", p1, p2)
+               if p1, ok := existing.(hmaps.Params); ok {
+                       if p2, ok := v.(hmaps.Params); ok {
+                               hmaps.MergeParamsWithStrategy("", p1, p2)
                        }
                }
        } else {
@@ -245,10 +244,10 @@ func (c *defaultConfigProvider) Keys() []string {
        return keys
 }
 
-func (c *defaultConfigProvider) WalkParams(walkFn func(params ...maps.KeyParams) bool) {
+func (c *defaultConfigProvider) WalkParams(walkFn func(params ...hmaps.KeyParams) bool) {
        maxDepth := 1000
-       var walk func(depth int, params ...maps.KeyParams)
-       walk = func(depth int, params ...maps.KeyParams) {
+       var walk func(depth int, params ...hmaps.KeyParams)
+       walk = func(depth int, params ...hmaps.KeyParams) {
                if depth > maxDepth {
                        panic(errors.New("max depth exceeded"))
                }
@@ -258,24 +257,24 @@ func (c *defaultConfigProvider) WalkParams(walkFn func(params ...maps.KeyParams)
                p1 := params[len(params)-1]
                i := len(params)
                for k, v := range p1.Params {
-                       if p2, ok := v.(maps.Params); ok {
-                               paramsplus1 := make([]maps.KeyParams, i+1)
+                       if p2, ok := v.(hmaps.Params); ok {
+                               paramsplus1 := make([]hmaps.KeyParams, i+1)
                                copy(paramsplus1, params)
-                               paramsplus1[i] = maps.KeyParams{Key: k, Params: p2}
+                               paramsplus1[i] = hmaps.KeyParams{Key: k, Params: p2}
                                walk(depth+1, paramsplus1...)
                        }
                }
        }
-       walk(0, maps.KeyParams{Key: "", Params: c.root})
+       walk(0, hmaps.KeyParams{Key: "", Params: c.root})
 }
 
-func (c *defaultConfigProvider) determineMergeStrategy(params ...maps.KeyParams) maps.ParamsMergeStrategy {
+func (c *defaultConfigProvider) determineMergeStrategy(params ...hmaps.KeyParams) hmaps.ParamsMergeStrategy {
        if len(params) == 0 {
-               return maps.ParamsMergeStrategyNone
+               return hmaps.ParamsMergeStrategyNone
        }
 
        var (
-               strategy   maps.ParamsMergeStrategy
+               strategy   hmaps.ParamsMergeStrategy
                prevIsRoot bool
                curr       = params[len(params)-1]
        )
@@ -299,10 +298,10 @@ func (c *defaultConfigProvider) determineMergeStrategy(params ...maps.KeyParams)
        // Don't set a merge strategy on the root unless set by user.
        // This will be handled as a special case.
        case "params":
-               strategy = maps.ParamsMergeStrategyDeep
+               strategy = hmaps.ParamsMergeStrategyDeep
        case "outputformats", "mediatypes":
                if prevIsRoot {
-                       strategy = maps.ParamsMergeStrategyShallow
+                       strategy = hmaps.ParamsMergeStrategyShallow
                }
        case "menus":
                isMenuKey := prevIsRoot
@@ -314,11 +313,11 @@ func (c *defaultConfigProvider) determineMergeStrategy(params ...maps.KeyParams)
                        }
                }
                if isMenuKey {
-                       strategy = maps.ParamsMergeStrategyShallow
+                       strategy = hmaps.ParamsMergeStrategyShallow
                }
        default:
                if strategy == "" {
-                       strategy = maps.ParamsMergeStrategyNone
+                       strategy = hmaps.ParamsMergeStrategyNone
                }
        }
 
@@ -326,7 +325,7 @@ func (c *defaultConfigProvider) determineMergeStrategy(params ...maps.KeyParams)
 }
 
 func (c *defaultConfigProvider) SetDefaultMergeStrategy() {
-       c.WalkParams(func(params ...maps.KeyParams) bool {
+       c.WalkParams(func(params ...hmaps.KeyParams) bool {
                if len(params) == 0 {
                        return false
                }
@@ -344,7 +343,7 @@ func (c *defaultConfigProvider) SetDefaultMergeStrategy() {
        })
 }
 
-func (c *defaultConfigProvider) getNestedKeyAndMap(key string, create bool) (string, maps.Params) {
+func (c *defaultConfigProvider) getNestedKeyAndMap(key string, create bool) (string, hmaps.Params) {
        var parts []string
        v, ok := c.keyCache.Load(key)
        if ok {
@@ -358,14 +357,14 @@ func (c *defaultConfigProvider) getNestedKeyAndMap(key string, create bool) (str
                next, found := current[parts[i]]
                if !found {
                        if create {
-                               next = make(maps.Params)
+                               next = make(hmaps.Params)
                                current[parts[i]] = next
                        } else {
                                return "", nil
                        }
                }
                var ok bool
-               current, ok = next.(maps.Params)
+               current, ok = next.(hmaps.Params)
                if !ok {
                        // E.g. a string, not a map that we can store values in.
                        return "", nil
index a21d573ed5ef3182b3e5f14bd076cde1262407f0..7ab4185f8a9e5ceb14c72a3dcf9b70778db81060 100644 (file)
@@ -22,10 +22,9 @@ import (
        "strings"
        "testing"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/para"
 
-       "github.com/gohugoio/hugo/common/maps"
-
        qt "github.com/frankban/quicktest"
 )
 
@@ -48,7 +47,7 @@ func TestDefaultConfigProvider(t *testing.T) {
                c.Assert(cfg.Get(k), qt.Equals, v)
                c.Assert(cfg.GetInt(k), qt.Equals, v)
 
-               c.Assert(cfg.Get(""), qt.DeepEquals, maps.Params{
+               c.Assert(cfg.Get(""), qt.DeepEquals, hmaps.Params{
                        "foo": 42,
                })
        })
@@ -60,7 +59,7 @@ func TestDefaultConfigProvider(t *testing.T) {
                        "bar": "baz",
                })
 
-               c.Assert(cfg.Get("foo"), qt.DeepEquals, maps.Params{
+               c.Assert(cfg.Get("foo"), qt.DeepEquals, hmaps.Params{
                        "bar": "baz",
                })
 
@@ -76,14 +75,14 @@ func TestDefaultConfigProvider(t *testing.T) {
                })
                cfg.Set("a.c", "cv")
 
-               c.Assert(cfg.Get("a"), qt.DeepEquals, maps.Params{
+               c.Assert(cfg.Get("a"), qt.DeepEquals, hmaps.Params{
                        "b": "bv",
                        "c": "cv",
                })
                c.Assert(cfg.Get("a.c"), qt.Equals, "cv")
 
                cfg.Set("b.a", "av")
-               c.Assert(cfg.Get("b"), qt.DeepEquals, maps.Params{
+               c.Assert(cfg.Get("b"), qt.DeepEquals, hmaps.Params{
                        "a": "av",
                })
 
@@ -91,7 +90,7 @@ func TestDefaultConfigProvider(t *testing.T) {
                        "b": "bv",
                })
 
-               c.Assert(cfg.Get("b"), qt.DeepEquals, maps.Params{
+               c.Assert(cfg.Get("b"), qt.DeepEquals, hmaps.Params{
                        "a": "av",
                        "b": "bv",
                })
@@ -105,7 +104,7 @@ func TestDefaultConfigProvider(t *testing.T) {
                        "b": "bv2",
                })
 
-               c.Assert(cfg.Get(""), qt.DeepEquals, maps.Params{
+               c.Assert(cfg.Get(""), qt.DeepEquals, hmaps.Params{
                        "a": "av2",
                        "b": "bv2",
                })
@@ -118,7 +117,7 @@ func TestDefaultConfigProvider(t *testing.T) {
                        "b": "bv2",
                })
 
-               c.Assert(cfg.Get(""), qt.DeepEquals, maps.Params{
+               c.Assert(cfg.Get(""), qt.DeepEquals, hmaps.Params{
                        "a": "av",
                        "b": "bv2",
                })
@@ -137,7 +136,7 @@ func TestDefaultConfigProvider(t *testing.T) {
                        },
                })
 
-               c.Assert(cfg.Get("foo"), qt.DeepEquals, maps.Params{
+               c.Assert(cfg.Get("foo"), qt.DeepEquals, hmaps.Params{
                        "a": "av",
                        "b": "bv2",
                })
@@ -155,7 +154,7 @@ func TestDefaultConfigProvider(t *testing.T) {
                        "c": "cv2",
                })
 
-               c.Assert(cfg.Get("a"), qt.DeepEquals, maps.Params{
+               c.Assert(cfg.Get("a"), qt.DeepEquals, hmaps.Params{
                        "b": "bv",
                        "c": "cv2",
                })
@@ -169,7 +168,7 @@ func TestDefaultConfigProvider(t *testing.T) {
                        "b": "bv2",
                })
 
-               c.Assert(cfg.Get(""), qt.DeepEquals, maps.Params{
+               c.Assert(cfg.Get(""), qt.DeepEquals, hmaps.Params{
                        "a": "av",
                })
        })
@@ -192,11 +191,11 @@ func TestDefaultConfigProvider(t *testing.T) {
                        "e": "ev2",
                })
 
-               c.Assert(cfg.Get("a"), qt.DeepEquals, maps.Params{
+               c.Assert(cfg.Get("a"), qt.DeepEquals, hmaps.Params{
                        "e":      "ev2",
-                       "_merge": maps.ParamsMergeStrategyShallow,
+                       "_merge": hmaps.ParamsMergeStrategyShallow,
                        "b":      "bv",
-                       "c": maps.Params{
+                       "c": hmaps.Params{
                                "b": "bv",
                        },
                })
@@ -221,15 +220,15 @@ func TestDefaultConfigProvider(t *testing.T) {
                                "b": left,
                        })
 
-                       cfg.Merge("", maps.Params{
-                               "b": maps.Params{
+                       cfg.Merge("", hmaps.Params{
+                               "b": hmaps.Params{
                                        "c": "cv2",
                                        "d": "dv2",
                                },
                        })
 
-                       c.Assert(cfg.Get(""), qt.DeepEquals, maps.Params{
-                               "b": maps.Params{
+                       c.Assert(cfg.Get(""), qt.DeepEquals, hmaps.Params{
+                               "b": hmaps.Params{
                                        "c": "cv1",
                                        "d": "dv2",
                                },
@@ -267,8 +266,8 @@ func TestDefaultConfigProvider(t *testing.T) {
 
                                cfg.Merge("a", right)
 
-                               c.Assert(cfg.Get(""), qt.DeepEquals, maps.Params{
-                                       "a": maps.Params{
+                               c.Assert(cfg.Get(""), qt.DeepEquals, hmaps.Params{
+                                       "a": hmaps.Params{
                                                "b": "bv1",
                                                "c": "cv2",
                                        },
@@ -292,7 +291,7 @@ func TestDefaultConfigProvider(t *testing.T) {
                        },
                })
 
-               c.Assert(cfg.Get(""), qt.DeepEquals, maps.Params{
+               c.Assert(cfg.Get(""), qt.DeepEquals, hmaps.Params{
                        "b": "bv",
                })
        })
@@ -341,7 +340,7 @@ func TestDefaultConfigProvider(t *testing.T) {
                                        return err
                                }
 
-                               m := maps.Params{
+                               m := hmaps.Params{
                                        "new": 42,
                                }
 
@@ -371,8 +370,8 @@ func TestDefaultConfigProvider(t *testing.T) {
                cfg := New()
                k := "foo"
 
-               cfg.Set(k, maps.Params{k: true})
-               c.Assert(cfg.GetParams(k), qt.DeepEquals, maps.Params{
+               cfg.Set(k, hmaps.Params{k: true})
+               c.Assert(cfg.GetParams(k), qt.DeepEquals, hmaps.Params{
                        k: true,
                })
 
@@ -384,8 +383,8 @@ func TestDefaultConfigProvider(t *testing.T) {
                k := "foo"
                k2 := "bar"
 
-               cfg.Set(k, maps.Params{k: struct{}{}})
-               cfg.Set(k2, maps.Params{k2: struct{}{}})
+               cfg.Set(k, hmaps.Params{k: struct{}{}})
+               cfg.Set(k2, hmaps.Params{k2: struct{}{}})
 
                c.Assert(len(cfg.Keys()), qt.Equals, 2)
 
@@ -401,11 +400,11 @@ func TestDefaultConfigProvider(t *testing.T) {
        c.Run("WalkParams", func(c *qt.C) {
                cfg := New()
 
-               cfg.Set("x", maps.Params{})
-               cfg.Set("y", maps.Params{})
+               cfg.Set("x", hmaps.Params{})
+               cfg.Set("y", hmaps.Params{})
 
                var got []string
-               cfg.WalkParams(func(params ...maps.KeyParams) bool {
+               cfg.WalkParams(func(params ...hmaps.KeyParams) bool {
                        got = append(got, params[len(params)-1].Key)
                        return false
                })
@@ -417,7 +416,7 @@ func TestDefaultConfigProvider(t *testing.T) {
                c.Assert(got, qt.DeepEquals, want)
 
                cfg = New()
-               cfg.WalkParams(func(params ...maps.KeyParams) bool {
+               cfg.WalkParams(func(params ...hmaps.KeyParams) bool {
                        return true
                })
 
@@ -429,7 +428,7 @@ func TestDefaultConfigProvider(t *testing.T) {
        c.Run("SetDefaults", func(c *qt.C) {
                cfg := New()
 
-               cfg.SetDefaults(maps.Params{
+               cfg.SetDefaults(hmaps.Params{
                        "foo": "bar",
                        "bar": "baz",
                })
index f443523a4aec02a5c6d64e090e6f21d604ebdbb7..481302d26bcb431a9e690384948b3b2df04bb8cd 100644 (file)
@@ -18,7 +18,7 @@ import (
        "testing"
 
        qt "github.com/frankban/quicktest"
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/mitchellh/mapstructure"
 )
 
@@ -32,7 +32,7 @@ func TestNamespace(t *testing.T) {
                map[string]any{"foo": "bar"},
                func(v any) (*tstNsExt, any, error) {
                        t := &tstNsExt{}
-                       m, err := maps.ToStringMapE(v)
+                       m, err := hmaps.ToStringMapE(v)
                        if err != nil {
                                return nil, nil, err
                        }
index 596e0515d5b6f0defad996cc526912367496b0ff..20497b2b552af824c372044e13c1f7c2457b7276 100644 (file)
@@ -17,7 +17,7 @@ package testconfig
 import (
        _ "unsafe"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/config"
        "github.com/gohugoio/hugo/config/allconfig"
        "github.com/gohugoio/hugo/deps"
@@ -84,7 +84,7 @@ func GetTestConfigSectionFromStruct(section string, v any) config.AllProvider {
        if err != nil {
                panic(err)
        }
-       p := maps.Params{
+       p := hmaps.Params{
                section: config.FromTOMLConfigString(string(data)).Get(""),
        }
        cfg := config.NewFrom(p)
index 024b22ec83f57ac83eec84991abd4992563fac17..33b2240139349ddfe282fd0295f32454b8063c24 100644 (file)
@@ -28,8 +28,8 @@ import (
        "github.com/gohugoio/hugo/cache/dynacache"
        "github.com/gohugoio/hugo/cache/filecache"
        "github.com/gohugoio/hugo/common/hexec"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/types"
        "github.com/gohugoio/hugo/config"
        "github.com/gohugoio/hugo/config/allconfig"
@@ -173,8 +173,8 @@ func (d *Deps) Init() error {
                        d.BuildState.DeferredExecutionsGroupedByRenderingContext = make(map[tpl.RenderingContext]*DeferredExecutions)
                }
                d.BuildState.DeferredExecutions = &DeferredExecutions{
-                       Executions:              maps.NewCache[string, *tpl.DeferredExecution](),
-                       FilenamesWithPostPrefix: maps.NewCache[string, bool](),
+                       Executions:              hmaps.NewCache[string, *tpl.DeferredExecution](),
+                       FilenamesWithPostPrefix: hmaps.NewCache[string, bool](),
                }
        }
 
@@ -464,10 +464,10 @@ type Counters struct {
 type DeferredExecutions struct {
        // A set of filenames in /public that
        // contains a post-processing prefix.
-       FilenamesWithPostPrefix *maps.Cache[string, bool]
+       FilenamesWithPostPrefix *hmaps.Cache[string, bool]
 
        // Maps a placeholder to a deferred execution.
-       Executions *maps.Cache[string, *tpl.DeferredExecution]
+       Executions *hmaps.Cache[string, *tpl.DeferredExecution]
 }
 
 var _ identity.SignalRebuilder = (*BuildState)(nil)
@@ -480,8 +480,8 @@ func (b *BuildState) StartStageRender(stage tpl.RenderingContext) {
 func (b *BuildState) StopStageRender(stage tpl.RenderingContext) {
        b.DeferredExecutionsGroupedByRenderingContext[stage] = b.DeferredExecutions
        b.DeferredExecutions = &DeferredExecutions{
-               Executions:              maps.NewCache[string, *tpl.DeferredExecution](),
-               FilenamesWithPostPrefix: maps.NewCache[string, bool](),
+               Executions:              hmaps.NewCache[string, *tpl.DeferredExecution](),
+               FilenamesWithPostPrefix: hmaps.NewCache[string, bool](),
        }
 }
 
index 15d3ba2cb4e3fbe2710501ef11d9d1c39f9136b3..7a3597f177e84497716adde87743955e9a30a59d 100644 (file)
@@ -22,7 +22,7 @@ import (
 
        "github.com/gobwas/glob"
        "github.com/gobwas/glob/syntax"
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/identity"
 )
 
@@ -32,9 +32,9 @@ var (
        isWindows        = runtime.GOOS == "windows"
        defaultGlobCache = &pathGlobCache{
                isWindows: isWindows,
-               cache:     maps.NewCache[string, globErr](),
+               cache:     hmaps.NewCache[string, globErr](),
        }
-       dotGlobCache = maps.NewCache[string, globErr]()
+       dotGlobCache = hmaps.NewCache[string, globErr]()
 )
 
 type globErr struct {
@@ -47,7 +47,7 @@ type pathGlobCache struct {
        isWindows bool
 
        // Cache
-       cache *maps.Cache[string, globErr]
+       cache *hmaps.Cache[string, globErr]
 }
 
 // GetGlobDot returns a glob.Glob that matches the given pattern, using '.' as the path separator.
index 59470d6d0fc3580b4f860de9db7f789732dcac0c..77b89b54c14ab9dbeb06be0b14370f6a43d5ff45 100644 (file)
@@ -21,7 +21,7 @@ import (
 
        iofs "io/fs"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/config"
        "github.com/gohugoio/hugo/hugofs/hglob"
        "github.com/gohugoio/hugo/hugolib/sitesmatrix"
@@ -556,5 +556,5 @@ func TestRootMappingFileFilter(t *testing.T) {
 var testDims = sitesmatrix.NewTestingDimensions([]string{"en", "no"}, []string{"v1", "v2", "v3"}, []string{"admin", "editor", "viewer", "guest"})
 
 func sitesMatrixForLangs(langs ...int) *sitesmatrix.IntSets {
-       return sitesmatrix.NewIntSetsBuilder(testDims).WithSets(maps.NewOrderedIntSet(langs...), nil, nil).Build()
+       return sitesmatrix.NewIntSetsBuilder(testDims).WithSets(hmaps.NewOrderedIntSet(langs...), nil, nil).Build()
 }
index 91b3cd0a6a49ac04344f15c9b7ae3217bbb98371..18d92fa6982238b47555c11ffd5a1359e87efe8d 100644 (file)
@@ -20,11 +20,11 @@ import (
        "testing"
 
        "github.com/bep/logg"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/config"
        "github.com/gohugoio/hugo/config/allconfig"
 
        qt "github.com/frankban/quicktest"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/spf13/afero"
 )
 
@@ -53,8 +53,8 @@ title = "English Comments Title"
        enSite := b.H.Sites[0]
        b.Assert(enSite.Title(), qt.Equals, "English Title")
        b.Assert(enSite.Home().Title(), qt.Equals, "English Title")
-       b.Assert(enSite.Params(), qt.DeepEquals, maps.Params{
-               "comments": maps.Params{
+       b.Assert(enSite.Params(), qt.DeepEquals, hmaps.Params{
+               "comments": hmaps.Params{
                        "color": "blue",
                        "title": "English Comments Title",
                },
@@ -424,13 +424,13 @@ name = "menu-theme"
 
                got := b.H.Configs.Base
 
-               b.Assert(got.Params, qt.DeepEquals, maps.Params{
-                       "b": maps.Params{
+               b.Assert(got.Params, qt.DeepEquals, hmaps.Params{
+                       "b": hmaps.Params{
                                "b1": "b1 main",
-                               "c": maps.Params{
+                               "c": hmaps.Params{
                                        "bc1": "bc1 main",
                                        "bc2": "bc2 theme",
-                                       "d":   maps.Params{"bcd1": string("bcd1 theme")},
+                                       "d":   hmaps.Params{"bcd1": string("bcd1 theme")},
                                },
                                "b2": "b2 theme",
                        },
@@ -447,11 +447,11 @@ name = "menu-theme"
                got := b.H.Configs.Base.Params
 
                // Shallow merge, only add new keys to params.
-               b.Assert(got, qt.DeepEquals, maps.Params{
+               b.Assert(got, qt.DeepEquals, hmaps.Params{
                        "p1": "p1 main",
-                       "b": maps.Params{
+                       "b": hmaps.Params{
                                "b1": "b1 main",
-                               "c": maps.Params{
+                               "c": hmaps.Params{
                                        "bc1": "bc1 main",
                                },
                        },
@@ -468,7 +468,7 @@ name = "menu-theme"
 
                got := b.H.Configs.Base.Params
 
-               b.Assert(got, qt.DeepEquals, maps.Params{
+               b.Assert(got, qt.DeepEquals, hmaps.Params{
                        "p1": "p1 theme",
                })
        })
@@ -534,7 +534,7 @@ t3: {{ .Site.Params.t3 }}
 
        got := b.H.Configs.Base.Params
 
-       b.Assert(got, qt.DeepEquals, maps.Params{
+       b.Assert(got, qt.DeepEquals, hmaps.Params{
                "m1": "mv1",
                "m2": "mv2",
                "t1": "tv1",
index ea75bbd5c4475af45b3e13b12e0db71d31cbcd4f..15b2c58a9e9e6a475d632754f40df041556e0955 100644 (file)
@@ -26,6 +26,7 @@ import (
        "github.com/bep/logg"
        "github.com/gohugoio/go-radix"
        "github.com/gohugoio/hugo/cache/dynacache"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/loggers"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/common/predicate"
@@ -39,8 +40,6 @@ import (
        "github.com/gohugoio/hugo/output"
        "github.com/gohugoio/hugo/resources"
 
-       "github.com/gohugoio/hugo/common/maps"
-
        "github.com/gohugoio/hugo/resources/kinds"
        "github.com/gohugoio/hugo/resources/page"
        "github.com/gohugoio/hugo/resources/resource"
@@ -100,7 +99,7 @@ type pageMap struct {
        cacheContentPlain      *dynacache.Partition[string, *resources.StaleValue[contentPlainPlainWords]]
        contentTableOfContents *dynacache.Partition[string, *resources.StaleValue[contentTableOfContents]]
 
-       contentDataFileSeenItems *maps.Cache[string, map[uint64]bool]
+       contentDataFileSeenItems *hmaps.Cache[string, map[uint64]bool]
 
        cfg contentMapConfig
 }
@@ -710,7 +709,7 @@ func newPageMap(s *Site, mcache *dynacache.Cache, pageTrees *pageTrees) *pageMap
                cacheContentPlain:      dynacache.GetOrCreatePartition[string, *resources.StaleValue[contentPlainPlainWords]](mcache, fmt.Sprintf("/cont/pla/%s", languageVersionRole), dynacache.OptionsPartition{Weight: 70, ClearWhen: dynacache.ClearOnChange}),
                contentTableOfContents: dynacache.GetOrCreatePartition[string, *resources.StaleValue[contentTableOfContents]](mcache, fmt.Sprintf("/cont/toc/%s", languageVersionRole), dynacache.OptionsPartition{Weight: 70, ClearWhen: dynacache.ClearOnChange}),
 
-               contentDataFileSeenItems: maps.NewCache[string, map[uint64]bool](),
+               contentDataFileSeenItems: hmaps.NewCache[string, map[uint64]bool](),
 
                cfg: contentMapConfig{
                        lang:                 s.Lang(),
@@ -756,13 +755,13 @@ func newPageMap(s *Site, mcache *dynacache.Cache, pageTrees *pageTrees) *pageMap
 func newContentTreeTreverseIndex(init func(get func(key any) (contentNode, bool), set func(key any, val contentNode))) *contentTreeReverseIndex {
        return &contentTreeReverseIndex{
                initFn: init,
-               mm:     maps.NewCache[any, contentNode](),
+               mm:     hmaps.NewCache[any, contentNode](),
        }
 }
 
 type contentTreeReverseIndex struct {
        initFn func(get func(key any) (contentNode, bool), set func(key any, val contentNode))
-       mm     *maps.Cache[any, contentNode]
+       mm     *hmaps.Cache[any, contentNode]
 }
 
 func (c *contentTreeReverseIndex) Reset() {
index 7ba9ef5ab9b198e2b3997c6ab0afaa35f2310cea..e8c37084ce7b20c20b0091657e73d439fca8b79e 100644 (file)
@@ -22,7 +22,7 @@ import (
        "time"
 
        "github.com/gohugoio/go-radix"
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/common/types"
        "github.com/gohugoio/hugo/hugofs/files"
@@ -54,9 +54,9 @@ type allPagesAssembler struct {
        rwRoot *doctree.NodeShiftTreeWalker[contentNode] // walks resources.
 
        // Walking state.
-       seenTerms        *maps.Map[term, sitesmatrix.Vectors]
-       droppedPages     *maps.Map[*Site, []string] // e.g. drafts, expired, future.
-       seenRootSections *maps.Map[string, bool]
+       seenTerms        *hmaps.Map[term, sitesmatrix.Vectors]
+       droppedPages     *hmaps.Map[*Site, []string] // e.g. drafts, expired, future.
+       seenRootSections *hmaps.Map[string, bool]
        seenHome         bool // set before we fan out to multiple goroutines.
 }
 
@@ -75,7 +75,7 @@ func newAllPagesAssembler(
        pw := rw.Extend()
        pw.Tree = m.treePages
 
-       seenRootSections := maps.NewMap[string, bool]()
+       seenRootSections := hmaps.NewMap[string, bool]()
        seenRootSections.Set("", true) // home.
 
        return &allPagesAssembler{
@@ -83,8 +83,8 @@ func newAllPagesAssembler(
                h:                          h,
                m:                          m,
                assembleChanges:            assembleChanges,
-               seenTerms:                  maps.NewMap[term, sitesmatrix.Vectors](),
-               droppedPages:               maps.NewMap[*Site, []string](),
+               seenTerms:                  hmaps.NewMap[term, sitesmatrix.Vectors](),
+               droppedPages:               hmaps.NewMap[*Site, []string](),
                seenRootSections:           seenRootSections,
                assembleSectionsInParallel: true,
                pwRoot:                     pw,
index edd907ec2b955fd201d642244d1c70c94b069048..b64221e08dbad84dddbac24615d0e3bd53dc4344 100644 (file)
@@ -21,7 +21,7 @@ import (
 
        radix "github.com/gohugoio/go-radix"
        "github.com/gohugoio/hugo/common/collections"
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/hugolib/sitesmatrix"
 )
 
@@ -70,7 +70,7 @@ func (ctx *WalkContext[T]) Data() *SimpleThreadSafeTree[any] {
 
 func (ctx *WalkContext[T]) initDataRaw() {
        ctx.dataRawInit.Do(func() {
-               ctx.dataRaw = maps.NewCache[sitesmatrix.Vector, *SimpleThreadSafeTree[any]]()
+               ctx.dataRaw = hmaps.NewCache[sitesmatrix.Vector, *SimpleThreadSafeTree[any]]()
        })
 }
 
@@ -215,7 +215,7 @@ type WalkContext[T any] struct {
        data     *SimpleThreadSafeTree[any]
        dataInit sync.Once
 
-       dataRaw     *maps.Cache[sitesmatrix.Vector, *SimpleThreadSafeTree[any]]
+       dataRaw     *hmaps.Cache[sitesmatrix.Vector, *SimpleThreadSafeTree[any]]
        dataRawInit sync.Once
 
        eventHandlersMu sync.Mutex
index 32207325c44b9934189ed4ed54d9d855873f41c9..82601a8673e620c978e49271785720b08292f5ad 100644 (file)
@@ -38,10 +38,10 @@ import (
        "github.com/gohugoio/hugo/output"
        "github.com/gohugoio/hugo/parser/metadecoders"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hsync"
        "github.com/gohugoio/hugo/common/htime"
        "github.com/gohugoio/hugo/common/hugo"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/para"
        "github.com/gohugoio/hugo/common/terminal"
        "github.com/gohugoio/hugo/common/types"
@@ -95,11 +95,11 @@ type HugoSites struct {
        // Now the different page dimensions (e.g. language) are built-in to the page trees above.
        // But we sill need to support the overridden translationKey, but that should
        // be relatively rare and low volume.
-       translationKeyPages *maps.SliceCache[page.Page]
+       translationKeyPages *hmaps.SliceCache[page.Page]
 
        pageTrees                    *pageTrees
-       previousPageTreesWalkContext *doctree.WalkContext[contentNode]    // Set for rebuilds only.
-       previousSeenTerms            *maps.Map[term, sitesmatrix.Vectors] // Set for rebuilds only.
+       previousPageTreesWalkContext *doctree.WalkContext[contentNode]     // Set for rebuilds only.
+       previousSeenTerms            *hmaps.Map[term, sitesmatrix.Vectors] // Set for rebuilds only.
 
        printUnusedTemplatesInit sync.Once
        printPathWarningsInit    sync.Once
index 4f5b299dd47a97d7dd909fa3a4b31c96941bd6b9..ebc458e079f3edf416efee6774c1450342d88b1e 100644 (file)
@@ -26,8 +26,8 @@ import (
        "github.com/gohugoio/hugo/common/herrors"
        "github.com/gohugoio/hugo/common/hexec"
        "github.com/gohugoio/hugo/common/himage"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/types"
        "github.com/gohugoio/hugo/config"
        "github.com/gohugoio/hugo/config/allconfig"
@@ -858,12 +858,12 @@ func (s *IntegrationTestBuilder) initBuilder() error {
                }
 
                if s.Cfg.Running {
-                       flags.Set("internal", maps.Params{
+                       flags.Set("internal", hmaps.Params{
                                "running": s.Cfg.Running,
                                "watch":   s.Cfg.Running,
                        })
                } else if s.Cfg.Watching {
-                       flags.Set("internal", maps.Params{
+                       flags.Set("internal", hmaps.Params{
                                "watch": s.Cfg.Watching,
                        })
                }
index f1ed435e97cf67a313a6e51542d3c33b149be98b..0cca67bdb385a639697ffc1f1aae406fd733adc0 100644 (file)
@@ -29,9 +29,9 @@ import (
        "github.com/bep/logg"
 
        "github.com/gohugoio/hugo/common/herrors"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hugio"
        "github.com/gohugoio/hugo/common/hugo"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/predicate"
        "github.com/gohugoio/hugo/common/types/hstring"
        "github.com/gohugoio/hugo/helpers"
@@ -114,7 +114,7 @@ func (m *pageMeta) newCachedContent(s *Site) (*cachedContent, error) {
                StaleInfo:   m,
                pi:          m.pi,
                enableEmoji: s.conf.EnableEmoji,
-               scopes:      maps.NewCache[string, *cachedContentScope](),
+               scopes:      hmaps.NewCache[string, *cachedContentScope](),
        }
        var hasName predicate.P[string] = m.pi.shortcodeParseInfo.hasName
        c.hasShortcode.Store(&hasName)
@@ -136,7 +136,7 @@ type cachedContent struct {
        // Whether the content has a given shortcode name.
        hasShortcode atomic.Pointer[predicate.P[string]]
 
-       scopes *maps.Cache[string, *cachedContentScope]
+       scopes *hmaps.Cache[string, *cachedContentScope]
 }
 
 func (c *cachedContent) getOrCreateScope(scope string, pco *pageContentOutput) *cachedContentScope {
index 4da455de112cbd7f298db9bc1b83ba39cfa59994..3776cb3abdc729ae70376814aae95c4773f12bac 100644 (file)
@@ -15,13 +15,12 @@ package hugolib
 
 import (
        "fmt"
+       "maps"
        "path/filepath"
        "regexp"
        "strings"
        "time"
 
-       xmaps "maps"
-
        "github.com/bep/logg"
        "github.com/gobuffalo/flect"
        "github.com/gohugoio/hugo/hugofs"
@@ -36,10 +35,10 @@ import (
 
        "github.com/gohugoio/hugo/common/hashing"
        "github.com/gohugoio/hugo/common/hiter"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hugio"
        "github.com/gohugoio/hugo/common/hugo"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/config"
        "github.com/gohugoio/hugo/helpers"
@@ -373,7 +372,7 @@ func (s *Site) newPageMetaFromPageMetasource(ms *pageMetaSource) (*pageMeta, err
        m := &pageMeta{
                pageMetaSource: ms,
                pageConfig: &pagemeta.PageConfigLate{
-                       Params: make(maps.Params),
+                       Params: make(hmaps.Params),
                },
        }
        return m, nil
@@ -470,7 +469,7 @@ func (m *pageMeta) IsPage() bool {
        return m.Kind() == kinds.KindPage
 }
 
-func (m *pageMeta) Params() maps.Params {
+func (m *pageMeta) Params() hmaps.Params {
        return m.pageConfig.Params
 }
 
@@ -524,17 +523,17 @@ func (m *pageMeta) Weight() int {
 func (ps *pageState) setMetaPost(cascades *page.PageMatcherParamsConfigs) error {
        if ps.m.pageConfigSource.Frontmatter != nil {
                if ps.m.pageConfigSource.IsFromContentAdapter {
-                       ps.m.pageConfig.ContentAdapterData = xmaps.Clone(ps.m.pageConfigSource.Frontmatter)
+                       ps.m.pageConfig.ContentAdapterData = maps.Clone(ps.m.pageConfigSource.Frontmatter)
                } else {
-                       ps.m.pageConfig.Params = xmaps.Clone(ps.m.pageConfigSource.Frontmatter)
+                       ps.m.pageConfig.Params = maps.Clone(ps.m.pageConfigSource.Frontmatter)
                }
        }
 
        if ps.m.pageConfig.Params == nil {
-               ps.m.pageConfig.Params = make(maps.Params)
+               ps.m.pageConfig.Params = make(hmaps.Params)
        }
        if ps.m.pageConfigSource.IsFromContentAdapter && ps.m.pageConfig.ContentAdapterData == nil {
-               ps.m.pageConfig.ContentAdapterData = make(maps.Params)
+               ps.m.pageConfig.ContentAdapterData = make(hmaps.Params)
        }
 
        // Cascade defined on itself has higher priority than inherited ones.
@@ -660,7 +659,7 @@ params:
                loki := strings.ToLower(k)
 
                if loki == "params" {
-                       vv, err := maps.ToStringMapE(v)
+                       vv, err := hmaps.ToStringMapE(v)
                        if err != nil {
                                return err
                        }
@@ -753,7 +752,7 @@ params:
                        }
                        pcfg.Params[loki] = pcfg.Aliases
                case "sitemap":
-                       pcfg.Sitemap, err = config.DecodeSitemap(ps.s.conf.Sitemap, maps.ToStringMap(v))
+                       pcfg.Sitemap, err = config.DecodeSitemap(ps.s.conf.Sitemap, hmaps.ToStringMap(v))
                        if err != nil {
                                return fmt.Errorf("failed to decode sitemap config in front matter: %s", err)
                        }
@@ -771,7 +770,7 @@ params:
                        switch vv := v.(type) {
                        case []map[any]any:
                                for _, vvv := range vv {
-                                       resources = append(resources, maps.ToStringMap(vvv))
+                                       resources = append(resources, hmaps.ToStringMap(vvv))
                                }
                        case []map[string]any:
                                resources = append(resources, vv...)
@@ -779,7 +778,7 @@ params:
                                for _, vvv := range vv {
                                        switch vvvv := vvv.(type) {
                                        case map[any]any:
-                                               resources = append(resources, maps.ToStringMap(vvvv))
+                                               resources = append(resources, hmaps.ToStringMap(vvvv))
                                        case map[string]any:
                                                resources = append(resources, vvvv)
                                        }
index b6e9f6602cf1ea9d0291d8fca93d623e9e41fff5..3d0cb5ff78c79252893bc749ab24fdf25a6376e1 100644 (file)
@@ -22,7 +22,7 @@ import (
        "sync"
        "sync/atomic"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/text"
        "github.com/gohugoio/hugo/identity"
        "github.com/gohugoio/hugo/tpl/tplimpl"
@@ -67,7 +67,7 @@ func newPageContentOutput(po *pageOutput) (*pageContentOutput, error) {
        cp := &pageContentOutput{
                po:           po,
                renderHooks:  &renderHooks{},
-               otherOutputs: maps.NewCache[uint64, *pageContentOutput](),
+               otherOutputs: hmaps.NewCache[uint64, *pageContentOutput](),
        }
        return cp, nil
 }
@@ -83,7 +83,7 @@ type pageContentOutput struct {
 
        // Other pages involved in rendering of this page,
        // typically included with .RenderShortcodes.
-       otherOutputs *maps.Cache[uint64, *pageContentOutput]
+       otherOutputs *hmaps.Cache[uint64, *pageContentOutput]
 
        contentRenderedVersion uint32      // Incremented on reset.
        contentRendered        atomic.Bool // Set on content render.
index db2931503d4e3aeaf5d6b1dc4173ab5e23b3b3c8..c2214cdca14f85d16f23545fd463a4761a949d37 100644 (file)
@@ -20,8 +20,8 @@ import (
        "path/filepath"
 
        "github.com/gohugoio/hugo/common/hashing"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hstore"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/helpers"
        "github.com/gohugoio/hugo/hugofs"
@@ -65,7 +65,7 @@ type pagesFromDataTemplateContext struct {
 }
 
 func (p *pagesFromDataTemplateContext) toPathSitesMap(v any) (string, map[string]any, map[string]any, error) {
-       m, err := maps.ToStringMapE(v)
+       m, err := hmaps.ToStringMapE(v)
        if err != nil {
                return "", nil, nil, err
        }
@@ -75,7 +75,7 @@ func (p *pagesFromDataTemplateContext) toPathSitesMap(v any) (string, map[string
                return "", nil, nil, fmt.Errorf("invalid path %q", path)
        }
 
-       sites := maps.ToStringMap(m["sites"])
+       sites := hmaps.ToStringMap(m["sites"])
 
        return path, sites, m, nil
 }
@@ -161,7 +161,7 @@ func NewPagesFromTemplate(opts PagesFromTemplateOptions) *PagesFromTemplate {
                PagesFromTemplateOptions: opts,
                PagesFromTemplateDeps:    opts.DepsFromSite(opts.Site),
                buildState: &BuildState{
-                       sourceInfosCurrent: maps.NewCache[string, *sourceInfo](),
+                       sourceInfosCurrent: hmaps.NewCache[string, *sourceInfo](),
                },
                store: hstore.NewScratch(),
        }
@@ -231,8 +231,8 @@ type BuildState struct {
        NumPagesAdded     uint64
        NumResourcesAdded uint64
 
-       sourceInfosCurrent  *maps.Cache[string, *sourceInfo]
-       sourceInfosPrevious *maps.Cache[string, *sourceInfo]
+       sourceInfosCurrent  *hmaps.Cache[string, *sourceInfo]
+       sourceInfosPrevious *hmaps.Cache[string, *sourceInfo]
 }
 
 func (b *BuildState) hash(v any) uint64 {
@@ -304,7 +304,7 @@ func (b *BuildState) resolveDeletedPaths() {
 
 func (b *BuildState) PrepareNextBuild() {
        b.sourceInfosPrevious = b.sourceInfosCurrent
-       b.sourceInfosCurrent = maps.NewCache[string, *sourceInfo]()
+       b.sourceInfosCurrent = hmaps.NewCache[string, *sourceInfo]()
        b.StaleVersion = 0
        b.DeletedPaths = nil
        b.ChangedIdentities = nil
@@ -317,7 +317,7 @@ func (p PagesFromTemplate) CloneForSite(s page.Site) *PagesFromTemplate {
        p.PagesFromTemplateOptions.Site = s
        p.PagesFromTemplateDeps = p.PagesFromTemplateOptions.DepsFromSite(s)
        p.buildState = &BuildState{
-               sourceInfosCurrent: maps.NewCache[string, *sourceInfo](),
+               sourceInfosCurrent: hmaps.NewCache[string, *sourceInfo](),
        }
        return &p
 }
index 273811a53d791448e8cc2909ffea694582b66f67..382b8032b673575a1a45de9ffcb5ec0e85a26936 100644 (file)
@@ -18,9 +18,9 @@ import (
        "strings"
 
        "github.com/gobwas/glob"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hugo"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/predicate"
        "github.com/gohugoio/hugo/config"
        hglob "github.com/gohugoio/hugo/hugofs/hglob"
@@ -276,14 +276,14 @@ func getGlob(s string) (glob.Glob, error) {
 
 func DecodeSegments(in map[string]any, segmentsToRender []string, logger loggers.Logger) (*config.ConfigNamespace[map[string]SegmentConfig, *Segments], error) {
        buildConfig := func(in any) (*Segments, any, error) {
-               m, err := maps.ToStringMapE(in)
+               m, err := hmaps.ToStringMapE(in)
                if err != nil {
                        return nil, nil, err
                }
                if m == nil {
                        m = map[string]any{}
                }
-               m = maps.CleanConfigStringMap(m)
+               m = hmaps.CleanConfigStringMap(m)
 
                var segmentCfg map[string]SegmentConfig
                if err := mapstructure.WeakDecode(m, &segmentCfg); err != nil {
index 849d48dcccd93d70aa01b03c5af227f29cec0821..2f04bd4a8bdfa988b23447f362a603fd0e960b8c 100644 (file)
@@ -18,6 +18,7 @@ import (
        "errors"
        "fmt"
        "io"
+       "maps"
        "mime"
        "net/url"
        "os"
@@ -32,13 +33,13 @@ import (
        "github.com/bep/logg"
        "github.com/gohugoio/go-radix"
        "github.com/gohugoio/hugo/cache/dynacache"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hstore"
        "github.com/gohugoio/hugo/common/hsync"
        "github.com/gohugoio/hugo/common/htime"
        "github.com/gohugoio/hugo/common/hugio"
        "github.com/gohugoio/hugo/common/hugo"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/para"
        "github.com/gohugoio/hugo/common/types"
        "github.com/gohugoio/hugo/config"
@@ -55,8 +56,6 @@ import (
        "github.com/gohugoio/hugo/modules"
        "github.com/gohugoio/hugo/resources"
 
-       xmaps "maps"
-
        "github.com/gohugoio/hugo/tpl/tplimpl"
        "github.com/gohugoio/hugo/tpl/tplimplinit"
 
@@ -478,7 +477,7 @@ func newHugoSites(
                        dynacache.OptionsPartition{Weight: 10, ClearWhen: dynacache.ClearOnRebuild},
                ),
                cacheContentSource:      dynacache.GetOrCreatePartition[uint64, *resources.StaleValue[[]byte]](d.MemCache, "/cont/src", dynacache.OptionsPartition{Weight: 70, ClearWhen: dynacache.ClearOnChange}),
-               translationKeyPages:     maps.NewSliceCache[page.Page](),
+               translationKeyPages:     hmaps.NewSliceCache[page.Page](),
                currentSite:             first[0],
                skipRebuildForFilenames: make(map[string]bool),
                init:                    &hugoSitesInit{},
@@ -669,7 +668,7 @@ func (s *Site) Lastmod() time.Time {
 }
 
 // Returns the Params configured for this site.
-func (s *Site) Params() maps.Params {
+func (s *Site) Params() hmaps.Params {
        return s.conf.Params
 }
 
@@ -1140,7 +1139,7 @@ func (w *WhatChanged) Changes() []identity.Identity {
        if w == nil || w.ids == nil {
                return nil
        }
-       return slices.Collect(xmaps.Keys(w.ids))
+       return slices.Collect(maps.Keys(w.ids))
 }
 
 func (w *WhatChanged) Drain() []identity.Identity {
index 015efb6413fccc2f302ac1bedd307e24f2284fed..53a6f2782c2aa0c4830b2ed1eaef47d644b2a85a 100644 (file)
@@ -17,14 +17,14 @@ import (
        "cmp"
        "fmt"
        "iter"
-       xmaps "maps"
+       "maps"
        "slices"
        "sort"
        "sync"
 
        "github.com/gohugoio/hashstructure"
        "github.com/gohugoio/hugo/common/hashing"
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/predicate"
        "github.com/gohugoio/hugo/common/types"
        "github.com/gohugoio/hugo/hugofs/hglob"
@@ -250,7 +250,7 @@ func (s *vectorStoreMap) HasRole(i int) bool {
 func (s *vectorStoreMap) clone() *vectorStoreMap {
        c := *s
        c.h = &hashOnce{}
-       c.sets = xmaps.Clone(s.sets)
+       c.sets = maps.Clone(s.sets)
        return &c
 }
 
@@ -277,7 +277,7 @@ type ConfiguredDimensions struct {
        ConfiguredRoles     ConfiguredDimension
        CommonSitesMatrix   CommonSitestMatrix
 
-       singleVectorStoreCache *maps.Cache[Vector, *IntSets]
+       singleVectorStoreCache *hmaps.Cache[Vector, *IntSets]
 }
 
 func (c *ConfiguredDimensions) IsSingleVector() bool {
@@ -295,7 +295,7 @@ func (c *ConfiguredDimensions) GetOrCreateSingleVectorStore(vec Vector) *IntSets
 }
 
 func (c *ConfiguredDimensions) Init() error {
-       c.singleVectorStoreCache = maps.NewCache[Vector, *IntSets]()
+       c.singleVectorStoreCache = hmaps.NewCache[Vector, *IntSets]()
        b := NewIntSetsBuilder(c).WithDefaultsIfNotSet().Build()
        defaultVec := b.VectorSample()
        c.singleVectorStoreCache.Set(defaultVec, b)
@@ -339,9 +339,9 @@ func (c *ConfiguredDimensions) ResolveVector(names types.Strings3) Vector {
 // IntSets holds the ordered sets of integers for the dimensions,
 // which is used for fast membership testing of files, resources and pages.
 type IntSets struct {
-       languages *maps.OrderedIntSet `mapstructure:"-" json:"-"`
-       versions  *maps.OrderedIntSet `mapstructure:"-" json:"-"`
-       roles     *maps.OrderedIntSet `mapstructure:"-" json:"-"`
+       languages *hmaps.OrderedIntSet `mapstructure:"-" json:"-"`
+       versions  *hmaps.OrderedIntSet `mapstructure:"-" json:"-"`
+       roles     *hmaps.OrderedIntSet `mapstructure:"-" json:"-"`
 
        h *hashOnce
 }
@@ -592,7 +592,7 @@ func (s IntSets) shallowClone() *IntSets {
 // WithLanguageIndices replaces the current language set with a single language index.
 func (s *IntSets) WithLanguageIndices(i int) VectorStore {
        c := s.shallowClone()
-       c.languages = maps.NewOrderedIntSet(i)
+       c.languages = hmaps.NewOrderedIntSet(i)
        return c.init()
 }
 
@@ -615,22 +615,22 @@ func (s *IntSets) MustHash() uint64 {
 // setDefaultsIfNotSet applies default values to the IntSets if they are not already set.
 func (s *IntSets) setDefaultsIfNotSet(cfg *ConfiguredDimensions) {
        if s.languages == nil {
-               s.languages = maps.NewOrderedIntSet()
+               s.languages = hmaps.NewOrderedIntSet()
                s.languages.Set(cfg.ConfiguredLanguages.IndexDefault())
        }
        if s.versions == nil {
-               s.versions = maps.NewOrderedIntSet()
+               s.versions = hmaps.NewOrderedIntSet()
                s.versions.Set(cfg.ConfiguredVersions.IndexDefault())
        }
        if s.roles == nil {
-               s.roles = maps.NewOrderedIntSet()
+               s.roles = hmaps.NewOrderedIntSet()
                s.roles.Set(cfg.ConfiguredRoles.IndexDefault())
        }
 }
 
 func (s *IntSets) setDefaultsAndAllLAnguagesIfNotSet(cfg *ConfiguredDimensions) {
        if s.languages == nil {
-               s.languages = maps.NewOrderedIntSet()
+               s.languages = hmaps.NewOrderedIntSet()
                for i := range cfg.ConfiguredLanguages.ForEachIndex() {
                        s.languages.Set(i)
                }
@@ -640,19 +640,19 @@ func (s *IntSets) setDefaultsAndAllLAnguagesIfNotSet(cfg *ConfiguredDimensions)
 
 func (s *IntSets) setAllIfNotSet(cfg *ConfiguredDimensions) {
        if s.languages == nil {
-               s.languages = maps.NewOrderedIntSet()
+               s.languages = hmaps.NewOrderedIntSet()
                for i := range cfg.ConfiguredLanguages.ForEachIndex() {
                        s.languages.Set(i)
                }
        }
        if s.versions == nil {
-               s.versions = maps.NewOrderedIntSet()
+               s.versions = hmaps.NewOrderedIntSet()
                for i := range cfg.ConfiguredVersions.ForEachIndex() {
                        s.versions.Set(i)
                }
        }
        if s.roles == nil {
-               s.roles = maps.NewOrderedIntSet()
+               s.roles = hmaps.NewOrderedIntSet()
                for i := range cfg.ConfiguredRoles.ForEachIndex() {
                        s.roles.Set(i)
                }
@@ -696,20 +696,20 @@ func (s *IntSets) setDimensionsFromOtherIfNotSet(other VectorIterator) {
 func (s *IntSets) setValuesInNilSets(vec Vector, setLang, setVer, setRole bool) {
        if setLang {
                if s.languages == nil {
-                       s.languages = maps.NewOrderedIntSet()
+                       s.languages = hmaps.NewOrderedIntSet()
                }
                s.languages.Set(vec.Language())
        }
        if setVer {
                if s.versions == nil {
-                       s.versions = maps.NewOrderedIntSet()
+                       s.versions = hmaps.NewOrderedIntSet()
                }
                s.versions.Set(vec.Version())
        }
 
        if setRole {
                if s.roles == nil {
-                       s.roles = maps.NewOrderedIntSet()
+                       s.roles = hmaps.NewOrderedIntSet()
                }
                s.roles.Set(vec.Role())
        }
@@ -737,12 +737,12 @@ func (b *IntSetsBuilder) Build() *IntSets {
 }
 
 func (b *IntSetsBuilder) WithConfig(cfg IntSetsConfig) *IntSetsBuilder {
-       applyFilter := func(what string, values []string, matcher ConfiguredDimension) (*maps.OrderedIntSet, error) {
-               var result *maps.OrderedIntSet
+       applyFilter := func(what string, values []string, matcher ConfiguredDimension) (*hmaps.OrderedIntSet, error) {
+               var result *hmaps.OrderedIntSet
                if len(values) == 0 {
 
                        if cfg.ApplyDefaults > 0 {
-                               result = maps.NewOrderedIntSet()
+                               result = hmaps.NewOrderedIntSet()
                        }
                        switch cfg.ApplyDefaults {
                        case IntSetsConfigApplyDefaultsIfNotSet:
@@ -772,7 +772,7 @@ func (b *IntSetsBuilder) WithConfig(cfg IntSetsConfig) *IntSetsBuilder {
                        }
                        for i := range iter {
                                if result == nil {
-                                       result = maps.NewOrderedIntSet()
+                                       result = hmaps.NewOrderedIntSet()
                                }
                                result.Set(i)
                        }
@@ -807,7 +807,7 @@ func (s *IntSetsBuilder) WithLanguageIndices(idxs ...int) *IntSetsBuilder {
                return s
        }
        if s.s.languages == nil {
-               s.s.languages = maps.NewOrderedIntSet()
+               s.s.languages = hmaps.NewOrderedIntSet()
        }
        for _, i := range idxs {
                s.s.languages.Set(i)
@@ -835,7 +835,7 @@ func (s *IntSetsBuilder) WithDimensionsFromOtherIfNotSet(other VectorIterator) *
        return s
 }
 
-func (b *IntSetsBuilder) WithSets(languages, versions, roles *maps.OrderedIntSet) *IntSetsBuilder {
+func (b *IntSetsBuilder) WithSets(languages, versions, roles *hmaps.OrderedIntSet) *IntSetsBuilder {
        b.s.languages = languages
        b.s.versions = versions
        b.s.roles = roles
@@ -867,17 +867,17 @@ func (s *Sites) Equal(other Sites) bool {
        return s.Matrix.Equal(other.Matrix) && s.Complements.Equal(other.Complements)
 }
 
-func (s *Sites) SetFromParamsIfNotSet(params maps.Params) {
+func (s *Sites) SetFromParamsIfNotSet(params hmaps.Params) {
        const (
                matrixKey      = "matrix"
                complementsKey = "complements"
        )
 
        if m, ok := params[matrixKey]; ok {
-               s.Matrix.SetFromParamsIfNotSet(m.(maps.Params))
+               s.Matrix.SetFromParamsIfNotSet(m.(hmaps.Params))
        }
        if f, ok := params[complementsKey]; ok {
-               s.Complements.SetFromParamsIfNotSet(f.(maps.Params))
+               s.Complements.SetFromParamsIfNotSet(f.(hmaps.Params))
        }
 }
 
@@ -899,7 +899,7 @@ func (d StringSlices) Equal(other StringSlices) bool {
                slices.Equal(d.Roles, other.Roles)
 }
 
-func (d *StringSlices) SetFromParamsIfNotSet(params maps.Params) {
+func (d *StringSlices) SetFromParamsIfNotSet(params hmaps.Params) {
        const (
                languagesKey = "languages"
                versionsKey  = "versions"
index 3f5bd5905e0bd19b0fe2c32495a497fc73e9ab78..c6919a7b382ed65257ad4349b65ed852c5dae1ea 100644 (file)
@@ -18,7 +18,7 @@ import (
 
        qt "github.com/frankban/quicktest"
        "github.com/gohugoio/hugo/common/hashing"
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/hugolib/sitesmatrix"
 )
 
@@ -31,27 +31,27 @@ func TestIntSets(t *testing.T) {
        testDims := newTestDims()
 
        sets := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-               maps.NewOrderedIntSet(1, 2),
-               maps.NewOrderedIntSet(1, 2, 3),
-               maps.NewOrderedIntSet(1, 2, 3),
+               hmaps.NewOrderedIntSet(1, 2),
+               hmaps.NewOrderedIntSet(1, 2, 3),
+               hmaps.NewOrderedIntSet(1, 2, 3),
        ).Build()
 
        sets2 := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-               maps.NewOrderedIntSet(1, 2),
-               maps.NewOrderedIntSet(1, 2, 3),
-               maps.NewOrderedIntSet(1, 2, 4),
+               hmaps.NewOrderedIntSet(1, 2),
+               hmaps.NewOrderedIntSet(1, 2, 3),
+               hmaps.NewOrderedIntSet(1, 2, 4),
        ).Build()
 
        sets3 := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-               maps.NewOrderedIntSet(2, 1),
-               maps.NewOrderedIntSet(1, 2, 3),
-               maps.NewOrderedIntSet(2, 1, 4),
+               hmaps.NewOrderedIntSet(2, 1),
+               hmaps.NewOrderedIntSet(1, 2, 3),
+               hmaps.NewOrderedIntSet(2, 1, 4),
        ).Build()
 
        sets4 := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-               maps.NewOrderedIntSet(3, 4, 5),
-               maps.NewOrderedIntSet(3, 4, 5),
-               maps.NewOrderedIntSet(3, 4, 5),
+               hmaps.NewOrderedIntSet(3, 4, 5),
+               hmaps.NewOrderedIntSet(3, 4, 5),
+               hmaps.NewOrderedIntSet(3, 4, 5),
        ).Build()
 
        c.Assert(hashing.HashStringHex(sets), qt.Equals, "790f6004619934ff")
@@ -68,24 +68,24 @@ func TestIntSets(t *testing.T) {
        c.Assert(sets.EqualsVector(sets), qt.Equals, true)
        c.Assert(sets.EqualsVector(
                sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-                       maps.NewOrderedIntSet(1, 2),
-                       maps.NewOrderedIntSet(1, 2, 3),
-                       maps.NewOrderedIntSet(1, 2, 3),
+                       hmaps.NewOrderedIntSet(1, 2),
+                       hmaps.NewOrderedIntSet(1, 2, 3),
+                       hmaps.NewOrderedIntSet(1, 2, 3),
                ).Build(),
        ), qt.Equals, true)
        c.Assert(sets.EqualsVector(
                sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-                       maps.NewOrderedIntSet(1, 2, 3),
-                       maps.NewOrderedIntSet(1, 2, 3, 4),
-                       maps.NewOrderedIntSet(1, 2, 3, 4),
+                       hmaps.NewOrderedIntSet(1, 2, 3),
+                       hmaps.NewOrderedIntSet(1, 2, 3, 4),
+                       hmaps.NewOrderedIntSet(1, 2, 3, 4),
                ).Build(),
        ), qt.Equals, false)
 
        c.Assert(sets.EqualsVector(
                sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-                       maps.NewOrderedIntSet(1, 2),
-                       maps.NewOrderedIntSet(1, 2, 3),
-                       maps.NewOrderedIntSet(2, 3, 4),
+                       hmaps.NewOrderedIntSet(1, 2),
+                       hmaps.NewOrderedIntSet(1, 2, 3),
+                       hmaps.NewOrderedIntSet(2, 3, 4),
                ).Build(),
        ), qt.Equals, false)
 
@@ -126,17 +126,17 @@ func TestIntSetsComplement(t *testing.T) {
                testDims := newTestDims()
 
                self := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-                       maps.NewOrderedIntSet(test.left.v0...),
-                       maps.NewOrderedIntSet(test.left.v1...),
-                       maps.NewOrderedIntSet(test.left.v2...),
+                       hmaps.NewOrderedIntSet(test.left.v0...),
+                       hmaps.NewOrderedIntSet(test.left.v1...),
+                       hmaps.NewOrderedIntSet(test.left.v2...),
                ).Build()
 
                var input []sitesmatrix.VectorProvider
                for _, v := range test.input {
                        input = append(input, sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-                               maps.NewOrderedIntSet(v.v0...),
-                               maps.NewOrderedIntSet(v.v1...),
-                               maps.NewOrderedIntSet(v.v2...),
+                               hmaps.NewOrderedIntSet(v.v0...),
+                               hmaps.NewOrderedIntSet(v.v1...),
+                               hmaps.NewOrderedIntSet(v.v2...),
                        ).Build())
                }
 
@@ -262,15 +262,15 @@ func TestIntSetsComplementOfComplement(t *testing.T) {
        testDims := newTestDims()
 
        sets1 := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-               maps.NewOrderedIntSet(1),
-               maps.NewOrderedIntSet(1),
-               maps.NewOrderedIntSet(1),
+               hmaps.NewOrderedIntSet(1),
+               hmaps.NewOrderedIntSet(1),
+               hmaps.NewOrderedIntSet(1),
        ).Build()
 
        sets2 := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-               maps.NewOrderedIntSet(1, 2),
-               maps.NewOrderedIntSet(1),
-               maps.NewOrderedIntSet(1, 3),
+               hmaps.NewOrderedIntSet(1, 2),
+               hmaps.NewOrderedIntSet(1),
+               hmaps.NewOrderedIntSet(1, 3),
        ).Build()
 
        c1 := sets2.Complement(sets1)
@@ -296,27 +296,27 @@ func BenchmarkIntSetsComplement(b *testing.B) {
        testDims := newTestDims()
 
        sets1 := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-               maps.NewOrderedIntSet(1, 2, 3),
-               maps.NewOrderedIntSet(1, 2, 3),
-               maps.NewOrderedIntSet(1, 2, 3),
+               hmaps.NewOrderedIntSet(1, 2, 3),
+               hmaps.NewOrderedIntSet(1, 2, 3),
+               hmaps.NewOrderedIntSet(1, 2, 3),
        ).Build()
 
        sets1Copy := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-               maps.NewOrderedIntSet(1, 2, 3),
-               maps.NewOrderedIntSet(1, 2, 3),
-               maps.NewOrderedIntSet(1, 2, 3),
+               hmaps.NewOrderedIntSet(1, 2, 3),
+               hmaps.NewOrderedIntSet(1, 2, 3),
+               hmaps.NewOrderedIntSet(1, 2, 3),
        ).Build()
 
        sets2 := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-               maps.NewOrderedIntSet(1, 2, 3, 4),
-               maps.NewOrderedIntSet(1, 2, 3, 4),
-               maps.NewOrderedIntSet(1, 2, 3, 4, 6),
+               hmaps.NewOrderedIntSet(1, 2, 3, 4),
+               hmaps.NewOrderedIntSet(1, 2, 3, 4),
+               hmaps.NewOrderedIntSet(1, 2, 3, 4, 6),
        ).Build()
 
        setsLanguage1 := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-               maps.NewOrderedIntSet(1),
-               maps.NewOrderedIntSet(1),
-               maps.NewOrderedIntSet(1),
+               hmaps.NewOrderedIntSet(1),
+               hmaps.NewOrderedIntSet(1),
+               hmaps.NewOrderedIntSet(1),
        ).Build()
 
        b.ResetTimer()
@@ -361,21 +361,21 @@ func BenchmarkSets(b *testing.B) {
        testDims := newTestDims()
 
        sets1 := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-               maps.NewOrderedIntSet(1, 2),
-               maps.NewOrderedIntSet(1, 2, 3),
-               maps.NewOrderedIntSet(1, 2, 3),
+               hmaps.NewOrderedIntSet(1, 2),
+               hmaps.NewOrderedIntSet(1, 2, 3),
+               hmaps.NewOrderedIntSet(1, 2, 3),
        ).Build()
 
        sets1Copy := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-               maps.NewOrderedIntSet(1, 2),
-               maps.NewOrderedIntSet(1, 2, 3),
-               maps.NewOrderedIntSet(1, 2, 3),
+               hmaps.NewOrderedIntSet(1, 2),
+               hmaps.NewOrderedIntSet(1, 2, 3),
+               hmaps.NewOrderedIntSet(1, 2, 3),
        ).Build()
 
        sets2 := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-               maps.NewOrderedIntSet(1, 2, 3),
-               maps.NewOrderedIntSet(1, 2, 3, 4),
-               maps.NewOrderedIntSet(1, 2, 3, 4),
+               hmaps.NewOrderedIntSet(1, 2, 3),
+               hmaps.NewOrderedIntSet(1, 2, 3, 4),
+               hmaps.NewOrderedIntSet(1, 2, 3, 4),
        ).Build()
 
        v1 := sitesmatrix.Vector{1, 2, 3}
@@ -385,9 +385,9 @@ func BenchmarkSets(b *testing.B) {
        b.Run("Build", func(b *testing.B) {
                for b.Loop() {
                        _ = sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-                               maps.NewOrderedIntSet(1, 2),
-                               maps.NewOrderedIntSet(1, 2, 3),
-                               maps.NewOrderedIntSet(1, 2, 3),
+                               hmaps.NewOrderedIntSet(1, 2),
+                               hmaps.NewOrderedIntSet(1, 2, 3),
+                               hmaps.NewOrderedIntSet(1, 2, 3),
                        ).Build()
                }
        })
@@ -484,17 +484,17 @@ func TestVectorStoreMap(t *testing.T) {
 
        c.Run("Complement", func(c *qt.C) {
                v1 := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-                       maps.NewOrderedIntSet(1, 3),
-                       maps.NewOrderedIntSet(1),
-                       maps.NewOrderedIntSet(1, 3),
+                       hmaps.NewOrderedIntSet(1, 3),
+                       hmaps.NewOrderedIntSet(1),
+                       hmaps.NewOrderedIntSet(1, 3),
                ).Build()
 
                m := v1.ToVectorStoreMap()
 
                v2 := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-                       maps.NewOrderedIntSet(1, 2),
-                       maps.NewOrderedIntSet(1),
-                       maps.NewOrderedIntSet(1, 3),
+                       hmaps.NewOrderedIntSet(1, 2),
+                       hmaps.NewOrderedIntSet(1),
+                       hmaps.NewOrderedIntSet(1, 3),
                ).Build()
 
                complement := m.Complement(v2)
@@ -509,9 +509,9 @@ func TestVectorStoreMap(t *testing.T) {
 func BenchmarkHasAnyVectorSingle(b *testing.B) {
        testDims := newTestDims()
        set := sitesmatrix.NewIntSetsBuilder(testDims).WithSets(
-               maps.NewOrderedIntSet(0),
-               maps.NewOrderedIntSet(0),
-               maps.NewOrderedIntSet(0),
+               hmaps.NewOrderedIntSet(0),
+               hmaps.NewOrderedIntSet(0),
+               hmaps.NewOrderedIntSet(0),
        ).Build()
 
        v := sitesmatrix.Vector{0, 0, 0}
index 30180dece078c28a81568813bc640db55039bacb..fb60293343d8573485cda68be8d94277bc21029a 100644 (file)
@@ -16,14 +16,14 @@ package js
 import (
        "context"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/resources/resource"
 )
 
 // BatcherClient is used to do JS batch operations.
 type BatcherClient interface {
        New(id string) (Batcher, error)
-       Store() *maps.Cache[string, Batcher]
+       Store() *hmaps.Cache[string, Batcher]
 }
 
 // BatchPackage holds a group of JavaScript resources.
index 7f5d39855e6a73b764200c6086a9fdf1037f39ff..dd5eb194e97be169ca00df42ff3e86d03652962a 100644 (file)
@@ -31,9 +31,9 @@ import (
 
        "github.com/evanw/esbuild/pkg/api"
        "github.com/gohugoio/hugo/cache/dynacache"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hsync"
        "github.com/gohugoio/hugo/common/hugio"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/deps"
        "github.com/gohugoio/hugo/helpers"
@@ -74,8 +74,8 @@ func NewBatcherClient(deps *deps.Deps) (js.BatcherClient, error) {
                d:            deps,
                buildClient:  NewBuildClient(deps.BaseFs.Assets, deps.ResourceSpec),
                createClient: create.New(deps.ResourceSpec),
-               batcherStore: maps.NewCache[string, js.Batcher](),
-               bundlesStore: maps.NewCache[string, js.BatchPackage](),
+               batcherStore: hmaps.NewCache[string, js.Batcher](),
+               bundlesStore: hmaps.NewCache[string, js.BatchPackage](),
        }
 
        deps.BuildEndListeners.Add(func(...any) bool {
@@ -196,8 +196,8 @@ type BatcherClient struct {
        createClient *create.Client
        buildClient  *BuildClient
 
-       batcherStore *maps.Cache[string, js.Batcher]
-       bundlesStore *maps.Cache[string, js.BatchPackage]
+       batcherStore *hmaps.Cache[string, js.Batcher]
+       bundlesStore *hmaps.Cache[string, js.BatchPackage]
 }
 
 // New creates a new Batcher with the given ID.
@@ -279,7 +279,7 @@ func (c *BatcherClient) New(id string) (js.Batcher, error) {
        return b, nil
 }
 
-func (c *BatcherClient) Store() *maps.Cache[string, js.Batcher] {
+func (c *BatcherClient) Store() *hmaps.Cache[string, js.Batcher] {
        return c.batcherStore
 }
 
@@ -435,15 +435,15 @@ func (b *batcher) doBuild(ctx context.Context) (*Package, error) {
        }
 
        state := struct {
-               importResource        *maps.Cache[string, resource.Resource]
-               resultResource        *maps.Cache[string, resource.Resource]
-               importerImportContext *maps.Cache[string, importContext]
-               pathGroup             *maps.Cache[string, string]
+               importResource        *hmaps.Cache[string, resource.Resource]
+               resultResource        *hmaps.Cache[string, resource.Resource]
+               importerImportContext *hmaps.Cache[string, importContext]
+               pathGroup             *hmaps.Cache[string, string]
        }{
-               importResource:        maps.NewCache[string, resource.Resource](),
-               resultResource:        maps.NewCache[string, resource.Resource](),
-               importerImportContext: maps.NewCache[string, importContext](),
-               pathGroup:             maps.NewCache[string, string](),
+               importResource:        hmaps.NewCache[string, resource.Resource](),
+               resultResource:        hmaps.NewCache[string, resource.Resource](),
+               importerImportContext: hmaps.NewCache[string, importContext](),
+               pathGroup:             hmaps.NewCache[string, string](),
        }
 
        multihostBasePaths := b.client.d.ResourceSpec.MultihostTargetBasePaths
index 21f9e31cd9786f0617bf8aa01a0cd4957e6e192f..310fa305dee1b1435bf4a2d0c7b7f4f680f93f4e 100644 (file)
@@ -19,8 +19,8 @@ import (
        "path/filepath"
        "strings"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hugio"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/identity"
 
@@ -299,7 +299,7 @@ func (opts *Options) compile() (err error) {
 
        var defines map[string]string
        if opts.Defines != nil {
-               defines = maps.ToStringMapString(opts.Defines)
+               defines = hmaps.ToStringMapString(opts.Defines)
        }
 
        var drop api.Drop
index 18ad8a40a9059d5239524e82c536646c1a3bdb22..e66c72c7baeb7aa4b04e6d42b3cfd5194dd46b25 100644 (file)
@@ -18,16 +18,16 @@ import (
        "fmt"
        "os"
        "path/filepath"
+       "slices"
        "strings"
 
        "github.com/evanw/esbuild/pkg/api"
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/hugofs"
        "github.com/gohugoio/hugo/identity"
        "github.com/gohugoio/hugo/resources"
        "github.com/gohugoio/hugo/resources/resource"
        "github.com/spf13/afero"
-       "slices"
 )
 
 const (
@@ -132,12 +132,12 @@ func ResolveResource(impPath string, resourceGetter resource.ResourceGetter) (r
 }
 
 func newFSResolver(fs afero.Fs) *fsResolver {
-       return &fsResolver{fs: fs, resolved: maps.NewCache[string, *hugofs.FileMeta]()}
+       return &fsResolver{fs: fs, resolved: hmaps.NewCache[string, *hugofs.FileMeta]()}
 }
 
 type fsResolver struct {
        fs       afero.Fs
-       resolved *maps.Cache[string, *hugofs.FileMeta]
+       resolved *hmaps.Cache[string, *hugofs.FileMeta]
 }
 
 func (r *fsResolver) resolveComponent(impPath string) *hugofs.FileMeta {
index 5f9797de1ad32b67b25842d2a146801b679897cf..03f4a6ed8befdb3c7aa32ddf03fef1f9d8bb675c 100644 (file)
@@ -30,9 +30,9 @@ import (
 
        "github.com/bep/textandbinarywriter"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hstrings"
        "github.com/gohugoio/hugo/common/hugio"
-       "github.com/gohugoio/hugo/common/maps"
        "golang.org/x/sync/errgroup"
 
        "github.com/tetratelabs/wazero"
@@ -253,7 +253,7 @@ func (d *dispatcher[Q, R]) newCall(q Message[Q]) (*call[Q, R], error) {
        if err := q.init(); err != nil {
                return nil, err
        }
-       responseKinds := maps.NewMap[string, bool]()
+       responseKinds := hmaps.NewMap[string, bool]()
        for _, rk := range q.Header.ResponseKinds {
                responseKinds.Set(rk, true)
        }
@@ -424,7 +424,7 @@ func (d *dispatcher[Q, R]) pendingCall(id uint32) *call[Q, R] {
 type call[Q, R any] struct {
        request       Message[Q]
        response      Message[R]
-       responseKinds *maps.Map[string, bool]
+       responseKinds *hmaps.Map[string, bool]
        err           error
        donec         chan *call[Q, R]
 }
index 41f1898b25f26941873b264dec36215bf9b4ea99..24616e79e293709db8ff8cb2d55b6438500de4e9 100644 (file)
@@ -22,8 +22,8 @@ import (
        "golang.org/x/text/collate"
        "golang.org/x/text/language"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/htime"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/hugolib/sitesmatrix"
        "github.com/gohugoio/locales"
        translators "github.com/gohugoio/localescompressed"
@@ -54,7 +54,7 @@ type Language struct {
        isDefault bool
 
        // This is just an alias of Site.Params.
-       params maps.Params
+       params hmaps.Params
 }
 
 // Name is an alias for Lang.
@@ -114,7 +114,7 @@ var DeprecationFunc = func(item, alternative string, err bool) {}
 // Params returns the language params.
 // Note that this is the same as the Site.Params, but we keep it here for legacy reasons.
 // Deprecated: Use the site.Params instead.
-func (l *Language) Params() maps.Params {
+func (l *Language) Params() hmaps.Params {
        // TODO(bep) Remove this for now as it created a little too much noise. Need to think about this.
        // See https://github.com/gohugoio/hugo/issues/11025
        // DeprecationFunc(".Language.Params", paramsDeprecationWarning, false)
@@ -167,7 +167,7 @@ func (l Languages) AsIndexSet() map[string]int {
 // Internal access to unexported Language fields.
 // This construct is to prevent them from leaking to the templates.
 
-func SetParams(l *Language, params maps.Params) {
+func SetParams(l *Language, params hmaps.Params) {
        l.params = params
 }
 
index a35441affe1166ff6b1b7263b18ab0bda15969a9..2336b52aed5a4e59e7db29e65f6c577c5a081fa2 100644 (file)
@@ -31,9 +31,9 @@ import (
 
        "github.com/gohugoio/hugo/markup/markup_config"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hugio"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
 
        "github.com/gohugoio/hugo/markup/converter"
 
@@ -398,7 +398,7 @@ func TestConvertAttributes(t *testing.T) {
                        }
                        data, err := toml.Marshal(mconf)
                        c.Assert(err, qt.IsNil)
-                       m := maps.Params{
+                       m := hmaps.Params{
                                "markup": config.FromTOMLConfigString(string(data)).Get(""),
                        }
                        conf := testconfig.GetTestConfig(nil, config.NewFrom(m))
index dfa66a52fd3940a72418019c804028cd6d7698cd..d798790151c33b14843c1b5f991186654820a03f 100644 (file)
@@ -14,7 +14,7 @@
 package markup_config
 
 import (
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/config"
        "github.com/gohugoio/hugo/markup/asciidocext/asciidocext_config"
        "github.com/gohugoio/hugo/markup/goldmark/goldmark_config"
@@ -52,7 +52,7 @@ func Decode(cfg config.Provider) (conf Config, err error) {
        if m == nil {
                return
        }
-       m = maps.CleanConfigStringMap(m)
+       m = hmaps.CleanConfigStringMap(m)
 
        normalizeConfig(m)
 
@@ -73,9 +73,9 @@ func Decode(cfg config.Provider) (conf Config, err error) {
 }
 
 func normalizeConfig(m map[string]any) {
-       v, err := maps.GetNestedParam("goldmark.parser", ".", m)
+       v, err := hmaps.GetNestedParam("goldmark.parser", ".", m)
        if err == nil {
-               vm := maps.ToStringMap(v)
+               vm := hmaps.ToStringMap(v)
                // Changed from a bool in 0.81.0
                if vv, found := vm["attribute"]; found {
                        if vvb, ok := vv.(bool); ok {
@@ -87,9 +87,9 @@ func normalizeConfig(m map[string]any) {
        }
 
        // Handle changes to the Goldmark configuration.
-       v, err = maps.GetNestedParam("goldmark.extensions", ".", m)
+       v, err = hmaps.GetNestedParam("goldmark.extensions", ".", m)
        if err == nil {
-               vm := maps.ToStringMap(v)
+               vm := hmaps.ToStringMap(v)
 
                // We changed the typographer extension config from a bool to a struct in 0.112.0.
                migrateGoldmarkConfig(vm, "typographer", goldmark_config.Typographer{Disable: true})
index 6d3687a4fa4c022a99d83ae6d2e274eb9fa98e6d..40ed8621e253cc4b53706b55cb15b517182e9abc 100644 (file)
@@ -21,7 +21,7 @@ import (
        "sort"
        "strings"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/config"
 
@@ -180,7 +180,7 @@ func DecodeContentTypes(in map[string]any, types Types) (*config.ConfigNamespace
        buildConfig := func(v any) (ContentTypes, any, error) {
                var s map[string]ContentTypeConfig
                c := DefaultContentTypes
-               m, err := maps.ToStringMapE(v)
+               m, err := hmaps.ToStringMapE(v)
                if err != nil {
                        return c, nil, err
                }
@@ -188,7 +188,7 @@ func DecodeContentTypes(in map[string]any, types Types) (*config.ConfigNamespace
                        s = defaultContentTypesConfig
                } else {
                        s = make(map[string]ContentTypeConfig)
-                       m = maps.CleanConfigStringMap(m)
+                       m = hmaps.CleanConfigStringMap(m)
                        for k, v := range m {
                                var ctc ContentTypeConfig
                                if err := mapstructure.WeakDecode(v, &ctc); err != nil {
@@ -221,16 +221,16 @@ func DecodeContentTypes(in map[string]any, types Types) (*config.ConfigNamespace
 // DecodeTypes decodes the given map of media types.
 func DecodeTypes(in map[string]any) (*config.ConfigNamespace[map[string]MediaTypeConfig, Types], error) {
        buildConfig := func(v any) (Types, any, error) {
-               m, err := maps.ToStringMapE(v)
+               m, err := hmaps.ToStringMapE(v)
                if err != nil {
                        return nil, nil, err
                }
                if m == nil {
                        m = map[string]any{}
                }
-               m = maps.CleanConfigStringMap(m)
+               m = hmaps.CleanConfigStringMap(m)
                // Merge with defaults.
-               maps.MergeShallow(m, defaultMediaTypesConfig)
+               hmaps.MergeShallow(m, defaultMediaTypesConfig)
 
                var types Types
 
@@ -242,8 +242,8 @@ func DecodeTypes(in map[string]any) (*config.ConfigNamespace[map[string]MediaTyp
                        if err := mapstructure.WeakDecode(v, &mediaType); err != nil {
                                return nil, nil, err
                        }
-                       mm := maps.ToStringMap(v)
-                       suffixes, _, found := maps.LookupEqualFold(mm, "suffixes")
+                       mm := hmaps.ToStringMap(v)
+                       suffixes, _, found := hmaps.LookupEqualFold(mm, "suffixes")
                        if found {
                                mediaType.SuffixesCSV = strings.TrimSpace(strings.ToLower(strings.Join(cast.ToStringSlice(suffixes), ",")))
                        }
index 7a28d707d7e2dabf5a0fa091e1221595d97afb35..8b68a0bf01fd73d33d5c661135e43b983cfb78f8 100644 (file)
@@ -16,8 +16,8 @@ package minifiers
 import (
        "fmt"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hugo"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/spf13/cast"
 
        "github.com/mitchellh/mapstructure"
@@ -88,17 +88,17 @@ func DecodeConfig(v any) (conf MinifyConfig, err error) {
                return
        }
 
-       m := maps.ToStringMap(v)
+       m := hmaps.ToStringMap(v)
 
        // Handle deprecations.
        if td, found := m["tdewolff"]; found {
-               tdm := maps.ToStringMap(td)
+               tdm := hmaps.ToStringMap(td)
 
                // Decimals was renamed to Precision in tdewolff/minify v2.7.0.
                // https://github.com/tdewolff/minify/commit/2fed4401348ce36bd6c20e77335a463e69d94386
                for _, key := range []string{"css", "svg"} {
                        if v, found := tdm[key]; found {
-                               vm := maps.ToStringMap(v)
+                               vm := hmaps.ToStringMap(v)
                                ko := "decimals"
                                kn := "precision"
                                if vv, found := vm[ko]; found {
@@ -121,7 +121,7 @@ func DecodeConfig(v any) (conf MinifyConfig, err error) {
                // KeepConditionalComments was renamed to KeepSpecialComments in tdewolff/minify v2.20.13.
                // https://github.com/tdewolff/minify/commit/342cbc1974162db0ad3327f7a42a623b2cd3ebbc
                if v, found := tdm["html"]; found {
-                       vm := maps.ToStringMap(v)
+                       vm := hmaps.ToStringMap(v)
                        ko := "keepconditionalcomments"
                        kn := "keepspecialcomments"
                        if vv, found := vm[ko]; found {
@@ -140,7 +140,7 @@ func DecodeConfig(v any) (conf MinifyConfig, err error) {
                // KeepCSS2 was deprecated in favor of Version in tdewolff/minify v2.24.1.
                // https://github.com/tdewolff/minify/commit/57e3ebe0e6914b82c9ab0849a14f86bc29cd2ebf
                if v, found := tdm["css"]; found {
-                       vm := maps.ToStringMap(v)
+                       vm := hmaps.ToStringMap(v)
                        ko := "keepcss2"
                        kn := "version"
                        if vv, found := vm[ko]; found {
index 9a86c814029caeead323dd9a35c77ae63fd8ced3..de803dbd435f7f720738f6874684b55c32b42f0f 100644 (file)
@@ -28,6 +28,7 @@ import (
 
        "github.com/bep/debounce"
        "github.com/gohugoio/hugo/common/herrors"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/loggers"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/common/version"
@@ -35,8 +36,6 @@ import (
 
        "github.com/spf13/cast"
 
-       "github.com/gohugoio/hugo/common/maps"
-
        "github.com/gohugoio/hugo/parser/metadecoders"
 
        "github.com/gohugoio/hugo/hugofs/files"
@@ -494,7 +493,7 @@ LOOP:
                if err != nil {
                        c.logger.Warnf("Failed to read module config for %q in %q: %s", tc.Path(), themeTOML, err)
                } else {
-                       maps.PrepareParams(themeCfg)
+                       hmaps.PrepareParams(themeCfg)
                }
        }
 
index 0deed2f42cdd65f8d3c3ec37ee0a57aaf75f0e73..2c1b6f2f93d8246e6543333932339aeffdb11ffc 100644 (file)
@@ -21,6 +21,7 @@ import (
        "io/fs"
        "strings"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hugio"
 
        "github.com/gohugoio/hugo/hugofs/files"
@@ -28,8 +29,6 @@ import (
        "github.com/gohugoio/hugo/hugofs"
        "github.com/spf13/afero"
 
-       "github.com/gohugoio/hugo/common/maps"
-
        "github.com/gohugoio/hugo/helpers"
 )
 
@@ -130,7 +129,7 @@ func Pack(sourceFs, assetsWithDuplicatesPreservedFs afero.Fs) error {
        var commentsm map[string]any
        comments, found := b.originalPackageJSON["comments"]
        if found {
-               commentsm = maps.ToStringMap(comments)
+               commentsm = hmaps.ToStringMap(comments)
        } else {
                commentsm = make(map[string]any)
        }
@@ -213,7 +212,7 @@ func (b *packageBuilder) addm(source string, m map[string]any) {
        // These packages will be added by order of import (project, module1, module2...),
        // so that should at least give the project control over the situation.
        if devDeps, found := m[devDependenciesKey]; found {
-               mm := maps.ToStringMapString(devDeps)
+               mm := hmaps.ToStringMapString(devDeps)
                for k, v := range mm {
                        if _, added := b.devDependencies[k]; !added {
                                b.devDependencies[k] = v
@@ -223,7 +222,7 @@ func (b *packageBuilder) addm(source string, m map[string]any) {
        }
 
        if deps, found := m[dependenciesKey]; found {
-               mm := maps.ToStringMapString(deps)
+               mm := hmaps.ToStringMapString(deps)
                for k, v := range mm {
                        if _, added := b.dependencies[k]; !added {
                                b.dependencies[k] = v
index 5d4c5b93eaded726474ba8cde3cf32f75e3da59c..c020475bf07df3fe8b8ab9003b1b0b5ec00ae83a 100644 (file)
@@ -19,7 +19,7 @@ import (
        "slices"
        "sort"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/types"
        "github.com/gohugoio/hugo/compare"
        "github.com/gohugoio/hugo/config"
@@ -89,7 +89,7 @@ type Page interface {
        IsPage() bool
        IsSection() bool
        IsAncestor(other any) bool
-       Params() maps.Params
+       Params() hmaps.Params
 }
 
 // Menu is a collection of menu entries.
@@ -158,7 +158,7 @@ type MenuConfig struct {
        Weight     int
        Title      string
        // User defined params.
-       Params maps.Params
+       Params hmaps.Params
 }
 
 // For internal use.
@@ -279,11 +279,11 @@ func DecodeConfig(in any) (*config.ConfigNamespace[map[string]MenuConfig, Menus]
                        return ret, map[string]any{}, nil
                }
 
-               menus, err := maps.ToStringMapE(in)
+               menus, err := hmaps.ToStringMapE(in)
                if err != nil {
                        return ret, nil, err
                }
-               menus = maps.CleanConfigStringMap(menus)
+               menus = hmaps.CleanConfigStringMap(menus)
 
                for name, menu := range menus {
                        m, err := cast.ToSliceE(menu)
@@ -295,7 +295,7 @@ func DecodeConfig(in any) (*config.ConfigNamespace[map[string]MenuConfig, Menus]
                                        if err := mapstructure.WeakDecode(entry, &menuConfig); err != nil {
                                                return ret, nil, err
                                        }
-                                       maps.PrepareParams(menuConfig.Params)
+                                       hmaps.PrepareParams(menuConfig.Params)
                                        menuEntry := MenuEntry{
                                                Menu:       name,
                                                MenuConfig: menuConfig,
index 0919d93bb35c451caaf5e690aa4ef40f846d14c7..6890324214cb5843a7dc77e5fed97b12b6b63772 100644 (file)
@@ -16,7 +16,7 @@ package navigation
 import (
        "fmt"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/types"
        "github.com/mitchellh/mapstructure"
 
@@ -74,7 +74,7 @@ func PageMenusFromPage(ms any, p Page) (PageMenus, error) {
        }
 
        // Could be a structured menu entry
-       menus, err := maps.ToStringMapE(ms)
+       menus, err := hmaps.ToStringMapE(ms)
        if err != nil {
                return pm, wrapErr(err)
        }
@@ -82,7 +82,7 @@ func PageMenusFromPage(ms any, p Page) (PageMenus, error) {
        for name, menu := range menus {
                menuEntry := MenuEntry{Menu: name}
                if menu != nil {
-                       ime, err := maps.ToStringMapE(menu)
+                       ime, err := hmaps.ToStringMapE(menu)
                        if err != nil {
                                return pm, wrapErr(err)
                        }
index 09d29f1842f8e132fc6f5e3d036e80be1b265d11..3f6f4e2489da808718d0324ba6ea5684cfe1b247 100644 (file)
@@ -19,7 +19,7 @@ import (
        "sort"
        "strings"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/config"
        "github.com/gohugoio/hugo/media"
        "github.com/mitchellh/mapstructure"
@@ -42,11 +42,11 @@ func DecodeConfig(mediaTypes media.Types, in any) (*config.ConfigNamespace[map[s
                f := make(Formats, len(DefaultFormats))
                copy(f, DefaultFormats)
                if in != nil {
-                       m, err := maps.ToStringMapE(in)
+                       m, err := hmaps.ToStringMapE(in)
                        if err != nil {
                                return nil, nil, fmt.Errorf("failed convert config to map: %s", err)
                        }
-                       m = maps.CleanConfigStringMap(m)
+                       m = hmaps.CleanConfigStringMap(m)
 
                        for k, v := range m {
                                found := false
index 6443bfdf8d0beff32fc44a28a4976b61febd4918..02e7dbdb73b85ea6e7b12ec45ac68904be607582 100644 (file)
@@ -25,7 +25,7 @@ import (
        "unsafe"
 
        "github.com/gohugoio/hugo/common/herrors"
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/niklasfasching/go-org/org"
 
        xml "github.com/clbanning/mxj/v2"
@@ -120,7 +120,7 @@ func (d Decoder) UnmarshalStringTo(data string, typ any) (any, error) {
        switch typ.(type) {
        case string:
                return data, nil
-       case map[string]any, maps.Params:
+       case map[string]any, hmaps.Params:
                format := d.FormatFromContentString(data)
                return d.UnmarshalToMap([]byte(data), format)
        case []any:
index ebed77baa7848a00a3ece72d8d99e61ed3f3a042..9541ecd8a2136313b6ef3bde92db9bd6f90ce244 100644 (file)
@@ -18,16 +18,15 @@ import (
        "context"
        "errors"
        "fmt"
+       "maps"
        "math"
        "sort"
        "strings"
        "sync"
        "time"
 
-       xmaps "maps"
-
        "github.com/gohugoio/hugo/common/collections"
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/compare"
        "github.com/gohugoio/hugo/markup/tableofcontents"
        "github.com/spf13/cast"
@@ -557,7 +556,7 @@ func norm(num, min, max int) int {
 }
 
 // DecodeConfig decodes a slice of map into Config.
-func DecodeConfig(m maps.Params) (Config, error) {
+func DecodeConfig(m hmaps.Params) (Config, error) {
        if m == nil {
                return Config{}, errors.New("no related config provided")
        }
@@ -590,7 +589,7 @@ func DecodeConfig(m maps.Params) (Config, error) {
                        c.Indices[i].Type = TypeBasic
                }
                if !validTypes[c.Indices[i].Type] {
-                       return c, fmt.Errorf("invalid index type %q. Must be one of %v", c.Indices[i].Type, xmaps.Keys(validTypes))
+                       return c, fmt.Errorf("invalid index type %q. Must be one of %v", c.Indices[i].Type, maps.Keys(validTypes))
                }
                if icfg.CardinalityThreshold < 0 || icfg.CardinalityThreshold > 100 {
                        return Config{}, errors.New("cardinalityThreshold threshold must be between 0 and 100")
index 08c0a5007f8643231c1954302af511d0c81a3054..f72f0af23f860d7ec2df20293ed434d52b5cddc6 100644 (file)
@@ -21,7 +21,7 @@ import (
        "strings"
 
        "github.com/gohugoio/hugo/common/hashing"
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/config"
        "github.com/gohugoio/hugo/media"
        "github.com/mitchellh/mapstructure"
@@ -162,12 +162,12 @@ func DecodeConfig(in map[string]any) (*config.ConfigNamespace[ImagingConfig, Ima
        }
 
        buildConfig := func(in any) (ImagingConfigInternal, any, error) {
-               m, err := maps.ToStringMapE(in)
+               m, err := hmaps.ToStringMapE(in)
                if err != nil {
                        return ImagingConfigInternal{}, nil, err
                }
                // Merge in the defaults.
-               maps.MergeShallow(m, defaultImaging)
+               hmaps.MergeShallow(m, defaultImaging)
 
                var i ImagingConfigInternal
                if err := mapstructure.Decode(m, &i.Imaging); err != nil {
index 1e44f11841f51d00eb5bc7d652c89963ce59ecaf..5fb5dae1f400aa9773d6fb8d44a4349ceb366ab4 100644 (file)
@@ -19,8 +19,8 @@ import (
        "image/color"
        "strings"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hugio"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/resources/resource"
        "github.com/makeworld-the-better-one/dither/v2"
        "github.com/mitchellh/mapstructure"
@@ -83,9 +83,9 @@ func (*Filters) Text(text string, options ...any) gift.Filter {
                linespacing: 2,
        }
 
-       var opt maps.Params
+       var opt hmaps.Params
        if len(options) > 0 {
-               opt = maps.MustToParamsAndPrepare(options[0])
+               opt = hmaps.MustToParamsAndPrepare(options[0])
                for option, v := range opt {
                        switch option {
                        case "color":
index 163a91e902f904b8d7129c40a41334d12d059e0d..cb7922e7e78b13f7af40e8cbc86225ffbeadce8c 100644 (file)
@@ -21,10 +21,10 @@ import (
        "strings"
 
        "github.com/gohugoio/hugo/common/hashing"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hstrings"
        "github.com/gohugoio/hugo/common/hugo"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/config"
        "github.com/gohugoio/hugo/hugofs/hglob"
        "github.com/gohugoio/hugo/hugolib/sitesmatrix"
@@ -121,8 +121,8 @@ func checkCascadePattern(logger loggers.Logger, m PageMatcher) {
        }
 }
 
-func AddLangToCascadeTargetMap(lang string, m maps.Params) {
-       maps.SetNestedParamIfNotSet("target.sites.matrix.languages", ".", lang, m)
+func AddLangToCascadeTargetMap(lang string, m hmaps.Params) {
+       hmaps.SetNestedParamIfNotSet("target.sites.matrix.languages", ".", lang, m)
 }
 
 func DecodeCascadeConfig(in any) (*PageMatcherParamsConfigs, error) {
@@ -133,7 +133,7 @@ func DecodeCascadeConfig(in any) (*PageMatcherParamsConfigs, error) {
                        return CascadeConfig{}, []map[string]any{}, nil
                }
 
-               ms, err := maps.ToSliceStringMap(in)
+               ms, err := hmaps.ToSliceStringMap(in)
                if err != nil {
                        return CascadeConfig{}, nil, err
                }
@@ -141,7 +141,7 @@ func DecodeCascadeConfig(in any) (*PageMatcherParamsConfigs, error) {
                var cfgs []PageMatcherParamsConfig
 
                for _, m := range ms {
-                       m = maps.CleanConfigStringMap(m)
+                       m = hmaps.CleanConfigStringMap(m)
                        var (
                                c   PageMatcherParamsConfig
                                err error
@@ -192,10 +192,10 @@ type cascadeConfigDecoder struct{}
 func (d cascadeConfigDecoder) mapToPageMatcherParamsConfig(m map[string]any) (PageMatcherParamsConfig, error) {
        var pcfg PageMatcherParamsConfig
        if pcfg.Fields == nil {
-               pcfg.Fields = make(maps.Params)
+               pcfg.Fields = make(hmaps.Params)
        }
        if pcfg.Params == nil {
-               pcfg.Params = make(maps.Params)
+               pcfg.Params = make(hmaps.Params)
        }
 
        for k, v := range m {
@@ -207,7 +207,7 @@ func (d cascadeConfigDecoder) mapToPageMatcherParamsConfig(m map[string]any) (Pa
                        }
                        pcfg.Target = target
                case "params":
-                       params := maps.ToStringMap(v)
+                       params := hmaps.ToStringMap(v)
                        for k, v := range params {
                                if _, found := pcfg.Params[k]; !found {
                                        pcfg.Params[k] = v
@@ -271,25 +271,25 @@ type CascadeConfig struct {
 
 type PageMatcherParamsConfig struct {
        // Apply Params to all Pages matching Target.
-       Params maps.Params
+       Params hmaps.Params
        // Fields holds all fields but Params.
-       Fields maps.Params
+       Fields hmaps.Params
        // Target is the PageMatcher that this config applies to.
        Target PageMatcher
 }
 
 func (p *PageMatcherParamsConfig) init() error {
-       maps.PrepareParams(p.Params)
-       maps.PrepareParams(p.Fields)
+       hmaps.PrepareParams(p.Params)
+       hmaps.PrepareParams(p.Fields)
 
        return nil
 }
 
 func (p *PageMatcherParamsConfig) hasSitesMatrix() bool {
        if m, ok := p.Fields["sites"]; ok {
-               mm := maps.ToStringMap(m)
+               mm := hmaps.ToStringMap(m)
                if sm, found := mm["matrix"]; found {
-                       mmm := maps.ToStringMap(sm)
+                       mmm := hmaps.ToStringMap(sm)
                        return len(mmm) > 0
                }
        }
index 127af247d58fb56e535ca977e9d02edb8a950c42..3dafef7b9913cf9d1632d281a4c189310cfd6b08 100644 (file)
@@ -17,9 +17,9 @@ import (
        "path/filepath"
        "testing"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hugo"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/hugolib/sitesmatrix"
 
        qt "github.com/frankban/quicktest"
@@ -87,18 +87,18 @@ func TestPageMatcher(t *testing.T) {
                        return v
                }
                c.Assert(fn(map[string]any{"_target": map[string]any{"kind": "page"}, "foo": "bar"}), qt.DeepEquals, PageMatcherParamsConfig{
-                       Params: maps.Params{},
-                       Fields: maps.Params{
+                       Params: hmaps.Params{},
+                       Fields: hmaps.Params{
                                "foo": "bar",
                        },
                        Target: PageMatcher{Path: "", Kind: "page", Lang: "", Environment: ""},
                })
 
                c.Assert(fn(map[string]any{"target": map[string]any{"kind": "page"}, "params": map[string]any{"foo": "bar"}}), qt.DeepEquals, PageMatcherParamsConfig{
-                       Params: maps.Params{
+                       Params: hmaps.Params{
                                "foo": "bar",
                        },
-                       Fields: maps.Params{},
+                       Fields: hmaps.Params{},
                        Target: PageMatcher{Path: "", Kind: "page", Lang: "", Environment: ""},
                })
        })
@@ -134,10 +134,10 @@ func TestDecodeCascadeConfig(t *testing.T) {
        c.Assert(got.c[0].Config.Cascades, qt.HasLen, 2)
        first := got.c[0].Config.Cascades[0]
        c.Assert(first, qt.DeepEquals, PageMatcherParamsConfig{
-               Params: maps.Params{
+               Params: hmaps.Params{
                        "a": "av",
                },
-               Fields: maps.Params{},
+               Fields: hmaps.Params{},
                Target: PageMatcher{
                        Kind:        "page",
                        Sites:       sitesmatrix.Sites{},
@@ -147,11 +147,11 @@ func TestDecodeCascadeConfig(t *testing.T) {
 
        c.Assert(got.c[0].SourceStructure, qt.DeepEquals, []PageMatcherParamsConfig{
                {
-                       Params: maps.Params{"a": string("av")},
-                       Fields: maps.Params{},
+                       Params: hmaps.Params{"a": string("av")},
+                       Fields: hmaps.Params{},
                        Target: PageMatcher{Kind: "page", Environment: "production"},
                },
-               {Params: maps.Params{"b": string("bv")}, Fields: maps.Params{}, Target: PageMatcher{Kind: "page"}},
+               {Params: hmaps.Params{"b": string("bv")}, Fields: hmaps.Params{}, Target: PageMatcher{Kind: "page"}},
        })
 
        got, err = DecodeCascadeConfig(nil)
index 297ebda22f0c923e9046c8ea4700a815dd2c7d99..d4ca5bff6516db994dcb69bf25823405acf4e608 100644 (file)
@@ -29,9 +29,9 @@ import (
 
        "github.com/gohugoio/hugo/navigation"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hstore"
        "github.com/gohugoio/hugo/common/hugo"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/source"
 
@@ -320,7 +320,7 @@ func (p *nopPage) Param(key any) (any, error) {
        return nil, nil
 }
 
-func (p *nopPage) Params() maps.Params {
+func (p *nopPage) Params() hmaps.Params {
        return nil
 }
 
index d90ae074c84da438a10adfd323fd57eb27b3c7c1..b5f9149b76359e90733e57b6be96c03e9ade2b47 100644 (file)
@@ -20,12 +20,12 @@ import (
        "strings"
        "time"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hreflect"
        "github.com/gohugoio/hugo/common/hstrings"
        "github.com/gohugoio/hugo/common/htime"
        "github.com/gohugoio/hugo/common/hugio"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/hugofs"
        "github.com/gohugoio/hugo/hugofs/files"
@@ -104,7 +104,7 @@ func (pcfg *PageConfigEarly) SetMetaPreFromMap(ext string, frontmatter map[strin
 
 func (pcfg *PageConfigEarly) setFromFrontMatter(frontmatter map[string]any) error {
        // Needed for case insensitive fetching of params values.
-       maps.PrepareParams(frontmatter)
+       hmaps.PrepareParams(frontmatter)
        pcfg.Frontmatter = frontmatter
 
        if v, found := frontmatter[pageMetaKeyMarkup]; found {
@@ -122,7 +122,7 @@ func (pcfg *PageConfigEarly) setFromFrontMatter(frontmatter map[string]any) erro
 func (p *PageConfigEarly) setCascadeEarlyValueIfNotSet(key string, value any) (done bool) {
        switch key {
        case pageMetaKeySites:
-               p.Sites.SetFromParamsIfNotSet(value.(maps.Params))
+               p.Sites.SetFromParamsIfNotSet(value.(hmaps.Params))
        }
 
        return !p.Sites.Matrix.IsZero()
@@ -137,7 +137,7 @@ type PageConfigEarly struct {
        Sites   sitesmatrix.Sites
        Content Source // Content holds the content for this page.
 
-       Frontmatter maps.Params `mapstructure:"-" json:"-"` // The original front matter or content adapter map.
+       Frontmatter hmaps.Params `mapstructure:"-" json:"-"` // The original front matter or content adapter map.
 
        // Compiled values.
        SitesMatrixAndComplements `mapstructure:"-" json:"-"`
@@ -151,7 +151,7 @@ type PageConfigEarly struct {
 type PageConfigLate struct {
        Dates Dates `json:"-"` // Dates holds the four core dates for this page.
        DatesStrings
-       Params maps.Params // User defined params.
+       Params hmaps.Params // User defined params.
 
        Title          string   // The title of the page.
        LinkTitle      string   // The link title of the page.
@@ -438,9 +438,9 @@ func (p *PageConfigLate) Compile(e *PageConfigEarly, logger loggers.Logger, outp
        }
 
        if p.Params == nil {
-               p.Params = make(maps.Params)
+               p.Params = make(hmaps.Params)
        } else {
-               maps.PrepareParams(p.Params)
+               hmaps.PrepareParams(p.Params)
        }
 
        if len(p.Outputs) > 0 {
@@ -466,7 +466,7 @@ type ResourceConfig struct {
        Path    string
        Name    string
        Title   string
-       Params  maps.Params
+       Params  hmaps.Params
        Content Source
        Sites   sitesmatrix.Sites
 
@@ -486,7 +486,7 @@ func (rc *ResourceConfig) Validate() error {
 
 func (rc *ResourceConfig) Compile(basePath string, fim hugofs.FileMetaInfo, conf config.AllProvider, mediaTypes media.Types) error {
        if rc.Params != nil {
-               maps.PrepareParams(rc.Params)
+               hmaps.PrepareParams(rc.Params)
        }
 
        // Note that NormalizePathStringBasic will make sure that we don't preserve the unnormalized path.
index 1d6078b4ab4c3d132a691b7791f31b243427f46b..adaa9faeede99e91c77e9c345d7a0d5f9359a0b7 100644 (file)
@@ -24,8 +24,8 @@ import (
        "strings"
        "time"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hstrings"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/helpers"
        "github.com/gohugoio/hugo/resources/kinds"
 )
@@ -41,7 +41,7 @@ type PermalinkExpander struct {
 
        urlize func(uri string) string
 
-       patternCache *maps.Cache[string, func(Page) (string, error)]
+       patternCache *hmaps.Cache[string, func(Page) (string, error)]
 }
 
 // Time for checking date formats. Every field is different than the
@@ -83,7 +83,7 @@ func (p PermalinkExpander) callback(attr string) (pageToPermaAttribute, bool) {
 func NewPermalinkExpander(urlize func(uri string) string, patterns map[string]map[string]string) (PermalinkExpander, error) {
        p := PermalinkExpander{
                urlize:       urlize,
-               patternCache: maps.NewCache[string, func(Page) (string, error)](),
+               patternCache: hmaps.NewCache[string, func(Page) (string, error)](),
        }
 
        p.knownPermalinkAttributes = map[string]pageToPermaAttribute{
@@ -494,7 +494,7 @@ func DecodePermalinksConfig(m map[string]any) (map[string]map[string]string, err
        permalinksConfig[kinds.KindTaxonomy] = make(map[string]string)
        permalinksConfig[kinds.KindTerm] = make(map[string]string)
 
-       config := maps.CleanConfigStringMap(m)
+       config := hmaps.CleanConfigStringMap(m)
        for k, v := range config {
                switch v := v.(type) {
                case string:
@@ -505,7 +505,7 @@ func DecodePermalinksConfig(m map[string]any) (map[string]map[string]string, err
                        permalinksConfig[kinds.KindPage][k] = v
                        permalinksConfig[kinds.KindTerm][k] = v
 
-               case maps.Params:
+               case hmaps.Params:
                        // [permalinks.key]
                        //   xyz = ???
 
index 33dd947361553a8f1bb0490f41925ba83e0fb5df..e6016c508d2bd5761fefa95dad5ad108bb93a7c5 100644 (file)
@@ -16,8 +16,8 @@ package page
 import (
        "time"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hstore"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/config/privacy"
        "github.com/gohugoio/hugo/config/services"
        "github.com/gohugoio/hugo/hugolib/roles"
@@ -105,7 +105,7 @@ type Site interface {
        MainSections() []string
 
        // Returns the Params configured for this site.
-       Params() maps.Params
+       Params() hmaps.Params
 
        // Param is a convenience method to do lookups in Params.
        Param(key any) (any, error)
@@ -308,7 +308,7 @@ func (s *siteWrapper) MainSections() []string {
        return s.s.MainSections()
 }
 
-func (s *siteWrapper) Params() maps.Params {
+func (s *siteWrapper) Params() hmaps.Params {
        return s.s.Params()
 }
 
@@ -472,7 +472,7 @@ func (t testSite) BaseURL() string {
        return ""
 }
 
-func (t testSite) Params() maps.Params {
+func (t testSite) Params() hmaps.Params {
        return nil
 }
 
index 4c6cfbd3070d39f55efe237f414fd53aabd5baf1..1d6085e7370ae4e420850be90197f704eda94099 100644 (file)
@@ -27,9 +27,9 @@ import (
 
        "github.com/gohugoio/hugo/navigation"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hstore"
        "github.com/gohugoio/hugo/common/hugo"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/config"
        "github.com/gohugoio/hugo/hugofs"
@@ -398,7 +398,7 @@ func (p *testPage) Param(key any) (any, error) {
        return resource.Param(p, nil, key)
 }
 
-func (p *testPage) Params() maps.Params {
+func (p *testPage) Params() hmaps.Params {
        return p.params
 }
 
index 65e32145c0242044f14c73d0fc6fc736b0bf4676..f1aab7001f46dee24181d18b6e094c7f37a4f93c 100644 (file)
@@ -22,8 +22,8 @@ import (
 
        "github.com/spf13/cast"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hreflect"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/media"
        "github.com/gohugoio/hugo/resources/resource"
 )
@@ -169,7 +169,7 @@ func (r *PostPublishResource) Title() string {
        return r.field("Title")
 }
 
-func (r *PostPublishResource) Params() maps.Params {
+func (r *PostPublishResource) Params() hmaps.Params {
        panic(r.fieldNotSupported("Params"))
 }
 
index 1666e76921c2cb5fc1e5303e7e9f32ebcdf1502c..cf6e1e597c0840e25f0671a648d14319c2a7527f 100644 (file)
@@ -29,13 +29,13 @@ import (
 
        "github.com/gohugoio/hugo/common/hashing"
        "github.com/gohugoio/hugo/common/herrors"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hsync"
        "github.com/gohugoio/hugo/common/paths"
 
        "github.com/gohugoio/hugo/media"
 
        "github.com/gohugoio/hugo/common/hugio"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/resources/resource"
 
        "github.com/gohugoio/hugo/helpers"
@@ -91,7 +91,7 @@ type ResourceSourceDescriptor struct {
        Data map[string]any
 
        // The Params to associate with this resource.
-       Params maps.Params
+       Params hmaps.Params
 
        // Delay publishing until either Permalink or RelPermalink is called. Maybe never.
        LazyPublish bool
@@ -122,7 +122,7 @@ func (fd *ResourceSourceDescriptor) init(r *Spec) error {
        }
 
        if fd.Params == nil {
-               fd.Params = make(maps.Params)
+               fd.Params = make(hmaps.Params)
        }
 
        if fd.Path == nil {
@@ -498,7 +498,7 @@ func (l *genericResource) NameNormalized() string {
        return l.sd.NameNormalized
 }
 
-func (l *genericResource) Params() maps.Params {
+func (l *genericResource) Params() hmaps.Params {
        return l.params
 }
 
index d88424e9db9e6abcfd0800e4d8d4e2e19b4789de..cc85e3c92ba5eb44bf89321212081befb0c4f4ac 100644 (file)
 package resource
 
 import (
-       "github.com/gohugoio/hugo/common/maps"
-
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/spf13/cast"
 )
 
-func Param(r ResourceParamsProvider, fallback maps.Params, key any) (any, error) {
+func Param(r ResourceParamsProvider, fallback hmaps.Params, key any) (any, error) {
        keyStr, err := cast.ToStringE(key)
        if err != nil {
                return nil, err
        }
 
        if fallback == nil {
-               return maps.GetNestedParam(keyStr, ".", r.Params())
+               return hmaps.GetNestedParam(keyStr, ".", r.Params())
        }
 
-       return maps.GetNestedParam(keyStr, ".", r.Params(), fallback)
+       return hmaps.GetNestedParam(keyStr, ".", r.Params(), fallback)
 }
index 8575ae79eaf7694a773597b8f86526d237188b58..742379b1870c4bfb95b0c201e3efbca1c85d1837 100644 (file)
@@ -17,8 +17,7 @@ import (
        "strings"
        "time"
 
-       "github.com/gohugoio/hugo/common/maps"
-
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/helpers"
        "github.com/pelletier/go-toml/v2"
 
@@ -38,7 +37,7 @@ func GetParamToLower(r Resource, key string) any {
 }
 
 func getParam(r Resource, key string, stringToLower bool) any {
-       v, err := maps.GetNestedParam(key, ".", r.Params())
+       v, err := hmaps.GetNestedParam(key, ".", r.Params())
 
        if v == nil || err != nil {
                return nil
index 013d9b097305746a88e1b5d5cac703560f829b48..28fbab42f005c9a24a7617b7941de694fab14d3b 100644 (file)
@@ -20,8 +20,8 @@ import (
        "slices"
        "strings"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hreflect"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/hugofs/hglob"
        "github.com/spf13/cast"
@@ -330,7 +330,7 @@ func NewCachedResourceGetter(os ...any) *cachedResourceGetter {
        }
 
        return &cachedResourceGetter{
-               cache:    maps.NewCache[string, Resource](),
+               cache:    hmaps.NewCache[string, Resource](),
                delegate: getters,
        }
 }
@@ -352,7 +352,7 @@ var (
 )
 
 type cachedResourceGetter struct {
-       cache    *maps.Cache[string, Resource]
+       cache    *hmaps.Cache[string, Resource]
        delegate ResourceGetter
 }
 
index e55e7169fc81d5283317177eafe5cbba2ba3807e..66b49f9003398c18d2c18c7450fbee6f9711a4d6 100644 (file)
@@ -16,7 +16,7 @@ package resource
 import (
        "context"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/types"
        "github.com/gohugoio/hugo/langs"
        "github.com/gohugoio/hugo/media"
@@ -139,7 +139,7 @@ type NameNormalizedProvider interface {
 
 type ResourceParamsProvider interface {
        // Params set in front matter for this resource.
-       Params() maps.Params
+       Params() hmaps.Params
 }
 
 type ResourceDataProvider interface {
index c4dffaf9567416e23429eb24c79b108eaf9258e0..899ac8330dfcebe48c5dff761b587e369ac5eb67 100644 (file)
@@ -18,6 +18,7 @@ import (
        "context"
        "fmt"
        "io"
+       "maps"
        "math/rand"
        "mime"
        "net/http"
@@ -26,14 +27,12 @@ import (
        "strings"
        "time"
 
-       gmaps "maps"
-
        "github.com/gohugoio/httpcache"
        "github.com/gohugoio/hugo/common/hashing"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hstrings"
        "github.com/gohugoio/hugo/common/hugio"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/tasks"
        "github.com/gohugoio/hugo/common/types"
        "github.com/gohugoio/hugo/config"
@@ -172,12 +171,12 @@ func (c *Client) FromRemote(uri string, optionsm map[string]any) (resource.Resou
        }
 
        method := "GET"
-       if s, _, ok := maps.LookupEqualFold(optionsm, "method"); ok {
+       if s, _, ok := hmaps.LookupEqualFold(optionsm, "method"); ok {
                method = strings.ToUpper(s.(string))
        }
        isHeadMethod := method == "HEAD"
 
-       optionsm = gmaps.Clone(optionsm)
+       optionsm = maps.Clone(optionsm)
        userKey, optionsKey := remoteResourceKeys(uri, optionsm)
 
        // A common pattern is to use the key in the options map as
@@ -323,7 +322,7 @@ 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 {
+       if key, k, found := hmaps.LookupEqualFold(optionsm, "key"); found {
                userKey = hashing.HashString(key)
                delete(optionsm, k)
        }
index 955809c93d337cca895e45bc4564f90f61dce3b2..c97ed260db4d6f14c5a2fdb6d89ae20cac0b065d 100644 (file)
@@ -28,7 +28,7 @@ import (
 
        maps0 "maps"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/paths"
 )
 
@@ -60,7 +60,7 @@ type metaResource struct {
        changed bool
        title   string
        name    string
-       params  maps.Params
+       params  hmaps.Params
 }
 
 func (r *metaResource) Name() string {
@@ -71,7 +71,7 @@ func (r *metaResource) Title() string {
        return r.title
 }
 
-func (r *metaResource) Params() maps.Params {
+func (r *metaResource) Params() hmaps.Params {
        return r.params
 }
 
@@ -209,9 +209,9 @@ func assignMetadata(metadata []map[string]any, ma *metaResource) error {
 
                        params, found := meta["params"]
                        if found {
-                               m := maps.ToStringMap(params)
+                               m := hmaps.ToStringMap(params)
                                // Needed for case insensitive fetching of params values
-                               maps.PrepareParams(m)
+                               hmaps.PrepareParams(m)
                                ma.updateParams(m)
                        }
                }
index bb1f57fd32dd66e8d0a0712745fb59adcba30a4d..4d3d7c1b8d6c9114d5bb5c79825564aa45206f30 100644 (file)
@@ -25,6 +25,7 @@ import (
 
        "github.com/gohugoio/hugo/common/constants"
        "github.com/gohugoio/hugo/common/hashing"
+       "github.com/gohugoio/hugo/common/hmaps"
        "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/resources/internal"
        "github.com/gohugoio/hugo/resources/resource"
 
@@ -133,7 +133,7 @@ type ResourceTransformationCtx struct {
        // to be simple types, as it needs to be serialized to JSON and back.
        Data map[string]any
 
-       // This is used to publish additional artifacts, e.g. source maps.
+       // This is used to publish additional artifacts, e.g. source hhmaps.
        // We may improve this.
        OpenResourcePublisher func(relTargetPath string) (io.WriteCloser, error)
 }
@@ -310,7 +310,7 @@ func (r *resourceAdapter) NameNormalized() string {
        return r.target.(resource.NameNormalizedProvider).NameNormalized()
 }
 
-func (r *resourceAdapter) Params() maps.Params {
+func (r *resourceAdapter) Params() hmaps.Params {
        r.init(false, false)
        return r.metaProvider.Params()
 }
index f10466fd94156a7976826185b7997bc4e8d64b6d..749ed612f2f257b095d545721911ade09f63ee28 100644 (file)
@@ -25,9 +25,9 @@ import (
        "time"
 
        "github.com/gohugoio/hugo/common/collections"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hreflect"
        "github.com/gohugoio/hugo/common/hstore"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/types"
        "github.com/gohugoio/hugo/deps"
        "github.com/gohugoio/hugo/langs"
@@ -43,7 +43,7 @@ func New(deps *deps.Deps) *Namespace {
        }
        loc := langs.GetLocation(language)
 
-       dCache := maps.NewCacheWithOptions[dKey, []int](maps.CacheOptions{Size: 100})
+       dCache := hmaps.NewCacheWithOptions[dKey, []int](hmaps.CacheOptions{Size: 100})
 
        return &Namespace{
                loc:      loc,
@@ -57,7 +57,7 @@ func New(deps *deps.Deps) *Namespace {
 type Namespace struct {
        loc      *time.Location
        sortComp *compare.Namespace
-       dCache   *maps.Cache[dKey, []int]
+       dCache   *hmaps.Cache[dKey, []int]
        deps     *deps.Deps
 }
 
index 2d0a6c7df5b0962b0c212f1e0a1b87f7d2a47ac2..5562a80d6a5b195e2eb7e6d095d2942e83b0e872 100644 (file)
@@ -23,7 +23,7 @@ import (
        "testing"
        "time"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/config/testconfig"
 
        qt "github.com/frankban/quicktest"
@@ -912,10 +912,10 @@ type TstX struct {
 }
 
 type TstParams struct {
-       params maps.Params
+       params hmaps.Params
 }
 
-func (x TstParams) Params() maps.Params {
+func (x TstParams) Params() hmaps.Params {
        return x.params
 }
 
index 7de27931edca0993b650438c86e6051fc23fbf23..999abf829c243fc9bb6705777ae65a0f9486bb1f 100644 (file)
@@ -20,8 +20,8 @@ import (
 
        "github.com/spf13/cast"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hreflect"
-       "github.com/gohugoio/hugo/common/maps"
 )
 
 // Index returns the result of indexing its first argument by the following
@@ -63,7 +63,7 @@ func (ns *Namespace) doIndex(item any, args ...any) (any, error) {
                indices = args
        }
 
-       lowerm, ok := item.(maps.Params)
+       lowerm, ok := item.(hmaps.Params)
        if ok {
                return lowerm.GetNested(cast.ToStringSlice(indices)...), nil
        }
index 0c5a5875677e7a3b0effbfa1fe430bd2fb117261..5b56ba341140247edf98c1f401b62f5b967aa99c 100644 (file)
@@ -17,9 +17,8 @@ import (
        "fmt"
        "testing"
 
-       "github.com/gohugoio/hugo/common/maps"
-
        qt "github.com/frankban/quicktest"
+       "github.com/gohugoio/hugo/common/hmaps"
 )
 
 func TestIndex(t *testing.T) {
@@ -47,8 +46,8 @@ func TestIndex(t *testing.T) {
                {map[string]map[string]string{"a": {"b": "c"}}, []any{"a", "b"}, "c", false},
                {[]map[string]map[string]string{{"a": {"b": "c"}}}, []any{0, "a", "b"}, "c", false},
                {map[string]map[string]any{"a": {"b": []string{"c", "d"}}}, []any{"a", "b", 1}, "d", false},
-               {maps.Params{"a": "av"}, []any{"A"}, "av", false},
-               {maps.Params{"a": map[string]any{"b": "bv"}}, []any{"A", "B"}, "bv", false},
+               {hmaps.Params{"a": "av"}, []any{"A"}, "av", false},
+               {hmaps.Params{"a": map[string]any{"b": "bv"}}, []any{"A", "B"}, "bv", false},
 
                // These used to be errors.
                // See issue 10489.
index b9696b5026c0aa84cb9f15e73648e203ad0f3a16..b506979317ebc243f25202e2a1dbec9998b00244 100644 (file)
@@ -19,8 +19,8 @@ import (
        "reflect"
        "strings"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hreflect"
-       "github.com/gohugoio/hugo/common/maps"
 )
 
 // Merge creates a copy of the final parameter in params and merges the preceding
@@ -92,7 +92,7 @@ func mergeMap(dst, src reflect.Value) reflect.Value {
        out := reflect.MakeMap(dst.Type())
 
        // If the destination is Params, we must lower case all keys.
-       _, lowerCase := dst.Interface().(maps.Params)
+       _, lowerCase := dst.Interface().(hmaps.Params)
 
        k := reflect.New(dst.Type().Key()).Elem()
        v := reflect.New(dst.Type().Elem()).Elem()
index 3642e9060be68c526ea1063303e6c6b540870086..978c2ae89f82f77eca27ac9d481a2677c6d22a92 100644 (file)
@@ -18,7 +18,7 @@ import (
        "reflect"
        "testing"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/parser"
        "github.com/gohugoio/hugo/parser/metadecoders"
 
@@ -78,24 +78,24 @@ func TestMerge(t *testing.T) {
                        "params dst",
                        []any{
                                map[string]any{"a": 42, "c": 3},
-                               maps.Params{"a": 1, "b": 2},
+                               hmaps.Params{"a": 1, "b": 2},
                        },
-                       maps.Params{"a": int(1), "b": int(2), "c": int(3)},
+                       hmaps.Params{"a": int(1), "b": int(2), "c": int(3)},
                        false,
                },
                {
                        "params dst, upper case src",
                        []any{
                                map[string]any{"a": 42, "C": 3},
-                               maps.Params{"a": 1, "b": 2},
+                               hmaps.Params{"a": 1, "b": 2},
                        },
-                       maps.Params{"a": int(1), "b": int(2), "c": int(3)},
+                       hmaps.Params{"a": int(1), "b": int(2), "c": int(3)},
                        false,
                },
                {
                        "params src",
                        []any{
-                               maps.Params{"a": 42, "c": 3},
+                               hmaps.Params{"a": 42, "c": 3},
                                map[string]any{"a": 1, "c": 2},
                        },
                        map[string]any{"a": int(1), "c": int(2)},
@@ -104,7 +104,7 @@ func TestMerge(t *testing.T) {
                {
                        "params src, upper case dst",
                        []any{
-                               maps.Params{"a": 42, "c": 3},
+                               hmaps.Params{"a": 42, "c": 3},
                                map[string]any{"a": 1, "C": 2},
                        },
                        map[string]any{"a": int(1), "C": int(2)},
@@ -114,9 +114,9 @@ func TestMerge(t *testing.T) {
                        "nested, params dst",
                        []any{
                                map[string]any{"a": 42, "c": 3, "b": map[string]any{"d": 55, "e": 66, "f": 3}},
-                               maps.Params{"a": 1, "b": maps.Params{"d": 1, "e": 2}},
+                               hmaps.Params{"a": 1, "b": hmaps.Params{"d": 1, "e": 2}},
                        },
-                       maps.Params{"a": 1, "b": maps.Params{"d": 1, "e": 2, "f": 3}, "c": 3},
+                       hmaps.Params{"a": 1, "b": hmaps.Params{"d": 1, "e": 2, "f": 3}, "c": 3},
                        false,
                },
                {
@@ -136,7 +136,6 @@ func TestMerge(t *testing.T) {
                {"different map types", []any{map[int]any{32: "a"}, simpleMap}, nil, true},
                {"all nil", []any{nil, nil}, nil, true},
        } {
-
                t.Run(test.name, func(t *testing.T) {
                        t.Parallel()
                        errMsg := qt.Commentf("[%d] %v", i, test)
index 19e6d8afedd3f2b3c1f28c69dc61775d759ade53..164a6e43cf743724b13149d5662a6ded964b546b 100644 (file)
@@ -17,7 +17,7 @@ import (
        "errors"
        "net/url"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/spf13/cast"
 )
 
@@ -37,7 +37,7 @@ func (ns *Namespace) Querify(params ...any) (string, error) {
                switch v := params[0].(type) {
                case map[string]any: // created with collections.Dictionary
                        return mapToQueryString(v)
-               case maps.Params: // site configuration or page parameters
+               case hmaps.Params: // site configuration or page parameters
                        return mapToQueryString(v)
                case []string:
                        return stringSliceToQueryString(v)
@@ -66,7 +66,7 @@ func (ns *Namespace) Querify(params ...any) (string, error) {
 // mapToQueryString returns a URL query string derived from the given string
 // map, encoded and sorted by key. The function returns an error if it cannot
 // convert an element value to a string.
-func mapToQueryString[T map[string]any | maps.Params](m T) (string, error) {
+func mapToQueryString[T map[string]any | hmaps.Params](m T) (string, error) {
        if len(m) == 0 {
                return "", nil
        }
index 9d4f72923f728c123acb0baf64a24c0a6e0ec52d..3c09fbab739f6c1c942ca72d9a4d788eda956f4a 100644 (file)
@@ -17,7 +17,7 @@ import (
        "testing"
 
        qt "github.com/frankban/quicktest"
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
 )
 
 func TestQuerify(t *testing.T) {
@@ -31,9 +31,9 @@ func TestQuerify(t *testing.T) {
                expect any
        }{
                // map
-               {"01", []any{maps.Params{"a": "foo", "b": "bar"}}, `a=foo&b=bar`},
-               {"02", []any{maps.Params{"a": 6, "b": 7}}, `a=6&b=7`},
-               {"03", []any{maps.Params{"a": "foo", "b": 7}}, `a=foo&b=7`},
+               {"01", []any{hmaps.Params{"a": "foo", "b": "bar"}}, `a=foo&b=bar`},
+               {"02", []any{hmaps.Params{"a": 6, "b": 7}}, `a=6&b=7`},
+               {"03", []any{hmaps.Params{"a": "foo", "b": 7}}, `a=foo&b=7`},
                {"04", []any{map[string]any{"a": "foo", "b": "bar"}}, `a=foo&b=bar`},
                {"05", []any{map[string]any{"a": 6, "b": 7}}, `a=6&b=7`},
                {"06", []any{map[string]any{"a": "foo", "b": 7}}, `a=foo&b=7`},
@@ -53,7 +53,7 @@ func TestQuerify(t *testing.T) {
                // no arguments
                {"16", []any{}, ``},
                // errors: zero key length
-               {"17", []any{maps.Params{"": "foo"}}, false},
+               {"17", []any{hmaps.Params{"": "foo"}}, false},
                {"18", []any{map[string]any{"": "foo"}}, false},
                {"19", []any{[]string{"", "foo"}}, false},
                {"20", []any{[]any{"", 6}}, false},
index 2a0a4f3bb9f89057b1ae8caee1e3f2fc2e82b946..6d6a2ad566e5e04cc9d30e7f2199523327a3297c 100644 (file)
@@ -20,8 +20,8 @@ import (
        "sort"
        "strings"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hreflect"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/langs"
        "github.com/gohugoio/hugo/tpl/compare"
        "github.com/spf13/cast"
@@ -89,8 +89,8 @@ func (ns *Namespace) Sort(ctx context.Context, l any, args ...any) (any, error)
                                        if !v.IsValid() {
                                                continue
                                        }
-                                       // Special handling of lower cased maps.
-                                       if params, ok := v.Interface().(maps.Params); ok {
+                                       // Special handling of lower cased hmaps.
+                                       if params, ok := v.Interface().(hmaps.Params); ok {
                                                v = reflect.ValueOf(params.GetNested(path[i+1:]...))
                                                break
                                        }
@@ -122,8 +122,8 @@ func (ns *Namespace) Sort(ctx context.Context, l any, args ...any) (any, error)
                                        if !v.IsValid() {
                                                continue
                                        }
-                                       // Special handling of lower cased maps.
-                                       if params, ok := v.Interface().(maps.Params); ok {
+                                       // Special handling of lower cased hmaps.
+                                       if params, ok := v.Interface().(hmaps.Params); ok {
                                                v = reflect.ValueOf(params.GetNested(path[j+1:]...))
                                                break
                                        }
index 4fc95ac8a9b686b2ae5f8443af9270c54b9430be..0a6f04373246af9ca482867cc22c5617fde70850 100644 (file)
@@ -19,7 +19,7 @@ import (
        "reflect"
        "testing"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
 )
 
 type stringsSlice []string
@@ -103,17 +103,17 @@ func TestSort(t *testing.T) {
                },
                // Lower case Params, slice
                {
-                       []TstParams{{params: maps.Params{"color": "indigo"}}, {params: maps.Params{"color": "blue"}}, {params: maps.Params{"color": "green"}}},
+                       []TstParams{{params: hmaps.Params{"color": "indigo"}}, {params: hmaps.Params{"color": "blue"}}, {params: hmaps.Params{"color": "green"}}},
                        ".Params.COLOR",
                        "asc",
-                       []TstParams{{params: maps.Params{"color": "blue"}}, {params: maps.Params{"color": "green"}}, {params: maps.Params{"color": "indigo"}}},
+                       []TstParams{{params: hmaps.Params{"color": "blue"}}, {params: hmaps.Params{"color": "green"}}, {params: hmaps.Params{"color": "indigo"}}},
                },
                // Lower case Params, map
                {
-                       map[string]TstParams{"1": {params: maps.Params{"color": "indigo"}}, "2": {params: maps.Params{"color": "blue"}}, "3": {params: maps.Params{"color": "green"}}},
+                       map[string]TstParams{"1": {params: hmaps.Params{"color": "indigo"}}, "2": {params: hmaps.Params{"color": "blue"}}, "3": {params: hmaps.Params{"color": "green"}}},
                        ".Params.CoLoR",
                        "asc",
-                       []TstParams{{params: maps.Params{"color": "blue"}}, {params: maps.Params{"color": "green"}}, {params: maps.Params{"color": "indigo"}}},
+                       []TstParams{{params: hmaps.Params{"color": "blue"}}, {params: hmaps.Params{"color": "green"}}, {params: hmaps.Params{"color": "indigo"}}},
                },
                // test map sorting by struct's method
                {
index 9a45ba12f22ca47632c93a79b27e7eaa0bd20184..bc7dcd2295b77c12249a3b09571899e171e5b101 100644 (file)
@@ -20,9 +20,9 @@ import (
        "reflect"
        "strings"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hreflect"
        "github.com/gohugoio/hugo/common/hstrings"
-       "github.com/gohugoio/hugo/common/maps"
 )
 
 // Where returns a filtered subset of collection c.
@@ -403,7 +403,7 @@ func (ns *Namespace) checkWhereArray(ctxv, seqv, kv, mv reflect.Value, path []st
                rvv := seqv.Index(i)
 
                if kv.Kind() == reflect.String {
-                       if params, ok := rvv.Interface().(maps.Params); ok {
+                       if params, ok := rvv.Interface().(hmaps.Params); ok {
                                vvv = reflect.ValueOf(params.GetNested(path...))
                        } else {
                                vvv = rvv
@@ -415,7 +415,7 @@ func (ns *Namespace) checkWhereArray(ctxv, seqv, kv, mv reflect.Value, path []st
                                        }
 
                                        if i < len(path)-1 && vvv.IsValid() {
-                                               if params, ok := vvv.Interface().(maps.Params); ok {
+                                               if params, ok := vvv.Interface().(hmaps.Params); ok {
                                                        // The current path element is the map itself, .Params.
                                                        vvv = reflect.ValueOf(params.GetNested(path[i+1:]...))
                                                        break
index 3b55ffdbd51f136da4772ab1e35b25d0151f9cd2..2caf1e830e6fd65551c9ed114759d33d88c63b53 100644 (file)
@@ -23,7 +23,7 @@ import (
        "testing"
        "time"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
 )
 
 func TestWhere(t *testing.T) {
@@ -176,35 +176,35 @@ func TestWhere(t *testing.T) {
                                {1: "a", 2: "m"},
                        },
                },
-               // Case insensitive maps.Params
+               // Case insensitive hmaps.Params
                // Slice of structs
                {
-                       seq: []TstParams{{params: maps.Params{"i": 0, "color": "indigo"}}, {params: maps.Params{"i": 1, "color": "blue"}}, {params: maps.Params{"i": 2, "color": "green"}}, {params: maps.Params{"i": 3, "color": "blue"}}},
+                       seq: []TstParams{{params: hmaps.Params{"i": 0, "color": "indigo"}}, {params: hmaps.Params{"i": 1, "color": "blue"}}, {params: hmaps.Params{"i": 2, "color": "green"}}, {params: hmaps.Params{"i": 3, "color": "blue"}}},
                        key: ".Params.COLOR", match: "blue",
-                       expect: []TstParams{{params: maps.Params{"i": 1, "color": "blue"}}, {params: maps.Params{"i": 3, "color": "blue"}}},
+                       expect: []TstParams{{params: hmaps.Params{"i": 1, "color": "blue"}}, {params: hmaps.Params{"i": 3, "color": "blue"}}},
                },
                {
-                       seq: []TstParams{{params: maps.Params{"nested": map[string]any{"color": "indigo"}}}, {params: maps.Params{"nested": map[string]any{"color": "blue"}}}},
+                       seq: []TstParams{{params: hmaps.Params{"nested": map[string]any{"color": "indigo"}}}, {params: hmaps.Params{"nested": map[string]any{"color": "blue"}}}},
                        key: ".Params.NEsTED.COLOR", match: "blue",
-                       expect: []TstParams{{params: maps.Params{"nested": map[string]any{"color": "blue"}}}},
+                       expect: []TstParams{{params: hmaps.Params{"nested": map[string]any{"color": "blue"}}}},
                },
                {
-                       seq: []TstParams{{params: maps.Params{"i": 0, "color": "indigo"}}, {params: maps.Params{"i": 1, "color": "blue"}}, {params: maps.Params{"i": 2, "color": "green"}}, {params: maps.Params{"i": 3, "color": "blue"}}},
+                       seq: []TstParams{{params: hmaps.Params{"i": 0, "color": "indigo"}}, {params: hmaps.Params{"i": 1, "color": "blue"}}, {params: hmaps.Params{"i": 2, "color": "green"}}, {params: hmaps.Params{"i": 3, "color": "blue"}}},
                        key: ".Params", match: "blue",
                        expect: []TstParams{},
                },
                // Slice of maps
                {
-                       seq: []maps.Params{
+                       seq: []hmaps.Params{
                                {"a": "a1", "b": "b1"}, {"a": "a2", "b": "b2"},
                        },
                        key: "B", match: "b2",
-                       expect: []maps.Params{
+                       expect: []hmaps.Params{
                                {"a": "a2", "b": "b2"},
                        },
                },
                {
-                       seq: []maps.Params{
+                       seq: []hmaps.Params{
                                {
                                        "a": map[string]any{
                                                "b": "b1",
@@ -217,7 +217,7 @@ func TestWhere(t *testing.T) {
                                },
                        },
                        key: "A.B", match: "b2",
-                       expect: []maps.Params{
+                       expect: []hmaps.Params{
                                {
                                        "a": map[string]any{
                                                "b": "b2",
@@ -622,14 +622,14 @@ func TestWhere(t *testing.T) {
                },
                {
                        seq: map[string]any{
-                               "foo": []any{maps.Params{"a": 1, "b": 2}},
-                               "bar": []any{maps.Params{"a": 3, "b": 4}},
-                               "zap": []any{maps.Params{"a": 5, "b": 6}},
+                               "foo": []any{hmaps.Params{"a": 1, "b": 2}},
+                               "bar": []any{hmaps.Params{"a": 3, "b": 4}},
+                               "zap": []any{hmaps.Params{"a": 5, "b": 6}},
                        },
                        key: "B", op: ">", match: 3,
                        expect: map[string]any{
-                               "bar": []any{maps.Params{"a": 3, "b": 4}},
-                               "zap": []any{maps.Params{"a": 5, "b": 6}},
+                               "bar": []any{hmaps.Params{"a": 3, "b": 4}},
+                               "zap": []any{hmaps.Params{"a": 5, "b": 6}},
                        },
                },
        } {
index 6ac37d6d8e64aa4d4d01c989d0e33cc2c308e50f..9a2761f510534bdb51b191b8288ef8433056d1d3 100644 (file)
@@ -6,8 +6,8 @@ import (
        "fmt"
        "sync"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hugo"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/common/types/css"
        "github.com/gohugoio/hugo/deps"
@@ -105,7 +105,7 @@ func (ns *Namespace) Sass(args ...any) (resource.Resource, error) {
        }
 
        if m != nil {
-               if t, _, found := maps.LookupEqualFold(m, "transpiler"); found {
+               if t, _, found := hmaps.LookupEqualFold(m, "transpiler"); found {
                        switch t {
                        case sass.TranspilerDart:
                                transpiler = cast.ToString(t)
index ca17968262de5e85e0f9da6e7cbfb51050612b4a..0de72ebbc7435432fb0c4db0bcb64bc1c991a5d9 100644 (file)
@@ -22,11 +22,12 @@ import (
        "errors"
        "fmt"
        "net/http"
+       "slices"
        "strings"
 
        "github.com/gohugoio/hugo/cache/filecache"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hugo"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/config/security"
 
        "github.com/gohugoio/hugo/common/types"
@@ -36,7 +37,6 @@ import (
        "github.com/spf13/cast"
 
        "github.com/gohugoio/hugo/deps"
-       "slices"
 )
 
 // New returns a new instance of the data-namespaced template functions.
@@ -185,7 +185,7 @@ func toURLAndHeaders(urlParts []any) (string, map[string]any) {
        }
 
        // The last argument may be a map.
-       headers, err := maps.ToStringMapE(urlParts[len(urlParts)-1])
+       headers, err := hmaps.ToStringMapE(urlParts[len(urlParts)-1])
        if err == nil {
                urlParts = urlParts[:len(urlParts)-1]
        } else {
index 7c49d80763ccdfa6bde3625964ec9d9453c4b363..d50c99384dd35af8810c1e872ef1dc611a36c09f 100644 (file)
@@ -23,7 +23,7 @@ import (
        "testing"
 
        "github.com/bep/logg"
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
 
        qt "github.com/frankban/quicktest"
 )
@@ -241,7 +241,7 @@ func TestHeaders(t *testing.T) {
                },
                {
                        `Params`,
-                       maps.Params{
+                       hmaps.Params{
                                "Accept-Charset": "utf-8",
                        },
                        func(c *qt.C, headers string) {
index f9102967ae34e1603ec75b6f5d4762b963f8bc2d..6ac0e4f1ecc70ad8cf16a181b3e1f6b6c9dfc9d4 100644 (file)
@@ -21,8 +21,8 @@ import (
        "html/template"
 
        bp "github.com/gohugoio/hugo/bufferpool"
+       "github.com/gohugoio/hugo/common/hmaps"
 
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/mitchellh/mapstructure"
        "github.com/spf13/cast"
 )
@@ -76,7 +76,7 @@ func (ns *Namespace) Jsonify(args ...any) (template.HTML, error) {
                obj = args[0]
        case 2:
                var m map[string]any
-               m, err = maps.ToStringMapE(args[0])
+               m, err = hmaps.ToStringMapE(args[0])
                if err != nil {
                        break
                }
index a777c8c3b1c9c93a271ed9856579d3a8d10bda7f..88635c6751e86dc5e59645760cb1edeff0751998 100644 (file)
@@ -19,7 +19,7 @@ import (
        "errors"
        "fmt"
 
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/resources"
 )
 
@@ -60,7 +60,7 @@ func ResolveArgs(args []any) (resources.ResourceTransformer, map[string]any, err
                return nil, nil, fmt.Errorf("type %T not supported in Resource transformations", args[0])
        }
 
-       m, err := maps.ToStringMapE(args[0])
+       m, err := hmaps.ToStringMapE(args[0])
        if err != nil {
                return nil, nil, fmt.Errorf("invalid options type: %w", err)
        }
index 4cadae52399aab06d068be97b9e11a0e417507e3..7fef754635f9348c467e8874d1329812a022388b 100644 (file)
@@ -27,7 +27,7 @@ import (
        kopenapi3 "github.com/getkin/kin-openapi/openapi3"
        "github.com/gohugoio/hugo/cache/dynacache"
        "github.com/gohugoio/hugo/common/hashing"
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/deps"
        "github.com/gohugoio/hugo/identity"
        "github.com/gohugoio/hugo/parser/metadecoders"
@@ -81,7 +81,7 @@ func (ns *Namespace) Unmarshal(ctx context.Context, args ...any) (*OpenAPIDocume
 
        var opts unmarshalOptions
        if len(args) > 1 {
-               optsm, err := maps.ToStringMapE(args[1])
+               optsm, err := hmaps.ToStringMapE(args[1])
                if err != nil {
                        return nil, err
                }
index f28cc36fe07cab59829195f512574cebd57a5017..da537ab99cdf1eff7f72a6027c3a4d6a204ccc49 100644 (file)
@@ -19,8 +19,8 @@ import (
        "errors"
        "fmt"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hugo"
-       "github.com/gohugoio/hugo/common/maps"
 
        "github.com/gohugoio/hugo/tpl/css"
        "github.com/gohugoio/hugo/tpl/js"
@@ -129,7 +129,7 @@ func (ns *Namespace) GetRemote(args ...any) (resource.Resource, error) {
                var options map[string]any
 
                if len(args) > 1 {
-                       options, err = maps.ToStringMapE(args[1])
+                       options, err = hmaps.ToStringMapE(args[1])
                        if err != nil {
                                return nil, err
                        }
index 18d4d4a279672841d5bdebff253d9d1ed2f147da..43a8bdfbe67ef64489b48177159e03ee61594fae 100644 (file)
@@ -20,8 +20,8 @@ import (
        "reflect"
        "strings"
 
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hreflect"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/identity"
        "github.com/gohugoio/hugo/tpl"
 
@@ -68,7 +68,7 @@ func (t *templateExecHelper) Init(ctx context.Context, tmpl texttemplate.Prepare
 }
 
 func (t *templateExecHelper) GetMapValue(ctx context.Context, tmpl texttemplate.Preparer, receiver, key reflect.Value) (reflect.Value, bool) {
-       if params, ok := receiver.Interface().(maps.Params); ok {
+       if params, ok := receiver.Interface().(hmaps.Params); ok {
                // Case insensitive.
                keystr := strings.ToLower(key.String())
                v, found := params[keystr]
@@ -83,7 +83,7 @@ func (t *templateExecHelper) GetMapValue(ctx context.Context, tmpl texttemplate.
        return v, v.IsValid()
 }
 
-var typeParams = reflect.TypeOf(maps.Params{})
+var typeParams = reflect.TypeOf(hmaps.Params{})
 
 func (t *templateExecHelper) GetMethod(ctx context.Context, tmpl texttemplate.Preparer, receiver reflect.Value, name string) (method reflect.Value, firstArg reflect.Value) {
        if strings.EqualFold(name, "mainsections") && receiver.Type() == typeParams && receiver.Pointer() == t.siteParams.Pointer() {
index 48f3139b93dfce352f5d5faeddecea082352d287..944a0953fd36329911e08fd9860d0f8b5c60bfd7 100644 (file)
@@ -37,9 +37,9 @@ import (
 
        "github.com/gohugoio/hugo/common/collections"
        "github.com/gohugoio/hugo/common/herrors"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/common/hstrings"
        "github.com/gohugoio/hugo/common/loggers"
-       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/common/paths"
        "github.com/gohugoio/hugo/helpers"
        "github.com/gohugoio/hugo/hugofs"
@@ -126,10 +126,10 @@ func NewStore(opts StoreOptions, siteOpts SiteOptions) (*TemplateStore, error) {
                storeSite:            configureSiteStorage(siteOpts, opts.Watching),
                treeMain:             doctree.NewSimpleTree[map[nodeKey]*TemplInfo](),
                treeShortcodes:       doctree.NewSimpleTree[map[string]map[TemplateDescriptor]*TemplInfo](),
-               templatesByPath:      maps.NewCache[string, *TemplInfo](),
-               shortcodesByName:     maps.NewCache[string, *TemplInfo](),
-               cacheLookupPartials:  maps.NewCache[string, *TemplInfo](),
-               templatesSnapshotSet: maps.NewCache[*parse.Tree, struct{}](),
+               templatesByPath:      hmaps.NewCache[string, *TemplInfo](),
+               shortcodesByName:     hmaps.NewCache[string, *TemplInfo](),
+               cacheLookupPartials:  hmaps.NewCache[string, *TemplInfo](),
+               templatesSnapshotSet: hmaps.NewCache[*parse.Tree, struct{}](),
 
                // Note that the funcs passed below is just for name validation.
                tns: newTemplateNamespace(siteOpts.TemplateFuncs),
@@ -437,9 +437,9 @@ type TemplateStore struct {
 
        treeMain             *doctree.SimpleTree[map[nodeKey]*TemplInfo]
        treeShortcodes       *doctree.SimpleTree[map[string]map[TemplateDescriptor]*TemplInfo]
-       templatesByPath      *maps.Cache[string, *TemplInfo]
-       shortcodesByName     *maps.Cache[string, *TemplInfo]
-       templatesSnapshotSet *maps.Cache[*parse.Tree, struct{}]
+       templatesByPath      *hmaps.Cache[string, *TemplInfo]
+       shortcodesByName     *hmaps.Cache[string, *TemplInfo]
+       templatesSnapshotSet *hmaps.Cache[*parse.Tree, struct{}]
 
        dh descriptorHandler
 
@@ -455,7 +455,7 @@ type TemplateStore struct {
        siteOptsOrig SiteOptions
 
        // caches. These need to be refreshed when the templates are refreshed.
-       cacheLookupPartials *maps.Cache[string, *TemplInfo]
+       cacheLookupPartials *hmaps.Cache[string, *TemplInfo]
 }
 
 // NewFromOpts creates a new store with the same configuration as the original.
index 6ace0f109e93f0394c7e9a67c83da711f485869b..ffb859b3ea9000e754d153cfeef12789c4217ac6 100644 (file)
@@ -13,7 +13,7 @@ import (
        texttemplate "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate"
 
        "github.com/gohugoio/hugo/common/hashing"
-       "github.com/gohugoio/hugo/common/maps"
+       "github.com/gohugoio/hugo/common/hmaps"
        "github.com/gohugoio/hugo/tpl"
        "github.com/mitchellh/mapstructure"
 )
@@ -478,7 +478,7 @@ func (c *templateTransformContext) collectConfig(n *parse.PipeNode) {
 
        if s, ok := cmd.Args[0].(*parse.StringNode); ok {
                errMsg := "failed to decode $_hugo_config in template: %w"
-               m, err := maps.ToStringMapE(s.Text)
+               m, err := hmaps.ToStringMapE(s.Text)
                if err != nil {
                        c.err = fmt.Errorf(errMsg, err)
                        return