shithub: hugo

Download patch

ref: 4a2f16f91e213b02f008405938fe289c58820e88
parent: 73f203ad86a71136a1d35e0aa1bba574edb91a51
author: spf13 <[email protected]>
date: Thu Nov 20 07:39:09 EST 2014

refactor handlers to use types instead of structs.

--- /dev/null
+++ b/hugolib/handler_base.go
@@ -1,0 +1,61 @@
+// Copyright © 2014 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 hugolib
+
+import (
+	"github.com/spf13/hugo/source"
+	"github.com/spf13/hugo/tpl"
+)
+
+type Handler interface {
+	FileConvert(*source.File, *Site) HandledResult
+	PageConvert(*Page, tpl.Template) HandledResult
+	Read(*source.File, *Site) HandledResult
+	Extensions() []string
+}
+
+type Handle struct {
+	extensions []string
+}
+
+func (h Handle) Extensions() []string {
+	return h.extensions
+}
+
+type HandledResult struct {
+	page *Page
+	file *source.File
+	err  error
+}
+
+// HandledResult is an error
+func (h HandledResult) Error() string {
+	if h.err != nil {
+		if h.page != nil {
+			return "Error:" + h.err.Error() + " for " + h.page.File.LogicalName()
+		}
+		if h.file != nil {
+			return "Error:" + h.err.Error() + " for " + h.file.LogicalName()
+		}
+	}
+	return h.err.Error()
+}
+
+func (h HandledResult) String() string {
+	return h.Error()
+}
+
+func (hr HandledResult) Page() *Page {
+	return hr.page
+}
--- a/hugolib/handler_file.go
+++ b/hugolib/handler_file.go
@@ -17,19 +17,30 @@
 	"github.com/dchest/cssmin"
 	"github.com/spf13/hugo/helpers"
 	"github.com/spf13/hugo/source"
+	"github.com/spf13/hugo/tpl"
 )
 
 func init() {
-	RegisterHandler(css)
+	RegisterHandler(new(cssHandler))
 }
 
-var css = Handle{
-	extensions: []string{"css"},
-	read: func(f *source.File, s *Site, results HandleResults) {
-		results <- HandledResult{file: f}
-	},
-	fileConvert: func(f *source.File, s *Site, results HandleResults) {
-		x := cssmin.Minify(f.Bytes())
-		s.WriteDestFile(f.Path(), helpers.BytesToReader(x))
-	},
+type basicFileHandler Handle
+
+func (h basicFileHandler) Read(f *source.File, s *Site) HandledResult {
+	return HandledResult{file: f}
+}
+
+func (h basicFileHandler) PageConvert(*Page, tpl.Template) HandledResult {
+	return HandledResult{}
+}
+
+type cssHandler struct {
+	basicFileHandler
+}
+
+func (h cssHandler) Extensions() []string { return []string{"css"} }
+func (h cssHandler) FileConvert(f *source.File, s *Site) HandledResult {
+	x := cssmin.Minify(f.Bytes())
+	s.WriteDestFile(f.Path(), helpers.BytesToReader(x))
+	return HandledResult{file: f}
 }
--- /dev/null
+++ b/hugolib/handler_meta.go
@@ -1,0 +1,106 @@
+// Copyright © 2014 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 hugolib
+
+import (
+	"errors"
+
+	"github.com/spf13/hugo/source"
+)
+
+var handlers []Handler
+
+type MetaHandler interface {
+	// Read the Files in and register
+	Read(*source.File, *Site, HandleResults)
+
+	// Generic Convert Function with coordination
+	Convert(interface{}, *Site, HandleResults)
+
+	Handle() Handler
+}
+
+type HandleResults chan<- HandledResult
+
+func NewMetaHandler(in string) *MetaHandle {
+	x := &MetaHandle{ext: in}
+	x.Handler()
+	return x
+}
+
+type MetaHandle struct {
+	handler Handler
+	ext     string
+}
+
+func (mh *MetaHandle) Read(f *source.File, s *Site, results HandleResults) {
+	if h := mh.Handler(); h != nil {
+		results <- h.Read(f, s)
+		return
+	}
+
+	results <- HandledResult{err: errors.New("No handler found"), file: f}
+}
+
+func (mh *MetaHandle) Convert(i interface{}, s *Site, results HandleResults) {
+	h := mh.Handler()
+
+	if f, ok := i.(*source.File); ok {
+		results <- h.FileConvert(f, s)
+		return
+	}
+
+	if p, ok := i.(*Page); ok {
+		if p == nil {
+			results <- HandledResult{err: errors.New("file resulted in a nil page")}
+			return
+		}
+		results <- h.PageConvert(p, s.Tmpl)
+		p.setSummary()
+		p.analyzePage()
+	}
+}
+
+func (mh *MetaHandle) Handler() Handler {
+	if mh.handler == nil {
+		mh.handler = FindHandler(mh.ext)
+	}
+	return mh.handler
+}
+
+func FindHandler(ext string) Handler {
+	for _, h := range Handlers() {
+		if HandlerMatch(h, ext) {
+			return h
+		}
+	}
+	return nil
+}
+
+func HandlerMatch(h Handler, ext string) bool {
+	for _, x := range h.Extensions() {
+		if ext == x {
+			return true
+		}
+	}
+	return false
+}
+
+func RegisterHandler(h Handler) {
+	handlers = append(handlers, h)
+}
+
+func Handlers() []Handler {
+	return handlers
+}
--- a/hugolib/handler_page.go
+++ b/hugolib/handler_page.go
@@ -13,65 +13,89 @@
 
 package hugolib
 
-import "github.com/spf13/hugo/source"
+import (
+	"github.com/spf13/hugo/helpers"
+	"github.com/spf13/hugo/source"
+	"github.com/spf13/hugo/tpl"
+	jww "github.com/spf13/jwalterweatherman"
+)
 
 func init() {
-	RegisterHandler(markdownHandler)
-	RegisterHandler(htmlHandler)
+	RegisterHandler(new(markdownHandler))
+	RegisterHandler(new(htmlHandler))
+	RegisterHandler(new(asciidocHandler))
 }
 
-var markdownHandler = Handle{
-	extensions: []string{"mdown", "markdown", "md"},
-	read: func(f *source.File, s *Site, results HandleResults) {
-		page, err := NewPage(f.Path())
-		if err != nil {
-			results <- HandledResult{file: f, err: err}
-		}
+type basicPageHandler Handle
 
-		if err := page.ReadFrom(f.Contents); err != nil {
-			results <- HandledResult{file: f, err: err}
-		}
+func (b basicPageHandler) Read(f *source.File, s *Site) HandledResult {
+	page, err := NewPage(f.Path())
+	if err != nil {
+		return HandledResult{file: f, err: err}
+	}
 
-		page.Site = &s.Info
-		page.Tmpl = s.Tmpl
+	if err := page.ReadFrom(f.Contents); err != nil {
+		return HandledResult{file: f, err: err}
+	}
 
-		results <- HandledResult{file: f, page: page, err: err}
-	},
-	pageConvert: func(p *Page, s *Site, results HandleResults) {
-		p.ProcessShortcodes(s.Tmpl)
-		err := p.Convert()
-		if err != nil {
-			results <- HandledResult{err: err}
-		}
+	page.Site = &s.Info
+	page.Tmpl = s.Tmpl
 
-		results <- HandledResult{err: err}
-	},
+	return HandledResult{file: f, page: page, err: err}
 }
 
-var htmlHandler = Handle{
-	extensions: []string{"html", "htm"},
-	read: func(f *source.File, s *Site, results HandleResults) {
-		page, err := NewPage(f.Path())
-		if err != nil {
-			results <- HandledResult{file: f, err: err}
-		}
+func (b basicPageHandler) FileConvert(*source.File, *Site) HandledResult {
+	return HandledResult{}
+}
 
-		if err := page.ReadFrom(f.Contents); err != nil {
-			results <- HandledResult{file: f, err: err}
-		}
+type markdownHandler struct {
+	basicPageHandler
+}
 
-		page.Site = &s.Info
-		page.Tmpl = s.Tmpl
+func (h markdownHandler) Extensions() []string { return []string{"mdown", "markdown", "md"} }
+func (h markdownHandler) PageConvert(p *Page, t tpl.Template) HandledResult {
+	p.ProcessShortcodes(t)
 
-		results <- HandledResult{file: f, page: page, err: err}
-	},
-	pageConvert: func(p *Page, s *Site, results HandleResults) {
-		p.ProcessShortcodes(s.Tmpl)
-		err := p.Convert()
+	tmpContent, tmpTableOfContents := helpers.ExtractTOC(p.renderContent(helpers.RemoveSummaryDivider(p.rawContent)))
+
+	if len(p.contentShortCodes) > 0 {
+		tmpContentWithTokensReplaced, err := replaceShortcodeTokens(tmpContent, shortcodePlaceholderPrefix, -1, true, p.contentShortCodes)
+
 		if err != nil {
-			results <- HandledResult{err: err}
+			jww.FATAL.Printf("Fail to replace short code tokens in %s:\n%s", p.BaseFileName(), err.Error())
+			return HandledResult{err: err}
+		} else {
+			tmpContent = tmpContentWithTokensReplaced
 		}
+	}
 
-		results <- HandledResult{err: err}
-	},
+	p.Content = helpers.BytesToHTML(tmpContent)
+	p.TableOfContents = helpers.BytesToHTML(tmpTableOfContents)
+
+	return HandledResult{err: nil}
+}
+
+type htmlHandler struct {
+	basicPageHandler
+}
+
+func (h htmlHandler) Extensions() []string { return []string{"html", "htm"} }
+func (h htmlHandler) PageConvert(p *Page, t tpl.Template) HandledResult {
+	p.ProcessShortcodes(t)
+	p.Content = helpers.BytesToHTML(p.rawContent)
+	return HandledResult{err: nil}
+}
+
+type asciidocHandler struct {
+	basicPageHandler
+}
+
+func (h asciidocHandler) Extensions() []string { return []string{"asciidoc", "ad"} }
+func (h asciidocHandler) PageConvert(p *Page, t tpl.Template) HandledResult {
+	p.ProcessShortcodes(t)
+
+	// TODO(spf13) Add Ascii Doc Logic here
+
+	//err := p.Convert()
+	return HandledResult{page: p, err: nil}
 }
--- a/hugolib/handlers.go
+++ /dev/null
@@ -1,91 +1,0 @@
-// Copyright © 2014 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 hugolib
-
-import "github.com/spf13/hugo/source"
-
-type Handler interface {
-	// Read the Files in and register
-	Read(*source.File, *Site, HandleResults)
-
-	// Convert Pages to prepare for templatizing
-	// Convert Files to their final destination
-	Convert(interface{}, *Site, HandleResults)
-
-	// Extensions to register the handle for
-	Extensions() []string
-}
-
-type HandledResult struct {
-	page *Page
-	file *source.File
-	err  error
-}
-
-type HandleResults chan<- HandledResult
-
-type ReadFunc func(*source.File, *Site, HandleResults)
-type PageConvertFunc func(*Page, *Site, HandleResults)
-type FileConvertFunc ReadFunc
-
-type Handle struct {
-	extensions  []string
-	read        ReadFunc
-	pageConvert PageConvertFunc
-	fileConvert FileConvertFunc
-}
-
-var handlers []Handler
-
-func (h Handle) Extensions() []string {
-	return h.extensions
-}
-
-func (h Handle) Read(f *source.File, s *Site, results HandleResults) {
-	h.read(f, s, results)
-}
-
-func (h Handle) Convert(i interface{}, s *Site, results HandleResults) {
-	if h.pageConvert != nil {
-		h.pageConvert(i.(*Page), s, results)
-	} else {
-		h.fileConvert(i.(*source.File), s, results)
-	}
-}
-
-func RegisterHandler(h Handler) {
-	handlers = append(handlers, h)
-}
-
-func Handlers() []Handler {
-	return handlers
-}
-
-func FindHandler(ext string) Handler {
-	for _, h := range Handlers() {
-		if HandlerMatch(h, ext) {
-			return h
-		}
-	}
-	return nil
-}
-
-func HandlerMatch(h Handler, ext string) bool {
-	for _, x := range h.Extensions() {
-		if ext == x {
-			return true
-		}
-	}
-	return false
-}
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -640,32 +640,20 @@
 
 }
 
+// TODO(spf13): Remove this entirely
+// Here for backwards compatibility & testing. Only works in isolation
 func (page *Page) Convert() error {
-	markupType := page.guessMarkupType()
-	switch markupType {
-	case "markdown", "rst":
-
-		tmpContent, tmpTableOfContents := helpers.ExtractTOC(page.renderContent(helpers.RemoveSummaryDivider(page.rawContent)))
-
-		if len(page.contentShortCodes) > 0 {
-			tmpContentWithTokensReplaced, err := replaceShortcodeTokens(tmpContent, shortcodePlaceholderPrefix, -1, true, page.contentShortCodes)
-
-			if err != nil {
-				jww.FATAL.Printf("Fail to replace short code tokens in %s:\n%s", page.BaseFileName(), err.Error())
-			} else {
-				tmpContent = tmpContentWithTokensReplaced
-			}
-		}
-
-		page.Content = helpers.BytesToHTML(tmpContent)
-		page.TableOfContents = helpers.BytesToHTML(tmpTableOfContents)
-	case "html":
-		page.Content = helpers.BytesToHTML(page.rawContent)
-	default:
-		return fmt.Errorf("Error converting unsupported file type '%s' for page '%s'", markupType, page.Source.Path())
+	var h Handler
+	if page.Markup != "" {
+		h = FindHandler(page.Markup)
+	} else {
+		h = FindHandler(page.File.Extension())
 	}
+	if h != nil {
+		h.PageConvert(page, tpl.T())
+	}
 
-	// now we know enough to create a summary of the page and count some words
+	//// now we know enough to create a summary of the page and count some words
 	page.setSummary()
 	//analyze for raw stats
 	page.analyzePage()
--- a/hugolib/page_test.go
+++ b/hugolib/page_test.go
@@ -342,7 +342,6 @@
 	if err != nil {
 		t.Fatalf("Unable to create a page with frontmatter and body content: %s", err)
 	}
-	p.ProcessShortcodes(s.Tmpl)
 	p.Convert()
 
 	checkPageTitle(t, p, "Simple")
--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -417,7 +417,7 @@
 func sourceReader(s *Site, files <-chan *source.File, results chan<- HandledResult, wg *sync.WaitGroup) {
 	defer wg.Done()
 	for file := range files {
-		h := FindHandler(file.Extension())
+		h := NewMetaHandler(file.Extension())
 		if h != nil {
 			h.Read(file, s, results)
 		} else {
@@ -429,11 +429,11 @@
 func pageConverter(s *Site, pages <-chan *Page, results HandleResults, wg *sync.WaitGroup) {
 	defer wg.Done()
 	for page := range pages {
-		var h Handler
+		var h *MetaHandle
 		if page.Markup != "" {
-			h = FindHandler(page.Markup)
+			h = NewMetaHandler(page.Markup)
 		} else {
-			h = FindHandler(page.File.Extension())
+			h = NewMetaHandler(page.File.Extension())
 		}
 		if h != nil {
 			h.Convert(page, s, results)
@@ -444,7 +444,7 @@
 func fileConverter(s *Site, files <-chan *source.File, results HandleResults, wg *sync.WaitGroup) {
 	defer wg.Done()
 	for file := range files {
-		h := FindHandler(file.Extension())
+		h := NewMetaHandler(file.Extension())
 		if h != nil {
 			h.Convert(file, s, results)
 		}
@@ -470,7 +470,7 @@
 	errMsgs := []string{}
 	for r := range results {
 		if r.err != nil {
-			errMsgs = append(errMsgs, r.err.Error())
+			errMsgs = append(errMsgs, r.Error())
 			continue
 		}