1
0
mirror of https://github.com/kataras/iris.git synced 2026-03-11 02:45:56 +00:00

Implement a new View Engine for the Jet template parser as requested at: https://github.com/kataras/iris/issues/1281

Former-commit-id: 3e00bdfbf1f3998a1744c390c12fd70430ac0320
This commit is contained in:
Gerasimos (Makis) Maropoulos
2019-06-22 21:34:19 +03:00
parent b71d4032e6
commit 076d9121f1
22 changed files with 1124 additions and 40 deletions

View File

@@ -0,0 +1,11 @@
# Jet Engine Example
This example is a fork of <https://github.com/CloudyKit/jet/tree/master/examples/todos> to work with Iris, so you can
notice the differences side by side.
Read more at: https://github.com/kataras/iris/issues/1281
> The Iris Jet View Engine fixes some bugs that the underline [jet template parser](https://github.com/CloudyKit/jet) currently has.
Continue by learning how you can [serve embedded templates](../template_jet_1_embedded).

View File

@@ -0,0 +1,131 @@
// Package main shows how to use jet template parser with ease using the Iris built-in Jet view engine.
// This example is customized fork of https://github.com/CloudyKit/jet/tree/master/examples/todos, so you can
// notice the differences side by side.
package main
import (
"bytes"
"encoding/base64"
"fmt"
"os"
"reflect"
"strings"
"github.com/kataras/iris"
"github.com/kataras/iris/view"
)
type tTODO struct {
Text string
Done bool
}
type doneTODOs struct {
list map[string]*tTODO
keys []string
len int
i int
}
func (dt *doneTODOs) New(todos map[string]*tTODO) *doneTODOs {
dt.len = len(todos)
for k := range todos {
dt.keys = append(dt.keys, k)
}
dt.list = todos
return dt
}
// Range satisfies the jet.Ranger interface and only returns TODOs that are done,
// even when the list contains TODOs that are not done.
func (dt *doneTODOs) Range() (reflect.Value, reflect.Value, bool) {
for dt.i < dt.len {
key := dt.keys[dt.i]
dt.i++
if dt.list[key].Done {
return reflect.ValueOf(key), reflect.ValueOf(dt.list[key]), false
}
}
return reflect.Value{}, reflect.Value{}, true
}
func (dt *doneTODOs) Render(r *view.JetRuntime) {
r.Write([]byte(fmt.Sprintf("custom renderer")))
}
// Render implements jet.Renderer interface
func (t *tTODO) Render(r *view.JetRuntime) {
done := "yes"
if !t.Done {
done = "no"
}
r.Write([]byte(fmt.Sprintf("TODO: %s (done: %s)", t.Text, done)))
}
func main() {
//
// Type aliases:
// view.JetRuntimeVars = jet.VarMap
// view.JetRuntime = jet.Runtime
// view.JetArguments = jet.Arguments
//
// Iris also gives you the ability to put runtime variables
// from middlewares as well, by:
// view.AddJetRuntimeVars(ctx, vars)
// or tmpl.AddRuntimeVars(ctx, vars)
//
// The Iris Jet fixes the issue when custom jet.Ranger and custom jet.Renderer are not actually work at all,
// hope that this is a temp issue on the jet parser itself and authors will fix it soon
// so we can remove the "hacks" we've putted for those to work as expected.
app := iris.New()
tmpl := iris.Jet("./views", ".jet") // <--
tmpl.Reload(true) // remove in production.
tmpl.AddFunc("base64", func(a view.JetArguments) reflect.Value {
a.RequireNumOfArguments("base64", 1, 1)
buffer := bytes.NewBuffer(nil)
fmt.Fprint(buffer, a.Get(0))
return reflect.ValueOf(base64.URLEncoding.EncodeToString(buffer.Bytes()))
})
app.RegisterView(tmpl) // <--
var todos = map[string]*tTODO{
"example-todo-1": {Text: "Add an show todo page to the example project", Done: true},
"example-todo-2": {Text: "Add an add todo page to the example project"},
"example-todo-3": {Text: "Add an update todo page to the example project"},
"example-todo-4": {Text: "Add an delete todo page to the example project", Done: true},
}
app.Get("/", func(ctx iris.Context) {
ctx.View("todos/index.jet", todos) // <--
// Note that the `ctx.View` already logs the error if logger level is allowing it and returns the error.
})
app.Get("/todo", func(ctx iris.Context) {
id := ctx.URLParam("id")
todo, ok := todos[id]
if !ok {
ctx.Redirect("/")
return
}
ctx.View("todos/show.jet", todo)
})
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.Set("showingAllDone", true)
view.AddJetRuntimeVars(ctx, vars) // <--
ctx.View("todos/index.jet", (&doneTODOs{}).New(todos))
})
port := os.Getenv("PORT")
if len(port) == 0 {
port = ":8080"
} else if !strings.HasPrefix(":", port) {
port = ":" + port
}
app.Run(iris.Addr(port))
}

View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ isset(title) ? title : "" }}</title>
</head>
<body>
{{block documentBody()}}{{end}}
</body>
</html>

View File

@@ -0,0 +1,30 @@
{{extends "layouts/application.jet"}}
{{block button(label, href="javascript:void(0)")}}
<a href="{{ href }}">{{ label }}</a>
{{end}}
{{block ul()}}
<ul>
{{yield content}}
</ul>
{{end}}
{{block documentBody()}}
<h1>List of TODOs</h1>
{{if isset(showingAllDone) && showingAllDone}}
<p>Showing only TODOs that are done</p>
{{else}}
<p><a href="/all-done">Show only TODOs that are done</a></p>
{{end}}
{{yield ul() content}}
{{range id, value := .}}
<li {{if value.Done}}style="color:red;text-decoration: line-through;"{{end}}>
<a href="/todo?id={{ id }}">{{ value.Text }}</a>
{{yield button(label="UP", href="/update/?id="+base64(id))}} - {{yield button(href="/delete/?id="+id, label="DL")}}
</li>
{{end}}
{{end}}
{{end}}

View File

@@ -0,0 +1,9 @@
{{extends "layouts/application.jet"}}
{{block documentBody()}}
<h1>Show TODO</h1>
<p>This uses a custom renderer by implementing the jet.Renderer interface.
<p>
{{.}}
</p>
{{end}}