Skip to content

Commit 54ee905

Browse files
committed
feat: support custom template with --template; search multi dir with --dir, comma separated; exclude dir with --excludes.
1 parent 6d1a7ba commit 54ee905

File tree

12 files changed

+147
-64
lines changed

12 files changed

+147
-64
lines changed

.vscode/launch.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
"type": "go",
1010
"request": "launch",
1111
"mode": "debug",
12+
"cwd": "${workspaceRoot}",
1213
"program": "${workspaceFolder}/cmd/apidoc/main.go",
1314
"args": [
14-
"--dir", "../../examples/svc-user/",
15-
"--output", "../../examples/docs",
15+
"--dir", "examples/svc-user,examples/common",
16+
"--output", "examples/docs",
1617
]
1718
}
1819
]

cmd/apidoc/main.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,36 @@ import (
1111
func main() {
1212
var searchDir string
1313
var outputDir string
14+
var templateDir string
15+
var excludesDir string
1416
var isSingle bool
1517
var isHelp bool
1618
flag.StringVar(&searchDir, "dir", ".", "--dir")
1719
flag.StringVar(&outputDir, "output", "./docs/", "--output")
20+
flag.StringVar(&templateDir, "template", "", "--template")
21+
flag.StringVar(&excludesDir, "excludes", "", "--excludes")
1822
flag.BoolVar(&isSingle, "single", false, "--single")
1923
flag.BoolVar(&isHelp, "help", false, "--help")
2024
flag.Parse()
2125
if isHelp {
2226
fmt.Println(`apidoc is a tool for Go to generate apis markdown docs.
2327
2428
Usage:
25-
apidoc --dir= --output= --single
29+
apidoc --dir= --output= --template= --single
2630
2731
Flags:
28-
--dir: search apis dir, default .
29-
--output: generate markdown files dir, default ./docs/
30-
--single: generate single markdown file, default multi group files`)
32+
--dir: Search apis dir, comma separated, default .
33+
--excludes: Exclude directories and files when searching, comma separated
34+
--output: Generate markdown files dir, default ./docs/
35+
--template: Custom template files dir.
36+
--single: If true, generate a single markdown file, default false`)
3137
return
3238
}
3339
g := gen.New(&gen.Config{
3440
SearchDir: searchDir,
3541
OutputDir: outputDir,
42+
TemplateDir: templateDir,
43+
Excludes: excludesDir,
3644
IsGenSingleFile: isSingle,
3745
})
3846
if err := g.Build(); err != nil {

examples/docs/apis-demo.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,15 @@ __id__|_param_|int64|false|||DemoID
155155

156156
_body_:
157157

158-
```javascript
158+
```xml
159159
<request> //object(handler.DemoXMLRequest), XML测试请求对象
160160
<id>123</id> //int64, DemoID
161161
</request>
162162
```
163163

164164
__Response__:
165165

166-
```javascript
166+
```xml
167167
//StatusCode: 200
168168
<response> //object(common.Response), 通用返回结果
169169
<code>0</code> //int, 返回状态码
@@ -176,7 +176,7 @@ __Response__:
176176
</response>
177177
```
178178

179-
```javascript
179+
```xml
180180
//StatusCode: 200
181181
<response> //object(common.Response), 通用返回结果
182182
<code>0</code> //int, 返回状态码
@@ -189,7 +189,7 @@ __Response__:
189189
</response>
190190
```
191191

192-
```javascript
192+
```xml
193193
//StatusCode: 200
194194
<response> //object(common.Response), 通用返回结果
195195
<code>10010</code> //int, 返回状态码
@@ -216,7 +216,7 @@ __Response__:
216216
"data": { //object(handler.DemoTime)
217217
"time_1": "2022-05-16T16:47:48.741899+08:00", //object(time.Time), example1
218218
"time_2": "2022-05-14 15:04:05", //object(time.Time), example2
219-
"time_3": "2022-05-16T16:47:48.742123+08:00" //object(time.Time)
219+
"time_3": "2022-05-16T16:47:48.741899+08:00" //object(time.Time)
220220
},
221221
"msg": "success" //string, 返回消息
222222
}

gen/embed.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
package gen
22

33
import (
4+
"embed"
45
_ "embed"
56
)
67

7-
//go:embed template/single.tpl
8-
var singleApisTemplate string
9-
10-
//go:embed template/group_readme.tpl
11-
var groupReadmeTemplate string
12-
13-
//go:embed template/group_apis.tpl
14-
var groupApisTemplate string
8+
//go:embed template/*
9+
var defaultTemplateFS embed.FS

gen/gen.go

Lines changed: 82 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package gen
22

33
import (
4+
"encoding/json"
45
"errors"
56
"fmt"
7+
"io/fs"
68
"os"
79
"path/filepath"
810
"sort"
@@ -13,7 +15,9 @@ import (
1315
)
1416

1517
type Gen struct {
16-
c *Config
18+
c *Config
19+
templateFS fs.FS
20+
defaultFS fs.FS
1721
}
1822

1923
func New(c *Config) *Gen {
@@ -25,16 +29,84 @@ func New(c *Config) *Gen {
2529
type Config struct {
2630
SearchDir string
2731
OutputDir string
28-
TemplateFile string
32+
TemplateDir string
33+
Excludes string
2934
IsGenSingleFile bool
3035
}
3136

37+
type TemplateConfig struct {
38+
Name string `json:"name"`
39+
Index string `json:"index"`
40+
}
41+
42+
func (g *Gen) readTemplate(name string) (s string, err error) {
43+
var bs []byte
44+
if g.templateFS != nil {
45+
if bs, err = fs.ReadFile(g.templateFS, name); err != nil {
46+
return
47+
} else {
48+
s = string(bs)
49+
return
50+
}
51+
} else {
52+
if bs, err = fs.ReadFile(g.defaultFS, name); err != nil {
53+
return
54+
} else {
55+
s = string(bs)
56+
return
57+
}
58+
}
59+
}
60+
3261
func (g *Gen) Build() error {
3362
if g.c == nil {
3463
return errors.New("error config")
3564
}
65+
searchDirs := strings.Split(g.c.SearchDir, ",")
66+
for _, searchDir := range searchDirs {
67+
if _, err := os.Stat(searchDir); os.IsNotExist(err) {
68+
return fmt.Errorf("dir: %s does not exist", searchDir)
69+
}
70+
}
71+
var err error
72+
if g.defaultFS == nil {
73+
if g.defaultFS, err = fs.Sub(defaultTemplateFS, "template"); err != nil {
74+
return err
75+
}
76+
}
77+
78+
if g.templateFS == nil && g.c.TemplateDir != "" {
79+
g.templateFS = os.DirFS(g.c.TemplateDir)
80+
}
81+
var templateSingle string
82+
var templateGroupIndex string
83+
var templateGroupApis string
84+
var templateConfig TemplateConfig
85+
86+
if templateSingle, err = g.readTemplate("single.tpl"); err != nil {
87+
return err
88+
}
89+
if templateGroupIndex, err = g.readTemplate("group_index.tpl"); err != nil {
90+
return err
91+
}
92+
if templateGroupApis, err = g.readTemplate("group_apis.tpl"); err != nil {
93+
return err
94+
}
95+
if s, err := g.readTemplate("config.json"); err != nil {
96+
return err
97+
} else {
98+
if err = json.Unmarshal([]byte(s), &templateConfig); err != nil {
99+
return err
100+
}
101+
if templateConfig.Index == "" {
102+
templateConfig.Index = "README.md"
103+
}
104+
fmt.Println("use template:", templateConfig.Name)
105+
}
106+
36107
p := apidoc.New()
37-
if err := p.Parse(g.c.SearchDir); err != nil {
108+
apidoc.SetExcludedDirsAndFiles(g.c.Excludes)(p)
109+
if err := p.Parse(searchDirs); err != nil {
38110
return err
39111
}
40112
doc := p.GetApiDoc()
@@ -84,14 +156,13 @@ func (g *Gen) Build() error {
84156
}
85157
sort.Slice(apis, less)
86158
}
87-
88159
if g.c.IsGenSingleFile {
89160
t := template.New("apis-single").Funcs(funcMap)
90-
t, err := t.Parse(singleApisTemplate)
161+
t, err := t.Parse(templateSingle)
91162
if err != nil {
92163
return err
93164
}
94-
f, err := os.Create(filepath.Join(g.c.OutputDir, "README.md"))
165+
f, err := os.Create(filepath.Join(g.c.OutputDir, templateConfig.Index))
95166
if err != nil {
96167
return err
97168
}
@@ -104,11 +175,11 @@ func (g *Gen) Build() error {
104175
if err = t.Execute(f, doc); err != nil {
105176
return err
106177
}
107-
fmt.Println("generated: README.md")
178+
fmt.Println("generated: ", templateConfig.Index)
108179
} else {
109180
//group
110181
t := template.New("group-apis").Funcs(funcMap)
111-
t, err := t.Parse(groupApisTemplate)
182+
t, err := t.Parse(templateGroupApis)
112183
if err != nil {
113184
return err
114185
}
@@ -129,19 +200,19 @@ func (g *Gen) Build() error {
129200

130201
//readme
131202
t = template.New("group-readme").Funcs(funcMap)
132-
t, err = t.Parse(groupReadmeTemplate)
203+
t, err = t.Parse(templateGroupIndex)
133204
if err != nil {
134205
return err
135206
}
136-
f, err := os.Create(filepath.Join(g.c.OutputDir, "README.md"))
207+
f, err := os.Create(filepath.Join(g.c.OutputDir, templateConfig.Index))
137208
if err != nil {
138209
return err
139210
}
140211
defer f.Close()
141212
if err = t.Execute(f, doc); err != nil {
142213
return err
143214
}
144-
fmt.Println("generated: README.md")
215+
fmt.Println("generated:", templateConfig.Index)
145216
}
146217
fmt.Println("apis total count:", doc.TotalCount)
147218
return nil

gen/template/config.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name":"default",
3+
"index":"README.md"
4+
}

gen/template/group_apis.tpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ __{{$p.Name}}__|_{{$p.ParameterTypes}}_|{{$p.DataType}}|{{$p.Required}}|{{$p.Val
4848

4949
_body_:
5050

51-
```javascript
51+
```{{if eq $v.Accept "json"}}javascript{{else}}{{$v.Accept}}{{end}}
5252
{{$v.Requests.Body}}
5353
```
5454
{{- end}}
@@ -58,7 +58,7 @@ _body_:
5858
__Response__:
5959
{{- range $res := $v.Responses}}
6060

61-
```javascript
61+
```{{if eq $v.Format "json"}}javascript{{else}}{{$v.Format}}{{end}}
6262
//StatusCode: {{$res.StatusCode}} {{$res.Description}}
6363
{{$res.Body}}
6464
```
File renamed without changes.

gen/template/single.tpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ __{{$p.Name}}__|_{{$p.ParameterTypes}}_|{{$p.DataType}}|{{$p.Required}}|{{$p.Val
5858

5959
_body_:
6060

61-
```javascript
61+
```{{if eq $v.Accept "json"}}javascript{{else}}{{$v.Accept}}{{end}}
6262
{{$v.Requests.Body}}
6363
```
6464
{{- end}}
@@ -68,7 +68,7 @@ _body_:
6868
__Response__:
6969
{{- range $res := $v.Responses}}
7070

71-
```javascript
71+
```{{if eq $v.Format "json"}}javascript{{else}}{{$v.Format}}{{end}}
7272
//StatusCode: {{$res.StatusCode}} {{$res.Description}}
7373
{{$res.Body}}
7474
```

operation.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ func (operation *Operation) ParseRequestComment(commentLine string, astFile *ast
159159
}
160160
}
161161
if parameterCount < len(schema.Properties) {
162+
if operation.Accept == "" {
163+
operation.Accept = "json"
164+
}
162165
operation.Requests.Accept = operation.Accept
163166
operation.Requests.Schema = schema
164167
}
@@ -212,6 +215,9 @@ func (operation *Operation) ParseResponseComment(commentLine string, astFile *as
212215
// fmt.Printf("schema:%+v\n", schema)
213216
// fmt.Println("json:")
214217
// fmt.Println(j)
218+
if operation.Format == "" {
219+
operation.Format = "json"
220+
}
215221
operation.Responses = append(operation.Responses, &ApiResponseSpec{
216222
StatusCode: code,
217223
Format: operation.Format,

0 commit comments

Comments
 (0)