commit b402a3b581e1c89949f12347211cccf4042a1145 Author: Brandon Dyck Date: Thu Mar 21 11:26:40 2019 -0600 First commit: the bones diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..eee059b --- /dev/null +++ b/go.mod @@ -0,0 +1 @@ +module gitlab.codemonkeysoftware.com/b/hatmill diff --git a/hatmill.go b/hatmill.go new file mode 100644 index 0000000..ca60127 --- /dev/null +++ b/hatmill.go @@ -0,0 +1,183 @@ +package main + +import "fmt" +import "io" +import "os" +import "strings" + +// Html is either Element or Text +type Html interface { + io.WriterTo + // isHtml is a non-functional marker to differentiate Html from interface{} + isHtml() +} + +func Reader() io.Reader { + // TODO in-order traversal of HTML tree to spit out bytes + return nil +} + +func String() string { + panic("this could be trivially implemented with a Reader and a bytes.Buffer") +} + +type Attrib struct { + Key string + Value string +} + +type element struct { + tagName string + attribs []Attrib + empty bool + children []Html +} + +// writeTo attempts to write the strings in ss to w, incrementing n by the +// number of bytes written. +func writeTo(w io.Writer, n *int64, ss ...string) error { + for _, s := range ss { + nCurr, err := io.WriteString(w, s) + *n += int64(nCurr) + if err != nil { + return err + } + } + return nil +} + +func (a Attrib) WriteTo(w io.Writer) (n int64, err error) { + err = writeTo(w, &n, a.Key) + if err != nil { + return + } + if a.Value != "" { + err = writeTo(w, &n, "='", a.Value, "'") + } + return +} + +func (e *element) WriteTo(w io.Writer) (n int64, err error) { + err = writeTo(w, &n, "<", e.tagName) + if err != nil { + return + } + + for _, attrib := range e.attribs { + err = writeTo(w, &n, " ") + if err != nil { + return + } + + var nCurr int64 + nCurr, err = attrib.WriteTo(w) + n += int64(nCurr) + if err != nil { + return + } + } + + err = writeTo(w, &n, ">") + if err != nil { + return + } + + if !e.empty { + for _, child := range e.children { + var nCurr int64 + nCurr, err = child.WriteTo(w) + n += int64(nCurr) + if err != nil { + return + } + } + + err = writeTo(w, &n, "") + } + return +} + +func (*element) isHtml() {} + +func emptyElement(tagName string, attribs []Attrib) Html { + return &element{ + tagName: tagName, + attribs: attribs, + empty: true, + } +} + +func elementFunc(tagName string, attribs []Attrib) func(...Html) Html { + return func(children ...Html) Html { + return &element{ + tagName: tagName, + attribs: attribs, + children: children, + empty: false, + } + } +} + +type text string + +func Text(s string) Html { + return text(s) +} + +func (text) isHtml() {} + +func (t text) WriteTo(w io.Writer) (n int64, err error) { + err = writeTo(w, &n, string(t)) + return +} + +type rText struct { + io.Reader +} + +func RText(r io.Reader) Html { + return rText{Reader: r} +} + +func (rText) isHtml() {} + +func (rt rText) WriteTo(w io.Writer) (n int64, err error) { + return io.Copy(w, rt.Reader) +} + +// Html5 functions + +func Div(attribs ...Attrib) func(children ...Html) Html { + return elementFunc("div", attribs) +} + +func Img(attribs ...Attrib) Html { + return emptyElement("img", attribs) +} + +func Id(id string) Attrib { + return Attrib{ + Key: "id", + Value: id, + } +} + +func Disabled() Attrib { + return Attrib { + Key: "disabled", + } +} + +func main() { + var page = Div(Disabled(), Id("container"))( + Img(Id("profile-photo")), + Text("hello"), + Img(Disabled()), + RText(strings.NewReader("goodbye!")), + ) + + n, err := page.WriteTo(os.Stdout) + fmt.Println() + fmt.Println(n) + fmt.Println(err) +}