mirror of
https://github.com/danog/gojekyll.git
synced 2024-12-12 10:09:37 +01:00
171 lines
5.0 KiB
Go
171 lines
5.0 KiB
Go
// Package plugins holds emulated Jekyll plugins.
|
|
//
|
|
// 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
|
|
// are far from baked.
|
|
package plugins
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"sort"
|
|
|
|
"github.com/kyokomi/emoji"
|
|
"github.com/osteele/gojekyll/config"
|
|
"github.com/osteele/gojekyll/pages"
|
|
"github.com/osteele/gojekyll/utils"
|
|
"github.com/osteele/liquid"
|
|
)
|
|
|
|
// Plugin describes the hooks that a plugin can override.
|
|
type Plugin interface {
|
|
AfterInitSite(Site) error
|
|
ConfigureTemplateEngine(*liquid.Engine) error
|
|
ModifyPluginList([]string) []string
|
|
ModifySiteDrop(Site, map[string]interface{}) error
|
|
PostInitPage(Site, Page) error
|
|
PostReadSite(Site) error
|
|
PostRender([]byte) ([]byte, error)
|
|
}
|
|
|
|
// Site is the site interface that is available to plugins.
|
|
type Site interface {
|
|
AddHTMLPage(url string, tpl string, fm pages.FrontMatter)
|
|
Config() *config.Config
|
|
TemplateEngine() *liquid.Engine
|
|
Pages() []Page
|
|
Posts() []Page
|
|
HasLayout(string) bool
|
|
}
|
|
|
|
// Page is in package pages.
|
|
type Page = pages.Page
|
|
|
|
// Lookup returns a plugin if it has been registered.
|
|
func Lookup(name string) (Plugin, bool) {
|
|
p, found := directory[name]
|
|
return p, found
|
|
}
|
|
|
|
// Install installs a registered plugin.
|
|
func Install(names []string, site Site) error {
|
|
for _, name := range names {
|
|
if p, found := directory[name]; found {
|
|
if err := p.AfterInitSite(site); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
fmt.Printf("warning: gojekyll does not emulate the %s plugin.\n", name)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
// Embed plugin to implement defaults implementations of the Plugin interface.
|
|
//
|
|
// This is internal until better baked.
|
|
type plugin struct{}
|
|
|
|
func (p plugin) AfterInitSite(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) PostReadSite(Site) error { return nil }
|
|
func (p plugin) PostRender(b []byte) ([]byte, error) { return b, nil }
|
|
|
|
var directory = map[string]Plugin{}
|
|
|
|
// register installs a plugin in the plugin directory.
|
|
//
|
|
// This is internal until better baked.
|
|
func register(name string, p Plugin) {
|
|
directory[name] = p
|
|
}
|
|
|
|
// Add the built-in plugins defined in this file.
|
|
// More extensive plugins are defined and registered in own files.
|
|
func init() {
|
|
register("jemoji", jemojiPlugin{})
|
|
register("jekyll-mentions", jekyllMentionsPlugin{})
|
|
register("jekyll-optional-front-matter", jekyllOptionalFrontMatterPlugin{})
|
|
|
|
// Gojekyll behaves as though the following plugins are always loaded.
|
|
// Define them here so we don't see warnings that they aren't defined.
|
|
register("jekyll-live-reload", plugin{})
|
|
register("jekyll-sass-converter", plugin{})
|
|
}
|
|
|
|
// Some small plugins are below. More involved plugins are in separate files.
|
|
|
|
// jemojiPlugin emulates the jekyll-jemoji plugin.
|
|
type jemojiPlugin struct{ plugin }
|
|
|
|
func (p jemojiPlugin) PostRender(b []byte) ([]byte, error) {
|
|
return utils.ApplyToHTMLText(b, func(s string) string {
|
|
return emoji.Sprint(s)
|
|
}), nil
|
|
}
|
|
|
|
// jekyllMentionsPlugin emulates the jekyll-mentions plugin.
|
|
type jekyllMentionsPlugin struct{ plugin }
|
|
|
|
var mentionPattern = regexp.MustCompile(`@(\w+)`)
|
|
|
|
func (p jekyllMentionsPlugin) PostRender(b []byte) ([]byte, error) {
|
|
return utils.ApplyToHTMLText(b, func(s string) string {
|
|
return mentionPattern.ReplaceAllString(s, `<a href="https://github.com/$1" class="user-mention">@$1</a>`)
|
|
}), nil
|
|
}
|
|
|
|
// jekyllOptionalFrontMatterPlugin emulates the jekyll-optional-front-matter plugin.
|
|
type jekyllOptionalFrontMatterPlugin struct{ plugin }
|
|
|
|
var requireFrontMatterExclude = []string{
|
|
"README",
|
|
"LICENSE",
|
|
"LICENCE",
|
|
"COPYING",
|
|
"CODE_OF_CONDUCT",
|
|
"CONTRIBUTING",
|
|
"ISSUE_TEMPLATE",
|
|
"PULL_REQUEST_TEMPLATE",
|
|
}
|
|
|
|
func (p jekyllOptionalFrontMatterPlugin) AfterInitSite(s Site) error {
|
|
m := map[string]bool{}
|
|
for _, k := range requireFrontMatterExclude {
|
|
m[k] = true
|
|
}
|
|
s.Config().RequireFrontMatter = false
|
|
s.Config().RequireFrontMatterExclude = m
|
|
return nil
|
|
}
|
|
|
|
// helpers
|
|
|
|
// 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
|
|
// }
|
|
// }
|