Whitespace with Mako

131 views
Skip to first unread message

realcr

unread,
Nov 25, 2014, 11:25:34 AM11/25/14
to mako-d...@googlegroups.com
Hi,
I have an issue with whitespace added by Mako. I was wondering what could be done about it, and if I want to contribute, where should I begin.

Let me show demonstrate the issue.
I have this template:

<%namespace name="conf_general" module="conf.general" inheritable="True"/>
<%namespace name="entries_index" module="content.entries_index"/>
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
...

</channel>
</
rss>

Which is a template for generating RSS feeds.
It turns out that the output is something like this:



<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
...

</channel>
</rss>

Note the whitespace in the head of the document. Usually with HTML it doesn't really matter, but with RSS (And some other XML things) it does matter.
In fact, this RSS is considered to be invalid. It will not work in Firefox, for example.
I wonder if there is a simple solution to this problem.

One workaround I use myself is doing this:

<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<%namespace name="conf_general" module="conf.general" inheritable="True"/>
<%namespace name="entries_index" module="content.entries_index"/>
<channel>
...

</channel>
</
rss>

What do you think?

Regards,
real.

Michael Bayer

unread,
Nov 25, 2014, 11:34:28 AM11/25/14
to mako-d...@googlegroups.com
On Nov 25, 2014, at 11:25 AM, realcr <rea...@gmail.com> wrote:

Hi,
I have an issue with whitespace added by Mako. I was wondering what could be done about it, and if I want to contribute, where should I begin.

Let me show demonstrate the issue.
I have this template:

<%namespace name="conf_general" module="conf.general" inheritable="True"/>
<%namespace name="entries_index" module="content.entries_index"/>
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
...

</channel>
</
rss>

Which is a template for generating RSS feeds.
It turns out that the output is something like this:



<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
...

</channel>
</rss>


Let’s escape out the newlines in your template, so that we have this:

<%namespace name="conf_general" module="conf.general" inheritable="True”/>\n
<%namespace name="entries_index" module="content.entries_index”/>\n

<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
...

</channel>
</
rss>

as you can see, your template parses to this:

<%namespace …><NEWLINE><%namespace …><NEWLINE><?xml …>

the solution is to use backslashes:

<%namespace name="conf_general" module="conf.general" inheritable="True”/>\
<%namespace name="entries_index" module="content.entries_index”/>\
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
...

</channel>
</
rss>

here is a demo:

classics-MacBook-Pro-2:mako classic$ cat test.py 
from mako.template import Template

t = Template("""\
<%namespace name="conf_general" module="conf.general" inheritable="True"/>\
<%namespace name="entries_index" module="content.entries_index"/>\
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
...

</channel>
</rss>""")

print t.render()classics-MacBook-Pro-2:mako classic$ python test.py
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
...

</channel>
</rss>


Note the whitespace in the head of the document. Usually with HTML it doesn't really matter, but with RSS (And some other XML things) it does matter.
In fact, this RSS is considered to be invalid. It will not work in Firefox, for example.
I wonder if there is a simple solution to this problem.

One workaround I use myself is doing this:

<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<%namespace name="conf_general" module="conf.general" inheritable="True"/>
<%namespace name="entries_index" module="content.entries_index"/>
<channel>
...

</channel>
</
rss>

What do you think?

Regards,
real.

--
You received this message because you are subscribed to the Google Groups "Mako Templates for Python" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mako-discuss...@googlegroups.com.
To post to this group, send email to mako-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/mako-discuss.
For more options, visit https://groups.google.com/d/optout.

Michael Bayer

unread,
Nov 25, 2014, 11:38:03 AM11/25/14
to mako-d...@googlegroups.com

On Nov 25, 2014, at 11:34 AM, Michael Bayer <mik...@zzzcomputing.com> wrote:


here is a demo:

classics-MacBook-Pro-2:mako classic$ cat test.py 
from mako.template import Template

t = Template("""\
<%namespace name="conf_general" module="conf.general" inheritable="True"/>\
<%namespace name="entries_index" module="content.entries_index"/>\
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
...

</channel>
</rss>""")

print t.render()classics-MacBook-Pro-2:mako classic$ python test.py
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
...

</channel>
</rss>



let me correct, that the demo should have an “r” so that those backslashes are in the actual template, as this demo starts from a Python string expression:

$ cat test.py 
from mako.template import Template

t = Template(r"""\

realcr

unread,
Nov 27, 2014, 7:27:52 AM11/27/14
to mako-d...@googlegroups.com
Hi Michael,
Thank you for your response. It does solve my problem. I will use it with my templates.

I have to add some questions about the design though. Please don't take them as some kind of criticism. I use Mako for
a few static websites I own, and it made my life much easier. I just want to understand some choices that were made.

First regarding the whitespaces. I had an idea that every % based tag will automatically remove the new line that comes after it.
Are there cases where this is expected to cause problems?
In the first few times I used Mako I was really surprised to see that there lots of whitespace in my templates. It's like people
get some kind of metadata about how much code was inside my template originally when they view the source in the browser.

Second, about the backslash. I find it very reasonable that the backslash will escape new lines inside <% > constructs.
I even find it more reasonable that the backslash will escape new lines inside python code (This is the way python works).
However it always surprises me that the backslash works outside of those constructs too. It happened to me more than once that I had to use
the <%text> tag to be able to show some example code (In python for example). I find it unexpected that Mako's engine interferes with content
that I put outside of Mako blocks and tags. Are there any special use cases for this behaviour, besides dealing with
the whitespaces problem?

Here is an example from a static website engine I wrote. I have to admit that it uses Mako in a bit of twisted way,
but maybe it still serves my point. It shows an example blog post, where I want to present some bash code,
but I have to wrap it inside <%text>:
https://github.com/xorpd/static_weber/blob/master/content/blog/vim_python3_install.mako


Thanks. I really appreciate that time you take to answer our questions here.

Regards,
real.







Michael Bayer

unread,
Nov 28, 2014, 4:28:30 PM11/28/14
to mako-d...@googlegroups.com
On Nov 27, 2014, at 7:27 AM, realcr <rea...@gmail.com> wrote:

Hi Michael,
Thank you for your response. It does solve my problem. I will use it with my templates.

I have to add some questions about the design though. Please don't take them as some kind of criticism. I use Mako for
a few static websites I own, and it made my life much easier. I just want to understand some choices that were made.

note that Mako has been around a long time, doesn’t have many releases nowadays and is buried deep within a lot of applications and libraries, not really being noticed and doing the identical thing it did when it was first released :).  At this point most of the design choices that would change fundamental behavior are pretty much “baked”.  



First regarding the whitespaces. I had an idea that every % based tag will automatically remove the new line that comes after it.

That might have been a good idea.   Then again it would be an exception to the otherwise consistent rule that all literal text in a template is rendered as is.    It’s hard to say, but when building Mako I tried as much as possible to go for “explicit is better than implicit”.    

However, note there’s more than one way to actually cause this behavior to occur; one is using a preprocessor (docs.makotemplates.org/en/latest/usage.html#mako.template.Template.params.preprocessor) to remove newlines as needed (or add backslashes) and the other is to apply a string filter to the output of template.render() that does what you need.  In the case where very regular HTML formatting is desirable, an HTML rewriter can be an easy way to get at this if the performance penalty is acceptable, or if caching is used.

Are there cases where this is expected to cause problems?

sure, suppose two defs “somecontent” and “someothercontent” both render some HTML, with some <divs> or whatever.   If a template like this expects a newline between the content rendered by each of:

<%self:somecontent /%>
<%self:someothercontent /%>

then that newline suddenly vanishing would almost certainly be something I’d be hearing about.


In the first few times I used Mako I was really surprised to see that there lots of whitespace in my templates.

Sure, it depends on how you look upon the “\n” characters that are in your template :).   As Mako is oriented towards HTML, whitespace in HTML templates is not something people normally worry about.  You will see the same thing in almost any template language, PHP, whatever.   Look at the HTML source of many major websites, more often than not you’ll see all kinds of weird whitespace patterns due to their templating / includes / etc.

It's like people
get some kind of metadata about how much code was inside my template originally when they view the source in the browser.

While I’m familiar with people who want their HTML output to look very nicely formatted, I’ve been building server-dynamic websites professionally since 1996 and have never heard of this being a concern.



Second, about the backslash. I find it very reasonable that the backslash will escape new lines inside <% > constructs.
I even find it more reasonable that the backslash will escape new lines inside python code (This is the way python works).
However it always surprises me that the backslash works outside of those constructs too.

This is a convention taken from Mako’s original predecessor HTML::Mason: http://search.cpan.org/~drolsky/HTML-Mason-1.56/lib/HTML/Mason/Devel.pod#Backslash_at_end_of_line.    A lot of Mako’s syntaxes come, directly or indirectly, from this venerable old language.   I’ve used it for years and find it very familiar.

It happened to me more than once that I had to use
the <%text> tag to be able to show some example code (In python for example). I find it unexpected that Mako's engine interferes with content
that I put outside of Mako blocks and tags.

The “##” and the “\” symbols are part of those symbols which Mako deems as syntactically significant.   All template languages of any complexity have such characters.  If you want templating that goes through effort to be very harmonious with HTML’s natural flow and a minimum of syntaxes, I’d suggest a push style system; here’s an article http://www.perlmonks.org/?node_id=674225 which even though it’s on a Perl site, explicitly calls out Mako and HTML::Mason as *not* being “push style” and sprinkling a good amount of FUD regarding the evils of not being push style, while I think this argument is bullshit (http://techspot.zzzeek.org/2010/12/04/in-response-to-stupid-template-languages/), it’s true that Mako et al’s style of templating is definitely more old school; in the more modern area I am a big fan of Mustache http://mustache.github.io/ as mentioned on that page; as web applications need to produce all of their data in JSON format in any case now due to the necessity of providing a service model, push style templates go nicely as a means to ensure you really have a very rich API, since your own site now depends on it.


Are there any special use cases for this behaviour, besides dealing with
the whitespaces problem?

the use case for the backslash is that of suppressing newline output, im not sure what other use you’d be referring to.


Here is an example from a static website engine I wrote. I have to admit that it uses Mako in a bit of twisted way,
but maybe it still serves my point. It shows an example blog post, where I want to present some bash code,
but I have to wrap it inside <%text>:
https://github.com/xorpd/static_weber/blob/master/content/blog/vim_python3_install.mako

the reason this template is giving you problems is because you’re attempting to use Mako as a markup language for content.  This isn’t really what template languages are used for, you should instead use a system like Markdown or ReStructuredText.   The template language is meant to tie together dynamic elements into a presentational system and as such the content elements, which tend to be much more freeform, would be coming from somewhere else.  

realcr

unread,
Dec 1, 2014, 12:05:33 PM12/1/14
to mako-d...@googlegroups.com
Hey,
I'm glad I sent that email. I learned a lot from your answer.
Thanks :)

real.
Reply all
Reply to author
Forward
0 new messages