From 9b2d5b7dd37e8dac0bfd34220205c1cf479f144d Mon Sep 17 00:00:00 2001 From: James Tucker Date: Tue, 14 May 2013 07:03:37 -0700 Subject: [PATCH 01/51] Add a class cache to avoid runtime extend calls * Strainer has a class cache that creates Strainer subclasses for each filter set that is used on .create calls. * Context now creates a list of filters and passes this to Strainer.create to utilize the class cache in almost all use cases. * If add_filter was called after a render, then the method cache may still be invalidated. Conflicts: lib/liquid/strainer.rb --- lib/liquid/context.rb | 16 +++++++++++++--- lib/liquid/strainer.rb | 16 ++++++++++++---- test/liquid/strainer_test.rb | 11 +++++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/lib/liquid/context.rb b/lib/liquid/context.rb index 452b750..2687dab 100644 --- a/lib/liquid/context.rb +++ b/lib/liquid/context.rb @@ -25,6 +25,7 @@ module Liquid squash_instance_assigns_with_environments @interrupts = [] + @filters = [] end def resource_limits_reached? @@ -34,7 +35,7 @@ module Liquid end def strainer - @strainer ||= Strainer.create(self) + @strainer ||= Strainer.create(self, @filters) end # Adds filters to this context. @@ -43,11 +44,20 @@ module Liquid # for that def add_filters(filters) filters = [filters].flatten.compact - filters.each do |f| raise ArgumentError, "Expected module but got: #{f.class}" unless f.is_a?(Module) Strainer.add_known_filter(f) - strainer.extend(f) + end + + # If strainer is already setup then there's no choice but to use a runtime + # extend call. If strainer is not yet created, we can utilize strainers + # cached class based API, which avoids busting the method cache. + if @strainer + filters.each do |f| + strainer.extend(f) + end + else + @filters.concat filters end end diff --git a/lib/liquid/strainer.rb b/lib/liquid/strainer.rb index 5e75cdd..0aa3035 100644 --- a/lib/liquid/strainer.rb +++ b/lib/liquid/strainer.rb @@ -11,6 +11,11 @@ module Liquid @@filters = [] @@known_filters = Set.new @@known_methods = Set.new + @@strainer_class_cache = Hash.new do |hash, filters| + hash[filters] = Class.new(Strainer) do + filters.each { |f| include f } + end + end def initialize(context) @context = context @@ -32,10 +37,13 @@ module Liquid end end - def self.create(context) - strainer = Strainer.new(context) - @@filters.each { |m| strainer.extend(m) } - strainer + def self.strainer_class_cache + @@strainer_class_cache + end + + def self.create(context, filters = nil) + filters = @@filters.values + (filters || []) + strainer_class_cache[filters].new(context) end def invoke(method, *args) diff --git a/test/liquid/strainer_test.rb b/test/liquid/strainer_test.rb index 582ed7f..32b3331 100644 --- a/test/liquid/strainer_test.rb +++ b/test/liquid/strainer_test.rb @@ -49,4 +49,15 @@ class StrainerTest < Test::Unit::TestCase assert_equal "has_method?", strainer.invoke("invoke", "has_method?", "invoke") end + def test_strainer_uses_a_class_cache_to_avoid_method_cache_invalidation + a, b = Module.new, Module.new + strainer = Strainer.create(nil, [a,b]) + assert_kind_of Strainer, strainer + assert_kind_of a, strainer + assert_kind_of b, strainer + Strainer.class_variable_get(:@@filters).values.each do |m| + assert_kind_of m, strainer + end + end + end # StrainerTest From d4679cd550e59b0276b44130dafdfc21a79b34ba Mon Sep 17 00:00:00 2001 From: James Tucker Date: Tue, 14 May 2013 07:52:05 -0700 Subject: [PATCH 02/51] Strainer test now works on 1.8 --- test/liquid/strainer_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/liquid/strainer_test.rb b/test/liquid/strainer_test.rb index 32b3331..6bcbe29 100644 --- a/test/liquid/strainer_test.rb +++ b/test/liquid/strainer_test.rb @@ -55,7 +55,7 @@ class StrainerTest < Test::Unit::TestCase assert_kind_of Strainer, strainer assert_kind_of a, strainer assert_kind_of b, strainer - Strainer.class_variable_get(:@@filters).values.each do |m| + Strainer.send(:class_variable_get, :@@filters).values.each do |m| assert_kind_of m, strainer end end From 7c5b3e0c3b5a69f90077ba2ba134a3bc0b037f31 Mon Sep 17 00:00:00 2001 From: Tristan Hume Date: Wed, 4 Sep 2013 18:13:31 -0400 Subject: [PATCH 03/51] Fix bad range parsing. --- lib/liquid/lexer.rb | 2 ++ lib/liquid/parser.rb | 3 +-- test/liquid/parser_test.rb | 8 ++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/liquid/lexer.rb b/lib/liquid/lexer.rb index 32991c9..47a9fc4 100644 --- a/lib/liquid/lexer.rb +++ b/lib/liquid/lexer.rb @@ -15,6 +15,7 @@ module Liquid SINGLE_STRING_LITERAL = /'[^\']*'/ DOUBLE_STRING_LITERAL = /"[^\"]*"/ NUMBER_LITERAL = /-?\d+(\.\d+)?/ + DOTDOT = /\.\./ COMPARISON_OPERATOR = /==|!=|<>|<=?|>=?|contains/ def initialize(input) @@ -32,6 +33,7 @@ module Liquid when t = @ss.scan(DOUBLE_STRING_LITERAL) then [:string, t] when t = @ss.scan(NUMBER_LITERAL) then [:number, t] when t = @ss.scan(IDENTIFIER) then [:id, t] + when t = @ss.scan(DOTDOT) then [:dotdot, t] else c = @ss.getch if s = SPECIALS[c] diff --git a/lib/liquid/parser.rb b/lib/liquid/parser.rb index 9626001..26f235f 100644 --- a/lib/liquid/parser.rb +++ b/lib/liquid/parser.rb @@ -53,8 +53,7 @@ module Liquid elsif token.first == :open_round consume first = expression - consume(:dot) - consume(:dot) + consume(:dotdot) last = expression consume(:close_round) "(#{first}..#{last})" diff --git a/test/liquid/parser_test.rb b/test/liquid/parser_test.rb index c588f12..a9f848f 100644 --- a/test/liquid/parser_test.rb +++ b/test/liquid/parser_test.rb @@ -56,6 +56,14 @@ class ParserTest < Test::Unit::TestCase assert_equal '"wut"', p.expression end + def test_ranges + p = Parser.new("(5..7) (1.5..9.6) (young..old) (hi[5].wat..old)") + assert_equal '(5..7)', p.expression + assert_equal '(1.5..9.6)', p.expression + assert_equal '(young..old)', p.expression + assert_equal '(hi[5].wat..old)', p.expression + end + def test_arguments p = Parser.new("filter: hi.there[5], keyarg: 7") assert_equal 'filter', p.consume(:id) From 13c826933c0c0a7cfe48e8731fc93dc594507561 Mon Sep 17 00:00:00 2001 From: James Tucker Date: Sat, 7 Sep 2013 01:42:41 +0000 Subject: [PATCH 04/51] Update against failed cherry-pick --- lib/liquid/strainer.rb | 2 +- test/liquid/strainer_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/liquid/strainer.rb b/lib/liquid/strainer.rb index 0aa3035..f5d525d 100644 --- a/lib/liquid/strainer.rb +++ b/lib/liquid/strainer.rb @@ -42,7 +42,7 @@ module Liquid end def self.create(context, filters = nil) - filters = @@filters.values + (filters || []) + filters = @@filters + (filters || []) strainer_class_cache[filters].new(context) end diff --git a/test/liquid/strainer_test.rb b/test/liquid/strainer_test.rb index 6bcbe29..b7ec593 100644 --- a/test/liquid/strainer_test.rb +++ b/test/liquid/strainer_test.rb @@ -55,7 +55,7 @@ class StrainerTest < Test::Unit::TestCase assert_kind_of Strainer, strainer assert_kind_of a, strainer assert_kind_of b, strainer - Strainer.send(:class_variable_get, :@@filters).values.each do |m| + Strainer.send(:class_variable_get, :@@filters).each do |m| assert_kind_of m, strainer end end From a5285d3d093fd991bd33df41a548e6fb908feb71 Mon Sep 17 00:00:00 2001 From: Ishibashi Hideto Date: Tue, 10 Sep 2013 22:58:56 +0900 Subject: [PATCH 05/51] =?UTF-8?q?test=20for=20the=20Jekyll's=20issue:=20[L?= =?UTF-8?q?iquid=20doesn't=20render=20my=20partial=20=C2=B7=20Issue=20#151?= =?UTF-8?q?9=20=C2=B7=20mojombo/jekyll](https://github.com/mojombo/jekyll/?= =?UTF-8?q?issues/1519)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/liquid/tags/include_tag_test.rb | 49 ++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/test/liquid/tags/include_tag_test.rb b/test/liquid/tags/include_tag_test.rb index 8bdb19c..56cbc34 100644 --- a/test/liquid/tags/include_tag_test.rb +++ b/test/liquid/tags/include_tag_test.rb @@ -163,4 +163,53 @@ class IncludeTagTest < Test::Unit::TestCase Template.parse("{% include 'pick_a_source' %}").render({}, :registers => {:file_system => file_system}) assert_equal 2, file_system.count end + + def test_include_tag_within_if_statement + assert_equal "foo_if_true", + Template.parse("{% if true %}{% include 'foo_if_true' %}{% endif %}").render + end + + def test_custom_include_tag + original_tag = Liquid::Template.tags['include'] + Liquid::Template.tags['include'] = CustomInclude + begin + assert_equal "custom_foo", + Template.parse("{% include 'custom_foo' %}").render + ensure + Liquid::Template.tags['include'] = original_tag + end + end + + def test_custom_include_tag_within_if_statement + original_tag = Liquid::Template.tags['include'] + Liquid::Template.tags['include'] = CustomInclude + begin + assert_equal "custom_foo_if_true", + Template.parse("{% if true %}{% include 'custom_foo_if_true' %}{% endif %}").render + ensure + Liquid::Template.tags['include'] = original_tag + end + end + + class CustomInclude < Liquid::Tag + include Liquid + Syntax = /(#{QuotedFragment}+)(\s+(?:with|for)\s+(#{QuotedFragment}+))?/o + + def initialize(tag_name, markup, tokens) + markup =~ Syntax + @template_name = $1 + super + end + + def parse(tokens) + end + + def blank? + false + end + + def render(context) + @template_name[1..-2] + end + end end # IncludeTagTest From 70513fccaf159e322dabcbe84d8b96f86cb00081 Mon Sep 17 00:00:00 2001 From: Ishibashi Hideto Date: Wed, 11 Sep 2013 03:25:06 +0900 Subject: [PATCH 06/51] remove `include Liquid` from the class `CustomInclude` and substitute `QuotedFragment` with `Liquid::QuotedFragment` --- test/liquid/tags/include_tag_test.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/liquid/tags/include_tag_test.rb b/test/liquid/tags/include_tag_test.rb index 56cbc34..cd12495 100644 --- a/test/liquid/tags/include_tag_test.rb +++ b/test/liquid/tags/include_tag_test.rb @@ -192,8 +192,7 @@ class IncludeTagTest < Test::Unit::TestCase end class CustomInclude < Liquid::Tag - include Liquid - Syntax = /(#{QuotedFragment}+)(\s+(?:with|for)\s+(#{QuotedFragment}+))?/o + Syntax = /(#{Liquid::QuotedFragment}+)(\s+(?:with|for)\s+(#{Liquid::QuotedFragment}+))?/o def initialize(tag_name, markup, tokens) markup =~ Syntax From 01d352bc51f2ff2b51e0416478449ed4efe940f6 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Wed, 11 Sep 2013 14:40:11 +0200 Subject: [PATCH 07/51] Move stuff in test around --- test/liquid/tags/include_tag_test.rb | 42 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/test/liquid/tags/include_tag_test.rb b/test/liquid/tags/include_tag_test.rb index cd12495..52970e1 100644 --- a/test/liquid/tags/include_tag_test.rb +++ b/test/liquid/tags/include_tag_test.rb @@ -48,6 +48,27 @@ class CountingFileSystem end end +class CustomInclude < Liquid::Tag + Syntax = /(#{Liquid::QuotedFragment}+)(\s+(?:with|for)\s+(#{Liquid::QuotedFragment}+))?/o + + def initialize(tag_name, markup, tokens) + markup =~ Syntax + @template_name = $1 + super + end + + def parse(tokens) + end + + def blank? + false + end + + def render(context) + @template_name[1..-2] + end +end + class IncludeTagTest < Test::Unit::TestCase include Liquid @@ -190,25 +211,4 @@ class IncludeTagTest < Test::Unit::TestCase Liquid::Template.tags['include'] = original_tag end end - - class CustomInclude < Liquid::Tag - Syntax = /(#{Liquid::QuotedFragment}+)(\s+(?:with|for)\s+(#{Liquid::QuotedFragment}+))?/o - - def initialize(tag_name, markup, tokens) - markup =~ Syntax - @template_name = $1 - super - end - - def parse(tokens) - end - - def blank? - false - end - - def render(context) - @template_name[1..-2] - end - end end # IncludeTagTest From 45795f8766b571c1107e7f4107004ce986ec4d64 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Wed, 11 Sep 2013 10:01:04 -0400 Subject: [PATCH 08/51] Fix handling of unknown tags in comments --- lib/liquid/tags/comment.rb | 4 +++- test/liquid/tags/standard_tag_test.rb | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/liquid/tags/comment.rb b/lib/liquid/tags/comment.rb index 1eaf71f..94875a9 100644 --- a/lib/liquid/tags/comment.rb +++ b/lib/liquid/tags/comment.rb @@ -1,5 +1,7 @@ +require "liquid/tags/raw" + module Liquid - class Comment < Block + class Comment < Raw def render(context) '' end diff --git a/test/liquid/tags/standard_tag_test.rb b/test/liquid/tags/standard_tag_test.rb index 4d8bdd3..a592a40 100644 --- a/test/liquid/tags/standard_tag_test.rb +++ b/test/liquid/tags/standard_tag_test.rb @@ -34,6 +34,12 @@ class StandardTagTest < Test::Unit::TestCase assert_template_result('','{%comment%}comment{%endcomment%}') assert_template_result('','{% comment %}comment{% endcomment %}') + assert_template_result('','{%comment%}{%blabla%}{%endcomment%}') + assert_template_result('','{% comment %}{% blabla %}{% endcomment %}') + assert_template_result('','{%comment%}{% endif %}{%endcomment%}') + assert_template_result('','{% comment %}{% endwhatever %}{% endcomment %}') + assert_template_result('','{% comment %} {{ %} {{%%%}} {% endcomment {% endcomment %}') + assert_template_result('foobar','foo{%comment%}comment{%endcomment%}bar') assert_template_result('foobar','foo{% comment %}comment{% endcomment %}bar') assert_template_result('foobar','foo{%comment%} comment {%endcomment%}bar') From f938756a584daaaf6330490af8658b274baac063 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Wed, 11 Sep 2013 12:13:55 -0400 Subject: [PATCH 09/51] Revert "Merge pull request #256 from Shopify/unknown_tags_in_comments" This reverts commit 1ae8c0e90a18e2764d83662c3913f3c8faa3dcad, reversing changes made to 01d352bc51f2ff2b51e0416478449ed4efe940f6. --- lib/liquid/tags/comment.rb | 4 +--- test/liquid/tags/standard_tag_test.rb | 6 ------ 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/liquid/tags/comment.rb b/lib/liquid/tags/comment.rb index 94875a9..1eaf71f 100644 --- a/lib/liquid/tags/comment.rb +++ b/lib/liquid/tags/comment.rb @@ -1,7 +1,5 @@ -require "liquid/tags/raw" - module Liquid - class Comment < Raw + class Comment < Block def render(context) '' end diff --git a/test/liquid/tags/standard_tag_test.rb b/test/liquid/tags/standard_tag_test.rb index a592a40..4d8bdd3 100644 --- a/test/liquid/tags/standard_tag_test.rb +++ b/test/liquid/tags/standard_tag_test.rb @@ -34,12 +34,6 @@ class StandardTagTest < Test::Unit::TestCase assert_template_result('','{%comment%}comment{%endcomment%}') assert_template_result('','{% comment %}comment{% endcomment %}') - assert_template_result('','{%comment%}{%blabla%}{%endcomment%}') - assert_template_result('','{% comment %}{% blabla %}{% endcomment %}') - assert_template_result('','{%comment%}{% endif %}{%endcomment%}') - assert_template_result('','{% comment %}{% endwhatever %}{% endcomment %}') - assert_template_result('','{% comment %} {{ %} {{%%%}} {% endcomment {% endcomment %}') - assert_template_result('foobar','foo{%comment%}comment{%endcomment%}bar') assert_template_result('foobar','foo{% comment %}comment{% endcomment %}bar') assert_template_result('foobar','foo{%comment%} comment {%endcomment%}bar') From bd20595f1ade6e69f44ec0a9c1436ba4a7845ea4 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Wed, 11 Sep 2013 12:14:27 -0400 Subject: [PATCH 10/51] Add regression test for comment tag --- test/liquid/tags/standard_tag_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/liquid/tags/standard_tag_test.rb b/test/liquid/tags/standard_tag_test.rb index 4d8bdd3..6ce18fa 100644 --- a/test/liquid/tags/standard_tag_test.rb +++ b/test/liquid/tags/standard_tag_test.rb @@ -33,6 +33,7 @@ class StandardTagTest < Test::Unit::TestCase assert_template_result('','{% comment %}{% endcomment %}') assert_template_result('','{%comment%}comment{%endcomment%}') assert_template_result('','{% comment %}comment{% endcomment %}') + assert_template_result('','{% comment %} 1 {% comment %} 2 {% endcomment %} 3 {% endcomment %}') assert_template_result('foobar','foo{%comment%}comment{%endcomment%}bar') assert_template_result('foobar','foo{% comment %}comment{% endcomment %}bar') From 5b172a4c058a4b54d8ce285dae80a5a1630241df Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Wed, 11 Sep 2013 12:31:54 -0400 Subject: [PATCH 11/51] Fix unknown tags in comment tags, second try --- lib/liquid/tags/comment.rb | 3 +++ test/liquid/tags/standard_tag_test.rb | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/lib/liquid/tags/comment.rb b/lib/liquid/tags/comment.rb index 1eaf71f..099310e 100644 --- a/lib/liquid/tags/comment.rb +++ b/lib/liquid/tags/comment.rb @@ -4,6 +4,9 @@ module Liquid '' end + def unknown_tag(tag, markup, tokens) + end + def blank? true end diff --git a/test/liquid/tags/standard_tag_test.rb b/test/liquid/tags/standard_tag_test.rb index 6ce18fa..58d125e 100644 --- a/test/liquid/tags/standard_tag_test.rb +++ b/test/liquid/tags/standard_tag_test.rb @@ -35,6 +35,12 @@ class StandardTagTest < Test::Unit::TestCase assert_template_result('','{% comment %}comment{% endcomment %}') assert_template_result('','{% comment %} 1 {% comment %} 2 {% endcomment %} 3 {% endcomment %}') + assert_template_result('','{%comment%}{%blabla%}{%endcomment%}') + assert_template_result('','{% comment %}{% blabla %}{% endcomment %}') + assert_template_result('','{%comment%}{% endif %}{%endcomment%}') + assert_template_result('','{% comment %}{% endwhatever %}{% endcomment %}') + assert_template_result('','{% comment %}{% raw %} {{%%%%}} }} { {% endcomment %} {% comment {% endraw %} {% endcomment %}') + assert_template_result('foobar','foo{%comment%}comment{%endcomment%}bar') assert_template_result('foobar','foo{% comment %}comment{% endcomment %}bar') assert_template_result('foobar','foo{%comment%} comment {%endcomment%}bar') From 6ce0b9d7056dac760093c0137475f26a6a1d42d7 Mon Sep 17 00:00:00 2001 From: Simon Eskildsen Date: Mon, 16 Sep 2013 14:35:33 -0400 Subject: [PATCH 12/51] Fix i18n regex warning in Ruby 1.8 --- lib/liquid/i18n.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/liquid/i18n.rb b/lib/liquid/i18n.rb index de90e99..205b740 100644 --- a/lib/liquid/i18n.rb +++ b/lib/liquid/i18n.rb @@ -24,7 +24,7 @@ module Liquid private def interpolate(name, vars) - name.gsub(/%{(\w+)}/) { + name.gsub(/%\{(\w+)\}/) { # raise TranslationError, "Undefined key #{$1} for interpolation in translation #{name}" unless vars[$1.to_sym] "#{vars[$1.to_sym]}" } From 2efe809e11ee5db6feea5e62d6c6585471f9f8b5 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Mon, 23 Sep 2013 08:43:26 -0400 Subject: [PATCH 13/51] Make blank? default to false for all tags to maintain backwards compatible --- lib/liquid/tag.rb | 2 +- lib/liquid/tags/assign.rb | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/liquid/tag.rb b/lib/liquid/tag.rb index c119562..eb2934b 100644 --- a/lib/liquid/tag.rb +++ b/lib/liquid/tag.rb @@ -31,7 +31,7 @@ module Liquid end def blank? - @blank || true + @blank || false end def parse_with_selected_parser(markup) diff --git a/lib/liquid/tags/assign.rb b/lib/liquid/tags/assign.rb index 45c6bed..0af0976 100644 --- a/lib/liquid/tags/assign.rb +++ b/lib/liquid/tags/assign.rb @@ -29,6 +29,9 @@ module Liquid '' end + def blank? + true + end end Template.register_tag('assign', Assign) From 81d3733f57d6997ae018790267da75714b9bd38b Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Mon, 23 Sep 2013 09:38:45 -0400 Subject: [PATCH 14/51] Regression test for change of blank? default behaviour (2efe809e11ee5db6feea5e62d6c6585471f9f8b5) --- test/liquid/blank_test.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/liquid/blank_test.rb b/test/liquid/blank_test.rb index 8c039f7..d2e2f73 100644 --- a/test/liquid/blank_test.rb +++ b/test/liquid/blank_test.rb @@ -1,5 +1,13 @@ require 'test_helper' +class FoobarTag < Liquid::Tag + def render(*args) + " " + end + + Liquid::Template.register_tag('foobar', FoobarTag) +end + class BlankTestFileSystem def read_template_file(template_path, context) template_path @@ -22,6 +30,10 @@ class BlankTest < Test::Unit::TestCase wrap_in_for(body) + wrap_in_if(body) end + def test_new_tags_are_not_blank_by_default + assert_template_result(" "*N, wrap_in_for("{% foobar %}")) + end + def test_loops_are_blank assert_template_result("", wrap_in_for(" ")) end From 96b30a89a95e4fc37f51a15280c8edcc8d91e61e Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Tue, 8 Oct 2013 08:18:03 -0400 Subject: [PATCH 15/51] Fix map filter on Hash inputs --- lib/liquid/standardfilters.rb | 2 +- test/liquid/standard_filter_test.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/liquid/standardfilters.rb b/lib/liquid/standardfilters.rb index b7f6418..718a8d9 100644 --- a/lib/liquid/standardfilters.rb +++ b/lib/liquid/standardfilters.rb @@ -250,7 +250,7 @@ module Liquid def flatten_if_necessary(input) ary = if input.is_a?(Array) input.flatten - elsif input.kind_of?(Enumerable) + elsif input.is_a?(Enumerable) && !input.is_a?(Hash) input else [input].flatten diff --git a/test/liquid/standard_filter_test.rb b/test/liquid/standard_filter_test.rb index b317b68..fc1a3cb 100644 --- a/test/liquid/standard_filter_test.rb +++ b/test/liquid/standard_filter_test.rb @@ -140,6 +140,10 @@ class StandardFiltersTest < Test::Unit::TestCase assert_equal "woot: 1", Liquid::Template.parse('{{ foo | map: "whatever" }}').render("foo" => [t]) end + def test_map_on_hashes + assert_equal "4217", Liquid::Template.parse('{{ thing | map: "foo" | map: "bar" }}').render("thing" => { "foo" => [ { "bar" => 42 }, { "bar" => 17 } ] }) + end + def test_sort_calls_to_liquid t = TestThing.new assert_equal "woot: 1", Liquid::Template.parse('{{ foo | sort: "whatever" }}').render("foo" => [t]) From 534338f92368bd07e78721c9c97ce454252e37e1 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Wed, 9 Oct 2013 17:11:19 -0400 Subject: [PATCH 16/51] Update history Add 3.0.0 history Add changes related to 2.5.x --- History.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/History.md b/History.md index b4517e9..e148af9 100644 --- a/History.md +++ b/History.md @@ -1,9 +1,6 @@ # Liquid Version History -IMPORTANT: Liquid 2.6 is going to be the last version of Liquid which maintains explicit Ruby 1.8 compatability. -The following releases will only be tested against Ruby 1.9 and Ruby 2.0 and are likely to break on Ruby 1.8. - -## 2.6.0 / Master branch (not yet released) +## 3.0.0 / not yet released / branch "master" * ... * Add optional strict parsing and warn parsing, see #235 [Tristan Hume, trishume] @@ -11,8 +8,13 @@ The following releases will only be tested against Ruby 1.9 and Ruby 2.0 and are * Make sort filter work on enumerable drops, see #239 [Florian Weingarten, fw42] * Fix clashing method names in enumerable drops, see #238 [Florian Weingarten, fw42] * Make map filter work on enumerable drops, see #233 [Florian Weingarten, fw42] -* Fix security issue with map filter, see #230, #232, #234, #237 [Florian Weingarten, fw42] * Improved whitespace stripping for blank blocks, related to #216 [Florian Weingarten, fw42] + +## 2.6.0 / not yet released / branch "2.6-stable" + +IMPORTANT: Liquid 2.6 is going to be the last version of Liquid which maintains explicit Ruby 1.8 compatability. +The following releases will only be tested against Ruby 1.9 and Ruby 2.0 and are likely to break on Ruby 1.8. + * Bugfix for #106: fix example servlet [gnowoel] * Bugfix for #97: strip_html filter supports multi-line tags [Jo Liss, joliss] * Bugfix for #114: strip_html filter supports style tags [James Allardice, jamesallardice] @@ -31,6 +33,17 @@ The following releases will only be tested against Ruby 1.9 and Ruby 2.0 and are * Better documentation for 'include' tag (closes #163) [Peter Schröder, phoet] * Use of BigDecimal on filters to have better precision (closes #155) [Arthur Nogueira Neves, arthurnn] +## 2.5.3 / 2013-10-09 / branch "2.5-stable" + +* #232, #234, #237: Fix map filter bugs [Florian Weingarten, fw42] + +## 2.5.2 / 2013-09-03 / deleted + +Yanked from rubygems, as it contained too many changes that broke compatibility. Those changes will be on following major releases. + +## 2.5.1 / 2013-07-24 + +* #230: Fix security issue with map filter, Use invoke_drop in map filter [Florian Weingarten, fw42] ## 2.5.0 / 2013-03-06 From fa3155fdcc62648b96ce28ea3243e44d9338bf2d Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Wed, 9 Oct 2013 17:12:03 -0400 Subject: [PATCH 17/51] Bump version to 3.0.0 --- lib/liquid/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/liquid/version.rb b/lib/liquid/version.rb index ee4d213..d27c6d3 100644 --- a/lib/liquid/version.rb +++ b/lib/liquid/version.rb @@ -1,4 +1,4 @@ # encoding: utf-8 module Liquid - VERSION = "2.6.0" + VERSION = "3.0.0" end From 5db1695694e1cbf12892d5dd67c7773282a669af Mon Sep 17 00:00:00 2001 From: Derrick Reimer Date: Wed, 9 Oct 2013 16:07:32 -0700 Subject: [PATCH 18/51] Add default filter to standard filters --- lib/liquid/standardfilters.rb | 5 +++++ test/liquid/standard_filter_test.rb | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/lib/liquid/standardfilters.rb b/lib/liquid/standardfilters.rb index 718a8d9..c938f3a 100644 --- a/lib/liquid/standardfilters.rb +++ b/lib/liquid/standardfilters.rb @@ -245,6 +245,11 @@ module Liquid apply_operation(input, operand, :%) end + def default(input, default_value = "") + is_blank = input.respond_to?(:empty?) ? input.empty? : !input + is_blank ? default_value : input + end + private def flatten_if_necessary(input) diff --git a/test/liquid/standard_filter_test.rb b/test/liquid/standard_filter_test.rb index fc1a3cb..91c219d 100644 --- a/test/liquid/standard_filter_test.rb +++ b/test/liquid/standard_filter_test.rb @@ -274,6 +274,15 @@ class StandardFiltersTest < Test::Unit::TestCase assert_template_result('abc',"{{ a | prepend: b}}",assigns) end + def test_default + assert_equal "foo", @filters.default("foo", "bar") + assert_equal "bar", @filters.default(nil, "bar") + assert_equal "bar", @filters.default("", "bar") + assert_equal "bar", @filters.default(false, "bar") + assert_equal "bar", @filters.default([], "bar") + assert_equal "bar", @filters.default({}, "bar") + end + def test_cannot_access_private_methods assert_template_result('a',"{{ 'a' | to_number }}") end From 0644da02bbae2123109b59685f401cb9e9e8511c Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Thu, 10 Oct 2013 10:44:16 -0400 Subject: [PATCH 19/51] Improve Rakefile --- Rakefile | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/Rakefile b/Rakefile index 137b8e3..219b7cc 100755 --- a/Rakefile +++ b/Rakefile @@ -1,9 +1,7 @@ -#!/usr/bin/env ruby - -require 'rubygems' require 'rake' require 'rake/testtask' -require 'rubygems/package_task' +$LOAD_PATH.unshift File.expand_path("../lib", __FILE__) +require "liquid/version" task :default => 'test' @@ -29,14 +27,20 @@ task :test do Rake::Task['base_test'].invoke end -gemspec = eval(File.read('liquid.gemspec')) -Gem::PackageTask.new(gemspec) do |pkg| - pkg.gem_spec = gemspec +task :gem => :build +task :build do + system "gem build liquid.gemspec" end -desc "Build the gem and release it to rubygems.org" -task :release => :gem do - sh "gem push pkg/liquid-#{gemspec.version}.gem" +task :install => :build do + system "gem install liquid-#{Liquid::VERSION}.gem" +end + +task :release => :build do + system "git tag -a v#{Liquid::VERSION} -m 'Tagging #{Liquid::VERSION}'" + system "git push --tags" + system "gem push liquid-#{Liquid::VERSION}.gem" + system "rm liquid-#{Liquid::VERSION}.gem" end namespace :benchmark do From 6710ef60bc088b7721a6b09b5db722e4653e96da Mon Sep 17 00:00:00 2001 From: Derrick Reimer Date: Thu, 10 Oct 2013 09:15:01 -0700 Subject: [PATCH 20/51] Add default filter to history --- History.md | 1 + 1 file changed, 1 insertion(+) diff --git a/History.md b/History.md index e148af9..35fde61 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,7 @@ ## 3.0.0 / not yet released / branch "master" * ... +* Add default filter to standard filters, see #267 [Derrick Reimer, djreimer] * Add optional strict parsing and warn parsing, see #235 [Tristan Hume, trishume] * Add I18n syntax error translation, see #241 [Simon Hørup Eskildsen, Sirupsen] * Make sort filter work on enumerable drops, see #239 [Florian Weingarten, fw42] From c9ea578b640571b5a11e844301068ba0fb79410b Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Fri, 11 Oct 2013 12:03:01 -0400 Subject: [PATCH 21/51] Drop 1.8 support on travis CI and add 2.0.0 --- .travis.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index fb899f9..2e5359e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,13 @@ rvm: - - 1.8.7 - 1.9.3 - - ree - - jruby-18mode + - 2.0.0 - jruby-19mode - - rbx-18mode + - jruby-head - rbx-19mode +matrix: + allow_failures: + - rvm: 2.0.0 + - rvm: jruby-head script: "rake test" From 7e1a0be752d7bbf51dd30d78644c3babca389532 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Fri, 11 Oct 2013 12:08:19 -0400 Subject: [PATCH 22/51] Put travis badge on top --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 481f18e..0d81dd9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Build Status](https://secure.travis-ci.org/Shopify/liquid.png)](http://travis-ci.org/Shopify/liquid) # Liquid template engine * [Contributing guidelines](CONTRIBUTING.md) @@ -71,5 +72,3 @@ This is useful for doing things like enabling strict mode only in the theme edit It is recommended that you enable `:strict` or `:warn` mode on new apps to stop invalid templates from being created. It is also recommended that you use it in the template editors of existing apps to give editors better error messages. - -[![Build Status](https://secure.travis-ci.org/Shopify/liquid.png)](http://travis-ci.org/Shopify/liquid) From 9b910a4e6d433cb00c40bc0cb9ecefcd45fcfb71 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Tue, 15 Oct 2013 13:14:39 -0400 Subject: [PATCH 23/51] Update README.md Remove old wiki link --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 0d81dd9..95b8089 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ * [Contributing guidelines](CONTRIBUTING.md) * [Version history](History.md) * [Liquid documentation from Shopify](http://docs.shopify.com/themes/liquid-basics) -* [Liquid Wiki from Shopify](http://wiki.shopify.com/Liquid) * [Liquid Wiki at GitHub](https://github.com/Shopify/liquid/wiki) * [Website](http://liquidmarkup.org/) From 5eddfe87d0030c1d5073e97e0bfccf19da660abb Mon Sep 17 00:00:00 2001 From: Joost Hietbrink Date: Wed, 16 Oct 2013 11:55:12 +0200 Subject: [PATCH 24/51] Support for passing variables to snippets in subdirs Now you can use "include 'some/snippet' with variable". --- lib/liquid/tags/include.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/liquid/tags/include.rb b/lib/liquid/tags/include.rb index 76448f8..1d0ce66 100644 --- a/lib/liquid/tags/include.rb +++ b/lib/liquid/tags/include.rb @@ -51,13 +51,14 @@ module Liquid context[key] = context[value] end + context_variable_name = @template_name[1..-2].split('/').last # for a snippet in a subdir only use the filename if variable.is_a?(Array) variable.collect do |var| - context[@template_name[1..-2]] = var + context[context_variable_name] = var partial.render(context) end else - context[@template_name[1..-2]] = variable + context[context_variable_name] = variable partial.render(context) end end From 511ee7fbe16bdfba3368357101773872404818f6 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 28 Oct 2013 13:56:11 +0100 Subject: [PATCH 25/51] Remove to_sym from condition creation This prevents a DoS http://www.tricksonrails.com/2010/06/avoid-memory-leaks-in-ruby-rails-code-and-protect-against-denial-of-service/ --- lib/liquid/tags/if.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/liquid/tags/if.rb b/lib/liquid/tags/if.rb index c376f6c..1b46b2c 100644 --- a/lib/liquid/tags/if.rb +++ b/lib/liquid/tags/if.rb @@ -63,7 +63,7 @@ module Liquid raise(SyntaxError.new(options[:locale].t("errors.syntax.if"))) unless expressions.shift.to_s =~ Syntax new_condition = Condition.new($1, $2, $3) - new_condition.send(operator.to_sym, condition) + new_condition.send(operator, condition) condition = new_condition end From a5cd661dd9d77c620b38cd0b4593285b1ea34510 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 28 Oct 2013 13:56:57 +0100 Subject: [PATCH 26/51] Use public_send on condition creation This makes sure you can't call Kernel methods like `throw` --- lib/liquid/tags/if.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/liquid/tags/if.rb b/lib/liquid/tags/if.rb index 1b46b2c..ce086ef 100644 --- a/lib/liquid/tags/if.rb +++ b/lib/liquid/tags/if.rb @@ -63,7 +63,7 @@ module Liquid raise(SyntaxError.new(options[:locale].t("errors.syntax.if"))) unless expressions.shift.to_s =~ Syntax new_condition = Condition.new($1, $2, $3) - new_condition.send(operator, condition) + new_condition.public_send(operator, condition) condition = new_condition end From 2f50a0c42273fe17347a9d792b2b0f36f4803e67 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 28 Oct 2013 14:10:13 +0100 Subject: [PATCH 27/51] Add history message --- History.md | 1 + 1 file changed, 1 insertion(+) diff --git a/History.md b/History.md index 35fde61..161688a 100644 --- a/History.md +++ b/History.md @@ -10,6 +10,7 @@ * Fix clashing method names in enumerable drops, see #238 [Florian Weingarten, fw42] * Make map filter work on enumerable drops, see #233 [Florian Weingarten, fw42] * Improved whitespace stripping for blank blocks, related to #216 [Florian Weingarten, fw42] +* Don't call to_sym when creating conditions and use public_send for security reasons, see #273 [Bouke van der Bijl, bouk] ## 2.6.0 / not yet released / branch "2.6-stable" From cc982e92d0329f27ea38e525b01f9adfbff26614 Mon Sep 17 00:00:00 2001 From: Dylan Thacker-Smith Date: Mon, 28 Oct 2013 11:19:25 -0400 Subject: [PATCH 28/51] security: Prevent arbitrary method invocation on conditions in if tag. --- History.md | 3 ++- lib/liquid/tags/if.rb | 4 +++- test/liquid/tags/if_else_tag_test.rb | 6 ++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 161688a..d402b5f 100644 --- a/History.md +++ b/History.md @@ -10,7 +10,8 @@ * Fix clashing method names in enumerable drops, see #238 [Florian Weingarten, fw42] * Make map filter work on enumerable drops, see #233 [Florian Weingarten, fw42] * Improved whitespace stripping for blank blocks, related to #216 [Florian Weingarten, fw42] -* Don't call to_sym when creating conditions and use public_send for security reasons, see #273 [Bouke van der Bijl, bouk] +* Don't call to_sym when creating conditions for security reasons, see #273 [Bouke van der Bijl, bouk] +* Prevent arbitrary method invocation on condition objects, see #274 [Dylan Thacker-Smith, dylanahsmith] ## 2.6.0 / not yet released / branch "2.6-stable" diff --git a/lib/liquid/tags/if.rb b/lib/liquid/tags/if.rb index ce086ef..2225e8f 100644 --- a/lib/liquid/tags/if.rb +++ b/lib/liquid/tags/if.rb @@ -12,6 +12,7 @@ module Liquid 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) def initialize(tag_name, markup, tokens) @blocks = [] @@ -63,7 +64,8 @@ module Liquid raise(SyntaxError.new(options[:locale].t("errors.syntax.if"))) unless expressions.shift.to_s =~ Syntax new_condition = Condition.new($1, $2, $3) - new_condition.public_send(operator, condition) + raise(SyntaxError.new(options[:locale].t("errors.syntax.if"))) unless BOOLEAN_OPERATORS.include?(operator) + new_condition.send(operator, condition) condition = new_condition end diff --git a/test/liquid/tags/if_else_tag_test.rb b/test/liquid/tags/if_else_tag_test.rb index 1282c2d..19869fb 100644 --- a/test/liquid/tags/if_else_tag_test.rb +++ b/test/liquid/tags/if_else_tag_test.rb @@ -157,4 +157,10 @@ class IfElseTagTest < Test::Unit::TestCase assert_template_result('yes', %({% if 'gnomeslab-and-or-liquid' contains 'gnomeslab-and-or-liquid' %}yes{% endif %})) end + + def test_operators_are_whitelisted + assert_raise(SyntaxError) do + assert_template_result('', %({% if 1 or throw or or 1 %}yes{% endif %})) + end + end end # IfElseTest From a599a26f1abfc06bc03608c6c210e73509757c8a Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Thu, 31 Oct 2013 15:33:56 -0400 Subject: [PATCH 29/51] Remove some legacy Ruby 1.8 compatibility code --- History.md | 1 + lib/liquid/drop.rb | 9 ++++----- lib/liquid/standardfilters.rb | 3 +-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/History.md b/History.md index 35fde61..2d940ba 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,7 @@ ## 3.0.0 / not yet released / branch "master" * ... +* Remove some legacy Ruby 1.8 compatibility code, see #276 [Florian Weingarten, fw42] * Add default filter to standard filters, see #267 [Derrick Reimer, djreimer] * Add optional strict parsing and warn parsing, see #235 [Tristan Hume, trishume] * Add I18n syntax error translation, see #241 [Simon Hørup Eskildsen, Sirupsen] diff --git a/lib/liquid/drop.rb b/lib/liquid/drop.rb index f1bf48a..d4e5941 100644 --- a/lib/liquid/drop.rb +++ b/lib/liquid/drop.rb @@ -59,13 +59,12 @@ module Liquid # Check for method existence without invoking respond_to?, which creates symbols def self.invokable?(method_name) unless @invokable_methods - # Ruby 1.8 compatibility: call to_s on method names (which are strings in 1.8, but already symbols in 1.9) - blacklist = (Liquid::Drop.public_instance_methods + [:each]).map(&:to_s) + blacklist = Liquid::Drop.public_instance_methods + [:each] if include?(Enumerable) - blacklist += Enumerable.public_instance_methods.map(&:to_s) - blacklist -= [:sort, :count, :first, :min, :max, :include?].map(&:to_s) + blacklist += Enumerable.public_instance_methods + blacklist -= [:sort, :count, :first, :min, :max, :include?] end - whitelist = [:to_liquid] + (public_instance_methods.map(&:to_s) - blacklist.map(&:to_s)) + whitelist = [:to_liquid] + (public_instance_methods - blacklist) @invokable_methods = Set.new(whitelist.map(&:to_s)) end @invokable_methods.include?(method_name.to_s) diff --git a/lib/liquid/standardfilters.rb b/lib/liquid/standardfilters.rb index c938f3a..54ab799 100644 --- a/lib/liquid/standardfilters.rb +++ b/lib/liquid/standardfilters.rb @@ -43,8 +43,7 @@ module Liquid if input.nil? then return end l = length.to_i - truncate_string.length l = 0 if l < 0 - truncated = RUBY_VERSION[0,3] == "1.8" ? input.scan(/./mu)[0...l].to_s : input[0...l] - input.length > length.to_i ? truncated + truncate_string : input + input.length > length.to_i ? input[0...l] + truncate_string : input end def truncatewords(input, words = 15, truncate_string = "...") From 78c42bce44f1a00a0bbfe61c2336fc384c2a7d4e Mon Sep 17 00:00:00 2001 From: Arthur Nogueira Neves Date: Mon, 4 Nov 2013 18:37:53 -0500 Subject: [PATCH 30/51] Update README.md Show travis badge from master only. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 95b8089..6572520 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://secure.travis-ci.org/Shopify/liquid.png)](http://travis-ci.org/Shopify/liquid) +[![Build Status](https://secure.travis-ci.org/Shopify/liquid.png?branch=master)](http://travis-ci.org/Shopify/liquid) # Liquid template engine * [Contributing guidelines](CONTRIBUTING.md) From f015d804eaca84417623897b1c942d0779e6af03 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Mon, 11 Nov 2013 09:03:39 -0500 Subject: [PATCH 31/51] Update history --- History.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 3434814..7ed1fa6 100644 --- a/History.md +++ b/History.md @@ -19,6 +19,7 @@ IMPORTANT: Liquid 2.6 is going to be the last version of Liquid which maintains explicit Ruby 1.8 compatability. The following releases will only be tested against Ruby 1.9 and Ruby 2.0 and are likely to break on Ruby 1.8. +* ... * Bugfix for #106: fix example servlet [gnowoel] * Bugfix for #97: strip_html filter supports multi-line tags [Jo Liss, joliss] * Bugfix for #114: strip_html filter supports style tags [James Allardice, jamesallardice] @@ -27,6 +28,7 @@ The following releases will only be tested against Ruby 1.9 and Ruby 2.0 and are * Bugfix for #204: 'raw' parsing bug [Florian Weingarten, fw42] * Bugfix for #150: 'for' parsing bug [Peter Schröder, phoet] * Bugfix for #126: Strip CRLF in strip_newline [Peter Schröder, phoet] +* Bugfix for #174, "can't convert Fixnum into String" for "replace" [wǒ_is神仙, jsw0528] * Allow a Liquid::Drop to be passed into Template#render [Daniel Huckstep, darkhelmet] * Resource limits [Florian Weingarten, fw42] * Add reverse filter [Jay Strybis, unreal] @@ -37,7 +39,11 @@ The following releases will only be tested against Ruby 1.9 and Ruby 2.0 and are * Better documentation for 'include' tag (closes #163) [Peter Schröder, phoet] * Use of BigDecimal on filters to have better precision (closes #155) [Arthur Nogueira Neves, arthurnn] -## 2.5.3 / 2013-10-09 / branch "2.5-stable" +## 2.5.4 / 2013-11-11 / branch "2.5-stable" + +* Fix "can't convert Fixnum into String" for "replace", see #173, [wǒ_is神仙, jsw0528] + +## 2.5.3 / 2013-10-09 * #232, #234, #237: Fix map filter bugs [Florian Weingarten, fw42] From cf49b06ccc19f86704cae9f4f319032092f3d78a Mon Sep 17 00:00:00 2001 From: Tom Burns Date: Sun, 24 Nov 2013 12:29:15 -0500 Subject: [PATCH 32/51] allow drops to optimize loading a slice of elements --- lib/liquid/tags/for.rb | 7 +++-- test/liquid/tags/for_tag_test.rb | 48 ++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/lib/liquid/tags/for.rb b/lib/liquid/tags/for.rb index 5902704..c8887e9 100644 --- a/lib/liquid/tags/for.rb +++ b/lib/liquid/tags/for.rb @@ -75,8 +75,11 @@ module Liquid limit = context[@attributes['limit']] to = limit ? limit.to_i + from : nil - - segment = Utils.slice_collection_using_each(collection, from, to) + segment = if (from != 0 || to != nil) && collection.respond_to?(:load_slice) + collection.load_slice(from, to) + else + Utils.slice_collection_using_each(collection, from, to) + end return render_else(context) if segment.empty? diff --git a/test/liquid/tags/for_tag_test.rb b/test/liquid/tags/for_tag_test.rb index 9186d3f..b98f7f0 100644 --- a/test/liquid/tags/for_tag_test.rb +++ b/test/liquid/tags/for_tag_test.rb @@ -294,4 +294,52 @@ HERE assigns = {'items' => [1,2,3,4,5]} assert_template_result(expected, template, assigns) end + + class LoaderDrop < Liquid::Drop + attr_accessor :each_called, :load_slice_called + + def initialize(data) + @data = data + end + + def each + @each_called = true + @data.each { |el| yield el } + end + + def load_slice(from, to) + @load_slice_called = true + @data[(from..to-1)] + end + end + + def test_iterate_with_each_when_no_limit_applied + loader = LoaderDrop.new([1,2,3,4,5]) + assigns = {'items' => loader} + expected = '12345' + template = '{% for item in items %}{{item}}{% endfor %}' + assert_template_result(expected, template, assigns) + assert loader.each_called + assert !loader.load_slice_called + end + + def test_iterate_with_load_slice_when_limit_applied + loader = LoaderDrop.new([1,2,3,4,5]) + assigns = {'items' => loader} + expected = '1' + template = '{% for item in items limit:1 %}{{item}}{% endfor %}' + assert_template_result(expected, template, assigns) + assert !loader.each_called + assert loader.load_slice_called + end + + def test_iterate_with_load_slice_when_limit_and_offset_applied + loader = LoaderDrop.new([1,2,3,4,5]) + assigns = {'items' => loader} + expected = '34' + template = '{% for item in items offset:2 limit:2 %}{{item}}{% endfor %}' + assert_template_result(expected, template, assigns) + assert !loader.each_called + assert loader.load_slice_called + end end From 2c26a880f0cee54bde80db171a8fceecba251c79 Mon Sep 17 00:00:00 2001 From: Tom Burns Date: Sun, 24 Nov 2013 12:32:32 -0500 Subject: [PATCH 33/51] add another test showing equivalent functionality --- test/liquid/tags/for_tag_test.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/liquid/tags/for_tag_test.rb b/test/liquid/tags/for_tag_test.rb index b98f7f0..4dde8a4 100644 --- a/test/liquid/tags/for_tag_test.rb +++ b/test/liquid/tags/for_tag_test.rb @@ -342,4 +342,14 @@ HERE assert !loader.each_called assert loader.load_slice_called end + + def test_iterate_with_load_slice_returns_same_results_as_without + loader = LoaderDrop.new([1,2,3,4,5]) + loader_assigns = {'items' => loader} + array_assigns = {'items' => [1,2,3,4,5]} + expected = '34' + template = '{% for item in items offset:2 limit:2 %}{{item}}{% endfor %}' + assert_template_result(expected, template, loader_assigns) + assert_template_result(expected, template, array_assigns) + end end From e6673526294426404a54b2f137632852828a20e7 Mon Sep 17 00:00:00 2001 From: Tom Burns Date: Sun, 24 Nov 2013 14:00:23 -0500 Subject: [PATCH 34/51] move slice_collection optimization to utils --- lib/liquid/htmltags.rb | 2 +- lib/liquid/tags/for.rb | 6 +----- lib/liquid/utils.rb | 19 +++++++++++++++---- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/lib/liquid/htmltags.rb b/lib/liquid/htmltags.rb index 05b0419..8ceab44 100644 --- a/lib/liquid/htmltags.rb +++ b/lib/liquid/htmltags.rb @@ -23,7 +23,7 @@ module Liquid from = @attributes['offset'] ? context[@attributes['offset']].to_i : 0 to = @attributes['limit'] ? from + context[@attributes['limit']].to_i : nil - collection = Utils.slice_collection_using_each(collection, from, to) + collection = Utils.slice_collection(collection, from, to) length = collection.length diff --git a/lib/liquid/tags/for.rb b/lib/liquid/tags/for.rb index c8887e9..9955b5e 100644 --- a/lib/liquid/tags/for.rb +++ b/lib/liquid/tags/for.rb @@ -75,11 +75,7 @@ module Liquid limit = context[@attributes['limit']] to = limit ? limit.to_i + from : nil - segment = if (from != 0 || to != nil) && collection.respond_to?(:load_slice) - collection.load_slice(from, to) - else - Utils.slice_collection_using_each(collection, from, to) - end + segment = Utils.slice_collection(collection, from, to) return render_else(context) if segment.empty? diff --git a/lib/liquid/utils.rb b/lib/liquid/utils.rb index 0bf6df2..fa409e4 100644 --- a/lib/liquid/utils.rb +++ b/lib/liquid/utils.rb @@ -1,5 +1,20 @@ module Liquid module Utils + + def self.slice_collection(collection, from, to) + if (from != 0 || to != nil) && collection.respond_to?(:load_slice) + collection.load_slice(from, to) + else + slice_collection_using_each(collection, from, to) + end + end + + def self.non_blank_string?(collection) + collection.is_a?(String) && collection != '' + end + + private + def self.slice_collection_using_each(collection, from, to) segments = [] index = 0 @@ -22,9 +37,5 @@ module Liquid segments end - - def self.non_blank_string?(collection) - collection.is_a?(String) && collection != '' - end end end From c264459931dbdf3cd9be3e802e713402183dc120 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Mon, 25 Nov 2013 10:25:39 -0500 Subject: [PATCH 35/51] Update history log Conflicts: History.md --- History.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/History.md b/History.md index 7ed1fa6..7777e85 100644 --- a/History.md +++ b/History.md @@ -14,12 +14,11 @@ * Don't call to_sym when creating conditions for security reasons, see #273 [Bouke van der Bijl, bouk] * Prevent arbitrary method invocation on condition objects, see #274 [Dylan Thacker-Smith, dylanahsmith] -## 2.6.0 / not yet released / branch "2.6-stable" +## 2.6.0 / 2013-11-25 / branch "2.6-stable" IMPORTANT: Liquid 2.6 is going to be the last version of Liquid which maintains explicit Ruby 1.8 compatability. The following releases will only be tested against Ruby 1.9 and Ruby 2.0 and are likely to break on Ruby 1.8. -* ... * Bugfix for #106: fix example servlet [gnowoel] * Bugfix for #97: strip_html filter supports multi-line tags [Jo Liss, joliss] * Bugfix for #114: strip_html filter supports style tags [James Allardice, jamesallardice] From 7989e834f30a99780cf0827ad6108b971ac43ad9 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Mon, 25 Nov 2013 10:33:41 -0500 Subject: [PATCH 36/51] Allow rbx failure and not 2.0.0 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2e5359e..d16629c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ rvm: - rbx-19mode matrix: allow_failures: - - rvm: 2.0.0 + - rvm: rbx-19mode - rvm: jruby-head script: "rake test" From d465d5e20c7585fbbee5e73046c2d554f9941fcf Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Mon, 25 Nov 2013 10:35:24 -0500 Subject: [PATCH 37/51] Add ruby 2.1 on travis --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index d16629c..f668296 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,13 @@ rvm: - 1.9.3 - 2.0.0 + - ruby-head - jruby-19mode - jruby-head - rbx-19mode matrix: allow_failures: + - rvm: ruby-head - rvm: rbx-19mode - rvm: jruby-head From 30e5f06313f0b7b0b37b37dba89af45cfef20ee2 Mon Sep 17 00:00:00 2001 From: Tom Burns Date: Mon, 25 Nov 2013 10:37:10 -0500 Subject: [PATCH 38/51] don't make original slice_collection_using_each private --- lib/liquid/utils.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/liquid/utils.rb b/lib/liquid/utils.rb index fa409e4..cb96524 100644 --- a/lib/liquid/utils.rb +++ b/lib/liquid/utils.rb @@ -13,8 +13,6 @@ module Liquid collection.is_a?(String) && collection != '' end - private - def self.slice_collection_using_each(collection, from, to) segments = [] index = 0 From f1a5f6899ba0315b6165e821b26c1611fa3cd42e Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Mon, 25 Nov 2013 10:48:03 -0500 Subject: [PATCH 39/51] Add raggi's change to History, remove Ruby 1.8 code from test --- History.md | 1 + lib/liquid/strainer.rb | 4 ++-- test/liquid/strainer_test.rb | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 7777e85..ba21d87 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,7 @@ ## 3.0.0 / not yet released / branch "master" * ... +* Add a class cache to avoid runtime extend calls, see #249 [James Tucker, raggi] * Remove some legacy Ruby 1.8 compatibility code, see #276 [Florian Weingarten, fw42] * Add default filter to standard filters, see #267 [Derrick Reimer, djreimer] * Add optional strict parsing and warn parsing, see #235 [Tristan Hume, trishume] diff --git a/lib/liquid/strainer.rb b/lib/liquid/strainer.rb index f5d525d..bc429b6 100644 --- a/lib/liquid/strainer.rb +++ b/lib/liquid/strainer.rb @@ -41,8 +41,8 @@ module Liquid @@strainer_class_cache end - def self.create(context, filters = nil) - filters = @@filters + (filters || []) + def self.create(context, filters = []) + filters = @@filters + filters strainer_class_cache[filters].new(context) end diff --git a/test/liquid/strainer_test.rb b/test/liquid/strainer_test.rb index b7ec593..fd0a969 100644 --- a/test/liquid/strainer_test.rb +++ b/test/liquid/strainer_test.rb @@ -55,7 +55,7 @@ class StrainerTest < Test::Unit::TestCase assert_kind_of Strainer, strainer assert_kind_of a, strainer assert_kind_of b, strainer - Strainer.send(:class_variable_get, :@@filters).each do |m| + Strainer.class_variable_get(:@@filters).each do |m| assert_kind_of m, strainer end end From 4647e6d86bd848f335963bcffcb8b9b0354ad095 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Mon, 25 Nov 2013 10:52:46 -0500 Subject: [PATCH 40/51] Remove unnecessary comment, add joost's change to History.md --- History.md | 1 + lib/liquid/tags/include.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index ba21d87..0fc46ca 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,7 @@ ## 3.0.0 / not yet released / branch "master" * ... +* Support for passing variables to snippets in subdirs, see #271 [Joost Hietbrink, joost] * Add a class cache to avoid runtime extend calls, see #249 [James Tucker, raggi] * Remove some legacy Ruby 1.8 compatibility code, see #276 [Florian Weingarten, fw42] * Add default filter to standard filters, see #267 [Derrick Reimer, djreimer] diff --git a/lib/liquid/tags/include.rb b/lib/liquid/tags/include.rb index 1d0ce66..d439fff 100644 --- a/lib/liquid/tags/include.rb +++ b/lib/liquid/tags/include.rb @@ -51,7 +51,7 @@ module Liquid context[key] = context[value] end - context_variable_name = @template_name[1..-2].split('/').last # for a snippet in a subdir only use the filename + context_variable_name = @template_name[1..-2].split('/').last if variable.is_a?(Array) variable.collect do |var| context[context_variable_name] = var From 5ce36f79e99c65611e8a8b5918b00ae2dda5f769 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Mon, 25 Nov 2013 11:12:33 -0500 Subject: [PATCH 41/51] Add Tom's slice loading change to History.md --- History.md | 1 + 1 file changed, 1 insertion(+) diff --git a/History.md b/History.md index 0fc46ca..306e43c 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,7 @@ ## 3.0.0 / not yet released / branch "master" * ... +* Allow drops to optimize loading a slice of elements, see #282 [Tom Burns, boourns] * Support for passing variables to snippets in subdirs, see #271 [Joost Hietbrink, joost] * Add a class cache to avoid runtime extend calls, see #249 [James Tucker, raggi] * Remove some legacy Ruby 1.8 compatibility code, see #276 [Florian Weingarten, fw42] From 0edb252489ae4e5b642639322d052f2d0f5e0a0c Mon Sep 17 00:00:00 2001 From: Andrei Gladkyi Date: Sat, 30 Nov 2013 17:55:53 +0200 Subject: [PATCH 42/51] Option to specify custom pattern for template filenames --- lib/liquid/file_system.rb | 17 ++++++++++++++--- test/liquid/file_system_test.rb | 5 +++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/liquid/file_system.rb b/lib/liquid/file_system.rb index c7eeddc..b3efef6 100644 --- a/lib/liquid/file_system.rb +++ b/lib/liquid/file_system.rb @@ -31,11 +31,22 @@ module Liquid # file_system.full_path("mypartial") # => "/some/path/_mypartial.liquid" # file_system.full_path("dir/mypartial") # => "/some/path/dir/_mypartial.liquid" # + # Optionally in the second argument you can specify a custom pattern for template filenames. + # The Kernel::sprintf format specification is used. + # Default pattern is "_%s.liquid". + # + # Example: + # + # file_system = Liquid::LocalFileSystem.new("/some/path", "%s.html") + # + # file_system.full_path("index") # => "/some/path/index.html" + # class LocalFileSystem attr_accessor :root - def initialize(root) + def initialize(root, pattern = "_%s.liquid") @root = root + @pattern = pattern end def read_template_file(template_path, context) @@ -49,9 +60,9 @@ module Liquid raise FileSystemError, "Illegal template name '#{template_path}'" unless template_path =~ /^[^.\/][a-zA-Z0-9_\/]+$/ full_path = if template_path.include?('/') - File.join(root, File.dirname(template_path), "_#{File.basename(template_path)}.liquid") + File.join(root, File.dirname(template_path), @pattern % File.basename(template_path)) else - File.join(root, "_#{template_path}.liquid") + File.join(root, @pattern % template_path) end raise FileSystemError, "Illegal template path '#{File.expand_path(full_path)}'" unless File.expand_path(full_path) =~ /^#{File.expand_path(root)}/ diff --git a/test/liquid/file_system_test.rb b/test/liquid/file_system_test.rb index e9abaa8..b9999e0 100644 --- a/test/liquid/file_system_test.rb +++ b/test/liquid/file_system_test.rb @@ -25,5 +25,10 @@ class FileSystemTest < Test::Unit::TestCase assert_raise(FileSystemError) do file_system.full_path("/etc/passwd") end + + # custom pattern for template filenames + file_system = Liquid::LocalFileSystem.new("/some/path", "%s.html") + assert_equal "/some/path/mypartial.html" , file_system.full_path("mypartial") + assert_equal "/some/path/dir/mypartial.html", file_system.full_path("dir/mypartial") end end # FileSystemTest From 5e8f2f8bd04d3d89e2e0fd45bec49c4e831ff8ed Mon Sep 17 00:00:00 2001 From: Gaurav Chande Date: Sun, 1 Dec 2013 20:35:25 -0500 Subject: [PATCH 43/51] Fix escape_once filter --- lib/liquid/standardfilters.rb | 6 +++--- test/liquid/standard_filter_test.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/liquid/standardfilters.rb b/lib/liquid/standardfilters.rb index 54ab799..027c0b3 100644 --- a/lib/liquid/standardfilters.rb +++ b/lib/liquid/standardfilters.rb @@ -4,6 +4,8 @@ require 'bigdecimal' module Liquid module StandardFilters + HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"', "'" => ''' } + HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+));)/ # Return the size of an array or of an string def size(input) @@ -31,9 +33,7 @@ module Liquid end def escape_once(input) - ActionView::Helpers::TagHelper.escape_once(input) - rescue NameError - input + input.to_s.gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE) end alias_method :h, :escape diff --git a/test/liquid/standard_filter_test.rb b/test/liquid/standard_filter_test.rb index 91c219d..d9c5cd6 100644 --- a/test/liquid/standard_filter_test.rb +++ b/test/liquid/standard_filter_test.rb @@ -89,7 +89,7 @@ class StandardFiltersTest < Test::Unit::TestCase end def test_escape_once - assert_equal '<strong>', @filters.escape_once(@filters.escape('')) + assert_equal '<strong>Hulk</strong>', @filters.escape_once('<strong>Hulk') end def test_truncatewords From 0ae42bbc32fdcbc7b139a4b89eca8b1be7c7e3d7 Mon Sep 17 00:00:00 2001 From: Andrei Gladkyi Date: Mon, 16 Dec 2013 17:48:43 +0200 Subject: [PATCH 44/51] Added separate test for custom patterns specifying + updated History.md --- History.md | 1 + test/liquid/file_system_test.rb | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 306e43c..4b114c1 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,7 @@ ## 3.0.0 / not yet released / branch "master" * ... +* Allow specifying custom patterns for template filenames, see #284 [Andrei Gladkyi, agladkyi] * Allow drops to optimize loading a slice of elements, see #282 [Tom Burns, boourns] * Support for passing variables to snippets in subdirs, see #271 [Joost Hietbrink, joost] * Add a class cache to avoid runtime extend calls, see #249 [James Tucker, raggi] diff --git a/test/liquid/file_system_test.rb b/test/liquid/file_system_test.rb index b9999e0..4b2a2f1 100644 --- a/test/liquid/file_system_test.rb +++ b/test/liquid/file_system_test.rb @@ -25,8 +25,9 @@ class FileSystemTest < Test::Unit::TestCase assert_raise(FileSystemError) do file_system.full_path("/etc/passwd") end + end - # custom pattern for template filenames + def test_custom_template_filename_patterns file_system = Liquid::LocalFileSystem.new("/some/path", "%s.html") assert_equal "/some/path/mypartial.html" , file_system.full_path("mypartial") assert_equal "/some/path/dir/mypartial.html", file_system.full_path("dir/mypartial") From 9ec2b9da2d7b73fc6946f67902e243f1a77ff18f Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Tue, 7 Jan 2014 11:20:32 -0500 Subject: [PATCH 45/51] Rename tests because of name clashes (same method name used twice) --- test/liquid/output_test.rb | 2 +- test/liquid/regexp_test.rb | 4 ++-- test/liquid/standard_filter_test.rb | 5 ----- test/liquid/tags/standard_tag_test.rb | 14 ++++++-------- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/test/liquid/output_test.rb b/test/liquid/output_test.rb index e545a41..d5be6f8 100644 --- a/test/liquid/output_test.rb +++ b/test/liquid/output_test.rb @@ -86,7 +86,7 @@ class OutputTest < Test::Unit::TestCase assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter]) end - def test_variable_piping_with_args + def test_variable_piping_with_multiple_args text = %! {{ car.gm | add_tag : 'span', 'bar'}} ! expected = %| bad | diff --git a/test/liquid/regexp_test.rb b/test/liquid/regexp_test.rb index 280d62b..667d5bb 100644 --- a/test/liquid/regexp_test.rb +++ b/test/liquid/regexp_test.rb @@ -21,11 +21,11 @@ class RegexpTest < Test::Unit::TestCase assert_equal ['', ''], %||.scan(QuotedFragment) end - def test_quoted_words + def test_double_quoted_words assert_equal ['arg1', 'arg2', '"arg 3"'], 'arg1 arg2 "arg 3"'.scan(QuotedFragment) end - def test_quoted_words + def test_single_quoted_words assert_equal ['arg1', 'arg2', "'arg 3'"], 'arg1 arg2 \'arg 3\''.scan(QuotedFragment) end diff --git a/test/liquid/standard_filter_test.rb b/test/liquid/standard_filter_test.rb index d9c5cd6..9e51432 100644 --- a/test/liquid/standard_filter_test.rb +++ b/test/liquid/standard_filter_test.rb @@ -62,11 +62,6 @@ class StandardFiltersTest < Test::Unit::TestCase assert_equal '', @filters.upcase(nil) end - def test_upcase - assert_equal 'TESTING', @filters.upcase("Testing") - assert_equal '', @filters.upcase(nil) - end - def test_truncate assert_equal '1234...', @filters.truncate('1234567890', 7) assert_equal '1234567890', @filters.truncate('1234567890', 20) diff --git a/test/liquid/tags/standard_tag_test.rb b/test/liquid/tags/standard_tag_test.rb index 58d125e..ddd365f 100644 --- a/test/liquid/tags/standard_tag_test.rb +++ b/test/liquid/tags/standard_tag_test.rb @@ -54,16 +54,9 @@ class StandardTagTest < Test::Unit::TestCase {%endcomment%}bar') end - def test_assign - assigns = {'var' => 'content' } - assert_template_result('var2: var2:content', 'var2:{{var2}} {%assign var2 = var%} var2:{{var2}}', assigns) - - end - def test_hyphenated_assign assigns = {'a-b' => '1' } assert_template_result('a-b:1 a-b:2', 'a-b:{{a-b}} {%assign a-b = 2 %}a-b:{{a-b}}', assigns) - end def test_assign_with_colon_and_spaces @@ -225,7 +218,12 @@ class StandardTagTest < Test::Unit::TestCase end def test_assign - assert_equal 'variable', Liquid::Template.parse( '{% assign a = "variable"%}{{a}}' ).render + assert_equal 'variable', Liquid::Template.parse( '{% assign a = "variable"%}{{a}}').render + end + + def test_assign_unassigned + assigns = { 'var' => 'content' } + assert_template_result('var2: var2:content', 'var2:{{var2}} {%assign var2 = var%} var2:{{var2}}', assigns) end def test_assign_an_empty_string From 208c6c8800868f760f4a425a13ee34c8c1f23785 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Tue, 7 Jan 2014 11:31:46 -0500 Subject: [PATCH 46/51] remove ruby-debug --- test/test_helper.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index e1f12f0..b3d2818 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -2,11 +2,6 @@ require 'test/unit' require 'test/unit/assertions' -begin - require 'ruby-debug' -rescue LoadError - puts "Couldn't load ruby-debug. gem install ruby-debug if you need it." -end $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')) require 'liquid.rb' From a13f237d3ccf13156e76574e8935c0a476f7a5b4 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Tue, 7 Jan 2014 11:37:01 -0500 Subject: [PATCH 47/51] Remove some 192 tests --- test/liquid/standard_filter_test.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/liquid/standard_filter_test.rb b/test/liquid/standard_filter_test.rb index 9e51432..3b58711 100644 --- a/test/liquid/standard_filter_test.rb +++ b/test/liquid/standard_filter_test.rb @@ -232,9 +232,6 @@ class StandardFiltersTest < Test::Unit::TestCase assert_template_result "12", "{{ 3 | times:4 }}" assert_template_result "0", "{{ 'foo' | times:4 }}" - # Ruby v1.9.2-rc1, or higher, backwards compatible Float test - assert_match(/(6\.3)|(6\.(0{13})1)/, Template.parse("{{ '2.1' | times:3 }}").render) - assert_template_result "6", "{{ '2.1' | times:3 | replace: '.','-' | plus:0}}" assert_template_result "7.25", "{{ 0.0725 | times:100 }}" @@ -244,9 +241,6 @@ class StandardFiltersTest < Test::Unit::TestCase assert_template_result "4", "{{ 12 | divided_by:3 }}" assert_template_result "4", "{{ 14 | divided_by:3 }}" - # Ruby v1.9.2-rc1, or higher, backwards compatible Float test - assert_match(/4\.(6{13,14})7/, Template.parse("{{ 14 | divided_by:'3.0' }}").render) - assert_template_result "5", "{{ 15 | divided_by:3 }}" assert_template_result "Liquid error: divided by 0", "{{ 5 | divided_by:0 }}" From 57c8583dc38b53c6fe892148c752a64a422a4a1f Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Tue, 7 Jan 2014 11:37:24 -0500 Subject: [PATCH 48/51] Add 2.1.0 to travis --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index f668296..92a360e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,12 @@ rvm: - 1.9.3 - 2.0.0 - - ruby-head + - 2.1.0 - jruby-19mode - jruby-head - rbx-19mode matrix: allow_failures: - - rvm: ruby-head - rvm: rbx-19mode - rvm: jruby-head From c6e0c1e4903f72bb8ae7f0c274634939d76863a7 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Wed, 8 Jan 2014 13:00:53 -0500 Subject: [PATCH 49/51] Fix resource counting bug with respond_to?(:length) --- lib/liquid/block.rb | 2 +- lib/liquid/context.rb | 8 ++++++++ lib/liquid/tags/assign.rb | 2 +- lib/liquid/tags/capture.rb | 2 +- test/liquid/template_test.rb | 14 ++++++++++++++ 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/lib/liquid/block.rb b/lib/liquid/block.rb index 0281b91..d1356eb 100644 --- a/lib/liquid/block.rb +++ b/lib/liquid/block.rb @@ -135,7 +135,7 @@ module Liquid end token_output = (token.respond_to?(:render) ? token.render(context) : token) - context.resource_limits[:render_length_current] += (token_output.respond_to?(:length) ? token_output.length : 1) + context.increment_used_resources(:render_length_current, token_output) if context.resource_limits_reached? context.resource_limits[:reached] = true raise MemoryError.new("Memory limits exceeded") diff --git a/lib/liquid/context.rb b/lib/liquid/context.rb index 2687dab..ade5c6d 100644 --- a/lib/liquid/context.rb +++ b/lib/liquid/context.rb @@ -28,6 +28,14 @@ module Liquid @filters = [] end + def increment_used_resources(key, obj) + @resource_limits[key] += if obj.class.ancestors & [ String, Array, Hash ] != [] + obj.length + else + 1 + end + end + def resource_limits_reached? (@resource_limits[:render_length_limit] && @resource_limits[:render_length_current] > @resource_limits[:render_length_limit]) || (@resource_limits[:render_score_limit] && @resource_limits[:render_score_current] > @resource_limits[:render_score_limit] ) || diff --git a/lib/liquid/tags/assign.rb b/lib/liquid/tags/assign.rb index 0af0976..4699a6a 100644 --- a/lib/liquid/tags/assign.rb +++ b/lib/liquid/tags/assign.rb @@ -25,7 +25,7 @@ module Liquid def render(context) val = @from.render(context) context.scopes.last[@to] = val - context.resource_limits[:assign_score_current] += (val.respond_to?(:length) ? val.length : 1) + context.increment_used_resources(:assign_score_current, val) '' end diff --git a/lib/liquid/tags/capture.rb b/lib/liquid/tags/capture.rb index 92b9950..34036be 100644 --- a/lib/liquid/tags/capture.rb +++ b/lib/liquid/tags/capture.rb @@ -27,7 +27,7 @@ module Liquid def render(context) output = super context.scopes.last[@to] = output - context.resource_limits[:assign_score_current] += (output.respond_to?(:length) ? output.length : 1) + context.increment_used_resources(:assign_score_current, output) '' end diff --git a/test/liquid/template_test.rb b/test/liquid/template_test.rb index 5fd4d1e..f9afac1 100644 --- a/test/liquid/template_test.rb +++ b/test/liquid/template_test.rb @@ -14,6 +14,14 @@ class TemplateContextDrop < Liquid::Drop end end +class SomethingWithLength + def length + nil + end + + liquid_methods :length +end + class TemplateTest < Test::Unit::TestCase include Liquid @@ -86,6 +94,12 @@ class TemplateTest < Test::Unit::TestCase @global = nil end + def test_resource_limits_works_with_custom_length_method + t = Template.parse("{% assign foo = bar %}") + t.resource_limits = { :render_length_limit => 42 } + assert_equal "", t.render("bar" => SomethingWithLength.new) + end + def test_resource_limits_render_length t = Template.parse("0123456789") t.resource_limits = { :render_length_limit => 5 } From 62a86a25aec745466c8bb372680ab19082245827 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Wed, 8 Jan 2014 13:37:24 -0500 Subject: [PATCH 50/51] update history --- History.md | 1 + 1 file changed, 1 insertion(+) diff --git a/History.md b/History.md index 4b114c1..8b77e2a 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,7 @@ ## 3.0.0 / not yet released / branch "master" * ... +* Fix resource counting bug with respond_to?(:length), see #263 [Florian Weingarten, fw42] * Allow specifying custom patterns for template filenames, see #284 [Andrei Gladkyi, agladkyi] * Allow drops to optimize loading a slice of elements, see #282 [Tom Burns, boourns] * Support for passing variables to snippets in subdirs, see #271 [Joost Hietbrink, joost] From 17dae40707be925cd814af817827266388fa275a Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Mon, 13 Jan 2014 15:38:18 -0500 Subject: [PATCH 51/51] Fix History.md ordering --- History.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 8b77e2a..4af0dd9 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,8 @@ ## 3.0.0 / not yet released / branch "master" * ... +* Prevent arbitrary method invocation on condition objects, see #274 [Dylan Thacker-Smith, dylanahsmith] +* Don't call to_sym when creating conditions for security reasons, see #273 [Bouke van der Bijl, bouk] * Fix resource counting bug with respond_to?(:length), see #263 [Florian Weingarten, fw42] * Allow specifying custom patterns for template filenames, see #284 [Andrei Gladkyi, agladkyi] * Allow drops to optimize loading a slice of elements, see #282 [Tom Burns, boourns] @@ -16,8 +18,6 @@ * Fix clashing method names in enumerable drops, see #238 [Florian Weingarten, fw42] * Make map filter work on enumerable drops, see #233 [Florian Weingarten, fw42] * Improved whitespace stripping for blank blocks, related to #216 [Florian Weingarten, fw42] -* Don't call to_sym when creating conditions for security reasons, see #273 [Bouke van der Bijl, bouk] -* Prevent arbitrary method invocation on condition objects, see #274 [Dylan Thacker-Smith, dylanahsmith] ## 2.6.0 / 2013-11-25 / branch "2.6-stable"