@@ -67,9 +67,13 @@ const (
67
67
68
68
// KclPackage contains package information of package metadata(such as name, version, description, ...) and exported models(such as schemas)
69
69
type KclPackage struct {
70
- Name string
71
- Version string `toml:"version,omitempty"` // kcl package version
72
- Schemas []* KclOpenAPIType
70
+ Name string `json:"name,omitempty"` // kcl package name
71
+ Version string `json:"version,omitempty"` // kcl package version
72
+ Description string `json:"description,omitempty"` // summary of the kcl package
73
+ schemaMapping map [string ]* KclOpenAPIType
74
+ subPackageMapping map [string ]* KclPackage
75
+ SchemaList []* KclOpenAPIType `json:"schemaList,omitempty"` // the schema list sorted by name in the KCL package
76
+ SubPackageList []* KclPackage `json:"subPackageList,omitempty"` // the sub package list sorted by name in the KCL package
73
77
}
74
78
75
79
func (g * GenContext ) render (spec * SwaggerV2Spec ) error {
@@ -78,48 +82,78 @@ func (g *GenContext) render(spec *SwaggerV2Spec) error {
78
82
if err != nil {
79
83
return fmt .Errorf ("failed to create docs/ directory under the target directory: %s" , err )
80
84
}
85
+ // extract kcl package from swaggerV2 spec
86
+ rootPkg := spec .toKclPackage ()
87
+ // sort schemas and subpackages by their names
88
+ rootPkg .sortSchemasAndPkgs ()
89
+ // render the package
90
+ err = g .renderPackage (rootPkg , g .Target )
91
+ if err != nil {
92
+ return err
93
+ }
94
+ return nil
95
+ }
81
96
82
- // collect all the packages and schema list that they contain
83
- pkgs := make (map [string ]* KclPackage )
97
+ // toKclPackage extracts a kcl package and sub packages, schemas from a SwaggerV2 spec
98
+ func (spec SwaggerV2Spec ) toKclPackage () * KclPackage {
99
+ rootPkg := & KclPackage {
100
+ Name : spec .Info .Title ,
101
+ Version : spec .Info .Version ,
102
+ Description : spec .Info .Description ,
103
+ }
84
104
85
- for _ , schema := range spec .Definitions {
105
+ for schemaName , schema := range spec .Definitions {
86
106
pkgName := schema .KclExtensions .XKclModelType .Import .Package
87
- if _ , ok := pkgs [pkgName ]; ok {
88
- pkgs [pkgName ].Schemas = append (pkgs [pkgName ].Schemas , schema )
89
- } else {
90
- pkgs [pkgName ] = & KclPackage {
91
- Name : pkgName ,
107
+ if pkgName == "" {
108
+ addOrCreateSchema (rootPkg , schemaName , schema )
109
+ continue
110
+ }
111
+ parentPkg := rootPkg
112
+ subs := strings .Split (pkgName , "." )
113
+ for _ , sub := range subs {
114
+ if parentPkg .subPackageMapping == nil {
115
+ parentPkg .subPackageMapping = map [string ]* KclPackage {}
92
116
}
93
- pkgs [pkgName ].Schemas = []* KclOpenAPIType {schema }
117
+ if _ , ok := parentPkg .subPackageMapping [sub ]; ! ok {
118
+ parentPkg .subPackageMapping [sub ] = & KclPackage {
119
+ Name : sub ,
120
+ }
121
+ }
122
+ parentPkg = parentPkg .subPackageMapping [sub ]
94
123
}
124
+
125
+ addOrCreateSchema (parentPkg , schemaName , schema )
95
126
}
127
+ return rootPkg
128
+ }
96
129
97
- err = g .renderPackage (pkgs )
98
- if err != nil {
99
- return err
130
+ func (pkg * KclPackage ) sortSchemasAndPkgs () {
131
+ pkg .SubPackageList = sortMapToSlice (pkg .subPackageMapping )
132
+ pkg .SchemaList = sortMapToSlice (pkg .schemaMapping )
133
+ for _ , sub := range pkg .SubPackageList {
134
+ sub .sortSchemasAndPkgs ()
100
135
}
136
+ }
101
137
102
- for _ , schema := range spec .Definitions {
103
- // create package directory if not exist
104
- pkgDir := schema .GetSchemaPkgDir (g .Target )
105
- err := os .MkdirAll (pkgDir , 0755 )
106
- if err != nil {
107
- return fmt .Errorf ("failed to create docs/%s directory under the target directory: %s" , pkgDir , err )
108
- }
109
- // get doc file name
110
- fileName := fmt .Sprintf ("%s.%s" , schema .KclExtensions .XKclModelType .Type , g .Format )
111
- // render doc content
112
- content , err := g .renderSchemaDocContent (schema )
113
- if err != nil {
114
- return err
115
- }
116
- // write content to file
117
- err = os .WriteFile (filepath .Join (pkgDir , fileName ), content , 0644 )
118
- if err != nil {
119
- return fmt .Errorf ("failed to write file %s in %s: %v" , fileName , pkgDir , err )
120
- }
138
+ func sortMapToSlice [T any ](mapping map [string ]T ) []T {
139
+ keys := make ([]string , 0 , len (mapping ))
140
+ for k := range mapping {
141
+ keys = append (keys , k )
142
+ }
143
+ sort .Strings (keys )
144
+ sorted := make ([]T , 0 , len (mapping ))
145
+ for _ , k := range keys {
146
+ sorted = append (sorted , mapping [k ])
147
+ }
148
+ return sorted
149
+ }
150
+
151
+ func addOrCreateSchema (pkg * KclPackage , schemaName string , schema * KclOpenAPIType ) {
152
+ if pkg .schemaMapping == nil {
153
+ pkg .schemaMapping = map [string ]* KclOpenAPIType {schemaName : schema }
154
+ } else {
155
+ pkg .schemaMapping [schemaName ] = schema
121
156
}
122
- return nil
123
157
}
124
158
125
159
func funcMap () template.FuncMap {
@@ -145,38 +179,69 @@ func funcMap() template.FuncMap {
145
179
// todo: let users specify the source code base path
146
180
return filepath .Join (tpe .GetSchemaPkgDir ("" ), tpe .KclExtensions .XKclModelType .Import .Alias )
147
181
},
148
- "sortSchemas" : func (schemas []* KclOpenAPIType ) []* KclOpenAPIType {
149
- sort .Slice (schemas , func (i , j int ) bool {
150
- return schemas [i ].KclExtensions .XKclModelType .Type < schemas [j ].KclExtensions .XKclModelType .Type
151
- })
152
- return schemas
182
+ "index" : func (pkg * KclPackage ) string {
183
+ return pkg .getIndexContent (0 , " " , "" )
153
184
},
154
185
}
155
186
}
156
187
157
- func (g * GenContext ) renderPackage (pkgs map [string ]* KclPackage ) error {
158
- for name , pkg := range pkgs {
159
- // create the package directory
160
- pkgDir := GetPkgDir (g .Target , name )
188
+ func (pkg * KclPackage ) getPackageIndexContent (level int , indentation string , pkgPath string ) string {
189
+ currentPkgPath := filepath .Join (pkgPath , pkg .Name )
190
+ currentDocPath := filepath .Join (currentPkgPath , "index.md" )
191
+ return fmt .Sprintf (`%s- [%s](%s)
192
+ %s` , strings .Repeat (indentation , level ), pkg .Name , currentDocPath , pkg .getIndexContent (level + 1 , indentation , currentPkgPath ))
193
+ }
194
+
195
+ func (tpe * KclOpenAPIType ) getSchemaIndexContent (level int , indentation string , pkgPath string ) string {
196
+ docPath := filepath .Join (pkgPath , "index.md" )
197
+ if level == 0 {
198
+ docPath = ""
199
+ }
200
+ return fmt .Sprintf (`%s- [%s](%s#schema-%s)
201
+ ` , strings .Repeat (indentation , level ), tpe .KclExtensions .XKclModelType .Type , docPath , tpe .KclExtensions .XKclModelType .Type )
202
+ }
203
+
204
+ func (pkg * KclPackage ) getIndexContent (level int , indentation string , pkgPath string ) string {
205
+ var content string
206
+ if len (pkg .SchemaList ) > 0 {
207
+ for _ , sch := range pkg .SchemaList {
208
+ content += sch .getSchemaIndexContent (level , indentation , pkgPath )
209
+ }
210
+ }
211
+ if len (pkg .SubPackageList ) > 0 {
212
+ for _ , pkg := range pkg .SubPackageList {
213
+ content += pkg .getPackageIndexContent (level , indentation , pkgPath )
214
+ }
215
+ }
216
+ return content
217
+ }
218
+
219
+ func (g * GenContext ) renderPackage (pkg * KclPackage , parentDir string ) error {
220
+ // render the package's index.md page
221
+ //fmt.Println(fmt.Sprintf("creating %s/index.md", parentDir))
222
+ indexFileName := fmt .Sprintf ("%s.%s" , "index" , g .Format )
223
+ var contentBuf bytes.Buffer
224
+ err := tmpl .ExecuteTemplate (& contentBuf , "packageDoc" , pkg )
225
+ if err != nil {
226
+ return fmt .Errorf ("failed to render package %s with template, err: %s" , pkg .Name , err )
227
+ }
228
+ // write content to file
229
+ err = os .WriteFile (filepath .Join (parentDir , indexFileName ), contentBuf .Bytes (), 0644 )
230
+ if err != nil {
231
+ return fmt .Errorf ("failed to write file %s in %s: %v" , indexFileName , parentDir , err )
232
+ }
233
+
234
+ for _ , sub := range pkg .SubPackageList {
235
+ pkgDir := GetPkgDir (parentDir , sub .Name )
236
+ //fmt.Println(fmt.Sprintf("creating directory: %s", pkgDir))
161
237
err := os .MkdirAll (pkgDir , 0755 )
162
238
if err != nil {
163
239
return fmt .Errorf ("failed to create docs/%s directory under the target directory: %s" , pkgDir , err )
164
240
}
165
- indexFileName := fmt .Sprintf ("%s.%s" , "index" , g .Format )
166
- // render index doc content
167
- var contentBuf bytes.Buffer
168
- err = tmpl .ExecuteTemplate (& contentBuf , "packageDoc" , pkg )
169
- if err != nil {
170
- return fmt .Errorf ("failed to render package %s with template, err: %s" , name , err )
171
- }
241
+ err = g .renderPackage (sub , pkgDir )
172
242
if err != nil {
173
243
return err
174
244
}
175
- // write content to file
176
- err = os .WriteFile (filepath .Join (pkgDir , indexFileName ), contentBuf .Bytes (), 0644 )
177
- if err != nil {
178
- return fmt .Errorf ("failed to write file %s in %s: %v" , indexFileName , pkgDir , err )
179
- }
180
245
}
181
246
return nil
182
247
}
@@ -251,7 +316,6 @@ func (g *GenContext) GenDoc() error {
251
316
return fmt .Errorf ("filePath is not a KCL package: %s" , err )
252
317
}
253
318
spec , err := g .getSwagger2Spec (pkg )
254
- //todo: deal err
255
319
err = g .render (spec )
256
320
if err != nil {
257
321
return fmt .Errorf ("render doc failed: %s" , err )
0 commit comments