mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-07 11:28:48 +03:00
Merge branch 'master' into macros
This commit is contained in:
commit
345b312e00
4 changed files with 71 additions and 16 deletions
|
@ -68,8 +68,13 @@ type Config struct {
|
||||||
// Template(s) to render with
|
// Template(s) to render with
|
||||||
Template *template.Template
|
Template *template.Template
|
||||||
|
|
||||||
// a pair of template's name and its underlying file path
|
// a pair of template's name and its underlying file information
|
||||||
TemplateFiles map[string]string
|
TemplateFiles map[string]*cachedFileInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type cachedFileInfo struct {
|
||||||
|
path string
|
||||||
|
fi os.FileInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeHTTP implements the http.Handler interface.
|
// ServeHTTP implements the http.Handler interface.
|
||||||
|
|
|
@ -62,7 +62,7 @@ func markdownParse(c *caddy.Controller) ([]*Config, error) {
|
||||||
Extensions: make(map[string]struct{}),
|
Extensions: make(map[string]struct{}),
|
||||||
Template: GetDefaultTemplate(),
|
Template: GetDefaultTemplate(),
|
||||||
IndexFiles: []string{},
|
IndexFiles: []string{},
|
||||||
TemplateFiles: make(map[string]string),
|
TemplateFiles: make(map[string]*cachedFileInfo),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the path scope
|
// Get the path scope
|
||||||
|
@ -133,7 +133,9 @@ func loadParams(c *caddy.Controller, mdc *Config) error {
|
||||||
return c.Errf("default template parse error: %v", err)
|
return c.Errf("default template parse error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mdc.TemplateFiles[""] = fpath
|
mdc.TemplateFiles[""] = &cachedFileInfo{
|
||||||
|
path: fpath,
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
case 2:
|
case 2:
|
||||||
fpath := filepath.ToSlash(filepath.Clean(cfg.Root + string(filepath.Separator) + tArgs[1]))
|
fpath := filepath.ToSlash(filepath.Clean(cfg.Root + string(filepath.Separator) + tArgs[1]))
|
||||||
|
@ -142,7 +144,9 @@ func loadParams(c *caddy.Controller, mdc *Config) error {
|
||||||
return c.Errf("template parse error: %v", err)
|
return c.Errf("template parse error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mdc.TemplateFiles[tArgs[0]] = fpath
|
mdc.TemplateFiles[tArgs[0]] = &cachedFileInfo{
|
||||||
|
path: fpath,
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case "templatedir":
|
case "templatedir":
|
||||||
|
@ -164,7 +168,9 @@ func loadParams(c *caddy.Controller, mdc *Config) error {
|
||||||
return c.Errf("glob %q failed: %v", pattern, err)
|
return c.Errf("glob %q failed: %v", pattern, err)
|
||||||
}
|
}
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
mdc.TemplateFiles[filepath.Base(path)] = path
|
mdc.TemplateFiles[filepath.Base(path)] = &cachedFileInfo{
|
||||||
|
path: path,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -77,7 +77,7 @@ func TestMarkdownParse(t *testing.T) {
|
||||||
Styles: []string{"/resources/css/blog.css"},
|
Styles: []string{"/resources/css/blog.css"},
|
||||||
Scripts: []string{"/resources/js/blog.js"},
|
Scripts: []string{"/resources/js/blog.js"},
|
||||||
Template: GetDefaultTemplate(),
|
Template: GetDefaultTemplate(),
|
||||||
TemplateFiles: make(map[string]string),
|
TemplateFiles: make(map[string]*cachedFileInfo),
|
||||||
}}},
|
}}},
|
||||||
{`markdown /blog {
|
{`markdown /blog {
|
||||||
ext .md
|
ext .md
|
||||||
|
@ -88,8 +88,8 @@ func TestMarkdownParse(t *testing.T) {
|
||||||
".md": {},
|
".md": {},
|
||||||
},
|
},
|
||||||
Template: setDefaultTemplate("./testdata/tpl_with_include.html"),
|
Template: setDefaultTemplate("./testdata/tpl_with_include.html"),
|
||||||
TemplateFiles: map[string]string{
|
TemplateFiles: map[string]*cachedFileInfo{
|
||||||
"": "testdata/tpl_with_include.html",
|
"": {path: "testdata/tpl_with_include.html"},
|
||||||
},
|
},
|
||||||
}}},
|
}}},
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@ package markdown
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/mholt/caddy/caddyhttp/httpserver"
|
"github.com/mholt/caddy/caddyhttp/httpserver"
|
||||||
|
@ -41,6 +43,8 @@ func (d Data) Include(filename string, args ...interface{}) (string, error) {
|
||||||
return httpserver.ContextInclude(filename, d, d.Root)
|
return httpserver.ContextInclude(filename, d, d.Root)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var templateUpdateMu sync.RWMutex
|
||||||
|
|
||||||
// execTemplate executes a template given a requestPath, template, and metadata
|
// execTemplate executes a template given a requestPath, template, and metadata
|
||||||
func execTemplate(c *Config, mdata metadata.Metadata, meta map[string]string, files []FileInfo, ctx httpserver.Context) ([]byte, error) {
|
func execTemplate(c *Config, mdata metadata.Metadata, meta map[string]string, files []FileInfo, ctx httpserver.Context) ([]byte, error) {
|
||||||
mdData := Data{
|
mdData := Data{
|
||||||
|
@ -51,18 +55,43 @@ func execTemplate(c *Config, mdata metadata.Metadata, meta map[string]string, fi
|
||||||
Meta: meta,
|
Meta: meta,
|
||||||
Files: files,
|
Files: files,
|
||||||
}
|
}
|
||||||
|
|
||||||
templateName := mdata.Template
|
templateName := mdata.Template
|
||||||
// reload template on every request for now
|
|
||||||
// TODO: cache templates by a general plugin
|
updateTemplate := func() error {
|
||||||
if templateFile, ok := c.TemplateFiles[templateName]; ok {
|
templateUpdateMu.Lock()
|
||||||
err := SetTemplate(c.Template, templateName, templateFile)
|
defer templateUpdateMu.Unlock()
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
templateFile, ok := c.TemplateFiles[templateName]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentFileInfo, err := os.Lstat(templateFile.path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !fileChanged(currentFileInfo, templateFile.fi) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// update template due to file changes
|
||||||
|
err = SetTemplate(c.Template, templateName, templateFile.path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
templateFile.fi = currentFileInfo
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := updateTemplate(); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
|
templateUpdateMu.RLock()
|
||||||
|
defer templateUpdateMu.RUnlock()
|
||||||
if err := c.Template.ExecuteTemplate(b, templateName, mdData); err != nil {
|
if err := c.Template.ExecuteTemplate(b, templateName, mdData); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -70,6 +99,21 @@ func execTemplate(c *Config, mdata metadata.Metadata, meta map[string]string, fi
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fileChanged(new, old os.FileInfo) bool {
|
||||||
|
// never checked before
|
||||||
|
if old == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if new.Size() != old.Size() ||
|
||||||
|
new.Mode() != old.Mode() ||
|
||||||
|
new.ModTime() != old.ModTime() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// SetTemplate reads in the template with the filename provided. If the file does not exist or is not parsable, it will return an error.
|
// SetTemplate reads in the template with the filename provided. If the file does not exist or is not parsable, it will return an error.
|
||||||
func SetTemplate(t *template.Template, name, filename string) error {
|
func SetTemplate(t *template.Template, name, filename string) error {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue