mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 02:31:04 +01:00
Full support of the http.FileSystem on all view engines as requested at #1575
Also, the HandleDir accepts both string and http.FileSystem (interface{}) (like the view's fs)
This commit is contained in:
parent
7e6d453dad
commit
e1f25eb098
|
@ -364,6 +364,8 @@ Response:
|
|||
|
||||
Other Improvements:
|
||||
|
||||
- Full `http.FileSystem` interface support for all **view** engines as [requested](https://github.com/kataras/iris/issues/1575). The first argument of the functions(`HTML`, `Blocks`, `Pug`, `Amber`, `Ace`, `Jet`, `Django`, `Handlebars`) can now be either a directory of `string` type (like before) or a value which completes the `http.FileSystem` interface. The `.Binary` method of all view engines was removed: pass the go-bindata's latest version `AssetFile()` exported function as the first argument instead of string.
|
||||
|
||||
- Add `Route.ExcludeSitemap() *Route` to exclude a route from sitemap as requested in [chat](https://chat.iris-go.com), also offline routes are excluded automatically now.
|
||||
|
||||
- Improved tracing (with `app.Logger().SetLevel("debug")`) for routes. Screens:
|
||||
|
@ -641,6 +643,7 @@ New Context Methods:
|
|||
|
||||
Breaking Changes:
|
||||
|
||||
- The `.Binary` method of all view engines was removed: pass the go-bindata's latest version `AssetFile()` exported function as the first argument instead of string. All examples updated.
|
||||
- `ContextUploadFormFiles(destDirectory string, before ...func(*Context, *multipart.FileHeader) bool) (uploaded []*multipart.FileHeader, n int64, err error)` now returns the total files uploaded too (as its first parameter) and the "before" variadic option should return a boolean, if false then the specific file is skipped.
|
||||
- `Context.PostValues(name string) ([]string, error)` now returns a second output argument of `error` type too, which reports `ErrEmptyForm` or `ErrNotFound` or `ErrEmptyFormField`. The single post value getters now returns the **last value** if multiple was given instead of the first one (this allows clients to append values on flow updates).
|
||||
- `Party.GetReporter()` **removed**. The `Application.Build` returns the first error now and the API's errors are logged, this allows the server to run even if some of the routes are invalid but not fatal to the entire application (it was a request from a company).
|
||||
|
@ -652,7 +655,7 @@ Breaking Changes:
|
|||
- `iris.Gzip` and `iris.GzipReader` replaced with `iris.Compression` (middleware).
|
||||
- `ctx.ClientSupportsGzip() bool` replaced with `ctx.ClientSupportsEncoding("gzip", "br" ...) bool`.
|
||||
- `ctx.GzipResponseWriter()` is **removed**.
|
||||
- `Party.HandleDir/iris.FileServer` now accepts a `http.FileSystem` instead of a string and returns a list of `[]*Route` (GET and HEAD) instead of GET only. Write: `app.HandleDir("/", iris.Dir("./assets"))` instead of `app.HandleDir("/", "./assets")` and `DirOptions.Asset, AssetNames, AssetInfo` removed, use `go-bindata -fs [..]` and `app.HandleDir("/", AssetFile())` instead.
|
||||
- `Party.HandleDir/iris.FileServer` now accepts both `http.FileSystem` and `string` and returns a list of `[]*Route` (GET and HEAD) instead of GET only. You can write: both `app.HandleDir("/", iris.Dir("./assets"))` and `app.HandleDir("/", "./assets")` and `DirOptions.Asset, AssetNames, AssetInfo` removed, use `go-bindata -fs [..]` and `app.HandleDir("/", AssetFile())` instead.
|
||||
- `Context.OnClose` and `Context.OnCloseConnection` now both accept an `iris.Handler` instead of a simple `func()` as their callback.
|
||||
- `Context.StreamWriter(writer func(w io.Writer) bool)` changed to `StreamWriter(writer func(w io.Writer) error) error` and it's now the `Context.Request().Context().Done()` channel that is used to receive any close connection/manual cancel signals, instead of the deprecated `ResponseWriter().CloseNotify()` one. Same for the `Context.OnClose` and `Context.OnCloseConnection` methods.
|
||||
- Fixed handler's error response not be respected when response recorder was used instead of the common writer. Fixes [#1531](https://github.com/kataras/iris/issues/1531). It contains a **BREAKING CHANGE** of: the new `Configuration.ResetOnFireErrorCode` field should be set **to true** in order to behave as it used before this update (to reset the contents on recorder).
|
||||
|
|
|
@ -113,15 +113,16 @@
|
|||
* [Write to a custom `io.Writer`](view/write-to)
|
||||
* [Blocks](view/template_blocks_0)
|
||||
* [Blocks Embedded](view/template_blocks_1_embedded)
|
||||
* [Pug: Greeting](view/template_pug_0)
|
||||
* [Pug: `Actions`](view/template_pug_1)
|
||||
* [Pug: `Includes`](view/template_pug_2)
|
||||
* [Pug: `Extends`](view/template_pug_3)
|
||||
* [Jet Template](view/template_jet_0)
|
||||
* [Pug: `Actions`](view/template_pug_0)
|
||||
* [Pug: `Includes`](view/template_pug_1)
|
||||
* [Pug Embedded`](view/template_pug_2_embedded)
|
||||
* [Jet](view/template_jet_0)
|
||||
* [Jet Embedded](view/template_jet_1_embedded)
|
||||
* [Jet 'urlpath' tmpl func](view/template_jet_2)
|
||||
* [Jet Template Funcs from Struct](view/template_jet_3)
|
||||
* [Ace](view/template_ace_0)
|
||||
* [Amber](view/template_amber_0)
|
||||
* [Amber Embedded](view/template_amber_1_embedded)
|
||||
* [Handlebars](view/template_handlebars_0)
|
||||
* Third-Parties
|
||||
* [Render `valyala/quicktemplate` templates](view/quicktemplate)
|
||||
|
|
|
@ -5,7 +5,9 @@ import (
|
|||
)
|
||||
|
||||
// Follow these steps first:
|
||||
// $ go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// $ go get -u github.com/go-bindata/go-bindata
|
||||
// # OR: go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// # to save it to your go.mod file
|
||||
// $ go-bindata -prefix "assets" -fs ./assets/...
|
||||
// $ go run .
|
||||
// "physical" files are not used, you can delete the "assets" folder and run the example.
|
||||
|
|
|
@ -6,7 +6,9 @@ import (
|
|||
|
||||
// How to run:
|
||||
//
|
||||
// $ go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// $ go get -u github.com/go-bindata/go-bindata
|
||||
// # OR: go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// # to save it to your go.mod file
|
||||
// $ go-bindata -prefix "../embedding-files-into-app/assets/" -fs ../embedding-files-into-app/assets/...
|
||||
// $ go run .
|
||||
// Time to complete the compression and caching of [2/3] files: 31.9998ms
|
||||
|
|
|
@ -7,7 +7,9 @@ import (
|
|||
)
|
||||
|
||||
// How to run:
|
||||
// $ go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// $ go get -u github.com/go-bindata/go-bindata
|
||||
// # OR: go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// # to save it to your go.mod file
|
||||
// $ go-bindata -nomemcopy -fs -prefix "../http2push/assets" ../http2push/assets/...
|
||||
// # OR if the ./assets directory was inside this example foder:
|
||||
// # go-bindata -nomemcopy -refix "assets" ./assets/...
|
||||
|
|
|
@ -2,7 +2,9 @@ package main
|
|||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
// $ go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// $ go get -u github.com/go-bindata/go-bindata
|
||||
// # OR: go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// # to save it to your go.mod file
|
||||
// $ go-bindata -fs -prefix "public" ./public/...
|
||||
// $ go run .
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func bindataRead(data, name string) ([]byte, error) {
|
||||
gz, err := gzip.NewReader(strings.NewReader(data))
|
||||
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)
|
||||
}
|
||||
|
@ -168,82 +168,82 @@ func AssetFile() http.FileSystem {
|
|||
return &assetOperator{}
|
||||
}
|
||||
|
||||
var _publicAppJs = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2a\xcf\xcc\x4b\xc9\x2f\xd7\x4b\xcc\x49\x2d\x2a\xd1\x50\x4a\x2c\x28\xd0\xcb\x2a\x56\xc8\xc9\x4f\x4c\x49\x4d\x51\x48\x2b\xca\xcf\x55\x88\x51\xd2\x57\xd2\xb4\x06\x04\x00\x00\xff\xff\xa9\x06\xf7\xa3\x27\x00\x00\x00"
|
||||
var _appJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2a\xcf\xcc\x4b\xc9\x2f\xd7\x4b\xcc\x49\x2d\x2a\xd1\x50\x4a\x2c\x28\xd0\xcb\x2a\x56\xc8\xc9\x4f\x4c\x49\x4d\x51\x48\x2b\xca\xcf\x55\x88\x51\xd2\x57\xd2\xb4\x06\x04\x00\x00\xff\xff\xa9\x06\xf7\xa3\x27\x00\x00\x00")
|
||||
|
||||
func publicAppJsBytes() ([]byte, error) {
|
||||
func appJsBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_publicAppJs,
|
||||
"public/app.js",
|
||||
_appJs,
|
||||
"app.js",
|
||||
)
|
||||
}
|
||||
|
||||
func publicAppJs() (*asset, error) {
|
||||
bytes, err := publicAppJsBytes()
|
||||
func appJs() (*asset, error) {
|
||||
bytes, err := appJsBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "public/app.js", size: 39, mode: os.FileMode(438), modTime: time.Unix(1595516291, 0)}
|
||||
info := bindataFileInfo{name: "app.js", size: 39, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _publicApp2IndexHtml = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x8d\x41\x0a\xc2\x40\x0c\x45\xf7\x81\xdc\xe1\x9f\xc0\xd0\xae\x43\xc0\x9d\xd7\xa8\x4c\x24\x85\xd4\x09\x32\x0b\xbd\xbd\xb4\xd6\xe5\x87\xf7\xde\xd7\x18\x5b\x1a\x13\x93\x86\x2f\xcd\x98\x00\x40\xc7\x3a\xd2\xed\x5a\x85\x59\xe5\x37\x98\x54\x4e\x84\x49\xef\xbd\x7d\xfe\x70\x4c\x86\x9b\x67\x76\x3c\x5e\x7d\xc3\x52\x35\xcb\xfa\x6c\xfe\xbe\xec\x71\xa8\xc4\x74\xd8\xa7\x73\x84\xf6\xd7\x6f\x00\x00\x00\xff\xff\xfd\x28\x92\x95\x7c\x00\x00\x00"
|
||||
var _app2IndexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x8d\x41\x0a\xc2\x40\x0c\x45\xf7\x81\xdc\xe1\x9f\xc0\xd0\xae\x43\xc0\x9d\xd7\xa8\x4c\x24\x85\xd4\x09\x32\x0b\xbd\xbd\xb4\xd6\xe5\x87\xf7\xde\xd7\x18\x5b\x1a\x13\x93\x86\x2f\xcd\x98\x00\x40\xc7\x3a\xd2\xed\x5a\x85\x59\xe5\x37\x98\x54\x4e\x84\x49\xef\xbd\x7d\xfe\x70\x4c\x86\x9b\x67\x76\x3c\x5e\x7d\xc3\x52\x35\xcb\xfa\x6c\xfe\xbe\xec\x71\xa8\xc4\x74\xd8\xa7\x73\x84\xf6\xd7\x6f\x00\x00\x00\xff\xff\xfd\x28\x92\x95\x7c\x00\x00\x00")
|
||||
|
||||
func publicApp2IndexHtmlBytes() ([]byte, error) {
|
||||
func app2IndexHtmlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_publicApp2IndexHtml,
|
||||
"public/app2/index.html",
|
||||
_app2IndexHtml,
|
||||
"app2/index.html",
|
||||
)
|
||||
}
|
||||
|
||||
func publicApp2IndexHtml() (*asset, error) {
|
||||
bytes, err := publicApp2IndexHtmlBytes()
|
||||
func app2IndexHtml() (*asset, error) {
|
||||
bytes, err := app2IndexHtmlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "public/app2/index.html", size: 124, mode: os.FileMode(438), modTime: time.Unix(1572105320, 0)}
|
||||
info := bindataFileInfo{name: "app2/index.html", size: 124, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _publicCssMainCss = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xca\x4f\xa9\x54\xa8\xe6\xe5\x52\x50\x50\x50\x48\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x48\xca\x49\x4c\xce\xb6\xe6\xe5\xaa\xe5\xe5\x02\x04\x00\x00\xff\xff\x03\x25\x9c\x89\x29\x00\x00\x00"
|
||||
var _cssMainCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xca\x4f\xa9\x54\xa8\xe6\xe5\x52\x50\x50\x50\x48\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x48\xca\x49\x4c\xce\xb6\xe6\xe5\xaa\xe5\xe5\x02\x04\x00\x00\xff\xff\x03\x25\x9c\x89\x29\x00\x00\x00")
|
||||
|
||||
func publicCssMainCssBytes() ([]byte, error) {
|
||||
func cssMainCssBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_publicCssMainCss,
|
||||
"public/css/main.css",
|
||||
_cssMainCss,
|
||||
"css/main.css",
|
||||
)
|
||||
}
|
||||
|
||||
func publicCssMainCss() (*asset, error) {
|
||||
bytes, err := publicCssMainCssBytes()
|
||||
func cssMainCss() (*asset, error) {
|
||||
bytes, err := cssMainCssBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "public/css/main.css", size: 41, mode: os.FileMode(438), modTime: time.Unix(1565946441, 0)}
|
||||
info := bindataFileInfo{name: "css/main.css", size: 41, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _publicIndexHtml = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x8e\x41\x0e\xc2\x20\x10\x45\xf7\x24\xdc\xe1\xa7\x07\x80\x74\x3f\xb2\x76\xe9\xc2\x0b\x60\x41\xc1\x50\x21\xc0\x42\xd3\xf4\xee\x06\x4a\x97\x93\xf7\x66\xde\x90\xab\x6b\x50\x9c\x71\x46\xce\x6a\xa3\x38\x03\x00\xaa\xbe\x06\xab\xb6\x0d\xe2\xa6\x5f\x56\xdc\xdb\x88\x7d\x27\x79\x00\xce\x48\x0e\x9d\x33\x7a\x44\xf3\x3b\x17\xdd\xac\x70\xb5\x21\x44\x3c\x73\x5c\xe1\x3f\xc6\x7e\x45\x6b\x80\xa4\x9b\xbb\x3f\xcc\xb2\x64\x9f\x2a\x4a\x5e\x2e\x93\xd4\x29\x89\x77\x99\x14\x40\xf2\x00\xbd\x31\x2e\xf7\x5c\xfb\xf3\x1f\x00\x00\xff\xff\x25\xe9\x37\x57\xae\x00\x00\x00"
|
||||
var _indexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x8e\x41\x0e\xc2\x20\x10\x45\xf7\x24\xdc\xe1\xa7\x07\x80\x74\x3f\xb2\x76\xe9\xc2\x0b\x60\x41\xc1\x50\x21\xc0\x42\xd3\xf4\xee\x06\x4a\x97\x93\xf7\x66\xde\x90\xab\x6b\x50\x9c\x71\x46\xce\x6a\xa3\x38\x03\x00\xaa\xbe\x06\xab\xb6\x0d\xe2\xa6\x5f\x56\xdc\xdb\x88\x7d\x27\x79\x00\xce\x48\x0e\x9d\x33\x7a\x44\xf3\x3b\x17\xdd\xac\x70\xb5\x21\x44\x3c\x73\x5c\xe1\x3f\xc6\x7e\x45\x6b\x80\xa4\x9b\xbb\x3f\xcc\xb2\x64\x9f\x2a\x4a\x5e\x2e\x93\xd4\x29\x89\x77\x99\x14\x40\xf2\x00\xbd\x31\x2e\xf7\x5c\xfb\xf3\x1f\x00\x00\xff\xff\x25\xe9\x37\x57\xae\x00\x00\x00")
|
||||
|
||||
func publicIndexHtmlBytes() ([]byte, error) {
|
||||
func indexHtmlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_publicIndexHtml,
|
||||
"public/index.html",
|
||||
_indexHtml,
|
||||
"index.html",
|
||||
)
|
||||
}
|
||||
|
||||
func publicIndexHtml() (*asset, error) {
|
||||
bytes, err := publicIndexHtmlBytes()
|
||||
func indexHtml() (*asset, error) {
|
||||
bytes, err := indexHtmlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "public/index.html", size: 174, mode: os.FileMode(438), modTime: time.Unix(1565946441, 0)}
|
||||
info := bindataFileInfo{name: "index.html", size: 174, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -300,10 +300,10 @@ func AssetNames() []string {
|
|||
|
||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
"public/app.js": publicAppJs,
|
||||
"public/app2/index.html": publicApp2IndexHtml,
|
||||
"public/css/main.css": publicCssMainCss,
|
||||
"public/index.html": publicIndexHtml,
|
||||
"app.js": appJs,
|
||||
"app2/index.html": app2IndexHtml,
|
||||
"css/main.css": cssMainCss,
|
||||
"index.html": indexHtml,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
|
@ -347,16 +347,14 @@ type bintree struct {
|
|||
}
|
||||
|
||||
var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"public": {nil, map[string]*bintree{
|
||||
"app.js": {publicAppJs, map[string]*bintree{}},
|
||||
"app2": {nil, map[string]*bintree{
|
||||
"index.html": {publicApp2IndexHtml, map[string]*bintree{}},
|
||||
}},
|
||||
"css": {nil, map[string]*bintree{
|
||||
"main.css": {publicCssMainCss, map[string]*bintree{}},
|
||||
}},
|
||||
"index.html": {publicIndexHtml, map[string]*bintree{}},
|
||||
"app.js": {appJs, map[string]*bintree{}},
|
||||
"app2": {nil, map[string]*bintree{
|
||||
"index.html": {app2IndexHtml, map[string]*bintree{}},
|
||||
}},
|
||||
"css": {nil, map[string]*bintree{
|
||||
"main.css": {cssMainCss, map[string]*bintree{}},
|
||||
}},
|
||||
"index.html": {indexHtml, map[string]*bintree{}},
|
||||
}}
|
||||
|
||||
// RestoreAsset restores an asset under the given directory
|
||||
|
|
|
@ -4,8 +4,10 @@ import (
|
|||
"github.com/kataras/iris/v12"
|
||||
)
|
||||
|
||||
// $ go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// $ go-bindata -nomemcopy -fs ./public/...
|
||||
// $ go get -u github.com/go-bindata/go-bindata
|
||||
// # OR: go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// # to save it to your go.mod file
|
||||
// $ go-bindata -fs -prefix "public" ./public/...
|
||||
// $ go run .
|
||||
|
||||
var page = struct {
|
||||
|
@ -14,20 +16,16 @@ var page = struct {
|
|||
|
||||
func newApp() *iris.Application {
|
||||
app := iris.New()
|
||||
app.RegisterView(iris.HTML("./public", ".html").Binary(Asset, AssetNames))
|
||||
|
||||
app.RegisterView(iris.HTML(AssetFile(), ".html"))
|
||||
|
||||
app.HandleDir("/", AssetFile())
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.ViewData("Page", page)
|
||||
ctx.View("index.html")
|
||||
})
|
||||
|
||||
// We didn't add a `-prefix "public"` argument on go-bindata command
|
||||
// because the view's `Assset` and `AssetNames` require fullpath.
|
||||
// Make use of the `PrefixDir` to serve assets on cases like that;
|
||||
// when bindata.go file contains files that are
|
||||
// not necessary public assets to be served.
|
||||
app.HandleDir("/", iris.PrefixDir("public", AssetFile()))
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Code generated for package main by go-bindata DO NOT EDIT. (@generated)
|
||||
// sources:
|
||||
// Code generated by go-bindata. (@generated) DO NOT EDIT.
|
||||
|
||||
//Package main generated by go-bindata.// sources:
|
||||
// templates/layouts/layout.html
|
||||
// templates/layouts/mylayout.html
|
||||
// templates/page1.html
|
||||
|
@ -12,6 +13,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -21,7 +23,7 @@ import (
|
|||
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)
|
||||
return nil, fmt.Errorf("read %q: %v", name, err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
@ -29,7 +31,7 @@ func bindataRead(data []byte, name string) ([]byte, error) {
|
|||
clErr := gz.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||
return nil, fmt.Errorf("read %q: %v", name, err)
|
||||
}
|
||||
if clErr != nil {
|
||||
return nil, err
|
||||
|
@ -65,7 +67,7 @@ func (fi bindataFileInfo) Mode() os.FileMode {
|
|||
return fi.mode
|
||||
}
|
||||
|
||||
// Mode return file modify time
|
||||
// ModTime return file modify time
|
||||
func (fi bindataFileInfo) ModTime() time.Time {
|
||||
return fi.modTime
|
||||
}
|
||||
|
@ -80,82 +82,168 @@ func (fi bindataFileInfo) Sys() interface{} {
|
|||
return nil
|
||||
}
|
||||
|
||||
var _templatesLayoutsLayoutHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\xce\xc1\xa9\xc3\x30\x0c\x06\xe0\xf3\x33\x78\x07\xbd\x01\x8c\xc9\x5d\x78\x82\x9e\x4a\x17\x70\x6a\x51\x19\x94\xa4\x38\xca\xc1\x84\xec\x5e\xec\xba\x27\x49\xf0\x89\xff\x47\xd6\x45\x82\x35\xc8\x14\x53\x9b\x9a\x55\x28\xdc\x62\xdd\x0e\x45\xff\xbd\xac\xb1\x06\xfd\x4f\xcc\x5b\xaa\xc1\x9a\x3f\xe4\x29\x3c\x38\xef\x90\x77\x50\x26\x78\xc9\x36\x47\x01\x19\xaf\x3c\x75\x34\x17\xf0\x7d\xf9\x77\x0e\xee\xb4\x26\x2a\x5d\x3f\x8f\x52\x68\x55\x50\x5a\xde\x12\x95\x80\xa9\x10\x38\xd7\xec\x79\x42\xcd\x24\x09\xae\xab\x05\x8f\x40\xf4\xa3\xeb\x27\x00\x00\xff\xff\x68\xca\x16\xc2\xb4\x00\x00\x00")
|
||||
type assetFile struct {
|
||||
*bytes.Reader
|
||||
name string
|
||||
childInfos []os.FileInfo
|
||||
childInfoOffset int
|
||||
}
|
||||
|
||||
func templatesLayoutsLayoutHtmlBytes() ([]byte, error) {
|
||||
type assetOperator struct{}
|
||||
|
||||
// Open implement http.FileSystem interface
|
||||
func (f *assetOperator) Open(name string) (http.File, error) {
|
||||
var err error
|
||||
if len(name) > 0 && name[0] == '/' {
|
||||
name = name[1:]
|
||||
}
|
||||
content, err := Asset(name)
|
||||
if err == nil {
|
||||
return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil
|
||||
}
|
||||
children, err := AssetDir(name)
|
||||
if err == nil {
|
||||
childInfos := make([]os.FileInfo, 0, len(children))
|
||||
for _, child := range children {
|
||||
childPath := filepath.Join(name, child)
|
||||
info, errInfo := AssetInfo(filepath.Join(name, child))
|
||||
if errInfo == nil {
|
||||
childInfos = append(childInfos, info)
|
||||
} else {
|
||||
childInfos = append(childInfos, newDirFileInfo(childPath))
|
||||
}
|
||||
}
|
||||
return &assetFile{name: name, childInfos: childInfos}, nil
|
||||
} else {
|
||||
// If the error is not found, return an error that will
|
||||
// result in a 404 error. Otherwise the server returns
|
||||
// a 500 error for files not found.
|
||||
if strings.Contains(err.Error(), "not found") {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Close no need do anything
|
||||
func (f *assetFile) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Readdir read dir's children file info
|
||||
func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) {
|
||||
if len(f.childInfos) == 0 {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
if count <= 0 {
|
||||
return f.childInfos, nil
|
||||
}
|
||||
if f.childInfoOffset+count > len(f.childInfos) {
|
||||
count = len(f.childInfos) - f.childInfoOffset
|
||||
}
|
||||
offset := f.childInfoOffset
|
||||
f.childInfoOffset += count
|
||||
return f.childInfos[offset : offset+count], nil
|
||||
}
|
||||
|
||||
// Stat read file info from asset item
|
||||
func (f *assetFile) Stat() (os.FileInfo, error) {
|
||||
if len(f.childInfos) != 0 {
|
||||
return newDirFileInfo(f.name), nil
|
||||
}
|
||||
return AssetInfo(f.name)
|
||||
}
|
||||
|
||||
// newDirFileInfo return default dir file info
|
||||
func newDirFileInfo(name string) os.FileInfo {
|
||||
return &bindataFileInfo{
|
||||
name: name,
|
||||
size: 0,
|
||||
mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir
|
||||
modTime: time.Time{}}
|
||||
}
|
||||
|
||||
// AssetFile return a http.FileSystem instance that data backend by asset
|
||||
func AssetFile() http.FileSystem {
|
||||
return &assetOperator{}
|
||||
}
|
||||
|
||||
var _layoutsLayoutHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\xce\xc1\xa9\xc3\x30\x0c\x06\xe0\xf3\x33\x78\x07\xbd\x01\x8c\xc9\x5d\x78\x82\x9e\x4a\x17\x70\x6a\x51\x19\x94\xa4\x38\xca\xc1\x84\xec\x5e\xec\xba\x27\x49\xf0\x89\xff\x47\xd6\x45\x82\x35\xc8\x14\x53\x9b\x9a\x55\x28\xdc\x62\xdd\x0e\x45\xff\xbd\xac\xb1\x06\xfd\x4f\xcc\x5b\xaa\xc1\x9a\x3f\xe4\x29\x3c\x38\xef\x90\x77\x50\x26\x78\xc9\x36\x47\x01\x19\xaf\x3c\x75\x34\x17\xf0\x7d\xf9\x77\x0e\xee\xb4\x26\x2a\x5d\x3f\x8f\x52\x68\x55\x50\x5a\xde\x12\x95\x80\xa9\x10\x38\xd7\xec\x79\x42\xcd\x24\x09\xae\xab\x05\x8f\x40\xf4\xa3\xeb\x27\x00\x00\xff\xff\x68\xca\x16\xc2\xb4\x00\x00\x00")
|
||||
|
||||
func layoutsLayoutHtmlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_templatesLayoutsLayoutHtml,
|
||||
"templates/layouts/layout.html",
|
||||
_layoutsLayoutHtml,
|
||||
"layouts/layout.html",
|
||||
)
|
||||
}
|
||||
|
||||
func templatesLayoutsLayoutHtml() (*asset, error) {
|
||||
bytes, err := templatesLayoutsLayoutHtmlBytes()
|
||||
func layoutsLayoutHtml() (*asset, error) {
|
||||
bytes, err := layoutsLayoutHtmlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "templates/layouts/layout.html", size: 180, mode: os.FileMode(438), modTime: time.Unix(1565946441, 0)}
|
||||
info := bindataFileInfo{name: "layouts/layout.html", size: 180, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _templatesLayoutsMylayoutHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x8f\x4d\x6a\xc5\x30\x0c\x84\xd7\x35\xf8\x0e\xd3\x03\x18\x93\xbd\xf1\x09\xba\x2a\xbd\x80\x53\xab\xc8\xe0\x9f\xe2\x28\x0b\x13\x72\xf7\x47\x9c\xbc\x95\x46\x62\x46\x7c\xe3\x58\x4a\xf6\x5a\x39\xa6\x10\xaf\x29\x49\x32\xf9\x32\xf0\x15\x46\xdb\xc5\xd9\xfb\xa0\x95\x56\xce\xbe\x4d\x6b\x8b\xc3\x6b\xf5\xe1\x78\xf1\x3f\x9c\x36\xa4\x0d\xc2\x84\x3c\x33\xf8\x6b\x7d\xae\xb6\x0c\x8b\x50\xe3\x14\x4d\x98\x3a\x7a\xdb\x85\x36\xb4\x9a\x87\xb3\xbc\xcc\x27\x6b\x87\x9d\xe2\xd3\x18\x7c\x53\x8d\x74\xc7\x7f\xf7\xde\xa9\x0a\x84\xca\x7f\x0e\x42\x60\xea\x04\x63\x2e\xef\x71\x60\x24\xca\x11\xe7\x79\x81\x3d\x40\xce\x3e\x75\x5e\x01\x00\x00\xff\xff\x64\xea\xc5\x1d\xd7\x00\x00\x00")
|
||||
var _layoutsMylayoutHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x8f\x4d\x6a\xc5\x30\x0c\x84\xd7\x35\xf8\x0e\xd3\x03\x18\x93\xbd\xf1\x09\xba\x2a\xbd\x80\x53\xab\xc8\xe0\x9f\xe2\x28\x0b\x13\x72\xf7\x47\x9c\xbc\x95\x46\x62\x46\x7c\xe3\x58\x4a\xf6\x5a\x39\xa6\x10\xaf\x29\x49\x32\xf9\x32\xf0\x15\x46\xdb\xc5\xd9\xfb\xa0\x95\x56\xce\xbe\x4d\x6b\x8b\xc3\x6b\xf5\xe1\x78\xf1\x3f\x9c\x36\xa4\x0d\xc2\x84\x3c\x33\xf8\x6b\x7d\xae\xb6\x0c\x8b\x50\xe3\x14\x4d\x98\x3a\x7a\xdb\x85\x36\xb4\x9a\x87\xb3\xbc\xcc\x27\x6b\x87\x9d\xe2\xd3\x18\x7c\x53\x8d\x74\xc7\x7f\xf7\xde\xa9\x0a\x84\xca\x7f\x0e\x42\x60\xea\x04\x63\x2e\xef\x71\x60\x24\xca\x11\xe7\x79\x81\x3d\x40\xce\x3e\x75\x5e\x01\x00\x00\xff\xff\x64\xea\xc5\x1d\xd7\x00\x00\x00")
|
||||
|
||||
func templatesLayoutsMylayoutHtmlBytes() ([]byte, error) {
|
||||
func layoutsMylayoutHtmlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_templatesLayoutsMylayoutHtml,
|
||||
"templates/layouts/mylayout.html",
|
||||
_layoutsMylayoutHtml,
|
||||
"layouts/mylayout.html",
|
||||
)
|
||||
}
|
||||
|
||||
func templatesLayoutsMylayoutHtml() (*asset, error) {
|
||||
bytes, err := templatesLayoutsMylayoutHtmlBytes()
|
||||
func layoutsMylayoutHtml() (*asset, error) {
|
||||
bytes, err := layoutsMylayoutHtmlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "templates/layouts/mylayout.html", size: 215, mode: os.FileMode(438), modTime: time.Unix(1565946441, 0)}
|
||||
info := bindataFileInfo{name: "layouts/mylayout.html", size: 215, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _templatesPage1Html = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x3c\xca\x41\xaa\xc2\x30\x10\x00\xd0\xf5\x2f\xf4\x0e\xc3\xec\xbf\x25\x5b\x8d\x3d\x83\x37\x90\x69\x33\xa4\xa1\x63\x53\x26\x69\x40\x42\xee\x2e\xa2\xb8\x7c\xf0\xac\x0b\x05\x52\x7e\x0a\x5f\x71\xa2\x79\xf5\x1a\x8f\xcd\xfd\xcf\x51\xa2\x9e\x61\x12\x9a\xd7\x0b\xfc\x74\x30\x8e\x7d\xd7\x77\x7f\x76\x31\xe3\x8d\x3c\x83\x81\x5a\xc1\x2b\x73\x06\x0c\x1a\x12\x38\x2e\x2c\x71\x67\xc5\xd6\xec\xb0\x98\xcf\xaf\x15\x94\x37\xc7\x0a\xb8\x93\xe6\x40\x92\x86\x9d\x3c\x9b\xfb\x97\xe6\xb4\xe4\x87\x60\x6b\xef\x6e\x07\x17\xca\xd8\x77\xaf\x00\x00\x00\xff\xff\x47\x41\x4a\x5c\x9d\x00\x00\x00")
|
||||
var _page1Html = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x3c\xca\x41\xaa\xc2\x30\x10\x00\xd0\xf5\x2f\xf4\x0e\xc3\xec\xbf\x25\x5b\x8d\x3d\x83\x37\x90\x69\x33\xa4\xa1\x63\x53\x26\x69\x40\x42\xee\x2e\xa2\xb8\x7c\xf0\xac\x0b\x05\x52\x7e\x0a\x5f\x71\xa2\x79\xf5\x1a\x8f\xcd\xfd\xcf\x51\xa2\x9e\x61\x12\x9a\xd7\x0b\xfc\x74\x30\x8e\x7d\xd7\x77\x7f\x76\x31\xe3\x8d\x3c\x83\x81\x5a\xc1\x2b\x73\x06\x0c\x1a\x12\x38\x2e\x2c\x71\x67\xc5\xd6\xec\xb0\x98\xcf\xaf\x15\x94\x37\xc7\x0a\xb8\x93\xe6\x40\x92\x86\x9d\x3c\x9b\xfb\x97\xe6\xb4\xe4\x87\x60\x6b\xef\x6e\x07\x17\xca\xd8\x77\xaf\x00\x00\x00\xff\xff\x47\x41\x4a\x5c\x9d\x00\x00\x00")
|
||||
|
||||
func templatesPage1HtmlBytes() ([]byte, error) {
|
||||
func page1HtmlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_templatesPage1Html,
|
||||
"templates/page1.html",
|
||||
_page1Html,
|
||||
"page1.html",
|
||||
)
|
||||
}
|
||||
|
||||
func templatesPage1Html() (*asset, error) {
|
||||
bytes, err := templatesPage1HtmlBytes()
|
||||
func page1Html() (*asset, error) {
|
||||
bytes, err := page1HtmlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "templates/page1.html", size: 157, mode: os.FileMode(438), modTime: time.Unix(1565946441, 0)}
|
||||
info := bindataFileInfo{name: "page1.html", size: 157, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _templatesPartialsPage1_partial1Html = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb2\x49\xc9\x2c\x53\x28\x2e\xa9\xcc\x49\xb5\x55\x4a\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x28\xcf\xc8\x2c\x49\xb5\x56\x80\xf2\x8a\x52\x53\x94\xec\x78\xb9\x38\x6d\x32\x0c\xed\x02\x12\xd3\x53\x15\x0c\xd5\x8b\x15\x02\x12\x8b\x4a\x32\x13\x73\x14\x0c\x6d\xf4\x33\x0c\xed\x78\xb9\x6c\xf4\x53\x32\xcb\xec\x78\xb9\x00\x01\x00\x00\xff\xff\xa2\xa6\x60\xb6\x59\x00\x00\x00")
|
||||
var _partialsPage1_partial1Html = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb2\x49\xc9\x2c\x53\x28\x2e\xa9\xcc\x49\xb5\x55\x4a\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x28\xcf\xc8\x2c\x49\xb5\x56\x80\xf2\x8a\x52\x53\x94\xec\x78\xb9\x38\x6d\x32\x0c\xed\x02\x12\xd3\x53\x15\x0c\xd5\x8b\x15\x02\x12\x8b\x4a\x32\x13\x73\x14\x0c\x6d\xf4\x33\x0c\xed\x78\xb9\x6c\xf4\x53\x32\xcb\xec\x78\xb9\x00\x01\x00\x00\xff\xff\xa2\xa6\x60\xb6\x59\x00\x00\x00")
|
||||
|
||||
func templatesPartialsPage1_partial1HtmlBytes() ([]byte, error) {
|
||||
func partialsPage1_partial1HtmlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_templatesPartialsPage1_partial1Html,
|
||||
"templates/partials/page1_partial1.html",
|
||||
_partialsPage1_partial1Html,
|
||||
"partials/page1_partial1.html",
|
||||
)
|
||||
}
|
||||
|
||||
func templatesPartialsPage1_partial1Html() (*asset, error) {
|
||||
bytes, err := templatesPartialsPage1_partial1HtmlBytes()
|
||||
func partialsPage1_partial1Html() (*asset, error) {
|
||||
bytes, err := partialsPage1_partial1HtmlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "templates/partials/page1_partial1.html", size: 89, mode: os.FileMode(438), modTime: time.Unix(1565946441, 0)}
|
||||
info := bindataFileInfo{name: "partials/page1_partial1.html", size: 89, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -212,10 +300,10 @@ func AssetNames() []string {
|
|||
|
||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
"templates/layouts/layout.html": templatesLayoutsLayoutHtml,
|
||||
"templates/layouts/mylayout.html": templatesLayoutsMylayoutHtml,
|
||||
"templates/page1.html": templatesPage1Html,
|
||||
"templates/partials/page1_partial1.html": templatesPartialsPage1_partial1Html,
|
||||
"layouts/layout.html": layoutsLayoutHtml,
|
||||
"layouts/mylayout.html": layoutsMylayoutHtml,
|
||||
"page1.html": page1Html,
|
||||
"partials/page1_partial1.html": partialsPage1_partial1Html,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
|
@ -259,15 +347,13 @@ type bintree struct {
|
|||
}
|
||||
|
||||
var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"templates": {nil, map[string]*bintree{
|
||||
"layouts": {nil, map[string]*bintree{
|
||||
"layout.html": {templatesLayoutsLayoutHtml, map[string]*bintree{}},
|
||||
"mylayout.html": {templatesLayoutsMylayoutHtml, map[string]*bintree{}},
|
||||
}},
|
||||
"page1.html": {templatesPage1Html, map[string]*bintree{}},
|
||||
"partials": {nil, map[string]*bintree{
|
||||
"page1_partial1.html": {templatesPartialsPage1_partial1Html, map[string]*bintree{}},
|
||||
}},
|
||||
"layouts": {nil, map[string]*bintree{
|
||||
"layout.html": {layoutsLayoutHtml, map[string]*bintree{}},
|
||||
"mylayout.html": {layoutsMylayoutHtml, map[string]*bintree{}},
|
||||
}},
|
||||
"page1.html": {page1Html, map[string]*bintree{}},
|
||||
"partials": {nil, map[string]*bintree{
|
||||
"page1_partial1.html": {partialsPage1_partial1Html, map[string]*bintree{}},
|
||||
}},
|
||||
}}
|
||||
|
||||
|
|
|
@ -1,24 +1,22 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris/v12"
|
||||
)
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
tmpl := iris.HTML("./templates", ".html")
|
||||
// $ go get -u github.com/go-bindata/go-bindata
|
||||
// # OR: go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// # to save it to your go.mod file
|
||||
// $ go-bindata -fs -prefix "templates" ./templates/...
|
||||
// $ go run .
|
||||
// html files are not used, you can delete the folder and run the example.
|
||||
tmpl := iris.HTML(AssetFile(), ".html")
|
||||
tmpl.Layout("layouts/layout.html")
|
||||
tmpl.AddFunc("greet", func(s string) string {
|
||||
return "Greetings " + s + "!"
|
||||
})
|
||||
|
||||
// $ go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// $ go-bindata ./templates/...
|
||||
// $ go run .
|
||||
// html files are not used, you can delete the folder and run the example.
|
||||
tmpl.Binary(Asset, AssetNames) // <-- IMPORTANT
|
||||
|
||||
app.RegisterView(tmpl)
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
|
@ -54,8 +52,3 @@ func main() {
|
|||
// http://localhost:8080/my/other
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
// Note for new Gophers:
|
||||
// `go build` is used instead of `go run main.go` as the example comments says
|
||||
// otherwise you will get compile errors, this is a Go thing;
|
||||
// because you have multiple files in the `package main`.
|
||||
|
|
|
@ -3,4 +3,5 @@ html
|
|||
head
|
||||
title Main Page
|
||||
body
|
||||
h1 Layout
|
||||
{{ yield }}
|
20
_examples/view/template_amber_0/main.go
Normal file
20
_examples/view/template_amber_0/main.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package main
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
// Read about its markup syntax at: https://github.com/eknkc/amber
|
||||
tmpl := iris.Amber("./views", ".amber")
|
||||
|
||||
app.RegisterView(tmpl)
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.View("index.amber", iris.Map{
|
||||
"Title": "Title of The Page",
|
||||
})
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
11
_examples/view/template_amber_0/views/index.amber
Normal file
11
_examples/view/template_amber_0/views/index.amber
Normal file
|
@ -0,0 +1,11 @@
|
|||
extends layouts/main.amber
|
||||
|
||||
block append meta
|
||||
meta[name="keywords"][content="These are added by the child template"]
|
||||
|
||||
block menu
|
||||
li Item 1
|
||||
li Item 2
|
||||
|
||||
block content
|
||||
p Content from child template
|
15
_examples/view/template_amber_0/views/layouts/main.amber
Normal file
15
_examples/view/template_amber_0/views/layouts/main.amber
Normal file
|
@ -0,0 +1,15 @@
|
|||
!!! transitional
|
||||
html
|
||||
head
|
||||
title #{Title}
|
||||
|
||||
block meta
|
||||
meta[name="description"][value="This is a sample"]
|
||||
|
||||
body
|
||||
header#mainHeader
|
||||
ul
|
||||
block menu
|
||||
|
||||
div#content
|
||||
block content
|
357
_examples/view/template_amber_1_embedded/bindata.go
Normal file
357
_examples/view/template_amber_1_embedded/bindata.go
Normal file
|
@ -0,0 +1,357 @@
|
|||
// Code generated by go-bindata. (@generated) DO NOT EDIT.
|
||||
|
||||
// Package main generated by go-bindata.// sources:
|
||||
// ../template_amber_0/views/index.amber
|
||||
// ../template_amber_0/views/layouts/main.amber
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"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 os.FileInfo
|
||||
}
|
||||
|
||||
type bindataFileInfo struct {
|
||||
name string
|
||||
size int64
|
||||
mode os.FileMode
|
||||
modTime time.Time
|
||||
}
|
||||
|
||||
// Name return file name
|
||||
func (fi bindataFileInfo) Name() string {
|
||||
return fi.name
|
||||
}
|
||||
|
||||
// Size return file size
|
||||
func (fi bindataFileInfo) Size() int64 {
|
||||
return fi.size
|
||||
}
|
||||
|
||||
// Mode return file mode
|
||||
func (fi bindataFileInfo) Mode() os.FileMode {
|
||||
return fi.mode
|
||||
}
|
||||
|
||||
// ModTime return file modify time
|
||||
func (fi bindataFileInfo) ModTime() time.Time {
|
||||
return fi.modTime
|
||||
}
|
||||
|
||||
// IsDir return file whether a directory
|
||||
func (fi bindataFileInfo) IsDir() bool {
|
||||
return fi.mode&os.ModeDir != 0
|
||||
}
|
||||
|
||||
// Sys return file is sys mode
|
||||
func (fi bindataFileInfo) Sys() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
type assetFile struct {
|
||||
*bytes.Reader
|
||||
name string
|
||||
childInfos []os.FileInfo
|
||||
childInfoOffset int
|
||||
}
|
||||
|
||||
type assetOperator struct{}
|
||||
|
||||
// Open implement http.FileSystem interface
|
||||
func (f *assetOperator) Open(name string) (http.File, error) {
|
||||
var err error
|
||||
if len(name) > 0 && name[0] == '/' {
|
||||
name = name[1:]
|
||||
}
|
||||
content, err := Asset(name)
|
||||
if err == nil {
|
||||
return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil
|
||||
}
|
||||
children, err := AssetDir(name)
|
||||
if err == nil {
|
||||
childInfos := make([]os.FileInfo, 0, len(children))
|
||||
for _, child := range children {
|
||||
childPath := filepath.Join(name, child)
|
||||
info, errInfo := AssetInfo(filepath.Join(name, child))
|
||||
if errInfo == nil {
|
||||
childInfos = append(childInfos, info)
|
||||
} else {
|
||||
childInfos = append(childInfos, newDirFileInfo(childPath))
|
||||
}
|
||||
}
|
||||
return &assetFile{name: name, childInfos: childInfos}, nil
|
||||
} else {
|
||||
// If the error is not found, return an error that will
|
||||
// result in a 404 error. Otherwise the server returns
|
||||
// a 500 error for files not found.
|
||||
if strings.Contains(err.Error(), "not found") {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Close no need do anything
|
||||
func (f *assetFile) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Readdir read dir's children file info
|
||||
func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) {
|
||||
if len(f.childInfos) == 0 {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
if count <= 0 {
|
||||
return f.childInfos, nil
|
||||
}
|
||||
if f.childInfoOffset+count > len(f.childInfos) {
|
||||
count = len(f.childInfos) - f.childInfoOffset
|
||||
}
|
||||
offset := f.childInfoOffset
|
||||
f.childInfoOffset += count
|
||||
return f.childInfos[offset : offset+count], nil
|
||||
}
|
||||
|
||||
// Stat read file info from asset item
|
||||
func (f *assetFile) Stat() (os.FileInfo, error) {
|
||||
if len(f.childInfos) != 0 {
|
||||
return newDirFileInfo(f.name), nil
|
||||
}
|
||||
return AssetInfo(f.name)
|
||||
}
|
||||
|
||||
// newDirFileInfo return default dir file info
|
||||
func newDirFileInfo(name string) os.FileInfo {
|
||||
return &bindataFileInfo{
|
||||
name: name,
|
||||
size: 0,
|
||||
mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir
|
||||
modTime: time.Time{}}
|
||||
}
|
||||
|
||||
// AssetFile return a http.FileSystem instance that data backend by asset
|
||||
func AssetFile() http.FileSystem {
|
||||
return &assetOperator{}
|
||||
}
|
||||
|
||||
var _indexAmber = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x5c\x8d\x31\x8a\xc3\x30\x14\x44\x7b\x83\xef\x30\xe8\x00\xbb\xec\xf6\xae\xb6\xda\x3e\x9d\x71\xf1\x6d\x4d\xb0\xb1\xbe\x24\xa4\x6f\x12\xdf\x3e\x10\x07\x4c\xd2\xcd\x63\x86\x79\xbc\x1b\xa3\xaf\x08\xb2\xa7\xcd\xea\xb7\xca\x12\xbf\x44\x47\x96\xb6\x69\x9b\x31\xa4\x69\x85\xe4\xcc\xe8\xa1\x34\x69\x1b\x00\xcf\xd4\x47\x51\x76\x6e\xe5\x7e\x4b\xc5\x57\x37\xf4\x53\x8a\xc6\x68\x9d\xbb\xcc\xac\x84\x14\x42\xbc\xa7\xc7\xb8\xc3\x66\x62\x9a\x97\xe0\x61\xd4\x1c\xc4\xe8\x86\x53\xa0\x8c\xdb\xf1\x1c\x16\xfc\x1b\x15\x3f\xef\xf8\x7b\x6e\x5f\x96\xa3\xcf\xf8\x3b\x10\xd7\x92\xf4\xc3\xf0\x08\x00\x00\xff\xff\xaa\xd2\x87\xd5\xdb\x00\x00\x00")
|
||||
|
||||
func indexAmberBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_indexAmber,
|
||||
"index.amber",
|
||||
)
|
||||
}
|
||||
|
||||
func indexAmber() (*asset, error) {
|
||||
bytes, err := indexAmberBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "index.amber", size: 219, mode: os.FileMode(438), modTime: time.Unix(1599264617, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _layoutsMainAmber = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x54\x4e\xc1\xae\x83\x30\x0c\xbb\x23\xf1\x0f\xa1\x7c\x07\xf7\xf7\x01\xdc\x10\x87\x40\x23\x11\xbd\x34\x45\x34\x20\x4d\xd3\xfe\x7d\xea\xd8\x04\xf5\xa5\xae\xdd\xda\x6e\x9a\x06\x6c\x43\x4d\x6c\x1c\x15\xa5\xae\x16\x0b\x52\x57\x00\x00\x0b\xa1\x3f\x59\x86\xb1\x09\x41\xfb\xec\xf3\xf9\xaa\xab\xcb\x99\x24\xce\xff\x10\xc8\xf0\xd2\x32\xb2\x32\x28\x06\xea\x9c\xa7\x34\x6f\xbc\xe6\x0e\x37\x0e\x07\xca\x4e\x9d\xeb\x17\x4e\xc0\x09\x10\x12\x86\x55\xc8\x8d\xbf\xd4\x29\xfa\xc7\x95\x95\x77\xd0\xd6\x06\x64\xfd\xfb\xd0\xb2\x66\x97\xf2\x7e\x9f\xa4\xfb\x7d\xa8\xe7\xa3\x9d\xa3\x1a\xa9\x95\x5f\xce\xe7\x5f\xeb\x1d\x00\x00\xff\xff\x56\x99\x59\x53\x13\x01\x00\x00")
|
||||
|
||||
func layoutsMainAmberBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_layoutsMainAmber,
|
||||
"layouts/main.amber",
|
||||
)
|
||||
}
|
||||
|
||||
func layoutsMainAmber() (*asset, error) {
|
||||
bytes, err := layoutsMainAmberBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "layouts/main.amber", size: 275, mode: os.FileMode(438), modTime: time.Unix(1599263735, 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) {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; 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, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
|
||||
// MustAsset is like Asset but panics when Asset would return an error.
|
||||
// It simplifies safe initialization of global variables.
|
||||
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) {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; 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, fmt.Errorf("AssetInfo %s not found", name)
|
||||
}
|
||||
|
||||
// AssetNames returns the names of the assets.
|
||||
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){
|
||||
"index.amber": indexAmber,
|
||||
"layouts/main.amber": layoutsMainAmber,
|
||||
}
|
||||
|
||||
// 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("nonexistent") would return an error
|
||||
// AssetDir("") will return []string{"data"}.
|
||||
func AssetDir(name string) ([]string, error) {
|
||||
node := _bintree
|
||||
if len(name) != 0 {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
pathList := strings.Split(canonicalName, "/")
|
||||
for _, p := range pathList {
|
||||
node = node.Children[p]
|
||||
if node == nil {
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
if node.Func != nil {
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
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{nil, map[string]*bintree{
|
||||
"index.amber": {indexAmber, map[string]*bintree{}},
|
||||
"layouts": {nil, map[string]*bintree{
|
||||
"main.amber": {layoutsMainAmber, 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
|
||||
}
|
||||
err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
|
||||
}
|
30
_examples/view/template_amber_1_embedded/main.go
Normal file
30
_examples/view/template_amber_1_embedded/main.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package main
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
// $ go get -u github.com/go-bindata/go-bindata
|
||||
// # OR: go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// # to save it to your go.mod file
|
||||
//
|
||||
// $ go-bindata -fs -prefix "../template_amber_0/views" ../template_amber_0/views/...
|
||||
// $ go run .
|
||||
// # OR: go-bindata -fs -prefix "views" ./views/... if the views dir is rel to the executable.
|
||||
//
|
||||
// System files are not used, you can optionally delete the folder and run the example now.
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
// Read about its markup syntax at: https://github.com/eknkc/amber
|
||||
tmpl := iris.Amber(AssetFile(), ".amber")
|
||||
|
||||
app.RegisterView(tmpl)
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.View("index.amber", iris.Map{
|
||||
"Title": "Title of The Page",
|
||||
})
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
// Code generated by go-bindata. (@generated) DO NOT EDIT.
|
||||
|
||||
//Package main generated by go-bindata.// sources:
|
||||
// Package main generated by go-bindata.// sources:
|
||||
// ../template_blocks_0/views/500.html
|
||||
// ../template_blocks_0/views/index.html
|
||||
// ../template_blocks_0/views/layouts/error.html
|
||||
|
@ -14,6 +14,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -82,102 +83,188 @@ func (fi bindataFileInfo) Sys() interface{} {
|
|||
return nil
|
||||
}
|
||||
|
||||
var _views500Html = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x8f\xb1\x4e\xf3\x30\x14\x85\xf7\x48\x79\x87\xfb\x67\xe9\x8f\xd4\xa4\xea\x5a\x42\x37\x06\x06\xa6\x22\x21\x46\xc7\x3e\xad\x2d\x9c\x7b\x23\xdb\x49\x89\xa2\xbc\x3b\x6a\x5a\x04\x2c\xac\xf7\x7e\xe7\x3b\x3a\xf5\xbf\xb2\xa4\x37\xe9\x49\x2b\x26\x83\xa3\x63\x50\x2b\x01\x94\xac\x62\x12\x06\x35\x5e\xf4\x7b\x95\x67\x2f\x16\x17\x40\xf5\x3e\x2d\x77\x17\xa9\xd0\xc2\x09\x9c\x0a\x3a\x5b\xa7\x2d\x45\x2b\xbd\x37\xd4\x5c\xd2\xa0\x56\x39\xa6\x84\xb6\xf3\x2a\x61\x15\xa9\x11\x33\x56\x79\x76\x90\x35\x61\x00\x93\x3b\x92\x4b\xab\x48\xad\x8b\xd1\xf1\x89\xfe\x47\x80\x1c\x1b\x7c\x54\x36\xb5\xfe\x6e\x7d\x7d\x2b\x63\x60\x48\xf5\x49\x5a\x95\x9c\x56\xde\x8f\xd4\x8c\x4b\xc3\xe0\x70\x26\xf0\xc9\x31\xaa\x3c\x7b\xb5\x60\x1a\xa5\x27\x06\x0c\x25\xf9\x63\xce\x7a\xe1\xac\x1a\x70\xe1\x9a\x1b\x13\x3b\x68\x77\x74\x7a\x97\x67\x65\xb9\xcf\xb3\x69\xfa\x52\x7c\x0f\x9d\xe7\x3c\xab\xed\x76\xff\xc4\x09\x81\x95\xa7\x03\xc2\x80\x40\x8f\x21\x48\xa8\x37\x76\x7b\xcd\x81\xcd\x82\xfe\x92\xb4\x88\x51\x9d\x70\x93\x74\x14\xd3\xe8\xf1\x50\x68\xf1\x12\x76\x01\xe6\xbe\xd8\x4f\x53\xf5\x7c\xa5\xe6\xb9\xde\x74\x3f\x65\x9f\x01\x00\x00\xff\xff\xb3\xfa\x91\xbd\xaa\x01\x00\x00")
|
||||
type assetFile struct {
|
||||
*bytes.Reader
|
||||
name string
|
||||
childInfos []os.FileInfo
|
||||
childInfoOffset int
|
||||
}
|
||||
|
||||
func views500HtmlBytes() ([]byte, error) {
|
||||
type assetOperator struct{}
|
||||
|
||||
// Open implement http.FileSystem interface
|
||||
func (f *assetOperator) Open(name string) (http.File, error) {
|
||||
var err error
|
||||
if len(name) > 0 && name[0] == '/' {
|
||||
name = name[1:]
|
||||
}
|
||||
content, err := Asset(name)
|
||||
if err == nil {
|
||||
return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil
|
||||
}
|
||||
children, err := AssetDir(name)
|
||||
if err == nil {
|
||||
childInfos := make([]os.FileInfo, 0, len(children))
|
||||
for _, child := range children {
|
||||
childPath := filepath.Join(name, child)
|
||||
info, errInfo := AssetInfo(filepath.Join(name, child))
|
||||
if errInfo == nil {
|
||||
childInfos = append(childInfos, info)
|
||||
} else {
|
||||
childInfos = append(childInfos, newDirFileInfo(childPath))
|
||||
}
|
||||
}
|
||||
return &assetFile{name: name, childInfos: childInfos}, nil
|
||||
} else {
|
||||
// If the error is not found, return an error that will
|
||||
// result in a 404 error. Otherwise the server returns
|
||||
// a 500 error for files not found.
|
||||
if strings.Contains(err.Error(), "not found") {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Close no need do anything
|
||||
func (f *assetFile) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Readdir read dir's children file info
|
||||
func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) {
|
||||
if len(f.childInfos) == 0 {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
if count <= 0 {
|
||||
return f.childInfos, nil
|
||||
}
|
||||
if f.childInfoOffset+count > len(f.childInfos) {
|
||||
count = len(f.childInfos) - f.childInfoOffset
|
||||
}
|
||||
offset := f.childInfoOffset
|
||||
f.childInfoOffset += count
|
||||
return f.childInfos[offset : offset+count], nil
|
||||
}
|
||||
|
||||
// Stat read file info from asset item
|
||||
func (f *assetFile) Stat() (os.FileInfo, error) {
|
||||
if len(f.childInfos) != 0 {
|
||||
return newDirFileInfo(f.name), nil
|
||||
}
|
||||
return AssetInfo(f.name)
|
||||
}
|
||||
|
||||
// newDirFileInfo return default dir file info
|
||||
func newDirFileInfo(name string) os.FileInfo {
|
||||
return &bindataFileInfo{
|
||||
name: name,
|
||||
size: 0,
|
||||
mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir
|
||||
modTime: time.Time{}}
|
||||
}
|
||||
|
||||
// AssetFile return a http.FileSystem instance that data backend by asset
|
||||
func AssetFile() http.FileSystem {
|
||||
return &assetOperator{}
|
||||
}
|
||||
|
||||
var __500Html = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x8f\xb1\x4e\xf3\x30\x14\x85\xf7\x48\x79\x87\xfb\x67\xe9\x8f\xd4\xa4\xea\x5a\x42\x37\x06\x06\xa6\x22\x21\x46\xc7\x3e\xad\x2d\x9c\x7b\x23\xdb\x49\x89\xa2\xbc\x3b\x6a\x5a\x04\x2c\xac\xf7\x7e\xe7\x3b\x3a\xf5\xbf\xb2\xa4\x37\xe9\x49\x2b\x26\x83\xa3\x63\x50\x2b\x01\x94\xac\x62\x12\x06\x35\x5e\xf4\x7b\x95\x67\x2f\x16\x17\x40\xf5\x3e\x2d\x77\x17\xa9\xd0\xc2\x09\x9c\x0a\x3a\x5b\xa7\x2d\x45\x2b\xbd\x37\xd4\x5c\xd2\xa0\x56\x39\xa6\x84\xb6\xf3\x2a\x61\x15\xa9\x11\x33\x56\x79\x76\x90\x35\x61\x00\x93\x3b\x92\x4b\xab\x48\xad\x8b\xd1\xf1\x89\xfe\x47\x80\x1c\x1b\x7c\x54\x36\xb5\xfe\x6e\x7d\x7d\x2b\x63\x60\x48\xf5\x49\x5a\x95\x9c\x56\xde\x8f\xd4\x8c\x4b\xc3\xe0\x70\x26\xf0\xc9\x31\xaa\x3c\x7b\xb5\x60\x1a\xa5\x27\x06\x0c\x25\xf9\x63\xce\x7a\xe1\xac\x1a\x70\xe1\x9a\x1b\x13\x3b\x68\x77\x74\x7a\x97\x67\x65\xb9\xcf\xb3\x69\xfa\x52\x7c\x0f\x9d\xe7\x3c\xab\xed\x76\xff\xc4\x09\x81\x95\xa7\x03\xc2\x80\x40\x8f\x21\x48\xa8\x37\x76\x7b\xcd\x81\xcd\x82\xfe\x92\xb4\x88\x51\x9d\x70\x93\x74\x14\xd3\xe8\xf1\x50\x68\xf1\x12\x76\x01\xe6\xbe\xd8\x4f\x53\xf5\x7c\xa5\xe6\xb9\xde\x74\x3f\x65\x9f\x01\x00\x00\xff\xff\xb3\xfa\x91\xbd\xaa\x01\x00\x00")
|
||||
|
||||
func _500HtmlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_views500Html,
|
||||
"views/500.html",
|
||||
__500Html,
|
||||
"500.html",
|
||||
)
|
||||
}
|
||||
|
||||
func views500Html() (*asset, error) {
|
||||
bytes, err := views500HtmlBytes()
|
||||
func _500Html() (*asset, error) {
|
||||
bytes, err := _500HtmlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "views/500.html", size: 426, mode: os.FileMode(438), modTime: time.Unix(1596515591, 0)}
|
||||
info := bindataFileInfo{name: "500.html", size: 426, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _viewsIndexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb2\xc9\x30\xb4\xf3\xcc\x4b\x49\xad\x50\x70\xca\x4f\xa9\xb4\xd1\xcf\x30\xb4\x03\x04\x00\x00\xff\xff\xcc\x4b\x98\x69\x13\x00\x00\x00")
|
||||
var _indexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb2\xc9\x30\xb4\xf3\xcc\x4b\x49\xad\x50\x70\xca\x4f\xa9\xb4\xd1\xcf\x30\xb4\x03\x04\x00\x00\xff\xff\xcc\x4b\x98\x69\x13\x00\x00\x00")
|
||||
|
||||
func viewsIndexHtmlBytes() ([]byte, error) {
|
||||
func indexHtmlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_viewsIndexHtml,
|
||||
"views/index.html",
|
||||
_indexHtml,
|
||||
"index.html",
|
||||
)
|
||||
}
|
||||
|
||||
func viewsIndexHtml() (*asset, error) {
|
||||
bytes, err := viewsIndexHtmlBytes()
|
||||
func indexHtml() (*asset, error) {
|
||||
bytes, err := indexHtmlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "views/index.html", size: 19, mode: os.FileMode(438), modTime: time.Unix(1596514225, 0)}
|
||||
info := bindataFileInfo{name: "index.html", size: 19, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _viewsLayoutsErrorHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x54\x90\xbf\x4e\xf3\x40\x10\xc4\x7b\x4b\x7e\x87\xfd\xb6\xfe\x6c\x43\x47\x71\xe7\x26\x40\x0b\x45\x28\x28\x37\x77\xa3\xf8\xc4\xfd\x89\xe2\x55\x22\x74\xf2\xbb\xa3\x18\x83\x44\xb5\xda\x99\x9f\x66\x57\x63\xfe\x3d\xbe\xec\xf6\xef\xaf\x4f\x34\x69\x8a\x63\xdb\x98\xdb\xa4\x28\xf9\x68\x19\x99\x57\x05\xe2\xc7\xb6\x21\x22\x32\x09\x2a\xe4\x26\x39\xcf\x50\xcb\x6f\xfb\xe7\xee\x81\xff\x78\x59\x12\x2c\x5f\x02\xae\xa7\x72\x56\x26\x57\xb2\x22\xab\xe5\x6b\xf0\x3a\x59\x8f\x4b\x70\xe8\xd6\xe5\x3f\x85\x1c\x34\x48\xec\x66\x27\x11\xf6\xbe\xbf\xfb\xcd\xd2\xa0\x11\x63\xad\xfd\xae\x78\x2c\x8b\x19\xbe\x85\xb6\x31\xc3\xf6\x8e\x39\x14\xff\xb9\xe1\xb5\x92\x22\x9d\xa2\x28\x88\xb7\x8b\x4c\xfd\xb2\xb4\xcd\x0f\x70\x88\xc5\x7d\x10\x27\xcc\xb3\x1c\xb1\x9a\xb5\x22\xfb\x1b\x63\x86\x2d\xcb\x0c\x6b\x0b\x5f\x01\x00\x00\xff\xff\xbe\xb7\x11\x67\x15\x01\x00\x00")
|
||||
var _layoutsErrorHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x54\x90\xbf\x4e\xf3\x40\x10\xc4\x7b\x4b\x7e\x87\xfd\xb6\xfe\x6c\x43\x47\x71\xe7\x26\x40\x0b\x45\x28\x28\x37\x77\xa3\xf8\xc4\xfd\x89\xe2\x55\x22\x74\xf2\xbb\xa3\x18\x83\x44\xb5\xda\x99\x9f\x66\x57\x63\xfe\x3d\xbe\xec\xf6\xef\xaf\x4f\x34\x69\x8a\x63\xdb\x98\xdb\xa4\x28\xf9\x68\x19\x99\x57\x05\xe2\xc7\xb6\x21\x22\x32\x09\x2a\xe4\x26\x39\xcf\x50\xcb\x6f\xfb\xe7\xee\x81\xff\x78\x59\x12\x2c\x5f\x02\xae\xa7\x72\x56\x26\x57\xb2\x22\xab\xe5\x6b\xf0\x3a\x59\x8f\x4b\x70\xe8\xd6\xe5\x3f\x85\x1c\x34\x48\xec\x66\x27\x11\xf6\xbe\xbf\xfb\xcd\xd2\xa0\x11\x63\xad\xfd\xae\x78\x2c\x8b\x19\xbe\x85\xb6\x31\xc3\xf6\x8e\x39\x14\xff\xb9\xe1\xb5\x92\x22\x9d\xa2\x28\x88\xb7\x8b\x4c\xfd\xb2\xb4\xcd\x0f\x70\x88\xc5\x7d\x10\x27\xcc\xb3\x1c\xb1\x9a\xb5\x22\xfb\x1b\x63\x86\x2d\xcb\x0c\x6b\x0b\x5f\x01\x00\x00\xff\xff\xbe\xb7\x11\x67\x15\x01\x00\x00")
|
||||
|
||||
func viewsLayoutsErrorHtmlBytes() ([]byte, error) {
|
||||
func layoutsErrorHtmlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_viewsLayoutsErrorHtml,
|
||||
"views/layouts/error.html",
|
||||
_layoutsErrorHtml,
|
||||
"layouts/error.html",
|
||||
)
|
||||
}
|
||||
|
||||
func viewsLayoutsErrorHtml() (*asset, error) {
|
||||
bytes, err := viewsLayoutsErrorHtmlBytes()
|
||||
func layoutsErrorHtml() (*asset, error) {
|
||||
bytes, err := layoutsErrorHtmlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "views/layouts/error.html", size: 277, mode: os.FileMode(438), modTime: time.Unix(1596514340, 0)}
|
||||
info := bindataFileInfo{name: "layouts/error.html", size: 277, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _viewsLayoutsMainHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x54\x90\xb1\x4e\xf4\x30\x10\x84\xfb\x48\x79\x87\xf9\x5d\xff\x49\xa0\xa3\xb0\xd3\x70\xd0\x21\x28\x42\x41\xb9\x24\x1b\x62\xc9\x71\xa2\x64\xb9\x13\xb2\xfc\xee\xc8\x39\x0b\xe9\x2a\xcf\xfa\xb3\x66\xc6\xab\xff\x9d\x5e\x1f\xbb\x8f\xb7\x27\x4c\x32\xbb\xb6\x2c\x74\x3a\xe1\xc8\x7f\x19\xc5\x5e\x1d\x37\x4c\x43\x5b\x16\x00\xa0\x67\x16\x42\x3f\xd1\xb6\xb3\x18\xf5\xde\x3d\x57\x0f\xea\x86\x79\x9a\xd9\xa8\xb3\xe5\xcb\xba\x6c\xa2\xd0\x2f\x5e\xd8\x8b\x51\x17\x3b\xc8\x64\x06\x3e\xdb\x9e\xab\x63\xf8\x0f\xeb\xad\x58\x72\xd5\xde\x93\x63\x73\x5f\xdf\xfd\x79\x89\x15\xc7\x6d\x08\xb0\x23\xea\x2e\x0d\x88\x31\x84\x1b\xcd\x6e\x4f\xea\xc4\x23\x7d\x3b\xc1\x0b\x59\x8f\x03\x27\xe6\x07\xc4\xa8\x9b\xab\x4f\x59\xe8\x26\xff\x42\x7f\x2e\xc3\x4f\x4e\x09\x01\xc2\xf3\xea\x48\x18\x2a\x17\x55\xa8\x11\x63\x59\x94\x85\x1e\x97\x45\x78\x4b\x25\x56\xda\x52\x4f\xa8\x2c\xf6\xe6\xca\x14\xea\x14\x92\x1f\xa6\x94\xec\xae\x9b\x63\x9d\xbf\x01\x00\x00\xff\xff\x44\x95\x63\x98\x5e\x01\x00\x00")
|
||||
var _layoutsMainHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x54\x90\xb1\x4e\xf4\x30\x10\x84\xfb\x48\x79\x87\xf9\x5d\xff\x49\xa0\xa3\xb0\xd3\x70\xd0\x21\x28\x42\x41\xb9\x24\x1b\x62\xc9\x71\xa2\x64\xb9\x13\xb2\xfc\xee\xc8\x39\x0b\xe9\x2a\xcf\xfa\xb3\x66\xc6\xab\xff\x9d\x5e\x1f\xbb\x8f\xb7\x27\x4c\x32\xbb\xb6\x2c\x74\x3a\xe1\xc8\x7f\x19\xc5\x5e\x1d\x37\x4c\x43\x5b\x16\x00\xa0\x67\x16\x42\x3f\xd1\xb6\xb3\x18\xf5\xde\x3d\x57\x0f\xea\x86\x79\x9a\xd9\xa8\xb3\xe5\xcb\xba\x6c\xa2\xd0\x2f\x5e\xd8\x8b\x51\x17\x3b\xc8\x64\x06\x3e\xdb\x9e\xab\x63\xf8\x0f\xeb\xad\x58\x72\xd5\xde\x93\x63\x73\x5f\xdf\xfd\x79\x89\x15\xc7\x6d\x08\xb0\x23\xea\x2e\x0d\x88\x31\x84\x1b\xcd\x6e\x4f\xea\xc4\x23\x7d\x3b\xc1\x0b\x59\x8f\x03\x27\xe6\x07\xc4\xa8\x9b\xab\x4f\x59\xe8\x26\xff\x42\x7f\x2e\xc3\x4f\x4e\x09\x01\xc2\xf3\xea\x48\x18\x2a\x17\x55\xa8\x11\x63\x59\x94\x85\x1e\x97\x45\x78\x4b\x25\x56\xda\x52\x4f\xa8\x2c\xf6\xe6\xca\x14\xea\x14\x92\x1f\xa6\x94\xec\xae\x9b\x63\x9d\xbf\x01\x00\x00\xff\xff\x44\x95\x63\x98\x5e\x01\x00\x00")
|
||||
|
||||
func viewsLayoutsMainHtmlBytes() ([]byte, error) {
|
||||
func layoutsMainHtmlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_viewsLayoutsMainHtml,
|
||||
"views/layouts/main.html",
|
||||
_layoutsMainHtml,
|
||||
"layouts/main.html",
|
||||
)
|
||||
}
|
||||
|
||||
func viewsLayoutsMainHtml() (*asset, error) {
|
||||
bytes, err := viewsLayoutsMainHtmlBytes()
|
||||
func layoutsMainHtml() (*asset, error) {
|
||||
bytes, err := layoutsMainHtmlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "views/layouts/main.html", size: 350, mode: os.FileMode(438), modTime: time.Unix(1596514155, 0)}
|
||||
info := bindataFileInfo{name: "layouts/main.html", size: 350, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _viewsPartialsFooterHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb2\xc9\x30\xb6\x73\xcb\xcf\x2f\x49\x2d\x52\x08\x48\x2c\x2a\xc9\x4c\xcc\xb1\xd1\xcf\x30\xb6\x03\x04\x00\x00\xff\xff\x08\xe6\xe9\xf8\x17\x00\x00\x00")
|
||||
var _partialsFooterHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb2\xc9\x30\xb6\x73\xcb\xcf\x2f\x49\x2d\x52\x08\x48\x2c\x2a\xc9\x4c\xcc\xb1\xd1\xcf\x30\xb6\x03\x04\x00\x00\xff\xff\x08\xe6\xe9\xf8\x17\x00\x00\x00")
|
||||
|
||||
func viewsPartialsFooterHtmlBytes() ([]byte, error) {
|
||||
func partialsFooterHtmlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_viewsPartialsFooterHtml,
|
||||
"views/partials/footer.html",
|
||||
_partialsFooterHtml,
|
||||
"partials/footer.html",
|
||||
)
|
||||
}
|
||||
|
||||
func viewsPartialsFooterHtml() (*asset, error) {
|
||||
bytes, err := viewsPartialsFooterHtmlBytes()
|
||||
func partialsFooterHtml() (*asset, error) {
|
||||
bytes, err := partialsFooterHtmlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "views/partials/footer.html", size: 23, mode: os.FileMode(438), modTime: time.Unix(1596514093, 0)}
|
||||
info := bindataFileInfo{name: "partials/footer.html", size: 23, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -186,8 +273,8 @@ func viewsPartialsFooterHtml() (*asset, error) {
|
|||
// 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 {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
|
||||
|
@ -212,8 +299,8 @@ func MustAsset(name string) []byte {
|
|||
// 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 {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
|
||||
|
@ -234,11 +321,11 @@ func AssetNames() []string {
|
|||
|
||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
"views/500.html": views500Html,
|
||||
"views/index.html": viewsIndexHtml,
|
||||
"views/layouts/error.html": viewsLayoutsErrorHtml,
|
||||
"views/layouts/main.html": viewsLayoutsMainHtml,
|
||||
"views/partials/footer.html": viewsPartialsFooterHtml,
|
||||
"500.html": _500Html,
|
||||
"index.html": indexHtml,
|
||||
"layouts/error.html": layoutsErrorHtml,
|
||||
"layouts/main.html": layoutsMainHtml,
|
||||
"partials/footer.html": partialsFooterHtml,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
|
@ -252,13 +339,13 @@ var _bindata = map[string]func() (*asset, error){
|
|||
// 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("foo.txt") and AssetDir("nonexistent") 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, "/")
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
pathList := strings.Split(canonicalName, "/")
|
||||
for _, p := range pathList {
|
||||
node = node.Children[p]
|
||||
if node == nil {
|
||||
|
@ -282,16 +369,14 @@ type bintree struct {
|
|||
}
|
||||
|
||||
var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"views": {nil, map[string]*bintree{
|
||||
"500.html": {views500Html, map[string]*bintree{}},
|
||||
"index.html": {viewsIndexHtml, map[string]*bintree{}},
|
||||
"layouts": {nil, map[string]*bintree{
|
||||
"error.html": {viewsLayoutsErrorHtml, map[string]*bintree{}},
|
||||
"main.html": {viewsLayoutsMainHtml, map[string]*bintree{}},
|
||||
}},
|
||||
"partials": {nil, map[string]*bintree{
|
||||
"footer.html": {viewsPartialsFooterHtml, map[string]*bintree{}},
|
||||
}},
|
||||
"500.html": {_500Html, map[string]*bintree{}},
|
||||
"index.html": {indexHtml, map[string]*bintree{}},
|
||||
"layouts": {nil, map[string]*bintree{
|
||||
"error.html": {layoutsErrorHtml, map[string]*bintree{}},
|
||||
"main.html": {layoutsMainHtml, map[string]*bintree{}},
|
||||
}},
|
||||
"partials": {nil, map[string]*bintree{
|
||||
"footer.html": {partialsFooterHtml, map[string]*bintree{}},
|
||||
}},
|
||||
}}
|
||||
|
||||
|
@ -338,6 +423,6 @@ func RestoreAssets(dir, name string) error {
|
|||
}
|
||||
|
||||
func _filePath(dir, name string) string {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
|
||||
}
|
||||
|
|
|
@ -2,15 +2,21 @@ package main
|
|||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
// $ go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// $ go-bindata -prefix "../template_blocks_0" ../template_blocks_0/views/...
|
||||
// $ go get -u github.com/go-bindata/go-bindata
|
||||
// # OR: go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// # to save it to your go.mod file
|
||||
//
|
||||
// $ go-bindata -fs -prefix "../template_blocks_0/views" ../template_blocks_0/views/...
|
||||
// $ go run .
|
||||
// # OR go-bindata -prefix "../template_blocks_0/views" ../template_blocks_0/views/... with iris.Blocks("").Binary(...)
|
||||
//
|
||||
// # OR: go-bindata -fs -prefix "views" ./views/... if the views dir is rel to the executable.
|
||||
// # OR: go-bindata -fs -prefix "../template_blocks_0" ../template_blocks_0/views/...
|
||||
// # with iris.Blocks(AssetFile()).RootDir("/views")
|
||||
//
|
||||
// System files are not used, you can optionally delete the folder and run the example now.
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.RegisterView(iris.Blocks("./views", ".html").Binary(Asset, AssetNames))
|
||||
app.RegisterView(iris.Blocks(AssetFile(), ".html"))
|
||||
|
||||
app.Get("/", index)
|
||||
app.Get("/500", internalServerError)
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
# 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/go-bindata/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/go-bindata/go-bindata/v3/go-bindata
|
||||
$ 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.
|
|
@ -1,5 +1,6 @@
|
|||
// Code generated by go-bindata. DO NOT EDIT.
|
||||
// sources:
|
||||
// Code generated by go-bindata. (@generated) DO NOT EDIT.
|
||||
|
||||
// Package main generated by go-bindata.// sources:
|
||||
// views/includes/_partial.jet
|
||||
// views/includes/blocks.jet
|
||||
// views/index.jet
|
||||
|
@ -12,6 +13,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -21,7 +23,7 @@ import (
|
|||
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)
|
||||
return nil, fmt.Errorf("read %q: %v", name, err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
@ -29,7 +31,7 @@ func bindataRead(data []byte, name string) ([]byte, error) {
|
|||
clErr := gz.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||
return nil, fmt.Errorf("read %q: %v", name, err)
|
||||
}
|
||||
if clErr != nil {
|
||||
return nil, err
|
||||
|
@ -50,101 +52,198 @@ type bindataFileInfo struct {
|
|||
modTime time.Time
|
||||
}
|
||||
|
||||
// Name return file name
|
||||
func (fi bindataFileInfo) Name() string {
|
||||
return fi.name
|
||||
}
|
||||
|
||||
// Size return file size
|
||||
func (fi bindataFileInfo) Size() int64 {
|
||||
return fi.size
|
||||
}
|
||||
|
||||
// Mode return file mode
|
||||
func (fi bindataFileInfo) Mode() os.FileMode {
|
||||
return fi.mode
|
||||
}
|
||||
|
||||
// ModTime return file modify time
|
||||
func (fi bindataFileInfo) ModTime() time.Time {
|
||||
return fi.modTime
|
||||
}
|
||||
|
||||
// IsDir return file whether a directory
|
||||
func (fi bindataFileInfo) IsDir() bool {
|
||||
return false
|
||||
return fi.mode&os.ModeDir != 0
|
||||
}
|
||||
|
||||
// Sys return file is sys mode
|
||||
func (fi bindataFileInfo) Sys() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
var _viewsIncludes_partialJet = []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\xe5\x02\x04\x00\x00\xff\xff\x90\x62\x4f\xfb\x19\x00\x00\x00")
|
||||
type assetFile struct {
|
||||
*bytes.Reader
|
||||
name string
|
||||
childInfos []os.FileInfo
|
||||
childInfoOffset int
|
||||
}
|
||||
|
||||
func viewsIncludes_partialJetBytes() ([]byte, error) {
|
||||
type assetOperator struct{}
|
||||
|
||||
// Open implement http.FileSystem interface
|
||||
func (f *assetOperator) Open(name string) (http.File, error) {
|
||||
var err error
|
||||
if len(name) > 0 && name[0] == '/' {
|
||||
name = name[1:]
|
||||
}
|
||||
content, err := Asset(name)
|
||||
if err == nil {
|
||||
return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil
|
||||
}
|
||||
children, err := AssetDir(name)
|
||||
if err == nil {
|
||||
childInfos := make([]os.FileInfo, 0, len(children))
|
||||
for _, child := range children {
|
||||
childPath := filepath.Join(name, child)
|
||||
info, errInfo := AssetInfo(filepath.Join(name, child))
|
||||
if errInfo == nil {
|
||||
childInfos = append(childInfos, info)
|
||||
} else {
|
||||
childInfos = append(childInfos, newDirFileInfo(childPath))
|
||||
}
|
||||
}
|
||||
return &assetFile{name: name, childInfos: childInfos}, nil
|
||||
} else {
|
||||
// If the error is not found, return an error that will
|
||||
// result in a 404 error. Otherwise the server returns
|
||||
// a 500 error for files not found.
|
||||
if strings.Contains(err.Error(), "not found") {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Close no need do anything
|
||||
func (f *assetFile) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Readdir read dir's children file info
|
||||
func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) {
|
||||
if len(f.childInfos) == 0 {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
if count <= 0 {
|
||||
return f.childInfos, nil
|
||||
}
|
||||
if f.childInfoOffset+count > len(f.childInfos) {
|
||||
count = len(f.childInfos) - f.childInfoOffset
|
||||
}
|
||||
offset := f.childInfoOffset
|
||||
f.childInfoOffset += count
|
||||
return f.childInfos[offset : offset+count], nil
|
||||
}
|
||||
|
||||
// Stat read file info from asset item
|
||||
func (f *assetFile) Stat() (os.FileInfo, error) {
|
||||
if len(f.childInfos) != 0 {
|
||||
return newDirFileInfo(f.name), nil
|
||||
}
|
||||
return AssetInfo(f.name)
|
||||
}
|
||||
|
||||
// newDirFileInfo return default dir file info
|
||||
func newDirFileInfo(name string) os.FileInfo {
|
||||
return &bindataFileInfo{
|
||||
name: name,
|
||||
size: 0,
|
||||
mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir
|
||||
modTime: time.Time{}}
|
||||
}
|
||||
|
||||
// AssetFile return a http.FileSystem instance that data backend by asset
|
||||
func AssetFile() http.FileSystem {
|
||||
return &assetOperator{}
|
||||
}
|
||||
|
||||
var _includes_partialJet = []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\xe5\x02\x04\x00\x00\xff\xff\x90\x62\x4f\xfb\x19\x00\x00\x00")
|
||||
|
||||
func includes_partialJetBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_viewsIncludes_partialJet,
|
||||
"views/includes/_partial.jet",
|
||||
_includes_partialJet,
|
||||
"includes/_partial.jet",
|
||||
)
|
||||
}
|
||||
|
||||
func viewsIncludes_partialJet() (*asset, error) {
|
||||
bytes, err := viewsIncludes_partialJetBytes()
|
||||
func includes_partialJet() (*asset, error) {
|
||||
bytes, err := includes_partialJetBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "views/includes/_partial.jet", size: 25, mode: os.FileMode(438), modTime: time.Unix(1565946441, 0)}
|
||||
info := bindataFileInfo{name: "includes/_partial.jet", size: 25, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _viewsIncludesBlocksJet = []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\xe5\x52\x50\xb0\x29\xb0\x0b\xc9\x48\x05\x0b\x29\x40\x64\xcb\x13\x8b\x15\x32\xf3\xca\xf2\xb3\x53\x53\xf4\x6c\xf4\x0b\xec\x78\xb9\xaa\xab\x53\xf3\x52\x40\xca\x01\x01\x00\x00\xff\xff\xa0\xd9\xd9\x5d\x41\x00\x00\x00")
|
||||
var _includesBlocksJet = []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\xe5\x52\x50\xb0\x29\xb0\x0b\xc9\x48\x05\x0b\x29\x40\x64\xcb\x13\x8b\x15\x32\xf3\xca\xf2\xb3\x53\x53\xf4\x6c\xf4\x0b\xec\x78\xb9\xaa\xab\x53\xf3\x52\x40\xca\x01\x01\x00\x00\xff\xff\xa0\xd9\xd9\x5d\x41\x00\x00\x00")
|
||||
|
||||
func viewsIncludesBlocksJetBytes() ([]byte, error) {
|
||||
func includesBlocksJetBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_viewsIncludesBlocksJet,
|
||||
"views/includes/blocks.jet",
|
||||
_includesBlocksJet,
|
||||
"includes/blocks.jet",
|
||||
)
|
||||
}
|
||||
|
||||
func viewsIncludesBlocksJet() (*asset, error) {
|
||||
bytes, err := viewsIncludesBlocksJetBytes()
|
||||
func includesBlocksJet() (*asset, error) {
|
||||
bytes, err := includesBlocksJetBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "views/includes/blocks.jet", size: 65, mode: os.FileMode(438), modTime: time.Unix(1565946441, 0)}
|
||||
info := bindataFileInfo{name: "includes/blocks.jet", size: 65, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _viewsIndexJet = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x64\x90\xb1\x6a\xf3\x30\x14\x85\xf7\x1f\xfe\x77\x38\xf5\xd2\x74\xa9\xc9\x5a\x8c\x87\x42\x86\x2e\x5d\xfa\x00\x45\xb6\x6e\xb0\x1a\x59\x57\xf8\x5e\xd7\x36\x22\xef\x5e\x2c\x9b\x10\xda\xed\x48\xe7\x3b\xe8\x43\x29\xd1\xac\x14\xac\xa0\xf0\x66\xe1\x51\xa5\x34\x31\x7a\xd7\x1a\x75\x1c\x9e\xbf\x48\x8b\xeb\xf5\xff\xbf\x94\x5c\x1f\x79\x50\x14\x2e\xb4\x7e\xb4\x24\x65\xe3\xb9\xbd\xc8\x8d\x58\x99\x7c\x05\xcb\xed\xd8\x53\xd0\x57\xb6\xcb\xe1\x69\xed\x80\xaa\x3b\xd6\xa7\xbe\x21\x6b\xc9\x82\x66\xd3\x47\x4f\x55\xd9\x1d\xeb\x75\x08\x54\xc1\x7c\xd7\x6b\x00\x52\x5a\x1c\x79\x8b\x9e\xc2\x78\x5b\x97\x5b\xbf\xe6\x94\x76\x83\x3b\x95\xcf\x68\x06\x75\xc6\xdf\xc9\x64\xf0\x8c\x87\x9d\x79\x3b\x9f\x66\x27\x2a\x87\xc2\x32\xc9\x3b\x6b\x3e\x66\x7e\x7f\x03\xa8\x62\xfd\xd1\xf1\x24\xe8\x78\xfa\x33\xc4\xc4\xc3\x45\x5e\xf0\x7b\x8e\xc9\x08\x02\x2b\x76\xde\xa2\xa1\xd6\x8c\x42\x70\x9a\xe1\xf0\xa8\xa0\x4c\x57\x65\xac\x37\x31\x0a\x76\xfb\xd4\x3d\xfc\x04\x00\x00\xff\xff\x28\x5a\x9d\x42\x85\x01\x00\x00")
|
||||
var _indexJet = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x64\x90\xb1\x6a\xf3\x30\x14\x85\xf7\x1f\xfe\x77\x38\xf5\xd2\x74\xa9\xc9\x5a\x8c\x87\x42\x86\x2e\x5d\xfa\x00\x45\xb6\x6e\xb0\x1a\x59\x57\xf8\x5e\xd7\x36\x22\xef\x5e\x2c\x9b\x10\xda\xed\x48\xe7\x3b\xe8\x43\x29\xd1\xac\x14\xac\xa0\xf0\x66\xe1\x51\xa5\x34\x31\x7a\xd7\x1a\x75\x1c\x9e\xbf\x48\x8b\xeb\xf5\xff\xbf\x94\x5c\x1f\x79\x50\x14\x2e\xb4\x7e\xb4\x24\x65\xe3\xb9\xbd\xc8\x8d\x58\x99\x7c\x05\xcb\xed\xd8\x53\xd0\x57\xb6\xcb\xe1\x69\xed\x80\xaa\x3b\xd6\xa7\xbe\x21\x6b\xc9\x82\x66\xd3\x47\x4f\x55\xd9\x1d\xeb\x75\x08\x54\xc1\x7c\xd7\x6b\x00\x52\x5a\x1c\x79\x8b\x9e\xc2\x78\x5b\x97\x5b\xbf\xe6\x94\x76\x83\x3b\x95\xcf\x68\x06\x75\xc6\xdf\xc9\x64\xf0\x8c\x87\x9d\x79\x3b\x9f\x66\x27\x2a\x87\xc2\x32\xc9\x3b\x6b\x3e\x66\x7e\x7f\x03\xa8\x62\xfd\xd1\xf1\x24\xe8\x78\xfa\x33\xc4\xc4\xc3\x45\x5e\xf0\x7b\x8e\xc9\x08\x02\x2b\x76\xde\xa2\xa1\xd6\x8c\x42\x70\x9a\xe1\xf0\xa8\xa0\x4c\x57\x65\xac\x37\x31\x0a\x76\xfb\xd4\x3d\xfc\x04\x00\x00\xff\xff\x28\x5a\x9d\x42\x85\x01\x00\x00")
|
||||
|
||||
func viewsIndexJetBytes() ([]byte, error) {
|
||||
func indexJetBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_viewsIndexJet,
|
||||
"views/index.jet",
|
||||
_indexJet,
|
||||
"index.jet",
|
||||
)
|
||||
}
|
||||
|
||||
func viewsIndexJet() (*asset, error) {
|
||||
bytes, err := viewsIndexJetBytes()
|
||||
func indexJet() (*asset, error) {
|
||||
bytes, err := indexJetBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "views/index.jet", size: 389, mode: os.FileMode(438), modTime: time.Unix(1594059793, 0)}
|
||||
info := bindataFileInfo{name: "index.jet", size: 389, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _viewsLayoutsApplicationJet = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x3c\x8e\xbd\xae\xc2\x30\x0c\x85\xf7\x4a\x7d\x07\xdf\x4c\x97\x01\x75\x65\x70\x3b\x00\x65\x85\xa1\x0c\x8c\x69\x6d\x11\x44\x7e\x10\x18\x89\x2a\xca\xbb\x23\xda\xc0\x64\xcb\x3e\xdf\xa7\x83\x7f\xdb\xfd\xa6\x3b\x1d\x5a\x30\xe2\x6c\x53\x16\xf8\x99\x60\xb5\x3f\xd7\x8a\xbd\x6a\xca\x02\x00\x0d\x6b\x9a\x36\x00\x74\x2c\x1a\x06\xa3\xef\x0f\x96\x5a\x1d\xbb\xdd\x72\xa5\xbe\x3f\xb9\x88\xe5\xa6\x75\x3d\x13\x31\x01\xbf\xb4\xbb\x59\xc6\x6a\xbe\x4f\xaa\xea\xe7\xc2\x3e\xd0\x98\xc9\x18\x7b\x1b\x86\x2b\x50\x18\x9e\x8e\xbd\xac\x03\x8d\xff\x8b\x94\x62\x64\x4f\x29\xcd\x64\xce\x63\x95\xab\xbe\x03\x00\x00\xff\xff\xee\xc2\x94\xa4\xbc\x00\x00\x00")
|
||||
var _layoutsApplicationJet = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x3c\x8e\xbd\xae\xc2\x30\x0c\x85\xf7\x4a\x7d\x07\xdf\x4c\x97\x01\x75\x65\x70\x3b\x00\x65\x85\xa1\x0c\x8c\x69\x6d\x11\x44\x7e\x10\x18\x89\x2a\xca\xbb\x23\xda\xc0\x64\xcb\x3e\xdf\xa7\x83\x7f\xdb\xfd\xa6\x3b\x1d\x5a\x30\xe2\x6c\x53\x16\xf8\x99\x60\xb5\x3f\xd7\x8a\xbd\x6a\xca\x02\x00\x0d\x6b\x9a\x36\x00\x74\x2c\x1a\x06\xa3\xef\x0f\x96\x5a\x1d\xbb\xdd\x72\xa5\xbe\x3f\xb9\x88\xe5\xa6\x75\x3d\x13\x31\x01\xbf\xb4\xbb\x59\xc6\x6a\xbe\x4f\xaa\xea\xe7\xc2\x3e\xd0\x98\xc9\x18\x7b\x1b\x86\x2b\x50\x18\x9e\x8e\xbd\xac\x03\x8d\xff\x8b\x94\x62\x64\x4f\x29\xcd\x64\xce\x63\x95\xab\xbe\x03\x00\x00\xff\xff\xee\xc2\x94\xa4\xbc\x00\x00\x00")
|
||||
|
||||
func viewsLayoutsApplicationJetBytes() ([]byte, error) {
|
||||
func layoutsApplicationJetBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_viewsLayoutsApplicationJet,
|
||||
"views/layouts/application.jet",
|
||||
_layoutsApplicationJet,
|
||||
"layouts/application.jet",
|
||||
)
|
||||
}
|
||||
|
||||
func viewsLayoutsApplicationJet() (*asset, error) {
|
||||
bytes, err := viewsLayoutsApplicationJetBytes()
|
||||
func layoutsApplicationJet() (*asset, error) {
|
||||
bytes, err := layoutsApplicationJetBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "views/layouts/application.jet", size: 188, mode: os.FileMode(438), modTime: time.Unix(1565946441, 0)}
|
||||
info := bindataFileInfo{name: "layouts/application.jet", size: 188, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -153,8 +252,8 @@ func viewsLayoutsApplicationJet() (*asset, error) {
|
|||
// 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 {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
|
||||
|
@ -179,8 +278,8 @@ func MustAsset(name string) []byte {
|
|||
// 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 {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
|
||||
|
@ -201,10 +300,10 @@ func AssetNames() []string {
|
|||
|
||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
"views/includes/_partial.jet": viewsIncludes_partialJet,
|
||||
"views/includes/blocks.jet": viewsIncludesBlocksJet,
|
||||
"views/index.jet": viewsIndexJet,
|
||||
"views/layouts/application.jet": viewsLayoutsApplicationJet,
|
||||
"includes/_partial.jet": includes_partialJet,
|
||||
"includes/blocks.jet": includesBlocksJet,
|
||||
"index.jet": indexJet,
|
||||
"layouts/application.jet": layoutsApplicationJet,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
|
@ -218,13 +317,13 @@ var _bindata = map[string]func() (*asset, error){
|
|||
// 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("foo.txt") and AssetDir("nonexistent") 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, "/")
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
pathList := strings.Split(canonicalName, "/")
|
||||
for _, p := range pathList {
|
||||
node = node.Children[p]
|
||||
if node == nil {
|
||||
|
@ -248,15 +347,13 @@ type bintree struct {
|
|||
}
|
||||
|
||||
var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"views": {nil, map[string]*bintree{
|
||||
"includes": {nil, map[string]*bintree{
|
||||
"_partial.jet": {viewsIncludes_partialJet, map[string]*bintree{}},
|
||||
"blocks.jet": {viewsIncludesBlocksJet, map[string]*bintree{}},
|
||||
}},
|
||||
"index.jet": {viewsIndexJet, map[string]*bintree{}},
|
||||
"layouts": {nil, map[string]*bintree{
|
||||
"application.jet": {viewsLayoutsApplicationJet, map[string]*bintree{}},
|
||||
}},
|
||||
"includes": {nil, map[string]*bintree{
|
||||
"_partial.jet": {includes_partialJet, map[string]*bintree{}},
|
||||
"blocks.jet": {includesBlocksJet, map[string]*bintree{}},
|
||||
}},
|
||||
"index.jet": {indexJet, map[string]*bintree{}},
|
||||
"layouts": {nil, map[string]*bintree{
|
||||
"application.jet": {layoutsApplicationJet, map[string]*bintree{}},
|
||||
}},
|
||||
}}
|
||||
|
||||
|
@ -303,6 +400,6 @@ func RestoreAssets(dir, name string) error {
|
|||
}
|
||||
|
||||
func _filePath(dir, name string) string {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
|
||||
}
|
||||
|
|
|
@ -6,29 +6,31 @@ package main
|
|||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
)
|
||||
|
||||
// $ go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// $ go-bindata ./views/...
|
||||
// $ go get -u github.com/go-bindata/go-bindata
|
||||
// # OR: go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// # to save it to your go.mod file
|
||||
//
|
||||
// $ go-bindata -fs -prefix "views" ./views/...
|
||||
// $ go run .
|
||||
//
|
||||
// System files are not used, you can optionally delete the folder and run the example now.
|
||||
func main() {
|
||||
app := iris.New()
|
||||
tmpl := iris.Jet("./views", ".jet").Binary(Asset, AssetNames)
|
||||
tmpl := iris.Jet(AssetFile(), ".jet")
|
||||
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
|
||||
addr := ":8080"
|
||||
if port := os.Getenv("PORT"); port != "" {
|
||||
addr = ":" + port
|
||||
}
|
||||
|
||||
app.Listen(port)
|
||||
app.Listen(addr)
|
||||
}
|
||||
|
|
|
@ -9,8 +9,6 @@ import (
|
|||
"github.com/kataras/iris/v12/view"
|
||||
)
|
||||
|
||||
// https://github.com/kataras/iris/issues/1443
|
||||
|
||||
func main() {
|
||||
|
||||
tmpl := iris.Jet("./views", ".jet")
|
||||
|
@ -44,12 +42,12 @@ func (ViewBuiler) Asset(a view.JetArguments) reflect.Value {
|
|||
|
||||
func (ViewBuiler) Style(a view.JetArguments) reflect.Value {
|
||||
path := a.Get(0).String()
|
||||
s := fmt.Sprintf(`<link href="%v" rel="stylesheet"> `, path)
|
||||
s := fmt.Sprintf(`<link href="%v" rel="stylesheet">`, path)
|
||||
return reflect.ValueOf(s)
|
||||
}
|
||||
|
||||
func (ViewBuiler) Script(a view.JetArguments) reflect.Value {
|
||||
path := a.Get(0).String()
|
||||
s := fmt.Sprintf(`<script src="%v" ></script>`, path)
|
||||
s := fmt.Sprintf(`<script src="%v"></script>`, path)
|
||||
return reflect.ValueOf(s)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,16 @@
|
|||
{{ asset("./myasset.mp3")}}
|
||||
<br/>
|
||||
{{ style("my-stle.css")}}
|
||||
{{ style("my-stle.css") | raw}}
|
||||
<br/>
|
||||
{{ script("my-script.js")}}
|
||||
{{ script("my-script.js") | raw}}
|
||||
|
||||
<!-- view page source: can't add a link as chrome blocks loading local source, instead
|
||||
do that: -->
|
||||
|
||||
<code>
|
||||
./myasset.mp3
|
||||
<br/>
|
||||
<link href="my-stle.css" rel="stylesheet">
|
||||
<br/>
|
||||
<script src="my-script.js"></script>
|
||||
</code>
|
|
@ -1,16 +1,24 @@
|
|||
// Package main shows an example of pug actions based on https://github.com/Joker/jade/tree/master/example/actions
|
||||
package main
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
Emails []string
|
||||
Jobs []*Job
|
||||
}
|
||||
|
||||
type Job struct {
|
||||
Employer string
|
||||
Role string
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
tmpl := iris.Pug("./templates", ".pug")
|
||||
tmpl.Reload(true) // reload templates on each request (development mode)
|
||||
tmpl.AddFunc("greet", func(s string) string { // add your template func here.
|
||||
return "Greetings " + s + "!"
|
||||
})
|
||||
|
||||
app.RegisterView(tmpl)
|
||||
|
||||
app.Get("/", index)
|
||||
|
@ -20,9 +28,15 @@ func main() {
|
|||
}
|
||||
|
||||
func index(ctx iris.Context) {
|
||||
ctx.ViewData("pageTitle", "My Index Page")
|
||||
ctx.ViewData("youAreUsingJade", true)
|
||||
// Q: why need extension .pug?
|
||||
// A: Because you can register more than one view engine per Iris application.
|
||||
ctx.View("index.pug")
|
||||
job1 := Job{Employer: "Monash B", Role: "Honorary"}
|
||||
job2 := Job{Employer: "Box Hill", Role: "Head of HE"}
|
||||
|
||||
person := Person{
|
||||
Name: "jan",
|
||||
Age: 50,
|
||||
Emails: []string{"jan@newmarch.name", "jan.newmarch@gmail.com"},
|
||||
Jobs: []*Job{&job1, &job2},
|
||||
}
|
||||
|
||||
ctx.View("index.pug", person)
|
||||
}
|
||||
|
|
|
@ -1,25 +1,20 @@
|
|||
mixin withGo
|
||||
| Generating Go html/template output.
|
||||
|
||||
doctype html
|
||||
html(lang="en")
|
||||
head
|
||||
title= .pageTitle
|
||||
script(type='text/javascript').
|
||||
if (foo) {
|
||||
bar(1 + 5)
|
||||
}
|
||||
body
|
||||
h1 Jade - template engine
|
||||
#container.col
|
||||
if .youAreUsingJade
|
||||
p {{ greet "iris user" }} <!-- execute template funcs -->
|
||||
p You are amazing!
|
||||
else
|
||||
p Get on it!
|
||||
p.
|
||||
Jade is #[a(terse)] and simple
|
||||
templating language with a
|
||||
#[strong focus] on performance
|
||||
and powerful features.
|
||||
+ withGo
|
||||
head
|
||||
meta(charset="utf-8")
|
||||
title Title
|
||||
body
|
||||
p ads
|
||||
ul
|
||||
li The name is {{.Name}}.
|
||||
li The age is {{.Age}}.
|
||||
|
||||
each _,_ in .Emails
|
||||
div An email is {{.}}
|
||||
|
||||
| {{ with .Jobs }}
|
||||
each _,_ in .
|
||||
div
|
||||
An employer is {{.Employer}}
|
||||
and the role is {{.Role}}
|
||||
| {{ end }}
|
|
@ -1,24 +1,20 @@
|
|||
// Package main shows an example of pug actions based on https://github.com/Joker/jade/tree/master/example/actions
|
||||
package main
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
import (
|
||||
"html/template"
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
Emails []string
|
||||
Jobs []*Job
|
||||
}
|
||||
|
||||
type Job struct {
|
||||
Employer string
|
||||
Role string
|
||||
}
|
||||
"github.com/kataras/iris/v12"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
tmpl := iris.Pug("./templates", ".pug")
|
||||
tmpl.Reload(true) // reload templates on each request (development mode)
|
||||
tmpl.AddFunc("bold", func(s string) (template.HTML, error) { // add your template func here.
|
||||
return template.HTML("<b>" + s + "</b>"), nil
|
||||
})
|
||||
|
||||
app.RegisterView(tmpl)
|
||||
|
||||
app.Get("/", index)
|
||||
|
@ -28,15 +24,5 @@ func main() {
|
|||
}
|
||||
|
||||
func index(ctx iris.Context) {
|
||||
job1 := Job{Employer: "Monash B", Role: "Honorary"}
|
||||
job2 := Job{Employer: "Box Hill", Role: "Head of HE"}
|
||||
|
||||
person := Person{
|
||||
Name: "jan",
|
||||
Age: 50,
|
||||
Emails: []string{"jan@newmarch.name", "jan.newmarch@gmail.com"},
|
||||
Jobs: []*Job{&job1, &job2},
|
||||
}
|
||||
|
||||
ctx.View("index.pug", person)
|
||||
ctx.View("index.pug")
|
||||
}
|
||||
|
|
|
@ -1,20 +1,7 @@
|
|||
doctype html
|
||||
html(lang="en")
|
||||
head
|
||||
meta(charset="utf-8")
|
||||
title Title
|
||||
body
|
||||
p ads
|
||||
ul
|
||||
li The name is {{.Name}}.
|
||||
li The age is {{.Age}}.
|
||||
|
||||
each _,_ in .Emails
|
||||
div An email is {{.}}
|
||||
|
||||
| {{ with .Jobs }}
|
||||
each _,_ in .
|
||||
div
|
||||
An employer is {{.Employer}}
|
||||
and the role is {{.Role}}
|
||||
| {{ end }}
|
||||
html
|
||||
include header.pug
|
||||
body
|
||||
h1 My Site
|
||||
p {{ bold "Welcome to my super lame site."}}
|
||||
include footer.pug
|
|
@ -1,28 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
tmpl := iris.Pug("./templates", ".pug")
|
||||
tmpl.Reload(true) // reload templates on each request (development mode)
|
||||
tmpl.AddFunc("bold", func(s string) (template.HTML, error) { // add your template func here.
|
||||
return template.HTML("<b>" + s + "</b>"), nil
|
||||
})
|
||||
|
||||
app.RegisterView(tmpl)
|
||||
|
||||
app.Get("/", index)
|
||||
|
||||
// http://localhost:8080
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func index(ctx iris.Context) {
|
||||
ctx.View("index.pug")
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
doctype html
|
||||
html
|
||||
include header.pug
|
||||
body
|
||||
h1 My Site
|
||||
p {{ bold "Welcome to my super lame site."}}
|
||||
include footer.pug
|
|
@ -1,5 +1,6 @@
|
|||
// Code generated for package main by go-bindata DO NOT EDIT. (@generated)
|
||||
// sources:
|
||||
// Code generated by go-bindata. (@generated) DO NOT EDIT.
|
||||
|
||||
// Package main generated by go-bindata.// sources:
|
||||
// templates/index.pug
|
||||
// templates/layout.pug
|
||||
package main
|
||||
|
@ -10,6 +11,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -19,7 +21,7 @@ import (
|
|||
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)
|
||||
return nil, fmt.Errorf("read %q: %v", name, err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
@ -27,7 +29,7 @@ func bindataRead(data []byte, name string) ([]byte, error) {
|
|||
clErr := gz.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||
return nil, fmt.Errorf("read %q: %v", name, err)
|
||||
}
|
||||
if clErr != nil {
|
||||
return nil, err
|
||||
|
@ -63,7 +65,7 @@ func (fi bindataFileInfo) Mode() os.FileMode {
|
|||
return fi.mode
|
||||
}
|
||||
|
||||
// Mode return file modify time
|
||||
// ModTime return file modify time
|
||||
func (fi bindataFileInfo) ModTime() time.Time {
|
||||
return fi.modTime
|
||||
}
|
||||
|
@ -78,42 +80,128 @@ func (fi bindataFileInfo) Sys() interface{} {
|
|||
return nil
|
||||
}
|
||||
|
||||
var _templatesIndexPug = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xad\x28\x49\xcd\x4b\x29\x56\xc8\x49\xac\xcc\x2f\x2d\xd1\x2b\x28\x4d\xe7\xe5\xe2\xe5\x4a\xca\xc9\x4f\xce\x56\x28\xc9\x2c\xc9\x49\xe5\xe5\x52\x80\x30\x14\x1c\x8b\x4a\x32\x93\x73\x52\x15\x42\x20\xc2\x30\x55\xc9\xf9\x79\x25\xa9\x79\x25\x20\x75\x19\x86\x0a\xbe\x95\x30\x75\x80\x00\x00\x00\xff\xff\xa6\xfd\x18\x8c\x5a\x00\x00\x00")
|
||||
type assetFile struct {
|
||||
*bytes.Reader
|
||||
name string
|
||||
childInfos []os.FileInfo
|
||||
childInfoOffset int
|
||||
}
|
||||
|
||||
func templatesIndexPugBytes() ([]byte, error) {
|
||||
type assetOperator struct{}
|
||||
|
||||
// Open implement http.FileSystem interface
|
||||
func (f *assetOperator) Open(name string) (http.File, error) {
|
||||
var err error
|
||||
if len(name) > 0 && name[0] == '/' {
|
||||
name = name[1:]
|
||||
}
|
||||
content, err := Asset(name)
|
||||
if err == nil {
|
||||
return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil
|
||||
}
|
||||
children, err := AssetDir(name)
|
||||
if err == nil {
|
||||
childInfos := make([]os.FileInfo, 0, len(children))
|
||||
for _, child := range children {
|
||||
childPath := filepath.Join(name, child)
|
||||
info, errInfo := AssetInfo(filepath.Join(name, child))
|
||||
if errInfo == nil {
|
||||
childInfos = append(childInfos, info)
|
||||
} else {
|
||||
childInfos = append(childInfos, newDirFileInfo(childPath))
|
||||
}
|
||||
}
|
||||
return &assetFile{name: name, childInfos: childInfos}, nil
|
||||
} else {
|
||||
// If the error is not found, return an error that will
|
||||
// result in a 404 error. Otherwise the server returns
|
||||
// a 500 error for files not found.
|
||||
if strings.Contains(err.Error(), "not found") {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Close no need do anything
|
||||
func (f *assetFile) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Readdir read dir's children file info
|
||||
func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) {
|
||||
if len(f.childInfos) == 0 {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
if count <= 0 {
|
||||
return f.childInfos, nil
|
||||
}
|
||||
if f.childInfoOffset+count > len(f.childInfos) {
|
||||
count = len(f.childInfos) - f.childInfoOffset
|
||||
}
|
||||
offset := f.childInfoOffset
|
||||
f.childInfoOffset += count
|
||||
return f.childInfos[offset : offset+count], nil
|
||||
}
|
||||
|
||||
// Stat read file info from asset item
|
||||
func (f *assetFile) Stat() (os.FileInfo, error) {
|
||||
if len(f.childInfos) != 0 {
|
||||
return newDirFileInfo(f.name), nil
|
||||
}
|
||||
return AssetInfo(f.name)
|
||||
}
|
||||
|
||||
// newDirFileInfo return default dir file info
|
||||
func newDirFileInfo(name string) os.FileInfo {
|
||||
return &bindataFileInfo{
|
||||
name: name,
|
||||
size: 0,
|
||||
mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir
|
||||
modTime: time.Time{}}
|
||||
}
|
||||
|
||||
// AssetFile return a http.FileSystem instance that data backend by asset
|
||||
func AssetFile() http.FileSystem {
|
||||
return &assetOperator{}
|
||||
}
|
||||
|
||||
var _indexPug = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xad\x28\x49\xcd\x4b\x29\x56\xc8\x49\xac\xcc\x2f\x2d\xd1\x2b\x28\x4d\xe7\xe5\xe2\xe5\x4a\xca\xc9\x4f\xce\x56\x28\xc9\x2c\xc9\x49\xe5\xe5\x52\x80\x30\x14\x1c\x8b\x4a\x32\x93\x73\x52\x15\x42\x20\xc2\x30\x55\xc9\xf9\x79\x25\xa9\x79\x25\x20\x75\x19\x86\x0a\xbe\x95\x30\x75\x80\x00\x00\x00\xff\xff\xa6\xfd\x18\x8c\x5a\x00\x00\x00")
|
||||
|
||||
func indexPugBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_templatesIndexPug,
|
||||
"templates/index.pug",
|
||||
_indexPug,
|
||||
"index.pug",
|
||||
)
|
||||
}
|
||||
|
||||
func templatesIndexPug() (*asset, error) {
|
||||
bytes, err := templatesIndexPugBytes()
|
||||
func indexPug() (*asset, error) {
|
||||
bytes, err := indexPugBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "templates/index.pug", size: 90, mode: os.FileMode(438), modTime: time.Unix(1581790962, 0)}
|
||||
info := bindataFileInfo{name: "index.pug", size: 90, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _templatesLayoutPug = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xc9\x4f\x2e\xa9\x2c\x48\x55\xc8\x28\xc9\xcd\xe1\xe5\x82\x90\x0a\x0a\x19\xa9\x89\x29\x20\x5a\x41\x21\x29\x27\x3f\x39\x5b\xa1\x24\xb3\x24\x27\x15\x22\xa0\x00\xe1\x28\xb8\xa4\xa6\x25\x96\xe6\x94\x20\xa4\x92\xf2\x53\x2a\x91\xf5\x24\xe7\xe7\x95\xa4\xe6\x95\x00\x02\x00\x00\xff\xff\x5f\xa5\x93\xf9\x61\x00\x00\x00")
|
||||
var _layoutPug = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xc9\x4f\x2e\xa9\x2c\x48\x55\xc8\x28\xc9\xcd\xe1\xe5\x82\x90\x0a\x0a\x19\xa9\x89\x29\x20\x5a\x41\x21\x29\x27\x3f\x39\x5b\xa1\x24\xb3\x24\x27\x15\x22\xa0\x00\xe1\x28\xb8\xa4\xa6\x25\x96\xe6\x94\x20\xa4\x92\xf2\x53\x2a\x91\xf5\x24\xe7\xe7\x95\xa4\xe6\x95\x00\x02\x00\x00\xff\xff\x5f\xa5\x93\xf9\x61\x00\x00\x00")
|
||||
|
||||
func templatesLayoutPugBytes() ([]byte, error) {
|
||||
func layoutPugBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_templatesLayoutPug,
|
||||
"templates/layout.pug",
|
||||
_layoutPug,
|
||||
"layout.pug",
|
||||
)
|
||||
}
|
||||
|
||||
func templatesLayoutPug() (*asset, error) {
|
||||
bytes, err := templatesLayoutPugBytes()
|
||||
func layoutPug() (*asset, error) {
|
||||
bytes, err := layoutPugBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "templates/layout.pug", size: 97, mode: os.FileMode(438), modTime: time.Unix(1581790962, 0)}
|
||||
info := bindataFileInfo{name: "layout.pug", size: 97, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -122,8 +210,8 @@ func templatesLayoutPug() (*asset, error) {
|
|||
// 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 {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
|
||||
|
@ -148,8 +236,8 @@ func MustAsset(name string) []byte {
|
|||
// 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 {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
|
||||
|
@ -170,8 +258,8 @@ func AssetNames() []string {
|
|||
|
||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
"templates/index.pug": templatesIndexPug,
|
||||
"templates/layout.pug": templatesLayoutPug,
|
||||
"index.pug": indexPug,
|
||||
"layout.pug": layoutPug,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
|
@ -185,13 +273,13 @@ var _bindata = map[string]func() (*asset, error){
|
|||
// 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("foo.txt") and AssetDir("nonexistent") 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, "/")
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
pathList := strings.Split(canonicalName, "/")
|
||||
for _, p := range pathList {
|
||||
node = node.Children[p]
|
||||
if node == nil {
|
||||
|
@ -215,10 +303,8 @@ type bintree struct {
|
|||
}
|
||||
|
||||
var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"templates": {nil, map[string]*bintree{
|
||||
"index.pug": {templatesIndexPug, map[string]*bintree{}},
|
||||
"layout.pug": {templatesLayoutPug, map[string]*bintree{}},
|
||||
}},
|
||||
"index.pug": {indexPug, map[string]*bintree{}},
|
||||
"layout.pug": {layoutPug, map[string]*bintree{}},
|
||||
}}
|
||||
|
||||
// RestoreAsset restores an asset under the given directory
|
||||
|
@ -264,6 +350,6 @@ func RestoreAssets(dir, name string) error {
|
|||
}
|
||||
|
||||
func _filePath(dir, name string) string {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
|
||||
}
|
28
_examples/view/template_pug_2_embedded/main.go
Normal file
28
_examples/view/template_pug_2_embedded/main.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
package main
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
// $ go get -u github.com/go-bindata/go-bindata
|
||||
// # OR: go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// # to save it to your go.mod file
|
||||
//
|
||||
// $ go-bindata -fs -prefix "templates" ./templates/...
|
||||
// $ go run .
|
||||
//
|
||||
// System files are not used, you can optionally delete the folder and run the example now.
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
tmpl := iris.Pug(AssetFile(), ".pug")
|
||||
|
||||
app.RegisterView(tmpl)
|
||||
|
||||
app.Get("/", index)
|
||||
|
||||
// http://localhost:8080
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func index(ctx iris.Context) {
|
||||
ctx.View("index.pug")
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package main
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
// $ go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// $ go-bindata ./templates/...
|
||||
// $ go build
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
tmpl := iris.Pug("./templates", ".pug").Binary(Asset, AssetNames)
|
||||
|
||||
app.RegisterView(tmpl)
|
||||
|
||||
app.Get("/", index)
|
||||
|
||||
// http://localhost:8080
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func index(ctx iris.Context) {
|
||||
ctx.View("index.pug")
|
||||
}
|
|
@ -475,13 +475,28 @@ func (api *APIBuilder) HandleMany(methodOrMulti string, relativePathorMulti stri
|
|||
//
|
||||
// Returns all the registered routes, including GET index and path patterm and HEAD.
|
||||
//
|
||||
// Examples can be found at: https://github.com/kataras/iris/tree/master/_examples/file-server
|
||||
func (api *APIBuilder) HandleDir(requestPath string, fs http.FileSystem, opts ...DirOptions) (routes []*Route) {
|
||||
// Usage:
|
||||
// HandleDir("/public", "./assets", DirOptions{...}) or
|
||||
// HandleDir("/public", iris.Dir("./assets"), DirOptions{...})
|
||||
//
|
||||
// Examples:
|
||||
// https://github.com/kataras/iris/tree/master/_examples/file-server
|
||||
func (api *APIBuilder) HandleDir(requestPath string, fsOrDir interface{}, opts ...DirOptions) (routes []*Route) {
|
||||
options := DefaultDirOptions
|
||||
if len(opts) > 0 {
|
||||
options = opts[0]
|
||||
}
|
||||
|
||||
var fs http.FileSystem
|
||||
switch v := fsOrDir.(type) {
|
||||
case string:
|
||||
fs = http.Dir(v)
|
||||
case http.FileSystem:
|
||||
fs = v
|
||||
default:
|
||||
panic(fmt.Errorf(`unexpected "fsOrDir" argument type of %T (string or http.FileSystem)`, v))
|
||||
}
|
||||
|
||||
h := FileServer(fs, options)
|
||||
description := "file server"
|
||||
if d, ok := fs.(http.Dir); ok {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package router
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/kataras/iris/v12/context"
|
||||
"github.com/kataras/iris/v12/macro"
|
||||
|
||||
|
@ -201,8 +199,13 @@ type Party interface {
|
|||
//
|
||||
// Returns all the registered routes, including GET index and path patterm and HEAD.
|
||||
//
|
||||
// Examples can be found at: https://github.com/kataras/iris/tree/master/_examples/file-server
|
||||
HandleDir(requestPath string, fs http.FileSystem, opts ...DirOptions) []*Route
|
||||
// Usage:
|
||||
// HandleDir("/public", "./assets", DirOptions{...}) or
|
||||
// HandleDir("/public", iris.Dir("./assets"), DirOptions{...})
|
||||
//
|
||||
// Examples:
|
||||
// https://github.com/kataras/iris/tree/master/_examples/file-server
|
||||
HandleDir(requestPath string, fileSystem interface{}, opts ...DirOptions) []*Route
|
||||
|
||||
// None registers an "offline" route
|
||||
// see context.ExecRoute(routeName) and
|
||||
|
|
2
go.mod
2
go.mod
|
@ -19,7 +19,7 @@ require (
|
|||
github.com/iris-contrib/pongo2 v0.0.1
|
||||
github.com/iris-contrib/schema v0.0.6
|
||||
github.com/json-iterator/go v1.1.10
|
||||
github.com/kataras/blocks v0.0.2
|
||||
github.com/kataras/blocks v0.0.3
|
||||
github.com/kataras/golog v0.1.2
|
||||
github.com/kataras/neffos v0.0.16
|
||||
github.com/kataras/pio v0.0.10
|
||||
|
|
|
@ -115,11 +115,19 @@ func hi(ctx iris.Context) {
|
|||
|
||||
## Embedded
|
||||
|
||||
View engine supports bundled(https://github.com/go-bindata/go-bindata) template files too.
|
||||
`go-bindata` gives you two functions, `Assset` and `AssetNames`,
|
||||
these can be set to each of the template engines using the `.Binary` function.
|
||||
View engine supports bundled(https://github.com/go-bindata/go-bindata) template files too. Latest
|
||||
`go-bindata` release gives you a compatible `http.FileSystem` that can be provided as the first argument of a view engine's initialization, e.g. `HTML(AssetFile(), ".html")`.
|
||||
|
||||
Example code:
|
||||
|
||||
```sh
|
||||
$ go get -u github.com/go-bindata/go-bindata
|
||||
# OR: go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
# to save it to your go.mod file
|
||||
$ go-bindata -fs -prefix "templates" ./templates/...
|
||||
$ go run .
|
||||
```
|
||||
|
||||
Example Code:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
@ -128,12 +136,7 @@ import "github.com/kataras/iris/v12"
|
|||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
// $ go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
// $ go-bindata ./templates/...
|
||||
// $ go build
|
||||
// $ ./embedding-templates-into-app
|
||||
// html files are not used, you can delete the folder and run the example
|
||||
app.RegisterView(iris.HTML("./templates", ".html").Binary(Asset, AssetNames))
|
||||
app.RegisterView(iris.HTML(AssetFile(), ".html"))
|
||||
app.Get("/", hi)
|
||||
|
||||
// http://localhost:8080
|
||||
|
|
12
view/ace.go
12
view/ace.go
|
@ -1,7 +1,6 @@
|
|||
package view
|
||||
|
||||
import (
|
||||
"path"
|
||||
"sync"
|
||||
|
||||
"github.com/yosssi/ace"
|
||||
|
@ -13,8 +12,13 @@ import (
|
|||
// 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 {
|
||||
s := HTML(directory, extension)
|
||||
//
|
||||
// Usage:
|
||||
// Ace("./views", ".ace") or
|
||||
// Ace(iris.Dir("./views"), ".ace") or
|
||||
// Ace(AssetFile(), ".ace") for embedded data.
|
||||
func Ace(fs interface{}, extension string) *HTMLEngine {
|
||||
s := HTML(fs, extension)
|
||||
|
||||
funcs := make(map[string]interface{}, 0)
|
||||
|
||||
|
@ -30,7 +34,7 @@ func Ace(directory, extension string) *HTMLEngine {
|
|||
}
|
||||
})
|
||||
|
||||
name = path.Join(path.Clean(directory), name)
|
||||
// name = path.Join(path.Clean(directory), name)
|
||||
|
||||
src := ace.NewSource(
|
||||
ace.NewFile(name, text),
|
||||
|
|
164
view/amber.go
164
view/amber.go
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -14,11 +15,10 @@ import (
|
|||
|
||||
// AmberEngine contains the amber view engine structure.
|
||||
type AmberEngine struct {
|
||||
fs http.FileSystem
|
||||
// files configuration
|
||||
directory string
|
||||
rootDir string
|
||||
extension string
|
||||
assetFn func(name string) ([]byte, error) // for embedded, in combination with directory & extension
|
||||
namesFn func() []string // for embedded, in combination with directory & extension
|
||||
reload bool
|
||||
//
|
||||
rmu sync.RWMutex // locks for `ExecuteWiter` when `reload` is true.
|
||||
|
@ -33,9 +33,15 @@ var (
|
|||
|
||||
// Amber creates and returns a new amber view engine.
|
||||
// The given "extension" MUST begin with a dot.
|
||||
func Amber(directory, extension string) *AmberEngine {
|
||||
//
|
||||
// Usage:
|
||||
// Amber("./views", ".amber") or
|
||||
// Amber(iris.Dir("./views"), ".amber") or
|
||||
// Amber(AssetFile(), ".amber") for embedded data.
|
||||
func Amber(fs interface{}, extension string) *AmberEngine {
|
||||
s := &AmberEngine{
|
||||
directory: directory,
|
||||
fs: getFS(fs),
|
||||
rootDir: "/",
|
||||
extension: extension,
|
||||
templateCache: make(map[string]*template.Template),
|
||||
funcs: make(map[string]interface{}),
|
||||
|
@ -44,20 +50,18 @@ func Amber(directory, extension string) *AmberEngine {
|
|||
return s
|
||||
}
|
||||
|
||||
// RootDir sets the directory to be used as a starting point
|
||||
// to load templates from the provided file system.
|
||||
func (s *AmberEngine) RootDir(root string) *AmberEngine {
|
||||
s.rootDir = filepath.ToSlash(root)
|
||||
return s
|
||||
}
|
||||
|
||||
// Ext returns the file extension which this view engine is responsible to render.
|
||||
func (s *AmberEngine) Ext() string {
|
||||
return s.extension
|
||||
}
|
||||
|
||||
// Binary optionally, use it when template files are distributed
|
||||
// inside the app executable (.go generated files).
|
||||
//
|
||||
// The assetFn and namesFn can come from the go-bindata library.
|
||||
func (s *AmberEngine) Binary(assetFn func(name string) ([]byte, error), namesFn func() []string) *AmberEngine {
|
||||
s.assetFn, s.namesFn = assetFn, namesFn
|
||||
return s
|
||||
}
|
||||
|
||||
// Reload if set to true the templates are reloading on each render,
|
||||
// use it when you're in development and you're boring of restarting
|
||||
// the whole app when you edit a template file.
|
||||
|
@ -86,32 +90,8 @@ func (s *AmberEngine) AddFunc(funcName string, funcBody interface{}) {
|
|||
//
|
||||
// Returns an error if something bad happens, user is responsible to catch it.
|
||||
func (s *AmberEngine) Load() error {
|
||||
if s.assetFn != nil && s.namesFn != nil {
|
||||
// embedded
|
||||
return s.loadAssets()
|
||||
}
|
||||
|
||||
// load from directory, make the dir absolute here too.
|
||||
dir, err := filepath.Abs(s.directory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
// change the directory field configuration, load happens after directory has been set, so we will not have any problems here.
|
||||
s.directory = dir
|
||||
return s.loadDirectory()
|
||||
}
|
||||
|
||||
// loadDirectory loads the amber templates from directory.
|
||||
func (s *AmberEngine) loadDirectory() error {
|
||||
dir, extension := s.directory, s.extension
|
||||
|
||||
opt := amber.DirOptions{}
|
||||
opt.Recursive = true
|
||||
s.rmu.Lock()
|
||||
defer s.rmu.Unlock()
|
||||
|
||||
// prepare the global amber funcs
|
||||
funcs := template.FuncMap{}
|
||||
|
@ -125,84 +105,52 @@ func (s *AmberEngine) loadDirectory() error {
|
|||
}
|
||||
|
||||
amber.FuncMap = funcs // set the funcs
|
||||
opt.Ext = extension
|
||||
|
||||
templates, err := amber.CompileDir(dir, opt, amber.DefaultOptions) // this returns the map with stripped extension, we want extension so we copy the map
|
||||
if err == nil {
|
||||
s.templateCache = make(map[string]*template.Template)
|
||||
for k, v := range templates {
|
||||
name := filepath.ToSlash(k + opt.Ext)
|
||||
s.templateCache[name] = v
|
||||
delete(templates, k)
|
||||
}
|
||||
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// loadAssets builds the templates by binary, embedded.
|
||||
func (s *AmberEngine) loadAssets() error {
|
||||
virtualDirectory, virtualExtension := s.directory, s.extension
|
||||
assetFn, namesFn := s.assetFn, s.namesFn
|
||||
|
||||
// prepare the global amber funcs
|
||||
funcs := template.FuncMap{}
|
||||
|
||||
for k, v := range amber.FuncMap { // add the amber's default funcs
|
||||
funcs[k] = v
|
||||
opts := amber.Options{
|
||||
PrettyPrint: false,
|
||||
LineNumbers: false,
|
||||
VirtualFilesystem: s.fs,
|
||||
}
|
||||
|
||||
for k, v := range s.funcs {
|
||||
funcs[k] = v
|
||||
}
|
||||
|
||||
if len(virtualDirectory) > 0 {
|
||||
if virtualDirectory[0] == '.' { // first check for .wrong
|
||||
virtualDirectory = virtualDirectory[1:]
|
||||
return walk(s.fs, s.rootDir, func(path string, info os.FileInfo, err error) error {
|
||||
if info == nil || info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if virtualDirectory[0] == '/' || virtualDirectory[0] == filepath.Separator { // second check for /something, (or ./something if we had dot on 0 it will be removed
|
||||
virtualDirectory = virtualDirectory[1:]
|
||||
}
|
||||
}
|
||||
amber.FuncMap = funcs // set the funcs
|
||||
|
||||
names := namesFn()
|
||||
|
||||
for _, path := range names {
|
||||
if !strings.HasPrefix(path, virtualDirectory) {
|
||||
continue
|
||||
}
|
||||
ext := filepath.Ext(path)
|
||||
if ext == virtualExtension {
|
||||
|
||||
rel, err := filepath.Rel(virtualDirectory, path)
|
||||
if err != nil {
|
||||
return err
|
||||
if s.extension != "" {
|
||||
if !strings.HasSuffix(path, s.extension) {
|
||||
return nil
|
||||
}
|
||||
|
||||
buf, err := assetFn(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
name := filepath.ToSlash(rel)
|
||||
tmpl, err := amber.CompileData(buf, name, amber.DefaultOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.templateCache[name] = tmpl
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
buf, err := asset(s.fs, path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", path, err)
|
||||
}
|
||||
|
||||
name := strings.TrimPrefix(path, "/")
|
||||
|
||||
tmpl, err := amber.CompileData(buf, name, opts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", path, err)
|
||||
}
|
||||
|
||||
s.templateCache[name] = tmpl
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AmberEngine) fromCache(relativeName string) *template.Template {
|
||||
tmpl, ok := s.templateCache[relativeName]
|
||||
if ok {
|
||||
if s.reload {
|
||||
s.rmu.RLock()
|
||||
defer s.rmu.RUnlock()
|
||||
}
|
||||
|
||||
if tmpl, ok := s.templateCache[relativeName]; ok {
|
||||
return tmpl
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -211,10 +159,6 @@ func (s *AmberEngine) fromCache(relativeName string) *template.Template {
|
|||
func (s *AmberEngine) ExecuteWriter(w io.Writer, filename string, layout string, bindingData interface{}) error {
|
||||
// re-parse the templates if reload is enabled.
|
||||
if s.reload {
|
||||
// locks to fix #872, it's the simplest solution and the most correct,
|
||||
// to execute writers with "wait list", one at a time.
|
||||
s.rmu.Lock()
|
||||
defer s.rmu.Unlock()
|
||||
if err := s.Load(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -224,5 +168,5 @@ func (s *AmberEngine) ExecuteWriter(w io.Writer, filename string, layout string,
|
|||
return tmpl.Execute(w, bindingData)
|
||||
}
|
||||
|
||||
return fmt.Errorf("Template with name: %s does not exist in the dir: %s", filename, s.directory)
|
||||
return ErrNotExist{filename, false}
|
||||
}
|
||||
|
|
|
@ -39,8 +39,28 @@ func WrapBlocks(v *blocks.Blocks) *BlocksEngine {
|
|||
// 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))
|
||||
//
|
||||
// Usage:
|
||||
// Blocks("./views", ".html") or
|
||||
// Blocks(iris.Dir("./views"), ".html") or
|
||||
// Blocks(AssetFile(), ".html") for embedded data.
|
||||
func Blocks(fs interface{}, extension string) *BlocksEngine {
|
||||
return WrapBlocks(blocks.New(fs).Extension(extension))
|
||||
}
|
||||
|
||||
// RootDir sets the directory to use as the root one inside the provided File System.
|
||||
func (s *BlocksEngine) RootDir(root string) *BlocksEngine {
|
||||
s.Engine.RootDir(root)
|
||||
return s
|
||||
}
|
||||
|
||||
// LayoutDir sets a custom layouts directory,
|
||||
// always relative to the "rootDir" one.
|
||||
// Layouts are recognised by their prefix names.
|
||||
// Defaults to "layouts".
|
||||
func (s *BlocksEngine) LayoutDir(relToDirLayoutDir string) *BlocksEngine {
|
||||
s.Engine.LayoutDir(relToDirLayoutDir)
|
||||
return s
|
||||
}
|
||||
|
||||
// Ext returns empty ext as this template engine
|
||||
|
@ -66,18 +86,6 @@ func (s *BlocksEngine) AddLayoutFunc(funcName string, funcBody interface{}) *Blo
|
|||
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.
|
||||
//
|
||||
|
|
195
view/django.go
195
view/django.go
|
@ -2,9 +2,8 @@ package view
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
stdPath "path"
|
||||
"path/filepath"
|
||||
|
@ -60,41 +59,40 @@ var AsValue = pongo2.AsValue
|
|||
var AsSafeValue = pongo2.AsSafeValue
|
||||
|
||||
type tDjangoAssetLoader struct {
|
||||
baseDir string
|
||||
assetGet func(name string) ([]byte, error)
|
||||
rootDir string
|
||||
fs http.FileSystem
|
||||
}
|
||||
|
||||
// Abs calculates the path to a given template. Whenever a path must be resolved
|
||||
// due to an import from another template, the base equals the parent template's path.
|
||||
func (dal *tDjangoAssetLoader) Abs(base, name string) string {
|
||||
func (l *tDjangoAssetLoader) Abs(base, name string) string {
|
||||
if stdPath.IsAbs(name) {
|
||||
return name
|
||||
}
|
||||
|
||||
return stdPath.Join(dal.baseDir, name)
|
||||
return stdPath.Join(l.rootDir, name)
|
||||
}
|
||||
|
||||
// Get returns an io.Reader where the template's content can be read from.
|
||||
func (dal *tDjangoAssetLoader) Get(path string) (io.Reader, error) {
|
||||
func (l *tDjangoAssetLoader) Get(path string) (io.Reader, error) {
|
||||
if stdPath.IsAbs(path) {
|
||||
path = path[1:]
|
||||
}
|
||||
|
||||
res, err := dal.assetGet(path)
|
||||
res, err := asset(l.fs, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bytes.NewBuffer(res), nil
|
||||
return bytes.NewReader(res), nil
|
||||
}
|
||||
|
||||
// DjangoEngine contains the django view engine structure.
|
||||
type DjangoEngine struct {
|
||||
fs http.FileSystem
|
||||
// files configuration
|
||||
directory string
|
||||
rootDir string
|
||||
extension string
|
||||
assetFn func(name string) ([]byte, error) // for embedded, in combination with directory & extension
|
||||
namesFn func() []string // for embedded, in combination with directory & extension
|
||||
reload bool
|
||||
//
|
||||
rmu sync.RWMutex // locks for filters, globals and `ExecuteWiter` when `reload` is true.
|
||||
|
@ -102,7 +100,6 @@ type DjangoEngine struct {
|
|||
filters map[string]FilterFunction
|
||||
// globals share context fields between templates.
|
||||
globals map[string]interface{}
|
||||
mu sync.Mutex // locks for template cache
|
||||
templateCache map[string]*pongo2.Template
|
||||
}
|
||||
|
||||
|
@ -113,9 +110,15 @@ var (
|
|||
|
||||
// Django creates and returns a new django view engine.
|
||||
// The given "extension" MUST begin with a dot.
|
||||
func Django(directory, extension string) *DjangoEngine {
|
||||
//
|
||||
// Usage:
|
||||
// Django("./views", ".html") or
|
||||
// Django(iris.Dir("./views"), ".html") or
|
||||
// Django(AssetFile(), ".html") for embedded data.
|
||||
func Django(fs interface{}, extension string) *DjangoEngine {
|
||||
s := &DjangoEngine{
|
||||
directory: directory,
|
||||
fs: getFS(fs),
|
||||
rootDir: "/",
|
||||
extension: extension,
|
||||
globals: make(map[string]interface{}),
|
||||
filters: make(map[string]FilterFunction),
|
||||
|
@ -125,20 +128,18 @@ func Django(directory, extension string) *DjangoEngine {
|
|||
return s
|
||||
}
|
||||
|
||||
// RootDir sets the directory to be used as a starting point
|
||||
// to load templates from the provided file system.
|
||||
func (s *DjangoEngine) RootDir(root string) *DjangoEngine {
|
||||
s.rootDir = filepath.ToSlash(root)
|
||||
return s
|
||||
}
|
||||
|
||||
// Ext returns the file extension which this view engine is responsible to render.
|
||||
func (s *DjangoEngine) Ext() string {
|
||||
return s.extension
|
||||
}
|
||||
|
||||
// Binary optionally, use it when template files are distributed
|
||||
// inside the app executable (.go generated files).
|
||||
//
|
||||
// The assetFn and namesFn can come from the go-bindata library.
|
||||
func (s *DjangoEngine) Binary(assetFn func(name string) ([]byte, error), namesFn func() []string) *DjangoEngine {
|
||||
s.assetFn, s.namesFn = assetFn, namesFn
|
||||
return s
|
||||
}
|
||||
|
||||
// Reload if set to true the templates are reloading on each render,
|
||||
// use it when you're in development and you're boring of restarting
|
||||
// the whole app when you edit a template file.
|
||||
|
@ -203,133 +204,32 @@ func (s *DjangoEngine) RegisterTag(tagName string, fn TagParser) error {
|
|||
//
|
||||
// Returns an error if something bad happens, user is responsible to catch it.
|
||||
func (s *DjangoEngine) Load() error {
|
||||
if s.assetFn != nil && s.namesFn != nil {
|
||||
// embedded
|
||||
return s.loadAssets()
|
||||
}
|
||||
|
||||
// load from directory, make the dir absolute here too.
|
||||
dir, err := filepath.Abs(s.directory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
// change the directory field configuration, load happens after directory has been set, so we will not have any problems here.
|
||||
s.directory = dir
|
||||
return s.loadDirectory()
|
||||
}
|
||||
|
||||
// LoadDirectory loads the templates from directory.
|
||||
func (s *DjangoEngine) loadDirectory() (templateErr error) {
|
||||
dir, extension := s.directory, s.extension
|
||||
|
||||
fsLoader, err := pongo2.NewLocalFileSystemLoader(dir) // I see that this doesn't read the content if already parsed, so do it manually via filepath.Walk
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
set := pongo2.NewSet("", fsLoader)
|
||||
set := pongo2.NewSet("", &tDjangoAssetLoader{fs: s.fs, rootDir: s.rootDir})
|
||||
set.Globals = getPongoContext(s.globals)
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.rmu.Lock()
|
||||
defer s.rmu.Unlock()
|
||||
|
||||
// Walk the supplied directory and compile any files that match our extension list.
|
||||
err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
// Fix same-extension-dirs bug: some dir might be named to: "users.tmpl", "local.html".
|
||||
// These dirs should be excluded as they are not valid golang templates, but files under
|
||||
// them should be treat as normal.
|
||||
// If is a dir, return immediately (dir is not a valid golang template).
|
||||
return walk(s.fs, s.rootDir, func(path string, info os.FileInfo, err error) error {
|
||||
if info == nil || info.IsDir() {
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
rel, err := filepath.Rel(dir, path)
|
||||
if err != nil {
|
||||
templateErr = err
|
||||
return err
|
||||
if s.extension != "" {
|
||||
if !strings.HasSuffix(path, s.extension) {
|
||||
return nil
|
||||
}
|
||||
|
||||
ext := filepath.Ext(rel)
|
||||
if ext == extension {
|
||||
|
||||
buf, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
templateErr = err
|
||||
return err
|
||||
}
|
||||
name := filepath.ToSlash(rel)
|
||||
|
||||
s.templateCache[name], templateErr = set.FromString(string(buf))
|
||||
|
||||
if templateErr != nil {
|
||||
return templateErr
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// loadAssets loads the templates by binary (go-bindata for embedded).
|
||||
func (s *DjangoEngine) loadAssets() error {
|
||||
virtualDirectory, virtualExtension := s.directory, s.extension
|
||||
assetFn, namesFn := s.assetFn, s.namesFn
|
||||
|
||||
// Make a file set with a template loader based on asset function
|
||||
set := pongo2.NewSet("", &tDjangoAssetLoader{baseDir: s.directory, assetGet: s.assetFn})
|
||||
set.Globals = getPongoContext(s.globals)
|
||||
|
||||
if len(virtualDirectory) > 0 {
|
||||
if virtualDirectory[0] == '.' { // first check for .wrong
|
||||
virtualDirectory = virtualDirectory[1:]
|
||||
}
|
||||
if virtualDirectory[0] == '/' || virtualDirectory[0] == os.PathSeparator { // second check for /something, (or ./something if we had dot on 0 it will be removed
|
||||
virtualDirectory = virtualDirectory[1:]
|
||||
}
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
names := namesFn()
|
||||
for _, path := range names {
|
||||
if !strings.HasPrefix(path, virtualDirectory) {
|
||||
continue
|
||||
}
|
||||
|
||||
rel, err := filepath.Rel(virtualDirectory, path)
|
||||
buf, err := asset(s.fs, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ext := filepath.Ext(rel)
|
||||
if ext == virtualExtension {
|
||||
|
||||
buf, err := assetFn(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
name := filepath.ToSlash(rel)
|
||||
s.templateCache[name], err = set.FromString(string(buf))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
name := strings.TrimPrefix(path, "/")
|
||||
s.templateCache[name], err = set.FromBytes(buf)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// getPongoContext returns the pongo2.Context from map[string]interface{} or from pongo2.Context, used internaly
|
||||
|
@ -350,15 +250,14 @@ func getPongoContext(templateData interface{}) pongo2.Context {
|
|||
}
|
||||
|
||||
func (s *DjangoEngine) fromCache(relativeName string) *pongo2.Template {
|
||||
s.mu.Lock()
|
||||
if s.reload {
|
||||
s.rmu.RLock()
|
||||
defer s.rmu.RUnlock()
|
||||
}
|
||||
|
||||
tmpl, ok := s.templateCache[relativeName]
|
||||
|
||||
if ok {
|
||||
s.mu.Unlock()
|
||||
if tmpl, ok := s.templateCache[relativeName]; ok {
|
||||
return tmpl
|
||||
}
|
||||
s.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -367,10 +266,6 @@ func (s *DjangoEngine) fromCache(relativeName string) *pongo2.Template {
|
|||
func (s *DjangoEngine) ExecuteWriter(w io.Writer, filename string, layout string, bindingData interface{}) error {
|
||||
// re-parse the templates if reload is enabled.
|
||||
if s.reload {
|
||||
// locks to fix #872, it's the simplest solution and the most correct,
|
||||
// to execute writers with "wait list", one at a time.
|
||||
s.rmu.Lock()
|
||||
defer s.rmu.Unlock()
|
||||
if err := s.Load(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -380,5 +275,5 @@ func (s *DjangoEngine) ExecuteWriter(w io.Writer, filename string, layout string
|
|||
return tmpl.ExecuteWriter(getPongoContext(bindingData), w)
|
||||
}
|
||||
|
||||
return fmt.Errorf("template with name: %s ddoes not exist in the dir: %s", filename, s.directory)
|
||||
return ErrNotExist{filename, false}
|
||||
}
|
||||
|
|
106
view/fs.go
Normal file
106
view/fs.go
Normal file
|
@ -0,0 +1,106 @@
|
|||
package view
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// walk recursively in "fs" descends "root" path, calling "walkFn".
|
||||
func walk(fs http.FileSystem, root string, walkFn filepath.WalkFunc) error {
|
||||
names, err := assetNames(fs, root)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", root, err)
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
fullpath := path.Join(root, name)
|
||||
f, err := fs.Open(fullpath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", fullpath, err)
|
||||
}
|
||||
stat, err := f.Stat()
|
||||
err = walkFn(fullpath, stat, err)
|
||||
if err != nil {
|
||||
if err != filepath.SkipDir {
|
||||
return fmt.Errorf("%s: %w", fullpath, err)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if stat.IsDir() {
|
||||
if err := walk(fs, fullpath, walkFn); err != nil {
|
||||
return fmt.Errorf("%s: %w", fullpath, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// assetNames returns the first-level directories and file, sorted, names.
|
||||
func assetNames(fs http.FileSystem, name string) ([]string, error) {
|
||||
f, err := fs.Open(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
infos, err := f.Readdir(-1)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
names := make([]string, 0, len(infos))
|
||||
for _, info := range infos {
|
||||
// note: go-bindata fs returns full names whether
|
||||
// the http.Dir returns the base part, so
|
||||
// we only work with their base names.
|
||||
name := filepath.ToSlash(info.Name())
|
||||
name = path.Base(name)
|
||||
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
sort.Strings(names)
|
||||
return names, nil
|
||||
}
|
||||
|
||||
func asset(fs http.FileSystem, name string) ([]byte, error) {
|
||||
f, err := fs.Open(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
contents, err := ioutil.ReadAll(f)
|
||||
f.Close()
|
||||
return contents, err
|
||||
}
|
||||
|
||||
func getFS(fsOrDir interface{}) (fs http.FileSystem) {
|
||||
switch v := fsOrDir.(type) {
|
||||
case string:
|
||||
fs = httpDirWrapper{http.Dir(v)}
|
||||
case http.FileSystem:
|
||||
fs = v
|
||||
default:
|
||||
panic(fmt.Errorf(`unexpected "fsOrDir" argument type of %T (string or http.FileSystem)`, v))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// fixes: "invalid character in file path"
|
||||
// on amber engine (it uses the virtual fs directly
|
||||
// and it uses filepath instead of the path package...).
|
||||
type httpDirWrapper struct {
|
||||
http.Dir
|
||||
}
|
||||
|
||||
func (d httpDirWrapper) Open(name string) (http.File, error) {
|
||||
return d.Dir.Open(filepath.ToSlash(name))
|
||||
}
|
|
@ -3,7 +3,7 @@ package view
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -14,15 +14,16 @@ import (
|
|||
|
||||
// HandlebarsEngine contains the handlebars view engine structure.
|
||||
type HandlebarsEngine struct {
|
||||
fs http.FileSystem
|
||||
// files configuration
|
||||
directory string
|
||||
rootDir string
|
||||
extension string
|
||||
assetFn func(name string) ([]byte, error) // for embedded, in combination with directory & extension
|
||||
namesFn func() []string // for embedded, in combination with directory & extension
|
||||
reload bool // if true, each time the ExecuteWriter is called the templates will be reloaded.
|
||||
// parser configuration
|
||||
layout string
|
||||
rmu sync.RWMutex // locks for helpers and `ExecuteWiter` when `reload` is true.
|
||||
rmu sync.RWMutex
|
||||
helpers map[string]interface{}
|
||||
templateCache map[string]*raymond.Template
|
||||
}
|
||||
|
@ -34,9 +35,15 @@ var (
|
|||
|
||||
// Handlebars creates and returns a new handlebars view engine.
|
||||
// The given "extension" MUST begin with a dot.
|
||||
func Handlebars(directory, extension string) *HandlebarsEngine {
|
||||
//
|
||||
// Usage:
|
||||
// Handlebars("./views", ".html") or
|
||||
// Handlebars(iris.Dir("./views"), ".html") or
|
||||
// Handlebars(AssetFile(), ".html") for embedded data.
|
||||
func Handlebars(fs interface{}, extension string) *HandlebarsEngine {
|
||||
s := &HandlebarsEngine{
|
||||
directory: directory,
|
||||
fs: getFS(fs),
|
||||
rootDir: "/",
|
||||
extension: extension,
|
||||
templateCache: make(map[string]*raymond.Template),
|
||||
helpers: make(map[string]interface{}),
|
||||
|
@ -54,20 +61,18 @@ func Handlebars(directory, extension string) *HandlebarsEngine {
|
|||
return s
|
||||
}
|
||||
|
||||
// RootDir sets the directory to be used as a starting point
|
||||
// to load templates from the provided file system.
|
||||
func (s *HandlebarsEngine) RootDir(root string) *HandlebarsEngine {
|
||||
s.rootDir = filepath.ToSlash(root)
|
||||
return s
|
||||
}
|
||||
|
||||
// Ext returns the file extension which this view engine is responsible to render.
|
||||
func (s *HandlebarsEngine) Ext() string {
|
||||
return s.extension
|
||||
}
|
||||
|
||||
// Binary optionally, use it when template files are distributed
|
||||
// inside the app executable (.go generated files).
|
||||
//
|
||||
// The assetFn and namesFn can come from the go-bindata library.
|
||||
func (s *HandlebarsEngine) Binary(assetFn func(name string) ([]byte, error), namesFn func() []string) *HandlebarsEngine {
|
||||
s.assetFn, s.namesFn = assetFn, namesFn
|
||||
return s
|
||||
}
|
||||
|
||||
// Reload if set to true the templates are reloading on each render,
|
||||
// use it when you're in development and you're boring of restarting
|
||||
// the whole app when you edit a template file.
|
||||
|
@ -105,135 +110,52 @@ func (s *HandlebarsEngine) AddFunc(funcName string, funcBody interface{}) {
|
|||
//
|
||||
// Returns an error if something bad happens, user is responsible to catch it.
|
||||
func (s *HandlebarsEngine) Load() error {
|
||||
if s.assetFn != nil && s.namesFn != nil {
|
||||
// embedded
|
||||
return s.loadAssets()
|
||||
}
|
||||
s.rmu.Lock()
|
||||
defer s.rmu.Unlock()
|
||||
|
||||
// load from directory, make the dir absolute here too.
|
||||
dir, err := filepath.Abs(s.directory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
// change the directory field configuration, load happens after directory has been set, so we will not have any problems here.
|
||||
s.directory = dir
|
||||
return s.loadDirectory()
|
||||
}
|
||||
|
||||
// loadDirectory builds the handlebars templates from directory.
|
||||
func (s *HandlebarsEngine) loadDirectory() error {
|
||||
// register the global helpers on the first load
|
||||
if len(s.templateCache) == 0 && s.helpers != nil {
|
||||
raymond.RegisterHelpers(s.helpers)
|
||||
}
|
||||
|
||||
dir, extension := s.directory, s.extension
|
||||
|
||||
// the render works like {{ render "myfile.html" theContext.PartialContext}}
|
||||
// instead of the html/template engine which works like {{ render "myfile.html"}} and accepts the parent binding, with handlebars we can't do that because of lack of runtime helpers (dublicate error)
|
||||
|
||||
var templateErr error
|
||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, _ error) error {
|
||||
return walk(s.fs, s.rootDir, func(path string, info os.FileInfo, _ error) error {
|
||||
if info == nil || info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
rel, err := filepath.Rel(dir, path)
|
||||
if s.extension != "" {
|
||||
if !strings.HasSuffix(path, s.extension) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
buf, err := asset(s.fs, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ext := filepath.Ext(rel)
|
||||
if ext == extension {
|
||||
buf, err := ioutil.ReadFile(path)
|
||||
contents := string(buf)
|
||||
|
||||
if err != nil {
|
||||
templateErr = err
|
||||
return err
|
||||
}
|
||||
|
||||
name := filepath.ToSlash(rel)
|
||||
|
||||
tmpl, err := raymond.Parse(contents)
|
||||
if err != nil {
|
||||
templateErr = err
|
||||
return err
|
||||
}
|
||||
s.templateCache[name] = tmpl
|
||||
name := strings.TrimPrefix(path, "/")
|
||||
tmpl, err := raymond.Parse(string(buf))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.templateCache[name] = tmpl
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return templateErr
|
||||
}
|
||||
|
||||
// loadAssets loads the templates by binary, embedded.
|
||||
func (s *HandlebarsEngine) loadAssets() error {
|
||||
// register the global helpers
|
||||
if len(s.templateCache) == 0 && s.helpers != nil {
|
||||
raymond.RegisterHelpers(s.helpers)
|
||||
}
|
||||
|
||||
virtualDirectory, virtualExtension := s.directory, s.extension
|
||||
assetFn, namesFn := s.assetFn, s.namesFn
|
||||
|
||||
if len(virtualDirectory) > 0 {
|
||||
if virtualDirectory[0] == '.' { // first check for .wrong
|
||||
virtualDirectory = virtualDirectory[1:]
|
||||
}
|
||||
if virtualDirectory[0] == '/' || virtualDirectory[0] == os.PathSeparator { // second check for /something, (or ./something if we had dot on 0 it will be removed
|
||||
virtualDirectory = virtualDirectory[1:]
|
||||
}
|
||||
}
|
||||
|
||||
names := namesFn()
|
||||
for _, path := range names {
|
||||
if !strings.HasPrefix(path, virtualDirectory) {
|
||||
continue
|
||||
}
|
||||
ext := filepath.Ext(path)
|
||||
if ext == virtualExtension {
|
||||
|
||||
rel, err := filepath.Rel(virtualDirectory, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf, err := assetFn(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
contents := string(buf)
|
||||
name := filepath.ToSlash(rel)
|
||||
|
||||
tmpl, err := raymond.Parse(contents)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.templateCache[name] = tmpl
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *HandlebarsEngine) fromCache(relativeName string) *raymond.Template {
|
||||
tmpl, ok := s.templateCache[relativeName]
|
||||
if !ok {
|
||||
return nil
|
||||
if s.reload {
|
||||
s.rmu.RLock()
|
||||
defer s.rmu.RUnlock()
|
||||
}
|
||||
return tmpl
|
||||
|
||||
if tmpl, ok := s.templateCache[relativeName]; ok {
|
||||
return tmpl
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *HandlebarsEngine) executeTemplateBuf(name string, binding interface{}) (string, error) {
|
||||
|
@ -247,10 +169,6 @@ func (s *HandlebarsEngine) executeTemplateBuf(name string, binding interface{})
|
|||
func (s *HandlebarsEngine) ExecuteWriter(w io.Writer, filename string, layout string, bindingData interface{}) error {
|
||||
// re-parse the templates if reload is enabled.
|
||||
if s.reload {
|
||||
// locks to fix #872, it's the simplest solution and the most correct,
|
||||
// to execute writers with "wait list", one at a time.
|
||||
s.rmu.Lock()
|
||||
defer s.rmu.Unlock()
|
||||
if err := s.Load(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -295,5 +213,5 @@ func (s *HandlebarsEngine) ExecuteWriter(w io.Writer, filename string, layout st
|
|||
return err
|
||||
}
|
||||
|
||||
return fmt.Errorf("template with name: %s[original name = %s] does not exist in the dir: %s", renderFilename, filename, s.directory)
|
||||
return ErrNotExist{fmt.Sprintf("%s (file: %s)", renderFilename, filename), false}
|
||||
}
|
||||
|
|
280
view/html.go
280
view/html.go
|
@ -5,7 +5,7 @@ import (
|
|||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -14,14 +14,16 @@ import (
|
|||
|
||||
// HTMLEngine contains the html view engine structure.
|
||||
type HTMLEngine struct {
|
||||
// the file system to load from.
|
||||
fs http.FileSystem
|
||||
// files configuration
|
||||
directory string
|
||||
rootDir string
|
||||
extension string
|
||||
assetFn func(name string) ([]byte, error) // for embedded, in combination with directory & extension
|
||||
namesFn func() []string // for embedded, in combination with directory & extension
|
||||
reload bool // if true, each time the ExecuteWriter is called the templates will be reloaded, each ExecuteWriter waits to be finished before writing to a new one.
|
||||
// if true, each time the ExecuteWriter is called the templates will be reloaded,
|
||||
// each ExecuteWriter waits to be finished before writing to a new one.
|
||||
reload bool
|
||||
// parser configuration
|
||||
options []string // text options
|
||||
options []string // (text) template options
|
||||
left string
|
||||
right string
|
||||
layout string
|
||||
|
@ -65,12 +67,16 @@ var emptyFuncs = template.FuncMap{
|
|||
// 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 {
|
||||
//
|
||||
// Usage:
|
||||
// HTML("./views", ".html") or
|
||||
// HTML(iris.Dir("./views"), ".html") or
|
||||
// HTML(AssetFile(), ".html") for embedded data.
|
||||
func HTML(fs interface{}, extension string) *HTMLEngine {
|
||||
s := &HTMLEngine{
|
||||
directory: directory,
|
||||
fs: getFS(fs),
|
||||
rootDir: "/",
|
||||
extension: extension,
|
||||
assetFn: nil,
|
||||
namesFn: nil,
|
||||
reload: false,
|
||||
left: "{{",
|
||||
right: "}}",
|
||||
|
@ -82,20 +88,18 @@ func HTML(directory, extension string) *HTMLEngine {
|
|||
return s
|
||||
}
|
||||
|
||||
// RootDir sets the directory to be used as a starting point
|
||||
// to load templates from the provided file system.
|
||||
func (s *HTMLEngine) RootDir(root string) *HTMLEngine {
|
||||
s.rootDir = filepath.ToSlash(root)
|
||||
return s
|
||||
}
|
||||
|
||||
// Ext returns the file extension which this view engine is responsible to render.
|
||||
func (s *HTMLEngine) Ext() string {
|
||||
return s.extension
|
||||
}
|
||||
|
||||
// Binary optionally, use it when template files are distributed
|
||||
// inside the app executable (.go generated files).
|
||||
//
|
||||
// The assetFn and namesFn can come from the go-bindata library.
|
||||
func (s *HTMLEngine) Binary(assetFn func(name string) ([]byte, error), namesFn func() []string) *HTMLEngine {
|
||||
s.assetFn, s.namesFn = assetFn, namesFn
|
||||
return s
|
||||
}
|
||||
|
||||
// Reload if set to true the templates are reloading on each render,
|
||||
// use it when you're in development and you're boring of restarting
|
||||
// the whole app when you edit a template file.
|
||||
|
@ -211,213 +215,49 @@ func (s *HTMLEngine) Funcs(funcMap template.FuncMap) *HTMLEngine {
|
|||
//
|
||||
// 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.
|
||||
// atomic.StoreUint32(&s.isLoading, 1)
|
||||
// s.rmu.Lock()
|
||||
// defer func() {
|
||||
// s.rmu.Unlock()
|
||||
// atomic.StoreUint32(&s.isLoading, 0)
|
||||
// }()
|
||||
s.rmu.Lock()
|
||||
defer s.rmu.Unlock()
|
||||
|
||||
if s.assetFn != nil && s.namesFn != nil {
|
||||
// NOT NECESSARY "fix" of https://github.com/kataras/iris/issues/784,
|
||||
// IT'S BAD CODE WRITTEN WE KEEP HERE ONLY FOR A REMINDER
|
||||
// for any future questions.
|
||||
//
|
||||
// if strings.HasPrefix(s.directory, "../") {
|
||||
// // this and some more additions are fixes for https://github.com/kataras/iris/issues/784
|
||||
// // however, the dev SHOULD
|
||||
// // run the go-bindata command from the "$dir" parent directory
|
||||
// // and just use the ./$dir in the declaration,
|
||||
// // so all these fixes are not really necessary but they are here
|
||||
// // for the future
|
||||
// dir, err := filepath.Abs(s.directory)
|
||||
// // the absolute dir here can be invalid if running from other
|
||||
// // folder but we really don't care
|
||||
// // when we're working with the bindata because
|
||||
// // we only care for its relative directory
|
||||
// // see `loadAssets` for more.
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// s.directory = dir
|
||||
// }
|
||||
|
||||
// embedded
|
||||
return s.loadAssets()
|
||||
}
|
||||
|
||||
// load from directory, make the dir absolute here too.
|
||||
dir, err := filepath.Abs(s.directory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
// change the directory field configuration, load happens after directory has been set, so we will not have any problems here.
|
||||
s.directory = dir
|
||||
return s.loadDirectory()
|
||||
}
|
||||
|
||||
// loadDirectory builds the templates from directory.
|
||||
func (s *HTMLEngine) loadDirectory() error {
|
||||
dir, extension := s.directory, s.extension
|
||||
|
||||
var templateErr error
|
||||
s.Templates = template.New(dir)
|
||||
s.Templates = template.New(s.rootDir)
|
||||
s.Templates.Delims(s.left, s.right)
|
||||
|
||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
return walk(s.fs, s.rootDir, func(path string, info os.FileInfo, err error) error {
|
||||
if info == nil || info.IsDir() {
|
||||
} else {
|
||||
rel, err := filepath.Rel(dir, path)
|
||||
return nil
|
||||
}
|
||||
|
||||
if s.extension != "" {
|
||||
if !strings.HasSuffix(path, s.extension) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
buf, err := asset(s.fs, path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", path, err)
|
||||
}
|
||||
contents := string(buf)
|
||||
|
||||
name := strings.TrimPrefix(path, "/")
|
||||
tmpl := s.Templates.New(name)
|
||||
tmpl.Option(s.options...)
|
||||
|
||||
if s.middleware != nil {
|
||||
contents, err = s.middleware(name, buf)
|
||||
if err != nil {
|
||||
templateErr = err
|
||||
return err
|
||||
}
|
||||
|
||||
ext := filepath.Ext(path)
|
||||
if ext == extension {
|
||||
|
||||
buf, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
templateErr = err
|
||||
return err
|
||||
}
|
||||
|
||||
contents := string(buf)
|
||||
|
||||
name := filepath.ToSlash(rel)
|
||||
tmpl := s.Templates.New(name)
|
||||
tmpl.Option(s.options...)
|
||||
|
||||
if s.middleware != nil {
|
||||
contents, err = s.middleware(name, buf)
|
||||
}
|
||||
if err != nil {
|
||||
templateErr = err
|
||||
return err
|
||||
}
|
||||
// s.mu.Lock()
|
||||
// Add our funcmaps.
|
||||
_, err = tmpl.
|
||||
Funcs(emptyFuncs).
|
||||
// Funcs(s.makeDefaultLayoutFuncs(name)).
|
||||
// Funcs(s.layoutFuncs).
|
||||
Funcs(s.funcs).
|
||||
Parse(contents)
|
||||
// s.mu.Unlock()
|
||||
if err != nil {
|
||||
templateErr = err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
// Add our funcmaps.
|
||||
_, err = tmpl.
|
||||
Funcs(emptyFuncs).
|
||||
// Funcs(s.makeDefaultLayoutFuncs(name)).
|
||||
// Funcs(s.layoutFuncs).
|
||||
Funcs(s.funcs).
|
||||
Parse(contents)
|
||||
return err
|
||||
}
|
||||
|
||||
return templateErr
|
||||
}
|
||||
|
||||
// loadAssets loads the templates by binary (go-bindata for embedded).
|
||||
func (s *HTMLEngine) loadAssets() error {
|
||||
virtualDirectory, virtualExtension := s.directory, s.extension
|
||||
assetFn, namesFn := s.assetFn, s.namesFn
|
||||
|
||||
var templateErr error
|
||||
s.Templates = template.New(virtualDirectory)
|
||||
s.Templates.Delims(s.left, s.right)
|
||||
names := namesFn()
|
||||
if len(virtualDirectory) > 0 {
|
||||
if virtualDirectory[0] == '.' { // first check for .wrong
|
||||
virtualDirectory = virtualDirectory[1:]
|
||||
}
|
||||
if virtualDirectory[0] == '/' || virtualDirectory[0] == os.PathSeparator { // second check for /something, (or ./something if we had dot on 0 it will be removed
|
||||
virtualDirectory = virtualDirectory[1:]
|
||||
}
|
||||
}
|
||||
|
||||
for _, path := range names {
|
||||
// if filepath.IsAbs(virtualDirectory) {
|
||||
// // fixes https://github.com/kataras/iris/issues/784
|
||||
// // we take the absolute fullpath of the template file.
|
||||
// pathFileAbs, err := filepath.Abs(path)
|
||||
// if err != nil {
|
||||
// templateErr = err
|
||||
// continue
|
||||
// }
|
||||
//
|
||||
// path = pathFileAbs
|
||||
// }
|
||||
|
||||
// bindata may contain more files than the templates
|
||||
// so keep that check as it's.
|
||||
if !strings.HasPrefix(path, virtualDirectory) {
|
||||
continue
|
||||
}
|
||||
|
||||
ext := filepath.Ext(path)
|
||||
// check if extension matches
|
||||
if ext == virtualExtension {
|
||||
|
||||
// take the relative path of the path as base of
|
||||
// virtualDirectory (the absolute path of the view engine that dev passed).
|
||||
rel, err := filepath.Rel(virtualDirectory, path)
|
||||
if err != nil {
|
||||
templateErr = err
|
||||
break
|
||||
}
|
||||
|
||||
// // take the current working directory
|
||||
// cpath, err := filepath.Abs(".")
|
||||
// if err == nil {
|
||||
// // set the path as relative to "path" of the current working dir.
|
||||
// // fixes https://github.com/kataras/iris/issues/784
|
||||
// rpath, err := filepath.Rel(cpath, path)
|
||||
// // fix view: Asset not found for path ''
|
||||
// if err == nil && rpath != "" {
|
||||
// path = rpath
|
||||
// }
|
||||
// }
|
||||
|
||||
buf, err := assetFn(path)
|
||||
if err != nil {
|
||||
templateErr = fmt.Errorf("%v for path '%s'", err, path)
|
||||
break
|
||||
}
|
||||
|
||||
contents := string(buf)
|
||||
name := filepath.ToSlash(rel)
|
||||
|
||||
// name should be the filename of the template.
|
||||
tmpl := s.Templates.New(name)
|
||||
tmpl.Option(s.options...)
|
||||
|
||||
if s.middleware != nil {
|
||||
contents, err = s.middleware(name, buf)
|
||||
if err != nil {
|
||||
templateErr = fmt.Errorf("%v for name '%s'", err, name)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Add our funcmaps.
|
||||
if _, err = tmpl.Funcs(emptyFuncs).Funcs(s.funcs).Parse(contents); err != nil {
|
||||
templateErr = err
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return templateErr
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HTMLEngine) executeTemplateBuf(name string, binding interface{}) (*bytes.Buffer, error) {
|
||||
|
@ -494,10 +334,6 @@ func (s *HTMLEngine) runtimeFuncsFor(t *template.Template, name string, binding
|
|||
func (s *HTMLEngine) ExecuteWriter(w io.Writer, name string, layout string, bindingData interface{}) error {
|
||||
// re-parse the templates if reload is enabled.
|
||||
if s.reload {
|
||||
// locks to fix #872, it's the simplest solution and the most correct,
|
||||
// to execute writers with "wait list", one at a time.
|
||||
s.rmu.Lock()
|
||||
defer s.rmu.Unlock()
|
||||
if err := s.Load(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -505,14 +341,14 @@ 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)
|
||||
return ErrNotExist{name, false}
|
||||
}
|
||||
s.runtimeFuncsFor(t, name, bindingData)
|
||||
|
||||
if layout = getLayout(layout, s.layout); layout != "" {
|
||||
lt := s.Templates.Lookup(layout)
|
||||
if lt == nil {
|
||||
return fmt.Errorf("layout: %s does not exist in the dir: %s", name, s.directory)
|
||||
return ErrNotExist{name, true}
|
||||
}
|
||||
|
||||
s.layoutFuncsFor(lt, name, bindingData)
|
||||
|
|
142
view/jet.go
142
view/jet.go
|
@ -3,8 +3,7 @@ package view
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
@ -18,9 +17,10 @@ const jetEngineName = "jet"
|
|||
|
||||
// JetEngine is the jet template parser's view engine.
|
||||
type JetEngine struct {
|
||||
directory string
|
||||
fs http.FileSystem
|
||||
rootDir string
|
||||
extension string
|
||||
// physical system files or app-embedded, see `Binary(..., ...)`. Defaults to file system on initialization.
|
||||
|
||||
loader jet.Loader
|
||||
|
||||
developmentMode bool
|
||||
|
@ -51,11 +51,12 @@ 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)
|
||||
// }
|
||||
|
||||
//
|
||||
// Usage:
|
||||
// Jet("./views", ".jet") or
|
||||
// Jet(iris.Dir("./views"), ".jet") or
|
||||
// Jet(AssetFile(), ".jet") for embedded data.
|
||||
func Jet(fs interface{}, extension string) *JetEngine {
|
||||
extOK := false
|
||||
for _, ext := range jetExtensions {
|
||||
if ext == extension {
|
||||
|
@ -69,9 +70,9 @@ func Jet(directory, extension string) *JetEngine {
|
|||
}
|
||||
|
||||
s := &JetEngine{
|
||||
directory: directory,
|
||||
rootDir: "/",
|
||||
extension: extension,
|
||||
loader: jet.NewOSFileSystemLoader(directory),
|
||||
loader: &jetLoader{fs: getFS(fs)},
|
||||
jetDataContextKey: "_jet",
|
||||
}
|
||||
|
||||
|
@ -83,6 +84,13 @@ func (s *JetEngine) String() string {
|
|||
return jetEngineName
|
||||
}
|
||||
|
||||
// RootDir sets the directory to be used as a starting point
|
||||
// to load templates from the provided file system.
|
||||
func (s *JetEngine) RootDir(root string) *JetEngine {
|
||||
s.rootDir = filepath.ToSlash(root)
|
||||
return s
|
||||
}
|
||||
|
||||
// Ext should return the final file extension which this view engine is responsible to render.
|
||||
func (s *JetEngine) Ext() string {
|
||||
return s.extension
|
||||
|
@ -175,121 +183,27 @@ func (s *JetEngine) Reload(developmentMode bool) *JetEngine {
|
|||
}
|
||||
|
||||
// SetLoader can be used when the caller wants to use something like
|
||||
// multi.Loader or httpfs.Loader of the jet subpackages,
|
||||
// overrides any previous loader may set by `Binary` or the default.
|
||||
// Should act before `Load` or `iris.Application#RegisterView`.
|
||||
// multi.Loader or httpfs.Loader.
|
||||
func (s *JetEngine) SetLoader(loader jet.Loader) *JetEngine {
|
||||
s.loader = loader
|
||||
return s
|
||||
}
|
||||
|
||||
// Binary optionally, use it when template files are distributed
|
||||
// inside the app executable (.go generated files).
|
||||
//
|
||||
// The assetFn and namesFn can come from the go-bindata library.
|
||||
// Should act before `Load` or `iris.Application#RegisterView`.
|
||||
func (s *JetEngine) Binary(assetFn func(name string) ([]byte, error), assetNames func() []string) *JetEngine {
|
||||
// embedded.
|
||||
vdir := s.directory
|
||||
|
||||
if vdir[0] == '.' {
|
||||
vdir = vdir[1:]
|
||||
}
|
||||
|
||||
// second check for /something, (or ./something if we had dot on 0 it will be removed)
|
||||
if vdir[0] == '/' || vdir[0] == os.PathSeparator {
|
||||
vdir = vdir[1:]
|
||||
}
|
||||
|
||||
// check for trailing slashes because new users may be do that by mistake
|
||||
// although all examples are showing the correct way but you never know
|
||||
// i.e "./assets/" is not correct, if was inside "./assets".
|
||||
// remove last "/".
|
||||
if trailingSlashIdx := len(vdir) - 1; vdir[trailingSlashIdx] == '/' {
|
||||
vdir = vdir[0:trailingSlashIdx]
|
||||
}
|
||||
|
||||
namesSlice := assetNames()
|
||||
names := make(map[string]struct{})
|
||||
for _, name := range namesSlice {
|
||||
if !strings.HasPrefix(name, vdir) {
|
||||
continue
|
||||
}
|
||||
|
||||
extOK := false
|
||||
fileExt := path.Ext(name)
|
||||
for _, ext := range jetExtensions {
|
||||
if ext == fileExt {
|
||||
extOK = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !extOK {
|
||||
continue
|
||||
}
|
||||
|
||||
names[name] = struct{}{}
|
||||
}
|
||||
|
||||
if len(names) == 0 {
|
||||
panic("JetEngine.Binary: no embedded files found in directory: " + vdir)
|
||||
}
|
||||
|
||||
s.loader = &embeddedLoader{
|
||||
vdir: vdir,
|
||||
asset: assetFn,
|
||||
names: names,
|
||||
}
|
||||
return s
|
||||
type jetLoader struct {
|
||||
fs http.FileSystem
|
||||
}
|
||||
|
||||
type (
|
||||
embeddedLoader struct {
|
||||
vdir string
|
||||
asset func(name string) ([]byte, error)
|
||||
names map[string]struct{}
|
||||
}
|
||||
embeddedFile struct {
|
||||
contents []byte // the contents are NOT consumed.
|
||||
readen int64
|
||||
}
|
||||
)
|
||||
var _ jet.Loader = (*jetLoader)(nil)
|
||||
|
||||
var (
|
||||
_ jet.Loader = (*embeddedLoader)(nil)
|
||||
_ io.ReadCloser = (*embeddedFile)(nil)
|
||||
)
|
||||
|
||||
func (f *embeddedFile) Close() error { return nil }
|
||||
func (f *embeddedFile) Read(p []byte) (int, error) {
|
||||
if f.readen >= int64(len(f.contents)) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
n := copy(p, f.contents[f.readen:])
|
||||
f.readen += int64(n)
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// Open opens a file from OS file system.
|
||||
func (l *embeddedLoader) Open(name string) (io.ReadCloser, error) {
|
||||
name = path.Join(l.vdir, filepath.ToSlash(name))
|
||||
contents, err := l.asset(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &embeddedFile{
|
||||
contents: contents,
|
||||
}, nil
|
||||
// Open opens a file from file system.
|
||||
func (l *jetLoader) Open(name string) (io.ReadCloser, error) {
|
||||
return l.fs.Open(name)
|
||||
}
|
||||
|
||||
// Exists checks if the template name exists by walking the list of template paths
|
||||
// returns string with the full path of the template and bool true if the template file was found
|
||||
func (l *embeddedLoader) Exists(name string) (string, bool) {
|
||||
name = path.Join(l.vdir, filepath.ToSlash(name))
|
||||
|
||||
if _, ok := l.names[name]; ok {
|
||||
func (l *jetLoader) Exists(name string) (string, bool) {
|
||||
if _, err := l.fs.Open(name); err == nil {
|
||||
return name, true
|
||||
}
|
||||
|
||||
|
|
23
view/pug.go
23
view/pug.go
|
@ -2,9 +2,6 @@ package view
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/iris-contrib/jade"
|
||||
)
|
||||
|
@ -16,26 +13,23 @@ import (
|
|||
//
|
||||
// Read more about the Jade Go Parser: https://github.com/Joker/jade
|
||||
//
|
||||
// Usage:
|
||||
// Pug("./views", ".pug") or
|
||||
// Pug(iris.Dir("./views"), ".pug") or
|
||||
// Pug(AssetFile(), ".pug") for embedded data.
|
||||
//
|
||||
// Examples:
|
||||
// https://github.com/kataras/iris/tree/master/_examples/view/template_pug_0
|
||||
// https://github.com/kataras/iris/tree/master/_examples/view/template_pug_1
|
||||
// https://github.com/kataras/iris/tree/master/_examples/view/template_pug_2
|
||||
// https://github.com/kataras/iris/tree/master/_examples/view/template_pug_3
|
||||
func Pug(directory, extension string) *HTMLEngine {
|
||||
s := HTML(directory, extension)
|
||||
func Pug(fs interface{}, extension string) *HTMLEngine {
|
||||
s := HTML(fs, extension)
|
||||
|
||||
s.middleware = func(name string, text []byte) (contents string, err error) {
|
||||
name = path.Join(path.Clean(directory), name)
|
||||
tmpl := jade.New(name)
|
||||
tmpl.ReadFunc = func(name string) ([]byte, error) {
|
||||
if !strings.HasPrefix(path.Clean(name), path.Clean(directory)) {
|
||||
name = path.Join(directory, name)
|
||||
}
|
||||
|
||||
if s.assetFn != nil {
|
||||
return s.assetFn(name)
|
||||
}
|
||||
return ioutil.ReadFile(name)
|
||||
return asset(s.fs, name)
|
||||
}
|
||||
|
||||
// Fixes: https://github.com/kataras/iris/issues/1450
|
||||
|
@ -43,7 +37,6 @@ func Pug(directory, extension string) *HTMLEngine {
|
|||
// And Also able to use relative paths on "extends" and "include" directives:
|
||||
// e.g. instead of extends "templates/layout.pug" we use "layout.pug"
|
||||
// so contents of templates are independent of their root location.
|
||||
|
||||
exec, err := tmpl.Parse(text)
|
||||
if err != nil {
|
||||
return
|
||||
|
|
15
view/view.go
15
view/view.go
|
@ -19,6 +19,21 @@ type (
|
|||
EngineFuncer = context.ViewEngineFuncer
|
||||
)
|
||||
|
||||
// ErrNotExist reports whether a template was not found in the parsed templates tree.
|
||||
type ErrNotExist struct {
|
||||
Name string
|
||||
IsLayout bool
|
||||
}
|
||||
|
||||
// Error implements the `error` interface.
|
||||
func (e ErrNotExist) Error() string {
|
||||
title := "template"
|
||||
if e.IsLayout {
|
||||
title = "layout"
|
||||
}
|
||||
return fmt.Sprintf("%s '%s' does not exist", title, e.Name)
|
||||
}
|
||||
|
||||
// View is responsible to
|
||||
// load the correct templates
|
||||
// for each of the registered view engines.
|
||||
|
|
Loading…
Reference in New Issue
Block a user