diff options
author | guillep2k <18600385+guillep2k@users.noreply.github.com> | 2019-11-07 10:34:28 -0300 |
---|---|---|
committer | Lunny Xiao <xiaolunwen@gmail.com> | 2019-11-07 21:34:28 +0800 |
commit | 1f90147f3942065e2a7f564e8a3c97d23d41e6c0 (patch) | |
tree | fd5fb0bda2d84deb179bf99f9172b28f736ba9fe /modules/templates/helper.go | |
parent | d5b1e6bc51f87eb1be07a4682798428bf4bbb9ce (diff) | |
download | gitea-1f90147f3942065e2a7f564e8a3c97d23d41e6c0.tar.gz gitea-1f90147f3942065e2a7f564e8a3c97d23d41e6c0.zip |
Use templates for issue e-mail subject and body (#8329)
* Add template capability for issue mail subject
* Remove test string
* Fix trim subject length
* Add comment to template and run make fmt
* Add information for the template
* Rename defaultMailSubject() to fallbackMailSubject()
* General rewrite of the mail template code
* Fix .Doer name
* Use text/template for subject instead of html
* Fix subject Re: prefix
* Fix mail tests
* Fix static templates
* [skip ci] Updated translations via Crowdin
* Expose db.SetMaxOpenConns and allow non MySQL dbs to set conn pool params (#8528)
* Expose db.SetMaxOpenConns and allow other dbs to set their connection params
* Add note about port exhaustion
Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com>
* Prevent .code-view from overriding font on icon fonts (#8614)
* Correct some outdated statements in the contributing guidelines (#8612)
* More information for drone-cli in CONTRIBUTING.md
* Increases the version of drone-cli to 1.2.0
* Adds a note for the Docker Toolbox on Windows
Signed-off-by: LukBukkit <luk.bukkit@gmail.com>
* Fix the url for the blog repository (now on gitea.com)
Signed-off-by: LukBukkit <luk.bukkit@gmail.com>
* Remove TrN due to lack of lang context
* Redo templates to match previous code
* Fix extra character in template
* Unify PR & Issue tempaltes, fix format
* Remove default subject
* Add template tests
* Fix template
* Remove replaced function
* Provide User as models.User for better consistency
* Add docs
* Fix doc inaccuracies, improve examples
* Change mail footer to math AppName
* Add test for mail subject/body template separation
* Add support for code review comments
* Update docs/content/doc/advanced/mail-templates-us.md
Co-Authored-By: 6543 <24977596+6543@users.noreply.github.com>
Diffstat (limited to 'modules/templates/helper.go')
-rw-r--r-- | modules/templates/helper.go | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/modules/templates/helper.go b/modules/templates/helper.go index 2d7a1aee9b..1347835b80 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -16,8 +16,10 @@ import ( "mime" "net/url" "path/filepath" + "regexp" "runtime" "strings" + texttmpl "text/template" "time" "unicode" @@ -34,6 +36,9 @@ import ( "github.com/editorconfig/editorconfig-core-go/v2" ) +// Used from static.go && dynamic.go +var mailSubjectSplit = regexp.MustCompile(`(?m)^-{3,}[\s]*$`) + // NewFuncMap returns functions for injecting to templates func NewFuncMap() []template.FuncMap { return []template.FuncMap{map[string]interface{}{ @@ -261,6 +266,112 @@ func NewFuncMap() []template.FuncMap { }} } +// NewTextFuncMap returns functions for injecting to text templates +// It's a subset of those used for HTML and other templates +func NewTextFuncMap() []texttmpl.FuncMap { + return []texttmpl.FuncMap{map[string]interface{}{ + "GoVer": func() string { + return strings.Title(runtime.Version()) + }, + "AppName": func() string { + return setting.AppName + }, + "AppSubUrl": func() string { + return setting.AppSubURL + }, + "AppUrl": func() string { + return setting.AppURL + }, + "AppVer": func() string { + return setting.AppVer + }, + "AppBuiltWith": func() string { + return setting.AppBuiltWith + }, + "AppDomain": func() string { + return setting.Domain + }, + "TimeSince": timeutil.TimeSince, + "TimeSinceUnix": timeutil.TimeSinceUnix, + "RawTimeSince": timeutil.RawTimeSince, + "DateFmtLong": func(t time.Time) string { + return t.Format(time.RFC1123Z) + }, + "DateFmtShort": func(t time.Time) string { + return t.Format("Jan 02, 2006") + }, + "List": List, + "SubStr": func(str string, start, length int) string { + if len(str) == 0 { + return "" + } + end := start + length + if length == -1 { + end = len(str) + } + if len(str) < end { + return str + } + return str[start:end] + }, + "EllipsisString": base.EllipsisString, + "URLJoin": util.URLJoin, + "Dict": func(values ...interface{}) (map[string]interface{}, error) { + if len(values)%2 != 0 { + return nil, errors.New("invalid dict call") + } + dict := make(map[string]interface{}, len(values)/2) + for i := 0; i < len(values); i += 2 { + key, ok := values[i].(string) + if !ok { + return nil, errors.New("dict keys must be strings") + } + dict[key] = values[i+1] + } + return dict, nil + }, + "Printf": fmt.Sprintf, + "Escape": Escape, + "Sec2Time": models.SecToTime, + "ParseDeadline": func(deadline string) []string { + return strings.Split(deadline, "|") + }, + "dict": func(values ...interface{}) (map[string]interface{}, error) { + if len(values) == 0 { + return nil, errors.New("invalid dict call") + } + + dict := make(map[string]interface{}) + + for i := 0; i < len(values); i++ { + switch key := values[i].(type) { + case string: + i++ + if i == len(values) { + return nil, errors.New("specify the key for non array values") + } + dict[key] = values[i] + case map[string]interface{}: + m := values[i].(map[string]interface{}) + for i, v := range m { + dict[i] = v + } + default: + return nil, errors.New("dict values must be maps") + } + } + return dict, nil + }, + "percentage": func(n int, values ...int) float32 { + var sum = 0 + for i := 0; i < len(values); i++ { + sum += values[i] + } + return float32(n) * 100 / float32(sum) + }, + }} +} + // Safe render raw as HTML func Safe(raw string) template.HTML { return template.HTML(raw) @@ -551,3 +662,22 @@ func MigrationIcon(hostname string) string { return "fa-git-alt" } } + +func buildSubjectBodyTemplate(stpl *texttmpl.Template, btpl *template.Template, name string, content []byte) { + // Split template into subject and body + var subjectContent []byte + bodyContent := content + loc := mailSubjectSplit.FindIndex(content) + if loc != nil { + subjectContent = content[0:loc[0]] + bodyContent = content[loc[1]:] + } + if _, err := stpl.New(name). + Parse(string(subjectContent)); err != nil { + log.Warn("Failed to parse template [%s/subject]: %v", name, err) + } + if _, err := btpl.New(name). + Parse(string(bodyContent)); err != nil { + log.Warn("Failed to parse template [%s/body]: %v", name, err) + } +} |