Skip to content

Commit

Permalink
feat: support custom template with --template; search multi dir with …
Browse files Browse the repository at this point in the history
…--dir, comma separated; exclude dir with --excludes.
  • Loading branch information
alovn committed May 17, 2022
1 parent 6d1a7ba commit 54ee905
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 64 deletions.
5 changes: 3 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
"type": "go",
"request": "launch",
"mode": "debug",
"cwd": "${workspaceRoot}",
"program": "${workspaceFolder}/cmd/apidoc/main.go",
"args": [
"--dir", "../../examples/svc-user/",
"--output", "../../examples/docs",
"--dir", "examples/svc-user,examples/common",
"--output", "examples/docs",
]
}
]
Expand Down
16 changes: 12 additions & 4 deletions cmd/apidoc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,36 @@ import (
func main() {
var searchDir string
var outputDir string
var templateDir string
var excludesDir string
var isSingle bool
var isHelp bool
flag.StringVar(&searchDir, "dir", ".", "--dir")
flag.StringVar(&outputDir, "output", "./docs/", "--output")
flag.StringVar(&templateDir, "template", "", "--template")
flag.StringVar(&excludesDir, "excludes", "", "--excludes")
flag.BoolVar(&isSingle, "single", false, "--single")
flag.BoolVar(&isHelp, "help", false, "--help")
flag.Parse()
if isHelp {
fmt.Println(`apidoc is a tool for Go to generate apis markdown docs.
Usage:
apidoc --dir= --output= --single
apidoc --dir= --output= --template= --single
Flags:
--dir: search apis dir, default .
--output: generate markdown files dir, default ./docs/
--single: generate single markdown file, default multi group files`)
--dir: Search apis dir, comma separated, default .
--excludes: Exclude directories and files when searching, comma separated
--output: Generate markdown files dir, default ./docs/
--template: Custom template files dir.
--single: If true, generate a single markdown file, default false`)
return
}
g := gen.New(&gen.Config{
SearchDir: searchDir,
OutputDir: outputDir,
TemplateDir: templateDir,
Excludes: excludesDir,
IsGenSingleFile: isSingle,
})
if err := g.Build(); err != nil {
Expand Down
10 changes: 5 additions & 5 deletions examples/docs/apis-demo.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,15 @@ __id__|_param_|int64|false|||DemoID

_body_:

```javascript
```xml
<request> //object(handler.DemoXMLRequest), XML测试请求对象
<id>123</id> //int64, DemoID
</request>
```

__Response__:

```javascript
```xml
//StatusCode: 200
<response> //object(common.Response), 通用返回结果
<code>0</code> //int, 返回状态码
Expand All @@ -176,7 +176,7 @@ __Response__:
</response>
```

```javascript
```xml
//StatusCode: 200
<response> //object(common.Response), 通用返回结果
<code>0</code> //int, 返回状态码
Expand All @@ -189,7 +189,7 @@ __Response__:
</response>
```

```javascript
```xml
//StatusCode: 200
<response> //object(common.Response), 通用返回结果
<code>10010</code> //int, 返回状态码
Expand All @@ -216,7 +216,7 @@ __Response__:
"data": { //object(handler.DemoTime)
"time_1": "2022-05-16T16:47:48.741899+08:00", //object(time.Time), example1
"time_2": "2022-05-14 15:04:05", //object(time.Time), example2
"time_3": "2022-05-16T16:47:48.742123+08:00" //object(time.Time)
"time_3": "2022-05-16T16:47:48.741899+08:00" //object(time.Time)
},
"msg": "success" //string, 返回消息
}
Expand Down
11 changes: 3 additions & 8 deletions gen/embed.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
package gen

import (
"embed"
_ "embed"
)

//go:embed template/single.tpl
var singleApisTemplate string

//go:embed template/group_readme.tpl
var groupReadmeTemplate string

//go:embed template/group_apis.tpl
var groupApisTemplate string
//go:embed template/*
var defaultTemplateFS embed.FS
93 changes: 82 additions & 11 deletions gen/gen.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package gen

import (
"encoding/json"
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"sort"
Expand All @@ -13,7 +15,9 @@ import (
)

type Gen struct {
c *Config
c *Config
templateFS fs.FS
defaultFS fs.FS
}

func New(c *Config) *Gen {
Expand All @@ -25,16 +29,84 @@ func New(c *Config) *Gen {
type Config struct {
SearchDir string
OutputDir string
TemplateFile string
TemplateDir string
Excludes string
IsGenSingleFile bool
}

type TemplateConfig struct {
Name string `json:"name"`
Index string `json:"index"`
}

func (g *Gen) readTemplate(name string) (s string, err error) {
var bs []byte
if g.templateFS != nil {
if bs, err = fs.ReadFile(g.templateFS, name); err != nil {
return
} else {
s = string(bs)
return
}
} else {
if bs, err = fs.ReadFile(g.defaultFS, name); err != nil {
return
} else {
s = string(bs)
return
}
}
}

func (g *Gen) Build() error {
if g.c == nil {
return errors.New("error config")
}
searchDirs := strings.Split(g.c.SearchDir, ",")
for _, searchDir := range searchDirs {
if _, err := os.Stat(searchDir); os.IsNotExist(err) {
return fmt.Errorf("dir: %s does not exist", searchDir)
}
}
var err error
if g.defaultFS == nil {
if g.defaultFS, err = fs.Sub(defaultTemplateFS, "template"); err != nil {
return err
}
}

if g.templateFS == nil && g.c.TemplateDir != "" {
g.templateFS = os.DirFS(g.c.TemplateDir)
}
var templateSingle string
var templateGroupIndex string
var templateGroupApis string
var templateConfig TemplateConfig

if templateSingle, err = g.readTemplate("single.tpl"); err != nil {
return err
}
if templateGroupIndex, err = g.readTemplate("group_index.tpl"); err != nil {
return err
}
if templateGroupApis, err = g.readTemplate("group_apis.tpl"); err != nil {
return err
}
if s, err := g.readTemplate("config.json"); err != nil {
return err
} else {
if err = json.Unmarshal([]byte(s), &templateConfig); err != nil {
return err
}
if templateConfig.Index == "" {
templateConfig.Index = "README.md"
}
fmt.Println("use template:", templateConfig.Name)
}

p := apidoc.New()
if err := p.Parse(g.c.SearchDir); err != nil {
apidoc.SetExcludedDirsAndFiles(g.c.Excludes)(p)
if err := p.Parse(searchDirs); err != nil {
return err
}
doc := p.GetApiDoc()
Expand Down Expand Up @@ -84,14 +156,13 @@ func (g *Gen) Build() error {
}
sort.Slice(apis, less)
}

if g.c.IsGenSingleFile {
t := template.New("apis-single").Funcs(funcMap)
t, err := t.Parse(singleApisTemplate)
t, err := t.Parse(templateSingle)
if err != nil {
return err
}
f, err := os.Create(filepath.Join(g.c.OutputDir, "README.md"))
f, err := os.Create(filepath.Join(g.c.OutputDir, templateConfig.Index))
if err != nil {
return err
}
Expand All @@ -104,11 +175,11 @@ func (g *Gen) Build() error {
if err = t.Execute(f, doc); err != nil {
return err
}
fmt.Println("generated: README.md")
fmt.Println("generated: ", templateConfig.Index)
} else {
//group
t := template.New("group-apis").Funcs(funcMap)
t, err := t.Parse(groupApisTemplate)
t, err := t.Parse(templateGroupApis)
if err != nil {
return err
}
Expand All @@ -129,19 +200,19 @@ func (g *Gen) Build() error {

//readme
t = template.New("group-readme").Funcs(funcMap)
t, err = t.Parse(groupReadmeTemplate)
t, err = t.Parse(templateGroupIndex)
if err != nil {
return err
}
f, err := os.Create(filepath.Join(g.c.OutputDir, "README.md"))
f, err := os.Create(filepath.Join(g.c.OutputDir, templateConfig.Index))
if err != nil {
return err
}
defer f.Close()
if err = t.Execute(f, doc); err != nil {
return err
}
fmt.Println("generated: README.md")
fmt.Println("generated:", templateConfig.Index)
}
fmt.Println("apis total count:", doc.TotalCount)
return nil
Expand Down
4 changes: 4 additions & 0 deletions gen/template/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name":"default",
"index":"README.md"
}
4 changes: 2 additions & 2 deletions gen/template/group_apis.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ __{{$p.Name}}__|_{{$p.ParameterTypes}}_|{{$p.DataType}}|{{$p.Required}}|{{$p.Val

_body_:

```javascript
```{{if eq $v.Accept "json"}}javascript{{else}}{{$v.Accept}}{{end}}
{{$v.Requests.Body}}
```
{{- end}}
Expand All @@ -58,7 +58,7 @@ _body_:
__Response__:
{{- range $res := $v.Responses}}

```javascript
```{{if eq $v.Format "json"}}javascript{{else}}{{$v.Format}}{{end}}
//StatusCode: {{$res.StatusCode}} {{$res.Description}}
{{$res.Body}}
```
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions gen/template/single.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ __{{$p.Name}}__|_{{$p.ParameterTypes}}_|{{$p.DataType}}|{{$p.Required}}|{{$p.Val

_body_:

```javascript
```{{if eq $v.Accept "json"}}javascript{{else}}{{$v.Accept}}{{end}}
{{$v.Requests.Body}}
```
{{- end}}
Expand All @@ -68,7 +68,7 @@ _body_:
__Response__:
{{- range $res := $v.Responses}}

```javascript
```{{if eq $v.Format "json"}}javascript{{else}}{{$v.Format}}{{end}}
//StatusCode: {{$res.StatusCode}} {{$res.Description}}
{{$res.Body}}
```
Expand Down
6 changes: 6 additions & 0 deletions operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ func (operation *Operation) ParseRequestComment(commentLine string, astFile *ast
}
}
if parameterCount < len(schema.Properties) {
if operation.Accept == "" {
operation.Accept = "json"
}
operation.Requests.Accept = operation.Accept
operation.Requests.Schema = schema
}
Expand Down Expand Up @@ -212,6 +215,9 @@ func (operation *Operation) ParseResponseComment(commentLine string, astFile *as
// fmt.Printf("schema:%+v\n", schema)
// fmt.Println("json:")
// fmt.Println(j)
if operation.Format == "" {
operation.Format = "json"
}
operation.Responses = append(operation.Responses, &ApiResponseSpec{
StatusCode: code,
Format: operation.Format,
Expand Down
Loading

0 comments on commit 54ee905

Please sign in to comment.