@marcel91200 / caddy Mirror · read-only / commits / 003403ec
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

templates: Add support for dots to close yaml frontmatter (#3498)

* templates: Add support for dots to close yaml frontmatter * templates: Fix regression in body output

Francis Lavoie committed Jun 15, 2020 at 14:38 UTC 003403ecbccbd3fa53040ee1f0fd5d411a887215
2 files changed +59 -19
modules/caddyhttp/templates/frontmatter.go
+42 -19
@@ -34,25 +34,30 @@ func extractFrontMatter(input string) (map[string]interface{}, string, error) {
34 firstLine = strings.TrimSpace(firstLine)
35
36 // see what kind of front matter there is, if any
37 - var closingFence string
37 + var closingFence []string
38 var fmParser func([]byte) (map[string]interface{}, error)
39 - switch firstLine {
40 - case yamlFrontMatterFenceOpen:
41 - fmParser = yamlFrontMatter
42 - closingFence = yamlFrontMatterFenceClose
43 - case tomlFrontMatterFenceOpen:
44 - fmParser = tomlFrontMatter
45 - closingFence = tomlFrontMatterFenceClose
46 - case jsonFrontMatterFenceOpen:
47 - fmParser = jsonFrontMatter
48 - closingFence = jsonFrontMatterFenceClose
49 - default:
39 + for _, fmType := range supportedFrontMatterTypes {
40 + if firstLine == fmType.FenceOpen {
41 + closingFence = fmType.FenceClose
42 + fmParser = fmType.ParseFunc
43 + }
44 + }
45 +
46 + if fmParser == nil {
47 // no recognized front matter; whole document is body
48 return nil, input, nil
49 }
50
51 // find end of front matter
55 - fmEndFenceStart := strings.Index(input[firstLineEnd:], "\n"+closingFence)
52 + var fmEndFence string
53 + fmEndFenceStart := -1
54 + for _, fence := range closingFence {
55 + index := strings.Index(input[firstLineEnd:], "\n"+fence)
56 + if index >= 0 {
57 + fmEndFenceStart = index
58 + fmEndFence = fence
59 + }
60 + }
61 if fmEndFenceStart < 0 {
62 return nil, "", fmt.Errorf("unterminated front matter")
63 }
@@ -66,7 +71,7 @@ func extractFrontMatter(input string) (map[string]interface{}, string, error) {
71 }
72
73 // the rest is the body
69 - body := input[fmEndFenceStart+len(closingFence):]
74 + body := input[fmEndFenceStart+len(fmEndFence):]
75
76 return fm, body, nil
77 }
@@ -96,8 +101,26 @@ type parsedMarkdownDoc struct {
101 Body string `json:"body,omitempty"`
102 }
103
99 -const (
100 - yamlFrontMatterFenceOpen, yamlFrontMatterFenceClose = "---", "---"
101 - tomlFrontMatterFenceOpen, tomlFrontMatterFenceClose = "+++", "+++"
102 - jsonFrontMatterFenceOpen, jsonFrontMatterFenceClose = "{", "}"
103 -)
104 +type frontMatterType struct {
105 + FenceOpen string
106 + FenceClose []string
107 + ParseFunc func(input []byte) (map[string]interface{}, error)
108 +}
109 +
110 +var supportedFrontMatterTypes = []frontMatterType{
111 + {
112 + FenceOpen: "---",
113 + FenceClose: []string{"---", "..."},
114 + ParseFunc: yamlFrontMatter,
115 + },
116 + {
117 + FenceOpen: "+++",
118 + FenceClose: []string{"+++"},
119 + ParseFunc: tomlFrontMatter,
120 + },
121 + {
122 + FenceOpen: "{",
123 + FenceClose: []string{"}"},
124 + ParseFunc: jsonFrontMatter,
125 + },
126 +}
modules/caddyhttp/templates/tplcontext_test.go
+17
@@ -290,11 +290,13 @@ func TestSplitFrontMatter(t *testing.T) {
290 for i, test := range []struct {
291 input string
292 expect string
293 + body string
294 }{
295 {
296 // yaml with windows newline
297 input: "---\r\ntitle: Welcome\r\n---\r\n# Test\\r\\n",
298 expect: `Welcome`,
299 + body: "\r\n# Test\\r\\n",
300 },
301 {
302 // yaml
@@ -303,6 +305,16 @@ title: Welcome
305 ---
306 ### Test`,
307 expect: `Welcome`,
308 + body: "\n### Test",
309 + },
310 + {
311 + // yaml with dots for closer
312 + input: `---
313 +title: Welcome
314 +...
315 +### Test`,
316 + expect: `Welcome`,
317 + body: "\n### Test",
318 },
319 {
320 // toml
@@ -311,6 +323,7 @@ title = "Welcome"
323 +++
324 ### Test`,
325 expect: `Welcome`,
326 + body: "\n### Test",
327 },
328 {
329 // json
@@ -319,12 +332,16 @@ title = "Welcome"
332 }
333 ### Test`,
334 expect: `Welcome`,
335 + body: "\n### Test",
336 },
337 } {
338 result, _ := context.funcSplitFrontMatter(test.input)
339 if result.Meta["title"] != test.expect {
340 t.Errorf("Test %d: Expected %s, found %s. Input was SplitFrontMatter(%s)", i, test.expect, result.Meta["title"], test.input)
341 }
342 + if result.Body != test.body {
343 + t.Errorf("Test %d: Expected body %s, found %s. Input was SplitFrontMatter(%s)", i, test.body, result.Body, test.input)
344 + }
345 }
346
347 }