Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extra line feeds #2

Open
SmithSamuelM opened this issue Jun 28, 2013 · 7 comments
Open

Extra line feeds #2

SmithSamuelM opened this issue Jun 28, 2013 · 7 comments

Comments

@SmithSamuelM
Copy link

the following template fragment renders differently in Stache than in others such as pystache, mustache

{{#scripts}}
    <script src="{{name}}"></script>
{{/scripts}}

In pystache each script element is on a separate line
in Stache there is an extra line feed between each script element line

@SmithSamuelM
Copy link
Author

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}}

@SmithSamuelM
Copy link
Author

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>

@SmithSamuelM
Copy link
Author

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>

@SmithSamuelM
Copy link
Author

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

@clach04
Copy link

clach04 commented Feb 12, 2022

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>

@clach04
Copy link

clach04 commented Feb 12, 2022

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>

@clach04
Copy link

clach04 commented Feb 12, 2022

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()

clach04 added a commit to clach04/Stache_fork that referenced this issue Feb 12, 2022
Extracted code from
SmithSamuelM@f2c591e

NOTE this no longer passes test suite as test suite is white space
sensitive, the test suite has not been updated. The test suite stops
on failure, more testing needed.
clach04 added a commit to clach04/Stache_fork that referenced this issue Feb 19, 2022
Working test suite to match previous test, adds a new test for
with and without white space.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants