Adding upstream version 2.52.6.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
a960158181
commit
6d002e9543
441 changed files with 95392 additions and 0 deletions
206
internal/template/html/html.go
Normal file
206
internal/template/html/html.go
Normal file
|
@ -0,0 +1,206 @@
|
|||
package html
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/gofiber/fiber/v2/internal/template/utils"
|
||||
"github.com/gofiber/fiber/v2/log"
|
||||
)
|
||||
|
||||
// Engine struct
|
||||
type Engine struct {
|
||||
// delimiters
|
||||
left string
|
||||
right string
|
||||
// views folder
|
||||
directory string
|
||||
// http.FileSystem supports embedded files
|
||||
fileSystem http.FileSystem
|
||||
// views extension
|
||||
extension string
|
||||
// layout variable name that incapsulates the template
|
||||
layout string
|
||||
// determines if the engine parsed all templates
|
||||
loaded bool
|
||||
// reload on each render
|
||||
reload bool
|
||||
// debug prints the parsed templates
|
||||
debug bool
|
||||
// lock for funcmap and templates
|
||||
mutex sync.RWMutex
|
||||
// template funcmap
|
||||
funcmap map[string]interface{}
|
||||
// templates
|
||||
Templates *template.Template
|
||||
}
|
||||
|
||||
// New returns a HTML render engine for Fiber
|
||||
func New(directory, extension string) *Engine {
|
||||
engine := &Engine{
|
||||
left: "{{",
|
||||
right: "}}",
|
||||
directory: directory,
|
||||
extension: extension,
|
||||
layout: "embed",
|
||||
funcmap: make(map[string]interface{}),
|
||||
}
|
||||
engine.AddFunc(engine.layout, func() error {
|
||||
return fmt.Errorf("layout called unexpectedly.")
|
||||
})
|
||||
return engine
|
||||
}
|
||||
|
||||
// NewFileSystem ...
|
||||
func NewFileSystem(fs http.FileSystem, extension string) *Engine {
|
||||
engine := &Engine{
|
||||
left: "{{",
|
||||
right: "}}",
|
||||
directory: "/",
|
||||
fileSystem: fs,
|
||||
extension: extension,
|
||||
layout: "embed",
|
||||
funcmap: make(map[string]interface{}),
|
||||
}
|
||||
engine.AddFunc(engine.layout, func() error {
|
||||
return fmt.Errorf("layout called unexpectedly.")
|
||||
})
|
||||
return engine
|
||||
}
|
||||
|
||||
// Layout defines the variable name that will incapsulate the template
|
||||
func (e *Engine) Layout(key string) *Engine {
|
||||
e.layout = key
|
||||
return e
|
||||
}
|
||||
|
||||
// Delims sets the action delimiters to the specified strings, to be used in
|
||||
// templates. An empty delimiter stands for the
|
||||
// corresponding default: {{ or }}.
|
||||
func (e *Engine) Delims(left, right string) *Engine {
|
||||
e.left, e.right = left, right
|
||||
return e
|
||||
}
|
||||
|
||||
// AddFunc adds the function to the template's function map.
|
||||
// It is legal to overwrite elements of the default actions
|
||||
func (e *Engine) AddFunc(name string, fn interface{}) *Engine {
|
||||
e.mutex.Lock()
|
||||
e.funcmap[name] = fn
|
||||
e.mutex.Unlock()
|
||||
return e
|
||||
}
|
||||
|
||||
// Reload if set to true the templates are reloading on each render,
|
||||
// use it when you're in development and you don't want to restart
|
||||
// the application when you edit a template file.
|
||||
func (e *Engine) Reload(enabled bool) *Engine {
|
||||
e.reload = enabled
|
||||
return e
|
||||
}
|
||||
|
||||
// Debug will print the parsed templates when Load is triggered.
|
||||
func (e *Engine) Debug(enabled bool) *Engine {
|
||||
e.debug = enabled
|
||||
return e
|
||||
}
|
||||
|
||||
// Parse is deprecated, please use Load() instead
|
||||
func (e *Engine) Parse() error {
|
||||
log.Warn("Parse() is deprecated, please use Load() instead.")
|
||||
return e.Load()
|
||||
}
|
||||
|
||||
// Load parses the templates to the engine.
|
||||
func (e *Engine) Load() error {
|
||||
if e.loaded {
|
||||
return nil
|
||||
}
|
||||
// race safe
|
||||
e.mutex.Lock()
|
||||
defer e.mutex.Unlock()
|
||||
e.Templates = template.New(e.directory)
|
||||
|
||||
// Set template settings
|
||||
e.Templates.Delims(e.left, e.right)
|
||||
e.Templates.Funcs(e.funcmap)
|
||||
|
||||
walkFn := func(path string, info os.FileInfo, err error) error {
|
||||
// Return error if exist
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Skip file if it's a directory or has no file info
|
||||
if info == nil || info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
// Skip file if it does not equal the given template extension
|
||||
if len(e.extension) >= len(path) || path[len(path)-len(e.extension):] != e.extension {
|
||||
return nil
|
||||
}
|
||||
// Get the relative file path
|
||||
// ./views/html/index.tmpl -> index.tmpl
|
||||
rel, err := filepath.Rel(e.directory, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Reverse slashes '\' -> '/' and
|
||||
// partials\footer.tmpl -> partials/footer.tmpl
|
||||
name := filepath.ToSlash(rel)
|
||||
// Remove ext from name 'index.tmpl' -> 'index'
|
||||
name = strings.TrimSuffix(name, e.extension)
|
||||
// name = strings.Replace(name, e.extension, "", -1)
|
||||
// Read the file
|
||||
// #gosec G304
|
||||
buf, err := utils.ReadFile(path, e.fileSystem)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Create new template associated with the current one
|
||||
// This enable use to invoke other templates {{ template .. }}
|
||||
_, err = e.Templates.New(name).Parse(string(buf))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Debugging
|
||||
if e.debug {
|
||||
log.Infof("views: parsed template: %s", name)
|
||||
}
|
||||
return err
|
||||
}
|
||||
// notify engine that we parsed all templates
|
||||
e.loaded = true
|
||||
if e.fileSystem != nil {
|
||||
return utils.Walk(e.fileSystem, e.directory, walkFn)
|
||||
}
|
||||
return filepath.Walk(e.directory, walkFn)
|
||||
}
|
||||
|
||||
// Render will execute the template name along with the given values.
|
||||
func (e *Engine) Render(out io.Writer, template string, binding interface{}, layout ...string) error {
|
||||
tmpl := e.Templates.Lookup(template)
|
||||
if tmpl == nil {
|
||||
return fmt.Errorf("render: template %s does not exist", template)
|
||||
}
|
||||
if len(layout) > 0 && layout[0] != "" {
|
||||
lay := e.Templates.Lookup(layout[0])
|
||||
if lay == nil {
|
||||
return fmt.Errorf("render: layout %s does not exist", layout[0])
|
||||
}
|
||||
e.mutex.Lock()
|
||||
defer e.mutex.Unlock()
|
||||
lay.Funcs(map[string]interface{}{
|
||||
e.layout: func() error {
|
||||
return tmpl.Execute(out, binding)
|
||||
},
|
||||
})
|
||||
return lay.Execute(out, binding)
|
||||
}
|
||||
return tmpl.Execute(out, binding)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue