From 267ab89779f4c3edbca5d5053f830209aca811d5 Mon Sep 17 00:00:00 2001 From: David Jencks Date: Thu, 20 Jan 2022 17:42:32 -0800 Subject: [PATCH 1/5] Adapt to generate AsciiDoc with appropriate templates --- main.go | 63 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/main.go b/main.go index 76104ac..672fed3 100644 --- a/main.go +++ b/main.go @@ -60,6 +60,9 @@ type generatorConfig struct { // MarkdownDisabled controls markdown rendering for comment lines. MarkdownDisabled bool `json:"markdownDisabled"` + // AsciiDoc controls HTML/text output and some comment escaping. + AsciiDoc bool `json:"asciiDoc"` + // GitCommitDisabled causes the git commit information to be excluded from the output. GitCommitDisabled bool `json:"gitCommitDisabled"` } @@ -150,9 +153,11 @@ func main() { return "", errors.Wrap(err, "failed to render the result") } - // remove trailing whitespace from each html line for markdown renderers - s := regexp.MustCompile(`(?m)^\s+`).ReplaceAllString(b.String(), "") - return s, nil + if !config.AsciiDoc { + // remove trailing whitespace from each html line for markdown renderers + return regexp.MustCompile(`(?m)^\s+`).ReplaceAllString(b.String(), ""), nil + } + return b.String(), nil } if *flOutFile != "" { @@ -346,7 +351,7 @@ func isLocalType(t *types.Type, typePkgMap map[*types.Type]*apiPackage) bool { return ok } -func renderComments(s []string, markdown bool) string { +func renderComments(s []string, markdown bool, asciiDoc bool) string { s = filterCommentTags(s) doc := strings.Join(s, "\n") @@ -355,7 +360,16 @@ func renderComments(s []string, markdown bool) string { // we treat this as a HTML tag with markdown renderer below. solve this. return string(blackfriday.Run([]byte(doc))) } - return nl2br(doc) + + if asciiDoc{ + doc = strings.ReplaceAll(doc, "#", "\\#") // avoid highlighting + doc = strings.ReplaceAll(doc, "{", "\\{") // avoid interpretation as attribute + doc = strings.ReplaceAll(doc, "|", "{vbar}") // avoid alternation interpreted as column separator + } else { + doc = nl2br(doc) + } + + return doc } func safe(s string) template.HTML { return template.HTML(s) } @@ -393,7 +407,7 @@ func apiGroupForType(t *types.Type, typePkgMap map[*types.Type]*apiPackage) stri // anchorIDForLocalType returns the #anchor string for the local type func anchorIDForLocalType(t *types.Type, typePkgMap map[*types.Type]*apiPackage) string { - return fmt.Sprintf("%s.%s", apiGroupForType(t, typePkgMap), t.Name.Name) + return sanitizeId(fmt.Sprintf("%s.%s", apiGroupForType(t, typePkgMap), t.Name.Name)) } // linkForType returns an anchor to the type if it can be generated. returns @@ -648,18 +662,22 @@ func constantsOfType(t *types.Type, pkg *apiPackage) []*types.Type { return sortTypes(constants) } +func sanitizeId(s string) string { + return "_" + regexp.MustCompile("[./ -]+").ReplaceAllString(s, "_") +} + func render(w io.Writer, pkgs []*apiPackage, config generatorConfig) error { references := findTypeReferences(pkgs) typePkgMap := extractTypeToPackageMap(pkgs) - t, err := template.New("").Funcs(map[string]interface{}{ + funcMap := map[string]interface{}{ "isExportedType": isExportedType, "fieldName": fieldName, "fieldEmbedded": fieldEmbedded, "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, !config.MarkdownDisabled, config.AsciiDoc) }, "packageDisplayName": func(p *apiPackage) string { return p.identifier() }, "apiGroup": func(t *types.Type) string { return apiGroupForType(t, typePkgMap) }, "packageAnchorID": func(p *apiPackage) string { @@ -667,7 +685,7 @@ func render(w io.Writer, pkgs []*apiPackage, config generatorConfig) error { // func, and it's fine since it retuns valid DOM id strings like // 'serving.knative.dev/v1alpha1' which is valid per HTML5, except // spaces, so just trim those. - return strings.Replace(p.identifier(), " ", "", -1) + return sanitizeId(p.identifier()) }, "linkForType": func(t *types.Type) string { v, err := linkForType(t, config, typePkgMap) @@ -682,22 +700,33 @@ func render(w io.Writer, pkgs []*apiPackage, config generatorConfig) error { "sortedTypes": sortTypes, "typeReferences": func(t *types.Type) []*types.Type { return typeReferences(t, config, references) }, "hiddenMember": func(m types.Member) bool { return hiddenMember(m, config) }, - "isLocalType": isLocalType, + "isLocalType": func(t *types.Type) bool { return isLocalType(t, typePkgMap) }, "isOptionalMember": isOptionalMember, "constantsOfType": func(t *types.Type) []*types.Type { return constantsOfType(t, typePkgMap[t]) }, - }).ParseGlob(filepath.Join(*flTemplateDir, "*.tpl")) - if err != nil { - return errors.Wrap(err, "parse error") } - var gitCommit []byte if !config.GitCommitDisabled { gitCommit, _ = exec.Command("git", "rev-parse", "--short", "HEAD").Output() } - - return errors.Wrap(t.ExecuteTemplate(w, "packages", map[string]interface{}{ + data := map[string]interface{}{ "packages": pkgs, "config": config, "gitCommit": strings.TrimSpace(string(gitCommit)), - }), "template execution error") + } + + if config.AsciiDoc { + t, err := texttemplate.New("").Funcs(funcMap).ParseGlob(filepath.Join(*flTemplateDir, "*.tpl")) + if err != nil { + return errors.Wrap(err, "parse error") + } + + return errors.Wrap(t.ExecuteTemplate(w, "packages", data), "template execution error") + } else { + t, err := template.New("").Funcs(funcMap).ParseGlob(filepath.Join(*flTemplateDir, "*.tpl")) + if err != nil { + return errors.Wrap(err, "parse error") + } + + return errors.Wrap(t.ExecuteTemplate(w, "packages", data), "template execution error") + } } From 5319c98b89a5438b096aeccb0049a5f6c75543a6 Mon Sep 17 00:00:00 2001 From: David Jencks Date: Thu, 20 Jan 2022 18:12:45 -0800 Subject: [PATCH 2/5] Is this needed to use? change go.mod source to djencks --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 074dd3d..2431d71 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/ahmetb/gen-crd-api-reference-docs +module github.com/djencks/gen-crd-api-reference-docs go 1.15 From 7400a10b36d7cfa7563ea48ce0df15a9d4c2de87 Mon Sep 17 00:00:00 2001 From: David Jencks Date: Tue, 25 Jan 2022 23:01:42 -0800 Subject: [PATCH 3/5] Improve AsciiDoc comment escaping and add asciiDocAttributeEscape function for xrefs to arrays --- main.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 672fed3..9bbf150 100644 --- a/main.go +++ b/main.go @@ -362,8 +362,9 @@ func renderComments(s []string, markdown bool, asciiDoc bool) string { } if asciiDoc{ - doc = strings.ReplaceAll(doc, "#", "\\#") // avoid highlighting - doc = strings.ReplaceAll(doc, "{", "\\{") // avoid interpretation as attribute + doc = strings.Replace(doc, "#", "\\#", strings.Count(doc, "#") - 1) // avoid highlighting + non_attribute_re := regexp.MustCompile("{([^} ]+})") + doc = non_attribute_re.ReplaceAllString(doc, "\\{$1") // avoid interpretation as attribute doc = strings.ReplaceAll(doc, "|", "{vbar}") // avoid alternation interpreted as column separator } else { doc = nl2br(doc) @@ -703,6 +704,7 @@ func render(w io.Writer, pkgs []*apiPackage, config generatorConfig) error { "isLocalType": func(t *types.Type) bool { return isLocalType(t, typePkgMap) }, "isOptionalMember": isOptionalMember, "constantsOfType": func(t *types.Type) []*types.Type { return constantsOfType(t, typePkgMap[t]) }, + "asciiDocAttributeEscape": func(s string) string { return strings.ReplaceAll(s, "]", "\\]") }, } var gitCommit []byte if !config.GitCommitDisabled { From 544fe2859c8d199c8caa9374da600859686fff05 Mon Sep 17 00:00:00 2001 From: David Jencks Date: Sun, 30 Jan 2022 18:13:16 -0800 Subject: [PATCH 4/5] Expose sanitizeId as function for template; dereference local types when computing anchor id --- main.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 9bbf150..8c74696 100644 --- a/main.go +++ b/main.go @@ -408,7 +408,8 @@ func apiGroupForType(t *types.Type, typePkgMap map[*types.Type]*apiPackage) stri // anchorIDForLocalType returns the #anchor string for the local type func anchorIDForLocalType(t *types.Type, typePkgMap map[*types.Type]*apiPackage) string { - return sanitizeId(fmt.Sprintf("%s.%s", apiGroupForType(t, typePkgMap), t.Name.Name)) + t = tryDereference(t) + return fmt.Sprintf("%s.%s", apiGroupForType(t, typePkgMap), t.Name.Name) } // linkForType returns an anchor to the type if it can be generated. returns @@ -681,12 +682,12 @@ func render(w io.Writer, pkgs []*apiPackage, config generatorConfig) error { "renderComments": func(s []string) string { return renderComments(s, !config.MarkdownDisabled, config.AsciiDoc) }, "packageDisplayName": func(p *apiPackage) string { return p.identifier() }, "apiGroup": func(t *types.Type) string { return apiGroupForType(t, typePkgMap) }, - "packageAnchorID": func(p *apiPackage) string { + "packageAnchorID": func(p *apiPackage) string { // TODO(ahmetb): currently this is the same as packageDisplayName // func, and it's fine since it retuns valid DOM id strings like // 'serving.knative.dev/v1alpha1' which is valid per HTML5, except // spaces, so just trim those. - return sanitizeId(p.identifier()) + return strings.ReplaceAll(p.identifier(), " ", "") }, "linkForType": func(t *types.Type) string { v, err := linkForType(t, config, typePkgMap) @@ -704,6 +705,7 @@ func render(w io.Writer, pkgs []*apiPackage, config generatorConfig) error { "isLocalType": func(t *types.Type) bool { return isLocalType(t, typePkgMap) }, "isOptionalMember": isOptionalMember, "constantsOfType": func(t *types.Type) []*types.Type { return constantsOfType(t, typePkgMap[t]) }, + "sanitizeId": sanitizeId, "asciiDocAttributeEscape": func(s string) string { return strings.ReplaceAll(s, "]", "\\]") }, } var gitCommit []byte From e63530f10b55be5f2d82e223d83f86c13e5158e5 Mon Sep 17 00:00:00 2001 From: David Jencks Date: Sun, 30 Jan 2022 18:13:44 -0800 Subject: [PATCH 5/5] try updating travis to 1.12 to allow use of strings.ReplaceAll --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d6845ba..8d971bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: go go: - - 1.11.x + - 1.12.x install: - echo noop before_script: