init tiramisu
This commit is contained in:
commit
967b77c51c
10 changed files with 253 additions and 0 deletions
52
.air.toml
Normal file
52
.air.toml
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
root = "."
|
||||||
|
testdata_dir = "testdata"
|
||||||
|
tmp_dir = "tmp"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
args_bin = []
|
||||||
|
bin = "tmp\\main.exe"
|
||||||
|
cmd = "go build -o ./tmp/main.exe ./example"
|
||||||
|
delay = 1000
|
||||||
|
exclude_dir = ["assets", "tmp", "vendor", "testdata", "runtime/out", "node_modules", "dist"]
|
||||||
|
exclude_file = []
|
||||||
|
exclude_regex = ["_test.go", "out"]
|
||||||
|
exclude_unchanged = true
|
||||||
|
follow_symlink = false
|
||||||
|
full_bin = ""
|
||||||
|
include_dir = []
|
||||||
|
include_ext = ["go", "tpl", "tmpl", "html", "js", "ts"]
|
||||||
|
include_file = []
|
||||||
|
kill_delay = "0s"
|
||||||
|
log = "build-errors.log"
|
||||||
|
poll = false
|
||||||
|
poll_interval = 0
|
||||||
|
post_cmd = []
|
||||||
|
pre_cmd = ["bunx tsc -p ./runtime"]
|
||||||
|
rerun = false
|
||||||
|
rerun_delay = 500
|
||||||
|
send_interrupt = false
|
||||||
|
stop_on_error = false
|
||||||
|
|
||||||
|
[color]
|
||||||
|
app = ""
|
||||||
|
build = "yellow"
|
||||||
|
main = "magenta"
|
||||||
|
runner = "green"
|
||||||
|
watcher = "cyan"
|
||||||
|
|
||||||
|
[log]
|
||||||
|
main_only = false
|
||||||
|
silent = false
|
||||||
|
time = false
|
||||||
|
|
||||||
|
[misc]
|
||||||
|
clean_on_exit = false
|
||||||
|
|
||||||
|
[proxy]
|
||||||
|
app_port = 0
|
||||||
|
enabled = false
|
||||||
|
proxy_port = 0
|
||||||
|
|
||||||
|
[screen]
|
||||||
|
clear_on_rebuild = false
|
||||||
|
keep_scroll = true
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
tmp/
|
||||||
|
out/
|
4
README.md
Normal file
4
README.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# 🍥 tiramisu
|
||||||
|
> ` is tiramisu a cake or a pie?`
|
||||||
|
|
||||||
|
Build modern, cross-platform desktop apps in HTML + Go from one codebase.
|
49
example/main.go
Normal file
49
example/main.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
t "github.com/grngxd/tiramisu"
|
||||||
|
webview "github.com/webview/webview_go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := t.New(t.TiramisuOptions{
|
||||||
|
Debug: true,
|
||||||
|
Width: 1200,
|
||||||
|
Height: 800,
|
||||||
|
Title: "Tiramisu Example",
|
||||||
|
Hints: webview.HintFixed,
|
||||||
|
})
|
||||||
|
|
||||||
|
app.Run(func() {
|
||||||
|
app.Bind("hello", func(args ...any) (any, error) {
|
||||||
|
if len(args) == 0 {
|
||||||
|
return "Hello, World!", nil
|
||||||
|
}
|
||||||
|
if len(args) == 1 {
|
||||||
|
return fmt.Sprintf("Hello, %s!", args[0]), nil
|
||||||
|
}
|
||||||
|
return "Hello, unknown!", nil
|
||||||
|
})
|
||||||
|
|
||||||
|
app.HTML(`
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1>Tiramisu Example</h1>
|
||||||
|
<p>Click the button to see a greeting:</p>
|
||||||
|
<button onclick="greet()">Greet</button>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function greet() {
|
||||||
|
tiramisu.invoke("hello", "world")
|
||||||
|
.then(response => alert(response))
|
||||||
|
.catch(console.error)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`)
|
||||||
|
})
|
||||||
|
}
|
5
go.mod
Normal file
5
go.mod
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
module github.com/grngxd/tiramisu
|
||||||
|
|
||||||
|
go 1.23.4
|
||||||
|
|
||||||
|
require github.com/webview/webview_go v0.0.0-20240831120633-6173450d4dd6 // indirect
|
2
go.sum
Normal file
2
go.sum
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
github.com/webview/webview_go v0.0.0-20240831120633-6173450d4dd6 h1:VQpB2SpK88C6B5lPHTuSZKb2Qee1QWwiFlC5CKY4AW0=
|
||||||
|
github.com/webview/webview_go v0.0.0-20240831120633-6173450d4dd6/go.mod h1:yE65LFCeWf4kyWD5re+h4XNvOHJEXOCOuJZ4v8l5sgk=
|
11
runtime/index.d.ts
vendored
Normal file
11
runtime/index.d.ts
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
invoke: (name: string, ...args: any[]) => Promise<any>;
|
||||||
|
tiramisu: {
|
||||||
|
invoke: (name: string, ...args: any[]) => Promise<any>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { };
|
||||||
|
|
5
runtime/preload.ts
Normal file
5
runtime/preload.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
const tiramisu = {
|
||||||
|
invoke: window.invoke
|
||||||
|
}
|
||||||
|
|
||||||
|
window.tiramisu = tiramisu
|
12
runtime/tsconfig.json
Normal file
12
runtime/tsconfig.json
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "esnext",
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"strict": false,
|
||||||
|
"declaration": true,
|
||||||
|
"outDir": "./out",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true
|
||||||
|
},
|
||||||
|
}
|
111
tiramisu.go
Normal file
111
tiramisu.go
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
package tiramisu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
wv "github.com/webview/webview_go"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TiramisuOptions struct {
|
||||||
|
Debug bool
|
||||||
|
Width int
|
||||||
|
Height int
|
||||||
|
Title string
|
||||||
|
Hints wv.Hint
|
||||||
|
}
|
||||||
|
|
||||||
|
type FuncHandler func(args ...any) (any, error)
|
||||||
|
|
||||||
|
type Tiramisu struct {
|
||||||
|
w wv.WebView
|
||||||
|
funcs map[string]FuncHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(o TiramisuOptions) *Tiramisu {
|
||||||
|
w := wv.New(o.Debug)
|
||||||
|
t := &Tiramisu{
|
||||||
|
w: w,
|
||||||
|
funcs: make(map[string]FuncHandler),
|
||||||
|
}
|
||||||
|
|
||||||
|
w.SetSize(o.Width, o.Height, o.Hints)
|
||||||
|
w.SetTitle(o.Title)
|
||||||
|
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tiramisu) Run(fn func()) {
|
||||||
|
defer t.w.Destroy()
|
||||||
|
t.w.Dispatch(func() {
|
||||||
|
t.injectJS()
|
||||||
|
|
||||||
|
if fn != nil {
|
||||||
|
fn()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
t.w.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tiramisu) bind(name string, fn FuncHandler) {
|
||||||
|
t.w.Bind(name, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tiramisu) Bind(name string, fn FuncHandler) {
|
||||||
|
if _, exists := t.funcs[name]; exists {
|
||||||
|
panic(fmt.Sprintf("function %s is already bound", name))
|
||||||
|
}
|
||||||
|
|
||||||
|
t.funcs[name] = fn
|
||||||
|
t.bind(name, func(args ...any) (any, error) {
|
||||||
|
return t.invoke(name, args...)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tiramisu) invoke(name string, args ...any) (any, error) {
|
||||||
|
fn, ok := t.funcs[name]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("function %s not found", name)
|
||||||
|
}
|
||||||
|
result, err := fn(args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error invoking function %s: %w", name, err)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tiramisu) Eval(js string) {
|
||||||
|
t.w.Eval(js)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tiramisu) Evalf(js string, args ...any) {
|
||||||
|
fmt := fmt.Sprintf(js, args...)
|
||||||
|
t.w.Eval(fmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tiramisu) HTML(html string) {
|
||||||
|
t.w.SetHtml(html)
|
||||||
|
t.injectJS()
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:embed runtime/out/*
|
||||||
|
var runtimeFS embed.FS
|
||||||
|
|
||||||
|
func (t *Tiramisu) injectJS() {
|
||||||
|
js, err := runtimeFS.ReadFile("runtime/out/preload.js")
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to read preload.js: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
t.w.Eval(string(js))
|
||||||
|
t.bind("invoke", func(args ...any) (any, error) {
|
||||||
|
name, ok := args[0].(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("first argument must be a string, got %T", args[0])
|
||||||
|
}
|
||||||
|
if len(args) == 1 {
|
||||||
|
return t.invoke(name)
|
||||||
|
}
|
||||||
|
return t.invoke(name, args[1:]...)
|
||||||
|
})
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue