rwiki/server/main.go
2024-03-01 02:23:26 +05:00

108 lines
2 KiB
Go

package server
import (
"github.com/gomarkdown/markdown"
"vultras.su/core/bond"
"vultras.su/core/bond/contents"
"vultras.su/util/pp"
"path/filepath"
"os"
)
type ServerOptions struct {
WikiPath string
WebPath string
}
type Server struct {
handler bond.Handler
options ServerOptions
prep *pp.Preprocessor
}
func New(opts ServerOptions) *Server {
srv := &Server{}
srv.handler = makeRootHandler(opts)
srv.options = opts
srv.prep = pp.NewPp(pp.NewTengo())
return srv
}
func (srv *Server) Handle(c *bond.Context) {
c.Data = ContextData{
Server: srv,
}
srv.handler.Handle(c)
}
func (srv *Server) ProcessPmd(pth string, bts []byte) ([]byte, error) {
prep, err := srv.prep.Process(pth, string(bts))
if err != nil {
return nil, err
}
return []byte(prep), nil
}
func (srv *Server) ProcessToHtml(bts []byte) ([]byte, error) {
html := markdown.ToHTML(bts, nil, nil)
ret := append([]byte(htmlHead), html...)
return append(ret, []byte(htmlFooter)...), nil
}
func (srv *Server) wikiFilePath(pth string) string {
if pth == "/" || pth == "" {
return srv.options.WikiPath + "/index.pmd"
}
if pth[len(pth)-1] == '/' {
pth += "index"
}
return filepath.FromSlash(
srv.options.WikiPath + "/" + pth + ".pmd",
)
}
const htmlHead = `
<!doctype html>
<html><head>
<title>Title</title>
<link rel="stylesheet" href="/web/main.css">
</head><body>
<main>
`
const htmlFooter = `
</main>
</body></html>
`
var makeRootHandler = func(opts ServerOptions) bond.Handler {
return bond.Root(bond.Path().
Case(
"web",
bond.StaticDir(opts.WebPath),
).Case(
"api",
nil,
).Default(
Func(func(c *Context){
pth := c.wikiFilePath(c.Path())
bts, err := os.ReadFile(pth)
if err != nil {
c.NotFound()
return
}
prep, err := c.ProcessPmd(pth, bts)
if err != nil {
c.InternalServerError(err)
return
}
bts, _ = c.ProcessToHtml(prep)
c.SetContentType(contents.Html, contents.Utf8)
c.W.Write(bts)
}),
))
}