@@ -5,21 +5,30 @@ import (
55 "io/ioutil"
66 "os"
77 "path/filepath"
8+ "sort"
9+ "strconv"
810 "strings"
911
12+ "github.com/gertd/go-pluralize"
1013 "github.com/invopop/jsonschema"
1114 "github.com/loft-sh/devspace/docs/hack/util"
15+ "github.com/loft-sh/devspace/pkg/devspace/config/versions"
1216 "github.com/loft-sh/devspace/pkg/devspace/config/versions/latest"
1317)
1418
1519const configPartialBasePath = "docs/pages/configuration/_partials/"
1620const nameFieldName = "name"
21+ const versionFieldName = "version"
22+ const groupKey = "group"
23+ const groupNameKey = "group_name"
24+
25+ var pluralizeClient = pluralize .NewClient ()
1726
1827func main () {
1928 r := new (jsonschema.Reflector )
2029 r .AllowAdditionalProperties = true
2130 r .PreferYAMLSchema = true
22- r .RequiredFromJSONSchemaTags = false
31+ r .RequiredFromJSONSchemaTags = true
2332 r .YAMLEmbeddedStructs = false
2433 r .ExpandedStruct = true
2534
@@ -30,14 +39,51 @@ func main() {
3039
3140 schema := r .Reflect (& latest.Config {})
3241
42+ versionField , ok := schema .Properties .Get (versionFieldName )
43+ if ok {
44+ if fieldSchema , ok := versionField .(* jsonschema.Schema ); ok {
45+ versionEnum := []string {}
46+ for version := range versions .VersionLoader {
47+ versionEnum = append (versionEnum , version )
48+ }
49+
50+ sort .SliceStable (versionEnum , func (a , b int ) bool {
51+ majorA , _ := strconv .Atoi (string (versionEnum [a ][1 ]))
52+ majorB , _ := strconv .Atoi (string (versionEnum [b ][1 ]))
53+ minorA , _ := strconv .Atoi (string (versionEnum [a ][6 :]))
54+ minorB , _ := strconv .Atoi (string (versionEnum [b ][6 :]))
55+
56+ if majorA == majorB {
57+ return minorA > minorB
58+ } else {
59+ return majorA > majorB
60+ }
61+ })
62+
63+ fieldSchema .Enum = []interface {}{}
64+ for _ , version := range versionEnum {
65+ fieldSchema .Enum = append (fieldSchema .Enum , version )
66+ }
67+ }
68+ }
69+
3370 createSections ("" , schema , schema .Definitions , 1 , false )
3471}
3572
73+ type Group struct {
74+ File string
75+ Name string
76+ Content string
77+ Imports * []string
78+ }
79+
3680func createSections (prefix string , schema * jsonschema.Schema , definitions jsonschema.Definitions , depth int , parentIsNameObjectMap bool ) string {
3781 partialImports := & []string {}
3882 content := ""
3983 headlinePrefix := strings .Repeat ("#" , depth + 1 ) + " "
4084
85+ groups := map [string ]* Group {}
86+
4187 for _ , fieldName := range schema .Properties .Keys () {
4288 if parentIsNameObjectMap && fieldName == nameFieldName {
4389 continue
@@ -50,14 +96,16 @@ func createSections(prefix string, schema *jsonschema.Schema, definitions jsonsc
5096 fieldFile := fmt .Sprintf (configPartialBasePath + "%s/%s%s.mdx" , latest .Version , prefix , fieldName )
5197 fieldType := "object"
5298 isNameObjectMap := false
99+ groupID , _ := fieldSchema .Extras [groupKey ].(string )
53100
101+ var patternPropertySchema * jsonschema.Schema
54102 var nestedSchema * jsonschema.Schema
55103
56104 ref := ""
57105 if fieldSchema .Type == "array" {
58106 ref = fieldSchema .Items .Ref
59107 fieldType = "object[]"
60- } else if patternPropertySchema , ok : = fieldSchema .PatternProperties [".*" ]; ok {
108+ } else if patternPropertySchema , ok = fieldSchema .PatternProperties [".*" ]; ok {
61109 ref = patternPropertySchema .Ref
62110 isNameObjectMap = true
63111 } else if fieldSchema .Ref != "" {
@@ -74,17 +122,49 @@ func createSections(prefix string, schema *jsonschema.Schema, definitions jsonsc
74122 }
75123 } else {
76124 required := contains (schema .Required , fieldName )
125+ fieldDefault := ""
126+
77127 fieldType = fieldSchema .Type
128+ if fieldType == "" && fieldSchema .OneOf != nil {
129+ for _ , oneOfType := range fieldSchema .OneOf {
130+ if fieldType != "" {
131+ fieldType = fieldType + "|"
132+ }
133+ fieldType = fieldType + oneOfType .Type
134+ }
135+ }
136+
137+ if isNameObjectMap {
138+ fieldNameSingular := pluralizeClient .Singular (fieldName )
139+ fieldType = "<" + fieldNameSingular + "_name>:"
140+
141+ if patternPropertySchema != nil && patternPropertySchema .Type != "" {
142+ fieldType = fieldType + patternPropertySchema .Type
143+ } else {
144+ fieldType = fieldType + "object"
145+ }
146+ }
147+
78148 if fieldType == "array" {
79149 fieldType = fieldSchema .Items .Type + "[]"
80150 }
81151
82- fieldDefault , ok := fieldSchema .Default .(string )
83- if ! ok {
84- fieldDefault = ""
152+ if fieldType == "boolean" {
153+ fieldDefault = "false"
154+ if required {
155+ fieldDefault = "true"
156+ required = false
157+ }
158+ } else {
159+ fieldDefault , ok = fieldSchema .Default .(string )
160+ if ! ok {
161+ fieldDefault = ""
162+ }
85163 }
86164
87- fieldContent = fmt .Sprintf (util .TemplateConfigField , false , " open" , headlinePrefix , fieldName , required , fieldType , fieldDefault , fieldSchema .Description , "" )
165+ enumValues := GetEumValues (fieldSchema , required , & fieldDefault )
166+
167+ fieldContent = fmt .Sprintf (util .TemplateConfigField , false , " open" , headlinePrefix , fieldName , required , fieldType , fieldDefault , enumValues , fieldSchema .Description , "" )
88168
89169 err := os .MkdirAll (filepath .Dir (fieldFile ), os .ModePerm )
90170 if err != nil {
@@ -97,43 +177,93 @@ func createSections(prefix string, schema *jsonschema.Schema, definitions jsonsc
97177 }
98178 }
99179
100- * partialImports = append (* partialImports , fieldFile )
101180 fieldPartial := fmt .Sprintf (util .TemplatePartialUse , util .GetPartialImportName (fieldFile ))
102181 if ref != "" {
103182 if isNameObjectMap && nestedSchema != nil {
104183 nameField , ok := nestedSchema .Properties .Get (nameFieldName )
105184 if ok {
106185 if nameFieldSchema , ok := nameField .(* jsonschema.Schema ); ok {
107- fieldPartial = fmt .Sprintf (util .TemplateConfigField , true , "open" , headlinePrefix , "<" + nameFieldName + ">" , false , "object" , "" , nameFieldSchema .Description , fieldPartial )
186+ fieldNameSingular := pluralizeClient .Singular (fieldName )
187+ nameFieldRequired := true
188+ nameFieldDefault := ""
189+ nameFieldEnumValues := GetEumValues (nameFieldSchema , nameFieldRequired , & nameFieldDefault )
190+
191+ fieldPartial = fmt .Sprintf (util .TemplateConfigField , true , "open" , headlinePrefix , "<" + fieldNameSingular + "_" + nameFieldName + ">" , nameFieldRequired , "string" , nameFieldDefault , nameFieldEnumValues , nameFieldSchema .Description , fieldPartial )
192+ fieldType = "<" + fieldNameSingular + "_name>:object"
108193 }
109194 }
110195 }
111- fieldPartial = fmt .Sprintf (util .TemplateConfigField , true , "" , headlinePrefix , fieldName , false , fieldType , "" , fieldSchema .Description , fieldPartial )
196+
197+ fieldPartial = fmt .Sprintf (util .TemplateConfigField , true , "" , headlinePrefix , fieldName , false , fieldType , "" , "" , fieldSchema .Description , fieldPartial )
112198 }
113199
114- content = content + "\n \n " + fieldPartial
200+ if groupID != "" {
201+ group , ok := groups [groupID ]
202+ if ! ok {
203+ group = & Group {
204+ File : fmt .Sprintf (configPartialBasePath + "%s/%sgroup_%s.mdx" , latest .Version , prefix , groupID ),
205+ Imports : & []string {},
206+ }
207+ groups [groupID ] = group
208+
209+ groupPartial := fmt .Sprintf (util .TemplatePartialUse , util .GetPartialImportName (group .File ))
210+
211+ content = content + "\n \n " + groupPartial
212+ * partialImports = append (* partialImports , group .File )
213+ }
214+
215+ if groupName , ok := fieldSchema .Extras [groupNameKey ]; ok {
216+ group .Name = groupName .(string )
217+ }
218+
219+ group .Content = group .Content + fieldPartial
220+ * group .Imports = append (* group .Imports , fieldFile )
221+ } else {
222+ content = content + "\n \n " + fieldPartial
223+ * partialImports = append (* partialImports , fieldFile )
224+ }
115225 }
116226 }
117227 }
118228
119- if prefix == "" {
120- prefix = "reference"
121- }
229+ for groupID , group := range groups {
230+ groupContent := group .Content
122231
123- pageFile := fmt .Sprintf (configPartialBasePath + "%s/%s.mdx" , latest .Version , strings .TrimSuffix (prefix , "/" ))
232+ if group .Name != "" {
233+ groupContent = "\n " + `<div className="group-name">` + group .Name + `</div>` + "\n \n " + groupContent
234+ }
124235
125- importContent := ""
126- for _ , partialImport := range * partialImports {
127- partialImportPath , err := filepath .Rel (filepath .Dir (pageFile ), partialImport )
236+ groupImportContent := ""
237+ for _ , partialFile := range * group .Imports {
238+ groupImportContent = groupImportContent + GetPartialImport (partialFile , group .File )
239+ }
240+
241+ if groupImportContent != "" {
242+ groupImportContent = groupImportContent + "\n \n "
243+ }
244+
245+ groupFileContent := fmt .Sprintf (`%s<div className="group" data-group="%s">%s` + "\n " + `</div>` , groupImportContent , groupID , groupContent )
246+
247+ err := os .MkdirAll (filepath .Dir (group .File ), os .ModePerm )
128248 if err != nil {
129249 panic (err )
130250 }
131251
132- if partialImportPath [0 :1 ] != "." {
133- partialImportPath = "./" + partialImportPath
252+ err = ioutil .WriteFile (group .File , []byte (groupFileContent ), os .ModePerm )
253+ if err != nil {
254+ panic (err )
134255 }
256+ }
257+
258+ if prefix == "" {
259+ prefix = "reference"
260+ }
135261
136- importContent = importContent + fmt .Sprintf (util .TemplatePartialImport , util .GetPartialImportName (partialImport ), partialImportPath )
262+ pageFile := fmt .Sprintf (configPartialBasePath + "%s/%s.mdx" , latest .Version , strings .TrimSuffix (prefix , "/" ))
263+
264+ importContent := ""
265+ for _ , partialFile := range * partialImports {
266+ importContent = importContent + GetPartialImport (partialFile , pageFile )
137267 }
138268
139269 content = fmt .Sprintf ("%s%s" , importContent , content )
@@ -148,6 +278,40 @@ func createSections(prefix string, schema *jsonschema.Schema, definitions jsonsc
148278 return content
149279}
150280
281+ func GetPartialImport (partialFile , importingFile string ) string {
282+ partialImportPath , err := filepath .Rel (filepath .Dir (importingFile ), partialFile )
283+ if err != nil {
284+ panic (err )
285+ }
286+
287+ if partialImportPath [0 :1 ] != "." {
288+ partialImportPath = "./" + partialImportPath
289+ }
290+
291+ return fmt .Sprintf (util .TemplatePartialImport , util .GetPartialImportName (partialFile ), partialImportPath )
292+ }
293+
294+ func GetEumValues (fieldSchema * jsonschema.Schema , required bool , fieldDefault * string ) string {
295+ enumValues := ""
296+ if fieldSchema .Enum != nil {
297+ for i , enumVal := range fieldSchema .Enum {
298+ enumValString , ok := enumVal .(string )
299+ if ok {
300+ if i == 0 && ! required && * fieldDefault == "" {
301+ * fieldDefault = enumValString
302+ }
303+
304+ if enumValues != "" {
305+ enumValues = enumValues + "<br/>"
306+ }
307+ enumValues = enumValues + enumValString
308+ }
309+ }
310+ enumValues = fmt .Sprintf ("<span>%s</span>" , enumValues )
311+ }
312+ return enumValues
313+ }
314+
151315func contains (s []string , e string ) bool {
152316 for _ , a := range s {
153317 if a == e {
0 commit comments