Initial commit
This commit is contained in:
commit
b7cd308016
7 changed files with 400 additions and 0 deletions
117
site.go
Normal file
117
site.go
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
// External
|
||||
"github.com/chromedp/cdproto/target"
|
||||
"github.com/chromedp/chromedp"
|
||||
"github.com/google/uuid"
|
||||
|
||||
// Standard
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os/exec"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
sites map[string]*Site
|
||||
siteLock *sync.Mutex
|
||||
)
|
||||
|
||||
type Site struct {
|
||||
UUID string
|
||||
URL string
|
||||
Watch string
|
||||
WatchLoop *exec.Cmd `json:"-"`
|
||||
StopLoop bool
|
||||
Context context.Context `json:"-"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
siteLock = &sync.Mutex{}
|
||||
sites = make(map[string]*Site)
|
||||
}
|
||||
|
||||
func NewSite(wsURL, url, watch string) (s Site, err error) {
|
||||
s.UUID = uuid.NewString()
|
||||
s.URL = url
|
||||
s.Watch = watch
|
||||
|
||||
allocatorContext, _ := chromedp.NewRemoteAllocator(context.Background(), wsURL)
|
||||
|
||||
// Used to optionally enable debugging output.
|
||||
var opts []chromedp.ContextOption
|
||||
if flagVerbose {
|
||||
opts = append(opts, chromedp.WithDebugf(log.Printf))
|
||||
}
|
||||
s.Context, _ = chromedp.NewContext(allocatorContext, opts...)
|
||||
|
||||
// A tab is started up and navigated to in order to get a context for this instance.
|
||||
if err = chromedp.Run(
|
||||
s.Context,
|
||||
chromedp.Navigate(url),
|
||||
); err != nil {
|
||||
err = fmt.Errorf("Failed getting body of %s: %v", url, err)
|
||||
return
|
||||
}
|
||||
|
||||
siteLock.Lock()
|
||||
sites[s.UUID] = &s
|
||||
defer siteLock.Unlock()
|
||||
|
||||
// chromedp.Run crashes something really hard and undetectable with recover().
|
||||
// ListenBrowser gives the possibility to cancel the watch loop.
|
||||
chromedp.ListenBrowser(s.Context, func(ev any) {
|
||||
_, event1 := ev.(*target.EventDetachedFromTarget)
|
||||
_, event2 := ev.(*target.EventTargetCrashed)
|
||||
_, event3 := ev.(*target.EventTargetDestroyed)
|
||||
if event1 || event2 || event3 {
|
||||
log.Printf("Stopping loop for %s\n", s.UUID)
|
||||
s.StopLoop = true
|
||||
if s.WatchLoop != nil {
|
||||
log.Printf("Killing inotifywait for %s\n", s.UUID)
|
||||
s.WatchLoop.Process.Kill()
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
// Start watching file/dir for changes.
|
||||
go s.watchLoop()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Site) watchLoop() {
|
||||
for !s.StopLoop {
|
||||
log.Println("Starting watching " + s.Watch)
|
||||
s.WatchLoop = exec.Command("inotifywait", "-e", "close_write", s.Watch)
|
||||
if err := s.WatchLoop.Run(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
s.ReloadCSS()
|
||||
}
|
||||
log.Printf("Stopping watch loop [%s]\n", s.UUID)
|
||||
}
|
||||
|
||||
func (s *Site) ReloadCSS() {
|
||||
var buf []byte
|
||||
|
||||
cssReloadScript := chromedp.Evaluate(`
|
||||
(()=>{
|
||||
const stylesheets = document.querySelectorAll('link[rel="stylesheet"]')
|
||||
for (const ss of stylesheets) {
|
||||
const url = URL.parse(ss.href, location.protocol + '//' + location.host)
|
||||
const nextReloadCounter = parseInt(url.searchParams.get('reload') || 0) + 1
|
||||
url.searchParams.set('reload', nextReloadCounter)
|
||||
ss.href = url.toString()
|
||||
}
|
||||
})()
|
||||
`, &buf)
|
||||
|
||||
err := chromedp.Run(s.Context, cssReloadScript)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue