@@ -8,24 +8,25 @@ import (
8
8
"github.com/FileFormatInfo/fflint/internal/shared"
9
9
"github.com/adrg/frontmatter"
10
10
"github.com/spf13/cobra"
11
- "gopkg.in/yaml.v2 "
11
+ "gopkg.in/yaml.v3 "
12
12
)
13
13
14
14
var (
15
- fmStrict bool
16
- fmStrictSet map [string ]bool
17
- fmSorted bool
18
- fmRequired []string
19
- fmOptional []string
20
- fmForbidden []string
21
- fmDelimiters []string
15
+ fmSchemaOptions shared.SchemaOptions
16
+ fmStrict bool
17
+ fmStrictSet map [string ]bool
18
+ fmSorted bool
19
+ fmRequired []string
20
+ fmOptional []string
21
+ fmForbidden []string
22
+ fmDelimiters []string
22
23
)
23
24
var frontmatterCmd = & cobra.Command {
24
25
Args : cobra .MinimumNArgs (1 ),
25
26
Use : "frontmatter [options] files..." ,
26
27
Short : "Validate frontmatter" ,
27
28
Long : `Checks that the frontmatter in your files is valid` ,
28
- PreRunE : frontmatterPrepare ,
29
+ PreRunE : frontmatterInit ,
29
30
RunE : shared .MakeFileCommand (frontmatterCheck ),
30
31
}
31
32
@@ -39,8 +40,9 @@ func AddFrontmatterCommand(rootCmd *cobra.Command) {
39
40
frontmatterCmd .Flags ().BoolVar (& fmSorted , "sorted" , false , "Keys need to be in alphabetical order" )
40
41
frontmatterCmd .Flags ().StringSliceVar (& fmDelimiters , "delimiters" , []string {}, "Custom delimiters (if other than `---`, `+++` and `;;;`)" )
41
42
43
+ fmSchemaOptions .AddFlags (frontmatterCmd )
44
+
42
45
//LATER: report
43
- //LATER: schema
44
46
}
45
47
46
48
func frontmatterCheck (f * shared.FileContext ) {
@@ -53,8 +55,6 @@ func frontmatterCheck(f *shared.FileContext) {
53
55
return
54
56
}
55
57
56
- yamlData := make (map [interface {}]interface {})
57
-
58
58
var formats []* frontmatter.Format
59
59
60
60
if len (fmDelimiters ) > 0 {
@@ -68,7 +68,9 @@ func frontmatterCheck(f *shared.FileContext) {
68
68
}
69
69
}
70
70
71
- _ , parseErr := frontmatter .MustParse (bytes .NewReader (data ), & yamlData , formats ... )
71
+ yamlRawData := make (map [string ]any )
72
+ //LATER: maybe flag to require contents?
73
+ _ , parseErr := frontmatter .MustParse (bytes .NewReader (data ), & yamlRawData , formats ... )
72
74
73
75
f .RecordResult ("frontmatterParse" , parseErr == nil , map [string ]interface {}{
74
76
"error" : shared .ErrString (parseErr ),
@@ -77,6 +79,15 @@ func frontmatterCheck(f *shared.FileContext) {
77
79
return
78
80
}
79
81
82
+ /*
83
+ yamlDataOrArray, stringKeysErr := shared.ToStringKeys(yamlRawData)
84
+ f.RecordResult("frontmatterStringKeys", stringKeysErr == nil, map[string]interface{}{
85
+ "error": stringKeysErr,
86
+ })
87
+ */
88
+ yamlDataOrArray := convert (yamlRawData )
89
+ yamlData := yamlDataOrArray .(map [string ]interface {})
90
+
80
91
if len (fmRequired ) > 0 {
81
92
for _ , key := range fmRequired {
82
93
_ , ok := yamlData [key ]
@@ -97,45 +108,28 @@ func frontmatterCheck(f *shared.FileContext) {
97
108
98
109
if fmStrict {
99
110
for key := range yamlData {
100
- keyStr , strErr := key .(string )
101
- if ! strErr {
102
- f .RecordResult ("frontmatterStrictParse" , false , map [string ]interface {}{
103
- "err" : "key is not a string" ,
104
- "key" : fmt .Sprintf ("%v" , key ),
105
- })
106
- continue
107
- }
108
- _ , ok := fmStrictSet [keyStr ]
111
+ _ , ok := fmStrictSet [key ]
109
112
f .RecordResult ("frontmatterStrict" , ok , map [string ]interface {}{
110
- "key" : keyStr ,
113
+ "key" : key ,
111
114
})
112
115
}
113
116
}
114
117
115
118
if fmSorted {
116
- sortedData := yaml.MapSlice {}
117
-
118
- frontmatter .Parse (bytes .NewReader (data ), & sortedData )
119
119
previousKey := ""
120
- for _ , item := range sortedData {
121
- currentKey , strErr := item .Key .(string )
122
- if ! strErr {
123
- f .RecordResult ("frontmatterSortedParse" , false , map [string ]interface {}{
124
- "err" : "key is not a string" ,
125
- "key" : fmt .Sprintf ("%v" , item .Key ),
126
- })
127
- continue
128
- }
120
+ for currentKey := range yamlData {
129
121
f .RecordResult ("frontmatterSorted" , previousKey < currentKey , map [string ]interface {}{
130
122
"previous" : previousKey ,
131
123
"current" : currentKey ,
132
124
})
133
125
previousKey = currentKey
134
126
}
135
127
}
128
+
129
+ fmSchemaOptions .Validate (f , yamlData )
136
130
}
137
131
138
- func frontmatterPrepare (cmd * cobra.Command , args []string ) error {
132
+ func frontmatterInit (cmd * cobra.Command , args []string ) error {
139
133
if fmStrict {
140
134
fmStrictSet = make (map [string ]bool )
141
135
for _ , key := range fmRequired {
@@ -150,5 +144,34 @@ func frontmatterPrepare(cmd *cobra.Command, args []string) error {
150
144
fmt .Fprintf (os .Stderr , "ERROR: delimiter count must be <=2 (passed %d)" , len (fmDelimiters ))
151
145
os .Exit (7 )
152
146
}
147
+
148
+ schemaPrepErr := fmSchemaOptions .Prepare ()
149
+ if schemaPrepErr != nil {
150
+ return schemaPrepErr
151
+ }
152
+
153
153
return nil
154
154
}
155
+
156
+ // from https://stackoverflow.com/a/40737676
157
+ func convert (i interface {}) interface {} {
158
+ switch x := i .(type ) {
159
+ case map [interface {}]interface {}:
160
+ m2 := map [string ]interface {}{}
161
+ for k , v := range x {
162
+ m2 [k .(string )] = convert (v )
163
+ }
164
+ return m2
165
+ case map [string ]interface {}:
166
+ m2 := map [string ]interface {}{}
167
+ for k , v := range x {
168
+ m2 [k ] = convert (v )
169
+ }
170
+ return m2
171
+ case []interface {}:
172
+ for i , v := range x {
173
+ x [i ] = convert (v )
174
+ }
175
+ }
176
+ return i
177
+ }
0 commit comments