Browse Source

Add support for custom pages (Fixes #393)

delete_twt
James Mills 4 weeks ago
parent
commit
4dd69dc2f6
Signed by: prologic GPG Key ID: AC4C014F1440EBD6
  1. 0
      data/pages/.gitkeep
  2. 74
      internal/handlers.go
  3. 109
      internal/page_handlers.go

0
data/pages/.gitkeep

74
internal/handlers.go

@ -1,11 +1,9 @@
package internal
import (
"embed"
"encoding/json"
"errors"
"fmt"
"html/template"
"image/png"
"io"
"io/ioutil"
@ -18,11 +16,7 @@ import (
"time"
"github.com/dgrijalva/jwt-go"
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/html"
"github.com/gomarkdown/markdown/parser"
"github.com/gorilla/feeds"
"github.com/james4k/fmatter"
"github.com/julienschmidt/httprouter"
log "github.com/sirupsen/logrus"
"github.com/vcraescu/go-paginator"
@ -46,9 +40,6 @@ var (
ErrFeedImposter = errors.New("error: imposter detected, you do not own this feed")
)
//go:embed pages/*.md
var pages embed.FS
func (s *Server) NotFoundHandler(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Accept") == "application/json" {
w.Header().Set("Content-Type", "application/json")
@ -62,71 +53,6 @@ func (s *Server) NotFoundHandler(w http.ResponseWriter, r *http.Request) {
s.render("404", w, ctx)
}
type FrontMatter struct {
Title string
}
// PageHandler ...
func (s *Server) PageHandler(name string) httprouter.Handle {
var mdTpl string
if b, err := pages.ReadFile(fmt.Sprintf("pages/%s.md", name)); err == nil {
mdTpl = string(b)
} else {
log.WithError(err).Errorf("error finding page %s", name)
panic(err)
}
return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
ctx := NewContext(s, r)
md, err := RenderHTML(mdTpl, ctx)
if err != nil {
log.WithError(err).Errorf("error rendering page %s", name)
ctx.Error = true
ctx.Message = s.tr(ctx, "ErrorRenderingPage")
s.render("error", w, ctx)
return
}
var frontmatter FrontMatter
content, err := fmatter.Read([]byte(md), &frontmatter)
if err != nil {
log.WithError(err).Error("error parsing front matter")
ctx.Error = true
ctx.Message = s.tr(ctx, "ErrorLoadingPage")
s.render("error", w, ctx)
return
}
extensions := parser.CommonExtensions | parser.AutoHeadingIDs
p := parser.NewWithExtensions(extensions)
htmlFlags := html.CommonFlags
opts := html.RendererOptions{
Flags: htmlFlags,
Generator: "",
}
renderer := html.NewRenderer(opts)
html := markdown.ToHTML(content, p, renderer)
var title string
if frontmatter.Title != "" {
title = frontmatter.Title
} else {
title = strings.Title(name)
}
ctx.Title = title
ctx.Page = name
ctx.Content = template.HTML(html)
s.render("page", w, ctx)
}
}
// UserConfigHandler ...
func (s *Server) UserConfigHandler() httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {

109
internal/page_handlers.go

@ -0,0 +1,109 @@
package internal
import (
"embed"
"fmt"
"html/template"
"net/http"
"os"
"path/filepath"
"strings"
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/html"
"github.com/gomarkdown/markdown/parser"
"github.com/james4k/fmatter"
"github.com/julienschmidt/httprouter"
log "github.com/sirupsen/logrus"
)
const (
pagesDir = "pages"
markdownErrorPageTemplate = `# Error loading page
An error occurred trying to read the source of this page {{ .Page }}
Please try again later...`
)
//go:embed pages/*.md
var builtinPages embed.FS
type FrontMatter struct {
Title string
Description string
}
// PageHandler ...
func (s *Server) PageHandler(page string) httprouter.Handle {
var markdownTemplate string
name := filepath.Join(pagesDir, fmt.Sprintf("%s.md", page))
fn := filepath.Join(s.config.Data, name)
if FileExists(fn) {
if data, err := os.ReadFile(fn); err != nil {
log.WithError(err).Errorf("error reading custom page %s", page)
markdownTemplate = markdownErrorPageTemplate
} else {
markdownTemplate = string(data)
}
} else {
if data, err := builtinPages.ReadFile(name); err != nil {
log.WithError(err).Errorf("error reading custom page %s", page)
markdownTemplate = markdownErrorPageTemplate
} else {
markdownTemplate = string(data)
}
}
return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
ctx := NewContext(s, r)
markdownContent, err := RenderHTML(markdownTemplate, ctx)
if err != nil {
log.WithError(err).Errorf("error rendering page %s", name)
ctx.Error = true
ctx.Message = s.tr(ctx, "ErrorRenderingPage")
s.render("error", w, ctx)
return
}
var frontmatter FrontMatter
content, err := fmatter.Read([]byte(markdownContent), &frontmatter)
if err != nil {
log.WithError(err).Error("error parsing front matter")
ctx.Error = true
ctx.Message = s.tr(ctx, "ErrorLoadingPage")
s.render("error", w, ctx)
return
}
extensions := parser.CommonExtensions | parser.AutoHeadingIDs
p := parser.NewWithExtensions(extensions)
htmlFlags := html.CommonFlags
opts := html.RendererOptions{
Flags: htmlFlags,
Generator: "",
}
renderer := html.NewRenderer(opts)
html := markdown.ToHTML(content, p, renderer)
var title string
if frontmatter.Title != "" {
title = frontmatter.Title
} else {
title = strings.Title(name)
}
ctx.Title = title
ctx.Meta.Description = frontmatter.Description
ctx.Page = name
ctx.Content = template.HTML(html)
s.render("page", w, ctx)
}
}
Loading…
Cancel
Save