doc.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package docgen
  2. import (
  3. "bytes"
  4. "fmt"
  5. "html/template"
  6. "strconv"
  7. "strings"
  8. "git.i2edu.net/i2/go-zero/core/stringx"
  9. "git.i2edu.net/i2/go-zero/tools/goctl/api/gogen"
  10. "git.i2edu.net/i2/go-zero/tools/goctl/api/spec"
  11. "git.i2edu.net/i2/go-zero/tools/goctl/api/util"
  12. )
  13. const (
  14. markdownTemplate = `
  15. ### {{.index}}. {{.routeComment}}
  16. 1. 路由定义
  17. - Url: {{.uri}}
  18. - Method: {{.method}}
  19. - Request: {{.requestType}}
  20. - Response: {{.responseType}}
  21. 2. 请求定义
  22. {{.requestContent}}
  23. 3. 返回定义
  24. {{.responseContent}}
  25. `
  26. )
  27. func genDoc(api *spec.ApiSpec, dir, filename string) error {
  28. fp, _, err := util.MaybeCreateFile(dir, "", filename)
  29. if err != nil {
  30. return err
  31. }
  32. defer fp.Close()
  33. var builder strings.Builder
  34. for index, route := range api.Service.Routes() {
  35. routeComment := route.JoinedDoc()
  36. if len(routeComment) == 0 {
  37. routeComment = "N/A"
  38. }
  39. requestContent, err := buildDoc(route.RequestType)
  40. if err != nil {
  41. return err
  42. }
  43. responseContent, err := buildDoc(route.ResponseType)
  44. if err != nil {
  45. return err
  46. }
  47. t := template.Must(template.New("markdownTemplate").Parse(markdownTemplate))
  48. var tmplBytes bytes.Buffer
  49. err = t.Execute(&tmplBytes, map[string]string{
  50. "index": strconv.Itoa(index + 1),
  51. "routeComment": routeComment,
  52. "method": strings.ToUpper(route.Method),
  53. "uri": route.Path,
  54. "requestType": "`" + stringx.TakeOne(route.RequestTypeName(), "-") + "`",
  55. "responseType": "`" + stringx.TakeOne(route.ResponseTypeName(), "-") + "`",
  56. "requestContent": requestContent,
  57. "responseContent": responseContent,
  58. })
  59. if err != nil {
  60. return err
  61. }
  62. builder.Write(tmplBytes.Bytes())
  63. }
  64. _, err = fp.WriteString(strings.Replace(builder.String(), """, `"`, -1))
  65. return err
  66. }
  67. func buildDoc(route spec.Type) (string, error) {
  68. if route == nil || len(route.Name()) == 0 {
  69. return "", nil
  70. }
  71. tps := make([]spec.Type, 0)
  72. tps = append(tps, route)
  73. if definedType, ok := route.(spec.DefineStruct); ok {
  74. associatedTypes(definedType, &tps)
  75. }
  76. value, err := gogen.BuildTypes(tps)
  77. if err != nil {
  78. return "", err
  79. }
  80. return fmt.Sprintf("\n\n```golang\n%s\n```\n", value), nil
  81. }
  82. func associatedTypes(tp spec.DefineStruct, tps *[]spec.Type) {
  83. hasAdded := false
  84. for _, item := range *tps {
  85. if item.Name() == tp.Name() {
  86. hasAdded = true
  87. break
  88. }
  89. }
  90. if !hasAdded {
  91. *tps = append(*tps, tp)
  92. }
  93. for _, item := range tp.Members {
  94. if definedType, ok := item.Type.(spec.DefineStruct); ok {
  95. associatedTypes(definedType, tps)
  96. }
  97. }
  98. }