2019-03-24 19:28:36 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2019-03-24 21:42:48 +00:00
|
|
|
"encoding/json"
|
|
|
|
"flag"
|
2019-03-24 19:28:36 +00:00
|
|
|
"fmt"
|
|
|
|
"go/format"
|
|
|
|
"io/ioutil"
|
|
|
|
"log"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2019-03-24 21:42:48 +00:00
|
|
|
const headerFmt = `// GENERATED BY gitlab.codemonkeysoftware.net/b/hatmill/internal/codegen
|
|
|
|
// DO NOT EDIT!
|
2019-03-24 19:28:36 +00:00
|
|
|
|
2019-03-24 21:42:48 +00:00
|
|
|
package %s
|
2019-04-03 02:05:48 +00:00
|
|
|
|
|
|
|
import "gitlab.codemonkeysoftware.net/b/hatmill"
|
2019-03-24 21:42:48 +00:00
|
|
|
`
|
2019-03-24 19:28:36 +00:00
|
|
|
|
2019-04-03 02:05:48 +00:00
|
|
|
func fileHeader(packageName string) string {
|
|
|
|
return fmt.Sprintf(headerFmt, packageName)
|
2019-03-24 21:42:48 +00:00
|
|
|
}
|
2019-03-24 19:28:36 +00:00
|
|
|
|
2019-03-24 21:42:48 +00:00
|
|
|
type AttribType int
|
|
|
|
|
|
|
|
const (
|
|
|
|
String AttribType = iota
|
|
|
|
Bool
|
|
|
|
)
|
|
|
|
|
|
|
|
func (t *AttribType) UnmarshalJSON(data []byte) error {
|
|
|
|
if string(data) == "null" {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var typeName string
|
|
|
|
err := json.Unmarshal(data, &typeName)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("type property must be a string")
|
|
|
|
}
|
|
|
|
switch typeName {
|
|
|
|
case "bool":
|
|
|
|
*t = Bool
|
|
|
|
case "string":
|
|
|
|
*t = String
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("unrecognized attribute type %s", typeName)
|
|
|
|
}
|
|
|
|
return nil
|
2019-03-24 19:28:36 +00:00
|
|
|
}
|
|
|
|
|
2019-03-24 21:42:48 +00:00
|
|
|
type AttribDef struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
Type AttribType `json:"type"`
|
|
|
|
}
|
2019-03-24 19:28:36 +00:00
|
|
|
|
2019-04-03 02:05:48 +00:00
|
|
|
func (def AttribDef) Generate() string {
|
2019-03-24 21:42:48 +00:00
|
|
|
const (
|
2019-03-24 19:28:36 +00:00
|
|
|
boolType = "bool"
|
|
|
|
stringType = "string"
|
|
|
|
|
2019-03-25 02:35:40 +00:00
|
|
|
stringTemplate = `// %[1]s creates a "%[2]s" attribute
|
2019-04-03 02:05:48 +00:00
|
|
|
func %[1]s(value string) hatmill.Attrib {
|
|
|
|
return hatmill.Attrib{
|
2019-03-25 02:32:15 +00:00
|
|
|
Key: "%[2]s",
|
2019-03-24 19:28:36 +00:00
|
|
|
Value: value,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`
|
2019-03-25 02:35:40 +00:00
|
|
|
boolTemplate = `// %[1]s creates a "%[2]s" attribute
|
2019-04-03 02:05:48 +00:00
|
|
|
func %[1]s() hatmill.Attrib {
|
|
|
|
return hatmill.Attrib{
|
2019-03-25 02:32:15 +00:00
|
|
|
Key: "%[2]s",
|
2019-03-24 19:28:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
`
|
|
|
|
)
|
|
|
|
|
2019-03-24 21:42:48 +00:00
|
|
|
var template string
|
|
|
|
switch def.Type {
|
|
|
|
case Bool:
|
|
|
|
template = boolTemplate
|
|
|
|
case String:
|
|
|
|
template = stringTemplate
|
|
|
|
default:
|
2019-03-25 02:32:15 +00:00
|
|
|
panic(fmt.Errorf("unknown attribute type: %v", def.Type))
|
2019-03-24 21:42:48 +00:00
|
|
|
}
|
|
|
|
|
2019-04-03 02:05:48 +00:00
|
|
|
return fmt.Sprintf(template, strings.Title(def.Name), def.Name)
|
2019-03-24 21:42:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type ElemDef struct {
|
|
|
|
Name string `json:"name"`
|
2019-03-29 02:22:31 +00:00
|
|
|
Void bool `json:"void"`
|
2019-03-24 21:42:48 +00:00
|
|
|
}
|
|
|
|
|
2019-04-03 02:05:48 +00:00
|
|
|
func (def ElemDef) Generate() string {
|
2019-03-24 21:42:48 +00:00
|
|
|
const (
|
|
|
|
parentTemplate = `// %[1]s creates a <%[2]s> element.
|
2019-04-03 02:05:48 +00:00
|
|
|
func %[1]s(attribs ...hatmill.Attrib) func(children ...hatmill.Term) hatmill.ParentElement {
|
|
|
|
return func(children ...hatmill.Term) hatmill.ParentElement {
|
|
|
|
return hatmill.ParentElement{
|
|
|
|
VoidElement: hatmill.VoidElement{
|
2019-03-24 21:42:48 +00:00
|
|
|
TagName: "%[2]s",
|
|
|
|
Attribs: attribs,
|
|
|
|
},
|
|
|
|
Children: children,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`
|
2019-03-29 02:18:25 +00:00
|
|
|
voidTemplate = `// %[1]s creates a <%[2]s> element.
|
2019-04-03 02:05:48 +00:00
|
|
|
func %[1]s(attribs ...hatmill.Attrib) hatmill.VoidElement {
|
|
|
|
return hatmill.VoidElement{
|
2019-03-24 21:42:48 +00:00
|
|
|
TagName: "%[2]s",
|
|
|
|
Attribs: attribs,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`
|
|
|
|
)
|
|
|
|
|
|
|
|
template := parentTemplate
|
2019-03-29 02:22:31 +00:00
|
|
|
if def.Void {
|
2019-03-29 02:18:25 +00:00
|
|
|
template = voidTemplate
|
2019-03-24 21:42:48 +00:00
|
|
|
}
|
2019-04-03 02:05:48 +00:00
|
|
|
return fmt.Sprintf(template, strings.Title(def.Name), def.Name)
|
2019-03-24 21:42:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Defs struct {
|
|
|
|
Attributes []AttribDef `json:"attributes"`
|
|
|
|
Elements []ElemDef `json:"elements"`
|
2019-03-24 19:28:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
2019-03-24 21:42:48 +00:00
|
|
|
inputPath := flag.String("input", "", "JSON input file")
|
|
|
|
outputPath := flag.String("output", "", ".go output file")
|
|
|
|
packageName := flag.String("package", "", "output package name")
|
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
input, err := ioutil.ReadFile(*inputPath)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var defs Defs
|
|
|
|
err = json.Unmarshal(input, &defs)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
output := new(bytes.Buffer)
|
2019-04-03 02:05:48 +00:00
|
|
|
output.WriteString(fileHeader(*packageName))
|
2019-03-24 21:42:48 +00:00
|
|
|
for _, elemDef := range defs.Elements {
|
2019-04-03 02:05:48 +00:00
|
|
|
output.WriteString(elemDef.Generate())
|
2019-03-24 21:42:48 +00:00
|
|
|
}
|
|
|
|
for _, attribDef := range defs.Attributes {
|
2019-04-03 02:05:48 +00:00
|
|
|
output.WriteString(attribDef.Generate())
|
2019-03-24 21:42:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
formatted, err := format.Source(output.Bytes())
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = ioutil.WriteFile(*outputPath, formatted, 0644)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2019-03-24 19:28:36 +00:00
|
|
|
}
|