curlybars 1.3.1 → 1.7.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 (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