From 502fc83b1bdd0ad61cea480735f6fbd00b27b9ca Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Mon, 4 Aug 2025 11:50:09 -0400 Subject: [PATCH] It will now watch the static directory as well and do the sync operation when that changes. --- README.md | 65 ++++++++++++++++++++++++++++++++++++++++++---- example/ssgod.toml | 1 + main.go | 40 ++++++++++++++++++---------- 3 files changed, 87 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 25129b3..71e1cc5 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,6 @@ SSG is a Static Site Generator that is only a Static Site Generator. No resumes here! I'll never work at Amazon, Google, or Microsoft so SSG doesn't include every single thing they've ever made. Just a piece of code that generates static files from templates for websites, and can do it live while you develop said templates. - ## Planned Features Needed * Simply converts dir to other dir. @@ -20,10 +19,66 @@ SSG is a Static Site Generator that is only a Static Site Generator. No resumes ## Usage -Look in examples/ssgod.toml for a sample. Copy that to your directory then just do this: +Create a default `ssgod.toml` config: + +```shell +ssgod init +``` + +The config assumes you have a `public/` as a target, and a `pages/` as source full of templates to +render. You can change this in the config. Once you're ready run: + +```shell +ssgod +``` + +It will render all `pages/**/*.md` and `pages/**/*.html` into the `public/` directory using the +`pages/layout/main.html` as the layout. You can then have it watch your `pages/` templates for +changes and do a sync: + +```shell +ssgod watch +``` + +This will watch the directory and whenever you change something it'll rebuild. It has a 500ms delay +to prevent running the render too often. + +## Syncing a `static/` Dir + +> __WARNING__: This deletes your target `public/` directory. It's assumed that you _want_ to keep a +> clean public that is only built from other sources. Anything precious in `public/` should be moved +> into `static/` so `ssgod` can faithfully recreate your `public/`. -```bash -$ ssgod +If you want to have `ssgod` sync a `static` directory then you have to uncomment a line in the +`ssgod.toml` file to enable `sync_dir` as an option: + +```toml +views = "pages" +layout = "pages/layouts/main.html" +target = "public" +watch_delay = "500ms" +# comment this out to sync static +sync_dir = "static" ``` -In the future there will be a command to init a config and to setup directories that you need for your config to run. +In this example I've removed the comment. Once you do that `ssgod` will then __remove your +public/__ directory on each run, but recreate it from the `static/` and `pages/` directory. This +ensures your `public/` is "clean" and doesn't contain any random junk that might mess up your build. + +> __NOTE__: This is a valid reason to do this, but the technical reason is that Go's `os.CopyFS` +> will error out when the target file exists. Not sure what kind of Nanny-State bullshit is going +> on over at Google but the only viable solution is to just remove the directory that's the target, +> _or_ make my own `os.CopyFS`...but with Blackjack...and...and Hookers. + +After that when you work on the templates it'll sync them over and rebuild your public for you. + +In this example I've removed the comment. Once you do that `ssgod` will then __remove your +public/__ directory on each run, but recreate it from the `static/` and `pages/` directory. This +ensures your `public/` is "clean" and doesn't contain any random junk that might mess up your build. + +> __NOTE__: This is a valid reason to do this, but the technical reason is that Go's `os.CopyFS` +> will error out when the target file exists. Not sure what kind of Nanny-State bullshit is going +> on over at Google but the only viable solution is to just remove the directory that's the target, +> _or_ make my own `os.CopyFS`...but with Blackjack...and...and Hookers. + +After that when you work on the templates it'll sync them over and rebuild your public for you. diff --git a/example/ssgod.toml b/example/ssgod.toml index 71a1a2c..cb6a558 100644 --- a/example/ssgod.toml +++ b/example/ssgod.toml @@ -1,3 +1,4 @@ + views = "pages" layout = "pages/layouts/main.html" target = "public" diff --git a/main.go b/main.go index 8ea2bf0..d88fdba 100644 --- a/main.go +++ b/main.go @@ -22,7 +22,8 @@ views = "pages" layout = "pages/layouts/main.html" target = "public" watch_delay = "500ms" -sync_dir = "static" +# comment this out, WARNING this deletes target! +# sync_dir = "static" ` func Fatal(err error, format string, v ...any) { @@ -201,9 +202,24 @@ func RenderPages() { } func WatchMatches(name string) bool { - return filepath.Ext(name) == ".html" || filepath.Ext(name) == ".md" + is_static := strings.Index(name, config.Settings.SyncDir) == 0 + return is_static || filepath.Ext(name) == ".html" || filepath.Ext(name) == ".md" } +func AddWatchDir(watcher *fsnotify.Watcher, name string) error { + return filepath.WalkDir(name, + func (path string, d fs.DirEntry, err error) error { + if d.IsDir() { + log.Println("WATCHING: ", path) + err = watcher.Add(path) + if err != nil { return Fail(err, "failed to watch %s", path) } + } + + return nil + }) +} + + func WatchDir() { watcher, err := fsnotify.NewWatcher() if err != nil { log.Fatal(err) } @@ -237,18 +253,15 @@ func WatchDir() { } }() - err = filepath.WalkDir(config.Settings.Views, - func (path string, d fs.DirEntry, err error) error { - if d.IsDir() { - log.Println("WATCHING: ", path) - err = watcher.Add(path) - if err != nil { return Fail(err, "failed to watch %s", path) } - } - - return nil - }) + err = AddWatchDir(watcher, config.Settings.Views) + if err != nil { + Fatal(err, "failed to watch %s", config.Settings.Views) + } - if err != nil { log.Fatalf("can't walk content") } + err = AddWatchDir(watcher, config.Settings.SyncDir) + if err != nil { + Fatal(err, "failed to watch %s", config.Settings.SyncDir) + } <-make(chan struct{}) } @@ -273,7 +286,6 @@ func main() { flag.Parse() command := flag.Arg(0) - switch command { case "watch": config.Load(config_file)