-
-
Notifications
You must be signed in to change notification settings - Fork 263
Description
Problem Description
LiquidJS currently does not support using value expressions (filter operations) directly as operands in conditional statements (if, elsif, unless) or in loop tags (for). This limitation requires developers to use workarounds that make templates less readable and more verbose.
Current Limitation
The following syntax is NOT supported:
{% if (strValue | size) > 10 %}
<a href="{{person | prepend: "https://example.com/"}}">
{{ person | capitalize }}
</a>
{% endif %}This results in a syntax error or unexpected behavior because the value expression (strValue | size) cannot be used directly as an operand in the conditional statement.
Additional Examples of Unsupported Syntax
Example 1: String Length Validation in Conditionals
{% if (username | size) >= 3 %}
Username is valid
{% elsif (username | size) == 0 %}
Username is required
{% else %}
Username is too short
{% endif %}Example 2: Array Size comparison
{% if (firstArray | size) == (secondArray | size) %}
No items found
{% else %}
Found {{ firstArray | size }} in firstArray and {{ secondArray | size }} in secondArray
{% endif %}Example 3: String Transformation in Conditions
{% if (email | downcase) contains "@example.com" %}
Internal user detected
{% endif %}Example 4: Numeric Calculations
{% if (price | times: 0.9) < 100 %}
Discounted price is under $100
{% endif %}Example 5: Chained Filters in Conditions
{% if (description | strip_html | size) > 50 %}
Long description detected
{% endif %}Example 6: For Loop with Filtered Range
{# Loop through first N items #}
{% for i in (1..items | size) %}
Item {{ i }}
{% endfor %}Example 7: Unless with Filter Expression
{% unless (content | strip_html | size) > 0 %}
No content available
{% endunless %}Example 8: Case Statement with Filtered Value
{% case (status | downcase) %}
{% when "active" %}
Active status
{% when "pending" %}
Pending status
{% endcase %}Example 9: Complex Logical Expression
{% if (name | size) > 0 and (email | downcase) contains "@" %}
Valid user entry
{% endif %}Example 10: Nested Filter in Loop Limit
{% for item in items limit: (maxItems | default: 10) %}
{{ item }}
{% endfor %}Current Workaround
To work around this limitation, you must assign the filtered value to a variable first:
{% assign strValueSize = strValue | size %}
{% if strValueSize > 10 %}
<a href="{{person | prepend: "https://example.com/"}}">
{{ person | capitalize }}
</a>
{% endif %}More Workaround Examples
{# Example 1: String Length Validation #}
{% assign usernameLength = username | size %}
{% if usernameLength >= 3 %}
Username is valid
{% elsif usernameLength == 0 %}
Username is required
{% else %}
Username is too short
{% endif %}
{# Example 2: Array Size Check #}
{% assign itemCount = items | size %}
{% if itemCount == 0 %}
No items found
{% else %}
Found {{ itemCount }} items
{% endif %}
{# Example 3: String Transformation #}
{% assign emailLower = email | downcase %}
{% if emailLower contains "@example.com" %}
Internal user detected
{% endif %}
{# Example 4: Numeric Calculations #}
{% assign discountedPrice = price | times: 0.9 %}
{% if discountedPrice < 100 %}
Discounted price is under $100
{% endif %}
{# Example 5: Chained Filters #}
{% assign cleanDescription = description | strip_html %}
{% assign descriptionLength = cleanDescription | size %}
{% if descriptionLength > 50 %}
Long description detected
{% endif %}
{# Example 6: For Loop with Filtered Range #}
{% assign itemCount = items | size %}
{% for i in (1..itemCount) %}
Item {{ i }}
{% endfor %}
{# Example 7: Complex Logical Expression #}
{% assign nameLength = name | size %}
{% assign emailLower = email | downcase %}
{% if nameLength > 0 and emailLower contains "@" %}
Valid user entry
{% endif %}Why This Matters
While the workaround functions correctly, it has several significant drawbacks:
- Reduced Readability: The intent is less clear when logic is split across multiple statements
- Increased Verbosity: More lines of code for simple operations
- Variable Pollution: Creates intermediate variables that clutter the template scope and may conflict with other variables
- Maintenance Burden: More code to maintain and understand, especially for complex expressions
- Cognitive Load: Developers must mentally track intermediate variables and their purpose
- Inconsistency: Filters work inline in output expressions
{{ }}but not in logic expressions{% %}
Desired Behavior
Ideally, LiquidJS should support inline value expressions (filter operations) within logical operations and loop tags, similar to how they work in output statements:
{% if (strValue | size) > 10 %}
{# Direct filter use in condition #}
{% endif %}This would make templates:
- More concise and readable
- Easier to maintain
- More intuitive for developers
- Consistent with filter usage in output contexts (
{{ }}) - More expressive and powerful
Use Cases
This feature would be particularly useful in scenarios such as:
- Validation Logic: Checking string lengths, array sizes, or data formats without intermediate variables
- Conditional Rendering: Showing/hiding content based on processed values
- Access Control: Making decisions based on transformed user data
- Data Formatting: Conditional formatting based on calculated values
- Dynamic Loops: Iterating with dynamically calculated limits or ranges
- Complex Business Logic: Implementing multi-step conditionals with transformations
- Template Optimization: Reducing template size and complexity
Expected Behavior
Value expressions should be evaluated before being used as operands in conditionals and loops:
{# These should all work #}
{% if (value | size) > 10 %}...{% endif %}
{% for i in (1..items | size) %}...{% endfor %}
{% unless (text | strip_html | size) == 0 %}...{% endunless %}
{% case (status | downcase) %}...{% endcase %}The parentheses would indicate to the parser that the enclosed expression should be evaluated as a complete value expression before being used in the containing statement.
Comparison with Other Templating Engines
Many other templating engines support inline expressions in conditionals:
- Jinja2 (Python): Supports complex expressions in conditionals
- Twig (PHP): Allows filter operations in conditional statements
- Nunjucks (JavaScript): Supports inline transformations in logic blocks
- Handlebars (JavaScript): Allows helper functions in conditionals
Supporting this syntax would align LiquidJS with industry standards and improve developer experience.
Proposed Solution
Allow value expressions (enclosed in parentheses or maybe not) to be evaluated and used as operands in:
- Conditional tags:
if,elsif,unless,case - Loop tags:
for(range expressions, limit parameters) - Any other tag that accepts value operands
This should maintain backward compatibility while adding this enhancement. The parentheses provide a clear signal to the parser that the enclosed content is a value expression that should be fully evaluated before being used.
Metadata
Metadata
Assignees
Projects
Status