htmgo/h/render.go

125 lines
2.4 KiB
Go
Raw Normal View History

2024-01-22 15:22:16 +00:00
package h
import (
"fmt"
"strings"
2024-09-11 00:52:18 +00:00
"time"
2024-01-22 15:22:16 +00:00
)
const FlagSkip = "skip"
2024-09-11 00:52:18 +00:00
const FlagText = "text"
const FlagRaw = "raw"
const FlagAttributeList = "attribute-list"
2024-01-22 15:22:16 +00:00
type Builder struct {
builder *strings.Builder
root *Node
}
func (page Builder) render() {
page.renderNode(page.root)
}
func insertAttribute(node *Node, name string, value string) {
existing := node.attributes[name]
if existing != "" {
node.attributes[name] = existing + " " + value
} else {
node.attributes[name] = value
}
}
func (page Builder) renderNode(node *Node) {
if node.tag != "" {
page.builder.WriteString(fmt.Sprintf("<%s", node.tag))
index := 0
if node.attributes == nil {
node.attributes = map[string]string{}
}
for _, child := range node.children {
2024-09-11 00:52:18 +00:00
if child == nil {
continue
}
2024-01-22 15:22:16 +00:00
if child.tag == "class" {
insertAttribute(node, "class", child.value)
child.tag = FlagSkip
}
2024-09-11 00:52:18 +00:00
if child.tag == FlagAttributeList {
for _, gc := range child.children {
for key, value := range gc.attributes {
insertAttribute(node, key, value)
}
gc.tag = FlagSkip
}
child.tag = FlagSkip
}
2024-01-22 15:22:16 +00:00
if child.tag == "attribute" {
for key, value := range child.attributes {
insertAttribute(node, key, value)
}
child.tag = FlagSkip
}
}
for key, value := range node.attributes {
if index == 0 {
page.builder.WriteString(" ")
}
page.builder.WriteString(key)
page.builder.WriteString("=")
page.builder.WriteRune('"')
page.builder.WriteString(value)
page.builder.WriteRune('"')
if index < len(node.attributes) {
page.builder.WriteRune(' ')
}
index += 1
}
page.builder.WriteString(">")
if node.text != "" {
page.builder.WriteString(node.text)
}
}
for _, child := range node.children {
2024-09-11 00:52:18 +00:00
if child == nil {
continue
}
if child.tag == FlagText {
page.builder.WriteString(child.text)
continue
}
if child.tag == FlagRaw {
page.builder.WriteString(child.value)
continue
}
2024-01-22 15:22:16 +00:00
if child.tag != FlagSkip {
page.renderNode(child)
}
}
if node.tag != "" {
page.builder.WriteString(fmt.Sprintf("</%s>", node.tag))
}
}
func Render(node *Node) string {
2024-09-11 00:52:18 +00:00
start := time.Now()
2024-01-22 15:22:16 +00:00
builder := strings.Builder{}
page := Builder{
builder: &builder,
root: node,
}
page.render()
d := page.builder.String()
2024-09-11 00:52:18 +00:00
duration := time.Since(start)
fmt.Printf("render took %s\n", duration)
2024-01-22 15:22:16 +00:00
return d
}