Files
athens/vendor/github.com/gobuffalo/buffalo/render/template.go
Henry Jenkins d26b99d41c Upgrade Buffalo (#789)
* Upgrade buffalo

* Switch to go modules everywhere

* Fixes from buffalo fix

* Add missing modules from module list

* Update vendored modules in /vendor

* Stop using vendor directory for tests

* Check go.mod and go.sum files on verify

* Upgrade Buffalo from v0.13.0 to v0.13.1

* Fix test for new Buffalo

Allow for new Buffalo code

* Add test for endpoint with trailing slash
2018-10-23 16:49:32 -07:00

209 lines
4.5 KiB
Go

package render
import (
"fmt"
"html/template"
"io"
"os"
"path/filepath"
"sort"
"strings"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
type templateRenderer struct {
*Engine
contentType string
names []string
data Data
}
func (s templateRenderer) ContentType() string {
return s.contentType
}
func (s *templateRenderer) Render(w io.Writer, data Data) error {
s.data = data
var body template.HTML
var err error
for _, name := range s.names {
body, err = s.exec(name, data)
if err != nil {
return err
}
data["yield"] = body
}
w.Write([]byte(body))
return nil
}
func (s templateRenderer) partial(name string, dd Data) (template.HTML, error) {
d, f := filepath.Split(name)
name = filepath.Join(d, "_"+f)
m := Data{}
for k, v := range s.data {
m[k] = v
}
for k, v := range dd {
m[k] = v
}
if _, ok := m["layout"]; ok {
var body template.HTML
var err error
body, err = s.exec(name, m)
if err != nil {
return body, err
}
m["yield"] = body
d, f := filepath.Split(fmt.Sprintf("%v", m["layout"]))
name = filepath.Join(d, "_"+f)
}
return s.exec(name, m)
}
func (s templateRenderer) exec(name string, data Data) (template.HTML, error) {
ct := strings.ToLower(s.contentType)
data["contentType"] = ct
if filepath.Ext(name) == "" {
switch {
case strings.Contains(ct, "html"):
name += ".html"
case strings.Contains(ct, "javascript"):
name += ".js"
case strings.Contains(ct, "markdown"):
name += ".md"
}
}
// Try to use localized version
templateName := name
if languages, ok := data["languages"].([]string); ok {
ll := len(languages)
if ll > 0 {
// Default language is the last in the list
defaultLanguage := languages[ll-1]
ext := filepath.Ext(name)
rawName := strings.TrimSuffix(name, ext)
for _, l := range languages {
var candidateName string
if l == defaultLanguage {
break
}
candidateName = rawName + "." + strings.ToLower(l) + ext
if s.TemplatesBox.Has(candidateName) {
// Replace name with the existing suffixed version
templateName = candidateName
break
}
}
}
}
// Set current_template to context
if _, ok := data["current_template"]; !ok {
data["current_template"] = templateName
}
source, err := s.TemplatesBox.MustBytes(templateName)
if err != nil {
return "", err
}
helpers := map[string]interface{}{
"partial": s.partial,
}
helpers = s.addAssetsHelpers(helpers)
for k, v := range s.Helpers {
helpers[k] = v
}
body := string(source)
for _, ext := range s.exts(name) {
te, ok := s.TemplateEngines[ext]
if !ok {
logrus.Errorf("could not find a template engine for %s\n", ext)
continue
}
body, err = te(body, data, helpers)
if err != nil {
return "", errors.Wrap(err, name)
}
}
return template.HTML(body), nil
}
func (s templateRenderer) exts(name string) []string {
exts := []string{}
for {
ext := filepath.Ext(name)
if ext == "" {
break
}
name = strings.TrimSuffix(name, ext)
exts = append(exts, strings.ToLower(ext[1:]))
}
if len(exts) == 0 {
return []string{"html"}
}
sort.Sort(sort.Reverse(sort.StringSlice(exts)))
return exts
}
func (s templateRenderer) assetPath(file string) (string, error) {
if len(assetMap) == 0 || os.Getenv("GO_ENV") != "production" {
manifest, err := s.AssetsBox.MustString("manifest.json")
if err != nil {
manifest, err = s.AssetsBox.MustString("assets/manifest.json")
if err != nil {
return assetPathFor(file), nil
}
}
err = loadManifest(manifest)
if err != nil {
return assetPathFor(file), errors.Wrap(err, "your manifest.json is not correct")
}
}
return assetPathFor(file), nil
}
// Template renders the named files using the specified
// content type and the github.com/gobuffalo/plush
// package for templating. If more than 1 file is provided
// the second file will be considered a "layout" file
// and the first file will be the "content" file which will
// be placed into the "layout" using "{{yield}}".
func Template(c string, names ...string) Renderer {
e := New(Options{})
return e.Template(c, names...)
}
// Template renders the named files using the specified
// content type and the github.com/gobuffalo/plush
// package for templating. If more than 1 file is provided
// the second file will be considered a "layout" file
// and the first file will be the "content" file which will
// be placed into the "layout" using "{{yield}}".
func (e *Engine) Template(c string, names ...string) Renderer {
return &templateRenderer{
Engine: e,
contentType: c,
names: names,
}
}