hatmill/hatmill.go

184 lines
3.1 KiB
Go

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, "</", e.tagName, ">")
}
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)
}