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:
|
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.
|
- 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:
|
- Improved tracing (with `app.Logger().SetLevel("debug")`) for routes. Screens:
|
||||||
|
@ -641,6 +643,7 @@ New Context Methods:
|
||||||
|
|
||||||
Breaking Changes:
|
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.
|
- `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).
|
- `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).
|
- `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).
|
- `iris.Gzip` and `iris.GzipReader` replaced with `iris.Compression` (middleware).
|
||||||
- `ctx.ClientSupportsGzip() bool` replaced with `ctx.ClientSupportsEncoding("gzip", "br" ...) bool`.
|
- `ctx.ClientSupportsGzip() bool` replaced with `ctx.ClientSupportsEncoding("gzip", "br" ...) bool`.
|
||||||
- `ctx.GzipResponseWriter()` is **removed**.
|
- `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.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.
|
- `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).
|
- 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)
|
* [Write to a custom `io.Writer`](view/write-to)
|
||||||
* [Blocks](view/template_blocks_0)
|
* [Blocks](view/template_blocks_0)
|
||||||
* [Blocks Embedded](view/template_blocks_1_embedded)
|
* [Blocks Embedded](view/template_blocks_1_embedded)
|
||||||
* [Pug: Greeting](view/template_pug_0)
|
* [Pug: `Actions`](view/template_pug_0)
|
||||||
* [Pug: `Actions`](view/template_pug_1)
|
* [Pug: `Includes`](view/template_pug_1)
|
||||||
* [Pug: `Includes`](view/template_pug_2)
|
* [Pug Embedded`](view/template_pug_2_embedded)
|
||||||
* [Pug: `Extends`](view/template_pug_3)
|
* [Jet](view/template_jet_0)
|
||||||
* [Jet Template](view/template_jet_0)
|
|
||||||
* [Jet Embedded](view/template_jet_1_embedded)
|
* [Jet Embedded](view/template_jet_1_embedded)
|
||||||
* [Jet 'urlpath' tmpl func](view/template_jet_2)
|
* [Jet 'urlpath' tmpl func](view/template_jet_2)
|
||||||
* [Jet Template Funcs from Struct](view/template_jet_3)
|
* [Jet Template Funcs from Struct](view/template_jet_3)
|
||||||
* [Ace](view/template_ace_0)
|
* [Ace](view/template_ace_0)
|
||||||
|
* [Amber](view/template_amber_0)
|
||||||
|
* [Amber Embedded](view/template_amber_1_embedded)
|
||||||
* [Handlebars](view/template_handlebars_0)
|
* [Handlebars](view/template_handlebars_0)
|
||||||
* Third-Parties
|
* Third-Parties
|
||||||
* [Render `valyala/quicktemplate` templates](view/quicktemplate)
|
* [Render `valyala/quicktemplate` templates](view/quicktemplate)
|
||||||
|
|
|
@ -5,7 +5,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Follow these steps first:
|
// 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-bindata -prefix "assets" -fs ./assets/...
|
||||||
// $ go run .
|
// $ go run .
|
||||||
// "physical" files are not used, you can delete the "assets" folder and run the example.
|
// "physical" files are not used, you can delete the "assets" folder and run the example.
|
||||||
|
|
|
@ -6,7 +6,9 @@ import (
|
||||||
|
|
||||||
// How to run:
|
// 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-bindata -prefix "../embedding-files-into-app/assets/" -fs ../embedding-files-into-app/assets/...
|
||||||
// $ go run .
|
// $ go run .
|
||||||
// Time to complete the compression and caching of [2/3] files: 31.9998ms
|
// Time to complete the compression and caching of [2/3] files: 31.9998ms
|
||||||
|
|
|
@ -7,7 +7,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// How to run:
|
// 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/...
|
// $ go-bindata -nomemcopy -fs -prefix "../http2push/assets" ../http2push/assets/...
|
||||||
// # OR if the ./assets directory was inside this example foder:
|
// # OR if the ./assets directory was inside this example foder:
|
||||||
// # go-bindata -nomemcopy -refix "assets" ./assets/...
|
// # go-bindata -nomemcopy -refix "assets" ./assets/...
|
||||||
|
|
|
@ -2,7 +2,9 @@ package main
|
||||||
|
|
||||||
import "github.com/kataras/iris/v12"
|
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-bindata -fs -prefix "public" ./public/...
|
||||||
// $ go run .
|
// $ go run .
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func bindataRead(data, name string) ([]byte, error) {
|
func bindataRead(data []byte, name string) ([]byte, error) {
|
||||||
gz, err := gzip.NewReader(strings.NewReader(data))
|
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("read %q: %v", name, err)
|
return nil, fmt.Errorf("read %q: %v", name, err)
|
||||||
}
|
}
|
||||||
|
@ -168,82 +168,82 @@ func AssetFile() http.FileSystem {
|
||||||
return &assetOperator{}
|
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(
|
return bindataRead(
|
||||||
_publicAppJs,
|
_appJs,
|
||||||
"public/app.js",
|
"app.js",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func publicAppJs() (*asset, error) {
|
func appJs() (*asset, error) {
|
||||||
bytes, err := publicAppJsBytes()
|
bytes, err := appJsBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
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(
|
return bindataRead(
|
||||||
_publicApp2IndexHtml,
|
_app2IndexHtml,
|
||||||
"public/app2/index.html",
|
"app2/index.html",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func publicApp2IndexHtml() (*asset, error) {
|
func app2IndexHtml() (*asset, error) {
|
||||||
bytes, err := publicApp2IndexHtmlBytes()
|
bytes, err := app2IndexHtmlBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
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(
|
return bindataRead(
|
||||||
_publicCssMainCss,
|
_cssMainCss,
|
||||||
"public/css/main.css",
|
"css/main.css",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func publicCssMainCss() (*asset, error) {
|
func cssMainCss() (*asset, error) {
|
||||||
bytes, err := publicCssMainCssBytes()
|
bytes, err := cssMainCssBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
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(
|
return bindataRead(
|
||||||
_publicIndexHtml,
|
_indexHtml,
|
||||||
"public/index.html",
|
"index.html",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func publicIndexHtml() (*asset, error) {
|
func indexHtml() (*asset, error) {
|
||||||
bytes, err := publicIndexHtmlBytes()
|
bytes, err := indexHtmlBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
@ -300,10 +300,10 @@ func AssetNames() []string {
|
||||||
|
|
||||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||||
var _bindata = map[string]func() (*asset, error){
|
var _bindata = map[string]func() (*asset, error){
|
||||||
"public/app.js": publicAppJs,
|
"app.js": appJs,
|
||||||
"public/app2/index.html": publicApp2IndexHtml,
|
"app2/index.html": app2IndexHtml,
|
||||||
"public/css/main.css": publicCssMainCss,
|
"css/main.css": cssMainCss,
|
||||||
"public/index.html": publicIndexHtml,
|
"index.html": indexHtml,
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssetDir returns the file names below a certain
|
// AssetDir returns the file names below a certain
|
||||||
|
@ -347,16 +347,14 @@ type bintree struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var _bintree = &bintree{nil, map[string]*bintree{
|
var _bintree = &bintree{nil, map[string]*bintree{
|
||||||
"public": {nil, map[string]*bintree{
|
"app.js": {appJs, map[string]*bintree{}},
|
||||||
"app.js": {publicAppJs, map[string]*bintree{}},
|
"app2": {nil, map[string]*bintree{
|
||||||
"app2": {nil, map[string]*bintree{
|
"index.html": {app2IndexHtml, 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{}},
|
|
||||||
}},
|
}},
|
||||||
|
"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
|
// RestoreAsset restores an asset under the given directory
|
||||||
|
|
|
@ -4,8 +4,10 @@ import (
|
||||||
"github.com/kataras/iris/v12"
|
"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
|
||||||
// $ go-bindata -nomemcopy -fs ./public/...
|
// # 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 .
|
// $ go run .
|
||||||
|
|
||||||
var page = struct {
|
var page = struct {
|
||||||
|
@ -14,20 +16,16 @@ var page = struct {
|
||||||
|
|
||||||
func newApp() *iris.Application {
|
func newApp() *iris.Application {
|
||||||
app := iris.New()
|
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) {
|
app.Get("/", func(ctx iris.Context) {
|
||||||
ctx.ViewData("Page", page)
|
ctx.ViewData("Page", page)
|
||||||
ctx.View("index.html")
|
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
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// Code generated for package main by go-bindata DO NOT EDIT. (@generated)
|
// Code generated by go-bindata. (@generated) DO NOT EDIT.
|
||||||
// sources:
|
|
||||||
|
//Package main generated by go-bindata.// sources:
|
||||||
// templates/layouts/layout.html
|
// templates/layouts/layout.html
|
||||||
// templates/layouts/mylayout.html
|
// templates/layouts/mylayout.html
|
||||||
// templates/page1.html
|
// templates/page1.html
|
||||||
|
@ -12,6 +13,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -21,7 +23,7 @@ import (
|
||||||
func bindataRead(data []byte, name string) ([]byte, error) {
|
func bindataRead(data []byte, name string) ([]byte, error) {
|
||||||
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
||||||
if err != nil {
|
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
|
var buf bytes.Buffer
|
||||||
|
@ -29,7 +31,7 @@ func bindataRead(data []byte, name string) ([]byte, error) {
|
||||||
clErr := gz.Close()
|
clErr := gz.Close()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
return nil, fmt.Errorf("read %q: %v", name, err)
|
||||||
}
|
}
|
||||||
if clErr != nil {
|
if clErr != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -65,7 +67,7 @@ func (fi bindataFileInfo) Mode() os.FileMode {
|
||||||
return fi.mode
|
return fi.mode
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mode return file modify time
|
// ModTime return file modify time
|
||||||
func (fi bindataFileInfo) ModTime() time.Time {
|
func (fi bindataFileInfo) ModTime() time.Time {
|
||||||
return fi.modTime
|
return fi.modTime
|
||||||
}
|
}
|
||||||
|
@ -80,82 +82,168 @@ func (fi bindataFileInfo) Sys() interface{} {
|
||||||
return nil
|
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(
|
return bindataRead(
|
||||||
_templatesLayoutsLayoutHtml,
|
_layoutsLayoutHtml,
|
||||||
"templates/layouts/layout.html",
|
"layouts/layout.html",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func templatesLayoutsLayoutHtml() (*asset, error) {
|
func layoutsLayoutHtml() (*asset, error) {
|
||||||
bytes, err := templatesLayoutsLayoutHtmlBytes()
|
bytes, err := layoutsLayoutHtmlBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
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(
|
return bindataRead(
|
||||||
_templatesLayoutsMylayoutHtml,
|
_layoutsMylayoutHtml,
|
||||||
"templates/layouts/mylayout.html",
|
"layouts/mylayout.html",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func templatesLayoutsMylayoutHtml() (*asset, error) {
|
func layoutsMylayoutHtml() (*asset, error) {
|
||||||
bytes, err := templatesLayoutsMylayoutHtmlBytes()
|
bytes, err := layoutsMylayoutHtmlBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
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(
|
return bindataRead(
|
||||||
_templatesPage1Html,
|
_page1Html,
|
||||||
"templates/page1.html",
|
"page1.html",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func templatesPage1Html() (*asset, error) {
|
func page1Html() (*asset, error) {
|
||||||
bytes, err := templatesPage1HtmlBytes()
|
bytes, err := page1HtmlBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
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(
|
return bindataRead(
|
||||||
_templatesPartialsPage1_partial1Html,
|
_partialsPage1_partial1Html,
|
||||||
"templates/partials/page1_partial1.html",
|
"partials/page1_partial1.html",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func templatesPartialsPage1_partial1Html() (*asset, error) {
|
func partialsPage1_partial1Html() (*asset, error) {
|
||||||
bytes, err := templatesPartialsPage1_partial1HtmlBytes()
|
bytes, err := partialsPage1_partial1HtmlBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
@ -212,10 +300,10 @@ func AssetNames() []string {
|
||||||
|
|
||||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||||
var _bindata = map[string]func() (*asset, error){
|
var _bindata = map[string]func() (*asset, error){
|
||||||
"templates/layouts/layout.html": templatesLayoutsLayoutHtml,
|
"layouts/layout.html": layoutsLayoutHtml,
|
||||||
"templates/layouts/mylayout.html": templatesLayoutsMylayoutHtml,
|
"layouts/mylayout.html": layoutsMylayoutHtml,
|
||||||
"templates/page1.html": templatesPage1Html,
|
"page1.html": page1Html,
|
||||||
"templates/partials/page1_partial1.html": templatesPartialsPage1_partial1Html,
|
"partials/page1_partial1.html": partialsPage1_partial1Html,
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssetDir returns the file names below a certain
|
// AssetDir returns the file names below a certain
|
||||||
|
@ -259,15 +347,13 @@ type bintree struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var _bintree = &bintree{nil, map[string]*bintree{
|
var _bintree = &bintree{nil, map[string]*bintree{
|
||||||
"templates": {nil, map[string]*bintree{
|
"layouts": {nil, map[string]*bintree{
|
||||||
"layouts": {nil, map[string]*bintree{
|
"layout.html": {layoutsLayoutHtml, map[string]*bintree{}},
|
||||||
"layout.html": {templatesLayoutsLayoutHtml, map[string]*bintree{}},
|
"mylayout.html": {layoutsMylayoutHtml, map[string]*bintree{}},
|
||||||
"mylayout.html": {templatesLayoutsMylayoutHtml, map[string]*bintree{}},
|
}},
|
||||||
}},
|
"page1.html": {page1Html, map[string]*bintree{}},
|
||||||
"page1.html": {templatesPage1Html, map[string]*bintree{}},
|
"partials": {nil, map[string]*bintree{
|
||||||
"partials": {nil, map[string]*bintree{
|
"page1_partial1.html": {partialsPage1_partial1Html, map[string]*bintree{}},
|
||||||
"page1_partial1.html": {templatesPartialsPage1_partial1Html, map[string]*bintree{}},
|
|
||||||
}},
|
|
||||||
}},
|
}},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,22 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "github.com/kataras/iris/v12"
|
||||||
"github.com/kataras/iris/v12"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := iris.New()
|
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.Layout("layouts/layout.html")
|
||||||
tmpl.AddFunc("greet", func(s string) string {
|
tmpl.AddFunc("greet", func(s string) string {
|
||||||
return "Greetings " + s + "!"
|
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.RegisterView(tmpl)
|
||||||
|
|
||||||
app.Get("/", func(ctx iris.Context) {
|
app.Get("/", func(ctx iris.Context) {
|
||||||
|
@ -54,8 +52,3 @@ func main() {
|
||||||
// http://localhost:8080/my/other
|
// http://localhost:8080/my/other
|
||||||
app.Listen(":8080")
|
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
|
head
|
||||||
title Main Page
|
title Main Page
|
||||||
body
|
body
|
||||||
|
h1 Layout
|
||||||
{{ yield }}
|
{{ 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.
|
// 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/500.html
|
||||||
// ../template_blocks_0/views/index.html
|
// ../template_blocks_0/views/index.html
|
||||||
// ../template_blocks_0/views/layouts/error.html
|
// ../template_blocks_0/views/layouts/error.html
|
||||||
|
@ -14,6 +14,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -82,102 +83,188 @@ func (fi bindataFileInfo) Sys() interface{} {
|
||||||
return nil
|
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(
|
return bindataRead(
|
||||||
_views500Html,
|
__500Html,
|
||||||
"views/500.html",
|
"500.html",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func views500Html() (*asset, error) {
|
func _500Html() (*asset, error) {
|
||||||
bytes, err := views500HtmlBytes()
|
bytes, err := _500HtmlBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
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(
|
return bindataRead(
|
||||||
_viewsIndexHtml,
|
_indexHtml,
|
||||||
"views/index.html",
|
"index.html",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewsIndexHtml() (*asset, error) {
|
func indexHtml() (*asset, error) {
|
||||||
bytes, err := viewsIndexHtmlBytes()
|
bytes, err := indexHtmlBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
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(
|
return bindataRead(
|
||||||
_viewsLayoutsErrorHtml,
|
_layoutsErrorHtml,
|
||||||
"views/layouts/error.html",
|
"layouts/error.html",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewsLayoutsErrorHtml() (*asset, error) {
|
func layoutsErrorHtml() (*asset, error) {
|
||||||
bytes, err := viewsLayoutsErrorHtmlBytes()
|
bytes, err := layoutsErrorHtmlBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
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(
|
return bindataRead(
|
||||||
_viewsLayoutsMainHtml,
|
_layoutsMainHtml,
|
||||||
"views/layouts/main.html",
|
"layouts/main.html",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewsLayoutsMainHtml() (*asset, error) {
|
func layoutsMainHtml() (*asset, error) {
|
||||||
bytes, err := viewsLayoutsMainHtmlBytes()
|
bytes, err := layoutsMainHtmlBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
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(
|
return bindataRead(
|
||||||
_viewsPartialsFooterHtml,
|
_partialsFooterHtml,
|
||||||
"views/partials/footer.html",
|
"partials/footer.html",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewsPartialsFooterHtml() (*asset, error) {
|
func partialsFooterHtml() (*asset, error) {
|
||||||
bytes, err := viewsPartialsFooterHtmlBytes()
|
bytes, err := partialsFooterHtmlBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
@ -186,8 +273,8 @@ func viewsPartialsFooterHtml() (*asset, error) {
|
||||||
// It returns an error if the asset could not be found or
|
// It returns an error if the asset could not be found or
|
||||||
// could not be loaded.
|
// could not be loaded.
|
||||||
func Asset(name string) ([]byte, error) {
|
func Asset(name string) ([]byte, error) {
|
||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
if f, ok := _bindata[cannonicalName]; ok {
|
if f, ok := _bindata[canonicalName]; ok {
|
||||||
a, err := f()
|
a, err := f()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
|
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
|
// It returns an error if the asset could not be found or
|
||||||
// could not be loaded.
|
// could not be loaded.
|
||||||
func AssetInfo(name string) (os.FileInfo, error) {
|
func AssetInfo(name string) (os.FileInfo, error) {
|
||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
if f, ok := _bindata[cannonicalName]; ok {
|
if f, ok := _bindata[canonicalName]; ok {
|
||||||
a, err := f()
|
a, err := f()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
|
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.
|
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||||
var _bindata = map[string]func() (*asset, error){
|
var _bindata = map[string]func() (*asset, error){
|
||||||
"views/500.html": views500Html,
|
"500.html": _500Html,
|
||||||
"views/index.html": viewsIndexHtml,
|
"index.html": indexHtml,
|
||||||
"views/layouts/error.html": viewsLayoutsErrorHtml,
|
"layouts/error.html": layoutsErrorHtml,
|
||||||
"views/layouts/main.html": viewsLayoutsMainHtml,
|
"layouts/main.html": layoutsMainHtml,
|
||||||
"views/partials/footer.html": viewsPartialsFooterHtml,
|
"partials/footer.html": partialsFooterHtml,
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssetDir returns the file names below a certain
|
// AssetDir returns the file names below a certain
|
||||||
|
@ -252,13 +339,13 @@ var _bindata = map[string]func() (*asset, error){
|
||||||
// b.png
|
// b.png
|
||||||
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
||||||
// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
// 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"}.
|
// AssetDir("") will return []string{"data"}.
|
||||||
func AssetDir(name string) ([]string, error) {
|
func AssetDir(name string) ([]string, error) {
|
||||||
node := _bintree
|
node := _bintree
|
||||||
if len(name) != 0 {
|
if len(name) != 0 {
|
||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
pathList := strings.Split(cannonicalName, "/")
|
pathList := strings.Split(canonicalName, "/")
|
||||||
for _, p := range pathList {
|
for _, p := range pathList {
|
||||||
node = node.Children[p]
|
node = node.Children[p]
|
||||||
if node == nil {
|
if node == nil {
|
||||||
|
@ -282,16 +369,14 @@ type bintree struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var _bintree = &bintree{nil, map[string]*bintree{
|
var _bintree = &bintree{nil, map[string]*bintree{
|
||||||
"views": {nil, map[string]*bintree{
|
"500.html": {_500Html, map[string]*bintree{}},
|
||||||
"500.html": {views500Html, map[string]*bintree{}},
|
"index.html": {indexHtml, map[string]*bintree{}},
|
||||||
"index.html": {viewsIndexHtml, map[string]*bintree{}},
|
"layouts": {nil, map[string]*bintree{
|
||||||
"layouts": {nil, map[string]*bintree{
|
"error.html": {layoutsErrorHtml, map[string]*bintree{}},
|
||||||
"error.html": {viewsLayoutsErrorHtml, map[string]*bintree{}},
|
"main.html": {layoutsMainHtml, map[string]*bintree{}},
|
||||||
"main.html": {viewsLayoutsMainHtml, map[string]*bintree{}},
|
}},
|
||||||
}},
|
"partials": {nil, map[string]*bintree{
|
||||||
"partials": {nil, map[string]*bintree{
|
"footer.html": {partialsFooterHtml, map[string]*bintree{}},
|
||||||
"footer.html": {viewsPartialsFooterHtml, map[string]*bintree{}},
|
|
||||||
}},
|
|
||||||
}},
|
}},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
@ -338,6 +423,6 @@ func RestoreAssets(dir, name string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func _filePath(dir, name string) string {
|
func _filePath(dir, name string) string {
|
||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,21 @@ package main
|
||||||
|
|
||||||
import "github.com/kataras/iris/v12"
|
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
|
||||||
// $ go-bindata -prefix "../template_blocks_0" ../template_blocks_0/views/...
|
// # 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 .
|
// $ 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.
|
// System files are not used, you can optionally delete the folder and run the example now.
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
app.RegisterView(iris.Blocks("./views", ".html").Binary(Asset, AssetNames))
|
app.RegisterView(iris.Blocks(AssetFile(), ".html"))
|
||||||
|
|
||||||
app.Get("/", index)
|
app.Get("/", index)
|
||||||
app.Get("/500", internalServerError)
|
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.
|
// Code generated by go-bindata. (@generated) DO NOT EDIT.
|
||||||
// sources:
|
|
||||||
|
// Package main generated by go-bindata.// sources:
|
||||||
// views/includes/_partial.jet
|
// views/includes/_partial.jet
|
||||||
// views/includes/blocks.jet
|
// views/includes/blocks.jet
|
||||||
// views/index.jet
|
// views/index.jet
|
||||||
|
@ -12,6 +13,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -21,7 +23,7 @@ import (
|
||||||
func bindataRead(data []byte, name string) ([]byte, error) {
|
func bindataRead(data []byte, name string) ([]byte, error) {
|
||||||
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
||||||
if err != nil {
|
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
|
var buf bytes.Buffer
|
||||||
|
@ -29,7 +31,7 @@ func bindataRead(data []byte, name string) ([]byte, error) {
|
||||||
clErr := gz.Close()
|
clErr := gz.Close()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
return nil, fmt.Errorf("read %q: %v", name, err)
|
||||||
}
|
}
|
||||||
if clErr != nil {
|
if clErr != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -50,101 +52,198 @@ type bindataFileInfo struct {
|
||||||
modTime time.Time
|
modTime time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name return file name
|
||||||
func (fi bindataFileInfo) Name() string {
|
func (fi bindataFileInfo) Name() string {
|
||||||
return fi.name
|
return fi.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Size return file size
|
||||||
func (fi bindataFileInfo) Size() int64 {
|
func (fi bindataFileInfo) Size() int64 {
|
||||||
return fi.size
|
return fi.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mode return file mode
|
||||||
func (fi bindataFileInfo) Mode() os.FileMode {
|
func (fi bindataFileInfo) Mode() os.FileMode {
|
||||||
return fi.mode
|
return fi.mode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ModTime return file modify time
|
||||||
func (fi bindataFileInfo) ModTime() time.Time {
|
func (fi bindataFileInfo) ModTime() time.Time {
|
||||||
return fi.modTime
|
return fi.modTime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDir return file whether a directory
|
||||||
func (fi bindataFileInfo) IsDir() bool {
|
func (fi bindataFileInfo) IsDir() bool {
|
||||||
return false
|
return fi.mode&os.ModeDir != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sys return file is sys mode
|
||||||
func (fi bindataFileInfo) Sys() interface{} {
|
func (fi bindataFileInfo) Sys() interface{} {
|
||||||
return nil
|
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(
|
return bindataRead(
|
||||||
_viewsIncludes_partialJet,
|
_includes_partialJet,
|
||||||
"views/includes/_partial.jet",
|
"includes/_partial.jet",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewsIncludes_partialJet() (*asset, error) {
|
func includes_partialJet() (*asset, error) {
|
||||||
bytes, err := viewsIncludes_partialJetBytes()
|
bytes, err := includes_partialJetBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
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(
|
return bindataRead(
|
||||||
_viewsIncludesBlocksJet,
|
_includesBlocksJet,
|
||||||
"views/includes/blocks.jet",
|
"includes/blocks.jet",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewsIncludesBlocksJet() (*asset, error) {
|
func includesBlocksJet() (*asset, error) {
|
||||||
bytes, err := viewsIncludesBlocksJetBytes()
|
bytes, err := includesBlocksJetBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
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(
|
return bindataRead(
|
||||||
_viewsIndexJet,
|
_indexJet,
|
||||||
"views/index.jet",
|
"index.jet",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewsIndexJet() (*asset, error) {
|
func indexJet() (*asset, error) {
|
||||||
bytes, err := viewsIndexJetBytes()
|
bytes, err := indexJetBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
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(
|
return bindataRead(
|
||||||
_viewsLayoutsApplicationJet,
|
_layoutsApplicationJet,
|
||||||
"views/layouts/application.jet",
|
"layouts/application.jet",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewsLayoutsApplicationJet() (*asset, error) {
|
func layoutsApplicationJet() (*asset, error) {
|
||||||
bytes, err := viewsLayoutsApplicationJetBytes()
|
bytes, err := layoutsApplicationJetBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
@ -153,8 +252,8 @@ func viewsLayoutsApplicationJet() (*asset, error) {
|
||||||
// It returns an error if the asset could not be found or
|
// It returns an error if the asset could not be found or
|
||||||
// could not be loaded.
|
// could not be loaded.
|
||||||
func Asset(name string) ([]byte, error) {
|
func Asset(name string) ([]byte, error) {
|
||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
if f, ok := _bindata[cannonicalName]; ok {
|
if f, ok := _bindata[canonicalName]; ok {
|
||||||
a, err := f()
|
a, err := f()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
|
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
|
// It returns an error if the asset could not be found or
|
||||||
// could not be loaded.
|
// could not be loaded.
|
||||||
func AssetInfo(name string) (os.FileInfo, error) {
|
func AssetInfo(name string) (os.FileInfo, error) {
|
||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
if f, ok := _bindata[cannonicalName]; ok {
|
if f, ok := _bindata[canonicalName]; ok {
|
||||||
a, err := f()
|
a, err := f()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
|
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.
|
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||||
var _bindata = map[string]func() (*asset, error){
|
var _bindata = map[string]func() (*asset, error){
|
||||||
"views/includes/_partial.jet": viewsIncludes_partialJet,
|
"includes/_partial.jet": includes_partialJet,
|
||||||
"views/includes/blocks.jet": viewsIncludesBlocksJet,
|
"includes/blocks.jet": includesBlocksJet,
|
||||||
"views/index.jet": viewsIndexJet,
|
"index.jet": indexJet,
|
||||||
"views/layouts/application.jet": viewsLayoutsApplicationJet,
|
"layouts/application.jet": layoutsApplicationJet,
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssetDir returns the file names below a certain
|
// AssetDir returns the file names below a certain
|
||||||
|
@ -218,13 +317,13 @@ var _bindata = map[string]func() (*asset, error){
|
||||||
// b.png
|
// b.png
|
||||||
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
||||||
// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
// 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"}.
|
// AssetDir("") will return []string{"data"}.
|
||||||
func AssetDir(name string) ([]string, error) {
|
func AssetDir(name string) ([]string, error) {
|
||||||
node := _bintree
|
node := _bintree
|
||||||
if len(name) != 0 {
|
if len(name) != 0 {
|
||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
pathList := strings.Split(cannonicalName, "/")
|
pathList := strings.Split(canonicalName, "/")
|
||||||
for _, p := range pathList {
|
for _, p := range pathList {
|
||||||
node = node.Children[p]
|
node = node.Children[p]
|
||||||
if node == nil {
|
if node == nil {
|
||||||
|
@ -248,15 +347,13 @@ type bintree struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var _bintree = &bintree{nil, map[string]*bintree{
|
var _bintree = &bintree{nil, map[string]*bintree{
|
||||||
"views": {nil, map[string]*bintree{
|
"includes": {nil, map[string]*bintree{
|
||||||
"includes": {nil, map[string]*bintree{
|
"_partial.jet": {includes_partialJet, map[string]*bintree{}},
|
||||||
"_partial.jet": {viewsIncludes_partialJet, map[string]*bintree{}},
|
"blocks.jet": {includesBlocksJet, map[string]*bintree{}},
|
||||||
"blocks.jet": {viewsIncludesBlocksJet, map[string]*bintree{}},
|
}},
|
||||||
}},
|
"index.jet": {indexJet, map[string]*bintree{}},
|
||||||
"index.jet": {viewsIndexJet, map[string]*bintree{}},
|
"layouts": {nil, map[string]*bintree{
|
||||||
"layouts": {nil, map[string]*bintree{
|
"application.jet": {layoutsApplicationJet, map[string]*bintree{}},
|
||||||
"application.jet": {viewsLayoutsApplicationJet, map[string]*bintree{}},
|
|
||||||
}},
|
|
||||||
}},
|
}},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
@ -303,6 +400,6 @@ func RestoreAssets(dir, name string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func _filePath(dir, name string) string {
|
func _filePath(dir, name string) string {
|
||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,29 +6,31 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/kataras/iris/v12"
|
"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
|
||||||
// $ go-bindata ./views/...
|
// # 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 .
|
// $ go run .
|
||||||
|
//
|
||||||
|
// System files are not used, you can optionally delete the folder and run the example now.
|
||||||
func main() {
|
func main() {
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
tmpl := iris.Jet("./views", ".jet").Binary(Asset, AssetNames)
|
tmpl := iris.Jet(AssetFile(), ".jet")
|
||||||
app.RegisterView(tmpl)
|
app.RegisterView(tmpl)
|
||||||
|
|
||||||
app.Get("/", func(ctx iris.Context) {
|
app.Get("/", func(ctx iris.Context) {
|
||||||
ctx.View("index.jet")
|
ctx.View("index.jet")
|
||||||
})
|
})
|
||||||
|
|
||||||
port := os.Getenv("PORT")
|
addr := ":8080"
|
||||||
if len(port) == 0 {
|
if port := os.Getenv("PORT"); port != "" {
|
||||||
port = ":8080"
|
addr = ":" + port
|
||||||
} else if !strings.HasPrefix(":", port) {
|
|
||||||
port = ":" + port
|
|
||||||
}
|
}
|
||||||
|
|
||||||
app.Listen(port)
|
app.Listen(addr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,6 @@ import (
|
||||||
"github.com/kataras/iris/v12/view"
|
"github.com/kataras/iris/v12/view"
|
||||||
)
|
)
|
||||||
|
|
||||||
// https://github.com/kataras/iris/issues/1443
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
tmpl := iris.Jet("./views", ".jet")
|
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 {
|
func (ViewBuiler) Style(a view.JetArguments) reflect.Value {
|
||||||
path := a.Get(0).String()
|
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)
|
return reflect.ValueOf(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ViewBuiler) Script(a view.JetArguments) reflect.Value {
|
func (ViewBuiler) Script(a view.JetArguments) reflect.Value {
|
||||||
path := a.Get(0).String()
|
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)
|
return reflect.ValueOf(s)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,16 @@
|
||||||
{{ asset("./myasset.mp3")}}
|
{{ asset("./myasset.mp3")}}
|
||||||
<br/>
|
<br/>
|
||||||
{{ style("my-stle.css")}}
|
{{ style("my-stle.css") | raw}}
|
||||||
<br/>
|
<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
|
package main
|
||||||
|
|
||||||
import "github.com/kataras/iris/v12"
|
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() {
|
func main() {
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
|
|
||||||
tmpl := iris.Pug("./templates", ".pug")
|
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.RegisterView(tmpl)
|
||||||
|
|
||||||
app.Get("/", index)
|
app.Get("/", index)
|
||||||
|
@ -20,9 +28,15 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func index(ctx iris.Context) {
|
func index(ctx iris.Context) {
|
||||||
ctx.ViewData("pageTitle", "My Index Page")
|
job1 := Job{Employer: "Monash B", Role: "Honorary"}
|
||||||
ctx.ViewData("youAreUsingJade", true)
|
job2 := Job{Employer: "Box Hill", Role: "Head of HE"}
|
||||||
// Q: why need extension .pug?
|
|
||||||
// A: Because you can register more than one view engine per Iris application.
|
person := Person{
|
||||||
ctx.View("index.pug")
|
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
|
doctype html
|
||||||
html(lang="en")
|
html(lang="en")
|
||||||
head
|
head
|
||||||
title= .pageTitle
|
meta(charset="utf-8")
|
||||||
script(type='text/javascript').
|
title Title
|
||||||
if (foo) {
|
body
|
||||||
bar(1 + 5)
|
p ads
|
||||||
}
|
ul
|
||||||
body
|
li The name is {{.Name}}.
|
||||||
h1 Jade - template engine
|
li The age is {{.Age}}.
|
||||||
#container.col
|
|
||||||
if .youAreUsingJade
|
each _,_ in .Emails
|
||||||
p {{ greet "iris user" }} <!-- execute template funcs -->
|
div An email is {{.}}
|
||||||
p You are amazing!
|
|
||||||
else
|
| {{ with .Jobs }}
|
||||||
p Get on it!
|
each _,_ in .
|
||||||
p.
|
div
|
||||||
Jade is #[a(terse)] and simple
|
An employer is {{.Employer}}
|
||||||
templating language with a
|
and the role is {{.Role}}
|
||||||
#[strong focus] on performance
|
| {{ end }}
|
||||||
and powerful features.
|
|
||||||
+ withGo
|
|
|
@ -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
|
package main
|
||||||
|
|
||||||
import "github.com/kataras/iris/v12"
|
import (
|
||||||
|
"html/template"
|
||||||
|
|
||||||
type Person struct {
|
"github.com/kataras/iris/v12"
|
||||||
Name string
|
)
|
||||||
Age int
|
|
||||||
Emails []string
|
|
||||||
Jobs []*Job
|
|
||||||
}
|
|
||||||
|
|
||||||
type Job struct {
|
|
||||||
Employer string
|
|
||||||
Role string
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
|
|
||||||
tmpl := iris.Pug("./templates", ".pug")
|
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.RegisterView(tmpl)
|
||||||
|
|
||||||
app.Get("/", index)
|
app.Get("/", index)
|
||||||
|
@ -28,15 +24,5 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func index(ctx iris.Context) {
|
func index(ctx iris.Context) {
|
||||||
job1 := Job{Employer: "Monash B", Role: "Honorary"}
|
ctx.View("index.pug")
|
||||||
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,20 +1,7 @@
|
||||||
doctype html
|
doctype html
|
||||||
html(lang="en")
|
html
|
||||||
head
|
include header.pug
|
||||||
meta(charset="utf-8")
|
body
|
||||||
title Title
|
h1 My Site
|
||||||
body
|
p {{ bold "Welcome to my super lame site."}}
|
||||||
p ads
|
include footer.pug
|
||||||
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,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)
|
// Code generated by go-bindata. (@generated) DO NOT EDIT.
|
||||||
// sources:
|
|
||||||
|
// Package main generated by go-bindata.// sources:
|
||||||
// templates/index.pug
|
// templates/index.pug
|
||||||
// templates/layout.pug
|
// templates/layout.pug
|
||||||
package main
|
package main
|
||||||
|
@ -10,6 +11,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -19,7 +21,7 @@ import (
|
||||||
func bindataRead(data []byte, name string) ([]byte, error) {
|
func bindataRead(data []byte, name string) ([]byte, error) {
|
||||||
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
||||||
if err != nil {
|
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
|
var buf bytes.Buffer
|
||||||
|
@ -27,7 +29,7 @@ func bindataRead(data []byte, name string) ([]byte, error) {
|
||||||
clErr := gz.Close()
|
clErr := gz.Close()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
return nil, fmt.Errorf("read %q: %v", name, err)
|
||||||
}
|
}
|
||||||
if clErr != nil {
|
if clErr != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -63,7 +65,7 @@ func (fi bindataFileInfo) Mode() os.FileMode {
|
||||||
return fi.mode
|
return fi.mode
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mode return file modify time
|
// ModTime return file modify time
|
||||||
func (fi bindataFileInfo) ModTime() time.Time {
|
func (fi bindataFileInfo) ModTime() time.Time {
|
||||||
return fi.modTime
|
return fi.modTime
|
||||||
}
|
}
|
||||||
|
@ -78,42 +80,128 @@ func (fi bindataFileInfo) Sys() interface{} {
|
||||||
return nil
|
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(
|
return bindataRead(
|
||||||
_templatesIndexPug,
|
_indexPug,
|
||||||
"templates/index.pug",
|
"index.pug",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func templatesIndexPug() (*asset, error) {
|
func indexPug() (*asset, error) {
|
||||||
bytes, err := templatesIndexPugBytes()
|
bytes, err := indexPugBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
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(
|
return bindataRead(
|
||||||
_templatesLayoutPug,
|
_layoutPug,
|
||||||
"templates/layout.pug",
|
"layout.pug",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func templatesLayoutPug() (*asset, error) {
|
func layoutPug() (*asset, error) {
|
||||||
bytes, err := templatesLayoutPugBytes()
|
bytes, err := layoutPugBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
@ -122,8 +210,8 @@ func templatesLayoutPug() (*asset, error) {
|
||||||
// It returns an error if the asset could not be found or
|
// It returns an error if the asset could not be found or
|
||||||
// could not be loaded.
|
// could not be loaded.
|
||||||
func Asset(name string) ([]byte, error) {
|
func Asset(name string) ([]byte, error) {
|
||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
if f, ok := _bindata[cannonicalName]; ok {
|
if f, ok := _bindata[canonicalName]; ok {
|
||||||
a, err := f()
|
a, err := f()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
|
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
|
// It returns an error if the asset could not be found or
|
||||||
// could not be loaded.
|
// could not be loaded.
|
||||||
func AssetInfo(name string) (os.FileInfo, error) {
|
func AssetInfo(name string) (os.FileInfo, error) {
|
||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
if f, ok := _bindata[cannonicalName]; ok {
|
if f, ok := _bindata[canonicalName]; ok {
|
||||||
a, err := f()
|
a, err := f()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
|
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.
|
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||||
var _bindata = map[string]func() (*asset, error){
|
var _bindata = map[string]func() (*asset, error){
|
||||||
"templates/index.pug": templatesIndexPug,
|
"index.pug": indexPug,
|
||||||
"templates/layout.pug": templatesLayoutPug,
|
"layout.pug": layoutPug,
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssetDir returns the file names below a certain
|
// AssetDir returns the file names below a certain
|
||||||
|
@ -185,13 +273,13 @@ var _bindata = map[string]func() (*asset, error){
|
||||||
// b.png
|
// b.png
|
||||||
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
||||||
// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
// 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"}.
|
// AssetDir("") will return []string{"data"}.
|
||||||
func AssetDir(name string) ([]string, error) {
|
func AssetDir(name string) ([]string, error) {
|
||||||
node := _bintree
|
node := _bintree
|
||||||
if len(name) != 0 {
|
if len(name) != 0 {
|
||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
pathList := strings.Split(cannonicalName, "/")
|
pathList := strings.Split(canonicalName, "/")
|
||||||
for _, p := range pathList {
|
for _, p := range pathList {
|
||||||
node = node.Children[p]
|
node = node.Children[p]
|
||||||
if node == nil {
|
if node == nil {
|
||||||
|
@ -215,10 +303,8 @@ type bintree struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var _bintree = &bintree{nil, map[string]*bintree{
|
var _bintree = &bintree{nil, map[string]*bintree{
|
||||||
"templates": {nil, map[string]*bintree{
|
"index.pug": {indexPug, map[string]*bintree{}},
|
||||||
"index.pug": {templatesIndexPug, map[string]*bintree{}},
|
"layout.pug": {layoutPug, map[string]*bintree{}},
|
||||||
"layout.pug": {templatesLayoutPug, map[string]*bintree{}},
|
|
||||||
}},
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
// RestoreAsset restores an asset under the given directory
|
// RestoreAsset restores an asset under the given directory
|
||||||
|
@ -264,6 +350,6 @@ func RestoreAssets(dir, name string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func _filePath(dir, name string) string {
|
func _filePath(dir, name string) string {
|
||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
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.
|
// 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
|
// Usage:
|
||||||
func (api *APIBuilder) HandleDir(requestPath string, fs http.FileSystem, opts ...DirOptions) (routes []*Route) {
|
// 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
|
options := DefaultDirOptions
|
||||||
if len(opts) > 0 {
|
if len(opts) > 0 {
|
||||||
options = 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)
|
h := FileServer(fs, options)
|
||||||
description := "file server"
|
description := "file server"
|
||||||
if d, ok := fs.(http.Dir); ok {
|
if d, ok := fs.(http.Dir); ok {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/kataras/iris/v12/context"
|
"github.com/kataras/iris/v12/context"
|
||||||
"github.com/kataras/iris/v12/macro"
|
"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.
|
// 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
|
// Usage:
|
||||||
HandleDir(requestPath string, fs http.FileSystem, opts ...DirOptions) []*Route
|
// 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
|
// None registers an "offline" route
|
||||||
// see context.ExecRoute(routeName) and
|
// 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/pongo2 v0.0.1
|
||||||
github.com/iris-contrib/schema v0.0.6
|
github.com/iris-contrib/schema v0.0.6
|
||||||
github.com/json-iterator/go v1.1.10
|
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/golog v0.1.2
|
||||||
github.com/kataras/neffos v0.0.16
|
github.com/kataras/neffos v0.0.16
|
||||||
github.com/kataras/pio v0.0.10
|
github.com/kataras/pio v0.0.10
|
||||||
|
|
|
@ -115,11 +115,19 @@ func hi(ctx iris.Context) {
|
||||||
|
|
||||||
## Embedded
|
## Embedded
|
||||||
|
|
||||||
View engine supports bundled(https://github.com/go-bindata/go-bindata) template files too.
|
View engine supports bundled(https://github.com/go-bindata/go-bindata) template files too. Latest
|
||||||
`go-bindata` gives you two functions, `Assset` and `AssetNames`,
|
`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")`.
|
||||||
these can be set to each of the template engines using the `.Binary` function.
|
|
||||||
|
|
||||||
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
|
```go
|
||||||
package main
|
package main
|
||||||
|
@ -128,12 +136,7 @@ import "github.com/kataras/iris/v12"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
// $ go get -u github.com/go-bindata/go-bindata/v3/go-bindata
|
app.RegisterView(iris.HTML(AssetFile(), ".html"))
|
||||||
// $ 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.Get("/", hi)
|
app.Get("/", hi)
|
||||||
|
|
||||||
// http://localhost:8080
|
// http://localhost:8080
|
||||||
|
|
12
view/ace.go
12
view/ace.go
|
@ -1,7 +1,6 @@
|
||||||
package view
|
package view
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/yosssi/ace"
|
"github.com/yosssi/ace"
|
||||||
|
@ -13,8 +12,13 @@ import (
|
||||||
// The given "extension" MUST begin with a dot.
|
// The given "extension" MUST begin with a dot.
|
||||||
//
|
//
|
||||||
// Read more about the Ace Go Parser: https://github.com/yosssi/ace
|
// 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)
|
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(
|
src := ace.NewSource(
|
||||||
ace.NewFile(name, text),
|
ace.NewFile(name, text),
|
||||||
|
|
164
view/amber.go
164
view/amber.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -14,11 +15,10 @@ import (
|
||||||
|
|
||||||
// AmberEngine contains the amber view engine structure.
|
// AmberEngine contains the amber view engine structure.
|
||||||
type AmberEngine struct {
|
type AmberEngine struct {
|
||||||
|
fs http.FileSystem
|
||||||
// files configuration
|
// files configuration
|
||||||
directory string
|
rootDir string
|
||||||
extension 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
|
reload bool
|
||||||
//
|
//
|
||||||
rmu sync.RWMutex // locks for `ExecuteWiter` when `reload` is true.
|
rmu sync.RWMutex // locks for `ExecuteWiter` when `reload` is true.
|
||||||
|
@ -33,9 +33,15 @@ var (
|
||||||
|
|
||||||
// Amber creates and returns a new amber view engine.
|
// Amber creates and returns a new amber view engine.
|
||||||
// The given "extension" MUST begin with a dot.
|
// 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{
|
s := &AmberEngine{
|
||||||
directory: directory,
|
fs: getFS(fs),
|
||||||
|
rootDir: "/",
|
||||||
extension: extension,
|
extension: extension,
|
||||||
templateCache: make(map[string]*template.Template),
|
templateCache: make(map[string]*template.Template),
|
||||||
funcs: make(map[string]interface{}),
|
funcs: make(map[string]interface{}),
|
||||||
|
@ -44,20 +50,18 @@ func Amber(directory, extension string) *AmberEngine {
|
||||||
return s
|
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.
|
// Ext returns the file extension which this view engine is responsible to render.
|
||||||
func (s *AmberEngine) Ext() string {
|
func (s *AmberEngine) Ext() string {
|
||||||
return s.extension
|
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,
|
// 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
|
// use it when you're in development and you're boring of restarting
|
||||||
// the whole app when you edit a template file.
|
// 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.
|
// Returns an error if something bad happens, user is responsible to catch it.
|
||||||
func (s *AmberEngine) Load() error {
|
func (s *AmberEngine) Load() error {
|
||||||
if s.assetFn != nil && s.namesFn != nil {
|
s.rmu.Lock()
|
||||||
// embedded
|
defer s.rmu.Unlock()
|
||||||
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
|
|
||||||
|
|
||||||
// prepare the global amber funcs
|
// prepare the global amber funcs
|
||||||
funcs := template.FuncMap{}
|
funcs := template.FuncMap{}
|
||||||
|
@ -125,84 +105,52 @@ func (s *AmberEngine) loadDirectory() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
amber.FuncMap = funcs // set the funcs
|
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
|
opts := amber.Options{
|
||||||
if err == nil {
|
PrettyPrint: false,
|
||||||
s.templateCache = make(map[string]*template.Template)
|
LineNumbers: false,
|
||||||
for k, v := range templates {
|
VirtualFilesystem: s.fs,
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range s.funcs {
|
return walk(s.fs, s.rootDir, func(path string, info os.FileInfo, err error) error {
|
||||||
funcs[k] = v
|
if info == nil || info.IsDir() {
|
||||||
}
|
return nil
|
||||||
|
|
||||||
if len(virtualDirectory) > 0 {
|
|
||||||
if virtualDirectory[0] == '.' { // first check for .wrong
|
|
||||||
virtualDirectory = virtualDirectory[1:]
|
|
||||||
}
|
}
|
||||||
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()
|
if s.extension != "" {
|
||||||
|
if !strings.HasSuffix(path, s.extension) {
|
||||||
for _, path := range names {
|
return nil
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
func (s *AmberEngine) fromCache(relativeName string) *template.Template {
|
||||||
tmpl, ok := s.templateCache[relativeName]
|
if s.reload {
|
||||||
if ok {
|
s.rmu.RLock()
|
||||||
|
defer s.rmu.RUnlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
if tmpl, ok := s.templateCache[relativeName]; ok {
|
||||||
return tmpl
|
return tmpl
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
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 {
|
func (s *AmberEngine) ExecuteWriter(w io.Writer, filename string, layout string, bindingData interface{}) error {
|
||||||
// re-parse the templates if reload is enabled.
|
// re-parse the templates if reload is enabled.
|
||||||
if s.reload {
|
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 {
|
if err := s.Load(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -224,5 +168,5 @@ func (s *AmberEngine) ExecuteWriter(w io.Writer, filename string, layout string,
|
||||||
return tmpl.Execute(w, bindingData)
|
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.
|
// The given "extension" MUST begin with a dot.
|
||||||
//
|
//
|
||||||
// See `WrapBlocks` package-level function too.
|
// 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
|
// Ext returns empty ext as this template engine
|
||||||
|
@ -66,18 +86,6 @@ func (s *BlocksEngine) AddLayoutFunc(funcName string, funcBody interface{}) *Blo
|
||||||
return s
|
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
|
// Layout sets the default layout which inside should use
|
||||||
// the {{ template "content" . }} to render the main template.
|
// the {{ template "content" . }} to render the main template.
|
||||||
//
|
//
|
||||||
|
|
195
view/django.go
195
view/django.go
|
@ -2,9 +2,8 @@ package view
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
stdPath "path"
|
stdPath "path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -60,41 +59,40 @@ var AsValue = pongo2.AsValue
|
||||||
var AsSafeValue = pongo2.AsSafeValue
|
var AsSafeValue = pongo2.AsSafeValue
|
||||||
|
|
||||||
type tDjangoAssetLoader struct {
|
type tDjangoAssetLoader struct {
|
||||||
baseDir string
|
rootDir string
|
||||||
assetGet func(name string) ([]byte, error)
|
fs http.FileSystem
|
||||||
}
|
}
|
||||||
|
|
||||||
// Abs calculates the path to a given template. Whenever a path must be resolved
|
// 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.
|
// 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) {
|
if stdPath.IsAbs(name) {
|
||||||
return 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.
|
// 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) {
|
if stdPath.IsAbs(path) {
|
||||||
path = path[1:]
|
path = path[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := dal.assetGet(path)
|
res, err := asset(l.fs, path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytes.NewBuffer(res), nil
|
return bytes.NewReader(res), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DjangoEngine contains the django view engine structure.
|
// DjangoEngine contains the django view engine structure.
|
||||||
type DjangoEngine struct {
|
type DjangoEngine struct {
|
||||||
|
fs http.FileSystem
|
||||||
// files configuration
|
// files configuration
|
||||||
directory string
|
rootDir string
|
||||||
extension 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
|
reload bool
|
||||||
//
|
//
|
||||||
rmu sync.RWMutex // locks for filters, globals and `ExecuteWiter` when `reload` is true.
|
rmu sync.RWMutex // locks for filters, globals and `ExecuteWiter` when `reload` is true.
|
||||||
|
@ -102,7 +100,6 @@ type DjangoEngine struct {
|
||||||
filters map[string]FilterFunction
|
filters map[string]FilterFunction
|
||||||
// globals share context fields between templates.
|
// globals share context fields between templates.
|
||||||
globals map[string]interface{}
|
globals map[string]interface{}
|
||||||
mu sync.Mutex // locks for template cache
|
|
||||||
templateCache map[string]*pongo2.Template
|
templateCache map[string]*pongo2.Template
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,9 +110,15 @@ var (
|
||||||
|
|
||||||
// Django creates and returns a new django view engine.
|
// Django creates and returns a new django view engine.
|
||||||
// The given "extension" MUST begin with a dot.
|
// 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{
|
s := &DjangoEngine{
|
||||||
directory: directory,
|
fs: getFS(fs),
|
||||||
|
rootDir: "/",
|
||||||
extension: extension,
|
extension: extension,
|
||||||
globals: make(map[string]interface{}),
|
globals: make(map[string]interface{}),
|
||||||
filters: make(map[string]FilterFunction),
|
filters: make(map[string]FilterFunction),
|
||||||
|
@ -125,20 +128,18 @@ func Django(directory, extension string) *DjangoEngine {
|
||||||
return s
|
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.
|
// Ext returns the file extension which this view engine is responsible to render.
|
||||||
func (s *DjangoEngine) Ext() string {
|
func (s *DjangoEngine) Ext() string {
|
||||||
return s.extension
|
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,
|
// 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
|
// use it when you're in development and you're boring of restarting
|
||||||
// the whole app when you edit a template file.
|
// 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.
|
// Returns an error if something bad happens, user is responsible to catch it.
|
||||||
func (s *DjangoEngine) Load() error {
|
func (s *DjangoEngine) Load() error {
|
||||||
if s.assetFn != nil && s.namesFn != nil {
|
set := pongo2.NewSet("", &tDjangoAssetLoader{fs: s.fs, rootDir: s.rootDir})
|
||||||
// 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.Globals = getPongoContext(s.globals)
|
set.Globals = getPongoContext(s.globals)
|
||||||
|
|
||||||
s.mu.Lock()
|
s.rmu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.rmu.Unlock()
|
||||||
|
|
||||||
// Walk the supplied directory and compile any files that match our extension list.
|
return walk(s.fs, s.rootDir, func(path string, info os.FileInfo, err error) error {
|
||||||
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).
|
|
||||||
if info == nil || info.IsDir() {
|
if info == nil || info.IsDir() {
|
||||||
} else {
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
rel, err := filepath.Rel(dir, path)
|
if s.extension != "" {
|
||||||
if err != nil {
|
if !strings.HasSuffix(path, s.extension) {
|
||||||
templateErr = err
|
return nil
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ext := filepath.Ext(rel)
|
name := strings.TrimPrefix(path, "/")
|
||||||
if ext == virtualExtension {
|
s.templateCache[name], err = set.FromBytes(buf)
|
||||||
|
return err
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getPongoContext returns the pongo2.Context from map[string]interface{} or from pongo2.Context, used internaly
|
// 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 {
|
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 tmpl, ok := s.templateCache[relativeName]; ok {
|
||||||
|
|
||||||
if ok {
|
|
||||||
s.mu.Unlock()
|
|
||||||
return tmpl
|
return tmpl
|
||||||
}
|
}
|
||||||
s.mu.Unlock()
|
|
||||||
return nil
|
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 {
|
func (s *DjangoEngine) ExecuteWriter(w io.Writer, filename string, layout string, bindingData interface{}) error {
|
||||||
// re-parse the templates if reload is enabled.
|
// re-parse the templates if reload is enabled.
|
||||||
if s.reload {
|
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 {
|
if err := s.Load(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -380,5 +275,5 @@ func (s *DjangoEngine) ExecuteWriter(w io.Writer, filename string, layout string
|
||||||
return tmpl.ExecuteWriter(getPongoContext(bindingData), w)
|
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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -14,15 +14,16 @@ import (
|
||||||
|
|
||||||
// HandlebarsEngine contains the handlebars view engine structure.
|
// HandlebarsEngine contains the handlebars view engine structure.
|
||||||
type HandlebarsEngine struct {
|
type HandlebarsEngine struct {
|
||||||
|
fs http.FileSystem
|
||||||
// files configuration
|
// files configuration
|
||||||
directory string
|
rootDir string
|
||||||
extension string
|
extension string
|
||||||
assetFn func(name string) ([]byte, error) // for embedded, in combination with directory & extension
|
assetFn func(name string) ([]byte, error) // for embedded, in combination with directory & extension
|
||||||
namesFn func() []string // 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.
|
reload bool // if true, each time the ExecuteWriter is called the templates will be reloaded.
|
||||||
// parser configuration
|
// parser configuration
|
||||||
layout string
|
layout string
|
||||||
rmu sync.RWMutex // locks for helpers and `ExecuteWiter` when `reload` is true.
|
rmu sync.RWMutex
|
||||||
helpers map[string]interface{}
|
helpers map[string]interface{}
|
||||||
templateCache map[string]*raymond.Template
|
templateCache map[string]*raymond.Template
|
||||||
}
|
}
|
||||||
|
@ -34,9 +35,15 @@ var (
|
||||||
|
|
||||||
// Handlebars creates and returns a new handlebars view engine.
|
// Handlebars creates and returns a new handlebars view engine.
|
||||||
// The given "extension" MUST begin with a dot.
|
// 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{
|
s := &HandlebarsEngine{
|
||||||
directory: directory,
|
fs: getFS(fs),
|
||||||
|
rootDir: "/",
|
||||||
extension: extension,
|
extension: extension,
|
||||||
templateCache: make(map[string]*raymond.Template),
|
templateCache: make(map[string]*raymond.Template),
|
||||||
helpers: make(map[string]interface{}),
|
helpers: make(map[string]interface{}),
|
||||||
|
@ -54,20 +61,18 @@ func Handlebars(directory, extension string) *HandlebarsEngine {
|
||||||
return s
|
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.
|
// Ext returns the file extension which this view engine is responsible to render.
|
||||||
func (s *HandlebarsEngine) Ext() string {
|
func (s *HandlebarsEngine) Ext() string {
|
||||||
return s.extension
|
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,
|
// 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
|
// use it when you're in development and you're boring of restarting
|
||||||
// the whole app when you edit a template file.
|
// 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.
|
// Returns an error if something bad happens, user is responsible to catch it.
|
||||||
func (s *HandlebarsEngine) Load() error {
|
func (s *HandlebarsEngine) Load() error {
|
||||||
if s.assetFn != nil && s.namesFn != nil {
|
s.rmu.Lock()
|
||||||
// embedded
|
defer s.rmu.Unlock()
|
||||||
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 handlebars templates from directory.
|
|
||||||
func (s *HandlebarsEngine) loadDirectory() error {
|
|
||||||
// register the global helpers on the first load
|
// register the global helpers on the first load
|
||||||
if len(s.templateCache) == 0 && s.helpers != nil {
|
if len(s.templateCache) == 0 && s.helpers != nil {
|
||||||
raymond.RegisterHelpers(s.helpers)
|
raymond.RegisterHelpers(s.helpers)
|
||||||
}
|
}
|
||||||
|
|
||||||
dir, extension := s.directory, s.extension
|
return walk(s.fs, s.rootDir, func(path string, info os.FileInfo, _ error) error {
|
||||||
|
|
||||||
// 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 {
|
|
||||||
if info == nil || info.IsDir() {
|
if info == nil || info.IsDir() {
|
||||||
return nil
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ext := filepath.Ext(rel)
|
name := strings.TrimPrefix(path, "/")
|
||||||
if ext == extension {
|
tmpl, err := raymond.Parse(string(buf))
|
||||||
buf, err := ioutil.ReadFile(path)
|
if err != nil {
|
||||||
contents := string(buf)
|
return err
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
s.templateCache[name] = tmpl
|
||||||
|
|
||||||
return nil
|
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 {
|
func (s *HandlebarsEngine) fromCache(relativeName string) *raymond.Template {
|
||||||
tmpl, ok := s.templateCache[relativeName]
|
if s.reload {
|
||||||
if !ok {
|
s.rmu.RLock()
|
||||||
return nil
|
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) {
|
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 {
|
func (s *HandlebarsEngine) ExecuteWriter(w io.Writer, filename string, layout string, bindingData interface{}) error {
|
||||||
// re-parse the templates if reload is enabled.
|
// re-parse the templates if reload is enabled.
|
||||||
if s.reload {
|
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 {
|
if err := s.Load(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -295,5 +213,5 @@ func (s *HandlebarsEngine) ExecuteWriter(w io.Writer, filename string, layout st
|
||||||
return err
|
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"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -14,14 +14,16 @@ import (
|
||||||
|
|
||||||
// HTMLEngine contains the html view engine structure.
|
// HTMLEngine contains the html view engine structure.
|
||||||
type HTMLEngine struct {
|
type HTMLEngine struct {
|
||||||
|
// the file system to load from.
|
||||||
|
fs http.FileSystem
|
||||||
// files configuration
|
// files configuration
|
||||||
directory string
|
rootDir string
|
||||||
extension string
|
extension string
|
||||||
assetFn func(name string) ([]byte, error) // for embedded, in combination with directory & extension
|
// if true, each time the ExecuteWriter is called the templates will be reloaded,
|
||||||
namesFn func() []string // for embedded, in combination with directory & extension
|
// each ExecuteWriter waits to be finished before writing to a new one.
|
||||||
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.
|
reload bool
|
||||||
// parser configuration
|
// parser configuration
|
||||||
options []string // text options
|
options []string // (text) template options
|
||||||
left string
|
left string
|
||||||
right string
|
right string
|
||||||
layout string
|
layout string
|
||||||
|
@ -65,12 +67,16 @@ var emptyFuncs = template.FuncMap{
|
||||||
// The html engine used like the "html/template" standard go package
|
// The html engine used like the "html/template" standard go package
|
||||||
// but with a lot of extra features.
|
// but with a lot of extra features.
|
||||||
// The given "extension" MUST begin with a dot.
|
// 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{
|
s := &HTMLEngine{
|
||||||
directory: directory,
|
fs: getFS(fs),
|
||||||
|
rootDir: "/",
|
||||||
extension: extension,
|
extension: extension,
|
||||||
assetFn: nil,
|
|
||||||
namesFn: nil,
|
|
||||||
reload: false,
|
reload: false,
|
||||||
left: "{{",
|
left: "{{",
|
||||||
right: "}}",
|
right: "}}",
|
||||||
|
@ -82,20 +88,18 @@ func HTML(directory, extension string) *HTMLEngine {
|
||||||
return s
|
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.
|
// Ext returns the file extension which this view engine is responsible to render.
|
||||||
func (s *HTMLEngine) Ext() string {
|
func (s *HTMLEngine) Ext() string {
|
||||||
return s.extension
|
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,
|
// 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
|
// use it when you're in development and you're boring of restarting
|
||||||
// the whole app when you edit a template file.
|
// 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.
|
// Returns an error if something bad happens, caller is responsible to handle that.
|
||||||
func (s *HTMLEngine) Load() error {
|
func (s *HTMLEngine) Load() error {
|
||||||
// No need to make this with a complicated and "pro" way, just add lockers to the `ExecuteWriter`.
|
s.rmu.Lock()
|
||||||
// if `Reload(true)` and add a note for non conc access on dev mode.
|
defer s.rmu.Unlock()
|
||||||
// atomic.StoreUint32(&s.isLoading, 1)
|
|
||||||
// s.rmu.Lock()
|
|
||||||
// defer func() {
|
|
||||||
// s.rmu.Unlock()
|
|
||||||
// atomic.StoreUint32(&s.isLoading, 0)
|
|
||||||
// }()
|
|
||||||
|
|
||||||
if s.assetFn != nil && s.namesFn != nil {
|
s.Templates = template.New(s.rootDir)
|
||||||
// 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.Delims(s.left, s.right)
|
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() {
|
if info == nil || info.IsDir() {
|
||||||
} else {
|
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 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 {
|
if err != nil {
|
||||||
templateErr = err
|
|
||||||
return 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 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) {
|
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 {
|
func (s *HTMLEngine) ExecuteWriter(w io.Writer, name string, layout string, bindingData interface{}) error {
|
||||||
// re-parse the templates if reload is enabled.
|
// re-parse the templates if reload is enabled.
|
||||||
if s.reload {
|
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 {
|
if err := s.Load(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -505,14 +341,14 @@ func (s *HTMLEngine) ExecuteWriter(w io.Writer, name string, layout string, bind
|
||||||
|
|
||||||
t := s.Templates.Lookup(name)
|
t := s.Templates.Lookup(name)
|
||||||
if t == nil {
|
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)
|
s.runtimeFuncsFor(t, name, bindingData)
|
||||||
|
|
||||||
if layout = getLayout(layout, s.layout); layout != "" {
|
if layout = getLayout(layout, s.layout); layout != "" {
|
||||||
lt := s.Templates.Lookup(layout)
|
lt := s.Templates.Lookup(layout)
|
||||||
if lt == nil {
|
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)
|
s.layoutFuncsFor(lt, name, bindingData)
|
||||||
|
|
142
view/jet.go
142
view/jet.go
|
@ -3,8 +3,7 @@ package view
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"net/http"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -18,9 +17,10 @@ const jetEngineName = "jet"
|
||||||
|
|
||||||
// JetEngine is the jet template parser's view engine.
|
// JetEngine is the jet template parser's view engine.
|
||||||
type JetEngine struct {
|
type JetEngine struct {
|
||||||
directory string
|
fs http.FileSystem
|
||||||
|
rootDir string
|
||||||
extension string
|
extension string
|
||||||
// physical system files or app-embedded, see `Binary(..., ...)`. Defaults to file system on initialization.
|
|
||||||
loader jet.Loader
|
loader jet.Loader
|
||||||
|
|
||||||
developmentMode bool
|
developmentMode bool
|
||||||
|
@ -51,11 +51,12 @@ var jetExtensions = [...]string{
|
||||||
|
|
||||||
// Jet creates and returns a new jet view engine.
|
// Jet creates and returns a new jet view engine.
|
||||||
// The given "extension" MUST begin with a dot.
|
// The given "extension" MUST begin with a dot.
|
||||||
func Jet(directory, extension string) *JetEngine {
|
//
|
||||||
// if _, err := os.Stat(directory); os.IsNotExist(err) {
|
// Usage:
|
||||||
// panic(err)
|
// 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
|
extOK := false
|
||||||
for _, ext := range jetExtensions {
|
for _, ext := range jetExtensions {
|
||||||
if ext == extension {
|
if ext == extension {
|
||||||
|
@ -69,9 +70,9 @@ func Jet(directory, extension string) *JetEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &JetEngine{
|
s := &JetEngine{
|
||||||
directory: directory,
|
rootDir: "/",
|
||||||
extension: extension,
|
extension: extension,
|
||||||
loader: jet.NewOSFileSystemLoader(directory),
|
loader: &jetLoader{fs: getFS(fs)},
|
||||||
jetDataContextKey: "_jet",
|
jetDataContextKey: "_jet",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +84,13 @@ func (s *JetEngine) String() string {
|
||||||
return jetEngineName
|
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.
|
// Ext should return the final file extension which this view engine is responsible to render.
|
||||||
func (s *JetEngine) Ext() string {
|
func (s *JetEngine) Ext() string {
|
||||||
return s.extension
|
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
|
// SetLoader can be used when the caller wants to use something like
|
||||||
// multi.Loader or httpfs.Loader of the jet subpackages,
|
// multi.Loader or httpfs.Loader.
|
||||||
// overrides any previous loader may set by `Binary` or the default.
|
|
||||||
// Should act before `Load` or `iris.Application#RegisterView`.
|
|
||||||
func (s *JetEngine) SetLoader(loader jet.Loader) *JetEngine {
|
func (s *JetEngine) SetLoader(loader jet.Loader) *JetEngine {
|
||||||
s.loader = loader
|
s.loader = loader
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Binary optionally, use it when template files are distributed
|
type jetLoader struct {
|
||||||
// inside the app executable (.go generated files).
|
fs http.FileSystem
|
||||||
//
|
|
||||||
// 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 (
|
var _ jet.Loader = (*jetLoader)(nil)
|
||||||
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 (
|
// Open opens a file from file system.
|
||||||
_ jet.Loader = (*embeddedLoader)(nil)
|
func (l *jetLoader) Open(name string) (io.ReadCloser, error) {
|
||||||
_ io.ReadCloser = (*embeddedFile)(nil)
|
return l.fs.Open(name)
|
||||||
)
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exists checks if the template name exists by walking the list of template paths
|
// 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
|
// 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) {
|
func (l *jetLoader) Exists(name string) (string, bool) {
|
||||||
name = path.Join(l.vdir, filepath.ToSlash(name))
|
if _, err := l.fs.Open(name); err == nil {
|
||||||
|
|
||||||
if _, ok := l.names[name]; ok {
|
|
||||||
return name, true
|
return name, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
23
view/pug.go
23
view/pug.go
|
@ -2,9 +2,6 @@ package view
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/iris-contrib/jade"
|
"github.com/iris-contrib/jade"
|
||||||
)
|
)
|
||||||
|
@ -16,26 +13,23 @@ import (
|
||||||
//
|
//
|
||||||
// Read more about the Jade Go Parser: https://github.com/Joker/jade
|
// 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:
|
// Examples:
|
||||||
// https://github.com/kataras/iris/tree/master/_examples/view/template_pug_0
|
// 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_1
|
||||||
// https://github.com/kataras/iris/tree/master/_examples/view/template_pug_2
|
// https://github.com/kataras/iris/tree/master/_examples/view/template_pug_2
|
||||||
// https://github.com/kataras/iris/tree/master/_examples/view/template_pug_3
|
// https://github.com/kataras/iris/tree/master/_examples/view/template_pug_3
|
||||||
func Pug(directory, extension string) *HTMLEngine {
|
func Pug(fs interface{}, extension string) *HTMLEngine {
|
||||||
s := HTML(directory, extension)
|
s := HTML(fs, extension)
|
||||||
|
|
||||||
s.middleware = func(name string, text []byte) (contents string, err error) {
|
s.middleware = func(name string, text []byte) (contents string, err error) {
|
||||||
name = path.Join(path.Clean(directory), name)
|
|
||||||
tmpl := jade.New(name)
|
tmpl := jade.New(name)
|
||||||
tmpl.ReadFunc = func(name string) ([]byte, error) {
|
tmpl.ReadFunc = func(name string) ([]byte, error) {
|
||||||
if !strings.HasPrefix(path.Clean(name), path.Clean(directory)) {
|
return asset(s.fs, name)
|
||||||
name = path.Join(directory, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.assetFn != nil {
|
|
||||||
return s.assetFn(name)
|
|
||||||
}
|
|
||||||
return ioutil.ReadFile(name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fixes: https://github.com/kataras/iris/issues/1450
|
// 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:
|
// And Also able to use relative paths on "extends" and "include" directives:
|
||||||
// e.g. instead of extends "templates/layout.pug" we use "layout.pug"
|
// e.g. instead of extends "templates/layout.pug" we use "layout.pug"
|
||||||
// so contents of templates are independent of their root location.
|
// so contents of templates are independent of their root location.
|
||||||
|
|
||||||
exec, err := tmpl.Parse(text)
|
exec, err := tmpl.Parse(text)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
15
view/view.go
15
view/view.go
|
@ -19,6 +19,21 @@ type (
|
||||||
EngineFuncer = context.ViewEngineFuncer
|
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
|
// View is responsible to
|
||||||
// load the correct templates
|
// load the correct templates
|
||||||
// for each of the registered view engines.
|
// for each of the registered view engines.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user