mirror of
https://github.com/kataras/iris.git
synced 2025-02-09 18:46:19 +01:00
Former-commit-id: 221e01638b671586cdab2b84518bd6a1c8d07bda
This commit is contained in:
parent
eb29a80753
commit
b7bc89335d
|
@ -12,7 +12,8 @@ import (
|
||||||
// tested with redis version 3.0.503.
|
// tested with redis version 3.0.503.
|
||||||
// for windows see: https://github.com/ServiceStack/redis-windows
|
// for windows see: https://github.com/ServiceStack/redis-windows
|
||||||
func main() {
|
func main() {
|
||||||
// replace with your running redis' server settings:
|
// These are the default values,
|
||||||
|
// you can replace them based on your running redis' server settings:
|
||||||
db := redis.New(redis.Config{
|
db := redis.New(redis.Config{
|
||||||
Network: "tcp",
|
Network: "tcp",
|
||||||
Addr: "127.0.0.1:6379",
|
Addr: "127.0.0.1:6379",
|
||||||
|
@ -25,14 +26,14 @@ func main() {
|
||||||
Driver: redis.Redigo(), // redis.Radix() can be used instead.
|
Driver: redis.Redigo(), // redis.Radix() can be used instead.
|
||||||
})
|
})
|
||||||
|
|
||||||
// optionally configure the underline driver:
|
// Optionally configure the underline driver:
|
||||||
// driver := redis.Redigo()
|
// driver := redis.Redigo()
|
||||||
// driver.MaxIdle = ...
|
// driver.MaxIdle = ...
|
||||||
// driver.IdleTimeout = ...
|
// driver.IdleTimeout = ...
|
||||||
// driver.Wait = ...
|
// driver.Wait = ...
|
||||||
// redis.Config {Driver: driver}
|
// redis.Config {Driver: driver}
|
||||||
|
|
||||||
// close connection when control+C/cmd+C
|
// Close connection when control+C/cmd+C
|
||||||
iris.RegisterOnInterrupt(func() {
|
iris.RegisterOnInterrupt(func() {
|
||||||
db.Close()
|
db.Close()
|
||||||
})
|
})
|
||||||
|
|
|
@ -114,10 +114,27 @@ func main() {
|
||||||
ctx.View("todos/show.jet", todo)
|
ctx.View("todos/show.jet", todo)
|
||||||
})
|
})
|
||||||
app.Get("/all-done", func(ctx iris.Context) {
|
app.Get("/all-done", func(ctx iris.Context) {
|
||||||
vars := make(view.JetRuntimeVars) // <-- or keep use the jet.VarMap, decision up to you, it refers to the same type.
|
// vars := make(view.JetRuntimeVars)
|
||||||
vars.Set("showingAllDone", true)
|
// vars.Set("showingAllDone", true)
|
||||||
view.AddJetRuntimeVars(ctx, vars) // <--
|
// vars.Set("title", "Todos - All Done")
|
||||||
ctx.View("todos/index.jet", (&doneTODOs{}).New(todos))
|
// view.AddJetRuntimeVars(ctx, vars)
|
||||||
|
// ctx.View("todos/index.jet", (&doneTODOs{}).New(todos))
|
||||||
|
//
|
||||||
|
// OR
|
||||||
|
|
||||||
|
ctx.ViewData("showingAllDone", true)
|
||||||
|
ctx.ViewData("title", "Todos - All Done")
|
||||||
|
|
||||||
|
// Key does not actual matters at all here.
|
||||||
|
// However, you can enable it for better performance.
|
||||||
|
// In order to enable key mapping for
|
||||||
|
// jet specific renderer and ranger types
|
||||||
|
// then initialize the View Engine
|
||||||
|
// by `tmpl.DisableViewDataTypeCheck("_jet")`.
|
||||||
|
//
|
||||||
|
// Defaults to type checks, empty key.
|
||||||
|
ctx.ViewData("_jet", (&doneTODOs{}).New(todos))
|
||||||
|
ctx.View("todos/index.jet")
|
||||||
})
|
})
|
||||||
|
|
||||||
port := os.Getenv("PORT")
|
port := os.Getenv("PORT")
|
||||||
|
|
|
@ -1018,8 +1018,8 @@ var Gzip = func(ctx Context) {
|
||||||
ctx.Next()
|
ctx.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map is just a shortcut of the map[string]interface{}.
|
// Map is just a type alias of the map[string]interface{} type.
|
||||||
type Map map[string]interface{}
|
type Map = map[string]interface{}
|
||||||
|
|
||||||
// +------------------------------------------------------------+
|
// +------------------------------------------------------------+
|
||||||
// | Context Implementation |
|
// | Context Implementation |
|
||||||
|
|
116
view/jet.go
116
view/jet.go
|
@ -31,6 +31,8 @@ type JetEngine struct {
|
||||||
// Note that global vars and functions are set in a single spot on the jet parser.
|
// Note that global vars and functions are set in a single spot on the jet parser.
|
||||||
// If AddFunc or AddVar called before `Load` then these will be set here to be used via `Load` and clear.
|
// If AddFunc or AddVar called before `Load` then these will be set here to be used via `Load` and clear.
|
||||||
vars map[string]interface{}
|
vars map[string]interface{}
|
||||||
|
|
||||||
|
jetRendererRangerContextKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Engine = (*JetEngine)(nil)
|
var _ Engine = (*JetEngine)(nil)
|
||||||
|
@ -66,6 +68,20 @@ func Jet(directory, extension string) *JetEngine {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DisableViewDataTypeCheck accepts a context key name to use
|
||||||
|
// to map the jet specific renderer and ranger over context's view data.
|
||||||
|
//
|
||||||
|
// If "jetDataContextKey" is not empty then `ExecuteWriter` will not check for
|
||||||
|
// types to check if an element passed through `Context.ViewData`
|
||||||
|
// contains a jet.Renderer or jet.Ranger or both.
|
||||||
|
// Instead will map those with simple key data naming (faster).
|
||||||
|
// Also it wont check if a value is already a reflect.Value (jet expects this type as values).
|
||||||
|
//
|
||||||
|
// Defaults to empty.
|
||||||
|
func (s *JetEngine) DisableViewDataTypeCheck(jetDataContextKey string) {
|
||||||
|
s.jetRendererRangerContextKey = jetDataContextKey
|
||||||
|
}
|
||||||
|
|
||||||
// String returns the name of this view engine, the "jet".
|
// String returns the name of this view engine, the "jet".
|
||||||
func (s *JetEngine) String() string {
|
func (s *JetEngine) String() string {
|
||||||
return jetEngineName
|
return jetEngineName
|
||||||
|
@ -358,7 +374,40 @@ func (rr rangerAndRenderer) Render(jetRuntime *jet.Runtime) {
|
||||||
rr.renderer.Render(jetRuntime)
|
rr.renderer.Render(jetRuntime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func rangerRenderer(bindingData interface{}) (interface{}, bool) {
|
||||||
|
if ranger, ok := bindingData.(jet.Ranger); ok {
|
||||||
|
// Externally fixes a BUG on the jet template parser:
|
||||||
|
// eval.go#executeList(list *ListNode):NodeRange.isSet.getRanger(expression = st.evalPrimaryExpressionGroup)
|
||||||
|
// which does not act the "ranger" as element, instead is converted to a value of struct, which makes a jet.Ranger func(*myStruct) Range...
|
||||||
|
// not a compatible jet.Ranger.
|
||||||
|
// getRanger(st.context) should work but author of the jet library is not currently available,
|
||||||
|
// to allow a recommentation or a PR and I don't really want to vendor it because
|
||||||
|
// some end-users may use the jet import path to pass things like Global Funcs and etc.
|
||||||
|
// So to fix it (at least temporarily and only for ref Ranger) we ptr the ptr the "ranger", not the bindingData, and this may
|
||||||
|
// have its downside because the same bindingData may be compatible with other node actions like range or custom Render
|
||||||
|
// but we have no other way at the moment. The same problem exists on the `Renderer` too!
|
||||||
|
// The solution below fixes the above issue but any fields of the struct are not available,
|
||||||
|
// this is ok because most of the times if not always, the users of jet don't use fields on Ranger and custom Renderer inside the templates.
|
||||||
|
|
||||||
|
if renderer, ok := bindingData.(jet.Renderer); ok {
|
||||||
|
// this can make a Ranger and Renderer both work together, unlike the jet parser itself.
|
||||||
|
return rangerAndRenderer{ranger, renderer}, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ranger, true
|
||||||
|
}
|
||||||
|
|
||||||
|
if renderer, ok := bindingData.(jet.Renderer); ok {
|
||||||
|
// Here the fields are not available but usually if completes the jet.Renderer no
|
||||||
|
// fields are used in the template.
|
||||||
|
return &renderer, true // see above ^.
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
// ExecuteWriter should execute a template by its filename with an optional layout and bindingData.
|
// ExecuteWriter should execute a template by its filename with an optional layout and bindingData.
|
||||||
|
// See `DisableViewDataTypeCheck` too.
|
||||||
func (s *JetEngine) ExecuteWriter(w io.Writer, filename string, layout string, bindingData interface{}) error {
|
func (s *JetEngine) ExecuteWriter(w io.Writer, filename string, layout string, bindingData interface{}) error {
|
||||||
tmpl, err := s.Set.GetTemplate(filename)
|
tmpl, err := s.Set.GetTemplate(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -376,32 +425,51 @@ func (s *JetEngine) ExecuteWriter(w io.Writer, filename string, layout string, b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ranger, ok := bindingData.(jet.Ranger); ok {
|
if bindingData == nil {
|
||||||
// Externally fixes a BUG on the jet template parser:
|
return tmpl.Execute(w, vars, nil)
|
||||||
// eval.go#executeList(list *ListNode):NodeRange.isSet.getRanger(expression = st.evalPrimaryExpressionGroup)
|
|
||||||
// which does not act the "ranger" as element, instead is converted to a value of struct, which makes a jet.Ranger func(*myStruct) Range...
|
|
||||||
// not a compatible jet.Ranger.
|
|
||||||
// getRanger(st.context) should work but author of the jet library is not currently available,
|
|
||||||
// to allow a recommentation or a PR and I don't really want to vendor it because
|
|
||||||
// some end-users may use the jet import path to pass things like Global Funcs and etc.
|
|
||||||
// So to fix it (at least temporarily and only for ref Ranger) we ptr the ptr the "ranger", not the bindingData, and this may
|
|
||||||
// have its downside because the same bindingData may be compatible with other node actions like range or custom Render
|
|
||||||
// but we have no other way at the moment. The same problem exists on the `Renderer` too!
|
|
||||||
// The solution below fixes the above issue but any fields of the struct are not available,
|
|
||||||
// this is ok because most of the times if not always, the users of jet don't use fields on Ranger and custom Renderer inside the templates.
|
|
||||||
|
|
||||||
if renderer, ok := bindingData.(jet.Renderer); ok {
|
|
||||||
// this can make a Ranger and Renderer both work together, unlike the jet parser itself.
|
|
||||||
return tmpl.Execute(w, vars, rangerAndRenderer{ranger, renderer})
|
|
||||||
}
|
|
||||||
|
|
||||||
return tmpl.Execute(w, vars, &ranger)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if renderer, ok := bindingData.(jet.Renderer); ok {
|
jetRangerRenderer, ok := rangerRenderer(bindingData)
|
||||||
// Here the fields are not available but usually if completes the jet.Renderer no
|
if ok {
|
||||||
// fields are used in the template.
|
return tmpl.Execute(w, vars, jetRangerRenderer)
|
||||||
return tmpl.Execute(w, vars, &renderer) // see above ^.
|
}
|
||||||
|
|
||||||
|
if m, ok := bindingData.(context.Map); ok {
|
||||||
|
for k, v := range m {
|
||||||
|
if s.jetRendererRangerContextKey == "" {
|
||||||
|
|
||||||
|
switch value := v.(type) {
|
||||||
|
case jet.Ranger, jet.Renderer:
|
||||||
|
jetRangerRenderer, _ = rangerRenderer(value)
|
||||||
|
case reflect.Value:
|
||||||
|
if vars == nil {
|
||||||
|
vars = make(JetRuntimeVars)
|
||||||
|
}
|
||||||
|
// if it's already a reflect value.
|
||||||
|
vars[k] = value
|
||||||
|
default:
|
||||||
|
if vars == nil {
|
||||||
|
vars = make(JetRuntimeVars)
|
||||||
|
}
|
||||||
|
vars.Set(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if k == s.jetRendererRangerContextKey {
|
||||||
|
jetRangerRenderer = v
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if vars == nil {
|
||||||
|
vars = make(JetRuntimeVars)
|
||||||
|
}
|
||||||
|
|
||||||
|
vars.Set(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmpl.Execute(w, vars, jetRangerRenderer)
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmpl.Execute(w, vars, bindingData)
|
return tmpl.Execute(w, vars, bindingData)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user