// LoadDir works like Load, but loads the articles from the given directory // in the local filesystem. func (a *App) LoadDir(dir string) ([]*article.Article, error) { fs, err := vfs.FS(dir) if err != nil { return nil, err } return a.Load(fs, "/") }
// ParseFromDir is a conveniency function which creates a vfs.VFS rooted at dir // and creates a new template from the file with the given name. It's equivalent // to Parse(vfs.FS(dir), manager, name) (minus error handling). func ParseFromDir(manager *assets.Manager, dir string, name string) (*Template, error) { fs, err := vfs.FS(dir) if err != nil { return nil, err } return Parse(fs, manager, name) }
// HandleAssets adds several handlers to the app which handle // assets efficiently and allows the use of the "assset" // function from the templates. This function will also modify the // asset loader associated with this app. prefix might be a relative // (e.g. /static/) or absolute (e.g. http://static.example.com/) url // while dir should be the path to the directory where the static // assets reside. You probably want to use pathutil.Relative() // to define the directory relative to the application binary. Note // that /favicon.ico and /robots.txt will be handled too, but they // will must be in the directory which contains the rest of the assets. func (app *App) HandleAssets(prefix string, dir string) { fs, err := vfs.FS(dir) if err != nil { panic(err) } manager := assets.New(fs, prefix) app.SetAssetsManager(manager) app.addAssetsManager(manager, true) }
// DefaultVFS returns a VFS which loads templates from // the tmpl directory, relative to the application binary. func DefaultVFS() vfs.VFS { fs, err := vfs.FS(pathutil.Relative("tmpl")) if err != nil { // Very unlikely, since FS only fails when // os.Getwd() fails. panic(err) } return fs }
func MemFromDir(dir string) VFS { fs, err := vfs.FS(dir) if err != nil { panic(err) } mem := vfs.Memory() if err := vfs.Clone(mem, fs); err != nil { panic(err) } return mem }
// NewDiskCache returns a disk-backed cache func NewDiskCache(dir string) (Cache, error) { if err := os.MkdirAll(dir, 0777); err != nil { return nil, err } fs, err := vfs.FS(dir) if err != nil { return nil, err } chfs, err := vfs.Chroot("/", fs) if err != nil { return nil, err } return NewVFSCache(chfs), nil }
func parseTestTemplate(tb testing.TB, name string) *Template { fs, err := vfs.FS("_testdata") if err != nil { tb.Fatal(err) } tmpl := New(fs, assets.New(fs, "")) tmpl.RawFuncs(map[string]interface{}{"t": func(s string) string { return s }}) if err := tmpl.Parse(name); err != nil { tb.Errorf("error parsing %q: %s", name, err) return nil } if err := tmpl.Compile(); err != nil { tb.Errorf("error compiling %q: %s", name, err) return nil } return tmpl }
// Bake writes the data for a VFS generated from dir to the given // io.Writer. The extensions argument can be used to limit the // files included in the VFS by their extension. If empty, all // files are included. func Bake(w io.Writer, dir string, extensions []string) error { fs, err := vfs.FS(dir) if err != nil { return err } if len(extensions) > 0 { // Clone the fs and remove files not matching the extension exts := make(map[string]bool) for _, v := range extensions { if v == "" { continue } if v[0] != '.' { v = "." + v } exts[strings.ToLower(v)] = true } mem := vfs.Memory() if err := vfs.Clone(mem, fs); err != nil { return err } err := vfs.Walk(mem, "/", func(fs vfs.VFS, p string, info os.FileInfo, err error) error { if err != nil || info.IsDir() { return err } if !exts[strings.ToLower(path.Ext(p))] { if err := fs.Remove(p); err != nil { return err } } return nil }) if err != nil { return err } fs = mem } vfs.Walk(fs, "/", func(_ vfs.VFS, p string, info os.FileInfo, err error) error { if !info.IsDir() { log.Debugf("baking %s", p) } return nil }) return vfs.WriteTarGzip(w, fs) }
func openVFS(appName string, abspath string, baked string) (vfsutil.VFS, error) { if appName == "" { return nil, errors.New("empty app name") } if len(baked) > 0 { noVFS := false fields, _ := stringutil.SplitFields(os.Getenv("GONDOLA_APP_NO_BAKED_DATA"), " ") lowerAppName := strings.ToLower(appName) for _, field := range fields { if strings.ToLower(field) == lowerAppName { noVFS = true } } if !noVFS { return vfsutil.OpenBaked(baked) } } return vfs.FS(abspath) }