ref: cbd9506c296dba99c59fef310a16b21be12b7b63
parent: 58f8b43feed9a487e63b61352226d934743ebafe
author: spf13 <[email protected]>
date: Thu May 1 09:19:51 EDT 2014
moving front matter parsing (and creation) to parse package
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -24,7 +24,6 @@
"strings"
"time"
- "github.com/BurntSushi/toml"
"github.com/spf13/cast"
"github.com/spf13/hugo/helpers"
"github.com/spf13/hugo/parser"
@@ -31,28 +30,29 @@
jww "github.com/spf13/jwalterweatherman"
"github.com/spf13/viper"
"github.com/theplant/blackfriday"
- "launchpad.net/goyaml"
- json "launchpad.net/rjson"
)
type Page struct {
- Status string
- Images []string
- rawContent []byte
- Content template.HTML
- Summary template.HTML
- TableOfContents template.HTML
- Truncated bool
- plain string // TODO should be []byte
- Params map[string]interface{}
- contentType string
- Draft bool
- Aliases []string
- Tmpl Template
- Markup string
- renderable bool
- layout string
- linkTitle string
+ Status string
+ Images []string
+ rawContent []byte
+ Content template.HTML
+ Summary template.HTML
+ TableOfContents template.HTML
+ Truncated bool
+ plain string // TODO should be []byte
+ Params map[string]interface{}
+ contentType string
+ Draft bool
+ Aliases []string
+ Tmpl Template
+ Markup string
+ renderable bool
+ layout string
+ linkTitle string
+ frontmatter []byte
+ sourceFrontmatter []byte
+ sourceContent []byte
PageMeta
File
Position
@@ -293,35 +293,6 @@
return link.String(), nil
}
-func (page *Page) handleTomlMetaData(datum []byte) (interface{}, error) {
- m := map[string]interface{}{}
- datum = removeTomlIdentifier(datum)
- if _, err := toml.Decode(string(datum), &m); err != nil {
- return m, fmt.Errorf("Invalid TOML in %s \nError parsing page meta data: %s", page.FileName, err)
- }
- return m, nil
-}
-
-func removeTomlIdentifier(datum []byte) []byte {
- return bytes.Replace(datum, []byte("+++"), []byte(""), -1)
-}
-
-func (page *Page) handleYamlMetaData(datum []byte) (interface{}, error) {
- m := map[string]interface{}{}
- if err := goyaml.Unmarshal(datum, &m); err != nil {
- return m, fmt.Errorf("Invalid YAML in %s \nError parsing page meta data: %s", page.FileName, err)
- }
- return m, nil
-}
-
-func (page *Page) handleJsonMetaData(datum []byte) (interface{}, error) {
- var f interface{}
- if err := json.Unmarshal(datum, &f); err != nil {
- return f, fmt.Errorf("Invalid JSON in %v \nError parsing page meta data: %s", page.FileName, err)
- }
- return f, nil
-}
-
func (page *Page) update(f interface{}) error {
m := f.(map[string]interface{})
@@ -499,28 +470,6 @@
return nil
}
-type frontmatterType struct {
- markstart, markend []byte
- parse func([]byte) (interface{}, error)
- includeMark bool
-}
-
-const YAML_DELIM = "---"
-const TOML_DELIM = "+++"
-
-func (page *Page) detectFrontMatter(mark rune) (f *frontmatterType) {
- switch mark {
- case '-':
- return &frontmatterType{[]byte(YAML_DELIM), []byte(YAML_DELIM), page.handleYamlMetaData, false}
- case '+':
- return &frontmatterType{[]byte(TOML_DELIM), []byte(TOML_DELIM), page.handleTomlMetaData, false}
- case '{':
- return &frontmatterType{[]byte{'{'}, []byte{'}'}, page.handleJsonMetaData, true}
- default:
- return nil
- }
-}
-
func (p *Page) Render(layout ...string) template.HTML {
curLayout := ""
@@ -573,30 +522,45 @@
return "unknown"
}
+func (page *Page) detectFrontMatter() (f *parser.FrontmatterType) {
+ return parser.DetectFrontMatter(rune(page.frontmatter[0]))
+}
+
func (page *Page) parse(reader io.Reader) error {
- p, err := parser.ReadFrom(reader)
+ psr, err := parser.ReadFrom(reader)
if err != nil {
return err
}
- page.renderable = p.IsRenderable()
+ page.renderable = psr.IsRenderable()
+ page.frontmatter = psr.FrontMatter()
+ meta, err := psr.Metadata()
+ if err != nil {
+ jww.ERROR.Printf("Error parsing page meta data for %s", page.FileName)
+ jww.ERROR.Println(err)
+ return err
+ }
+ if err = page.update(meta); err != nil {
+ return err
+ }
- front := p.FrontMatter()
+ page.rawContent = psr.Content()
+ page.setSummary()
- if len(front) != 0 {
- fm := page.detectFrontMatter(rune(front[0]))
- meta, err := fm.parse(front)
- if err != nil {
- return err
- }
+ return nil
+}
- if err = page.update(meta); err != nil {
- return err
- }
+func (page *Page) SetSourceContent(content []byte) {
+ page.sourceContent = content
+}
+func (page *Page) SetSourceMetaData(in interface{}, mark rune) (err error) {
+ by, err := parser.InterfaceToFrontMatter(in, mark)
+ if err != nil {
+ return err
}
- page.rawContent = p.Content()
- page.setSummary()
+
+ page.sourceFrontmatter = by
return nil
}
--- /dev/null
+++ b/parser/frontmatter.go
@@ -1,0 +1,129 @@
+// Copyright © 2013 Steve Francia <[email protected]>.
+//
+// Licensed under the Simple Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://opensource.org/licenses/Simple-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package parser
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+
+ "github.com/BurntSushi/toml"
+ "launchpad.net/goyaml"
+)
+
+type FrontmatterType struct {
+ markstart, markend []byte
+ Parse func([]byte) (interface{}, error)
+ includeMark bool
+}
+
+func InterfaceToFrontMatter(in interface{}, mark rune) ([]byte, error) {
+ if in == nil {
+ return []byte{}, fmt.Errorf("input was nil")
+ }
+
+ b := new(bytes.Buffer)
+
+ switch mark {
+ case rune(YAML_LEAD[0]):
+ _, err := b.Write([]byte(YAML_DELIM_UNIX))
+ if err != nil {
+ return nil, err
+ }
+ by, err := goyaml.Marshal(in)
+ if err != nil {
+ return nil, err
+ }
+ b.Write(by)
+ _, err = b.Write([]byte(YAML_DELIM_UNIX))
+ if err != nil {
+ return nil, err
+ }
+ return b.Bytes(), nil
+ case rune(TOML_LEAD[0]):
+ _, err := b.Write([]byte(TOML_DELIM_UNIX))
+ if err != nil {
+ return nil, err
+ }
+
+ err = toml.NewEncoder(b).Encode(in)
+ if err != nil {
+ fmt.Println("toml encoder failed", in)
+ fmt.Println(err)
+ return nil, err
+ }
+ _, err = b.Write([]byte("\n" + TOML_DELIM_UNIX))
+ if err != nil {
+ return nil, err
+ }
+ return b.Bytes(), nil
+ case rune(JSON_LEAD[0]):
+ by, err := json.MarshalIndent(in, "", " ")
+ if err != nil {
+ fmt.Println("json encoder failed", in)
+ fmt.Println(err)
+ return nil, err
+ }
+ b.Write(by)
+ _, err = b.Write([]byte("\n"))
+ if err != nil {
+ return nil, err
+ }
+ return b.Bytes(), nil
+ default:
+ return nil, fmt.Errorf("Unsupported Format provided")
+ }
+}
+
+func DetectFrontMatter(mark rune) (f *FrontmatterType) {
+ switch mark {
+ case '-':
+ return &FrontmatterType{[]byte(YAML_DELIM), []byte(YAML_DELIM), HandleYamlMetaData, false}
+ case '+':
+ return &FrontmatterType{[]byte(TOML_DELIM), []byte(TOML_DELIM), HandleTomlMetaData, false}
+ case '{':
+ return &FrontmatterType{[]byte{'{'}, []byte{'}'}, HandleJsonMetaData, true}
+ default:
+ return nil
+ }
+}
+
+func HandleTomlMetaData(datum []byte) (interface{}, error) {
+ m := map[string]interface{}{}
+ datum = removeTomlIdentifier(datum)
+ if _, err := toml.Decode(string(datum), &m); err != nil {
+ return m, err
+ }
+ return m, nil
+}
+
+func removeTomlIdentifier(datum []byte) []byte {
+ return bytes.Replace(datum, []byte(TOML_DELIM), []byte(""), -1)
+}
+
+func HandleYamlMetaData(datum []byte) (interface{}, error) {
+ m := map[string]interface{}{}
+ if err := goyaml.Unmarshal(datum, &m); err != nil {
+ return m, err
+ }
+ return m, nil
+}
+
+func HandleJsonMetaData(datum []byte) (interface{}, error) {
+ var f interface{}
+ if err := json.Unmarshal(datum, &f); err != nil {
+ return f, err
+ }
+ return f, nil
+}
--- a/parser/page.go
+++ b/parser/page.go
@@ -13,9 +13,11 @@
YAML_LEAD = "-"
YAML_DELIM_UNIX = "---\n"
YAML_DELIM_DOS = "---\r\n"
+ YAML_DELIM = "---"
TOML_LEAD = "+"
TOML_DELIM_UNIX = "+++\n"
TOML_DELIM_DOS = "+++\r\n"
+ TOML_DELIM = "+++"
JSON_LEAD = "{"
)
@@ -39,6 +41,7 @@
FrontMatter() FrontMatter
Content() Content
IsRenderable() bool
+ Metadata() (interface{}, error)
}
type page struct {
@@ -57,6 +60,19 @@
func (p *page) IsRenderable() bool {
return p.render
+}
+
+func (p *page) Metadata() (meta interface{}, err error) {
+ frontmatter := p.FrontMatter()
+
+ if len(frontmatter) != 0 {
+ fm := DetectFrontMatter(rune(frontmatter[0]))
+ meta, err = fm.Parse(frontmatter)
+ if err != nil {
+ return
+ }
+ }
+ return
}
// ReadFrom reads the content from an io.Reader and constructs a page.