@bookshop/hugo-engine 3.3.2 → 3.4.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/.nyc_output/{396c364e-fec4-4f27-9ff2-8b236061ef8f.json → 0f70a16f-6a79-48c7-8b16-3b4665e247b2.json} +0 -0
  2. package/.nyc_output/{4ef43740-059b-4329-96cd-0643fd8fe8d8.json → 6285d5fa-be3d-49e4-8f2f-82157d95dcd8.json} +0 -0
  3. package/.nyc_output/{656275f4-66d6-4d27-bfab-c2f7a3087670.json → 8b5e1314-6e86-4197-a3ae-3c40e4c2f39e.json} +0 -0
  4. package/.nyc_output/{6aec5420-0b83-4260-b300-4d595dfd0660.json → c5490eb0-70c0-468f-a43f-e58c75dd34c8.json} +0 -0
  5. package/.nyc_output/{874bd79b-45da-4726-9afc-1f6cab44be1f.json → ee1a9bec-d318-4aea-af93-7269debcf6df.json} +0 -0
  6. package/.nyc_output/processinfo/{396c364e-fec4-4f27-9ff2-8b236061ef8f.json → 0f70a16f-6a79-48c7-8b16-3b4665e247b2.json} +1 -1
  7. package/.nyc_output/processinfo/6285d5fa-be3d-49e4-8f2f-82157d95dcd8.json +1 -0
  8. package/.nyc_output/processinfo/{4ef43740-059b-4329-96cd-0643fd8fe8d8.json → 8b5e1314-6e86-4197-a3ae-3c40e4c2f39e.json} +1 -1
  9. package/.nyc_output/processinfo/{656275f4-66d6-4d27-bfab-c2f7a3087670.json → c5490eb0-70c0-468f-a43f-e58c75dd34c8.json} +1 -1
  10. package/.nyc_output/processinfo/{874bd79b-45da-4726-9afc-1f6cab44be1f.json → ee1a9bec-d318-4aea-af93-7269debcf6df.json} +1 -1
  11. package/.nyc_output/processinfo/index.json +1 -1
  12. package/bookshop-hugo-templates/bookshop.html +56 -0
  13. package/bookshop-hugo-templates/bookshop_bindings.html +29 -0
  14. package/bookshop-hugo-templates/bookshop_component_browser.html +30 -0
  15. package/bookshop-hugo-templates/bookshop_partial.html +42 -0
  16. package/bookshop-hugo-templates/bookshop_scss.html +9 -0
  17. package/bookshop-hugo-templates/errors/bad_bookshop_tag.html +39 -0
  18. package/bookshop-hugo-templates/errors/err.html +6 -0
  19. package/bookshop-hugo-templates/helpers/component.html +25 -0
  20. package/bookshop-hugo-templates/helpers/component_key.html +11 -0
  21. package/bookshop-hugo-templates/helpers/partial.html +25 -0
  22. package/bookshop-hugo-templates/helpers/partial_key.html +9 -0
  23. package/full-hugo-renderer/build.sh +34 -0
  24. package/full-hugo-renderer/go.mod +87 -0
  25. package/{hugo-renderer → full-hugo-renderer}/go.sum +204 -12
  26. package/full-hugo-renderer/hugo_renderer.wasm +0 -0
  27. package/full-hugo-renderer/hugo_renderer.wasm.gz +0 -0
  28. package/full-hugo-renderer/main.go +215 -0
  29. package/{hugo-renderer → full-hugo-renderer}/wasm_exec.js +6 -2
  30. package/lib/builder.js +2 -2
  31. package/lib/engine.js +109 -42
  32. package/lib/hugoIdentifierParser.js +5 -0
  33. package/lib/translateTextTemplate.js +3 -0
  34. package/lib/translateTextTemplate.test.js +22 -16
  35. package/package.json +4 -4
  36. package/.nyc_output/processinfo/6aec5420-0b83-4260-b300-4d595dfd0660.json +0 -1
  37. package/hugo-renderer/build.sh +0 -66
  38. package/hugo-renderer/deps/bookshop_modified_deps.go +0 -6
  39. package/hugo-renderer/go.mod +0 -19
  40. package/hugo-renderer/helpers/bookshop_modified_content.go +0 -98
  41. package/hugo-renderer/helpers/bookshop_modified_general.go +0 -33
  42. package/hugo-renderer/helpers/emoji.go +0 -96
  43. package/hugo-renderer/hugo_renderer.wasm +0 -0
  44. package/hugo-renderer/hugo_renderer.wasm.gz +0 -0
  45. package/hugo-renderer/main.go +0 -42
  46. package/hugo-renderer/tpl/bookshop_engine/bookshop_func_importer.go +0 -35
  47. package/hugo-renderer/tpl/bookshop_engine/bookshop_render.go +0 -64
  48. package/hugo-renderer/tpl/bookshop_library/bookshop_components.go +0 -129
  49. package/hugo-renderer/tpl/bookshop_library/bookshop_data.go +0 -53
  50. package/hugo-renderer/tpl/cast/cast.go +0 -63
  51. package/hugo-renderer/tpl/cast/init.go +0 -57
  52. package/hugo-renderer/tpl/collections/append.go +0 -37
  53. package/hugo-renderer/tpl/collections/apply.go +0 -131
  54. package/hugo-renderer/tpl/collections/collections.go +0 -768
  55. package/hugo-renderer/tpl/collections/complement.go +0 -55
  56. package/hugo-renderer/tpl/collections/index.go +0 -133
  57. package/hugo-renderer/tpl/collections/init.go +0 -214
  58. package/hugo-renderer/tpl/collections/merge.go +0 -126
  59. package/hugo-renderer/tpl/collections/reflect_helpers.go +0 -216
  60. package/hugo-renderer/tpl/collections/sort.go +0 -183
  61. package/hugo-renderer/tpl/collections/symdiff.go +0 -68
  62. package/hugo-renderer/tpl/collections/where.go +0 -517
  63. package/hugo-renderer/tpl/compare/compare.go +0 -324
  64. package/hugo-renderer/tpl/compare/init.go +0 -85
  65. package/hugo-renderer/tpl/crypto/crypto.go +0 -109
  66. package/hugo-renderer/tpl/crypto/init.go +0 -65
  67. package/hugo-renderer/tpl/debug/debug.go +0 -40
  68. package/hugo-renderer/tpl/debug/init.go +0 -45
  69. package/hugo-renderer/tpl/encoding/encoding.go +0 -90
  70. package/hugo-renderer/tpl/encoding/init.go +0 -59
  71. package/hugo-renderer/tpl/fmt/fmt.go +0 -66
  72. package/hugo-renderer/tpl/fmt/init.go +0 -77
  73. package/hugo-renderer/tpl/inflect/inflect.go +0 -79
  74. package/hugo-renderer/tpl/inflect/init.go +0 -60
  75. package/hugo-renderer/tpl/internal/bookshop_modified_templatefuncsRegistry.go +0 -88
  76. package/hugo-renderer/tpl/math/init.go +0 -134
  77. package/hugo-renderer/tpl/math/math.go +0 -164
  78. package/hugo-renderer/tpl/math/round.go +0 -61
  79. package/hugo-renderer/tpl/partials/init.go +0 -55
  80. package/hugo-renderer/tpl/partials/partials.go +0 -88
  81. package/hugo-renderer/tpl/path/init.go +0 -60
  82. package/hugo-renderer/tpl/path/path.go +0 -159
  83. package/hugo-renderer/tpl/reflect/init.go +0 -51
  84. package/hugo-renderer/tpl/reflect/reflect.go +0 -36
  85. package/hugo-renderer/tpl/safe/init.go +0 -80
  86. package/hugo-renderer/tpl/safe/safe.go +0 -72
  87. package/hugo-renderer/tpl/site/bookshop_site.go +0 -67
  88. package/hugo-renderer/tpl/site/init.go +0 -41
  89. package/hugo-renderer/tpl/strings/init.go +0 -229
  90. package/hugo-renderer/tpl/strings/regexp.go +0 -125
  91. package/hugo-renderer/tpl/strings/strings.go +0 -500
  92. package/hugo-renderer/tpl/strings/truncate.go +0 -157
  93. package/hugo-renderer/tpl/transform/bookshop_unmarshal.go +0 -39
  94. package/hugo-renderer/tpl/transform/init.go +0 -113
  95. package/hugo-renderer/tpl/transform/transform.go +0 -116
  96. package/hugo-renderer/update-from-hugo.sh +0 -19
@@ -1,55 +0,0 @@
1
- // Copyright 2018 The Hugo Authors. All rights reserved.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- // http://www.apache.org/licenses/LICENSE-2.0
7
- //
8
- // Unless required by applicable law or agreed to in writing, software
9
- // distributed under the License is distributed on an "AS IS" BASIS,
10
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
- // See the License for the specific language governing permissions and
12
- // limitations under the License.
13
-
14
- package collections
15
-
16
- import (
17
- "errors"
18
- "fmt"
19
- "reflect"
20
- )
21
-
22
- // Complement gives the elements in the last element of seqs that are not in
23
- // any of the others.
24
- // All elements of seqs must be slices or arrays of comparable types.
25
- //
26
- // The reasoning behind this rather clumsy API is so we can do this in the templates:
27
- // {{ $c := .Pages | complement $last4 }}
28
- func (ns *Namespace) Complement(seqs ...interface{}) (interface{}, error) {
29
- if len(seqs) < 2 {
30
- return nil, errors.New("complement needs at least two arguments")
31
- }
32
-
33
- universe := seqs[len(seqs)-1]
34
- as := seqs[:len(seqs)-1]
35
-
36
- aset, err := collectIdentities(as...)
37
- if err != nil {
38
- return nil, err
39
- }
40
-
41
- v := reflect.ValueOf(universe)
42
- switch v.Kind() {
43
- case reflect.Array, reflect.Slice:
44
- sl := reflect.MakeSlice(v.Type(), 0, 0)
45
- for i := 0; i < v.Len(); i++ {
46
- ev, _ := indirectInterface(v.Index(i))
47
- if _, found := aset[normalize(ev)]; !found {
48
- sl = reflect.Append(sl, ev)
49
- }
50
- }
51
- return sl.Interface(), nil
52
- default:
53
- return nil, fmt.Errorf("arguments to complement must be slices or arrays")
54
- }
55
- }
@@ -1,133 +0,0 @@
1
- // Copyright 2017 The Hugo Authors. All rights reserved.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- // http://www.apache.org/licenses/LICENSE-2.0
7
- //
8
- // Unless required by applicable law or agreed to in writing, software
9
- // distributed under the License is distributed on an "AS IS" BASIS,
10
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
- // See the License for the specific language governing permissions and
12
- // limitations under the License.
13
-
14
- package collections
15
-
16
- import (
17
- "errors"
18
- "fmt"
19
- "reflect"
20
-
21
- "github.com/spf13/cast"
22
-
23
- "github.com/gohugoio/hugo/common/maps"
24
- )
25
-
26
- // Index returns the result of indexing its first argument by the following
27
- // arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each
28
- // indexed item must be a map, slice, or array.
29
- //
30
- // Copied from Go stdlib src/text/template/funcs.go.
31
- //
32
- // We deviate from the stdlib due to https://github.com/golang/go/issues/14751.
33
- //
34
- // TODO(moorereason): merge upstream changes.
35
- func (ns *Namespace) Index(item interface{}, args ...interface{}) (interface{}, error) {
36
- v := reflect.ValueOf(item)
37
- if !v.IsValid() {
38
- return nil, errors.New("index of untyped nil")
39
- }
40
-
41
- lowerm, ok := item.(maps.Params)
42
- if ok {
43
- return lowerm.Get(cast.ToStringSlice(args)...), nil
44
- }
45
-
46
- var indices []interface{}
47
-
48
- if len(args) == 1 {
49
- v := reflect.ValueOf(args[0])
50
- if v.Kind() == reflect.Slice {
51
- for i := 0; i < v.Len(); i++ {
52
- indices = append(indices, v.Index(i).Interface())
53
- }
54
- }
55
- }
56
-
57
- if indices == nil {
58
- indices = args
59
- }
60
-
61
- for _, i := range indices {
62
- index := reflect.ValueOf(i)
63
- var isNil bool
64
- if v, isNil = indirect(v); isNil {
65
- return nil, errors.New("index of nil pointer")
66
- }
67
- switch v.Kind() {
68
- case reflect.Array, reflect.Slice, reflect.String:
69
- var x int64
70
- switch index.Kind() {
71
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
72
- x = index.Int()
73
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
74
- x = int64(index.Uint())
75
- case reflect.Invalid:
76
- return nil, errors.New("cannot index slice/array with nil")
77
- default:
78
- return nil, fmt.Errorf("cannot index slice/array with type %s", index.Type())
79
- }
80
- if x < 0 || x >= int64(v.Len()) {
81
- // We deviate from stdlib here. Don't return an error if the
82
- // index is out of range.
83
- return nil, nil
84
- }
85
- v = v.Index(int(x))
86
- case reflect.Map:
87
- index, err := prepareArg(index, v.Type().Key())
88
- if err != nil {
89
- return nil, err
90
- }
91
-
92
- if x := v.MapIndex(index); x.IsValid() {
93
- v = x
94
- } else {
95
- v = reflect.Zero(v.Type().Elem())
96
- }
97
- case reflect.Invalid:
98
- // the loop holds invariant: v.IsValid()
99
- panic("unreachable")
100
- default:
101
- return nil, fmt.Errorf("can't index item of type %s", v.Type())
102
- }
103
- }
104
- return v.Interface(), nil
105
- }
106
-
107
- // prepareArg checks if value can be used as an argument of type argType, and
108
- // converts an invalid value to appropriate zero if possible.
109
- //
110
- // Copied from Go stdlib src/text/template/funcs.go.
111
- func prepareArg(value reflect.Value, argType reflect.Type) (reflect.Value, error) {
112
- if !value.IsValid() {
113
- if !canBeNil(argType) {
114
- return reflect.Value{}, fmt.Errorf("value is nil; should be of type %s", argType)
115
- }
116
- value = reflect.Zero(argType)
117
- }
118
- if !value.Type().AssignableTo(argType) {
119
- return reflect.Value{}, fmt.Errorf("value has type %s; should be %s", value.Type(), argType)
120
- }
121
- return value, nil
122
- }
123
-
124
- // canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero.
125
- //
126
- // Copied from Go stdlib src/text/template/exec.go.
127
- func canBeNil(typ reflect.Type) bool {
128
- switch typ.Kind() {
129
- case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
130
- return true
131
- }
132
- return false
133
- }
@@ -1,214 +0,0 @@
1
- // Copyright 2017 The Hugo Authors. All rights reserved.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- // http://www.apache.org/licenses/LICENSE-2.0
7
- //
8
- // Unless required by applicable law or agreed to in writing, software
9
- // distributed under the License is distributed on an "AS IS" BASIS,
10
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
- // See the License for the specific language governing permissions and
12
- // limitations under the License.
13
-
14
- package collections
15
-
16
- import (
17
- "hugo-renderer/deps"
18
- "hugo-renderer/tpl/internal"
19
- )
20
-
21
- const name = "collections"
22
-
23
- func init() {
24
- f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
25
- ctx := New(d)
26
-
27
- ns := &internal.TemplateFuncsNamespace{
28
- Name: name,
29
- Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
30
- }
31
-
32
- ns.AddMethodMapping(ctx.After,
33
- []string{"after"},
34
- [][2]string{},
35
- )
36
-
37
- ns.AddMethodMapping(ctx.Apply,
38
- []string{"apply"},
39
- [][2]string{},
40
- )
41
-
42
- ns.AddMethodMapping(ctx.Complement,
43
- []string{"complement"},
44
- [][2]string{
45
- {`{{ slice "a" "b" "c" "d" "e" "f" | complement (slice "b" "c") (slice "d" "e") }}`, `[a f]`},
46
- },
47
- )
48
-
49
- ns.AddMethodMapping(ctx.SymDiff,
50
- []string{"symdiff"},
51
- [][2]string{
52
- {`{{ slice 1 2 3 | symdiff (slice 3 4) }}`, `[1 2 4]`},
53
- },
54
- )
55
-
56
- ns.AddMethodMapping(ctx.Delimit,
57
- []string{"delimit"},
58
- [][2]string{
59
- {`{{ delimit (slice "A" "B" "C") ", " " and " }}`, `A, B and C`},
60
- },
61
- )
62
-
63
- ns.AddMethodMapping(ctx.Dictionary,
64
- []string{"dict"},
65
- [][2]string{},
66
- )
67
-
68
- ns.AddMethodMapping(ctx.EchoParam,
69
- []string{"echoParam"},
70
- [][2]string{
71
- {`{{ echoParam .Params "langCode" }}`, `en`},
72
- },
73
- )
74
-
75
- ns.AddMethodMapping(ctx.First,
76
- []string{"first"},
77
- [][2]string{},
78
- )
79
-
80
- ns.AddMethodMapping(ctx.KeyVals,
81
- []string{"keyVals"},
82
- [][2]string{
83
- {`{{ keyVals "key" "a" "b" }}`, `key: [a b]`},
84
- },
85
- )
86
-
87
- ns.AddMethodMapping(ctx.In,
88
- []string{"in"},
89
- [][2]string{
90
- {`{{ if in "this string contains a substring" "substring" }}Substring found!{{ end }}`, `Substring found!`},
91
- },
92
- )
93
-
94
- ns.AddMethodMapping(ctx.Index,
95
- []string{"index"},
96
- [][2]string{},
97
- )
98
-
99
- ns.AddMethodMapping(ctx.Intersect,
100
- []string{"intersect"},
101
- [][2]string{},
102
- )
103
-
104
- ns.AddMethodMapping(ctx.IsSet,
105
- []string{"isSet", "isset"},
106
- [][2]string{},
107
- )
108
-
109
- ns.AddMethodMapping(ctx.Last,
110
- []string{"last"},
111
- [][2]string{},
112
- )
113
-
114
- ns.AddMethodMapping(ctx.Querify,
115
- []string{"querify"},
116
- [][2]string{
117
- {
118
- `{{ (querify "foo" 1 "bar" 2 "baz" "with spaces" "qux" "this&that=those") | safeHTML }}`,
119
- `bar=2&baz=with+spaces&foo=1&qux=this%26that%3Dthose`,
120
- },
121
- {
122
- `<a href="https://www.google.com?{{ (querify "q" "test" "page" 3) | safeURL }}">Search</a>`,
123
- `<a href="https://www.google.com?page=3&amp;q=test">Search</a>`,
124
- },
125
- {
126
- `{{ slice "foo" 1 "bar" 2 | querify | safeHTML }}`,
127
- `bar=2&foo=1`,
128
- },
129
- },
130
- )
131
-
132
- ns.AddMethodMapping(ctx.Shuffle,
133
- []string{"shuffle"},
134
- [][2]string{},
135
- )
136
-
137
- ns.AddMethodMapping(ctx.Slice,
138
- []string{"slice"},
139
- [][2]string{
140
- {`{{ slice "B" "C" "A" | sort }}`, `[A B C]`},
141
- },
142
- )
143
-
144
- ns.AddMethodMapping(ctx.Sort,
145
- []string{"sort"},
146
- [][2]string{},
147
- )
148
-
149
- ns.AddMethodMapping(ctx.Union,
150
- []string{"union"},
151
- [][2]string{
152
- {`{{ union (slice 1 2 3) (slice 3 4 5) }}`, `[1 2 3 4 5]`},
153
- },
154
- )
155
-
156
- ns.AddMethodMapping(ctx.Where,
157
- []string{"where"},
158
- [][2]string{},
159
- )
160
-
161
- ns.AddMethodMapping(ctx.Append,
162
- []string{"append"},
163
- [][2]string{},
164
- )
165
-
166
- ns.AddMethodMapping(ctx.Group,
167
- []string{"group"},
168
- [][2]string{},
169
- )
170
-
171
- ns.AddMethodMapping(ctx.Seq,
172
- []string{"seq"},
173
- [][2]string{
174
- {`{{ seq 3 }}`, `[1 2 3]`},
175
- },
176
- )
177
-
178
- ns.AddMethodMapping(ctx.NewScratch,
179
- []string{"newScratch"},
180
- [][2]string{
181
- {`{{ $scratch := newScratch }}{{ $scratch.Add "b" 2 }}{{ $scratch.Add "b" 2 }}{{ $scratch.Get "b" }}`, `4`},
182
- },
183
- )
184
-
185
- ns.AddMethodMapping(ctx.Uniq,
186
- []string{"uniq"},
187
- [][2]string{
188
- {`{{ slice 1 2 3 2 | uniq }}`, `[1 2 3]`},
189
- },
190
- )
191
-
192
- ns.AddMethodMapping(ctx.Merge,
193
- []string{"merge"},
194
- [][2]string{
195
- {
196
- `{{ dict "title" "Hugo Rocks!" | collections.Merge (dict "title" "Default Title" "description" "Yes, Hugo Rocks!") | sort }}`,
197
- `[Yes, Hugo Rocks! Hugo Rocks!]`,
198
- },
199
- {
200
- `{{ merge (dict "title" "Default Title" "description" "Yes, Hugo Rocks!") (dict "title" "Hugo Rocks!") | sort }}`,
201
- `[Yes, Hugo Rocks! Hugo Rocks!]`,
202
- },
203
- {
204
- `{{ merge (dict "title" "Default Title" "description" "Yes, Hugo Rocks!") (dict "title" "Hugo Rocks!") (dict "extra" "For reals!") | sort }}`,
205
- `[Yes, Hugo Rocks! For reals! Hugo Rocks!]`,
206
- },
207
- },
208
- )
209
-
210
- return ns
211
- }
212
-
213
- internal.AddTemplateFuncsNamespace(f)
214
- }
@@ -1,126 +0,0 @@
1
- // Copyright 2019 The Hugo Authors. All rights reserved.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- // http://www.apache.org/licenses/LICENSE-2.0
7
- //
8
- // Unless required by applicable law or agreed to in writing, software
9
- // distributed under the License is distributed on an "AS IS" BASIS,
10
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
- // See the License for the specific language governing permissions and
12
- // limitations under the License.
13
-
14
- package collections
15
-
16
- import (
17
- "reflect"
18
- "strings"
19
-
20
- "github.com/gohugoio/hugo/common/hreflect"
21
- "github.com/gohugoio/hugo/common/maps"
22
-
23
- "github.com/pkg/errors"
24
- )
25
-
26
- // Merge creates a copy of the final parameter and merges the preceding
27
- // parameters into it in reverse order.
28
- // Currently only maps are supported. Key handling is case insensitive.
29
- func (ns *Namespace) Merge(params ...interface{}) (interface{}, error) {
30
- if len(params) < 2 {
31
- return nil, errors.New("merge requires at least two parameters")
32
- }
33
-
34
- var err error
35
- result := params[len(params)-1]
36
-
37
- for i := len(params) - 2; i >= 0; i-- {
38
- result, err = ns.merge(params[i], result)
39
- if err != nil {
40
- return nil, err
41
- }
42
- }
43
-
44
- return result, nil
45
- }
46
-
47
- // merge creates a copy of dst and merges src into it.
48
- func (ns *Namespace) merge(src, dst interface{}) (interface{}, error) {
49
- vdst, vsrc := reflect.ValueOf(dst), reflect.ValueOf(src)
50
-
51
- if vdst.Kind() != reflect.Map {
52
- return nil, errors.Errorf("destination must be a map, got %T", dst)
53
- }
54
-
55
- if !hreflect.IsTruthfulValue(vsrc) {
56
- return dst, nil
57
- }
58
-
59
- if vsrc.Kind() != reflect.Map {
60
- return nil, errors.Errorf("source must be a map, got %T", src)
61
- }
62
-
63
- if vsrc.Type().Key() != vdst.Type().Key() {
64
- return nil, errors.Errorf("incompatible map types, got %T to %T", src, dst)
65
- }
66
-
67
- return mergeMap(vdst, vsrc).Interface(), nil
68
- }
69
-
70
- func caseInsensitiveLookup(m, k reflect.Value) (reflect.Value, bool) {
71
- if m.Type().Key().Kind() != reflect.String || k.Kind() != reflect.String {
72
- // Fall back to direct lookup.
73
- v := m.MapIndex(k)
74
- return v, hreflect.IsTruthfulValue(v)
75
- }
76
-
77
- for _, key := range m.MapKeys() {
78
- if strings.EqualFold(k.String(), key.String()) {
79
- return m.MapIndex(key), true
80
- }
81
- }
82
-
83
- return reflect.Value{}, false
84
- }
85
-
86
- func mergeMap(dst, src reflect.Value) reflect.Value {
87
- out := reflect.MakeMap(dst.Type())
88
-
89
- // If the destination is Params, we must lower case all keys.
90
- _, lowerCase := dst.Interface().(maps.Params)
91
-
92
- // Copy the destination map.
93
- for _, key := range dst.MapKeys() {
94
- v := dst.MapIndex(key)
95
- out.SetMapIndex(key, v)
96
- }
97
-
98
- // Add all keys in src not already in destination.
99
- // Maps of the same type will be merged.
100
- for _, key := range src.MapKeys() {
101
- sv := src.MapIndex(key)
102
- dv, found := caseInsensitiveLookup(dst, key)
103
-
104
- if found {
105
- // If both are the same map key type, merge.
106
- dve := dv.Elem()
107
- if dve.Kind() == reflect.Map {
108
- sve := sv.Elem()
109
- if sve.Kind() != reflect.Map {
110
- continue
111
- }
112
-
113
- if dve.Type().Key() == sve.Type().Key() {
114
- out.SetMapIndex(key, mergeMap(dve, sve))
115
- }
116
- }
117
- } else {
118
- if lowerCase && key.Kind() == reflect.String {
119
- key = reflect.ValueOf(strings.ToLower(key.String()))
120
- }
121
- out.SetMapIndex(key, sv)
122
- }
123
- }
124
-
125
- return out
126
- }