mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-06 22:40:31 -05:00
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
This commit is contained in:
parent
5b48f784ae
commit
003403ecbc
2 changed files with 59 additions and 19 deletions
|
@ -34,25 +34,30 @@ func extractFrontMatter(input string) (map[string]interface{}, string, error) {
|
||||||
firstLine = strings.TrimSpace(firstLine)
|
firstLine = strings.TrimSpace(firstLine)
|
||||||
|
|
||||||
// see what kind of front matter there is, if any
|
// see what kind of front matter there is, if any
|
||||||
var closingFence string
|
var closingFence []string
|
||||||
var fmParser func([]byte) (map[string]interface{}, error)
|
var fmParser func([]byte) (map[string]interface{}, error)
|
||||||
switch firstLine {
|
for _, fmType := range supportedFrontMatterTypes {
|
||||||
case yamlFrontMatterFenceOpen:
|
if firstLine == fmType.FenceOpen {
|
||||||
fmParser = yamlFrontMatter
|
closingFence = fmType.FenceClose
|
||||||
closingFence = yamlFrontMatterFenceClose
|
fmParser = fmType.ParseFunc
|
||||||
case tomlFrontMatterFenceOpen:
|
}
|
||||||
fmParser = tomlFrontMatter
|
}
|
||||||
closingFence = tomlFrontMatterFenceClose
|
|
||||||
case jsonFrontMatterFenceOpen:
|
if fmParser == nil {
|
||||||
fmParser = jsonFrontMatter
|
|
||||||
closingFence = jsonFrontMatterFenceClose
|
|
||||||
default:
|
|
||||||
// no recognized front matter; whole document is body
|
// no recognized front matter; whole document is body
|
||||||
return nil, input, nil
|
return nil, input, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// find end of front matter
|
// find end of front matter
|
||||||
fmEndFenceStart := strings.Index(input[firstLineEnd:], "\n"+closingFence)
|
var fmEndFence string
|
||||||
|
fmEndFenceStart := -1
|
||||||
|
for _, fence := range closingFence {
|
||||||
|
index := strings.Index(input[firstLineEnd:], "\n"+fence)
|
||||||
|
if index >= 0 {
|
||||||
|
fmEndFenceStart = index
|
||||||
|
fmEndFence = fence
|
||||||
|
}
|
||||||
|
}
|
||||||
if fmEndFenceStart < 0 {
|
if fmEndFenceStart < 0 {
|
||||||
return nil, "", fmt.Errorf("unterminated front matter")
|
return nil, "", fmt.Errorf("unterminated front matter")
|
||||||
}
|
}
|
||||||
|
@ -66,7 +71,7 @@ func extractFrontMatter(input string) (map[string]interface{}, string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// the rest is the body
|
// the rest is the body
|
||||||
body := input[fmEndFenceStart+len(closingFence):]
|
body := input[fmEndFenceStart+len(fmEndFence):]
|
||||||
|
|
||||||
return fm, body, nil
|
return fm, body, nil
|
||||||
}
|
}
|
||||||
|
@ -96,8 +101,26 @@ type parsedMarkdownDoc struct {
|
||||||
Body string `json:"body,omitempty"`
|
Body string `json:"body,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
type frontMatterType struct {
|
||||||
yamlFrontMatterFenceOpen, yamlFrontMatterFenceClose = "---", "---"
|
FenceOpen string
|
||||||
tomlFrontMatterFenceOpen, tomlFrontMatterFenceClose = "+++", "+++"
|
FenceClose []string
|
||||||
jsonFrontMatterFenceOpen, jsonFrontMatterFenceClose = "{", "}"
|
ParseFunc func(input []byte) (map[string]interface{}, error)
|
||||||
)
|
}
|
||||||
|
|
||||||
|
var supportedFrontMatterTypes = []frontMatterType{
|
||||||
|
{
|
||||||
|
FenceOpen: "---",
|
||||||
|
FenceClose: []string{"---", "..."},
|
||||||
|
ParseFunc: yamlFrontMatter,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
FenceOpen: "+++",
|
||||||
|
FenceClose: []string{"+++"},
|
||||||
|
ParseFunc: tomlFrontMatter,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
FenceOpen: "{",
|
||||||
|
FenceClose: []string{"}"},
|
||||||
|
ParseFunc: jsonFrontMatter,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
|
@ -290,11 +290,13 @@ func TestSplitFrontMatter(t *testing.T) {
|
||||||
for i, test := range []struct {
|
for i, test := range []struct {
|
||||||
input string
|
input string
|
||||||
expect string
|
expect string
|
||||||
|
body string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
// yaml with windows newline
|
// yaml with windows newline
|
||||||
input: "---\r\ntitle: Welcome\r\n---\r\n# Test\\r\\n",
|
input: "---\r\ntitle: Welcome\r\n---\r\n# Test\\r\\n",
|
||||||
expect: `Welcome`,
|
expect: `Welcome`,
|
||||||
|
body: "\r\n# Test\\r\\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// yaml
|
// yaml
|
||||||
|
@ -303,6 +305,16 @@ title: Welcome
|
||||||
---
|
---
|
||||||
### Test`,
|
### Test`,
|
||||||
expect: `Welcome`,
|
expect: `Welcome`,
|
||||||
|
body: "\n### Test",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// yaml with dots for closer
|
||||||
|
input: `---
|
||||||
|
title: Welcome
|
||||||
|
...
|
||||||
|
### Test`,
|
||||||
|
expect: `Welcome`,
|
||||||
|
body: "\n### Test",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// toml
|
// toml
|
||||||
|
@ -311,6 +323,7 @@ title = "Welcome"
|
||||||
+++
|
+++
|
||||||
### Test`,
|
### Test`,
|
||||||
expect: `Welcome`,
|
expect: `Welcome`,
|
||||||
|
body: "\n### Test",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// json
|
// json
|
||||||
|
@ -319,12 +332,16 @@ title = "Welcome"
|
||||||
}
|
}
|
||||||
### Test`,
|
### Test`,
|
||||||
expect: `Welcome`,
|
expect: `Welcome`,
|
||||||
|
body: "\n### Test",
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
result, _ := context.funcSplitFrontMatter(test.input)
|
result, _ := context.funcSplitFrontMatter(test.input)
|
||||||
if result.Meta["title"] != test.expect {
|
if result.Meta["title"] != test.expect {
|
||||||
t.Errorf("Test %d: Expected %s, found %s. Input was SplitFrontMatter(%s)", i, test.expect, result.Meta["title"], test.input)
|
t.Errorf("Test %d: Expected %s, found %s. Input was SplitFrontMatter(%s)", i, test.expect, result.Meta["title"], test.input)
|
||||||
}
|
}
|
||||||
|
if result.Body != test.body {
|
||||||
|
t.Errorf("Test %d: Expected body %s, found %s. Input was SplitFrontMatter(%s)", i, test.body, result.Body, test.input)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue