165 lines
3.6 KiB
Go
165 lines
3.6 KiB
Go
package server
|
|
|
|
import (
|
|
"fes/modules/config"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
lua "github.com/yuin/gopher-lua"
|
|
)
|
|
|
|
/* this is the request data we pass over the bus to the application, via the fes.bus interface */
|
|
type reqData struct {
|
|
path string
|
|
params map[string]string
|
|
}
|
|
|
|
/* returns a string of rendered html */
|
|
func render(luapath string, requestData reqData) ([]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 {
|
|
continue
|
|
} else {
|
|
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)
|
|
}
|
|
L.Push(L.Get(-1))
|
|
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 {
|
|
mod := L.NewTable()
|
|
libModules := []string{}
|
|
if ents, err := fs.ReadDir(config.Lib, "lib"); err == nil {
|
|
for _, e := range ents {
|
|
if e.IsDir() || !strings.HasSuffix(e.Name(), ".lua") {
|
|
continue
|
|
}
|
|
libModules = append(libModules, strings.TrimSuffix(e.Name(), ".lua"))
|
|
}
|
|
}
|
|
for _, modName := range libModules {
|
|
path := filepath.Join("lib", modName+".lua")
|
|
fileData, err := config.Lib.ReadFile(path)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if err := L.DoString(string(fileData)); err != nil {
|
|
continue
|
|
}
|
|
val := L.Get(-1)
|
|
L.Pop(1)
|
|
tbl, ok := val.(*lua.LTable)
|
|
if !ok || tbl == nil {
|
|
tbl = L.NewTable()
|
|
}
|
|
if modName == "fes" {
|
|
tbl.ForEach(func(k, v lua.LValue) { mod.RawSet(k, v) })
|
|
} else {
|
|
mod.RawSetString(modName, tbl)
|
|
}
|
|
}
|
|
|
|
mod.RawSetString("app", func() *lua.LTable {
|
|
app := L.NewTable()
|
|
includeDir := "include"
|
|
|
|
includes, err := os.ReadDir(includeDir)
|
|
if err != nil {
|
|
return app // load no includes
|
|
}
|
|
|
|
for _, de := range includes {
|
|
if de.IsDir() || !strings.HasSuffix(de.Name(), ".lua") {
|
|
continue
|
|
}
|
|
|
|
base := strings.TrimSuffix(de.Name(), ".lua")
|
|
path := filepath.Join(includeDir, de.Name())
|
|
|
|
if _, err := os.Stat(path); err != nil {
|
|
continue
|
|
} else if err := L.DoFile(path); err != nil {
|
|
continue
|
|
}
|
|
|
|
val := L.Get(-1)
|
|
L.Pop(1)
|
|
tbl, ok := val.(*lua.LTable)
|
|
if !ok || tbl == nil {
|
|
tbl = L.NewTable()
|
|
}
|
|
app.RawSetString(base, tbl)
|
|
}
|
|
|
|
return app
|
|
}())
|
|
|
|
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)
|
|
mod.RawSetString("bus", bus)
|
|
|
|
mod.RawSetString("markdown_to_html", L.NewFunction(func(L *lua.LState) int {
|
|
L.Push(lua.LString(markdownToHTML(L.ToString(1))))
|
|
return 1
|
|
}))
|
|
|
|
L.Push(mod)
|
|
return 1
|
|
})
|
|
|
|
if err := L.DoFile(luapath); err != nil {
|
|
return []byte(""), err
|
|
}
|
|
|
|
if L.GetTop() == 0 {
|
|
return []byte(""), nil
|
|
}
|
|
|
|
L.SetGlobal("__fes_result", L.Get(-1))
|
|
if err := L.DoString("return tostring(__fes_result)"); err != nil {
|
|
L.GetGlobal("__fes_result")
|
|
if s := L.ToString(-1); s != "" {
|
|
return []byte(s), nil
|
|
}
|
|
return []byte(""), nil
|
|
}
|
|
|
|
if s := L.ToString(-1); s != "" {
|
|
return []byte(s), nil
|
|
}
|
|
|
|
return []byte(""), nil
|
|
}
|