From 90c24d2f32bad972682d18d668e300cfba31ec97 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Mon, 7 Mar 2016 15:32:07 -0700 Subject: [PATCH] Included files in Markdown templates have access to document vars (fixes #660) Refactor how middleware.Context includes files --- middleware/context.go | 60 ++++++++++++++---------- middleware/markdown/markdown_test.go | 4 +- middleware/markdown/process.go | 6 +++ middleware/markdown/testdata/header.html | 2 +- 4 files changed, 43 insertions(+), 29 deletions(-) diff --git a/middleware/context.go b/middleware/context.go index 7cea124e..272bee4a 100644 --- a/middleware/context.go +++ b/middleware/context.go @@ -20,35 +20,12 @@ import ( type Context struct { Root http.FileSystem Req *http.Request - // This is used to access information about the URL. - URL *url.URL + URL *url.URL } -// Include returns the contents of filename relative to the site root +// Include returns the contents of filename relative to the site root. func (c Context) Include(filename string) (string, error) { - file, err := c.Root.Open(filename) - if err != nil { - return "", err - } - defer file.Close() - - body, err := ioutil.ReadAll(file) - if err != nil { - return "", err - } - - tpl, err := template.New(filename).Parse(string(body)) - if err != nil { - return "", err - } - - var buf bytes.Buffer - err = tpl.Execute(&buf, c) - if err != nil { - return "", err - } - - return buf.String(), nil + return ContextInclude(filename, c, c.Root) } // Now returns the current timestamp in the specified format. @@ -212,3 +189,34 @@ func (c Context) Markdown(filename string) (string, error) { return string(markdown), nil } + +// ContextInclude opens filename using fs and executes a template with the context ctx. +// This does the same thing that Context.Include() does, but with the ability to provide +// your own context so that the included files can have access to additional fields your +// type may provide. You can embed Context in your type, then override its Include method +// to call this function with ctx being the instance of your type, and fs being Context.Root. +func ContextInclude(filename string, ctx interface{}, fs http.FileSystem) (string, error) { + file, err := fs.Open(filename) + if err != nil { + return "", err + } + defer file.Close() + + body, err := ioutil.ReadAll(file) + if err != nil { + return "", err + } + + tpl, err := template.New(filename).Parse(string(body)) + if err != nil { + return "", err + } + + var buf bytes.Buffer + err = tpl.Execute(&buf, ctx) + if err != nil { + return "", err + } + + return buf.String(), nil +} diff --git a/middleware/markdown/markdown_test.go b/middleware/markdown/markdown_test.go index bcc041c4..e8796d11 100644 --- a/middleware/markdown/markdown_test.go +++ b/middleware/markdown/markdown_test.go @@ -107,7 +107,7 @@ func TestMarkdown(t *testing.T) { Markdown test 1 -

Header

+

Header for: Markdown test 1

Welcome to A Caddy website!

Welcome on the blog

@@ -208,7 +208,7 @@ DocFlags.var_bool true` first_post -

Header

+

Header for: first_post

Welcome to title!

Test h1

diff --git a/middleware/markdown/process.go b/middleware/markdown/process.go index a0d1ae68..94887d0e 100644 --- a/middleware/markdown/process.go +++ b/middleware/markdown/process.go @@ -28,6 +28,12 @@ type Data struct { Links []PageLink } +// Include "overrides" the embedded middleware.Context's Include() +// method so that included files have access to d's fields. +func (d Data) Include(filename string) (string, error) { + return middleware.ContextInclude(filename, d, d.Root) +} + // Process processes the contents of a page in b. It parses the metadata // (if any) and uses the template (if found). func (md Markdown) Process(c *Config, requestPath string, b []byte, ctx middleware.Context) ([]byte, error) { diff --git a/middleware/markdown/testdata/header.html b/middleware/markdown/testdata/header.html index 78e5a6a4..cfbdc75b 100644 --- a/middleware/markdown/testdata/header.html +++ b/middleware/markdown/testdata/header.html @@ -1 +1 @@ -

Header

+

Header for: {{.Doc.title}}

\ No newline at end of file