forked from forgejo/forgejo
Use a general approach to access custom/static/builtin assets (#24022)
The idea is to use a Layered Asset File-system (modules/assetfs/layered.go) For example: when there are 2 layers: "custom", "builtin", when access to asset "my/page.tmpl", the Layered Asset File-system will first try to use "custom" assets, if not found, then use "builtin" assets. This approach will hugely simplify a lot of code, make them testable. Other changes: * Simplify the AssetsHandlerFunc code * Simplify the `gitea embedded` sub-command code --------- Co-authored-by: Jason Song <i@wolfogre.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
parent
42919ccb7c
commit
50a72e7a83
36 changed files with 689 additions and 1055 deletions
|
@ -21,7 +21,6 @@ import (
|
|||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/watcher"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -66,20 +65,23 @@ func (h *HTMLRender) TemplateLookup(name string) (*template.Template, error) {
|
|||
}
|
||||
|
||||
func (h *HTMLRender) CompileTemplates() error {
|
||||
dirPrefix := "templates/"
|
||||
extSuffix := ".tmpl"
|
||||
tmpls := template.New("")
|
||||
for _, path := range GetTemplateAssetNames() {
|
||||
if !strings.HasSuffix(path, extSuffix) {
|
||||
assets := AssetFS()
|
||||
files, err := ListWebTemplateAssetNames(assets)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, file := range files {
|
||||
if !strings.HasSuffix(file, extSuffix) {
|
||||
continue
|
||||
}
|
||||
name := strings.TrimPrefix(path, dirPrefix)
|
||||
name = strings.TrimSuffix(name, extSuffix)
|
||||
name := strings.TrimSuffix(file, extSuffix)
|
||||
tmpl := tmpls.New(filepath.ToSlash(name))
|
||||
for _, fm := range NewFuncMap() {
|
||||
tmpl.Funcs(fm)
|
||||
}
|
||||
buf, err := GetAsset(path)
|
||||
buf, err := assets.ReadFile(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -112,13 +114,10 @@ func HTMLRenderer(ctx context.Context) (context.Context, *HTMLRender) {
|
|||
log.Fatal("HTMLRenderer error: %v", err)
|
||||
}
|
||||
if !setting.IsProd {
|
||||
watcher.CreateWatcher(ctx, "HTML Templates", &watcher.CreateWatcherOpts{
|
||||
PathsCallback: walkTemplateFiles,
|
||||
BetweenCallback: func() {
|
||||
if err := renderer.CompileTemplates(); err != nil {
|
||||
log.Error("Template error: %v\n%s", err, log.Stack(2))
|
||||
}
|
||||
},
|
||||
go AssetFS().WatchLocalChanges(ctx, func() {
|
||||
if err := renderer.CompileTemplates(); err != nil {
|
||||
log.Error("Template error: %v\n%s", err, log.Stack(2))
|
||||
}
|
||||
})
|
||||
}
|
||||
return context.WithValue(ctx, rendererKey, renderer), renderer
|
||||
|
@ -138,14 +137,8 @@ func handleGenericTemplateError(err error) (string, []interface{}) {
|
|||
}
|
||||
|
||||
templateName, lineNumberStr, message := groups[1], groups[2], groups[3]
|
||||
|
||||
filename, assetErr := GetAssetFilename("templates/" + templateName + ".tmpl")
|
||||
if assetErr != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
filename := fmt.Sprintf("%s (provided by %s)", templateName, AssetFS().GetFileLayerName(templateName+".tmpl"))
|
||||
lineNumber, _ := strconv.Atoi(lineNumberStr)
|
||||
|
||||
line := GetLineFromTemplate(templateName, lineNumber, "", -1)
|
||||
|
||||
return "PANIC: Unable to compile templates!\n%s in template file %s at line %d:\n\n%s\nStacktrace:\n\n%s", []interface{}{message, filename, lineNumber, log.NewColoredValue(line, log.Reset), log.Stack(2)}
|
||||
|
@ -158,16 +151,9 @@ func handleNotDefinedPanicError(err error) (string, []interface{}) {
|
|||
}
|
||||
|
||||
templateName, lineNumberStr, functionName := groups[1], groups[2], groups[3]
|
||||
|
||||
functionName, _ = strconv.Unquote(`"` + functionName + `"`)
|
||||
|
||||
filename, assetErr := GetAssetFilename("templates/" + templateName + ".tmpl")
|
||||
if assetErr != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
filename := fmt.Sprintf("%s (provided by %s)", templateName, AssetFS().GetFileLayerName(templateName+".tmpl"))
|
||||
lineNumber, _ := strconv.Atoi(lineNumberStr)
|
||||
|
||||
line := GetLineFromTemplate(templateName, lineNumber, functionName, -1)
|
||||
|
||||
return "PANIC: Unable to compile templates!\nUndefined function %q in template file %s at line %d:\n\n%s", []interface{}{functionName, filename, lineNumber, log.NewColoredValue(line, log.Reset)}
|
||||
|
@ -181,14 +167,8 @@ func handleUnexpected(err error) (string, []interface{}) {
|
|||
|
||||
templateName, lineNumberStr, unexpected := groups[1], groups[2], groups[3]
|
||||
unexpected, _ = strconv.Unquote(`"` + unexpected + `"`)
|
||||
|
||||
filename, assetErr := GetAssetFilename("templates/" + templateName + ".tmpl")
|
||||
if assetErr != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
filename := fmt.Sprintf("%s (provided by %s)", templateName, AssetFS().GetFileLayerName(templateName+".tmpl"))
|
||||
lineNumber, _ := strconv.Atoi(lineNumberStr)
|
||||
|
||||
line := GetLineFromTemplate(templateName, lineNumber, unexpected, -1)
|
||||
|
||||
return "PANIC: Unable to compile templates!\nUnexpected %q in template file %s at line %d:\n\n%s", []interface{}{unexpected, filename, lineNumber, log.NewColoredValue(line, log.Reset)}
|
||||
|
@ -201,14 +181,8 @@ func handleExpectedEnd(err error) (string, []interface{}) {
|
|||
}
|
||||
|
||||
templateName, lineNumberStr, unexpected := groups[1], groups[2], groups[3]
|
||||
|
||||
filename, assetErr := GetAssetFilename("templates/" + templateName + ".tmpl")
|
||||
if assetErr != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
filename := fmt.Sprintf("%s (provided by %s)", templateName, AssetFS().GetFileLayerName(templateName+".tmpl"))
|
||||
lineNumber, _ := strconv.Atoi(lineNumberStr)
|
||||
|
||||
line := GetLineFromTemplate(templateName, lineNumber, unexpected, -1)
|
||||
|
||||
return "PANIC: Unable to compile templates!\nMissing end with unexpected %q in template file %s at line %d:\n\n%s", []interface{}{unexpected, filename, lineNumber, log.NewColoredValue(line, log.Reset)}
|
||||
|
@ -218,7 +192,7 @@ const dashSeparator = "---------------------------------------------------------
|
|||
|
||||
// GetLineFromTemplate returns a line from a template with some context
|
||||
func GetLineFromTemplate(templateName string, targetLineNum int, target string, position int) string {
|
||||
bs, err := GetAsset("templates/" + templateName + ".tmpl")
|
||||
bs, err := AssetFS().ReadFile(templateName + ".tmpl")
|
||||
if err != nil {
|
||||
return fmt.Sprintf("(unable to read template file: %v)", err)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue