@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.
- package/.nyc_output/{396c364e-fec4-4f27-9ff2-8b236061ef8f.json → 0f70a16f-6a79-48c7-8b16-3b4665e247b2.json} +0 -0
- package/.nyc_output/{4ef43740-059b-4329-96cd-0643fd8fe8d8.json → 6285d5fa-be3d-49e4-8f2f-82157d95dcd8.json} +0 -0
- package/.nyc_output/{656275f4-66d6-4d27-bfab-c2f7a3087670.json → 8b5e1314-6e86-4197-a3ae-3c40e4c2f39e.json} +0 -0
- package/.nyc_output/{6aec5420-0b83-4260-b300-4d595dfd0660.json → c5490eb0-70c0-468f-a43f-e58c75dd34c8.json} +0 -0
- package/.nyc_output/{874bd79b-45da-4726-9afc-1f6cab44be1f.json → ee1a9bec-d318-4aea-af93-7269debcf6df.json} +0 -0
- package/.nyc_output/processinfo/{396c364e-fec4-4f27-9ff2-8b236061ef8f.json → 0f70a16f-6a79-48c7-8b16-3b4665e247b2.json} +1 -1
- package/.nyc_output/processinfo/6285d5fa-be3d-49e4-8f2f-82157d95dcd8.json +1 -0
- package/.nyc_output/processinfo/{4ef43740-059b-4329-96cd-0643fd8fe8d8.json → 8b5e1314-6e86-4197-a3ae-3c40e4c2f39e.json} +1 -1
- package/.nyc_output/processinfo/{656275f4-66d6-4d27-bfab-c2f7a3087670.json → c5490eb0-70c0-468f-a43f-e58c75dd34c8.json} +1 -1
- package/.nyc_output/processinfo/{874bd79b-45da-4726-9afc-1f6cab44be1f.json → ee1a9bec-d318-4aea-af93-7269debcf6df.json} +1 -1
- package/.nyc_output/processinfo/index.json +1 -1
- package/bookshop-hugo-templates/bookshop.html +56 -0
- package/bookshop-hugo-templates/bookshop_bindings.html +29 -0
- package/bookshop-hugo-templates/bookshop_component_browser.html +30 -0
- package/bookshop-hugo-templates/bookshop_partial.html +42 -0
- package/bookshop-hugo-templates/bookshop_scss.html +9 -0
- package/bookshop-hugo-templates/errors/bad_bookshop_tag.html +39 -0
- package/bookshop-hugo-templates/errors/err.html +6 -0
- package/bookshop-hugo-templates/helpers/component.html +25 -0
- package/bookshop-hugo-templates/helpers/component_key.html +11 -0
- package/bookshop-hugo-templates/helpers/partial.html +25 -0
- package/bookshop-hugo-templates/helpers/partial_key.html +9 -0
- package/full-hugo-renderer/build.sh +34 -0
- package/full-hugo-renderer/go.mod +87 -0
- package/{hugo-renderer → full-hugo-renderer}/go.sum +204 -12
- package/full-hugo-renderer/hugo_renderer.wasm +0 -0
- package/full-hugo-renderer/hugo_renderer.wasm.gz +0 -0
- package/full-hugo-renderer/main.go +215 -0
- package/{hugo-renderer → full-hugo-renderer}/wasm_exec.js +6 -2
- package/lib/builder.js +2 -2
- package/lib/engine.js +109 -42
- package/lib/hugoIdentifierParser.js +5 -0
- package/lib/translateTextTemplate.js +3 -0
- package/lib/translateTextTemplate.test.js +22 -16
- package/package.json +4 -4
- package/.nyc_output/processinfo/6aec5420-0b83-4260-b300-4d595dfd0660.json +0 -1
- package/hugo-renderer/build.sh +0 -66
- package/hugo-renderer/deps/bookshop_modified_deps.go +0 -6
- package/hugo-renderer/go.mod +0 -19
- package/hugo-renderer/helpers/bookshop_modified_content.go +0 -98
- package/hugo-renderer/helpers/bookshop_modified_general.go +0 -33
- package/hugo-renderer/helpers/emoji.go +0 -96
- package/hugo-renderer/hugo_renderer.wasm +0 -0
- package/hugo-renderer/hugo_renderer.wasm.gz +0 -0
- package/hugo-renderer/main.go +0 -42
- package/hugo-renderer/tpl/bookshop_engine/bookshop_func_importer.go +0 -35
- package/hugo-renderer/tpl/bookshop_engine/bookshop_render.go +0 -64
- package/hugo-renderer/tpl/bookshop_library/bookshop_components.go +0 -129
- package/hugo-renderer/tpl/bookshop_library/bookshop_data.go +0 -53
- package/hugo-renderer/tpl/cast/cast.go +0 -63
- package/hugo-renderer/tpl/cast/init.go +0 -57
- package/hugo-renderer/tpl/collections/append.go +0 -37
- package/hugo-renderer/tpl/collections/apply.go +0 -131
- package/hugo-renderer/tpl/collections/collections.go +0 -768
- package/hugo-renderer/tpl/collections/complement.go +0 -55
- package/hugo-renderer/tpl/collections/index.go +0 -133
- package/hugo-renderer/tpl/collections/init.go +0 -214
- package/hugo-renderer/tpl/collections/merge.go +0 -126
- package/hugo-renderer/tpl/collections/reflect_helpers.go +0 -216
- package/hugo-renderer/tpl/collections/sort.go +0 -183
- package/hugo-renderer/tpl/collections/symdiff.go +0 -68
- package/hugo-renderer/tpl/collections/where.go +0 -517
- package/hugo-renderer/tpl/compare/compare.go +0 -324
- package/hugo-renderer/tpl/compare/init.go +0 -85
- package/hugo-renderer/tpl/crypto/crypto.go +0 -109
- package/hugo-renderer/tpl/crypto/init.go +0 -65
- package/hugo-renderer/tpl/debug/debug.go +0 -40
- package/hugo-renderer/tpl/debug/init.go +0 -45
- package/hugo-renderer/tpl/encoding/encoding.go +0 -90
- package/hugo-renderer/tpl/encoding/init.go +0 -59
- package/hugo-renderer/tpl/fmt/fmt.go +0 -66
- package/hugo-renderer/tpl/fmt/init.go +0 -77
- package/hugo-renderer/tpl/inflect/inflect.go +0 -79
- package/hugo-renderer/tpl/inflect/init.go +0 -60
- package/hugo-renderer/tpl/internal/bookshop_modified_templatefuncsRegistry.go +0 -88
- package/hugo-renderer/tpl/math/init.go +0 -134
- package/hugo-renderer/tpl/math/math.go +0 -164
- package/hugo-renderer/tpl/math/round.go +0 -61
- package/hugo-renderer/tpl/partials/init.go +0 -55
- package/hugo-renderer/tpl/partials/partials.go +0 -88
- package/hugo-renderer/tpl/path/init.go +0 -60
- package/hugo-renderer/tpl/path/path.go +0 -159
- package/hugo-renderer/tpl/reflect/init.go +0 -51
- package/hugo-renderer/tpl/reflect/reflect.go +0 -36
- package/hugo-renderer/tpl/safe/init.go +0 -80
- package/hugo-renderer/tpl/safe/safe.go +0 -72
- package/hugo-renderer/tpl/site/bookshop_site.go +0 -67
- package/hugo-renderer/tpl/site/init.go +0 -41
- package/hugo-renderer/tpl/strings/init.go +0 -229
- package/hugo-renderer/tpl/strings/regexp.go +0 -125
- package/hugo-renderer/tpl/strings/strings.go +0 -500
- package/hugo-renderer/tpl/strings/truncate.go +0 -157
- package/hugo-renderer/tpl/transform/bookshop_unmarshal.go +0 -39
- package/hugo-renderer/tpl/transform/init.go +0 -113
- package/hugo-renderer/tpl/transform/transform.go +0 -116
- 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
|
-
}
|