elastic / crd-ref-docs

Generates Kubernetes CRD API reference documentation
Apache License 2.0
104 stars 54 forks source link

[Feature Request] support more custom markers #70

Closed zirain closed 7 months ago

zirain commented 8 months ago

start from v0.0.11, crd-ref-docs support markers, https://github.com/elastic/crd-ref-docs/pull/55 https://github.com/elastic/crd-ref-docs/pull/49

Right now, it only support markers from upstream https://github.com/elastic/crd-ref-docs/blob/15438a197f339a5b68be2e622725327c3e367811/processor/processor.go#L490

I just open this to see if anyone also interest in support custom marker:

I have a prototype here, it support hide unimplemented/deprecated filed from doc.

please kindly share your opinion.

tenstad commented 8 months ago

I support implementing custom markers! 😄

We use a custom marker (doc:Doc) to provide a short field description in a type's fields table (Foo), when the field's type (Bar) has a long description. In the docs, one can then read the short description when viewing the parent type (Foo), and click on the underlying type (Bar) to get all the details. The reasoning behind a custom marker instead a normal comment on the field is to propate the detailed description to the field when generating the CRD.

type Foo struct {
    //+doc:Doc=Short summary.
    Bar *Bar `json:"bar,omitempty"`
}

// Detailed description.
type Bar struct {}
thbkrkr commented 7 months ago

@tenstad > I support implementing custom markers!

Could you elaborate on how you do this?

tenstad commented 7 months ago

Could you elaborate on how you do this?

We hardcoded the implementation in a fork:

diff --git a/processor/processor.go b/processor/processor.go
index 631ba09..cb398a4 100644
--- a/processor/processor.go
+++ b/processor/processor.go
@@ -36,6 +36,7 @@ import (

 const (
        objectRootMarker = "kubebuilder:object:root"
+       docMarker        = "doc:Doc"
 )

 var ignoredCommentRegex = regexp.MustCompile(`\s*^(?i:\+|copyright)`)
@@ -486,6 +487,14 @@ func mkRegistry() (*markers.Registry, error) {
        if err != nil {
                return nil, err
        }
+       err = registry.Define(docMarker, markers.DescribesType, "")
+       if err != nil {
+               return nil, err
+       }
+       err = registry.Define(docMarker, markers.DescribesField, "")
+       if err != nil {
+               return nil, err
+       }

        for _, marker := range crdmarkers.AllDefinitions {
                err = registry.Register(marker.Definition)
@@ -497,7 +506,8 @@ func mkRegistry() (*markers.Registry, error) {
        return registry, nil
 }

-func parseMarkers(markers markers.MarkerValues) (string, []string) {
+func parseMarkers(markers markers.MarkerValues) (string, string, []string) {
+       doc := []string{}
        defaultValue := ""
        validation := []string{}

@@ -536,14 +546,30 @@ func parseMarkers(markers markers.MarkerValues) (string, []string) {
                }
        }

-       return defaultValue, validation
+       if value, exists := markers[docMarker]; exists {
+               for _, v := range value {
+                       doc = append(doc, v.(string))
+               }
+       }
+
+       return strings.Join(doc, " "), defaultValue, validation
 }

 func (p *processor) parseMarkers() {
        for _, t := range p.types {
-               t.Default, t.Validation = parseMarkers(t.Markers)
+               var doc string
+               doc, t.Default, t.Validation = parseMarkers(t.Markers)
+               if doc != "" {
+                       t.Doc = doc
+               }
                for _, f := range t.Fields {
-                       f.Default, f.Validation = parseMarkers(f.Markers)
+                       doc, f.Default, f.Validation = parseMarkers(f.Markers)
+                       if doc != "" {
+                               f.Doc = doc
+                       }
+                       if f.Doc == "" && f.Type != nil {
+                               f.Doc = f.Type.Doc
+                       }
                }
        }
 }