flavour_saver 0.3.9 → 2.0.1
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 +5 -5
- data/.github/workflows/ci.yml +47 -0
- data/CHANGELOG.md +46 -0
- data/Gemfile.lock +34 -62
- data/README.md +3 -10
- data/flavour_saver.gemspec +14 -9
- data/lib/flavour_saver/helpers.rb +28 -16
- data/lib/flavour_saver/lexer.rb +1 -1
- data/lib/flavour_saver/parser.rb +14 -8
- data/lib/flavour_saver/runtime.rb +7 -7
- data/lib/flavour_saver/version.rb +1 -1
- data/spec/acceptance/backtrack_spec.rb +1 -1
- data/spec/acceptance/comment_spec.rb +1 -1
- data/spec/acceptance/custom_block_helper_spec.rb +2 -2
- data/spec/acceptance/custom_helper_spec.rb +1 -1
- data/spec/acceptance/ensure_no_rce_spec.rb +2 -2
- data/spec/acceptance/handlebars_qunit_spec.rb +297 -219
- data/spec/acceptance/if_else_spec.rb +37 -6
- data/spec/acceptance/multi_level_with_spec.rb +1 -1
- data/spec/acceptance/one_character_identifier_spec.rb +2 -2
- data/spec/acceptance/raw_block_spec.rb +1 -1
- data/spec/acceptance/runtime_run_spec.rb +1 -1
- data/spec/acceptance/sections_spec.rb +3 -3
- data/spec/acceptance/segment_literals_spec.rb +3 -3
- data/spec/acceptance/simple_expression_spec.rb +3 -3
- data/spec/acceptance/subexpression_spec.rb +4 -5
- data/spec/acceptance/unless_spec.rb +48 -0
- data/spec/fixtures/if_else.hbs +3 -3
- data/spec/fixtures/unless.hbs +5 -0
- data/spec/lib/flavour_saver/lexer_spec.rb +67 -36
- data/spec/lib/flavour_saver/parser_spec.rb +91 -91
- data/spec/lib/flavour_saver/runtime_spec.rb +37 -37
- metadata +25 -72
- data/.travis.yml +0 -18
- data/Guardfile +0 -12
| @@ -22,8 +22,8 @@ describe FlavourSaver do | |
| 22 22 | 
             
                  let(:template) { "{{foo}}" }
         | 
| 23 23 |  | 
| 24 24 | 
             
                  it 'returns "foo"' do
         | 
| 25 | 
            -
                    context. | 
| 26 | 
            -
                    subject. | 
| 25 | 
            +
                    allow(context).to receive(:foo).and_return('foo')
         | 
| 26 | 
            +
                    expect(subject).to eq 'foo'
         | 
| 27 27 | 
             
                  end
         | 
| 28 28 | 
             
                end
         | 
| 29 29 |  | 
| @@ -31,9 +31,9 @@ describe FlavourSaver do | |
| 31 31 | 
             
                  let(:template) { "Goodbye\n{{cruel}}\n{{world}}!" }
         | 
| 32 32 |  | 
| 33 33 | 
             
                  it 'it works if all the required keys are provided' do
         | 
| 34 | 
            -
                    context. | 
| 35 | 
            -
                    context. | 
| 36 | 
            -
                    subject. | 
| 34 | 
            +
                    expect(context).to receive(:cruel).and_return('cruel')
         | 
| 35 | 
            +
                    expect(context).to receive(:world).and_return('world')
         | 
| 36 | 
            +
                    expect(subject).to eq "Goodbye\ncruel\nworld!"
         | 
| 37 37 | 
             
                  end
         | 
| 38 38 | 
             
                end
         | 
| 39 39 |  | 
| @@ -41,9 +41,9 @@ describe FlavourSaver do | |
| 41 41 | 
             
                  let(:template) {"{{! Goodbye}}Goodbye\n{{cruel}}\n{{world}}!"}
         | 
| 42 42 |  | 
| 43 43 | 
             
                  it 'comments are ignored' do
         | 
| 44 | 
            -
                    context. | 
| 45 | 
            -
                    context. | 
| 46 | 
            -
                    subject. | 
| 44 | 
            +
                    expect(context).to receive(:cruel).and_return('cruel')
         | 
| 45 | 
            +
                    expect(context).to receive(:world).and_return('world')
         | 
| 46 | 
            +
                    expect(subject).to eq "Goodbye\ncruel\nworld!"
         | 
| 47 47 | 
             
                  end
         | 
| 48 48 | 
             
                end
         | 
| 49 49 |  | 
| @@ -51,15 +51,15 @@ describe FlavourSaver do | |
| 51 51 | 
             
                  let(:template) { "{{#goodbye}}GOODBYE {{/goodbye}}cruel {{world}}!" }
         | 
| 52 52 |  | 
| 53 53 | 
             
                  it 'booleans show the contents when true' do
         | 
| 54 | 
            -
                    context. | 
| 55 | 
            -
                    context. | 
| 56 | 
            -
                    subject. | 
| 54 | 
            +
                    allow(context).to receive(:goodbye).and_return(true)
         | 
| 55 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 56 | 
            +
                    expect(subject).to eq "GOODBYE cruel world!"
         | 
| 57 57 | 
             
                  end
         | 
| 58 58 |  | 
| 59 59 | 
             
                  it 'booleans do not show the contents when false' do
         | 
| 60 | 
            -
                    context. | 
| 61 | 
            -
                    context. | 
| 62 | 
            -
                    subject. | 
| 60 | 
            +
                    allow(context).to receive(:goodbye).and_return(false)
         | 
| 61 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 62 | 
            +
                    expect(subject).to eq "cruel world!"
         | 
| 63 63 | 
             
                  end
         | 
| 64 64 | 
             
                end
         | 
| 65 65 |  | 
| @@ -68,9 +68,9 @@ describe FlavourSaver do | |
| 68 68 | 
             
                    let (:template) { "num1: {{num1}}, num2: {{num2}}" }
         | 
| 69 69 |  | 
| 70 70 | 
             
                    it 'should compile to "num1: 42, num2: 0"' do
         | 
| 71 | 
            -
                      context. | 
| 72 | 
            -
                      context. | 
| 73 | 
            -
                      subject. | 
| 71 | 
            +
                      allow(context).to receive(:num1).and_return(42)
         | 
| 72 | 
            +
                      allow(context).to receive(:num2).and_return(0)
         | 
| 73 | 
            +
                      expect(subject).to eq 'num1: 42, num2: 0'
         | 
| 74 74 | 
             
                    end
         | 
| 75 75 | 
             
                  end
         | 
| 76 76 |  | 
| @@ -78,7 +78,7 @@ describe FlavourSaver do | |
| 78 78 | 
             
                    let (:template) { 'num: {{.}}' }
         | 
| 79 79 |  | 
| 80 80 | 
             
                    it 'should compile to "num: 0"' do
         | 
| 81 | 
            -
                      FlavourSaver.evaluate(template,0). | 
| 81 | 
            +
                      expect(FlavourSaver.evaluate(template,0)).to eq 'num: 0'
         | 
| 82 82 | 
             
                    end
         | 
| 83 83 | 
             
                  end
         | 
| 84 84 |  | 
| @@ -86,8 +86,8 @@ describe FlavourSaver do | |
| 86 86 | 
             
                    let(:template) { 'num: {{num1/num2}}' }
         | 
| 87 87 |  | 
| 88 88 | 
             
                    it 'should compile to "num: 0"' do
         | 
| 89 | 
            -
                      context. | 
| 90 | 
            -
                      subject. | 
| 89 | 
            +
                      allow(context).to receive_message_chain(:num1, :num2).and_return(0)
         | 
| 90 | 
            +
                      expect(subject).to eq 'num: 0'
         | 
| 91 91 | 
             
                    end
         | 
| 92 92 | 
             
                  end
         | 
| 93 93 | 
             
                end
         | 
| @@ -97,7 +97,7 @@ describe FlavourSaver do | |
| 97 97 | 
             
                    let(:template) { "Alan's\nTest" }
         | 
| 98 98 |  | 
| 99 99 | 
             
                    it 'works' do
         | 
| 100 | 
            -
                      subject. | 
| 100 | 
            +
                      expect(subject).to eq "Alan's\nTest"
         | 
| 101 101 | 
             
                    end
         | 
| 102 102 | 
             
                  end
         | 
| 103 103 |  | 
| @@ -105,7 +105,7 @@ describe FlavourSaver do | |
| 105 105 | 
             
                    let(:template) { "Alan's\rTest" }
         | 
| 106 106 |  | 
| 107 107 | 
             
                    it 'works' do
         | 
| 108 | 
            -
                      subject. | 
| 108 | 
            +
                      expect(subject).to eq "Alan's\rTest"
         | 
| 109 109 | 
             
                    end
         | 
| 110 110 | 
             
                  end
         | 
| 111 111 | 
             
                end
         | 
| @@ -115,7 +115,7 @@ describe FlavourSaver do | |
| 115 115 | 
             
                    let(:template) {"Awesome's"}
         | 
| 116 116 |  | 
| 117 117 | 
             
                    it "text is escapes so that it doesn't get caught in single quites" do
         | 
| 118 | 
            -
                      subject. | 
| 118 | 
            +
                      expect(subject).to eq "Awesome's"
         | 
| 119 119 | 
             
                    end
         | 
| 120 120 | 
             
                  end
         | 
| 121 121 |  | 
| @@ -123,7 +123,7 @@ describe FlavourSaver do | |
| 123 123 | 
             
                    let(:template) { "Awesome \\" }
         | 
| 124 124 |  | 
| 125 125 | 
             
                    it "text is escaped so that the closing quote can't be ignored" do
         | 
| 126 | 
            -
                      subject. | 
| 126 | 
            +
                      expect(subject).to eq "Awesome \\"
         | 
| 127 127 | 
             
                    end
         | 
| 128 128 | 
             
                  end
         | 
| 129 129 |  | 
| @@ -131,7 +131,7 @@ describe FlavourSaver do | |
| 131 131 | 
             
                    let(:template) { "Awesome\\\\ foo" }
         | 
| 132 132 |  | 
| 133 133 | 
             
                    it "text is escapes so that it doesn't mess up the backslashes" do
         | 
| 134 | 
            -
                      subject. | 
| 134 | 
            +
                      expect(subject).to eq "Awesome\\\\ foo"
         | 
| 135 135 | 
             
                    end
         | 
| 136 136 | 
             
                  end
         | 
| 137 137 |  | 
| @@ -139,8 +139,8 @@ describe FlavourSaver do | |
| 139 139 | 
             
                    let(:template) { "Awesome {{foo}}" }
         | 
| 140 140 |  | 
| 141 141 | 
             
                    it "text is escaped so that it doesn't mess up backslashes" do
         | 
| 142 | 
            -
                      context. | 
| 143 | 
            -
                      subject. | 
| 142 | 
            +
                      allow(context).to receive(:foo).and_return('\\')
         | 
| 143 | 
            +
                      expect(subject).to eq "Awesome \\"
         | 
| 144 144 | 
             
                    end
         | 
| 145 145 | 
             
                  end
         | 
| 146 146 |  | 
| @@ -148,7 +148,7 @@ describe FlavourSaver do | |
| 148 148 | 
             
                    let(:template) { ' " " ' }
         | 
| 149 149 |  | 
| 150 150 | 
             
                    it "double quotes never produce invalid javascript" do
         | 
| 151 | 
            -
                      subject. | 
| 151 | 
            +
                      expect(subject).to eq ' " " '
         | 
| 152 152 | 
             
                    end
         | 
| 153 153 | 
             
                  end
         | 
| 154 154 | 
             
                end
         | 
| @@ -158,8 +158,8 @@ describe FlavourSaver do | |
| 158 158 | 
             
                    let(:template) { "{{{awesome}}}" }
         | 
| 159 159 |  | 
| 160 160 | 
             
                    it "shouldn't be escaped" do
         | 
| 161 | 
            -
                      context. | 
| 162 | 
            -
                      subject. | 
| 161 | 
            +
                      allow(context).to receive(:awesome).and_return("&\"\\<>")
         | 
| 162 | 
            +
                      expect(subject).to eq "&\"\\<>"
         | 
| 163 163 | 
             
                    end
         | 
| 164 164 | 
             
                  end
         | 
| 165 165 |  | 
| @@ -167,8 +167,8 @@ describe FlavourSaver do | |
| 167 167 | 
             
                    let(:template) { "{{&awesome}}" }
         | 
| 168 168 |  | 
| 169 169 | 
             
                    it "shouldn't be escaped" do
         | 
| 170 | 
            -
                      context. | 
| 171 | 
            -
                      subject. | 
| 170 | 
            +
                      allow(context).to receive(:awesome).and_return("&\"\\<>")
         | 
| 171 | 
            +
                      expect(subject).to eq "&\"\\<>"
         | 
| 172 172 | 
             
                    end
         | 
| 173 173 | 
             
                  end
         | 
| 174 174 |  | 
| @@ -176,11 +176,11 @@ describe FlavourSaver do | |
| 176 176 | 
             
                    let(:template) { "{{awesome}}" }
         | 
| 177 177 |  | 
| 178 178 | 
             
                    it "should be escaped" do
         | 
| 179 | 
            -
                      context. | 
| 179 | 
            +
                      allow(context).to receive(:awesome).and_return("&\"'`\\<>")
         | 
| 180 180 | 
             
                      if RUBY_VERSION >= '2.0.0'
         | 
| 181 | 
            -
                        subject. | 
| 181 | 
            +
                        expect(subject).to eq "&"'`\\<>"
         | 
| 182 182 | 
             
                      else
         | 
| 183 | 
            -
                        subject. | 
| 183 | 
            +
                        expect(subject).to eq "&"'`\\<>"
         | 
| 184 184 | 
             
                      end
         | 
| 185 185 | 
             
                    end
         | 
| 186 186 | 
             
                  end
         | 
| @@ -189,8 +189,8 @@ describe FlavourSaver do | |
| 189 189 | 
             
                    let(:template) { "{{awesome}}" }
         | 
| 190 190 |  | 
| 191 191 | 
             
                    it "should be escaped" do
         | 
| 192 | 
            -
                      context. | 
| 193 | 
            -
                      subject. | 
| 192 | 
            +
                      allow(context).to receive(:awesome).and_return("Escaped, <b> looks like: <b>")
         | 
| 193 | 
            +
                      expect(subject).to eq "Escaped, <b> looks like: &lt;b&gt;"
         | 
| 194 194 | 
             
                    end
         | 
| 195 195 | 
             
                  end
         | 
| 196 196 | 
             
                end
         | 
| @@ -199,8 +199,8 @@ describe FlavourSaver do | |
| 199 199 | 
             
                  let(:template) { "{{awesome}}" }
         | 
| 200 200 |  | 
| 201 201 | 
             
                  it "shouldn't be escaped" do
         | 
| 202 | 
            -
                    context. | 
| 203 | 
            -
                    subject. | 
| 202 | 
            +
                    allow(context).to receive(:awesome).and_return("&\"\\<>".html_safe)
         | 
| 203 | 
            +
                    expect(subject).to eq "&\"\\<>"
         | 
| 204 204 | 
             
                  end
         | 
| 205 205 | 
             
                end
         | 
| 206 206 |  | 
| @@ -208,8 +208,8 @@ describe FlavourSaver do | |
| 208 208 | 
             
                  let(:template) { "{{awesome}}" }
         | 
| 209 209 |  | 
| 210 210 | 
             
                  it "are called and render their output" do
         | 
| 211 | 
            -
                    context. | 
| 212 | 
            -
                    subject. | 
| 211 | 
            +
                    allow(context).to receive(:awesome).and_return("Awesome")
         | 
| 212 | 
            +
                    expect(subject).to eq "Awesome"
         | 
| 213 213 | 
             
                  end
         | 
| 214 214 | 
             
                end
         | 
| 215 215 |  | 
| @@ -218,8 +218,8 @@ describe FlavourSaver do | |
| 218 218 | 
             
                    let(:template) { "{{foo-bar}}" }
         | 
| 219 219 |  | 
| 220 220 | 
             
                    it 'paths can contain hyphens (-)' do
         | 
| 221 | 
            -
                      context. | 
| 222 | 
            -
                      subject. | 
| 221 | 
            +
                      expect(context).to receive(:[]).with('foo-bar').and_return('baz')
         | 
| 222 | 
            +
                      expect(subject).to eq 'baz'
         | 
| 223 223 | 
             
                    end
         | 
| 224 224 | 
             
                  end
         | 
| 225 225 |  | 
| @@ -227,8 +227,8 @@ describe FlavourSaver do | |
| 227 227 | 
             
                    let(:template) { "{{foo.foo-bar}}" }
         | 
| 228 228 |  | 
| 229 229 | 
             
                    it 'paths can contain hyphens (-)' do
         | 
| 230 | 
            -
                      context. | 
| 231 | 
            -
                      subject. | 
| 230 | 
            +
                      allow(context).to receive_message_chain(:foo, :[]).with('foo-bar').and_return(proc { 'baz' })
         | 
| 231 | 
            +
                      expect(subject).to eq 'baz'
         | 
| 232 232 | 
             
                    end
         | 
| 233 233 | 
             
                  end
         | 
| 234 234 |  | 
| @@ -236,8 +236,8 @@ describe FlavourSaver do | |
| 236 236 | 
             
                    let(:template) { "{{foo/foo-bar}}" }
         | 
| 237 237 |  | 
| 238 238 | 
             
                    it 'paths can contain hyphens (-)' do
         | 
| 239 | 
            -
                      context. | 
| 240 | 
            -
                      subject. | 
| 239 | 
            +
                      allow(context).to receive_message_chain(:foo, :[]).with('foo-bar').and_return('baz')
         | 
| 240 | 
            +
                      expect(subject).to eq 'baz'
         | 
| 241 241 | 
             
                    end
         | 
| 242 242 | 
             
                  end
         | 
| 243 243 |  | 
| @@ -245,8 +245,8 @@ describe FlavourSaver do | |
| 245 245 | 
             
                    let(:template) {"Goodbye {{alan/expression}} world!"}
         | 
| 246 246 |  | 
| 247 247 | 
             
                    it 'access nested object' do
         | 
| 248 | 
            -
                      context. | 
| 249 | 
            -
                      subject. | 
| 248 | 
            +
                      allow(context).to receive_message_chain(:alan, :expression).and_return('beautiful')
         | 
| 249 | 
            +
                      expect(subject).to eq 'Goodbye beautiful world!'
         | 
| 250 250 | 
             
                    end
         | 
| 251 251 | 
             
                  end
         | 
| 252 252 |  | 
| @@ -254,8 +254,8 @@ describe FlavourSaver do | |
| 254 254 | 
             
                    let(:template) {"Goodbye {{alan/expression}} world!"}
         | 
| 255 255 |  | 
| 256 256 | 
             
                    it 'access nested object' do
         | 
| 257 | 
            -
                      context. | 
| 258 | 
            -
                      subject. | 
| 257 | 
            +
                      allow(context).to receive_message_chain(:alan, :expression).and_return('')
         | 
| 258 | 
            +
                      expect(subject).to eq 'Goodbye  world!'
         | 
| 259 259 | 
             
                    end
         | 
| 260 260 | 
             
                  end
         | 
| 261 261 |  | 
| @@ -264,9 +264,9 @@ describe FlavourSaver do | |
| 264 264 |  | 
| 265 265 | 
             
                    it 'literal paths can be used' do
         | 
| 266 266 | 
             
                      alan = double(:alan)
         | 
| 267 | 
            -
                      context. | 
| 268 | 
            -
                      alan. | 
| 269 | 
            -
                      subject. | 
| 267 | 
            +
                      expect(context).to receive(:[]).with('@alan').and_return(alan)
         | 
| 268 | 
            +
                      expect(alan).to receive(:expression).and_return('beautiful')
         | 
| 269 | 
            +
                      expect(subject).to eq 'Goodbye beautiful world!'
         | 
| 270 270 | 
             
                    end
         | 
| 271 271 | 
             
                  end
         | 
| 272 272 |  | 
| @@ -274,13 +274,13 @@ describe FlavourSaver do | |
| 274 274 | 
             
                    let(:template) { '{{person/name}}' }
         | 
| 275 275 |  | 
| 276 276 | 
             
                    it 'returns empty string from nested paths' do
         | 
| 277 | 
            -
                      context. | 
| 278 | 
            -
                      subject. | 
| 277 | 
            +
                      allow(context).to receive_message_chain(:person,:name).and_return('')
         | 
| 278 | 
            +
                      expect(subject).to eq ''
         | 
| 279 279 | 
             
                    end
         | 
| 280 280 |  | 
| 281 281 | 
             
                    it 'returns empty string from nil objects' do
         | 
| 282 | 
            -
                      context. | 
| 283 | 
            -
                      subject. | 
| 282 | 
            +
                      allow(context).to receive_message_chain(:person,:name)
         | 
| 283 | 
            +
                      expect(subject).to eq ''
         | 
| 284 284 | 
             
                    end
         | 
| 285 285 | 
             
                  end
         | 
| 286 286 |  | 
| @@ -289,8 +289,8 @@ describe FlavourSaver do | |
| 289 289 | 
             
                      let(:template) { "{{#goodbyes}}{{this}}{{/goodbyes}}" }
         | 
| 290 290 |  | 
| 291 291 | 
             
                      it 'evaluates to the current context' do
         | 
| 292 | 
            -
                        context. | 
| 293 | 
            -
                        subject. | 
| 292 | 
            +
                        allow(context).to receive(:goodbyes).and_return(["goodbye", "Goodbye", "GOODBYE"])
         | 
| 293 | 
            +
                        expect(subject).to eq "goodbyeGoodbyeGOODBYE"
         | 
| 294 294 | 
             
                      end
         | 
| 295 295 | 
             
                    end
         | 
| 296 296 |  | 
| @@ -300,13 +300,13 @@ describe FlavourSaver do | |
| 300 300 | 
             
                      it 'evaluates in more complex paths' do
         | 
| 301 301 | 
             
                        hellos = []
         | 
| 302 302 | 
             
                        hellos << double(:hello)
         | 
| 303 | 
            -
                        hellos[0]. | 
| 303 | 
            +
                        expect(hellos[0]).to receive(:text).and_return('hello')
         | 
| 304 304 | 
             
                        hellos << double(:Hello)
         | 
| 305 | 
            -
                        hellos[1]. | 
| 305 | 
            +
                        expect(hellos[1]).to receive(:text).and_return('Hello')
         | 
| 306 306 | 
             
                        hellos << double(:HELLO)
         | 
| 307 | 
            -
                        hellos[2]. | 
| 308 | 
            -
                        context. | 
| 309 | 
            -
                        subject. | 
| 307 | 
            +
                        expect(hellos[2]).to receive(:text).and_return('HELLO')
         | 
| 308 | 
            +
                        allow(context).to receive(:hellos).and_return(hellos)
         | 
| 309 | 
            +
                        expect(subject).to eq "helloHelloHELLO"
         | 
| 310 310 | 
             
                      end
         | 
| 311 311 | 
             
                    end
         | 
| 312 312 | 
             
                  end
         | 
| @@ -318,8 +318,8 @@ describe FlavourSaver do | |
| 318 318 | 
             
                      let(:template) { "{{#goodbyes}}{{foo this}}{{/goodbyes}}" }
         | 
| 319 319 |  | 
| 320 320 | 
             
                      it 'evaluates to current context' do
         | 
| 321 | 
            -
                        context. | 
| 322 | 
            -
                        subject. | 
| 321 | 
            +
                        allow(context).to receive(:goodbyes).and_return(["goodbye", "Goodbye", "GOODBYE"])
         | 
| 322 | 
            +
                        expect(subject).to eq "bar goodbyebar Goodbyebar GOODBYE"
         | 
| 323 323 | 
             
                      end
         | 
| 324 324 | 
             
                    end
         | 
| 325 325 |  | 
| @@ -329,13 +329,13 @@ describe FlavourSaver do | |
| 329 329 | 
             
                      it 'evaluates to current context' do
         | 
| 330 330 | 
             
                        hellos = []
         | 
| 331 331 | 
             
                        hellos << double(:hello)
         | 
| 332 | 
            -
                        hellos[0]. | 
| 332 | 
            +
                        expect(hellos[0]).to receive(:text).and_return('hello')
         | 
| 333 333 | 
             
                        hellos << double(:Hello)
         | 
| 334 | 
            -
                        hellos[1]. | 
| 334 | 
            +
                        expect(hellos[1]).to receive(:text).and_return('Hello')
         | 
| 335 335 | 
             
                        hellos << double(:HELLO)
         | 
| 336 | 
            -
                        hellos[2]. | 
| 337 | 
            -
                        context. | 
| 338 | 
            -
                        subject. | 
| 336 | 
            +
                        expect(hellos[2]).to receive(:text).and_return('HELLO')
         | 
| 337 | 
            +
                        allow(context).to receive(:hellos).and_return(hellos)
         | 
| 338 | 
            +
                        expect(subject).to eq "bar hellobar Hellobar HELLO"
         | 
| 339 339 | 
             
                      end
         | 
| 340 340 | 
             
                    end
         | 
| 341 341 | 
             
                  end
         | 
| @@ -347,22 +347,22 @@ describe FlavourSaver do | |
| 347 347 |  | 
| 348 348 | 
             
                describe 'with unset value' do
         | 
| 349 349 | 
             
                  it 'renders' do
         | 
| 350 | 
            -
                    context. | 
| 351 | 
            -
                    subject. | 
| 350 | 
            +
                    allow(context).to receive(:goodbyes)
         | 
| 351 | 
            +
                    expect(subject).to eq 'Right On!'
         | 
| 352 352 | 
             
                  end
         | 
| 353 353 | 
             
                end
         | 
| 354 354 |  | 
| 355 355 | 
             
                describe 'with false value' do
         | 
| 356 356 | 
             
                  it 'renders' do
         | 
| 357 | 
            -
                    context. | 
| 358 | 
            -
                    subject. | 
| 357 | 
            +
                    allow(context).to receive(:goodbyes).and_return(false)
         | 
| 358 | 
            +
                    expect(subject).to eq 'Right On!'
         | 
| 359 359 | 
             
                  end
         | 
| 360 360 | 
             
                end
         | 
| 361 361 |  | 
| 362 362 | 
             
                describe 'with an empty set' do
         | 
| 363 363 | 
             
                  it 'renders' do
         | 
| 364 | 
            -
                    context. | 
| 365 | 
            -
                    subject. | 
| 364 | 
            +
                    allow(context).to receive(:goodbyes).and_return([])
         | 
| 365 | 
            +
                    expect(subject).to eq 'Right On!'
         | 
| 366 366 | 
             
                  end
         | 
| 367 367 | 
             
                end
         | 
| 368 368 | 
             
              end
         | 
| @@ -373,20 +373,20 @@ describe FlavourSaver do | |
| 373 373 | 
             
                it 'arrays iterate the contents with non-empty' do
         | 
| 374 374 | 
             
                  goodbyes = []
         | 
| 375 375 | 
             
                  goodbyes << double(:goodbye)
         | 
| 376 | 
            -
                  goodbyes[0]. | 
| 376 | 
            +
                  expect(goodbyes[0]).to receive(:text).and_return('goodbye')
         | 
| 377 377 | 
             
                  goodbyes << double(:Goodbye)
         | 
| 378 | 
            -
                  goodbyes[1]. | 
| 378 | 
            +
                  expect(goodbyes[1]).to receive(:text).and_return('Goodbye')
         | 
| 379 379 | 
             
                  goodbyes << double(:GOODBYE)
         | 
| 380 | 
            -
                  goodbyes[2]. | 
| 381 | 
            -
                  context. | 
| 382 | 
            -
                  context. | 
| 383 | 
            -
                  subject. | 
| 380 | 
            +
                  expect(goodbyes[2]).to receive(:text).and_return('GOODBYE')
         | 
| 381 | 
            +
                  allow(context).to receive(:goodbyes).and_return(goodbyes)
         | 
| 382 | 
            +
                  allow(context).to receive(:world).and_return('world')
         | 
| 383 | 
            +
                  expect(subject).to eq "goodbye! Goodbye! GOODBYE! cruel world!"
         | 
| 384 384 | 
             
                end
         | 
| 385 385 |  | 
| 386 386 | 
             
                it 'ignores the contents when the array is empty' do
         | 
| 387 | 
            -
                  context. | 
| 388 | 
            -
                  context. | 
| 389 | 
            -
                  subject. | 
| 387 | 
            +
                  allow(context).to receive(:goodbyes).and_return([])
         | 
| 388 | 
            +
                  allow(context).to receive(:world).and_return('world')
         | 
| 389 | 
            +
                  expect(subject).to eq "cruel world!"
         | 
| 390 390 | 
             
                end
         | 
| 391 391 |  | 
| 392 392 | 
             
                describe 'array with @index' do
         | 
| @@ -395,14 +395,29 @@ describe FlavourSaver do | |
| 395 395 | 
             
                  it 'the @index variable is used' do
         | 
| 396 396 | 
             
                    goodbyes = []
         | 
| 397 397 | 
             
                    goodbyes << double(:goodbye)
         | 
| 398 | 
            -
                    goodbyes[0]. | 
| 398 | 
            +
                    expect(goodbyes[0]).to receive(:text).and_return('goodbye')
         | 
| 399 399 | 
             
                    goodbyes << double(:Goodbye)
         | 
| 400 | 
            -
                    goodbyes[1]. | 
| 400 | 
            +
                    expect(goodbyes[1]).to receive(:text).and_return('Goodbye')
         | 
| 401 401 | 
             
                    goodbyes << double(:GOODBYE)
         | 
| 402 | 
            -
                    goodbyes[2]. | 
| 403 | 
            -
                    context. | 
| 404 | 
            -
                    context. | 
| 405 | 
            -
                    subject. | 
| 402 | 
            +
                    expect(goodbyes[2]).to receive(:text).and_return('GOODBYE')
         | 
| 403 | 
            +
                    allow(context).to receive(:goodbyes).and_return(goodbyes)
         | 
| 404 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 405 | 
            +
                    expect(subject).to eq "0. goodbye! 1. Goodbye! 2. GOODBYE! cruel world!"
         | 
| 406 | 
            +
                  end
         | 
| 407 | 
            +
                end
         | 
| 408 | 
            +
             | 
| 409 | 
            +
                describe 'array with numeric dereference' do
         | 
| 410 | 
            +
                  let(:template) {"{{goodbyes.0.text}} cruel {{world}}!"}
         | 
| 411 | 
            +
             | 
| 412 | 
            +
                  it 'properly inserts the referenced element' do
         | 
| 413 | 
            +
                    goodbyes = []
         | 
| 414 | 
            +
                    goodbyes << double(:goodbye)
         | 
| 415 | 
            +
                    expect(goodbyes[0]).to receive(:text).and_return('goodbye')
         | 
| 416 | 
            +
             | 
| 417 | 
            +
                    allow(context).to receive(:goodbyes).and_return(goodbyes)
         | 
| 418 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 419 | 
            +
             | 
| 420 | 
            +
                    expect(subject).to eq "goodbye cruel world!"
         | 
| 406 421 | 
             
                  end
         | 
| 407 422 | 
             
                end
         | 
| 408 423 |  | 
| @@ -412,20 +427,20 @@ describe FlavourSaver do | |
| 412 427 | 
             
                  it 'arrays iterate the contents with non-empty' do
         | 
| 413 428 | 
             
                    goodbyes = []
         | 
| 414 429 | 
             
                    goodbyes << double(:goodbye)
         | 
| 415 | 
            -
                    goodbyes[0]. | 
| 430 | 
            +
                    allow(goodbyes[0]).to receive(:text).and_return('goodbye')
         | 
| 416 431 | 
             
                    goodbyes << double(:Goodbye)
         | 
| 417 | 
            -
                    goodbyes[1]. | 
| 432 | 
            +
                    allow(goodbyes[1]).to receive(:text).and_return('Goodbye')
         | 
| 418 433 | 
             
                    goodbyes << double(:GOODBYE)
         | 
| 419 | 
            -
                    goodbyes[2]. | 
| 420 | 
            -
                    context. | 
| 421 | 
            -
                    context. | 
| 422 | 
            -
                    subject. | 
| 434 | 
            +
                    allow(goodbyes[2]).to receive(:text).and_return('GOODBYE')
         | 
| 435 | 
            +
                    allow(context).to receive(:goodbyes).and_return(goodbyes)
         | 
| 436 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 437 | 
            +
                    expect(subject).to eq "cruel world!"
         | 
| 423 438 | 
             
                  end
         | 
| 424 439 |  | 
| 425 440 | 
             
                  it 'ignores the contents when the array is empty' do
         | 
| 426 | 
            -
                    context. | 
| 427 | 
            -
                    context. | 
| 428 | 
            -
                    subject. | 
| 441 | 
            +
                    allow(context).to receive(:goodbyes).and_return([])
         | 
| 442 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 443 | 
            +
                    expect(subject).to eq "cruel world!"
         | 
| 429 444 | 
             
                  end
         | 
| 430 445 | 
             
                end
         | 
| 431 446 |  | 
| @@ -435,16 +450,16 @@ describe FlavourSaver do | |
| 435 450 | 
             
                  let(:template) {"{{#goodbyes}}{{text}} cruel {{../name}}! {{/goodbyes}}"}
         | 
| 436 451 |  | 
| 437 452 | 
             
                  it 'templates can access variables in contexts up the stack with relative path syntax' do
         | 
| 438 | 
            -
                    context. | 
| 453 | 
            +
                    allow(context).to receive(:name).and_return('Alan')
         | 
| 439 454 | 
             
                    goodbyes = []
         | 
| 440 455 | 
             
                    goodbyes << double(:goodbye)
         | 
| 441 | 
            -
                    goodbyes[0]. | 
| 456 | 
            +
                    expect(goodbyes[0]).to receive(:text).and_return('goodbye')
         | 
| 442 457 | 
             
                    goodbyes << double(:Goodbye)
         | 
| 443 | 
            -
                    goodbyes[1]. | 
| 458 | 
            +
                    expect(goodbyes[1]).to receive(:text).and_return('Goodbye')
         | 
| 444 459 | 
             
                    goodbyes << double(:GOODBYE)
         | 
| 445 | 
            -
                    goodbyes[2]. | 
| 446 | 
            -
                    context. | 
| 447 | 
            -
                    subject. | 
| 460 | 
            +
                    expect(goodbyes[2]).to receive(:text).and_return('GOODBYE')
         | 
| 461 | 
            +
                    allow(context).to receive(:goodbyes).and_return(goodbyes)
         | 
| 462 | 
            +
                    expect(subject).to eq "goodbye cruel Alan! Goodbye cruel Alan! GOODBYE cruel Alan! "
         | 
| 448 463 | 
             
                  end
         | 
| 449 464 | 
             
                end
         | 
| 450 465 |  | 
| @@ -457,13 +472,13 @@ describe FlavourSaver do | |
| 457 472 | 
             
                  end
         | 
| 458 473 |  | 
| 459 474 | 
             
                  it 'renders correctly' do
         | 
| 460 | 
            -
                    context. | 
| 475 | 
            +
                    allow(context).to receive(:prefix).and_return('/root')
         | 
| 461 476 | 
             
                    goodbyes = []
         | 
| 462 477 | 
             
                    goodbyes << double(:Goodbye)
         | 
| 463 | 
            -
                    goodbyes[0]. | 
| 464 | 
            -
                    goodbyes[0]. | 
| 465 | 
            -
                    context. | 
| 466 | 
            -
                    subject. | 
| 478 | 
            +
                    expect(goodbyes[0]).to receive(:text).and_return('Goodbye')
         | 
| 479 | 
            +
                    expect(goodbyes[0]).to receive(:url).and_return('goodbye')
         | 
| 480 | 
            +
                    allow(context).to receive(:goodbyes).and_return(goodbyes)
         | 
| 481 | 
            +
                    expect(subject).to eq "<a href='/root/goodbye'>Goodbye</a>"
         | 
| 467 482 | 
             
                  end
         | 
| 468 483 | 
             
                end
         | 
| 469 484 |  | 
| @@ -478,8 +493,8 @@ describe FlavourSaver do | |
| 478 493 | 
             
                  end
         | 
| 479 494 |  | 
| 480 495 | 
             
                  it 'renders correctly' do
         | 
| 481 | 
            -
                    context. | 
| 482 | 
            -
                    subject. | 
| 496 | 
            +
                    allow(context).to receive(:name).and_return('Alan')
         | 
| 497 | 
            +
                    expect(subject).to eq "Goodbye Alan! goodbye Alan! GOODBYE Alan! "
         | 
| 483 498 | 
             
                  end
         | 
| 484 499 | 
             
                end
         | 
| 485 500 |  | 
| @@ -492,12 +507,12 @@ describe FlavourSaver do | |
| 492 507 | 
             
                  end
         | 
| 493 508 |  | 
| 494 509 | 
             
                  it 'renders correctly' do
         | 
| 495 | 
            -
                    context. | 
| 510 | 
            +
                    allow(context).to receive(:prefix).and_return('/root')
         | 
| 496 511 | 
             
                    goodbye = double(:goodbye)
         | 
| 497 | 
            -
                    goodbye. | 
| 498 | 
            -
                    goodbye. | 
| 499 | 
            -
                    context. | 
| 500 | 
            -
                    subject. | 
| 512 | 
            +
                    allow(goodbye).to receive(:text).and_return('Goodbye')
         | 
| 513 | 
            +
                    allow(goodbye).to receive(:url).and_return('goodbye')
         | 
| 514 | 
            +
                    allow(context).to receive(:goodbyes).and_return([goodbye])
         | 
| 515 | 
            +
                    expect(subject).to eq "<a href='/root/goodbye'>Goodbye</a>"
         | 
| 501 516 | 
             
                  end
         | 
| 502 517 | 
             
                end
         | 
| 503 518 |  | 
| @@ -506,12 +521,12 @@ describe FlavourSaver do | |
| 506 521 |  | 
| 507 522 | 
             
                  example do
         | 
| 508 523 | 
             
                    goodbye = double(:goodbye)
         | 
| 509 | 
            -
                    goodbye. | 
| 524 | 
            +
                    allow(goodbye).to receive(:text).and_return('goodbye')
         | 
| 510 525 | 
             
                    inner = double(:inner)
         | 
| 511 | 
            -
                    inner. | 
| 512 | 
            -
                    context. | 
| 513 | 
            -
                    context. | 
| 514 | 
            -
                    subject. | 
| 526 | 
            +
                    allow(inner).to receive(:inner).and_return([goodbye])
         | 
| 527 | 
            +
                    allow(context).to receive(:omg).and_return('OMG!')
         | 
| 528 | 
            +
                    allow(context).to receive(:outer).and_return([inner])
         | 
| 529 | 
            +
                    expect(subject).to eq "Goodbye cruel OMG!"
         | 
| 515 530 | 
             
                  end
         | 
| 516 531 | 
             
                end
         | 
| 517 532 |  | 
| @@ -524,7 +539,7 @@ describe FlavourSaver do | |
| 524 539 | 
             
                  end
         | 
| 525 540 |  | 
| 526 541 | 
             
                  example do
         | 
| 527 | 
            -
                    context. | 
| 542 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 528 543 | 
             
                  end
         | 
| 529 544 | 
             
                end
         | 
| 530 545 |  | 
| @@ -537,8 +552,8 @@ describe FlavourSaver do | |
| 537 552 | 
             
                  end
         | 
| 538 553 |  | 
| 539 554 | 
             
                  example do
         | 
| 540 | 
            -
                    context. | 
| 541 | 
            -
                    subject. | 
| 555 | 
            +
                    allow(context).to receive(:name).and_return('Yehuda')
         | 
| 556 | 
            +
                    expect(subject).to eq "<form><p>Yehuda</p></form>"
         | 
| 542 557 | 
             
                  end
         | 
| 543 558 | 
             
                end
         | 
| 544 559 |  | 
| @@ -551,15 +566,15 @@ describe FlavourSaver do | |
| 551 566 | 
             
                  end
         | 
| 552 567 | 
             
                  example do
         | 
| 553 568 | 
             
                    person = Struct.new(:name, :id)
         | 
| 554 | 
            -
                    context. | 
| 555 | 
            -
                    subject. | 
| 569 | 
            +
                    allow(context).to receive(:people).and_return([person.new('Alan', 1), person.new('Yehuda', 2)])
         | 
| 570 | 
            +
                    expect(subject).to eq "<ul><li><a href=\"/people/1\">Alan</a></li><li><a href=\"/people/2\">Yehuda</a></li></ul>"
         | 
| 556 571 | 
             
                  end
         | 
| 557 572 | 
             
                end
         | 
| 558 573 |  | 
| 559 574 | 
             
                describe 'block helper for undefined value' do
         | 
| 560 575 | 
             
                  let(:template) { "{{#empty}}shoulnd't render{{/empty}}" }
         | 
| 561 576 | 
             
                  example do
         | 
| 562 | 
            -
                     | 
| 577 | 
            +
                    expect { subject }.to raise_exception(FlavourSaver::UnknownHelperException)
         | 
| 563 578 | 
             
                  end
         | 
| 564 579 | 
             
                end
         | 
| 565 580 |  | 
| @@ -571,8 +586,8 @@ describe FlavourSaver do | |
| 571 586 | 
             
                    end
         | 
| 572 587 | 
             
                  end
         | 
| 573 588 | 
             
                  example do
         | 
| 574 | 
            -
                    context. | 
| 575 | 
            -
                    subject. | 
| 589 | 
            +
                    allow(context).to receive_message_chain(:yehuda,:name).and_return('Yehuda')
         | 
| 590 | 
            +
                    expect(subject).to eq "<form><p>Yehuda</p></form>"
         | 
| 576 591 | 
             
                  end
         | 
| 577 592 | 
             
                end
         | 
| 578 593 |  | 
| @@ -585,10 +600,10 @@ describe FlavourSaver do | |
| 585 600 | 
             
                  end
         | 
| 586 601 | 
             
                  example do
         | 
| 587 602 | 
             
                    yehuda = double(:yehuda)
         | 
| 588 | 
            -
                    yehuda. | 
| 589 | 
            -
                    yehuda. | 
| 590 | 
            -
                    context. | 
| 591 | 
            -
                    subject. | 
| 603 | 
            +
                    allow(yehuda).to receive(:name).and_return('Yehuda')
         | 
| 604 | 
            +
                    allow(yehuda).to receive_message_chain(:cat,:name).and_return('Harold')
         | 
| 605 | 
            +
                    allow(context).to receive(:yehuda).and_return(yehuda)
         | 
| 606 | 
            +
                    expect(subject).to eq "<form><p>Harold</p></form>"
         | 
| 592 607 | 
             
                  end
         | 
| 593 608 | 
             
                end
         | 
| 594 609 |  | 
| @@ -603,26 +618,26 @@ describe FlavourSaver do | |
| 603 618 | 
             
                    end
         | 
| 604 619 | 
             
                  end
         | 
| 605 620 | 
             
                  example do
         | 
| 606 | 
            -
                    context. | 
| 607 | 
            -
                    subject. | 
| 621 | 
            +
                    allow(context).to receive_message_chain(:yehuda,:name).and_return('Yehuda')
         | 
| 622 | 
            +
                    expect(subject).to eq "<form><p>Yehuda</p><a href='Yehuda'>Hello</a></form>"
         | 
| 608 623 | 
             
                  end
         | 
| 609 624 | 
             
                end
         | 
| 610 625 |  | 
| 611 626 | 
             
                describe 'block inverted sections' do
         | 
| 612 627 | 
             
                  let(:template) { "{{#people}}{{name}}{{^}}{{none}}{{/people}}" }
         | 
| 613 628 | 
             
                  example do
         | 
| 614 | 
            -
                    context. | 
| 615 | 
            -
                    context. | 
| 616 | 
            -
                    subject. | 
| 629 | 
            +
                    allow(context).to receive(:none).and_return("No people")
         | 
| 630 | 
            +
                    allow(context).to receive(:people).and_return(false)
         | 
| 631 | 
            +
                    expect(subject).to eq "No people"
         | 
| 617 632 | 
             
                  end
         | 
| 618 633 | 
             
                end
         | 
| 619 634 |  | 
| 620 635 | 
             
                describe 'block inverted sections with empty arrays' do
         | 
| 621 636 | 
             
                  let(:template) { "{{#people}}{{name}}{{^}}{{none}}{{/people}}" }
         | 
| 622 637 | 
             
                  example do
         | 
| 623 | 
            -
                    context. | 
| 624 | 
            -
                    context. | 
| 625 | 
            -
                    subject. | 
| 638 | 
            +
                    allow(context).to receive(:none).and_return('No people')
         | 
| 639 | 
            +
                    allow(context).to receive(:people).and_return([])
         | 
| 640 | 
            +
                    expect(subject).to eq "No people"
         | 
| 626 641 | 
             
                  end
         | 
| 627 642 | 
             
                end
         | 
| 628 643 |  | 
| @@ -642,24 +657,24 @@ describe FlavourSaver do | |
| 642 657 |  | 
| 643 658 | 
             
                  example 'an inverse wrapper is passed in as a new context' do
         | 
| 644 659 | 
             
                    person = Struct.new(:name)
         | 
| 645 | 
            -
                    context. | 
| 646 | 
            -
                    subject. | 
| 660 | 
            +
                    allow(context).to receive(:people).and_return([person.new('Alan'),person.new('Yehuda')])
         | 
| 661 | 
            +
                    expect(subject).to eq "<ul><li>Alan</li><li>Yehuda</li></ul>"
         | 
| 647 662 | 
             
                  end
         | 
| 648 663 |  | 
| 649 664 | 
             
                  example 'an inverse wrapper can optionally be called' do
         | 
| 650 | 
            -
                    context. | 
| 651 | 
            -
                    subject. | 
| 665 | 
            +
                    allow(context).to receive(:people).and_return([])
         | 
| 666 | 
            +
                    expect(subject).to eq "<p><em>Nobody's here</em></p>"
         | 
| 652 667 | 
             
                  end
         | 
| 653 668 |  | 
| 654 669 | 
             
                  describe 'the context of an inverse is the parent of the block' do
         | 
| 655 670 | 
             
                    let(:template) { "{{#list people}}Hello{{^}}{{message}}{{/list}}" }
         | 
| 656 671 | 
             
                    example do
         | 
| 657 | 
            -
                      context. | 
| 658 | 
            -
                      context. | 
| 672 | 
            +
                      allow(context).to receive(:people).and_return([])
         | 
| 673 | 
            +
                      allow(context).to receive(:message).and_return("Nobody's here")
         | 
| 659 674 | 
             
                      if RUBY_VERSION >= '2.0.0'
         | 
| 660 | 
            -
                        subject. | 
| 675 | 
            +
                        expect(subject).to eq "<p>Nobody's here</p>"
         | 
| 661 676 | 
             
                      else
         | 
| 662 | 
            -
                        subject. | 
| 677 | 
            +
                        expect(subject).to eq "<p>Nobody's here</p>"
         | 
| 663 678 | 
             
                      end
         | 
| 664 679 | 
             
                    end
         | 
| 665 680 | 
             
                  end
         | 
| @@ -673,8 +688,8 @@ describe FlavourSaver do | |
| 673 688 | 
             
                end
         | 
| 674 689 | 
             
                example do
         | 
| 675 690 | 
             
                  person = Struct.new(:name, :url)
         | 
| 676 | 
            -
                  context. | 
| 677 | 
            -
                  subject. | 
| 691 | 
            +
                  allow(context).to receive(:dudes).and_return([person.new('Yehuda', 'http://yehuda'), person.new('Alan', 'http://alan')])
         | 
| 692 | 
            +
                  expect(subject).to eq "Dudes: Yehuda (http://yehuda) Alan (http://alan) "
         | 
| 678 693 | 
             
                end
         | 
| 679 694 | 
             
              end
         | 
| 680 695 |  | 
| @@ -685,8 +700,8 @@ describe FlavourSaver do | |
| 685 700 | 
             
                end
         | 
| 686 701 | 
             
                example "Partials can be passed a context" do
         | 
| 687 702 | 
             
                  person = Struct.new(:name, :url)
         | 
| 688 | 
            -
                  context. | 
| 689 | 
            -
                  subject. | 
| 703 | 
            +
                  allow(context).to receive(:dudes).and_return([person.new('Yehuda', 'http://yehuda'), person.new('Alan', 'http://alan')])
         | 
| 704 | 
            +
                  expect(subject).to eq "Dudes: Yehuda (http://yehuda) Alan (http://alan) "
         | 
| 690 705 | 
             
                end
         | 
| 691 706 | 
             
              end
         | 
| 692 707 |  | 
| @@ -698,15 +713,15 @@ describe FlavourSaver do | |
| 698 713 | 
             
                end
         | 
| 699 714 | 
             
                example "Partials can be passed a context" do
         | 
| 700 715 | 
             
                  person = Struct.new(:name, :url)
         | 
| 701 | 
            -
                  context. | 
| 702 | 
            -
                  subject. | 
| 716 | 
            +
                  allow(context).to receive(:dudes).and_return([person.new('Yehuda', 'http://yehuda'), person.new('Alan', 'http://alan')])
         | 
| 717 | 
            +
                  expect(subject).to eq "Dudes: Yehuda <a href='http://yehuda'>http://yehuda</a> Alan <a href='http://alan'>http://alan</a> "
         | 
| 703 718 | 
             
                end
         | 
| 704 719 | 
             
              end
         | 
| 705 720 |  | 
| 706 721 | 
             
              describe 'rendering undefined partial throws an exception' do
         | 
| 707 722 | 
             
                let(:template) { "{{> whatever}}" }
         | 
| 708 723 | 
             
                example do
         | 
| 709 | 
            -
                   | 
| 724 | 
            +
                  expect { subject }.to raise_error(FS::UnknownPartialException)
         | 
| 710 725 | 
             
                end
         | 
| 711 726 | 
             
              end
         | 
| 712 727 |  | 
| @@ -719,8 +734,8 @@ describe FlavourSaver do | |
| 719 734 | 
             
                end
         | 
| 720 735 | 
             
                example do
         | 
| 721 736 | 
             
                  person = Struct.new(:name, :url)
         | 
| 722 | 
            -
                  context. | 
| 723 | 
            -
                  subject. | 
| 737 | 
            +
                  allow(context).to receive(:dudes).and_return([person.new('Yehuda', 'http://yehuda'), person.new('Alan', 'http://alan')])
         | 
| 738 | 
            +
                  expect(subject).to eq "Dudes: Yehuda (http://yehuda) Alan (http://alan) "
         | 
| 724 739 | 
             
                end
         | 
| 725 740 | 
             
              end
         | 
| 726 741 |  | 
| @@ -730,9 +745,9 @@ describe FlavourSaver do | |
| 730 745 | 
             
                  FS.register_partial(:dude, "{{name}}")
         | 
| 731 746 | 
             
                end
         | 
| 732 747 | 
             
                example do
         | 
| 733 | 
            -
                  context. | 
| 734 | 
            -
                  context. | 
| 735 | 
            -
                  subject. | 
| 748 | 
            +
                  allow(context).to receive(:name).and_return('Jeepers')
         | 
| 749 | 
            +
                  allow(context).to receive(:another_dude).and_return('Creepers')
         | 
| 750 | 
            +
                  expect(subject).to eq "Dudes: Jeepers Creepers"
         | 
| 736 751 | 
             
                end
         | 
| 737 752 | 
             
              end
         | 
| 738 753 |  | 
| @@ -742,9 +757,9 @@ describe FlavourSaver do | |
| 742 757 | 
             
                  FS.register_partial(:dude, "{{name}}")
         | 
| 743 758 | 
             
                end
         | 
| 744 759 | 
             
                example do
         | 
| 745 | 
            -
                  context. | 
| 746 | 
            -
                  context. | 
| 747 | 
            -
                  subject. | 
| 760 | 
            +
                  allow(context).to receive(:name).and_return('Jeepers')
         | 
| 761 | 
            +
                  allow(context).to receive(:another_dude).and_return('Creepers')
         | 
| 762 | 
            +
                  expect(subject).to eq "Dudes: Jeepers"
         | 
| 748 763 | 
             
                end
         | 
| 749 764 | 
             
              end
         | 
| 750 765 |  | 
| @@ -754,9 +769,9 @@ describe FlavourSaver do | |
| 754 769 | 
             
                  FS.register_partial("dude/man", "{{name}}")
         | 
| 755 770 | 
             
                end
         | 
| 756 771 | 
             
                example do
         | 
| 757 | 
            -
                  context. | 
| 758 | 
            -
                  context. | 
| 759 | 
            -
                  subject. | 
| 772 | 
            +
                  allow(context).to receive(:name).and_return('Jeepers')
         | 
| 773 | 
            +
                  allow(context).to receive(:another_dude).and_return('Creepers')
         | 
| 774 | 
            +
                  expect(subject).to eq "Dudes: Jeepers"
         | 
| 760 775 | 
             
                end
         | 
| 761 776 | 
             
              end
         | 
| 762 777 |  | 
| @@ -773,14 +788,14 @@ describe FlavourSaver do | |
| 773 788 | 
             
                    end
         | 
| 774 789 | 
             
                  end
         | 
| 775 790 | 
             
                  example do
         | 
| 776 | 
            -
                    subject. | 
| 791 | 
            +
                    expect(subject).to eq "Message: Hello world 12 times: true false"
         | 
| 777 792 | 
             
                  end
         | 
| 778 793 | 
             
                end
         | 
| 779 794 |  | 
| 780 795 | 
             
                describe 'using a quote in the middle of a parameter raises an error' do
         | 
| 781 796 | 
             
                  let(:template) { "Message: {{hello wo\"rld\"}}" }
         | 
| 782 797 | 
             
                  example do
         | 
| 783 | 
            -
                     | 
| 798 | 
            +
                    expect { subject }.to raise_error(RLTK::NotInLanguage)
         | 
| 784 799 | 
             
                  end
         | 
| 785 800 | 
             
                end
         | 
| 786 801 |  | 
| @@ -792,7 +807,7 @@ describe FlavourSaver do | |
| 792 807 | 
             
                    end
         | 
| 793 808 | 
             
                  end
         | 
| 794 809 | 
             
                  example do
         | 
| 795 | 
            -
                    subject. | 
| 810 | 
            +
                    expect(subject).to eq 'Message: Hello \"world\"'
         | 
| 796 811 | 
             
                  end
         | 
| 797 812 | 
             
                end
         | 
| 798 813 |  | 
| @@ -804,7 +819,7 @@ describe FlavourSaver do | |
| 804 819 | 
             
                    end
         | 
| 805 820 | 
             
                  end
         | 
| 806 821 | 
             
                  example do
         | 
| 807 | 
            -
                    subject. | 
| 822 | 
            +
                    expect(subject).to eq "Message: Hello Alan's world"
         | 
| 808 823 | 
             
                  end
         | 
| 809 824 | 
             
                end
         | 
| 810 825 |  | 
| @@ -815,9 +830,9 @@ describe FlavourSaver do | |
| 815 830 | 
             
                  let(:template) { "Message: {{goodbye cruel world}}" }
         | 
| 816 831 | 
             
                  before { FS.register_helper(:goodbye) { |cruel,world| "Goodbye #{cruel} #{world}" } }
         | 
| 817 832 | 
             
                  example do
         | 
| 818 | 
            -
                    context. | 
| 819 | 
            -
                    context. | 
| 820 | 
            -
                    subject. | 
| 833 | 
            +
                    allow(context).to receive(:cruel).and_return('cruel')
         | 
| 834 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 835 | 
            +
                    expect(subject).to eq "Message: Goodbye cruel world"
         | 
| 821 836 | 
             
                  end
         | 
| 822 837 | 
             
                end
         | 
| 823 838 |  | 
| @@ -825,9 +840,9 @@ describe FlavourSaver do | |
| 825 840 | 
             
                  let(:template) { "Message: {{#goodbye cruel world}}{{greeting}} {{adj}} {{noun}}{{/goodbye}}" }
         | 
| 826 841 | 
             
                  before { FS.register_helper(:goodbye) { |adj,noun,&b| b.call.contents Struct.new(:greeting,:adj,:noun).new('Goodbye', adj, noun) } }
         | 
| 827 842 | 
             
                  example do
         | 
| 828 | 
            -
                    context. | 
| 829 | 
            -
                    context. | 
| 830 | 
            -
                    subject. | 
| 843 | 
            +
                    allow(context).to receive(:cruel).and_return('cruel')
         | 
| 844 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 845 | 
            +
                    expect(subject).to eq "Message: Goodbye cruel world"
         | 
| 831 846 | 
             
                  end
         | 
| 832 847 | 
             
                end
         | 
| 833 848 | 
             
              end
         | 
| @@ -836,8 +851,8 @@ describe FlavourSaver do | |
| 836 851 | 
             
                describe 'with' do
         | 
| 837 852 | 
             
                  let(:template) { "{{#with person}}{{first}} {{last}}{{/with}}" }
         | 
| 838 853 | 
             
                  example do
         | 
| 839 | 
            -
                    context. | 
| 840 | 
            -
                    subject. | 
| 854 | 
            +
                    allow(context).to receive(:person).and_return(Struct.new(:first,:last).new('Alan','Johnson'))
         | 
| 855 | 
            +
                    expect(subject).to eq 'Alan Johnson'
         | 
| 841 856 | 
             
                  end
         | 
| 842 857 | 
             
                end
         | 
| 843 858 |  | 
| @@ -845,39 +860,39 @@ describe FlavourSaver do | |
| 845 860 | 
             
                  let(:template) { "{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!" }
         | 
| 846 861 |  | 
| 847 862 | 
             
                  example 'if with boolean argument shows the contents when true' do
         | 
| 848 | 
            -
                    context. | 
| 849 | 
            -
                    context. | 
| 850 | 
            -
                    subject. | 
| 863 | 
            +
                    allow(context).to receive(:goodbye).and_return(true)
         | 
| 864 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 865 | 
            +
                    expect(subject).to eq "GOODBYE cruel world!"
         | 
| 851 866 | 
             
                  end
         | 
| 852 867 |  | 
| 853 868 | 
             
                  example 'if with string argument shows the contents with true' do
         | 
| 854 | 
            -
                    context. | 
| 855 | 
            -
                    context. | 
| 856 | 
            -
                    subject. | 
| 869 | 
            +
                    allow(context).to receive(:goodbye).and_return('dummy')
         | 
| 870 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 871 | 
            +
                    expect(subject).to eq "GOODBYE cruel world!"
         | 
| 857 872 | 
             
                  end
         | 
| 858 873 |  | 
| 859 874 | 
             
                  example 'if with boolean argument does not show the contents when false' do
         | 
| 860 | 
            -
                    context. | 
| 861 | 
            -
                    context. | 
| 862 | 
            -
                    subject. | 
| 875 | 
            +
                    allow(context).to receive(:goodbye).and_return(false)
         | 
| 876 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 877 | 
            +
                    expect(subject).to eq "cruel world!"
         | 
| 863 878 | 
             
                  end
         | 
| 864 879 |  | 
| 865 880 | 
             
                  example 'if with undefined does not show the contents' do
         | 
| 866 | 
            -
                    context. | 
| 867 | 
            -
                    context. | 
| 868 | 
            -
                    subject. | 
| 881 | 
            +
                    allow(context).to receive(:goodbye)
         | 
| 882 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 883 | 
            +
                    expect(subject).to eq "cruel world!"
         | 
| 869 884 | 
             
                  end
         | 
| 870 885 |  | 
| 871 886 | 
             
                  example 'if with non-empty array shows the contents' do
         | 
| 872 | 
            -
                    context. | 
| 873 | 
            -
                    context. | 
| 874 | 
            -
                    subject. | 
| 887 | 
            +
                    allow(context).to receive(:goodbye).and_return(['foo'])
         | 
| 888 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 889 | 
            +
                    expect(subject).to eq "GOODBYE cruel world!"
         | 
| 875 890 | 
             
                  end
         | 
| 876 891 |  | 
| 877 892 | 
             
                  example 'if with empty array does not show the contents' do
         | 
| 878 | 
            -
                    context. | 
| 879 | 
            -
                    context. | 
| 880 | 
            -
                    subject. | 
| 893 | 
            +
                    allow(context).to receive(:goodbye).and_return([])
         | 
| 894 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 895 | 
            +
                    expect(subject).to eq "cruel world!"
         | 
| 881 896 | 
             
                  end
         | 
| 882 897 | 
             
                end
         | 
| 883 898 |  | 
| @@ -886,15 +901,15 @@ describe FlavourSaver do | |
| 886 901 |  | 
| 887 902 | 
             
                  example 'each with array iterates over the contents with non-empty' do
         | 
| 888 903 | 
             
                    g = Struct.new(:text)
         | 
| 889 | 
            -
                    context. | 
| 890 | 
            -
                    context. | 
| 891 | 
            -
                    subject. | 
| 904 | 
            +
                    allow(context).to receive(:goodbyes).and_return([g.new('goodbye'), g.new('Goodbye'), g.new('GOODBYE')])
         | 
| 905 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 906 | 
            +
                    expect(subject).to eq "goodbye! Goodbye! GOODBYE! cruel world!"
         | 
| 892 907 | 
             
                  end
         | 
| 893 908 |  | 
| 894 909 | 
             
                  example 'each with array ignores the contents when empty' do
         | 
| 895 | 
            -
                    context. | 
| 896 | 
            -
                    context. | 
| 897 | 
            -
                    subject. | 
| 910 | 
            +
                    allow(context).to receive(:goodbyes).and_return([])
         | 
| 911 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 912 | 
            +
                    expect(subject).to eq "cruel world!"
         | 
| 898 913 | 
             
                  end
         | 
| 899 914 | 
             
                end
         | 
| 900 915 |  | 
| @@ -903,9 +918,20 @@ describe FlavourSaver do | |
| 903 918 |  | 
| 904 919 | 
             
                  example 'the @index variable is used' do
         | 
| 905 920 | 
             
                    g = Struct.new(:text)
         | 
| 906 | 
            -
                    context. | 
| 907 | 
            -
                    context. | 
| 908 | 
            -
                    subject. | 
| 921 | 
            +
                    allow(context).to receive(:goodbyes).and_return([g.new('goodbye'), g.new('Goodbye'), g.new('GOODBYE')])
         | 
| 922 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 923 | 
            +
                    expect(subject).to eq "0. goodbye! 1. Goodbye! 2. GOODBYE! cruel world!"
         | 
| 924 | 
            +
                  end
         | 
| 925 | 
            +
                end
         | 
| 926 | 
            +
             | 
| 927 | 
            +
                describe 'each with @index in a nested block' do
         | 
| 928 | 
            +
                  let(:template) { "{{#each goodbyes}}{{#if @last}}{{@index}}. {{/if}}{{text}}! {{/each}}cruel {{world}}!" }
         | 
| 929 | 
            +
             | 
| 930 | 
            +
                  example 'the @index variable is used' do
         | 
| 931 | 
            +
                    g = Struct.new(:text)
         | 
| 932 | 
            +
                    allow(context).to receive(:goodbyes).and_return([g.new('goodbye'), g.new('Goodbye'), g.new('GOODBYE')])
         | 
| 933 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 934 | 
            +
                    expect(subject).to eq "goodbye! Goodbye! 2. GOODBYE! cruel world!"
         | 
| 909 935 | 
             
                  end
         | 
| 910 936 | 
             
                end
         | 
| 911 937 |  | 
| @@ -914,9 +940,9 @@ describe FlavourSaver do | |
| 914 940 |  | 
| 915 941 | 
             
                  example 'the @last variable is used' do
         | 
| 916 942 | 
             
                    g = Struct.new(:text)
         | 
| 917 | 
            -
                    context. | 
| 918 | 
            -
                    context. | 
| 919 | 
            -
                    subject. | 
| 943 | 
            +
                    allow(context).to receive(:goodbyes).and_return([g.new('goodbye'), g.new('Goodbye'), g.new('GOODBYE')])
         | 
| 944 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 945 | 
            +
                    expect(subject).to eq "0. goodbye! 1. Goodbye! 2. GOODBYE! last cruel world!"
         | 
| 920 946 | 
             
                  end
         | 
| 921 947 | 
             
                end
         | 
| 922 948 |  | 
| @@ -925,9 +951,61 @@ describe FlavourSaver do | |
| 925 951 |  | 
| 926 952 | 
             
                  example 'the first variable is used' do
         | 
| 927 953 | 
             
                    g = Struct.new(:text)
         | 
| 928 | 
            -
                    context. | 
| 929 | 
            -
                    context. | 
| 930 | 
            -
                    subject. | 
| 954 | 
            +
                    allow(context).to receive(:goodbyes).and_return([g.new('goodbye'), g.new('Goodbye'), g.new('GOODBYE')])
         | 
| 955 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 956 | 
            +
                    expect(subject).to eq "0. goodbye first! 1. Goodbye ! 2. GOODBYE ! cruel world!"
         | 
| 957 | 
            +
                  end
         | 
| 958 | 
            +
                end
         | 
| 959 | 
            +
             | 
| 960 | 
            +
                describe 'each with @root' do
         | 
| 961 | 
            +
                  let(:template) { "{{#each goodbyes}}{{@index}}. {{text}} cruel {{@root.place}}! {{/each}}" }
         | 
| 962 | 
            +
             | 
| 963 | 
            +
                  example 'the root variable is used' do
         | 
| 964 | 
            +
                    g = Struct.new(:text)
         | 
| 965 | 
            +
                    allow(context).to receive(:goodbyes).and_return([g.new('goodbye'), g.new('Goodbye'), g.new('GOODBYE')])
         | 
| 966 | 
            +
                    allow(context).to receive(:place).and_return('world')
         | 
| 967 | 
            +
                    expect(subject).to eq "0. goodbye cruel world! 1. Goodbye cruel world! 2. GOODBYE cruel world! "
         | 
| 968 | 
            +
                  end
         | 
| 969 | 
            +
                end
         | 
| 970 | 
            +
             | 
| 971 | 
            +
                describe 'each with @root in a nested block' do
         | 
| 972 | 
            +
                  let(:template) { "{{#each goodbyes}}{{@index}}. {{text}}{{#if @last}} cruel {{@root.place}}{{/if}}! {{/each}}" }
         | 
| 973 | 
            +
             | 
| 974 | 
            +
                  example 'the root variable is used' do
         | 
| 975 | 
            +
                    g = Struct.new(:text)
         | 
| 976 | 
            +
                    allow(context).to receive(:goodbyes).and_return([g.new('goodbye'), g.new('Goodbye'), g.new('GOODBYE')])
         | 
| 977 | 
            +
                    allow(context).to receive(:place).and_return('world')
         | 
| 978 | 
            +
                    expect(subject).to eq "0. goodbye! 1. Goodbye! 2. GOODBYE cruel world! "
         | 
| 979 | 
            +
                  end
         | 
| 980 | 
            +
                end
         | 
| 981 | 
            +
             | 
| 982 | 
            +
                describe 'each with @key' do
         | 
| 983 | 
            +
                  let(:template) { "{{#each goodbyes}}{{@key}}. {{text}}! {{/each}}cruel {{world}}!" }
         | 
| 984 | 
            +
             | 
| 985 | 
            +
                  example 'the @key variable is used' do
         | 
| 986 | 
            +
                    g = Struct.new(:text)
         | 
| 987 | 
            +
                    allow(context).to receive(:goodbyes).and_return({
         | 
| 988 | 
            +
                      one: g.new('goodbye'),
         | 
| 989 | 
            +
                      two: g.new('Goodbye'),
         | 
| 990 | 
            +
                      three: g.new('GOODBYE')
         | 
| 991 | 
            +
                    })
         | 
| 992 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 993 | 
            +
                    expect(subject).to eq "one. goodbye! two. Goodbye! three. GOODBYE! cruel world!"
         | 
| 994 | 
            +
                  end
         | 
| 995 | 
            +
                end
         | 
| 996 | 
            +
             | 
| 997 | 
            +
                describe 'each with @key in a nested block' do
         | 
| 998 | 
            +
                  let(:template) { "{{#each goodbyes}}{{#if @last}}{{@key}}. {{/if}}{{text}}! {{/each}}cruel {{world}}!" }
         | 
| 999 | 
            +
             | 
| 1000 | 
            +
                  example 'the @key variable is used' do
         | 
| 1001 | 
            +
                    g = Struct.new(:text)
         | 
| 1002 | 
            +
                    allow(context).to receive(:goodbyes).and_return({
         | 
| 1003 | 
            +
                      one: g.new('goodbye'),
         | 
| 1004 | 
            +
                      two: g.new('Goodbye'),
         | 
| 1005 | 
            +
                      three: g.new('GOODBYE')
         | 
| 1006 | 
            +
                    })
         | 
| 1007 | 
            +
                    allow(context).to receive(:world).and_return('world')
         | 
| 1008 | 
            +
                    expect(subject).to eq "goodbye! Goodbye! three. GOODBYE! cruel world!"
         | 
| 931 1009 | 
             
                  end
         | 
| 932 1010 | 
             
                end
         | 
| 933 1011 |  | 
| @@ -937,9 +1015,9 @@ describe FlavourSaver do | |
| 937 1015 | 
             
                  before { FS.logger = log }
         | 
| 938 1016 | 
             
                  after  { FS.logger = nil }
         | 
| 939 1017 | 
             
                  example do
         | 
| 940 | 
            -
                    context. | 
| 941 | 
            -
                    log. | 
| 942 | 
            -
                    subject. | 
| 1018 | 
            +
                    allow(context).to receive(:blah).and_return('whee')
         | 
| 1019 | 
            +
                    expect(log).to receive(:debug).with('FlavourSaver: whee')
         | 
| 1020 | 
            +
                    expect(subject).to eq ''
         | 
| 943 1021 | 
             
                  end
         | 
| 944 1022 | 
             
                end
         | 
| 945 1023 | 
             
              end
         |