mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-20 21:31:32 +02:00
tpl: Refactor package
Now: * The template API lives in /tpl * The rest lives in /tpl/tplimpl This is bound te be more improved in the future. Updates #2701
This commit is contained in:
269
tpl/tplimpl/template_ast_transformers_test.go
Normal file
269
tpl/tplimpl/template_ast_transformers_test.go
Normal file
@@ -0,0 +1,269 @@
|
||||
// Copyright 2016 The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package tplimpl
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"html/template"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
testFuncs = map[string]interface{}{
|
||||
"Echo": func(v interface{}) interface{} { return v },
|
||||
}
|
||||
|
||||
paramsData = map[string]interface{}{
|
||||
"NotParam": "Hi There",
|
||||
"Slice": []int{1, 3},
|
||||
"Params": map[string]interface{}{
|
||||
"lower": "P1L",
|
||||
},
|
||||
"Site": map[string]interface{}{
|
||||
"Params": map[string]interface{}{
|
||||
"lower": "P2L",
|
||||
"slice": []int{1, 3},
|
||||
},
|
||||
"Language": map[string]interface{}{
|
||||
"Params": map[string]interface{}{
|
||||
"lower": "P22L",
|
||||
},
|
||||
},
|
||||
"Data": map[string]interface{}{
|
||||
"Params": map[string]interface{}{
|
||||
"NOLOW": "P3H",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
paramsTempl = `
|
||||
{{ $page := . }}
|
||||
{{ $pageParams := .Params }}
|
||||
{{ $site := .Site }}
|
||||
{{ $siteParams := .Site.Params }}
|
||||
{{ $data := .Site.Data }}
|
||||
{{ $notparam := .NotParam }}
|
||||
|
||||
P1: {{ .Params.LOWER }}
|
||||
P1_2: {{ $.Params.LOWER }}
|
||||
P1_3: {{ $page.Params.LOWER }}
|
||||
P1_4: {{ $pageParams.LOWER }}
|
||||
P2: {{ .Site.Params.LOWER }}
|
||||
P2_2: {{ $.Site.Params.LOWER }}
|
||||
P2_3: {{ $site.Params.LOWER }}
|
||||
P2_4: {{ $siteParams.LOWER }}
|
||||
P22: {{ .Site.Language.Params.LOWER }}
|
||||
P3: {{ .Site.Data.Params.NOLOW }}
|
||||
P3_2: {{ $.Site.Data.Params.NOLOW }}
|
||||
P3_3: {{ $site.Data.Params.NOLOW }}
|
||||
P3_4: {{ $data.Params.NOLOW }}
|
||||
P4: {{ range $i, $e := .Site.Params.SLICE }}{{ $e }}{{ end }}
|
||||
P5: {{ Echo .Params.LOWER }}
|
||||
P5_2: {{ Echo $site.Params.LOWER }}
|
||||
{{ if .Params.LOWER }}
|
||||
IF: {{ .Params.LOWER }}
|
||||
{{ end }}
|
||||
{{ if .Params.NOT_EXIST }}
|
||||
{{ else }}
|
||||
ELSE: {{ .Params.LOWER }}
|
||||
{{ end }}
|
||||
|
||||
|
||||
{{ with .Params.LOWER }}
|
||||
WITH: {{ . }}
|
||||
{{ end }}
|
||||
|
||||
|
||||
{{ range .Slice }}
|
||||
RANGE: {{ . }}: {{ $.Params.LOWER }}
|
||||
{{ end }}
|
||||
{{ index .Slice 1 }}
|
||||
{{ .NotParam }}
|
||||
{{ .NotParam }}
|
||||
{{ .NotParam }}
|
||||
{{ .NotParam }}
|
||||
{{ .NotParam }}
|
||||
{{ .NotParam }}
|
||||
{{ .NotParam }}
|
||||
{{ .NotParam }}
|
||||
{{ .NotParam }}
|
||||
{{ .NotParam }}
|
||||
{{ $notparam }}
|
||||
|
||||
|
||||
{{ $lower := .Site.Params.LOWER }}
|
||||
F1: {{ printf "themes/%s-theme" .Site.Params.LOWER }}
|
||||
F2: {{ Echo (printf "themes/%s-theme" $lower) }}
|
||||
F3: {{ Echo (printf "themes/%s-theme" .Site.Params.LOWER) }}
|
||||
`
|
||||
)
|
||||
|
||||
func TestParamsKeysToLower(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
require.Error(t, applyTemplateTransformers(nil))
|
||||
|
||||
templ, err := template.New("foo").Funcs(testFuncs).Parse(paramsTempl)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
c := newTemplateContext(templ)
|
||||
|
||||
require.Equal(t, -1, c.decl.indexOfReplacementStart([]string{}))
|
||||
|
||||
c.paramsKeysToLower(templ.Tree.Root)
|
||||
|
||||
var b bytes.Buffer
|
||||
|
||||
require.NoError(t, templ.Execute(&b, paramsData))
|
||||
|
||||
result := b.String()
|
||||
|
||||
require.Contains(t, result, "P1: P1L")
|
||||
require.Contains(t, result, "P1_2: P1L")
|
||||
require.Contains(t, result, "P1_3: P1L")
|
||||
require.Contains(t, result, "P1_4: P1L")
|
||||
require.Contains(t, result, "P2: P2L")
|
||||
require.Contains(t, result, "P2_2: P2L")
|
||||
require.Contains(t, result, "P2_3: P2L")
|
||||
require.Contains(t, result, "P2_4: P2L")
|
||||
require.Contains(t, result, "P22: P22L")
|
||||
require.Contains(t, result, "P3: P3H")
|
||||
require.Contains(t, result, "P3_2: P3H")
|
||||
require.Contains(t, result, "P3_3: P3H")
|
||||
require.Contains(t, result, "P3_4: P3H")
|
||||
require.Contains(t, result, "P4: 13")
|
||||
require.Contains(t, result, "P5: P1L")
|
||||
require.Contains(t, result, "P5_2: P2L")
|
||||
|
||||
require.Contains(t, result, "IF: P1L")
|
||||
require.Contains(t, result, "ELSE: P1L")
|
||||
|
||||
require.Contains(t, result, "WITH: P1L")
|
||||
|
||||
require.Contains(t, result, "RANGE: 3: P1L")
|
||||
|
||||
require.Contains(t, result, "Hi There")
|
||||
|
||||
// Issue #2740
|
||||
require.Contains(t, result, "F1: themes/P2L-theme")
|
||||
require.Contains(t, result, "F2: themes/P2L-theme")
|
||||
require.Contains(t, result, "F3: themes/P2L-theme")
|
||||
|
||||
}
|
||||
|
||||
func BenchmarkTemplateParamsKeysToLower(b *testing.B) {
|
||||
templ, err := template.New("foo").Funcs(testFuncs).Parse(paramsTempl)
|
||||
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
templates := make([]*template.Template, b.N)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
templates[i], err = templ.Clone()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
c := newTemplateContext(templates[i])
|
||||
c.paramsKeysToLower(templ.Tree.Root)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParamsKeysToLowerVars(t *testing.T) {
|
||||
t.Parallel()
|
||||
var (
|
||||
ctx = map[string]interface{}{
|
||||
"Params": map[string]interface{}{
|
||||
"colors": map[string]interface{}{
|
||||
"blue": "Amber",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// This is how Amber behaves:
|
||||
paramsTempl = `
|
||||
{{$__amber_1 := .Params.Colors}}
|
||||
{{$__amber_2 := $__amber_1.Blue}}
|
||||
Color: {{$__amber_2}}
|
||||
Blue: {{ $__amber_1.Blue}}
|
||||
`
|
||||
)
|
||||
|
||||
templ, err := template.New("foo").Parse(paramsTempl)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
c := newTemplateContext(templ)
|
||||
|
||||
c.paramsKeysToLower(templ.Tree.Root)
|
||||
|
||||
var b bytes.Buffer
|
||||
|
||||
require.NoError(t, templ.Execute(&b, ctx))
|
||||
|
||||
result := b.String()
|
||||
|
||||
require.Contains(t, result, "Color: Amber")
|
||||
|
||||
}
|
||||
|
||||
func TestParamsKeysToLowerInBlockTemplate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var (
|
||||
ctx = map[string]interface{}{
|
||||
"Params": map[string]interface{}{
|
||||
"lower": "P1L",
|
||||
},
|
||||
}
|
||||
|
||||
master = `
|
||||
P1: {{ .Params.LOWER }}
|
||||
{{ block "main" . }}DEFAULT{{ end }}`
|
||||
overlay = `
|
||||
{{ define "main" }}
|
||||
P2: {{ .Params.LOWER }}
|
||||
{{ end }}`
|
||||
)
|
||||
|
||||
masterTpl, err := template.New("foo").Parse(master)
|
||||
require.NoError(t, err)
|
||||
|
||||
overlayTpl, err := template.Must(masterTpl.Clone()).Parse(overlay)
|
||||
require.NoError(t, err)
|
||||
overlayTpl = overlayTpl.Lookup(overlayTpl.Name())
|
||||
|
||||
c := newTemplateContext(overlayTpl)
|
||||
|
||||
c.paramsKeysToLower(overlayTpl.Tree.Root)
|
||||
|
||||
var b bytes.Buffer
|
||||
|
||||
require.NoError(t, overlayTpl.Execute(&b, ctx))
|
||||
|
||||
result := b.String()
|
||||
|
||||
require.Contains(t, result, "P1: P1L")
|
||||
require.Contains(t, result, "P2: P1L")
|
||||
}
|
Reference in New Issue
Block a user