funkybob / stencil

A minimalist template engine for Python3
MIT License
58 stars 8 forks source link

Make {% if %} tag able to perform comparisons #20

Open funkybob opened 5 years ago

funkybob commented 5 years ago

Currently {% if %} can only do "if " or "if not "

It would obviously be far more powerful to be able to express other comparisons, against full expressions.

funkybob commented 5 years ago

I've a branch, now, that uses python's built in expression parsing to handle all expressions.

This makes ALL tags far more flexible. However, it presents a large stumbling block: the handling of {% include %}

Currently since we control the parsing of tokens, we can parse a single expression from the token stream, then parse a series of name=expre sequences.

I can't yet see a way to provide this same functionality without recreating the full expression parsing abilities of Python anyway.

Alysha-94 commented 5 years ago

Hey is there a workaround for this? I'm using stencil with Gilbert and trying to display certain team cards if they match the author/s of a post

For example I have a BlogPost and TeamMember class in plugins.py:

class BlogPost(Templated, Content):
    authors: list
    template: str = "blog/post_detail.html"

class TeamMember(Templated, Content):
    name: str
    template: str="team/team_detail.html"

Then in the post_detail template I pass each author of the post with all the team members to team_list template:

{% for author in this.authors %}
{% include "team/team_list.html" author=author, members=site.content["team.yaml"].pages %}
{% endfor %}

Now in team_list I want to display the team information only if the member.name matches the author:

{% for member in members %}
{% if member.name == author %}
<div>display team member details</div>
{% endfor %}
funkybob commented 5 years ago

A dirty hack might be to use {% if author.__contains__(member.name) %}.

>>> from stencil import Template
>>> t = Template("""{% if authors.__contains__(user) %}Woo{% endif %}""")
>>> t.render({"authors": ['one', 'two', 'four'], "user": "foo"})
''
>>> t.render({"authors": ['one', 'two', 'four'], "user": "one"})
'Woo'
Alysha-94 commented 5 years ago

A dirty hack might be to use {% if author.__contains__(member.name) %}.

Ah clever I think that will be fine to use, thanks for providing an example