summaryrefslogtreecommitdiffstats
path: root/internal/builder/frontmatter.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/builder/frontmatter.go')
-rw-r--r--internal/builder/frontmatter.go64
1 files changed, 64 insertions, 0 deletions
diff --git a/internal/builder/frontmatter.go b/internal/builder/frontmatter.go
new file mode 100644
index 0000000..34de484
--- /dev/null
+++ b/internal/builder/frontmatter.go
@@ -0,0 +1,64 @@
+package builder
+
+import (
+ "strings"
+)
+
+// Frontmatter holds parsed page metadata from YAML-style front matter.
+type Frontmatter struct {
+ Title string
+ Date string
+ Tags []string
+ Layout string // template name without extension, default "base"
+ Draft bool
+}
+
+// ParseFrontmatter splits the optional ---...--- block from the markdown body.
+// Supports: title, date, tags (comma-list or [a, b]), layout, draft.
+func ParseFrontmatter(content string) (Frontmatter, string) {
+ fm := Frontmatter{Layout: "base"}
+ if !strings.HasPrefix(content, "---") {
+ return fm, content
+ }
+ // Find closing ---
+ rest := content[3:]
+ end := strings.Index(rest, "\n---")
+ if end == -1 {
+ return fm, content
+ }
+ block := strings.TrimSpace(rest[:end])
+ body := strings.TrimSpace(rest[end+4:]) // skip \n---
+
+ for _, line := range strings.Split(block, "\n") {
+ k, v, ok := strings.Cut(strings.TrimSpace(line), ":")
+ if !ok {
+ continue
+ }
+ k = strings.TrimSpace(k)
+ v = strings.TrimSpace(v)
+ switch k {
+ case "title":
+ fm.Title = strings.Trim(v, `"'`)
+ case "date":
+ fm.Date = v
+ case "layout":
+ fm.Layout = strings.Trim(v, `"'`)
+ case "draft":
+ fm.Draft = v == "true"
+ case "tags":
+ fm.Tags = parseTags(v)
+ }
+ }
+ return fm, body
+}
+
+func parseTags(v string) []string {
+ v = strings.Trim(v, "[] ")
+ var tags []string
+ for _, p := range strings.Split(v, ",") {
+ if t := strings.Trim(strings.TrimSpace(p), `"'`); t != "" {
+ tags = append(tags, t)
+ }
+ }
+ return tags
+}