mirror of
https://github.com/kataras/iris.git
synced 2025-03-14 08:16:28 +01:00
Developers can ignore this update. Replace the template engines with a new cross-framework package (kataras/go-template)
This commit is contained in:
parent
6163726bc5
commit
c38a9b2459
|
@ -2,7 +2,13 @@
|
||||||
|
|
||||||
**How to upgrade**: remove your `$GOPATH/src/github.com/kataras/iris` folder, open your command-line and execute this command: `go get -u github.com/kataras/iris/iris`.
|
**How to upgrade**: remove your `$GOPATH/src/github.com/kataras/iris` folder, open your command-line and execute this command: `go get -u github.com/kataras/iris/iris`.
|
||||||
|
|
||||||
## 4.1.1 -> 4.1.2
|
## 4.1.2 -> 4.1.3
|
||||||
|
|
||||||
|
Zero front-end changes. No real improvements, developers can ignore this update.
|
||||||
|
|
||||||
|
- Replace the template engines with a new cross-framework package, [go-template](https://github.com/kataras/go-websocket). Same front-end API, examples and iris-contrib/template are compatible.
|
||||||
|
|
||||||
|
## 4.1.1 -> 4.1.2
|
||||||
|
|
||||||
Zero front-end changes. No real improvements, developers can ignore this update.
|
Zero front-end changes. No real improvements, developers can ignore this update.
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
<a href="https://github.com/kataras/iris/blob/master/LICENSE"><img src="https://img.shields.io/badge/%20license-MIT%20%20License%20-E91E63.svg?style=flat-square" alt="License"></a>
|
<a href="https://github.com/kataras/iris/blob/master/LICENSE"><img src="https://img.shields.io/badge/%20license-MIT%20%20License%20-E91E63.svg?style=flat-square" alt="License"></a>
|
||||||
|
|
||||||
<a href="https://github.com/kataras/iris/releases"><img src="https://img.shields.io/badge/%20release%20-%20v4.1.2%20-blue.svg?style=flat-square" alt="Releases"></a>
|
<a href="https://github.com/kataras/iris/releases"><img src="https://img.shields.io/badge/%20release%20-%20v4.1.3%20-blue.svg?style=flat-square" alt="Releases"></a>
|
||||||
|
|
||||||
<a href="https://www.gitbook.com/book/kataras/iris/details"><img src="https://img.shields.io/badge/%20docs-reference-5272B4.svg?style=flat-square" alt="Practical Guide/Docs"></a><br/>
|
<a href="https://www.gitbook.com/book/kataras/iris/details"><img src="https://img.shields.io/badge/%20docs-reference-5272B4.svg?style=flat-square" alt="Practical Guide/Docs"></a><br/>
|
||||||
|
|
||||||
|
@ -113,10 +113,11 @@ go-* packages
|
||||||
|
|
||||||
| Name | Description
|
| Name | Description
|
||||||
| ------------------|:---------------------:|
|
| ------------------|:---------------------:|
|
||||||
|
| [go-template](https://github.com/kataras/go-template) | Cross-framework template engines
|
||||||
|
| [go-websocket](https://github.com/kataras/go-errors) | A websocket server and ,optionally, client side lib for Go
|
||||||
| [go-errors](https://github.com/kataras/go-errors) | Error handling
|
| [go-errors](https://github.com/kataras/go-errors) | Error handling
|
||||||
| [go-fs](https://github.com/kataras/go-fs) | FileSystem utils and common net/http static files handlers
|
| [go-fs](https://github.com/kataras/go-fs) | FileSystem utils and common net/http static files handlers
|
||||||
| [go-events](https://github.com/kataras/go-events) | EventEmmiter for Go
|
| [go-events](https://github.com/kataras/go-events) | EventEmmiter for Go
|
||||||
| [go-websocket](https://github.com/kataras/go-errors) | A websocket server and ,optionally, client side lib for Go
|
|
||||||
| [go-ssh](https://github.com/kataras/go-ssh) | SSH Server, build ssh interfaces, remote commands and remote cli with ease
|
| [go-ssh](https://github.com/kataras/go-ssh) | SSH Server, build ssh interfaces, remote commands and remote cli with ease
|
||||||
| [go-gzipwriter](https://github.com/kataras/go-gzipwriter) | Write gzip data to a io.Writer
|
| [go-gzipwriter](https://github.com/kataras/go-gzipwriter) | Write gzip data to a io.Writer
|
||||||
| [go-mailer](https://github.com/kataras/go-mailer) | E-mail Sender, send rich mails with one call
|
| [go-mailer](https://github.com/kataras/go-mailer) | E-mail Sender, send rich mails with one call
|
||||||
|
@ -159,7 +160,7 @@ I recommend writing your API tests using this new library, [httpexpect](https://
|
||||||
Versioning
|
Versioning
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Current: **v4.1.2**
|
Current: **v4.1.3**
|
||||||
|
|
||||||
> Iris is an active project
|
> Iris is an active project
|
||||||
|
|
||||||
|
@ -194,7 +195,7 @@ License can be found [here](LICENSE).
|
||||||
[Travis]: http://travis-ci.org/kataras/iris
|
[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 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
|
[License]: https://github.com/kataras/iris/blob/master/LICENSE
|
||||||
[Release Widget]: https://img.shields.io/badge/release-v4.1.2-blue.svg?style=flat-square
|
[Release Widget]: https://img.shields.io/badge/release-v4.1.3-blue.svg?style=flat-square
|
||||||
[Release]: https://github.com/kataras/iris/releases
|
[Release]: https://github.com/kataras/iris/releases
|
||||||
[Chat Widget]: https://img.shields.io/badge/community-chat-00BCD4.svg?style=flat-square
|
[Chat Widget]: https://img.shields.io/badge/community-chat-00BCD4.svg?style=flat-square
|
||||||
[Chat]: https://kataras.rocket.chat/channel/iris
|
[Chat]: https://kataras.rocket.chat/channel/iris
|
||||||
|
|
|
@ -546,7 +546,7 @@ func (ctx *Context) Gzip(b []byte, status int) {
|
||||||
func (ctx *Context) RenderWithStatus(status int, name string, binding interface{}, options ...map[string]interface{}) error {
|
func (ctx *Context) RenderWithStatus(status int, name string, binding interface{}, options ...map[string]interface{}) error {
|
||||||
ctx.SetStatusCode(status)
|
ctx.SetStatusCode(status)
|
||||||
if strings.IndexByte(name, '.') > -1 { //we have template
|
if strings.IndexByte(name, '.') > -1 { //we have template
|
||||||
return ctx.framework.templates.getBy(name).execute(ctx, name, binding, options...)
|
return ctx.framework.templates.render(ctx, name, binding, options...)
|
||||||
}
|
}
|
||||||
return ctx.framework.responses.getBy(name).render(ctx, binding, options...)
|
return ctx.framework.responses.getBy(name).render(ctx, binding, options...)
|
||||||
}
|
}
|
||||||
|
|
31
iris.go
31
iris.go
|
@ -78,6 +78,7 @@ import (
|
||||||
"github.com/iris-contrib/template/html"
|
"github.com/iris-contrib/template/html"
|
||||||
"github.com/kataras/go-errors"
|
"github.com/kataras/go-errors"
|
||||||
"github.com/kataras/go-fs"
|
"github.com/kataras/go-fs"
|
||||||
|
"github.com/kataras/go-template"
|
||||||
"github.com/kataras/iris/config"
|
"github.com/kataras/iris/config"
|
||||||
"github.com/kataras/iris/context"
|
"github.com/kataras/iris/context"
|
||||||
"github.com/kataras/iris/utils"
|
"github.com/kataras/iris/utils"
|
||||||
|
@ -86,7 +87,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Version of the iris
|
// Version of the iris
|
||||||
Version = "4.1.2"
|
Version = "4.1.3"
|
||||||
|
|
||||||
banner = ` _____ _
|
banner = ` _____ _
|
||||||
|_ _| (_)
|
|_ _| (_)
|
||||||
|
@ -155,7 +156,7 @@ type (
|
||||||
Close() error
|
Close() error
|
||||||
UseSessionDB(SessionDatabase)
|
UseSessionDB(SessionDatabase)
|
||||||
UseResponse(ResponseEngine, ...string) func(string)
|
UseResponse(ResponseEngine, ...string) func(string)
|
||||||
UseTemplate(TemplateEngine) *TemplateEngineLocation
|
UseTemplate(template.Engine) *template.Loader
|
||||||
UseGlobal(...Handler)
|
UseGlobal(...Handler)
|
||||||
UseGlobalFunc(...HandlerFunc)
|
UseGlobalFunc(...HandlerFunc)
|
||||||
Lookup(string) Route
|
Lookup(string) Route
|
||||||
|
@ -216,13 +217,10 @@ func New(cfg ...config.Iris) *Framework {
|
||||||
// set the plugin container
|
// set the plugin container
|
||||||
s.Plugins = &pluginContainer{logger: s.Logger}
|
s.Plugins = &pluginContainer{logger: s.Logger}
|
||||||
// set the templates
|
// set the templates
|
||||||
s.templates = &templateEngines{
|
s.templates = newTemplateEngines(map[string]interface{}{
|
||||||
helpers: map[string]interface{}{
|
"url": s.URL,
|
||||||
"url": s.URL,
|
"urlpath": s.Path,
|
||||||
"urlpath": s.Path,
|
})
|
||||||
},
|
|
||||||
engines: make([]*templateEngineWrapper, 0),
|
|
||||||
}
|
|
||||||
// set the sessions
|
// set the sessions
|
||||||
if s.Config.Sessions.Cookie != "" {
|
if s.Config.Sessions.Cookie != "" {
|
||||||
//set the session manager
|
//set the session manager
|
||||||
|
@ -270,13 +268,13 @@ func (s *Framework) initialize() {
|
||||||
// prepare the templates if enabled
|
// prepare the templates if enabled
|
||||||
if !s.Config.DisableTemplateEngines {
|
if !s.Config.DisableTemplateEngines {
|
||||||
|
|
||||||
s.templates.reload = s.Config.IsDevelopment
|
s.templates.Reload = s.Config.IsDevelopment
|
||||||
// check and prepare the templates
|
// check and prepare the templates
|
||||||
if len(s.templates.engines) == 0 { // no template engine is registered, let's use the default
|
if len(s.templates.Entries) == 0 { // no template engine is registered, let's use the default
|
||||||
s.UseTemplate(html.New())
|
s.UseTemplate(html.New())
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.templates.loadAll(); err != nil {
|
if err := s.templates.Load(); err != nil {
|
||||||
s.Logger.Panic(err) // panic on templates loading before listening if we have an error.
|
s.Logger.Panic(err) // panic on templates loading before listening if we have an error.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -661,14 +659,14 @@ func (s *Framework) UseResponse(e ResponseEngine, forContentTypesOrKeys ...strin
|
||||||
|
|
||||||
// UseTemplate adds a template engine to the iris view system
|
// UseTemplate adds a template engine to the iris view system
|
||||||
// it does not build/load them yet
|
// it does not build/load them yet
|
||||||
func UseTemplate(e TemplateEngine) *TemplateEngineLocation {
|
func UseTemplate(e template.Engine) *template.Loader {
|
||||||
return Default.UseTemplate(e)
|
return Default.UseTemplate(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseTemplate adds a template engine to the iris view system
|
// UseTemplate adds a template engine to the iris view system
|
||||||
// it does not build/load them yet
|
// it does not build/load them yet
|
||||||
func (s *Framework) UseTemplate(e TemplateEngine) *TemplateEngineLocation {
|
func (s *Framework) UseTemplate(e template.Engine) *template.Loader {
|
||||||
return s.templates.add(e)
|
return s.templates.AddEngine(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseGlobal registers Handler middleware to the beginning, prepends them instead of append
|
// UseGlobal registers Handler middleware to the beginning, prepends them instead of append
|
||||||
|
@ -938,7 +936,8 @@ func (s *Framework) TemplateString(templateFile string, pageContext interface{},
|
||||||
if s.Config.DisableTemplateEngines {
|
if s.Config.DisableTemplateEngines {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
res, err := s.templates.getBy(templateFile).executeToString(templateFile, pageContext, options...)
|
|
||||||
|
res, err := s.templates.ExecuteString(templateFile, pageContext, options...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
|
|
||||||
"github.com/kataras/cli"
|
"github.com/kataras/cli"
|
||||||
"github.com/kataras/go-fs"
|
"github.com/kataras/go-fs"
|
||||||
"github.com/kataras/go-installer"
|
|
||||||
"github.com/kataras/iris/utils"
|
"github.com/kataras/iris/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -86,7 +85,7 @@ func create(flags cli.Flags) (err error) {
|
||||||
func downloadPackages() {
|
func downloadPackages() {
|
||||||
errMsg := "\nProblem while downloading the assets from the internet for the first time. Trace: %s"
|
errMsg := "\nProblem while downloading the assets from the internet for the first time. Trace: %s"
|
||||||
|
|
||||||
installedDir, err := installer.Install(PackagesURL, packagesInstallDir, true)
|
installedDir, err := fs.Install(PackagesURL, packagesInstallDir, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printer.Dangerf(errMsg, err.Error())
|
printer.Dangerf(errMsg, err.Error())
|
||||||
return
|
return
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
|
|
||||||
"github.com/iris-contrib/logger"
|
"github.com/iris-contrib/logger"
|
||||||
"github.com/kataras/go-fs"
|
"github.com/kataras/go-fs"
|
||||||
"github.com/kataras/go-installer"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -205,12 +204,12 @@ func (d *pluginDownloadManager) DirectoryExists(dir string) bool {
|
||||||
|
|
||||||
// DownloadZip downlodas a zip to the given local path location
|
// DownloadZip downlodas a zip to the given local path location
|
||||||
func (d *pluginDownloadManager) DownloadZip(zipURL string, targetDir string) (string, error) {
|
func (d *pluginDownloadManager) DownloadZip(zipURL string, targetDir string) (string, error) {
|
||||||
return installer.DownloadZip(zipURL, targetDir, true)
|
return fs.DownloadZip(zipURL, targetDir, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unzip unzips a zip to the given local path location
|
// Unzip unzips a zip to the given local path location
|
||||||
func (d *pluginDownloadManager) Unzip(archive string, target string) (string, error) {
|
func (d *pluginDownloadManager) Unzip(archive string, target string) (string, error) {
|
||||||
return installer.DownloadZip(archive, target, true)
|
return fs.DownloadZip(archive, target, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove deletes/removes/rm a file
|
// Remove deletes/removes/rm a file
|
||||||
|
@ -220,7 +219,7 @@ func (d *pluginDownloadManager) Remove(filePath string) error {
|
||||||
|
|
||||||
// Install is just the flow of the: DownloadZip->Unzip->Remove the zip
|
// Install is just the flow of the: DownloadZip->Unzip->Remove the zip
|
||||||
func (d *pluginDownloadManager) Install(remoteFileZip string, targetDirectory string) (string, error) {
|
func (d *pluginDownloadManager) Install(remoteFileZip string, targetDirectory string) (string, error) {
|
||||||
return installer.Install(remoteFileZip, targetDirectory, true)
|
return fs.Install(remoteFileZip, targetDirectory, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pluginContainer is the base container of all Iris, registed plugins
|
// pluginContainer is the base container of all Iris, registed plugins
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/kataras/go-errors"
|
"github.com/kataras/go-errors"
|
||||||
|
"github.com/kataras/go-template"
|
||||||
"github.com/valyala/fasthttp"
|
"github.com/valyala/fasthttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -139,10 +140,8 @@ func (r *responseEngineMap) render(ctx *Context, obj interface{}, options ...map
|
||||||
gzipEnabled := ctx.framework.Config.Gzip
|
gzipEnabled := ctx.framework.Config.Gzip
|
||||||
charset := ctx.framework.Config.Charset
|
charset := ctx.framework.Config.Charset
|
||||||
if len(options) > 0 {
|
if len(options) > 0 {
|
||||||
gzipEnabled = getGzipOption(ctx, options[0]) // located to the template.go below the RenderOptions
|
gzipEnabled = template.GetGzipOption(gzipEnabled, options[0]) // located to the template.go below the RenderOptions
|
||||||
if chs := getCharsetOption(options[0]); chs != "" {
|
charset = template.GetCharsetOption(charset, options[0])
|
||||||
charset = chs
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ctype := r.contentType
|
ctype := r.contentType
|
||||||
|
|
||||||
|
|
250
template.go
250
template.go
|
@ -1,192 +1,49 @@
|
||||||
package iris
|
package iris
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/kataras/go-template"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/kataras/go-errors"
|
|
||||||
"github.com/kataras/iris/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
builtinFuncs = [...]string{"url", "urlpath"}
|
builtinFuncs = [...]string{"url", "urlpath"}
|
||||||
|
|
||||||
// DefaultTemplateDirectory the default directory if empty setted
|
|
||||||
DefaultTemplateDirectory = "." + utils.PathSeparator + "templates"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
||||||
// DefaultTemplateExtension the default file extension if empty setted
|
|
||||||
DefaultTemplateExtension = ".html"
|
|
||||||
// NoLayout to disable layout for a particular template file
|
// NoLayout to disable layout for a particular template file
|
||||||
NoLayout = "@.|.@iris_no_layout@.|.@"
|
NoLayout = template.NoLayout
|
||||||
// TemplateLayoutContextKey is the name of the user values which can be used to set a template layout from a middleware and override the parent's
|
// TemplateLayoutContextKey is the name of the user values which can be used to set a template layout from a middleware and override the parent's
|
||||||
TemplateLayoutContextKey = "templateLayout"
|
TemplateLayoutContextKey = "templateLayout"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// TemplateEngine the interface that all template engines must implement
|
|
||||||
TemplateEngine interface {
|
|
||||||
// LoadDirectory builds the templates, usually by directory and extension but these are engine's decisions
|
|
||||||
LoadDirectory(directory string, extension string) error
|
|
||||||
// LoadAssets loads the templates by binary
|
|
||||||
// assetFn is a func which returns bytes, use it to load the templates by binary
|
|
||||||
// namesFn returns the template filenames
|
|
||||||
LoadAssets(virtualDirectory string, virtualExtension string, assetFn func(name string) ([]byte, error), namesFn func() []string) error
|
|
||||||
|
|
||||||
// ExecuteWriter finds, execute a template and write its result to the out writer
|
|
||||||
// options are the optional runtime options can be passed by user and catched by the template engine when render
|
|
||||||
// an example of this is the "layout" or "gzip" option
|
|
||||||
ExecuteWriter(out io.Writer, name string, binding interface{}, options ...map[string]interface{}) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// TemplateEngineFuncs is optional interface for the TemplateEngine
|
|
||||||
// used to insert the Iris' standard funcs, see var 'usedFuncs'
|
|
||||||
TemplateEngineFuncs interface {
|
|
||||||
// Funcs should returns the context or the funcs,
|
|
||||||
// this property is used in order to register the iris' helper funcs
|
|
||||||
Funcs() map[string]interface{}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
// TemplateFuncs is is a helper type for map[string]interface{}
|
|
||||||
TemplateFuncs map[string]interface{}
|
|
||||||
// RenderOptions is a helper type for the optional runtime options can be passed by user when Render
|
// RenderOptions is a helper type for the optional runtime options can be passed by user when Render
|
||||||
// an example of this is the "layout" or "gzip" option
|
// an example of this is the "layout" or "gzip" option
|
||||||
// same as Map but more specific name
|
// same as Map but more specific name
|
||||||
RenderOptions map[string]interface{}
|
RenderOptions map[string]interface{}
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsFree returns true if a function can be inserted to this map
|
// templateEngines just a wrapper of template.Mux in order to use it's execute without break the whole of the API
|
||||||
// return false if this key is already used by Iris
|
type templateEngines struct {
|
||||||
func (t TemplateFuncs) IsFree(key string) bool {
|
*template.Mux
|
||||||
for i := range builtinFuncs {
|
|
||||||
if builtinFuncs[i] == key {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getGzipOption(ctx *Context, options map[string]interface{}) bool {
|
func newTemplateEngines(sharedFuncs map[string]interface{}) *templateEngines {
|
||||||
gzipOpt := options["gzip"] // we only need that, so don't create new map to keep the options.
|
return &templateEngines{Mux: template.NewMux(sharedFuncs)}
|
||||||
if b, isBool := gzipOpt.(bool); isBool {
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
return ctx.framework.Config.Gzip
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCharsetOption(options map[string]interface{}) string {
|
// render executes a template and write its result to the context's body
|
||||||
charsetOpt := options["charset"]
|
|
||||||
if s, isString := charsetOpt.(string); isString {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
return "" // we return empty in order to set the default charset if not founded.
|
|
||||||
}
|
|
||||||
|
|
||||||
type (
|
|
||||||
// TemplateEngineLocation contains the funcs to set the location for the templates by directory or by binary
|
|
||||||
TemplateEngineLocation struct {
|
|
||||||
directory string
|
|
||||||
extension string
|
|
||||||
assetFn func(name string) ([]byte, error)
|
|
||||||
namesFn func() []string
|
|
||||||
}
|
|
||||||
// TemplateEngineBinaryLocation called after TemplateEngineLocation's Directory, used when files are distrubuted inside the app executable
|
|
||||||
TemplateEngineBinaryLocation struct {
|
|
||||||
location *TemplateEngineLocation
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Directory sets the directory to load from
|
|
||||||
// returns the Binary location which is optional
|
|
||||||
func (t *TemplateEngineLocation) Directory(dir string, fileExtension string) *TemplateEngineBinaryLocation {
|
|
||||||
if dir == "" {
|
|
||||||
dir = DefaultTemplateDirectory // the default templates dir
|
|
||||||
}
|
|
||||||
if fileExtension == "" {
|
|
||||||
fileExtension = DefaultTemplateExtension
|
|
||||||
} else if fileExtension[0] != '.' { // if missing the start dot
|
|
||||||
fileExtension = "." + fileExtension
|
|
||||||
}
|
|
||||||
|
|
||||||
t.directory = dir
|
|
||||||
t.extension = fileExtension
|
|
||||||
return &TemplateEngineBinaryLocation{location: t}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Binary sets the asset(s) and asssets names to load from, works with Directory
|
|
||||||
func (t *TemplateEngineBinaryLocation) Binary(assetFn func(name string) ([]byte, error), namesFn func() []string) {
|
|
||||||
if assetFn == nil || namesFn == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
t.location.assetFn = assetFn
|
|
||||||
t.location.namesFn = namesFn
|
|
||||||
// if extension is not static(setted by .Directory)
|
|
||||||
if t.location.extension == "" {
|
|
||||||
if names := namesFn(); len(names) > 0 {
|
|
||||||
t.location.extension = filepath.Ext(names[0]) // we need the extension to get the correct template engine on the Render method
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TemplateEngineLocation) isBinary() bool {
|
|
||||||
return t.assetFn != nil && t.namesFn != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// templateEngineWrapper is the wrapper of a template engine
|
|
||||||
type templateEngineWrapper struct {
|
|
||||||
TemplateEngine
|
|
||||||
location *TemplateEngineLocation
|
|
||||||
buffer *utils.BufferPool
|
|
||||||
reload bool
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
errMissingDirectoryOrAssets = errors.New("Missing Directory or Assets by binary for the template engine!")
|
|
||||||
errNoTemplateEngineForExt = errors.New("No template engine found to manage '%s' extensions")
|
|
||||||
)
|
|
||||||
|
|
||||||
func (t *templateEngineWrapper) load() error {
|
|
||||||
if t.location.isBinary() {
|
|
||||||
t.LoadAssets(t.location.directory, t.location.extension, t.location.assetFn, t.location.namesFn)
|
|
||||||
} else if t.location.directory != "" {
|
|
||||||
t.LoadDirectory(t.location.directory, t.location.extension)
|
|
||||||
} else {
|
|
||||||
return errMissingDirectoryOrAssets
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// execute execute a template and write its result to the context's body
|
|
||||||
// options are the optional runtime options can be passed by user and catched by the template engine when render
|
// options are the optional runtime options can be passed by user and catched by the template engine when render
|
||||||
// an example of this is the "layout"
|
// an example of this is the "layout"
|
||||||
// note that gzip option is an iris dynamic option which exists for all template engines
|
// note that gzip option is an iris dynamic option which exists for all template engines
|
||||||
// the gzip and charset options are built'n with iris
|
// the gzip and charset options are built'n with iris
|
||||||
func (t *templateEngineWrapper) execute(ctx *Context, filename string, binding interface{}, options ...map[string]interface{}) (err error) {
|
func (t *templateEngines) render(ctx *Context, filename string, binding interface{}, options ...map[string]interface{}) (err error) {
|
||||||
if t == nil {
|
|
||||||
//file extension, but no template engine registered, this caused by context, and templateEngines. getBy
|
|
||||||
return errNoTemplateEngineForExt.Format(filepath.Ext(filename))
|
|
||||||
}
|
|
||||||
if t.reload {
|
|
||||||
if err = t.load(); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// we do all these because we don't want to initialize a new map for each execution...
|
// we do all these because we don't want to initialize a new map for each execution...
|
||||||
gzipEnabled := ctx.framework.Config.Gzip
|
gzipEnabled := ctx.framework.Config.Gzip
|
||||||
charset := ctx.framework.Config.Charset
|
charset := ctx.framework.Config.Charset
|
||||||
if len(options) > 0 {
|
if len(options) > 0 {
|
||||||
gzipEnabled = getGzipOption(ctx, options[0])
|
gzipEnabled = template.GetGzipOption(gzipEnabled, options[0])
|
||||||
|
charset = template.GetCharsetOption(charset, options[0])
|
||||||
if chs := getCharsetOption(options[0]); chs != "" {
|
|
||||||
charset = chs
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxLayout := ctx.GetString(TemplateLayoutContextKey)
|
ctxLayout := ctx.GetString(TemplateLayoutContextKey)
|
||||||
|
@ -215,88 +72,3 @@ func (t *templateEngineWrapper) execute(ctx *Context, filename string, binding i
|
||||||
err = t.ExecuteWriter(out, filename, binding, options...)
|
err = t.ExecuteWriter(out, filename, binding, options...)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// executeToString executes a template from a specific template engine and returns its contents result as string, it doesn't renders
|
|
||||||
func (t *templateEngineWrapper) executeToString(filename string, binding interface{}, opt ...map[string]interface{}) (result string, err error) {
|
|
||||||
if t == nil {
|
|
||||||
//file extension, but no template engine registered, this caused by context, and templateEngines. getBy
|
|
||||||
return "", errNoTemplateEngineForExt.Format(filepath.Ext(filename))
|
|
||||||
}
|
|
||||||
if t.reload {
|
|
||||||
if err = t.load(); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out := t.buffer.Get()
|
|
||||||
defer t.buffer.Put(out)
|
|
||||||
err = t.ExecuteWriter(out, filename, binding, opt...)
|
|
||||||
if err == nil {
|
|
||||||
result = out.String()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// templateEngines is the container and manager of the template engines
|
|
||||||
type templateEngines struct {
|
|
||||||
helpers map[string]interface{}
|
|
||||||
engines []*templateEngineWrapper
|
|
||||||
reload bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// getBy receives a filename, gets its extension and returns the template engine responsible for that file extension
|
|
||||||
func (t *templateEngines) getBy(filename string) *templateEngineWrapper {
|
|
||||||
extension := filepath.Ext(filename)
|
|
||||||
for i, n := 0, len(t.engines); i < n; i++ {
|
|
||||||
e := t.engines[i]
|
|
||||||
|
|
||||||
if e.location.extension == extension {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// add adds but not loads a template engine
|
|
||||||
func (t *templateEngines) add(e TemplateEngine) *TemplateEngineLocation {
|
|
||||||
location := &TemplateEngineLocation{}
|
|
||||||
// add the iris helper funcs
|
|
||||||
if funcer, ok := e.(TemplateEngineFuncs); ok {
|
|
||||||
if funcer.Funcs() != nil {
|
|
||||||
for k, v := range t.helpers {
|
|
||||||
funcer.Funcs()[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tmplEngine := &templateEngineWrapper{
|
|
||||||
TemplateEngine: e,
|
|
||||||
location: location,
|
|
||||||
buffer: utils.NewBufferPool(8),
|
|
||||||
reload: t.reload,
|
|
||||||
}
|
|
||||||
|
|
||||||
t.engines = append(t.engines, tmplEngine)
|
|
||||||
return location
|
|
||||||
}
|
|
||||||
|
|
||||||
// loadAll loads all templates using all template engines, returns the first error
|
|
||||||
// called on iris' initialize
|
|
||||||
func (t *templateEngines) loadAll() error {
|
|
||||||
for i, n := 0, len(t.engines); i < n; i++ {
|
|
||||||
e := t.engines[i]
|
|
||||||
if e.location.directory == "" {
|
|
||||||
e.location.directory = DefaultTemplateDirectory // the defualt dir ./templates
|
|
||||||
}
|
|
||||||
if e.location.extension == "" {
|
|
||||||
e.location.extension = DefaultTemplateExtension // the default file ext .html
|
|
||||||
}
|
|
||||||
|
|
||||||
e.reload = t.reload // update the configuration every time a load happens
|
|
||||||
|
|
||||||
if err := e.load(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user