flavour_saver 0.3.7 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c3efa30121a2e226ebb1274cf5597d35ab7f9c47
4
- data.tar.gz: c89bc7f065e3dfbb07882c44465711981643d454
3
+ metadata.gz: 0965ce577ba5f5e0e84097ff444c306b053ba899
4
+ data.tar.gz: f92b0741008a767ef778841404397eabf41620f6
5
5
  SHA512:
6
- metadata.gz: 1292541b248293451704808a7458b2132ab7109f9664845c77d01c375581396192af2ee2a19c6cfae4fa567294757cb5b563803e23ccfd8110961f204adbdd03
7
- data.tar.gz: a74f63a36b4864fbc248fde7ff9e03c19ffc49412f37b472521cf2ed13bf7403e24243e423211c1599c924a92a8e9f9b1472ba15c07b12a12955de70f131da7c
6
+ metadata.gz: 11472cf0bc62d973eb98cf1e1c6c1275aa1c37b55ac52f43776104cb5629308ad5d2676887fc760657fa794a560e0f2bd8e826ddb338557772254fca4e6ef10a
7
+ data.tar.gz: 6e238d05a52deafb8309454977ca86d4a6c2f09171baff67a814bac81a005cfb97511e95bd8b0feec0ea0e47c47e9c1a15fee75d68966ddc902946d9de00ba19
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- flavour_saver (0.3.7)
4
+ flavour_saver (0.3.8)
5
5
  rltk (~> 2.2.0)
6
6
  tilt
7
7
 
data/README.md CHANGED
@@ -74,6 +74,7 @@ Currently supported:
74
74
  - Inverse blocks
75
75
  - Partials
76
76
  - Raw content (`{{{{raw}}}} not parsed or validated {{{{/raw}}}}`)
77
+ - Subexpressions (`{{sum 1 (sum 1 1)}}` returns `3`)
77
78
 
78
79
  ## Helpers
79
80
 
@@ -248,6 +249,35 @@ Which could be used like so:
248
249
  {{/isFemale}}
249
250
  ```
250
251
 
252
+ ### Subexpressions
253
+
254
+ You can use a subexpression as any value for a helper, and it will be executed before it is ran. You can also nest them, and use them in assignment of variables.
255
+
256
+ Below are some examples, utilizing a "sum" helper than adds together two numbers.
257
+
258
+ ```
259
+ {{sum (sum 5 10) (sum 2 (sum 1 4))}}
260
+ #=> 22
261
+
262
+ {{#if (sum 1 2) > 2}}its more{{/if}}
263
+ #=> its more
264
+
265
+ {{#student_heights size=(sum boys girls)}}
266
+ ```
267
+
268
+ ### Raw Content
269
+
270
+ Sometimes you don't want a section of content to be evaluted as handlebars, such as when you want to display it in a page that renders with handlebars. FlavourSaver offers a `raw` helper, that will allow you to pass anything through wrapped in those elements, and it will not be evaluated.
271
+
272
+ ```
273
+ {{{{raw}}}}
274
+ {{if} this tries to parse, it will break on syntax
275
+ {{{{/raw}}}}
276
+ => {{if} this tries to parse, it will break on syntax
277
+ ```
278
+
279
+ Its important to note that while this looks like a block helper, it is not in practice. This is why you must omit the use of a `#` when writing it.
280
+
251
281
  ### Using Partials
252
282
 
253
283
  Handlebars allows you to register a partial either as a function or a string template with
@@ -11,7 +11,10 @@ module FlavourSaver
11
11
  r = []
12
12
  count = 0
13
13
  collection.each do |element|
14
- r << yield.contents(element, 'index' => count)
14
+ r << yield.contents(element,
15
+ 'index' => count,
16
+ 'last' => count == collection.size - 1,
17
+ 'first' => count == 0)
15
18
  count += 1
16
19
  end
17
20
  yield.rendered!
@@ -86,6 +86,14 @@ module FlavourSaver
86
86
  :DOT
87
87
  end
88
88
 
89
+ rule /\(/, :expression do
90
+ :OPAR
91
+ end
92
+
93
+ rule /\)/, :expression do
94
+ :CPAR
95
+ end
96
+
89
97
  rule /\=/, :expression do
90
98
  :EQ
91
99
  end
@@ -86,6 +86,10 @@ module FlavourSaver
86
86
  clause('EXPRST expression_contents EXPRE') { |_,e,_| e }
87
87
  end
88
88
 
89
+ production(:subexpr) do
90
+ clause('OPAR expression_contents CPAR') { |_,e,_| e }
91
+ end
92
+
89
93
  production(:expr_comment) do
90
94
  clause('EXPRST BANG COMMENT EXPRE') { |_,_,e,_| e }
91
95
  end
@@ -129,8 +133,8 @@ module FlavourSaver
129
133
  clause('argument_list WHITE hash') { |e0,_,e1| e0 + [e1] }
130
134
  clause('hash') { |e| [e] }
131
135
  end
132
-
133
- nonempty_list(:argument_list, [:object_path,:lit], :WHITE)
136
+
137
+ nonempty_list(:argument_list, [:object_path,:lit, :local, :subexpr], :WHITE)
134
138
 
135
139
  production(:lit) do
136
140
  clause('string') { |e| e }
@@ -157,6 +161,7 @@ module FlavourSaver
157
161
  end
158
162
 
159
163
  production(:hash_item) do
164
+ clause('IDENT EQ subexpr') { |e0,_,e1| { e0.to_sym => e1 } }
160
165
  clause('IDENT EQ string') { |e0,_,e1| { e0.to_sym => e1 } }
161
166
  clause('IDENT EQ number') { |e0,_,e1| { e0.to_sym => e1 } }
162
167
  clause('IDENT EQ object_path') { |e0,_,e1| { e0.to_sym => e1 } }
@@ -34,7 +34,7 @@ module FlavourSaver
34
34
  @privates = old_privates
35
35
  @context = old_context
36
36
  else
37
- result = evaluate_node(@ast)
37
+ result = evaluate_node(@ast).to_s.force_encoding(Encoding::default_external)
38
38
  end
39
39
  result
40
40
  end
@@ -1,3 +1,3 @@
1
1
  module FlavourSaver
2
- VERSION = "0.3.7"
2
+ VERSION = "0.3.8"
3
3
  end
@@ -909,6 +909,28 @@ describe FlavourSaver do
909
909
  end
910
910
  end
911
911
 
912
+ describe 'each with @last' do
913
+ let(:template) { "{{#each goodbyes}}{{@index}}. {{text}}! {{#if @last}}last{{/if}}{{/each}} cruel {{world}}!" }
914
+
915
+ example 'the @last variable is used' do
916
+ g = Struct.new(:text)
917
+ context.stub(:goodbyes).and_return([g.new('goodbye'), g.new('Goodbye'), g.new('GOODBYE')])
918
+ context.stub(:world).and_return('world')
919
+ subject.should == "0. goodbye! 1. Goodbye! 2. GOODBYE! last cruel world!"
920
+ end
921
+ end
922
+
923
+ describe 'each with @first' do
924
+ let(:template) { "{{#each goodbyes}}{{@index}}. {{text}} {{#if @first}}first{{/if}}! {{/each}}cruel {{world}}!" }
925
+
926
+ example 'the first variable is used' do
927
+ g = Struct.new(:text)
928
+ context.stub(:goodbyes).and_return([g.new('goodbye'), g.new('Goodbye'), g.new('GOODBYE')])
929
+ context.stub(:world).and_return('world')
930
+ subject.should == "0. goodbye first! 1. Goodbye ! 2. GOODBYE ! cruel world!"
931
+ end
932
+ end
933
+
912
934
  describe 'log' do
913
935
  let(:template) { "{{log blah}}" }
914
936
  let(:log) { double(:log) }
@@ -0,0 +1,38 @@
1
+ require 'tilt'
2
+ require 'flavour_saver'
3
+
4
+ describe 'Subexpressions' do
5
+
6
+ subject { Tilt['handlebars'].new{ template }.render(context).gsub(/[\s\r\n]+/, ' ').strip }
7
+
8
+ let(:context) { double(:context) }
9
+ before(:all) do
10
+ FlavourSaver.register_helper(:sum) { |a,b| a + b}
11
+ end
12
+ context "simple subexpression" do
13
+ let(:template) { "{{sum 1 (sum 1 1)}}" }
14
+ specify{subject.should == "3"}
15
+ end
16
+
17
+ context "nested subexpressions" do
18
+ let(:template) { "{{sum 1 (sum 1 (sum 1 1))}}" }
19
+ specify{subject.should == "4"}
20
+ end
21
+
22
+ context "subexpression as argument" do
23
+ before {FlavourSaver.register_helper(:cents) { |a| a[:total] + 10}}
24
+ let(:template) { "{{cents total=(sum 1 1)}}" }
25
+ specify{subject.should == "12"}
26
+ end
27
+
28
+ context "subexpression in block" do
29
+ before {FlavourSaver.register_helper(:repeat) do |a, &block|
30
+ s = ''
31
+ a.times {s += block.call.contents}
32
+ s
33
+ end}
34
+ let(:template) { "{{#repeat (sum 1 2)}}*{{/repeat}}" }
35
+ specify{subject.should == "***"}
36
+ end
37
+
38
+ end
@@ -49,6 +49,18 @@ describe FlavourSaver::Lexer do
49
49
  end
50
50
  end
51
51
 
52
+ describe '{{foo (bar "baz")}}' do
53
+ subject { FlavourSaver::Lexer.lex "{{foo (bar 'baz')}}" }
54
+
55
+ it 'has tokens in the correct order' do
56
+ subject.map(&:type).should == [ :EXPRST, :IDENT, :WHITE, :OPAR, :IDENT, :WHITE, :S_STRING, :CPAR, :EXPRE, :EOS ]
57
+ end
58
+
59
+ it 'has values in the correct order' do
60
+ subject.map(&:value).compact.should == [ 'foo', 'bar', 'baz' ]
61
+ end
62
+ end
63
+
52
64
  describe '{{foo bar="baz" hello="goodbye"}}' do
53
65
  subject { FlavourSaver::Lexer.lex '{{foo bar="baz" hello="goodbye"}}' }
54
66
 
@@ -63,6 +75,18 @@ describe FlavourSaver::Lexer do
63
75
  end
64
76
  end
65
77
 
78
+ describe '{{foo bar=(baz qux)}}' do
79
+ subject { FlavourSaver::Lexer.lex '{{foo bar=(baz qux)}}' }
80
+
81
+ it 'has tokens in the correct order' do
82
+ subject.map(&:type).should == [:EXPRST, :IDENT, :WHITE, :IDENT, :EQ, :OPAR, :IDENT, :WHITE, :IDENT, :CPAR, :EXPRE, :EOS]
83
+ end
84
+
85
+ it 'has values in the correct order' do
86
+ subject.map(&:value).compact.should == [ 'foo', 'bar', 'baz', 'qux' ]
87
+ end
88
+ end
89
+
66
90
  describe '{{else}}' do
67
91
  subject { FlavourSaver::Lexer.lex '{{else}}' }
68
92
 
@@ -143,6 +143,28 @@ describe FlavourSaver::Parser do
143
143
  end
144
144
  end
145
145
 
146
+ describe '{{foo (bar "baz") }}' do
147
+ subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo (bar "baz") }}')) }
148
+
149
+ it 'calls the method "foo"' do
150
+ items.first.method.should be_one
151
+ items.first.method.first.should be_a(FlavourSaver::CallNode)
152
+ items.first.method.first.name.should == 'foo'
153
+ end
154
+
155
+ describe 'with arguments' do
156
+ subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo (bar "baz") }}')).items.first.method.first.arguments }
157
+
158
+ describe '[0]' do
159
+ it 'is a subexpression' do
160
+ subject.first.first.should be_a(FlavourSaver::CallNode)
161
+ subject.first.first.name.should == 'bar'
162
+ end
163
+ end
164
+
165
+ end
166
+ end
167
+
146
168
  describe '{{foo bar="baz"}}' do
147
169
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar="baz"}}')) }
148
170
 
@@ -154,6 +176,17 @@ describe FlavourSaver::Parser do
154
176
  end
155
177
  end
156
178
 
179
+ describe '{{foo bar=(baz "qux")}}' do
180
+ subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar=(baz "qux")}}')) }
181
+
182
+ it 'calls the method "foo" with the hash {:bar => (baz "qux")} as arguments' do
183
+ items.first.method.first.should be_a(FlavourSaver::CallNode)
184
+ items.first.method.first.name.should == 'foo'
185
+ items.first.method.first.arguments.first.should be_a(Hash)
186
+ items.first.method.first.arguments.first[:bar].first.should be_a(FlavourSaver::CallNode)
187
+ end
188
+ end
189
+
157
190
  describe "{{foo bar=1}}" do
158
191
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{foo bar=1}}")) }
159
192
 
@@ -110,6 +110,17 @@ describe FlavourSaver::Runtime do
110
110
  end
111
111
  end
112
112
 
113
+ describe 'when called with a subexpression' do
114
+ let(:template) { "{{hello (there world)}}" }
115
+
116
+ it 'calls there & world first, then passes off to hello' do
117
+ context.should_receive(:world).and_return('world')
118
+ context.should_receive(:there).with('world').and_return('there world')
119
+ context.should_receive(:hello).with('there world').and_return('hello there world')
120
+ subject.evaluate_expression(expr).should == 'hello there world'
121
+ end
122
+ end
123
+
113
124
  describe 'when called with an object path' do
114
125
  let(:template) { "{{hello.world}}" }
115
126
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flavour_saver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.7
4
+ version: 0.3.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Harton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-16 00:00:00.000000000 Z
11
+ date: 2015-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -177,6 +177,7 @@ files:
177
177
  - spec/acceptance/sections_spec.rb
178
178
  - spec/acceptance/segment_literals_spec.rb
179
179
  - spec/acceptance/simple_expression_spec.rb
180
+ - spec/acceptance/subexpression_spec.rb
180
181
  - spec/fixtures/backtrack.hbs
181
182
  - spec/fixtures/comment.hbs
182
183
  - spec/fixtures/custom_block_helper.hbs
@@ -230,6 +231,7 @@ test_files:
230
231
  - spec/acceptance/sections_spec.rb
231
232
  - spec/acceptance/segment_literals_spec.rb
232
233
  - spec/acceptance/simple_expression_spec.rb
234
+ - spec/acceptance/subexpression_spec.rb
233
235
  - spec/fixtures/backtrack.hbs
234
236
  - spec/fixtures/comment.hbs
235
237
  - spec/fixtures/custom_block_helper.hbs