mirror of
https://github.com/kataras/iris.git
synced 2026-01-07 12:07:28 +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:
@@ -339,6 +339,7 @@ Follow the examples below,
|
||||
| handlebars | `iris.Handlebars(...)` |
|
||||
| amber | `iris.Amber(...)` |
|
||||
| pug(jade) | `iris.Pug(...)` |
|
||||
| jet | `iris.Jet(...)` |
|
||||
|
||||
- [Overview](view/overview/main.go)
|
||||
- [Hi](view/template_html_0/main.go)
|
||||
@@ -353,6 +354,8 @@ Follow the examples below,
|
||||
- [Pug (Jade) Actions`](view/template_pug_1)
|
||||
- [Pug (Jade) Includes`](view/template_pug_2)
|
||||
- [Pug (Jade) Extends`](view/template_pug_3)
|
||||
- [Jet](/view/template_jet_0) **NEW**
|
||||
- [Jet Embedded](view/template_jet_1_embedded) **NEW**
|
||||
|
||||
You can serve [quicktemplate](https://github.com/valyala/quicktemplate) and [hero templates](https://github.com/shiyanhui/hero/hero) files too, simply by using the `context#ResponseWriter`, take a look at the [http_responsewriter/quicktemplate](http_responsewriter/quicktemplate) and [http_responsewriter/herotemplate](http_responsewriter/herotemplate) examples.
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ func main() {
|
||||
|
||||
sess := sessions.New(sessions.Config{
|
||||
Cookie: "sessionscookieid",
|
||||
Expires: 0, // defauls to 0: unlimited life. Another good value is: 45 * time.Minute,
|
||||
Expires: 0, // defaults to 0: unlimited life. Another good value is: 45 * time.Minute,
|
||||
AllowReclaim: true,
|
||||
})
|
||||
|
||||
|
||||
@@ -5,11 +5,6 @@ import "github.com/kataras/iris"
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
// - standard html | iris.HTML(...)
|
||||
// - django | iris.Django(...)
|
||||
// - pug(jade) | iris.Pug(...)
|
||||
// - handlebars | iris.Handlebars(...)
|
||||
// - amber | iris.Amber(...)
|
||||
// with default template funcs:
|
||||
//
|
||||
// - {{ urlpath "mynamedroute" "pathParameter_ifneeded" }}
|
||||
|
||||
@@ -7,12 +7,6 @@ import (
|
||||
func main() {
|
||||
app := iris.New() // defaults to these
|
||||
|
||||
// - standard html | iris.HTML(...)
|
||||
// - django | iris.Django(...)
|
||||
// - pug(jade) | iris.Pug(...)
|
||||
// - handlebars | iris.Handlebars(...)
|
||||
// - amber | iris.Amber(...)
|
||||
|
||||
tmpl := iris.HTML("./templates", ".html")
|
||||
tmpl.Reload(true) // reload templates on each request (development mode)
|
||||
// default template funcs are:
|
||||
|
||||
11
_examples/view/template_jet_0/README.md
Normal file
11
_examples/view/template_jet_0/README.md
Normal 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).
|
||||
131
_examples/view/template_jet_0/main.go
Normal file
131
_examples/view/template_jet_0/main.go
Normal 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))
|
||||
}
|
||||
10
_examples/view/template_jet_0/views/layouts/application.jet
Normal file
10
_examples/view/template_jet_0/views/layouts/application.jet
Normal 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>
|
||||
30
_examples/view/template_jet_0/views/todos/index.jet
Normal file
30
_examples/view/template_jet_0/views/todos/index.jet
Normal 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}}
|
||||
9
_examples/view/template_jet_0/views/todos/show.jet
Normal file
9
_examples/view/template_jet_0/views/todos/show.jet
Normal 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}}
|
||||
25
_examples/view/template_jet_1_embedded/README.md
Normal file
25
_examples/view/template_jet_1_embedded/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Jet Engine Example (Embedded)
|
||||
|
||||
Take a look at the [../template_jet_0](../template_jet_0)'s README first.
|
||||
|
||||
This example teaches you how to use jet templates embedded in your applications with ease using the Iris built-in Jet view engine.
|
||||
|
||||
This example is a customized fork of https://github.com/CloudyKit/jet/tree/master/examples/asset_packaging, so you can
|
||||
notice the differences side by side. For example, you don't have to use any external package inside your application,
|
||||
Iris manually builds the template loader for binary data when Asset and AssetNames are available through tools like the [go-bindata](github.com/shuLhan/go-bindata).
|
||||
|
||||
Note that you can still use any custom loaders through the `JetEngine.SetLoader`
|
||||
which overrides any previous loaders like `JetEngine.Binary` we use on this example.
|
||||
|
||||
## How to run
|
||||
|
||||
```sh
|
||||
$ go get -u github.com/shuLhan/go-bindata/... # or any active alternative
|
||||
$ go-bindata ./views/...
|
||||
$ go build
|
||||
$ ./template_jet_0_embedded
|
||||
```
|
||||
|
||||
Repeat the above steps on any `./views` changes.
|
||||
|
||||
> html files are not used, only binary data. You can move or delete the `./views` folder.
|
||||
387
_examples/view/template_jet_1_embedded/bindata.go
Normal file
387
_examples/view/template_jet_1_embedded/bindata.go
Normal file
@@ -0,0 +1,387 @@
|
||||
// Code generated by go-bindata. DO NOT EDIT.
|
||||
// sources:
|
||||
// views\includes\_partial.jet
|
||||
// views\includes\blocks.jet
|
||||
// views\index.jet
|
||||
// views\layouts\application.jet
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func bindataRead(data []byte, name string) ([]byte, error) {
|
||||
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
_, err = io.Copy(&buf, gz)
|
||||
clErr := gz.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||
}
|
||||
if clErr != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
type asset struct {
|
||||
bytes []byte
|
||||
info fileInfoEx
|
||||
}
|
||||
|
||||
type fileInfoEx interface {
|
||||
os.FileInfo
|
||||
MD5Checksum() string
|
||||
}
|
||||
|
||||
type bindataFileInfo struct {
|
||||
name string
|
||||
size int64
|
||||
mode os.FileMode
|
||||
modTime time.Time
|
||||
md5checksum string
|
||||
}
|
||||
|
||||
func (fi bindataFileInfo) Name() string {
|
||||
return fi.name
|
||||
}
|
||||
func (fi bindataFileInfo) Size() int64 {
|
||||
return fi.size
|
||||
}
|
||||
func (fi bindataFileInfo) Mode() os.FileMode {
|
||||
return fi.mode
|
||||
}
|
||||
func (fi bindataFileInfo) ModTime() time.Time {
|
||||
return fi.modTime
|
||||
}
|
||||
func (fi bindataFileInfo) MD5Checksum() string {
|
||||
return fi.md5checksum
|
||||
}
|
||||
func (fi bindataFileInfo) IsDir() bool {
|
||||
return false
|
||||
}
|
||||
func (fi bindataFileInfo) Sys() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
var _bindataViewsincludespartialjet = []byte(
|
||||
"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb2\x29\xb0\xf3\xcc\x4b\xce\x29\x4d\x49\x4d\x51\x28\x48\x2c\x2a\xc9\x4c" +
|
||||
"\xcc\xb1\xd1\x2f\xb0\xe3\x02\x04\x00\x00\xff\xff\xd0\x10\x20\x0a\x18\x00\x00\x00")
|
||||
|
||||
func bindataViewsincludespartialjetBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_bindataViewsincludespartialjet,
|
||||
"views/includes/_partial.jet",
|
||||
)
|
||||
}
|
||||
|
||||
func bindataViewsincludespartialjet() (*asset, error) {
|
||||
bytes, err := bindataViewsincludespartialjetBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{
|
||||
name: "views/includes/_partial.jet",
|
||||
size: 24,
|
||||
md5checksum: "",
|
||||
mode: os.FileMode(438),
|
||||
modTime: time.Unix(1533831061, 0),
|
||||
}
|
||||
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _bindataViewsincludesblocksjet = []byte(
|
||||
"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xaa\xae\x4e\xca\xc9\x4f\xce\x56\xc8\x4d\xcd\x2b\xd5\xd0\xac\xad\xe5\x52" +
|
||||
"\x50\xb0\x29\xb0\x0b\xc9\x48\x05\x8b\x28\x40\x24\xcb\x13\x8b\x15\x32\xf3\xca\xf2\xb3\x53\x53\xf4\x6c\xf4\x0b\xec" +
|
||||
"\xb8\xaa\xab\x53\xf3\x52\x6a\x6b\xb9\x00\x01\x00\x00\xff\xff\x3f\xde\x27\x27\x3e\x00\x00\x00")
|
||||
|
||||
func bindataViewsincludesblocksjetBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_bindataViewsincludesblocksjet,
|
||||
"views/includes/blocks.jet",
|
||||
)
|
||||
}
|
||||
|
||||
func bindataViewsincludesblocksjet() (*asset, error) {
|
||||
bytes, err := bindataViewsincludesblocksjetBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{
|
||||
name: "views/includes/blocks.jet",
|
||||
size: 62,
|
||||
md5checksum: "",
|
||||
mode: os.FileMode(438),
|
||||
modTime: time.Unix(1533831061, 0),
|
||||
}
|
||||
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _bindataViewsindexjet = []byte(
|
||||
"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x64\x90\xb1\x6e\xf3\x30\x0c\x84\x77\x3d\xc5\xfd\x5e\xfe\x74\xa9\x91\xb5" +
|
||||
"\x30\x3c\x14\xc8\xd0\xa5\x4b\x1f\xa0\x50\x2c\x06\x56\x23\x8b\x42\x48\xd7\x36\x04\xbf\x7b\x11\xc5\x29\x8a\x76\x22" +
|
||||
"\xc8\xfb\x8e\x3c\x30\x67\x9a\x95\xa2\x13\x54\xc1\x2e\x3c\xaa\xd4\x36\xa5\xe0\x3b\xab\x9e\xe3\xe3\x07\x69\xb5\xae" +
|
||||
"\x26\x67\x3f\x24\xbe\x28\x2a\x1f\xbb\x30\x3a\x92\xfa\x18\xb8\x3b\xcb\x1d\x30\x39\x97\x01\x1c\x77\xe3\x40\x51\x9f" +
|
||||
"\xd9\x2d\xbb\x87\x75\x35\x40\xd3\xef\xdb\xc3\x70\x24\xe7\xc8\x81\x66\x3b\xa4\x40\x4d\xdd\xef\x5b\x73\x15\xa3\xfd" +
|
||||
"\x6c\x0d\x00\xe4\xbc\x78\x0a\x0e\x03\xc5\xf1\xee\xac\x8b\x6a\xae\xe2\x76\xf8\x47\x82\xf7\x64\x2f\xea\x6d\xf8\xce" +
|
||||
"\x50\xb0\x13\xfe\x6d\xc4\xcb\xe9\x30\x7b\x51\xd9\x55\x8e\x49\x5e\x59\x4b\x5b\xe8\xdb\x7a\xa0\x49\xed\x5b\xcf\x93" +
|
||||
"\xa0\xe7\xe9\x8f\x0f\x13\x5f\xce\xf2\x84\xdf\x6e\x4c\x56\x10\x59\xb1\xf1\x0e\x47\xea\xec\x28\x04\xaf\x05\x8e\xff" +
|
||||
"\x15\x54\xe8\xa6\x4e\x6d\x89\x45\xd1\x95\x37\xde\xea\x57\x00\x00\x00\xff\xff\xff\xe0\x1f\xae\x75\x01\x00\x00")
|
||||
|
||||
func bindataViewsindexjetBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_bindataViewsindexjet,
|
||||
"views/index.jet",
|
||||
)
|
||||
}
|
||||
|
||||
func bindataViewsindexjet() (*asset, error) {
|
||||
bytes, err := bindataViewsindexjetBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{
|
||||
name: "views/index.jet",
|
||||
size: 373,
|
||||
md5checksum: "",
|
||||
mode: os.FileMode(438),
|
||||
modTime: time.Unix(1561227802, 0),
|
||||
}
|
||||
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _bindataViewslayoutsapplicationjet = []byte(
|
||||
"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x8e\xbd\xae\xc2\x30\x0c\x85\xf7\x3e\x85\x6f\xa6\xcb\x80\xba\x32\xb8" +
|
||||
"\x1d\x80\xb2\xc2\x50\x06\xc6\x34\xb6\x08\x22\x3f\x08\x8c\x44\x15\xe5\xdd\x51\x08\x4c\xb6\xec\xf3\x7d\x3a\xf8\xb7" +
|
||||
"\xdd\x6f\xc6\xd3\x61\x00\x2b\xde\xf5\x0d\x96\x01\x4e\x87\x73\xa7\x38\xa8\xbe\x01\x40\xcb\x9a\xca\x02\x80\x9e\x45" +
|
||||
"\x83\xb1\xfa\xfe\x60\xe9\xd4\x71\xdc\x2d\x57\xea\xfb\x92\x8b\x38\xee\x07\x3f\x31\x11\x13\xf0\x4b\xfb\x9b\x63\x6c" +
|
||||
"\xeb\xbd\x78\xda\x9f\x08\xa7\x48\x73\xc5\x52\x9a\x5c\x34\x57\xa0\x68\x9e\x9e\x83\xac\x23\xcd\xff\x8b\x9c\x53\xe2" +
|
||||
"\x40\x39\x7f\xb0\x9a\xc6\xb6\x36\x7c\x07\x00\x00\xff\xff\x76\x86\x91\x20\xb2\x00\x00\x00")
|
||||
|
||||
func bindataViewslayoutsapplicationjetBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_bindataViewslayoutsapplicationjet,
|
||||
"views/layouts/application.jet",
|
||||
)
|
||||
}
|
||||
|
||||
func bindataViewslayoutsapplicationjet() (*asset, error) {
|
||||
bytes, err := bindataViewslayoutsapplicationjetBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{
|
||||
name: "views/layouts/application.jet",
|
||||
size: 178,
|
||||
md5checksum: "",
|
||||
mode: os.FileMode(438),
|
||||
modTime: time.Unix(1561227776, 0),
|
||||
}
|
||||
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
|
||||
return a, nil
|
||||
}
|
||||
|
||||
//
|
||||
// Asset loads and returns the asset for the given name.
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
//
|
||||
func Asset(name string) ([]byte, error) {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[cannonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
|
||||
}
|
||||
return a.bytes, nil
|
||||
}
|
||||
return nil, &os.PathError{Op: "open", Path: name, Err: os.ErrNotExist}
|
||||
}
|
||||
|
||||
//
|
||||
// MustAsset is like Asset but panics when Asset would return an error.
|
||||
// It simplifies safe initialization of global variables.
|
||||
// nolint: deadcode
|
||||
//
|
||||
func MustAsset(name string) []byte {
|
||||
a, err := Asset(name)
|
||||
if err != nil {
|
||||
panic("asset: Asset(" + name + "): " + err.Error())
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
//
|
||||
// AssetInfo loads and returns the asset info for the given name.
|
||||
// It returns an error if the asset could not be found or could not be loaded.
|
||||
//
|
||||
func AssetInfo(name string) (os.FileInfo, error) {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[cannonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
|
||||
}
|
||||
return a.info, nil
|
||||
}
|
||||
return nil, &os.PathError{Op: "open", Path: name, Err: os.ErrNotExist}
|
||||
}
|
||||
|
||||
//
|
||||
// AssetNames returns the names of the assets.
|
||||
// nolint: deadcode
|
||||
//
|
||||
func AssetNames() []string {
|
||||
names := make([]string, 0, len(_bindata))
|
||||
for name := range _bindata {
|
||||
names = append(names, name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
//
|
||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||
//
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
"views/includes/_partial.jet": bindataViewsincludespartialjet,
|
||||
"views/includes/blocks.jet": bindataViewsincludesblocksjet,
|
||||
"views/index.jet": bindataViewsindexjet,
|
||||
"views/layouts/application.jet": bindataViewslayoutsapplicationjet,
|
||||
}
|
||||
|
||||
//
|
||||
// AssetDir returns the file names below a certain
|
||||
// directory embedded in the file by go-bindata.
|
||||
// For example if you run go-bindata on data/... and data contains the
|
||||
// following hierarchy:
|
||||
// data/
|
||||
// foo.txt
|
||||
// img/
|
||||
// a.png
|
||||
// b.png
|
||||
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
||||
// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
||||
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
|
||||
// AssetDir("") will return []string{"data"}.
|
||||
//
|
||||
func AssetDir(name string) ([]string, error) {
|
||||
node := _bintree
|
||||
if len(name) != 0 {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
pathList := strings.Split(cannonicalName, "/")
|
||||
for _, p := range pathList {
|
||||
node = node.Children[p]
|
||||
if node == nil {
|
||||
return nil, &os.PathError{
|
||||
Op: "open",
|
||||
Path: name,
|
||||
Err: os.ErrNotExist,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if node.Func != nil {
|
||||
return nil, &os.PathError{
|
||||
Op: "open",
|
||||
Path: name,
|
||||
Err: os.ErrNotExist,
|
||||
}
|
||||
}
|
||||
rv := make([]string, 0, len(node.Children))
|
||||
for childName := range node.Children {
|
||||
rv = append(rv, childName)
|
||||
}
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
type bintree struct {
|
||||
Func func() (*asset, error)
|
||||
Children map[string]*bintree
|
||||
}
|
||||
|
||||
var _bintree = &bintree{Func: nil, Children: map[string]*bintree{
|
||||
"views": {Func: nil, Children: map[string]*bintree{
|
||||
"includes": {Func: nil, Children: map[string]*bintree{
|
||||
"_partial.jet": {Func: bindataViewsincludespartialjet, Children: map[string]*bintree{}},
|
||||
"blocks.jet": {Func: bindataViewsincludesblocksjet, Children: map[string]*bintree{}},
|
||||
}},
|
||||
"index.jet": {Func: bindataViewsindexjet, Children: map[string]*bintree{}},
|
||||
"layouts": {Func: nil, Children: map[string]*bintree{
|
||||
"application.jet": {Func: bindataViewslayoutsapplicationjet, Children: map[string]*bintree{}},
|
||||
}},
|
||||
}},
|
||||
}}
|
||||
|
||||
// RestoreAsset restores an asset under the given directory
|
||||
func RestoreAsset(dir, name string) error {
|
||||
data, err := Asset(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := AssetInfo(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
|
||||
}
|
||||
|
||||
// RestoreAssets restores an asset under the given directory recursively
|
||||
func RestoreAssets(dir, name string) error {
|
||||
children, err := AssetDir(name)
|
||||
// File
|
||||
if err != nil {
|
||||
return RestoreAsset(dir, name)
|
||||
}
|
||||
// Dir
|
||||
for _, child := range children {
|
||||
err = RestoreAssets(dir, filepath.Join(name, child))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func _filePath(dir, name string) string {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
||||
}
|
||||
31
_examples/view/template_jet_1_embedded/main.go
Normal file
31
_examples/view/template_jet_1_embedded/main.go
Normal file
@@ -0,0 +1,31 @@
|
||||
// Package main shows how to use jet templates embedded in your application with ease using the Iris built-in Jet view engine.
|
||||
// This example is a customized fork of https://github.com/CloudyKit/jet/tree/master/examples/asset_packaging, so you can
|
||||
// notice the differences side by side. For example, you don't have to use any external package inside your application,
|
||||
// Iris manually builds the template loader for binary data when Asset and AssetNames are available via tools like the go-bindata.
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
tmpl := iris.Jet("./views", ".jet").Binary(Asset, AssetNames)
|
||||
app.RegisterView(tmpl)
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.View("index.jet")
|
||||
})
|
||||
|
||||
port := os.Getenv("PORT")
|
||||
if len(port) == 0 {
|
||||
port = ":8080"
|
||||
} else if !strings.HasPrefix(":", port) {
|
||||
port = ":" + port
|
||||
}
|
||||
|
||||
app.Run(iris.Addr(port))
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<p>Included partial</p>
|
||||
@@ -0,0 +1,3 @@
|
||||
{{block menu()}}
|
||||
<p>The menu block was invoked.</p>
|
||||
{{end}}
|
||||
16
_examples/view/template_jet_1_embedded/views/index.jet
Normal file
16
_examples/view/template_jet_1_embedded/views/index.jet
Normal file
@@ -0,0 +1,16 @@
|
||||
{{extends "layouts/application.jet"}}
|
||||
{{import "includes/blocks.jet"}}
|
||||
|
||||
{{block documentBody()}}
|
||||
<h1>Embedded example</h1>
|
||||
|
||||
<nav>
|
||||
{{yield menu()}}
|
||||
</nav>
|
||||
|
||||
{{include "includes/_partial.jet"}}
|
||||
|
||||
{{if !includeIfExists("doesNotExist.jet")}}
|
||||
<p>Shows how !includeIfExists works: doesNotExist.jet was not included because it doesn't exist.</p>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Embedded example</title>
|
||||
</head>
|
||||
<body>
|
||||
{{block documentBody()}}{{end}}
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user