// RenderWith renders the template(s) using the locator to fill in variable references and writes to the // writer. 'templates' is an array of SilverStripe templates minus the ".ss" extension. If there is one template, // it is assumed to be in the base templates folder. If two are present, the first is the base template, the // second is the $Layout template. func RenderWith(w http.ResponseWriter, templates []string, context interface{}, require goss.RequirementsProvider, request *http.Request) error { if require == nil { require = requirements.NewRequirements() } // make templates relative to templates folder if len(templates) > 1 { templates[1] = "Layout/" + templates[1] } // corresponding compiled templates will go in here for execution. var compiled []*compiledTemplate first := true for _, t := range templates { template, e := compileTemplate(t, first) first = false if e != nil { return e } compiled = append(compiled, template) } // execute the template using the data locator r, e := executeTemplate(compiled, context, require, request) if e != nil { return e } // finally write the result _, e = w.Write([]byte(r)) return e }
// utility function to compile and execute template source using the given context func compileAndExecute(source string, context interface{}) ([]byte, error) { compiled, e := newParser().parseSource(source, true, "") if e != nil { return nil, e } exec := newExecuter([]*compiledTemplate{compiled}, context, requirements.NewRequirements()) return exec.render() }
// @todo refactor into a number of case-specific tests func TestExec(t *testing.T) { e := configure() if e != nil { t.Error(e.Error()) return } source := `this is some markup for $name, with gratuitous nested var: {$parent.child}. $function1(name) $function0 <%if v1==v2 %>rhubarb equal bananas<% else %>of course a banana is not rhubarb.<% end_if %> we like food $salutation(title, name)` compiled, e := newParser().parseSource(source, true, "") if e != nil { t.Error(e.Error()) return } context := make(map[string]interface{}) context["foo"] = "bar" context["name"] = "mickey mouse" sub := make(map[string]interface{}) sub["child"] = "foobar!" context["parent"] = sub context["function0"] = func() string { return "hey, function with zero parameters" } context["function1"] = func(s string) string { return "hello '" + s + "' from function 1!" } context["salutation"] = func(t string, n string) string { return t + " " + n } context["v1"] = "rhubarb" context["v1"] = "bananas" context["title"] = "dear" // evaluate it exec := newExecuter([]*compiledTemplate{compiled}, context, requirements.NewRequirements()) bytes, e := exec.renderChunk(compiled.chunk) if e != nil { t.Error(e.Error()) } fmt.Printf("bytes are: %s\n", bytes) }