step/meta.go
Sasha Koshka 43084fb5bb Add ability to parse quoted strings in meta
This should actually make migration from Caddy easier, because
Caddy's YAML front matter seems to support quoted strings? IDK,
the current Holanet has them. Closes #11
2024-12-09 12:56:16 -05:00

73 lines
2.0 KiB
Go

package step
import "strconv"
import "strings"
const metaRule = "---"
// Meta represents optional metadata that can occur at the very start of
// a document.
type Meta = map[string] string
// SplitMeta parses the metadata (if it exists), returning a map representing it
// along with the rest of the input as a string. If there is no metadata, an
// empty map will be returned.
func SplitMeta (input string) (Meta, string, error) {
// i hate crlf!!!!! uwehhh!!! TODO remove
input = strings.ReplaceAll(input, "\r\n", "\n")
// TODO call internal function that takes in an io.Reader and scans it
// by line instead of operating directly on the string. have that call
// yet another function which will solve #11
// stop if there is no metadata
if !strings.HasPrefix(input, metaRule + "\n") {
return Meta { }, input, nil
}
// get the start and the end of the metadata
input = strings.TrimPrefix(input, metaRule)
index := strings.Index(input, "\n" + metaRule + "\n")
if index < 0 {
return nil, "", ErrMetaNeverClosed
}
metaStr := input[:index]
bodyStr := input[index + len(metaRule) + 2:]
// parse metadata
meta, err := ParseMeta(metaStr)
if err != nil { return Meta { }, "", err }
return meta, bodyStr, nil
}
// ParseMeta parses isolated metadata (without the horizontal starting and
// ending rules).
func ParseMeta (input string) (Meta, error) {
meta := make(Meta)
for _, line := range strings.Split(input, "\n") {
line = strings.TrimSpace(line)
if line == "" { continue }
key, value, ok := strings.Cut(line, ":")
if !ok {
return nil, ErrMetaMalformed
}
key = strings.ToLower(strings.TrimSpace(key))
value = strings.TrimSpace(value)
if strings.HasPrefix(value, "\"") || strings.HasPrefix(value, "'") {
unquoted, err := strconv.Unquote(value)
if err != nil {
return nil, err
}
value = unquoted
}
if key == "" {
return nil, ErrMetaMalformed
}
if _, exists := meta[key]; exists {
return nil, ErrMetaDuplicateKey
}
meta[key] = value
}
return meta, nil
}