summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authora73x <[email protected]>2024-12-22 12:12:50 +0000
committera73x <[email protected]>2024-12-22 12:12:50 +0000
commitf1cc5903f84fe41c1e9566768d53d95f6be20236 (patch)
treee642dd7dd19df924aa0345fffc2b89f28d6186a0
parent6beea1d4127d2d51bfdc75162423407c198d19da (diff)
hack in some hotreloading
-rw-r--r--cmd/home/main.go196
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--web/web.go46
4 files changed, 187 insertions, 61 deletions
diff --git a/cmd/home/main.go b/cmd/home/main.go
index 3f04b39..6854299 100644
--- a/cmd/home/main.go
+++ b/cmd/home/main.go
@@ -1,32 +1,198 @@
package main
import (
+ "errors"
+ "fmt"
+ "log"
+ "net/http"
"os"
- "os/signal"
- "syscall"
+ "path"
+ "path/filepath"
+ "strings"
+ "time"
- "git.sr.ht/~a73x/home/web"
+ "git.sr.ht/~a73x/home/pages"
+ "github.com/fsnotify/fsnotify"
"go.uber.org/zap"
)
-func main() {
- logger, _ := zap.NewProduction()
- server, err := web.New(logger)
+func Build(directory string) error {
+ pages, err := pages.Collect(directory)
+ if err != nil {
+ return err
+ }
+
+ var errs []error
+ for _, page := range pages {
+ fmt.Println("building", page.Path)
+ err = writeFile(path.Join("public", page.Path), []byte(page.Content))
+ if err != nil {
+ errs = append(errs, err)
+ }
+ }
+
+ if errs != nil {
+ return errors.Join(errs...)
+ }
+
+ return nil
+}
+
+func Serve() error {
+ logger, err := zap.NewProduction()
if err != nil {
- logger.Fatal("failed to start webserver", zap.Error(err))
+ return err
+ }
+
+ loggingMiddleware := func(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ start := time.Now()
+ next.ServeHTTP(w, r)
+ logger.Info("request received",
+ zap.String("url", r.URL.Path),
+ zap.String("method", r.Method),
+ zap.Duration("duration", time.Since(start)),
+ zap.String("user-agent", r.UserAgent()),
+ )
+ })
+ }
+
+ mux := http.NewServeMux()
+
+ mux.HandleFunc("GET /", serveFile)
+
+ server := http.Server{
+ Addr: ":8080",
+ Handler: loggingMiddleware(mux),
+ }
+
+ return server.ListenAndServe()
+}
+
+func serveFile(w http.ResponseWriter, r *http.Request) {
+ fsPath := strings.TrimRight(r.URL.Path, "/")
+
+ if fsPath == "" {
+ fsPath = "index"
+ }
+
+ if ext := filepath.Ext(fsPath); ext == "" {
+ fsPath += ".html"
}
- done := make(chan os.Signal, 0)
- signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
- logger.Info("Starting web server")
+ http.ServeFile(w, r, path.Join("public", fsPath))
+}
+
+func watchDir(watchDir string) error {
+ // Directory to watch
+
+ // Ensure the directory exists
+ if _, err := os.Stat(watchDir); os.IsNotExist(err) {
+ return err
+ }
+ // Create a new watcher
+ watcher, err := fsnotify.NewWatcher()
+ if err != nil {
+ return err
+ }
+
+ // Start a goroutine to process events
go func() {
- if err := server.ListenAndServe(); err != nil {
- logger.Error("fail running web server", zap.Error(err))
+ defer watcher.Close()
+
+ for {
+ select {
+ case event, ok := <-watcher.Events:
+ if !ok {
+ return
+ }
+ log.Printf("Event: %s", event)
+
+ // Trigger a command when a change is detected
+ if event.Op&fsnotify.Write == fsnotify.Write ||
+ event.Op&fsnotify.Create == fsnotify.Create ||
+ event.Op&fsnotify.Remove == fsnotify.Remove {
+ err := Build(watchDir)
+ if err != nil {
+ fmt.Println(err)
+ } else {
+ fmt.Println("built")
+ }
+
+ }
+
+ case err, ok := <-watcher.Errors:
+ if !ok {
+ return
+ }
+ log.Printf("Error: %v", err)
+ }
}
- done <- nil
}()
- <-done
- logger.Info("Stopping web server")
+ // Add the directory to the watcher
+ err = filepath.Walk(watchDir, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ if info.IsDir() {
+ log.Printf("Watching directory: %s", path)
+ return watcher.Add(path)
+ }
+ return nil
+ })
+
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+func Run() error {
+ contentDir := "content"
+ actualPath, err := filepath.EvalSymlinks(contentDir)
+ if err != nil {
+ return err
+ }
+
+ if err := Build(actualPath); err != nil {
+ return err
+ }
+
+ // watcher
+ if err := watchDir(actualPath); err != nil {
+ return err
+ }
+
+ if err := Serve(); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func writeFile(name string, contents []byte) error {
+ folders := path.Dir(name)
+ _, err := os.Stat(folders)
+ if os.IsNotExist(err) {
+ if err := os.MkdirAll(folders, 0744); err != nil {
+ return fmt.Errorf("failed to mkdir %s\n%w", folders, err)
+ }
+ } else if err != nil {
+ return fmt.Errorf("failed to stat folder %s\n%w", folders, err)
+ }
+
+ err = os.WriteFile(name, contents, 0666)
+ if err != nil {
+ return fmt.Errorf("failed to write file %s\n%w", name, err)
+ }
+
+ return nil
+}
+
+func main() {
+ if err := Run(); err != nil {
+ log.Panic(err)
+ }
}
diff --git a/go.mod b/go.mod
index 9fe68a0..957ad30 100644
--- a/go.mod
+++ b/go.mod
@@ -5,6 +5,7 @@ go 1.23
require (
github.com/adrg/frontmatter v0.2.0
github.com/alecthomas/chroma v0.10.0
+ github.com/fsnotify/fsnotify v1.8.0
github.com/gomarkdown/markdown v0.0.0-20240730141124-034f12af3bf6
go.uber.org/zap v1.27.0
)
@@ -14,5 +15,6 @@ require (
github.com/dlclark/regexp2 v1.4.0 // indirect
github.com/stretchr/testify v1.9.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
+ golang.org/x/sys v0.13.0 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
)
diff --git a/go.sum b/go.sum
index a1016c7..9502cb0 100644
--- a/go.sum
+++ b/go.sum
@@ -10,6 +10,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
+github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
+github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/gomarkdown/markdown v0.0.0-20240730141124-034f12af3bf6 h1:ZPy+2XJ8u0bB3sNFi+I72gMEMS7MTg7aZCCXPOjV8iw=
github.com/gomarkdown/markdown v0.0.0-20240730141124-034f12af3bf6/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -24,6 +26,8 @@ go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
diff --git a/web/web.go b/web/web.go
deleted file mode 100644
index 96f85d2..0000000
--- a/web/web.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package web
-
-import (
- "net/http"
- "time"
-
- "git.sr.ht/~a73x/home/pages"
- "go.uber.org/zap"
-)
-
-func New(logger *zap.Logger) (*http.Server, error) {
- loggingMiddleware := func(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- start := time.Now()
- next.ServeHTTP(w, r)
- logger.Info("request received",
- zap.String("url", r.URL.Path),
- zap.String("method", r.Method),
- zap.Duration("duration", time.Since(start)),
- zap.String("user-agent", r.UserAgent()),
- )
- })
- }
-
- mux := http.NewServeMux()
- pages, err := pages.Collect("./content")
- if err != nil {
- return nil, err
- }
-
- staticFs := http.FileServer(http.Dir("./public/static"))
-
- mux.Handle("GET /static/", http.StripPrefix("/static/", staticFs))
- for _, page := range pages {
- mux.HandleFunc("GET "+page.Path, func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte(page.Content))
- })
- }
-
- server := http.Server{
- Addr: ":8080",
- Handler: loggingMiddleware(mux),
- }
-
- return &server, nil
-}