diff --git a/example/index.html b/example/index.html new file mode 100644 index 0000000..af6d2e8 --- /dev/null +++ b/example/index.html @@ -0,0 +1,32 @@ + + + + + + + + + + \ No newline at end of file diff --git a/example/main.go b/example/main.go index c5bff7c..da18ba3 100644 --- a/example/main.go +++ b/example/main.go @@ -3,16 +3,21 @@ package main import ( "fmt" + _ "embed" + t "git.iwakura.rip/grng/tiramisu" webview "github.com/webview/webview_go" ) +//go:embed index.html +var html string + func main() { app := t.New(t.TiramisuOptions{ Debug: true, - Width: 1200, - Height: 800, - Title: "Tiramisu Example", + Width: 800, + Height: 600, + Title: "Tiramisu", Hints: webview.HintFixed, }) @@ -27,23 +32,6 @@ func main() { return "Hello, unknown!", nil }) - app.HTML(` - - - -

Tiramisu Example

-

Click the button to see a greeting:

- - - - - - `) + app.HTML(html) }) } diff --git a/runtime/index.d.ts b/runtime/index.d.ts index afb0fc3..a6fe80f 100644 --- a/runtime/index.d.ts +++ b/runtime/index.d.ts @@ -1,8 +1,15 @@ declare global { interface Window { - invoke: (name: string, ...args: any[]) => Promise; + __TIRAMISU_INTERNAL_invoke: (name: string, ...args: any[]) => Promise; + __TIRAMISU_INTERNAL_readFile: (path: string) => Promise; + __TIRAMISU_INTERNAL_readDir: (path: string) => Promise; + tiramisu: { invoke: (name: string, ...args: any[]) => Promise; + fs: { + readFile(path: string): Promise; + readDir(path: string): Promise; + } }; } } diff --git a/runtime/preload.ts b/runtime/preload.ts index 99e6691..ec9dad9 100644 --- a/runtime/preload.ts +++ b/runtime/preload.ts @@ -1,5 +1,9 @@ const tiramisu = { - invoke: window.invoke + invoke: window.__TIRAMISU_INTERNAL_invoke, + fs: { + readFile: window.__TIRAMISU_INTERNAL_readFile, + readDir: window.__TIRAMISU_INTERNAL_readDir + } } window.tiramisu = tiramisu \ No newline at end of file diff --git a/tiramisu.go b/tiramisu.go index 8b42e76..5fc900d 100644 --- a/tiramisu.go +++ b/tiramisu.go @@ -3,6 +3,7 @@ package tiramisu import ( "embed" "fmt" + "os" wv "github.com/webview/webview_go" ) @@ -38,7 +39,8 @@ func New(o TiramisuOptions) *Tiramisu { func (t *Tiramisu) Run(fn func()) { defer t.w.Destroy() t.w.Dispatch(func() { - t.injectJS() + t.loadJSRuntime() + t.loadGoRuntime() if fn != nil { fn() @@ -85,20 +87,24 @@ func (t *Tiramisu) Evalf(js string, args ...any) { func (t *Tiramisu) HTML(html string) { t.w.SetHtml(html) - t.injectJS() + t.loadJSRuntime() + t.loadGoRuntime() } //go:embed runtime/out/* var runtimeFS embed.FS -func (t *Tiramisu) injectJS() { +func (t *Tiramisu) loadJSRuntime() { 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) { +} + +func (t *Tiramisu) loadGoRuntime() { + t.bind("__TIRAMISU_INTERNAL_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]) @@ -108,4 +114,43 @@ func (t *Tiramisu) injectJS() { } 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 + }) }