diff --git a/README.md b/README.md new file mode 100644 index 0000000..2f0b230 --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +# docgen + +Route documentation generator for [chi](https://github.com/go-chi/chi) routers. + +## Install + +```bash +go get github.com/go-chi/docgen +``` + +## Usage + +Generate markdown API docs from your router: + +```go +package main + +import ( + "net/http" + + "github.com/go-chi/chi/v5" + "github.com/go-chi/docgen" +) + +func main() { + r := chi.NewRouter() + r.Get("/", func(w http.ResponseWriter, r *http.Request) {}) + + md := docgen.NewMarkdownDoc(r) + md.Opts.ProjectPath = "github.com/my/app" + md.Opts.URLMap = map[string]string{ + "github.com/go-chi/chi/v5": "https://github.com/go-chi/chi/tree/master", + } + println(md.Markdown()) +} +``` + +See `docgen_test.go` and `raml/raml_test.go` for more examples. + +## License + +MIT diff --git a/builder.go b/builder.go index 9012109..8a69a1d 100644 --- a/builder.go +++ b/builder.go @@ -10,6 +10,7 @@ import ( "github.com/go-chi/chi/v5" ) +// BuildDoc walks a chi router and builds structured route documentation. func BuildDoc(r chi.Routes) (Doc, error) { d := Doc{} diff --git a/docgen.go b/docgen.go index 94f8439..d60ab94 100644 --- a/docgen.go +++ b/docgen.go @@ -1,3 +1,4 @@ +// Package docgen generates route documentation from chi routers. package docgen import ( @@ -7,6 +8,7 @@ import ( "github.com/go-chi/chi/v5" ) +// Doc is the JSON-serializable documentation for a chi router tree. type Doc struct { Router DocRouter `json:"router"` } @@ -36,6 +38,7 @@ type DocHandler struct { type DocHandlers map[string]DocHandler // Method : DocHandler +// PrintRoutes prints route patterns from a chi router to stdout. func PrintRoutes(r chi.Routes) { var printRoutes func(parentPattern string, r chi.Routes) printRoutes = func(parentPattern string, r chi.Routes) { @@ -54,6 +57,7 @@ func PrintRoutes(r chi.Routes) { printRoutes("", r) } +// JSONRoutesDoc returns indented JSON documentation for a chi router. func JSONRoutesDoc(r chi.Routes) string { doc, _ := BuildDoc(r) v, err := json.MarshalIndent(doc, "", " ") diff --git a/funcinfo.go b/funcinfo.go index 6013f10..d6d4b89 100644 --- a/funcinfo.go +++ b/funcinfo.go @@ -19,6 +19,7 @@ type FuncInfo struct { Unresolvable bool `json:"unresolvable,omitempty"` } +// GetFuncInfo returns source location and comment metadata for a handler. func GetFuncInfo(i interface{}) FuncInfo { fi := FuncInfo{} frame := getCallerFrame(i) diff --git a/markdown.go b/markdown.go index ec1a043..d25a872 100644 --- a/markdown.go +++ b/markdown.go @@ -4,12 +4,16 @@ import ( "bytes" "errors" "fmt" + "regexp" "sort" "strings" "github.com/go-chi/chi/v5" ) +// moduleVersionInPath matches Go module cache version segments (e.g. @v5.0.11). +var moduleVersionInPath = regexp.MustCompile(`@v[^/]+`) + type MarkdownDoc struct { Opts MarkdownOpts Router chi.Router @@ -36,6 +40,7 @@ type MarkdownOpts struct { URLMap map[string]string } +// MarkdownRoutesDoc renders route documentation as Markdown for a chi router. func MarkdownRoutesDoc(r chi.Router, opts MarkdownOpts) string { md := &MarkdownDoc{Router: r, Opts: opts} if err := md.Generate(); err != nil { @@ -193,6 +198,8 @@ func (md *MarkdownDoc) WriteRoutes() { } func (md *MarkdownDoc) githubSourceURL(file string, line int) string { + file = moduleVersionInPath.ReplaceAllString(file, "") + // Currently, we only automatically link to source for github projects if strings.Index(file, "github.com/") != 0 && !md.Opts.ForceRelativeLinks { return "" diff --git a/markdown_test.go b/markdown_test.go new file mode 100644 index 0000000..ad4f15a --- /dev/null +++ b/markdown_test.go @@ -0,0 +1,21 @@ +package docgen + +import "testing" + +func TestGithubSourceURLStripsModuleVersion(t *testing.T) { + md := &MarkdownDoc{ + Opts: MarkdownOpts{ + ProjectPath: "github.com/go-chi/chi/v5", + URLMap: map[string]string{ + "github.com/go-chi/chi/v5": "https://github.com/go-chi/chi/tree/master", + }, + }, + } + + file := "github.com/go-chi/chi/v5@v5.0.11/middleware/logger.go" + got := md.githubSourceURL(file, 39) + want := "https://github.com/go-chi/chi/tree/master/middleware/logger.go#L39" + if got != want { + t.Fatalf("got %q, want %q", got, want) + } +}