diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2017-01-10 10:55:03 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2017-02-04 11:37:25 +0700 |
commit | c71e1b106e6011d148cac899f83c4685dee33a22 (patch) | |
tree | c5c7090f0c2398c7771e4908ebcc97aa7714ffd2 /tpl | |
parent | 0ada40591216572b0e4c6a8ab986b0aa4fb13c13 (diff) |
all: Refactor to nonglobal file systems
Updates #2701
Fixes #2951
Diffstat (limited to 'tpl')
-rw-r--r-- | tpl/amber_compiler.go | 42 | ||||
-rw-r--r-- | tpl/template.go | 170 | ||||
-rw-r--r-- | tpl/template_funcs.go | 92 | ||||
-rw-r--r-- | tpl/template_funcs_test.go | 189 | ||||
-rw-r--r-- | tpl/template_i18n.go | 1 | ||||
-rw-r--r-- | tpl/template_resources.go | 19 | ||||
-rw-r--r-- | tpl/template_resources_test.go | 32 | ||||
-rw-r--r-- | tpl/template_test.go | 110 |
8 files changed, 399 insertions, 256 deletions
diff --git a/tpl/amber_compiler.go b/tpl/amber_compiler.go new file mode 100644 index 000000000..4477f6ac0 --- /dev/null +++ b/tpl/amber_compiler.go @@ -0,0 +1,42 @@ +// Copyright 2017 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 tpl + +import ( + "html/template" + + "github.com/eknkc/amber" +) + +func (gt *GoHTMLTemplate) CompileAmberWithTemplate(b []byte, path string, t *template.Template) (*template.Template, error) { + c := amber.New() + + if err := c.ParseData(b, path); err != nil { + return nil, err + } + + data, err := c.CompileString() + + if err != nil { + return nil, err + } + + tpl, err := t.Funcs(gt.amberFuncMap).Parse(data) + + if err != nil { + return nil, err + } + + return tpl, nil +} diff --git a/tpl/template.go b/tpl/template.go index 867c0a2ef..1c71989f4 100644 --- a/tpl/template.go +++ b/tpl/template.go @@ -24,33 +24,12 @@ import ( "github.com/eknkc/amber" "github.com/spf13/afero" bp "github.com/spf13/hugo/bufferpool" + "github.com/spf13/hugo/deps" "github.com/spf13/hugo/helpers" - "github.com/spf13/hugo/hugofs" - jww "github.com/spf13/jwalterweatherman" "github.com/yosssi/ace" ) // TODO(bep) globals get rid of the rest of the jww.ERR etc. -//var tmpl *GoHTMLTemplate - -// TODO(bep) an interface with hundreds of methods ... remove it. -// And unexport most of these methods. -type Template interface { - ExecuteTemplate(wr io.Writer, name string, data interface{}) error - Lookup(name string) *template.Template - Templates() []*template.Template - New(name string) *template.Template - GetClone() *template.Template - LoadTemplates(absPath string) - LoadTemplatesWithPrefix(absPath, prefix string) - AddTemplate(name, tpl string) error - AddTemplateFileWithMaster(name, overlayFilename, masterFilename string) error - AddAceTemplate(name, basePath, innerPath string, baseContent, innerContent []byte) error - AddInternalTemplate(prefix, name, tpl string) error - AddInternalShortcode(name, tpl string) error - PrintErrors() - Funcs(funcMap template.FuncMap) -} type templateErr struct { name string @@ -70,52 +49,105 @@ type GoHTMLTemplate struct { funcster *templateFuncster - // TODO(bep) globals template - log *jww.Notepad + amberFuncMap template.FuncMap + + *deps.Deps } -// New returns a new Hugo Template System +type TemplateProvider struct{} + +var DefaultTemplateProvider *TemplateProvider + +// Update updates the Hugo Template System in the provided Deps. // with all the additional features, templates & functions -func New(logger *jww.Notepad, withTemplate ...func(templ Template) error) *GoHTMLTemplate { +func (*TemplateProvider) Update(deps *deps.Deps) error { + // TODO(bep) check that this isn't called too many times. tmpl := &GoHTMLTemplate{ Template: template.New(""), overlays: make(map[string]*template.Template), errors: make([]*templateErr, 0), - log: logger, + Deps: deps, } - tmpl.funcster = newTemplateFuncster(tmpl) + deps.Tmpl = tmpl - // The URL funcs in the funcMap is somewhat language dependent, - // so we need to wait until the language and site config is loaded. - // TODO(bep) globals - tmpl.funcster.initFuncMap() - - // TODO(bep) globals - for k, v := range tmpl.funcster.funcMap { - amber.FuncMap[k] = v - } + tmpl.initFuncs(deps) tmpl.LoadEmbedded() - for _, wt := range withTemplate { - err := wt(tmpl) + if deps.WithTemplate != nil { + err := deps.WithTemplate(tmpl) if err != nil { tmpl.errors = append(tmpl.errors, &templateErr{"init", err}) } } - tmpl.markReady() + tmpl.MarkReady() + + return nil + +} + +// Clone clones +func (*TemplateProvider) Clone(d *deps.Deps) error { + + t := d.Tmpl.(*GoHTMLTemplate) + + // 1. Clone the clone with new template funcs + // 2. Clone any overlays with new template funcs + + tmpl := &GoHTMLTemplate{ + Template: template.Must(t.Template.Clone()), + overlays: make(map[string]*template.Template), + errors: make([]*templateErr, 0), + Deps: d, + } + + d.Tmpl = tmpl + tmpl.initFuncs(d) + + for k, v := range t.overlays { + vc := template.Must(v.Clone()) + vc.Funcs(tmpl.funcster.funcMap) + tmpl.overlays[k] = vc + } + + tmpl.MarkReady() + + return nil +} + +func (t *GoHTMLTemplate) initFuncs(d *deps.Deps) { + + t.funcster = newTemplateFuncster(d) + + // The URL funcs in the funcMap is somewhat language dependent, + // so we need to wait until the language and site config is loaded. + t.funcster.initFuncMap() + + t.amberFuncMap = template.FuncMap{} + + for k, v := range amber.FuncMap { + t.amberFuncMap[k] = v + } + + for k, v := range t.funcster.funcMap { + t.amberFuncMap[k] = v + // Hacky, but we need to make sure that the func names are in the global map. + amber.FuncMap[k] = func() string { + panic("should never be invoked") + return "" + } + } - return tmpl } func (t *GoHTMLTemplate) Funcs(funcMap template.FuncMap) { t.Template.Funcs(funcMap) } -func (t *GoHTMLTemplate) partial(name string, contextList ...interface{}) template.HTML { +func (t *GoHTMLTemplate) Partial(name string, contextList ...interface{}) template.HTML { if strings.HasPrefix("partials/", name) { name = name[8:] } @@ -147,8 +179,8 @@ func (t *GoHTMLTemplate) executeTemplate(context interface{}, w io.Writer, layou } } if !worked { - t.log.ERROR.Println("Unable to render", layouts) - t.log.ERROR.Println("Expecting to find a template in either the theme/layouts or /layouts in one of the following relative locations", layouts) + t.Log.ERROR.Println("Unable to render", layouts) + t.Log.ERROR.Println("Expecting to find a template in either the theme/layouts or /layouts in one of the following relative locations", layouts) } } @@ -186,9 +218,9 @@ func (t *GoHTMLTemplate) LoadEmbedded() { t.EmbedTemplates() } -// markReady marks the template as "ready for execution". No changes allowed +// MarkReady marks the template as "ready for execution". No changes allowed // after this is set. -func (t *GoHTMLTemplate) markReady() { +func (t *GoHTMLTemplate) MarkReady() { if t.clone == nil { t.clone = template.Must(t.Template.Clone()) } @@ -244,7 +276,7 @@ func (t *GoHTMLTemplate) AddTemplateFileWithMaster(name, overlayFilename, master masterTpl := t.Lookup(masterFilename) if masterTpl == nil { - b, err := afero.ReadFile(hugofs.Source(), masterFilename) + b, err := afero.ReadFile(t.Fs.Source, masterFilename) if err != nil { return err } @@ -257,7 +289,7 @@ func (t *GoHTMLTemplate) AddTemplateFileWithMaster(name, overlayFilename, master } } - b, err := afero.ReadFile(hugofs.Source(), overlayFilename) + b, err := afero.ReadFile(t.Fs.Source, overlayFilename) if err != nil { return err } @@ -315,19 +347,13 @@ func (t *GoHTMLTemplate) AddTemplateFile(name, baseTemplatePath, path string) er switch ext { case ".amber": templateName := strings.TrimSuffix(name, filepath.Ext(name)) + ".html" - compiler := amber.New() - b, err := afero.ReadFile(hugofs.Source(), path) + b, err := afero.ReadFile(t.Fs.Source, path) if err != nil { return err } - // Parse the input data - if err := compiler.ParseData(b, path); err != nil { - return err - } - - templ, err := compiler.CompileWithTemplate(t.New(templateName)) + templ, err := t.CompileAmberWithTemplate(b, path, t.New(templateName)) if err != nil { return err } @@ -335,14 +361,14 @@ func (t *GoHTMLTemplate) AddTemplateFile(name, baseTemplatePath, path string) er return applyTemplateTransformers(templ) case ".ace": var innerContent, baseContent []byte - innerContent, err := afero.ReadFile(hugofs.Source(), path) + innerContent, err := afero.ReadFile(t.Fs.Source, path) if err != nil { return err } if baseTemplatePath != "" { - baseContent, err = afero.ReadFile(hugofs.Source(), baseTemplatePath) + baseContent, err = afero.ReadFile(t.Fs.Source, baseTemplatePath) if err != nil { return err } @@ -355,13 +381,13 @@ func (t *GoHTMLTemplate) AddTemplateFile(name, baseTemplatePath, path string) er return t.AddTemplateFileWithMaster(name, path, baseTemplatePath) } - b, err := afero.ReadFile(hugofs.Source(), path) + b, err := afero.ReadFile(t.Fs.Source, path) if err != nil { return err } - t.log.DEBUG.Printf("Add template file from path %s", path) + t.Log.DEBUG.Printf("Add template file from path %s", path) return t.AddTemplate(name, string(b)) } @@ -391,25 +417,25 @@ func isBaseTemplate(path string) bool { } func (t *GoHTMLTemplate) loadTemplates(absPath string, prefix string) { - t.log.DEBUG.Printf("Load templates from path %q prefix %q", absPath, prefix) + t.Log.DEBUG.Printf("Load templates from path %q prefix %q", absPath, prefix) walker := func(path string, fi os.FileInfo, err error) error { if err != nil { return nil } - t.log.DEBUG.Println("Template path", path) + t.Log.DEBUG.Println("Template path", path) if fi.Mode()&os.ModeSymlink == os.ModeSymlink { link, err := filepath.EvalSymlinks(absPath) if err != nil { - t.log.ERROR.Printf("Cannot read symbolic link '%s', error was: %s", absPath, err) + t.Log.ERROR.Printf("Cannot read symbolic link '%s', error was: %s", absPath, err) return nil } - linkfi, err := hugofs.Source().Stat(link) + linkfi, err := t.Fs.Source.Stat(link) if err != nil { - t.log.ERROR.Printf("Cannot stat '%s', error was: %s", link, err) + t.Log.ERROR.Printf("Cannot stat '%s', error was: %s", link, err) return nil } if !linkfi.Mode().IsRegular() { - t.log.ERROR.Printf("Symbolic links for directories not supported, skipping '%s'", absPath) + t.Log.ERROR.Printf("Symbolic links for directories not supported, skipping '%s'", absPath) } return nil } @@ -441,7 +467,7 @@ func (t *GoHTMLTemplate) loadTemplates(absPath string, prefix string) { // This may be a view that shouldn't have base template // Have to look inside it to make sure - needsBase, err := helpers.FileContainsAny(path, innerMarkers, hugofs.Source()) + needsBase, err := helpers.FileContainsAny(path, innerMarkers, t.Fs.Source) if err != nil { return err } @@ -482,7 +508,7 @@ func (t *GoHTMLTemplate) loadTemplates(absPath string, prefix string) { for _, pair := range pairsToCheck { pathsToCheck := basePathsToCheck(pair, layoutDir, themeDir) for _, pathToCheck := range pathsToCheck { - if ok, err := helpers.Exists(pathToCheck, hugofs.Source()); err == nil && ok { + if ok, err := helpers.Exists(pathToCheck, t.Fs.Source); err == nil && ok { baseTemplatePath = pathToCheck break Loop } @@ -492,14 +518,14 @@ func (t *GoHTMLTemplate) loadTemplates(absPath string, prefix string) { } if err := t.AddTemplateFile(tplName, baseTemplatePath, path); err != nil { - t.log.ERROR.Printf("Failed to add template %s in path %s: %s", tplName, path, err) + t.Log.ERROR.Printf("Failed to add template %s in path %s: %s", tplName, path, err) } } return nil } - if err := helpers.SymbolicWalk(hugofs.Source(), absPath, walker); err != nil { - t.log.ERROR.Printf("Failed to load templates: %s", err) + if err := helpers.SymbolicWalk(t.Fs.Source, absPath, walker); err != nil { + t.Log.ERROR.Printf("Failed to load templates: %s", err) } } @@ -526,6 +552,6 @@ func (t *GoHTMLTemplate) LoadTemplates(absPath string) { func (t *GoHTMLTemplate) PrintErrors() { for i, e := range t.errors { - t.log.ERROR.Println(i, ":", e.err) + t.Log.ERROR.Println(i, ":", e.err) } } diff --git a/tpl/template_funcs.go b/tpl/template_funcs.go index 8f653808b..5db5e54ac 100644 --- a/tpl/template_funcs.go +++ b/tpl/template_funcs.go @@ -43,8 +43,8 @@ import ( "github.com/bep/inflect" "github.com/spf13/afero" "github.com/spf13/cast" + "github.com/spf13/hugo/deps" "github.com/spf13/hugo/helpers" - "github.com/spf13/hugo/hugofs" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" @@ -56,14 +56,15 @@ import ( // Some of the template funcs are'nt entirely stateless. type templateFuncster struct { - t *GoHTMLTemplate funcMap template.FuncMap cachedPartials partialCache + + *deps.Deps } -func newTemplateFuncster(t *GoHTMLTemplate) *templateFuncster { +func newTemplateFuncster(deps *deps.Deps) *templateFuncster { return &templateFuncster{ - t: t, + Deps: deps, cachedPartials: partialCache{p: make(map[string]template.HTML)}, } } @@ -424,7 +425,7 @@ func resetImageConfigCache() { // imageConfig returns the image.Config for the specified path relative to the // working directory. resetImageConfigCache must be run beforehand. -func imageConfig(path interface{}) (image.Config, error) { +func (t *templateFuncster) imageConfig(path interface{}) (image.Config, error) { filename, err := cast.ToStringE(path) if err != nil { return image.Config{}, err @@ -443,7 +444,7 @@ func imageConfig(path interface{}) (image.Config, error) { return config, nil } - f, err := hugofs.WorkingDir().Open(filename) + f, err := t.Fs.WorkingDir.Open(filename) if err != nil { return image.Config{}, err } @@ -1013,7 +1014,7 @@ func where(seq, key interface{}, args ...interface{}) (interface{}, error) { } // apply takes a map, array, or slice and returns a new slice with the function fname applied over it. -func (tf *templateFuncster) apply(seq interface{}, fname string, args ...interface{}) (interface{}, error) { +func (t *templateFuncster) apply(seq interface{}, fname string, args ...interface{}) (interface{}, error) { if seq == nil { return make([]interface{}, 0), nil } @@ -1028,7 +1029,7 @@ func (tf *templateFuncster) apply(seq interface{}, fname string, args ...interfa return nil, errors.New("can't iterate over a nil value") } - fn, found := tf.funcMap[fname] + fn, found := t.funcMap[fname] if !found { return nil, errors.New("can't find function " + fname) } @@ -1528,26 +1529,27 @@ type partialCache struct { // Get retrieves partial output from the cache based upon the partial name. // If the partial is not found in the cache, the partial is rendered and added // to the cache. -func (tf *templateFuncster) Get(key, name string, context interface{}) (p template.HTML) { +func (t *templateFuncster) Get(key, name string, context interface{}) (p template.HTML) { var ok bool - tf.cachedPartials.RLock() - p, ok = tf.cachedPartials.p[key] - tf.cachedPartials.RUnlock() + t.cachedPartials.RLock() + p, ok = t.cachedPartials.p[key] + t.cachedPartials.RUnlock() if ok { return p } - tf.cachedPartials.Lock() - if p, ok = tf.cachedPartials.p[key]; !ok { - tf.cachedPartials.Unlock() - p = tf.t.partial(name, context) + t.cachedPartials.Lock() + if p, ok = t.cachedPartials.p[key]; !ok { + t.cachedPartials.Unlock() + p = t.Tmpl.Partial(name, context) + + t.cachedPartials.Lock() + t.cachedPartials.p[key] = p - tf.cachedPartials.Lock() - tf.cachedPartials.p[key] = p } - tf.cachedPartials.Unlock() + t.cachedPartials.Unlock() return p } @@ -1556,14 +1558,14 @@ func (tf *templateFuncster) Get(key, name string, context interface{}) (p templa // string parameter (a string slice actually, but be only use a variadic // argument to make it optional) can be passed so that a given partial can have // multiple uses. The cache is created with name+variant as the key. -func (tf *templateFuncster) partialCached(name string, context interface{}, variant ...string) template.HTML { +func (t *templateFuncster) partialCached(name string, context interface{}, variant ...string) template.HTML { key := name if len(variant) > 0 { for i := 0; i < len(variant); i++ { key += variant[i] } } - return tf.Get(key, name, context) + return t.Get(key, name, context) } // regexpCache represents a cache of regexp objects protected by a mutex. @@ -1814,23 +1816,23 @@ func readFile(fs *afero.BasePathFs, filename string) (string, error) { // configured WorkingDir. // It returns the contents as a string. // There is a upper size limit set at 1 megabytes. -func readFileFromWorkingDir(i interface{}) (string, error) { +func (t *templateFuncster) readFileFromWorkingDir(i interface{}) (string, error) { s, err := cast.ToStringE(i) if err != nil { return "", err } - return readFile(hugofs.WorkingDir(), s) + return readFile(t.Fs.WorkingDir, s) } // readDirFromWorkingDir listst the directory content relative to the // configured WorkingDir. -func readDirFromWorkingDir(i interface{}) ([]os.FileInfo, error) { +func (t *templateFuncster) readDirFromWorkingDir(i interface{}) ([]os.FileInfo, error) { path, err := cast.ToStringE(i) if err != nil { return nil, err } - list, err := afero.ReadDir(hugofs.WorkingDir(), path) + list, err := afero.ReadDir(t.Fs.WorkingDir, path) if err != nil { return nil, fmt.Errorf("Failed to read Directory %s with error message %s", path, err) @@ -2074,20 +2076,20 @@ func htmlUnescape(in interface{}) (string, error) { return html.UnescapeString(conv), nil } -func absURL(a interface{}) (template.HTML, error) { +func (t *templateFuncster) absURL(a interface{}) (template.HTML, error) { s, err := cast.ToStringE(a) if err != nil { return "", nil } - return template.HTML(helpers.CurrentPathSpec().AbsURL(s, false)), nil + return template.HTML(t.PathSpec.AbsURL(s, false)), nil } -func relURL(a interface{}) (template.HTML, error) { +func (t *templateFuncster) relURL(a interface{}) (template.HTML, error) { s, err := cast.ToStringE(a) if err != nil { return "", nil } - return template.HTML(helpers.CurrentPathSpec().RelURL(s, false)), nil + return template.HTML(t.PathSpec.RelURL(s, false)), nil } // getenv retrieves the value of the environment variable named by the key. @@ -2101,19 +2103,19 @@ func getenv(key interface{}) (string, error) { return os.Getenv(skey), nil } -func (tf *templateFuncster) initFuncMap() { +func (t *templateFuncster) initFuncMap() { funcMap := template.FuncMap{ - "absURL": absURL, + "absURL": t.absURL, "absLangURL": func(i interface{}) (template.HTML, error) { s, err := cast.ToStringE(i) if err != nil { return "", err } - return template.HTML(helpers.CurrentPathSpec().AbsURL(s, true)), nil + return template.HTML(t.PathSpec.AbsURL(s, true)), nil }, "add": func(a, b interface{}) (interface{}, error) { return helpers.DoArithmetic(a, b, '+') }, "after": after, - "apply": tf.apply, + "apply": t.apply, "base64Decode": base64Decode, "base64Encode": base64Encode, "chomp": chomp, @@ -2130,8 +2132,8 @@ func (tf *templateFuncster) initFuncMap() { "findRE": findRE, "first": first, "ge": ge, - "getCSV": getCSV, - "getJSON": getJSON, + "getCSV": t.getCSV, + "getJSON": t.getJSON, "getenv": getenv, "gt": gt, "hasPrefix": hasPrefix, @@ -2139,7 +2141,7 @@ func (tf *templateFuncster) initFuncMap() { "htmlEscape": htmlEscape, "htmlUnescape": htmlUnescape, "humanize": humanize, - "imageConfig": imageConfig, + "imageConfig": t.imageConfig, "in": in, "index": index, "int": func(v interface{}) (int, error) { return cast.ToIntE(v) }, @@ -2158,21 +2160,21 @@ func (tf *templateFuncster) initFuncMap() { "mul": func(a, b interface{}) (interface{}, error) { return helpers.DoArithmetic(a, b, '*') }, "ne": ne, "now": func() time.Time { return time.Now() }, - "partial": tf.t.partial, - "partialCached": tf.partialCached, + "partial": t.Tmpl.Partial, + "partialCached": t.partialCached, "plainify": plainify, "pluralize": pluralize, "querify": querify, - "readDir": readDirFromWorkingDir, - "readFile": readFileFromWorkingDir, + "readDir": t.readDirFromWorkingDir, + "readFile": t.readFileFromWorkingDir, "ref": ref, - "relURL": relURL, + "relURL": t.relURL, "relLangURL": func(i interface{}) (template.HTML, error) { s, err := cast.ToStringE(i) if err != nil { return "", err } - return template.HTML(helpers.CurrentPathSpec().RelURL(s, true)), nil + return template.HTML(t.PathSpec.RelURL(s, true)), nil }, "relref": relRef, "replace": replace, @@ -2201,12 +2203,12 @@ func (tf *templateFuncster) initFuncMap() { "trim": trim, "truncate": truncate, "upper": upper, - "urlize": helpers.CurrentPathSpec().URLize, + "urlize": t.PathSpec.URLize, "where": where, "i18n": i18nTranslate, "T": i18nTranslate, } - tf.funcMap = funcMap - tf.t.Funcs(funcMap) + t.funcMap = funcMap + t.Tmpl.Funcs(funcMap) } diff --git a/tpl/template_funcs_test.go b/tpl/template_funcs_test.go index e0c185092..e5d0193a6 100644 --- a/tpl/template_funcs_test.go +++ b/tpl/template_funcs_test.go @@ -31,6 +31,9 @@ import ( "testing" "time" + "github.com/spf13/hugo/tplapi" + + "github.com/spf13/hugo/deps" "github.com/spf13/hugo/helpers" "io/ioutil" @@ -43,9 +46,17 @@ import ( jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -var logger = jww.NewNotepad(jww.LevelFatal, jww.LevelFatal, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime) +var ( + logger = jww.NewNotepad(jww.LevelFatal, jww.LevelFatal, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime) + defaultDepsConfig = deps.DepsCfg{ + Language: helpers.NewLanguage("en"), + Logger: logger, + TemplateProvider: DefaultTemplateProvider, + } +) type tstNoStringer struct { } @@ -80,8 +91,7 @@ func tstInitTemplates() { func TestFuncsInTemplate(t *testing.T) { - viper.Reset() - defer viper.Reset() + testReset() workingDir := "/home/hugo" @@ -89,10 +99,9 @@ func TestFuncsInTemplate(t *testing.T) { viper.Set("currentContentLanguage", helpers.NewDefaultLanguage()) viper.Set("multilingual", true) - fs := &afero.MemMapFs{} - hugofs.InitFs(fs) + fs := hugofs.NewMem() - afero.WriteFile(fs, filepath.Join(workingDir, "README.txt"), []byte("Hugo Rocks!"), 0755) + afero.WriteFile(fs.Source, filepath.Join(workingDir, "README.txt"), []byte("Hugo Rocks!"), 0755) // Add the examples from the docs: As a smoke test and to make sure the examples work. // TODO(bep): docs: fix title example @@ -244,7 +253,7 @@ urlize: bat-man ` var b bytes.Buffer - templ, err := New(logger).New("test").Parse(in) + var data struct { Title string Section string @@ -259,11 +268,21 @@ urlize: bat-man tstInitTemplates() - if err != nil { - t.Fatal("Got error on parse", err) + config := defaultDepsConfig + config.WithTemplate = func(templ tplapi.Template) error { + if _, err := templ.New("test").Parse(in); err != nil { + t.Fatal("Got error on parse", err) + } + return nil + } + config.Fs = fs + + d := deps.New(config) + if err := d.LoadTemplates(); err != nil { + t.Fatal(err) } - err = templ.Execute(&b, &data) + err := d.Tmpl.Lookup("test").Execute(&b, &data) if err != nil { t.Fatal("Got error on execute", err) @@ -624,15 +643,13 @@ func blankImage(width, height int) []byte { } func TestImageConfig(t *testing.T) { - viper.Reset() - defer viper.Reset() + testReset() workingDir := "/home/hugo" viper.Set("workingDir", workingDir) - fs := &afero.MemMapFs{} - hugofs.InitFs(fs) + f := newTestFuncster() for i, this := range []struct { resetCache bool @@ -692,13 +709,13 @@ func TestImageConfig(t *testing.T) { }, }, } { - afero.WriteFile(fs, filepath.Join(workingDir, this.path), this.input, 0755) + afero.WriteFile(f.Fs.Source, filepath.Join(workingDir, this.path), this.input, 0755) if this.resetCache { resetImageConfigCache() } - result, err := imageConfig(this.path) + result, err := f.imageConfig(this.path) if err != nil { t.Errorf("imageConfig returned error: %s", err) } @@ -712,15 +729,15 @@ func TestImageConfig(t *testing.T) { } } - if _, err := imageConfig(t); err == nil { + if _, err := f.imageConfig(t); err == nil { t.Error("Expected error from imageConfig when passed invalid path") } - if _, err := imageConfig("non-existent.png"); err == nil { + if _, err := f.imageConfig("non-existent.png"); err == nil { t.Error("Expected error from imageConfig when passed non-existent file") } - if _, err := imageConfig(""); err == nil { + if _, err := f.imageConfig(""); err == nil { t.Error("Expected error from imageConfig when passed empty path") } @@ -2381,14 +2398,11 @@ func TestDefault(t *testing.T) { {map[string]string{"foo": "dog"}, `{{ default "nope" .foo "extra" }}`, ``, false}, {map[string]interface{}{"images": []string{}}, `{{ default "default.jpg" (index .images 0) }}`, `default.jpg`, true}, } { - tmpl, err := New(logger).New("test").Parse(this.tpl) - if err != nil { - t.Errorf("[%d] unable to create new html template %q: %s", i, this.tpl, err) - continue - } + + tmpl := newTestTemplate(t, "test", this.tpl) buf := new(bytes.Buffer) - err = tmpl.Execute(buf, this.input) + err := tmpl.Execute(buf, this.input) if (err == nil) != this.ok { t.Errorf("[%d] execute template returned unexpected error: %s", i, err) continue @@ -2520,6 +2534,7 @@ func TestSafeCSS(t *testing.T) { } } +// TODO(bep) what is this? Also look above. func TestSafeJS(t *testing.T) { for i, this := range []struct { str string @@ -2560,6 +2575,7 @@ func TestSafeJS(t *testing.T) { } } +// TODO(bep) what is this? func TestSafeURL(t *testing.T) { for i, this := range []struct { str string @@ -2716,18 +2732,16 @@ func TestSHA256(t *testing.T) { } func TestReadFile(t *testing.T) { - viper.Reset() - defer viper.Reset() + testReset() workingDir := "/home/hugo" viper.Set("workingDir", workingDir) - fs := &afero.MemMapFs{} - hugofs.InitFs(fs) + f := newTestFuncster() - afero.WriteFile(fs, filepath.Join(workingDir, "/f/f1.txt"), []byte("f1-content"), 0755) - afero.WriteFile(fs, filepath.Join("/home", "f2.txt"), []byte("f2-content"), 0755) + afero.WriteFile(f.Fs.Source, filepath.Join(workingDir, "/f |