From d1dee7bc3db980792b1159cfecbf1e575915495a Mon Sep 17 00:00:00 2001 From: Leon Mika Date: Fri, 26 Sep 2025 17:28:30 +1000 Subject: [PATCH] Added a Go template playground --- .idea/webtools.iml | 7 ++- Makefile | 1 + cmds/gotemplate/main.go | 92 ++++++++++++++++++++++++++++++++++++++ site/clocks/main.js | 5 ++- site/gotemplate/index.html | 33 ++++++++++++++ site/gotemplate/main.js | 8 ++++ site/gotemplate/style.css | 3 ++ site/index.html | 1 + 8 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 cmds/gotemplate/main.go create mode 100644 site/gotemplate/index.html create mode 100644 site/gotemplate/main.js create mode 100644 site/gotemplate/style.css diff --git a/.idea/webtools.iml b/.idea/webtools.iml index 5e764c4..11646b4 100644 --- a/.idea/webtools.iml +++ b/.idea/webtools.iml @@ -1,6 +1,11 @@ - + + + + diff --git a/Makefile b/Makefile index 3b92b15..ff98715 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ clean: build.wasm: mkdir target/wasm GOOS=js GOARCH=wasm go build -o target/wasm/clocks.wasm ./cmds/clocks + GOOS=js GOARCH=wasm go build -o target/wasm/gotemplate.wasm ./cmds/gotemplate cp $(GOROOT)/lib/wasm/wasm_exec.js target/wasm/. .Phony: build.site diff --git a/cmds/gotemplate/main.go b/cmds/gotemplate/main.go new file mode 100644 index 0000000..d5e148c --- /dev/null +++ b/cmds/gotemplate/main.go @@ -0,0 +1,92 @@ +//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) +} diff --git a/site/clocks/main.js b/site/clocks/main.js index ba74c81..8e287c9 100644 --- a/site/clocks/main.js +++ b/site/clocks/main.js @@ -5,4 +5,7 @@ const go = new Go(); WebAssembly.instantiateStreaming(fetch("/wasm/clocks.wasm"), go.importObject) .then((result) => { go.run(result.instance); - }); \ No newline at end of file + }); + + +document.a \ No newline at end of file diff --git a/site/gotemplate/index.html b/site/gotemplate/index.html new file mode 100644 index 0000000..69e4e08 --- /dev/null +++ b/site/gotemplate/index.html @@ -0,0 +1,33 @@ + + + + + + Go Template Playground - Tools + + + + +
+
+

Go Template Playground

+

Playground of text/template.

+
+
+
+
+ +
+
+ +
+ +
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/site/gotemplate/main.js b/site/gotemplate/main.js new file mode 100644 index 0000000..3fd1225 --- /dev/null +++ b/site/gotemplate/main.js @@ -0,0 +1,8 @@ +import "/wasm/wasm_exec.js"; + +const go = new Go(); + +WebAssembly.instantiateStreaming(fetch("/wasm/gotemplate.wasm"), go.importObject) + .then((result) => { + go.run(result.instance); + }); \ No newline at end of file diff --git a/site/gotemplate/style.css b/site/gotemplate/style.css new file mode 100644 index 0000000..9c74412 --- /dev/null +++ b/site/gotemplate/style.css @@ -0,0 +1,3 @@ +textarea { + height: 15rem; +} \ No newline at end of file diff --git a/site/index.html b/site/index.html index 9ab1ec8..3e33e42 100644 --- a/site/index.html +++ b/site/index.html @@ -21,6 +21,7 @@