mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-02-14 07:55:03 -05:00
- Add new template package to handle variable substitution with {{variable}} syntax
- Move substitution logic from patterns to centralized template system
- Update patterns.go to use template package for variable processing
- Support special {{input}} handling for pattern content
- Update chatter.go and rest API to pass input parameter
- Enable multiple passes to handle nested variables
- Report errors for missing required variables
This change sets up a foundation for future templating features like front matter
and plugin support while keeping the substitution logic centralized.
131 lines
3.3 KiB
Go
131 lines
3.3 KiB
Go
package fsdb
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/danielmiessler/fabric/plugins/template"
|
|
)
|
|
|
|
type PatternsEntity struct {
|
|
*StorageEntity
|
|
SystemPatternFile string
|
|
UniquePatternsFilePath string
|
|
}
|
|
|
|
// Pattern represents a single pattern with its metadata
|
|
type Pattern struct {
|
|
Name string
|
|
Description string
|
|
Pattern string
|
|
}
|
|
|
|
// main entry point for getting patterns from any source
|
|
func (o *PatternsEntity) GetApplyVariables(source string, variables map[string]string, input string) (*Pattern, error) {
|
|
var pattern *Pattern
|
|
var err error
|
|
|
|
// Determine if this is a file path
|
|
isFilePath := strings.HasPrefix(source, "\\") ||
|
|
strings.HasPrefix(source, "/") ||
|
|
strings.HasPrefix(source, "~") ||
|
|
strings.HasPrefix(source, ".")
|
|
|
|
if isFilePath {
|
|
pattern, err = o.getFromFile(source)
|
|
} else {
|
|
pattern, err = o.getFromDB(source)
|
|
}
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
pattern, err = o.applyVariables(pattern, variables, input)
|
|
if err != nil {
|
|
return nil, err // Return the error if applyVariables failed
|
|
}
|
|
return pattern, nil
|
|
}
|
|
|
|
|
|
func (o *PatternsEntity) applyVariables(pattern *Pattern, variables map[string]string, input string) (*Pattern, error) {
|
|
// If {{input}} isn't in pattern, append it on new line
|
|
if !strings.Contains(pattern.Pattern, "{{input}}") {
|
|
if !strings.HasSuffix(pattern.Pattern, "\n") {
|
|
pattern.Pattern += "\n"
|
|
}
|
|
pattern.Pattern += "{{input}}"
|
|
}
|
|
|
|
result, err := template.ApplyTemplate(pattern.Pattern, variables, input)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pattern.Pattern = result
|
|
return pattern, nil
|
|
}
|
|
|
|
// retrieves a pattern from the database by name
|
|
func (o *PatternsEntity) getFromDB(name string) (ret *Pattern, err error) {
|
|
patternPath := filepath.Join(o.Dir, name, o.SystemPatternFile)
|
|
|
|
var pattern []byte
|
|
if pattern, err = os.ReadFile(patternPath); err != nil {
|
|
return
|
|
}
|
|
|
|
patternStr := string(pattern)
|
|
ret = &Pattern{
|
|
Name: name,
|
|
Pattern: patternStr,
|
|
}
|
|
return
|
|
}
|
|
|
|
func (o *PatternsEntity) PrintLatestPatterns(latestNumber int) (err error) {
|
|
var contents []byte
|
|
if contents, err = os.ReadFile(o.UniquePatternsFilePath); err != nil {
|
|
err = fmt.Errorf("could not read unique patterns file. Pleas run --updatepatterns (%s)", err)
|
|
return
|
|
}
|
|
uniquePatterns := strings.Split(string(contents), "\n")
|
|
if latestNumber > len(uniquePatterns) {
|
|
latestNumber = len(uniquePatterns)
|
|
}
|
|
|
|
for i := len(uniquePatterns) - 1; i > len(uniquePatterns)-latestNumber-1; i-- {
|
|
fmt.Println(uniquePatterns[i])
|
|
}
|
|
return
|
|
}
|
|
|
|
// reads a pattern from a file path and returns it
|
|
func (o *PatternsEntity) getFromFile(pathStr string) (*Pattern, error) {
|
|
// Handle home directory expansion
|
|
if strings.HasPrefix(pathStr, "~/") {
|
|
homedir, err := os.UserHomeDir()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not get home directory: %v", err)
|
|
}
|
|
pathStr = filepath.Join(homedir, pathStr[2:])
|
|
}
|
|
|
|
content, err := os.ReadFile(pathStr)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not read pattern file %s: %v", pathStr, err)
|
|
}
|
|
|
|
return &Pattern{
|
|
Name: pathStr,
|
|
Pattern: string(content),
|
|
}, nil
|
|
}
|
|
|
|
// Get required for Storage interface
|
|
func (o *PatternsEntity) Get(name string) (*Pattern, error) {
|
|
// Use GetPattern with no variables
|
|
return o.GetApplyVariables(name, nil, "")
|
|
} |