large changes

This commit is contained in:
2025-12-26 10:06:23 -05:00
parent 9d7dbc31ca
commit e4eb7d62e4
15 changed files with 119 additions and 90 deletions

View File

@@ -1,9 +0,0 @@
FROM alpine:3.20
ARG SITE
RUN echo "https://git.vxserver.dev/api/packages/fSD/alpine/main/fports" >> /etc/apk/repositories
&& apk update \
&& apk add --no-cache fes
ENTRYPOINT ["fes", "run", ${SITE}]

19
Makefile Normal file
View File

@@ -0,0 +1,19 @@
GO ?= go
.PHONY: build deps lint install
all: build
deps:
$(GO) mod download
build: deps
$(GO) build -ldflags "-X fes/modules/version.gitCommit=$(shell git rev-parse --short HEAD)" -o fes
@echo "Fes is now built to ./fes"
lint:
$(GO) vet ./...
$(GO) fmt ./...
install:
$(GO) install fes

View File

@@ -1,4 +1,4 @@
local std = require("core.std") local std = require("lib.std")
local M = {} local M = {}
M.__index = M M.__index = M

View File

@@ -1,5 +1,5 @@
local std = require("core.std") local std = require("lib.std")
local symbol = require("core.symbol") local symbol = require("lib.symbol")
local M = {} local M = {}

24
main.go
View File

@@ -9,15 +9,15 @@ import (
"github.com/fatih/color" "github.com/fatih/color"
"fes/src/config" "fes/modules/config"
"fes/src/doc" "fes/modules/doc"
"fes/src/new" "fes/modules/new"
"fes/src/server" "fes/modules/server"
"fes/src/version" "fes/modules/version"
) )
//go:embed core/* //go:embed lib/*
var core embed.FS var lib embed.FS
//go:embed index.html //go:embed index.html
var documentation string var documentation string
@@ -25,7 +25,8 @@ var documentation string
func init() { 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.Color = flag.Bool("no-color", false, "Disable color output")
config.Core = core config.Static = flag.Bool("static", false, "Render and save all pages.")
config.Lib = lib
config.Doc = documentation config.Doc = documentation
} }
@@ -38,15 +39,22 @@ func main() {
fmt.Println(" run <project_dir> Start the server") fmt.Println(" run <project_dir> Start the server")
fmt.Println("Options:") fmt.Println("Options:")
flag.PrintDefaults() flag.PrintDefaults()
fmt.Println("For bug reports, contact a developer and describe the issue. Provide the output of the `-V1` flag.")
} }
showVersion := flag.Bool("version", false, "Show version and exit") showVersion := flag.Bool("version", false, "Show version and exit")
showFullVersion := flag.Bool("V1", false, "Show extended version information and exit")
flag.Parse() flag.Parse()
if *showVersion { if *showVersion {
version.Version() version.Version()
} }
if *showFullVersion {
version.FullVersion()
}
if *config.Color { if *config.Color {
color.NoColor = true color.NoColor = true
} }

View File

@@ -5,12 +5,13 @@ import (
"errors" "errors"
) )
var Core embed.FS var Lib embed.FS
var Doc string var Doc string
var Port *int var Port *int
var Color *bool var Color *bool
var Static *bool
type MyConfig struct { type AppConfig struct {
App struct { App struct {
Name string `toml:"name"` Name string `toml:"name"`
Version string `toml:"version"` Version string `toml:"version"`

View File

@@ -1,7 +1,7 @@
package doc package doc
import ( import (
"fes/src/config" "fes/modules/config"
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"

View File

@@ -1,26 +1,20 @@
package server package server
import ( import (
"fes/modules/config"
"fes/modules/ui"
"fmt" "fmt"
"github.com/pelletier/go-toml/v2"
lua "github.com/yuin/gopher-lua"
"html/template" "html/template"
"io/fs" "io/fs"
"net/http" "net/http"
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"regexp"
"sort" "sort"
"strings" "strings"
"time" "time"
"fes/src/config"
"fes/src/ui"
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/html"
"github.com/gomarkdown/markdown/parser"
"github.com/pelletier/go-toml/v2"
lua "github.com/yuin/gopher-lua"
) )
type reqData struct { type reqData struct {
@@ -28,42 +22,6 @@ type reqData struct {
params map[string]string params map[string]string
} }
func joinBase(base, name string) string {
if base == "" {
return "/" + name
}
return base + "/" + name
}
func basePath(base string) string {
if base == "" || base == "." {
return "/"
}
return base
}
func fixMalformedToml(content string) string {
re := regexp.MustCompile(`(?m)^(\s*\w+\s*=\s*)$`)
return re.ReplaceAllStringFunc(content, func(match string) string {
parts := strings.Split(strings.TrimSpace(match), "=")
if len(parts) == 2 && strings.TrimSpace(parts[1]) == "" {
key := strings.TrimSpace(parts[0])
return key + " = \"\""
}
return match
})
}
func markdownToHTML(mdText string) string {
extensions := parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock
p := parser.NewWithExtensions(extensions)
doc := p.Parse([]byte(mdText))
htmlFlags := html.CommonFlags | html.HrefTargetBlank
opts := html.RendererOptions{Flags: htmlFlags}
renderer := html.NewRenderer(opts)
return string(markdown.Render(doc, renderer))
}
func handleDir(entries []os.DirEntry, dir string, routes map[string]string, base string, isStatic bool) error { func handleDir(entries []os.DirEntry, dir string, routes map[string]string, base string, isStatic bool) error {
for _, entry := range entries { for _, entry := range entries {
path := filepath.Join(dir, entry.Name()) path := filepath.Join(dir, entry.Name())
@@ -136,18 +94,18 @@ func loadIncludeModules(L *lua.LState, includeDir string) *lua.LTable {
return app return app
} }
func loadLua(entry string, cfg *config.MyConfig, requestData reqData) ([]byte, error) { func loadLua(entry string, cfg *config.AppConfig, requestData reqData) ([]byte, error) {
L := lua.NewState() L := lua.NewState()
defer L.Close() defer L.Close()
coreFiles, err := fs.ReadDir(config.Core, "core") libFiles, err := fs.ReadDir(config.Lib, "lib")
if err == nil { if err == nil {
for _, de := range coreFiles { for _, de := range libFiles {
if de.IsDir() || !strings.HasSuffix(de.Name(), ".lua") { if de.IsDir() || !strings.HasSuffix(de.Name(), ".lua") {
continue continue
} }
path := filepath.Join("core", de.Name()) path := filepath.Join("lib", de.Name())
fileData, err := config.Core.ReadFile(path) fileData, err := config.Lib.ReadFile(path)
if err != nil { if err != nil {
continue continue
} }
@@ -157,7 +115,7 @@ func loadLua(entry string, cfg *config.MyConfig, requestData reqData) ([]byte, e
preloadLuaModule := func(name, path string) { preloadLuaModule := func(name, path string) {
L.PreloadModule(name, func(L *lua.LState) int { L.PreloadModule(name, func(L *lua.LState) int {
fileData, err := config.Core.ReadFile(path) fileData, err := config.Lib.ReadFile(path)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@@ -169,24 +127,24 @@ func loadLua(entry string, cfg *config.MyConfig, requestData reqData) ([]byte, e
}) })
} }
preloadLuaModule("core.std", "core/std.lua") preloadLuaModule("lib.std", "lib/std.lua")
preloadLuaModule("core.symbol", "core/symbol.lua") preloadLuaModule("lib.symbol", "lib/symbol.lua")
preloadLuaModule("core.util", "core/util.lua") preloadLuaModule("lib.util", "lib/util.lua")
L.PreloadModule("fes", func(L *lua.LState) int { L.PreloadModule("fes", func(L *lua.LState) int {
mod := L.NewTable() mod := L.NewTable()
coreModules := []string{} libModules := []string{}
if ents, err := fs.ReadDir(config.Core, "core"); err == nil { if ents, err := fs.ReadDir(config.Lib, "lib"); err == nil {
for _, e := range ents { for _, e := range ents {
if e.IsDir() || !strings.HasSuffix(e.Name(), ".lua") { if e.IsDir() || !strings.HasSuffix(e.Name(), ".lua") {
continue continue
} }
coreModules = append(coreModules, strings.TrimSuffix(e.Name(), ".lua")) libModules = append(libModules, strings.TrimSuffix(e.Name(), ".lua"))
} }
} }
for _, modName := range coreModules { for _, modName := range libModules {
path := filepath.Join("core", modName+".lua") path := filepath.Join("lib", modName+".lua")
fileData, err := config.Core.ReadFile(path) fileData, err := config.Lib.ReadFile(path)
if err != nil { if err != nil {
continue continue
} }
@@ -199,7 +157,7 @@ func loadLua(entry string, cfg *config.MyConfig, requestData reqData) ([]byte, e
if !ok || tbl == nil { if !ok || tbl == nil {
tbl = L.NewTable() tbl = L.NewTable()
} }
if modName == "builtin" { if modName == "fes" {
tbl.ForEach(func(k, v lua.LValue) { mod.RawSet(k, v) }) tbl.ForEach(func(k, v lua.LValue) { mod.RawSet(k, v) })
} else { } else {
mod.RawSetString(modName, tbl) mod.RawSetString(modName, tbl)
@@ -351,7 +309,7 @@ func generateArchiveIndex(fsPath string, urlPath string) (string, error) {
return b.String(), nil return b.String(), nil
} }
func generateNotFoundData(cfg *config.MyConfig) []byte { func generateNotFoundData(cfg *config.AppConfig) []byte {
notFoundData := []byte(` notFoundData := []byte(`
<html> <html>
<head><title>404 Not Found</title></head> <head><title>404 Not Found</title></head>
@@ -397,14 +355,14 @@ func loadDirs() map[string]string {
return routes return routes
} }
func parseConfig() config.MyConfig { func parseConfig() config.AppConfig {
tomlDocument, err := os.ReadFile("Fes.toml") tomlDocument, err := os.ReadFile("Fes.toml")
if err != nil { if err != nil {
ui.Error("failed to read Fes.toml", err) ui.Error("failed to read Fes.toml", err)
os.Exit(1) os.Exit(1)
} }
docStr := fixMalformedToml(string(tomlDocument)) docStr := fixMalformedToml(string(tomlDocument))
var cfg config.MyConfig var cfg config.AppConfig
if err := toml.Unmarshal([]byte(docStr), &cfg); err != nil { if err := toml.Unmarshal([]byte(docStr), &cfg); err != nil {
ui.Warning("failed to parse Fes.toml", err) ui.Warning("failed to parse Fes.toml", err)
cfg.App.Authors = []string{"unknown"} cfg.App.Authors = []string{"unknown"}

45
modules/server/util.go Normal file
View File

@@ -0,0 +1,45 @@
package server
import (
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/html"
"github.com/gomarkdown/markdown/parser"
"regexp"
"strings"
)
func joinBase(base, name string) string {
if base == "" {
return "/" + name
}
return base + "/" + name
}
func basePath(base string) string {
if base == "" || base == "." {
return "/"
}
return base
}
func fixMalformedToml(content string) string {
re := regexp.MustCompile(`(?m)^(\s*\w+\s*=\s*)$`)
return re.ReplaceAllStringFunc(content, func(match string) string {
parts := strings.Split(strings.TrimSpace(match), "=")
if len(parts) == 2 && strings.TrimSpace(parts[1]) == "" {
key := strings.TrimSpace(parts[0])
return key + " = \"\""
}
return match
})
}
func markdownToHTML(mdText string) string {
extensions := parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock
p := parser.NewWithExtensions(extensions)
doc := p.Parse([]byte(mdText))
htmlFlags := html.CommonFlags | html.HrefTargetBlank
opts := html.RendererOptions{Flags: htmlFlags}
renderer := html.NewRenderer(opts)
return string(markdown.Render(doc, renderer))
}

View File

@@ -5,8 +5,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"fes/src/config" "fes/modules/config"
"fes/src/version" "fes/modules/version"
"github.com/fatih/color" "github.com/fatih/color"
) )

View File

@@ -5,6 +5,8 @@ import (
"os" "os"
) )
var gitCommit string = "devel"
const PROGRAM_NAME string = "fes" const PROGRAM_NAME string = "fes"
const PROGRAM_NAME_LONG string = "fes/fSD" const PROGRAM_NAME_LONG string = "fes/fSD"
const VERSION string = "beta" const VERSION string = "beta"
@@ -13,3 +15,8 @@ func Version() {
fmt.Printf("%s version %s\n", PROGRAM_NAME_LONG, VERSION) fmt.Printf("%s version %s\n", PROGRAM_NAME_LONG, VERSION)
os.Exit(0) os.Exit(0)
} }
func FullVersion() {
fmt.Printf("%s+%s\n", VERSION, gitCommit)
os.Exit(0)
}