Skip to content

Commit

Permalink
misc: write html to Writer instead of returning the string, update RE…
Browse files Browse the repository at this point in the history
…ADME.md
  • Loading branch information
radulucut committed Jul 31, 2024
1 parent d786b8f commit 42354fd
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 28 deletions.
33 changes: 30 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# htnoml
# HTnoML

Experimental alternative to HTML
HTML-like DSL that that can be converted into HTML.

![Test](https://github.com/radulucut/htnoml/actions/workflows/test.yml/badge.svg)

### Example
### Example of HTnoML syntax

```htnoml
{:html
Expand All @@ -20,3 +20,30 @@ Experimental alternative to HTML
}
}
```

### Usage

```go
package main

import (
"fmt"
"github.com/radulucut/htnoml"
)

func main() {
f, err := os.Open("example.htnoml")
if err != nil {
panic(err)
}
defer f.Close()

p, err := NewParser(f)
if err != nil {
panic(err)
}

w := new(bytes.Buffer)
p.ToHTML(w) // writes the HTML to the buffer
}
```
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ module github.com/radulucut/htnoml

go 1.20

require github.com/google/go-cmp v0.6.0 // indirect
require github.com/google/go-cmp v0.6.0
55 changes: 33 additions & 22 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,39 +56,50 @@ func NewParser(reader io.ReadSeeker) (*Parser, error) {
}, nil
}

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

func (p *Parser) nodeToHTML(node *Node, isRoot bool) string {
func (p *Parser) nodeToHTML(w io.Writer, node *Node, isRoot bool) {
if node.Text != nil {
return string(p.buf[node.Text.Start:node.Text.End])
w.Write(p.buf[node.Text.Start:node.Text.End])
return
}
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]) + "\""
var tag []byte
if !isRoot {
w.Write([]byte{'<'})
if node.ElementType == nil {
tag = []byte{'d', 'i', 'v'}
} else {
tag = p.buf[node.ElementType.Start:node.ElementType.End]
}
w.Write(tag)
for _, attr := range node.Attributes {
w.Write([]byte{' '})
w.Write(p.buf[attr.Name.Start:attr.Name.End])
if attr.Value != nil {
w.Write([]byte{'=', '"'})
w.Write(p.buf[attr.Value.Start:attr.Value.End])
w.Write([]byte{'"'})
}
}
if len(node.Children) == 0 && isVoidElement(string(tag)) {
w.Write([]byte{' ', '/', '>'})
return
}
w.Write([]byte{'>'})
}
if node.ElementType == nil {
return "<div" + attributes + ">" + children + "</div>"
for _, child := range node.Children {
p.nodeToHTML(w, &child, false)
}
tag := string(p.buf[node.ElementType.Start:node.ElementType.End])
if children == "" && isVoidElement(tag) {
return "<" + tag + attributes + " />"
if !isRoot {
w.Write([]byte{'<', '/'})
w.Write(tag)
w.Write([]byte{'>'})
}
return "<" + tag + attributes + ">" + children + "</" + tag + ">"
}

func (p *Parser) parse() {
Expand Down
6 changes: 4 additions & 2 deletions parser_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package htnoml

import (
"bytes"
"os"
"testing"

Expand All @@ -19,12 +20,13 @@ func TestParser(t *testing.T) {
if err != nil {
t.Fatal(err)
}
html := p.ToHTML()
w := new(bytes.Buffer)
p.ToHTML(w)
expected, err := os.ReadFile("fixtures/basic.html")
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(string(expected), html); diff != "" {
if diff := cmp.Diff(string(expected), w.String()); diff != "" {
t.Errorf("ToHTML() mismatch (-want +got):\n%s", diff)
}
})
Expand Down

0 comments on commit 42354fd

Please sign in to comment.