flavour_saver 0.3.7 → 0.3.8

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