This package provides universal methods to use multiple template engines with the [Fiber web framework](https://github.com/gofiber/fiber) using the new [Views](https://godoc.org/github.com/gofiber/fiber#Views) interface that is available from `> v1.11.1`. Special thanks to @bdtomlin & @arsmn for helping!
9 template engines are supported:
-- [html](https://github.com/gofiber/template/tree/master/html)
-
-
-- [ace](https://github.com/gofiber/template/tree/master/ace)
-
-- [amber](https://github.com/gofiber/template/tree/master/amber)
-
-- [django](https://github.com/gofiber/template/tree/master/django)
-
-- [handlebars](https://github.com/gofiber/template/tree/master/handlebars)
-
-- [jet](https://github.com/gofiber/template/tree/master/jet)
-
-- [mustache](https://github.com/gofiber/template/tree/master/mustache)
-
-- [pug](https://github.com/gofiber/template/tree/master/pug)
-
-- [slim](https://github.com/gofiber/template/tree/master/slim)
-
+- [ace](./ace/README.md)
+- [amber](./amber/README.md)
+- [django](./django/README.md)
+- [handlebars](./handlebars/README.md)
+- [html](./html/README.md)
+- [jet](./jet/README.md)
+- [mustache](./mustache/README.md)
+- [pug](./pug/README.md)
+- [slim](./slim/README.md)
### Installation
> Go version `1.17` or higher is required.
@@ -121,15 +114,15 @@ func main() {
### More Examples
To view more specific examples, you could visit each engine folder to learn more
-- [html](https://github.com/gofiber/template/tree/master/html)
-- [ace](https://github.com/gofiber/template/tree/master/ace)
-- [amber](https://github.com/gofiber/template/tree/master/amber)
-- [django](https://github.com/gofiber/template/tree/master/django)
-- [handlebars](https://github.com/gofiber/template/tree/master/handlebars)
-- [jet](https://github.com/gofiber/template/tree/master/jet)
-- [mustache](https://github.com/gofiber/template/tree/master/mustache)
-- [pug](https://github.com/gofiber/template/tree/master/pug)
-- [slim](https://github.com/gofiber/template/tree/master/slim)
+- [ace](./ace/README.md)
+- [amber](./amber/README.md)
+- [django](./django/README.md)
+- [handlebars](./handlebars/README.md)
+- [html](./html/README.md)
+- [jet](./jet/README.md)
+- [mustache](./mustache/README.md)
+- [pug](./pug/README.md)
+- [slim](./slim/README.md)
### embedded Systems
@@ -242,9 +235,9 @@ func main() {
### Benchmarks
#### Simple
-
+
#### Extended
-
+
Benchmarks were ran on Apple Macbook M1. Each engine was benchmarked 20 times and the results averaged into a single xlsx file. Mustache was excluded from the extended benchmark
diff --git a/src/vendor/github.com/gofiber/template/html/v2/README.md b/src/vendor/github.com/gofiber/template/html/v2/README.md
index 88f159b2..4dfef2c4 100644
--- a/src/vendor/github.com/gofiber/template/html/v2/README.md
+++ b/src/vendor/github.com/gofiber/template/html/v2/README.md
@@ -72,7 +72,7 @@ func main() {
// Or from an embedded system
// See github.com/gofiber/embed for examples
- // engine := html.NewFileSystem(http.Dir("./views", ".html"))
+ // engine := html.NewFileSystem(http.Dir("./views"), ".html")
// Pass the engine to the Views
app := fiber.New(fiber.Config{
diff --git a/src/vendor/github.com/gofiber/template/html/v2/TEMPLATES_CHEATSHEET.md b/src/vendor/github.com/gofiber/template/html/v2/TEMPLATES_CHEATSHEET.md
index f5ec54c7..e83f761c 100644
--- a/src/vendor/github.com/gofiber/template/html/v2/TEMPLATES_CHEATSHEET.md
+++ b/src/vendor/github.com/gofiber/template/html/v2/TEMPLATES_CHEATSHEET.md
@@ -85,7 +85,7 @@ Go templates can also be used with javascript. Structs and maps will be expanded
```js
// Javascript
- var cat = {"Name":"Sam", "Age" 12}
+ var cat = {"Name":"Sam", "Age":12}
```
---
@@ -296,12 +296,12 @@ The not function returns the boolean negation of the argument.
The `html/template` package provides a variety of functions to do comparisons between operators. The operators may only be basic types or named basic types such as `type Temp float32` Remember that template functions take the form `{{ function arg1 arg2 }}`.
-- `eq` Returns the result of arg1 == arg2
-- `ne` Returns the result of arg1 != arg2
-- `lt` Returns the result of arg1 < arg2
-- `le` Returns the result of arg1 <= arg2
-- `gt` Returns the result of arg1 > arg2
-- `ge` Returns the result of arg1 >= arg2
+- `eq` Returns the result of `arg1 == arg2`
+- `ne` Returns the result of `arg1 != arg2`
+- `lt` Returns the result of `arg1 < arg2`
+- `le` Returns the result of `arg1 <= arg2`
+- `gt` Returns the result of `arg1 > arg2`
+- `ge` Returns the result of `arg1 >= arg2`
Of special note `eq` can be used with two or more arguments by comparing all arguments to the first. `{{ eq arg1 arg2 arg3 arg4}}` will result in the following logical expression:
@@ -358,7 +358,7 @@ We use the same range to loop through Items as before but we pass the name to th
Glob patterns specify sets of filenames with wildcard characters. The `template.ParseGlob(pattern string)` function will parse all templates that match the string pattern. `template.ParseFiles(files...)` can also be used with a list of file names.
-The templates are named by default based on the base names of the argument files. This mean `views/layouts/hello.gohtml` will have the name `hello.gohtml` . If the template has a ``{{define ātemplateNameā}}` within it then that name will be usable.
+The templates are named by default based on the base names of the argument files. This mean `views/layouts/hello.gohtml` will have the name `hello.gohtml` . If the template has a `{{define ātemplateNameā}}` within it then that name will be usable.
A specific template can be executed using `t.ExecuteTemplate(w, "templateName", nil)` . `t` is an object of type Template, `w` is type io.Writer such as an `http.ResponseWriter`, Then there is the name of the template to execute, and finally passing any data to the template, in this case a nil value.
diff --git a/src/vendor/github.com/gofiber/template/html/v2/html.go b/src/vendor/github.com/gofiber/template/html/v2/html.go
index 66ba14a4..4c1c4c27 100644
--- a/src/vendor/github.com/gofiber/template/html/v2/html.go
+++ b/src/vendor/github.com/gofiber/template/html/v2/html.go
@@ -21,37 +21,31 @@ type Engine struct {
Templates *template.Template
}
-// New returns an HTML render engine for Fiber
+// New returns a HTML render engine for Fiber
func New(directory, extension string) *Engine {
- engine := &Engine{
- Engine: core.Engine{
- Left: "{{",
- Right: "}}",
- Directory: directory,
- Extension: extension,
- LayoutName: "embed",
- Funcmap: make(map[string]interface{}),
- },
- }
- engine.AddFunc(engine.LayoutName, func() error {
- return fmt.Errorf("layoutName called unexpectedly")
- })
- return engine
+ return newEngine(directory, extension, nil)
}
-// NewFileSystem returns an HTML render engine for Fiber with file system
+// NewFileSystem returns a HTML render engine for Fiber with file system
func NewFileSystem(fs http.FileSystem, extension string) *Engine {
+ return newEngine("/", extension, fs)
+}
+
+// newEngine creates a new Engine instance with common initialization logic.
+func newEngine(directory, extension string, fs http.FileSystem) *Engine {
engine := &Engine{
Engine: core.Engine{
Left: "{{",
Right: "}}",
- Directory: "/",
+ Directory: directory,
FileSystem: fs,
Extension: extension,
LayoutName: "embed",
Funcmap: make(map[string]interface{}),
},
}
+ // Add a default function that throws an error if called unexpectedly.
+ // This can be useful for debugging or ensuring certain functions are used correctly.
engine.AddFunc(engine.LayoutName, func() error {
return fmt.Errorf("layoutName called unexpectedly")
})
@@ -63,6 +57,7 @@ func (e *Engine) Load() error {
if e.Loaded {
return nil
}
+
// race safe
e.Mutex.Lock()
defer e.Mutex.Unlock()
@@ -77,20 +72,24 @@ func (e *Engine) Load() error {
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)
@@ -103,20 +102,24 @@ func (e *Engine) Load() error {
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.Verbose {
log.Printf("views: parsed template: %s\n", name)
}
return err
}
- // notify engine that we parsed all templates
+
+ // notify Engine that we parsed all templates
e.Loaded = true
+
if e.FileSystem != nil {
return utils.Walk(e.FileSystem, e.Directory, walkFn)
}
@@ -125,23 +128,28 @@ func (e *Engine) Load() error {
// Render will execute the template name along with the given values.
func (e *Engine) Render(out io.Writer, name string, binding interface{}, layout ...string) error {
- if !e.Loaded || e.ShouldReload {
- if e.ShouldReload {
- e.Loaded = false
- }
+ // Check if templates need to be loaded/reloaded
+ if e.PreRenderCheck() {
if err := e.Load(); err != nil {
return err
}
}
+
+ // Acquire read lock for accessing the template
+ e.Mutex.RLock()
tmpl := e.Templates.Lookup(name)
+ e.Mutex.RUnlock()
+
if tmpl == nil {
return fmt.Errorf("render: template %s does not exist", name)
}
+
render := renderFuncCreate(e, out, binding, *tmpl, nil)
if len(layout) > 0 && layout[0] != "" {
e.Mutex.Lock()
defer e.Mutex.Unlock()
}
+
// construct a nested render function to embed templates in layouts
for _, layName := range layout {
if layName == "" {
diff --git a/src/vendor/github.com/gofiber/template/template.go b/src/vendor/github.com/gofiber/template/template.go
index b9865aab..ab443f67 100644
--- a/src/vendor/github.com/gofiber/template/template.go
+++ b/src/vendor/github.com/gofiber/template/template.go
@@ -22,6 +22,7 @@ type IEngineCore interface {
FuncMap() map[string]interface{}
Layout(key string) IEngineCore
Reload(enabled bool) IEngineCore
+ PreRenderCheck() bool
}
// Engine engine struct
@@ -52,7 +53,7 @@ type Engine struct {
// 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 {
+func (e *Engine) AddFunc(name string, fn interface{}) IEngineCore {
e.Mutex.Lock()
e.Funcmap[name] = fn
e.Mutex.Unlock()
@@ -61,7 +62,7 @@ func (e *Engine) AddFunc(name string, fn interface{}) *Engine {
// AddFuncMap adds the functions from a map to the template's function map.
// It is legal to overwrite elements of the default actions
-func (e *Engine) AddFuncMap(m map[string]interface{}) *Engine {
+func (e *Engine) AddFuncMap(m map[string]interface{}) IEngineCore {
e.Mutex.Lock()
for name, fn := range m {
e.Funcmap[name] = fn
@@ -71,16 +72,20 @@ func (e *Engine) AddFuncMap(m map[string]interface{}) *Engine {
}
// Debug will print the parsed templates when Load is triggered.
-func (e *Engine) Debug(enabled bool) *Engine {
+func (e *Engine) Debug(enabled bool) IEngineCore {
+ e.Mutex.Lock()
e.Verbose = enabled
+ e.Mutex.Unlock()
return e
}
// Delims sets the action delimiters to the specified strings, to be used in
// templates. An empty delimiter stands for the
// corresponding default: "{{" and "}}".
-func (e *Engine) Delims(left, right string) *Engine {
+func (e *Engine) Delims(left, right string) IEngineCore {
+ e.Mutex.Lock()
e.Left, e.Right = left, right
+ e.Mutex.Unlock()
return e
}
@@ -90,15 +95,35 @@ func (e *Engine) FuncMap() map[string]interface{} {
}
// Layout defines the variable name that will incapsulate the template
-func (e *Engine) Layout(key string) *Engine {
+func (e *Engine) Layout(key string) IEngineCore {
+ e.Mutex.Lock()
e.LayoutName = key
+ 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 {
+func (e *Engine) Reload(enabled bool) IEngineCore {
+ e.Mutex.Lock()
e.ShouldReload = enabled
+ e.Mutex.Unlock()
return e
}
+
+// Check if the engine should reload the templates before rendering
+// Explicit Mute Unlock vs defer offers better performance
+func (e *Engine) PreRenderCheck() bool {
+ e.Mutex.Lock()
+
+ if !e.Loaded || e.ShouldReload {
+ if e.ShouldReload {
+ e.Loaded = false
+ }
+ e.Mutex.Unlock()
+ return true
+ }
+ e.Mutex.Unlock()
+ return false
+}
diff --git a/src/vendor/github.com/valyala/fasthttp/coarseTime.go b/src/vendor/github.com/valyala/fasthttp/coarsetime.go
similarity index 100%
rename from src/vendor/github.com/valyala/fasthttp/coarseTime.go
rename to src/vendor/github.com/valyala/fasthttp/coarsetime.go
diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt
index 78a74712..c59d2321 100644
--- a/src/vendor/modules.txt
+++ b/src/vendor/modules.txt
@@ -27,10 +27,10 @@ github.com/gofiber/fiber/v2/middleware/logger
github.com/gofiber/fiber/v2/middleware/recover
github.com/gofiber/fiber/v2/middleware/requestid
github.com/gofiber/fiber/v2/utils
-# github.com/gofiber/template v1.8.2
+# github.com/gofiber/template v1.8.3
## explicit; go 1.20
github.com/gofiber/template
-# github.com/gofiber/template/html/v2 v2.1.0
+# github.com/gofiber/template/html/v2 v2.1.3
## explicit; go 1.20
github.com/gofiber/template/html/v2
# github.com/gofiber/utils v1.1.0