diff --git a/cmd/serve/serve.go b/cmd/serve/serve.go index 28a3de2..182cabd 100644 --- a/cmd/serve/serve.go +++ b/cmd/serve/serve.go @@ -23,12 +23,13 @@ type Fileserver interface { type command struct { binPath string // master, as in adjective 'master record' non-slavery kind - masterPath string - mirrorPath string - port *int - wsPath *string - flagset *flag.FlagSet - fileserver Fileserver + masterPath string + mirrorPath string + port *int + wsPath *string + forceReload *bool + flagset *flag.FlagSet + fileserver Fileserver } func Command() *command { @@ -52,7 +53,7 @@ func (c *command) Setup() error { c.masterPath = path.Clean(relPath) if c.masterPath != "" { - c.fileserver = wsinject.NewFileServer(*c.port, *c.wsPath) + c.fileserver = wsinject.NewFileServer(*c.port, *c.wsPath, *c.forceReload) mirrorPath, err := c.fileserver.Setup(c.masterPath) if err != nil { return fmt.Errorf("failed to setup websocket injected mirror filesystem: %v", err) @@ -121,6 +122,7 @@ func (c *command) Flagset() *flag.FlagSet { fs := flag.NewFlagSet("server", flag.ExitOnError) c.port = fs.Int("port", 8080, "port to serve http server on") c.wsPath = fs.String("wsPort", "/delta-streamer-ws", "the path which the delta streamer websocket should be hosted on") + c.forceReload = fs.Bool("forceReload", false, "set to true if you wish to reload all attached browser pages on any file change") c.flagset = fs return fs } diff --git a/internal/wsinject/delta_streamer.ws.go b/internal/wsinject/delta_streamer.ws.go index f424502..7b8ed65 100644 --- a/internal/wsinject/delta_streamer.ws.go +++ b/internal/wsinject/delta_streamer.ws.go @@ -1,6 +1,6 @@ package wsinject -const DeltaStreamerSourceCode = `/** +const deltaStreamerSourceCode = `/** * This file has been injected by the wd-41 web development * hot reload tool. */ @@ -33,7 +33,11 @@ function startWebsocket() { if(event.data === fileName || // Always reload on js and css files since its difficult to know where these are used event.data.includes(".js") || - event.data.includes(".css")) { + event.data.includes(".css") || + // This funny-looking comparison is set using string interpolation from the -forceReload flag + // when writing this script + %v === true + ) { location.reload(); } }); diff --git a/internal/wsinject/wsinject.go b/internal/wsinject/wsinject.go index 2d73bd5..b4bd363 100644 --- a/internal/wsinject/wsinject.go +++ b/internal/wsinject/wsinject.go @@ -19,11 +19,12 @@ import ( ) type Fileserver struct { - masterPath string - mirrorPath string - wsPort int - wsPath string - watcher *fsnotify.Watcher + masterPath string + mirrorPath string + forceReload bool + wsPort int + wsPath string + watcher *fsnotify.Watcher pageReloadChan chan string wsDispatcher sync.Map @@ -36,7 +37,7 @@ var ErrNoHeaderTagFound = errors.New("no header tag found") const deltaStreamer = ` ` -func NewFileServer(wsPort int, wsPath string) *Fileserver { +func NewFileServer(wsPort int, wsPath string, forceReload bool) *Fileserver { mirrorDir, err := os.MkdirTemp("", "wd-41_*") if err != nil { panic(err) @@ -46,6 +47,7 @@ func NewFileServer(wsPort int, wsPath string) *Fileserver { mirrorPath: mirrorDir, wsPort: wsPort, wsPath: wsPath, + forceReload: forceReload, pageReloadChan: make(chan string), wsDispatcher: sync.Map{}, wsDispatcherStarted: &started, @@ -95,7 +97,10 @@ func (fs *Fileserver) mirrorMaker(p string, info os.DirEntry, err error) error { } func (fs *Fileserver) writeDeltaStreamerScript() error { - err := os.WriteFile(path.Join(fs.mirrorPath, "delta-streamer.js"), []byte(fmt.Sprintf(DeltaStreamerSourceCode, fs.wsPort, fs.wsPath)), 0o755) + err := os.WriteFile( + path.Join(fs.mirrorPath, "delta-streamer.js"), + []byte(fmt.Sprintf(deltaStreamerSourceCode, fs.wsPort, fs.wsPath, fs.forceReload)), + 0o755) if err != nil { return fmt.Errorf("failed to write delta-streamer.js: %w", err) } diff --git a/internal/wsinject/wsinject_test.go b/internal/wsinject/wsinject_test.go index 0bc3784..3f007f4 100644 --- a/internal/wsinject/wsinject_test.go +++ b/internal/wsinject/wsinject_test.go @@ -76,7 +76,7 @@ func Test_Setup(t *testing.T) { } nestedFile := path.Join(nestedDir, "nested.html") os.WriteFile(nestedFile, []byte(mockHtml), 0o777) - fs := NewFileServer(8080, "/delta-streamer-ws.js") + fs := NewFileServer(8080, "/delta-streamer-ws.js", false) _, err = fs.Setup(tmpDir) if err != nil { t.Fatalf("failed to setup: %v", err) @@ -145,7 +145,7 @@ func Test_Start(t *testing.T) { if err != nil { t.Fatalf("failed to create temp dir: %v", err) } - return NewFileServer(8080, "/delta-streamer-ws.js"), testFileSystem{ + return NewFileServer(8080, "/delta-streamer-ws.js", false), testFileSystem{ root: tmpDir, nestedDir: nestedDir, }