locomotivecms_solid 0.2.1

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 (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