2016-12-06 20:58:31 +03:00
// +build bindata
// Copyright 2016 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package templates
import (
2017-03-01 04:45:21 +03:00
"bytes"
"fmt"
2016-12-06 20:58:31 +03:00
"html/template"
2017-03-01 04:45:21 +03:00
"io"
2016-12-06 20:58:31 +03:00
"io/ioutil"
"path"
"strings"
2019-11-07 16:34:28 +03:00
texttmpl "text/template"
2016-12-06 20:58:31 +03:00
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
2019-08-23 19:40:30 +03:00
"gitea.com/macaron/macaron"
"github.com/unknwon/com"
2016-12-06 20:58:31 +03:00
)
var (
2019-11-07 16:34:28 +03:00
subjectTemplates = texttmpl . New ( "" )
bodyTemplates = template . New ( "" )
2016-12-06 20:58:31 +03:00
)
2017-03-01 04:45:21 +03:00
type templateFileSystem struct {
files [ ] macaron . TemplateFile
}
func ( templates templateFileSystem ) ListFiles ( ) [ ] macaron . TemplateFile {
return templates . files
}
func ( templates templateFileSystem ) Get ( name string ) ( io . Reader , error ) {
for i := range templates . files {
if templates . files [ i ] . Name ( ) + templates . files [ i ] . Ext ( ) == name {
return bytes . NewReader ( templates . files [ i ] . Data ( ) ) , nil
}
}
return nil , fmt . Errorf ( "file '%s' not found" , name )
}
2018-07-28 03:19:01 +03:00
func NewTemplateFileSystem ( ) templateFileSystem {
2017-03-01 04:45:21 +03:00
fs := templateFileSystem { }
fs . files = make ( [ ] macaron . TemplateFile , 0 , 10 )
for _ , assetPath := range AssetNames ( ) {
if strings . HasPrefix ( assetPath , "mail/" ) {
continue
}
if ! strings . HasSuffix ( assetPath , ".tmpl" ) {
continue
}
content , err := Asset ( assetPath )
if err != nil {
log . Warn ( "Failed to read embedded %s template. %v" , assetPath , err )
continue
}
fs . files = append ( fs . files , macaron . NewTplFile (
strings . TrimSuffix (
assetPath ,
".tmpl" ,
) ,
content ,
".tmpl" ,
) )
}
customDir := path . Join ( setting . CustomPath , "templates" )
if com . IsDir ( customDir ) {
files , err := com . StatDir ( customDir )
if err != nil {
log . Warn ( "Failed to read %s templates dir. %v" , customDir , err )
} else {
for _ , filePath := range files {
if strings . HasPrefix ( filePath , "mail/" ) {
continue
}
if ! strings . HasSuffix ( filePath , ".tmpl" ) {
continue
}
content , err := ioutil . ReadFile ( path . Join ( customDir , filePath ) )
if err != nil {
log . Warn ( "Failed to read custom %s template. %v" , filePath , err )
continue
}
fs . files = append ( fs . files , macaron . NewTplFile (
strings . TrimSuffix (
filePath ,
".tmpl" ,
) ,
content ,
".tmpl" ,
) )
}
}
}
2018-07-28 03:19:01 +03:00
return fs
}
// HTMLRenderer implements the macaron handler for serving HTML templates.
func HTMLRenderer ( ) macaron . Handler {
return macaron . Renderer ( macaron . RenderOptions {
Funcs : NewFuncMap ( ) ,
2018-08-08 14:15:48 +03:00
TemplateFileSystem : NewTemplateFileSystem ( ) ,
2018-07-28 03:19:01 +03:00
} )
}
// JSONRenderer implements the macaron handler for serving JSON templates.
func JSONRenderer ( ) macaron . Handler {
2016-12-06 20:58:31 +03:00
return macaron . Renderer ( macaron . RenderOptions {
2017-03-01 04:45:21 +03:00
Funcs : NewFuncMap ( ) ,
2018-08-08 14:15:48 +03:00
TemplateFileSystem : NewTemplateFileSystem ( ) ,
2018-07-28 03:19:01 +03:00
HTMLContentType : "application/json" ,
2016-12-06 20:58:31 +03:00
} )
}
2018-11-27 18:18:26 +03:00
// JSRenderer implements the macaron handler for serving JS templates.
func JSRenderer ( ) macaron . Handler {
return macaron . Renderer ( macaron . RenderOptions {
Funcs : NewFuncMap ( ) ,
TemplateFileSystem : NewTemplateFileSystem ( ) ,
HTMLContentType : "application/javascript" ,
} )
}
2016-12-06 20:58:31 +03:00
// Mailer provides the templates required for sending notification mails.
2019-11-07 16:34:28 +03:00
func Mailer ( ) ( * texttmpl . Template , * template . Template ) {
for _ , funcs := range NewTextFuncMap ( ) {
subjectTemplates . Funcs ( funcs )
}
2016-12-06 20:58:31 +03:00
for _ , funcs := range NewFuncMap ( ) {
2019-11-07 16:34:28 +03:00
bodyTemplates . Funcs ( funcs )
2016-12-06 20:58:31 +03:00
}
for _ , assetPath := range AssetNames ( ) {
if ! strings . HasPrefix ( assetPath , "mail/" ) {
continue
}
if ! strings . HasSuffix ( assetPath , ".tmpl" ) {
continue
}
content , err := Asset ( assetPath )
if err != nil {
log . Warn ( "Failed to read embedded %s template. %v" , assetPath , err )
continue
}
2019-11-07 16:34:28 +03:00
buildSubjectBodyTemplate ( subjectTemplates ,
bodyTemplates ,
2016-12-06 20:58:31 +03:00
strings . TrimPrefix (
strings . TrimSuffix (
assetPath ,
".tmpl" ,
) ,
"mail/" ,
) ,
2019-11-07 16:34:28 +03:00
content )
2016-12-06 20:58:31 +03:00
}
customDir := path . Join ( setting . CustomPath , "templates" , "mail" )
if com . IsDir ( customDir ) {
files , err := com . StatDir ( customDir )
if err != nil {
log . Warn ( "Failed to read %s templates dir. %v" , customDir , err )
} else {
for _ , filePath := range files {
if ! strings . HasSuffix ( filePath , ".tmpl" ) {
continue
}
content , err := ioutil . ReadFile ( path . Join ( customDir , filePath ) )
if err != nil {
log . Warn ( "Failed to read custom %s template. %v" , filePath , err )
continue
}
2019-11-07 16:34:28 +03:00
buildSubjectBodyTemplate ( subjectTemplates ,
bodyTemplates ,
2016-12-06 20:58:31 +03:00
strings . TrimSuffix (
filePath ,
".tmpl" ,
) ,
2019-11-07 16:34:28 +03:00
content )
2016-12-06 20:58:31 +03:00
}
}
}
2019-11-07 16:34:28 +03:00
return subjectTemplates , bodyTemplates
2016-12-06 20:58:31 +03:00
}
2019-06-03 00:43:47 +03:00
func Asset ( name string ) ( [ ] byte , error ) {
f , err := Assets . Open ( "/" + name )
if err != nil {
return nil , err
}
defer f . Close ( )
return ioutil . ReadAll ( f )
}
func AssetNames ( ) [ ] string {
realFS := Assets . ( vfsgen۰ FS )
var results = make ( [ ] string , 0 , len ( realFS ) )
for k := range realFS {
results = append ( results , k [ 1 : ] )
}
return results
}
2020-02-02 05:17:44 +03:00
func AssetIsDir ( name string ) ( bool , error ) {
if f , err := Assets . Open ( "/" + name ) ; err != nil {
return false , err
} else {
defer f . Close ( )
if fi , err := f . Stat ( ) ; err != nil {
return false , err
} else {
return fi . IsDir ( ) , nil
}
}
}