Skip to content

Commit

Permalink
Add test for ToHTML
Browse files Browse the repository at this point in the history
  • Loading branch information
radulucut committed Dec 13, 2023
1 parent e11397c commit 61d35db
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 22 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# htnoml

Experimental DSL that compiles to HTML.
Experimental alternative to HTML

### Example

Expand All @@ -14,7 +14,7 @@ Experimental DSL that compiles to HTML.
{:link rel[stylesheet] href[css/style.css]}
}
{:body
{class[container main] > This HTnoML syntax}
{class[container main] > This is HTnoML syntax}
}
}
```
1 change: 1 addition & 0 deletions fixtures/basic.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<html><head><meta charset="utf-8" /><title> This is a HTML5 template</title><meta name="description" content="This is a HTML5 template" /><meta name="author" content="Radu Lucut" /><link rel="stylesheet" href="css/style.css" /></head><body><div class="container main"> This is HTnoML syntax</div></body></html>
4 changes: 2 additions & 2 deletions example.htnoml → fixtures/basic.htnoml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
{:link rel[stylesheet] href[css/style.css]}
}
{:body
{class[container main] > This HTnoML syntax}
{class[container main] > This is HTnoML syntax}
}
}
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/radulucut/htnoml

go 1.20

require github.com/google/go-cmp v0.6.0 // indirect
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
64 changes: 53 additions & 11 deletions parser.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
package htnoml

import "io"

type Node struct {
ElementType *Chunk
Text *Chunk // Only for text nodes
Attributes []Attribute // Only for element nodes
Children []Node // Only for element nodes
}
import (
"io"
)

type Chunk struct {
Start int
Expand All @@ -19,6 +14,13 @@ type Attribute struct {
Value *Chunk
}

type Node struct {
ElementType *Chunk
Text *Chunk // Only for text nodes
Attributes []Attribute // Only for element nodes
Children []Node // Only for element nodes
}

type TokenType byte

const (
Expand Down Expand Up @@ -54,7 +56,42 @@ func NewParser(reader io.ReadSeeker) (*Parser, error) {
}, nil
}

func (p *Parser) Parse() {
func (p *Parser) ToHTML() string {
if p.node == nil {
p.parse()
}
return p.nodeToHTML(p.node, true)
}

func (p *Parser) nodeToHTML(node *Node, isRoot bool) string {
if node.Text != nil {
return string(p.buf[node.Text.Start:node.Text.End])
}
children := ""
for _, child := range node.Children {
children += p.nodeToHTML(&child, false)
}
if isRoot {
return children
}
attributes := ""
for _, attr := range node.Attributes {
attributes += " " + string(p.buf[attr.Name.Start:attr.Name.End])
if attr.Value != nil {
attributes += "=" + "\"" + string(p.buf[attr.Value.Start:attr.Value.End]) + "\""
}
}
if node.ElementType == nil {
return "<div" + attributes + ">" + children + "</div>"
}
tag := string(p.buf[node.ElementType.Start:node.ElementType.End])
if children == "" && isVoidElement(tag) {
return "<" + tag + attributes + " />"
}
return "<" + tag + attributes + ">" + children + "</" + tag + ">"
}

func (p *Parser) parse() {
p.node = &Node{}
childParentMap := map[*Node]*Node{}
curr := p.node
Expand All @@ -64,10 +101,12 @@ func (p *Parser) Parse() {
continue
}
if t.Type == TokenTypeReserved && p.buf[t.Start] == ':' {
t = p.nextToken()
curr.ElementType = &Chunk{
Start: t.Start,
End: t.End,
}
continue
}
if t.Type == TokenTypeIdentifier {
name := &Chunk{
Expand All @@ -93,6 +132,7 @@ func (p *Parser) Parse() {
Name: name,
Value: value,
})
continue
}
if t.Type == TokenTypeReserved && p.buf[t.Start] == '{' {
curr.Children = append(curr.Children, Node{})
Expand All @@ -119,6 +159,7 @@ func (p *Parser) Parse() {
End: t.End,
},
})
continue
}
}
}
Expand Down Expand Up @@ -154,7 +195,7 @@ func (p *Parser) readNextToken() *Token {
return &Token{
Type: TokenTypeWhitespace,
Start: start,
End: p.pos - 1,
End: p.pos,
}
}
if p.isReserved(p.buf[p.pos]) {
Expand All @@ -163,6 +204,7 @@ func (p *Parser) readNextToken() *Token {
return &Token{
Type: TokenTypeReserved,
Start: p.pos - 1,
End: p.pos,
}
}
start := p.pos
Expand All @@ -173,7 +215,7 @@ func (p *Parser) readNextToken() *Token {
return &Token{
Type: TokenTypeIdentifier,
Start: start,
End: p.pos - 1,
End: p.pos,
}
}

Expand Down
20 changes: 13 additions & 7 deletions parser_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package htnoml

import (
"log"
"os"
"testing"

"github.com/google/go-cmp/cmp"
)

func TestParser(t *testing.T) {
t.Run("Parse", func(t *testing.T) {
t.Run("should return correct html", func(t *testing.T) {
f, err := os.Open("example.htnoml")
t.Run("ToHTML", func(t *testing.T) {
t.Run("basic.htnoml - should return correct html", func(t *testing.T) {
f, err := os.Open("fixtures/basic.htnoml")
if err != nil {
t.Fatal(err)
}
Expand All @@ -18,9 +19,14 @@ func TestParser(t *testing.T) {
if err != nil {
t.Fatal(err)
}
p.Parse()
log.Printf("%+v", p.node)
// TODO: assert
html := p.ToHTML()
expected, err := os.ReadFile("fixtures/basic.html")
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(string(expected), html); diff != "" {
t.Errorf("ToHTML() mismatch (-want +got):\n%s", diff)
}
})
})
}
10 changes: 10 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package htnoml

func isVoidElement(tag string) bool {
switch tag {
case "area", "base", "br", "col", "embed", "hr", "img", "input", "link",
"meta", "param", "source", "track", "wbr":
return true
}
return false
}

0 comments on commit 61d35db

Please sign in to comment.