-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfrontmatter.go
More file actions
105 lines (87 loc) · 2.23 KB
/
frontmatter.go
File metadata and controls
105 lines (87 loc) · 2.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package gonotes
import (
"gopkg.in/yaml.v3"
)
type Frontmatter struct {
yaml.Node
}
func NewFrontmatter() *Frontmatter {
return &Frontmatter{
Node: yaml.Node{
Kind: yaml.MappingNode,
Content: []*yaml.Node{},
},
}
}
func (f *Frontmatter) MarshalYAML() (any, error) {
return f.Node, nil
}
func (f *Frontmatter) UnmarshalYAML(node *yaml.Node) error {
f.Node = *node
return nil
}
func (f *Frontmatter) mappingNode() *yaml.Node {
// Root is already mapping node.
if f.Kind == yaml.MappingNode {
return &f.Node
}
// Root is document node.
if f.Kind == yaml.DocumentNode && len(f.Content) > 0 {
if f.Content[0].Kind == yaml.MappingNode {
return f.Content[0]
}
}
// No mapping node found, create and replace root.
f.Node = yaml.Node{
Kind: yaml.MappingNode,
Content: []*yaml.Node{},
}
return &f.Node
}
func (f *Frontmatter) Get(key string) (string, bool) {
mn := f.mappingNode()
for i := 0; i+1 < len(mn.Content); i += 2 {
if mn.Content[i].Value == key {
return mn.Content[i+1].Value, true
}
}
return "", false
}
func (f *Frontmatter) Set(key, value string) {
mn := f.mappingNode()
// Update existing.
for i := 0; i+1 < len(mn.Content); i += 2 {
if mn.Content[i].Value == key {
// Ensure value node is scalar, or convert it.
if mn.Content[i+1].Kind != yaml.ScalarNode {
mn.Content[i+1] = &yaml.Node{Kind: yaml.ScalarNode, Value: value}
} else {
mn.Content[i+1].Value = value
}
return
}
}
// Add new.
keyNode := &yaml.Node{Kind: yaml.ScalarNode, Value: key}
valueNode := &yaml.Node{Kind: yaml.ScalarNode, Value: value}
mn.Content = append(mn.Content, keyNode, valueNode)
}
func (f *Frontmatter) Unset(key string) {
mn := f.mappingNode()
for i := 0; i+1 < len(mn.Content); i += 2 {
if mn.Content[i].Value == key {
mn.Content = append(mn.Content[:i], mn.Content[i+2:]...)
return
}
}
}
// Map returns all scalar key-value pairs as a map. Non-scalar values are
// represented by their string Value (which may be empty for sequences/mappings).
func (f *Frontmatter) Map() map[string]string {
mn := f.mappingNode()
m := make(map[string]string, len(mn.Content)/2)
for i := 0; i+1 < len(mn.Content); i += 2 {
m[mn.Content[i].Value] = mn.Content[i+1].Value
}
return m
}