Open SmithSamuelM opened 11 years ago
I think the difference is that other mustache parsers treat a {{# }} strip the trailing linefeed when its on a line by itself so one can nest blocks to make the templates easy to read.
For example this produces what I want
{{#scripts}}<script src="{{name}}"></script>
{{/scripts}}
To be more specific
>>> data = { "scripts": [ {"name": "A"}, {"name": "B"}, {"name": "C"}]}
>>> fp = open("template.html", "ru")
>>> mold = fp.read()
>>> print mold
<html>
<head>
</head>
<body>
{{#scripts}}
<script src="{{name}}"></script>
{{/scripts}}
</body>
</html>
>>> import pystache
>>> renderer = pystache.Renderer()
>>> content = renderer.render(mold,data)
>>> print content
<html>
<head>
</head>
<body>
<script src="A"></script>
<script src="B"></script>
<script src="C"></script>
</body>
</html>
But in Stache
>>> import stache
>>> content = stache.render(mold,data)
>>> print content
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script src="A"></script>
<script src="B"></script>
<script src="C"></script>
</body>
</html>
I also verified this with Mustache python so it would be nice if Stache were consistent with the other implementations. I really like the fact that stache is just one file so I can easily include it as a dependency and I also like the additional features. The {{.}} especially
I keep forgetting to dig into this, I have some notes/workarounds that are Stache specific:
# based on https://github.com/hyperturtle/Stache/issues/2
import stache
data = {"scripts": [ {"name": "A"}, {"name": "B"}, {"name": "C"}]}
template_str1 = """<html>
<head>
</head>
<body>
{{#scripts}}
<script src="{{name}}"></script>
{{/scripts}}
</body>
</html>
"""
template_str2 = """<html>
<head>
</head>
<body>
{{#scripts}}
<script src="{{name}}"></script>{{/scripts}}
</body>
</html>
"""
content = stache.render(template_str1, data)
print(content)
content = stache.render(template_str2, data)
print(content)
Output:
<html>
<head>
</head>
<body>
<script src="A"></script>
<script src="B"></script>
<script src="C"></script>
</body>
</html>
Versus:
<html>
<head>
</head>
<body>
<script src="A"></script>
<script src="B"></script>
<script src="C"></script>
</body>
</html>
https://github.com/SmithSamuelM/staching fork has a fix for this, changing the above test case import to:
import staching as stache
results in:
<html>
<head>
</head>
<body>
<script src="A"></script>
<script src="B"></script>
<script src="C"></script>
</body>
</html>
Versus:
<html>
<head>
</head>
<body>
<script src="A"></script> <script src="B"></script> <script src="C"></script>
</body>
</html>
Fix appears to be:
diff --git a/__init__.py b/__init__.py
index 55ff995..2f92574 100644
--- a/__init__.py
+++ b/__init__.py
@@ -239,6 +239,61 @@ class Stache(object):
delim_tag = delim_tag.split(' ', 1) if delim_tag else None
delim_tag = delim_tag if delim_tag and len(delim_tag) == 2 else None
+ # fix for https://github.com/hyperturtle/Stache/issues/2 from https://github.com/SmithSamuelM/staching/commit/f2c591ec69cc922c6ffec67e0d66f8047f2f2bf3
+ if ( open_tag or invert_tag or comment_tag or
+ partial_tag or push_tag or bool_tag or
+ booltern_tag or unescape_tag or delim_tag): # not a variable
+ inline = False
+ if rest: # strip trailing whitespace and linefeed if present
+ front, sep, back = rest.partition("\n") # partition at linefeed
+ if sep:
+ if not front.strip(): # only whitespace before linefeed
+ rest = back # removed whitespace and linefeed
+ #if _debug: print( "open rest strip front: \n%s" % rest)
+ else: #inline
+ inline = True
+ #if _debug: print( "open inline:")
+ if not inline and pre: #strip trailing whitespace after linefeed if present
+ front, sep, back = pre.rpartition("\n")
+ if sep:
+ if not back.strip(): # only whitespace after linefeed
+ pre = ''.join((front, sep)) # restore linefeed
+ #if _debug: print( "open pre strip back: \n%s" % pre)
+ else:
+ pre = back.rstrip() #no linefeed so rstrip
+ #if _debug: print( "open pre rstrip back: \n%s" % pre)
+
+ elif close_tag:
+ inline = True # section is inline
+ follow = False # followed by inline
+ post = ''
+
+ if rest: # see if inline follows
+ front, sep, back = rest.partition("\n")
+ if front.strip(): # not empty before linefeed so inline follows
+ follow = True # inline follows
+ #if _debug: print( "close follow:")
+
+ if pre: #strip trailing whitespace after prev linefeed if present
+ front, sep, back = pre.rpartition("\n")
+ if sep and not back.strip(): # only whitespace after linefeed
+ inline = False
+ #if _debug: print() "close not inline:" )
+ if follow:
+ post = back # save spacing for following inline
+ pre = ''.join((front, sep)) # restore upto linefeed
+ #if _debug: print( "close pre strip back: \n%s" % pre)
+
+ if not inline and rest: # strip trailing whitespace and linefeed if present
+ if follow: # restore saved spacing
+ rest = post + rest
+ #print( "close follow rest: \n%s" % rest)
+ front, sep, back = rest.partition("\n") # partition at linefeed
+ if sep:
+ if not front.strip(): # only whitespace before linefeed
+ rest = back # remove trailing whitespace and linefeed
+ #if _debug: print( "close rest strip front: \n%s" % rest)
+
if push_tag:
pre = pre.rstrip()
rest = rest.lstrip()
the following template fragment renders differently in Stache than in others such as pystache, mustache
In pystache each script element is on a separate line in Stache there is an extra line feed between each script element line