stencilproject / Stencil

Stencil is a simple and powerful template language for Swift.
https://stencil.fuller.li
BSD 2-Clause "Simplified" License
2.34k stars 223 forks source link

String equality/inequality comparisons not working #159

Closed rlaguilar closed 6 years ago

rlaguilar commented 6 years ago

Hi there, it seems that equality/inequality comparisons aren't working at all. Consider the following code:

struct User {
   let name: String
}

let users = [
   User(name: "a"),
   User(name: "Kyle"),
   User(name: "b")
]

let context = ["users": users]

let templateStr = """
<ul>
{% for user in users where user.name != "Kyle" %}
<li>{{ user.name }}</li>
{% endfor %}
</ul>
"""

let template = Template(templateString: templateStr)
let rendered = try template.render(context)
print(rendered)

Even when the filter indicates that users with name Kyle should be ignored, it outputs:

<ul>
<li>a</li>
<li>Kyle</li>
<li>b</li>
</ul>

Am I missing something here? I'm using version Stencil (0.10.1)

rlaguilar commented 6 years ago

If instead of using the string literal in the comparison I use a variable in the context, then it works as expected. If I make the following changes:

First, in the context definition: let context: [String: Any] = ["users": users, "invalidName": "Kyle"]

and then in the template: {% for user in users where user.name != invalidName %}

The result is the expected one. Is the string literal syntax supported? Note that I take this example from the documentation page for the for tag using the where clause.

ilyapuchka commented 6 years ago

@rlaguilar I tried your example and can not reproduce this issue on master. It gives expected results. Here is my code:

    $0.it("handles literals comparison in for where") {
      struct User {
        let name: String
      }

      let users = [
        User(name: "a"),
        User(name: "Kyle"),
        User(name: "b")
      ]
      let templateStr = "{% for user in users where user.name != \"Kyle\" %}{{ user.name }}{% endfor %}"
      let template = Template(templateString: templateStr)
      let context = Context(dictionary: ["users": users])
      let rendered = try template.render(context)

      try expect(rendered) == "ab"
    }
rlaguilar commented 6 years ago

@ilyapuchka Your code doesn't work for me neither, I can't even use the Context type because it's internal in the Stencil module. Maybe it's due to the fact that I'm installing the library via cocoapods using the latest release of the project (0.10.1), which is from November 17. I'll try to install directly from master to see what happens.

ilyapuchka commented 6 years ago

It's a code from a unit test, you use a dictionary instead of a context. It passes even on top of 0.10.1 release.

rlaguilar commented 6 years ago

@ilyapuchka I just created a sample project in github so that you can see the problem. https://github.com/rlaguilar/stencil-demo

kylef commented 6 years ago

168 should fix this problem (could you please confirm with your case). I'll do a patch release soon, just want to finalise some other changes first.

werediver commented 6 years ago

A temporary workaround for those struggling with the issue right now:

{% if stringVariable|replace:"","" == "string literal" %}whatever{% endif %}