// Copyright 2015 Light Code Labs, LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package markdown import ( "bytes" "io/ioutil" "text/template" "github.com/mholt/caddy/caddyhttp/httpserver" "github.com/mholt/caddy/caddyhttp/markdown/metadata" ) // Data represents a markdown document. type Data struct { httpserver.Context Doc map[string]interface{} Styles []string Scripts []string Meta map[string]string Files []FileInfo } // Include "overrides" the embedded httpserver.Context's Include() // method so that included files have access to d's fields. // Note: using {{template 'template-name' .}} instead might be better. func (d Data) Include(filename string, args ...interface{}) (string, error) { d.Args = args return httpserver.ContextInclude(filename, d, d.Root) } // 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) { mdData := Data{ Context: ctx, Doc: mdata.Variables, Styles: c.Styles, Scripts: c.Scripts, Meta: meta, Files: files, } templateName := mdata.Template // reload template on every request for now // TODO: cache templates by a general plugin if templateFile, ok := c.TemplateFiles[templateName]; ok { err := SetTemplate(c.Template, templateName, templateFile) if err != nil { return nil, err } } b := new(bytes.Buffer) if err := c.Template.ExecuteTemplate(b, templateName, mdData); err != nil { return nil, err } return b.Bytes(), nil } // 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 { // 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 } // GetDefaultTemplate returns the default template. func GetDefaultTemplate() *template.Template { return template.Must(template.New("").Parse(defaultTemplate)) } const ( defaultTemplate = `