mirror of
https://github.com/TECHNOFAB11/docsonnet.git
synced 2025-12-12 06:20:12 +01:00
Docsonnet packages previously used to be declared in a `main.docsonnet`. Because this file basically always contains the same, it is kinda redundant. To avoid that, the information from there has been inlined into the main Jsonnet file, while the parser logic will become part of the Go application, as embedded Jsonnet.
165 lines
2.9 KiB
Go
165 lines
2.9 KiB
Go
package main
|
||
|
||
import (
|
||
"bytes"
|
||
"fmt"
|
||
"os"
|
||
"strings"
|
||
"text/template"
|
||
|
||
"github.com/Masterminds/sprig/v3"
|
||
)
|
||
|
||
var indexTmpl = strings.Replace(`
|
||
# package {{.Name}}
|
||
´´´jsonnet
|
||
local {{.Name}} = import "{{.Import}}"
|
||
´´´
|
||
|
||
{{.Help}}
|
||
|
||
## Index
|
||
|
||
{{ range .Index }}{{ $l := mul .Level 2}}{{repeat (int $l) " "}}* ´{{ .Line }}´
|
||
{{ end }}
|
||
|
||
{{ range .Fields }} {{.Render}}
|
||
{{ end }}
|
||
|
||
`, "´", "`", -1)
|
||
|
||
type Renderable interface {
|
||
Render() string
|
||
}
|
||
|
||
var objTmpl = strings.Replace(`
|
||
## {{ .Name }}
|
||
{{ .Help }}
|
||
`, "´", "`", -1)
|
||
|
||
type obj struct {
|
||
Object
|
||
}
|
||
|
||
func (o obj) Render() string {
|
||
t := template.Must(template.New("").Parse(objTmpl))
|
||
var buf bytes.Buffer
|
||
if err := t.Execute(&buf, o); err != nil {
|
||
panic(err)
|
||
}
|
||
return buf.String()
|
||
}
|
||
|
||
type fn struct {
|
||
Function
|
||
}
|
||
|
||
func (f fn) Params() string {
|
||
args := make([]string, 0, len(f.Args))
|
||
for _, a := range f.Args {
|
||
arg := a.Name
|
||
if a.Default != nil {
|
||
arg = fmt.Sprint("%s=%v", arg, a.Default)
|
||
}
|
||
args = append(args, arg)
|
||
}
|
||
|
||
return strings.Join(args, ", ")
|
||
}
|
||
|
||
func (f fn) Signature() string {
|
||
return fmt.Sprintf("%s(%s)", f.Name, f.Params())
|
||
}
|
||
|
||
var fnTmpl = strings.Replace(`
|
||
### fn {{ .Name }}
|
||
´´´
|
||
{{ .Signature }}
|
||
´´´
|
||
{{ .Help }}
|
||
`, "´", "`", -1)
|
||
|
||
func (f fn) Render() string {
|
||
t := template.Must(template.New("").Parse(fnTmpl))
|
||
var buf bytes.Buffer
|
||
if err := t.Execute(&buf, f); err != nil {
|
||
panic(err)
|
||
}
|
||
return buf.String()
|
||
}
|
||
|
||
func render(d Doc) (string, error) {
|
||
tmpl := template.Must(template.New("").Funcs(sprig.TxtFuncMap()).Parse(indexTmpl))
|
||
if err := tmpl.Execute(os.Stdout, &doc{
|
||
Name: d.Name,
|
||
Import: d.Import,
|
||
Help: d.Help,
|
||
Index: buildIndex(d.API, 0),
|
||
Fields: renderables(d.API, ""),
|
||
}); err != nil {
|
||
return "", err
|
||
}
|
||
|
||
return "", nil
|
||
}
|
||
|
||
type doc struct {
|
||
Name string
|
||
Import string
|
||
Help string
|
||
|
||
Index []indexElem
|
||
Fields []Renderable
|
||
}
|
||
|
||
type indexElem struct {
|
||
Line string
|
||
Level int
|
||
}
|
||
|
||
func renderables(fields map[string]Field, prefix string) []Renderable {
|
||
rs := []Renderable{}
|
||
for _, f := range fields {
|
||
switch {
|
||
case f.Function != nil:
|
||
fnc := fn{*f.Function}
|
||
fnc.Name = strings.TrimPrefix(prefix+"."+fnc.Name, ".")
|
||
rs = append(rs, fnc)
|
||
case f.Object != nil:
|
||
o := obj{*f.Object}
|
||
o.Name = strings.TrimPrefix(prefix+"."+o.Name, ".")
|
||
rs = append(rs, o)
|
||
|
||
childs := renderables(o.Fields, o.Name)
|
||
rs = append(rs, childs...)
|
||
}
|
||
}
|
||
return rs
|
||
}
|
||
|
||
func buildIndex(fields map[string]Field, level int) []indexElem {
|
||
elems := []indexElem{}
|
||
for _, f := range fields {
|
||
line := indexLine(f)
|
||
elems = append(elems, indexElem{
|
||
Line: line,
|
||
Level: level,
|
||
})
|
||
|
||
if f.Object != nil {
|
||
childs := buildIndex(f.Object.Fields, level+1)
|
||
elems = append(elems, childs...)
|
||
}
|
||
}
|
||
return elems
|
||
}
|
||
|
||
func indexLine(f Field) string {
|
||
switch {
|
||
case f.Function != nil:
|
||
return "fn " + fn{*f.Function}.Signature()
|
||
case f.Object != nil:
|
||
return fmt.Sprintf("obj %s", f.Object.Name)
|
||
}
|
||
panic("wtf")
|
||
}
|