code: func (e *Engine) LoadAssets(virtualDirectory string, virtualExtension string, assetFn func(name string) ([]byte, error), namesFn func() []string) error {
  	e.templateCache = make(map[string]*template.Template)
  	// prepare the global amber funcs
  	funcs := template.FuncMap{}
  
  	for k, v := range amber.FuncMap { // add the amber's default funcs
  		funcs[k] = v
  	}
  
  	if e.Config.Funcs != nil { // add the config's funcs
  		for k, v := range e.Config.Funcs {
  			funcs[k] = v
  		}
  	}
  	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
  
  	e.mu.Lock()
  	defer e.mu.Unlock()
  
  	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
  			}
  
  			name := filepath.ToSlash(rel)
  			tmpl, err := amber.CompileData(buf, name, amber.DefaultOptions)
  
  			if err != nil {
  				return err
  			}
  
  			e.templateCache[name] = tmpl
  		}
  	}
  
  	return nil
  }
docs: // LoadAssets builds the templates from binary assets