mirror of
https://github.com/kataras/iris.git
synced 2026-01-05 19:27:05 +00: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:
142
view/jet.go
142
view/jet.go
@@ -3,8 +3,7 @@ package view
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
@@ -18,9 +17,10 @@ const jetEngineName = "jet"
|
||||
|
||||
// JetEngine is the jet template parser's view engine.
|
||||
type JetEngine struct {
|
||||
directory string
|
||||
fs http.FileSystem
|
||||
rootDir string
|
||||
extension string
|
||||
// physical system files or app-embedded, see `Binary(..., ...)`. Defaults to file system on initialization.
|
||||
|
||||
loader jet.Loader
|
||||
|
||||
developmentMode bool
|
||||
@@ -51,11 +51,12 @@ var jetExtensions = [...]string{
|
||||
|
||||
// Jet creates and returns a new jet view engine.
|
||||
// The given "extension" MUST begin with a dot.
|
||||
func Jet(directory, extension string) *JetEngine {
|
||||
// if _, err := os.Stat(directory); os.IsNotExist(err) {
|
||||
// panic(err)
|
||||
// }
|
||||
|
||||
//
|
||||
// Usage:
|
||||
// Jet("./views", ".jet") or
|
||||
// Jet(iris.Dir("./views"), ".jet") or
|
||||
// Jet(AssetFile(), ".jet") for embedded data.
|
||||
func Jet(fs interface{}, extension string) *JetEngine {
|
||||
extOK := false
|
||||
for _, ext := range jetExtensions {
|
||||
if ext == extension {
|
||||
@@ -69,9 +70,9 @@ func Jet(directory, extension string) *JetEngine {
|
||||
}
|
||||
|
||||
s := &JetEngine{
|
||||
directory: directory,
|
||||
rootDir: "/",
|
||||
extension: extension,
|
||||
loader: jet.NewOSFileSystemLoader(directory),
|
||||
loader: &jetLoader{fs: getFS(fs)},
|
||||
jetDataContextKey: "_jet",
|
||||
}
|
||||
|
||||
@@ -83,6 +84,13 @@ func (s *JetEngine) String() string {
|
||||
return jetEngineName
|
||||
}
|
||||
|
||||
// RootDir sets the directory to be used as a starting point
|
||||
// to load templates from the provided file system.
|
||||
func (s *JetEngine) RootDir(root string) *JetEngine {
|
||||
s.rootDir = filepath.ToSlash(root)
|
||||
return s
|
||||
}
|
||||
|
||||
// Ext should return the final file extension which this view engine is responsible to render.
|
||||
func (s *JetEngine) Ext() string {
|
||||
return s.extension
|
||||
@@ -175,121 +183,27 @@ func (s *JetEngine) Reload(developmentMode bool) *JetEngine {
|
||||
}
|
||||
|
||||
// SetLoader can be used when the caller wants to use something like
|
||||
// multi.Loader or httpfs.Loader of the jet subpackages,
|
||||
// overrides any previous loader may set by `Binary` or the default.
|
||||
// Should act before `Load` or `iris.Application#RegisterView`.
|
||||
// multi.Loader or httpfs.Loader.
|
||||
func (s *JetEngine) SetLoader(loader jet.Loader) *JetEngine {
|
||||
s.loader = loader
|
||||
return s
|
||||
}
|
||||
|
||||
// Binary optionally, use it when template files are distributed
|
||||
// inside the app executable (.go generated files).
|
||||
//
|
||||
// The assetFn and namesFn can come from the go-bindata library.
|
||||
// Should act before `Load` or `iris.Application#RegisterView`.
|
||||
func (s *JetEngine) Binary(assetFn func(name string) ([]byte, error), assetNames func() []string) *JetEngine {
|
||||
// embedded.
|
||||
vdir := s.directory
|
||||
|
||||
if vdir[0] == '.' {
|
||||
vdir = vdir[1:]
|
||||
}
|
||||
|
||||
// second check for /something, (or ./something if we had dot on 0 it will be removed)
|
||||
if vdir[0] == '/' || vdir[0] == os.PathSeparator {
|
||||
vdir = vdir[1:]
|
||||
}
|
||||
|
||||
// check for trailing slashes because new users may be do that by mistake
|
||||
// although all examples are showing the correct way but you never know
|
||||
// i.e "./assets/" is not correct, if was inside "./assets".
|
||||
// remove last "/".
|
||||
if trailingSlashIdx := len(vdir) - 1; vdir[trailingSlashIdx] == '/' {
|
||||
vdir = vdir[0:trailingSlashIdx]
|
||||
}
|
||||
|
||||
namesSlice := assetNames()
|
||||
names := make(map[string]struct{})
|
||||
for _, name := range namesSlice {
|
||||
if !strings.HasPrefix(name, vdir) {
|
||||
continue
|
||||
}
|
||||
|
||||
extOK := false
|
||||
fileExt := path.Ext(name)
|
||||
for _, ext := range jetExtensions {
|
||||
if ext == fileExt {
|
||||
extOK = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !extOK {
|
||||
continue
|
||||
}
|
||||
|
||||
names[name] = struct{}{}
|
||||
}
|
||||
|
||||
if len(names) == 0 {
|
||||
panic("JetEngine.Binary: no embedded files found in directory: " + vdir)
|
||||
}
|
||||
|
||||
s.loader = &embeddedLoader{
|
||||
vdir: vdir,
|
||||
asset: assetFn,
|
||||
names: names,
|
||||
}
|
||||
return s
|
||||
type jetLoader struct {
|
||||
fs http.FileSystem
|
||||
}
|
||||
|
||||
type (
|
||||
embeddedLoader struct {
|
||||
vdir string
|
||||
asset func(name string) ([]byte, error)
|
||||
names map[string]struct{}
|
||||
}
|
||||
embeddedFile struct {
|
||||
contents []byte // the contents are NOT consumed.
|
||||
readen int64
|
||||
}
|
||||
)
|
||||
var _ jet.Loader = (*jetLoader)(nil)
|
||||
|
||||
var (
|
||||
_ jet.Loader = (*embeddedLoader)(nil)
|
||||
_ io.ReadCloser = (*embeddedFile)(nil)
|
||||
)
|
||||
|
||||
func (f *embeddedFile) Close() error { return nil }
|
||||
func (f *embeddedFile) Read(p []byte) (int, error) {
|
||||
if f.readen >= int64(len(f.contents)) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
n := copy(p, f.contents[f.readen:])
|
||||
f.readen += int64(n)
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// Open opens a file from OS file system.
|
||||
func (l *embeddedLoader) Open(name string) (io.ReadCloser, error) {
|
||||
name = path.Join(l.vdir, filepath.ToSlash(name))
|
||||
contents, err := l.asset(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &embeddedFile{
|
||||
contents: contents,
|
||||
}, nil
|
||||
// Open opens a file from file system.
|
||||
func (l *jetLoader) Open(name string) (io.ReadCloser, error) {
|
||||
return l.fs.Open(name)
|
||||
}
|
||||
|
||||
// Exists checks if the template name exists by walking the list of template paths
|
||||
// returns string with the full path of the template and bool true if the template file was found
|
||||
func (l *embeddedLoader) Exists(name string) (string, bool) {
|
||||
name = path.Join(l.vdir, filepath.ToSlash(name))
|
||||
|
||||
if _, ok := l.names[name]; ok {
|
||||
func (l *jetLoader) Exists(name string) (string, bool) {
|
||||
if _, err := l.fs.Open(name); err == nil {
|
||||
return name, true
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user