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")),
),
),
)
}
If you love Go, as I do, you love power && simplicity, then GOX is just for you.
Feel free to test, submit issues, etc...
- Elements
- Attributes
- Shared
- Raw
- Text
- Fragment
- Modifiers
- Functions
- Directives
- Factories
- Plugins
- Components
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()
),
)
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("*", "...")
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;}"))
Sometimes you need to write custom HTML, use styles, or anything else...
Raw("body{background:blue;}")
Raw("<div>raw custom</div>")
Only purpose is to write text content.
Div(Text("Example"))
The fragment has purpose to group nodes.
Fragment(
Div(),
Span(),
H1(),
)
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;}"))
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 function transforms GOX nodes and write them as content to provided writer as bytes.
Write(
w,
Div(Text("example")),
)
Directives are functions, which can be used for various operations.
someCondition := ...
If(someCondition, Div(Text("render if condition is true")))
someSlice := []int{1,2,3}
Range(someSlice, func(item int) Node {
return Div(Text(item))
})
Create custom reusable element.
SomeCustomElement := CreateElement("x-custom")
Render(SomeCustomElement(Text("example content")))
Create custom reusable attribute.
SomeCustomAttribute := CreateAttribute[string]("x-custom")
Render(Div(SomeCustomAttribute("custom attribute conttent"), Text("example content")))
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" },
)
)
)
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),
)
}
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