From e5ef285e5919220216bc72daa3269e171cd499ad Mon Sep 17 00:00:00 2001
From: Peer Beckmann <pbeckmann@users.noreply.github.com>
Date: Mon, 23 Jan 2017 03:16:38 +0100
Subject: [PATCH] Generate meta elements from prelude items description and
 keywords (#1335)

* Generate meta elements from useful front matters.
Limited to the default template and specific elements.

* Rerun gofmt

* Add "keywords" and remove "language" to/from the list of meta tags.

* Add a simple positive list test for the meta tag generation.

* Move the meta tag list to a var at the begin of the file.
Seperate the Meta tags from the other front matters:
	- Don't override user settings with name `meta`
	- Cleaner Code.

* Remove the uneccessary `[:]` in the []Bytes to String casting.
@mholt was right ;)

* One minor refinement. Combining two statements.
---
 caddyhttp/markdown/process.go      | 17 +++++++++++-
 caddyhttp/markdown/process_test.go | 42 ++++++++++++++++++++++++++++++
 caddyhttp/markdown/template.go     |  7 ++++-
 3 files changed, 64 insertions(+), 2 deletions(-)
 create mode 100644 caddyhttp/markdown/process_test.go

diff --git a/caddyhttp/markdown/process.go b/caddyhttp/markdown/process.go
index df2f5f776..7d4f85ebc 100644
--- a/caddyhttp/markdown/process.go
+++ b/caddyhttp/markdown/process.go
@@ -17,6 +17,13 @@ type FileInfo struct {
 	ctx httpserver.Context
 }
 
+var recognizedMetaTags = []string{
+	"author",
+	"copyright",
+	"description",
+	"subject",
+}
+
 // Summarize returns an abbreviated string representation of the markdown stored in this file.
 // wordcount is the number of words returned in the summary.
 func (f FileInfo) Summarize(wordcount int) (string, error) {
@@ -63,6 +70,14 @@ func (c *Config) Markdown(title string, r io.Reader, dirents []os.FileInfo, ctx
 		mdata.Variables["title"] = title
 	}
 
+	// move available and valid front matters to the meta values
+	meta := make(map[string]string)
+	for _, val := range recognizedMetaTags {
+		if mVal, ok := mdata.Variables[val]; ok {
+			meta[val] = mVal.(string)
+		}
+	}
+
 	// massage possible files
 	files := []FileInfo{}
 	for _, ent := range dirents {
@@ -73,5 +88,5 @@ func (c *Config) Markdown(title string, r io.Reader, dirents []os.FileInfo, ctx
 		files = append(files, file)
 	}
 
-	return execTemplate(c, mdata, files, ctx)
+	return execTemplate(c, mdata, meta, files, ctx)
 }
diff --git a/caddyhttp/markdown/process_test.go b/caddyhttp/markdown/process_test.go
new file mode 100644
index 000000000..bce1613d6
--- /dev/null
+++ b/caddyhttp/markdown/process_test.go
@@ -0,0 +1,42 @@
+package markdown
+
+import (
+	"github.com/mholt/caddy/caddyhttp/httpserver"
+	"os"
+	"strings"
+	"testing"
+)
+
+func TestConfig_Markdown(t *testing.T) {
+	tests := []map[string]string{
+		{"author": "authorVal"},
+		{"copyright": "copyrightVal"},
+		{"description": "descriptionVal"},
+		{"subject": "subjectVal"},
+		{"author": "authorVal", "copyright": "copyrightVal"},
+		{"author": "authorVal", "copyright": "copyrightVal", "description": "descriptionVal"},
+		{"author": "authorVal", "copyright": "copyrightVal", "description": "descriptionVal", "subject": "subjectVal"},
+	}
+
+	for i, meta := range tests {
+		config := &Config{
+			Template: GetDefaultTemplate(),
+		}
+
+		toml := "+++"
+		for key, val := range meta {
+			toml = toml + "\n" + key + "= \"" + val + "\""
+		}
+		toml = toml + "\n+++"
+
+		res, _ := config.Markdown("Test title", strings.NewReader(toml), []os.FileInfo{}, httpserver.Context{})
+		sRes := string(res)
+
+		for key, val := range meta {
+			c := strings.Contains(sRes, "<meta name=\""+key+"\" content=\""+val+"\">")
+			if !c {
+				t.Error("Test case", i, "should contain meta", key, val)
+			}
+		}
+	}
+}
diff --git a/caddyhttp/markdown/template.go b/caddyhttp/markdown/template.go
index 5427dd1ce..524c9fe94 100644
--- a/caddyhttp/markdown/template.go
+++ b/caddyhttp/markdown/template.go
@@ -15,6 +15,7 @@ type Data struct {
 	Doc     map[string]interface{}
 	Styles  []string
 	Scripts []string
+	Meta    map[string]string
 	Files   []FileInfo
 }
 
@@ -26,12 +27,13 @@ func (d Data) Include(filename string) (string, error) {
 }
 
 // execTemplate executes a template given a requestPath, template, and metadata
-func execTemplate(c *Config, mdata metadata.Metadata, files []FileInfo, ctx httpserver.Context) ([]byte, error) {
+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,
 	}
 
@@ -74,6 +76,9 @@ const (
 	<head>
 		<title>{{.Doc.title}}</title>
 		<meta charset="utf-8">
+		{{range $key, $val := .Meta}}
+		<meta name="{{$key}}" content="{{$val}}">
+		{{end}}
 		{{- range .Styles}}
 		<link rel="stylesheet" href="{{.}}">
 		{{- end}}