mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
refactor handlers to use types instead of structs.
This commit is contained in:
parent
73f203ad86
commit
4a2f16f91e
7 changed files with 227 additions and 129 deletions
61
hugolib/handler_base.go
Normal file
61
hugolib/handler_base.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
// Copyright © 2014 Steve Francia <spf@spf13.com>.
|
||||
//
|
||||
// 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
|
||||
}
|
|
@ -17,19 +17,30 @@ import (
|
|||
"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}
|
||||
}
|
||||
|
|
|
@ -13,63 +13,70 @@
|
|||
|
||||
package hugolib
|
||||
|
||||
import "github.com/spf13/hugo/source"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
type Handler interface {
|
||||
"github.com/spf13/hugo/source"
|
||||
)
|
||||
|
||||
var handlers []Handler
|
||||
|
||||
type MetaHandler interface {
|
||||
// Read the Files in and register
|
||||
Read(*source.File, *Site, HandleResults)
|
||||
|
||||
// Convert Pages to prepare for templatizing
|
||||
// Convert Files to their final destination
|
||||
// Generic Convert Function with coordination
|
||||
Convert(interface{}, *Site, HandleResults)
|
||||
|
||||
// Extensions to register the handle for
|
||||
Extensions() []string
|
||||
}
|
||||
|
||||
type HandledResult struct {
|
||||
page *Page
|
||||
file *source.File
|
||||
err error
|
||||
Handle() Handler
|
||||
}
|
||||
|
||||
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
|
||||
func NewMetaHandler(in string) *MetaHandle {
|
||||
x := &MetaHandle{ext: in}
|
||||
x.Handler()
|
||||
return x
|
||||
}
|
||||
|
||||
var handlers []Handler
|
||||
|
||||
func (h Handle) Extensions() []string {
|
||||
return h.extensions
|
||||
type MetaHandle struct {
|
||||
handler Handler
|
||||
ext string
|
||||
}
|
||||
|
||||
func (h Handle) Read(f *source.File, s *Site, results HandleResults) {
|
||||
h.read(f, s, results)
|
||||
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 (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 (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 RegisterHandler(h Handler) {
|
||||
handlers = append(handlers, h)
|
||||
}
|
||||
|
||||
func Handlers() []Handler {
|
||||
return handlers
|
||||
func (mh *MetaHandle) Handler() Handler {
|
||||
if mh.handler == nil {
|
||||
mh.handler = FindHandler(mh.ext)
|
||||
}
|
||||
return mh.handler
|
||||
}
|
||||
|
||||
func FindHandler(ext string) Handler {
|
||||
|
@ -89,3 +96,11 @@ func HandlerMatch(h Handler, ext string) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func RegisterHandler(h Handler) {
|
||||
handlers = append(handlers, h)
|
||||
}
|
||||
|
||||
func Handlers() []Handler {
|
||||
return handlers
|
||||
}
|
|
@ -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}
|
||||
}
|
||||
|
||||
if err := page.ReadFrom(f.Contents); err != nil {
|
||||
results <- HandledResult{file: f, err: err}
|
||||
}
|
||||
|
||||
page.Site = &s.Info
|
||||
page.Tmpl = s.Tmpl
|
||||
|
||||
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}
|
||||
}
|
||||
|
||||
results <- HandledResult{err: err}
|
||||
},
|
||||
func (b basicPageHandler) FileConvert(*source.File, *Site) HandledResult {
|
||||
return HandledResult{}
|
||||
}
|
||||
|
||||
type markdownHandler struct {
|
||||
basicPageHandler
|
||||
}
|
||||
|
||||
func (h markdownHandler) Extensions() []string { return []string{"mdown", "markdown", "md"} }
|
||||
func (h markdownHandler) PageConvert(p *Page, t tpl.Template) HandledResult {
|
||||
p.ProcessShortcodes(t)
|
||||
|
||||
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 {
|
||||
jww.FATAL.Printf("Fail to replace short code tokens in %s:\n%s", p.BaseFileName(), err.Error())
|
||||
return HandledResult{err: err}
|
||||
} else {
|
||||
tmpContent = tmpContentWithTokensReplaced
|
||||
}
|
||||
}
|
||||
|
||||
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}
|
||||
}
|
||||
|
|
|
@ -640,32 +640,20 @@ func (p *Page) ProcessShortcodes(t tpl.Template) {
|
|||
|
||||
}
|
||||
|
||||
// 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()
|
||||
|
|
|
@ -342,7 +342,6 @@ func TestPageWithShortCodeInSummary(t *testing.T) {
|
|||
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")
|
||||
|
|
|
@ -417,7 +417,7 @@ func (s *Site) CreatePages() error {
|
|||
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 sourceReader(s *Site, files <-chan *source.File, results chan<- HandledResu
|
|||
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 pageConverter(s *Site, pages <-chan *Page, results HandleResults, wg *sync.
|
|||
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 @@ func readCollator(s *Site, results <-chan HandledResult, errs chan<- error) {
|
|||
errMsgs := []string{}
|
||||
for r := range results {
|
||||
if r.err != nil {
|
||||
errMsgs = append(errMsgs, r.err.Error())
|
||||
errMsgs = append(errMsgs, r.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue