github.com/Jeffail/benthos/v3@v3.65.0/internal/docs/field_template.go (about)

     1  package docs
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/Jeffail/benthos/v3/lib/util/config"
     7  	"github.com/Jeffail/gabs/v2"
     8  )
     9  
    10  // FieldSpecCtx provides a field spec and rendered extras for documentation
    11  // templates to use.
    12  type FieldSpecCtx struct {
    13  	Spec FieldSpec
    14  
    15  	// FullName describes the full dot path name of the field relative to
    16  	// the root of the documented component.
    17  	FullName string
    18  
    19  	// ExamplesMarshalled is a list of examples marshalled into YAML format.
    20  	ExamplesMarshalled []string
    21  
    22  	// DefaultMarshalled is a marshalled string of the default value, if there is one.
    23  	DefaultMarshalled string
    24  }
    25  
    26  // FieldsTemplate returns a Go template for rendering markdown field
    27  // documentation. The context should have a field `.Fields` of the type
    28  // `[]FieldSpecCtx`.
    29  func FieldsTemplate(lintableExamples bool) string {
    30  	exampleHint := "yml"
    31  	if lintableExamples {
    32  		exampleHint = "yaml"
    33  	}
    34  	return `{{define "field_docs" -}}
    35  {{range $i, $field := .Fields -}}
    36  ### ` + "`{{$field.FullName}}`" + `
    37  
    38  {{$field.Spec.Description}}
    39  {{if $field.Spec.Interpolated -}}
    40  This field supports [interpolation functions](/docs/configuration/interpolation#bloblang-queries).
    41  {{end}}
    42  
    43  Type: {{if eq $field.Spec.Kind "array"}}list of {{end}}{{if eq $field.Spec.Kind "map"}}map of {{end}}` + "`{{$field.Spec.Type}}`" + `  
    44  {{if gt (len $field.DefaultMarshalled) 0}}Default: ` + "`{{$field.DefaultMarshalled}}`" + `  
    45  {{end -}}
    46  {{if gt (len $field.Spec.Version) 0}}Requires version {{$field.Spec.Version}} or newer  
    47  {{end -}}
    48  {{if gt (len $field.Spec.AnnotatedOptions) 0}}
    49  | Option | Summary |
    50  |---|---|
    51  {{range $j, $option := $field.Spec.AnnotatedOptions -}}` + "| `" + `{{index $option 0}}` + "` |" + ` {{index $option 1}} |
    52  {{end}}
    53  {{else if gt (len $field.Spec.Options) 0}}Options: {{range $j, $option := $field.Spec.Options -}}
    54  {{if ne $j 0}}, {{end}}` + "`" + `{{$option}}` + "`" + `{{end}}.
    55  {{end}}
    56  {{if gt (len $field.Spec.Examples) 0 -}}
    57  ` + "```" + exampleHint + `
    58  # Examples
    59  
    60  {{range $j, $example := $field.ExamplesMarshalled -}}
    61  {{if ne $j 0}}
    62  {{end}}{{$example}}{{end -}}
    63  ` + "```" + `
    64  
    65  {{end -}}
    66  {{end -}}
    67  {{end -}}`
    68  }
    69  
    70  // FlattenChildrenForDocs converts the children of a field into a flat list,
    71  // where the names contain hints as to their position in a structured hierarchy.
    72  // This makes it easier to list the fields in documentation.
    73  func (f FieldSpec) FlattenChildrenForDocs() []FieldSpecCtx {
    74  	flattenedFields := []FieldSpecCtx{}
    75  	var walkFields func(path string, f FieldSpecs)
    76  	walkFields = func(path string, f FieldSpecs) {
    77  		for _, v := range f {
    78  			if v.IsDeprecated {
    79  				continue
    80  			}
    81  			newV := FieldSpecCtx{
    82  				Spec: v,
    83  			}
    84  			newV.FullName = newV.Spec.Name
    85  			if len(path) > 0 {
    86  				newV.FullName = path + newV.Spec.Name
    87  			}
    88  			if len(v.Examples) > 0 {
    89  				newV.ExamplesMarshalled = make([]string, len(v.Examples))
    90  				for i, e := range v.Examples {
    91  					exampleBytes, err := config.MarshalYAML(map[string]interface{}{
    92  						v.Name: e,
    93  					})
    94  					if err == nil {
    95  						newV.ExamplesMarshalled[i] = string(exampleBytes)
    96  					}
    97  				}
    98  			}
    99  			if v.Default != nil {
   100  				newV.DefaultMarshalled = gabs.Wrap(*v.Default).String()
   101  			}
   102  			newV.Spec.Description = strings.TrimSpace(v.Description)
   103  			if newV.Spec.Description == "" {
   104  				newV.Spec.Description = "Sorry! This field is missing documentation."
   105  			}
   106  
   107  			flattenedFields = append(flattenedFields, newV)
   108  			if len(v.Children) > 0 {
   109  				newPath := path + v.Name
   110  				switch newV.Spec.Kind {
   111  				case KindArray:
   112  					newPath += "[]"
   113  				case Kind2DArray:
   114  					newPath += "[][]"
   115  				case KindMap:
   116  					newPath += ".<name>"
   117  				}
   118  				walkFields(newPath+".", v.Children)
   119  			}
   120  		}
   121  	}
   122  	rootPath := ""
   123  	switch f.Kind {
   124  	case KindArray:
   125  		rootPath = "[]."
   126  	case KindMap:
   127  		rootPath = "<name>."
   128  	}
   129  	walkFields(rootPath, f.Children)
   130  	return flattenedFields
   131  }