Skip to content

Commit

Permalink
docs: rework machine config documentation generation
Browse files Browse the repository at this point in the history
Generate a structured table of contents following the structure of the
config.

Make high-level examples follow the full structure of the config.

Document new multi-doc machine config.

Fixes siderolabs#8023

Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
  • Loading branch information
smira committed Dec 5, 2023
1 parent 4f195dd commit fb8b6b2
Show file tree
Hide file tree
Showing 5 changed files with 859 additions and 1,814 deletions.
40 changes: 39 additions & 1 deletion pkg/machinery/config/encoder/markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package encoder

import (
"bytes"
_ "embed"
"fmt"
"os"
"path/filepath"
Expand All @@ -16,7 +17,10 @@ import (
yaml "gopkg.in/yaml.v3"
)

var markdownTemplate = `
//go:embed "markdown.tmpl"
var markdownTemplate string

var oldMarkdownTemplate = `
{{ .Description }}
{{- $anchors := .Anchors -}}
{{- $tick := "` + "`" + `" -}}
Expand Down Expand Up @@ -60,6 +64,8 @@ type FileDoc struct {
Description string
// Structs structs defined in the file.
Structs []*Doc
// Types is map of all non-trivial types defined in the file.
Types map[string]*Doc
Anchors map[string]string

t *template.Template
Expand All @@ -74,11 +80,24 @@ func (fd *FileDoc) Encode() ([]byte, error) {

fd.Anchors = anchors

fd.Types = map[string]*Doc{}

for _, t := range fd.Structs {
if t.Type == "" || strings.ToLower(t.Type) == t.Type {
continue
}

fd.Types[t.Type] = t
}

fd.t = template.Must(template.New("file_markdown.tpl").
Funcs(template.FuncMap{
"yaml": encodeYaml,
"fmtDesc": formatDescription,
"encodeType": fd.encodeType,
"dict": tmplDict,
"repeat": strings.Repeat,
"add": func(a, b int) int { return a + b },
}).
Parse(markdownTemplate))

Expand Down Expand Up @@ -173,3 +192,22 @@ func formatDescription(description string) string {

return fmt.Sprintf("<details><summary>%s</summary>%s</details>", lines[0], strings.Join(lines[1:], "<br />"))
}

func tmplDict(vals ...any) (map[string]any, error) {
if len(vals)%2 != 0 {
return nil, fmt.Errorf("invalid number of arguments: %d", len(vals))
}

res := map[string]any{}

for i := 0; i < len(vals); i += 2 {
key, ok := vals[i].(string)
if !ok {
return nil, fmt.Errorf("invalid key type: %T", vals[i])
}

res[key] = vals[i+1]
}

return res, nil
}
37 changes: 37 additions & 0 deletions pkg/machinery/config/encoder/markdown.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{{ .Description }}
{{- $anchors := .Anchors -}}
{{- $struct := index .Structs 0 }}

{{ block "struct" dict "Struct" $struct "Level" 2 "Name" $struct.Type "Path" $struct.Type "Types" .Types }}
{{ repeat "#" .Level }} {{ .Name }} {#{{ .Path }}}

{{ if .Struct.Description -}}
{{ .Struct.Description }}
{{ end }}

{{ range $example := .Struct.Examples }}
{{ yaml $example.GetValue "" }}
{{ end }}

{{ if .Struct.Fields -}}
| Field | Type | Description | Value(s) |
|-------|------|-------------|----------|
{{ range $field := $.Struct.Fields -}}
{{ if $field.Name -}}
|`{{ $field.Name }}` |
{{- $type := index $.Types $field.Type }}{{ if $type }}<a href="#{{ $.Path }}.{{ $field.Name }}">{{ $field.Type }}</a>{{ else }}{{ $field.Type }}{{ end }} |
{{- fmtDesc $field.Description }} {{ with $field.Examples }}<details><summary>Show example(s)</summary>{{ range . }}{{ yaml .GetValue $field.Name }}{{ end }}</details>{{ end }} |
{{- range $value := $field.Values }}`{{ $value }}`<br />{{ end }} |
{{ end -}}
{{ end }}
{{ end }}


{{ range $field := .Struct.Fields }}
{{- $struct := index $.Types $field.Type -}}
{{- if $struct -}}
{{ template "struct" dict "Struct" $struct "Level" (add $.Level 1) "Name" $field.Name "Types" $.Types "Path" (printf "%s.%s" $.Path $field.Name) }}
{{- end -}}
{{ end }}

{{ end }}
2 changes: 0 additions & 2 deletions pkg/machinery/config/types/v1alpha1/v1alpha1_examples.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,10 @@ func mustParseURL(uri string) *url.URL {
func configExample() any {
return struct {
Version string `yaml:"version"`
Persist bool
Machine *yaml.Node
Cluster *yaml.Node
}{
Version: "v1alpha1",
Persist: true,
Machine: &yaml.Node{Kind: yaml.ScalarNode, LineComment: "..."},
Cluster: &yaml.Node{Kind: yaml.ScalarNode, LineComment: "..."},
}
Expand Down
5 changes: 5 additions & 0 deletions website/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ style = "solarized-dark"
# Uncomment if you want your chosen highlight style used for code blocks without a specified language
# guessSyntax = "true"

[markup.tableOfContents]
endLevel = 6
ordered = false
startLevel = 2

# Everything below this are Site Params

# Comment out if you don't want the "print entire section" link enabled.
Expand Down
Loading

0 comments on commit fb8b6b2

Please sign in to comment.