aboutsummaryrefslogtreecommitdiff
path: root/page
diff options
context:
space:
mode:
Diffstat (limited to 'page')
-rw-r--r--page/page.go58
-rw-r--r--page/render.go137
2 files changed, 160 insertions, 35 deletions
diff --git a/page/page.go b/page/page.go
index b2cc3e1..adb2362 100644
--- a/page/page.go
+++ b/page/page.go
@@ -46,11 +46,11 @@ import (
// The exported fields can be filled in the yaml at the top of a page and
// utilized within.
type Page struct {
- path string
- Title string
- Description string
- AuthorName string
- AuthorEmail string
+ path string
+ DefaultTitle string `yaml:"title"`
+ DefaultDescription string `yaml:"description"`
+ AuthorName string
+ AuthorEmail string
// Tags to apply to the page in question. Useful for Index()
Tags map[string]interface{}
Date *PageTime
@@ -76,8 +76,14 @@ var CacheIndex = true
// backend.
var FileSystem = os.DirFS(".")
+// TemplateDirectory is the parent directory which templates are stored,
+// usually the BaseTemplate is stored here as well, though it does not
+// have to be. Currently this is used for the 4xx and 5xx pages. ( 4xx.md
+// and 5xx.md respectively.
+var TemplateDirectory = "tpl"
+
// BaseTemplate can be adjusted to change the base template used in rendering.
-var BaseTemplate = "inc/base.html"
+var BaseTemplate = "tpl/base.md"
// Suffix is applied to all pages for reading off of the disk.
var Suffix = ".md"
@@ -107,6 +113,46 @@ func (p Page) Path() string {
return filepath.ToSlash(p.path)
}
+// Title returns `DefaultTitle` unless `.Vars.Title` is
+// set, then it returns that instead.
+func (p Page) Title() string {
+ if p.Vars == nil {
+ return p.DefaultTitle
+ }
+
+ t, ok := p.Vars["Title"]
+ if !ok {
+ return p.DefaultTitle
+ }
+
+ nt, ok := t.(string)
+ if !ok {
+ return p.DefaultTitle
+ }
+
+ return nt
+}
+
+// Description returns `DefaultDescription` unless `.Vars.Description` is
+// set, then it returns that instead.
+func (p Page) Description() string {
+ if p.Vars == nil {
+ return p.DefaultDescription
+ }
+
+ t, ok := p.Vars["Description"]
+ if !ok {
+ return p.DefaultDescription
+ }
+
+ nt, ok := t.(string)
+ if !ok {
+ return p.DefaultDescription
+ }
+
+ return nt
+}
+
// Global is specifically for use inside of a page markdown file or
// in a base template. This simply returns the package Global variable.
func (p *Page) Global() interface{} {
diff --git a/page/render.go b/page/render.go
index 6cbabf9..d35ba38 100644
--- a/page/render.go
+++ b/page/render.go
@@ -1,20 +1,104 @@
package page
import (
+ "bytes"
"net/http"
"path/filepath"
"strings"
)
-// Render is a lower level option, allowing you to specify local
-// variables and the status code in which to return.
-func Render(w http.ResponseWriter, r *http.Request,
- path string, vars map[string]interface{}, statusCode int) {
+func getURLPath(r *http.Request) string {
u := r.URL.Path
if u == "/" {
u = "/index"
}
+ return u
+}
+
+// Render5xx is automatically called if any render fails,
+// additionally you can call it for your own uses. It will
+// try to use the 5xx template but will fall back to a plain
+// page if that fails.
+func Render5xx(w http.ResponseWriter, r *http.Request,
+ vars map[string]interface{}, statusCode int) {
+ u := getURLPath(r)
+
+ Logger.Printf("%s %s %d %s",
+ r.RemoteAddr,
+ r.Method,
+ statusCode,
+ u)
+
+ p := NewPage(TemplateDirectory + "/5xx")
+
+ buf := &bytes.Buffer{}
+
+ err := p.Render(buf)
+ if err != nil {
+ Logger.Printf("%s %s path: %s while trying 5xx: %s",
+ r.RemoteAddr,
+ r.Method,
+ u,
+ err)
+ http.Error(w, "Internal server error", statusCode)
+
+ return
+ }
+
+ w.WriteHeader(statusCode)
+
+ _, _ = w.Write(buf.Bytes())
+
+ Logger.Printf("%s %s %d %s", r.RemoteAddr, r.Method, statusCode, u)
+}
+
+// Render4xx is mostly used to render a 404 page, pulls from 404 template.
+// automatically called by Render if a page is missing.
+func Render4xx(w http.ResponseWriter, r *http.Request,
+ vars map[string]interface{}, statusCode int) {
+ u := getURLPath(r)
+
+ Logger.Printf("%s %s %d %s",
+ r.RemoteAddr,
+ r.Method,
+ statusCode,
+ u)
+
+ p := NewPage(TemplateDirectory + "/4xx")
+
+ buf := &bytes.Buffer{}
+
+ err := p.Render(buf)
+ if err != nil {
+ Logger.Printf("%s %s path: %s while trying 404: %s",
+ r.RemoteAddr,
+ r.Method,
+ u,
+ err)
+ Render5xx(w, r, vars, http.StatusInternalServerError)
+
+ return
+ }
+
+ w.WriteHeader(statusCode)
+
+ _, err = w.Write(buf.Bytes())
+ if err != nil {
+ Render5xx(w, r, nil, http.StatusInternalServerError)
+
+ return
+ }
+
+ Logger.Printf("%s %s %d %s", r.RemoteAddr, r.Method, statusCode, u)
+}
+
+// Render is a lower level option, allowing you to specify local
+// variables and the status code in which to return.
+func Render(w http.ResponseWriter, r *http.Request,
+ path string, vars map[string]interface{}, statusCode int) {
+ u := getURLPath(r)
+
u = filepath.Join(".", u)
// Sepcifically use the specified path for the page
@@ -24,42 +108,37 @@ func Render(w http.ResponseWriter, r *http.Request,
p.Vars = vars
}
- err := p.Render(w)
+ buf := &bytes.Buffer{}
+
+ err := p.Render(buf)
if err != nil {
if strings.HasSuffix(err.Error(), "no such file or directory") {
- Logger.Printf("%s %s %d %s",
- r.RemoteAddr,
- r.Method,
- http.StatusNotFound,
- u)
+ Render4xx(w, r, vars, http.StatusNotFound)
- p = NewPage("404")
-
- w.WriteHeader(http.StatusNotFound)
+ return
+ }
- err := p.Render(w)
- if err != nil {
- Logger.Printf("%s %s path: %s while trying 404: %s",
- r.RemoteAddr,
- r.Method,
- u,
- err)
- http.Error(w, "Internal server error",
- http.StatusInternalServerError)
+ Logger.Printf("%s %s path: %s rendering encountered: %s",
+ r.RemoteAddr,
+ r.Method,
+ u,
+ err)
+ Render5xx(w, r, vars, http.StatusInternalServerError)
- return
- }
+ return
+ }
- return
- }
+ w.WriteHeader(statusCode)
- Logger.Printf("%s %s path: %s encountered: %s",
+ _, err = w.Write(buf.Bytes())
+ if err != nil {
+ Logger.Printf("%s %s %d %s: while writing buf: %s",
r.RemoteAddr,
r.Method,
+ statusCode,
u,
err)
- http.Error(w, "Internal server error",
- http.StatusInternalServerError)
+ Render5xx(w, r, nil, http.StatusInternalServerError)
return
}