Merge pull request #196 from evermax/master

markdown, browse: Integrated Context struct for templating
This commit is contained in:
Matt Holt
2015-07-25 15:15:51 -06:00
23 changed files with 457 additions and 49 deletions
+6 -1
View File
@@ -119,7 +119,12 @@ func (md Markdown) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
return http.StatusInternalServerError, err
}
html, err := md.Process(m, fpath, body)
ctx := middleware.Context{
Root: md.FileSys,
Req: r,
URL: r.URL,
}
html, err := md.Process(m, fpath, body, ctx)
if err != nil {
return http.StatusInternalServerError, err
}
+126
View File
@@ -0,0 +1,126 @@
package markdown
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/mholt/caddy/middleware"
"github.com/russross/blackfriday"
)
func TestMarkdown(t *testing.T) {
templates := make(map[string]string)
templates[DefaultTemplate] = "testdata/markdown_tpl.html"
md := Markdown{
Root: "./testdata",
FileSys: http.Dir("./testdata"),
Configs: []Config{
Config{
Renderer: blackfriday.HtmlRenderer(0, "", ""),
PathScope: "/blog",
Extensions: []string{".md"},
Styles: []string{},
Scripts: []string{},
Templates: templates,
},
Config{
Renderer: blackfriday.HtmlRenderer(0, "", ""),
PathScope: "/log",
Extensions: []string{".md"},
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),
},
},
IndexFiles: []string{"index.html"},
Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
t.Fatalf("Next shouldn't be called")
return 0, nil
}),
}
req, err := http.NewRequest("GET", "/blog/test.md", nil)
if err != nil {
t.Fatalf("Could not create HTTP request: %v", err)
}
rec := httptest.NewRecorder()
md.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("Wrong status, expected: %d and got %d", http.StatusOK, rec.Code)
}
respBody := rec.Body.String()
expectedBody := `<!DOCTYPE html>
<html>
<head>
<title>Markdown test</title>
</head>
<body>
<h1>Header</h1>
Welcome to A Caddy website!
<h2>Welcome on the blog</h2>
<p>Body</p>
<p><code>go
func getTrue() bool {
return true
}
</code></p>
</body>
</html>
`
if respBody != expectedBody {
t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
}
req, err = http.NewRequest("GET", "/log/test.md", nil)
if err != nil {
t.Fatalf("Could not create HTTP request: %v", err)
}
rec = httptest.NewRecorder()
md.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("Wrong status, expected: %d and got %d", http.StatusOK, rec.Code)
}
respBody = rec.Body.String()
expectedBody = `<!DOCTYPE html>
<html>
<head>
<title>Markdown test</title>
<meta charset="utf-8">
<link rel="stylesheet" href="/resources/css/log.css">
<link rel="stylesheet" href="/resources/css/default.css">
<script src="/resources/js/log.js"></script>
<script src="/resources/js/default.js"></script>
</head>
<body>
<h2>Welcome on the blog</h2>
<p>Body</p>
<p><code>go
func getTrue() bool {
return true
}
</code></p>
</body>
</html>`
replacer := strings.NewReplacer("\r", "", "\n", "")
respBody = replacer.Replace(respBody)
expectedBody = replacer.Replace(expectedBody)
if respBody != expectedBody {
t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
}
}
+25 -15
View File
@@ -9,6 +9,7 @@ import (
"strings"
"text/template"
"github.com/mholt/caddy/middleware"
"github.com/russross/blackfriday"
)
@@ -17,9 +18,14 @@ const (
DefaultStaticDir = "generated_site"
)
type MarkdownData struct {
middleware.Context
Doc map[string]interface{}
}
// 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) ([]byte, error) {
func (md Markdown) Process(c Config, requestPath string, b []byte, ctx middleware.Context) ([]byte, error) {
var metadata = Metadata{Variables: make(map[string]interface{})}
var markdown []byte
var err error
@@ -61,14 +67,21 @@ func (md Markdown) Process(c Config, requestPath string, b []byte) ([]byte, erro
markdown = blackfriday.Markdown(markdown, c.Renderer, 0)
// set it as body for template
metadata.Variables["markdown"] = string(markdown)
metadata.Variables["body"] = string(markdown)
title := metadata.Title
if title == "" {
title = filepath.Base(requestPath)
var extension = filepath.Ext(requestPath)
title = title[0 : len(title)-len(extension)]
}
metadata.Variables["title"] = title
return md.processTemplate(c, requestPath, tmpl, metadata)
return md.processTemplate(c, requestPath, tmpl, 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) ([]byte, error) {
func (md Markdown) processTemplate(c Config, requestPath string, tmpl []byte, metadata Metadata, ctx middleware.Context) ([]byte, error) {
// if template is not specified,
// use the default template
if tmpl == nil {
@@ -81,7 +94,12 @@ func (md Markdown) processTemplate(c Config, requestPath string, tmpl []byte, me
if err != nil {
return nil, err
}
if err = t.Execute(b, metadata.Variables); err != nil {
mdData := MarkdownData{
Context: ctx,
Doc: metadata.Variables,
}
if err = t.Execute(b, mdData); err != nil {
return nil, err
}
@@ -148,15 +166,7 @@ func defaultTemplate(c Config, metadata Metadata, requestPath string) []byte {
}
// Title is first line (length-limited), otherwise filename
title := metadata.Title
if title == "" {
title = filepath.Base(requestPath)
if body, _ := metadata.Variables["markdown"].([]byte); len(body) > 128 {
title = string(body[:128])
} else if len(body) > 0 {
title = string(body)
}
}
title, _ := metadata.Variables["title"].(string)
html := []byte(htmlTemplate)
html = bytes.Replace(html, []byte("{{title}}"), []byte(title), 1)
@@ -176,7 +186,7 @@ const (
{{js}}
</head>
<body>
{{.markdown}}
{{.Doc.body}}
</body>
</html>`
cssTemplate = `<link rel="stylesheet" href="{{url}}">`
+15
View File
@@ -0,0 +1,15 @@
---
title: Markdown test
variables:
sitename: A Caddy website
---
## Welcome on the blog
Body
``` go
func getTrue() bool {
return true
}
```
+1
View File
@@ -0,0 +1 @@
<h1>Header</h1>
+15
View File
@@ -0,0 +1,15 @@
---
title: Markdown test
variables:
sitename: A Caddy website
---
## Welcome on the blog
Body
``` go
func getTrue() bool {
return true
}
```
+11
View File
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>{{.Doc.title}}</title>
</head>
<body>
{{.Include "header.html"}}
Welcome to {{.Doc.sitename}}!
{{.Doc.body}}
</body>
</html>