Initial setup of the project directory.

master
Zed A. Shaw 3 weeks ago
parent 167321bf1f
commit 56b9321382
  1. 29
      .gitignore
  2. 26
      Makefile
  3. 9
      README.md
  4. 27
      config/loader.go
  5. 29
      go.mod
  6. 45
      go.sum
  7. 77
      main.go
  8. 2
      ssgod.toml
  9. 12
      tests/base_test.go

29
.gitignore vendored

@ -0,0 +1,29 @@
# ---> Vim
# Swap
[._]*.s[a-v][a-z]
!*.svg # comment out if you don't need vector files
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
# Session
Session.vim
Sessionx.vim
# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~
backup
*.exe
*.dll
coverage
coverage/*
.venv
*.gz
public

@ -0,0 +1,26 @@
GO_IS_STUPID_EXE=
ifeq '$(OS)' 'Windows_NT'
GO_IS_STUPID_EXE=.exe
endif
build:
go build .
test:
go test zedshaw.games/ssgod/tests -c -o runtests$(GO_IS_STUPID_EXE)
./runtests$(GO_IS_STUPID_EXE)
docs:
go tool pkgsite --open
coverage:
go build -cover -o webapp
mkdir -p .coverage
echo "GOCOVERDIR=.coverage ./webapp"
cover_report:
go tool covdata textfmt -i=.coverage -o coverage.txt
go tool cover -func=coverage.txt
go tool cover -html=coverage.txt -o coverage.html
open coverage.html

@ -25,11 +25,14 @@ SSG is a Static Site Generator that is only a Static Site Generator. No resumes
## Usage
```bash
# assumes a ssgod.tomly
$ beerus
# init your config
$ ssgod init
# creates a ssgod.tomly
$ ssgod
# explicit ssgod
$ beerus --config ssgod.toml
$ ssgod --config ssgod.toml
```
* Probably just an extension mapping: .md -> .html, .html -> .html

@ -0,0 +1,27 @@
package config
import (
"log"
"github.com/BurntSushi/toml"
)
type config struct {
Views string `toml:"views"`
Layouts string `toml:"layouts"`
}
var Settings config
func Load(path string) {
metadata, err := toml.DecodeFile(path, &Settings)
if err != nil {
log.Fatalf("error loading config.toml: %v", err)
}
bad_keys := metadata.Undecoded()
if len(bad_keys) > 0 {
log.Fatalf("unknown configuration keys: %v", bad_keys);
}
}

@ -0,0 +1,29 @@
module zedshaw.games/ssgod
go 1.24.2
require (
github.com/BurntSushi/toml v1.5.0
github.com/gofiber/fiber/v2 v2.52.9
github.com/gofiber/template/html/v2 v2.1.3
github.com/stretchr/testify v1.10.0
)
require (
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gofiber/template v1.8.3 // indirect
github.com/gofiber/utils v1.1.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.51.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
golang.org/x/sys v0.28.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

@ -0,0 +1,45 @@
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
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/gofiber/fiber/v2 v2.52.9 h1:YjKl5DOiyP3j0mO61u3NTmK7or8GzzWzCFzkboyP5cw=
github.com/gofiber/fiber/v2 v2.52.9/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc=
github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8=
github.com/gofiber/template/html/v2 v2.1.3 h1:n1LYBtmr9C0V/k/3qBblXyMxV5B0o/gpb6dFLp8ea+o=
github.com/gofiber/template/html/v2 v2.1.3/go.mod h1:U5Fxgc5KpyujU9OqKzy6Kn6Qup6Tm7zdsISR+VpnHRE=
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

@ -0,0 +1,77 @@
package main
import (
"log"
"fmt"
"strings"
"io/fs"
"path/filepath"
"os"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/template/html/v2"
"zedshaw.games/ssgod/config"
)
func Fail(err error, format string, v ...any) error {
err_format := fmt.Sprintf("ERROR: %v; %s", err, format)
log.Printf(err_format, v...)
return err
}
func RenderPages(pages_path string, target string, layout string) {
engine := html.New(pages_path, ".html")
engine.Load()
err := filepath.WalkDir(pages_path,
func(path string, d fs.DirEntry, err error) error {
if !d.IsDir() {
if err != nil { return Fail(err, "path: %s", path); }
dir := filepath.Dir(path)
err = os.MkdirAll(dir, 0750)
if err != nil {
return Fail(err, "making dir %s", dir);
}
split_path := strings.Split(path, string(os.PathSeparator))[1:]
source_name := strings.Join(split_path, "/") // Render wants / even on windows
ext := filepath.Ext(source_name)
template_name, found := strings.CutSuffix(source_name, ext)
if found && ext == ".html" && template_name != layout {
prefixed_path := append([]string{target}, split_path...)
target_path := filepath.Join(prefixed_path...)
_, err := os.Stat(target_path)
if os.IsNotExist(err) {
target_dir := filepath.Dir(target_path)
log.Println("MAKING: ", target_dir)
os.MkdirAll(target_dir, 0750)
}
// TODO: compare time stamps and skip if not newer
out, err := os.OpenFile(target_path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil { return Fail(err, "writing file %s", target_path) }
// generate a data-testid for all pages based on template name
page_id := strings.ReplaceAll(template_name, "/", "-") + "-page"
err = engine.Render(out, template_name, fiber.Map{"PageId": page_id}, layout)
if err != nil { return Fail(err, "failed to render %s", path) }
log.Printf("RENDER: %s -> %s", template_name, target_path)
out.Close()
}
}
return nil
})
if err != nil { log.Fatalf("can't walk content") }
}
func main() {
config.Load("ssgod.toml")
log.Printf("views=%s, layouts=%s", config.Settings.Views, config.Settings.Layouts)
}

@ -0,0 +1,2 @@
views = "./views"
layouts = "layouts/main"

@ -0,0 +1,12 @@
package tests
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestBasic(t *testing.T) {
assert := require.New(t)
assert.Equal(100, 100)
}
Loading…
Cancel
Save