mirror of
https://github.com/TECHNOFAB11/docsonnet.git
synced 2025-12-12 06:20:12 +01:00
feat: jsonnet interface
This commit is contained in:
parent
5977373772
commit
a63ddd1061
5 changed files with 166 additions and 83 deletions
|
|
@ -1,75 +0,0 @@
|
||||||
local d = {
|
|
||||||
new(name, url): {
|
|
||||||
name: name,
|
|
||||||
'import': url,
|
|
||||||
},
|
|
||||||
withAPI(obj): {
|
|
||||||
api: obj.object,
|
|
||||||
},
|
|
||||||
withHelp(help): {
|
|
||||||
help: help,
|
|
||||||
},
|
|
||||||
|
|
||||||
obj: {
|
|
||||||
// obj creates an object, optionally with fields
|
|
||||||
new(help='', fields={}): { object: {
|
|
||||||
help: help,
|
|
||||||
fields: fields,
|
|
||||||
} },
|
|
||||||
},
|
|
||||||
Obj: self.obj.new,
|
|
||||||
|
|
||||||
// fn creates a function, optionally with arguments
|
|
||||||
fn: {
|
|
||||||
new(help='', args=[]): { 'function': {
|
|
||||||
help: help,
|
|
||||||
args: args,
|
|
||||||
} },
|
|
||||||
},
|
|
||||||
Fn: self.fn.new,
|
|
||||||
|
|
||||||
// arg creates a function argument of given name,
|
|
||||||
// type and optionally a default value
|
|
||||||
arg: {
|
|
||||||
new(name, type, default=null): {
|
|
||||||
name: name,
|
|
||||||
type: type,
|
|
||||||
default: default,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Arg: self.arg.new,
|
|
||||||
|
|
||||||
// T contains constants for the Jsonnet types
|
|
||||||
T: {
|
|
||||||
string: 'string',
|
|
||||||
number: 'number',
|
|
||||||
bool: 'bool',
|
|
||||||
object: 'object',
|
|
||||||
array: 'array',
|
|
||||||
any: 'any',
|
|
||||||
func: 'function',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
local root = d.Obj('grafana.libsonnet is the offical Jsonnet library for Grafana', {
|
|
||||||
new: d.Fn('new returns Grafana resources with sane defaults'),
|
|
||||||
addConfig: d.Fn('addConfig adds config entries to grafana.ini', [
|
|
||||||
d.Arg('config', d.T.object),
|
|
||||||
]),
|
|
||||||
datasource: d.Obj('ds-util makes creating datasources easy', {
|
|
||||||
new: d.Fn('new creates a new datasource', [
|
|
||||||
d.Arg('name', d.T.string),
|
|
||||||
d.Arg('type', d.T.string),
|
|
||||||
]),
|
|
||||||
sheesh: d.Obj("sheesh is sheeshing around", {
|
|
||||||
shit: d.Fn("enough sheesh", [
|
|
||||||
d.Arg("lel", d.T.any),
|
|
||||||
d.Arg("lol", d.T.func),
|
|
||||||
])
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
d.new('grafana', 'github.com/sh0rez/grafana.libsonnet')
|
|
||||||
+ d.withAPI(std.prune(root))
|
|
||||||
+ d.withHelp("`grafana.libsonnet` is the offical Jsonnet package for using Grafana with Kubernetes")
|
|
||||||
8
doc-util/main.docsonnet
Normal file
8
doc-util/main.docsonnet
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
local d = import './main.libsonnet';
|
||||||
|
|
||||||
|
d.new('d', url='github.com/jsonnet-libs/docsonnet/doc-util')
|
||||||
|
+ d.withAPI(import './main.libsonnet')
|
||||||
|
+ d.withHelp(|||
|
||||||
|
`doc-util` provides a Jsonnet interface for `docsonnet`,
|
||||||
|
a Jsonnet API doc generator that uses structured data instead of comments.
|
||||||
|
|||)
|
||||||
124
doc-util/main.libsonnet
Normal file
124
doc-util/main.libsonnet
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
local _internal = {
|
||||||
|
// clean removes the hash from the key
|
||||||
|
clean(str): std.strReplace(str, '#', ''),
|
||||||
|
|
||||||
|
include(api, key):
|
||||||
|
// include docsonnet fields
|
||||||
|
if std.startsWith(key, '#') then true
|
||||||
|
|
||||||
|
// non-docsonnet object, might have nested docsonnet
|
||||||
|
else if std.isObject(api[key]) then
|
||||||
|
// skip if has docsonnet counterpart
|
||||||
|
(if std.objectHasAll(api, '#' + key) then false else true)
|
||||||
|
|
||||||
|
// some other field, skip it
|
||||||
|
else false,
|
||||||
|
|
||||||
|
// ds deals with docsonnet fields. Also checks for nested objects for
|
||||||
|
//docsonnet ones
|
||||||
|
ds(api, key):
|
||||||
|
local cleaned = self.clean(key);
|
||||||
|
if std.objectHasAll(api[key], 'object') && std.objectHasAll(api, cleaned) then
|
||||||
|
api[key] + $.object.withFields($.filter(api[cleaned]))
|
||||||
|
else
|
||||||
|
api[key],
|
||||||
|
|
||||||
|
// filter returns only docsonnet related objects from the api
|
||||||
|
filter(api): {
|
||||||
|
[self.clean(key)]:
|
||||||
|
// include all docsonnet
|
||||||
|
if std.startsWith(key, '#') then
|
||||||
|
$.ds(api, key)
|
||||||
|
// create docsonnet objects from regular ones
|
||||||
|
else if std.isObject(api[key]) then
|
||||||
|
$.obj('', $.filter(api[key]))
|
||||||
|
|
||||||
|
for key in std.objectFields(api)
|
||||||
|
if self.include(api, key)
|
||||||
|
},
|
||||||
|
|
||||||
|
fromMain(main): self.filter(main),
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
local internal = self + _internal,
|
||||||
|
local d = self,
|
||||||
|
|
||||||
|
'#new': d.fn('`new` initiates the api documentation model, taking the `name` and import `url` of your project', [d.arg('name', d.T.string), d.arg('url', d.T.string)]),
|
||||||
|
new(name, url):: {
|
||||||
|
name: name,
|
||||||
|
'import': url,
|
||||||
|
},
|
||||||
|
|
||||||
|
'#withAPI': d.fn('`withAPI` automatically builds the docsonnet model from your public API. The `main` parameter is usually set to `import "./main.libsonnet"`.', [d.arg('main', d.T.object)]),
|
||||||
|
withAPI(main):: {
|
||||||
|
api: internal.fromMain(main),
|
||||||
|
},
|
||||||
|
|
||||||
|
'#withFields': d.fn('`withFields` allows to manually specify the docsonnet model. Usually `withAPI` is the better alternative', [d.arg('fields', d.T.object)]),
|
||||||
|
withFields(fields):: {
|
||||||
|
api: fields,
|
||||||
|
},
|
||||||
|
|
||||||
|
"#withHelp": d.fn("`withHelp` sets the main description text, displayed right under the package's name", [d.arg("help", d.T.string)]),
|
||||||
|
withHelp(help):: {
|
||||||
|
help: help,
|
||||||
|
},
|
||||||
|
|
||||||
|
"#object": d.obj("Utilities for documenting Jsonnet objects (`{ }`)."),
|
||||||
|
object:: {
|
||||||
|
"#new": d.fn("new creates a new object, optionally with description and fields", [d.arg("help", d.T.string), d.arg("fields", d.T.object)]),
|
||||||
|
new(help='', fields={}):: { object: {
|
||||||
|
help: help,
|
||||||
|
fields: fields,
|
||||||
|
} },
|
||||||
|
|
||||||
|
"#withFields": d.fn("The `withFields` modifier overrides the fields property of an already created object", [d.arg("fields", d.T.object)]),
|
||||||
|
withFields(fields):: { object+: {
|
||||||
|
fields: fields,
|
||||||
|
} },
|
||||||
|
},
|
||||||
|
|
||||||
|
"#obj": self.object["#new"] + d.func.withHelp("`obj` is a shorthand for `object.new`"),
|
||||||
|
obj:: self.object.new,
|
||||||
|
|
||||||
|
"#func": d.obj("Utilities for documenting Jsonnet methods (functions of objects)"),
|
||||||
|
func:: {
|
||||||
|
"#new": d.fn("new creates a new function, optionally with description and arguments", [d.arg("help", d.T.string), d.arg("args", d.T.array)]),
|
||||||
|
new(help='', args=[]):: { 'function': {
|
||||||
|
help: help,
|
||||||
|
args: args,
|
||||||
|
} },
|
||||||
|
|
||||||
|
"#withHelp": d.fn("The `withHelp` modifier overrides the help text of that function", [d.arg("help", d.T.string)]),
|
||||||
|
withHelp(help):: {'function'+: {
|
||||||
|
help: help,
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
|
||||||
|
"#fn": self.func["#new"] + d.func.withHelp("`fn` is a shorthand for `func.new`"),
|
||||||
|
fn:: self.func.new,
|
||||||
|
|
||||||
|
"#argument": d.obj("Utilities for creating function arguments"),
|
||||||
|
argument:: {
|
||||||
|
"#new": d.fn("new creates a new function argument, taking the name, the type and optionally a default value", [d.arg("name", d.T.string), d.arg("type", d.T.string), d.arg("default", d.T.any)]),
|
||||||
|
new(name, type, default=null): {
|
||||||
|
name: name,
|
||||||
|
type: type,
|
||||||
|
default: default,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"#arg": self.argument["#new"] + self.func.withHelp("`arg` is a shorthand for `argument.new`"),
|
||||||
|
arg:: self.argument.new,
|
||||||
|
|
||||||
|
// T contains constants for the Jsonnet types
|
||||||
|
T:: {
|
||||||
|
string: 'string',
|
||||||
|
number: 'number',
|
||||||
|
bool: 'bool',
|
||||||
|
object: 'object',
|
||||||
|
array: 'array',
|
||||||
|
any: 'any',
|
||||||
|
func: 'function',
|
||||||
|
},
|
||||||
|
}
|
||||||
24
main.go
24
main.go
|
|
@ -13,7 +13,7 @@ type Doc struct {
|
||||||
Import string `json:"import"`
|
Import string `json:"import"`
|
||||||
Help string `json:"help"`
|
Help string `json:"help"`
|
||||||
|
|
||||||
API Object `json:"api"`
|
API Fields `json:"api"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
@ -78,6 +78,28 @@ type Field struct {
|
||||||
Value *Value `json:"value,omitempty"`
|
Value *Value `json:"value,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *Field) UnmarshalJSON(data []byte) error {
|
||||||
|
type fake Field
|
||||||
|
|
||||||
|
var f fake
|
||||||
|
if err := json.Unmarshal(data, &f); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case f.Function != nil:
|
||||||
|
o.Function = f.Function
|
||||||
|
case f.Object != nil:
|
||||||
|
o.Object = f.Object
|
||||||
|
case f.Value != nil:
|
||||||
|
o.Value = f.Value
|
||||||
|
default:
|
||||||
|
return errors.New("field has no value")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (o Field) MarshalJSON() ([]byte, error) {
|
func (o Field) MarshalJSON() ([]byte, error) {
|
||||||
if o.Function == nil && o.Object == nil && o.Value == nil {
|
if o.Function == nil && o.Object == nil && o.Value == nil {
|
||||||
return nil, errors.New("field has no value")
|
return nil, errors.New("field has no value")
|
||||||
|
|
|
||||||
18
render.go
18
render.go
|
|
@ -37,7 +37,9 @@ var objTmpl = strings.Replace(`
|
||||||
{{ .Help }}
|
{{ .Help }}
|
||||||
`, "´", "`", -1)
|
`, "´", "`", -1)
|
||||||
|
|
||||||
type obj Object
|
type obj struct {
|
||||||
|
Object
|
||||||
|
}
|
||||||
|
|
||||||
func (o obj) Render() string {
|
func (o obj) Render() string {
|
||||||
t := template.Must(template.New("").Parse(objTmpl))
|
t := template.Must(template.New("").Parse(objTmpl))
|
||||||
|
|
@ -48,7 +50,9 @@ func (o obj) Render() string {
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
type fn Function
|
type fn struct {
|
||||||
|
Function
|
||||||
|
}
|
||||||
|
|
||||||
func (f fn) Params() string {
|
func (f fn) Params() string {
|
||||||
args := make([]string, 0, len(f.Args))
|
args := make([]string, 0, len(f.Args))
|
||||||
|
|
@ -90,8 +94,8 @@ func render(d Doc) (string, error) {
|
||||||
Name: d.Name,
|
Name: d.Name,
|
||||||
Import: d.Import,
|
Import: d.Import,
|
||||||
Help: d.Help,
|
Help: d.Help,
|
||||||
Index: buildIndex(d.API.Fields, 0),
|
Index: buildIndex(d.API, 0),
|
||||||
Fields: renderables(d.API.Fields, ""),
|
Fields: renderables(d.API, ""),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
@ -118,11 +122,11 @@ func renderables(fields map[string]Field, prefix string) []Renderable {
|
||||||
for _, f := range fields {
|
for _, f := range fields {
|
||||||
switch {
|
switch {
|
||||||
case f.Function != nil:
|
case f.Function != nil:
|
||||||
fnc := fn(*f.Function)
|
fnc := fn{*f.Function}
|
||||||
fnc.Name = strings.TrimPrefix(prefix+"."+fnc.Name, ".")
|
fnc.Name = strings.TrimPrefix(prefix+"."+fnc.Name, ".")
|
||||||
rs = append(rs, fnc)
|
rs = append(rs, fnc)
|
||||||
case f.Object != nil:
|
case f.Object != nil:
|
||||||
o := obj(*f.Object)
|
o := obj{*f.Object}
|
||||||
o.Name = strings.TrimPrefix(prefix+"."+o.Name, ".")
|
o.Name = strings.TrimPrefix(prefix+"."+o.Name, ".")
|
||||||
rs = append(rs, o)
|
rs = append(rs, o)
|
||||||
|
|
||||||
|
|
@ -153,7 +157,7 @@ func buildIndex(fields map[string]Field, level int) []indexElem {
|
||||||
func indexLine(f Field) string {
|
func indexLine(f Field) string {
|
||||||
switch {
|
switch {
|
||||||
case f.Function != nil:
|
case f.Function != nil:
|
||||||
return "fn " + fn(*f.Function).Signature()
|
return "fn " + fn{*f.Function}.Signature()
|
||||||
case f.Object != nil:
|
case f.Object != nil:
|
||||||
return fmt.Sprintf("obj %s", f.Object.Name)
|
return fmt.Sprintf("obj %s", f.Object.Name)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue