liquid 3.0.0.rc1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +4 -0
  3. data/README.md +2 -2
  4. data/lib/liquid.rb +8 -0
  5. data/lib/liquid/block.rb +50 -46
  6. data/lib/liquid/block_body.rb +123 -0
  7. data/lib/liquid/condition.rb +12 -5
  8. data/lib/liquid/context.rb +75 -148
  9. data/lib/liquid/errors.rb +50 -2
  10. data/lib/liquid/expression.rb +33 -0
  11. data/lib/liquid/parser_switching.rb +31 -0
  12. data/lib/liquid/profiler.rb +159 -0
  13. data/lib/liquid/profiler/hooks.rb +23 -0
  14. data/lib/liquid/range_lookup.rb +22 -0
  15. data/lib/liquid/standardfilters.rb +29 -4
  16. data/lib/liquid/tag.rb +6 -25
  17. data/lib/liquid/tags/assign.rb +2 -1
  18. data/lib/liquid/tags/case.rb +1 -1
  19. data/lib/liquid/tags/if.rb +5 -5
  20. data/lib/liquid/tags/ifchanged.rb +1 -1
  21. data/lib/liquid/tags/include.rb +11 -1
  22. data/lib/liquid/tags/raw.rb +1 -4
  23. data/lib/liquid/tags/table_row.rb +1 -1
  24. data/lib/liquid/template.rb +55 -4
  25. data/lib/liquid/token.rb +18 -0
  26. data/lib/liquid/variable.rb +68 -41
  27. data/lib/liquid/variable_lookup.rb +78 -0
  28. data/lib/liquid/version.rb +1 -1
  29. data/test/integration/assign_test.rb +12 -1
  30. data/test/integration/blank_test.rb +1 -1
  31. data/test/integration/capture_test.rb +1 -1
  32. data/test/integration/context_test.rb +10 -11
  33. data/test/integration/drop_test.rb +29 -3
  34. data/test/integration/error_handling_test.rb +138 -41
  35. data/test/integration/filter_test.rb +7 -7
  36. data/test/integration/hash_ordering_test.rb +6 -8
  37. data/test/integration/output_test.rb +1 -1
  38. data/test/integration/parsing_quirks_test.rb +40 -18
  39. data/test/integration/render_profiling_test.rb +154 -0
  40. data/test/integration/security_test.rb +1 -1
  41. data/test/integration/standard_filter_test.rb +47 -1
  42. data/test/integration/tags/break_tag_test.rb +1 -1
  43. data/test/integration/tags/continue_tag_test.rb +1 -1
  44. data/test/integration/tags/for_tag_test.rb +2 -2
  45. data/test/integration/tags/if_else_tag_test.rb +23 -20
  46. data/test/integration/tags/include_tag_test.rb +24 -2
  47. data/test/integration/tags/increment_tag_test.rb +1 -1
  48. data/test/integration/tags/raw_tag_test.rb +1 -1
  49. data/test/integration/tags/standard_tag_test.rb +4 -4
  50. data/test/integration/tags/statements_test.rb +1 -1
  51. data/test/integration/tags/table_row_test.rb +1 -1
  52. data/test/integration/tags/unless_else_tag_test.rb +1 -1
  53. data/test/integration/template_test.rb +16 -4
  54. data/test/integration/variable_test.rb +11 -1
  55. data/test/test_helper.rb +59 -31
  56. data/test/unit/block_unit_test.rb +2 -5
  57. data/test/unit/condition_unit_test.rb +5 -1
  58. data/test/unit/context_unit_test.rb +13 -7
  59. data/test/unit/file_system_unit_test.rb +5 -5
  60. data/test/unit/i18n_unit_test.rb +3 -3
  61. data/test/unit/lexer_unit_test.rb +1 -1
  62. data/test/unit/module_ex_unit_test.rb +1 -1
  63. data/test/unit/parser_unit_test.rb +1 -1
  64. data/test/unit/regexp_unit_test.rb +1 -1
  65. data/test/unit/strainer_unit_test.rb +3 -2
  66. data/test/unit/tag_unit_test.rb +6 -1
  67. data/test/unit/tags/case_tag_unit_test.rb +1 -1
  68. data/test/unit/tags/for_tag_unit_test.rb +1 -1
  69. data/test/unit/tags/if_tag_unit_test.rb +1 -1
  70. data/test/unit/template_unit_test.rb +1 -1
  71. data/test/unit/tokenizer_unit_test.rb +10 -1
  72. data/test/unit/variable_unit_test.rb +49 -46
  73. metadata +71 -47
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class StandardTagTest < Test::Unit::TestCase
3
+ class StandardTagTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_no_transform
@@ -66,7 +66,7 @@ class StandardTagTest < Test::Unit::TestCase
66
66
  end
67
67
 
68
68
  def test_capture_detects_bad_syntax
69
- assert_raise(SyntaxError) do
69
+ assert_raises(SyntaxError) do
70
70
  assert_template_result('content foo content foo ',
71
71
  '{{ var2 }}{% capture %}{{ var }} foo {% endcapture %}{{ var2 }}{{ var2 }}',
72
72
  {'var' => 'content' })
@@ -229,11 +229,11 @@ class StandardTagTest < Test::Unit::TestCase
229
229
  end
230
230
 
231
231
  def test_case_detects_bad_syntax
232
- assert_raise(SyntaxError) do
232
+ assert_raises(SyntaxError) do
233
233
  assert_template_result('', '{% case false %}{% when %}true{% endcase %}', {})
234
234
  end
235
235
 
236
- assert_raise(SyntaxError) do
236
+ assert_raises(SyntaxError) do
237
237
  assert_template_result('', '{% case false %}{% huh %}true{% endcase %}', {})
238
238
  end
239
239
 
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class StatementsTest < Test::Unit::TestCase
3
+ class StatementsTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_true_eql_true
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class TableRowTest < Test::Unit::TestCase
3
+ class TableRowTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  class ArrayDrop < Liquid::Drop
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class UnlessElseTagTest < Test::Unit::TestCase
3
+ class UnlessElseTagTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_unless
@@ -28,7 +28,7 @@ class ErroneousDrop < Liquid::Drop
28
28
  end
29
29
  end
30
30
 
31
- class TemplateTest < Test::Unit::TestCase
31
+ class TemplateTest < Minitest::Test
32
32
  include Liquid
33
33
 
34
34
  def test_instance_assigns_persist_on_same_template_object_between_parses
@@ -93,7 +93,7 @@ class TemplateTest < Test::Unit::TestCase
93
93
  assert t.resource_limits[:reached]
94
94
  t.resource_limits = { :render_length_limit => 10 }
95
95
  assert_equal "0123456789", t.render!()
96
- assert_not_nil t.resource_limits[:render_length_current]
96
+ refute_nil t.resource_limits[:render_length_current]
97
97
  end
98
98
 
99
99
  def test_resource_limits_render_score
@@ -107,7 +107,7 @@ class TemplateTest < Test::Unit::TestCase
107
107
  assert t.resource_limits[:reached]
108
108
  t.resource_limits = { :render_score_limit => 200 }
109
109
  assert_equal (" foo " * 100), t.render!()
110
- assert_not_nil t.resource_limits[:render_score_current]
110
+ refute_nil t.resource_limits[:render_score_current]
111
111
  end
112
112
 
113
113
  def test_resource_limits_assign_score
@@ -117,7 +117,7 @@ class TemplateTest < Test::Unit::TestCase
117
117
  assert t.resource_limits[:reached]
118
118
  t.resource_limits = { :assign_score_limit => 2 }
119
119
  assert_equal "", t.render!()
120
- assert_not_nil t.resource_limits[:assign_score_current]
120
+ refute_nil t.resource_limits[:assign_score_current]
121
121
  end
122
122
 
123
123
  def test_resource_limits_aborts_rendering_after_first_error
@@ -135,6 +135,18 @@ class TemplateTest < Test::Unit::TestCase
135
135
  assert t.resource_limits[:render_length_current] > 0
136
136
  end
137
137
 
138
+ def test_default_resource_limits_unaffected_by_render_with_context
139
+ context = Context.new
140
+ t = Template.parse("{% for a in (1..100) %} {% assign foo = 1 %} {% endfor %}")
141
+ t.render!(context)
142
+ assert context.resource_limits[:assign_score_current] > 0
143
+ assert context.resource_limits[:render_score_current] > 0
144
+ assert context.resource_limits[:render_length_current] > 0
145
+ refute Template.default_resource_limits.key?(:assign_score_current)
146
+ refute Template.default_resource_limits.key?(:render_score_current)
147
+ refute Template.default_resource_limits.key?(:render_length_current)
148
+ end
149
+
138
150
  def test_can_use_drop_as_context
139
151
  t = Template.new
140
152
  t.registers['lulz'] = 'haha'
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class VariableTest < Test::Unit::TestCase
3
+ class VariableTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_simple_variable
@@ -9,6 +9,10 @@ class VariableTest < Test::Unit::TestCase
9
9
  assert_equal 'worked wonderfully', template.render!('test' => 'worked wonderfully')
10
10
  end
11
11
 
12
+ def test_variable_render_calls_to_liquid
13
+ assert_template_result 'foobar', '{{ foo }}', 'foo' => ThingWithToLiquid.new
14
+ end
15
+
12
16
  def test_simple_with_whitespaces
13
17
  template = Template.parse(%| {{ test }} |)
14
18
  assert_equal ' worked ', template.render!('test' => 'worked')
@@ -27,6 +31,12 @@ class VariableTest < Test::Unit::TestCase
27
31
 
28
32
  def test_false_renders_as_false
29
33
  assert_equal 'false', Template.parse("{{ foo }}").render!('foo' => false)
34
+ assert_equal 'false', Template.parse("{{ false }}").render!
35
+ end
36
+
37
+ def test_nil_renders_as_empty_string
38
+ assert_equal '', Template.parse("{{ nil }}").render!
39
+ assert_equal 'cat', Template.parse("{{ nil | append: 'cat' }}").render!
30
40
  end
31
41
 
32
42
  def test_preset_assigns
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'test/unit'
4
- require 'test/unit/assertions'
3
+ require 'minitest/autorun'
5
4
  require 'spy/integration'
6
5
 
7
6
  $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
@@ -14,41 +13,70 @@ if env_mode = ENV['LIQUID_PARSER_MODE']
14
13
  end
15
14
  Liquid::Template.error_mode = mode
16
15
 
16
+ if Minitest.const_defined?('Test')
17
+ # We're on Minitest 5+. Nothing to do here.
18
+ else
19
+ # Minitest 4 doesn't have Minitest::Test yet.
20
+ Minitest::Test = MiniTest::Unit::TestCase
21
+ end
17
22
 
18
- module Test
19
- module Unit
20
- class TestCase
21
- def fixture(name)
22
- File.join(File.expand_path(File.dirname(__FILE__)), "fixtures", name)
23
- end
23
+ module Minitest
24
+ class Test
25
+ def fixture(name)
26
+ File.join(File.expand_path(File.dirname(__FILE__)), "fixtures", name)
24
27
  end
28
+ end
25
29
 
26
- module Assertions
27
- include Liquid
30
+ module Assertions
31
+ include Liquid
28
32
 
29
- def assert_template_result(expected, template, assigns = {}, message = nil)
30
- assert_equal expected, Template.parse(template).render!(assigns)
31
- end
33
+ def assert_template_result(expected, template, assigns = {}, message = nil)
34
+ assert_equal expected, Template.parse(template).render!(assigns)
35
+ end
32
36
 
33
- def assert_template_result_matches(expected, template, assigns = {}, message = nil)
34
- return assert_template_result(expected, template, assigns, message) unless expected.is_a? Regexp
37
+ def assert_template_result_matches(expected, template, assigns = {}, message = nil)
38
+ return assert_template_result(expected, template, assigns, message) unless expected.is_a? Regexp
35
39
 
36
- assert_match expected, Template.parse(template).render!(assigns)
37
- end
40
+ assert_match expected, Template.parse(template).render!(assigns)
41
+ end
38
42
 
39
- def assert_match_syntax_error(match, template, registers = {})
40
- exception = assert_raise(Liquid::SyntaxError) {
41
- Template.parse(template).render(assigns)
42
- }
43
- assert_match match, exception.message
44
- end
43
+ def assert_match_syntax_error(match, template, registers = {})
44
+ exception = assert_raises(Liquid::SyntaxError) {
45
+ Template.parse(template).render(assigns)
46
+ }
47
+ assert_match match, exception.message
48
+ end
45
49
 
46
- def with_error_mode(mode)
47
- old_mode = Liquid::Template.error_mode
48
- Liquid::Template.error_mode = mode
49
- yield
50
- Liquid::Template.error_mode = old_mode
50
+ def with_global_filter(*globals)
51
+ original_filters = Array.new(Liquid::Strainer.class_variable_get(:@@filters))
52
+ globals.each do |global|
53
+ Liquid::Template.register_filter(global)
51
54
  end
52
- end # Assertions
53
- end # Unit
54
- end # Test
55
+ yield
56
+ ensure
57
+ Liquid::Strainer.class_variable_set(:@@filters, original_filters)
58
+ end
59
+
60
+ def with_taint_mode(mode)
61
+ old_mode = Liquid::Template.taint_mode
62
+ Liquid::Template.taint_mode = mode
63
+ yield
64
+ ensure
65
+ Liquid::Template.taint_mode = old_mode
66
+ end
67
+
68
+ def with_error_mode(mode)
69
+ old_mode = Liquid::Template.error_mode
70
+ Liquid::Template.error_mode = mode
71
+ yield
72
+ ensure
73
+ Liquid::Template.error_mode = old_mode
74
+ end
75
+ end
76
+ end
77
+
78
+ class ThingWithToLiquid
79
+ def to_liquid
80
+ 'foobar'
81
+ end
82
+ end
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class BlockUnitTest < Test::Unit::TestCase
3
+ class BlockUnitTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_blankspace
@@ -45,10 +45,7 @@ class BlockUnitTest < Test::Unit::TestCase
45
45
 
46
46
  def test_with_custom_tag
47
47
  Liquid::Template.register_tag("testtag", Block)
48
-
49
- assert_nothing_thrown do
50
- template = Liquid::Template.parse( "{% testtag %} {% endtesttag %}")
51
- end
48
+ assert Liquid::Template.parse( "{% testtag %} {% endtesttag %}")
52
49
  end
53
50
 
54
51
  private
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class ConditionUnitTest < Test::Unit::TestCase
3
+ class ConditionUnitTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_basic_condition
@@ -80,6 +80,10 @@ class ConditionUnitTest < Test::Unit::TestCase
80
80
  assert_evalutes_false "0", 'contains', 'not_assigned'
81
81
  end
82
82
 
83
+ def test_contains_return_false_on_wrong_data_type
84
+ assert_evalutes_false "1", 'contains', '0'
85
+ end
86
+
83
87
  def test_or_condition
84
88
  condition = Condition.new('1', '==', '2')
85
89
 
@@ -63,7 +63,7 @@ class ArrayLike
63
63
  end
64
64
  end
65
65
 
66
- class ContextUnitTest < Test::Unit::TestCase
66
+ class ContextUnitTest < Minitest::Test
67
67
  include Liquid
68
68
 
69
69
  def setup
@@ -107,16 +107,14 @@ class ContextUnitTest < Test::Unit::TestCase
107
107
  end
108
108
 
109
109
  def test_scoping
110
- assert_nothing_raised do
111
- @context.push
112
- @context.pop
113
- end
110
+ @context.push
111
+ @context.pop
114
112
 
115
- assert_raise(Liquid::ContextError) do
113
+ assert_raises(Liquid::ContextError) do
116
114
  @context.pop
117
115
  end
118
116
 
119
- assert_raise(Liquid::ContextError) do
117
+ assert_raises(Liquid::ContextError) do
120
118
  @context.push
121
119
  @context.pop
122
120
  @context.pop
@@ -483,4 +481,12 @@ class ContextUnitTest < Test::Unit::TestCase
483
481
  assert_equal 1, mock_scan.calls.size
484
482
  end
485
483
 
484
+ def test_context_initialization_with_a_proc_in_environment
485
+ contx = Context.new([:test => lambda { |c| c['poutine']}], {:test => :foo})
486
+
487
+ assert contx
488
+ assert_nil contx['poutine']
489
+ end
490
+
491
+
486
492
  end # ContextTest
@@ -1,10 +1,10 @@
1
1
  require 'test_helper'
2
2
 
3
- class FileSystemUnitTest < Test::Unit::TestCase
3
+ class FileSystemUnitTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_default
7
- assert_raise(FileSystemError) do
7
+ assert_raises(FileSystemError) do
8
8
  BlankFileSystem.new.read_template_file("dummy", {'dummy'=>'smarty'})
9
9
  end
10
10
  end
@@ -14,15 +14,15 @@ class FileSystemUnitTest < Test::Unit::TestCase
14
14
  assert_equal "/some/path/_mypartial.liquid" , file_system.full_path("mypartial")
15
15
  assert_equal "/some/path/dir/_mypartial.liquid", file_system.full_path("dir/mypartial")
16
16
 
17
- assert_raise(FileSystemError) do
17
+ assert_raises(FileSystemError) do
18
18
  file_system.full_path("../dir/mypartial")
19
19
  end
20
20
 
21
- assert_raise(FileSystemError) do
21
+ assert_raises(FileSystemError) do
22
22
  file_system.full_path("/dir/../../dir/mypartial")
23
23
  end
24
24
 
25
- assert_raise(FileSystemError) do
25
+ assert_raises(FileSystemError) do
26
26
  file_system.full_path("/etc/passwd")
27
27
  end
28
28
  end
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class I18nUnitTest < Test::Unit::TestCase
3
+ class I18nUnitTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def setup
@@ -20,13 +20,13 @@ class I18nUnitTest < Test::Unit::TestCase
20
20
  end
21
21
 
22
22
  # def test_raises_translation_error_on_undefined_interpolation_key
23
- # assert_raise I18n::TranslationError do
23
+ # assert_raises I18n::TranslationError do
24
24
  # @i18n.translate("whatever", :oopstypos => "yes")
25
25
  # end
26
26
  # end
27
27
 
28
28
  def test_raises_unknown_translation
29
- assert_raise I18n::TranslationError do
29
+ assert_raises I18n::TranslationError do
30
30
  @i18n.translate("doesnt_exist")
31
31
  end
32
32
  end
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class LexerUnitTest < Test::Unit::TestCase
3
+ class LexerUnitTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_strings
@@ -36,7 +36,7 @@ class TestClassC::LiquidDropClass
36
36
  end
37
37
  end
38
38
 
39
- class ModuleExUnitTest < Test::Unit::TestCase
39
+ class ModuleExUnitTest < Minitest::Test
40
40
  include Liquid
41
41
 
42
42
  def setup
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class ParserUnitTest < Test::Unit::TestCase
3
+ class ParserUnitTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_consume
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class RegexpUnitTest < Test::Unit::TestCase
3
+ class RegexpUnitTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_empty
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class StrainerUnitTest < Test::Unit::TestCase
3
+ class StrainerUnitTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  module AccessScopeFilters
@@ -57,7 +57,8 @@ class StrainerUnitTest < Test::Unit::TestCase
57
57
  end
58
58
 
59
59
  def test_strainer_uses_a_class_cache_to_avoid_method_cache_invalidation
60
- a, b = Module.new, Module.new
60
+ a = Module.new
61
+ b = Module.new
61
62
  strainer = Strainer.create(nil, [a,b])
62
63
  assert_kind_of Strainer, strainer
63
64
  assert_kind_of a, strainer
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class TagUnitTest < Test::Unit::TestCase
3
+ class TagUnitTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_tag
@@ -8,4 +8,9 @@ class TagUnitTest < Test::Unit::TestCase
8
8
  assert_equal 'liquid::tag', tag.name
9
9
  assert_equal '', tag.render(Context.new)
10
10
  end
11
+
12
+ def test_return_raw_text_of_tag
13
+ tag = Tag.parse("long_tag", "param1, param2, param3", [], {})
14
+ assert_equal("long_tag param1, param2, param3", tag.raw)
15
+ end
11
16
  end