# Packages
# README
GOX
Write reusable HTML in pure Go
package app
import . "github.com/creamsensation/gox"
func Page() string {
return Render(
Html(
Lang("en"),
Head(
Title(Text("Example app")),
Meta(Name("viewport"), Content("width=device-width,initial-scale=1.0")),
),
Body(
H1(Text("Example page")),
P(Text("Example paragraph")),
),
),
)
}
Main reason to use GOX
If you love Go, as I do, you love power && simplicity, then GOX is just for you.
Feel free to test, submit issues, etc...
Features
- Elements
- Attributes
- Shared
- Raw
- Text
- Fragment
- Modifiers
- Functions
- Directives
- Factories
- Plugins
- Components
Elements
You can create HTML structure with built-in elements or create your own with factory function.
Library should contains most of elements.
Html(
Head(
Title()
),
Body(
Div()
),
)
Attributes
If you need to add attribute to element. You can create your own attributes with factory function.
Library should contains most attributes.
Button(
Type("submit"),
CustomData("track", "submit-button"),
)
// data-*
CustomData("*", "...")
Shared
Some elements and attributes have same names, here comes shared nodes.
All shared nodes have default node type, which can be modified with modifier node.
Because of sharing, you need to use node for content, instead of writing simple string argument.
Shared nodes are: cite, data, form, label, slot, span, style, title.
Label(Text("E-mail"))
Style(Element(), Raw("body{background:red;}"))
Raw
Sometimes you need to write custom HTML, use styles, or anything else...
Raw("body{background:blue;}")
Raw("<div>raw custom</div>")
Text
Only purpose is to write text content.
Div(Text("Example"))
Fragment
The fragment has purpose to group nodes.
Fragment(
Div(),
Span(),
H1(),
)
Modifiers
When you use shared nodes, sometimes you need to change node type, then you have to use modifiers.
Label(Attribute(), Text("example label"))
Style(Element(), Raw(".text{color:red;}"))
Functions
Render
Render function transforms GOX nodes to string.
You can use multiple nodes as arguments, it automatically wraps them with Fragment.
Render(
Div(Text("example")),
)
Write
Write function transforms GOX nodes and write them as content to provided writer as bytes.
Write(
w,
Div(Text("example")),
)
Directives
Directives are functions, which can be used for various operations.
If
someCondition := ...
If(someCondition, Div(Text("render if condition is true")))
Range
someSlice := []int{1,2,3}
Range(someSlice, func(item int) Node {
return Div(Text(item))
})
Factories
Custom element
Create custom reusable element.
SomeCustomElement := CreateElement("x-custom")
Render(SomeCustomElement(Text("example content")))
Custom attribute
Create custom reusable attribute.
SomeCustomAttribute := CreateAttribute[string]("x-custom")
Render(Div(SomeCustomAttribute("custom attribute conttent"), Text("example content")))
Plugins
Custom Go struct can be used as GOX plugin, exists only one rule, must have Node method, which return gox.Node interface.
type CustomPlugin struct {
Value string
}
func (p CustomPlugin) Node() gox.Node {
return Div(Text(p.Value))
}
Render(
Html(
Body(
CustomPlugin{ Value: "example" },
)
)
)
Components
Power of GOX approach is to create simple reusable components like React, Svelte, etc...
func UiButton(content string) Node {
return Button(
Class("bg-blue-400", "text-white", "rounded"),
Type("button"),
CustomData("test", "test-id"),
Text(content),
)
}
FAQ
Why did I create the library?
I was tired of JS / TS ecosystem, so much bloat and I wanted something simple, yet powerful, like Go, for frontend.
What will be next steps?
I want to create the whole ecosystem, which will use GOX as primary view system