Files
marka/parser/blocks/template.go
2025-08-17 01:21:15 +02:00

142 lines
2.8 KiB
Go

package blocks
import (
"fmt"
"strings"
"go.yaml.in/yaml/v4"
)
func cleanTemplate(input string) string {
s := strings.TrimSpace(input)
s = strings.TrimPrefix(s, "{")
s = strings.TrimSuffix(s, "}")
return s
}
func parseShortTemplate(input string) (TemplateBlock, error) {
var split = strings.Split(cleanTemplate(input), "|")
if len(split) < 1 {
return TemplateBlock{}, fmt.Errorf("Invalid Short Template")
}
block := TemplateBlock{
Type: DataBlock,
Path: strings.TrimSpace(split[0]),
Codec: CodecText,
content: input,
}
if len(split) > 1 {
var optionSplit = strings.Split(split[1], ",")
for _, option := range optionSplit {
switch strings.TrimSpace(option) {
case "required":
block.Required = true
case "number":
block.Codec = CodecNumber
}
}
}
return block, nil
}
type yamlBlock struct {
Path string `yaml:"path"`
Codec string `yaml:"codec"`
Required bool `yaml:"required,omitempty"`
Fields []yamlField `yaml:"fields"`
Item *struct {
Template string `yaml:"template,omitempty"`
} `yaml:"item,omitempty"`
Template string `yaml:"template,omitempty"`
}
type yamlField struct {
Path string `yaml:"path"`
Value any `yaml:"value,omitempty"`
Codec string `yaml:"codec"`
Required bool `yaml:"required"`
}
func parseYamlTemplate(input string) (block TemplateBlock, err error) {
var blk yamlBlock
cleaned := cleanTemplate(input)
dec := yaml.NewDecoder(strings.NewReader(cleaned))
dec.KnownFields(true)
if err := dec.Decode(&blk); err != nil {
return block, err
}
if blk.Path == "" {
return block, fmt.Errorf("missing top-level 'path'")
}
if blk.Codec == "" {
blk.Codec = "text"
}
codec, err := parseCodecType(blk.Codec)
if err != nil {
return block, fmt.Errorf("failed to parse codec: %w", err)
}
var fields []BlockField
for _, field := range blk.Fields {
if field.Path == "" {
return block, fmt.Errorf("failed to parse field: %v", field)
}
if field.Codec == "" {
field.Codec = "text"
}
fieldCodec, err := parseCodecType(field.Codec)
if err != nil {
return block, fmt.Errorf("failed to parse codec: %w", err)
}
fields = append(fields, BlockField{
Path: field.Path,
CodecType: fieldCodec,
Required: field.Required,
})
}
return TemplateBlock{
Type: DataBlock,
Path: blk.Path,
Codec: codec,
Fields: fields,
content: input,
}, nil
}
func ParseTemplateBlock(template string, blockType BlockType) (block TemplateBlock, err error) {
if blockType == MatchingBlock {
return TemplateBlock{
Type: MatchingBlock,
content: template,
}, nil
}
switch DetectTemplateType(template) {
case ShortTemplate:
return parseShortTemplate(template)
case ExtendedTemplate:
return parseYamlTemplate(template)
}
return block, fmt.Errorf("Invalid Template")
}