Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@
# vendor/

# Go workspace file
go.work
# go.work
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ require (
github.com/mdm-code/scanner v1.2.1
github.com/pelletier/go-toml/v2 v2.1.0
)

require github.com/stretchr/testify v1.10.0 // indirect
3 changes: 2 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
6 changes: 6 additions & 0 deletions go.work
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
go 1.24.0

use (
.
./tqweb
)
42 changes: 42 additions & 0 deletions tqweb/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
GO=go
GOFLAGS=-mod=vendor
HTMX_VERSION?=2.0.8
# NOTE
# ====
# #1 The master version of the Javascript code fom the go-wasm-http-server has
# been updated since the version v2.2.1. If for any reason it might be necessary
# to revert to the version used in Go code, here is a quick shell script to
# pull the version from the go.mod file.
#
# #2 The master version seems not to work right with Go 1.24.0.
#
GO_WASM_HTTP_SERVER_VERSION?=$(shell\
grep go-wasm-http-server go.mod |\
cut -d' ' -f3\
)
# GO_WASM_HTTP_SERVER_VERSION?=master
# ====

# export CGO_ENABLED=0
export GOOS=js
export GOARCH=wasm

ifndef VERBOSE
.SILENT:
endif

.PHONY: assets build serve

.PHONY: .ONESHELL
.ONESHELL:

assets:
cp $$(go env GOROOT)/lib/wasm/wasm_exec.js wasm_exec.js
curl https://cdn.jsdelivr.net/npm/htmx.org@$(HTMX_VERSION)/dist/htmx.min.js > htmx.min.js
curl https://cdn.jsdelivr.net/gh/nlepage/go-wasm-http-server@$(GO_WASM_HTTP_SERVER_VERSION)/sw.js > sw.js

build:
$(GO) build $(GOFLAGS) -o api.wasm .

serve:
$(shell goexec 'http.ListenAndServe(`:18080`, http.FileServer(http.Dir(`.`)))')
16 changes: 16 additions & 0 deletions tqweb/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module github.com/mdm-code/tqweb

go 1.24.0

require (
github.com/mdm-code/tq/v2 v2.4.0
github.com/nlepage/go-wasm-http-server/v2 v2.2.1
)

require (
github.com/hack-pad/safejs v0.1.1 // indirect
github.com/mdm-code/scanner v1.2.1 // indirect
github.com/nlepage/go-js-promise v1.0.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/stretchr/testify v1.10.0 // indirect
)
29 changes: 29 additions & 0 deletions tqweb/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/hack-pad/safejs v0.1.1 h1:d5qPO0iQ7h2oVtpzGnLExE+Wn9AtytxIfltcS2b9KD8=
github.com/hack-pad/safejs v0.1.1/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio=
github.com/mdm-code/scanner v1.2.1 h1:GZ1DYAkhTXK+M4AG65L5fnl5eUt7M6XDAYBVZNH+cBc=
github.com/mdm-code/scanner v1.2.1/go.mod h1:ut94FGYZVrQk7uBkf0vJ0ngKuJbdkTEDnmY07ZI8yb0=
github.com/mdm-code/tq/v2 v2.4.0 h1:vjrQfjRROhzquRSjPCrYGdlXTAqZSOdwS6/62hRsfrA=
github.com/mdm-code/tq/v2 v2.4.0/go.mod h1:VfOFONplmcxx0EXu8rLZYpC8dOJg76EYnwbnXL9R4ZA=
github.com/nlepage/go-js-promise v1.0.0 h1:K7OmJ3+0BgWJ2LfXchg2sI6RDr7AW/KWR8182epFwGQ=
github.com/nlepage/go-js-promise v1.0.0/go.mod h1:bdOP0wObXu34euibyK39K1hoBCtlgTKXGc56AGflaRo=
github.com/nlepage/go-wasm-http-server/v2 v2.2.1 h1:4tzhSb3HKQ3Ykt2TPfqEnmcPfw8n1E8agv4OzAyckr8=
github.com/nlepage/go-wasm-http-server/v2 v2.2.1/go.mod h1:r8j7cEOeUqNp+c+C52sNuWaFTvvT/cNqIwBuEtA36HA=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
1 change: 1 addition & 0 deletions tqweb/htmx.min.js

Large diffs are not rendered by default.

77 changes: 77 additions & 0 deletions tqweb/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<script src="https://cdn.tailwindcss.com"></script>
<script src="htmx.min.js"></script>
<script>
navigator.serviceWorker.register("worker.js");
</script>
</head>
<body class="bg-[#000000] text-gray-100 min-h-screen">
<div class="flex flex-col min-h-screen">
<main class="flex flex-1 overflow-hidden">
<form class="flex w-full" id="tq-form">
<section class="w-1/2 border-r border-gray-700 flex flex-col gap-4 p-4">
<div class="border border border-gray-700 bg-[#171717] rounded" id="tq-form-field-query">
<header class="border-b border-gray-700 px-4 py-2">
<h2 class="text-sm font-semibold tracking-widest text-gray-200">
QUERY
</h2>
</header>
<div class="h-32">
<textarea
class="w-full h-full bg-transparent text-sm text-gray-100 px-4 py-2 resize-none focus:outline-none"
name="query"
id="query"
hx-post="api/process"
hx-trigger="input changed delay:1000ms"
hx-sync="this:replace"
hx-swap="outerHTML"
hx-target="#output"
></textarea>
</div>
</div>
<div class="flex-1 border border-gray-700 bg-[#171717] rouded flex flex-col" id="tq-form-field-input">
<header class="border-b border-gray-700 px-4 py-2">
<h2 class="text-sm font-semibold tracking-widest text-gray-200">
TOML
</h2>
</header>
<div class="flex-1">
<textarea
class="w-full h-full bg-transparent text-sm text-gray-100 px-4 py-2 resize-none focus:outline-none"
name="input"
id="input"
hx-post="api/process"
hx-trigger="input changed delay:1000ms"
hx-sync="this:replace"
hx-swap="outerHTML"
hx-target="#output"
></textarea>
</div>
</div>
</section>
<section class="w-1/2 flex flex-col p-4">
<div class="flex-1 border border-gray-700 bg-[#171717] rounded flex flex-col" id="tq-form-field-output">
<header class="border-b border-gray-700 px-4 py-2">
<h2 class="text-sm font-semibold tracking-widest text-gray-200">
OUTPUT
</h2>
</header>
<div class="flex-1">
<textarea
class="w-full h-full bg-transparent text-sm text-gray-100 px-4 py-2 resize-none focus:outline-none"
name="output"
id="output"
readonly
></textarea>
</div>
</div>
</section>
</form>
</main>
</div>
</body>
</html>
57 changes: 57 additions & 0 deletions tqweb/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//go:build js && wasm

package main

import (
"bytes"
_ "embed"
"html/template"
"net/http"
"strings"

"github.com/mdm-code/tq/v2"
"github.com/mdm-code/tq/v2/toml"
wasmhttp "github.com/nlepage/go-wasm-http-server/v2"
)

/*
TODO:
1. Tq config for GoTOML is sent from the frontend selection component.
- Checkboxes: send true if checked.
- Buttons: on click, keep highlighted and add to the payload.
2. The config and TQ has to be instantiated with each call.
3. Curl tailwind css scripts.
*/

var (
//go:embed views/index.html
index string
indexT = template.Must(template.New("index").Parse(index))
)

func main() {
conf := toml.GoTOMLConf{}
goToml := toml.NewGoTOML(conf)
adapter := toml.NewAdapter(goToml)
tq := tq.New(adapter)

http.HandleFunc("/process", func(w http.ResponseWriter, r *http.Request) {
var output bytes.Buffer
var data struct{ Output string }
input := r.FormValue("input")
query := r.FormValue("query")
err := tq.Run(strings.NewReader(input), &output, query)
if err != nil {
data.Output = err.Error()
} else {
data.Output = output.String()
}
if err := indexT.ExecuteTemplate(w, "output", data); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})

wasmhttp.Serve(nil)

select {}
}
42 changes: 42 additions & 0 deletions tqweb/sw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
function registerWasmHTTPListener(wasm, { base, cacheName, passthrough, args = [] } = {}) {
let path = new URL(registration.scope).pathname
if (base && base !== '') path = `${trimEnd(path, '/')}/${trimStart(base, '/')}`

const handlerPromise = new Promise(setHandler => {
self.wasmhttp = {
path,
setHandler,
}
})

const go = new Go()
go.argv = [wasm, ...args]
const source = cacheName
? caches.open(cacheName).then((cache) => cache.match(wasm)).then((response) => response ?? fetch(wasm))
: caches.match(wasm).then(response => (response) ?? fetch(wasm))
WebAssembly.instantiateStreaming(source, go.importObject).then(({ instance }) => go.run(instance))

addEventListener('fetch', e => {
if (passthrough?.(e.request)) {
e.respondWith(fetch(e.request))
return;
}

const { pathname } = new URL(e.request.url)
if (!pathname.startsWith(path)) return

e.respondWith(handlerPromise.then(handler => handler(e.request)))
})
}

function trimStart(s, c) {
let r = s
while (r.startsWith(c)) r = r.slice(c.length)
return r
}

function trimEnd(s, c) {
let r = s
while (r.endsWith(c)) r = r.slice(0, -c.length)
return r
}
8 changes: 8 additions & 0 deletions tqweb/views/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{{ block "output" . }}
<textarea
class="w-full h-full bg-transparent text-sm text-gray-100 px-4 py-2 resize-none focus:outline-none"
name="output"
id="output"
readonly
>{{ .Output }}</textarea>
{{ end }}
Loading
Loading