package template import ( "fmt" "regexp" "strings" ) var ( textPlugin = &TextPlugin{} datetimePlugin = &DateTimePlugin{} filePlugin = &FilePlugin{} fetchPlugin = &FetchPlugin{} sysPlugin = &SysPlugin{} Debug = false // Debug flag ) var pluginPattern = regexp.MustCompile(`\{\{plugin:([^:]+):([^:]+)(?::([^}]+))?\}\}`) func debugf(format string, a ...interface{}) { if Debug { fmt.Printf(format, a...) } } func ApplyTemplate(content string, variables map[string]string, input string) (string, error) { var missingVars []string r := regexp.MustCompile(`\{\{([^{}]+)\}\}`) debugf("Starting template processing\n") for strings.Contains(content, "{{") { matches := r.FindAllStringSubmatch(content, -1) if len(matches) == 0 { break } replaced := false for _, match := range matches { fullMatch := match[0] varName := match[1] // Check if this is a plugin call if strings.HasPrefix(varName, "plugin:") { pluginMatches := pluginPattern.FindStringSubmatch(fullMatch) if len(pluginMatches) >= 3 { namespace := pluginMatches[1] operation := pluginMatches[2] value := "" if len(pluginMatches) == 4 { value = pluginMatches[3] } debugf("\nPlugin call:\n") debugf(" Namespace: %s\n", namespace) debugf(" Operation: %s\n", operation) debugf(" Value: %s\n", value) var result string var err error switch namespace { case "text": debugf("Executing text plugin\n") result, err = textPlugin.Apply(operation, value) case "datetime": debugf("Executing datetime plugin\n") result, err = datetimePlugin.Apply(operation, value) case "file": debugf("Executing file plugin\n") result, err = filePlugin.Apply(operation, value) debugf("File plugin result: %#v\n", result) case "fetch": debugf("Executing fetch plugin\n") result, err = fetchPlugin.Apply(operation, value) case "sys": debugf("Executing sys plugin\n") result, err = sysPlugin.Apply(operation, value) default: return "", fmt.Errorf("unknown plugin namespace: %s", namespace) } if err != nil { debugf("Plugin error: %v\n", err) return "", fmt.Errorf("plugin %s error: %v", namespace, err) } debugf("Plugin result: %s\n", result) content = strings.ReplaceAll(content, fullMatch, result) debugf("Content after replacement: %s\n", content) continue } } // Handle regular variables and input debugf("Processing variable: %s\n", varName) if varName == "input" { debugf("Replacing {{input}}\n") replaced = true content = strings.ReplaceAll(content, fullMatch, input) } else { if val, ok := variables[varName]; !ok { debugf("Missing variable: %s\n", varName) missingVars = append(missingVars, varName) return "", fmt.Errorf("missing required variable: %s", varName) } else { debugf("Replacing variable %s with value: %s\n", varName, val) content = strings.ReplaceAll(content, fullMatch, val) replaced = true } } if !replaced { return "", fmt.Errorf("template processing stuck - potential infinite loop") } } } debugf("Template processing complete\n") return content, nil }