goht

package module
v1.1.2 Latest Latest
Warning

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

Go to latest
Published: Jun 29, 2022 License: MIT Imports: 4 Imported by: 1

README

goht

A minimalist package for creating web content in Go.

Features

  • Easy to learn if you already know html.
  • Dynamic. Generate html/css/js at build time or run time, server side or client side (using GopherJS or WebAssembly).
  • Over 80 common tags pre-defined. Adding new ones is trivially simple.
  • Composable. Reduce repetition by writing functions that return nested html fragments.
  • Fast. About 100ns per tag on typical hardware.

Usage

import . "github.com/Michael-F-Ellis/goht"

Dot imports are generally discouraged as bad style but they make sense for this package. It saves you having to put goht. in front of every tag function.

Hello, World
var page := Html("",Head(""),Body("", "Hello, World"))
var b bytes.Buffer
err := Render(page, &b, 0)

produces

<html>
  <head>
  </head>
  <body>Hello, World
  </body>
</html>

See Example 1 for a complete listing you can edit and run.

For a larger usage example, see webpage.go in the repository for my online ear-training app Infinite Etudes.

Composing

Our "Hello, World" example

can also be written

head := Head("")
body := Body("", "Hello, World")
page := Html("", head, body)

or, possibly (see Example 2)

func mkPage(c ...interface{}) *HtmlTree {
    body := Body("", c...)
    return Html("", Head(""), body)
}
page1 := mkPage("Hello, World")
page2 := mkPage(H1("", "Mars"), "Hello, Other World")

The point is that the full power and flexibility of Go is available to factor repetitive content. Any function that returns a valid *HtmlTree may be called to create content arguments for any tag function.

Under the hood

Tags

The definition for all (non-empty) html tags is the same:

func Tagname(a string, c ...interface{}) *HtmlTree {
	return &HtmlTree{"tagname", a, c, false}
}

The func name is simply the html tag name with an initial cap.

The first arg, a, is a string of attributes written exactly as you would in html, e.g. id=42 class="foo". In goht it's helpful to enclose the attribute string in back-quotes to allow use of both single and double quotes when specifying attributes.

The second arg, c, is the content of the tag. It's a variadic argument meaning that you may supply as many arguments as needed to define the inner html of the tag. The type of c is interface{}. Only two concrete types are supported: string or *HtmlTree. The latter is the return value type of every tag function.

Empty tags, like <br> can't contain other elements. In goht these tag have only the a argument, e.g

Br(a string) *HtmlTree { ... }

See tags.go for the complete list of tags defined in goht.

The Null Tag (added in V1.1.0)

Null is a pseudo tag doesn't correspond to a valid HTML tag. It's useful when you want to render content that can be injected as the innerHTML of an existing element. The signature is

Null(c ...interface{})

Note that Null, unlike other tags, doesn't accept an attribute string. When rendered it emits the rendered content without an enclosing tag.

Null(Br(``), Br(``)) // renders <br><br>

vs

Div(``, Br(``), Br(``))  // renders <div><br><br></div>
The HtmlTree struct

Goht represents nested html elements with a recursive struct:

// HtmlTree represents a tree of html content.
type HtmlTree struct {
	T     string        // html tagname, e.g. 'head'
	A     string        // zero or more html attributes, e.g 'id=1 class="foo"'
	C     []interface{} // a slice of content whose elements may be strings or *HtmlTree
	empty bool          // set to true for empty tags like <br>
}

You'll mostly use HtmlTree as a return type when composing grouped tag functions. The struct members are exported should you need to access them from within some clever on-the-fly html generation, but as Rob Pike says "Clear is better than clever. Don't be clever."

Rendering

A single func is exposed to handle rendering html text from HtmlTree structs.

func Render(h *HtmlTree, b *bytes.Buffer, nindent int) (err error)

Render walks through HtmlTree h and writes html text to byte buffer b. The nindent argument specifies whether and how much to indent the output where -1 means render all on one line and 0 means indent each inner tag by 2 spaces relative to its parent. Render returns an error when it encounters invalid content.

CSS

Goht provides the Style tag function. It's up to you to make sure the contents are valid CSS.

Style("", `
    body {
	  margin: 0;
	  height: 100%;
	  overflow: auto;
	  background-color: #DDA;
	  }
    h1 {font-size: 300%; margin-bottom: 1vh}
    `)

You can also import external stylesheets with the Link tag function. For example

Link(`rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css"`)

JavaScript

Use the Script tag function to import or contain JavaScript code.

Script("src=/midijs/midi.js charset=UTF-8")

Script("",
		`
		// chores at start-up
		function start() {
		  // Chrome and other browsers now disallow AudioContext until
		  // after a user action.
		  document.body.addEventListener("click", MIDIjs.resumeAudioContext);
		}
		// Run start when the doc is fully loaded.
		document.addEventListener("DOMContentLoaded", start);
	`)

Checking attributes

Goht includes a limited facility for checking tag attributes. It's mainly useful for unit tests.

func (e *HtmlTree) CheckAttributes(perrs *[]AttributeErrors)

CheckAttributes walks through an HtmlTree and checks each tag to verify that the attribute names associated with the tag are valid for that tag. It returns a slice of AttributeErrors. The slice will be empty if no errors were found.

type AttributeErrors struct {
	tag   string  // an html tag
	attrs string  // a string of zero or more attributes
	errs  []error // errors found in attrs
}

See Example 3 for usage details

Alternatives

Goht is designed with a "simplest thing that could possibly work" philosophy. Here are some more ambitious alternatives.

Documentation

Overview

Atempting to re-create my Python htmltree in go.

Index

Constants

This section is empty.

Variables

View Source
var Attributes map[string][]string

Attributes is filled in at init time with a list of attributes and the tag names that support them.

Functions

func Gohtify added in v1.1.2

func Gohtify(htext string, ignoreTags map[string]struct{}, gohttext *string) (err error)

Gohtify parses an html string, htext, and returns equivalent goht code in gohttext. The ignoreTags map contains one or more tags to be ignored as map keys. These are typically "html", "head" and "body" because html.Parse creates them if they're not present in the string. That's usually not desired since the chief use of Gohtify is to turn useful fragments of html into into equivalent Go code.

func Ids added in v1.1.2

func Ids(tree *HtmlTree, ids *[]string) (err error)

Ids returns a slice of string containing all the id attributes found in tree. It will return an error if the search finds a malformed id, multiple ids in the same tag or the same id in different tags.

func Render

func Render(h *HtmlTree, b *bytes.Buffer, nindent int) (err error)

Render walks through HtmlTree h and writes html text to byte buffer b. The nindent argument specifies whether and how much to indent the output where -1 means render all on one line and 0 means indent each inner tag by 2 spaces relative to its parent. Render returns an error when it encounters invalid content.

Types

type AttributeErrors

type AttributeErrors struct {
	Tag   string  // an html tag
	Attrs string  // a string of zero or more attributes
	Errs  []error // errors found in attrs
}

AttributeErrors is a struct returned by CheckAttributes. It contains the tag, the string of attributes and a slice of errors returned by checkTagAttributes.

type HtmlTree

type HtmlTree struct {
	T string        // html tagname, e.g. 'head'
	A string        // zero or more html attributes, e.g 'id=1 class="foo"'
	C []interface{} // a slice of content whose elements may be strings or *HtmlTree
	// contains filtered or unexported fields
}

HtmlTree represents a tree of html content.

func A

func A(a string, c ...interface{}) *HtmlTree

func Address

func Address(a string, c ...interface{}) *HtmlTree

func Area

func Area(a string) *HtmlTree

func Article

func Article(a string, c ...interface{}) *HtmlTree

func Aside

func Aside(a string, c ...interface{}) *HtmlTree

func Audio

func Audio(a string, c ...interface{}) *HtmlTree

func B

func B(a string, c ...interface{}) *HtmlTree

func Blockquote

func Blockquote(a string, c ...interface{}) *HtmlTree

func Body

func Body(a string, c ...interface{}) *HtmlTree

func Br

func Br(a string) *HtmlTree

func Button

func Button(a string, c ...interface{}) *HtmlTree

func Canvas

func Canvas(a string, c ...interface{}) *HtmlTree

func Caption

func Caption(a string, c ...interface{}) *HtmlTree

func Cite

func Cite(a string, c ...interface{}) *HtmlTree

func Code

func Code(a string, c ...interface{}) *HtmlTree

func Col

func Col(a string) *HtmlTree

func Datalist

func Datalist(a string, c ...interface{}) *HtmlTree

func Dd

func Dd(a string, c ...interface{}) *HtmlTree

func Details added in v1.1.2

func Details(a string, c ...interface{}) *HtmlTree

func Dialog added in v1.1.2

func Dialog(a string, c ...interface{}) *HtmlTree

func Div

func Div(a string, c ...interface{}) *HtmlTree

func Dl

func Dl(a string, c ...interface{}) *HtmlTree

func Dt

func Dt(a string, c ...interface{}) *HtmlTree

func Em

func Em(a string, c ...interface{}) *HtmlTree

func Embed

func Embed(a string) *HtmlTree

func Fieldset

func Fieldset(a string, c ...interface{}) *HtmlTree

func Figcaption

func Figcaption(a string, c ...interface{}) *HtmlTree

func Figure

func Figure(a string, c ...interface{}) *HtmlTree
func Footer(a string, c ...interface{}) *HtmlTree

func Form

func Form(a string, c ...interface{}) *HtmlTree

func H1

func H1(a string, c ...interface{}) *HtmlTree

func H2

func H2(a string, c ...interface{}) *HtmlTree

func H3

func H3(a string, c ...interface{}) *HtmlTree

func H4

func H4(a string, c ...interface{}) *HtmlTree

func H5

func H5(a string, c ...interface{}) *HtmlTree

func H6

func H6(a string, c ...interface{}) *HtmlTree
func Head(a string, c ...interface{}) *HtmlTree
func Header(a string, c ...interface{}) *HtmlTree

func Hr

func Hr(a string) *HtmlTree

func Html

func Html(a string, c ...interface{}) *HtmlTree

Main Root

func I

func I(a string, c ...interface{}) *HtmlTree

func Img

func Img(a string) *HtmlTree

func Input

func Input(a string) *HtmlTree

func Label

func Label(a string, c ...interface{}) *HtmlTree

func Legend

func Legend(a string, c ...interface{}) *HtmlTree

func Li

func Li(a string, c ...interface{}) *HtmlTree
func Link(a string) *HtmlTree

func Main

func Main(a string, c ...interface{}) *HtmlTree

func Map

func Map(a string, c ...interface{}) *HtmlTree

func Meta

func Meta(a string) *HtmlTree

func Meter

func Meter(a string, c ...interface{}) *HtmlTree
func Nav(a string, c ...interface{}) *HtmlTree

func Noscript

func Noscript(a string, c ...interface{}) *HtmlTree

func Null added in v1.1.0

func Null(c ...interface{}) *HtmlTree

Null tag is a special case and does not correspond to any valid HTML tag. When rendered it returns its content with no enclosing tag, e.g. Null(Br(“),Br(“)) --> <br><br> . It is defined in goht to support injecting a list of elements into an existing tag as JavaScript innerHTML content.

func Object

func Object(a string, c ...interface{}) *HtmlTree

func Ol

func Ol(a string, c ...interface{}) *HtmlTree

func Optgroup

func Optgroup(a string, c ...interface{}) *HtmlTree

func Option

func Option(a string, c ...interface{}) *HtmlTree

func Output

func Output(a string, c ...interface{}) *HtmlTree

func P

func P(a string, c ...interface{}) *HtmlTree

func Param

func Param(a string) *HtmlTree

func Pre

func Pre(a string, c ...interface{}) *HtmlTree

func Progress

func Progress(a string, c ...interface{}) *HtmlTree

func S

func S(a string, c ...interface{}) *HtmlTree

func Samp

func Samp(a string, c ...interface{}) *HtmlTree

func Script

func Script(a string, c ...interface{}) *HtmlTree

func Section

func Section(a string, c ...interface{}) *HtmlTree

func Select

func Select(a string, c ...interface{}) *HtmlTree

func Small

func Small(a string, c ...interface{}) *HtmlTree

func Source

func Source(a string) *HtmlTree

func Span

func Span(a string, c ...interface{}) *HtmlTree

func Strong

func Strong(a string, c ...interface{}) *HtmlTree

func Style

func Style(a string, c ...interface{}) *HtmlTree

Style is a special case in the sense that the only valid content is one or more strings of CSS. At this time there's no check to complain about other content.

func Sub

func Sub(a string, c ...interface{}) *HtmlTree

func Summary added in v1.1.2

func Summary(a string, c ...interface{}) *HtmlTree

func Sup

func Sup(a string, c ...interface{}) *HtmlTree

func Table

func Table(a string, c ...interface{}) *HtmlTree

func Tbody

func Tbody(a string, c ...interface{}) *HtmlTree

func Td

func Td(a string, c ...interface{}) *HtmlTree

func Textarea

func Textarea(a string, c ...interface{}) *HtmlTree

func Tfoot

func Tfoot(a string, c ...interface{}) *HtmlTree

func Th

func Th(a string, c ...interface{}) *HtmlTree

func Thead

func Thead(a string, c ...interface{}) *HtmlTree

func Title

func Title(a string, c ...interface{}) *HtmlTree

func Tr

func Tr(a string, c ...interface{}) *HtmlTree

func Track

func Track(a string) *HtmlTree

func U

func U(a string, c ...interface{}) *HtmlTree

func Ul

func Ul(a string, c ...interface{}) *HtmlTree

func Video

func Video(a string, c ...interface{}) *HtmlTree

func (*HtmlTree) CheckAttributes

func (e *HtmlTree) CheckAttributes(perrs *[]AttributeErrors)

CheckAttributes walks through an ElementTree and checks each tag to verify that the attribute names associated with the tag are valid for that tag. It returns a slice AttributeErrors. The slice will be empty if no errors were found.

Directories

Path Synopsis
cmd
gohtify
gohtify reads html fragments from stdin and emits goht code on stdout.
gohtify reads html fragments from stdin and emits goht code on stdout.

Jump to

Keyboard shortcuts

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