mirror of
https://github.com/TECHNOFAB11/docsonnet.git
synced 2026-02-01 23:25:12 +01:00
feat: ignore
Implements ignoring certain keys right in Jsonnet, by adding:
{
'#foo': "ignore",
foo: {}
}
This is especially useful for objects that include `self` references,
which might otherwise recurse infinitely
This commit is contained in:
parent
14e9fc8f3f
commit
66a158a8f2
7 changed files with 85 additions and 46 deletions
|
|
@ -12,6 +12,8 @@ local lib = {
|
||||||
local aux(old, key) =
|
local aux(old, key) =
|
||||||
if !std.isObject(pkg[key]) then
|
if !std.isObject(pkg[key]) then
|
||||||
old
|
old
|
||||||
|
else if std.objectHasAll(pkg, '#' + key) && pkg['#' + key] == 'ignore' then
|
||||||
|
old
|
||||||
else if std.startsWith(key, '#') then
|
else if std.startsWith(key, '#') then
|
||||||
old { [key]: pkg[key] }
|
old { [key]: pkg[key] }
|
||||||
else if self.scan(pkg[key]) then
|
else if self.scan(pkg[key]) then
|
||||||
|
|
@ -21,4 +23,5 @@ local lib = {
|
||||||
std.foldl(aux, std.objectFieldsAll(pkg), {}),
|
std.foldl(aux, std.objectFieldsAll(pkg), {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
lib.load(std.extVar('main'))
|
lib.load(std.extVar('main'))
|
||||||
|
|
|
||||||
49
main.go
49
main.go
|
|
@ -15,33 +15,52 @@ func main() {
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
|
|
||||||
root := &cli.Command{
|
root := &cli.Command{
|
||||||
Use: "docsonnet",
|
Use: "docsonnet <file>",
|
||||||
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",
|
||||||
|
Args: cli.ArgsExact(1),
|
||||||
}
|
}
|
||||||
|
|
||||||
dir := 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")
|
||||||
outputMd := root.Flags().Bool("md", true, "render as markdown files")
|
|
||||||
outputJSON := root.Flags().Bool("json", false, "print loaded docsonnet as JSON")
|
outputJSON := root.Flags().Bool("json", false, "print loaded docsonnet as JSON")
|
||||||
|
outputRaw := root.Flags().Bool("raw", false, "don't transform, dump raw eval result")
|
||||||
|
urlPrefix := root.Flags().String("urlPrefix", "/", "url-prefix for frontmatter")
|
||||||
|
|
||||||
root.Run = func(cmd *cli.Command, args []string) error {
|
root.Run = func(cmd *cli.Command, args []string) error {
|
||||||
file := args[0]
|
file := args[0]
|
||||||
|
|
||||||
switch {
|
log.Println("Extracting from Jsonnet")
|
||||||
case *outputJSON:
|
data, err := docsonnet.Extract(file)
|
||||||
model, err := docsonnet.Load(file)
|
if err != nil {
|
||||||
if err != nil {
|
log.Fatalln("Extracting:", err)
|
||||||
return err
|
}
|
||||||
}
|
if *outputRaw {
|
||||||
data, err := json.MarshalIndent(model, "", " ")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(string(data))
|
fmt.Println(string(data))
|
||||||
case *outputMd:
|
return nil
|
||||||
return render.To(file, *dir)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Println("Transforming to docsonnet model")
|
||||||
|
pkg, err := docsonnet.Transform(data)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Transforming:", err)
|
||||||
|
}
|
||||||
|
if *outputJSON {
|
||||||
|
data, err := json.MarshalIndent(pkg, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println(string(data))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Rendering markdown")
|
||||||
|
n, err := render.To(*pkg, *dir, render.Opts{
|
||||||
|
URLPrefix: *urlPrefix,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Rendering:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Success! Rendered %v packages from '%s' to '%s'", n, file, *dir)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import (
|
||||||
// Data assumptions:
|
// Data assumptions:
|
||||||
// - 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 {
|
||||||
pkg := d.Package()
|
pkg := d.Package()
|
||||||
|
|
||||||
pkg.API = make(Fields)
|
pkg.API = make(Fields)
|
||||||
|
|
@ -34,7 +34,7 @@ func fastLoad(d DS) Package {
|
||||||
// non-docsonnet
|
// non-docsonnet
|
||||||
// subpackage?
|
// subpackage?
|
||||||
if _, ok := f["#"]; ok {
|
if _, ok := f["#"]; ok {
|
||||||
p := fastLoad(DS(f))
|
p := fastLoad(ds(f))
|
||||||
pkg.Sub[p.Name] = p
|
pkg.Sub[p.Name] = p
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +94,7 @@ func loadField(name string, field map[string]interface{}, parent map[string]inte
|
||||||
return loadObj(name, iobj.(map[string]interface{}), parent)
|
return loadObj(name, iobj.(map[string]interface{}), parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
panic("field lacking {function | object}")
|
panic(fmt.Sprintf("field %s lacking {function | object}", name))
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadFn(name string, msi map[string]interface{}) Field {
|
func loadFn(name string, msi map[string]interface{}) Field {
|
||||||
|
|
@ -161,9 +161,9 @@ func loadObj(name string, msi map[string]interface{}, parent map[string]interfac
|
||||||
return Field{Object: &obj}
|
return Field{Object: &obj}
|
||||||
}
|
}
|
||||||
|
|
||||||
type DS map[string]interface{}
|
type ds map[string]interface{}
|
||||||
|
|
||||||
func (d DS) Package() Package {
|
func (d ds) Package() Package {
|
||||||
hash, ok := d["#"]
|
hash, ok := d["#"]
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Fatalln("Package declaration missing")
|
log.Fatalln("Package declaration missing")
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,22 @@ import (
|
||||||
"github.com/markbates/pkger"
|
"github.com/markbates/pkger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Load extracts docsonnet data from the given Jsonnet document
|
// Load extracts and transforms the docsonnet data in `filename`, returning the
|
||||||
|
// top level docsonnet package.
|
||||||
func Load(filename string) (*Package, error) {
|
func Load(filename string) (*Package, error) {
|
||||||
|
data, err := Extract(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Transform([]byte(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract parses the Jsonnet file at `filename`, extracting all docsonnet related
|
||||||
|
// information, exactly as they appear in Jsonnet. Keep in mind this
|
||||||
|
// representation is usually not suitable for any use, use `Transform` to
|
||||||
|
// convert it to the familiar docsonnet data model.
|
||||||
|
func Extract(filename string) ([]byte, error) {
|
||||||
// get load.libsonnet from embedded data
|
// get load.libsonnet from embedded data
|
||||||
file, err := pkger.Open("/load.libsonnet")
|
file, err := pkger.Open("/load.libsonnet")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -33,15 +47,18 @@ 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")
|
|
||||||
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("Transforming result")
|
return []byte(data), nil
|
||||||
// parse the result
|
}
|
||||||
var d DS
|
|
||||||
|
// Transform converts the raw result of `Extract` to the actual docsonnet object
|
||||||
|
// model `*docsonnet.Package`.
|
||||||
|
func Transform(data []byte) (*Package, error) {
|
||||||
|
var d ds
|
||||||
if err := json.Unmarshal([]byte(data), &d); err != nil {
|
if err := json.Unmarshal([]byte(data), &d); err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,31 +2,26 @@ package render
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/sh0rez/docsonnet/pkg/docsonnet"
|
"github.com/sh0rez/docsonnet/pkg/docsonnet"
|
||||||
)
|
)
|
||||||
|
|
||||||
func To(api, out string) error {
|
func To(pkg docsonnet.Package, dir string, opts Opts) (int, error) {
|
||||||
pkg, err := docsonnet.Load(api)
|
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||||
if err != nil {
|
return 0, err
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(out, os.ModePerm); err != nil {
|
data := Render(pkg, opts)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println("Rendering .md files")
|
n := 0
|
||||||
data := Render(*pkg)
|
|
||||||
for k, v := range data {
|
for k, v := range data {
|
||||||
if err := ioutil.WriteFile(filepath.Join(out, k), []byte(v), 0644); err != nil {
|
if err := ioutil.WriteFile(filepath.Join(dir, k), []byte(v), 0644); err != nil {
|
||||||
return err
|
return n, err
|
||||||
}
|
}
|
||||||
|
n++
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Success! Rendered %v packages from '%s' to '%s'", len(data), api, out)
|
return n, nil
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package render
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -10,14 +11,18 @@ import (
|
||||||
"github.com/sh0rez/docsonnet/pkg/slug"
|
"github.com/sh0rez/docsonnet/pkg/slug"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Render(pkg docsonnet.Package) map[string]string {
|
type Opts struct {
|
||||||
return render(pkg, nil, true)
|
URLPrefix string
|
||||||
}
|
}
|
||||||
|
|
||||||
func render(pkg docsonnet.Package, parents []string, root bool) map[string]string {
|
func Render(pkg docsonnet.Package, opts Opts) map[string]string {
|
||||||
link := "/" + strings.Join(append(parents, pkg.Name), "/")
|
return render(pkg, nil, true, opts.URLPrefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
func render(pkg docsonnet.Package, parents []string, root bool, urlPrefix string) map[string]string {
|
||||||
|
link := path.Join("/", urlPrefix, strings.Join(append(parents, pkg.Name), "/"))
|
||||||
if root {
|
if root {
|
||||||
link = "/"
|
link = path.Join("/", urlPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
// head
|
// head
|
||||||
|
|
@ -83,7 +88,7 @@ func render(pkg docsonnet.Package, parents []string, root bool) map[string]strin
|
||||||
if root {
|
if root {
|
||||||
path = parents
|
path = parents
|
||||||
}
|
}
|
||||||
got := render(s, path, false)
|
got := render(s, path, false, urlPrefix)
|
||||||
for k, v := range got {
|
for k, v := range got {
|
||||||
out[k] = v
|
out[k] = v
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
pkged.go
2
pkged.go
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue