Skip to content

Instantly share code, notes, and snippets.

@david-saint
Created December 18, 2020 12:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save david-saint/0a559a8d1a3d9aa9b683d0e86a2b8034 to your computer and use it in GitHub Desktop.
Save david-saint/0a559a8d1a3d9aa9b683d0e86a2b8034 to your computer and use it in GitHub Desktop.
package parser
const (
ElementTextNode = "text"
)
[
{
"element": "html",
"attributes": [
{
"key": "lang",
"value": "en"
}
],
"children": [
{
"element": "head",
"children": [
{
"element": "meta",
"attributes": [
{
"key": "charset",
"value": "UTF-8"
}
]
},
{
"element": "meta",
"attributes": [
{
"key": "name",
"value": "viewport"
},
{
"key": "content",
"value": "width=device-width, initial-scale=1.0"
}
]
},
{
"element": "title",
"children": [
{
"element": "text",
"value": "Fuck you Somto"
}
]
}
]
},
{
"element": "body",
"children": [
{
"element": "h1",
"children": [
{
"element": "text",
"value": "Methods"
}
]
},
{
"element": "p",
"children": [
{
"element": "text",
"value": "Although this is better than the first version of this code, we can improve it significantly by using a special type of function known as a method"
}
]
}
]
}
]
}
]
package main
import (
"calhoun/appscript/parser"
"fmt"
"os"
)
func main() {
file, _ := os.Open("in.json")
defer file.Close()
fmt.Println(parser.Parse(file))
}
package parser
import (
"encoding/json"
"fmt"
"html"
"os"
"strings"
"sync"
)
type DomNode struct {
Element string
Value string
Attributes []AttrNode
Css []CssNode
Children []DomNode
}
type CssNode struct {
Property string
Value string
}
type AttrNode struct {
Key string
Value string
}
type Stringer interface {
String() string
}
func (c CssNode) String() string {
return fmt.Sprintf("%s: %s;", c.Property, c.Value)
}
func (a AttrNode) String() string {
return fmt.Sprintf("%s=\"%s\"", a.Key, a.Value)
}
func Parse(f *os.File) (r string, err error) {
var domTree []DomNode
var wg sync.WaitGroup
decoder := json.NewDecoder(f)
err = decoder.Decode(&domTree)
if err != nil {
return
}
for _, node := range domTree {
wg.Add(1)
go func() {
r += node.parse()
wg.Done()
}()
}
wg.Wait()
return
}
func (t *DomNode) parse() string {
if t.Element == ElementTextNode {
return t.Value
}
var style string
var attributes string
var wg sync.WaitGroup
tag := html.EscapeString(t.Element)
html := "<" + tag
if len(t.Css) > 0 {
style = GenerateStringable(" ", t.Css...)
html += " style=\"" + style + "\""
}
if len(t.Attributes) > 0 {
attributes = GenerateStringable(" ", t.Attributes...)
html += attributes
}
if len(t.Children) == 0 {
html += "/>"
return html
}
html += ">"
for _, node := range t.Children {
wg.Add(1)
go func() {
html += node.parse()
wg.Done()
}()
wg.Wait()
}
html += "</" + tag + ">"
return html
}
func GenerateStringable(separator string, s ...Stringer) string {
var list []string
for _, kv := range s {
list = append(list, kv.String())
}
return strings.Join(list[:], separator)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment