|  | @@ -1,286 +0,0 @@
 | 
	
		
			
				|  |  | -// Copyright 2014 The Gogs Authors. All rights reserved.
 | 
	
		
			
				|  |  | -// Use of this source code is governed by a MIT-style
 | 
	
		
			
				|  |  | -// license that can be found in the LICENSE file.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// foked from https://github.com/martini-contrib/render/blob/master/render.go
 | 
	
		
			
				|  |  | -package middleware
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -import (
 | 
	
		
			
				|  |  | -	"bytes"
 | 
	
		
			
				|  |  | -	"encoding/json"
 | 
	
		
			
				|  |  | -	"fmt"
 | 
	
		
			
				|  |  | -	"html/template"
 | 
	
		
			
				|  |  | -	"io"
 | 
	
		
			
				|  |  | -	"io/ioutil"
 | 
	
		
			
				|  |  | -	"net/http"
 | 
	
		
			
				|  |  | -	"os"
 | 
	
		
			
				|  |  | -	"path/filepath"
 | 
	
		
			
				|  |  | -	"time"
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	"github.com/codegangsta/martini"
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	"github.com/gogits/gogs/modules/base"
 | 
	
		
			
				|  |  | -)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const (
 | 
	
		
			
				|  |  | -	ContentType    = "Content-Type"
 | 
	
		
			
				|  |  | -	ContentLength  = "Content-Length"
 | 
	
		
			
				|  |  | -	ContentJSON    = "application/json"
 | 
	
		
			
				|  |  | -	ContentHTML    = "text/html"
 | 
	
		
			
				|  |  | -	ContentXHTML   = "application/xhtml+xml"
 | 
	
		
			
				|  |  | -	defaultCharset = "UTF-8"
 | 
	
		
			
				|  |  | -)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -var helperFuncs = template.FuncMap{
 | 
	
		
			
				|  |  | -	"yield": func() (string, error) {
 | 
	
		
			
				|  |  | -		return "", fmt.Errorf("yield called with no layout defined")
 | 
	
		
			
				|  |  | -	},
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -type Delims struct {
 | 
	
		
			
				|  |  | -	Left string
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	Right string
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -type RenderOptions struct {
 | 
	
		
			
				|  |  | -	Directory string
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	Layout string
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	Extensions []string
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	Funcs []template.FuncMap
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	Delims Delims
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	Charset string
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	IndentJSON bool
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	HTMLContentType string
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -type HTMLOptions struct {
 | 
	
		
			
				|  |  | -	Layout string
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func Renderer(options ...RenderOptions) martini.Handler {
 | 
	
		
			
				|  |  | -	opt := prepareOptions(options)
 | 
	
		
			
				|  |  | -	cs := prepareCharset(opt.Charset)
 | 
	
		
			
				|  |  | -	t := compile(opt)
 | 
	
		
			
				|  |  | -	return func(res http.ResponseWriter, req *http.Request, c martini.Context) {
 | 
	
		
			
				|  |  | -		var tc *template.Template
 | 
	
		
			
				|  |  | -		if martini.Env == martini.Dev {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			tc = compile(opt)
 | 
	
		
			
				|  |  | -		} else {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			tc, _ = t.Clone()
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		rd := &Render{res, req, tc, opt, cs, base.TmplData{}, time.Time{}}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		rd.Data["TmplLoadTimes"] = func() string {
 | 
	
		
			
				|  |  | -			if rd.startTime.IsZero() {
 | 
	
		
			
				|  |  | -				return ""
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -			return fmt.Sprint(time.Since(rd.startTime).Nanoseconds()/1e6) + "ms"
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		c.Map(rd.Data)
 | 
	
		
			
				|  |  | -		c.Map(rd)
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func prepareCharset(charset string) string {
 | 
	
		
			
				|  |  | -	if len(charset) != 0 {
 | 
	
		
			
				|  |  | -		return "; charset=" + charset
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	return "; charset=" + defaultCharset
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func prepareOptions(options []RenderOptions) RenderOptions {
 | 
	
		
			
				|  |  | -	var opt RenderOptions
 | 
	
		
			
				|  |  | -	if len(options) > 0 {
 | 
	
		
			
				|  |  | -		opt = options[0]
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	if len(opt.Directory) == 0 {
 | 
	
		
			
				|  |  | -		opt.Directory = "templates"
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	if len(opt.Extensions) == 0 {
 | 
	
		
			
				|  |  | -		opt.Extensions = []string{".tmpl"}
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	if len(opt.HTMLContentType) == 0 {
 | 
	
		
			
				|  |  | -		opt.HTMLContentType = ContentHTML
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	return opt
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func compile(options RenderOptions) *template.Template {
 | 
	
		
			
				|  |  | -	dir := options.Directory
 | 
	
		
			
				|  |  | -	t := template.New(dir)
 | 
	
		
			
				|  |  | -	t.Delims(options.Delims.Left, options.Delims.Right)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	template.Must(t.Parse("Martini"))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
 | 
	
		
			
				|  |  | -		r, err := filepath.Rel(dir, path)
 | 
	
		
			
				|  |  | -		if err != nil {
 | 
	
		
			
				|  |  | -			return err
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		ext := filepath.Ext(r)
 | 
	
		
			
				|  |  | -		for _, extension := range options.Extensions {
 | 
	
		
			
				|  |  | -			if ext == extension {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -				buf, err := ioutil.ReadFile(path)
 | 
	
		
			
				|  |  | -				if err != nil {
 | 
	
		
			
				|  |  | -					panic(err)
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -				name := (r[0 : len(r)-len(ext)])
 | 
	
		
			
				|  |  | -				tmpl := t.New(filepath.ToSlash(name))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -				for _, funcs := range options.Funcs {
 | 
	
		
			
				|  |  | -					tmpl.Funcs(funcs)
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -				template.Must(tmpl.Funcs(helperFuncs).Parse(string(buf)))
 | 
	
		
			
				|  |  | -				break
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		return nil
 | 
	
		
			
				|  |  | -	})
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	return t
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -type Render struct {
 | 
	
		
			
				|  |  | -	http.ResponseWriter
 | 
	
		
			
				|  |  | -	req             *http.Request
 | 
	
		
			
				|  |  | -	t               *template.Template
 | 
	
		
			
				|  |  | -	opt             RenderOptions
 | 
	
		
			
				|  |  | -	compiledCharset string
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	Data base.TmplData
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	startTime time.Time
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (r *Render) JSON(status int, v interface{}) {
 | 
	
		
			
				|  |  | -	var result []byte
 | 
	
		
			
				|  |  | -	var err error
 | 
	
		
			
				|  |  | -	if r.opt.IndentJSON {
 | 
	
		
			
				|  |  | -		result, err = json.MarshalIndent(v, "", "  ")
 | 
	
		
			
				|  |  | -	} else {
 | 
	
		
			
				|  |  | -		result, err = json.Marshal(v)
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	if err != nil {
 | 
	
		
			
				|  |  | -		http.Error(r, err.Error(), 500)
 | 
	
		
			
				|  |  | -		return
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	r.Header().Set(ContentType, ContentJSON+r.compiledCharset)
 | 
	
		
			
				|  |  | -	r.WriteHeader(status)
 | 
	
		
			
				|  |  | -	r.Write(result)
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (r *Render) JSONString(v interface{}) (string, error) {
 | 
	
		
			
				|  |  | -	var result []byte
 | 
	
		
			
				|  |  | -	var err error
 | 
	
		
			
				|  |  | -	if r.opt.IndentJSON {
 | 
	
		
			
				|  |  | -		result, err = json.MarshalIndent(v, "", "  ")
 | 
	
		
			
				|  |  | -	} else {
 | 
	
		
			
				|  |  | -		result, err = json.Marshal(v)
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	if err != nil {
 | 
	
		
			
				|  |  | -		return "", err
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	return string(result), nil
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (r *Render) renderBytes(name string, binding interface{}, htmlOpt ...HTMLOptions) (*bytes.Buffer, error) {
 | 
	
		
			
				|  |  | -	opt := r.prepareHTMLOptions(htmlOpt)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	if len(opt.Layout) > 0 {
 | 
	
		
			
				|  |  | -		r.addYield(name, binding)
 | 
	
		
			
				|  |  | -		name = opt.Layout
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	out, err := r.execute(name, binding)
 | 
	
		
			
				|  |  | -	if err != nil {
 | 
	
		
			
				|  |  | -		return nil, err
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	return out, nil
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (r *Render) HTML(status int, name string, binding interface{}, htmlOpt ...HTMLOptions) {
 | 
	
		
			
				|  |  | -	r.startTime = time.Now()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	out, err := r.renderBytes(name, binding, htmlOpt...)
 | 
	
		
			
				|  |  | -	if err != nil {
 | 
	
		
			
				|  |  | -		http.Error(r, err.Error(), http.StatusInternalServerError)
 | 
	
		
			
				|  |  | -		return
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	r.Header().Set(ContentType, r.opt.HTMLContentType+r.compiledCharset)
 | 
	
		
			
				|  |  | -	r.WriteHeader(status)
 | 
	
		
			
				|  |  | -	io.Copy(r, out)
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (r *Render) HTMLString(name string, binding interface{}, htmlOpt ...HTMLOptions) (string, error) {
 | 
	
		
			
				|  |  | -	if out, err := r.renderBytes(name, binding, htmlOpt...); err != nil {
 | 
	
		
			
				|  |  | -		return "", err
 | 
	
		
			
				|  |  | -	} else {
 | 
	
		
			
				|  |  | -		return out.String(), nil
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (r *Render) Error(status int) {
 | 
	
		
			
				|  |  | -	r.WriteHeader(status)
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (r *Render) Redirect(location string, status ...int) {
 | 
	
		
			
				|  |  | -	code := http.StatusFound
 | 
	
		
			
				|  |  | -	if len(status) == 1 {
 | 
	
		
			
				|  |  | -		code = status[0]
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	http.Redirect(r, r.req, location, code)
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (r *Render) Template() *template.Template {
 | 
	
		
			
				|  |  | -	return r.t
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (r *Render) execute(name string, binding interface{}) (*bytes.Buffer, error) {
 | 
	
		
			
				|  |  | -	buf := new(bytes.Buffer)
 | 
	
		
			
				|  |  | -	return buf, r.t.ExecuteTemplate(buf, name, binding)
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (r *Render) addYield(name string, binding interface{}) {
 | 
	
		
			
				|  |  | -	funcs := template.FuncMap{
 | 
	
		
			
				|  |  | -		"yield": func() (template.HTML, error) {
 | 
	
		
			
				|  |  | -			buf, err := r.execute(name, binding)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			return template.HTML(buf.String()), err
 | 
	
		
			
				|  |  | -		},
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	r.t.Funcs(funcs)
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (r *Render) prepareHTMLOptions(htmlOpt []HTMLOptions) HTMLOptions {
 | 
	
		
			
				|  |  | -	if len(htmlOpt) > 0 {
 | 
	
		
			
				|  |  | -		return htmlOpt[0]
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	return HTMLOptions{
 | 
	
		
			
				|  |  | -		Layout: r.opt.Layout,
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -}
 |