From 42b7d574210e49020cc0f6ef0490e71116c90ed8 Mon Sep 17 00:00:00 2001 From: Tobias Weingartner Date: Sun, 10 Apr 2016 23:17:01 -0700 Subject: [PATCH] Fix more tests, and fix template parsing. --- caddy/setup/markdown.go | 27 ++++++++--- caddy/setup/markdown_test.go | 59 +++++++++++++++++++++--- middleware/markdown/markdown.go | 6 +-- middleware/markdown/markdown_test.go | 47 +++++++++---------- middleware/markdown/process.go | 68 ++-------------------------- middleware/markdown/template.go | 55 ++++++++++++++++++++++ 6 files changed, 160 insertions(+), 102 deletions(-) create mode 100644 middleware/markdown/template.go diff --git a/caddy/setup/markdown.go b/caddy/setup/markdown.go index 08a05567..fdc91991 100644 --- a/caddy/setup/markdown.go +++ b/caddy/setup/markdown.go @@ -36,7 +36,7 @@ func markdownParse(c *Controller) ([]*markdown.Config, error) { md := &markdown.Config{ Renderer: blackfriday.HtmlRenderer(0, "", ""), Extensions: make(map[string]struct{}), - Templates: make(map[string]string), + Template: markdown.GetDefaultTemplate(), } // Get the path scope @@ -95,17 +95,32 @@ func loadParams(c *Controller, mdc *markdown.Config) error { default: return c.ArgErr() case 1: - if _, ok := mdc.Templates[markdown.DefaultTemplate]; ok { - return c.Err("only one default template is allowed, use alias.") - } fpath := filepath.ToSlash(filepath.Clean(c.Root + string(filepath.Separator) + tArgs[0])) - mdc.Templates[markdown.DefaultTemplate] = fpath + + if err := markdown.SetTemplate(mdc.Template, "", fpath); err != nil { + c.Errf("default template parse error: %v", err) + } return nil case 2: fpath := filepath.ToSlash(filepath.Clean(c.Root + string(filepath.Separator) + tArgs[1])) - mdc.Templates[tArgs[0]] = fpath + + if err := markdown.SetTemplate(mdc.Template, tArgs[0], fpath); err != nil { + c.Errf("template parse error: %v", err) + } return nil } + case "templatedir": + if !c.NextArg() { + return c.ArgErr() + } + _, err := mdc.Template.ParseGlob(c.Val()) + if err != nil { + c.Errf("template load error: %v", err) + } + if c.NextArg() { + return c.ArgErr() + } + return nil default: return c.Err("Expected valid markdown configuration property") } diff --git a/caddy/setup/markdown_test.go b/caddy/setup/markdown_test.go index 18af6254..e1e698b2 100644 --- a/caddy/setup/markdown_test.go +++ b/caddy/setup/markdown_test.go @@ -1,9 +1,13 @@ package setup import ( + "bytes" "fmt" + "net/http" "testing" + "text/template" + "github.com/mholt/caddy/middleware" "github.com/mholt/caddy/middleware/markdown" ) @@ -58,8 +62,9 @@ func TestMarkdownParse(t *testing.T) { ".md": struct{}{}, ".txt": struct{}{}, }, - Styles: []string{"/resources/css/blog.css"}, - Scripts: []string{"/resources/js/blog.js"}, + Styles: []string{"/resources/css/blog.css"}, + Scripts: []string{"/resources/js/blog.js"}, + Template: markdown.GetDefaultTemplate(), }}}, {`markdown /blog { ext .md @@ -69,9 +74,13 @@ func TestMarkdownParse(t *testing.T) { Extensions: map[string]struct{}{ ".md": struct{}{}, }, - Templates: map[string]string{markdown.DefaultTemplate: "testdata/tpl_with_include.html"}, + Template: markdown.GetDefaultTemplate(), }}}, } + // Setup the extra template + tmpl := tests[1].expectedMarkdownConfig[0].Template + markdown.SetTemplate(tmpl, "", "./testdata/tpl_with_include.html") + for i, test := range tests { c := NewTestController(test.inputMarkdownConfig) c.Root = "./testdata" @@ -101,11 +110,47 @@ func TestMarkdownParse(t *testing.T) { t.Errorf("Test %d expected %dth Markdown Config Scripts to be %s , but got %s", i, j, fmt.Sprint(test.expectedMarkdownConfig[j].Scripts), fmt.Sprint(actualMarkdownConfig.Scripts)) } - if fmt.Sprint(actualMarkdownConfig.Templates) != fmt.Sprint(test.expectedMarkdownConfig[j].Templates) { - t.Errorf("Test %d expected %dth Markdown Config Templates to be %s , but got %s", - i, j, fmt.Sprint(test.expectedMarkdownConfig[j].Templates), fmt.Sprint(actualMarkdownConfig.Templates)) + if ok, tx, ty := equalTemplates(actualMarkdownConfig.Template, test.expectedMarkdownConfig[j].Template); !ok { + t.Errorf("Test %d the %dth Markdown Config Templates did not match, expected %s to be %s", i, j, tx, ty) } } } - +} + +func equalTemplates(i, j *template.Template) (bool, string, string) { + // Just in case :) + if i == j { + return true, "", "" + } + + // We can't do much here, templates can't really be compared. However, + // we can execute the templates and compare their outputs to be reasonably + // sure that they're the same. + + // This is exceedingly ugly. + ctx := middleware.Context{ + Root: http.Dir("./testdata"), + } + + md := markdown.Data{ + Context: ctx, + Doc: make(map[string]string), + DocFlags: make(map[string]bool), + Styles: []string{"style1"}, + Scripts: []string{"js1"}, + } + md.Doc["title"] = "some title" + md.Doc["body"] = "some body" + + bufi := new(bytes.Buffer) + bufj := new(bytes.Buffer) + + if err := i.Execute(bufi, md); err != nil { + return false, fmt.Sprintf("%v", err), "" + } + if err := j.Execute(bufj, md); err != nil { + return false, "", fmt.Sprintf("%v", err) + } + + return bytes.Equal(bufi.Bytes(), bufj.Bytes()), string(bufi.Bytes()), string(bufj.Bytes()) } diff --git a/middleware/markdown/markdown.go b/middleware/markdown/markdown.go index 5e4a2cb5..5c2ac5fc 100644 --- a/middleware/markdown/markdown.go +++ b/middleware/markdown/markdown.go @@ -4,10 +4,10 @@ package markdown import ( "io/ioutil" - "log" "net/http" "os" "path" + "text/template" "github.com/mholt/caddy/middleware" "github.com/russross/blackfriday" @@ -59,8 +59,8 @@ type Config struct { // List of JavaScript files to load for each markdown file Scripts []string - // Map of registered templates - Templates map[string]string + // Template(s) to render with + Template *template.Template } // ServeHTTP implements the http.Handler interface. diff --git a/middleware/markdown/markdown_test.go b/middleware/markdown/markdown_test.go index fbfb7379..b38c34f6 100644 --- a/middleware/markdown/markdown_test.go +++ b/middleware/markdown/markdown_test.go @@ -5,6 +5,7 @@ import ( "net/http" "net/http/httptest" "os" + "path/filepath" "strings" "testing" "time" @@ -14,11 +15,15 @@ import ( ) func TestMarkdown(t *testing.T) { - templates := make(map[string]string) - templates[DefaultTemplate] = "testdata/markdown_tpl.html" + rootDir := "./testdata" + + f := func(filename string) string { + return filepath.ToSlash(rootDir + string(filepath.Separator) + filename) + } + md := Markdown{ - Root: "./testdata", - FileSys: http.Dir("./testdata"), + Root: rootDir, + FileSys: http.Dir(rootDir), Configs: []*Config{ { Renderer: blackfriday.HtmlRenderer(0, "", ""), @@ -26,9 +31,9 @@ func TestMarkdown(t *testing.T) { Extensions: map[string]struct{}{ ".md": struct{}{}, }, - Styles: []string{}, - Scripts: []string{}, - Templates: templates, + Styles: []string{}, + Scripts: []string{}, + Template: setDefaultTemplate(f("markdown_tpl.html")), }, { Renderer: blackfriday.HtmlRenderer(0, "", ""), @@ -36,11 +41,9 @@ func TestMarkdown(t *testing.T) { Extensions: map[string]struct{}{ ".md": struct{}{}, }, - Styles: []string{}, - Scripts: []string{}, - Templates: map[string]string{ - DefaultTemplate: "testdata/docflags/template.txt", - }, + Styles: []string{}, + Scripts: []string{}, + Template: setDefaultTemplate(f("docflags/template.txt")), }, { Renderer: blackfriday.HtmlRenderer(0, "", ""), @@ -48,9 +51,9 @@ func TestMarkdown(t *testing.T) { Extensions: map[string]struct{}{ ".md": struct{}{}, }, - Styles: []string{"/resources/css/log.css", "/resources/css/default.css"}, - Scripts: []string{"/resources/js/log.js", "/resources/js/default.js"}, - Templates: make(map[string]string), + Styles: []string{"/resources/css/log.css", "/resources/css/default.css"}, + Scripts: []string{"/resources/js/log.js", "/resources/js/default.js"}, + Template: GetDefaultTemplate(), }, { Renderer: blackfriday.HtmlRenderer(0, "", ""), @@ -58,9 +61,9 @@ func TestMarkdown(t *testing.T) { Extensions: map[string]struct{}{ ".md": struct{}{}, }, - Styles: []string{}, - Scripts: []string{}, - Templates: templates, + Styles: []string{}, + Scripts: []string{}, + Template: setDefaultTemplate(f("markdown_tpl.html")), }, }, IndexFiles: []string{"index.html"}, @@ -145,12 +148,10 @@ DocFlags.var_bool true` Markdown test 2 - - + - - - + +

Welcome on the blog

diff --git a/middleware/markdown/process.go b/middleware/markdown/process.go index e9768627..e661e697 100644 --- a/middleware/markdown/process.go +++ b/middleware/markdown/process.go @@ -2,19 +2,12 @@ package markdown import ( "bytes" - "io/ioutil" "path/filepath" - "text/template" "github.com/mholt/caddy/middleware" "github.com/russross/blackfriday" ) -const ( - // DefaultTemplate is the default template. - DefaultTemplate = "defaultTemplate" -) - // Data represents a markdown document. type Data struct { middleware.Context @@ -52,24 +45,6 @@ func (md Markdown) Process(c *Config, requestPath string, b []byte, ctx middlewa metadata = parser.Metadata() } - // if template is not specified, check if Default template is set - if metadata.Template == "" { - if _, ok := c.Templates[DefaultTemplate]; ok { - metadata.Template = DefaultTemplate - } - } - - // if template is set, load it - var tmpl []byte - if metadata.Template != "" { - if t, ok := c.Templates[metadata.Template]; ok { - tmpl, err = ioutil.ReadFile(t) - } - if err != nil { - return nil, err - } - } - // process markdown extns := 0 extns |= blackfriday.EXTENSION_TABLES @@ -88,27 +63,12 @@ func (md Markdown) Process(c *Config, requestPath string, b []byte, ctx middlewa } metadata.Variables["title"] = title - return md.processTemplate(c, requestPath, tmpl, metadata, ctx) + // return md.processTemplate(c, requestPath, metadata, ctx) + return md.doTemplate(c, requestPath, metadata, ctx) } -// processTemplate processes a template given a requestPath, -// template (tmpl) and metadata -func (md Markdown) processTemplate(c *Config, requestPath string, tmpl []byte, metadata Metadata, ctx middleware.Context) ([]byte, error) { - var t *template.Template - var err error - - // if template is not specified, - // use the default template - if tmpl == nil { - t = template.Must(template.New("").Parse(htmlTemplate)) - } else { - t, err = template.New("").Parse(string(tmpl)) - if err != nil { - return nil, err - } - } - - // process the template +// doTemplate executes a template given a requestPath, template, and metadata +func (md Markdown) doTemplate(c *Config, reqPath string, metadata Metadata, ctx middleware.Context) ([]byte, error) { mdData := Data{ Context: ctx, Doc: metadata.Variables, @@ -118,27 +78,9 @@ func (md Markdown) processTemplate(c *Config, requestPath string, tmpl []byte, m } b := new(bytes.Buffer) - err = t.Execute(b, mdData) - if err != nil { + if err := c.Template.ExecuteTemplate(b, metadata.Template, mdData); err != nil { return nil, err } return b.Bytes(), nil } - -const ( - htmlTemplate = ` - - - {{.Doc.title}} - - {{range .Styles}} - {{end -}} - {{range .Scripts}} - {{end -}} - - - {{.Doc.body}} - -` -) diff --git a/middleware/markdown/template.go b/middleware/markdown/template.go new file mode 100644 index 00000000..b1118287 --- /dev/null +++ b/middleware/markdown/template.go @@ -0,0 +1,55 @@ +package markdown + +import ( + "io/ioutil" + "text/template" +) + +func setDefaultTemplate(filename string) *template.Template { + buf, err := ioutil.ReadFile(filename) + if err != nil { + return nil + } + + return template.Must(GetDefaultTemplate().Parse(string(buf))) +} + +func SetTemplate(t *template.Template, name, filename string) error { + + // Read template + buf, err := ioutil.ReadFile(filename) + if err != nil { + return err + } + + // Update if exists + if tt := t.Lookup(name); tt != nil { + _, err = tt.Parse(string(buf)) + return err + } + + // Allocate new name if not + _, err = t.New(name).Parse(string(buf)) + return err +} + +func GetDefaultTemplate() *template.Template { + return template.Must(template.New("").Parse(defaultTemplate)) +} + +const ( + defaultTemplate = ` + + + {{.Doc.title}} + + {{range .Styles}} + {{end -}} + {{range .Scripts}} + {{end -}} + + + {{.Doc.body}} + +` +)