1
0
View components in pure Go, that render to HTML 5. https://www.gomponents.com
Go to file
Markus Wüstenberg f387a71230
Add generic Map implementation (#108)
Instead of waiting for a good time to switch the `Map` implementation,
I've decided to just offer two implementations: one for Go versions
before 1.18, and one for 1.18 and onwards. This is achieved using build
tags in the source files.

This is obviously a breaking change for consumers of this library that
use Go 1.18 and onwards.

See #88
2022-09-22 09:41:06 +02:00
.github/workflows Add Go 1.19 to test matrix (#107) 2022-09-21 10:42:07 +02:00
components Mark the assert test helpers as such (#90) 2021-10-06 20:49:43 +02:00
examples Add generic Map implementation (#108) 2022-09-22 09:41:06 +02:00
html Mark the assert test helpers as such (#90) 2021-10-06 20:49:43 +02:00
http Add http.Adapt function (#92) 2021-10-08 15:00:20 +02:00
internal/assert Use output of strings.Builder in assert.Equal (#106) 2022-09-21 10:37:44 +02:00
svg Mark the assert test helpers as such (#90) 2021-10-06 20:49:43 +02:00
.editorconfig Add better example in readme (#16) 2020-09-23 22:05:59 +02:00
.gitignore Add Makefile (#4) 2020-09-18 13:57:04 +02:00
CONTRIBUTING.md Add contributing instructions (#33) 2020-10-23 14:32:55 +02:00
CONTRIBUTORS.md Add contributors file 2021-06-18 10:09:00 +02:00
go.mod Add generic Map implementation (#108) 2022-09-22 09:41:06 +02:00
gomponents_generic_test.go Add generic Map implementation (#108) 2022-09-22 09:41:06 +02:00
gomponents_generic.go Add generic Map implementation (#108) 2022-09-22 09:41:06 +02:00
gomponents_non_generic_test.go Add generic Map implementation (#108) 2022-09-22 09:41:06 +02:00
gomponents_non_generic.go Add generic Map implementation (#108) 2022-09-22 09:41:06 +02:00
gomponents_test.go Add generic Map implementation (#108) 2022-09-22 09:41:06 +02:00
gomponents.go Add generic Map implementation (#108) 2022-09-22 09:41:06 +02:00
LICENSE Update copyright year in license 2022-03-21 12:22:32 +01:00
Makefile Test using Go 1.17 (#91) 2021-10-06 20:51:31 +02:00
README.md Fix CI badge in Readme (#100) 2022-05-25 09:01:53 +00:00

Tired of complex template languages?

GoDoc Go codecov

Try view components in pure Go.

gomponents are view components written in pure Go. They render to HTML 5, and make it easy for you to build reusable components. So you can focus on building your app instead of learning yet another templating language.

The API may change until version 1 is reached.

Check out www.gomponents.com for an introduction.

Made in 🇩🇰 by maragu, maker of online Go courses.

Features

  • Build reusable view components
  • Write declarative HTML5 in Go without all the strings, so you get
    • Type safety
    • Auto-completion
    • Nice formatting with gofmt
  • Simple API that's easy to learn and use (you know most already if you know HTML)
  • No external dependencies

Usage

Get the library using go get:

go get -u github.com/maragudk/gomponents

The preferred way to use gomponents is with so-called dot-imports (note the dot before the gomponents/html import), to give you that smooth, native HTML feel:

package main

import (
	"net/http"

	g "github.com/maragudk/gomponents"
	c "github.com/maragudk/gomponents/components"
	. "github.com/maragudk/gomponents/html"
)

func main() {
	_ = http.ListenAndServe("localhost:8080", http.HandlerFunc(handler))
}

func handler(w http.ResponseWriter, r *http.Request) {
	_ = Page("Hi!", r.URL.Path).Render(w)
}

func Page(title, currentPath string) g.Node {
	return Doctype(
		HTML(
			Lang("en"),
			Head(
				TitleEl(g.Text(title)),
				StyleEl(Type("text/css"), g.Raw(".is-active{ font-weight: bold }")),
			),
			Body(
				Navbar(currentPath),
				H1(g.Text(title)),
				P(g.Textf("Welcome to the page at %v.", currentPath)),
			),
		),
	)
}

func Navbar(currentPath string) g.Node {
	return Nav(
		NavbarLink("/", "Home", currentPath),
		NavbarLink("/about", "About", currentPath),
	)
}

func NavbarLink(href, name, currentPath string) g.Node {
	return A(Href(href), c.Classes{"is-active": currentPath == href}, g.Text(name))
}

Some people don't like dot-imports, and luckily it's completely optional. If you don't like dot-imports, just use regular imports.

You could also use the provided HTML5 document template to simplify your code a bit:

package main

import (
	"net/http"

	g "github.com/maragudk/gomponents"
	c "github.com/maragudk/gomponents/components"
	. "github.com/maragudk/gomponents/html"
)

func main() {
	_ = http.ListenAndServe("localhost:8080", http.HandlerFunc(handler))
}

func handler(w http.ResponseWriter, r *http.Request) {
	_ = Page("Hi!", r.URL.Path).Render(w)
}

func Page(title, currentPath string) g.Node {
	return c.HTML5(c.HTML5Props{
		Title:    title,
		Language: "en",
		Head: []g.Node{
			StyleEl(Type("text/css"), g.Raw(".is-active{ font-weight: bold }")),
		},
		Body: []g.Node{
			Navbar(currentPath),
			H1(g.Text(title)),
			P(g.Textf("Welcome to the page at %v.", currentPath)),
		},
	})
}

func Navbar(currentPath string) g.Node {
	return Nav(
		NavbarLink("/", "Home", currentPath),
		NavbarLink("/about", "About", currentPath),
	)
}

func NavbarLink(href, name, currentPath string) g.Node {
	return A(Href(href), c.Classes{"is-active": currentPath == href}, g.Text(name))
}

For more complete examples, see the examples directory.

What's up with the specially named elements and attributes?

Unfortunately, there are four main name clashes in HTML elements and attributes, so they need an El or Attr suffix, respectively, to be able to co-exist in the same package in Go:

  • data (DataEl/DataAttr)
  • form (FormEl/FormAttr)
  • style (StyleEl/StyleAttr)
  • title (TitleEl/TitleAttr)