@@ -18,7 +18,7 @@ HTTP server at `themes/<name>/assets/*`. | |||||
## Plugins | ## Plugins | ||||
Lua plugins are supported. They can be dropped in `plugins/*.lua`. | |||||
Lua plugins are supported. They can be dropped in `plugins/<name>/main.lua`. | |||||
API: | API: | ||||
@@ -28,6 +28,8 @@ API: | |||||
* `koushin.set_route(method, path, f)`: register a new HTTP route, `f` will be | * `koushin.set_route(method, path, f)`: register a new HTTP route, `f` will be | ||||
called with the HTTP context | called with the HTTP context | ||||
Plugins can provide their own templates in `plugins/<name>/public/*.html`. | |||||
## Contributing | ## Contributing | ||||
Send patches [on the mailing list](https://lists.sr.ht/~sircmpwn/koushin), | Send patches [on the mailing list](https://lists.sr.ht/~sircmpwn/koushin), | ||||
@@ -6,9 +6,11 @@ import ( | |||||
"github.com/labstack/echo/v4" | "github.com/labstack/echo/v4" | ||||
) | ) | ||||
const pluginDir = "plugins" | |||||
type Plugin interface { | type Plugin interface { | ||||
Name() string | Name() string | ||||
Filters() template.FuncMap | |||||
LoadTemplate(t *template.Template) error | |||||
SetRoutes(group *echo.Group) | SetRoutes(group *echo.Group) | ||||
Inject(name string, data interface{}) error | Inject(name string, data interface{}) error | ||||
Close() error | Close() error | ||||
@@ -86,8 +86,20 @@ func (p *luaPlugin) Inject(name string, data interface{}) error { | |||||
return nil | return nil | ||||
} | } | ||||
func (p *luaPlugin) Filters() template.FuncMap { | |||||
return p.filters | |||||
func (p *luaPlugin) LoadTemplate(t *template.Template) error { | |||||
t.Funcs(p.filters) | |||||
paths, err := filepath.Glob(filepath.Dir(p.filename) + "/public/*.html") | |||||
if err != nil { | |||||
return err | |||||
} | |||||
if len(paths) > 0 { | |||||
if _, err := t.ParseFiles(paths...); err != nil { | |||||
return err | |||||
} | |||||
} | |||||
return nil | |||||
} | } | ||||
func (p *luaPlugin) SetRoutes(group *echo.Group) { | func (p *luaPlugin) SetRoutes(group *echo.Group) { | ||||
@@ -136,7 +148,7 @@ func loadLuaPlugin(filename string) (*luaPlugin, error) { | |||||
} | } | ||||
func loadAllLuaPlugins(log echo.Logger) ([]Plugin, error) { | func loadAllLuaPlugins(log echo.Logger) ([]Plugin, error) { | ||||
filenames, err := filepath.Glob("plugins/*.lua") | |||||
filenames, err := filepath.Glob(pluginDir + "/*/main.lua") | |||||
if err != nil { | if err != nil { | ||||
return nil, fmt.Errorf("filepath.Glob failed: %v", err) | return nil, fmt.Errorf("filepath.Glob failed: %v", err) | ||||
} | } | ||||
@@ -92,15 +92,18 @@ func loadTemplates(logger echo.Logger, defaultTheme string, plugins []Plugin) (* | |||||
return url.PathEscape(s) | return url.PathEscape(s) | ||||
}, | }, | ||||
}) | }) | ||||
for _, p := range plugins { | |||||
base = base.Funcs(p.Filters()) | |||||
} | |||||
base, err := base.ParseGlob("public/*.html") | base, err := base.ParseGlob("public/*.html") | ||||
if err != nil { | if err != nil { | ||||
return nil, err | return nil, err | ||||
} | } | ||||
for _, p := range plugins { | |||||
if err := p.LoadTemplate(base); err != nil { | |||||
return nil, fmt.Errorf("failed to load template for plugin '%v': %v", p.Name(), err) | |||||
} | |||||
} | |||||
themes := make(map[string]*template.Template) | themes := make(map[string]*template.Template) | ||||
files, err := ioutil.ReadDir(themesDir) | files, err := ioutil.ReadDir(themesDir) | ||||