package main import ( "encoding/json" "log" "os" "strings" "text/template" "unicode" ) var schemaFile = "./schema/cv.schema.json" var schemaReferenceTemplate = `= JSON schema reference NOTE: This page was auto-generated with spruce-docgen. == {{ .Title }} {{ .Description }} [%header,cols=3*] |=== |Field |Type |Description {{- range $key, $property := .Properties }} {{ print "" }} |{{ $key }} |{{ type $property }} |{{ $property.Description }} {{- end -}}{{ print "" }} |=== {{ print "" }} {{- range $i, $schema := .Defs }} === {{ capitalise $i }} {{ print "" }} [%header,cols=3*] |=== |Field |Type |Description {{- range $key, $property := $schema.Properties }} {{ print "" }} |{{ $key }} |{{ type $property }} |{{ $property.Description }} {{- end -}}{{ print "" }} |=== {{ print "" }} {{- end }} ` // Schema minimally represents the JSON schema format type Schema struct { Title string `json:"title"` Description string `json:"description"` Type string `json:"type"` Properties map[string]*Schema `json:"properties"` Items *Schema `json:"items"` Required []string `json:"required"` Ref string `json:"$ref"` Defs map[string]*Schema `json:"$defs"` AdditionalProperties any `json:"additionalProperties"` } func main() { file, err := os.Open(schemaFile) if err != nil { log.Fatal(err) } defer file.Close() decoder := json.NewDecoder(file) var schema Schema if err := decoder.Decode(&schema); err != nil { log.Fatal(err) } funcMap := template.FuncMap{ "capitalise": capitalise, "type": getType, } t := template.Must(template.New("asciidoc").Funcs(funcMap).Parse(schemaReferenceTemplate)) if err = t.Execute(os.Stdout, schema); err != nil { log.Fatal(err) } } func capitalise(str string) string { runes := []rune(str) runes[0] = unicode.ToUpper(runes[0]) return string(runes) } func getType(s Schema) string { if s.Type != "" && s.Type != "array" { return s.Type } if s.Type == "array" { if s.Items == nil { return "list(UNKNOWN)" } if s.Items.Type != "" { return "list(" + s.Items.Type + ")" } if s.Items.Ref != "" { return "list(<<" + capitalise(refType(s.Items.Ref)) + ">>)" } } if s.Type == "" && s.Ref != "" { return "<<" + capitalise(refType(s.Ref)) + ">>" } return "UNKNOWN" } func refType(str string) string { split := strings.Split(str, "/") return split[len(split)-1] }