mirror of
https://github.com/TECHNOFAB11/docsonnet.git
synced 2025-12-14 07:13:55 +01:00
refactor(render): filewriting in render pkg
This commit is contained in:
parent
f284bff4e5
commit
14e9fc8f3f
7 changed files with 68 additions and 285 deletions
234
fast/main.go
234
fast/main.go
|
|
@ -1,234 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/go-jsonnet"
|
|
||||||
"github.com/sh0rez/docsonnet/pkg/docsonnet"
|
|
||||||
"github.com/sh0rez/docsonnet/pkg/render"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
data, err := eval()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
// fmt.Println(string(data))
|
|
||||||
|
|
||||||
var d DS
|
|
||||||
if err := json.Unmarshal(data, &d); err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pkg := load(d)
|
|
||||||
|
|
||||||
fmt.Println("render")
|
|
||||||
res := render.Render(pkg)
|
|
||||||
for k, v := range res {
|
|
||||||
fmt.Println(k)
|
|
||||||
if err := ioutil.WriteFile(filepath.Join("docs", k), []byte(v), 0644); err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// load docsonnet
|
|
||||||
//
|
|
||||||
// Data assumptions:
|
|
||||||
// - only map[string]interface{} and docsonnet fields
|
|
||||||
// - docsonnet fields (#...) coming first
|
|
||||||
func load(d DS) docsonnet.Package {
|
|
||||||
start := time.Now()
|
|
||||||
|
|
||||||
pkg := d.Package()
|
|
||||||
fmt.Println("load", pkg.Name)
|
|
||||||
|
|
||||||
pkg.API = make(docsonnet.Fields)
|
|
||||||
pkg.Sub = make(map[string]docsonnet.Package)
|
|
||||||
|
|
||||||
for k, v := range d {
|
|
||||||
if k == "#" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
f := v.(map[string]interface{})
|
|
||||||
|
|
||||||
// docsonnet field
|
|
||||||
name := strings.TrimPrefix(k, "#")
|
|
||||||
if strings.HasPrefix(k, "#") {
|
|
||||||
pkg.API[name] = loadField(name, f, d)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// non-docsonnet
|
|
||||||
// subpackage?
|
|
||||||
if _, ok := f["#"]; ok {
|
|
||||||
p := load(DS(f))
|
|
||||||
pkg.Sub[p.Name] = p
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// non-annotated nested?
|
|
||||||
// try to load, but skip when already loaded as annotated above
|
|
||||||
if nested, ok := loadNested(name, f); ok && !fieldsHas(pkg.API, name) {
|
|
||||||
pkg.API[name] = *nested
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("done load", pkg.Name, time.Since(start))
|
|
||||||
return pkg
|
|
||||||
}
|
|
||||||
|
|
||||||
func fieldsHas(f docsonnet.Fields, key string) bool {
|
|
||||||
_, b := f[key]
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadNested(name string, msi map[string]interface{}) (*docsonnet.Field, bool) {
|
|
||||||
out := docsonnet.Object{
|
|
||||||
Name: name,
|
|
||||||
Fields: make(docsonnet.Fields),
|
|
||||||
}
|
|
||||||
|
|
||||||
ok := false
|
|
||||||
for k, v := range msi {
|
|
||||||
f := v.(map[string]interface{})
|
|
||||||
n := strings.TrimPrefix(k, "#")
|
|
||||||
|
|
||||||
if !strings.HasPrefix(k, "#") {
|
|
||||||
if l, ok := loadNested(k, f); ok {
|
|
||||||
out.Fields[n] = *l
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = true
|
|
||||||
l := loadField(n, f, msi)
|
|
||||||
out.Fields[n] = l
|
|
||||||
}
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
return &docsonnet.Field{Object: &out}, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadField(name string, field map[string]interface{}, parent map[string]interface{}) docsonnet.Field {
|
|
||||||
if ifn, ok := field["function"]; ok {
|
|
||||||
return loadFn(name, ifn.(map[string]interface{}))
|
|
||||||
}
|
|
||||||
|
|
||||||
if iobj, ok := field["object"]; ok {
|
|
||||||
return loadObj(name, iobj.(map[string]interface{}), parent)
|
|
||||||
}
|
|
||||||
|
|
||||||
panic("docsonnet field lacking {function | object}")
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadFn(name string, msi map[string]interface{}) docsonnet.Field {
|
|
||||||
fn := docsonnet.Function{
|
|
||||||
Name: name,
|
|
||||||
Help: msi["help"].(string),
|
|
||||||
}
|
|
||||||
if args, ok := msi["args"]; ok {
|
|
||||||
fn.Args = loadArgs(args.([]interface{}))
|
|
||||||
}
|
|
||||||
return docsonnet.Field{Function: &fn}
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadArgs(is []interface{}) []docsonnet.Argument {
|
|
||||||
args := make([]docsonnet.Argument, len(is))
|
|
||||||
for i := range is {
|
|
||||||
arg := is[i].(map[string]interface{})
|
|
||||||
args[i] = docsonnet.Argument{
|
|
||||||
Name: arg["name"].(string),
|
|
||||||
Type: docsonnet.Type(arg["type"].(string)),
|
|
||||||
Default: arg["default"],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return args
|
|
||||||
}
|
|
||||||
|
|
||||||
func fieldNames(msi map[string]interface{}) []string {
|
|
||||||
out := make([]string, 0, len(msi))
|
|
||||||
for k := range msi {
|
|
||||||
out = append(out, k)
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadObj(name string, msi map[string]interface{}, parent map[string]interface{}) docsonnet.Field {
|
|
||||||
obj := docsonnet.Object{
|
|
||||||
Name: name,
|
|
||||||
Help: msi["help"].(string),
|
|
||||||
Fields: make(docsonnet.Fields),
|
|
||||||
}
|
|
||||||
|
|
||||||
// look for children in same key without #
|
|
||||||
var iChilds interface{}
|
|
||||||
var ok bool
|
|
||||||
if iChilds, ok = parent[name]; !ok {
|
|
||||||
fmt.Println("aborting, no", name, strings.Join(fieldNames(parent), ", "))
|
|
||||||
return docsonnet.Field{Object: &obj}
|
|
||||||
}
|
|
||||||
|
|
||||||
childs := iChilds.(map[string]interface{})
|
|
||||||
for k, v := range childs {
|
|
||||||
name := strings.TrimPrefix(k, "#")
|
|
||||||
f := v.(map[string]interface{})
|
|
||||||
if !strings.HasPrefix(k, "#") {
|
|
||||||
if l, ok := loadNested(k, f); ok {
|
|
||||||
obj.Fields[name] = *l
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
obj.Fields[name] = loadField(name, f, childs)
|
|
||||||
}
|
|
||||||
|
|
||||||
return docsonnet.Field{Object: &obj}
|
|
||||||
}
|
|
||||||
|
|
||||||
type DS map[string]interface{}
|
|
||||||
|
|
||||||
func (d DS) Package() docsonnet.Package {
|
|
||||||
hash, ok := d["#"]
|
|
||||||
if !ok {
|
|
||||||
log.Fatalln("Package declaration missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
pkg := hash.(map[string]interface{})
|
|
||||||
return docsonnet.Package{
|
|
||||||
Help: pkg["help"].(string),
|
|
||||||
Name: pkg["name"].(string),
|
|
||||||
Import: pkg["import"].(string),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func eval() ([]byte, error) {
|
|
||||||
fmt.Println("eval start")
|
|
||||||
start := time.Now()
|
|
||||||
|
|
||||||
vm := jsonnet.MakeVM()
|
|
||||||
vm.Importer(&jsonnet.FileImporter{JPaths: []string{".."}})
|
|
||||||
data, err := ioutil.ReadFile("fast.libsonnet")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := vm.EvaluateSnippet("fast.libsonnet", string(data))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("eval:", time.Since(start))
|
|
||||||
return []byte(out), nil
|
|
||||||
}
|
|
||||||
31
main.go
31
main.go
|
|
@ -1,10 +1,9 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/go-clix/cli"
|
"github.com/go-clix/cli"
|
||||||
|
|
||||||
|
|
@ -20,19 +19,27 @@ func main() {
|
||||||
Short: "Utility to parse and transform Jsonnet code that uses the docsonnet extension",
|
Short: "Utility to parse and transform Jsonnet code that uses the docsonnet extension",
|
||||||
}
|
}
|
||||||
|
|
||||||
output := root.Flags().StringP("output", "o", "docs", "directory to write the .md files to")
|
dir := root.Flags().StringP("output", "o", "docs", "directory to write the .md files to")
|
||||||
root.Run = func(cmd *cli.Command, args []string) error {
|
outputMd := root.Flags().Bool("md", true, "render as markdown files")
|
||||||
pkg, err := docsonnet.Load(args[0])
|
outputJSON := root.Flags().Bool("json", false, "print loaded docsonnet as JSON")
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
data := render.Render(*pkg)
|
root.Run = func(cmd *cli.Command, args []string) error {
|
||||||
for k, v := range data {
|
file := args[0]
|
||||||
fmt.Println(k)
|
|
||||||
if err := ioutil.WriteFile(filepath.Join(*output, k), []byte(v), 0644); err != nil {
|
switch {
|
||||||
|
case *outputJSON:
|
||||||
|
model, err := docsonnet.Load(file)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
data, err := json.MarshalIndent(model, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(string(data))
|
||||||
|
case *outputMd:
|
||||||
|
return render.To(file, *dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// load docsonnet
|
// load docsonnet
|
||||||
|
|
@ -13,10 +12,7 @@ import (
|
||||||
// - only map[string]interface{} and fields
|
// - only map[string]interface{} and fields
|
||||||
// - fields (#...) coming first
|
// - fields (#...) coming first
|
||||||
func fastLoad(d DS) Package {
|
func fastLoad(d DS) Package {
|
||||||
start := time.Now()
|
|
||||||
|
|
||||||
pkg := d.Package()
|
pkg := d.Package()
|
||||||
fmt.Println("load", pkg.Name)
|
|
||||||
|
|
||||||
pkg.API = make(Fields)
|
pkg.API = make(Fields)
|
||||||
pkg.Sub = make(map[string]Package)
|
pkg.Sub = make(map[string]Package)
|
||||||
|
|
@ -51,7 +47,6 @@ func fastLoad(d DS) Package {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("done load", pkg.Name, time.Since(start))
|
|
||||||
return pkg
|
return pkg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,13 @@ func Load(filename string) (*Package, error) {
|
||||||
// invoke load.libsonnet
|
// invoke load.libsonnet
|
||||||
vm.ExtCode("main", fmt.Sprintf(`(import "%s")`, filename))
|
vm.ExtCode("main", fmt.Sprintf(`(import "%s")`, filename))
|
||||||
|
|
||||||
log.Println("evaluating Jsonnet")
|
log.Println("Evaluating Jsonnet")
|
||||||
data, err := vm.EvaluateSnippet("load.libsonnet", string(load))
|
data, err := vm.EvaluateSnippet("load.libsonnet", string(load))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("parsing result")
|
log.Println("Transforming result")
|
||||||
// parse the result
|
// parse the result
|
||||||
var d DS
|
var d DS
|
||||||
if err := json.Unmarshal([]byte(data), &d); err != nil {
|
if err := json.Unmarshal([]byte(data), &d); err != nil {
|
||||||
|
|
|
||||||
32
pkg/render/fs.go
Normal file
32
pkg/render/fs.go
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
package render
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/sh0rez/docsonnet/pkg/docsonnet"
|
||||||
|
)
|
||||||
|
|
||||||
|
func To(api, out string) error {
|
||||||
|
pkg, err := docsonnet.Load(api)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.MkdirAll(out, os.ModePerm); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Rendering .md files")
|
||||||
|
data := Render(*pkg)
|
||||||
|
for k, v := range data {
|
||||||
|
if err := ioutil.WriteFile(filepath.Join(out, k), []byte(v), 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Success! Rendered %v packages from '%s' to '%s'", len(data), api, out)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
package render
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/sh0rez/docsonnet/pkg/docsonnet"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Paths(pkg docsonnet.Package) map[string]docsonnet.Package {
|
|
||||||
p := paths(pkg)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func paths(pkg docsonnet.Package) map[string]docsonnet.Package {
|
|
||||||
pkgs := make(map[string]docsonnet.Package)
|
|
||||||
pkgs[pkg.Name+".md"] = pkg
|
|
||||||
|
|
||||||
if len(pkg.Sub) == 0 {
|
|
||||||
return pkgs
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, sub := range pkg.Sub {
|
|
||||||
for k, v := range paths(sub) {
|
|
||||||
v.Name = pkg.Name + "/" + k
|
|
||||||
pkgs[pkg.Name+"-"+k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkgs
|
|
||||||
}
|
|
||||||
|
|
@ -15,7 +15,6 @@ func Render(pkg docsonnet.Package) map[string]string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func render(pkg docsonnet.Package, parents []string, root bool) map[string]string {
|
func render(pkg docsonnet.Package, parents []string, root bool) map[string]string {
|
||||||
fmt.Println("render", pkg.Name)
|
|
||||||
link := "/" + strings.Join(append(parents, pkg.Name), "/")
|
link := "/" + strings.Join(append(parents, pkg.Name), "/")
|
||||||
if root {
|
if root {
|
||||||
link = "/"
|
link = "/"
|
||||||
|
|
@ -27,20 +26,32 @@ func render(pkg docsonnet.Package, parents []string, root bool) map[string]strin
|
||||||
"permalink": link,
|
"permalink": link,
|
||||||
}),
|
}),
|
||||||
md.Headline(1, "package "+pkg.Name),
|
md.Headline(1, "package "+pkg.Name),
|
||||||
md.CodeBlock("jsonnet", fmt.Sprintf(`local %s = import "%s"`, pkg.Name, pkg.Import)),
|
|
||||||
md.Text(pkg.Help),
|
|
||||||
}
|
}
|
||||||
|
if pkg.Import != "" {
|
||||||
|
elems = append(elems, md.CodeBlock("jsonnet", fmt.Sprintf(`local %s = import "%s"`, pkg.Name, pkg.Import)))
|
||||||
|
}
|
||||||
|
elems = append(elems, md.Text(pkg.Help))
|
||||||
|
|
||||||
if len(pkg.Sub) > 0 {
|
if len(pkg.Sub) > 0 {
|
||||||
elems = append(elems, md.Headline(2, "Subpackages"))
|
elems = append(elems, md.Headline(2, "Subpackages"))
|
||||||
var items []md.Elem
|
|
||||||
|
keys := make([]string, 0, len(pkg.Sub))
|
||||||
for _, s := range pkg.Sub {
|
for _, s := range pkg.Sub {
|
||||||
|
keys = append(keys, s.Name)
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
var items []md.Elem
|
||||||
|
for _, k := range keys {
|
||||||
|
s := pkg.Sub[k]
|
||||||
|
|
||||||
link := strings.Join(append(parents, pkg.Name, s.Name), "-")
|
link := strings.Join(append(parents, pkg.Name, s.Name), "-")
|
||||||
if root {
|
if root {
|
||||||
link = strings.Join(append(parents, s.Name), "-")
|
link = strings.Join(append(parents, s.Name), "-")
|
||||||
}
|
}
|
||||||
items = append(items, md.Link(md.Text(s.Name), link+".md"))
|
items = append(items, md.Link(md.Text(s.Name), link+".md"))
|
||||||
}
|
}
|
||||||
|
|
||||||
elems = append(elems, md.List(items...))
|
elems = append(elems, md.List(items...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue