diff --git a/hugolib/benchmark_test.go b/hugolib/benchmark_test.go index 62e4c3f99..31e58a14a 100644 --- a/hugolib/benchmark_test.go +++ b/hugolib/benchmark_test.go @@ -1,8 +1,8 @@ package hugolib import ( - "os" "bytes" + "os" "testing" ) @@ -12,7 +12,7 @@ func BenchmarkParsePage(b *testing.B) { sample.ReadFrom(f) b.ResetTimer() for i := 0; i < b.N; i++ { - ReadFrom(sample, "bench") + ReadFrom(sample, "bench") } } diff --git a/hugolib/page.go b/hugolib/page.go index 11ca82ddb..450f32a1f 100644 --- a/hugolib/page.go +++ b/hugolib/page.go @@ -303,25 +303,28 @@ func (page *Page) GetParam(key string) interface{} { return nil } -// TODO return error on last line instead of nil +var ErrDetectingFrontMatter = errors.New("unable to detect front matter") +var ErrMatchingStartingFrontMatterDelimiter = errors.New("unable to match beginning front matter delimiter") +var ErrMatchingEndingFrontMatterDelimiter = errors.New("unable to match ending front matter delimiter") + func (page *Page) parseFrontMatter(data *bufio.Reader) (err error) { if err = checkEmpty(data); err != nil { - return err + return } var mark rune if mark, err = chompWhitespace(data); err != nil { - return err + return } f := page.detectFrontMatter(mark) if f == nil { - return errors.New("unable to match beginning front matter delimiter") + return ErrDetectingFrontMatter } if found, err := beginFrontMatter(data, f); err != nil || !found { - return errors.New("unable to match beginning front matter delimiter") + return ErrMatchingStartingFrontMatterDelimiter } var frontmatter = new(bytes.Buffer) @@ -329,24 +332,29 @@ func (page *Page) parseFrontMatter(data *bufio.Reader) (err error) { line, _, err := data.ReadLine() if err != nil { if err == io.EOF { - return errors.New("unable to match ending front matter delimiter") + return ErrMatchingEndingFrontMatterDelimiter } return err } + if bytes.Equal(line, f.markend) { + if f.includeMark { + frontmatter.Write(line) + } break } + frontmatter.Write(line) frontmatter.Write([]byte{'\n'}) } metadata, err := f.parse(frontmatter.Bytes()) if err != nil { - return err + return } if err = page.update(metadata); err != nil { - return err + return } return @@ -365,24 +373,31 @@ func checkEmpty(data *bufio.Reader) (err error) { type frontmatterType struct { markstart, markend []byte parse func([]byte) (interface{}, error) + includeMark bool } func (page *Page) detectFrontMatter(mark rune) (f *frontmatterType) { switch mark { case '-': - return &frontmatterType{[]byte{'-', '-', '-'}, []byte{'-', '-', '-'}, page.handleYamlMetaData} + return &frontmatterType{[]byte{'-', '-', '-'}, []byte{'-', '-', '-'}, page.handleYamlMetaData, false} case '+': - return &frontmatterType{[]byte{'+', '+', '+'}, []byte{'+', '+', '+'}, page.handleTomlMetaData} + return &frontmatterType{[]byte{'+', '+', '+'}, []byte{'+', '+', '+'}, page.handleTomlMetaData, false} case '{': - return &frontmatterType{[]byte{'{'}, []byte{'}'}, page.handleJsonMetaData} + return &frontmatterType{[]byte{'{'}, []byte{'}'}, page.handleJsonMetaData, true} default: return nil } } func beginFrontMatter(data *bufio.Reader, f *frontmatterType) (bool, error) { - peek := make([]byte, 3) - _, err := data.Read(peek) + var err error + var peek []byte + if f.includeMark { + peek, err = data.Peek(len(f.markstart)) + } else { + peek = make([]byte, len(f.markstart)) + _, err = data.Read(peek) + } if err != nil { return false, err } diff --git a/hugolib/page_test.go b/hugolib/page_test.go index a31688cc9..363ee1941 100644 --- a/hugolib/page_test.go +++ b/hugolib/page_test.go @@ -39,6 +39,36 @@ title: Leading WS Leading ` +var SIMPLE_PAGE_JSON = ` +{ +"title": "spf13-vim 3.0 release and new website", +"description": "spf13-vim is a cross platform distribution of vim plugins and resources for Vim.", +"tags": [ ".vimrc", "plugins", "spf13-vim", "vim" ], +"date": "2012-04-06", +"categories": [ + "Development", + "VIM" +], +"slug": "spf13-vim-3-0-release-and-new-website" +} + +Content of the file goes Here +` + +var SIMPLE_PAGE_JSON_MULTIPLE = ` +{ + "title": "foobar", + "customData": { "foo": "bar" }, + "date": "2012-08-06" +} +Some text +` + +var SIMPLE_PAGE_JSON_COMPACT = ` +{"title":"foobar","customData":{"foo":"bar"},"date":"2012-08-06"} +Text +` + func checkError(t *testing.T, err error, expected string) { if err == nil { t.Fatalf("err is nil") @@ -101,6 +131,23 @@ func TestCreateNewPage(t *testing.T) { checkPageLayout(t, p, "page/single.html") } +func TestCreatePage(t *testing.T) { + var tests = []struct { + r io.Reader + }{ + {strings.NewReader(SIMPLE_PAGE_JSON)}, + {strings.NewReader(SIMPLE_PAGE_JSON_MULTIPLE)}, + //{strings.NewReader(SIMPLE_PAGE_JSON_COMPACT)}, + } + + for _, test := range tests { + _, err := ReadFrom(test.r, "page") + if err != nil { + t.Errorf("Unable to parse page: %s", err) + } + } +} + func TestDegenerateInvalidFrontMatterShortDelim(t *testing.T) { var tests = []struct { r io.Reader @@ -108,7 +155,7 @@ func TestDegenerateInvalidFrontMatterShortDelim(t *testing.T) { }{ {strings.NewReader(INVALID_FRONT_MATTER_SHORT_DELIM), "unable to match beginning front matter delimiter"}, {strings.NewReader(INVALID_FRONT_MATTER_SHORT_DELIM_ENDING), "unable to match ending front matter delimiter"}, - {strings.NewReader(INVALID_FRONT_MATTER_MISSING), "unable to match beginning front matter delimiter"}, + {strings.NewReader(INVALID_FRONT_MATTER_MISSING), "unable to detect front matter"}, } for _, test := range tests { _, err := ReadFrom(test.r, "invalid/front/matter/short/delim")