curlybars 1.3.1 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/lib/curlybars.rb +8 -1
  3. data/lib/curlybars/configuration.rb +1 -9
  4. data/lib/curlybars/error/base.rb +2 -0
  5. data/lib/curlybars/generic.rb +36 -0
  6. data/lib/curlybars/lexer.rb +3 -0
  7. data/lib/curlybars/method_whitelist.rb +25 -3
  8. data/lib/curlybars/node/block_helper_else.rb +1 -0
  9. data/lib/curlybars/node/each_else.rb +6 -2
  10. data/lib/curlybars/node/if_else.rb +1 -1
  11. data/lib/curlybars/node/path.rb +58 -11
  12. data/lib/curlybars/node/sub_expression.rb +108 -0
  13. data/lib/curlybars/node/unless_else.rb +1 -1
  14. data/lib/curlybars/node/with_else.rb +6 -2
  15. data/lib/curlybars/parser.rb +39 -0
  16. data/lib/curlybars/processor/tilde.rb +3 -0
  17. data/lib/curlybars/rendering_support.rb +9 -1
  18. data/lib/curlybars/template_handler.rb +18 -6
  19. data/lib/curlybars/version.rb +1 -1
  20. data/lib/curlybars/visitor.rb +6 -0
  21. data/spec/acceptance/application_layout_spec.rb +2 -2
  22. data/spec/acceptance/collection_blocks_spec.rb +1 -1
  23. data/spec/acceptance/global_helper_spec.rb +1 -1
  24. data/spec/curlybars/lexer_spec.rb +25 -2
  25. data/spec/curlybars/method_whitelist_spec.rb +8 -4
  26. data/spec/curlybars/rendering_support_spec.rb +4 -9
  27. data/spec/curlybars/template_handler_spec.rb +33 -30
  28. data/spec/integration/cache_spec.rb +20 -18
  29. data/spec/integration/node/block_helper_else_spec.rb +0 -2
  30. data/spec/integration/node/each_else_spec.rb +208 -4
  31. data/spec/integration/node/each_spec.rb +0 -2
  32. data/spec/integration/node/helper_spec.rb +12 -2
  33. data/spec/integration/node/if_else_spec.rb +0 -2
  34. data/spec/integration/node/if_spec.rb +2 -4
  35. data/spec/integration/node/output_spec.rb +0 -2
  36. data/spec/integration/node/partial_spec.rb +0 -2
  37. data/spec/integration/node/path_spec.rb +0 -2
  38. data/spec/integration/node/root_spec.rb +0 -2
  39. data/spec/integration/node/sub_expression_spec.rb +426 -0
  40. data/spec/integration/node/template_spec.rb +0 -2
  41. data/spec/integration/node/unless_else_spec.rb +2 -4
  42. data/spec/integration/node/unless_spec.rb +0 -2
  43. data/spec/integration/node/with_spec.rb +66 -4
  44. data/spec/integration/processor/tilde_spec.rb +1 -1
  45. data/spec/integration/processors_spec.rb +4 -5
  46. data/spec/integration/visitor_spec.rb +13 -5
  47. metadata +49 -15
@@ -53,8 +53,6 @@ describe "template" do
53
53
  end
54
54
 
55
55
  describe "#validate" do
56
- let(:presenter_class) { double(:presenter_class) }
57
-
58
56
  it "without errors" do
59
57
  dependency_tree = { presenter: { field: nil } }
60
58
 
@@ -82,8 +82,6 @@ describe "{{#unless}}...{{else}}...{{/unless}}" do
82
82
  end
83
83
 
84
84
  describe "#validate" do
85
- let(:presenter_class) { double(:presenter_class) }
86
-
87
85
  it "validates with errors the condition" do
88
86
  dependency_tree = {}
89
87
 
@@ -96,7 +94,7 @@ describe "{{#unless}}...{{else}}...{{/unless}}" do
96
94
  expect(errors).not_to be_empty
97
95
  end
98
96
 
99
- it "validates with errors the helper as condition" do
97
+ it "validates without errors when using a helper in the condition" do
100
98
  dependency_tree = { helper: :helper }
101
99
 
102
100
  source = <<-HBS
@@ -105,7 +103,7 @@ describe "{{#unless}}...{{else}}...{{/unless}}" do
105
103
 
106
104
  errors = Curlybars.validate(dependency_tree, source)
107
105
 
108
- expect(errors).not_to be_empty
106
+ expect(errors).to be_empty
109
107
  end
110
108
 
111
109
  it "validates with errors the nested unless_template" do
@@ -99,8 +99,6 @@ describe "{{#unless}}...{{/unless}}" do
99
99
  end
100
100
 
101
101
  describe "#validate" do
102
- let(:presenter_class) { double(:presenter_class) }
103
-
104
102
  it "validates with errors the condition" do
105
103
  dependency_tree = {}
106
104
 
@@ -1,5 +1,5 @@
1
1
  describe "{{#with presenter}}...{{/with}}" do
2
- let(:global_helpers_providers) { [] }
2
+ let(:global_helpers_providers) { [IntegrationTest::GlobalHelperProvider.new] }
3
3
 
4
4
  describe "#compile" do
5
5
  let(:post) { double("post") }
@@ -31,6 +31,18 @@ describe "{{#with presenter}}...{{/with}}" do
31
31
  HTML
32
32
  end
33
33
 
34
+ it "allows subexpressions" do
35
+ template = Curlybars.compile(<<-HBS)
36
+ {{#with (translate user "sk-SK")}}
37
+ {{avatar.url}}
38
+ {{/with}}
39
+ HBS
40
+
41
+ expect(eval(template)).to resemble(<<-HTML)
42
+ http://example.com/foo.png?locale=sk-SK
43
+ HTML
44
+ end
45
+
34
46
  it "allows empty with_template" do
35
47
  template = Curlybars.compile(<<-HBS)
36
48
  {{#with user}}{{/with}}
@@ -39,7 +51,7 @@ describe "{{#with presenter}}...{{/with}}" do
39
51
  expect(eval(template)).to resemble("")
40
52
  end
41
53
 
42
- it "renders the else templte if the context is nil" do
54
+ it "renders the else template if the context is nil" do
43
55
  template = Curlybars.compile(<<-HBS)
44
56
  {{#with return_nil}}
45
57
  text
@@ -75,8 +87,6 @@ describe "{{#with presenter}}...{{/with}}" do
75
87
  end
76
88
 
77
89
  describe "#validate" do
78
- let(:presenter_class) { double(:presenter_class) }
79
-
80
90
  it "without errors" do
81
91
  dependency_tree = { a_presenter: {} }
82
92
 
@@ -89,6 +99,34 @@ describe "{{#with presenter}}...{{/with}}" do
89
99
  expect(errors).to be_empty
90
100
  end
91
101
 
102
+ it "without errors when a presenter helper is used" do
103
+ dependency_tree = { translate_article: [:helper, { title: nil }] }
104
+
105
+ source = <<-HBS
106
+ {{#with (translate_article 12345 "en-US")}}
107
+ {{title}}
108
+ {{/with}}
109
+ HBS
110
+
111
+ errors = Curlybars.validate(dependency_tree, source)
112
+
113
+ expect(errors).to be_empty
114
+ end
115
+
116
+ it "without errors when a generic presenter helper is used" do
117
+ dependency_tree = { article: { title: nil }, translate: [:helper, {}] }
118
+
119
+ source = <<-HBS
120
+ {{#with (translate article "en-US")}}
121
+ {{title}}
122
+ {{/with}}
123
+ HBS
124
+
125
+ errors = Curlybars.validate(dependency_tree, source)
126
+
127
+ expect(errors).to be_empty
128
+ end
129
+
92
130
  it "with errors due to a leaf" do
93
131
  dependency_tree = { not_a_presenter: nil }
94
132
 
@@ -112,5 +150,29 @@ describe "{{#with presenter}}...{{/with}}" do
112
150
 
113
151
  expect(errors).not_to be_empty
114
152
  end
153
+
154
+ it "with errors due collection helpers" do
155
+ dependency_tree = { reverse_articles: [:helper, [{ title: nil }]] }
156
+
157
+ source = <<-HBS
158
+ {{#with (reverse_articles)}}{{/with}}
159
+ HBS
160
+
161
+ errors = Curlybars.validate(dependency_tree, source)
162
+
163
+ expect(errors).not_to be_empty
164
+ end
165
+
166
+ it "with errors due generic collection helpers" do
167
+ dependency_tree = { articles: [{ title: nil }], slice: [:helper, [{}]] }
168
+
169
+ source = <<-HBS
170
+ {{#with (slice articles 0 4)}}{{/with}}
171
+ HBS
172
+
173
+ errors = Curlybars.validate(dependency_tree, source)
174
+
175
+ expect(errors).not_to be_empty
176
+ end
115
177
  end
116
178
  end
@@ -30,7 +30,7 @@ describe "tilde operator" do
30
30
  it "runs even when 'run_processors' flag is set to false" do
31
31
  allow(Curlybars::Processor::Tilde).to receive(:process!)
32
32
 
33
- Curlybars.validate(presenter, "source", run_processors: false)
33
+ Curlybars.validate(presenter.dependency_tree, "source", run_processors: false)
34
34
 
35
35
  expect(Curlybars::Processor::Tilde).to have_received(:process!)
36
36
  end
@@ -1,6 +1,5 @@
1
1
  describe "processors" do
2
2
  let(:presenter) { double(:presenter, dependency_tree: { curlybars: nil }) }
3
- let(:global_helpers_providers) { [] }
4
3
  let(:processor) { double(:processor) }
5
4
 
6
5
  before do
@@ -10,19 +9,19 @@ describe "processors" do
10
9
 
11
10
  describe "validation" do
12
11
  it "are run by default" do
13
- Curlybars.validate(presenter, "source")
12
+ Curlybars.validate(presenter.dependency_tree, "source")
14
13
 
15
14
  expect(processor).to have_received(:process!)
16
15
  end
17
16
 
18
- it "are not run when run_processors is true" do
19
- Curlybars.validate(presenter, "source", run_processors: true)
17
+ it "are run when run_processors is true" do
18
+ Curlybars.validate(presenter.dependency_tree, "source", run_processors: true)
20
19
 
21
20
  expect(processor).to have_received(:process!)
22
21
  end
23
22
 
24
23
  it "are not run when run_processors is false" do
25
- Curlybars.validate(presenter, "source", run_processors: false)
24
+ Curlybars.validate(presenter.dependency_tree, "source", run_processors: false)
26
25
 
27
26
  expect(processor).not_to have_received(:process!)
28
27
  end
@@ -4,6 +4,8 @@ describe "visitor" do
4
4
  {{#print_args_and_options 'first' 'second' key='value'}}
5
5
  {{/print_args_and_options}}
6
6
 
7
+ {{calc (calc 1 "+" 2) "*" 3}}
8
+
7
9
  {{#render_inverse}}
8
10
  fn
9
11
  {{else}}
@@ -53,7 +55,7 @@ describe "visitor" do
53
55
  it "visits BlockHelperElse nodes" do
54
56
  visitor = counting_visitor_for(Curlybars::Node::BlockHelperElse)
55
57
  output = Curlybars.visit(visitor, source)
56
- expect(output).to eq(4)
58
+ expect(output).to eq(5)
57
59
  end
58
60
 
59
61
  it "visits EachElse nodes" do
@@ -71,13 +73,13 @@ describe "visitor" do
71
73
  it "visits Item nodes" do
72
74
  visitor = counting_visitor_for(Curlybars::Node::Item)
73
75
  output = Curlybars.visit(visitor, source)
74
- expect(output).to eq(42)
76
+ expect(output).to eq(44)
75
77
  end
76
78
 
77
79
  it "visits Literal nodes" do
78
80
  visitor = counting_visitor_for(Curlybars::Node::Literal)
79
81
  output = Curlybars.visit(visitor, source)
80
- expect(output).to eq(3)
82
+ expect(output).to eq(8)
81
83
  end
82
84
 
83
85
  it "visits Option nodes" do
@@ -95,7 +97,7 @@ describe "visitor" do
95
97
  it "visits Path nodes" do
96
98
  visitor = counting_visitor_for(Curlybars::Node::Path)
97
99
  output = Curlybars.visit(visitor, source)
98
- expect(output).to eq(13)
100
+ expect(output).to eq(15)
99
101
  end
100
102
 
101
103
  it "visits Root nodes" do
@@ -104,6 +106,12 @@ describe "visitor" do
104
106
  expect(output).to eq(1)
105
107
  end
106
108
 
109
+ it "visits SubExpression nodes" do
110
+ visitor = counting_visitor_for(Curlybars::Node::SubExpression)
111
+ output = Curlybars.visit(visitor, source)
112
+ expect(output).to eq(1)
113
+ end
114
+
107
115
  it "visits Template nodes" do
108
116
  visitor = counting_visitor_for(Curlybars::Node::Template)
109
117
  output = Curlybars.visit(visitor, source)
@@ -113,7 +121,7 @@ describe "visitor" do
113
121
  it "visits Text nodes" do
114
122
  visitor = counting_visitor_for(Curlybars::Node::Text)
115
123
  output = Curlybars.visit(visitor, source)
116
- expect(output).to eq(28)
124
+ expect(output).to eq(29)
117
125
  end
118
126
 
119
127
  it "visits UnlessElse nodes" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: curlybars
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Libo Cannici
@@ -10,10 +10,12 @@ authors:
10
10
  - Mauro Codella
11
11
  - Luís Almeida
12
12
  - Andreas Garnæs
13
+ - Augusto Silva
14
+ - Attila Večerek
13
15
  autorequire:
14
16
  bindir: bin
15
17
  cert_chain: []
16
- date: 2020-01-13 00:00:00.000000000 Z
18
+ date: 2021-02-17 00:00:00.000000000 Z
17
19
  dependencies:
18
20
  - !ruby/object:Gem::Dependency
19
21
  name: actionpack
@@ -24,7 +26,7 @@ dependencies:
24
26
  version: '4.2'
25
27
  - - "<"
26
28
  - !ruby/object:Gem::Version
27
- version: '6.0'
29
+ version: '6.2'
28
30
  type: :runtime
29
31
  prerelease: false
30
32
  version_requirements: !ruby/object:Gem::Requirement
@@ -34,7 +36,7 @@ dependencies:
34
36
  version: '4.2'
35
37
  - - "<"
36
38
  - !ruby/object:Gem::Version
37
- version: '6.0'
39
+ version: '6.2'
38
40
  - !ruby/object:Gem::Dependency
39
41
  name: activesupport
40
42
  requirement: !ruby/object:Gem::Requirement
@@ -44,7 +46,7 @@ dependencies:
44
46
  version: '4.2'
45
47
  - - "<"
46
48
  - !ruby/object:Gem::Version
47
- version: '6.0'
49
+ version: '6.2'
48
50
  type: :runtime
49
51
  prerelease: false
50
52
  version_requirements: !ruby/object:Gem::Requirement
@@ -54,7 +56,7 @@ dependencies:
54
56
  version: '4.2'
55
57
  - - "<"
56
58
  - !ruby/object:Gem::Version
57
- version: '6.0'
59
+ version: '6.2'
58
60
  - !ruby/object:Gem::Dependency
59
61
  name: ffi
60
62
  requirement: !ruby/object:Gem::Requirement
@@ -120,7 +122,7 @@ dependencies:
120
122
  version: '4.2'
121
123
  - - "<"
122
124
  - !ruby/object:Gem::Version
123
- version: '6.0'
125
+ version: '6.2'
124
126
  type: :development
125
127
  prerelease: false
126
128
  version_requirements: !ruby/object:Gem::Requirement
@@ -130,7 +132,7 @@ dependencies:
130
132
  version: '4.2'
131
133
  - - "<"
132
134
  - !ruby/object:Gem::Version
133
- version: '6.0'
135
+ version: '6.2'
134
136
  - !ruby/object:Gem::Dependency
135
137
  name: rake
136
138
  requirement: !ruby/object:Gem::Requirement
@@ -165,32 +167,60 @@ dependencies:
165
167
  requirements:
166
168
  - - "~>"
167
169
  - !ruby/object:Gem::Version
168
- version: 0.58.2
170
+ version: 1.6.0
169
171
  type: :development
170
172
  prerelease: false
171
173
  version_requirements: !ruby/object:Gem::Requirement
172
174
  requirements:
173
175
  - - "~>"
174
176
  - !ruby/object:Gem::Version
175
- version: 0.58.2
177
+ version: 1.6.0
178
+ - !ruby/object:Gem::Dependency
179
+ name: rubocop-performance
180
+ requirement: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - "~>"
183
+ - !ruby/object:Gem::Version
184
+ version: 1.9.0
185
+ type: :development
186
+ prerelease: false
187
+ version_requirements: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - "~>"
190
+ - !ruby/object:Gem::Version
191
+ version: 1.9.0
192
+ - !ruby/object:Gem::Dependency
193
+ name: rubocop-rake
194
+ requirement: !ruby/object:Gem::Requirement
195
+ requirements:
196
+ - - "~>"
197
+ - !ruby/object:Gem::Version
198
+ version: 0.5.0
199
+ type: :development
200
+ prerelease: false
201
+ version_requirements: !ruby/object:Gem::Requirement
202
+ requirements:
203
+ - - "~>"
204
+ - !ruby/object:Gem::Version
205
+ version: 0.5.0
176
206
  - !ruby/object:Gem::Dependency
177
207
  name: rubocop-rspec
178
208
  requirement: !ruby/object:Gem::Requirement
179
209
  requirements:
180
210
  - - "~>"
181
211
  - !ruby/object:Gem::Version
182
- version: 1.28.0
212
+ version: 2.1.0
183
213
  type: :development
184
214
  prerelease: false
185
215
  version_requirements: !ruby/object:Gem::Requirement
186
216
  requirements:
187
217
  - - "~>"
188
218
  - !ruby/object:Gem::Version
189
- version: 1.28.0
219
+ version: 2.1.0
190
220
  description: |-
191
221
  A view layer for your Rails apps that separates structure and logic, using Handlebars templates.
192
222
  Strongly inspired by Curly Template gem by Daniel Schierbeck.
193
- email: libo@zendesk.com
223
+ email: vikings@zendesk.com
194
224
  executables: []
195
225
  extensions: []
196
226
  extra_rdoc_files: []
@@ -205,6 +235,7 @@ files:
205
235
  - lib/curlybars/error/presenter/not_found.rb
206
236
  - lib/curlybars/error/render.rb
207
237
  - lib/curlybars/error/validate.rb
238
+ - lib/curlybars/generic.rb
208
239
  - lib/curlybars/lexer.rb
209
240
  - lib/curlybars/method_whitelist.rb
210
241
  - lib/curlybars/node/block_helper_else.rb
@@ -219,6 +250,7 @@ files:
219
250
  - lib/curlybars/node/path.rb
220
251
  - lib/curlybars/node/root.rb
221
252
  - lib/curlybars/node/string.rb
253
+ - lib/curlybars/node/sub_expression.rb
222
254
  - lib/curlybars/node/template.rb
223
255
  - lib/curlybars/node/text.rb
224
256
  - lib/curlybars/node/unless_else.rb
@@ -265,6 +297,7 @@ files:
265
297
  - spec/integration/node/partial_spec.rb
266
298
  - spec/integration/node/path_spec.rb
267
299
  - spec/integration/node/root_spec.rb
300
+ - spec/integration/node/sub_expression_spec.rb
268
301
  - spec/integration/node/template_spec.rb
269
302
  - spec/integration/node/unless_else_spec.rb
270
303
  - spec/integration/node/unless_spec.rb
@@ -285,14 +318,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
285
318
  requirements:
286
319
  - - ">="
287
320
  - !ruby/object:Gem::Version
288
- version: '0'
321
+ version: '2.4'
289
322
  required_rubygems_version: !ruby/object:Gem::Requirement
290
323
  requirements:
291
324
  - - ">="
292
325
  - !ruby/object:Gem::Version
293
326
  version: '0'
294
327
  requirements: []
295
- rubygems_version: 3.0.6
328
+ rubygems_version: 3.1.4
296
329
  signing_key:
297
330
  specification_version: 4
298
331
  summary: Create your views using Handlebars templates!
@@ -318,6 +351,7 @@ test_files:
318
351
  - spec/integration/node/unless_else_spec.rb
319
352
  - spec/integration/node/output_spec.rb
320
353
  - spec/integration/node/if_spec.rb
354
+ - spec/integration/node/sub_expression_spec.rb
321
355
  - spec/integration/node/unless_spec.rb
322
356
  - spec/integration/node/with_spec.rb
323
357
  - spec/integration/node/partial_spec.rb