tpl: Add findRE template func

This commit is contained in:
digitalcraftsman 2016-04-05 18:02:18 +02:00 committed by Bjørn Erik Pedersen
parent 54750b0780
commit 5bfe16ef8d
3 changed files with 73 additions and 0 deletions

View file

@ -474,6 +474,36 @@ Pluralize the given word with a set of common English pluralization rules.
e.g. `{{ "cat" | pluralize }}` → "cats"
### findRE
Returns a list of strings that match the regular expression. By default all matches will be included. The number of matches can be limitted with an optional third parameter.
The example below returns a list of all second level headers (`<h2>`) in the content:
{{ findRE "<h2.*?>(.|\n)*?</h2>" .Content }}
We can limit the number of matches in that list with a third parameter. Let's say we want to have at most one match (or none if no substring matched):
{{ findRE "<h2.*?>(.|\n)*?</h2>" .Content 1 }}
<!-- returns ["<h2 id="#foo">Foo</h2>"] -->
`findRe` allows us to build an automatically generated table of contents that could be used for a simple scrollspy:
{{ $headers := findRE "<h2.*?>(.|\n)*?</h2>" .Content }}
{{ if ge (len $headers) 1 }}
<ul>
{{ range $headers }}
<li>
<a href="#{{ . | plainify | urlize }}">
{{ . | plainify }}
</a>
</li>
{{ end }}
</ul>
{{ end }}
First, we try to find all second-level headers and generate a list if at least one header was found. `plainify` strips the HTML and `urlize` converts the header into an a valid URL.
### replace
Replaces all occurrences of the search string with the replacement string.

View file

@ -437,6 +437,22 @@ func first(limit interface{}, seq interface{}) (interface{}, error) {
return seqv.Slice(0, limitv).Interface(), nil
}
// findRE returns a list of strings that match the regular expression. By default all matches
// will be included. The number of matches can be limitted with an optional third parameter.
func findRE(expr string, content interface{}, limit ...int) ([]string, error) {
re, err := reCache.Get(expr)
if err != nil {
return nil, err
}
conv := cast.ToString(content)
if len(limit) > 0 {
return re.FindAllString(conv, limit[0]), nil
}
return re.FindAllString(conv, -1), nil
}
// last returns the last N items in a rangeable list.
func last(limit interface{}, seq interface{}) (interface{}, error) {
if limit == nil || seq == nil {
@ -1729,6 +1745,7 @@ func init() {
"echoParam": returnWhenSet,
"emojify": emojify,
"eq": eq,
"findRE": findRE,
"first": first,
"ge": ge,
"getCSV": getCSV,

View file

@ -89,6 +89,7 @@ delimit: {{ delimit (slice "A" "B" "C") ", " " and " }}
div: {{div 6 3}}
emojify: {{ "I :heart: Hugo" | emojify }}
eq: {{ if eq .Section "blog" }}current{{ end }}
findRE: {{ findRE "[G|g]o" "Hugo is a static side generator written in Go." 1 }}
hasPrefix 1: {{ hasPrefix "Hugo" "Hu" }}
hasPrefix 2: {{ hasPrefix "Hugo" "Fu" }}
in: {{ if in "this string contains a substring" "substring" }}Substring found!{{ end }}
@ -138,6 +139,7 @@ delimit: A, B and C
div: 2
emojify: I Hugo
eq: current
findRE: [go]
hasPrefix 1: true
hasPrefix 2: false
in: Substring found!
@ -1801,6 +1803,30 @@ func TestReplaceRE(t *testing.T) {
}
}
func TestFindRE(t *testing.T) {
for i, this := range []struct {
expr string
content string
limit int
expect []string
ok bool
}{
{"[G|g]o", "Hugo is a static side generator written in Go.", 2, []string{"go", "Go"}, true},
{"[G|g]o", "Hugo is a static side generator written in Go.", -1, []string{"go", "Go"}, true},
{"[G|g]o", "Hugo is a static side generator written in Go.", 1, []string{"go"}, true},
{"[G|g]o", "Hugo is a static side generator written in Go.", 0, []string(nil), true},
{"[G|go", "Hugo is a static side generator written in Go.", 0, []string(nil), false},
} {
res, err := findRE(this.expr, this.content, this.limit)
if err != nil && this.ok {
t.Errorf("[%d] returned an unexpected error: %s", i, err)
}
assert.Equal(t, this.expect, res)
}
}
func TestTrim(t *testing.T) {
for i, this := range []struct {