1
0
mirror of https://github.com/danog/gojekyll.git synced 2024-12-02 15:37:52 +01:00
gojekyll/plugins/plugins.go

171 lines
5.0 KiB
Go
Raw Normal View History

2017-07-01 05:10:58 +02:00
// Package plugins holds emulated Jekyll plugins.
//
2017-07-26 15:08:32 +02:00
// Unlike Jekyll, these are baked into the executable -- both because package "plugin'
// works only on Linux (as of 2017.07); and because the gojekyll implementation is immature and any possible interfaces
2017-07-01 05:10:58 +02:00
// are far from baked.
2017-06-30 18:53:34 +02:00
package plugins
import (
"fmt"
"regexp"
2017-08-11 20:24:09 +02:00
"sort"
2017-06-30 18:53:34 +02:00
2017-07-09 21:07:14 +02:00
"github.com/kyokomi/emoji"
2017-07-09 03:41:35 +02:00
"github.com/osteele/gojekyll/config"
"github.com/osteele/gojekyll/pages"
2017-07-09 22:17:20 +02:00
"github.com/osteele/gojekyll/utils"
2017-07-01 01:37:31 +02:00
"github.com/osteele/liquid"
2017-06-30 18:53:34 +02:00
)
2017-07-09 03:41:35 +02:00
// Plugin describes the hooks that a plugin can override.
type Plugin interface {
2017-09-02 19:57:28 +02:00
AfterInitSite(Site) error
ConfigureTemplateEngine(*liquid.Engine) error
2017-09-01 15:10:07 +02:00
ModifyPluginList([]string) []string
ModifySiteDrop(Site, map[string]interface{}) error
2017-09-02 18:10:35 +02:00
PostInitPage(Site, Page) error
2017-09-02 19:57:28 +02:00
PostReadSite(Site) error
PostRender([]byte) ([]byte, error)
2017-07-09 03:41:35 +02:00
}
2017-09-02 18:10:35 +02:00
// Site is the site interface that is available to plugins.
2017-07-26 15:08:32 +02:00
type Site interface {
2017-09-03 18:21:55 +02:00
AddHTMLPage(url string, tpl string, fm pages.FrontMatter)
2017-07-26 15:08:32 +02:00
Config() *config.Config
TemplateEngine() *liquid.Engine
2017-09-03 18:18:17 +02:00
Pages() []Page
Posts() []Page
2017-09-02 18:10:35 +02:00
HasLayout(string) bool
}
2017-09-03 18:18:17 +02:00
// Page is in package pages.
type Page = pages.Page
2017-07-09 03:41:35 +02:00
2017-07-09 04:47:50 +02:00
// Lookup returns a plugin if it has been registered.
func Lookup(name string) (Plugin, bool) {
p, found := directory[name]
return p, found
2017-07-09 03:41:35 +02:00
}
2017-07-26 15:08:32 +02:00
// Install installs a registered plugin.
2017-09-01 15:10:07 +02:00
func Install(names []string, site Site) error {
2017-07-09 04:47:50 +02:00
for _, name := range names {
2017-07-26 15:08:32 +02:00
if p, found := directory[name]; found {
2017-09-02 19:57:28 +02:00
if err := p.AfterInitSite(site); err != nil {
2017-09-01 15:10:07 +02:00
return err
2017-07-09 04:47:50 +02:00
}
} else {
fmt.Printf("warning: gojekyll does not emulate the %s plugin.\n", name)
2017-06-30 18:53:34 +02:00
}
}
2017-09-01 15:10:07 +02:00
return nil
2017-06-30 18:53:34 +02:00
}
2017-08-11 20:24:09 +02:00
// Names returns a sorted list of names of registered plugins.
func Names() []string {
var names []string
for name := range directory {
names = append(names, name)
}
sort.Strings(names)
return names
}
2017-07-26 15:08:32 +02:00
// Embed plugin to implement defaults implementations of the Plugin interface.
//
// This is internal until better baked.
type plugin struct{}
2017-09-02 19:57:28 +02:00
func (p plugin) AfterInitSite(Site) error { return nil }
2017-07-26 15:08:32 +02:00
func (p plugin) ConfigureTemplateEngine(*liquid.Engine) error { return nil }
2017-09-01 15:10:07 +02:00
func (p plugin) ModifyPluginList(names []string) []string { return names }
2017-07-26 15:08:32 +02:00
func (p plugin) ModifySiteDrop(Site, map[string]interface{}) error { return nil }
2017-09-02 18:10:35 +02:00
func (p plugin) PostInitPage(Site, Page) error { return nil }
2017-09-02 19:57:28 +02:00
func (p plugin) PostReadSite(Site) error { return nil }
func (p plugin) PostRender(b []byte) ([]byte, error) { return b, nil }
2017-07-26 15:08:32 +02:00
2017-07-09 04:47:50 +02:00
var directory = map[string]Plugin{}
2017-06-30 18:53:34 +02:00
2017-07-09 01:57:41 +02:00
// register installs a plugin in the plugin directory.
2017-07-26 15:08:32 +02:00
//
// This is internal until better baked.
2017-07-09 04:47:50 +02:00
func register(name string, p Plugin) {
directory[name] = p
2017-06-30 18:53:34 +02:00
}
2017-07-26 15:08:32 +02:00
// Add the built-in plugins defined in this file.
// More extensive plugins are defined and registered in own files.
2017-06-30 18:53:34 +02:00
func init() {
register("jemoji", jemojiPlugin{})
register("jekyll-mentions", jekyllMentionsPlugin{})
2017-07-24 18:18:24 +02:00
register("jekyll-optional-front-matter", jekyllOptionalFrontMatterPlugin{})
2017-07-05 22:54:48 +02:00
2017-07-26 15:08:32 +02:00
// Gojekyll behaves as though the following plugins are always loaded.
// Define them here so we don't see warnings that they aren't defined.
2017-07-09 04:47:50 +02:00
register("jekyll-live-reload", plugin{})
register("jekyll-sass-converter", plugin{})
2017-06-30 18:53:34 +02:00
}
2017-07-01 16:37:11 +02:00
2017-07-09 21:07:14 +02:00
// Some small plugins are below. More involved plugins are in separate files.
2017-07-26 15:08:32 +02:00
// jemojiPlugin emulates the jekyll-jemoji plugin.
type jemojiPlugin struct{ plugin }
2017-07-09 21:07:14 +02:00
func (p jemojiPlugin) PostRender(b []byte) ([]byte, error) {
2017-07-09 22:17:20 +02:00
return utils.ApplyToHTMLText(b, func(s string) string {
return emoji.Sprint(s)
}), nil
2017-07-09 21:07:14 +02:00
}
2017-07-26 15:08:32 +02:00
// jekyllMentionsPlugin emulates the jekyll-mentions plugin.
type jekyllMentionsPlugin struct{ plugin }
var mentionPattern = regexp.MustCompile(`@(\w+)`)
func (p jekyllMentionsPlugin) PostRender(b []byte) ([]byte, error) {
2017-07-09 22:17:20 +02:00
return utils.ApplyToHTMLText(b, func(s string) string {
return mentionPattern.ReplaceAllString(s, `<a href="https://github.com/$1" class="user-mention">@$1</a>`)
}), nil
}
2017-07-26 15:08:32 +02:00
// jekyllOptionalFrontMatterPlugin emulates the jekyll-optional-front-matter plugin.
2017-07-24 18:18:24 +02:00
type jekyllOptionalFrontMatterPlugin struct{ plugin }
var requireFrontMatterExclude = []string{
"README",
"LICENSE",
"LICENCE",
"COPYING",
"CODE_OF_CONDUCT",
"CONTRIBUTING",
"ISSUE_TEMPLATE",
"PULL_REQUEST_TEMPLATE",
}
2017-09-02 19:57:28 +02:00
func (p jekyllOptionalFrontMatterPlugin) AfterInitSite(s Site) error {
2017-07-24 18:18:24 +02:00
m := map[string]bool{}
for _, k := range requireFrontMatterExclude {
m[k] = true
}
s.Config().RequireFrontMatter = false
s.Config().RequireFrontMatterExclude = m
return nil
}
2017-07-09 21:07:14 +02:00
// helpers
2017-07-11 18:03:52 +02:00
// func (p plugin) stubbed(name string) {
// fmt.Printf("warning: gojekyll does not emulate the %s plugin. Some tags have been stubbed to prevent errors.\n", name)
// }
// func (p plugin) makeUnimplementedTag(pluginName string) liquid.Renderer {
// warned := false
// return func(ctx render.Context) (string, error) {
// if !warned {
// fmt.Printf("The %q tag in the %q plugin has not been implemented.\n", ctx.TagName(), pluginName)
// warned = true
// }
// return fmt.Sprintf(`<!-- unimplemented tag: %q -->`, ctx.TagName()), nil
// }
// }