mirror of
https://github.com/danog/gojekyll.git
synced 2024-11-30 09:59:03 +01:00
Add a plugin emulation mechanism
This commit is contained in:
parent
564ada3cab
commit
7e50bb1de1
@ -23,6 +23,9 @@ type Config struct {
|
||||
Exclude []string
|
||||
MarkdownExt string `yaml:"markdown_ext"`
|
||||
|
||||
// Plugins
|
||||
Plugins []string `yaml:"gems"` // TODO this differs from the Jekyll docs
|
||||
|
||||
// Serving
|
||||
AbsoluteURL string `yaml:"url"`
|
||||
BaseURL string
|
||||
@ -78,6 +81,7 @@ func (c *Config) GetFrontMatterDefaults(relpath, typename string) (m templates.V
|
||||
}
|
||||
|
||||
// From https://jekyllrb.com/docs/configuration/#default-configuration
|
||||
// The following includes only those keys that are currently implemented.
|
||||
const defaultSiteConfig = `
|
||||
# Where things are
|
||||
source: .
|
||||
@ -97,6 +101,9 @@ encoding: "utf-8"
|
||||
markdown_ext: "markdown,mkdown,mkdn,mkd,md"
|
||||
strict_front_matter: false
|
||||
|
||||
# Plugins
|
||||
plugins: []
|
||||
|
||||
# Outputting
|
||||
permalink: date
|
||||
paginate_path: /page:num
|
||||
|
@ -4,12 +4,14 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/osteele/liquid"
|
||||
"github.com/osteele/liquid/chunks"
|
||||
)
|
||||
|
||||
// Engine is a configured liquid engine.
|
||||
type Engine interface {
|
||||
Parse([]byte) (liquid.Template, error)
|
||||
ParseAndRender([]byte, map[string]interface{}) ([]byte, error)
|
||||
DefineTag(string, func(string) (func(io.Writer, chunks.Context) error, error))
|
||||
}
|
||||
|
||||
// Wrapper is a wrapper around the Liquid engine.
|
||||
@ -35,6 +37,11 @@ func NewEngine() *Wrapper {
|
||||
return e
|
||||
}
|
||||
|
||||
// DefineTag is in the Engine interface.
|
||||
func (e *Wrapper) DefineTag(name string, f func(string) (func(io.Writer, chunks.Context) error, error)) {
|
||||
e.engine.DefineTag(name, f)
|
||||
}
|
||||
|
||||
// LinkTagHandler sets the link tag handler.
|
||||
func (e *Wrapper) LinkTagHandler(h LinkTagHandler) {
|
||||
e.linkHandler = h
|
||||
|
@ -30,7 +30,6 @@ type Pipeline struct {
|
||||
// PipelineOptions configures a pipeline.
|
||||
type PipelineOptions struct {
|
||||
SourceDir string
|
||||
AbsoluteURL, BaseURL string
|
||||
RelativeFilenameToURL liquid.LinkTagHandler
|
||||
}
|
||||
|
||||
@ -44,6 +43,11 @@ func NewPipeline(c config.Config, options PipelineOptions) (*Pipeline, error) {
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
// Engine returns the Liquid engine.
|
||||
func (p *Pipeline) TemplateEngine() liquid.Engine {
|
||||
return p.liquidEngine
|
||||
}
|
||||
|
||||
// OutputExt returns the output extension.
|
||||
func (p *Pipeline) OutputExt(pathname string) string {
|
||||
return p.config.OutputExt(pathname)
|
||||
@ -108,9 +112,9 @@ func (p *Pipeline) makeLiquidEngine() liquid.Engine {
|
||||
_, err = w.Write(text)
|
||||
return err
|
||||
}
|
||||
engine.AbsoluteURL = p.config.AbsoluteURL
|
||||
engine.BaseURL = p.config.BaseURL
|
||||
engine.IncludeHandler(includeHandler)
|
||||
engine.LinkTagHandler(p.RelativeFilenameToURL)
|
||||
engine.AbsoluteURL = p.AbsoluteURL
|
||||
engine.BaseURL = p.BaseURL
|
||||
return engine
|
||||
}
|
||||
|
74
plugins/plugins.go
Normal file
74
plugins/plugins.go
Normal file
@ -0,0 +1,74 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/osteele/gojekyll/liquid"
|
||||
"github.com/osteele/liquid/chunks"
|
||||
)
|
||||
|
||||
type PluginContext interface {
|
||||
TemplateEngine() liquid.Engine
|
||||
}
|
||||
|
||||
func Install(name string, ctx PluginContext) bool {
|
||||
p, found := plugins[name]
|
||||
if p != nil {
|
||||
if err := p(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
var plugins = map[string]func(PluginContext) error{}
|
||||
|
||||
func registerPlugin(name string, fn func(PluginContext) error) {
|
||||
plugins[name] = fn
|
||||
}
|
||||
|
||||
func warnUnimplemented(name string) {
|
||||
fmt.Printf("warning: gojekyll does not emulate the %s plugin. Some tags have been stubbed to prevent errors.\n", name)
|
||||
}
|
||||
|
||||
func emptyTag(lexer string) (func(io.Writer, chunks.Context) error, error) {
|
||||
return func(w io.Writer, _ chunks.Context) error { return nil }, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
registerPlugin("jekyll-avatar", func(ctx PluginContext) error {
|
||||
warnUnimplemented("jekyll-avatar")
|
||||
ctx.TemplateEngine().DefineTag("avatar", avatarTag)
|
||||
return nil
|
||||
})
|
||||
|
||||
registerPlugin("jekyll-feed", func(ctx PluginContext) error {
|
||||
warnUnimplemented("jekyll-feed")
|
||||
ctx.TemplateEngine().DefineTag("feed_meta", emptyTag)
|
||||
return nil
|
||||
})
|
||||
|
||||
registerPlugin("jekyll-seo-tag", func(ctx PluginContext) error {
|
||||
warnUnimplemented("jekyll-seo-tag")
|
||||
ctx.TemplateEngine().DefineTag("seo", emptyTag)
|
||||
return nil
|
||||
})
|
||||
|
||||
// registerPlugin("jekyll-sitemap")
|
||||
// registerPlugin("jemoji")
|
||||
}
|
||||
|
||||
const avatarTemplate = `<img class="avatar avatar-small" src="https://avatars3.githubusercontent.com/{username}?v=3&s=40" alt="{username}" srcset="https://avatars3.githubusercontent.com/{username}?v=3&s=40 1x, https://avatars3.githubusercontent.com/{username}?v=3&s=80 2x, https://avatars3.githubusercontent.com/{username}?v=3&s=120 3x, https://avatars3.githubusercontent.com/{username}?v=3&s=160 4x" width="40" height="40" />`
|
||||
|
||||
func avatarTag(filename string) (func(io.Writer, chunks.Context) error, error) {
|
||||
username := "osteele" // TODO replace with real name
|
||||
size := 40
|
||||
return func(w io.Writer, _ chunks.Context) error {
|
||||
s := strings.Replace(avatarTemplate, "40", fmt.Sprintf("%s", size), -1)
|
||||
s = strings.Replace(s, "{username}", username, -1)
|
||||
_, err := w.Write([]byte(s))
|
||||
return err
|
||||
}, nil
|
||||
}
|
@ -10,8 +10,10 @@ import (
|
||||
"github.com/osteele/gojekyll/collections"
|
||||
"github.com/osteele/gojekyll/config"
|
||||
"github.com/osteele/gojekyll/helpers"
|
||||
"github.com/osteele/gojekyll/liquid"
|
||||
"github.com/osteele/gojekyll/pages"
|
||||
"github.com/osteele/gojekyll/pipelines"
|
||||
"github.com/osteele/gojekyll/plugins"
|
||||
"github.com/osteele/gojekyll/templates"
|
||||
)
|
||||
|
||||
@ -27,7 +29,7 @@ type Site struct {
|
||||
|
||||
config config.Config
|
||||
data map[string]interface{}
|
||||
pipeline pipelines.PipelineInterface
|
||||
pipeline *pipelines.Pipeline
|
||||
pages []pages.Document // all pages, output or not
|
||||
preparedToRender bool
|
||||
siteVariables templates.VariableMap
|
||||
@ -128,15 +130,26 @@ func (s *Site) RenderingPipeline() pipelines.PipelineInterface {
|
||||
return s.pipeline
|
||||
}
|
||||
|
||||
type pluginContext struct {
|
||||
engine liquid.Engine
|
||||
}
|
||||
|
||||
// Engine is in the PluginContext interface.
|
||||
func (c pluginContext) TemplateEngine() liquid.Engine { return c.engine }
|
||||
|
||||
// initializeRenderingPipeline initializes the rendering pipeline
|
||||
func (s *Site) initializeRenderingPipeline() (err error) {
|
||||
options := pipelines.PipelineOptions{
|
||||
SourceDir: s.Source,
|
||||
AbsoluteURL: s.config.AbsoluteURL,
|
||||
BaseURL: s.config.BaseURL,
|
||||
RelativeFilenameToURL: s.RelativeFilenameToURL,
|
||||
}
|
||||
s.pipeline, err = pipelines.NewPipeline(s.config, options)
|
||||
ctx := pluginContext{s.pipeline.TemplateEngine()}
|
||||
for _, name := range s.config.Plugins {
|
||||
if !plugins.Install(name, ctx) {
|
||||
fmt.Printf("warning: gojekyll does not emulate the %s plugin.\n", name)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user