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 f398e7bf052fef157b92e47aafba3c5f90a811d1
parent 71f0d3dba246487873e445ec38cabdc53fe87c13
Author: gearsix <gearsix@tuta.io>
Date:   Sat,  2 Oct 2021 00:35:19 +0100

finished LoadTemplateString & tests

Diffstat:
Mtemplate.go | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Mtemplate_test.go | 88++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
2 files changed, 116 insertions(+), 46 deletions(-)

diff --git a/template.go b/template.go @@ -193,47 +193,85 @@ 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) } - 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 } -// LoadTemplateStringTmpl -func LoadTemplateStringTmpl(name string, root string, partials ...string) (t Template, e error) { +// 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 specified") + 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" } - if e == nil { - template := tmpl.Must(tmpl.New(name).Parse(root)) + 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 } } 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 @@ -25,6 +25,24 @@ import ( "testing" ) +const tmplRootGood = "{{.eg}} {{ template \"tmplPartialGood.tmpl\" . }}" +const tmplPartialGood = "{{range .data}}{{.eg}}{{end}}" +const tmplResult = "0 00" +const tmplRootBad = "{{ example }}} {{{ template \"tmplPartialBad.tmpl\" . }}" +const tmplPartialBad = "{{{ .example }}" + +const hmplRootGood = "<!DOCTYPE html><html><p>{{.eg}} {{ template \"hmplPartialGood.hmpl\" . }}</p></html>" +const hmplPartialGood = "<b>{{range .data}}{{.eg}}{{end}}</b>" +const hmplResult = "<!DOCTYPE html><html><p>0 <b>00</b></p></html>" +const hmplRootBad = "{{ example }} {{{ template \"hmplPartialBad.hmpl\" . }}" +const hmplPartialBad = "<b>{{{ .example2 }}</b>" + +const mstRootGood = "{{eg}} {{> mstPartialGood}}" +const mstPartialGood = "{{#data}}{{eg}}{{/data}}" +const mstResult = "0 00" +const mstRootBad = "{{> badPartial.mst}}{{#doesnt-exist}}{{/exit}}" +const mstPartialBad = "p{{$}{{ > noexist}}" + func TestIsSupportedTemplateLang(t *testing.T) { exts := []string{ ".tmpl", "tmpl", "TMPL", ".TMPL", @@ -55,24 +73,6 @@ func TestIsSupportedTemplateLang(t *testing.T) { } } -const tmplRootGood = "{{.eg}} {{ template \"tmplPartialGood.tmpl\" . }}" -const tmplPartialGood = "{{range .data}}{{.eg}}{{end}}" -const tmplResult = "0 00" -const tmplRootBad = "{{ example }}} {{{ template \"tmplPartialBad.tmpl\" . }}" -const tmplPartialBad = "{{{ .example }}" - -const hmplRootGood = "<!DOCTYPE html><html><p>{{.eg}} {{ template \"hmplPartialGood.hmpl\" . }}</p></html>" -const hmplPartialGood = "<b>{{range .data}}{{.eg}}{{end}}</b>" -const hmplResult = "<!DOCTYPE html><html><p>0 <b>00</b></p></html>" -const hmplRootBad = "{{ example }} {{{ template \"hmplPartialBad.hmpl\" . }}" -const hmplPartialBad = "<b>{{{ .example2 }}</b>" - -const mstRootGood = "{{eg}} {{> mstPartialGood}}" -const mstPartialGood = "{{#data}}{{eg}}{{/data}}" -const mstResult = "0 00" -const mstRootBad = "{{> badPartial.mst}}{{#doesnt-exist}}{{/exit}}" -const mstPartialBad = "p{{$}{{ > noexist}}" - func validateTemplate(t *testing.T, template Template, templateType string, rootName string, partialNames ...string) { types := map[string]string{ "tmpl": "*template.Template", @@ -83,8 +83,9 @@ func validateTemplate(t *testing.T, template Template, templateType string, root "mustache": "*mustache.Template", } - if reflect.TypeOf(template.Template).String() != types[templateType] { - t.Fatal("invalid template loaded") + rt := reflect.TypeOf(template.Template).String() + if rt != types[templateType] { + t.Fatalf("invalid template type '%s' loaded, should be '%s'", rt, types[templateType]) } if types[templateType] == "*template.Template" { @@ -193,15 +194,46 @@ func TestLoadTemplateFile(t *testing.T) { } } -func TestLoadTemplateStringTmpl(t *testing.T) { - t.Parallel() +func TestLoadTemplateString(t *testing.T) { + var gr, gp, br, bp []string + + gr = append(gr, tmplRootGood) + gp = append(gp, tmplPartialGood) + br = append(br, tmplRootBad) + bp = append(bp, tmplPartialBad) - name := "tmplGood" - tmpl, err := LoadTemplateStringTmpl(name, tmplRootGood, tmplPartialGood) - if err != nil { - t.Fatal(err) - } - validateTemplate(t, tmpl, "tmpl", name, name + "-partial0") + gr = append(gr, hmplRootGood) + gp = append(gp, hmplPartialGood) + br = append(br, hmplRootBad) + bp = append(bp, hmplPartialBad) + + gr = append(gr, mstRootGood) + gp = append(gp, mstPartialGood) + br = append(br, mstRootBad) + bp = append(bp, mstPartialBad) + + name := "test" + var ttype string + for g, root := range gr { // good root, good partials + ttype = SupportedTemplateLangs[g] + if template, e := LoadTemplateString(ttype, name, root, gp[g]); e != nil { + t.Fatalf("'%s' template failed to load: %s", ttype, e) + } else { + validateTemplate(t, template, ttype, name, name + "-partial0") + } + } + for b, root := range br { // bad root, good partials + ttype = SupportedTemplateLangs[b] + if _, e := LoadTemplateString(ttype, name, root, gp...); e == nil { + t.Fatalf("no error for bad template with good partials\n") + } + } + for b, root := range br { // bad root, bad partials + ttype = SupportedTemplateLangs[b] + if _, e := LoadTemplateString(ttype, name, root, bp...); e == nil { + t.Fatalf("no error for bad template with bad partials\n") + } + } } func validateExecute(t *testing.T, results string, expect string, e error) {