@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,500 +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 strings provides template functions for manipulating strings.
15
- package strings
16
-
17
- import (
18
- "errors"
19
- "html/template"
20
- "hugo-renderer/deps"
21
- "regexp"
22
- "strings"
23
- "unicode/utf8"
24
-
25
- "hugo-renderer/helpers"
26
-
27
- _errors "github.com/pkg/errors"
28
- "github.com/spf13/cast"
29
- )
30
-
31
- // New returns a new instance of the strings-namespaced template functions.
32
- func New(d *deps.Deps) *Namespace {
33
- return &Namespace{titleFunc: strings.Title} // TODO(bookshop): Only the "Go" title formatting is supported
34
- }
35
-
36
- // Namespace provides template functions for the "strings" namespace.
37
- // Most functions mimic the Go stdlib, but the order of the parameters may be
38
- // different to ease their use in the Go template system.
39
- type Namespace struct {
40
- titleFunc func(s string) string
41
- }
42
-
43
- // CountRunes returns the number of runes in s, excluding whitespace.
44
- func (ns *Namespace) CountRunes(s interface{}) (int, error) {
45
- ss, err := cast.ToStringE(s)
46
- if err != nil {
47
- return 0, _errors.Wrap(err, "Failed to convert content to string")
48
- }
49
-
50
- counter := 0
51
- for _, r := range helpers.StripHTML(ss) {
52
- if !helpers.IsWhitespace(r) {
53
- counter++
54
- }
55
- }
56
-
57
- return counter, nil
58
- }
59
-
60
- // RuneCount returns the number of runes in s.
61
- func (ns *Namespace) RuneCount(s interface{}) (int, error) {
62
- ss, err := cast.ToStringE(s)
63
- if err != nil {
64
- return 0, _errors.Wrap(err, "Failed to convert content to string")
65
- }
66
- return utf8.RuneCountInString(ss), nil
67
- }
68
-
69
- // CountWords returns the approximate word count in s.
70
- func (ns *Namespace) CountWords(s interface{}) (int, error) {
71
- ss, err := cast.ToStringE(s)
72
- if err != nil {
73
- return 0, _errors.Wrap(err, "Failed to convert content to string")
74
- }
75
-
76
- isCJKLanguage, err := regexp.MatchString(`\p{Han}|\p{Hangul}|\p{Hiragana}|\p{Katakana}`, ss)
77
- if err != nil {
78
- return 0, _errors.Wrap(err, "Failed to match regex pattern against string")
79
- }
80
-
81
- if !isCJKLanguage {
82
- return len(strings.Fields(helpers.StripHTML((ss)))), nil
83
- }
84
-
85
- counter := 0
86
- for _, word := range strings.Fields(helpers.StripHTML(ss)) {
87
- runeCount := utf8.RuneCountInString(word)
88
- if len(word) == runeCount {
89
- counter++
90
- } else {
91
- counter += runeCount
92
- }
93
- }
94
-
95
- return counter, nil
96
- }
97
-
98
- // Count counts the number of non-overlapping instances of substr in s.
99
- // If substr is an empty string, Count returns 1 + the number of Unicode code points in s.
100
- func (ns *Namespace) Count(substr, s interface{}) (int, error) {
101
- substrs, err := cast.ToStringE(substr)
102
- if err != nil {
103
- return 0, _errors.Wrap(err, "Failed to convert substr to string")
104
- }
105
- ss, err := cast.ToStringE(s)
106
- if err != nil {
107
- return 0, _errors.Wrap(err, "Failed to convert s to string")
108
- }
109
- return strings.Count(ss, substrs), nil
110
- }
111
-
112
- // Chomp returns a copy of s with all trailing newline characters removed.
113
- func (ns *Namespace) Chomp(s interface{}) (interface{}, error) {
114
- ss, err := cast.ToStringE(s)
115
- if err != nil {
116
- return "", err
117
- }
118
-
119
- res := strings.TrimRight(ss, "\r\n")
120
- switch s.(type) {
121
- case template.HTML:
122
- return template.HTML(res), nil
123
- default:
124
- return res, nil
125
- }
126
- }
127
-
128
- // Contains reports whether substr is in s.
129
- func (ns *Namespace) Contains(s, substr interface{}) (bool, error) {
130
- ss, err := cast.ToStringE(s)
131
- if err != nil {
132
- return false, err
133
- }
134
-
135
- su, err := cast.ToStringE(substr)
136
- if err != nil {
137
- return false, err
138
- }
139
-
140
- return strings.Contains(ss, su), nil
141
- }
142
-
143
- // ContainsAny reports whether any Unicode code points in chars are within s.
144
- func (ns *Namespace) ContainsAny(s, chars interface{}) (bool, error) {
145
- ss, err := cast.ToStringE(s)
146
- if err != nil {
147
- return false, err
148
- }
149
-
150
- sc, err := cast.ToStringE(chars)
151
- if err != nil {
152
- return false, err
153
- }
154
-
155
- return strings.ContainsAny(ss, sc), nil
156
- }
157
-
158
- // HasPrefix tests whether the input s begins with prefix.
159
- func (ns *Namespace) HasPrefix(s, prefix interface{}) (bool, error) {
160
- ss, err := cast.ToStringE(s)
161
- if err != nil {
162
- return false, err
163
- }
164
-
165
- sx, err := cast.ToStringE(prefix)
166
- if err != nil {
167
- return false, err
168
- }
169
-
170
- return strings.HasPrefix(ss, sx), nil
171
- }
172
-
173
- // HasSuffix tests whether the input s begins with suffix.
174
- func (ns *Namespace) HasSuffix(s, suffix interface{}) (bool, error) {
175
- ss, err := cast.ToStringE(s)
176
- if err != nil {
177
- return false, err
178
- }
179
-
180
- sx, err := cast.ToStringE(suffix)
181
- if err != nil {
182
- return false, err
183
- }
184
-
185
- return strings.HasSuffix(ss, sx), nil
186
- }
187
-
188
- // Replace returns a copy of the string s with all occurrences of old replaced
189
- // with new. The number of replacements can be limited with an optional fourth
190
- // parameter.
191
- func (ns *Namespace) Replace(s, old, new interface{}, limit ...interface{}) (string, error) {
192
- ss, err := cast.ToStringE(s)
193
- if err != nil {
194
- return "", err
195
- }
196
-
197
- so, err := cast.ToStringE(old)
198
- if err != nil {
199
- return "", err
200
- }
201
-
202
- sn, err := cast.ToStringE(new)
203
- if err != nil {
204
- return "", err
205
- }
206
-
207
- if len(limit) == 0 {
208
- return strings.ReplaceAll(ss, so, sn), nil
209
- }
210
-
211
- lim, err := cast.ToIntE(limit[0])
212
- if err != nil {
213
- return "", err
214
- }
215
-
216
- return strings.Replace(ss, so, sn, lim), nil
217
- }
218
-
219
- // SliceString slices a string by specifying a half-open range with
220
- // two indices, start and end. 1 and 4 creates a slice including elements 1 through 3.
221
- // The end index can be omitted, it defaults to the string's length.
222
- func (ns *Namespace) SliceString(a interface{}, startEnd ...interface{}) (string, error) {
223
- aStr, err := cast.ToStringE(a)
224
- if err != nil {
225
- return "", err
226
- }
227
-
228
- var argStart, argEnd int
229
-
230
- argNum := len(startEnd)
231
-
232
- if argNum > 0 {
233
- if argStart, err = cast.ToIntE(startEnd[0]); err != nil {
234
- return "", errors.New("start argument must be integer")
235
- }
236
- }
237
- if argNum > 1 {
238
- if argEnd, err = cast.ToIntE(startEnd[1]); err != nil {
239
- return "", errors.New("end argument must be integer")
240
- }
241
- }
242
-
243
- if argNum > 2 {
244
- return "", errors.New("too many arguments")
245
- }
246
-
247
- asRunes := []rune(aStr)
248
-
249
- if argNum > 0 && (argStart < 0 || argStart >= len(asRunes)) {
250
- return "", errors.New("slice bounds out of range")
251
- }
252
-
253
- if argNum == 2 {
254
- if argEnd < 0 || argEnd > len(asRunes) {
255
- return "", errors.New("slice bounds out of range")
256
- }
257
- return string(asRunes[argStart:argEnd]), nil
258
- } else if argNum == 1 {
259
- return string(asRunes[argStart:]), nil
260
- } else {
261
- return string(asRunes[:]), nil
262
- }
263
- }
264
-
265
- // Split slices an input string into all substrings separated by delimiter.
266
- func (ns *Namespace) Split(a interface{}, delimiter string) ([]string, error) {
267
- aStr, err := cast.ToStringE(a)
268
- if err != nil {
269
- return []string{}, err
270
- }
271
-
272
- return strings.Split(aStr, delimiter), nil
273
- }
274
-
275
- // Substr extracts parts of a string, beginning at the character at the specified
276
- // position, and returns the specified number of characters.
277
- //
278
- // It normally takes two parameters: start and length.
279
- // It can also take one parameter: start, i.e. length is omitted, in which case
280
- // the substring starting from start until the end of the string will be returned.
281
- //
282
- // To extract characters from the end of the string, use a negative start number.
283
- //
284
- // In addition, borrowing from the extended behavior described at http://php.net/substr,
285
- // if length is given and is negative, then that many characters will be omitted from
286
- // the end of string.
287
- func (ns *Namespace) Substr(a interface{}, nums ...interface{}) (string, error) {
288
- s, err := cast.ToStringE(a)
289
- if err != nil {
290
- return "", err
291
- }
292
-
293
- asRunes := []rune(s)
294
- rlen := len(asRunes)
295
-
296
- var start, length int
297
-
298
- switch len(nums) {
299
- case 0:
300
- return "", errors.New("too few arguments")
301
- case 1:
302
- if start, err = cast.ToIntE(nums[0]); err != nil {
303
- return "", errors.New("start argument must be an integer")
304
- }
305
- length = rlen
306
- case 2:
307
- if start, err = cast.ToIntE(nums[0]); err != nil {
308
- return "", errors.New("start argument must be an integer")
309
- }
310
- if length, err = cast.ToIntE(nums[1]); err != nil {
311
- return "", errors.New("length argument must be an integer")
312
- }
313
- default:
314
- return "", errors.New("too many arguments")
315
- }
316
-
317
- if rlen == 0 {
318
- return "", nil
319
- }
320
-
321
- if start < 0 {
322
- start += rlen
323
- }
324
-
325
- // start was originally negative beyond rlen
326
- if start < 0 {
327
- start = 0
328
- }
329
-
330
- if start > rlen-1 {
331
- return "", nil
332
- }
333
-
334
- end := rlen
335
-
336
- switch {
337
- case length == 0:
338
- return "", nil
339
- case length < 0:
340
- end += length
341
- case length > 0:
342
- end = start + length
343
- }
344
-
345
- if start >= end {
346
- return "", nil
347
- }
348
-
349
- if end < 0 {
350
- return "", nil
351
- }
352
-
353
- if end > rlen {
354
- end = rlen
355
- }
356
-
357
- return string(asRunes[start:end]), nil
358
- }
359
-
360
- // Title returns a copy of the input s with all Unicode letters that begin words
361
- // mapped to their title case.
362
- func (ns *Namespace) Title(s interface{}) (string, error) {
363
- ss, err := cast.ToStringE(s)
364
- if err != nil {
365
- return "", err
366
- }
367
-
368
- return ns.titleFunc(ss), nil
369
- }
370
-
371
- // FirstUpper returns a string with the first character as upper case.
372
- func (ns *Namespace) FirstUpper(s interface{}) (string, error) {
373
- ss, err := cast.ToStringE(s)
374
- if err != nil {
375
- return "", err
376
- }
377
-
378
- return helpers.FirstUpper(ss), nil
379
- }
380
-
381
- // ToLower returns a copy of the input s with all Unicode letters mapped to their
382
- // lower case.
383
- func (ns *Namespace) ToLower(s interface{}) (string, error) {
384
- ss, err := cast.ToStringE(s)
385
- if err != nil {
386
- return "", err
387
- }
388
-
389
- return strings.ToLower(ss), nil
390
- }
391
-
392
- // ToUpper returns a copy of the input s with all Unicode letters mapped to their
393
- // upper case.
394
- func (ns *Namespace) ToUpper(s interface{}) (string, error) {
395
- ss, err := cast.ToStringE(s)
396
- if err != nil {
397
- return "", err
398
- }
399
-
400
- return strings.ToUpper(ss), nil
401
- }
402
-
403
- // Trim returns a string with all leading and trailing characters defined
404
- // contained in cutset removed.
405
- func (ns *Namespace) Trim(s, cutset interface{}) (string, error) {
406
- ss, err := cast.ToStringE(s)
407
- if err != nil {
408
- return "", err
409
- }
410
-
411
- sc, err := cast.ToStringE(cutset)
412
- if err != nil {
413
- return "", err
414
- }
415
-
416
- return strings.Trim(ss, sc), nil
417
- }
418
-
419
- // TrimLeft returns a slice of the string s with all leading characters
420
- // contained in cutset removed.
421
- func (ns *Namespace) TrimLeft(cutset, s interface{}) (string, error) {
422
- ss, err := cast.ToStringE(s)
423
- if err != nil {
424
- return "", err
425
- }
426
-
427
- sc, err := cast.ToStringE(cutset)
428
- if err != nil {
429
- return "", err
430
- }
431
-
432
- return strings.TrimLeft(ss, sc), nil
433
- }
434
-
435
- // TrimPrefix returns s without the provided leading prefix string. If s doesn't
436
- // start with prefix, s is returned unchanged.
437
- func (ns *Namespace) TrimPrefix(prefix, s interface{}) (string, error) {
438
- ss, err := cast.ToStringE(s)
439
- if err != nil {
440
- return "", err
441
- }
442
-
443
- sx, err := cast.ToStringE(prefix)
444
- if err != nil {
445
- return "", err
446
- }
447
-
448
- return strings.TrimPrefix(ss, sx), nil
449
- }
450
-
451
- // TrimRight returns a slice of the string s with all trailing characters
452
- // contained in cutset removed.
453
- func (ns *Namespace) TrimRight(cutset, s interface{}) (string, error) {
454
- ss, err := cast.ToStringE(s)
455
- if err != nil {
456
- return "", err
457
- }
458
-
459
- sc, err := cast.ToStringE(cutset)
460
- if err != nil {
461
- return "", err
462
- }
463
-
464
- return strings.TrimRight(ss, sc), nil
465
- }
466
-
467
- // TrimSuffix returns s without the provided trailing suffix string. If s
468
- // doesn't end with suffix, s is returned unchanged.
469
- func (ns *Namespace) TrimSuffix(suffix, s interface{}) (string, error) {
470
- ss, err := cast.ToStringE(s)
471
- if err != nil {
472
- return "", err
473
- }
474
-
475
- sx, err := cast.ToStringE(suffix)
476
- if err != nil {
477
- return "", err
478
- }
479
-
480
- return strings.TrimSuffix(ss, sx), nil
481
- }
482
-
483
- // Repeat returns a new string consisting of count copies of the string s.
484
- func (ns *Namespace) Repeat(n, s interface{}) (string, error) {
485
- ss, err := cast.ToStringE(s)
486
- if err != nil {
487
- return "", err
488
- }
489
-
490
- sn, err := cast.ToIntE(n)
491
- if err != nil {
492
- return "", err
493
- }
494
-
495
- if sn < 0 {
496
- return "", errors.New("strings: negative Repeat count")
497
- }
498
-
499
- return strings.Repeat(ss, sn), nil
500
- }
@@ -1,157 +0,0 @@
1
- // Copyright 2016 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 strings
15
-
16
- import (
17
- "errors"
18
- "html"
19
- "html/template"
20
- "regexp"
21
- "unicode"
22
- "unicode/utf8"
23
-
24
- "github.com/spf13/cast"
25
- )
26
-
27
- var (
28
- tagRE = regexp.MustCompile(`^<(/)?([^ ]+?)(?:(\s*/)| .*?)?>`)
29
- htmlSinglets = map[string]bool{
30
- "br": true, "col": true, "link": true,
31
- "base": true, "img": true, "param": true,
32
- "area": true, "hr": true, "input": true,
33
- }
34
- )
35
-
36
- type htmlTag struct {
37
- name string
38
- pos int
39
- openTag bool
40
- }
41
-
42
- // Truncate truncates a given string to the specified length.
43
- func (ns *Namespace) Truncate(a interface{}, options ...interface{}) (template.HTML, error) {
44
- length, err := cast.ToIntE(a)
45
- if err != nil {
46
- return "", err
47
- }
48
- var textParam interface{}
49
- var ellipsis string
50
-
51
- switch len(options) {
52
- case 0:
53
- return "", errors.New("truncate requires a length and a string")
54
- case 1:
55
- textParam = options[0]
56
- ellipsis = " …"
57
- case 2:
58
- textParam = options[1]
59
- ellipsis, err = cast.ToStringE(options[0])
60
- if err != nil {
61
- return "", errors.New("ellipsis must be a string")
62
- }
63
- if _, ok := options[0].(template.HTML); !ok {
64
- ellipsis = html.EscapeString(ellipsis)
65
- }
66
- default:
67
- return "", errors.New("too many arguments passed to truncate")
68
- }
69
- if err != nil {
70
- return "", errors.New("text to truncate must be a string")
71
- }
72
- text, err := cast.ToStringE(textParam)
73
- if err != nil {
74
- return "", errors.New("text must be a string")
75
- }
76
-
77
- _, isHTML := textParam.(template.HTML)
78
-
79
- if utf8.RuneCountInString(text) <= length {
80
- if isHTML {
81
- return template.HTML(text), nil
82
- }
83
- return template.HTML(html.EscapeString(text)), nil
84
- }
85
-
86
- tags := []htmlTag{}
87
- var lastWordIndex, lastNonSpace, currentLen, endTextPos, nextTag int
88
-
89
- for i, r := range text {
90
- if i < nextTag {
91
- continue
92
- }
93
-
94
- if isHTML {
95
- // Make sure we keep tag of HTML tags
96
- slice := text[i:]
97
- m := tagRE.FindStringSubmatchIndex(slice)
98
- if len(m) > 0 && m[0] == 0 {
99
- nextTag = i + m[1]
100
- tagname := slice[m[4]:m[5]]
101
- lastWordIndex = lastNonSpace
102
- _, singlet := htmlSinglets[tagname]
103
- if !singlet && m[6] == -1 {
104
- tags = append(tags, htmlTag{name: tagname, pos: i, openTag: m[2] == -1})
105
- }
106
-
107
- continue
108
- }
109
- }
110
-
111
- currentLen++
112
- if unicode.IsSpace(r) {
113
- lastWordIndex = lastNonSpace
114
- } else if unicode.In(r, unicode.Han, unicode.Hangul, unicode.Hiragana, unicode.Katakana) {
115
- lastWordIndex = i
116
- } else {
117
- lastNonSpace = i + utf8.RuneLen(r)
118
- }
119
-
120
- if currentLen > length {
121
- if lastWordIndex == 0 {
122
- endTextPos = i
123
- } else {
124
- endTextPos = lastWordIndex
125
- }
126
- out := text[0:endTextPos]
127
- if isHTML {
128
- out += ellipsis
129
- // Close out any open HTML tags
130
- var currentTag *htmlTag
131
- for i := len(tags) - 1; i >= 0; i-- {
132
- tag := tags[i]
133
- if tag.pos >= endTextPos || currentTag != nil {
134
- if currentTag != nil && currentTag.name == tag.name {
135
- currentTag = nil
136
- }
137
- continue
138
- }
139
-
140
- if tag.openTag {
141
- out += ("</" + tag.name + ">")
142
- } else {
143
- currentTag = &tag
144
- }
145
- }
146
-
147
- return template.HTML(out), nil
148
- }
149
- return template.HTML(html.EscapeString(out) + ellipsis), nil
150
- }
151
- }
152
-
153
- if isHTML {
154
- return template.HTML(text), nil
155
- }
156
- return template.HTML(html.EscapeString(text)), nil
157
- }
@@ -1,39 +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 transform
15
-
16
- import (
17
- "encoding/json"
18
-
19
- "github.com/pkg/errors"
20
- )
21
-
22
- // Unmarshal unmarshals the data given, which can be either a string, json.RawMessage
23
- // or a Resource. Supported formats are JSON, TOML, YAML, and CSV.
24
- // You can optionally provide an options map as the first argument.
25
- func (ns *Namespace) BookshopUnmarshal(args ...interface{}) (interface{}, error) {
26
- if len(args) != 1 {
27
- return nil, errors.New("Bookshop unmarshal takes 1 argument")
28
- }
29
-
30
- var data interface{}
31
-
32
- if r, ok := args[0].(string); ok {
33
- if err := json.Unmarshal([]byte(r), &data); err != nil {
34
- return nil, err
35
- }
36
- return data, nil
37
- }
38
- return nil, errors.New("Needed a string")
39
- }