diff --git a/v2/internal/frontend/assetserver/assetserver_dev.go b/v2/internal/frontend/assetserver/assetserver_browser_dev.go similarity index 50% rename from v2/internal/frontend/assetserver/assetserver_dev.go rename to v2/internal/frontend/assetserver/assetserver_browser_dev.go index 8ab9ec918..ffe758c49 100644 --- a/v2/internal/frontend/assetserver/assetserver_dev.go +++ b/v2/internal/frontend/assetserver/assetserver_browser_dev.go @@ -21,63 +21,63 @@ import ( "os" ) -type AssetServer struct { - indexFile []byte +type BrowserAssetServer struct { runtimeJS []byte assetdir string appOptions *options.App } -func NewAssetServer(assetdir string, bindingsJSON string, appOptions *options.App) (*AssetServer, error) { - result := &AssetServer{ +func NewBrowserAssetServer(assetdir string, bindingsJSON string, appOptions *options.App) (*BrowserAssetServer, error) { + result := &BrowserAssetServer{ assetdir: assetdir, appOptions: appOptions, } - err := result.init() - if err != nil { - return nil, err - } - var buffer bytes.Buffer buffer.WriteString(`window.wailsbindings='` + bindingsJSON + `';` + "\n") buffer.Write(runtime.RuntimeDesktopJS) result.runtimeJS = buffer.Bytes() - err = result.init() - return result, err + return result, nil } -func (a *AssetServer) loadFileFromDisk(filename string) ([]byte, error) { +func (a *BrowserAssetServer) loadFileFromDisk(filename string) ([]byte, error) { return os.ReadFile(filepath.Join(a.assetdir, filename)) } -func (a *AssetServer) init() error { - var err error - a.indexFile, err = a.loadFileFromDisk("index.html") +func (a *BrowserAssetServer) processIndexHTML() ([]byte, error) { + indexHTML, err := a.loadFileFromDisk("index.html") if err != nil { - return err + return nil, err } - a.indexFile, err = injectHTML(string(a.indexFile), `
`) + indexHTML, err = injectHTML(string(indexHTML), ``) if err != nil { - return err + return nil, err } - a.indexFile, err = injectHTML(string(a.indexFile), ``) + wailsOptions, err := extractOptions(indexHTML) if err != nil { - return err + return nil, err } - a.indexFile, err = injectHTML(string(a.indexFile), ``) - if err != nil { - return err + if wailsOptions.disableRuntimeInjection == false { + indexHTML, err = injectHTML(string(indexHTML), ``) + if err != nil { + return nil, err + } } - return nil + if wailsOptions.disableBindingsInjection == false { + indexHTML, err = injectHTML(string(indexHTML), ``) + if err != nil { + return nil, err + } + } + return indexHTML, nil } -func (a *AssetServer) Load(filename string) ([]byte, string, error) { +func (a *BrowserAssetServer) Load(filename string) ([]byte, string, error) { var content []byte var err error switch filename { case "/": - content = a.indexFile + content, err = a.processIndexHTML() case "/wails/runtime.js": content = a.runtimeJS case "/wails/ipc.js": diff --git a/v2/internal/frontend/assetserver/assetserver_desktop.go b/v2/internal/frontend/assetserver/assetserver_desktop.go index 557fbe958..8a7039782 100644 --- a/v2/internal/frontend/assetserver/assetserver_desktop.go +++ b/v2/internal/frontend/assetserver/assetserver_desktop.go @@ -10,13 +10,13 @@ import ( "github.com/wailsapp/wails/v2/internal/frontend/runtime" "github.com/wailsapp/wails/v2/internal/logger" "io/fs" + "log" "path/filepath" "strings" ) type DesktopAssetServer struct { assets debme.Debme - indexFile []byte runtimeJS []byte assetdir string logger *logger.Logger @@ -106,27 +106,42 @@ func (a *DesktopAssetServer) init(assets embed.FS) error { if err != nil { return err } - indexHTML, err := a.assets.ReadFile("index.html") - if err != nil { - return err - } - a.indexFile, err = injectHTML(string(indexHTML), ``) - if err != nil { - return err - } - a.indexFile, err = injectHTML(string(a.indexFile), ``) - if err != nil { - return err - } return nil } +func (a *DesktopAssetServer) processIndexHTML() ([]byte, error) { + indexHTML, err := a.ReadFile("index.html") + if err != nil { + return nil, err + } + wailsOptions, err := extractOptions(indexHTML) + if err != nil { + log.Fatal(err) + return nil, err + } + fmt.Printf("%+v\n", wailsOptions) + if wailsOptions.disableRuntimeInjection == false { + indexHTML, err = injectHTML(string(indexHTML), ``) + if err != nil { + return nil, err + } + } + if wailsOptions.disableBindingsInjection == false { + indexHTML, err = injectHTML(string(indexHTML), ``) + if err != nil { + return nil, err + } + } + + return indexHTML, nil +} + func (a *DesktopAssetServer) Load(filename string) ([]byte, string, error) { var content []byte var err error switch filename { case "/": - content = a.indexFile + content, err = a.processIndexHTML() case "/wails/runtime.js": content = a.runtimeJS case "/wails/ipc.js": diff --git a/v2/internal/frontend/assetserver/common.go b/v2/internal/frontend/assetserver/common.go index 826aee4c3..1d9c270ef 100644 --- a/v2/internal/frontend/assetserver/common.go +++ b/v2/internal/frontend/assetserver/common.go @@ -3,19 +3,86 @@ package assetserver import ( "bytes" "fmt" + "golang.org/x/net/html" "strings" ) +type optionType string + +const ( + noAutoInject optionType = "noautoinject" + noAutoInjectRuntime optionType = "noautoinjectruntime" + noAutoInjectBindings optionType = "noautoinjectbindings" +) + +type Options struct { + disableRuntimeInjection bool + disableBindingsInjection bool +} + +func newOptions(optionString string) *Options { + var result = &Options{} + optionString = strings.ToLower(optionString) + options := strings.Split(optionString, ",") + for _, option := range options { + switch optionType(strings.TrimSpace(option)) { + case noAutoInject: + result.disableRuntimeInjection = true + result.disableBindingsInjection = true + case noAutoInjectBindings: + result.disableBindingsInjection = true + case noAutoInjectRuntime: + result.disableRuntimeInjection = true + } + } + return result +} + func injectHTML(input string, html string) ([]byte, error) { - splits := strings.Split(input, " + +") + splits := strings.Split(input, "") if len(splits) != 2 { - return nil, fmt.Errorf("unable to locate a tag in your html") + return nil, fmt.Errorf("unable to locate a tag in your html") } var result bytes.Buffer result.WriteString(splits[0]) result.WriteString(html) - result.WriteString("") + result.WriteString("") result.WriteString(splits[1]) return result.Bytes(), nil } + +func extractOptions(htmldata []byte) (*Options, error) { + doc, err := html.Parse(bytes.NewReader(htmldata)) + if err != nil { + return nil, err + } + var extractor func(*html.Node) *Options + extractor = func(node *html.Node) *Options { + if node.Type == html.ElementNode && node.Data == "meta" { + isWailsOptionsTag := false + wailsOptions := "" + for _, attr := range node.Attr { + if isWailsOptionsTag && attr.Key == "content" { + wailsOptions = attr.Val + } + if attr.Val == "wails-options" { + isWailsOptionsTag = true + } + } + return newOptions(wailsOptions) + } + for child := node.FirstChild; child != nil; child = child.NextSibling { + result := extractor(child) + if result != nil { + return result + } + } + return nil + } + result := extractor(doc) + if result == nil { + result = &Options{} + } + return result, nil +} diff --git a/v2/internal/frontend/assetserver/common_test.go b/v2/internal/frontend/assetserver/common_test.go new file mode 100644 index 000000000..2c20b672e --- /dev/null +++ b/v2/internal/frontend/assetserver/common_test.go @@ -0,0 +1,70 @@ +package assetserver + +import ( + "reflect" + "testing" +) + +const realHTML = ` + +
+
+ + + + +
+ +