htmlkit

package module
v0.0.0-...-bd0fd5c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 24, 2020 License: MIT Imports: 4 Imported by: 0

README

htmlkit

htmlkit is a library for building HTML documents in Go. It is meant to serve as an alternative to html/template and other template libraries.

Why this project?

There's something missing in html/template package. It is really useful, but it lacks compile time safety. I find template reusability a bit problematic also.

Ok, can we do better? I don't know. But here is one attempt. It's not necessarily better, just different.

htmlkit is a very simple library for constructing HTML documents. It let's you write HTML DOM in more or less declarative way in Go. This is actually really nice since you get static type checks at build time and you can also easilly compose larger documents from reusable HTML nodes (think React components).

Examples

See examples folder on how to use it.

The following code:

package main

import (
	"context"
	"fmt"
	"github.com/tadasv/htmlkit"
	"os"
)

// Define a builder for a reusable comment list component
var commentListBuilder = htmlkit.NewElementBuilder(
	"ul",
).WithAttribute("class", "comments").WithChildFunc(func(ctx context.Context) ([]*htmlkit.Node, error) {
	comments := ctx.Value("comments").([]string)
	children := []*htmlkit.Node{}

	for _, comment := range comments {
		children = append(children, htmlkit.NewElementBuilder("li").WithChild(htmlkit.NewTextNode(comment)).Build(nil))
	}

	return children, nil
})

// An example illustrating full HTML page template or what it might look like.
func blogPostPageTemplate(title string, body string, comments []string) *htmlkit.Node {
	templateContext := context.WithValue(context.Background(), "comments", comments)

	document := htmlkit.NewDocumentNode()
	document.AppendChild(
		htmlkit.NewDoctypeNode(),
		htmlkit.NewElementBuilder(
			"html",
		).WithChildren(
			htmlkit.NewRawNode(fmt.Sprintf("<head><title>%s</title></head>", title)),
			htmlkit.NewRawNode(`<body>`),
			htmlkit.NewElementBuilder("div").WithAttribute("class", "post").WithChild(htmlkit.NewRawNode(body)).Build(templateContext),
			commentListBuilder.Build(templateContext),
			htmlkit.NewRawNode(`</body>`),
		).Build(templateContext),
	)
	return document
}

func main() {
	document := blogPostPageTemplate("htmlkit demo", "This is an example of htmlkit", []string{
		"it demonstrates declarative html document construction",
		"htmlkit let's you easilly mix in raw HTML when needed",
		"it offers dynamic html document rendering with type safety",
	})

	htmlkit.Render(os.Stdout, document)
}

Produces the following HTML document (pretty printed for readability):

<!DOCTYPE html>
<html>
  <head>
    <title>htmlkit demo</title>
  </head>
  <body>
    <div class="post">This is an example of htmlkit</div>
    <ul class="comments">
      <li>it demonstrates declarative html document construction</li>
      <li>htmlkit let&#39;s you easilly mix in raw HTML when needed</li>
      <li>it offers dynamic html document rendering with type safety</li>
    </ul>
  </body>
</html>

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Render

func Render(writer io.Writer, nodes ...*Node) error

Types

type Attribute

type Attribute struct {
	Key   string
	Value string
}

type AttributeFunc

type AttributeFunc func(context.Context) (*Attribute, error)

type ElementBuilder

type ElementBuilder struct {
	// contains filtered or unexported fields
}

func NewElementBuilder

func NewElementBuilder(name string) *ElementBuilder

func (*ElementBuilder) Build

func (b *ElementBuilder) Build(ctx context.Context) *Node

func (*ElementBuilder) WithAttribute

func (b *ElementBuilder) WithAttribute(key, value string) *ElementBuilder

func (*ElementBuilder) WithAttributeFunc

func (b *ElementBuilder) WithAttributeFunc(fnc AttributeFunc) *ElementBuilder

func (*ElementBuilder) WithChild

func (b *ElementBuilder) WithChild(child *Node) *ElementBuilder

func (*ElementBuilder) WithChildFunc

func (b *ElementBuilder) WithChildFunc(fnc NodeFunc) *ElementBuilder

func (*ElementBuilder) WithChildren

func (b *ElementBuilder) WithChildren(children ...*Node) *ElementBuilder

type Node

type Node struct {
	Type       NodeType
	Data       string
	Children   []*Node
	Attributes []Attribute
}

func NewCommentNode

func NewCommentNode(comment string) *Node

func NewDoctypeNode

func NewDoctypeNode() *Node

func NewDocumentNode

func NewDocumentNode() *Node

func NewElementNode

func NewElementNode(name string, attributes []Attribute, children []*Node) *Node

func NewRawNode

func NewRawNode(value string) *Node

func NewTextNode

func NewTextNode(text string) *Node

func (*Node) AppendChild

func (n *Node) AppendChild(children ...*Node)

type NodeFunc

type NodeFunc func(context.Context) ([]*Node, error)

type NodeType

type NodeType uint32
const (
	ErrorNode NodeType = iota
	TextNode
	DocumentNode
	ElementNode
	CommentNode
	DoctypeNode
	RawNode
)

type Renderer

type Renderer struct {
	// contains filtered or unexported fields
}

func NewRenderer

func NewRenderer(w io.Writer) *Renderer

func (*Renderer) Render

func (r *Renderer) Render(nodes ...*Node) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL