Handlebars support - Embrace the feature request https://github.com/kataras/iris/issues/239

This commit is contained in:
Makis Maropoulos 2016-06-28 12:50:26 +03:00
parent 04dbd0bac9
commit aa319fd8e4
7 changed files with 159 additions and 11 deletions

View File

@ -6,7 +6,7 @@
[Travis]: http://travis-ci.org/kataras/iris
[License Widget]: https://img.shields.io/badge/license-MIT%20%20License%20-E91E63.svg?style=flat-square
[License]: https://github.com/kataras/iris/blob/master/LICENSE
[Release Widget]: https://img.shields.io/badge/release-v3.0.0--rc.3-blue.svg?style=flat-square
[Release Widget]: https://img.shields.io/badge/release-v3.0.0--rc.4-blue.svg?style=flat-square
[Release]: https://github.com/kataras/iris/releases
[Gitter Widget]: https://img.shields.io/badge/chat-on%20gitter-00BCD4.svg?style=flat-square
[Gitter]: https://gitter.im/kataras/iris
@ -72,7 +72,7 @@ Features
------------
- Focus on high performance
- Robust routing supports static and wildcard subdomains
- View system supporting [5+](https://kataras.gitbooks.io/iris/content/render_templates.html) template engines
- View system supporting [6+](https://kataras.gitbooks.io/iris/content/render_templates.html) template engines
- Highly scalable Websocket API with custom events
- Sessions support with GC, memory & redis providers
- Middlewares & Plugins were never be easier
@ -151,7 +151,7 @@ I recommend writing your API tests using this new library, [httpexpect](https://
Versioning
------------
Current: **v3.0.0-rc.3**
Current: **v3.0.0-rc.4**
> Iris is an active project

View File

@ -2,7 +2,8 @@ Third party packages
------------
- [Iris is build on top of fasthttp](https://github.com/valyala/fasthttp)
- [pongo2 is one of the supporting template engines](https://github.com/flosch/pongo2)
- [django is one of the supporting template engines](https://github.com/flosch/pongo2)
- [handlebars is one of the supporting template engines](https://github.com/aymerick/raymond)
- [amber is one of the supporting template engines](https://github.com/eknkc/amber)
- [jade is one of the supporting template engines](https://github.com/Joker/jade)
- [blackfriday is one of the supporting template engines](https://github.com/russross/blackfriday)
@ -42,7 +43,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
pongo2 - The MIT License (MIT)
django - The MIT License (MIT)
Copyright (c) 2013-2014 Florian Schlachter
@ -63,6 +64,29 @@ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
handlebars - The MIT License (MIT)
Copyright (c) 2015 Aymerick JEHANNE
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Jade - Copyright (c) 2015, Joker
All rights reserved.

View File

@ -26,6 +26,9 @@ const (
// AmberEngine is a Template's config for engine type
// when use this, the templates are eknkc/amber
AmberEngine EngineType = 4
// HandlebarsEngine is a Template's config for engine type
// when use this, the templates are aymerick/raymond
HandlebarsEngine EngineType = 5
// DefaultEngine is the HTMLEngine
DefaultEngine EngineType = HTMLEngine
@ -115,6 +118,8 @@ type (
Markdown Markdown
// Amber contains specific configs for amber
Amber Amber
// Handlebars contains specific configs for handlebars
Handlebars Handlebars
}
// HTMLTemplate the configs for HTMLEngine
@ -154,6 +159,12 @@ type (
// Funcs for the html/template result, amber default funcs are not overrided so use it without worries
Funcs template.FuncMap
}
// Handlebars the configs for HandlebarsEngine
Handlebars struct {
// Helpers for Handlebars, you can register your own by raymond.RegisterHelper(name string, a interface{}) or RegisterHelpers(map[string]interface{})
// or just fill this method, do not override it it is not nil by default (because of Iris' helpers (url and urlpath)
Helpers map[string]interface{}
}
)
// DefaultRest returns the default config for rest
@ -210,6 +221,7 @@ func DefaultTemplate() Template {
Pongo: Pongo{Filters: make(map[string]pongo2.FilterFunction, 0), Globals: make(map[string]interface{}, 0)},
Markdown: Markdown{Sanitize: false},
Amber: Amber{Funcs: template.FuncMap{}},
Handlebars: Handlebars{Helpers: make(map[string]interface{}, 0)},
}
}

View File

@ -8,11 +8,10 @@ import (
"github.com/kataras/iris/config"
"github.com/kataras/iris/logger"
"github.com/kataras/iris/websocket"
"github.com/kataras/iris/render/rest"
"github.com/kataras/iris/render/template"
"github.com/kataras/iris/sessions"
"github.com/kataras/iris/websocket"
///NOTE: register the session providers, but the s.Config.Sessions.Provider will be used only, if this empty then sessions are disabled.
_ "github.com/kataras/iris/sessions/providers/memory"
_ "github.com/kataras/iris/sessions/providers/redis"
@ -39,7 +38,6 @@ func init() {
const (
/* conversional */
// HTMLEngine conversion for config.HTMLEngine
HTMLEngine = config.HTMLEngine
// PongoEngine conversion for config.PongoEngine
@ -50,7 +48,8 @@ const (
JadeEngine = config.JadeEngine
// AmberEngine conversion for config.AmberEngine
AmberEngine = config.AmberEngine
// HandlebarsEngine conversion for config.HandlebarsEngine
HandlebarsEngine = config.HandlebarsEngine
// DefaultEngine conversion for config.DefaultEngine
DefaultEngine = config.DefaultEngine
// NoEngine conversion for config.NoEngine
@ -58,7 +57,6 @@ const (
// NoLayout to disable layout for a particular template file
// conversion for config.NoLayout
NoLayout = config.NoLayout
/* end conversional */
)

View File

@ -68,7 +68,7 @@ import (
const (
// Version of the iris
Version = "3.0.0-rc.3"
Version = "3.0.0-rc.4"
banner = ` _____ _
|_ _| (_)
| | ____ _ ___

View File

@ -0,0 +1,110 @@
// Package handlebars the HandlebarsEngine's functionality
package handlebars
import (
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"sync"
"github.com/aymerick/raymond"
"github.com/kataras/iris/config"
)
type (
// Engine the Handlebars engine
Engine struct {
Config *config.Template
templateCache map[string]*raymond.Template
mu sync.Mutex
}
)
// New creates and returns the Handlebars template engine
func New(c config.Template) *Engine {
s := &Engine{Config: &c, templateCache: make(map[string]*raymond.Template, 0)}
return s
}
// BuildTemplates builds the handlebars templates
func (e *Engine) BuildTemplates() error {
if e.Config.Extensions == nil || len(e.Config.Extensions) == 0 {
e.Config.Extensions = []string{".html"}
}
// register the global helpers
if e.Config.Handlebars.Helpers != nil {
raymond.RegisterHelpers(e.Config.Handlebars.Helpers)
}
var templateErr error
dir := e.Config.Directory
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if info == nil || info.IsDir() {
return nil
}
rel, err := filepath.Rel(dir, path)
if err != nil {
return err
}
ext := ""
if strings.Index(rel, ".") != -1 {
ext = filepath.Ext(rel)
}
for _, extension := range e.Config.Extensions {
if ext == extension {
buf, err := ioutil.ReadFile(path)
contents := string(buf)
if err != nil {
templateErr = err
break
}
name := filepath.ToSlash(rel)
tmpl, err := raymond.Parse(contents)
if err != nil {
templateErr = err
continue
}
e.mu.Lock()
e.templateCache[name] = tmpl
e.mu.Unlock()
break
}
}
return nil
})
return templateErr
}
func (e *Engine) fromCache(relativeName string) *raymond.Template {
e.mu.Lock()
tmpl, ok := e.templateCache[relativeName]
if ok {
e.mu.Unlock()
return tmpl
}
e.mu.Unlock()
return nil
}
// ExecuteWriter executes a templates and write its results to the out writer
func (e *Engine) ExecuteWriter(out io.Writer, name string, binding interface{}, layout string) error {
if tmpl := e.fromCache(name); tmpl != nil {
res, err := tmpl.Exec(binding)
_, err = fmt.Fprint(out, res)
return err
}
return fmt.Errorf("[IRIS TEMPLATES] Template with name %s doesn't exists in the dir %s", name, e.Config.Directory)
}

View File

@ -11,6 +11,7 @@ import (
"github.com/kataras/iris/config"
"github.com/kataras/iris/context"
"github.com/kataras/iris/render/template/engine/amber"
"github.com/kataras/iris/render/template/engine/handlebars"
"github.com/kataras/iris/render/template/engine/html"
"github.com/kataras/iris/render/template/engine/jade"
"github.com/kataras/iris/render/template/engine/markdown"
@ -98,6 +99,9 @@ func New(c config.Template) *Template {
case config.AmberEngine:
setSharedFuncs(sharedFuncs, c.Amber.Funcs)
e = amber.New(c) // Amber
case config.HandlebarsEngine:
setSharedFuncs(sharedFuncs, c.Handlebars.Helpers)
e = handlebars.New(c)
default: // config.NoEngine
return nil
}