93 lines
2.1 KiB
Go
93 lines
2.1 KiB
Go
|
//go:build js
|
||
|
|
||
|
package main
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/json"
|
||
|
"syscall/js"
|
||
|
"text/template"
|
||
|
)
|
||
|
|
||
|
func main() {
|
||
|
regenChan := make(chan struct{})
|
||
|
go executeTemplate(regenChan)
|
||
|
|
||
|
eventListener := func(this js.Value, args []js.Value) interface{} {
|
||
|
ev := args[0]
|
||
|
ev.Call("preventDefault")
|
||
|
|
||
|
regenChan <- struct{}{}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
querySelector("#template").Call("addEventListener", "keyup", js.FuncOf(eventListener))
|
||
|
querySelector("#data").Call("addEventListener", "keyup", js.FuncOf(eventListener))
|
||
|
|
||
|
regenChan <- struct{}{}
|
||
|
<-make(chan struct{})
|
||
|
}
|
||
|
|
||
|
func executeTemplate(regenChan chan struct{}) {
|
||
|
templateEl := querySelector("#template")
|
||
|
dataEl := querySelector("#data")
|
||
|
outputEl := querySelector("#output")
|
||
|
|
||
|
tmplMessageEl := querySelector("#template-message")
|
||
|
dataMessageEl := querySelector("#data-message")
|
||
|
displayErrors := func(dataErr error, tmplErr error) {
|
||
|
if dataErr != nil {
|
||
|
dataMessageEl.Set("innerText", dataErr.Error())
|
||
|
} else {
|
||
|
dataMessageEl.Set("innerText", "")
|
||
|
}
|
||
|
if tmplErr != nil {
|
||
|
tmplMessageEl.Set("innerText", tmplErr.Error())
|
||
|
} else {
|
||
|
tmplMessageEl.Set("innerText", "")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var templateSource string
|
||
|
var tmpl *template.Template
|
||
|
setTemplateSource := func(newTemplateSource string) (*template.Template, error) {
|
||
|
if tmpl == nil || templateSource != newTemplateSource {
|
||
|
newTmpl := template.New("")
|
||
|
if _, err := newTmpl.Parse(newTemplateSource); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
tmpl = newTmpl
|
||
|
}
|
||
|
return tmpl, nil
|
||
|
}
|
||
|
|
||
|
var outBuf bytes.Buffer
|
||
|
for range regenChan {
|
||
|
templateValue := templateEl.Get("value").String()
|
||
|
dataValue := dataEl.Get("value").String()
|
||
|
|
||
|
var dataJson interface{}
|
||
|
dataErr := json.Unmarshal([]byte(dataValue), &dataJson)
|
||
|
tmplInst, tmplErr := setTemplateSource(templateValue)
|
||
|
|
||
|
if dataErr != nil || tmplErr != nil {
|
||
|
displayErrors(dataErr, tmplErr)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
outBuf.Reset()
|
||
|
if err := tmplInst.Execute(&outBuf, dataJson); err != nil {
|
||
|
displayErrors(nil, err)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
outputEl.Set("innerText", outBuf.String())
|
||
|
displayErrors(nil, nil)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func querySelector(query string) js.Value {
|
||
|
return js.Global().Get("document").Call("querySelector", query)
|
||
|
}
|