1
0
mirror of https://github.com/danog/gojekyll.git synced 2025-01-22 15:01:17 +01:00

Implement jekyll-default-layout plugin

This commit is contained in:
Oliver Steele 2017-09-02 12:10:35 -04:00
parent 2786ee38ce
commit 0344353d4d
8 changed files with 89 additions and 6 deletions

View File

@ -24,11 +24,12 @@ type Page interface {
// This has the side effect of causing the content to subsequently appear in the drop.
Render() error
SetContent(string)
FrontMatter() map[string]interface{}
FrontMatter() frontmatter.FrontMatter
// PostDate returns the date computed from the filename or frontmatter.
// It is an uncaught error to call this on a page that is not a Post.
// TODO Should posts have their own interface?
PostDate() time.Time
IsPost() bool
Categories() []string
Tags() []string
@ -124,7 +125,7 @@ func readFrontMatter(f *file) (b []byte, lineNo int, err error) {
return
}
func (p *page) FrontMatter() map[string]interface{} {
func (p *page) FrontMatter() frontmatter.FrontMatter {
return p.fm
}
@ -133,6 +134,11 @@ func (p *page) Categories() []string {
return p.fm.SortedStringArray("categories")
}
// IsPost is in the Page interface
func (p *page) IsPost() bool {
return p.fm["collection"] == "posts"
}
// Tags is in the Page interface
func (p *page) Tags() []string {
return p.fm.SortedStringArray("tags")

View File

@ -56,7 +56,7 @@ func (p *page) permalinkVariables() map[string]string {
"slug": slug,
"title": utils.Slugify(p.fm.String("title", name)),
"y_day": strconv.Itoa(p.modTime.YearDay()),
// Not documented, but evident:
// Undocumented but evident:
"output_ext": p.OutputExt(),
}
for k, v := range permalinkDateVariables {

View File

@ -17,6 +17,7 @@ type siteFake struct {
func (s siteFake) AddDocument(pages.Document, bool) {}
func (s siteFake) Config() *config.Config { return &s.c }
func (s siteFake) HasLayout(string) bool { return true }
func (s siteFake) Pages() []pages.Page { return nil }
func (s siteFake) Posts() []pages.Page { return nil }
func (s siteFake) TemplateEngine() *liquid.Engine { return s.e }

48
plugins/default_layout.go Normal file
View File

@ -0,0 +1,48 @@
package plugins
func init() {
register("jekyll-default-layout", jekyllDefaultLayout{})
}
type jekyllDefaultLayout struct{ plugin }
const (
defaultLayout int = iota
pageLayout
postLayout
homeLayout
)
var layoutNames = []string{"default", "post", "page", "home"}
func (p jekyllDefaultLayout) layoutNames(s Site) []string {
var ln string
names := make([]string, len(layoutNames))
for i, n := range layoutNames {
// fmt.Println("examine", i, n, names)
if s.HasLayout(n) {
ln = n
}
names[i] = ln
}
return names
}
func (p jekyllDefaultLayout) PostInitPage(s Site, pg Page) error {
fm := pg.FrontMatter()
if fm["layout"] != nil {
return nil
}
layoutNames := p.layoutNames(s)
ln := layoutNames[pageLayout]
switch {
case pg.IsPost():
ln = layoutNames[postLayout]
case pg.Permalink() == "/":
ln = layoutNames[homeLayout]
}
if ln != "" {
fm["layout"] = ln
}
return nil
}

View File

@ -12,6 +12,7 @@ import (
"github.com/kyokomi/emoji"
"github.com/osteele/gojekyll/config"
"github.com/osteele/gojekyll/frontmatter"
"github.com/osteele/gojekyll/pages"
"github.com/osteele/gojekyll/utils"
"github.com/osteele/liquid"
@ -23,17 +24,26 @@ type Plugin interface {
ConfigureTemplateEngine(*liquid.Engine) error
ModifyPluginList([]string) []string
ModifySiteDrop(Site, map[string]interface{}) error
PostInitPage(Site, Page) error
PostRead(Site) error
PostRender([]byte) ([]byte, error)
}
// Site is the site interface that is available to a plugin.
// Site is the site interface that is available to plugins.
type Site interface {
AddDocument(pages.Document, bool)
Config() *config.Config
TemplateEngine() *liquid.Engine
Pages() []pages.Page
Posts() []pages.Page
HasLayout(string) bool
}
// Page is the page interface that is available to plugins.
type Page interface {
FrontMatter() frontmatter.FrontMatter
IsPost() bool
Permalink() string
}
// Lookup returns a plugin if it has been registered.
@ -75,6 +85,7 @@ func (p plugin) Initialize(Site) error { return nil
func (p plugin) ConfigureTemplateEngine(*liquid.Engine) error { return nil }
func (p plugin) ModifyPluginList(names []string) []string { return names }
func (p plugin) ModifySiteDrop(Site, map[string]interface{}) error { return nil }
func (p plugin) PostInitPage(Site, Page) error { return nil }
func (p plugin) PostRead(Site) error { return nil }
func (p plugin) PostRender(b []byte) ([]byte, error) { return b, nil }

View File

@ -35,7 +35,7 @@ func (p *Manager) ApplyLayout(name string, content []byte, vars liquid.Bindings)
}
// FindLayout returns a template for the named layout.
func (p *Manager) FindLayout(base string, fm *map[string]interface{}) (tpl *liquid.Template, err error) {
func (p *Manager) FindLayout(base string, fmp *map[string]interface{}) (tpl *liquid.Template, err error) {
// not cached, but the time here is negligible
exts := []string{"", ".html"}
for _, ext := range strings.SplitN(p.cfg.MarkdownExt, `,`, -1) {
@ -64,10 +64,13 @@ loop:
return nil, fmt.Errorf("no template for %s", base)
}
lineNo := 1
*fm, err = frontmatter.Read(&content, &lineNo)
fm, err := frontmatter.Read(&content, &lineNo)
if err != nil {
return
}
if fmp != nil {
*fmp = fm
}
tpl, err = p.liquidEngine.ParseTemplateLocation(content, filename, lineNo)
if err != nil {
return nil, err

View File

@ -47,6 +47,14 @@ func (s *Site) Read() error {
if err := s.initializeRenderers(); err != nil {
return utils.WrapError(err, "initializing renderers")
}
for _, p := range s.Pages() {
err := s.runHooks(func(h plugins.Plugin) error {
return h.PostInitPage(s, p)
})
if err != nil {
return err
}
}
return s.runHooks(func(p plugins.Plugin) error { return p.PostRead(s) })
}

View File

@ -180,6 +180,12 @@ func (s *Site) initializeRenderers() (err error) {
})
}
// HasLayout is in the plugins.Site interface.
func (s *Site) HasLayout(ln string) bool {
l, err := s.renderer.FindLayout(ln, nil)
return err == nil && l != nil
}
// RelativePath is in the page.Container interface.
func (s *Site) RelativePath(path string) string {
if s.themeDir != "" {