diff options
| author | Gab Virebent <gabriel1@virebent.art> | 2026-07-07 16:24:28 +0200 |
|---|---|---|
| committer | Gab Virebent <gabriel1@virebent.art> | 2026-07-07 16:24:28 +0200 |
| commit | 37f156c30e2a2b01c840d39f0dd2bdbf811732d6 (patch) | |
| tree | e2ce84dc7f88ce0eb312899448f91b7bb93ca8a3 /internal/cms/simpletoml.go | |
| download | gemcms-37f156c30e2a2b01c840d39f0dd2bdbf811732d6.tar.gz gemcms-37f156c30e2a2b01c840d39f0dd2bdbf811732d6.tar.xz gemcms-37f156c30e2a2b01c840d39f0dd2bdbf811732d6.zip | |
Diffstat (limited to 'internal/cms/simpletoml.go')
| -rw-r--r-- | internal/cms/simpletoml.go | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/internal/cms/simpletoml.go b/internal/cms/simpletoml.go new file mode 100644 index 0000000..af2dcc7 --- /dev/null +++ b/internal/cms/simpletoml.go @@ -0,0 +1,172 @@ +package cms + +import ( + "fmt" + "strconv" + "strings" +) + +type simpleTable struct { + values map[string]string + lists map[string][]string +} + +func parseSimpleTable(data string) (simpleTable, error) { + table := simpleTable{ + values: map[string]string{}, + lists: map[string][]string{}, + } + + for lineNo, raw := range strings.Split(data, "\n") { + line := strings.TrimSpace(raw) + if line == "" || strings.HasPrefix(line, "#") || strings.HasPrefix(line, "[[") { + continue + } + key, rawValue, ok := strings.Cut(line, "=") + if !ok { + return table, fmt.Errorf("line %d: expected key = value", lineNo+1) + } + key = strings.TrimSpace(key) + rawValue = strings.TrimSpace(rawValue) + if key == "" { + return table, fmt.Errorf("line %d: empty key", lineNo+1) + } + if strings.HasPrefix(rawValue, "[") { + list, err := parseStringList(rawValue) + if err != nil { + return table, fmt.Errorf("line %d: %w", lineNo+1, err) + } + table.lists[key] = list + continue + } + value, err := parseScalar(rawValue) + if err != nil { + return table, fmt.Errorf("line %d: %w", lineNo+1, err) + } + table.values[key] = value + } + + return table, nil +} + +func parseMetadata(data string) (simpleTable, error) { + table, err := parseSimpleTable(data) + if err == nil { + return table, nil + } + yamlTable, yamlErr := parseSimpleYAMLTable(data) + if yamlErr == nil { + return yamlTable, nil + } + return table, err +} + +func parseSimpleYAMLTable(data string) (simpleTable, error) { + table := simpleTable{ + values: map[string]string{}, + lists: map[string][]string{}, + } + + for lineNo, raw := range strings.Split(data, "\n") { + line := strings.TrimSpace(raw) + if line == "" || strings.HasPrefix(line, "#") { + continue + } + key, rawValue, ok := strings.Cut(line, ":") + if !ok { + return table, fmt.Errorf("line %d: expected key: value", lineNo+1) + } + key = strings.TrimSpace(key) + rawValue = strings.TrimSpace(rawValue) + if key == "" { + return table, fmt.Errorf("line %d: empty key", lineNo+1) + } + if strings.HasPrefix(rawValue, "[") { + list, err := parseStringList(rawValue) + if err != nil { + return table, fmt.Errorf("line %d: %w", lineNo+1, err) + } + table.lists[key] = list + continue + } + if key == "tags" && strings.Contains(rawValue, ",") { + table.lists[key] = splitCommaList(rawValue) + continue + } + value, err := parseScalar(rawValue) + if err != nil { + return table, fmt.Errorf("line %d: %w", lineNo+1, err) + } + table.values[key] = value + } + + return table, nil +} + +func parseScalar(raw string) (string, error) { + raw = strings.TrimSpace(raw) + if raw == "" { + return "", nil + } + if strings.HasPrefix(raw, "\"") { + value, err := strconv.Unquote(raw) + if err != nil { + return "", err + } + return value, nil + } + return raw, nil +} + +func splitCommaList(value string) []string { + var out []string + for _, part := range strings.Split(value, ",") { + part = strings.TrimSpace(part) + if part != "" { + out = append(out, part) + } + } + return out +} + +func parseStringList(raw string) ([]string, error) { + raw = strings.TrimSpace(raw) + if !strings.HasPrefix(raw, "[") || !strings.HasSuffix(raw, "]") { + return nil, fmt.Errorf("expected string list") + } + raw = strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(raw, "["), "]")) + if raw == "" { + return nil, nil + } + + var values []string + for _, part := range strings.Split(raw, ",") { + value, err := parseScalar(strings.TrimSpace(part)) + if err != nil { + return nil, err + } + if value != "" { + values = append(values, value) + } + } + return values, nil +} + +func formatString(value string) string { + return strconv.Quote(value) +} + +func formatStringList(values []string) string { + quoted := make([]string, 0, len(values)) + for _, value := range values { + quoted = append(quoted, strconv.Quote(value)) + } + return "[" + strings.Join(quoted, ", ") + "]" +} + +func boolString(value bool) string { + if value { + return "true" + } + return "false" +} |
