gen-crd-api-reference-docs
gen-crd-api-reference-docs copied to clipboard
automatically link type names found in the doc comments
It would be a great enhancement to automatically link any API type names that are found in the doc comments. Adding a markdown link works, but it doesn't render properly in godoc, so if we can add the link in the generator we can have best of both worlds.
I can't think of a clean way of linking from parts of godoc comments without over-engineering.
Such a smart detection might also be susceptible to issues like:
-
generic type names such as Service could be linked unintentionally from all over the place
-
type A is in multiple pkgs (i.e. multiple apiversions) but we can't easily figure out which one to link to.
If we can live without, that'd be preferable. If you definitely want to do it, probably should be opt-in with an explicit syntax that doesn't break godoc too much.
Yeh, I think you are right; this is more problematic the more you think about it.
I poked at this using strings.Replacer which kinda works because all the types are in a single package (so the Name.Name field is unique). However, replacer does string replacements not word replacements, which is sometimes what you want. ListenerReasonDegradedRoutes gets the Listener part linked to the Listener type, which is totally unwanted, but Listeners also gets its Listener part linked, which could be what you want, but you'd want the whole word to be the link, not just the Listener prefix. There's a few variations of this.
If we switch to something like bufio.Scanwords we would have to deal with preserving the whitespace, which will be complicated. Still would need to have heuristics to get variants like "Listeners" and Gateway(s)" to all link to the same target.
There's no package context from renderComments which would result in the "easily figure out which one to link to" problem you point out above.
Here's a super-naive implementation:
diff --git main.go main.go
index 95193b8..6c7bb71 100644
--- main.go
+++ main.go
@@ -338,14 +338,25 @@ func isLocalType(t *types.Type, typePkgMap map[*types.Type]*apiPackage) bool {
return ok
}
-func renderComments(s []string, markdown bool) string {
+func renderComments(s []string, typePkgMap map[*types.Type]*apiPackage, markdown bool) string {
s = filterCommentTags(s)
doc := strings.Join(s, "\n")
if markdown {
+ var replacements []string
+
+ for t := range typePkgMap {
+ if lnk, err := linkForType(t, generatorConfig{}, typePkgMap); err == nil {
+ klog.Infof("type %q, link %q", t.Name.Name, lnk)
+ replacements = append(replacements, t.Name.Name, fmt.Sprintf("[%s](%s)", t.Name.Name, lnk))
+ }
+ }
+
+ r := strings.NewReplacer(replacements...)
+
// TODO(ahmetb): when a comment includes stuff like "http://<service>"
// we treat this as a HTML tag with markdown renderer below. solve this.
- return string(blackfriday.Run([]byte(doc)))
+ return string(blackfriday.Run([]byte(r.Replace(doc))))
}
return nl2br(doc)
}
@@ -649,7 +660,7 @@ func render(w io.Writer, pkgs []*apiPackage, config generatorConfig) error {
"typeIdentifier": func(t *types.Type) string { return typeIdentifier(t) },
"typeDisplayName": func(t *types.Type) string { return typeDisplayName(t, config, typePkgMap) },
"visibleTypes": func(t []*types.Type) []*types.Type { return visibleTypes(t, config) },
- "renderComments": func(s []string) string { return renderComments(s, !config.MarkdownDisabled) },
+ "renderComments": func(s []string) string { return renderComments(s, typePkgMap, !config.MarkdownDisabled) },
"packageDisplayName": func(p *apiPackage) string { return p.identifier() },
"apiGroup": func(t *types.Type) string { return apiGroupForType(t, typePkgMap) },
"packageAnchorID": func(p *apiPackage) string {