14

I am having a problem controlling whitespace and still formatting html/template templates in a readable fashion. My templates look somthing like this:

layout.tmpl

{{define "layout"}}
<!DOCTYPE html>
<html>
        <head>
                <title>{{.title}}</title>
        </head>
        <body>
                {{ template "body" . }}
        </body>
</html>
{{end}}

body.tmpl

{{define "body"}}
{{ range .items }}
{{.count}} items are made of {{.material}}
{{end}}
{{end}}

code

package main

import (
    "os"
    "text/template"
)

type View struct {
    layout string
    body   string
}

type Smap map[string]string

func (self View) Render(data map[string]interface{}) {
    layout := self.layout + ".tmpl"
    body   := self.body + ".tmpl"
    tmpl   := template.Must(template.New("layout").ParseFiles(layout, body))
    tmpl.ExecuteTemplate(os.Stdout, "layout", data)
}

func main() {
    view := View{ "layout", "body" }
    view.Render(map[string]interface{}{
        "title": "stock",
        "items": []Smap{
            Smap{
                "count":    "2",
                "material": "angora",
            },
            Smap{
                "count":    "3",
                "material": "wool",
            },
        },
    })
}

But that produces (note: there is a line above the doctype):

<!DOCTYPE html>
<html>
    <head>
        <title>stock</title>
    </head>
    <body>


2 items are made of angora

3 items are made of wool


    </body>
</html>

What I want is:

<!DOCTYPE html>
<html>
    <head>
        <title>stock</title>
    </head>
    <body>
2 items are made of angora
3 items are made of wool
    </body>
</html>

In other template languages I can say things like

[[- value -]]

and the whitespace before and after the action are stripped, but I don't see anything like that in html/template. Does this really mean I have to make my templates unreadable like the following?

layout.tmpl

{{define "layout"}}<!DOCTYPE html>
<html>
    <head>
        <title>.title</title>
    </head>
    <body>
{{ template "body" . }} </body>
</html>
{{end}}

body.tmpl

{{define "body"}}{{ range .items }}{{.count}} items are made of {{.material}}
{{end}}{{end}}
Chas. Owens
  • 64,182
  • 22
  • 135
  • 226

3 Answers3

20

You can use white space controller

{{range .foos -}} // eats trailing whitespace
    <tr><td>do something</td></tr>
{{- end}} // eats leading whitespace (\n from previous line)
edi9999
  • 19,701
  • 13
  • 88
  • 127
hkulekci
  • 1,894
  • 15
  • 27
2

Whitespace in this case makes no difference in the rendered output at the user's browser, so controlling it makes little sense above perhaps aesthetics.

Put differently, one can have nicely formatted templates (which I would prefer) or partially nicely formatted HTML (no nested indents). Pick one or post process the HTML using any of the existing formatters.

zzzz
  • 87,403
  • 16
  • 175
  • 139
1

Yes, whitespace and lines are translated literally. If you have a line with just a {{ define }} or anything else that does not produce output, you will have an empty line in the parsed file.

Ideally, because you are using template, you should not need to view or edit the parsed output. For reference, use JSP/JSF and see the ugly output it gives you. View the source of most pages online, they're also ugly.

Good luck!

twmb
  • 1,710
  • 1
  • 20
  • 18