parent
167321bf1f
commit
56b9321382
@ -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
|
@ -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…
Reference in new issue