mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
Fix more tests, and fix template parsing.
This commit is contained in:
parent
027f697fdf
commit
42b7d57421
6 changed files with 160 additions and 102 deletions
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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`
|
|||
<title>Markdown test 2</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="/resources/css/log.css">
|
||||
<link rel="stylesheet" href="/resources/css/default.css">
|
||||
|
||||
<link rel="stylesheet" href="/resources/css/default.css">
|
||||
<script src="/resources/js/log.js"></script>
|
||||
<script src="/resources/js/default.js"></script>
|
||||
|
||||
</head>
|
||||
<script src="/resources/js/default.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Welcome on the blog</h2>
|
||||
|
||||
|
|
|
@ -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 = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{.Doc.title}}</title>
|
||||
<meta charset="utf-8">
|
||||
{{range .Styles}}<link rel="stylesheet" href="{{.}}">
|
||||
{{end -}}
|
||||
{{range .Scripts}}<script src="{{.}}"></script>
|
||||
{{end -}}
|
||||
</head>
|
||||
<body>
|
||||
{{.Doc.body}}
|
||||
</body>
|
||||
</html>`
|
||||
)
|
||||
|
|
55
middleware/markdown/template.go
Normal file
55
middleware/markdown/template.go
Normal file
|
@ -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 = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{.Doc.title}}</title>
|
||||
<meta charset="utf-8">
|
||||
{{range .Styles}}<link rel="stylesheet" href="{{.}}">
|
||||
{{end -}}
|
||||
{{range .Scripts}}<script src="{{.}}"></script>
|
||||
{{end -}}
|
||||
</head>
|
||||
<body>
|
||||
{{.Doc.body}}
|
||||
</body>
|
||||
</html>`
|
||||
)
|
Loading…
Reference in a new issue