142 lines
2.8 KiB
Go
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")
|
|
|
|
}
|