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:
Francis Lavoie 2020-06-15 14:38:51 -04:00 committed by GitHub
parent 5b48f784ae
commit 003403ecbc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 19 deletions

View file

@ -34,25 +34,30 @@ func extractFrontMatter(input string) (map[string]interface{}, string, error) {
firstLine = strings.TrimSpace(firstLine)
// see what kind of front matter there is, if any
var closingFence string
var closingFence []string
var fmParser func([]byte) (map[string]interface{}, error)
switch firstLine {
case yamlFrontMatterFenceOpen:
fmParser = yamlFrontMatter
closingFence = yamlFrontMatterFenceClose
case tomlFrontMatterFenceOpen:
fmParser = tomlFrontMatter
closingFence = tomlFrontMatterFenceClose
case jsonFrontMatterFenceOpen:
fmParser = jsonFrontMatter
closingFence = jsonFrontMatterFenceClose
default:
for _, fmType := range supportedFrontMatterTypes {
if firstLine == fmType.FenceOpen {
closingFence = fmType.FenceClose
fmParser = fmType.ParseFunc
}
}
if fmParser == nil {
// no recognized front matter; whole document is body
return nil, input, nil
}
// 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 {
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
body := input[fmEndFenceStart+len(closingFence):]
body := input[fmEndFenceStart+len(fmEndFence):]
return fm, body, nil
}
@ -96,8 +101,26 @@ type parsedMarkdownDoc struct {
Body string `json:"body,omitempty"`
}
const (
yamlFrontMatterFenceOpen, yamlFrontMatterFenceClose = "---", "---"
tomlFrontMatterFenceOpen, tomlFrontMatterFenceClose = "+++", "+++"
jsonFrontMatterFenceOpen, jsonFrontMatterFenceClose = "{", "}"
)
type frontMatterType struct {
FenceOpen string
FenceClose []string
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,
},
}

View file

@ -290,11 +290,13 @@ func TestSplitFrontMatter(t *testing.T) {
for i, test := range []struct {
input string
expect string
body string
}{
{
// yaml with windows newline
input: "---\r\ntitle: Welcome\r\n---\r\n# Test\\r\\n",
expect: `Welcome`,
body: "\r\n# Test\\r\\n",
},
{
// yaml
@ -303,6 +305,16 @@ title: Welcome
---
### Test`,
expect: `Welcome`,
body: "\n### Test",
},
{
// yaml with dots for closer
input: `---
title: Welcome
...
### Test`,
expect: `Welcome`,
body: "\n### Test",
},
{
// toml
@ -311,6 +323,7 @@ title = "Welcome"
+++
### Test`,
expect: `Welcome`,
body: "\n### Test",
},
{
// json
@ -319,12 +332,16 @@ title = "Welcome"
}
### Test`,
expect: `Welcome`,
body: "\n### Test",
},
} {
result, _ := context.funcSplitFrontMatter(test.input)
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)
}
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)
}
}
}