fes

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit f5d928ebb90e9225240521d79c06caa55e9dbbb8
parent 2f877b63b8b09272567f8b00164426d844e9cfe7
Author: vx-clutch <[email protected]>
Date:   Wed,  3 Dec 2025 21:52:00 -0500

Merge pull request 'alpha p6' (#1) from master into main

Reviewed-on: https://git.vxserver.dev/fSD/fes/pulls/1

Diffstat:
DTODO | 2--
Mcore/builtin.lua | 26+++++++++-----------------
Aexamples/favicon/Fes.toml | 6++++++
Aexamples/favicon/static/image/favicon.ico | 0
Aexamples/favicon/www/index.lua | 9+++++++++
Msrc/server/server.go | 30++++++++++++++++++++++--------
6 files changed, 46 insertions(+), 27 deletions(-)

diff --git a/TODO b/TODO @@ -1,2 +0,0 @@ -Add an interval element -Add favicon support diff --git a/core/builtin.lua b/core/builtin.lua @@ -3,13 +3,8 @@ local std = require("core.std") local M = {} M.__index = M -local function encode(str) - return str:gsub("([^%w%-%_%.%~])", function(c) - return string.format("%%%02X", string.byte(c)) end) end - function M.fes(header, footer) - local config = {} - local site_config = {} + local config = {} local site_config = {} local fes_mod = package.loaded.fes if fes_mod and fes_mod.config then config = fes_mod.config @@ -18,20 +13,18 @@ function M.fes(header, footer) end end - local raw_favicon = site_config.favicon or [[<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><text y=".9em" font-size="90">🔥</text></svg>]] - local self = { - version = site_config.version or "", - title = site_config.title or "Document", - copyright = site_config.copyright or "&#169; The Copyright Holder", - favicon = "data:image/svg+xml," .. encode(raw_favicon), + version = site_config.version, + title = site_config.title, + copyright = site_config.copyright, + favicon = site_config.favicon, header = header or [[ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> -<link rel="icon" href="{{FAVICON}}"> +{{FAVICON}} <title>{{TITLE}}</title> <style> html, body { min-height: 100%; margin: 0; padding: 0; background: #0f1113; color: #e6eef3; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; line-height: 1.5; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } @@ -132,10 +125,9 @@ end function M:build() local header = self.header - local safe_title = self.title or "Document" - local safe_favicon = self.favicon:gsub("%%", "%%%%") - header = header:gsub("{{TITLE}}", safe_title) - header = header:gsub("{{FAVICON}}", safe_favicon) + header = header:gsub("{{TITLE}}", self.title or "Document") + local favicon_html = self.favicon and ('<link rel="icon" type="image/x-icon" href="' .. self.favicon .. '">') + header = header:gsub("{{FAVICON}}", favicon_html or [[<link rel="icon" href="data:image/svg+xml,<svg xmlns=%%22http://www.w3.org/2000/svg%%22 viewBox=%%220 0 100 100%%22><text y=%%22.9em%%22 font-size=%%2290%%22>🔥</text></svg>">]]) local footer = self.footer:gsub("{{COPYRIGHT}}", self.copyright or "&#169; The Copyright Holder") return header .. table.concat(self.parts, "\n") .. footer end diff --git a/examples/favicon/Fes.toml b/examples/favicon/Fes.toml @@ -0,0 +1,5 @@ +[app] + +name = "favicon" +version = "0.0.1" +authors = ["vx-clutch"] +\ No newline at end of file diff --git a/examples/favicon/static/image/favicon.ico b/examples/favicon/static/image/favicon.ico Binary files differ. diff --git a/examples/favicon/www/index.lua b/examples/favicon/www/index.lua @@ -0,0 +1,9 @@ +local fes = require("fes") +local site = fes.fes() + +site.title = "favicon" +site.favicon = "static/image/favicon.ico" + +site:h1("Hello, World!") + +return site diff --git a/src/server/server.go b/src/server/server.go @@ -24,10 +24,10 @@ type reqData struct { params map[string]string } -func handleDir(entries []os.DirEntry, wwwDir string, routes map[string]string, base string) error { +func handleDir(entries []os.DirEntry, dir string, routes map[string]string, base string) error { for _, entry := range entries { if entry.IsDir() { - sub := filepath.Join("www", entry.Name()) + sub := filepath.Join(dir, entry.Name()) subs, err := os.ReadDir(sub) if err != nil { return fmt.Errorf("failed to read %s: %w", sub, err) @@ -45,7 +45,7 @@ func handleDir(entries []os.DirEntry, wwwDir string, routes map[string]string, b } if strings.HasSuffix(entry.Name(), ".lua") { name := strings.TrimSuffix(entry.Name(), ".lua") - path := filepath.Join("www", entry.Name()) + path := filepath.Join(dir, entry.Name()) if name == "index" { if base == "" { routes["/"] = path @@ -61,6 +61,14 @@ func handleDir(entries []os.DirEntry, wwwDir string, routes map[string]string, b routes[base+"/"+name] = path } } + } else { + name := entry.Name() + path := filepath.Join(dir, entry.Name()) + if base == "" { + routes["/"+name] = path + } else { + routes[base+"/"+name] = path + } } } return nil @@ -262,10 +270,6 @@ func Start(dir string) error { return fmt.Errorf("failed to parse Fes.toml: %w", err) } - entries, err := os.ReadDir("www") - if err != nil { - return fmt.Errorf("failed to read www directory: %w", err) - } notFoundData := ` <html> @@ -290,15 +294,25 @@ func Start(dir string) error { } routes := make(map[string]string) + + entries, err := os.ReadDir("www") + if err != nil { + return fmt.Errorf("failed to read www directory: %w", err) + } handleDir(entries, "www", routes, "") + entries, err = os.ReadDir("static") + if err == nil { + handleDir(entries, "static", routes, "") + } + 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)) + fmt.Printf("> %s ", path) color.Yellow("not found") return }