Code Monkey home page Code Monkey logo

render's People

Contributors

7fffffff avatar arschles avatar blachniet avatar bonfy avatar brutella avatar darkdarkfruit avatar doctoro avatar dominik-lekse avatar elithrar avatar fmd avatar ian-kent avatar jaybeecave avatar ldez avatar lunny avatar nsmith5 avatar overvenus avatar romanornr avatar syntaqx avatar thesuess avatar tobarja avatar unrolled avatar untoldone avatar williambao avatar zeripath avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

render's Issues

Third party template engine support

Hi there, I use Amber templates, and I know that some people like using the popular Pongo2 templating engine. These both compile to *template.Template instances, rather than saving to files.

Would you accept a pull request where HTML, JSON, XML, etc all implement a interface? There's a similar situation at gin-gonic, where they handled this situation like this. This would let us write very simple types that let us use our templating libraries to write to the reponsewriter.

Thoughts?

blocks: how to handle undefined templates and subfolders?

"blocks" are new and well appreciated. May it be for css or scripts, we can use {{ block "css" }} to load css-templatename when templatename is current in layout.

Two minor remarks though:

  • for now, if the blockname-template.tmpl file is missing, a template: layout:9:7: executing "layout" at <block "blockname">: error calling block: html/template: "blockname-template" is undefined error will be triggered. Should we try to handle this kind of error in templates / layout, create as many blocks as necessary or should "render" return an empty template when the required file is missing?
  • if one uses subfolders for templates (resources.tmpl, resource.tmpl, admin/resources.tmpl, admin/resource.tmpl), blocks are intended to be found at blockname-subfolder/templatename.tmpl over what feels more logical to me subfolder/blockname-templatename.tmpl. Am I doing it wrong?

Return JSON that has a trailing newline

I know JSON is a machine language and not meant for human consumption but I so very very often use curl and then because the output doesn't end with a newline character the console prompt gets all confused.
Would it be possible to make it always end with a newline character?

PANIC: template: redefinition of template "layout"

My website using render, most of the time are normal, is occasionally appear : PANIC: template: redefinition of template "layout" , I don't know what the reason is, please help.

description:

2015/03/04 20:33:00 http: multiple response.WriteHeader calls
[negroni] PANIC: template: redefinition of template "layout"
goroutine 73776 [running]:
github.com/codegangsta/negroni.func·003()
/var/GOPATH/src/github.com/codegangsta/negroni/recovery.go:34 +0x10d
html/template.Must(0x0, 0x7f9c8a8c1c00, 0xc208299440, 0x0)
/var/go/src/html/template/template.go:304 +0x50
github.com/unrolled/render.func·003(0xc2082f79c0, 0x15, 0x7f9c8a8c7ad0, 0xc2086f3bd0, 0x0, 0x0, 0x0, 0x0)
/var/GOPATH/src/github.com/unrolled/render/render.go:167 +0x539
path/filepath.walk(0xc2082f79c0, 0x15, 0x7f9c8a8c7ad0, 0xc2086f3bd0, 0xc208859428, 0x0, 0x0)
/var/go/src/path/filepath/path.go:347 +0x91
path/filepath.walk(0x98e970, 0x9, 0x7f9c8a8c7ad0, 0xc2080f2000, 0xc208859428, 0x0, 0x0)
/var/go/src/path/filepath/path.go:372 +0x51d
path/filepath.Walk(0x98e970, 0x9, 0xc208859428, 0x0, 0x0)
/var/go/src/path/filepath/path.go:394 +0xf2
github.com/unrolled/render.(_Render).compileTemplates(0xc20809f860)
/var/GOPATH/src/github.com/unrolled/render/render.go:173 +0x106
github.com/unrolled/render.(_Render).HTML(0xc20809f860, 0x7f9c8a8d50d8, 0xc2087b1e80, 0xc8, 0x988150, 0x8, 0x7f0660, 0xc20848ddd0, 0xc208859640, 0x1, ...)
/var/GOPATH/src/github.com/unrolled/render/render.go:250 +0x3f

html/template: "layouts/main" is undefined

I'm probably doing something stupid, but I can't figure out what the problem is.

I'm getting the following error when trying to load my home page:

[ERRO] 2017-01-03 13:54:41 UTC html/template: "layouts/main" is undefined

My render object looks like so:

s.Render = render.New(render.Options{
		Directory:     s.Config.Templates,
		Layout:        "layouts/main",
		Extensions:    []string{".tmpl", ".html"},
		IsDevelopment: s.Config.RenderRecompile,
		Funcs:         []template.FuncMap{appHelpers},
		DisableHTTPErrorRendering: true,
	})

My layout file is located in templates/layouts/main.html, relative to my binary.

My controller is calling:

err := s.Render.HTML(w, http.StatusOK, "main/home", nil)

And the contents of my layout file:

<!DOCTYPE html>
<html>
	<head>
		<title>title</title>
	</head>
	<body>
		{{ yield }}
	</body>
</html>

But I don't think it's even finding the layout file. I've tried using a .tmpl instead of .html extension with no luck, I've also tried moving the layout file to the root of the templates folder, but that did not help either.

Surely I'm doing something really dumb here... Appreciate some guidance, thanks.

Best pattern for common variables in templates?

Thanks a lot for this - I'm finding the combination of render and negroni to be a really nice set up.

I've got a question, and maybe it'd be useful to add this to the documentation too. My layout has a header which is common across all pages. I need to add some links to it, and I don't want to pass them into the template's context each time. Is Funcs the right place to pass these in?

json how to use JSONNumber

use the json
how to set int to string

test:=uint(48711125038006272)
config.Render.JSON(w, http.StatusOK, test)
js
success: function (json) {
// json is 48711125038006270
}

partial wrong number of args

I Have This Code to Create Render instance

r:= render.New(render.Options{
		Directory:       "templates",
		Layout:          "layouts/base",
		Extensions:      []string{".html"},
		IsDevelopment:   true,
		RequirePartials: false,
	})

and this code for viewing 404 page

if err := r.HTML(w, http.StatusNotFound, "404.html", nil); err != nil {
		println(err.Error())
	}

and the structure of my templates folder is like that:

layouts/base.html
404.html
home.html

the Home.html is working fine but the problem with the 404 page gives me this error:

template: layouts/base:13:7: executing "layouts/base" at <partial>: wrong number of args for partial: want 0 got 1

the HTML Pages is:

<!-- templates/layouts/base.html -->
<!doctype html>
<html lang="en">
<head>
    <title>My Layout</title>
    {{ partial "css" }}
</head>
<body>
{{ partial "header" }}

<div class="container">
    {{ yield }}
</div>
{{ partial "footer" }}
</body>
</html>

<!-- templates/home.html -->
<div class="jumbotron border text-center" style="margin-top: 100px">
    <img class="border img-thumbnail" src="/static/img/logo.png" width="200px" alt="">
    <h1 class="display-4">Venom</h1>
    <p class="lead">it's a simple min golang starter app done by using some packages with MVC structure :) highly
        inspired by Laravel</p>
</div>

<!-- templates/404.html -->
<div class="error-wrapper">
    <img class="border img-thumbnail" src="/static/img/logo.png" width="200px" alt="">
    <h1>404</h1>
    <h3>Oh! Page not found</h3>
</div>


Error in documentation

Documentation on front page of github refers to the render.Render. Is this really right?
example:
"r := render.Render(render.Options{"

Render panics with enough concurrent requests incoming

I might be doing something wrong here, but I end up getting this fine error attempting to load-test my application (or just refreshing a lot).

Which template that is redefined constantly changes, so it is not the problem.
Have you encountered this before?

2015/01/06 15:03:25 Recovering from Panic: template: redefinition of template "partials/transaction_rows"
goroutine 2785 [running]:
github.com/unrolled/recovery.func·001()
        /home/kristoffer/code/go/src/github.com/unrolled/recovery/recovery.go:86 +0x12a
html/template.Must(0x0, 0x7f89c3f72b00, 0xc20800b600, 0x0)
        /usr/local/go/src/html/template/template.go:304 +0x50
github.com/unrolled/render.func·003(0xc208122ed0, 0x28, 0x7f89c3f770f0, 0xc208177b30, 0x0, 0x0, 0x0, 0x0) 
        /home/kristoffer/code/go/src/github.com/unrolled/render/render.go:167 +0x539
path/filepath.walk(0xc208122ed0, 0x28, 0x7f89c3f770f0, 0xc208177b30, 0xc20819f740, 0x0, 0x0) 
        /usr/local/go/src/path/filepath/path.go:347 +0x91
path/filepath.walk(0xc208178580, 0x12, 0x7f89c3f770f0, 0xc2081760a0, 0xc20819f740, 0x0, 0x0)
        /usr/local/go/src/path/filepath/path.go:372 +0x51d
path/filepath.walk(0x8c2e50, 0x9, 0x7f89c3f770f0, 0xc20811c230, 0xc20819f740, 0x0, 0x0)
        /usr/local/go/src/path/filepath/path.go:372 +0x51d
path/filepath.Walk(0x8c2e50, 0x9, 0xc20819f740, 0x0, 0x0)
        /usr/local/go/src/path/filepath/path.go:394 +0xf2
github.com/unrolled/render.(*Render).compileTemplates(0xc20808c000)
        /home/kristoffer/code/go/src/github.com/unrolled/render/render.go:173 +0x106 
github.com/unrolled/render.(*Render).HTML(0xc20808c000, 0x7f89c3f78dc0, 0xc20801ea00, 0xc8, 0x892ef0, 0x5, 0x0, 0x0, 0x0, 0x0, ...) 
        /home/kristoffer/code/go/src/github.com/unrolled/render/render.go:250 +0x3f 
github.com/flexd/evego/views.(*RequestHandler).Welcome(0xc2080e1880, 0x7f89c3f78dc0, 0xc20801ea00, 0xc2080324e0) 
        /home/kristoffer/code/go/src/github.com/flexd/evego/views/index.go:8 +0xc0 
github.com/flexd/evego/views.*RequestHandler.Welcome·fm(0x7f89c3f78dc0, 0xc20801ea00, 0xc2080324e0) 
        /home/kristoffer/code/go/src/github.com/flexd/evego/main.go:72 +0x45
net/http.HandlerFunc.ServeHTTP(0xc2080da680, 0x7f89c3f78dc0, 0xc20801ea00, 0xc2080324e0)
        /usr/local/go/src/net/http/server.go:1265 +0x41 
github.com/gorilla/mux.(*Router).ServeHTTP(0xc2080e2fa0, 0x7f89c3f78dc0, 0xc20801ea00, 0xc2080324e0) 
        /home/kristoffer/code/go/src/github.com/gorilla/mux/mux.go:98 +0x297
github.com/unrolled/recovery.func·002(0x7f89c3f78dc0, 0xc20801ea00, 0xc2080324e0)
        /home/kristoffer/code/go/src/github.com/unrolled/recovery/recovery.go:92 +0xe1
net/http.HandlerFunc.ServeHTTP(0xc20801f040, 0x7f89c3f78dc0, 0xc20801ea00, 0xc2080324e0)
        /usr/local/go/src/net/http/server.go:1265 +0x41 
github.com/gorilla/handlers.loggingHandler.ServeHTTP(0x7f89c3f78a78, 0xc20801f080, 0x7f89c3f78988, 0xc20801f040, 0x7f89c3f78d18, 0xc208164000, 0xc2080324e0) 
        /home/kristoffer/code/go/src/github.com/gorilla/handlers/handlers.go:75 +0x1be 
github.com/gorilla/handlers.(*loggingHandler).ServeHTTP(0xc20801f0a0, 0x7f89c3f78d18, 0xc208164000, 0xc2080324e0) 
        <autogenerated>:14 +0xbe
github.com/gorilla/context.func·001(0x7f89c3f78d18, 0xc208164000, 0xc2080324e0)
        /home/kristoffer/code/go/src/github.com/gorilla/context/context.go:141 +0x80
net/http.HandlerFunc.ServeHTTP(0xc2080db680, 0x7f89c3f78d18, 0xc208164000, 0xc2080324e0)
        /usr/local/go/src/net/http/server.go:1265 +0x41
net/http.serverHandler.ServeHTTP(0xc2080314a0, 0x7f89c3f78d18, 0xc208164000, 0xc2080324e0)
        /usr/local/go/src/net/http/server.go:1703 +0x19a
net/http.(*conn).serve(0xc208164500)
        /usr/local/go/src/net/http/server.go:1204 +0xb57
created by net/http.(*Server).Serve
        /usr/local/go/src/net/http/server.go:1751 +0x35e

Passing a string containing JSON to render.JSON()

Hi.

Would it be possible to add a check in engine.Render to not marshal already marshaled JSON?
The reason this would be useful is for example when/if something has been marshaled and stored to a cache or a key-value store like Redis. The data coming out of Redis (in my case) is already JSON, so I would have to unmarshal the data and then have render.JSON re-marshal it.

Does that make sense?

Template Functions added via HTMLOptions don't seem to work

Hi,

I needed to add a specific function which require the http.Request and found out that I could add them via the HTMLOptions struct.
However, it doesn't seem to work for me.

This is what I got:

func (c *AppContext) HTML(w http.ResponseWriter, r *http.Request, status int, tmpl string, data interface{}) {
	csrfField := csrf.TemplateField(r)
	htmlOpts := render.HTMLOptions{
		Funcs: template.FuncMap{
			"csrfField": func() template.HTML {
				return csrfField
			},
			"testFunc": func() string {
					return "My custom function"
				},
		},
	}
	c.Render.HTML(w, status, tmpl, data, htmlOpts)
}

and in my template I am trying to call it like this:

{{ csrfField }} // also tried with {{ .csrfField }} --> then it returns nothing

It always errors with

panic: template: index:1: function "csrfField" not defined

Upon further investigation I found out that the functions do get registered here:

tpl.Name(): index
opt.Funcs: map[csrfField:0x9141c0 testFunc:0x9141e0]

but don't seem to be available in the template?

I am kinda new to Go so I am not sure if either I am doing something wrong or if this is a bug?

Rendering the HTML of a string

Hey,

I'm sure there's a way to do it but I cant seem to find it anywhere in the docs.

is there a way to pump for example:
<//a href="link">link

and not have the renderer escape the html and properly display a link?

I was using beego and they had a str2html that did this and it seems like a pretty common feature that Im probably just being dense and not seeing.

Thanks!
-Ozzadar

Enforce Line Endings to LF

The tests expect that the line-endings used are always LF (\n). For example:

expect(t, res.Body.String(), "before gophers\n<h1>during</h1>\nafter gophers\n")

If you check out the repository on a Windows machine with git config core.autocrlf=true, any tests comparing strings with line endings fail because the line endings are automatically converted to CRLF (\r\n).

To ensure that LF line endings are always retained, we can add a .gitattributes file as described in GitHub's Dealing with line endings article.

Empty slice rendered as "null"

Hi,
I'm currently facing a really weird problem that I don't understand.
In a controller, I get a url slice (urls) from another function and I render it.
In the case I get an empty slice, it is rendered as "null" in the JSON.
The thing is, when I pass a freshly created empty slice ([]Url{}), it is well rendered as "[]".
You're going to tell me that the problem comes from the "urls" var but all the following commands give the same results for both the "urls" var and the fresh slice.
The only difference is when I try to render with the one or the other at the end.

fmt.Println(reflect.TypeOf(urls))
fmt.Println(reflect.TypeOf([]Url{}))

fmt.Println(reflect.ValueOf(urls))
fmt.Println(reflect.ValueOf([]Url{}))

fmt.Println(len(urls))
fmt.Println(len([]Url{}))

render := render.New()
render.JSON(w, http.StatusOK, urls)
render.JSON(w, http.StatusOK, []Url{})

Do you have any ideas ?
Thanks.

how to use render?

hi unrolled:I didn't know how to use demo

html:

<html>
    <head>
       <title>{{.Title}}</title>
    </head>
<body>
</body>
</html>

gocode:

type Test struct {
Title string
Content string
}

t := &Test{"title","content"}
r.HTML(w,http.StatusOk,"example",t) here t coun't works

Tests failing with Layout

I seem to be having an issue I'm not sure how to track down. I'm trying to write some tests with the "testing" library on some negro controllers that use unrolled/render. The issue I am running into is that the tests always fail because the server returns a 500 with the error that the "application" layout can't be found.

If i launch the server and hit it with a browser it works fine. I believe the issue has something to do with the controller being nested in a folder while my layouts are at the top level of my application. I'm guessing the test runner is launching the test from the nested folder and thus render can't resolve the layout.

Is there a way around this? Please let me know if you need more information.

Thanks.

Custom Error Handlers on Rendering Errors

When an error is encountered as part of the rendering pipeline http.Error is called and displays the simple plain-text error page:

func (r *Render) Render(w http.ResponseWriter, e Engine, data interface{}) {
    err := e.Render(w, data)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

It would be great if there was the ability to pass your own error handler. A potential implementation would be:

  • Add an ErrorHandler http.Handler field to the render.Options struct
  • In prepareOptions call if r.opt.ErrorHandler == nil { r.opt.ErrorHandler = defaultErrorHandler }
  • Add a defaultErrorHandler http.HandlerFunc that wraps http.Error(w, http.StatusText(500), 500)
  • Package users can supply their own handler to render "pretty" error pages or otherwise handle rendering errors. (my personal use case would be to call a static 500.html page with in-lined CSS that's a little friendlier than the plain text one from net/http)

Happy to provide a PR for this but wanted to run this by you first.

How can i get number of containers or images?

I tried "cap" and "len" command but both of these didn't help.

len(client.ListContainers(docker.ListContainersOptions{All: true}))
cap(client.ListImages(docker.ListImagesOptions{All: true}))

How can i get number of containers or images?

Rendering the wrong HTML template under load

Try running https://github.com/7fffffff/unrolledrendertest while also running an at least 2 instances of a http benchmark program (I used wrk for this)

unrolledrendertest
wrk -t 4 -c 4 -d 30s http://localhost:8080/example1
wrk -t 4 -c 4 -d 30s http://localhost:8080/example2

which leads to

2016/12/19 19:41:11 http: panic serving 127.0.0.1:46640: expected example2, got example1
goroutine 1530 [running]:
net/http.(*conn).serve.func1(0xc4204d5e80)
	/usr/local/go/src/net/http/server.go:1491 +0x12a
panic(0x6fe120, 0xc4200ca390)
	/usr/local/go/src/runtime/panic.go:458 +0x243
main.main.func2(0x8cf560, 0xc4200744e0, 0xc42022cd20)
	/home/u/go/src/github.com/7fffffff/unrolledrendertest/main.go:27 +0x3bd
net/http.HandlerFunc.ServeHTTP(0xc42000d300, 0x8cf560, 0xc4200744e0, 0xc42022cd20)
	/usr/local/go/src/net/http/server.go:1726 +0x44
net/http.(*ServeMux).ServeHTTP(0x8efe20, 0x8cf560, 0xc4200744e0, 0xc42022cd20)
	/usr/local/go/src/net/http/server.go:2022 +0x7f
net/http.serverHandler.ServeHTTP(0xc420108380, 0x8cf560, 0xc4200744e0, 0xc42022cd20)
	/usr/local/go/src/net/http/server.go:2202 +0x7d
net/http.(*conn).serve(0xc4204d5e80, 0x8cfba0, 0xc420014280)
	/usr/local/go/src/net/http/server.go:1579 +0x4b7
created by net/http.(*Server).Serve
	/usr/local/go/src/net/http/server.go:2293 +0x44d
2016/12/19 19:41:11 http: panic serving 127.0.0.1:46646: expected example1, got example2
goroutine 1514 [running]:
net/http.(*conn).serve.func1(0xc4200ba100)
	/usr/local/go/src/net/http/server.go:1491 +0x12a
panic(0x6fe120, 0xc4200ca730)
	/usr/local/go/src/runtime/panic.go:458 +0x243
main.main.func1(0x8cf560, 0xc4204b2f70, 0xc4203f8b40)
	/home/u/go/src/github.com/7fffffff/unrolledrendertest/main.go:19 +0x3bd
net/http.HandlerFunc.ServeHTTP(0xc42000d2f0, 0x8cf560, 0xc4204b2f70, 0xc4203f8b40)
	/usr/local/go/src/net/http/server.go:1726 +0x44
net/http.(*ServeMux).ServeHTTP(0x8efe20, 0x8cf560, 0xc4204b2f70, 0xc4203f8b40)
	/usr/local/go/src/net/http/server.go:2022 +0x7f
net/http.serverHandler.ServeHTTP(0xc420108380, 0x8cf560, 0xc4204b2f70, 0xc4203f8b40)
	/usr/local/go/src/net/http/server.go:2202 +0x7d
net/http.(*conn).serve(0xc4200ba100, 0x8cfba0, 0xc42023e180)
	/usr/local/go/src/net/http/server.go:1579 +0x4b7
created by net/http.(*Server).Serve
	/usr/local/go/src/net/http/server.go:2293 +0x44d

If only one instance of wrk is running, there are no panics.

I think the root cause is the call to Render.addLayoutFuncs(), which modifies a template. It seems possible for a request to call Render.HTML() (and thus addLayoutFuncs()) before a previous request has finished rendering.

Adding a mutex to Render seems to work. But it may also be possible to avoid locking through the use of Template.Clone()

How to use the HTML type

I want to specify the layout to be used in the handlers and HTML type seems like a good fit but I didn't find details in the documentation on how to use it.

Problem is http response

Hi, I am Kim Jeong Jin.
I have a ask you about problem.
When I get a http response, I use unrolled render HTML api.

I make html template under code.

out += `<ul class="jqueryFileTree" style="display: none;">`
files, _ := ioutil.ReadDir(dir)
for _, f := range files {
		if false == noHidden || f.Name()[0] != '.' {
			p := path.Join(dir, f.Name())
			if true == f.IsDir() {
				out += fmt.Sprintf(`<li class="directory collapsed"><a href="#" rel="%s">%s</a></li>`, p+"/", f.Name())
			} else {
				out += fmt.Sprintf(`<li class="file ext_%s"><a href="#" rel="%s">%s</a></li>`, path.Ext(f.Name())[1:], p, f.Name())
			}
		}
	}
out += `</ul>`

And I call a "func (r *Render) HTML(w io.Writer, status int, name string, binding interface{}, htmlOpt ...HTMLOptions) error"

But html tag changed from "<" to " & lt ; "

How do I set binding parameter for text html tag?

How best to use render in negroni middleware?

First off, thanks for sharing the code, it's a really helpful module.

We're using negroni and implementing a couple of our own handlers, primarily for authentication. If the authentication call fails, we want to return an error in JSON as well as the status code. Any advice on the most idiomatic / elegant way to achieve this?

My first thought was to pass the render.Render to my custom middleware when I instantiate it. That is working, but I'm not sure if it's the best approach.

Echo integration example error

The Echo integration example, copied and pasted as is, gives the following error at run:

cannot use c.Response (type func() *echo.Response) as type http.ResponseWriter in argument to     r.JSON:
    func() *echo.Response does not implement http.ResponseWriter (missing Header method)

(using echo and render updated/downloaded as of now.)

fasthttp support?

Would you like to plan support for fasthttp? Goji (I hear they will switch to fasthttp), echo v2 and Iris are based on fasthttp.

How can I tell which templates exist in a render object?

Prior to using unrolled/render, I had some code like this:

if templates.Lookup(templateName + ".html") == nil {
    templateName = "index"
}

To check whether a particular template existed, and if not to fall back to the "index" template.

As the template.Template object is not exposed through the Render object, I don't see any way to accomplish the same thing. Is there a way I'm not seeing, or can this be added?

Support for {{template "named"}} / {{define "named"}}

Is it possible to extend Render to allow the use of the Go template {{template "named"}} / {{define "named"}} syntax? It does somewhat work, but only in the single file scenario. Since all of the template files are compiled into one template.Template Go throws a redefinition error if you try to define a template more than once. This issue was brought up in martini-contrib/render here, but defers to the yield function which accomplishes the goal but only for a single block.

I would like to be able to add placeholders in my layout for things like scripts, styles, and even the title to later define in my view. I understand one possibility is to append the HTML into the context object or utilize a helper function, but I don't want to have HTML in my Go code.

I have been experimenting with potential fixes, and have found that it can be accomplished by changing the templates property from a *template.Template to a map[string]*template.Template, which then gets populated by compileTemplates by first creating a template.Template with the layout, then cloning it for each view in the directory. When accessing the template, it is retrieved from the map using its name and passed to the engine. I am not yet sure how this approach impacts performance. One flaw with this approach is layout overriding. Since the layout was not specified when compileTemplates was called, there is no combination containing the view and the override layout. This could be overcome by adding an on-the-fly compiling step for overrides, but this would result in higher potential for errors mid-runtime rather than at startup.

If there is an approach that others are taking to overcome this I would love to discuss it.

Render to mailer?

I'm interest in rendering to a mailer. AFAIK I can't easily do this because it is setup to write to http.ResponseWriter directly. Any ideas for getting this to work with a mailer?

cache the executed html

is there an option to to allow to cache the executed html(not the parsed template) ?
because it's slow when template.execute() on a big binding(map).

Asset and AssetNames render.Options fields

package main

import . "fmt"
import "io"

import "github.com/labstack/echo"
import "github.com/gobuffalo/packr"
import "github.com/unrolled/render"

var box packr.Box

type RenderWrapper struct { // We need to wrap the renderer because we need a different signature for echo.
	rnd *render.Render
}

func NewRender(ro render.Options) *RenderWrapper {
	return &RenderWrapper{render.New(ro)}
}

func (r *RenderWrapper) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
	return r.rnd.HTML(w, 0, name, data) // The zero status code is overwritten by echo.
}

var ro render.Options = render.Options{
	Asset: func(name string) ([]byte, error) {
		Println("A")
		return box.MustBytes(Sprintf("%s.tmpl", name))
	},
	AssetNames: func() []string {
		return box.List()
	},
}

func main() {
	box = packr.NewBox("./html")
	r := NewRender(ro)
	e := echo.New()

	e.Renderer = r

	e.GET("/", func(c echo.Context) error {
		return c.Render(200, "main", nil)
	})

	Println(e.Start(":1323"))
}

Won't work: html/template: "main" is undefined.
But box.MustBytes("main.tmpl") returns bytes from file. No additional docs found (or i can't). What i doing wrong?

Render to a Buffer Pool

Firstly: excuse any issue spam and (hopefully) any following PRs. I'm digging around your library—which I've been aware of for a while and have liked quite a bit—in order to finally get a side project finished instead of getting caught writing too much of my own junk!

Anyway:

We changed over to a buffer pool on the martini-contrib/render library to which you're a contributor and this approach is what I've been using for a while in other internal projects.

Implementation approach:

  • Had first considered adding a *bpool.BufferPool as a private field to the Render type, but the Engine interface prevents us from adding another argument to the Render(http.ResponseWriter, interface{}) error method (without breaking the API). That method on the HTML type has a fixed buffer we can't get to with this constraint.
  • Workaround: Create a package-level global var bufPool *bpool.BufferPool and assign a bpool.NewBufferPool(64) to it in func New(options ...Options) *Render.
  • Replace any bytes.Buffer initialisations with a buf := bufPool.Get() and an associated bufPool.Put() once done. We avoid defer bufPool.Put() since defer has a slight performance hit that'd be nice to avoid.

Let me know if this looks good and I'll submit a PR.

Response Streams

Is there a way to use r.JSON with a JSON Encoder to make use of streams? I read that usual marshaling is memory hungry on huge responses.

Nevertheless VERY clean and useful package! Keep it up!

Loaded assets from go-bindata are empty

Hello

I'm stuck with an issue regarding go-bindata and unrolled/render. I uploaded a sample code for reproduction: https://github.com/hachi8833/myapp

I added a route for assets as suggested in #44, and looked fine at first. But actually the loaded assets (css, js) from go-bindata binary are all empty (except template) while HTTP status are successful with 200.

I'm wondering if I misunderstand or overlook something and I'd be glad if you point out what is wrong with my code.

Best regards,

Unable to load assets via layout.tmpl from bindata

Hello, I'm stuck with an issue regarding the bindata.

I create a simplified project myapp for reproducing the issue.

Directory:

main.go
bindata.go
02_dist
├── scripts
│   └── main.8bd37191.js
├── styles
│   └── main.17e92ed5.css
└── template
│ └── index.tmpl
│ └── layout.tmpl

main.go:

package main

import (
    "flag"
    "net/http"

    ur "github.com/unrolled/render"
    "github.com/zenazn/goji"
)

//go:generate go-bindata 02_dist/...

type context struct {
    Title  string
    Result string
}

func main() {
    flag.Set("bind", ":3981")
    goji.DefaultMux.Get("/", index)
    goji.Serve()
}

func index(w http.ResponseWriter, r *http.Request) {
    ctx := context{
        Title:  "This is a title",
        Result: "This is a result",
    }

    re := setLayout()
    re.HTML(w, http.StatusOK, "index", ctx)
}

func setLayout() *ur.Render {
    return ur.New(ur.Options{
        Asset:      Asset,
        AssetNames: AssetNames,
        Directory:  "02_dist/template",
        Layout:     "layout",
    })
}

layout.tmpl:

<!DOCTYPE html>
<html lang='ja'>
  <head>
    <link rel="stylesheet" type="text/css" href="styles/main.17e92ed5.css">
    <title>{{ .Title }}</title>
  </head>
  <body>
    {{ yield }}
  </body>
  <script src="scripts/main.8bd37191.js"></script>
</html>

index.tmpl:

<div>{{ .Result }}</div>

(skipped css and js)

Run go run main.go bindata.go and accessing assets. All assets such as css, js, images or any other static files are unaccessible.

2015/11/29 17:58:51.119002 [MacBook-Pro.local/ZwzIfgQQvp-000002] Started GET "/styles/main.17e92ed5.css" from [::1]:64159
2015/11/29 17:58:51.119044 [MacBook-Pro.local/ZwzIfgQQvp-000002] Returning 404 in 13.154µs
2015/11/29 17:58:53.552403 [MacBook-Pro.local/ZwzIfgQQvp-000003] Started GET "/scripts/main.8bd37191.js" from [::1]:64159
2015/11/29 17:58:53.552437 [MacBook-Pro.local/ZwzIfgQQvp-000003] Returning 404 in 10.008µs

Please note that I'd like to convert all assets, including template files, into bindata.go.
Any other features work fine, except referring assets within bindata.go from the template.

Perhaps I might misunderstand or overlook something.
Could you please let me know how to resolve the references in bindata.go file?

Best regards,

.html files are not part of the default extensions in prepareOptions(), but is shown as defaults in the README

Hi, cool project!

I just started reading about go and came across this.

When trying it out I couldn't get it to work with files with the .html extension, as the README sort of says the default is.

Looking at the code here https://github.com/unrolled/render/blob/master/render.go#L117 I see that it is in fact not part of the default.

It would be a very quick fix but I figured maybe there are more options like that that would need changing.

Looking forward to using this more, thanks again 👍

Question: how to access partial name

Is there a way to reference the partial name similar to {{ current }}?

Related: can I reuse the same partial while changing a piece of it each time I use it? That's why I wanna reference the name of the partial.

In case what I'm asking isn't clear, or I'm heading in the wrong direction, this is my complete scenario:

I have a set of radio buttons for Yes/No/Maybe that look like this:

{{ define "nofinding-dashboard" }}
<div class="col">
    <div class="form-check form-check-inline">
        <input class="form-check-input" type="radio" name="nofinding" id="nofindingRadioY" value="Y">
        <label class="form-check-label" for="nofindingRadioY">Yes</label>
    </div>
    <div class="form-check form-check-inline">
        <input class="form-check-input" type="radio" name="nofinding" id="nofindingRadioN" value="N">
        <label class="form-check-label" for="nofindingRadioN">No</label>
    </div>
    <div class="form-check form-check-inline">
        <input class="form-check-input" type="radio" name="nofinding" id="nofindingRadioM" value="M" checked>
        <label class="form-check-label" for="nofindingRadioM">Maybe</label>
    </div>
</div>
{{ end }}

This pattern repeats, with another section looking like this:

{{ define "cardiomegaly-dashboard" }}
<div class="col">
    <div class="form-check form-check-inline">
        <input class="form-check-input" type="radio" name="cardiomegaly" id="cardiomegalyRadioY" value="Y">
        <label class="form-check-label" for="cardiomegalyRadioY">Yes</label>
    </div>
    <div class="form-check form-check-inline">
        <input class="form-check-input" type="radio" name="cardiomegaly" id="cardiomegalyRadioN" value="N">
        <label class="form-check-label" for="cardiomegalyRadioN">No</label>
    </div>
    <div class="form-check form-check-inline">
        <input class="form-check-input" type="radio" name="cardiomegaly" id="cardiomegalyRadioM" value="M" checked>
        <label class="form-check-label" for="cardiomegalyRadioM">Maybe</label>
    </div>
</div>
{{ end }}

The only difference is I've changed nofinding to cardiomegaly in the radio buttons. I have 15 Yes/No/Maybe radio buttons like that. There's a lot of repetition and if I want to change this layout I'll have to change all 15 partials which is very error prone.

My idea is to build only one partial and change the names/ids of the radio buttons using something like {{ current }}. Is this possible? Is this even a good idea? I'd appreciate some feedback.

How can I generate JSON from a template

I want to generate JSON from a template but I can't see how this is done. Do I need to read i the template file first and then return output? The HTML method seems easy why would the JSON be any different?

rd.JSON(w, http.StatusOK, "test")

Go 1.6 blocks conflict

It seems that the 1.6 release of go will have a block keyword. Are there plans to update render to work with the next version?

panic: runtime error: invalid memory address or nil pointer dereference

I bet I'm doing something wrong being a noob and all but it seems like it should work:

:~/dev/GO/autocompeter (integration-test +%)$ go test -v
=== RUN TestHandleIndexReturnsWithStatusOK
--- FAIL: TestHandleIndexReturnsWithStatusOK (0.00s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
    panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0xc8 pc=0xf2fba]

goroutine 5 [running]:
testing.func·006()
    /opt/boxen/homebrew/Cellar/go/1.4.1/libexec/src/testing/testing.go:441 +0x181
github.com/unrolled/render.(*Render).HTML(0x0, 0x823440, 0xc20800a0c0, 0xc8, 0x420370, 0x5, 0x0, 0x0, 0x0, 0x0, ...)
    /Users/peterbe/dev/GO/src/github.com/unrolled/render/render.go:249 +0x2a
_/Users/peterbe/dev/GO/autocompeter.IndexHandler(0x823440, 0xc20800a0c0, 0xc20801e5b0)
    /Users/peterbe/dev/GO/autocompeter/main.go:80 +0x8a
_/Users/peterbe/dev/GO/autocompeter.TestHandleIndexReturnsWithStatusOK(0xc20806a090)
    /Users/peterbe/dev/GO/autocompeter/main_test.go:13 +0x175
testing.tRunner(0xc20806a090, 0x752690)
    /opt/boxen/homebrew/Cellar/go/1.4.1/libexec/src/testing/testing.go:447 +0xbf
created by testing.RunTests
    /opt/boxen/homebrew/Cellar/go/1.4.1/libexec/src/testing/testing.go:555 +0xa8b

goroutine 1 [chan receive]:
testing.RunTests(0x5197e8, 0x752690, 0x1, 0x1, 0x75d301)
    /opt/boxen/homebrew/Cellar/go/1.4.1/libexec/src/testing/testing.go:556 +0xad6
testing.(*M).Run(0xc20802a0f0, 0x764780)
    /opt/boxen/homebrew/Cellar/go/1.4.1/libexec/src/testing/testing.go:485 +0x6c
main.main()
    _/Users/peterbe/dev/GO/autocompeter/_test/_testmain.go:52 +0x1d5
exit status 2
FAIL    _/Users/peterbe/dev/GO/autocompeter 0.021s

The test is extremely simple so far:

package main

import (
    "net/http"
    "net/http/httptest"
    "testing"
)

func TestHandleIndexReturnsWithStatusOK(t *testing.T) {
    request, _ := http.NewRequest("GET", "/", nil)
    response := httptest.NewRecorder()

    IndexHandler(response, request)

    if response.Code != http.StatusOK {
        t.Fatalf("Non-expected status code%v:\n\tbody: %v", "200", response.Code)
    }
}

And in main.go there's a bunch of other stuff but the things that matter should be:

package main
import "github.com/unrolled/render"

func IndexHandler(w http.ResponseWriter, req *http.Request) {
    // this assumes there's a `templates/index.tmpl` file
    renderer.HTML(w, http.StatusOK, "index", nil)
}

var (
    renderer   *render.Render
    debug      = true
)

func main() {
        ...
    renderer = render.New(render.Options{
        IndentJSON:    debug,
        IsDevelopment: debug,
    })
        ...
        mux := mux.NewRouter()
    mux.HandleFunc("/", IndexHandler).Methods("GET", "HEAD")

    n := negroni.Classic()
    n.UseHandler(mux)
    n.Run(fmt.Sprintf(":%d", port))

}

Perhaps that's now how you're supposed to do testing of http handlers.

error calling partial: html/template: "css-home/home" is undefined

When I use template with sub folder, I found follow error in partial rendering.
"error calling partial: html/template: "css-home/home" is undefined"

My template folder structure is

/views/layout/layout.tmpl
/views/home/home.tmpl

Sample Code!

###Layout
<html>
  <head>
    <title>My Layout</title>
    <!-- Render the partial template called `css-$current_template` here -->
    {{ partial "css" }}
  </head>
  <body>
    <!-- render the partial template called `header-$current_template` here -->
    {{ partial "header" }}
    This is the {{ current }} page.
    <!-- Render the current template here -->
    {{ yield }}
    <!-- render the partial template called `footer-$current_template` here -->
    {{ partial "footer" }}
  </body>
</html>


### Template

{{ define "css-home" }}
<h1>Home</h1>
{{ end }}

{{ define "header-home" }}
<h1>Home</h1>
{{ end }}

<h1>Hello {{.}}.</h1>

{{ define "footer-home"}}
<p>The E qnd</p>
{{ end }}


### Controller
r = render.New(render.Options{
        Directory: "app/views", // Specify what path to load the templates from.
        Layout: "layout/layout", // Specify a layout template. Layouts can call {{ yield }} to render the       current template or {{ partial "css" }} to render a partial from the current template.
        Extensions: []string{".tmpl", ".html"}, // Specify extensions to load for templates.
        Charset: "UTF-8", // Sets encoding for json and html content-types. Default is "UTF-8".
        UnEscapeHTML: true, // Replace ensure '&<>' are output correctly (JSON only).
        RequirePartials: true, // Return an error if a template is missing a partial used in a layout.
    })

r.HTML(res, http.StatusOK, "home/home", "World")

StreamingJSON does nothing / information in README is false

The README states the following:

By default, Render does not stream JSON to the http.ResponseWriter. It instead marshalls your object into a byte array, and if no errors occurred, writes that byte array to the http.ResponseWriter. This is ideal as you can catch errors before sending any data.

If however you have the need to stream your JSON response (ie: dealing with massive objects), you can set the StreamingJSON option to true. This will use the json.Encoder to stream the output to the http.ResponseWriter. If an error occurs, you will receive the error in your code, but the response will have already been sent. Also note that streaming is only implemented in render.JSON and not render.JSONP, and the UnEscapeHTML and Indent options are ignored when streaming.

However, encoding/json already buffers the complete output internally to catch errors, so this information is false.

I still think there are some benefits to the current approach (eg UnEscapeHTML and Indent) but I'd say that at the very least, the README should be updated to properly reflect the stdlib's behavior.

Here's some code to confirm:

package main

import (
	"encoding/json"
	"log"
	"net/http"
)

func main() {
	http.HandleFunc("/", forcedErrorHandler)
	http.ListenAndServe(":3000", nil)
}

func forcedErrorHandler(w http.ResponseWriter, r *http.Request) {
	// attempting to encode a channel will fail.
	if err := json.NewEncoder(w).Encode(make(chan int)); err != nil {
		log.Printf("Errored: %v", err)

		// json.NewEncoder hasn't written anything to the responsewriter at this point.
		// we have full control over the writer here.
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte("Error: " + err.Error()))
	}
}

Cheers!

Ask about Renderer.Text()

Hi, My name is Kim Jeong Jin.

I coded "render.Renderer.Text(h, http.StatusNoContent, "")", and compile completely.

But I didn't HTTP response from the HTTP request.

I changed the HTTP response code, and try to test, for example, "render.Renderer.Text(h, http.StatusOK, "")"
I got the HTTP response.

Why it doesn't reply to the client when the HTTP response code is set in http.StatusNoContent.

Please give me an answer, Thank you~

Not entirely great developer experience for JSONP

Currently handling JSONP with the following with negroni

func PreJSONP(rw http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
  vars := req.URL.Query()
  callback := vars["callback"]

  if callback != nil {
    SaveRenderForLater(render.New(render.Options{
      PrefixJSON: []byte(callback[0] + "("),
    }))
  }

  next(rw, req)
}

func PostJSONP(rw http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
  vars := req.URL.Query()
  callback := vars["callback"]

  if callback != nil {
    rw.Write([]byte(");"))
  }

  next(rw, req)
}

func main() {
    n := negroni.Classic()
    n.Use(negroni.HandlerFunc(PreJSONP))
    n.UseHandler(<router from somewhere>)
    n.Use(negroni.HandlerFunc(PostJSONP))
}

In addition to this, there's no way to set the content type to application/javascript instead of application/json as this is the more appropriate mime type for JSONP.

Would be awesome if in addition to PrefixJSON there was also PostfixJSON as an option. Would remove the need for the second middleware to handle jsonp. Alternatively, maybe something like accepting a callback before/ after to get the PreJSON would also be helpful so I wouldn't have to make a new Render/ Engine for every web request?

Set custom JSON Content-Type

I am using this together with Mux & Negroni (Go 1.8) and would like to set a custom content-type header when rendering JSON, application/vnd.api+json because I am writing an API complying with the JSON API format. There's an option for setting HTML type as in the README (e.g. HTMLContentType: "application/xhtml+xml"), but none for JSON. How would I go about setting it?

Export parsed templates for further handling.

In my app, I'd like to be able to grab the parsed template contents so that I can return it within a template function. My options now are to either not use unrolled/render (or use the std lib alongside it), or use httptest.NewRecorder() to gather the contents using the currently exported functions. I believe that having access to the parsed templates would offer a superior solution.

Is there a reason for templates to not be exported?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.