dati

A Go library/binary to parse & execute data against template langauges.
git clone git://src.gearsix.net/dati
Log | Files | Refs | Atom | README | LICENSE

commit c92784b306e68ebb5ff5722e9f52e4cf65a39035
parent cf16a5f0c2b5a76c2762d1bf521d07e4cdfb0d45
Author: gearsix <gearsix@tuta.io>
Date:   Thu, 17 Mar 2022 21:09:55 +0000

regressed compatibility - builds with go1.13

Diffstat:
Mcmd/suti.go | 3+--
Mdata_test.go | 2+-
Mfile_test.go | 2+-
Mgo.mod | 2+-
Mtemplate.go | 13+++++++------
Dtemplate.go.orig | 296-------------------------------------------------------------------------------
Mtemplate_test.go | 5+++--
7 files changed, 14 insertions(+), 309 deletions(-)

diff --git a/cmd/suti.go b/cmd/suti.go @@ -21,7 +21,6 @@ import ( "bufio" "bytes" "fmt" - "io/fs" "notabug.org/gearsix/suti" "os" "path/filepath" @@ -267,7 +266,7 @@ func loadFilePaths(paths ...string) (filepaths []string) { } } else { err = filepath.Walk(path, - func(p string, info fs.FileInfo, e error) error { + func(p string, info os.FileInfo, e error) error { if e == nil && !info.IsDir() { filepaths = append(filepaths, p) } diff --git a/data_test.go b/data_test.go @@ -130,7 +130,7 @@ func TestLoadDataFilepath(t *testing.T) { var d interface{} var e error var p string - tdir := t.TempDir() + tdir := os.TempDir() for lang, data := range good { p = tdir + "/good." + lang diff --git a/file_test.go b/file_test.go @@ -10,7 +10,7 @@ import ( func TestSortFileList(t *testing.T) { var err error - tdir := t.TempDir() + tdir := os.TempDir() paths := []string{tdir + "/1", tdir + "/3", tdir + "/2"} var sorted []string diff --git a/go.mod b/go.mod @@ -1,6 +1,6 @@ module notabug.org/gearsix/suti -go 1.16 +go 1.13 require ( github.com/cbroglie/mustache v1.2.0 diff --git a/template.go b/template.go @@ -23,6 +23,7 @@ import ( mst "github.com/cbroglie/mustache" hmpl "html/template" "io" + "io/ioutil" "os" "path/filepath" "reflect" @@ -151,14 +152,14 @@ func LoadTemplateString(lang string, rootName string, root string, partials map[ func loadTemplateTmpl(rootName string, root io.Reader, partials map[string]io.Reader) (*tmpl.Template, error) { var template *tmpl.Template - if buf, err := io.ReadAll(root); err != nil { + if buf, err := ioutil.ReadAll(root); err != nil { return nil, err } else if template, err = tmpl.New(rootName).Parse(string(buf)); err != nil { return nil, err } for name, partial := range partials { - if buf, err := io.ReadAll(partial); err != nil { + if buf, err := ioutil.ReadAll(partial); err != nil { return nil, err } else if _, err = template.New(name).Parse(string(buf)); err != nil { return nil, err @@ -171,14 +172,14 @@ func loadTemplateTmpl(rootName string, root io.Reader, partials map[string]io.Re func loadTemplateHmpl(rootName string, root io.Reader, partials map[string]io.Reader) (*hmpl.Template, error) { var template *hmpl.Template - if buf, err := io.ReadAll(root); err != nil { + if buf, err := ioutil.ReadAll(root); err != nil { return nil, err } else if template, err = hmpl.New(rootName).Parse(string(buf)); err != nil { return nil, err } for name, partial := range partials { - if buf, err := io.ReadAll(partial); err != nil { + if buf, err := ioutil.ReadAll(partial); err != nil { return nil, err } else if _, err = template.New(name).Parse(string(buf)); err != nil { return nil, err @@ -194,14 +195,14 @@ func loadTemplateMst(rootName string, root io.Reader, partials map[string]io.Rea mstpp := new(mst.StaticProvider) mstpp.Partials = make(map[string]string) for name, partial := range partials { - if buf, err := io.ReadAll(partial); err != nil { + if buf, err := ioutil.ReadAll(partial); err != nil { return nil, err } else { mstpp.Partials[name] = string(buf) } } - if buf, err := io.ReadAll(root); err != nil { + if buf, err := ioutil.ReadAll(root); err != nil { return nil, err } else if template, err = mst.ParseStringPartials(string(buf), mstpp); err != nil { return nil, err diff --git a/template.go.orig b/template.go.orig @@ -1,296 +0,0 @@ -package suti - -/* -Copyright (C) 2021 gearsix <gearsix@tuta.io> - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <https://www.gnu.org/licenses/>. -*/ - -import ( - "bytes" - "fmt" - mst "github.com/cbroglie/mustache" - hmpl "html/template" - "io/fs" - "os" - "path/filepath" - "reflect" - "strconv" - "strings" - tmpl "text/template" -) - -// SupportedTemplateLangs provides a list of supported languages for template files (lower-case) -var SupportedTemplateLangs = []string{"tmpl", "hmpl", "mst"} - -// IsSupportedTemplateLang provides the index of `SupportedTemplateLangs` that `lang` is at. -// If `lang` is not in `SupportedTemplateLangs`, `-1` will be returned. -// File extensions can be passed in `lang`, the prefixed `.` will be trimmed. -func IsSupportedTemplateLang(lang string) int { - lang = strings.ToLower(lang) - if len(lang) > 0 && lang[0] == '.' { - lang = lang[1:] - } - for i, l := range SupportedTemplateLangs { - if lang == l { - return i - } - } - return -1 -} - -func getTemplateType(path string) string { - return strings.TrimPrefix(filepath.Ext(path), ".") -} - -// Template is a generic interface to any template parsed from LoadTemplateFile -type Template struct { - Source string - Template interface{} -} - -// Execute executes `t` against `d`. Reflection is used to determine -// the template type and call it's execution fuction. -func (t *Template) Execute(d interface{}) (result bytes.Buffer, err error) { - var funcName string - var params []reflect.Value - switch (reflect.TypeOf(t.Template).String()) { - case "*template.Template": // golang templates - funcName = "Execute" - params = []reflect.Value{reflect.ValueOf(&result), reflect.ValueOf(d)} - case "*mustache.Template": - funcName = "FRender" - params = []reflect.Value{reflect.ValueOf(&result), reflect.ValueOf(d)} - default: - err = fmt.Errorf("unable to infer template type '%s'", reflect.TypeOf(t.Template).String()) - } - - if err == nil { - rval := reflect.ValueOf(t.Template).MethodByName(funcName).Call(params) - if !rval[0].IsNil() { // err != nil - err = rval[0].Interface().(error) - } - } - - return -} - -// TODO -func LoadTemplateFileTmpl(root string, partials ...string) (*tmpl.Template, error) { - var stat os.FileInfo - t, e := tmpl.ParseFiles(root) - - for i := 0; i < len(partials) && e == nil; i++ { - p := partials[i] - ptype := getTemplateType(p) - - stat, e = os.Stat(p) - if e == nil { - if ptype == "tmpl" || ptype == "gotmpl" { - t, e = t.ParseFiles(p) - } else if strings.Contains(p, "*") { - t, e = t.ParseGlob(p) - } else if stat.IsDir() { - e = filepath.Walk(p, func(path string, info fs.FileInfo, err error) error { - if err == nil && !info.IsDir() { - ptype = getTemplateType(path) - if ptype == "tmpl" || ptype == "gotmpl" { - t, err = t.ParseFiles(path) - } - } - return err - }) - } else { - return nil, fmt.Errorf("non-matching filetype (%s)", p) - } - } - } - - return t, e -} - -// TODO -func LoadTemplateFileHmpl(root string, partials ...string) (*hmpl.Template, error) { - var stat os.FileInfo - t, e := hmpl.ParseFiles(root) - - for i := 0; i < len(partials) && e == nil; i++ { - p := partials[i] - ptype := getTemplateType(p) - - stat, e = os.Stat(p) - if e == nil { - if ptype == "hmpl" || ptype == "gohmpl" { - t, e = t.ParseFiles(p) - } else if strings.Contains(p, "*") { - t, e = t.ParseGlob(p) - } else if stat.IsDir() { - e = filepath.Walk(p, func(path string, info fs.FileInfo, err error) error { - if err == nil && !info.IsDir() { - ptype = getTemplateType(path) - if ptype == "hmpl" || ptype == "gohmpl" { - t, err = t.ParseFiles(path) - } - } - return err - }) - } else { - return nil, fmt.Errorf("non-matching filetype (%s)", p) - } - } - } - - return t, e -} - -// TODO -func LoadTemplateFileMst(root string, partials ...string) (*mst.Template, error) { - var err error - for p, partial := range partials { - if err != nil { - break - } - - if stat, e := os.Stat(partial); e != nil { - partials = append(partials[:p], partials[p+1:]...) - err = e - } else if stat.IsDir() == false { - partials[p] = filepath.Dir(partial) - } else if strings.Contains(partial, "*") { - if paths, e := filepath.Glob(partial); e != nil { - partials = append(partials[:p], partials[p+1:]...) - err = e - } else { - partials = append(partials[:p], partials[p+1:]...) - partials = append(partials, paths...) - } - } - } - - if err != nil { - return nil, err - } - - mstfp := &mst.FileProvider{ - Paths: partials, - Extensions: []string{".mst", ".mustache"}, - } - return mst.ParseFilePartials(root, mstfp) -} - -// LoadTemplateFile loads a Template from file `root`. All files in `partials` -// that have the same template type (identified by file extension) are also -// parsed and associated with the parsed root template. -func LoadTemplateFile(root string, partials ...string) (t Template, e error) { - if len(root) == 0 { - e = fmt.Errorf("no root template specified") - } - if stat, err := os.Stat(root); err != nil { - e = err - } else if stat.IsDir() { - e = fmt.Errorf("root path must be a file, not a directory: %s", root) - } - -<<<<<<< HEAD - if e == nil { - t = Template{Source: root} - ttype := getTemplateType(root) - if ttype == "tmpl" || ttype == "gotmpl" { - t.Template, e = LoadTemplateFileTmpl(root, partials...) - } else if ttype == "hmpl" || ttype == "gohmpl" { - t.Template, e = LoadTemplateFileHmpl(root, partials...) - } else if ttype == "mst" || ttype == "mustache" { - t.Template, e = LoadTemplateFileMst(root, partials...) - } else { - e = fmt.Errorf("'%s' is not a supported template language", ttype) -======= - if e != nil { - return - } - - t = Template{Source: root} - ttype := getTemplateType(root) - if ttype == "tmpl" || ttype == "gotmpl" { - t.Template, e = loadTemplateFileTmpl(root, partials...) - } else if ttype == "hmpl" || ttype == "gohmpl" { - t.Template, e = loadTemplateFileHmpl(root, partials...) - } else if ttype == "mst" || ttype == "mustache" { - t.Template, e = loadTemplateFileMst(root, partials...) - } else { - e = fmt.Errorf("'%s' is not a supported template language", ttype) - } - - return -} - -// LoadTemplateString loads a Template from string `root` of type `ttype`, named `name`. -// `ttype` must be an element in `SupportedTemplateLangs`. -// `name` is optional, if empty the template name will be "template". -// `root` should be a string of template, with syntax matching that of `ttype`. -// `partials` should be a string of template, with syntax matching that of `ttype`. -func LoadTemplateString(ttype string, name string, root string, partials ...string) (t Template, e error) { - if len(root) == 0 { - e = fmt.Errorf("no root template") - } - if IsSupportedTemplateLang(ttype) == -1 { - e = fmt.Errorf("invalid type '%s'", ttype) - } - if e != nil { - return - } - - if len(name) == 0 { - name = "template" - } - - switch(ttype) { - case "tmpl": - var template *tmpl.Template - if template, e = tmpl.New(name).Parse(root); e != nil { - break - } - for i, p := range partials { - if _, e = template.New(name + "-partial" + strconv.Itoa(i)).Parse(p); e != nil { - break - } ->>>>>>> LoadTemplateString - } - t.Template = template - case "hmpl": - var template *hmpl.Template - if template, e = hmpl.New(name).Parse(root); e != nil { - break - } - for i, p := range partials { - if _, e = template.New(name + "-partial" + strconv.Itoa(i)).Parse(p); e != nil { - break - } - } - t.Template = template - case "mst": - var template *mst.Template - mstpp := new(mst.StaticProvider) - mstpp.Partials = make(map[string]string) - for p, partial := range partials { - mstpp.Partials[name+"-partial"+strconv.Itoa(p)] = partial - } - template, e = mst.ParseStringPartials(root, mstpp) - t.Template = template - default: - e = fmt.Errorf("'%s' is not a supported template language", ttype) - } - - return -} - diff --git a/template_test.go b/template_test.go @@ -20,6 +20,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. import ( "bytes" "os" + "io/ioutil" "path/filepath" "reflect" "strings" @@ -124,11 +125,11 @@ func validateTemplateFile(t *testing.T, template Template, rootPath string, part func TestLoadTemplateFilepath(t *testing.T) { t.Parallel() - tdir := t.TempDir() + tdir := os.TempDir() var goodRoots, goodPartials, badRoots, badPartials []string createFile := func(path string, data string) { - if err := os.WriteFile(path, []byte(data), 0666); err != nil { + if err := ioutil.WriteFile(path, []byte(data), 0666); err != nil { t.Error(err) } }