liquid-spec main changed the adapter API:
- compile block now receives (ctx, source, options) and should store
the template in ctx[:template]
- render block now receives (ctx, assigns, options) and retrieves
the template from ctx[:template]
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Implement liquid_blank? and liquid_empty? methods in Condition
to emulate ActiveSupport's behavior when it's not loaded
- This ensures templates like `{% if x == blank %}` work identically
whether ActiveSupport is loaded or not
- Update liquid-spec adapters for new API (ctx parameter)
- Add rake spec task for running liquid-spec matrix
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- nil is NOT empty (but IS blank) - matches Shopify production
- String first/last returns '' for empty strings, not nil - matches ActiveSupport
- Add test for nil not being empty
- Add liquid-spec gem from GitHub to :spec group
- Create spec/ruby-liquid.rb adapter for the reference implementation
- Add spec job to CI workflow to run liquid-spec tests
Implement ActiveSupport-compatible behaviors internally so Liquid works
correctly without ActiveSupport being loaded:
1. String first/last via property access (name.first, name.last)
- VariableLookup now handles string[0] and string[-1] for first/last
2. String first/last via filters (name | first, name | last)
- StandardFilters#first and #last now handle strings
3. blank?/empty? comparisons for types without these methods
- Condition now implements liquid_blank? and liquid_empty? internally
- blank? matches ActiveSupport: nil, false, empty/whitespace strings,
empty arrays/hashes are all blank
- empty? checks length == 0 only (whitespace is NOT empty)
This fixes spec failures for templates like:
- {{ name.first }} / {{ name | first }} on strings
- {% if x == blank %} for whitespace strings, empty hashes/arrays
- {% case ' ' %}{% when blank %} matching whitespace
## Summary
- BigDecimal values now stringify using `to_s("F")` format instead of the default `to_s`
## Why
Ruby's default `BigDecimal#to_s` produces engineering/scientific notation for certain values:
```ruby
BigDecimal("0.00001").to_s # => "0.1E-4"
BigDecimal("12345678.9").to_s # => "0.123456789E8"
```
This is rarely the desired output in templates. Using `to_s("F")` produces the expected floating-point format:
```ruby
BigDecimal("0.00001").to_s("F") # => "0.00001"
BigDecimal("12345678.9").to_s("F") # => "12345678.9"
```
Previously, strict2 case/when used `safe_parse_expression`
to parse when expressions causing `blank`/`empty` to be
treated as string literals (Expression::LITERALS maps 'empty' => ''),
rather than method literals
This caused unexpected behavior:
```
{%- case empty_obj -%}
{%- when empty -%}
previously: doesn't render (empty_obj == '' is false)
now: renders (empty_obj.empty? is true)
{%- endcase -%}
```
This commit instead calls `Condition.parse_expression`
with `safe: true`, which will correctly handle `blank`
and `empty`
This commit reverts the Inline Snippets tag (#2001) and bumps
Liquid to 5.11. For now, the inclusion of Inline Snippets
in the latest Liquid release is being treated as a bug.
While #2001 does implement the scope contained in RFC#1916,
we need to take a step back to make sure we’re setting our
sights high enough with this feature, and that we’re truly
supporting theme developers in the ways they need.
If you have any feedback, please leave a comment on RFC#1916.
- Liquid Developer Tools
Previously if you set `strict_variables` to `true` on the context using
`key?('key_name')` would raise a `Liquid::UndefinedVariable` error.
Raising this error makes sense if you're trying to access the variable
directly with something like `context['key_name']` but by using `key?`
you're safely checking if it exists first.
You should be able to enable `strict_variables` and use `key?` in
combination with each other to ensure code safety.