Hello community,

here is the log from the commit of package rubygem-liquid for openSUSE:Factory 
checked in at 2019-03-27 16:18:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-liquid (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-liquid.new.25356 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-liquid"

Wed Mar 27 16:18:03 2019 rev:4 rq:685132 version:4.0.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/rubygem-liquid/rubygem-liquid.changes    
2019-01-21 10:25:27.913743256 +0100
+++ /work/SRC/openSUSE:Factory/.rubygem-liquid.new.25356/rubygem-liquid.changes 
2019-03-27 16:18:07.355570786 +0100
@@ -1,0 +2,59 @@
+Thu Mar 14 10:58:54 UTC 2019 - Stephan Kulow <[email protected]>
+
+- updated to version 4.0.3
+ see installed History.md
+
+  ## 4.0.3 / 2019-03-12
+  
+  ### Fixed
+  * Fix break and continue tags inside included templates in loops (#1072) 
[Justin Li]
+  
+  ## 4.0.2 / 2019-03-08
+  
+  ### Changed
+  * Add `where` filter (#1026) [Samuel Doiron]
+  * Add `ParseTreeVisitor` to iterate the Liquid AST (#1025) [Stephen Paul 
Weber]
+  * Improve `strip_html` performance (#1032) [printercu]
+  
+  ### Fixed
+  * Add error checking for invalid combinations of inputs to sort, 
sort_natural, where, uniq, map, compact filters (#1059) [Garland Zhang]
+  * Validate the character encoding in url_decode (#1070) [Clayton Smith]
+  
+  ## 4.0.1 / 2018-10-09
+  
+  ### Changed
+  * Add benchmark group in Gemfile (#855) [Jerry Liu]
+  * Allow benchmarks to benchmark render by itself (#851) [Jerry Liu]
+  * Avoid calling `line_number` on String node when rescuing a render error. 
(#860) [Dylan Thacker-Smith]
+  * Avoid duck typing to detect whether to call render on a node. [Dylan 
Thacker-Smith]
+  * Clarify spelling of `reversed` on `for` block tag (#843) [Mark Crossfield]
+  * Replace recursion with loop to avoid potential stack overflow from 
malicious input (#891, #892) [Dylan Thacker-Smith]
+  * Limit block tag nesting to 100 (#894) [Dylan Thacker-Smith]
+  * Replace `assert_equal nil` with `assert_nil` (#895) [Dylan Thacker-Smith]
+  * Remove Spy Gem (#896) [Dylan Thacker-Smith]
+  * Add `collection_name` and `variable_name` reader to `For` block (#909)
+  * Symbols render as strings (#920) [Justin Li]
+  * Remove default value from Hash objects (#932) [Maxime Bedard]
+  * Remove one level of nesting (#944) [Dylan Thacker-Smith]
+  * Update Rubocop version (#952) [Justin Li]
+  * Add `at_least` and `at_most` filters (#954, #958) [Nithin Bekal]
+  * Add a regression test for a liquid-c trim mode bug (#972) [Dylan 
Thacker-Smith]
+  * Use https rather than git protocol to fetch liquid-c [Dylan Thacker-Smith]
+  * Add tests against Ruby 2.4 (#963) and 2.5 (#981)
+  * Replace RegExp literals with constants (#988) [Ashwin Maroli]
+  * Replace unnecessary `#each_with_index` with `#each` (#992) [Ashwin Maroli]
+  * Improve the unexpected end delimiter message for block tags. (#1003) 
[Dylan Thacker-Smith]
+  * Refactor and optimize rendering (#1005) [Christopher Aue]
+  * Add installation instruction (#1006) [Ben Gift]
+  * Remove Circle CI (#1010)
+  * Rename deprecated `BigDecimal.new` to `BigDecimal` (#1024) [Koichi ITO]
+  * Rename deprecated Rubocop name (#1027) [Justin Li]
+  
+  ### Fixed
+  * Handle `join` filter on non String joiners (#857) [Richard Monette]
+  * Fix duplicate inclusion condition logic error of 
`Liquid::Strainer.add_filter` method (#861)
+  * Fix `escape`, `url_encode`, `url_decode` not handling non-string values 
(#898) [Thierry Joyal]
+  * Fix raise when variable is defined but nil when using `strict_variables` 
[Pascal Betz]
+  * Fix `sort` and `sort_natural` to handle arrays with nils (#930) [Eric Chan]
+
+-------------------------------------------------------------------

Old:
----
  liquid-4.0.1.gem

New:
----
  liquid-4.0.3.gem

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rubygem-liquid.spec ++++++
--- /var/tmp/diff_new_pack.5BymmK/_old  2019-03-27 16:18:08.415570565 +0100
+++ /var/tmp/diff_new_pack.5BymmK/_new  2019-03-27 16:18:08.415570565 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package rubygem-liquid
 #
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -24,7 +24,7 @@
 #
 
 Name:           rubygem-liquid
-Version:        4.0.1
+Version:        4.0.3
 Release:        0
 %define mod_name liquid
 %define mod_full_name %{mod_name}-%{version}

++++++ liquid-4.0.1.gem -> liquid-4.0.3.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/History.md new/History.md
--- old/History.md      2018-10-09 11:14:52.000000000 +0200
+++ new/History.md      2019-03-12 17:44:15.000000000 +0100
@@ -1,5 +1,58 @@
 # Liquid Change Log
 
+## 4.0.3 / 2019-03-12
+
+### Fixed
+* Fix break and continue tags inside included templates in loops (#1072) 
[Justin Li]
+
+## 4.0.2 / 2019-03-08
+
+### Changed
+* Add `where` filter (#1026) [Samuel Doiron]
+* Add `ParseTreeVisitor` to iterate the Liquid AST (#1025) [Stephen Paul Weber]
+* Improve `strip_html` performance (#1032) [printercu]
+
+### Fixed
+* Add error checking for invalid combinations of inputs to sort, sort_natural, 
where, uniq, map, compact filters (#1059) [Garland Zhang]
+* Validate the character encoding in url_decode (#1070) [Clayton Smith]
+
+## 4.0.1 / 2018-10-09
+
+### Changed
+* Add benchmark group in Gemfile (#855) [Jerry Liu]
+* Allow benchmarks to benchmark render by itself (#851) [Jerry Liu]
+* Avoid calling `line_number` on String node when rescuing a render error. 
(#860) [Dylan Thacker-Smith]
+* Avoid duck typing to detect whether to call render on a node. [Dylan 
Thacker-Smith]
+* Clarify spelling of `reversed` on `for` block tag (#843) [Mark Crossfield]
+* Replace recursion with loop to avoid potential stack overflow from malicious 
input (#891, #892) [Dylan Thacker-Smith]
+* Limit block tag nesting to 100 (#894) [Dylan Thacker-Smith]
+* Replace `assert_equal nil` with `assert_nil` (#895) [Dylan Thacker-Smith]
+* Remove Spy Gem (#896) [Dylan Thacker-Smith]
+* Add `collection_name` and `variable_name` reader to `For` block (#909)
+* Symbols render as strings (#920) [Justin Li]
+* Remove default value from Hash objects (#932) [Maxime Bedard]
+* Remove one level of nesting (#944) [Dylan Thacker-Smith]
+* Update Rubocop version (#952) [Justin Li]
+* Add `at_least` and `at_most` filters (#954, #958) [Nithin Bekal]
+* Add a regression test for a liquid-c trim mode bug (#972) [Dylan 
Thacker-Smith]
+* Use https rather than git protocol to fetch liquid-c [Dylan Thacker-Smith]
+* Add tests against Ruby 2.4 (#963) and 2.5 (#981)
+* Replace RegExp literals with constants (#988) [Ashwin Maroli]
+* Replace unnecessary `#each_with_index` with `#each` (#992) [Ashwin Maroli]
+* Improve the unexpected end delimiter message for block tags. (#1003) [Dylan 
Thacker-Smith]
+* Refactor and optimize rendering (#1005) [Christopher Aue]
+* Add installation instruction (#1006) [Ben Gift]
+* Remove Circle CI (#1010)
+* Rename deprecated `BigDecimal.new` to `BigDecimal` (#1024) [Koichi ITO]
+* Rename deprecated Rubocop name (#1027) [Justin Li]
+
+### Fixed
+* Handle `join` filter on non String joiners (#857) [Richard Monette]
+* Fix duplicate inclusion condition logic error of 
`Liquid::Strainer.add_filter` method (#861)
+* Fix `escape`, `url_encode`, `url_decode` not handling non-string values 
(#898) [Thierry Joyal]
+* Fix raise when variable is defined but nil when using `strict_variables` 
[Pascal Betz]
+* Fix `sort` and `sort_natural` to handle arrays with nils (#930) [Eric Chan]
+
 ## 4.0.0 / 2016-12-14 / branch "4-0-stable"
 
 ### Changed
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/block_body.rb new/lib/liquid/block_body.rb
--- old/lib/liquid/block_body.rb        2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/block_body.rb        2019-03-12 17:44:15.000000000 +0100
@@ -89,6 +89,7 @@
           break
         else # Other non-Block tags
           render_node_to_output(node, output, context)
+          break if context.interrupt? # might have happened through an include
         end
         idx += 1
       end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/condition.rb new/lib/liquid/condition.rb
--- old/lib/liquid/condition.rb 2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/condition.rb 2019-03-12 17:44:15.000000000 +0100
@@ -29,7 +29,7 @@
       @@operators
     end
 
-    attr_reader :attachment
+    attr_reader :attachment, :child_condition
     attr_accessor :left, :operator, :right
 
     def initialize(left = nil, operator = nil, right = nil)
@@ -83,7 +83,7 @@
 
     protected
 
-    attr_reader :child_relation, :child_condition
+    attr_reader :child_relation
 
     private
 
@@ -128,6 +128,15 @@
         end
       end
     end
+
+    class ParseTreeVisitor < Liquid::ParseTreeVisitor
+      def children
+        [
+          @node.left, @node.right,
+          @node.child_condition, @node.attachment
+        ].compact
+      end
+    end
   end
 
   class ElseCondition < Condition
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/expression.rb new/lib/liquid/expression.rb
--- old/lib/liquid/expression.rb        2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/expression.rb        2019-03-12 17:44:15.000000000 +0100
@@ -19,7 +19,7 @@
       'false'.freeze => false,
       'blank'.freeze => MethodLiteral.new(:blank?, '').freeze,
       'empty'.freeze => MethodLiteral.new(:empty?, '').freeze
-    }
+    }.freeze
 
     SINGLE_QUOTED_STRING = /\A'(.*)'\z/m
     DOUBLE_QUOTED_STRING = /\A"(.*)"\z/m
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/i18n.rb new/lib/liquid/i18n.rb
--- old/lib/liquid/i18n.rb      2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/i18n.rb      2019-03-12 17:44:15.000000000 +0100
@@ -26,7 +26,7 @@
     def interpolate(name, vars)
       name.gsub(/%\{(\w+)\}/) do
         # raise TranslationError, "Undefined key #{$1} for interpolation in 
translation #{name}"  unless vars[$1.to_sym]
-        "#{vars[$1.to_sym]}"
+        (vars[$1.to_sym]).to_s
       end
     end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/lexer.rb new/lib/liquid/lexer.rb
--- old/lib/liquid/lexer.rb     2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/lexer.rb     2019-03-12 17:44:15.000000000 +0100
@@ -12,7 +12,7 @@
       ')'.freeze => :close_round,
       '?'.freeze => :question,
       '-'.freeze => :dash
-    }
+    }.freeze
     IDENTIFIER = /[a-zA-Z_][\w-]*\??/
     SINGLE_STRING_LITERAL = /'[^\']*'/
     DOUBLE_STRING_LITERAL = /"[^\"]*"/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/parse_tree_visitor.rb 
new/lib/liquid/parse_tree_visitor.rb
--- old/lib/liquid/parse_tree_visitor.rb        1970-01-01 01:00:00.000000000 
+0100
+++ new/lib/liquid/parse_tree_visitor.rb        2019-03-12 17:44:15.000000000 
+0100
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Liquid
+  class ParseTreeVisitor
+    def self.for(node, callbacks = Hash.new(proc {}))
+      if defined?(node.class::ParseTreeVisitor)
+        node.class::ParseTreeVisitor
+      else
+        self
+      end.new(node, callbacks)
+    end
+
+    def initialize(node, callbacks)
+      @node = node
+      @callbacks = callbacks
+    end
+
+    def add_callback_for(*classes, &block)
+      callback = block
+      callback = ->(node, _) { yield node } if block.arity.abs == 1
+      callback = ->(_, _) { yield } if block.arity.zero?
+      classes.each { |klass| @callbacks[klass] = callback }
+      self
+    end
+
+    def visit(context = nil)
+      children.map do |node|
+        item, new_context = @callbacks[node.class].call(node, context)
+        [
+          item,
+          ParseTreeVisitor.for(node, @callbacks).visit(new_context || context)
+        ]
+      end
+    end
+
+    protected
+
+    def children
+      @node.respond_to?(:nodelist) ? Array(@node.nodelist) : []
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/standardfilters.rb 
new/lib/liquid/standardfilters.rb
--- old/lib/liquid/standardfilters.rb   2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/standardfilters.rb   2019-03-12 17:44:15.000000000 +0100
@@ -9,8 +9,14 @@
       '<'.freeze => '&lt;'.freeze,
       '"'.freeze => '&quot;'.freeze,
       "'".freeze => '&#39;'.freeze
-    }
+    }.freeze
     HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+));)/
+    STRIP_HTML_BLOCKS = Regexp.union(
+      /<script.*?<\/script>/m,
+      /<!--.*?-->/m,
+      /<style.*?<\/style>/m
+    )
+    STRIP_HTML_TAGS = /<.*?>/m
 
     # Return the size of an array or of an string
     def size(input)
@@ -46,7 +52,12 @@
     end
 
     def url_decode(input)
-      CGI.unescape(input.to_s) unless input.nil?
+      return if input.nil?
+
+      result = CGI.unescape(input.to_s)
+      raise Liquid::ArgumentError, "invalid byte sequence in 
#{result.encoding}" unless result.valid_encoding?
+
+      result
     end
 
     def slice(input, offset, length = nil)
@@ -103,7 +114,9 @@
 
     def strip_html(input)
       empty = ''.freeze
-      input.to_s.gsub(/<script.*?<\/script>/m, empty).gsub(/<!--.*?-->/m, 
empty).gsub(/<style.*?<\/style>/m, empty).gsub(/<.*?>/m, empty)
+      result = input.to_s.gsub(STRIP_HTML_BLOCKS, empty)
+      result.gsub!(STRIP_HTML_TAGS, empty)
+      result
     end
 
     # Remove all newlines from the string
@@ -120,25 +133,18 @@
     # provide optional property with which to sort an array of hashes or drops
     def sort(input, property = nil)
       ary = InputIterator.new(input)
+
+      return [] if ary.empty?
+
       if property.nil?
         ary.sort do |a, b|
-          if !a.nil? && !b.nil?
-            a <=> b
-          else
-            a.nil? ? 1 : -1
-          end
+          nil_safe_compare(a, b)
         end
-      elsif ary.empty? # The next two cases assume a non-empty array.
-        []
       elsif ary.all? { |el| el.respond_to?(:[]) }
-        ary.sort do |a, b|
-          a = a[property]
-          b = b[property]
-          if !a.nil? && !b.nil?
-            a <=> b
-          else
-            a.nil? ? 1 : -1
-          end
+        begin
+          ary.sort { |a, b| nil_safe_compare(a[property], b[property]) }
+        rescue TypeError
+          raise_property_error(property)
         end
       end
     end
@@ -148,25 +154,39 @@
     def sort_natural(input, property = nil)
       ary = InputIterator.new(input)
 
+      return [] if ary.empty?
+
       if property.nil?
         ary.sort do |a, b|
-          if !a.nil? && !b.nil?
-            a.to_s.casecmp(b.to_s)
-          else
-            a.nil? ? 1 : -1
-          end
+          nil_safe_casecmp(a, b)
         end
-      elsif ary.empty? # The next two cases assume a non-empty array.
-        []
       elsif ary.all? { |el| el.respond_to?(:[]) }
-        ary.sort do |a, b|
-          a = a[property]
-          b = b[property]
-          if !a.nil? && !b.nil?
-            a.to_s.casecmp(b.to_s)
-          else
-            a.nil? ? 1 : -1
-          end
+        begin
+          ary.sort { |a, b| nil_safe_casecmp(a[property], b[property]) }
+        rescue TypeError
+          raise_property_error(property)
+        end
+      end
+    end
+
+    # Filter the elements of an array to those with a certain property value.
+    # By default the target is any truthy value.
+    def where(input, property, target_value = nil)
+      ary = InputIterator.new(input)
+
+      if ary.empty?
+        []
+      elsif ary.first.respond_to?(:[]) && target_value.nil?
+        begin
+          ary.select { |item| item[property] }
+        rescue TypeError
+          raise_property_error(property)
+        end
+      elsif ary.first.respond_to?(:[])
+        begin
+          ary.select { |item| item[property] == target_value }
+        rescue TypeError
+          raise_property_error(property)
         end
       end
     end
@@ -181,7 +201,11 @@
       elsif ary.empty? # The next two cases assume a non-empty array.
         []
       elsif ary.first.respond_to?(:[])
-        ary.uniq{ |a| a[property] }
+        begin
+          ary.uniq { |a| a[property] }
+        rescue TypeError
+          raise_property_error(property)
+        end
       end
     end
 
@@ -203,6 +227,8 @@
           r.is_a?(Proc) ? r.call : r
         end
       end
+    rescue TypeError
+      raise_property_error(property)
     end
 
     # Remove nils within an array
@@ -215,7 +241,11 @@
       elsif ary.empty? # The next two cases assume a non-empty array.
         []
       elsif ary.first.respond_to?(:[])
-        ary.reject{ |a| a[property].nil? }
+        begin
+          ary.reject { |a| a[property].nil? }
+        rescue TypeError
+          raise_property_error(property)
+        end
       end
     end
 
@@ -399,11 +429,31 @@
 
     private
 
+    def raise_property_error(property)
+      raise Liquid::ArgumentError.new("cannot select the property 
'#{property}'")
+    end
+
     def apply_operation(input, operand, operation)
       result = Utils.to_number(input).send(operation, Utils.to_number(operand))
       result.is_a?(BigDecimal) ? result.to_f : result
     end
 
+    def nil_safe_compare(a, b)
+      if !a.nil? && !b.nil?
+        a <=> b
+      else
+        a.nil? ? 1 : -1
+      end
+    end
+
+    def nil_safe_casecmp(a, b)
+      if !a.nil? && !b.nil?
+        a.to_s.casecmp(b.to_s)
+      else
+        a.nil? ? 1 : -1
+      end
+    end
+
     class InputIterator
       include Enumerable
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/tags/assign.rb 
new/lib/liquid/tags/assign.rb
--- old/lib/liquid/tags/assign.rb       2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/tags/assign.rb       2019-03-12 17:44:15.000000000 +0100
@@ -10,6 +10,8 @@
   class Assign < Tag
     Syntax = /(#{VariableSignature}+)\s*=\s*(.*)\s*/om
 
+    attr_reader :to, :from
+
     def initialize(tag_name, markup, options)
       super
       if markup =~ Syntax
@@ -45,6 +47,12 @@
         1
       end
     end
+
+    class ParseTreeVisitor < Liquid::ParseTreeVisitor
+      def children
+        [@node.from]
+      end
+    end
   end
 
   Template.register_tag('assign'.freeze, Assign)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/tags/case.rb new/lib/liquid/tags/case.rb
--- old/lib/liquid/tags/case.rb 2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/tags/case.rb 2019-03-12 17:44:15.000000000 +0100
@@ -3,6 +3,8 @@
     Syntax     = /(#{QuotedFragment})/o
     WhenSyntax = 
/(#{QuotedFragment})(?:(?:\s+or\s+|\s*\,\s*)(#{QuotedFragment}.*))?/om
 
+    attr_reader :blocks, :left
+
     def initialize(tag_name, markup, options)
       super
       @blocks = []
@@ -80,6 +82,12 @@
       block.attach(BlockBody.new)
       @blocks << block
     end
+
+    class ParseTreeVisitor < Liquid::ParseTreeVisitor
+      def children
+        [@node.left] + @node.blocks
+      end
+    end
   end
 
   Template.register_tag('case'.freeze, Case)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/tags/cycle.rb new/lib/liquid/tags/cycle.rb
--- old/lib/liquid/tags/cycle.rb        2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/tags/cycle.rb        2019-03-12 17:44:15.000000000 +0100
@@ -15,6 +15,8 @@
     SimpleSyntax = /\A#{QuotedFragment}+/o
     NamedSyntax  = /\A(#{QuotedFragment})\s*\:\s*(.*)/om
 
+    attr_reader :variables
+
     def initialize(tag_name, markup, options)
       super
       case markup
@@ -51,6 +53,12 @@
         $1 ? Expression.parse($1) : nil
       end.compact
     end
+
+    class ParseTreeVisitor < Liquid::ParseTreeVisitor
+      def children
+        Array(@node.variables)
+      end
+    end
   end
 
   Template.register_tag('cycle', Cycle)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/tags/for.rb new/lib/liquid/tags/for.rb
--- old/lib/liquid/tags/for.rb  2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/tags/for.rb  2019-03-12 17:44:15.000000000 +0100
@@ -46,8 +46,7 @@
   class For < Block
     Syntax = 
/\A(#{VariableSegment}+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/o
 
-    attr_reader :collection_name
-    attr_reader :variable_name
+    attr_reader :collection_name, :variable_name, :limit, :from
 
     def initialize(tag_name, markup, options)
       super
@@ -192,6 +191,12 @@
     def render_else(context)
       @else_block ? @else_block.render(context) : ''.freeze
     end
+
+    class ParseTreeVisitor < Liquid::ParseTreeVisitor
+      def children
+        (super + [@node.limit, @node.from, @node.collection_name]).compact
+      end
+    end
   end
 
   Template.register_tag('for'.freeze, For)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/tags/if.rb new/lib/liquid/tags/if.rb
--- old/lib/liquid/tags/if.rb   2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/tags/if.rb   2019-03-12 17:44:15.000000000 +0100
@@ -12,7 +12,9 @@
   class If < Block
     Syntax = /(#{QuotedFragment})\s*([=!<>a-z_]+)?\s*(#{QuotedFragment})?/o
     ExpressionsAndOperators = 
/(?:\b(?:\s?and\s?|\s?or\s?)\b|(?:\s*(?!\b(?:\s?and\s?|\s?or\s?)\b)(?:#{QuotedFragment}|\S+)\s*)+)/o
-    BOOLEAN_OPERATORS = %w(and or)
+    BOOLEAN_OPERATORS = %w(and or).freeze
+
+    attr_reader :blocks
 
     def initialize(tag_name, markup, options)
       super
@@ -20,15 +22,15 @@
       push_block('if'.freeze, markup)
     end
 
+    def nodelist
+      @blocks.map(&:attachment)
+    end
+
     def parse(tokens)
       while parse_body(@blocks.last.attachment, tokens)
       end
     end
 
-    def nodelist
-      @blocks.map(&:attachment)
-    end
-
     def unknown_tag(tag, markup, tokens)
       if ['elsif'.freeze, 'else'.freeze].include?(tag)
         push_block(tag, markup)
@@ -108,6 +110,12 @@
         Condition.new(a)
       end
     end
+
+    class ParseTreeVisitor < Liquid::ParseTreeVisitor
+      def children
+        @node.blocks
+      end
+    end
   end
 
   Template.register_tag('if'.freeze, If)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/tags/include.rb 
new/lib/liquid/tags/include.rb
--- old/lib/liquid/tags/include.rb      2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/tags/include.rb      2019-03-12 17:44:15.000000000 +0100
@@ -16,6 +16,8 @@
   class Include < Tag
     Syntax = /(#{QuotedFragment}+)(\s+(?:with|for)\s+(#{QuotedFragment}+))?/o
 
+    attr_reader :template_name_expr, :variable_name_expr, :attributes
+
     def initialize(tag_name, markup, options)
       super
 
@@ -107,6 +109,15 @@
 
       file_system.read_template_file(context.evaluate(@template_name_expr))
     end
+
+    class ParseTreeVisitor < Liquid::ParseTreeVisitor
+      def children
+        [
+          @node.template_name_expr,
+          @node.variable_name_expr
+        ] + @node.attributes.values
+      end
+    end
   end
 
   Template.register_tag('include'.freeze, Include)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/tags/table_row.rb 
new/lib/liquid/tags/table_row.rb
--- old/lib/liquid/tags/table_row.rb    2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/tags/table_row.rb    2019-03-12 17:44:15.000000000 +0100
@@ -2,6 +2,8 @@
   class TableRow < Block
     Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)/o
 
+    attr_reader :variable_name, :collection_name, :attributes
+
     def initialize(tag_name, markup, options)
       super
       if markup =~ Syntax
@@ -48,6 +50,12 @@
       result << "</tr>\n"
       result
     end
+
+    class ParseTreeVisitor < Liquid::ParseTreeVisitor
+      def children
+        super + @node.attributes.values + [@node.collection_name]
+      end
+    end
   end
 
   Template.register_tag('tablerow'.freeze, TableRow)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/truffle.rb new/lib/liquid/truffle.rb
--- old/lib/liquid/truffle.rb   1970-01-01 01:00:00.000000000 +0100
+++ new/lib/liquid/truffle.rb   2019-03-12 17:44:15.000000000 +0100
@@ -0,0 +1,5 @@
+module Liquid
+  module Truffle
+
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/variable.rb new/lib/liquid/variable.rb
--- old/lib/liquid/variable.rb  2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/variable.rb  2019-03-12 17:44:15.000000000 +0100
@@ -138,5 +138,11 @@
         raise error
       end
     end
+
+    class ParseTreeVisitor < Liquid::ParseTreeVisitor
+      def children
+        [@node.name] + @node.filters.flatten
+      end
+    end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/variable_lookup.rb 
new/lib/liquid/variable_lookup.rb
--- old/lib/liquid/variable_lookup.rb   2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/variable_lookup.rb   2019-03-12 17:44:15.000000000 +0100
@@ -1,7 +1,7 @@
 module Liquid
   class VariableLookup
     SQUARE_BRACKETED = /\A\[(.*)\]\z/m
-    COMMAND_METHODS = ['size'.freeze, 'first'.freeze, 'last'.freeze]
+    COMMAND_METHODS = ['size'.freeze, 'first'.freeze, 'last'.freeze].freeze
 
     attr_reader :name, :lookups
 
@@ -78,5 +78,11 @@
     def state
       [@name, @lookups, @command_flags]
     end
+
+    class ParseTreeVisitor < Liquid::ParseTreeVisitor
+      def children
+        @node.lookups
+      end
+    end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid/version.rb new/lib/liquid/version.rb
--- old/lib/liquid/version.rb   2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid/version.rb   2019-03-12 17:44:15.000000000 +0100
@@ -1,4 +1,5 @@
 # encoding: utf-8
+
 module Liquid
-  VERSION = "4.0.1"
+  VERSION = "4.0.3".freeze
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/liquid.rb new/lib/liquid.rb
--- old/lib/liquid.rb   2018-10-09 11:14:52.000000000 +0200
+++ new/lib/liquid.rb   2019-03-12 17:44:15.000000000 +0100
@@ -45,6 +45,7 @@
 end
 
 require "liquid/version"
+require 'liquid/parse_tree_visitor'
 require 'liquid/lexer'
 require 'liquid/parser'
 require 'liquid/i18n'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        2018-10-09 11:14:52.000000000 +0200
+++ new/metadata        2019-03-12 17:44:15.000000000 +0100
@@ -1,14 +1,14 @@
 --- !ruby/object:Gem::Specification
 name: liquid
 version: !ruby/object:Gem::Version
-  version: 4.0.1
+  version: 4.0.3
 platform: ruby
 authors:
 - Tobias Lütke
 autorequire: 
 bindir: bin
 cert_chain: []
-date: 2018-10-09 00:00:00.000000000 Z
+date: 2019-03-12 00:00:00.000000000 Z
 dependencies:
 - !ruby/object:Gem::Dependency
   name: rake
@@ -67,6 +67,7 @@
 - lib/liquid/lexer.rb
 - lib/liquid/locales/en.yml
 - lib/liquid/parse_context.rb
+- lib/liquid/parse_tree_visitor.rb
 - lib/liquid/parser.rb
 - lib/liquid/parser_switching.rb
 - lib/liquid/profiler.rb
@@ -95,6 +96,7 @@
 - lib/liquid/tags/unless.rb
 - lib/liquid/template.rb
 - lib/liquid/tokenizer.rb
+- lib/liquid/truffle.rb
 - lib/liquid/utils.rb
 - lib/liquid/variable.rb
 - lib/liquid/variable_lookup.rb
@@ -111,6 +113,7 @@
 - test/integration/filter_test.rb
 - test/integration/hash_ordering_test.rb
 - test/integration/output_test.rb
+- test/integration/parse_tree_visitor_test.rb
 - test/integration/parsing_quirks_test.rb
 - test/integration/render_profiling_test.rb
 - test/integration/security_test.rb
@@ -130,6 +133,7 @@
 - test/integration/trim_mode_test.rb
 - test/integration/variable_test.rb
 - test/test_helper.rb
+- test/truffle/truffle_test.rb
 - test/unit/block_unit_test.rb
 - test/unit/condition_unit_test.rb
 - test/unit/context_unit_test.rb
@@ -165,8 +169,7 @@
     - !ruby/object:Gem::Version
       version: 1.3.7
 requirements: []
-rubyforge_project: 
-rubygems_version: 2.7.6
+rubygems_version: 3.0.2
 signing_key: 
 specification_version: 4
 summary: A secure, non-evaling end user template engine with aesthetic markup.
@@ -191,6 +194,7 @@
 - test/integration/hash_ordering_test.rb
 - test/integration/variable_test.rb
 - test/integration/blank_test.rb
+- test/integration/parse_tree_visitor_test.rb
 - test/integration/assign_test.rb
 - test/integration/trim_mode_test.rb
 - test/integration/context_test.rb
@@ -216,5 +220,6 @@
 - test/integration/render_profiling_test.rb
 - test/integration/parsing_quirks_test.rb
 - test/integration/filter_test.rb
+- test/truffle/truffle_test.rb
 - test/fixtures/en_locale.yml
 - test/test_helper.rb
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/integration/error_handling_test.rb 
new/test/integration/error_handling_test.rb
--- old/test/integration/error_handling_test.rb 2018-10-09 11:14:52.000000000 
+0200
+++ new/test/integration/error_handling_test.rb 2019-03-12 17:44:15.000000000 
+0100
@@ -123,7 +123,7 @@
             ',
       error_mode: :warn,
       line_numbers: true
-                                     )
+    )
 
     assert_equal ['Liquid syntax error (line 4): Unexpected character = in "1 
=! 2"'],
       template.warnings.map(&:message)
@@ -140,7 +140,7 @@
                 ',
         error_mode: :strict,
         line_numbers: true
-                            )
+      )
     end
 
     assert_equal 'Liquid syntax error (line 4): Unexpected character = in "1 
=! 2"', err.message
@@ -158,7 +158,7 @@
           bla
                 ',
         line_numbers: true
-                            )
+      )
     end
 
     assert_equal "Liquid syntax error (line 5): Unknown tag 'foo'", err.message
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/integration/parse_tree_visitor_test.rb 
new/test/integration/parse_tree_visitor_test.rb
--- old/test/integration/parse_tree_visitor_test.rb     1970-01-01 
01:00:00.000000000 +0100
+++ new/test/integration/parse_tree_visitor_test.rb     2019-03-12 
17:44:16.000000000 +0100
@@ -0,0 +1,247 @@
+# frozen_string_literal: true
+
+require 'test_helper'
+
+class ParseTreeVisitorTest < Minitest::Test
+  include Liquid
+
+  def test_variable
+    assert_equal(
+      ["test"],
+      visit(%({{ test }}))
+    )
+  end
+
+  def test_varible_with_filter
+    assert_equal(
+      ["test", "infilter"],
+      visit(%({{ test | split: infilter }}))
+    )
+  end
+
+  def test_dynamic_variable
+    assert_equal(
+      ["test", "inlookup"],
+      visit(%({{ test[inlookup] }}))
+    )
+  end
+
+  def test_if_condition
+    assert_equal(
+      ["test"],
+      visit(%({% if test %}{% endif %}))
+    )
+  end
+
+  def test_complex_if_condition
+    assert_equal(
+      ["test"],
+      visit(%({% if 1 == 1 and 2 == test %}{% endif %}))
+    )
+  end
+
+  def test_if_body
+    assert_equal(
+      ["test"],
+      visit(%({% if 1 == 1 %}{{ test }}{% endif %}))
+    )
+  end
+
+  def test_unless_condition
+    assert_equal(
+      ["test"],
+      visit(%({% unless test %}{% endunless %}))
+    )
+  end
+
+  def test_complex_unless_condition
+    assert_equal(
+      ["test"],
+      visit(%({% unless 1 == 1 and 2 == test %}{% endunless %}))
+    )
+  end
+
+  def test_unless_body
+    assert_equal(
+      ["test"],
+      visit(%({% unless 1 == 1 %}{{ test }}{% endunless %}))
+    )
+  end
+
+  def test_elsif_condition
+    assert_equal(
+      ["test"],
+      visit(%({% if 1 == 1 %}{% elsif test %}{% endif %}))
+    )
+  end
+
+  def test_complex_elsif_condition
+    assert_equal(
+      ["test"],
+      visit(%({% if 1 == 1 %}{% elsif 1 == 1 and 2 == test %}{% endif %}))
+    )
+  end
+
+  def test_elsif_body
+    assert_equal(
+      ["test"],
+      visit(%({% if 1 == 1 %}{% elsif 2 == 2 %}{{ test }}{% endif %}))
+    )
+  end
+
+  def test_else_body
+    assert_equal(
+      ["test"],
+      visit(%({% if 1 == 1 %}{% else %}{{ test }}{% endif %}))
+    )
+  end
+
+  def test_case_left
+    assert_equal(
+      ["test"],
+      visit(%({% case test %}{% endcase %}))
+    )
+  end
+
+  def test_case_condition
+    assert_equal(
+      ["test"],
+      visit(%({% case 1 %}{% when test %}{% endcase %}))
+    )
+  end
+
+  def test_case_when_body
+    assert_equal(
+      ["test"],
+      visit(%({% case 1 %}{% when 2 %}{{ test }}{% endcase %}))
+    )
+  end
+
+  def test_case_else_body
+    assert_equal(
+      ["test"],
+      visit(%({% case 1 %}{% else %}{{ test }}{% endcase %}))
+    )
+  end
+
+  def test_for_in
+    assert_equal(
+      ["test"],
+      visit(%({% for x in test %}{% endfor %}))
+    )
+  end
+
+  def test_for_limit
+    assert_equal(
+      ["test"],
+      visit(%({% for x in (1..5) limit: test %}{% endfor %}))
+    )
+  end
+
+  def test_for_offset
+    assert_equal(
+      ["test"],
+      visit(%({% for x in (1..5) offset: test %}{% endfor %}))
+    )
+  end
+
+  def test_for_body
+    assert_equal(
+      ["test"],
+      visit(%({% for x in (1..5) %}{{ test }}{% endfor %}))
+    )
+  end
+
+  def test_tablerow_in
+    assert_equal(
+      ["test"],
+      visit(%({% tablerow x in test %}{% endtablerow %}))
+    )
+  end
+
+  def test_tablerow_limit
+    assert_equal(
+      ["test"],
+      visit(%({% tablerow x in (1..5) limit: test %}{% endtablerow %}))
+    )
+  end
+
+  def test_tablerow_offset
+    assert_equal(
+      ["test"],
+      visit(%({% tablerow x in (1..5) offset: test %}{% endtablerow %}))
+    )
+  end
+
+  def test_tablerow_body
+    assert_equal(
+      ["test"],
+      visit(%({% tablerow x in (1..5) %}{{ test }}{% endtablerow %}))
+    )
+  end
+
+  def test_cycle
+    assert_equal(
+      ["test"],
+      visit(%({% cycle test %}))
+    )
+  end
+
+  def test_assign
+    assert_equal(
+      ["test"],
+      visit(%({% assign x = test %}))
+    )
+  end
+
+  def test_capture
+    assert_equal(
+      ["test"],
+      visit(%({% capture x %}{{ test }}{% endcapture %}))
+    )
+  end
+
+  def test_include
+    assert_equal(
+      ["test"],
+      visit(%({% include test %}))
+    )
+  end
+
+  def test_include_with
+    assert_equal(
+      ["test"],
+      visit(%({% include "hai" with test %}))
+    )
+  end
+
+  def test_include_for
+    assert_equal(
+      ["test"],
+      visit(%({% include "hai" for test %}))
+    )
+  end
+
+  def test_preserve_tree_structure
+    assert_equal(
+      [[nil, [
+        [nil, [[nil, [["other", []]]]]],
+        ["test", []],
+        ["xs", []]
+      ]]],
+      traversal(%({% for x in xs offset: test %}{{ other }}{% endfor %})).visit
+    )
+  end
+
+  private
+
+  def traversal(template)
+    ParseTreeVisitor
+      .for(Template.parse(template).root)
+      .add_callback_for(VariableLookup, &:name)
+  end
+
+  def visit(template)
+    traversal(template).visit.flatten.compact
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/integration/parsing_quirks_test.rb 
new/test/integration/parsing_quirks_test.rb
--- old/test/integration/parsing_quirks_test.rb 2018-10-09 11:14:52.000000000 
+0200
+++ new/test/integration/parsing_quirks_test.rb 2019-03-12 17:44:16.000000000 
+0100
@@ -99,7 +99,7 @@
       # After the messed up quotes a filter without parameters (reverse) 
should work
       # but one with parameters (remove) shouldn't be detected.
       assert_template_result('here',  "{{ 'hi there' | split:\"t\"\" | reverse 
| first}}")
-      assert_template_result('hi ',  "{{ 'hi there' | split:\"t\"\" | 
remove:\"i\" | first}}")
+      assert_template_result('hi ', "{{ 'hi there' | split:\"t\"\" | 
remove:\"i\" | first}}")
     end
   end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/integration/standard_filter_test.rb 
new/test/integration/standard_filter_test.rb
--- old/test/integration/standard_filter_test.rb        2018-10-09 
11:14:52.000000000 +0200
+++ new/test/integration/standard_filter_test.rb        2019-03-12 
17:44:16.000000000 +0100
@@ -158,6 +158,10 @@
     assert_equal '1', @filters.url_decode(1)
     assert_equal '2001-02-03', @filters.url_decode(Date.new(2001, 2, 3))
     assert_nil @filters.url_decode(nil)
+    exception = assert_raises Liquid::ArgumentError do
+      @filters.url_decode('%ff')
+    end
+    assert_equal 'Liquid error: invalid byte sequence in UTF-8', 
exception.message
   end
 
   def test_truncatewords
@@ -177,6 +181,9 @@
     assert_equal 'test', 
@filters.strip_html("<div\nclass='multiline'>test</div>")
     assert_equal 'test', @filters.strip_html("<!-- foo bar \n test -->test")
     assert_equal '', @filters.strip_html(nil)
+
+    # Quirk of the existing implementation
+    assert_equal 'foo;', @filters.strip_html("<<<script 
</script>script>foo;</script>")
   end
 
   def test_join
@@ -268,10 +275,34 @@
     assert_equal [], @filters.sort([], "a")
   end
 
+  def test_sort_invalid_property
+    foo = [
+      [1],
+      [2],
+      [3]
+    ]
+
+    assert_raises Liquid::ArgumentError do
+      @filters.sort(foo, "bar")
+    end
+  end
+
   def test_sort_natural_empty_array
     assert_equal [], @filters.sort_natural([], "a")
   end
 
+  def test_sort_natural_invalid_property
+    foo = [
+      [1],
+      [2],
+      [3]
+    ]
+
+    assert_raises Liquid::ArgumentError do
+      @filters.sort_natural(foo, "bar")
+    end
+  end
+
   def test_legacy_sort_hash
     assert_equal [{ a: 1, b: 2 }], @filters.sort({ a: 1, b: 2 })
   end
@@ -295,10 +326,34 @@
     assert_equal [], @filters.uniq([], "a")
   end
 
+  def test_uniq_invalid_property
+    foo = [
+      [1],
+      [2],
+      [3]
+    ]
+
+    assert_raises Liquid::ArgumentError do
+      @filters.uniq(foo, "bar")
+    end
+  end
+
   def test_compact_empty_array
     assert_equal [], @filters.compact([], "a")
   end
 
+  def test_compact_invalid_property
+    foo = [
+      [1],
+      [2],
+      [3]
+    ]
+
+    assert_raises Liquid::ArgumentError do
+      @filters.compact(foo, "bar")
+    end
+  end
+
   def test_reverse
     assert_equal [4, 3, 2, 1], @filters.reverse([1, 2, 3, 4])
   end
@@ -364,6 +419,29 @@
     assert_template_result "123", '{{ foo | map: "foo" }}', "foo" => 
TestEnumerable.new
   end
 
+  def test_map_returns_empty_on_2d_input_array
+    foo = [
+      [1],
+      [2],
+      [3]
+    ]
+
+    assert_raises Liquid::ArgumentError do
+      @filters.map(foo, "bar")
+    end
+  end
+
+  def test_map_returns_empty_with_no_property
+    foo = [
+      [1],
+      [2],
+      [3]
+    ]
+    assert_raises Liquid::ArgumentError do
+      @filters.map(foo, nil)
+    end
+  end
+
   def test_sort_works_on_enumerables
     assert_template_result "213", '{{ foo | sort: "bar" | map: "foo" }}', 
"foo" => TestEnumerable.new
   end
@@ -394,9 +472,9 @@
     assert_equal '07/05/2006', @filters.date("2006-07-05 10:00:00", "%m/%d/%Y")
 
     assert_equal "07/16/2004", @filters.date("Fri Jul 16 01:00:00 2004", 
"%m/%d/%Y")
-    assert_equal "#{Date.today.year}", @filters.date('now', '%Y')
-    assert_equal "#{Date.today.year}", @filters.date('today', '%Y')
-    assert_equal "#{Date.today.year}", @filters.date('Today', '%Y')
+    assert_equal Date.today.year.to_s, @filters.date('now', '%Y')
+    assert_equal Date.today.year.to_s, @filters.date('today', '%Y')
+    assert_equal Date.today.year.to_s, @filters.date('Today', '%Y')
 
     assert_nil @filters.date(nil, "%B")
 
@@ -614,6 +692,78 @@
     assert_template_result('abc', "{{ 'abc' | date: '%D' }}")
   end
 
+  def test_where
+    input = [
+      { "handle" => "alpha", "ok" => true },
+      { "handle" => "beta", "ok" => false },
+      { "handle" => "gamma", "ok" => false },
+      { "handle" => "delta", "ok" => true }
+    ]
+
+    expectation = [
+      { "handle" => "alpha", "ok" => true },
+      { "handle" => "delta", "ok" => true }
+    ]
+
+    assert_equal expectation, @filters.where(input, "ok", true)
+    assert_equal expectation, @filters.where(input, "ok")
+  end
+
+  def test_where_no_key_set
+    input = [
+      { "handle" => "alpha", "ok" => true },
+      { "handle" => "beta" },
+      { "handle" => "gamma" },
+      { "handle" => "delta", "ok" => true }
+    ]
+
+    expectation = [
+      { "handle" => "alpha", "ok" => true },
+      { "handle" => "delta", "ok" => true }
+    ]
+
+    assert_equal expectation, @filters.where(input, "ok", true)
+    assert_equal expectation, @filters.where(input, "ok")
+  end
+
+  def test_where_non_array_map_input
+    assert_equal [{ "a" => "ok" }], @filters.where({ "a" => "ok" }, "a", "ok")
+    assert_equal [], @filters.where({ "a" => "not ok" }, "a", "ok")
+  end
+
+  def test_where_indexable_but_non_map_value
+    assert_raises(Liquid::ArgumentError) { @filters.where(1, "ok", true) }
+    assert_raises(Liquid::ArgumentError) { @filters.where(1, "ok") }
+  end
+
+  def test_where_non_boolean_value
+    input = [
+      { "message" => "Bonjour!", "language" => "French" },
+      { "message" => "Hello!", "language" => "English" },
+      { "message" => "Hallo!", "language" => "German" }
+    ]
+
+    assert_equal [{ "message" => "Bonjour!", "language" => "French" }], 
@filters.where(input, "language", "French")
+    assert_equal [{ "message" => "Hallo!", "language" => "German" }], 
@filters.where(input, "language", "German")
+    assert_equal [{ "message" => "Hello!", "language" => "English" }], 
@filters.where(input, "language", "English")
+  end
+
+  def test_where_array_of_only_unindexable_values
+    assert_nil @filters.where([nil], "ok", true)
+    assert_nil @filters.where([nil], "ok")
+  end
+
+  def test_where_no_target_value
+    input = [
+      { "foo" => false },
+      { "foo" => true },
+      { "foo" => "for sure" },
+      { "bar" => true }
+    ]
+
+    assert_equal [{ "foo" => true }, { "foo" => "for sure" }], 
@filters.where(input, "foo")
+  end
+
   private
 
   def with_timezone(tz)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/integration/tags/include_tag_test.rb 
new/test/integration/tags/include_tag_test.rb
--- old/test/integration/tags/include_tag_test.rb       2018-10-09 
11:14:52.000000000 +0200
+++ new/test/integration/tags/include_tag_test.rb       2019-03-12 
17:44:16.000000000 +0100
@@ -30,6 +30,9 @@
     when 'assignments'
       "{% assign foo = 'bar' %}"
 
+    when 'break'
+      "{% break %}"
+
     else
       template_path
     end
@@ -242,4 +245,9 @@
 
     assert_equal [], template.errors
   end
+
+  def test_break_through_include
+    assert_template_result "1", "{% for i in (1..3) %}{{ i }}{% break %}{{ i 
}}{% endfor %}"
+    assert_template_result "1", "{% for i in (1..3) %}{{ i }}{% include 
'break' %}{{ i }}{% endfor %}"
+  end
 end # IncludeTagTest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/truffle/truffle_test.rb 
new/test/truffle/truffle_test.rb
--- old/test/truffle/truffle_test.rb    1970-01-01 01:00:00.000000000 +0100
+++ new/test/truffle/truffle_test.rb    2019-03-12 17:44:16.000000000 +0100
@@ -0,0 +1,9 @@
+require 'test_helper'
+
+class TruffleTest < Minitest::Test
+  include Liquid
+
+  def test_truffle_works
+
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/unit/condition_unit_test.rb 
new/test/unit/condition_unit_test.rb
--- old/test/unit/condition_unit_test.rb        2018-10-09 11:14:52.000000000 
+0200
+++ new/test/unit/condition_unit_test.rb        2019-03-12 17:44:16.000000000 
+0100
@@ -24,9 +24,9 @@
     assert_evaluates_true 1, '<=', 1
     # negative numbers
     assert_evaluates_true 1, '>', -1
-    assert_evaluates_true (-1), '<', 1
+    assert_evaluates_true -1, '<', 1
     assert_evaluates_true 1.0, '>', -1.0
-    assert_evaluates_true (-1.0), '<', 1.0
+    assert_evaluates_true -1.0, '<', 1.0
   end
 
   def test_default_operators_evalute_false


Reply via email to