From 003403ecbccbd3fa53040ee1f0fd5d411a887215 Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Mon, 15 Jun 2020 14:38:51 -0400 Subject: 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 --- modules/caddyhttp/templates/frontmatter.go | 61 ++++++++++++++++++-------- modules/caddyhttp/templates/tplcontext_test.go | 17 +++++++ 2 files changed, 59 insertions(+), 19 deletions(-) (limited to 'modules/caddyhttp/templates') diff --git a/modules/caddyhttp/templates/frontmatter.go b/modules/caddyhttp/templates/frontmatter.go index d781c7b..f9d5fb2 100644 --- a/modules/caddyhttp/templates/frontmatter.go +++ b/modules/caddyhttp/templates/frontmatter.go @@ -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, + }, +} diff --git a/modules/caddyhttp/templates/tplcontext_test.go b/modules/caddyhttp/templates/tplcontext_test.go index 4c3da03..f90b851 100644 --- a/modules/caddyhttp/templates/tplcontext_test.go +++ b/modules/caddyhttp/templates/tplcontext_test.go @@ -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) + } } } -- cgit v1.2.3