mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
markdown: sitegen keyword and run generation at startup
Also fixed bug for markdown files that don't contain front matter
This commit is contained in:
parent
a96c4d707b
commit
4272536518
3 changed files with 110 additions and 40 deletions
|
@ -1,9 +1,12 @@
|
||||||
package setup
|
package setup
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/mholt/caddy/middleware"
|
"github.com/mholt/caddy/middleware"
|
||||||
"github.com/mholt/caddy/middleware/markdown"
|
"github.com/mholt/caddy/middleware/markdown"
|
||||||
|
@ -24,6 +27,57 @@ func Markdown(c *Controller) (middleware.Middleware, error) {
|
||||||
IndexFiles: []string{"index.md"},
|
IndexFiles: []string{"index.md"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For any configs that enabled static site gen, sweep the whole path at startup
|
||||||
|
c.Startup = append(c.Startup, func() error {
|
||||||
|
for _, cfg := range mdconfigs {
|
||||||
|
if cfg.StaticDir == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// If generated site already exists, clear it out
|
||||||
|
_, err := os.Stat(cfg.StaticDir)
|
||||||
|
if err == nil {
|
||||||
|
err := os.RemoveAll(cfg.StaticDir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fp := filepath.Join(md.Root, cfg.PathScope)
|
||||||
|
filepath.Walk(fp, func(path string, info os.FileInfo, err error) error {
|
||||||
|
for _, ext := range cfg.Extensions {
|
||||||
|
if !info.IsDir() && strings.HasSuffix(info.Name(), ext) {
|
||||||
|
// Load the file
|
||||||
|
body, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the relative path as if it were a HTTP request,
|
||||||
|
// then prepend with "/" (like a real HTTP request)
|
||||||
|
reqPath, err := filepath.Rel(md.Root, path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
reqPath = "/" + reqPath
|
||||||
|
|
||||||
|
// Generate the static file
|
||||||
|
_, err = md.Process(cfg, reqPath, body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
break // don't try other file extensions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
return func(next middleware.Handler) middleware.Handler {
|
return func(next middleware.Handler) middleware.Handler {
|
||||||
md.Next = next
|
md.Next = next
|
||||||
return md
|
return md
|
||||||
|
@ -38,7 +92,6 @@ func markdownParse(c *Controller) ([]markdown.Config, error) {
|
||||||
Renderer: blackfriday.HtmlRenderer(0, "", ""),
|
Renderer: blackfriday.HtmlRenderer(0, "", ""),
|
||||||
Templates: make(map[string]string),
|
Templates: make(map[string]string),
|
||||||
StaticFiles: make(map[string]string),
|
StaticFiles: make(map[string]string),
|
||||||
StaticDir: path.Join(c.Root, markdown.StaticDir),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the path scope
|
// Get the path scope
|
||||||
|
@ -83,6 +136,16 @@ func markdownParse(c *Controller) ([]markdown.Config, error) {
|
||||||
default:
|
default:
|
||||||
return mdconfigs, c.ArgErr()
|
return mdconfigs, c.ArgErr()
|
||||||
}
|
}
|
||||||
|
case "sitegen":
|
||||||
|
if c.NextArg() {
|
||||||
|
md.StaticDir = path.Join(c.Root, c.Val())
|
||||||
|
} else {
|
||||||
|
md.StaticDir = path.Join(c.Root, markdown.DefaultStaticDir)
|
||||||
|
}
|
||||||
|
if c.NextArg() {
|
||||||
|
// only 1 argument allowed
|
||||||
|
return mdconfigs, c.ArgErr()
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return mdconfigs, c.Err("Expected valid markdown configuration property")
|
return mdconfigs, c.Err("Expected valid markdown configuration property")
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,11 @@ func (md Markdown) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
|
||||||
if html, err := ioutil.ReadFile(filepath); err == nil {
|
if html, err := ioutil.ReadFile(filepath); err == nil {
|
||||||
w.Write(html)
|
w.Write(html)
|
||||||
return http.StatusOK, nil
|
return http.StatusOK, nil
|
||||||
|
} else {
|
||||||
|
if os.IsPermission(err) {
|
||||||
|
return http.StatusForbidden, err
|
||||||
|
}
|
||||||
|
return http.StatusNotFound, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,7 +120,7 @@ func (md Markdown) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
|
||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
|
|
||||||
html, err := md.process(m, fpath, body)
|
html, err := md.Process(m, fpath, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package markdown
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
@ -15,12 +14,12 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultTemplate = "defaultTemplate"
|
DefaultTemplate = "defaultTemplate"
|
||||||
StaticDir = ".caddy_static"
|
DefaultStaticDir = "generated_site"
|
||||||
)
|
)
|
||||||
|
|
||||||
// process processes the contents of a page.
|
// Process processes the contents of a page in b. It parses the metadata
|
||||||
// It parses the metadata (if any) and uses the template (if found)
|
// (if any) and uses the template (if found).
|
||||||
func (md Markdown) process(c Config, requestPath string, b []byte) ([]byte, error) {
|
func (md Markdown) Process(c Config, requestPath string, b []byte) ([]byte, error) {
|
||||||
var metadata = Metadata{Variables: make(map[string]interface{})}
|
var metadata = Metadata{Variables: make(map[string]interface{})}
|
||||||
var markdown []byte
|
var markdown []byte
|
||||||
var err error
|
var err error
|
||||||
|
@ -28,8 +27,11 @@ func (md Markdown) process(c Config, requestPath string, b []byte) ([]byte, erro
|
||||||
// find parser compatible with page contents
|
// find parser compatible with page contents
|
||||||
parser := findParser(b)
|
parser := findParser(b)
|
||||||
|
|
||||||
|
if parser == nil {
|
||||||
|
// if not found, assume whole file is markdown (no front matter)
|
||||||
|
markdown = b
|
||||||
|
} else {
|
||||||
// if found, assume metadata present and parse.
|
// if found, assume metadata present and parse.
|
||||||
if parser != nil {
|
|
||||||
markdown, err = parser.Parse(b)
|
markdown, err = parser.Parse(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -74,7 +76,7 @@ func (md Markdown) processTemplate(c Config, requestPath string, tmpl []byte, me
|
||||||
}
|
}
|
||||||
|
|
||||||
// process the template
|
// process the template
|
||||||
b := &bytes.Buffer{}
|
b := new(bytes.Buffer)
|
||||||
t, err := template.New("").Parse(string(tmpl))
|
t, err := template.New("").Parse(string(tmpl))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -87,6 +89,7 @@ func (md Markdown) processTemplate(c Config, requestPath string, tmpl []byte, me
|
||||||
if err = md.generatePage(c, requestPath, b.Bytes()); err != nil {
|
if err = md.generatePage(c, requestPath, b.Bytes()); err != nil {
|
||||||
// if static page generation fails,
|
// if static page generation fails,
|
||||||
// nothing fatal, only log the error.
|
// nothing fatal, only log the error.
|
||||||
|
// TODO: Report this non-fatal error, but don't log it here
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,14 +97,11 @@ func (md Markdown) processTemplate(c Config, requestPath string, tmpl []byte, me
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// generatePage generates a static html page from the markdown in content.
|
// generatePage generates a static html page from the markdown in content if c.StaticDir
|
||||||
|
// is a non-empty value, meaning that the user enabled static site generation.
|
||||||
func (md Markdown) generatePage(c Config, requestPath string, content []byte) error {
|
func (md Markdown) generatePage(c Config, requestPath string, content []byte) error {
|
||||||
// should not happen,
|
// Only generate the page if static site generation is enabled
|
||||||
// must be set on Markdown init.
|
if c.StaticDir != "" {
|
||||||
if c.StaticDir == "" {
|
|
||||||
return fmt.Errorf("Static directory not set")
|
|
||||||
}
|
|
||||||
|
|
||||||
// if static directory is not existing, create it
|
// if static directory is not existing, create it
|
||||||
if _, err := os.Stat(c.StaticDir); err != nil {
|
if _, err := os.Stat(c.StaticDir); err != nil {
|
||||||
err := os.MkdirAll(c.StaticDir, os.FileMode(0755))
|
err := os.MkdirAll(c.StaticDir, os.FileMode(0755))
|
||||||
|
@ -118,18 +118,20 @@ func (md Markdown) generatePage(c Config, requestPath string, content []byte) er
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the directory in case it is not existing
|
// Create the directory in case it is not existing
|
||||||
if err := os.MkdirAll(filePath, os.FileMode(0755)); err != nil {
|
if err := os.MkdirAll(filePath, os.FileMode(0744)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate index.html file in the directory
|
// generate index.html file in the directory
|
||||||
filePath = filepath.Join(filePath, "index.html")
|
filePath = filepath.Join(filePath, "index.html")
|
||||||
err := ioutil.WriteFile(filePath, content, os.FileMode(0755))
|
err := ioutil.WriteFile(filePath, content, os.FileMode(0664))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.StaticFiles[requestPath] = filePath
|
c.StaticFiles[requestPath] = filePath
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue