Files
fes/modules/server/render.go
2026-03-01 21:51:37 -05:00

153 lines
2.8 KiB
Go

package server
import (
"fes/modules/config"
"io/fs"
"path/filepath"
"strings"
lua "github.com/yuin/gopher-lua"
)
type reqData struct {
path string
params map[string]string
}
func render(luapath string, requestData reqData, protocol Protocols) ([]byte, error) {
L := lua.NewState()
defer L.Close()
if lib, err := fs.ReadDir(config.Lib, "lib"); err == nil {
for _, de := range lib {
if de.IsDir() || !strings.HasSuffix(de.Name(), ".lua") {
continue
}
path := filepath.Join("lib", de.Name())
if data, err := config.Lib.ReadFile(path); err == nil {
_ = L.DoString(string(data))
}
}
}
preloadLuaModule := func(name, path string) {
L.PreloadModule(name, func(L *lua.LState) int {
fileData, err := config.Lib.ReadFile(path)
if err != nil {
panic(err)
}
if err := L.DoString(string(fileData)); err != nil {
panic(err)
}
return 1
})
}
preloadLuaModule("lib.std", "lib/std.lua")
preloadLuaModule("lib.symbol", "lib/symbol.lua")
preloadLuaModule("lib.util", "lib/util.lua")
L.PreloadModule("fes", func(L *lua.LState) int {
fileData, err := config.Lib.ReadFile("lib/fes.lua")
if err != nil {
panic(err)
}
if err := L.DoString(string(fileData)); err != nil {
panic(err)
}
mod := L.Get(-1)
L.Pop(1)
tbl, ok := mod.(*lua.LTable)
if !ok {
panic("fes module did not return table")
}
if err := L.CallByParam(lua.P{
Fn: L.GetGlobal("require"),
NRet: 1,
Protect: true,
}, lua.LString("lib.std")); err != nil {
panic(err)
}
stdMod := L.Get(-1)
L.Pop(1)
stdTbl, ok := stdMod.(*lua.LTable)
if !ok {
panic("lib.std did not return table")
}
proto := func() string {
switch protocol {
case HTTP:
return "http"
case GEMINI:
return "gemini"
default:
return "http"
}
}()
proto = "gemini"
stdTbl.RawSetString("proto", lua.LString(proto))
tbl.RawSetString("std", stdTbl)
bus := L.NewTable()
bus.RawSetString("url", lua.LString(requestData.path))
params := L.NewTable()
for k, v := range requestData.params {
params.RawSetString(k, lua.LString(v))
}
bus.RawSetString("params", params)
tbl.RawSetString("bus", bus)
tbl.RawSetString("markdown_to_html", L.NewFunction(func(L *lua.LState) int {
L.Push(lua.LString(markdownToHTML(L.ToString(1))))
return 1
}))
L.Push(tbl)
return 1
})
if err := L.DoFile(luapath); err != nil {
return []byte(""), err
}
if L.GetTop() == 0 {
return []byte(""), nil
}
val := L.Get(-1)
L.Pop(1)
if val == lua.LNil {
return []byte(""), nil
}
if err := L.CallByParam(lua.P{
Fn: L.GetGlobal("tostring"),
NRet: 1,
Protect: true,
}, val); err != nil {
return nil, err
}
s := L.ToString(-1)
L.Pop(1)
if s != "" {
return []byte(s), nil
}
return []byte(""), nil
}