diff --git a/TODO b/TODO index 515b8af..04ab4f0 100644 --- a/TODO +++ b/TODO @@ -1,2 +1,3 @@ Add an interval element -Add a way to pass data to sites on load via fes.bus +Add a way to pass data to sites on load via fes.bus: pass a table of { url, IP, request, headers, body } +Serve site/static at /static diff --git a/examples/canonical/www/404.lua b/examples/canonical/www/404.lua new file mode 100644 index 0000000..304c8ee --- /dev/null +++ b/examples/canonical/www/404.lua @@ -0,0 +1,17 @@ +local fes = require("fes") +local std = fes.std +local u = fes.util + +local site = fes.fes() + +site.title = "404 Page Not Found" +site.copyright = u.copyright("https://git.vxserver.dev/fSD/", "fSD") + +site:banner(std.h1(std.center("Canonical"))) + +site:note(table.concat({ + std.center(std.h1("404 Page Not Found")), + std.center(std.p("The page you are looking for is not here. " .. std.a("/", "Go home?"))), +})) + +return site diff --git a/examples/error/Fes.toml b/examples/error/Fes.toml new file mode 100644 index 0000000..9cd794b --- /dev/null +++ b/examples/error/Fes.toml @@ -0,0 +1,5 @@ +[app] + +name = "error" +version = "0.0.1" +authors = ["vx-clutch"] \ No newline at end of file diff --git a/examples/error/www/index.lua b/examples/error/www/index.lua new file mode 100644 index 0000000..e0e2cf7 --- /dev/null +++ b/examples/error/www/index.lua @@ -0,0 +1,9 @@ +local fes = require("fes") +local site = fes.fes() + +site.title = "error" + +UNIX is very simple +GNU's Not UNIX + +return site diff --git a/go.mod b/go.mod index 64f6518..300d287 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,12 @@ module fes go 1.25.4 require ( + github.com/fatih/color v1.18.0 // indirect github.com/gomarkdown/markdown v0.0.0-20250810172220-2e2c11897d1a // indirect github.com/gomarkdown/mdtohtml v0.0.0-20240124153210-d773061d1585 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/yuin/gopher-lua v1.1.1 // indirect + golang.org/x/sys v0.25.0 // indirect ) diff --git a/go.sum b/go.sum index 42cadc2..ea99386 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,19 @@ +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/gomarkdown/markdown v0.0.0-20250810172220-2e2c11897d1a h1:l7A0loSszR5zHd/qK53ZIHMO8b3bBSmENnQ6eKnUT0A= github.com/gomarkdown/markdown v0.0.0-20250810172220-2e2c11897d1a/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/gomarkdown/mdtohtml v0.0.0-20240124153210-d773061d1585/go.mod h1:6grYm5/uY15CwgBBqwA3+o/cAzaxssckznJ0B35ouBY= +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/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= +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.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/main.go b/main.go index 55db57a..4df51a7 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,8 @@ import ( "fmt" "os" + "github.com/fatih/color" + "fes/src/config" "fes/src/new" "fes/src/server" @@ -16,7 +18,8 @@ import ( var core embed.FS func init() { - config.Port = flag.Int("p", 3000, "set the server port") + config.Port = flag.Int("p", 3000, "Set the server port") + config.Color = flag.Bool("no-color", false, "Disable color output") config.Core = core } @@ -27,6 +30,10 @@ func main() { os.Exit(1) } + if *config.Color { + color.NoColor = true + } + cmd := os.Args[1] dir := os.Args[2] diff --git a/src/config/config.go b/src/config/config.go index ba878fe..9f20968 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -4,6 +4,7 @@ import "embed" var Core embed.FS var Port *int +var Color *bool type MyConfig struct { App struct { diff --git a/src/server/server.go b/src/server/server.go index f4ee387..43dac1c 100644 --- a/src/server/server.go +++ b/src/server/server.go @@ -14,6 +14,7 @@ import ( "github.com/gomarkdown/markdown/parser" "github.com/pelletier/go-toml/v2" lua "github.com/yuin/gopher-lua" + "github.com/fatih/color" "fes/src/config" ) @@ -157,6 +158,18 @@ func loadLua(luaDir string, entry string, cfg *config.MyConfig) (string, error) return 1 }) + L.PreloadModule("core.util", func(L *lua.LState) int { + data, err := config.Core.ReadFile("core/util.lua") + if err != nil { + panic(err) + } + if err := L.DoString(string(data)); err != nil { + panic(err) + } + L.Push(L.Get(-1)) + return 1 + }) + L.PreloadModule("fes", func(L *lua.LState) int { mod := L.NewTable() coreModules := []string{} @@ -263,22 +276,43 @@ func Start(dir string) error { return fmt.Errorf("failed to read www directory: %w", err) } + notFoundData := "404 Page Not Found" + if _, err := os.Stat(filepath.Join(wwwDir, "404.lua")); err == nil { + notFoundData, err = loadLua(dir, filepath.Join(wwwDir, "404.lua"), &cfg) + if err != nil { + panic(err) + } + } else if _, err := os.Stat(filepath.Join(wwwDir, "404.html")); err == nil { + buf, err := os.ReadFile(filepath.Join(wwwDir, "404.html")) + if err != nil { + panic(err) + } + notFoundData = string(buf) + } + routes := make(map[string]string) handleDir(entries, wwwDir, routes, "") - for route, luaPath := range routes { - func(rt string, lp string) { - http.HandleFunc(rt, func(w http.ResponseWriter, r *http.Request) { - fmt.Printf("-> %s\n", lp) - data, err := loadLua(dir, lp, &cfg) - if err != nil { - http.Error(w, fmt.Sprintf("Error loading page: %v", err), http.StatusInternalServerError) - return - } - w.Write([]byte(data)) - }) - }(route, luaPath) - } + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + path := r.URL.Path + lp, ok := routes[path] + if !ok { + w.WriteHeader(http.StatusNotFound) + w.Write([]byte(notFoundData)) + fmt.Printf("> %s.lua ", filepath.Base(path)) + color.Yellow("not found") + return + } + fmt.Printf("> %s ", filepath.Base(lp)) + data, err := loadLua(dir, lp, &cfg) + if err != nil { + http.Error(w, fmt.Sprintf("Error loading page: %v", err), http.StatusInternalServerError) + color.Red("bad") + return + } + color.Green("ok") + w.Write([]byte(data)) + }) fmt.Printf("Server is running on http://localhost:%d\n", *config.Port) return http.ListenAndServe(fmt.Sprintf(":%d", *config.Port), nil)