1
0
mirror of https://github.com/kataras/iris.git synced 2025-12-17 09:57:01 +00:00

add 'iris.Blocks' template engine

read more about its features at: https://github.com/kataras/blocks
This commit is contained in:
Gerasimos (Makis) Maropoulos
2020-08-05 06:46:45 +03:00
parent 6844be57ea
commit b363492cca
24 changed files with 631 additions and 40 deletions

View File

@@ -1,18 +1,21 @@
# View
Iris supports 7 template engines out-of-the-box, developers can still use any external golang template engine,
Iris supports 8 template engines out-of-the-box, developers can still use any external golang template engine,
as `Context.ResponseWriter()` is an `io.Writer`.
All of these six template engines have common features with common API,
like Layout, Template Funcs, Party-specific layout, partial rendering and more.
All template engines share a common API i.e.
Parse using embedded assets, Layouts and Party-specific layout, Template Funcs, Partial Render and more.
- The standard html, its template parser is the [golang.org/pkg/html/template/](https://golang.org/pkg/html/template/)
- Django, its template parser is the [github.com/iris-contrib/pongo2](https://github.com/iris-contrib/pongo2)
- Pug(Jade), its template parser is the [github.com/Joker/jade](https://github.com/Joker/jade)
- Handlebars, its template parser is the [github.com/aymerick/raymond](https://github.com/aymerick/raymond)
- Amber, its template parser is the [github.com/eknkc/amber](https://github.com/eknkc/amber)
- Jet, its template parser is the [github.com/CloudyKit/jet](https://github.com/CloudyKit/jet)
- Ace, its template parser is the [github.com/yosssi/ace](https://github.com/yosssi/ace)
| # | Name | Parser |
|:---|:-----------|----------|
| 1 | HTML | [html/template](https://pkg.go.dev/html/template) |
| 2 | Blocks | [kataras/blocks](https://github.com/kataras/blocks) |
| 3 | Django | [flosch/pongo2](https://github.com/flosch/pongo2) |
| 4 | Pug | [Joker/jade](https://github.com/Joker/jade) |
| 5 | Handlebars | [aymerick/raymond](https://github.com/aymerick/raymond) |
| 6 | Amber | [eknkc/amber](https://github.com/eknkc/amber) |
| 7 | Jet | [CloudyKit/jet](https://github.com/CloudyKit/jet) |
| 8 | Ace | [yosssi/ace](https://github.com/yosssi/ace) |
## Examples
@@ -24,6 +27,8 @@ like Layout, Template Funcs, Party-specific layout, partial rendering and more.
- [The `url` tmpl func](https://github.com/kataras/iris/blob/master/_examples/view/template_html_4/main.go)
- [Inject Data Between Handlers](https://github.com/kataras/iris/blob/master/_examples/view/context-view-data/main.go)
- [Embedding Templates Into App Executable File](https://github.com/kataras/iris/blob/master/_examples/view/embedding-templates-into-app/main.go)
- [Blocks](https://github.com/kataras/iris/blob/master/_examples/view/template_blocks_0)
- [Blocks Embedded](https://github.com/kataras/iris/blob/master/_examples/view/template_blocks_1_embedded)
- [Greeting with Pug (Jade)`](view/template_pug_0)
- [Pug (Jade) Actions`](https://github.com/kataras/iris/blob/master/_examples/view/template_pug_1)
- [Pug (Jade) Includes`](https://github.com/kataras/iris/blob/master/_examples/view/template_pug_2)
@@ -32,7 +37,7 @@ like Layout, Template Funcs, Party-specific layout, partial rendering and more.
- [Jet Embedded](https://github.com/kataras/iris/blob/master/_examples/view/template_jet_1_embedded)
- [Ace](https://github.com/kataras/iris/blob/master/_examples/view/template_ace_0)
You can serve [quicktemplate](https://github.com/valyala/quicktemplate) files too, simply by using the `context#ResponseWriter`, take a look at the [iris/_examples/view/quicktemplate](https://github.com/kataras/iris/tree/master/_examples/view/quicktemplate) example.
You can serve [quicktemplate](https://github.com/valyala/quicktemplate) files too, simply by using the `Context.ResponseWriter`, take a look at the [iris/_examples/view/quicktemplate](https://github.com/kataras/iris/tree/master/_examples/view/quicktemplate) example.
## Overview

View File

@@ -10,6 +10,7 @@ import (
// Ace returns a new ace view engine.
// It shares the same exactly logic with the
// html view engine, it uses the same exactly configuration.
// The given "extension" MUST begin with a dot.
//
// Read more about the Ace Go Parser: https://github.com/yosssi/ace
func Ace(directory, extension string) *HTMLEngine {

View File

@@ -29,6 +29,7 @@ type AmberEngine struct {
var _ Engine = (*AmberEngine)(nil)
// Amber creates and returns a new amber view engine.
// The given "extension" MUST begin with a dot.
func Amber(directory, extension string) *AmberEngine {
s := &AmberEngine{
directory: directory,

109
view/blocks.go Normal file
View File

@@ -0,0 +1,109 @@
package view
import (
"html/template"
"io"
"github.com/kataras/blocks"
)
// BlocksEngine is an Iris view engine adapter for the blocks view engine.
// The blocks engine is based on the html/template standard Go package.
//
// To initialize a fresh one use the `Blocks` function.
// To wrap an existing one use the `WrapBlocks` function.
//
// It contains the following four default template functions:
// - url "routename" parameters...
// - urlpath "routename" parameters...
// - tr "language" "key" arguments...
// - partial "template_name" data
//
// Read more at: https://github.com/kataras/blocks.
type BlocksEngine struct {
Engine *blocks.Blocks
}
var _ Engine = (*BlocksEngine)(nil)
// WrapBlocks wraps an initialized blocks engine and returns its Iris adapter.
// See `Blocks` package-level function too.
func WrapBlocks(v *blocks.Blocks) *BlocksEngine {
return &BlocksEngine{Engine: v}
}
// Blocks returns a new blocks view engine.
// The given "extension" MUST begin with a dot.
//
// See `WrapBlocks` package-level function too.
func Blocks(directory, extension string) *BlocksEngine {
return WrapBlocks(blocks.New(directory).Extension(extension))
}
// Ext returns empty ext as this template engine
// supports template blocks without file suffix.
// Note that, if more than one view engine is registered to a single
// Iris application then, this Blocks engine should be the last entry one.
func (s *BlocksEngine) Ext() string {
return ""
}
// AddFunc implements the `EngineFuncer` which is being used
// by the framework to add template functions like:
// - url func(routeName string, args ...string) string
// - urlpath func(routeName string, args ...string) string
// - tr func(lang, key string, args ...interface{}) string
func (s *BlocksEngine) AddFunc(funcName string, funcBody interface{}) *BlocksEngine {
s.Engine.Funcs(template.FuncMap{funcName: funcBody})
return s
}
// AddLayoutFunc adds a template function for templates that are marked as layouts.
func (s *BlocksEngine) AddLayoutFunc(funcName string, funcBody interface{}) *BlocksEngine {
s.Engine.LayoutFuncs(template.FuncMap{funcName: funcBody})
return s
}
// Binary sets the function which reads contents based on a filename
// and a function that returns all the filenames.
// These functions are used to parse the corresponding files into templates.
// You do not need to set them when the given "rootDir" was a system directory.
// It's mostly useful when the application contains embedded template files,
// e.g. pass go-bindata's `Asset` and `AssetNames` functions
// to load templates from go-bindata generated content.
func (s *BlocksEngine) Binary(asset blocks.AssetFunc, assetNames blocks.AssetNamesFunc) *BlocksEngine {
s.Engine.Assets(asset, assetNames)
return s
}
// Layout sets the default layout which inside should use
// the {{ template "content" . }} to render the main template.
//
// Example for ./views/layouts/main.html:
// Blocks("./views", ".html").Layout("layouts/main")
func (s *BlocksEngine) Layout(layoutName string) *BlocksEngine {
s.Engine.DefaultLayout(layoutName)
return s
}
// Reload if called with a true parameter,
// each `ExecuteWriter` call will re-parse the templates.
// Useful when the application is at a development stage.
func (s *BlocksEngine) Reload(b bool) *BlocksEngine {
s.Engine.Reload(b)
return s
}
// Load parses the files into templates.
func (s *BlocksEngine) Load() error {
return s.Engine.Load()
}
// ExecuteWriter renders a template on "w".
func (s *BlocksEngine) ExecuteWriter(w io.Writer, tmplName, layoutName string, data interface{}) error {
if layoutName == NoLayout {
layoutName = ""
}
return s.Engine.ExecuteTemplate(w, tmplName, layoutName, data)
}

View File

@@ -108,7 +108,8 @@ type DjangoEngine struct {
var _ Engine = (*DjangoEngine)(nil)
// Django creates and returns a new amber view engine.
// Django creates and returns a new django view engine.
// The given "extension" MUST begin with a dot.
func Django(directory, extension string) *DjangoEngine {
s := &DjangoEngine{
directory: directory,

View File

@@ -30,6 +30,7 @@ type HandlebarsEngine struct {
var _ Engine = (*HandlebarsEngine)(nil)
// Handlebars creates and returns a new handlebars view engine.
// The given "extension" MUST begin with a dot.
func Handlebars(directory, extension string) *HandlebarsEngine {
s := &HandlebarsEngine{
directory: directory,

View File

@@ -61,6 +61,7 @@ var emptyFuncs = template.FuncMap{
// HTML creates and returns a new html view engine.
// The html engine used like the "html/template" standard go package
// but with a lot of extra features.
// The given "extension" MUST begin with a dot.
func HTML(directory, extension string) *HTMLEngine {
s := &HTMLEngine{
directory: directory,
@@ -173,6 +174,7 @@ func (s *HTMLEngine) AddLayoutFunc(funcName string, funcBody interface{}) *HTMLE
// - url func(routeName string, args ...string) string
// - urlpath func(routeName string, args ...string) string
// - render func(fullPartialName string) (template.HTML, error).
// - tr func(lang, key string, args ...interface{}) string
func (s *HTMLEngine) AddFunc(funcName string, funcBody interface{}) *HTMLEngine {
s.rmu.Lock()
s.funcs[funcName] = funcBody
@@ -206,7 +208,7 @@ func (s *HTMLEngine) Funcs(funcMap template.FuncMap) *HTMLEngine {
// Load parses the templates to the engine.
// It's also responsible to add the necessary global functions.
//
// Returns an error if something bad happens, user is responsible to catch it.
// Returns an error if something bad happens, caller is responsible to handle that.
func (s *HTMLEngine) Load() error {
// No need to make this with a complicated and "pro" way, just add lockers to the `ExecuteWriter`.
// if `Reload(true)` and add a note for non conc access on dev mode.
@@ -500,6 +502,12 @@ func (s *HTMLEngine) ExecuteWriter(w io.Writer, name string, layout string, bind
}
}
t := s.Templates.Lookup(name)
if t == nil {
return fmt.Errorf("template: %s does not exist in the dir: %s", name, s.directory)
}
s.runtimeFuncsFor(t, name, bindingData)
if layout = getLayout(layout, s.layout); layout != "" {
lt := s.Templates.Lookup(layout)
if lt == nil {
@@ -510,11 +518,5 @@ func (s *HTMLEngine) ExecuteWriter(w io.Writer, name string, layout string, bind
return lt.Execute(w, bindingData)
}
t := s.Templates.Lookup(name)
if t == nil {
return fmt.Errorf("template: %s does not exist in the dir: %s", name, s.directory)
}
s.runtimeFuncsFor(t, name, bindingData)
return t.Execute(w, bindingData)
}

View File

@@ -47,6 +47,7 @@ var jetExtensions = [...]string{
}
// Jet creates and returns a new jet view engine.
// The given "extension" MUST begin with a dot.
func Jet(directory, extension string) *JetEngine {
// if _, err := os.Stat(directory); os.IsNotExist(err) {
// panic(err)

View File

@@ -12,6 +12,7 @@ import (
// Pug (or Jade) returns a new pug view engine.
// It shares the same exactly logic with the
// html view engine, it uses the same exactly configuration.
// The given "extension" MUST begin with a dot.
//
// Read more about the Jade Go Parser: https://github.com/Joker/jade
//