gohtx

package module
v0.10.0 Latest Latest
Warning

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

Go to latest
Published: Nov 27, 2022 License: MIT Imports: 11 Imported by: 0

README

gohtx

A small framework for creating and serving 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.
  • Supports using Go's embed.FS package to compile an entire website into a single binary executable.
  • Includes support for HTMX hypertext and Bulma CSS

HTMX and Bulma

Gohtx is a fork of my goht package. It embeds htmx and bulma css to enable easy creation of responsive, attractive web applications almost entirely in Go. A single function call creates the necessary <head> content to freely use the added attributes and classes. The use of htmx and bulma are entirely optional, of course.

The Skeleton

Gohtx includes a complete skeleton app you can copy from the cmd/skeleton subdirectory as a starting point. For a quick and easy start, clone a local copy of this repo, cd to cmd/skeleton and run

go build
./skeleton

Then open a browser tab to localhost:8080

The skeleton uses htmx and bulma. Study the webpages.go file to see how they are used with gohtx. Both htmx and bulma are thoroughly documented on their respective web sites. You should consult those to understand their attributes and classes.

Creating HTML with gohtx

I recommend keeping your HTML generation in a separate file and importing gohtx as follows:

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

Dot imports are generally discouraged as bad style but they make sense for this package. It saves you having to put gohtx. 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.

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 gohtx 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 gohtx these tag have only the a argument, e.g

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

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

The Null Tag

Null is a pseudo tag that 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

Gohtx 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

Gohtx 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

Gohtx now includes attribute checking in the Render function to help you catch misspelled or misused attributes, so be sure to check and log the errors returned by Render()

Alternatives

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

  • vugu

  • vecty

  • html/template

    Note: Gohtx is compatible with Go templates in the sense that you can use both within the same app to generate content. For boilerplate content that needs simple substitutions at run time, templates are fast and convenient.

Documentation

Overview

Gohtx is an extended version of github.com/Michael-F-Ellis/goht. It embeds HTMX, HyperScript and Bulma CSS in the package binary.

Index

Constants

View Source
const GohtxAssetPath = "/gohtx/" // default route to embedded assets.

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.

View Source
var HxAttrs []string = []string{

	"hx-boost",
	"hx-get",
	"hx-post",
	"hx-push-url",
	"hx-select",
	"hx-select-oob",
	"hx-swap",
	"hx-swap-oob",
	"hx-target",
	"hx-trigger",
	"hx-vals",

	"hx-confirm",
	"hx-delete",
	"hx-disable",
	"hx-disinherit",
	"hx-encoding",
	"hx-ext",
	"hx-headers",
	"hx-history-elt",
	"hx-include",
	"hx-indicator",
	"hx-params",
	"hx-patch",
	"hx-preserve",
	"hx-prompt",
	"hx-put",
	"hx-replace-url",
	"hx-request",
	"hx-sse",
	"hx-sync",
	"hx-vars",
	"hx-ws",
	"_",
	"script",
}

HxAttrs is a slice of string containing the names of all valid htmx attributes. The names ad descriptions are taken from https://htmx.org/reference/

Functions

func AddGohtxAssetHandler added in v0.10.0

func AddGohtxAssetHandler()

AddGohtxAssetHandler is a convenience function that adds an http.Handler to process requests for assets in the embedded FS. Use this to avoid having to know about the path string.

func Gohtify

func Gohtify(htext string, gofmt bool, 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 GohtxFS

func GohtxFS() embed.FS

GohtxFS returns the embedded filesystem containing htmx.min.js and bulma.css. To serve them, do something like: fs := GohtxFS() buf, err := fs.ReadFile("htmx.min.js")

func Ids

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

A, when rendered, returns a <a> element with the given attributes and content.

func Address

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

Address, when rendered, returns a <address> element with the given attributes and content.

func Area

func Area(a string) *HtmlTree

Area, when rendered, returns an <area> element with the given attributes.

func Article

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

Article, when rendered, returns an <article> element with the given attributes and content.

func Aside

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

Aside, when rendered, returns an <aside> element with the given attributes and content.

func Audio

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

Audio, when rendered, returns a <audio> element with the given attributes and content.

func B

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

B, when rendered, returns a <b> element with the given attributes and content.

func Blockquote

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

Blockquote, when rendered, returns a <blockquote> element with the given attributes and content.

func Body

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

Body, when rendered, returns a <body> element with the given attributes and content.

func Br

func Br(a string) *HtmlTree

Br, when rendered, returns a <br> element with the given attributes and content.

func Button

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

Button, when rendered, returns a <button> element with the given attributes and content.

func Canvas

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

Canvas, when rendered, returns a <canvas> element with the given attributes and content.

func Caption

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

Caption, when rendered, returns a <caption> element with the given attributes and content.

func Cite

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

Cite, when rendered, returns a <cite> element with the given attributes and content.

func Code

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

Code, when rendered, returns a <code> element with the given attributes and content.

func Col

func Col(a string) *HtmlTree

Col, when rendered, returns a <col> element with the given attributes and content.

func Comment added in v0.10.0

func Comment(a string) *HtmlTree

Comment

func CustomHeadContent added in v0.9.0

func CustomHeadContent(htmx, hyperscript, bulma bool) (h *HtmlTree)

CustomHeadContent returns the same Meta elements you would typically include in the <head> element of a responsive web page and allows you to choose which, if any, of htmx, hyperscript, and bulma to include.

func Datalist

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

Datalist, when rendered, returns a <datalist> element with the given attributes and content.

func Dd

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

Dd, when rendered, returns a <dd> element with the given attributes and content.

func DefaultHeadContent added in v0.8.0

func DefaultHeadContent() (h *HtmlTree)

DefaultHeadContent calls CustomHeadContent specifying htmx and bulma without hyperscript.

func Details

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

Details, when rendered, returns a <details> element with the given attributes and content.

func Dialog

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

As of 2021, <dialog> is supported by Chrome, Edge & Opera but not by FireFox and Safari. Dialog, when rendered, returns a <dialog> element with the given attributes and content.

func Div

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

Div, when rendered, returns a <div> element with the given attributes and content.

func Dl

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

Dl, when rendered, returns a <dl> element with the given attributes and content.

func Dt

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

Dt, when rendered, returns a <dt> element with the given attributes and content.

func Em

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

Em, when rendered, returns a <em> element with the given attributes and content.

func Embed

func Embed(a string) *HtmlTree

Embed, when rendered, returns an <embed> element with the given attributes.

func Fieldset

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

Fieldset, when rendered, returns a <fieldset> element with the given attributes and content.

func Figcaption

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

Figcaption, when rendered, returns a <figcaption> element with the given attributes and content.

func Figure

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

Figure, when rendered, returns a <figure> element with the given attributes and content.

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

Footer, when rendered, returns a <footer> element with the given attributes and content.

func Form

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

Form, when rendered, returns a <form> element with the given attributes and content.

func H1

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

H1, when rendered, returns a <h1> element with the given attributes and content.

func H2

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

H2, when rendered, returns a <h2> element with the given attributes and content.

func H3

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

H3, when rendered, returns a <h3> element with the given attributes and content.

func H4

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

H4, when rendered, returns a <h4> element with the given attributes and content.

func H5

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

H5, when rendered, returns a <h5> element with the given attributes and content.

func H6

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

H6, when rendered, returns a <h6> element with the given attributes and content.

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

Head, when rendered, returns a <head> element with the given attributes and content.

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

Header, when rendered, returns a <header> element with the given attributes and content.

func Hr

func Hr(a string) *HtmlTree

Html, when rendered, returns an <hr> element with the given attributes.

func Html

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

Main Root

func I

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

I, when rendered, returns an <i> element with the given attributes and content.

func Img

func Img(a string) *HtmlTree

Img, when rendered, returns a <img> element with the given attributes.

func Input

func Input(a string) *HtmlTree

Input, when rendered, returns a <input> element with the given attributes and content.

func Label

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

Label, when rendered, returns a <label> element with the given attributes and content.

func Legend

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

Legend, when rendered, returns a <legend> element with the given attributes and content.

func Li

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

Li, when rendered, returns an <li> element with the given attributes and content.

func Link(a string) *HtmlTree

Link, when rendered, returns a <link> element with the given attributes and content.

func Main

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

Main, when rendered, returns an <main> element with the given attributes and content.

func Map

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

Map, when rendered, returns a <map> element with the given attributes and content.

func Meta

func Meta(a string) *HtmlTree

Meta, when rendered, returns a <meta> element with the given attributes.

func Meter

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

Meter, when rendered, returns a <meter> element with the given attributes and content.

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

Nav, when rendered, returns a <nav> element with the given attributes and content.

func Noscript

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

Noscript, when rendered, returns a <noscript> element with the given attributes and content.

func Null

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

Object, when rendered, returns a <object> element with the given attributes and content.

func Ol

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

Ol, when rendered, returns an <ol> element with the given attributes and content.

func Optgroup

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

Optgroup, when rendered, returns a <optgroup> element with the given attributes and content.

func Option

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

Option, when rendered, returns a <option> element with the given attributes and content.

func Output

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

Output, when rendered, returns a <output> element with the given attributes and content.

func P

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

P, when rendered, returns an <p> element with the given attributes and content.

func Param

func Param(a string) *HtmlTree

Param, when rendered, returns a <param> element with the given attributes.

func Pre

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

Pre, when rendered, returns a <pre> element with the given attributes and content.

func Progress

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

Progress, when rendered, returns a <progress> element with the given attributes and content.

func S

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

S, when rendered, returns an <s> element with the given attributes and content.

func Samp

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

Samp, when rendered, returns a <samp> element with the given attributes and content.

func Script

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

Script, when rendered, returns a <script> element with the given attributes and content.

func Section

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

Section, when rendered, returns a <section> element with the given attributes and content.

func Select

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

Select, when rendered, returns a <select> element with the given attributes and content.

func Small

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

Small, when rendered, returns a <small> element with the given attributes and content.

func Source

func Source(a string) *HtmlTree

Source, when rendered, returns a <source> element with the given attributes.

func Span

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

Span, when rendered, returns a <span> element with the given attributes and content.

func Strong

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

Strong, when rendered, returns a <strong> element with the given attributes and content.

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

Sub, when rendered, returns a <sub> element with the given attributes and content.

func Summary

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

Summary, when rendered, returns a <summary> element with the given attributes and content.

func Sup

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

Sup, when rendered, returns a <sup> element with the given attributes and content.

func Table

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

Table, when rendered, returns a <table> element with the given attributes and content.

func Tbody

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

Tbody, when rendered, returns a <tbody> element with the given attributes and content.

func Td

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

Td, when rendered, returns a <td> element with the given attributes and content.

func Textarea

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

Textarea, when rendered, returns a <textarea> element with the given attributes and content.

func Tfoot

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

Tfoot, when rendered, returns a <tfoot> element with the given attributes and content.

func Th

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

Th, when rendered, returns a <th> element with the given attributes and content.

func Thead

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

Thead, when rendered , returns a <thead> element with the given attributes and content.

func Title

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

Title, when rendered, returns a <title> element with the given attributes and content.

func Tr

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

Tr, when rendered, returns a <tr> element with the given attributes and content.

func Track

func Track(a string) *HtmlTree

Track, when rendered, returns a <track> element with the given attributes.

func U

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

U, when rendered, returns a <u> element with the given attributes and content.

func Ul

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

Ul, when rendered, returns a <ul> element with the given attributes and content.

func Video

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

Video, when rendered, returns a <video> element with the given attributes and content.

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.
playground
The gohtx app skeleton demonstrates the essentials of using gohtx, htmx, hyperscript and bulma to build a single binary containing a server and embedded content to generate and serve a responsive application.
The gohtx app skeleton demonstrates the essentials of using gohtx, htmx, hyperscript and bulma to build a single binary containing a server and embedded content to generate and serve a responsive application.
skeleton
The gohtx app skeleton demonstrates the essentials of using gohtx, htmx, hyperscript and bulma to build a single binary containing a server and embedded content to generate and serve a responsive application.
The gohtx app skeleton demonstrates the essentials of using gohtx, htmx, hyperscript and bulma to build a single binary containing a server and embedded content to generate and serve a responsive application.

Jump to

Keyboard shortcuts

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