locomotivecms_solid 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.gitignore +4 -0
  2. data/.rspec +1 -0
  3. data/.rvmrc +1 -0
  4. data/.travis.yml +9 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +20 -0
  7. data/README.md +152 -0
  8. data/Rakefile +7 -0
  9. data/lib/locomotivecms_solid.rb +2 -0
  10. data/lib/solid/arguments.rb +28 -0
  11. data/lib/solid/block.rb +13 -0
  12. data/lib/solid/conditional_block.rb +35 -0
  13. data/lib/solid/context_error.rb +2 -0
  14. data/lib/solid/default_security_rules.rb +24 -0
  15. data/lib/solid/element.rb +51 -0
  16. data/lib/solid/engine.rb +4 -0
  17. data/lib/solid/extensions.rb +17 -0
  18. data/lib/solid/iterable.rb +18 -0
  19. data/lib/solid/liquid_extensions/assign_tag.rb +21 -0
  20. data/lib/solid/liquid_extensions/for_tag.rb +102 -0
  21. data/lib/solid/liquid_extensions/if_tag.rb +44 -0
  22. data/lib/solid/liquid_extensions/unless_tag.rb +13 -0
  23. data/lib/solid/liquid_extensions/variable.rb +34 -0
  24. data/lib/solid/liquid_extensions.rb +87 -0
  25. data/lib/solid/method_whitelist.rb +56 -0
  26. data/lib/solid/model_drop.rb +119 -0
  27. data/lib/solid/parser.rb +265 -0
  28. data/lib/solid/tag.rb +11 -0
  29. data/lib/solid/template.rb +24 -0
  30. data/lib/solid/version.rb +3 -0
  31. data/lib/solid.rb +48 -0
  32. data/locomotivecms_solid.gemspec +25 -0
  33. data/spec/solid/arguments_spec.rb +310 -0
  34. data/spec/solid/block_spec.rb +39 -0
  35. data/spec/solid/conditional_block_spec.rb +39 -0
  36. data/spec/solid/default_security_rules_spec.rb +180 -0
  37. data/spec/solid/element_examples.rb +67 -0
  38. data/spec/solid/liquid_extensions/assign_tag_spec.rb +27 -0
  39. data/spec/solid/liquid_extensions/for_tag_spec.rb +48 -0
  40. data/spec/solid/liquid_extensions/if_tag_spec.rb +64 -0
  41. data/spec/solid/liquid_extensions/unless_tag_spec.rb +54 -0
  42. data/spec/solid/liquid_extensions/variable_spec.rb +25 -0
  43. data/spec/solid/model_drop_spec.rb +26 -0
  44. data/spec/solid/tag_spec.rb +26 -0
  45. data/spec/solid/template_spec.rb +37 -0
  46. data/spec/spec_helper.rb +8 -0
  47. data/spec/support/class_highjacker_examples.rb +33 -0
  48. data/spec/support/method_whitelist_matchers.rb +17 -0
  49. data/spec/support/tag_highjacker_examples.rb +33 -0
  50. metadata +201 -0
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ # FIXME: disabled for now
4
+
5
+ # describe Solid::LiquidExtensions::ForTag do
6
+ # it_should_behave_like 'a tag highjacker'
7
+
8
+ # context 'when Liquid::For is replaced' do
9
+
10
+ # before :each do
11
+ # described_class.load!
12
+ # end
13
+
14
+ # after :each do
15
+ # described_class.unload!
16
+ # end
17
+
18
+ # it 'should allow complex expression inside a for tag' do
19
+ # template = Solid::Template.parse(%(
20
+ # {% for foo in foos.concat(foos.reverse).flatten %}
21
+ # {{ foo }}
22
+ # {% endfor %}
23
+ # ))
24
+ # output = template.render('foos' => [1, 2, 3]).gsub(/[^\d]/, '')
25
+ # output.should be == '123321'
26
+ # end
27
+
28
+ # it 'should still provide the "forloop" object' do
29
+ # template = Solid::Template.parse(%(
30
+ # {% for foo in foos %}{{ forloop.first }},{{ forloop.index0 }}/{{ forloop.length }},{{ forloop.last }}|{% endfor %}
31
+ # ))
32
+ # output = template.render('foos' => [1, 2, 3]).strip
33
+ # output.should be == "true,0/3,false|false,1/3,false|false,2/3,true|"
34
+ # end
35
+
36
+ # it 'should consider all non iterable objects as empty arrays' do
37
+ # template = Solid::Template.parse(%(
38
+ # {% for foo in foos %}
39
+ # {{ foo }}
40
+ # {% endfor %}
41
+ # ))
42
+ # output = template.render('foos' => nil).strip
43
+ # output.should be == ''
44
+ # end
45
+
46
+ # end
47
+
48
+ # end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe Solid::LiquidExtensions::IfTag do
4
+ it_should_behave_like 'a tag highjacker'
5
+
6
+ context 'when Liquid::If is replaced' do
7
+
8
+ before :each do
9
+ described_class.load!
10
+ end
11
+
12
+ after :each do
13
+ described_class.unload!
14
+ end
15
+
16
+ it 'should allow complex expression inside an if tag' do
17
+ template = Solid::Template.parse(%(
18
+ {% if foo.include?('bar') %}
19
+ Hello !
20
+ {% endif %}
21
+ ))
22
+ output = template.render('foo' => ' bar ').strip
23
+ output.should be == 'Hello !'
24
+ end
25
+
26
+ it 'should render nothing if the predicate return false' do
27
+ template = Solid::Template.parse(%(
28
+ {% if foo.include?('bar') %}
29
+ Hello !
30
+ {% endif %}
31
+ ))
32
+ output = template.render('foo' => ' plop ').strip
33
+ output.should be == ''
34
+ end
35
+
36
+ it 'should still accept an else tag' do
37
+ template = Solid::Template.parse(%(
38
+ {% if foo.include?('bar') %}
39
+ Hello !
40
+ {% else %}
41
+ Failed
42
+ {% endif %}
43
+ ))
44
+ output = template.render('foo' => ' spam ').strip
45
+ output.should be == 'Failed'
46
+ end
47
+
48
+ it 'should still accept some elsif tags' do
49
+ template = Solid::Template.parse(%(
50
+ {% if foo.include?('bar') %}
51
+ Hello !
52
+ {% elsif foo.include?('spam') %}
53
+ World !
54
+ {% else %}
55
+ Failed
56
+ {% endif %}
57
+ ))
58
+ output = template.render('foo' => ' spam ').strip
59
+ output.should be == 'World !'
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe Solid::LiquidExtensions::UnlessTag do
4
+ it_should_behave_like 'a tag highjacker'
5
+
6
+ context 'when Liquid::Unless is replaced' do
7
+
8
+ before :each do
9
+ described_class.load!
10
+ end
11
+
12
+ after :each do
13
+ described_class.unload!
14
+ end
15
+
16
+ it 'should allow complex expression inside an unless tag' do
17
+ template = Solid::Template.parse(%(
18
+ {% unless foo.include?('bar') %}
19
+ Hello !
20
+ {% endunless %}
21
+ ))
22
+ output = template.render('foo' => ' spam ').strip
23
+ output.should be == 'Hello !'
24
+ end
25
+
26
+ it 'should still accept an else tag' do
27
+ template = Solid::Template.parse(%(
28
+ {% unless foo.include?('bar') %}
29
+ Hello !
30
+ {% else %}
31
+ Failed
32
+ {% endunless %}
33
+ ))
34
+ output = template.render('foo' => ' bar ').strip
35
+ output.should be == 'Failed'
36
+ end
37
+
38
+ it 'should still accept some elsif tags' do
39
+ template = Solid::Template.parse(%(
40
+ {% unless foo.include?('spam') %}
41
+ Hello !
42
+ {% elsif foo.include?('spam') %}
43
+ World !
44
+ {% else %}
45
+ Failed
46
+ {% endunless %}
47
+ ))
48
+ output = template.render('foo' => ' spam ').strip
49
+ output.should be == 'World !'
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Solid::LiquidExtensions::Variable do
4
+ it_should_behave_like 'a class highjacker'
5
+
6
+ context 'real world example' do
7
+
8
+ before :each do
9
+ described_class.load!
10
+ end
11
+
12
+ after :each do
13
+ described_class.unload!
14
+ end
15
+
16
+ let(:template) { template = Solid::Template.parse('{{ foo.include?("bar") | upcase }}') }
17
+
18
+ it 'should allow method call with arguments in variables brackets' do
19
+ template.render('foo' => 'egg bar spam').should be == 'TRUE'
20
+ template.render('foo' => '').should be == 'FALSE'
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+ require 'active_support/core_ext'
3
+ require 'ostruct'
4
+ Rails = OpenStruct.new(env: OpenStruct.new(test?: true))
5
+ require 'solid/model_drop'
6
+
7
+ describe Solid::ModelDrop do
8
+ describe "array methods" do
9
+
10
+ it "work on a drop" do
11
+ drop = described_class.new([1, 2, 3])
12
+ drop.reverse.should be == [3, 2, 1]
13
+ end
14
+
15
+ it "go through #each" do
16
+ klass = Class.new(described_class) do
17
+ def each
18
+ super.select(&:odd?)
19
+ end
20
+ end
21
+ drop = klass.new([1, 2, 3])
22
+ drop.reverse.should be == [3, 1]
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ class DummyTag < Solid::Tag
4
+
5
+ def display(*args)
6
+ args.inspect
7
+ end
8
+
9
+ end
10
+
11
+ describe Solid::Tag do
12
+
13
+ it_behaves_like "a Solid element"
14
+
15
+ subject{ DummyTag.new('dummy', '1, "foo", myvar, myopts: false', 'token') }
16
+
17
+ it 'should works' do
18
+ subject.render('myvar' => 'bar').should be == '[1, "foo", "bar", {:myopts=>false}]'
19
+ end
20
+
21
+ it 'should send all parsed arguments do #display' do
22
+ subject.should_receive(:display).with(1, 'foo', 'bar', :myopts => false).and_return('result')
23
+ subject.render('myvar' => 'bar').should be == 'result'
24
+ end
25
+
26
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Solid::Template do
4
+
5
+ let(:liquid) { %{first_string{% comment %}
6
+ {% if foo %}ifcontent{% endif %}
7
+ {% if foo %}ifsecondcontent{% endif %}
8
+ {% endcomment %}
9
+ {% unless foo %}unlesscontent{% endunless %}
10
+
11
+ } }
12
+
13
+ let(:template) { Solid::Template.parse(liquid) }
14
+
15
+ specify { subject.should be_an(Enumerable) }
16
+
17
+ describe '#each' do
18
+
19
+ let(:yielded_nodes) do
20
+ [].tap do |nodes|
21
+ template.each{ |node| nodes << node }
22
+ end
23
+ end
24
+
25
+ let(:yielded_classes) { yielded_nodes.map(&:class) }
26
+
27
+ it 'should yield parent nodes before child nodes' do
28
+ yielded_classes.index(Liquid::Comment).should be < yielded_classes.index(Liquid::If)
29
+ end
30
+
31
+ it 'should yield first sibling first (No ! really ? ...)' do
32
+ yielded_classes.index(Liquid::Comment).should be < yielded_classes.index(Liquid::Unless)
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,8 @@
1
+ require 'rspec'
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'solid'))
3
+
4
+ RSpec.configure do |c|
5
+ c.mock_with :rspec
6
+ end
7
+
8
+ Dir[File.join(File.dirname(__FILE__), '/**/*_examples.rb'), File.join(File.dirname(__FILE__), '/**/*_matchers.rb')].each{ |f| require f }
@@ -0,0 +1,33 @@
1
+ shared_examples "a class highjacker" do
2
+
3
+ context 'class highjacking' do
4
+
5
+ let(:highjacked_class_name) { "Liquid::#{described_class.demodulized_name}" }
6
+
7
+ def highjacked_class
8
+ highjacked_class_name.split('::').inject(Object) { |klass, const_name| klass.const_get(const_name) }
9
+ end
10
+
11
+ after :each do
12
+ described_class.unload!
13
+ end
14
+
15
+ let!(:original_class_id) { highjacked_class.object_id }
16
+
17
+ it 'should be able to replace original class' do
18
+ expect{
19
+ described_class.load!
20
+ }.to change{ highjacked_class.object_id }.from(original_class_id).to(described_class.object_id)
21
+ end
22
+
23
+ it 'should be able to restore original class' do
24
+ described_class.load!
25
+ expect{
26
+ described_class.unload!
27
+ }.to change{ highjacked_class.object_id }.from(described_class.object_id).to(original_class_id)
28
+ end
29
+
30
+ end
31
+
32
+
33
+ end
@@ -0,0 +1,17 @@
1
+ RSpec::Matchers.define :safely_respond_to do |method_name|
2
+ match do |object|
3
+ Solid::MethodWhitelist.safely_respond_to?(object, method_name)
4
+ end
5
+ end
6
+
7
+ def it_should_safely_respond_to(*methods)
8
+ methods.each do |method|
9
+ it { should safely_respond_to method }
10
+ end
11
+ end
12
+
13
+ def it_should_not_safely_respond_to(*methods)
14
+ methods.each do |method|
15
+ it { should_not safely_respond_to method }
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ shared_examples "a tag highjacker" do
2
+
3
+ context 'tag highjacking' do
4
+
5
+ let(:highjacked_tag_name) { described_class.tag_name.to_s }
6
+
7
+ def highjacked_tag
8
+ Liquid::Template.tags[highjacked_tag_name]
9
+ end
10
+
11
+ after :each do
12
+ described_class.unload!
13
+ end
14
+
15
+ let!(:original_tag_id) { highjacked_tag.object_id }
16
+
17
+ it 'should be able to replace original tag class' do
18
+ expect{
19
+ described_class.load!
20
+ }.to change{ highjacked_tag.object_id }.from(original_tag_id).to(described_class.object_id)
21
+ end
22
+
23
+ it 'should be able to restore original tag class' do
24
+ described_class.load!
25
+ expect{
26
+ described_class.unload!
27
+ }.to change{ highjacked_tag.object_id }.from(described_class.object_id).to(original_tag_id)
28
+ end
29
+
30
+ end
31
+
32
+
33
+ end
metadata ADDED
@@ -0,0 +1,201 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: locomotivecms_solid
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jean Boussier
9
+ - Yannick François
10
+ - Didier Lafforgue
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2013-08-19 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rspec
18
+ requirement: !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ! '>='
22
+ - !ruby/object:Gem::Version
23
+ version: '0'
24
+ type: :development
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ! '>='
30
+ - !ruby/object:Gem::Version
31
+ version: '0'
32
+ - !ruby/object:Gem::Dependency
33
+ name: rake
34
+ requirement: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ - !ruby/object:Gem::Dependency
49
+ name: i18n
50
+ requirement: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ - !ruby/object:Gem::Dependency
65
+ name: activesupport
66
+ requirement: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ~>
70
+ - !ruby/object:Gem::Version
71
+ version: '3'
72
+ type: :development
73
+ prerelease: false
74
+ version_requirements: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ~>
78
+ - !ruby/object:Gem::Version
79
+ version: '3'
80
+ - !ruby/object:Gem::Dependency
81
+ name: locomotive_liquid
82
+ requirement: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ version: 2.4.2
88
+ type: :runtime
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ~>
94
+ - !ruby/object:Gem::Version
95
+ version: 2.4.2
96
+ description: The Solid gem from the TigerLily team but modified to work with LocomotiveCMS
97
+ email:
98
+ - jean.boussier@tigerlilyapps.com
99
+ - yannick@tigerlilyapps.com
100
+ - didier.lafforgue@gmail.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - .gitignore
106
+ - .rspec
107
+ - .rvmrc
108
+ - .travis.yml
109
+ - Gemfile
110
+ - LICENSE
111
+ - README.md
112
+ - Rakefile
113
+ - lib/locomotivecms_solid.rb
114
+ - lib/solid.rb
115
+ - lib/solid/arguments.rb
116
+ - lib/solid/block.rb
117
+ - lib/solid/conditional_block.rb
118
+ - lib/solid/context_error.rb
119
+ - lib/solid/default_security_rules.rb
120
+ - lib/solid/element.rb
121
+ - lib/solid/engine.rb
122
+ - lib/solid/extensions.rb
123
+ - lib/solid/iterable.rb
124
+ - lib/solid/liquid_extensions.rb
125
+ - lib/solid/liquid_extensions/assign_tag.rb
126
+ - lib/solid/liquid_extensions/for_tag.rb
127
+ - lib/solid/liquid_extensions/if_tag.rb
128
+ - lib/solid/liquid_extensions/unless_tag.rb
129
+ - lib/solid/liquid_extensions/variable.rb
130
+ - lib/solid/method_whitelist.rb
131
+ - lib/solid/model_drop.rb
132
+ - lib/solid/parser.rb
133
+ - lib/solid/tag.rb
134
+ - lib/solid/template.rb
135
+ - lib/solid/version.rb
136
+ - locomotivecms_solid.gemspec
137
+ - spec/solid/arguments_spec.rb
138
+ - spec/solid/block_spec.rb
139
+ - spec/solid/conditional_block_spec.rb
140
+ - spec/solid/default_security_rules_spec.rb
141
+ - spec/solid/element_examples.rb
142
+ - spec/solid/liquid_extensions/assign_tag_spec.rb
143
+ - spec/solid/liquid_extensions/for_tag_spec.rb
144
+ - spec/solid/liquid_extensions/if_tag_spec.rb
145
+ - spec/solid/liquid_extensions/unless_tag_spec.rb
146
+ - spec/solid/liquid_extensions/variable_spec.rb
147
+ - spec/solid/model_drop_spec.rb
148
+ - spec/solid/tag_spec.rb
149
+ - spec/solid/template_spec.rb
150
+ - spec/spec_helper.rb
151
+ - spec/support/class_highjacker_examples.rb
152
+ - spec/support/method_whitelist_matchers.rb
153
+ - spec/support/tag_highjacker_examples.rb
154
+ homepage: ''
155
+ licenses: []
156
+ post_install_message:
157
+ rdoc_options: []
158
+ require_paths:
159
+ - lib
160
+ required_ruby_version: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ segments:
167
+ - 0
168
+ hash: -2528832747906395320
169
+ required_rubygems_version: !ruby/object:Gem::Requirement
170
+ none: false
171
+ requirements:
172
+ - - ! '>='
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ segments:
176
+ - 0
177
+ hash: -2528832747906395320
178
+ requirements: []
179
+ rubyforge_project:
180
+ rubygems_version: 1.8.23
181
+ signing_key:
182
+ specification_version: 3
183
+ summary: Helpers for easily creating custom Liquid tags and block
184
+ test_files:
185
+ - spec/solid/arguments_spec.rb
186
+ - spec/solid/block_spec.rb
187
+ - spec/solid/conditional_block_spec.rb
188
+ - spec/solid/default_security_rules_spec.rb
189
+ - spec/solid/element_examples.rb
190
+ - spec/solid/liquid_extensions/assign_tag_spec.rb
191
+ - spec/solid/liquid_extensions/for_tag_spec.rb
192
+ - spec/solid/liquid_extensions/if_tag_spec.rb
193
+ - spec/solid/liquid_extensions/unless_tag_spec.rb
194
+ - spec/solid/liquid_extensions/variable_spec.rb
195
+ - spec/solid/model_drop_spec.rb
196
+ - spec/solid/tag_spec.rb
197
+ - spec/solid/template_spec.rb
198
+ - spec/spec_helper.rb
199
+ - spec/support/class_highjacker_examples.rb
200
+ - spec/support/method_whitelist_matchers.rb
201
+ - spec/support/tag_highjacker_examples.rb