hatmill/hatmill.go

185 lines
3.1 KiB
Go
Raw Normal View History

2019-03-21 18:40:54 +00:00
package hatmill
2019-03-21 17:26:40 +00:00
import "fmt"
import "io"
import "os"
import "strings"
// Html is either Element or Text
type Html interface {
2019-03-21 18:40:54 +00:00
io.WriterTo
2019-03-21 17:26:40 +00:00
2019-03-21 18:40:54 +00:00
// isHtml is a no-op method to prevent external Html implementations, because
// Go doesn't have sum types.
isHtml()
2019-03-21 17:26:40 +00:00
}
2019-03-21 18:40:54 +00:00
// writeStringsTo attempts to write the strings in ss to w, incrementing n by the
// number of bytes written.
func writeStringsTo(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
2019-03-21 17:26:40 +00:00
}
type Attrib struct {
2019-03-21 18:40:54 +00:00
Key string
Value string
2019-03-21 17:26:40 +00:00
}
func (a Attrib) WriteTo(w io.Writer) (n int64, err error) {
2019-03-21 18:40:54 +00:00
err = writeStringsTo(w, &n, a.Key)
if err != nil {
return
}
if a.Value != "" {
err = writeStringsTo(w, &n, "='", a.Value, "'")
}
return
2019-03-21 17:26:40 +00:00
}
2019-03-21 18:40:54 +00:00
type EmptyElement struct {
TagName string
Attribs []Attrib
}
2019-03-21 17:26:40 +00:00
2019-03-21 18:40:54 +00:00
func (EmptyElement) isHtml() {}
2019-03-21 17:26:40 +00:00
2019-03-21 18:40:54 +00:00
func (e EmptyElement) WriteTo(w io.Writer) (n int64, err error) {
err = writeStringsTo(w, &n, "<", e.TagName)
if err != nil {
return
}
2019-03-21 17:26:40 +00:00
2019-03-21 18:40:54 +00:00
for _, attrib := range e.Attribs {
err = writeStringsTo(w, &n, " ")
if err != nil {
return
}
2019-03-21 17:26:40 +00:00
2019-03-21 18:40:54 +00:00
var nCurr int64
nCurr, err = attrib.WriteTo(w)
n += int64(nCurr)
if err != nil {
return
}
}
2019-03-21 17:26:40 +00:00
2019-03-21 18:40:54 +00:00
err = writeStringsTo(w, &n, ">")
return
2019-03-21 17:26:40 +00:00
}
2019-03-21 18:40:54 +00:00
type ParentElement struct {
EmptyElement
Children []Html
2019-03-21 17:26:40 +00:00
}
2019-03-21 18:40:54 +00:00
func (e *ParentElement) isHtml() {}
func (e *ParentElement) WriteTo(w io.Writer) (n int64, err error) {
n, err = e.EmptyElement.WriteTo(w)
if err != nil {
return
}
2019-03-21 17:26:40 +00:00
2019-03-21 18:40:54 +00:00
for _, child := range e.Children {
var nCurr int64
nCurr, err = child.WriteTo(w)
n += int64(nCurr)
if err != nil {
return
}
}
2019-03-21 17:26:40 +00:00
2019-03-21 18:40:54 +00:00
err = writeStringsTo(w, &n, "</", e.TagName, ">")
return
2019-03-21 17:26:40 +00:00
}
2019-03-21 18:40:54 +00:00
type Text string
2019-03-21 17:26:40 +00:00
2019-03-21 18:40:54 +00:00
func (Text) isHtml() {}
2019-03-21 17:26:40 +00:00
2019-03-21 18:40:54 +00:00
func (t Text) WriteTo(w io.Writer) (n int64, err error) {
err = writeStringsTo(w, &n, string(t))
return
2019-03-21 17:26:40 +00:00
}
2019-03-21 18:40:54 +00:00
type RText struct {
io.Reader
2019-03-21 17:26:40 +00:00
}
2019-03-21 18:40:54 +00:00
func (RText) isHtml() {}
2019-03-21 17:26:40 +00:00
2019-03-21 18:40:54 +00:00
func (rt RText) WriteTo(w io.Writer) (n int64, err error) {
return io.Copy(w, rt.Reader)
2019-03-21 17:26:40 +00:00
}
// Html5 functions
2019-03-21 18:40:54 +00:00
func Div(attribs ...Attrib) func(children ...Html) *ParentElement {
return func(children ...Html) *ParentElement {
return &ParentElement{
EmptyElement: EmptyElement{
TagName: "div",
Attribs: attribs,
},
Children: children,
}
}
2019-03-21 17:26:40 +00:00
}
2019-03-21 18:40:54 +00:00
func Img(attribs ...Attrib) EmptyElement {
return EmptyElement{
TagName: "img",
Attribs: attribs,
}
2019-03-21 17:26:40 +00:00
}
func Id(id string) Attrib {
2019-03-21 18:40:54 +00:00
return Attrib{
Key: "id",
Value: id,
}
2019-03-21 17:26:40 +00:00
}
func Disabled() Attrib {
2019-03-21 18:40:54 +00:00
return Attrib{
Key: "disabled",
}
}
// WriteDocument writes an HTML5 doctype declaration, followed by root.
// root should probably be an <html> element.
func WriteDocument(w io.Writer, root *ParentElement) (n int64, err error) {
err = writeStringsTo(w, &n, "<!DOCTYPE html>")
if err != nil {
return
}
var nroot int64
nroot, err = root.WriteTo(w)
n += nroot
return
}
func Main() {
var page = Div(Disabled(), Id("container"))(
Img(Id("profile-photo")),
Text("hello"),
Img(Disabled()),
RText{strings.NewReader("goodbye!")},
)
n, err := WriteDocument(os.Stdout, page)
fmt.Println()
fmt.Println(n)
if err != nil {
fmt.Println(err)
}
2019-03-21 17:26:40 +00:00
}