func foreachFunc(helper *structure.Helper, values *structure.RequestData) []byte { if len(helper.Arguments) != 0 { switch helper.Arguments[0].Name { case "posts": var buffer bytes.Buffer for index, _ := range values.Posts { //if values.Posts[index].Id != 0 { // If post is not empty (Commented out for now. This was only neccessary in previous versions, when the array length was always the postsPerPage length) values.CurrentPostIndex = index buffer.Write(executeHelper(helper, values, 1)) // context = post //} } return buffer.Bytes() case "tags": var buffer bytes.Buffer for index, _ := range values.Posts[values.CurrentPostIndex].Tags { //if values.Posts[values.CurrentPostIndex].Tags[index].Id != 0 { // If tag is not empty (Commented out for now. Not neccessary.) values.CurrentTagIndex = index buffer.Write(executeHelper(helper, values, 2)) // context = tag //} } return buffer.Bytes() case "navigation": var buffer bytes.Buffer for index, _ := range values.Blog.NavigationItems { values.CurrentNavigationIndex = index buffer.Write(executeHelper(helper, values, 4)) // context = navigation } return buffer.Bytes() default: return []byte{} } } return []byte{} }
func contentForFunc(helper *structure.Helper, values *structure.RequestData) []byte { // If there is no array attached to the request data already, make one if values.ContentForHelpers == nil { values.ContentForHelpers = make([]structure.Helper, 0) } // Collect all contentFor helpers to use them with a block helper values.ContentForHelpers = append(values.ContentForHelpers, *helper) return []byte{} }
func executeHelper(helper *structure.Helper, values *structure.RequestData, context int) []byte { // Set context and set it back to the old value once fuction returns defer setCurrentHelperContext(values, values.CurrentHelperContext) values.CurrentHelperContext = context block := helper.Block indexTracker := 0 extended := false var extendHelper *structure.Helper for index, child := range helper.Children { // Handle extend helper if index == 0 && child.Name == "!<" { extended = true extendHelper = compiledTemplates.m[string(child.Function(&child, values))] } else { var buffer bytes.Buffer toAdd := child.Function(&child, values) buffer.Write(block[:child.Position+indexTracker]) buffer.Write(toAdd) buffer.Write(block[child.Position+indexTracker:]) block = buffer.Bytes() indexTracker += len(toAdd) } } if extended { extendHelper.BodyHelper.Block = block return executeHelper(extendHelper, values, values.CurrentHelperContext) // TODO: not sure if context = values.CurrentHelperContext is right. } return block }
// Helper fuctions func nullFunc(helper *structure.Helper, values *structure.RequestData) []byte { // Check if the helper was defined in a plugin if plugins.LuaPool != nil { // Get a state map to execute and attach it to the request data if values.PluginVMs == nil { values.PluginVMs = plugins.LuaPool.Get(helper, values) } if values.PluginVMs[helper.Name] != nil { pluginResult, err := plugins.Execute(helper, values) if err != nil { return []byte{} } return evaluateEscape(pluginResult, helper.Unescaped) } else { // This helper is not implemented in a plugin. Get rid of the Lua VMs plugins.LuaPool.Put(values.PluginVMs) values.PluginVMs = nil } } log.Println("Warning: This helper is not implemented:", helper.Name) return []byte{} }
func Execute(helper *structure.Helper, values *structure.RequestData) ([]byte, error) { // Retrieve the lua state vm := values.PluginVMs[helper.Name] // Execute plugin err := vm.CallByParam(lua.P{Fn: vm.GetGlobal(helper.Name), NRet: 1, Protect: true}) if err != nil { log.Println("Error while executing plugin for helper "+helper.Name+":", err) // Since the vm threw an error, close all vms and don't put the map back into the pool for _, luavm := range values.PluginVMs { luavm.Close() } values.PluginVMs = nil return []byte{}, err } // Get return value from vm ret := vm.ToString(-1) return []byte(ret), nil }
func setCurrentHelperContext(values *structure.RequestData, context int) { values.CurrentHelperContext = context }