Skip to content

Instantly share code, notes, and snippets.

@hasenj
Created August 20, 2024 06:17
Show Gist options
  • Save hasenj/4fcaaf05320d863234a4c0c84828dd04 to your computer and use it in GitHub Desktop.
Save hasenj/4fcaaf05320d863234a4c0c84828dd04 to your computer and use it in GitHub Desktop.
html builder idea
package html_builder
import "core:fmt"
import "core:strings"
Attr :: struct {
name: string,
value: string,
}
Block :: struct {
type: string,
attrs: [dynamic]Attr,
children: [dynamic]Block,
text: string, // if children is nil
}
to_html :: proc(sb: ^strings.Builder, block: ^Block, level: int = 0) {
print_indent :: proc(sb: ^strings.Builder, level: int) {
for _ in 0..<level {
fmt.sbprint(sb, " ")
}
}
if block.type != "" {
print_indent(sb, level)
fmt.sbprintf(sb, "<%s", block.type)
for &attr in block.attrs {
// TODO: escape `"` characters in attr.value to `&quot;`
fmt.sbprintf(sb, " %s=\"%s\"", attr.name, attr.value)
}
fmt.sbprintf(sb, ">\n")
}
if len(block.children) > 0 {
for &block in block.children {
to_html(sb, &block, level + 1)
}
} else if block.text != "" {
print_indent(sb, level+1)
fmt.sbprint(sb, block.text)
fmt.sbprintln(sb)
}
if block.type != "" {
print_indent(sb, level)
fmt.sbprintf(sb, "</%s>\n", block.type)
}
}
// blocks builder
current: ^Block
begin :: proc(type: string) {
current = new(Block)
current.type = type
}
end :: proc() -> ^Block {
defer current = nil
return current
}
attr :: proc(name: string, value: string) {
append(&current.attrs, Attr{name, value})
}
text :: proc(t: string) {
current.text = t
}
@(deferred_out=_el_end)
el :: proc(type: string) -> (prev: ^Block) {
block := Block { type = type }
idx := len(current.children)
append(&current.children, block)
prev = current
current = &current.children[idx]
return prev
}
_el_end :: proc(prev: ^Block) {
current = prev
}
main :: proc() {
begin("html")
{
el("head")
{
el("title")
text("Test Document")
}
}
{
el("body")
{
el("div")
attr("class", "abc def")
{
el("p")
text("Hello World!")
}
}
}
doc := end()
sb: strings.Builder
to_html(&sb, doc)
fmt.println(strings.to_string(sb))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment