Added a Go template playground
All checks were successful
/ publish (push) Successful in 55s

This commit is contained in:
Leon Mika 2025-09-26 17:28:30 +10:00
parent e4ab1358e9
commit d1dee7bc3d
8 changed files with 148 additions and 2 deletions

View file

@ -1,6 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="Go" enabled="true">
<buildTags>
<option name="os" value="js" />
<option name="arch" value="wasm" />
</buildTags>
</component>
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />

View file

@ -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

92
cmds/gotemplate/main.go Normal file
View file

@ -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)
}

View file

@ -6,3 +6,6 @@ WebAssembly.instantiateStreaming(fetch("/wasm/clocks.wasm"), go.importObject)
.then((result) => {
go.run(result.instance);
});
document.a

View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Go Template Playground - Tools</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
<link rel="stylesheet" href="style.css">
</head>
<body class="container">
<header>
<hgroup>
<h1>Go Template Playground</h1>
<p>Playground of <a href="https://pkg.go.dev/text/template" target="_blank">text/template</a>.</p>
</hgroup>
</header>
<div class="inputs grid">
<div class="text-display">
<textarea id="template" placeholder="Template code">Hello, {{.what}}</textarea>
<div id="template-message"></div>
</div>
<div class="text-display">
<textarea id="data" placeholder="JSON data">{"what":"world"}</textarea>
<div id="data-message"></div>
</div>
</div>
<div class="output">
<div id="output"></div>
</div>
<script src="main.js" type="module"></script>
</body>
</html>

8
site/gotemplate/main.js Normal file
View file

@ -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);
});

View file

@ -0,0 +1,3 @@
textarea {
height: 15rem;
}

View file

@ -21,6 +21,7 @@
<ul>
<li><a href="/clocks/">Clocks</a></li>
<li><a href="/freelens-logo/">Freelens Logo Maker</a></li>
<li><a href="/gotemplate/">Go Template Playground</a></li>
<li><a href="/2lcc/">Two-letter Country Codes</a></li>
</ul>
</main>