Created
August 20, 2024 06:17
-
-
Save hasenj/4fcaaf05320d863234a4c0c84828dd04 to your computer and use it in GitHub Desktop.
html builder idea
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 `"` | |
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(¤t.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(¤t.children, block) | |
prev = current | |
current = ¤t.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