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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +30 -0
- data/lib/flavour_saver/helpers.rb +4 -1
- data/lib/flavour_saver/lexer.rb +8 -0
- data/lib/flavour_saver/parser.rb +7 -2
- data/lib/flavour_saver/runtime.rb +1 -1
- data/lib/flavour_saver/version.rb +1 -1
- data/spec/acceptance/handlebars_qunit_spec.rb +22 -0
- data/spec/acceptance/subexpression_spec.rb +38 -0
- data/spec/lib/flavour_saver/lexer_spec.rb +24 -0
- data/spec/lib/flavour_saver/parser_spec.rb +33 -0
- data/spec/lib/flavour_saver/runtime_spec.rb +11 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0965ce577ba5f5e0e84097ff444c306b053ba899
|
4
|
+
data.tar.gz: f92b0741008a767ef778841404397eabf41620f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11472cf0bc62d973eb98cf1e1c6c1275aa1c37b55ac52f43776104cb5629308ad5d2676887fc760657fa794a560e0f2bd8e826ddb338557772254fca4e6ef10a
|
7
|
+
data.tar.gz: 6e238d05a52deafb8309454977ca86d4a6c2f09171baff67a814bac81a005cfb97511e95bd8b0feec0ea0e47c47e9c1a15fee75d68966ddc902946d9de00ba19
|
data/Gemfile.lock
CHANGED
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,
|
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!
|
data/lib/flavour_saver/lexer.rb
CHANGED
data/lib/flavour_saver/parser.rb
CHANGED
@@ -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 } }
|
@@ -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.
|
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-
|
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
|