@bookshop/hugo-engine 3.3.3 → 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/{25f8c04a-7fe3-4d10-b99e-0688e18203ec.json → 0f70a16f-6a79-48c7-8b16-3b4665e247b2.json} +0 -0
  2. package/.nyc_output/{2c3e7d19-6b44-48be-857a-ceba6bb9bf99.json → 6285d5fa-be3d-49e4-8f2f-82157d95dcd8.json} +0 -0
  3. package/.nyc_output/{5429d932-0ea0-4757-b731-0a647f4adc5f.json → 8b5e1314-6e86-4197-a3ae-3c40e4c2f39e.json} +0 -0
  4. package/.nyc_output/{723f5a1e-49f4-48c2-8a96-069bb758bb7f.json → c5490eb0-70c0-468f-a43f-e58c75dd34c8.json} +0 -0
  5. package/.nyc_output/{e4df4511-7e66-4fa6-84ed-6bd96e3027fe.json → ee1a9bec-d318-4aea-af93-7269debcf6df.json} +0 -0
  6. package/.nyc_output/processinfo/{25f8c04a-7fe3-4d10-b99e-0688e18203ec.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/{2c3e7d19-6b44-48be-857a-ceba6bb9bf99.json → 8b5e1314-6e86-4197-a3ae-3c40e4c2f39e.json} +1 -1
  9. package/.nyc_output/processinfo/{5429d932-0ea0-4757-b731-0a647f4adc5f.json → c5490eb0-70c0-468f-a43f-e58c75dd34c8.json} +1 -1
  10. package/.nyc_output/processinfo/{723f5a1e-49f4-48c2-8a96-069bb758bb7f.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/e4df4511-7e66-4fa6-84ed-6bd96e3027fe.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,768 +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 provides template functions for manipulating collections
15
- // such as arrays, maps, and slices.
16
- package collections
17
-
18
- import (
19
- "fmt"
20
- "html/template"
21
- "math/rand"
22
- "net/url"
23
- "reflect"
24
- "strings"
25
- "time"
26
-
27
- "hugo-renderer/deps"
28
-
29
- "github.com/gohugoio/hugo/common/collections"
30
- "github.com/gohugoio/hugo/common/maps"
31
- "github.com/gohugoio/hugo/common/types"
32
- "github.com/pkg/errors"
33
- "github.com/spf13/cast"
34
- )
35
-
36
- func init() {
37
- rand.Seed(time.Now().UTC().UnixNano())
38
- }
39
-
40
- // New returns a new instance of the collections-namespaced template functions.
41
- func New(deps *deps.Deps) *Namespace {
42
- return &Namespace{
43
- deps: deps,
44
- }
45
- }
46
-
47
- // Namespace provides template functions for the "collections" namespace.
48
- type Namespace struct {
49
- deps *deps.Deps
50
- }
51
-
52
- // After returns all the items after the first N in a rangeable list.
53
- func (ns *Namespace) After(index interface{}, seq interface{}) (interface{}, error) {
54
- if index == nil || seq == nil {
55
- return nil, errors.New("both limit and seq must be provided")
56
- }
57
-
58
- indexv, err := cast.ToIntE(index)
59
- if err != nil {
60
- return nil, err
61
- }
62
-
63
- if indexv < 0 {
64
- return nil, errors.New("sequence bounds out of range [" + cast.ToString(indexv) + ":]")
65
- }
66
-
67
- seqv := reflect.ValueOf(seq)
68
- seqv, isNil := indirect(seqv)
69
- if isNil {
70
- return nil, errors.New("can't iterate over a nil value")
71
- }
72
-
73
- switch seqv.Kind() {
74
- case reflect.Array, reflect.Slice, reflect.String:
75
- // okay
76
- default:
77
- return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
78
- }
79
-
80
- if indexv >= seqv.Len() {
81
- return seqv.Slice(0, 0).Interface(), nil
82
- }
83
-
84
- return seqv.Slice(indexv, seqv.Len()).Interface(), nil
85
- }
86
-
87
- // Delimit takes a given sequence and returns a delimited HTML string.
88
- // If last is passed to the function, it will be used as the final delimiter.
89
- func (ns *Namespace) Delimit(seq, delimiter interface{}, last ...interface{}) (template.HTML, error) {
90
- d, err := cast.ToStringE(delimiter)
91
- if err != nil {
92
- return "", err
93
- }
94
-
95
- var dLast *string
96
- if len(last) > 0 {
97
- l := last[0]
98
- dStr, err := cast.ToStringE(l)
99
- if err != nil {
100
- dLast = nil
101
- } else {
102
- dLast = &dStr
103
- }
104
- }
105
-
106
- seqv := reflect.ValueOf(seq)
107
- seqv, isNil := indirect(seqv)
108
- if isNil {
109
- return "", errors.New("can't iterate over a nil value")
110
- }
111
-
112
- var str string
113
- switch seqv.Kind() {
114
- case reflect.Map:
115
- sortSeq, err := ns.Sort(seq)
116
- if err != nil {
117
- return "", err
118
- }
119
- seqv = reflect.ValueOf(sortSeq)
120
- fallthrough
121
- case reflect.Array, reflect.Slice, reflect.String:
122
- for i := 0; i < seqv.Len(); i++ {
123
- val := seqv.Index(i).Interface()
124
- valStr, err := cast.ToStringE(val)
125
- if err != nil {
126
- continue
127
- }
128
- switch {
129
- case i == seqv.Len()-2 && dLast != nil:
130
- str += valStr + *dLast
131
- case i == seqv.Len()-1:
132
- str += valStr
133
- default:
134
- str += valStr + d
135
- }
136
- }
137
-
138
- default:
139
- return "", fmt.Errorf("can't iterate over %v", seq)
140
- }
141
-
142
- return template.HTML(str), nil
143
- }
144
-
145
- // Dictionary creates a map[string]interface{} from the given parameters by
146
- // walking the parameters and treating them as key-value pairs. The number
147
- // of parameters must be even.
148
- // The keys can be string slices, which will create the needed nested structure.
149
- func (ns *Namespace) Dictionary(values ...interface{}) (map[string]interface{}, error) {
150
- if len(values)%2 != 0 {
151
- return nil, errors.New("invalid dictionary call")
152
- }
153
-
154
- root := make(map[string]interface{})
155
-
156
- for i := 0; i < len(values); i += 2 {
157
- dict := root
158
- var key string
159
- switch v := values[i].(type) {
160
- case string:
161
- key = v
162
- case []string:
163
- for i := 0; i < len(v)-1; i++ {
164
- key = v[i]
165
- var m map[string]interface{}
166
- v, found := dict[key]
167
- if found {
168
- m = v.(map[string]interface{})
169
- } else {
170
- m = make(map[string]interface{})
171
- dict[key] = m
172
- }
173
- dict = m
174
- }
175
- key = v[len(v)-1]
176
- default:
177
- return nil, errors.New("invalid dictionary key")
178
- }
179
- dict[key] = values[i+1]
180
- }
181
-
182
- return root, nil
183
- }
184
-
185
- // EchoParam returns a given value if it is set; otherwise, it returns an
186
- // empty string.
187
- func (ns *Namespace) EchoParam(a, key interface{}) interface{} {
188
- av, isNil := indirect(reflect.ValueOf(a))
189
- if isNil {
190
- return ""
191
- }
192
-
193
- var avv reflect.Value
194
- switch av.Kind() {
195
- case reflect.Array, reflect.Slice:
196
- index, ok := key.(int)
197
- if ok && av.Len() > index {
198
- avv = av.Index(index)
199
- }
200
- case reflect.Map:
201
- kv := reflect.ValueOf(key)
202
- if kv.Type().AssignableTo(av.Type().Key()) {
203
- avv = av.MapIndex(kv)
204
- }
205
- }
206
-
207
- avv, isNil = indirect(avv)
208
-
209
- if isNil {
210
- return ""
211
- }
212
-
213
- if avv.IsValid() {
214
- switch avv.Kind() {
215
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
216
- return avv.Int()
217
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
218
- return avv.Uint()
219
- case reflect.Float32, reflect.Float64:
220
- return avv.Float()
221
- case reflect.String:
222
- return avv.String()
223
- }
224
- }
225
-
226
- return ""
227
- }
228
-
229
- // First returns the first N items in a rangeable list.
230
- func (ns *Namespace) First(limit interface{}, seq interface{}) (interface{}, error) {
231
- if limit == nil || seq == nil {
232
- return nil, errors.New("both limit and seq must be provided")
233
- }
234
-
235
- limitv, err := cast.ToIntE(limit)
236
- if err != nil {
237
- return nil, err
238
- }
239
-
240
- if limitv < 0 {
241
- return nil, errors.New("sequence length must be non-negative")
242
- }
243
-
244
- seqv := reflect.ValueOf(seq)
245
- seqv, isNil := indirect(seqv)
246
- if isNil {
247
- return nil, errors.New("can't iterate over a nil value")
248
- }
249
-
250
- switch seqv.Kind() {
251
- case reflect.Array, reflect.Slice, reflect.String:
252
- // okay
253
- default:
254
- return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
255
- }
256
-
257
- if limitv > seqv.Len() {
258
- limitv = seqv.Len()
259
- }
260
-
261
- return seqv.Slice(0, limitv).Interface(), nil
262
- }
263
-
264
- // In returns whether v is in the set l. l may be an array or slice.
265
- func (ns *Namespace) In(l interface{}, v interface{}) (bool, error) {
266
- if l == nil || v == nil {
267
- return false, nil
268
- }
269
-
270
- lv := reflect.ValueOf(l)
271
- vv := reflect.ValueOf(v)
272
-
273
- vvk := normalize(vv)
274
-
275
- switch lv.Kind() {
276
- case reflect.Array, reflect.Slice:
277
- for i := 0; i < lv.Len(); i++ {
278
- lvv, isNil := indirectInterface(lv.Index(i))
279
- if isNil {
280
- continue
281
- }
282
-
283
- lvvk := normalize(lvv)
284
-
285
- if lvvk == vvk {
286
- return true, nil
287
- }
288
- }
289
- }
290
- ss, err := cast.ToStringE(l)
291
- if err != nil {
292
- return false, nil
293
- }
294
-
295
- su, err := cast.ToStringE(v)
296
- if err != nil {
297
- return false, nil
298
- }
299
- return strings.Contains(ss, su), nil
300
- }
301
-
302
- // Intersect returns the common elements in the given sets, l1 and l2. l1 and
303
- // l2 must be of the same type and may be either arrays or slices.
304
- func (ns *Namespace) Intersect(l1, l2 interface{}) (interface{}, error) {
305
- if l1 == nil || l2 == nil {
306
- return make([]interface{}, 0), nil
307
- }
308
-
309
- var ins *intersector
310
-
311
- l1v := reflect.ValueOf(l1)
312
- l2v := reflect.ValueOf(l2)
313
-
314
- switch l1v.Kind() {
315
- case reflect.Array, reflect.Slice:
316
- ins = &intersector{r: reflect.MakeSlice(l1v.Type(), 0, 0), seen: make(map[interface{}]bool)}
317
- switch l2v.Kind() {
318
- case reflect.Array, reflect.Slice:
319
- for i := 0; i < l1v.Len(); i++ {
320
- l1vv := l1v.Index(i)
321
- if !l1vv.Type().Comparable() {
322
- return make([]interface{}, 0), errors.New("intersect does not support slices or arrays of uncomparable types")
323
- }
324
-
325
- for j := 0; j < l2v.Len(); j++ {
326
- l2vv := l2v.Index(j)
327
- if !l2vv.Type().Comparable() {
328
- return make([]interface{}, 0), errors.New("intersect does not support slices or arrays of uncomparable types")
329
- }
330
-
331
- ins.handleValuePair(l1vv, l2vv)
332
- }
333
- }
334
- return ins.r.Interface(), nil
335
- default:
336
- return nil, errors.New("can't iterate over " + reflect.ValueOf(l2).Type().String())
337
- }
338
- default:
339
- return nil, errors.New("can't iterate over " + reflect.ValueOf(l1).Type().String())
340
- }
341
- }
342
-
343
- // Group groups a set of elements by the given key.
344
- // This is currently only supported for Pages.
345
- func (ns *Namespace) Group(key interface{}, items interface{}) (interface{}, error) {
346
- if key == nil {
347
- return nil, errors.New("nil is not a valid key to group by")
348
- }
349
-
350
- if g, ok := items.(collections.Grouper); ok {
351
- return g.Group(key, items)
352
- }
353
-
354
- in := newSliceElement(items)
355
-
356
- if g, ok := in.(collections.Grouper); ok {
357
- return g.Group(key, items)
358
- }
359
-
360
- return nil, fmt.Errorf("grouping not supported for type %T %T", items, in)
361
- }
362
-
363
- // IsSet returns whether a given array, channel, slice, or map has a key
364
- // defined.
365
- func (ns *Namespace) IsSet(a interface{}, key interface{}) (bool, error) {
366
- av := reflect.ValueOf(a)
367
- kv := reflect.ValueOf(key)
368
-
369
- switch av.Kind() {
370
- case reflect.Array, reflect.Chan, reflect.Slice:
371
- k, err := cast.ToIntE(key)
372
- if err != nil {
373
- return false, fmt.Errorf("isset unable to use key of type %T as index", key)
374
- }
375
- if av.Len() > k {
376
- return true, nil
377
- }
378
- case reflect.Map:
379
- if kv.Type() == av.Type().Key() {
380
- return av.MapIndex(kv).IsValid(), nil
381
- }
382
- default:
383
- // Bookshop: Removed deep Hugo function.
384
- // helpers.DistinctErrorLog.Printf("WARNING: calling IsSet with unsupported type %q (%T) will always return false.\n", av.Kind(), a)
385
- }
386
-
387
- return false, nil
388
- }
389
-
390
- // Last returns the last N items in a rangeable list.
391
- func (ns *Namespace) Last(limit interface{}, seq interface{}) (interface{}, error) {
392
- if limit == nil || seq == nil {
393
- return nil, errors.New("both limit and seq must be provided")
394
- }
395
-
396
- limitv, err := cast.ToIntE(limit)
397
- if err != nil {
398
- return nil, err
399
- }
400
-
401
- if limitv < 0 {
402
- return nil, errors.New("sequence length must be non-negative")
403
- }
404
-
405
- seqv := reflect.ValueOf(seq)
406
- seqv, isNil := indirect(seqv)
407
- if isNil {
408
- return nil, errors.New("can't iterate over a nil value")
409
- }
410
-
411
- switch seqv.Kind() {
412
- case reflect.Array, reflect.Slice, reflect.String:
413
- // okay
414
- default:
415
- return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
416
- }
417
-
418
- if limitv > seqv.Len() {
419
- limitv = seqv.Len()
420
- }
421
-
422
- return seqv.Slice(seqv.Len()-limitv, seqv.Len()).Interface(), nil
423
- }
424
-
425
- // Querify encodes the given parameters in URL-encoded form ("bar=baz&foo=quux") sorted by key.
426
- func (ns *Namespace) Querify(params ...interface{}) (string, error) {
427
- qs := url.Values{}
428
-
429
- if len(params) == 1 {
430
- switch v := params[0].(type) {
431
- case []string:
432
- if len(v)%2 != 0 {
433
- return "", errors.New("invalid query")
434
- }
435
-
436
- for i := 0; i < len(v); i += 2 {
437
- qs.Add(v[i], v[i+1])
438
- }
439
-
440
- return qs.Encode(), nil
441
-
442
- case []interface{}:
443
- params = v
444
-
445
- default:
446
- return "", errors.New("query keys must be strings")
447
- }
448
- }
449
-
450
- if len(params)%2 != 0 {
451
- return "", errors.New("invalid query")
452
- }
453
-
454
- for i := 0; i < len(params); i += 2 {
455
- switch v := params[i].(type) {
456
- case string:
457
- qs.Add(v, fmt.Sprintf("%v", params[i+1]))
458
- default:
459
- return "", errors.New("query keys must be strings")
460
- }
461
- }
462
-
463
- return qs.Encode(), nil
464
- }
465
-
466
- // Reverse creates a copy of slice and reverses it.
467
- func (ns *Namespace) Reverse(slice interface{}) (interface{}, error) {
468
- if slice == nil {
469
- return nil, nil
470
- }
471
- v := reflect.ValueOf(slice)
472
-
473
- switch v.Kind() {
474
- case reflect.Slice:
475
- default:
476
- return nil, errors.New("argument must be a slice")
477
- }
478
-
479
- sliceCopy := reflect.MakeSlice(v.Type(), v.Len(), v.Len())
480
-
481
- for i := v.Len() - 1; i >= 0; i-- {
482
- element := sliceCopy.Index(i)
483
- element.Set(v.Index(v.Len() - 1 - i))
484
- }
485
-
486
- return sliceCopy.Interface(), nil
487
- }
488
-
489
- // Seq creates a sequence of integers. It's named and used as GNU's seq.
490
- //
491
- // Examples:
492
- // 3 => 1, 2, 3
493
- // 1 2 4 => 1, 3
494
- // -3 => -1, -2, -3
495
- // 1 4 => 1, 2, 3, 4
496
- // 1 -2 => 1, 0, -1, -2
497
- func (ns *Namespace) Seq(args ...interface{}) ([]int, error) {
498
- if len(args) < 1 || len(args) > 3 {
499
- return nil, errors.New("invalid number of arguments to Seq")
500
- }
501
-
502
- intArgs := cast.ToIntSlice(args)
503
- if len(intArgs) < 1 || len(intArgs) > 3 {
504
- return nil, errors.New("invalid arguments to Seq")
505
- }
506
-
507
- inc := 1
508
- var last int
509
- first := intArgs[0]
510
-
511
- if len(intArgs) == 1 {
512
- last = first
513
- if last == 0 {
514
- return []int{}, nil
515
- } else if last > 0 {
516
- first = 1
517
- } else {
518
- first = -1
519
- inc = -1
520
- }
521
- } else if len(intArgs) == 2 {
522
- last = intArgs[1]
523
- if last < first {
524
- inc = -1
525
- }
526
- } else {
527
- inc = intArgs[1]
528
- last = intArgs[2]
529
- if inc == 0 {
530
- return nil, errors.New("'increment' must not be 0")
531
- }
532
- if first < last && inc < 0 {
533
- return nil, errors.New("'increment' must be > 0")
534
- }
535
- if first > last && inc > 0 {
536
- return nil, errors.New("'increment' must be < 0")
537
- }
538
- }
539
-
540
- // sanity check
541
- if last < -100000 {
542
- return nil, errors.New("size of result exceeds limit")
543
- }
544
- size := ((last - first) / inc) + 1
545
-
546
- // sanity check
547
- if size <= 0 || size > 2000 {
548
- return nil, errors.New("size of result exceeds limit")
549
- }
550
-
551
- seq := make([]int, size)
552
- val := first
553
- for i := 0; ; i++ {
554
- seq[i] = val
555
- val += inc
556
- if (inc < 0 && val < last) || (inc > 0 && val > last) {
557
- break
558
- }
559
- }
560
-
561
- return seq, nil
562
- }
563
-
564
- // Shuffle returns the given rangeable list in a randomised order.
565
- func (ns *Namespace) Shuffle(seq interface{}) (interface{}, error) {
566
- if seq == nil {
567
- return nil, errors.New("both count and seq must be provided")
568
- }
569
-
570
- seqv := reflect.ValueOf(seq)
571
- seqv, isNil := indirect(seqv)
572
- if isNil {
573
- return nil, errors.New("can't iterate over a nil value")
574
- }
575
-
576
- switch seqv.Kind() {
577
- case reflect.Array, reflect.Slice, reflect.String:
578
- // okay
579
- default:
580
- return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
581
- }
582
-
583
- shuffled := reflect.MakeSlice(reflect.TypeOf(seq), seqv.Len(), seqv.Len())
584
-
585
- randomIndices := rand.Perm(seqv.Len())
586
-
587
- for index, value := range randomIndices {
588
- shuffled.Index(value).Set(seqv.Index(index))
589
- }
590
-
591
- return shuffled.Interface(), nil
592
- }
593
-
594
- // Slice returns a slice of all passed arguments.
595
- func (ns *Namespace) Slice(args ...interface{}) interface{} {
596
- if len(args) == 0 {
597
- return args
598
- }
599
-
600
- return collections.Slice(args...)
601
- }
602
-
603
- type intersector struct {
604
- r reflect.Value
605
- seen map[interface{}]bool
606
- }
607
-
608
- func (i *intersector) appendIfNotSeen(v reflect.Value) {
609
- vi := v.Interface()
610
- if !i.seen[vi] {
611
- i.r = reflect.Append(i.r, v)
612
- i.seen[vi] = true
613
- }
614
- }
615
-
616
- func (i *intersector) handleValuePair(l1vv, l2vv reflect.Value) {
617
- switch kind := l1vv.Kind(); {
618
- case kind == reflect.String:
619
- l2t, err := toString(l2vv)
620
- if err == nil && l1vv.String() == l2t {
621
- i.appendIfNotSeen(l1vv)
622
- }
623
- case isNumber(kind):
624
- f1, err1 := numberToFloat(l1vv)
625
- f2, err2 := numberToFloat(l2vv)
626
- if err1 == nil && err2 == nil && f1 == f2 {
627
- i.appendIfNotSeen(l1vv)
628
- }
629
- case kind == reflect.Ptr, kind == reflect.Struct:
630
- if l1vv.Interface() == l2vv.Interface() {
631
- i.appendIfNotSeen(l1vv)
632
- }
633
- case kind == reflect.Interface:
634
- i.handleValuePair(reflect.ValueOf(l1vv.Interface()), l2vv)
635
- }
636
- }
637
-
638
- // Union returns the union of the given sets, l1 and l2. l1 and
639
- // l2 must be of the same type and may be either arrays or slices.
640
- // If l1 and l2 aren't of the same type then l1 will be returned.
641
- // If either l1 or l2 is nil then the non-nil list will be returned.
642
- func (ns *Namespace) Union(l1, l2 interface{}) (interface{}, error) {
643
- if l1 == nil && l2 == nil {
644
- return []interface{}{}, nil
645
- } else if l1 == nil && l2 != nil {
646
- return l2, nil
647
- } else if l1 != nil && l2 == nil {
648
- return l1, nil
649
- }
650
-
651
- l1v := reflect.ValueOf(l1)
652
- l2v := reflect.ValueOf(l2)
653
-
654
- var ins *intersector
655
-
656
- switch l1v.Kind() {
657
- case reflect.Array, reflect.Slice:
658
- switch l2v.Kind() {
659
- case reflect.Array, reflect.Slice:
660
- ins = &intersector{r: reflect.MakeSlice(l1v.Type(), 0, 0), seen: make(map[interface{}]bool)}
661
-
662
- if l1v.Type() != l2v.Type() &&
663
- l1v.Type().Elem().Kind() != reflect.Interface &&
664
- l2v.Type().Elem().Kind() != reflect.Interface {
665
- return ins.r.Interface(), nil
666
- }
667
-
668
- var (
669
- l1vv reflect.Value
670
- isNil bool
671
- )
672
-
673
- for i := 0; i < l1v.Len(); i++ {
674
- l1vv, isNil = indirectInterface(l1v.Index(i))
675
-
676
- if !l1vv.Type().Comparable() {
677
- return []interface{}{}, errors.New("union does not support slices or arrays of uncomparable types")
678
- }
679
-
680
- if !isNil {
681
- ins.appendIfNotSeen(l1vv)
682
- }
683
- }
684
-
685
- if !l1vv.IsValid() {
686
- // The first slice may be empty. Pick the first value of the second
687
- // to use as a prototype.
688
- if l2v.Len() > 0 {
689
- l1vv = l2v.Index(0)
690
- }
691
- }
692
-
693
- for j := 0; j < l2v.Len(); j++ {
694
- l2vv := l2v.Index(j)
695
-
696
- switch kind := l1vv.Kind(); {
697
- case kind == reflect.String:
698
- l2t, err := toString(l2vv)
699
- if err == nil {
700
- ins.appendIfNotSeen(reflect.ValueOf(l2t))
701
- }
702
- case isNumber(kind):
703
- var err error
704
- l2vv, err = convertNumber(l2vv, kind)
705
- if err == nil {
706
- ins.appendIfNotSeen(l2vv)
707
- }
708
- case kind == reflect.Interface, kind == reflect.Struct, kind == reflect.Ptr:
709
- ins.appendIfNotSeen(l2vv)
710
-
711
- }
712
- }
713
-
714
- return ins.r.Interface(), nil
715
- default:
716
- return nil, errors.New("can't iterate over " + reflect.ValueOf(l2).Type().String())
717
- }
718
- default:
719
- return nil, errors.New("can't iterate over " + reflect.ValueOf(l1).Type().String())
720
- }
721
- }
722
-
723
- // Uniq takes in a slice or array and returns a slice with subsequent
724
- // duplicate elements removed.
725
- func (ns *Namespace) Uniq(seq interface{}) (interface{}, error) {
726
- if seq == nil {
727
- return make([]interface{}, 0), nil
728
- }
729
-
730
- v := reflect.ValueOf(seq)
731
- var slice reflect.Value
732
-
733
- switch v.Kind() {
734
- case reflect.Slice:
735
- slice = reflect.MakeSlice(v.Type(), 0, 0)
736
-
737
- case reflect.Array:
738
- slice = reflect.MakeSlice(reflect.SliceOf(v.Type().Elem()), 0, 0)
739
- default:
740
- return nil, errors.Errorf("type %T not supported", seq)
741
- }
742
-
743
- seen := make(map[interface{}]bool)
744
-
745
- for i := 0; i < v.Len(); i++ {
746
- ev, _ := indirectInterface(v.Index(i))
747
-
748
- key := normalize(ev)
749
-
750
- if _, found := seen[key]; !found {
751
- slice = reflect.Append(slice, ev)
752
- seen[key] = true
753
- }
754
- }
755
-
756
- return slice.Interface(), nil
757
- }
758
-
759
- // KeyVals creates a key and values wrapper.
760
- func (ns *Namespace) KeyVals(key interface{}, vals ...interface{}) (types.KeyValues, error) {
761
- return types.KeyValues{Key: key, Values: vals}, nil
762
- }
763
-
764
- // NewScratch creates a new Scratch which can be used to store values in a
765
- // thread safe way.
766
- func (ns *Namespace) NewScratch() *maps.Scratch {
767
- return maps.NewScratch()
768
- }