// New returns a new App. Any errors will result in a panic, Since // this function should be called only during app initialization. func New(opts Options) *App { if opts.Name == "" { panic(errors.New("reusable app name can't be empty")) } a := &App{ App: *app.New(), opts: &opts, name: opts.Name, } var k interface{} = reusableAppKey if opts.DataKey != nil { k = opts.DataKey } a.Set(k, a) _, file, _, ok := runtime.Caller(1) if ok { a.dir = filepath.Dir(file) } assetsFS, assetsRel := a.mustOpenVFS("assets", opts.AssetsDir, opts.AssetsData) if assetsFS != nil { assetsPrefix := path.Clean("/" + filepath.ToSlash(assetsRel) + "/") manager := assets.New(assetsFS, assetsPrefix) a.SetAssetsManager(manager) a.Handle("^"+assetsPrefix, app.HandlerFromHTTPFunc(manager.Handler())) } templatesFS, _ := a.mustOpenVFS("tmpl", opts.TemplatesDir, opts.TemplatesData) if templatesFS != nil { a.SetTemplatesFS(templatesFS) } return a }
// 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) }
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 }
"errors" "io" "gnd.la/app/profile" "gnd.la/internal/devutil/devassets" "gnd.la/internal/templateutil" "gnd.la/template" "gnd.la/template/assets" "github.com/rainycape/vfs" "gnd.la/internal/devutil/devserver" ) var ( reservedVariables = []string{"Ctx", "App", "Apps"} internalAssetsManager = assets.New(devassets.AssetsFS, assetsPrefix) profilePlugin *template.Plugin errNoLoadedTemplate = errors.New("this template was not loaded from App.LoadTemplate nor NewTemplate") templateFuncs = []*template.Func{ {Name: "t", Fn: template_t, Traits: template.FuncTraitContext}, {Name: "tn", Fn: template_tn, Traits: template.FuncTraitContext}, {Name: "tc", Fn: template_tc, Traits: template.FuncTraitContext}, {Name: "tnc", Fn: template_tnc, Traits: template.FuncTraitContext}, {Name: "app", Fn: nop}, {Name: templateutil.BeginTranslatableBlock, Fn: nop}, {Name: templateutil.EndTranslatableBlock, Fn: nop}, } ) type TemplateProcessor func(*template.Template) (*template.Template, error)