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
}