diff --git a/ext/liquid/variable.c b/ext/liquid/variable.c index 8907de3..669edfe 100644 --- a/ext/liquid/variable.c +++ b/ext/liquid/variable.c @@ -26,7 +26,7 @@ static inline int skip_whitespace(char * str, int len) return skipped; } -static char * get_quoted_fragment(char * str, int len, int * ret_size, int * end_offset) +static char * get_quoted_fragment(char * str, int len, int * ret_size, int * end_offset, bool colon) { int p = 0; /* Current position in string */ int start = -1, end = -1; /* Start and end indices for the found string */ @@ -48,6 +48,12 @@ static char * get_quoted_fragment(char * str, int len, int * ret_size, int * end else if (quoted_by == -1) quoted_by = '\''; else if (quoted_by == '\'') quoted_by = -1; break; + case ':': + if (colon) + if (start != -1 && quoted_by == -1) {end = p-1; goto quoted_fragment_found;} + else + if (start == -1) start = p; + break; case '|': case ',': case '\n': @@ -67,7 +73,7 @@ static char * get_quoted_fragment(char * str, int len, int * ret_size, int * end if (p == len && start != -1 && end == -1) end = len-1; quoted_fragment_found: - if (end > start) { + if (end >= start) { *ret_size = end-start+1; *end_offset = end+1; return &str[start]; @@ -90,8 +96,8 @@ static VALUE get_filters(char * str, int len, VALUE self) { VALUE f_args = rb_ary_new(); p += skip_whitespace(&str[p+1], len-p-1); - f = get_quoted_fragment(&str[p], len-p, &ret_size, &end_offset); - p += end_offset-1; + f = get_quoted_fragment(&str[p], len-p, &ret_size, &end_offset, true); + p += end_offset; if (f) { if (f[ret_size-1] == ':') ret_size--; @@ -99,16 +105,28 @@ static VALUE get_filters(char * str, int len, VALUE self) { } /* Check for filter arguments */ - // do { - // p += skip_whitespace(&str[p+1], len-p-1); + do { + if (p e - # @warnings ||= [] - # @warnings << e + case @options[:error_mode] || Template.error_mode + when :strict then strict_parse(markup) + when :lax then lax_parse(markup) + when :warn + begin + strict_parse(markup) + rescue SyntaxError => e + @warnings ||= [] + @warnings << e lax_parse(markup) - # end - # end + end + end end # def lax_parse(markup) diff --git a/test/liquid/variable_test.rb b/test/liquid/variable_test.rb index f5fbd62..284e981 100644 --- a/test/liquid/variable_test.rb +++ b/test/liquid/variable_test.rb @@ -19,41 +19,41 @@ class VariableTest < Test::Unit::TestCase var = Variable.new(%! hello | strftime: '%Y'!) assert_equal 'hello', var.name - # assert_equal [["strftime",["'%Y'"]]], var.filters + assert_equal [["strftime",["'%Y'"]]], var.filters var = Variable.new(%! 'typo' | link_to: 'Typo', true !) assert_equal %!'typo'!, var.name - # assert_equal [["link_to",["'Typo'", "true"]]], var.filters + assert_equal [["link_to",["'Typo'", "true"]]], var.filters var = Variable.new(%! 'typo' | link_to: 'Typo', false !) assert_equal %!'typo'!, var.name - # assert_equal [["link_to",["'Typo'", "false"]]], var.filters + assert_equal [["link_to",["'Typo'", "false"]]], var.filters var = Variable.new(%! 'foo' | repeat: 3 !) assert_equal %!'foo'!, var.name - # assert_equal [["repeat",["3"]]], var.filters + assert_equal [["repeat",["3"]]], var.filters var = Variable.new(%! 'foo' | repeat: 3, 3 !) assert_equal %!'foo'!, var.name - # assert_equal [["repeat",["3","3"]]], var.filters + assert_equal [["repeat",["3","3"]]], var.filters var = Variable.new(%! 'foo' | repeat: 3, 3, 3 !) assert_equal %!'foo'!, var.name - # assert_equal [["repeat",["3","3","3"]]], var.filters + assert_equal [["repeat",["3","3","3"]]], var.filters var = Variable.new(%! hello | strftime: '%Y, okay?'!) assert_equal 'hello', var.name - # assert_equal [["strftime",["'%Y, okay?'"]]], var.filters + assert_equal [["strftime",["'%Y, okay?'"]]], var.filters var = Variable.new(%! hello | things: "%Y, okay?", 'the other one'!) assert_equal 'hello', var.name - # assert_equal [["things",["\"%Y, okay?\"","'the other one'"]]], var.filters + assert_equal [["things",["\"%Y, okay?\"","'the other one'"]]], var.filters end def test_filter_with_date_parameter var = Variable.new(%! '2006-06-06' | date: "%m/%d/%Y"!) assert_equal "'2006-06-06'", var.name - # assert_equal [["date",["\"%m/%d/%Y\""]]], var.filters + assert_equal [["date",["\"%m/%d/%Y\""]]], var.filters end def test_filters_without_whitespace @@ -63,23 +63,23 @@ class VariableTest < Test::Unit::TestCase var = Variable.new('hello|textileze|paragraph') assert_equal 'hello', var.name - # assert_equal [["textileze",[]], ["paragraph",[]]], var.filters + assert_equal [["textileze",[]], ["paragraph",[]]], var.filters var = Variable.new("hello|replace:'foo','bar'|textileze") assert_equal 'hello', var.name - # assert_equal [["replace", ["'foo'", "'bar'"]], ["textileze", []]], var.filters + assert_equal [["replace", ["'foo'", "'bar'"]], ["textileze", []]], var.filters end def test_symbol var = Variable.new("http://disney.com/logo.gif | image: 'med'", :error_mode => :lax) assert_equal "http://disney.com/logo.gif", var.name - # assert_equal [["image",["'med'"]]], var.filters + assert_equal [["image",["'med'"]]], var.filters end def test_string_to_filter var = Variable.new("'http://disney.com/logo.gif' | image: 'med' ") assert_equal "'http://disney.com/logo.gif'", var.name - # assert_equal [["image",["'med'"]]], var.filters + assert_equal [["image",["'med'"]]], var.filters end def test_string_single_quoted @@ -115,84 +115,84 @@ class VariableTest < Test::Unit::TestCase def test_filter_with_keyword_arguments var = Variable.new(%! hello | things: greeting: "world", farewell: 'goodbye'!) assert_equal 'hello', var.name - # assert_equal [['things',["greeting: \"world\"","farewell: 'goodbye'"]]], var.filters + assert_equal [['things',["greeting: \"world\"","farewell: 'goodbye'"]]], var.filters end def test_lax_filter_argument_parsing var = Variable.new(%! number_of_comments | pluralize: 'comment': 'comments' !, :error_mode => :lax) assert_equal 'number_of_comments', var.name - # assert_equal [['pluralize',["'comment'","'comments'"]]], var.filters + assert_equal [['pluralize',["'comment'","'comments'"]]], var.filters end - # def test_strict_filter_argument_parsing - # with_error_mode(:strict) do - # assert_raises(SyntaxError) do - # Variable.new(%! number_of_comments | pluralize: 'comment': 'comments' !) - # end - # end - # end + def test_strict_filter_argument_parsing + with_error_mode(:strict) do + assert_raises(SyntaxError) do + Variable.new(%! number_of_comments | pluralize: 'comment': 'comments' !) + end + end + end end -# class VariableResolutionTest < Test::Unit::TestCase -# include Liquid +class VariableResolutionTest < Test::Unit::TestCase + include Liquid -# def test_simple_variable -# template = Template.parse(%|{{test}}|) -# assert_equal 'worked', template.render('test' => 'worked') -# assert_equal 'worked wonderfully', template.render('test' => 'worked wonderfully') -# end + def test_simple_variable + template = Template.parse(%|{{test}}|) + assert_equal 'worked', template.render('test' => 'worked') + assert_equal 'worked wonderfully', template.render('test' => 'worked wonderfully') + end -# def test_simple_with_whitespaces -# template = Template.parse(%| {{ test }} |) -# assert_equal ' worked ', template.render('test' => 'worked') -# assert_equal ' worked wonderfully ', template.render('test' => 'worked wonderfully') -# end + def test_simple_with_whitespaces + template = Template.parse(%| {{ test }} |) + assert_equal ' worked ', template.render('test' => 'worked') + assert_equal ' worked wonderfully ', template.render('test' => 'worked wonderfully') + end -# def test_ignore_unknown -# template = Template.parse(%|{{ test }}|) -# assert_equal '', template.render -# end + def test_ignore_unknown + template = Template.parse(%|{{ test }}|) + assert_equal '', template.render + end -# def test_hash_scoping -# template = Template.parse(%|{{ test.test }}|) -# assert_equal 'worked', template.render('test' => {'test' => 'worked'}) -# end + def test_hash_scoping + template = Template.parse(%|{{ test.test }}|) + assert_equal 'worked', template.render('test' => {'test' => 'worked'}) + end -# def test_preset_assigns -# template = Template.parse(%|{{ test }}|) -# template.assigns['test'] = 'worked' -# assert_equal 'worked', template.render -# end + def test_preset_assigns + template = Template.parse(%|{{ test }}|) + template.assigns['test'] = 'worked' + assert_equal 'worked', template.render + end -# def test_reuse_parsed_template -# template = Template.parse(%|{{ greeting }} {{ name }}|) -# template.assigns['greeting'] = 'Goodbye' -# assert_equal 'Hello Tobi', template.render('greeting' => 'Hello', 'name' => 'Tobi') -# assert_equal 'Hello ', template.render('greeting' => 'Hello', 'unknown' => 'Tobi') -# assert_equal 'Hello Brian', template.render('greeting' => 'Hello', 'name' => 'Brian') -# assert_equal 'Goodbye Brian', template.render('name' => 'Brian') -# assert_equal({'greeting'=>'Goodbye'}, template.assigns) -# end + def test_reuse_parsed_template + template = Template.parse(%|{{ greeting }} {{ name }}|) + template.assigns['greeting'] = 'Goodbye' + assert_equal 'Hello Tobi', template.render('greeting' => 'Hello', 'name' => 'Tobi') + assert_equal 'Hello ', template.render('greeting' => 'Hello', 'unknown' => 'Tobi') + assert_equal 'Hello Brian', template.render('greeting' => 'Hello', 'name' => 'Brian') + assert_equal 'Goodbye Brian', template.render('name' => 'Brian') + assert_equal({'greeting'=>'Goodbye'}, template.assigns) + end -# def test_assigns_not_polluted_from_template -# template = Template.parse(%|{{ test }}{% assign test = 'bar' %}{{ test }}|) -# template.assigns['test'] = 'baz' -# assert_equal 'bazbar', template.render -# assert_equal 'bazbar', template.render -# assert_equal 'foobar', template.render('test' => 'foo') -# assert_equal 'bazbar', template.render -# end + def test_assigns_not_polluted_from_template + template = Template.parse(%|{{ test }}{% assign test = 'bar' %}{{ test }}|) + template.assigns['test'] = 'baz' + assert_equal 'bazbar', template.render + assert_equal 'bazbar', template.render + assert_equal 'foobar', template.render('test' => 'foo') + assert_equal 'bazbar', template.render + end -# def test_hash_with_default_proc -# template = Template.parse(%|Hello {{ test }}|) -# assigns = Hash.new { |h,k| raise "Unknown variable '#{k}'" } -# assigns['test'] = 'Tobi' -# assert_equal 'Hello Tobi', template.render!(assigns) -# assigns.delete('test') -# e = assert_raises(RuntimeError) { -# template.render!(assigns) -# } -# assert_equal "Unknown variable 'test'", e.message -# end -# end # VariableTest + def test_hash_with_default_proc + template = Template.parse(%|Hello {{ test }}|) + assigns = Hash.new { |h,k| raise "Unknown variable '#{k}'" } + assigns['test'] = 'Tobi' + assert_equal 'Hello Tobi', template.render!(assigns) + assigns.delete('test') + e = assert_raises(RuntimeError) { + template.render!(assigns) + } + assert_equal "Unknown variable 'test'", e.message + end +end # VariableTest