package server import ( "github.com/gomarkdown/markdown" "github.com/gomarkdown/markdown/html" "github.com/gomarkdown/markdown/parser" "vultras.su/core/bond" "vultras.su/core/bond/contents" "vultras.su/util/pp" "path/filepath" "path" "os" "fmt" //"strings" "bytes" ) const htmlHead = ` Title ` const htmlFooter = ` ` type ServerOptions struct { WikiPath string WikiExt string WebPath string AddFileNavigation bool AddDocNavigation bool } type Server struct { handler bond.Handler options ServerOptions prep *pp.Preprocessor } func (srv *Server) makeMdParser() *parser.Parser { return parser.NewWithExtensions( parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock | parser.Attributes | parser.Tables, ) } func (srv *Server) makeHtmlRenderer() *html.Renderer { return html.NewRenderer( html.RendererOptions{ Flags: html.CommonFlags | html.HrefTargetBlank, }, ) } 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) pageHead() string { return htmlHead } func (srv *Server) pageFooter() string { return htmlFooter } func (srv *Server) ProcessToHtml(urlPath, filePath string, bts []byte) ([]byte, error) { var b bytes.Buffer doc := srv.makeMdParser().Parse(bts) main_section := markdown.Render(doc, srv.makeHtmlRenderer()) fmt.Fprint(&b, srv.pageHead()) if srv.options.AddFileNavigation { fileDirPath := filepath.Dir(filePath) urlDirPath := path.Dir(urlPath) entries, err := os.ReadDir(fileDirPath) if err != nil { fmt.Println("leaving", fileDirPath) return nil, err } fmt.Fprint(&b, "
") fmt.Fprint(&b, "") fmt.Fprint(&b, "") fmt.Fprint(&b, "") headings := getDocumentHeadings(doc) trees := makeHeadingTrees(headings) docNav := RenderHeadingTrees(trees, true) fmt.Fprint(&b, docNav) fmt.Fprint(&b, "
") } fmt.Fprint(&b, "
") fmt.Fprint(&b, string(main_section)) fmt.Fprint(&b, "
") fmt.Fprint(&b, srv.pageFooter()) return b.Bytes(), nil } var makeRootHandler = func(opts ServerOptions) bond.Handler { return 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 { 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 } fmt.Println(c.Path(), pth) bts, err = c.ProcessToHtml(c.Path(), pth, prep) if err != nil { c.InternalServerError(err) return } c.SetContentType(contents.Html, contents.Utf8) c.W.Write(bts) }), ) }