This commit is contained in:
parent
e4ab1358e9
commit
d1dee7bc3d
|
@ -1,6 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module type="WEB_MODULE" version="4">
|
<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">
|
<component name="NewModuleRootManager">
|
||||||
<content url="file://$MODULE_DIR$" />
|
<content url="file://$MODULE_DIR$" />
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
|
|
1
Makefile
1
Makefile
|
@ -12,6 +12,7 @@ clean:
|
||||||
build.wasm:
|
build.wasm:
|
||||||
mkdir target/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/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/.
|
cp $(GOROOT)/lib/wasm/wasm_exec.js target/wasm/.
|
||||||
|
|
||||||
.Phony: build.site
|
.Phony: build.site
|
||||||
|
|
92
cmds/gotemplate/main.go
Normal file
92
cmds/gotemplate/main.go
Normal 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)
|
||||||
|
}
|
|
@ -6,3 +6,6 @@ WebAssembly.instantiateStreaming(fetch("/wasm/clocks.wasm"), go.importObject)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
go.run(result.instance);
|
go.run(result.instance);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
document.a
|
33
site/gotemplate/index.html
Normal file
33
site/gotemplate/index.html
Normal 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
8
site/gotemplate/main.js
Normal 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);
|
||||||
|
});
|
3
site/gotemplate/style.css
Normal file
3
site/gotemplate/style.css
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
textarea {
|
||||||
|
height: 15rem;
|
||||||
|
}
|
|
@ -21,6 +21,7 @@
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="/clocks/">Clocks</a></li>
|
<li><a href="/clocks/">Clocks</a></li>
|
||||||
<li><a href="/freelens-logo/">Freelens Logo Maker</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>
|
<li><a href="/2lcc/">Two-letter Country Codes</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</main>
|
</main>
|
||||||
|
|
Loading…
Reference in a new issue