This commit is contained in:
grngxd 2025-06-16 23:46:07 +01:00
parent 3bee70b536
commit 6c84e18ce8
5 changed files with 103 additions and 27 deletions

32
example/index.html Normal file
View file

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<body>
<button onclick="greet()">Greet</button>
<button onclick="file()">Read File</button>
<button onclick="directory()">List Directory</button>
<script>
function greet() {
tiramisu.invoke("hello", "world")
.then(response => alert(response))
.catch(console.error)
}
function file() {
const filename = prompt("Enter the filename to read:");
if (!filename) return;
tiramisu.fs.readFile(filename)
.then(data => alert("File content: " + data))
.catch(error => alert("Error reading file: " + error.message));
}
function directory() {
const dirname = prompt("Enter the directory to list:");
if (!dirname) return;
tiramisu.fs.readDir(dirname)
.then(files => alert("Files: " + files.join(", ")))
.catch(error => alert("Error listing directory: " + error.message));
}
</script>
</body>
</html>

View file

@ -3,16 +3,21 @@ package main
import ( import (
"fmt" "fmt"
_ "embed"
t "git.iwakura.rip/grng/tiramisu" t "git.iwakura.rip/grng/tiramisu"
webview "github.com/webview/webview_go" webview "github.com/webview/webview_go"
) )
//go:embed index.html
var html string
func main() { func main() {
app := t.New(t.TiramisuOptions{ app := t.New(t.TiramisuOptions{
Debug: true, Debug: true,
Width: 1200, Width: 800,
Height: 800, Height: 600,
Title: "Tiramisu Example", Title: "Tiramisu",
Hints: webview.HintFixed, Hints: webview.HintFixed,
}) })
@ -27,23 +32,6 @@ func main() {
return "Hello, unknown!", nil return "Hello, unknown!", nil
}) })
app.HTML(` app.HTML(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>
`)
}) })
} }

9
runtime/index.d.ts vendored
View file

@ -1,8 +1,15 @@
declare global { declare global {
interface Window { interface Window {
invoke: (name: string, ...args: any[]) => Promise<any>; __TIRAMISU_INTERNAL_invoke: (name: string, ...args: any[]) => Promise<any>;
__TIRAMISU_INTERNAL_readFile: (path: string) => Promise<string>;
__TIRAMISU_INTERNAL_readDir: (path: string) => Promise<string[]>;
tiramisu: { tiramisu: {
invoke: (name: string, ...args: any[]) => Promise<any>; invoke: (name: string, ...args: any[]) => Promise<any>;
fs: {
readFile(path: string): Promise<string>;
readDir(path: string): Promise<string[]>;
}
}; };
} }
} }

View file

@ -1,5 +1,9 @@
const tiramisu = { const tiramisu = {
invoke: window.invoke invoke: window.__TIRAMISU_INTERNAL_invoke,
fs: {
readFile: window.__TIRAMISU_INTERNAL_readFile,
readDir: window.__TIRAMISU_INTERNAL_readDir
}
} }
window.tiramisu = tiramisu window.tiramisu = tiramisu

View file

@ -3,6 +3,7 @@ package tiramisu
import ( import (
"embed" "embed"
"fmt" "fmt"
"os"
wv "github.com/webview/webview_go" wv "github.com/webview/webview_go"
) )
@ -38,7 +39,8 @@ func New(o TiramisuOptions) *Tiramisu {
func (t *Tiramisu) Run(fn func()) { func (t *Tiramisu) Run(fn func()) {
defer t.w.Destroy() defer t.w.Destroy()
t.w.Dispatch(func() { t.w.Dispatch(func() {
t.injectJS() t.loadJSRuntime()
t.loadGoRuntime()
if fn != nil { if fn != nil {
fn() fn()
@ -85,20 +87,24 @@ func (t *Tiramisu) Evalf(js string, args ...any) {
func (t *Tiramisu) HTML(html string) { func (t *Tiramisu) HTML(html string) {
t.w.SetHtml(html) t.w.SetHtml(html)
t.injectJS() t.loadJSRuntime()
t.loadGoRuntime()
} }
//go:embed runtime/out/* //go:embed runtime/out/*
var runtimeFS embed.FS var runtimeFS embed.FS
func (t *Tiramisu) injectJS() { func (t *Tiramisu) loadJSRuntime() {
js, err := runtimeFS.ReadFile("runtime/out/preload.js") js, err := runtimeFS.ReadFile("runtime/out/preload.js")
if err != nil { if err != nil {
panic(fmt.Sprintf("failed to read preload.js: %v", err)) panic(fmt.Sprintf("failed to read preload.js: %v", err))
} }
t.w.Eval(string(js)) t.w.Eval(string(js))
t.bind("invoke", func(args ...any) (any, error) { }
func (t *Tiramisu) loadGoRuntime() {
t.bind("__TIRAMISU_INTERNAL_invoke", func(args ...any) (any, error) {
name, ok := args[0].(string) name, ok := args[0].(string)
if !ok { if !ok {
return nil, fmt.Errorf("first argument must be a string, got %T", args[0]) return nil, fmt.Errorf("first argument must be a string, got %T", args[0])
@ -108,4 +114,43 @@ func (t *Tiramisu) injectJS() {
} }
return t.invoke(name, args[1:]...) return t.invoke(name, args[1:]...)
}) })
t.bind("__TIRAMISU_INTERNAL_readFile", func(args ...any) (any, error) {
if len(args) != 1 {
return nil, fmt.Errorf("readFile expects exactly one argument, got %d", len(args))
}
filename, ok := args[0].(string)
if !ok {
return nil, fmt.Errorf("readFile expects a string argument, got %T", args[0])
}
data, err := os.ReadFile(filename)
if err != nil {
return nil, fmt.Errorf("error reading file %s: %w", filename, err)
}
return string(data), nil
})
t.bind("__TIRAMISU_INTERNAL_readDir", func(args ...any) (any, error) {
if len(args) != 1 {
return nil, fmt.Errorf("readDir expects exactly one argument, got %d", len(args))
}
dirname, ok := args[0].(string)
if !ok {
return nil, fmt.Errorf("readDir expects a string argument, got %T", args[0])
}
files, err := os.ReadDir(dirname)
if err != nil {
return nil, fmt.Errorf("error reading directory %s: %w", dirname, err)
}
var fileNames []string
for _, file := range files {
fileNames = append(fileNames, file.Name())
}
return fileNames, nil
})
} }