Compare commits

...

9 Commits

Author SHA1 Message Date
Florian Weingarten
e77b1a09b6 Update gemspec 2013-11-11 08:57:22 -05:00
Florian Weingarten
73b39beef2 Update history 2013-11-11 08:56:56 -05:00
Dylan Thacker-Smith
fc63219087 Merge pull request #173 from jsw0528/master
fix `can't convert Fixnum into String` for `replace`
2013-11-11 08:54:03 -05:00
Florian Weingarten
53b6db48e3 History and gemspec 2013-10-09 16:45:32 -04:00
Arthur Neves
0bbc22b027 Update history 2013-10-09 15:33:11 -04:00
Florian Weingarten
145920738b Merge pull request #234 from Shopify/fix_mapping_procs
Fix mapping over procs
2013-10-09 15:24:45 -04:00
Florian Weingarten
6eb1f174de Merge pull request #232 from Shopify/to_liquid_stuff
Always call 'to_liquid' on stuff in map filter and allow to_liquid to be...
2013-10-09 15:24:20 -04:00
Florian Weingarten
2e71ce1efe Bump version 2013-07-24 18:02:20 -04:00
Florian Weingarten
8204c61e31 Use invoke_drop in map filter 2013-07-24 18:00:16 -04:00
6 changed files with 84 additions and 14 deletions

View File

@@ -1,5 +1,21 @@
# Liquid Version History
## 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]
## 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
* Prevent Object methods from being called on drops

View File

@@ -54,7 +54,7 @@ module Liquid
# Check for method existence without invoking respond_to?, which creates symbols
def self.invokable?(method_name)
@invokable_methods ||= Set.new((public_instance_methods - Liquid::Drop.public_instance_methods).map(&:to_s))
@invokable_methods ||= Set.new(["to_liquid"] + (public_instance_methods - Liquid::Drop.public_instance_methods).map(&:to_s))
@invokable_methods.include?(method_name.to_s)
end
end

View File

@@ -93,21 +93,26 @@ module Liquid
# map/collect on a given property
def map(input, property)
ary = [input].flatten
if ary.first.respond_to?('[]') and !ary.first[property].nil?
ary.map {|e| e[property] }
elsif ary.first.respond_to?(property)
ary.map {|e| e.send(property) }
ary.map do |e|
e = e.call if e.is_a?(Proc)
e = e.to_liquid if e.respond_to?(:to_liquid)
if property == "to_liquid"
e
elsif e.respond_to?(:[])
e[property]
end
end
end
# Replace occurrences of a string with another
def replace(input, string, replacement = '')
input.to_s.gsub(string, replacement)
input.to_s.gsub(string, replacement.to_s)
end
# Replace the first occurrences of a string with another
def replace_first(input, string, replacement = '')
input.to_s.sub(string, replacement)
input.to_s.sub(string, replacement.to_s)
end
# remove a substring

View File

@@ -2,7 +2,7 @@
Gem::Specification.new do |s|
s.name = "liquid"
s.version = "2.5.0"
s.version = "2.5.4"
s.platform = Gem::Platform::RUBY
s.summary = "A secure, non-evaling end user template engine with aesthetic markup."
s.authors = ["Tobias Luetke"]

View File

@@ -71,23 +71,34 @@ class DropsTest < Test::Unit::TestCase
include Liquid
def test_product_drop
assert_nothing_raised do
tpl = Liquid::Template.parse( ' ' )
tpl.render('product' => ProductDrop.new)
end
end
def test_drop_does_only_respond_to_whitelisted_methods
assert_equal "", Liquid::Template.parse("{{ product.inspect }}").render('product' => ProductDrop.new)
assert_equal "", Liquid::Template.parse("{{ product.pretty_inspect }}").render('product' => ProductDrop.new)
assert_equal "", Liquid::Template.parse("{{ product.whatever }}").render('product' => ProductDrop.new)
assert_equal "", Liquid::Template.parse('{{ product | map: "inspect" }}').render('product' => ProductDrop.new)
assert_equal "", Liquid::Template.parse('{{ product | map: "pretty_inspect" }}').render('product' => ProductDrop.new)
assert_equal "", Liquid::Template.parse('{{ product | map: "whatever" }}').render('product' => ProductDrop.new)
end
def test_drops_respond_to_to_liquid
assert_equal "text1", Liquid::Template.parse("{{ product.to_liquid.texts.text }}").render('product' => ProductDrop.new)
assert_equal "text1", Liquid::Template.parse('{{ product | map: "to_liquid" | map: "texts" | map: "text" }}').render('product' => ProductDrop.new)
end
def test_text_drop
output = Liquid::Template.parse( ' {{ product.texts.text }} ' ).render('product' => ProductDrop.new)
assert_equal ' text1 ', output
end
def test_unknown_method
output = Liquid::Template.parse( ' {{ product.catchall.unknown }} ' ).render('product' => ProductDrop.new)
assert_equal ' method: unknown ', output
end
def test_integer_argument_drop

View File

@@ -4,6 +4,27 @@ class Filters
include Liquid::StandardFilters
end
class TestThing
def initialize
@foo = 0
end
def to_s
"woot: #{@foo}"
end
def to_liquid
@foo += 1
self
end
end
class TestDrop < Liquid::Drop
def test
"testfoo"
end
end
class StandardFiltersTest < Test::Unit::TestCase
include Liquid
@@ -86,6 +107,23 @@ class StandardFiltersTest < Test::Unit::TestCase
'ary' => [{'foo' => {'bar' => 'a'}}, {'foo' => {'bar' => 'b'}}, {'foo' => {'bar' => 'c'}}]
end
def test_map_doesnt_call_arbitrary_stuff
assert_equal "", Liquid::Template.parse('{{ "foo" | map: "__id__" }}').render
assert_equal "", Liquid::Template.parse('{{ "foo" | map: "inspect" }}').render
end
def test_map_calls_to_liquid
t = TestThing.new
assert_equal "woot: 1", Liquid::Template.parse('{{ foo }}').render("foo" => t)
end
def test_map_over_proc
drop = TestDrop.new
p = Proc.new{ drop }
templ = '{{ procs | map: "test" }}'
assert_equal "testfoo", Liquid::Template.parse(templ).render("procs" => [p])
end
def test_date
assert_equal 'May', @filters.date(Time.parse("2006-05-05 10:00:00"), "%B")
assert_equal 'June', @filters.date(Time.parse("2006-06-05 10:00:00"), "%B")
@@ -119,9 +157,9 @@ class StandardFiltersTest < Test::Unit::TestCase
end
def test_replace
assert_equal 'b b b b', @filters.replace("a a a a", 'a', 'b')
assert_equal 'b a a a', @filters.replace_first("a a a a", 'a', 'b')
assert_template_result 'b a a a', "{{ 'a a a a' | replace_first: 'a', 'b' }}"
assert_equal '2 2 2 2', @filters.replace('1 1 1 1', '1', 2)
assert_equal '2 1 1 1', @filters.replace_first('1 1 1 1', '1', 2)
assert_template_result '2 1 1 1', "{{ '1 1 1 1' | replace_first: '1', 2 }}"
end
def test_remove