-
Notifications
You must be signed in to change notification settings - Fork 8.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
If method loading html files from embed.FS type could be helpful?? #2795
Comments
The workaround from @j1mmyson above doesn't handle templates in recursive directories. Combining this solution from stack exchange with the above lets you attach templates from recursive embedded directories: package main
import (
"embed"
"github.com/gin-gonic/gin"
"html/template"
"io/fs"
"net/http"
"strings"
)
// template files in directory:
// templates/index.html
// templates/test/nested.html
//go:embed templates/**
var f embed.FS
func main() {
r := gin.Default()
root := template.New("")
LoadAndAddToRoot(r.FuncMap, root)
r.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "templates/index.html", gin.H{})
})
r.GET("/embed", func(c *gin.Context) {
c.HTML(http.StatusOK, "templates/test/nested.html", gin.H{})
})
r.Run("127.0.0.1:8080")
}
func LoadAndAddToRoot(funcMap template.FuncMap, rootTemplate *template.Template) error {
// This solution is CC by share alike 4.0
// Copyright Rik-777
// https://stackoverflow.com/a/50581032
err := fs.WalkDir(f, ".", func(path string, d fs.DirEntry, walkErr error) error {
if walkErr != nil {
return walkErr
}
if !d.IsDir() && strings.HasSuffix(path, ".html") {
data, readErr := f.ReadFile(path)
if readErr != nil {
return readErr
}
t := rootTemplate.New(path).Funcs(funcMap)
if _, parseErr := t.Parse(string(data)); parseErr != nil {
return parseErr
}
}
return nil
})
return err
} |
@sesopenko Thank you for comments! func LoadHTMLFromEmbedFS(engine *gin.Engine, embedFS embed.FS, pattern string) {
root := template.New("")
tmpl := template.Must(root, LoadAndAddToRoot(engine.FuncMap, root, embedFS, pattern))
engine.SetHTMLTemplate(tmpl)
}
// Method version
// func (engine *gin.Engine) LoadHTMLFromFS(embedFS embed.FS, pattern string) {
// root := template.New("")
// tmpl := template.Must(root, LoadAndAddToRoot(engine.FuncMap, root, embedFS, pattern))
// engine.SetHTMLTemplate(tmpl)
// }
func LoadAndAddToRoot(funcMap template.FuncMap, rootTemplate *template.Template, embedFS embed.FS, pattern string) error {
pattern = strings.ReplaceAll(pattern, ".", "\\.")
pattern = strings.ReplaceAll(pattern, "*", ".*")
err := fs.WalkDir(embedFS, ".", func(path string, d fs.DirEntry, walkErr error) error {
if walkErr != nil {
return walkErr
}
if matched, _ := regexp.MatchString(pattern, path); !d.IsDir() && matched {
data, readErr := embedFS.ReadFile(path)
if readErr != nil {
return readErr
}
t := rootTemplate.New(path).Funcs(funcMap)
if _, parseErr := t.Parse(string(data)); parseErr != nil {
return parseErr
}
}
return nil
})
return err
} and use it like package main
import (
"embed"
"html/template"
"io/fs"
"net/http"
"regexp"
"strings"
"github.com/gin-gonic/gin"
)
//go:embed web/templates
var templatesFS embed.FS
func main() {
r := gin.Default()
LoadHTMLFromEmbedFS(r, templatesFS, "web/templates/*html")
// if method
// r.LoadHTMLFromEmbedFS(templatesFS, "web/templates/*html")
...
r.Run()
} following is an example: https://github.com/j1mmyson/LoadHTMLFromEmbedFS-example from now on, is there any improvement point or problems? |
the template has method
can add a method like this:
|
First of all, thank you for creating a very useful framework !!
Recently, I found out that the gin framework cannot load template with embed.FS type and I have solved it in the following way.
Is it convenient to use this function in the form of a method?
and users use it like
I don't know whether my code is safe or not, so leave it as an issue for now. Thank you!
The text was updated successfully, but these errors were encountered: