Use static assets for HTML templates
- implement custom http.Filesystem boardvoting.AssetFS - replace "footer" and "header" with "footer.html" and "header.html" - change renderTemplate to use Assets - use boardvoting.GetAssetFS() with http.Fileserverdebian
parent
4dd5e09820
commit
94dcb5bd75
@ -1,3 +1,143 @@
|
||||
package boardvoting
|
||||
|
||||
//go:generate go-bindata -pkg $GOPACKAGE -o assets.go ./migrations/... ./static/... ./templates/...
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var defaultFileTimestamp = time.Now()
|
||||
|
||||
type AssetFS struct {
|
||||
Asset func(path string) ([]byte, error)
|
||||
AssetDir func(path string) ([]string, error)
|
||||
AssetInfo func(path string) (os.FileInfo, error)
|
||||
}
|
||||
|
||||
type FakeFile struct {
|
||||
Path string
|
||||
Dir bool
|
||||
Len int64
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
func (f *FakeFile) Name() string {
|
||||
_, name := filepath.Split(f.Path)
|
||||
return name
|
||||
}
|
||||
|
||||
func (f *FakeFile) Size() int64 { return f.Len }
|
||||
|
||||
func (f *FakeFile) Mode() os.FileMode {
|
||||
mode := os.FileMode(0644)
|
||||
if f.Dir {
|
||||
return mode | os.ModeDir
|
||||
}
|
||||
return mode
|
||||
}
|
||||
|
||||
func (f *FakeFile) ModTime() time.Time { return f.Timestamp }
|
||||
func (f *FakeFile) IsDir() bool { return f.Dir }
|
||||
func (f *FakeFile) Sys() interface{} { return nil }
|
||||
|
||||
type AssetFile struct {
|
||||
*bytes.Reader
|
||||
io.Closer
|
||||
FakeFile
|
||||
}
|
||||
|
||||
func NewAssetFile(name string, content []byte, timestamp time.Time) *AssetFile {
|
||||
if timestamp.IsZero() {
|
||||
timestamp = defaultFileTimestamp
|
||||
}
|
||||
return &AssetFile{
|
||||
bytes.NewReader(content),
|
||||
ioutil.NopCloser(nil),
|
||||
FakeFile{name, false, int64(len(content)), timestamp},
|
||||
}
|
||||
}
|
||||
|
||||
func (f *AssetFile) Readdir(count int) ([]os.FileInfo, error) {
|
||||
return nil, errors.New("not a directory")
|
||||
}
|
||||
|
||||
func (f *AssetFile) Size() int64 {
|
||||
return f.FakeFile.Size()
|
||||
}
|
||||
|
||||
func (f *AssetFile) Stat() (os.FileInfo, error) {
|
||||
return f, nil
|
||||
}
|
||||
|
||||
type AssetDirectory struct {
|
||||
AssetFile
|
||||
ChildrenRead int
|
||||
Children []os.FileInfo
|
||||
}
|
||||
|
||||
func (f *AssetDirectory) Readdir(count int) ([]os.FileInfo, error) {
|
||||
if count <= 0 {
|
||||
return f.Children, nil
|
||||
}
|
||||
if f.ChildrenRead+count > len(f.Children) {
|
||||
count = len(f.Children) - f.ChildrenRead
|
||||
}
|
||||
rv := f.Children[f.ChildrenRead : f.ChildrenRead+count]
|
||||
f.ChildrenRead += count
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
func (f *AssetDirectory) Stat() (os.FileInfo, error) {
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func NewAssetDirectory(name string, children []string, fs *AssetFS) *AssetDirectory {
|
||||
fileInfos := make([]os.FileInfo, 0, len(children))
|
||||
for _, child := range children {
|
||||
_, err := fs.AssetDir(filepath.Join(name, child))
|
||||
fileInfos = append(fileInfos, &FakeFile{child, err == nil, 0, time.Time{}})
|
||||
}
|
||||
return &AssetDirectory{
|
||||
AssetFile{
|
||||
bytes.NewReader(nil),
|
||||
ioutil.NopCloser(nil),
|
||||
FakeFile{name, true, 0, time.Time{}},
|
||||
},
|
||||
0,
|
||||
fileInfos}
|
||||
}
|
||||
|
||||
func (f *AssetFS) Open(name string) (http.File, error) {
|
||||
if len(name) > 0 && name[0] == '/' {
|
||||
name = name[1:]
|
||||
}
|
||||
if b, err := f.Asset(name); err == nil {
|
||||
timestamp := defaultFileTimestamp
|
||||
if f.AssetInfo != nil {
|
||||
if info, err := f.AssetInfo(name); err == nil {
|
||||
timestamp = info.ModTime()
|
||||
}
|
||||
}
|
||||
return NewAssetFile(name, b, timestamp), nil
|
||||
}
|
||||
if children, err := f.AssetDir(name); err == nil {
|
||||
return NewAssetDirectory(name, children, f), nil
|
||||
} else {
|
||||
if strings.Contains(err.Error(), "not found") {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func GetAssetFS() *AssetFS {
|
||||
return &AssetFS{Asset: Asset, AssetDir: AssetDir, AssetInfo: AssetInfo}
|
||||
}
|
||||
|
Loading…
Reference in New Issue