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/dchest/cssmin"
|
||||||
"github.com/spf13/hugo/helpers"
|
"github.com/spf13/hugo/helpers"
|
||||||
"github.com/spf13/hugo/source"
|
"github.com/spf13/hugo/source"
|
||||||
|
"github.com/spf13/hugo/tpl"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
RegisterHandler(css)
|
RegisterHandler(new(cssHandler))
|
||||||
}
|
}
|
||||||
|
|
||||||
var css = Handle{
|
type basicFileHandler Handle
|
||||||
extensions: []string{"css"},
|
|
||||||
read: func(f *source.File, s *Site, results HandleResults) {
|
func (h basicFileHandler) Read(f *source.File, s *Site) HandledResult {
|
||||||
results <- HandledResult{file: f}
|
return HandledResult{file: f}
|
||||||
},
|
}
|
||||||
fileConvert: func(f *source.File, s *Site, results HandleResults) {
|
|
||||||
|
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())
|
x := cssmin.Minify(f.Bytes())
|
||||||
s.WriteDestFile(f.Path(), helpers.BytesToReader(x))
|
s.WriteDestFile(f.Path(), helpers.BytesToReader(x))
|
||||||
},
|
return HandledResult{file: f}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,63 +13,70 @@
|
||||||
|
|
||||||
package hugolib
|
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 the Files in and register
|
||||||
Read(*source.File, *Site, HandleResults)
|
Read(*source.File, *Site, HandleResults)
|
||||||
|
|
||||||
// Convert Pages to prepare for templatizing
|
// Generic Convert Function with coordination
|
||||||
// Convert Files to their final destination
|
|
||||||
Convert(interface{}, *Site, HandleResults)
|
Convert(interface{}, *Site, HandleResults)
|
||||||
|
|
||||||
// Extensions to register the handle for
|
Handle() Handler
|
||||||
Extensions() []string
|
|
||||||
}
|
|
||||||
|
|
||||||
type HandledResult struct {
|
|
||||||
page *Page
|
|
||||||
file *source.File
|
|
||||||
err error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type HandleResults chan<- HandledResult
|
type HandleResults chan<- HandledResult
|
||||||
|
|
||||||
type ReadFunc func(*source.File, *Site, HandleResults)
|
func NewMetaHandler(in string) *MetaHandle {
|
||||||
type PageConvertFunc func(*Page, *Site, HandleResults)
|
x := &MetaHandle{ext: in}
|
||||||
type FileConvertFunc ReadFunc
|
x.Handler()
|
||||||
|
return x
|
||||||
type Handle struct {
|
|
||||||
extensions []string
|
|
||||||
read ReadFunc
|
|
||||||
pageConvert PageConvertFunc
|
|
||||||
fileConvert FileConvertFunc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var handlers []Handler
|
type MetaHandle struct {
|
||||||
|
handler Handler
|
||||||
func (h Handle) Extensions() []string {
|
ext string
|
||||||
return h.extensions
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h Handle) Read(f *source.File, s *Site, results HandleResults) {
|
func (mh *MetaHandle) Read(f *source.File, s *Site, results HandleResults) {
|
||||||
h.read(f, s, results)
|
if h := mh.Handler(); h != nil {
|
||||||
|
results <- h.Read(f, s)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h Handle) Convert(i interface{}, s *Site, results HandleResults) {
|
results <- HandledResult{err: errors.New("No handler found"), file: f}
|
||||||
if h.pageConvert != nil {
|
}
|
||||||
h.pageConvert(i.(*Page), s, results)
|
|
||||||
} else {
|
func (mh *MetaHandle) Convert(i interface{}, s *Site, results HandleResults) {
|
||||||
h.fileConvert(i.(*source.File), s, results)
|
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) {
|
func (mh *MetaHandle) Handler() Handler {
|
||||||
handlers = append(handlers, h)
|
if mh.handler == nil {
|
||||||
|
mh.handler = FindHandler(mh.ext)
|
||||||
}
|
}
|
||||||
|
return mh.handler
|
||||||
func Handlers() []Handler {
|
|
||||||
return handlers
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func FindHandler(ext string) Handler {
|
func FindHandler(ext string) Handler {
|
||||||
|
@ -89,3 +96,11 @@ func HandlerMatch(h Handler, ext string) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RegisterHandler(h Handler) {
|
||||||
|
handlers = append(handlers, h)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Handlers() []Handler {
|
||||||
|
return handlers
|
||||||
|
}
|
|
@ -13,65 +13,89 @@
|
||||||
|
|
||||||
package hugolib
|
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() {
|
func init() {
|
||||||
RegisterHandler(markdownHandler)
|
RegisterHandler(new(markdownHandler))
|
||||||
RegisterHandler(htmlHandler)
|
RegisterHandler(new(htmlHandler))
|
||||||
|
RegisterHandler(new(asciidocHandler))
|
||||||
}
|
}
|
||||||
|
|
||||||
var markdownHandler = Handle{
|
type basicPageHandler Handle
|
||||||
extensions: []string{"mdown", "markdown", "md"},
|
|
||||||
read: func(f *source.File, s *Site, results HandleResults) {
|
func (b basicPageHandler) Read(f *source.File, s *Site) HandledResult {
|
||||||
page, err := NewPage(f.Path())
|
page, err := NewPage(f.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
results <- HandledResult{file: f, err: err}
|
return HandledResult{file: f, err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := page.ReadFrom(f.Contents); err != nil {
|
if err := page.ReadFrom(f.Contents); err != nil {
|
||||||
results <- HandledResult{file: f, err: err}
|
return HandledResult{file: f, err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
page.Site = &s.Info
|
page.Site = &s.Info
|
||||||
page.Tmpl = s.Tmpl
|
page.Tmpl = s.Tmpl
|
||||||
|
|
||||||
results <- HandledResult{file: f, page: page, err: err}
|
return HandledResult{file: f, page: page, err: err}
|
||||||
},
|
}
|
||||||
pageConvert: func(p *Page, s *Site, results HandleResults) {
|
|
||||||
p.ProcessShortcodes(s.Tmpl)
|
func (b basicPageHandler) FileConvert(*source.File, *Site) HandledResult {
|
||||||
err := p.Convert()
|
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 {
|
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}
|
||||||
}
|
}
|
||||||
|
|
||||||
var htmlHandler = Handle{
|
type htmlHandler struct {
|
||||||
extensions: []string{"html", "htm"},
|
basicPageHandler
|
||||||
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 {
|
func (h htmlHandler) Extensions() []string { return []string{"html", "htm"} }
|
||||||
results <- HandledResult{file: f, err: err}
|
func (h htmlHandler) PageConvert(p *Page, t tpl.Template) HandledResult {
|
||||||
|
p.ProcessShortcodes(t)
|
||||||
|
p.Content = helpers.BytesToHTML(p.rawContent)
|
||||||
|
return HandledResult{err: nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
page.Site = &s.Info
|
type asciidocHandler struct {
|
||||||
page.Tmpl = s.Tmpl
|
basicPageHandler
|
||||||
|
|
||||||
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 (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 {
|
func (page *Page) Convert() error {
|
||||||
markupType := page.guessMarkupType()
|
var h Handler
|
||||||
switch markupType {
|
if page.Markup != "" {
|
||||||
case "markdown", "rst":
|
h = FindHandler(page.Markup)
|
||||||
|
|
||||||
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 {
|
} else {
|
||||||
tmpContent = tmpContentWithTokensReplaced
|
h = FindHandler(page.File.Extension())
|
||||||
}
|
}
|
||||||
|
if h != nil {
|
||||||
|
h.PageConvert(page, tpl.T())
|
||||||
}
|
}
|
||||||
|
|
||||||
page.Content = helpers.BytesToHTML(tmpContent)
|
//// now we know enough to create a summary of the page and count some words
|
||||||
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())
|
|
||||||
}
|
|
||||||
|
|
||||||
// now we know enough to create a summary of the page and count some words
|
|
||||||
page.setSummary()
|
page.setSummary()
|
||||||
//analyze for raw stats
|
//analyze for raw stats
|
||||||
page.analyzePage()
|
page.analyzePage()
|
||||||
|
|
|
@ -342,7 +342,6 @@ func TestPageWithShortCodeInSummary(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unable to create a page with frontmatter and body content: %s", err)
|
t.Fatalf("Unable to create a page with frontmatter and body content: %s", err)
|
||||||
}
|
}
|
||||||
p.ProcessShortcodes(s.Tmpl)
|
|
||||||
p.Convert()
|
p.Convert()
|
||||||
|
|
||||||
checkPageTitle(t, p, "Simple")
|
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) {
|
func sourceReader(s *Site, files <-chan *source.File, results chan<- HandledResult, wg *sync.WaitGroup) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
for file := range files {
|
for file := range files {
|
||||||
h := FindHandler(file.Extension())
|
h := NewMetaHandler(file.Extension())
|
||||||
if h != nil {
|
if h != nil {
|
||||||
h.Read(file, s, results)
|
h.Read(file, s, results)
|
||||||
} else {
|
} 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) {
|
func pageConverter(s *Site, pages <-chan *Page, results HandleResults, wg *sync.WaitGroup) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
for page := range pages {
|
for page := range pages {
|
||||||
var h Handler
|
var h *MetaHandle
|
||||||
if page.Markup != "" {
|
if page.Markup != "" {
|
||||||
h = FindHandler(page.Markup)
|
h = NewMetaHandler(page.Markup)
|
||||||
} else {
|
} else {
|
||||||
h = FindHandler(page.File.Extension())
|
h = NewMetaHandler(page.File.Extension())
|
||||||
}
|
}
|
||||||
if h != nil {
|
if h != nil {
|
||||||
h.Convert(page, s, results)
|
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) {
|
func fileConverter(s *Site, files <-chan *source.File, results HandleResults, wg *sync.WaitGroup) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
for file := range files {
|
for file := range files {
|
||||||
h := FindHandler(file.Extension())
|
h := NewMetaHandler(file.Extension())
|
||||||
if h != nil {
|
if h != nil {
|
||||||
h.Convert(file, s, results)
|
h.Convert(file, s, results)
|
||||||
}
|
}
|
||||||
|
@ -470,7 +470,7 @@ func readCollator(s *Site, results <-chan HandledResult, errs chan<- error) {
|
||||||
errMsgs := []string{}
|
errMsgs := []string{}
|
||||||
for r := range results {
|
for r := range results {
|
||||||
if r.err != nil {
|
if r.err != nil {
|
||||||
errMsgs = append(errMsgs, r.err.Error())
|
errMsgs = append(errMsgs, r.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue