aboutsummaryrefslogtreecommitdiff
path: root/formatter
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2023-09-02 18:49:53 +0200
committerThomas Voss <mail@thomasvoss.com> 2023-09-08 23:16:19 +0200
commit643623dbecdc1ccb6f3ac77e4ebabdc6ca1d8d06 (patch)
treea9d6b50ad7263e792bc276f765ada74a5661a8b1 /formatter
Genesis commit
Diffstat (limited to 'formatter')
-rw-r--r--formatter/formatter.go104
1 files changed, 104 insertions, 0 deletions
diff --git a/formatter/formatter.go b/formatter/formatter.go
new file mode 100644
index 0000000..96e19d1
--- /dev/null
+++ b/formatter/formatter.go
@@ -0,0 +1,104 @@
+package formatter
+
+import (
+ "fmt"
+ "unicode"
+
+ "git.thomasvoss.com/gsp/parser"
+)
+
+var stringEscapes = map[rune]string{
+ '"': "&quot;",
+ '&': "&amp;",
+ '<': "&lt;",
+}
+
+func PrintHtml(ast parser.AstNode) {
+ if ast.Type == parser.Text {
+ fmt.Print(ast.Text)
+ return
+ }
+
+ if ast.Type == parser.Normal {
+ fmt.Printf("<%s", ast.Text)
+
+ // Classes are grouped together with ‘class="…"’, so we need
+ // special handling.
+ classes := []string{}
+ notClasses := []parser.Attr{}
+
+ for _, a := range ast.Attrs {
+ if a.Key == "class" {
+ classes = append(classes, a.Value)
+ } else {
+ notClasses = append(notClasses, a)
+ }
+ }
+
+ if len(classes) > 0 {
+ fmt.Printf(" class=\"%s", classes[0])
+ for _, c := range classes[1:] {
+ fmt.Printf(" %s", c)
+ }
+ fmt.Print("\"")
+ }
+
+ for _, a := range notClasses {
+ fmt.Printf(" %s", a.Key)
+ if a.Value == "" {
+ break
+ }
+ fmt.Print("=\"")
+ for _, r := range a.Value {
+ if v, ok := stringEscapes[r]; ok {
+ fmt.Print(v)
+ } else {
+ fmt.Printf("%c", r)
+ }
+ }
+ fmt.Print("\"")
+ }
+
+ fmt.Print(">")
+ }
+
+ if len(ast.Children) == 0 {
+ return
+ }
+
+ for i, n := range ast.Children {
+ if n.Type == parser.Text {
+ if i == 0 {
+ n.Text = trimLeftSpaces(n.Text)
+ }
+
+ if i == len(ast.Children)-1 {
+ n.Text = trimRightSpaces(n.Text)
+ }
+ }
+
+ PrintHtml(n)
+ }
+
+ if ast.Type == parser.Normal {
+ fmt.Printf("</%s>", ast.Text)
+ }
+}
+
+func trimLeftSpaces(s string) string {
+ i := 0
+ rs := []rune(s)
+ for i < len(s) && unicode.IsSpace(rs[i]) {
+ i++
+ }
+ return string(rs[i:])
+}
+
+func trimRightSpaces(s string) string {
+ rs := []rune(s)
+ i := len(rs) - 1
+ for i >= 0 && unicode.IsSpace(rs[i]) {
+ i--
+ }
+ return string(rs[:i+1])
+}