curly-templates 2.3.1 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cdd7bc20cc76f95d2375221dcd42a0b195df7757
4
- data.tar.gz: 3ad84f498e084560f579bbe91fde2684bbb7c53b
3
+ metadata.gz: d5d6cde1c07741229dc8ea78114e54af3f8203c1
4
+ data.tar.gz: c06295601f10d2b265334ef2e3a67255fd00b3f6
5
5
  SHA512:
6
- metadata.gz: 3998fc0caa17d607e4a13a3adc5bc17da44c6d8530d5c1910b273f16fca3ede99e352f2ddc44c318bda5040fa9a4f2b92eebb806f600b47679f937dcdd28c0f0
7
- data.tar.gz: 126b53d760f5b3c10e99e16b219b7f76f9f842bbc289d4b9e4848d716fc5ba038796bc7f0bbffaa1af17a325fa8dfe8841855187675261b2136a2e44bc58f034
6
+ metadata.gz: bff53c1b1165f5fbbf2882a172ac47b274bae2b9a635c757870b226e0087ebaeab035b856c55c33cde288d74999d9d5d5dd034d272faecaba8eb0b5319a2b30c
7
+ data.tar.gz: 3907be2a2506af3b65c0d2cdb787b83472f2b35d60f3dcef649fb1234585d9eca08714875b7ab975c9bacd16ec17f7aabf80a1e795b57e75626d0b511d2ed0a6
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  ### Unreleased
2
2
 
3
+ ### Curly 2.3.2 (January 13, 2015)
4
+
5
+ * Fix an issue that caused presenter parameters to get mixed up.
6
+
7
+ *Cristian Planas*
8
+
9
+ * Clean up the testing code.
10
+
11
+ *Daniel Schierbeck*
12
+
3
13
  ### Curly 2.3.1 (January 7, 2015)
4
14
 
5
15
  * Fix an issue with nested context blocks.
data/Gemfile CHANGED
@@ -7,7 +7,6 @@ platform :ruby do
7
7
  gem 'yard-tomdoc'
8
8
  gem 'redcarpet'
9
9
  gem 'github-markup'
10
- gem 'coveralls', require: false
11
10
  gem 'rails', '~> 4.2.0', require: false
12
11
  gem 'rspec-rails', require: false
13
12
  end
@@ -4,8 +4,8 @@ Gem::Specification.new do |s|
4
4
  s.rubygems_version = '1.3.5'
5
5
 
6
6
  s.name = 'curly-templates'
7
- s.version = '2.3.1'
8
- s.date = '2015-01-07'
7
+ s.version = '2.3.2'
8
+ s.date = '2015-01-13'
9
9
 
10
10
  s.summary = "Free your views!"
11
11
  s.description = "A view layer for your Rails apps that separates structure and logic."
data/lib/curly.rb CHANGED
@@ -25,7 +25,7 @@
25
25
  #
26
26
  # See Curly::Presenter for more information on presenters.
27
27
  module Curly
28
- VERSION = "2.3.1"
28
+ VERSION = "2.3.2"
29
29
 
30
30
  # Compiles a Curly template to Ruby code.
31
31
  #
@@ -67,6 +67,7 @@ module Curly
67
67
  buffer = ActiveSupport::SafeBuffer.new
68
68
  buffers = []
69
69
  presenters = []
70
+ options_stack = []
70
71
  #{@parts.join("\n")}
71
72
  buffer
72
73
  RUBY
@@ -102,6 +103,7 @@ module Curly
102
103
 
103
104
  output <<-RUBY
104
105
  presenters << presenter
106
+ options_stack << options
105
107
  items = Array(#{method_call})
106
108
  items.each_with_index do |item, index|
107
109
  options = options.merge("#{name}" => item, "#{counter}" => index + 1)
@@ -114,6 +116,7 @@ module Curly
114
116
 
115
117
  output <<-RUBY
116
118
  end
119
+ options = options_stack.pop
117
120
  presenter = presenters.pop
118
121
  RUBY
119
122
  end
@@ -151,6 +154,7 @@ module Curly
151
154
  end
152
155
 
153
156
  output <<-RUBY
157
+ options_stack << options
154
158
  presenters << presenter
155
159
  buffers << buffer
156
160
  buffer << #{method_call} do |item|
@@ -168,6 +172,7 @@ module Curly
168
172
  end
169
173
  buffer = buffers.pop
170
174
  presenter = presenters.pop
175
+ options = options_stack.pop
171
176
  RUBY
172
177
  end
173
178
 
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe Curly::AttributeScanner do
4
2
  it "scans attributes" do
5
3
  scan("width=10px height=20px").should == {
@@ -1,10 +1,8 @@
1
- require 'spec_helper'
2
-
3
1
  describe "Collection block components" do
4
- include RenderingSupport
2
+ include CompilationSupport
5
3
 
6
4
  before do
7
- item_presenter do
5
+ define_presenter "ItemPresenter" do
8
6
  presents :item
9
7
 
10
8
  def name
@@ -14,7 +12,7 @@ describe "Collection block components" do
14
12
  end
15
13
 
16
14
  example "with neither identifier nor attributes" do
17
- presenter do
15
+ define_presenter do
18
16
  def items
19
17
  ["one", "two", "three"]
20
18
  end
@@ -24,7 +22,7 @@ describe "Collection block components" do
24
22
  end
25
23
 
26
24
  example "with an identifier" do
27
- presenter do
25
+ define_presenter do
28
26
  def items(filter = nil)
29
27
  if filter == "even"
30
28
  ["two"]
@@ -42,7 +40,7 @@ describe "Collection block components" do
42
40
  end
43
41
 
44
42
  example "with attributes" do
45
- presenter do
43
+ define_presenter do
46
44
  def items(length: "1")
47
45
  ["x"] * length.to_i
48
46
  end
@@ -53,13 +51,13 @@ describe "Collection block components" do
53
51
  end
54
52
 
55
53
  example "with nested collection blocks" do
56
- presenter do
54
+ define_presenter do
57
55
  def items
58
56
  [{ parts: [1, 2] }, { parts: [3, 4] }]
59
57
  end
60
58
  end
61
59
 
62
- item_presenter do
60
+ define_presenter "ItemPresenter" do
63
61
  presents :item
64
62
 
65
63
  def parts
@@ -67,7 +65,7 @@ describe "Collection block components" do
67
65
  end
68
66
  end
69
67
 
70
- part_presenter do
68
+ define_presenter "PartPresenter" do
71
69
  presents :part
72
70
 
73
71
  def number
@@ -77,12 +75,4 @@ describe "Collection block components" do
77
75
 
78
76
  render("{{*items}}<{{*parts}}[{{number}}]{{/parts}}>{{/items}}").should == "<[1][2]><[3][4]>"
79
77
  end
80
-
81
- def item_presenter(&block)
82
- stub_const("ItemPresenter", Class.new(Curly::Presenter, &block))
83
- end
84
-
85
- def part_presenter(&block)
86
- stub_const("ItemPresenter::PartPresenter", Class.new(Curly::Presenter, &block))
87
- end
88
78
  end
@@ -1,153 +1,202 @@
1
- require 'spec_helper'
2
-
3
1
  describe Curly::Compiler do
4
2
  include CompilationSupport
5
3
 
6
- let(:presenter_class) do
7
- Class.new(Curly::Presenter) do
8
- presents :list
9
-
10
- def title
11
- @list.title
4
+ context "normal rendering" do
5
+ before do
6
+ define_presenter "ItemPresenter" do
7
+ presents :item
8
+ delegate :name, to: :@item
12
9
  end
10
+ end
13
11
 
14
- def items(status: nil)
15
- if status
16
- @list.items.select {|item| item.status == status }
17
- else
18
- @list.items
19
- end
12
+ it "compiles collection blocks" do
13
+ define_presenter do
14
+ presents :items
15
+ attr_reader :items
20
16
  end
21
17
 
22
- def companies
23
- "Nike, Adidas"
24
- end
18
+ item1 = double("item1", name: "foo")
19
+ item2 = double("item2", name: "bar")
25
20
 
26
- def numbers
27
- "one, two, three"
28
- end
21
+ template = "<ul>{{*items}}<li>{{name}}</li>{{/items}}</ul>"
22
+ expect(render(template, items: [item1, item2])).to eql "<ul><li>foo</li><li>bar</li></ul>"
29
23
  end
30
- end
31
24
 
32
- let(:simple_presenter_class) do
33
- Class.new(Curly::Presenter) do
34
- presents :company
25
+ it "allows attributes on collection blocks" do
26
+ define_presenter do
27
+ presents :items
35
28
 
36
- def name
37
- @company
29
+ def items(status: nil)
30
+ if status
31
+ @items.select {|item| item.status == status }
32
+ else
33
+ @items
34
+ end
35
+ end
38
36
  end
39
- end
40
- end
41
37
 
42
- let(:inner_presenter_class) do
43
- Class.new(Curly::Presenter) do
44
- presents :item, :item_counter
45
- presents :list, default: nil
38
+ item1 = double("item1", name: "foo", status: "active")
39
+ item2 = double("item2", name: "bar", status: "inactive")
46
40
 
47
- attr_reader :item_counter
41
+ template = "<ul>{{*items status=active}}<li>{{name}}</li>{{/items}}</ul>"
42
+ expect(render(template, items: [item1, item2])).to eql "<ul><li>foo</li></ul>"
43
+ end
48
44
 
49
- def name
50
- @item.name
51
- end
45
+ it "fails if the component doesn't support enumeration" do
46
+ template = "<ul>{{*numbers}}<li>{{name}}</li>{{/numbers}}</ul>"
47
+ expect { render(template) }.to raise_exception(Curly::Error)
48
+ end
52
49
 
53
- def list_title
54
- @list.title
50
+ it "works even if the component method doesn't return an Array" do
51
+ define_presenter do
52
+ def companies
53
+ "Arla"
54
+ end
55
55
  end
56
56
 
57
- def parts
58
- @item.parts
57
+ define_presenter "CompanyPresenter" do
58
+ presents :company
59
+
60
+ def name
61
+ @company
62
+ end
59
63
  end
64
+
65
+ template = "<ul>{{*companies}}<li>{{name}}</li>{{/companies}}</ul>"
66
+ expect(render(template)).to eql "<ul><li>Arla</li></ul>"
60
67
  end
61
- end
62
68
 
63
- let(:inner_inner_presenter_class) do
64
- Class.new(Curly::Presenter) do
65
- presents :part
69
+ it "passes the index of the current item to the nested presenter" do
70
+ define_presenter do
71
+ presents :items
72
+ attr_reader :items
73
+ end
74
+
75
+ define_presenter "ItemPresenter" do
76
+ presents :item_counter
66
77
 
67
- def identifier
68
- @part.identifier
78
+ def index
79
+ @item_counter
80
+ end
69
81
  end
82
+
83
+ item1 = double("item1")
84
+ item2 = double("item2")
85
+
86
+ template = "<ul>{{*items}}<li>{{index}}</li>{{/items}}</ul>"
87
+ expect(render(template, items: [item1, item2])).to eql "<ul><li>1</li><li>2</li></ul>"
70
88
  end
71
- end
72
89
 
73
- let(:list) { double("list", title: "Inventory") }
74
- let(:context) { double("context") }
75
- let(:presenter) { presenter_class.new(context, "list" => list) }
90
+ it "restores the previous scope after exiting the collection block" do
91
+ define_presenter do
92
+ presents :items
93
+ attr_reader :items
76
94
 
77
- before do
78
- stub_const("ItemPresenter", inner_presenter_class)
79
- stub_const("PartPresenter", inner_inner_presenter_class)
80
- end
95
+ def title
96
+ "Inventory"
97
+ end
98
+ end
99
+
100
+ define_presenter "ItemPresenter" do
101
+ presents :item
102
+ delegate :name, :parts, to: :@item
103
+ end
81
104
 
82
- it "compiles collection blocks" do
83
- item1 = double("item1", name: "foo")
84
- item2 = double("item2", name: "bar")
105
+ define_presenter "PartPresenter" do
106
+ presents :part
107
+ delegate :identifier, to: :@part
108
+ end
85
109
 
86
- list.stub(:items) { [item1, item2] }
110
+ part = double("part", identifier: "X")
111
+ item = double("item", name: "foo", parts: [part])
87
112
 
88
- template = "<ul>{{*items}}<li>{{name}}</li>{{/items}}</ul>"
89
- expect(evaluate(template)).to eql "<ul><li>foo</li><li>bar</li></ul>"
90
- end
113
+ template = "{{*items}}{{*parts}}{{identifier}}{{/parts}}{{name}}{{/items}}{{title}}"
114
+ expect(render(template, items: [item])).to eql "XfooInventory"
115
+ end
91
116
 
92
- it "allows attributes on collection blocks" do
93
- item1 = double("item1", name: "foo", status: "active")
94
- item2 = double("item2", name: "bar", status: "inactive")
117
+ it "passes the parent presenter's options to the nested presenter" do
118
+ define_presenter do
119
+ presents :items, :prefix
120
+ attr_reader :items
121
+ end
95
122
 
96
- list.stub(:items) { [item1, item2] }
123
+ define_presenter "ItemPresenter" do
124
+ presents :item, :prefix
125
+ delegate :name, to: :@item
126
+ attr_reader :prefix
127
+ end
97
128
 
98
- template = "<ul>{{*items status=active}}<li>{{name}}</li>{{/items}}</ul>"
99
- expect(evaluate(template)).to eql "<ul><li>foo</li></ul>"
100
- end
129
+ item1 = double(name: "foo")
130
+ item2 = double(name: "bar")
101
131
 
102
- it "fails if the component isn't available" do
103
- template = "<ul>{{*doodads}}<li>{{name}}</li>{{/doodads}}</ul>"
104
- expect { evaluate(template) }.to raise_exception(Curly::Error)
105
- end
132
+ template = "{{*items}}{{prefix}}: {{name}}; {{/items}}"
133
+ expect(render(template, prefix: "SKU", items: [item1, item2])).to eql "SKU: foo; SKU: bar; "
134
+ end
106
135
 
107
- it "fails if the component doesn't support enumeration" do
108
- template = "<ul>{{*numbers}}<li>{{name}}</li>{{/numbers}}</ul>"
109
- expect { evaluate(template) }.to raise_exception(Curly::Error)
110
- end
136
+ it "compiles nested collection blocks" do
137
+ define_presenter do
138
+ presents :items
139
+ attr_reader :items
140
+ end
111
141
 
112
- it "works even if the component method doesn't return an Array" do
113
- stub_const("CompanyPresenter", simple_presenter_class)
114
- template = "<ul>{{*companies}}<li>{{name}}</li>{{/companies}}</ul>"
115
- expect(evaluate(template)).to eql "<ul><li>Nike, Adidas</li></ul>"
116
- end
142
+ define_presenter "ItemPresenter" do
143
+ presents :item
144
+ delegate :name, :parts, to: :@item
145
+ end
117
146
 
118
- it "passes the index of the current item to the nested presenter" do
119
- item1 = double("item1")
120
- item2 = double("item2")
147
+ define_presenter "PartPresenter" do
148
+ presents :part
149
+ delegate :identifier, to: :@part
150
+ end
121
151
 
122
- list.stub(:items) { [item1, item2] }
152
+ item1 = double("item1", name: "item1", parts: [double(identifier: "A"), double(identifier: "B")])
153
+ item2 = double("item2", name: "item2", parts: [double(identifier: "C"), double(identifier: "D")])
123
154
 
124
- template = "<ul>{{*items}}<li>{{item_counter}}</li>{{/items}}</ul>"
125
- expect(evaluate(template)).to eql "<ul><li>1</li><li>2</li></ul>"
155
+ template = "{{*items}}{{name}}: {{*parts}}{{identifier}}{{/parts}}; {{/items}}"
156
+ expect(render(template, items: [item1, item2])).to eql "item1: AB; item2: CD; "
157
+ end
126
158
  end
127
159
 
128
- it "restores the previous scope after exiting the collection block" do
129
- part = double("part", identifier: "X")
130
- item = double("item", name: "foo", parts: [part])
131
- list.stub(:items) { [item] }
160
+ context "re-using assign names" do
161
+ before do
162
+ define_presenter do
163
+ presents :comment
132
164
 
133
- template = "{{*items}}{{*parts}}{{identifier}}{{/parts}}{{name}}{{/items}}{{title}}"
134
- expect(evaluate(template)).to eql "XfooInventory"
135
- end
165
+ attr_reader :comment
136
166
 
137
- it "passes the parent presenter's options to the nested presenter" do
138
- list.stub(:items) { [double(name: "foo"), double(name: "bar")] }
167
+ def comments
168
+ ["yolo", "xoxo"]
169
+ end
139
170
 
140
- template = "{{*items}}{{list_title}}: {{name}}. {{/items}}"
141
- expect(evaluate(template, list: list)).to eql "Inventory: foo. Inventory: bar. "
142
- end
171
+ def comment(&block)
172
+ block.call("viagra!")
173
+ end
174
+
175
+ def form(&block)
176
+ block.call
177
+ end
178
+ end
143
179
 
144
- it "compiles nested collection blocks" do
145
- item1 = double("item1", name: "item1", parts: [double(identifier: "A"), double(identifier: "B")])
146
- item2 = double("item2", name: "item2", parts: [double(identifier: "C"), double(identifier: "D")])
180
+ define_presenter "CommentPresenter" do
181
+ presents :comment
182
+ end
147
183
 
148
- list.stub(:items) { [item1, item2] }
184
+ define_presenter "FormPresenter" do
185
+ presents :comment
186
+ attr_reader :comment
187
+ end
188
+ end
149
189
 
150
- template = "{{title}}: {{*items}}{{name}} - {{*parts}}{{identifier}}{{/parts}}. {{/items}}"
151
- expect(evaluate(template)).to eql "Inventory: item1 - AB. item2 - CD. "
190
+ it "allows re-using assign names in collection blocks" do
191
+ options = { "comment" => "first post!" }
192
+ template = "{{*comments}}{{/comments}}{{@form}}{{comment}}{{/form}}"
193
+ expect(render(template, options)).to eql "first post!"
194
+ end
195
+
196
+ it "allows re-using assign names in context blocks" do
197
+ options = { "comment" => "first post!" }
198
+ template = "{{@comment}}{{/comment}}{{@form}}{{comment}}{{/form}}"
199
+ expect(render(template, options)).to eql "first post!"
200
+ end
152
201
  end
153
202
  end
@@ -1,53 +1,51 @@
1
- require 'spec_helper'
2
-
3
1
  describe Curly::Compiler do
4
2
  include CompilationSupport
5
3
 
6
- let(:presenter_class) do
7
- Class.new(Curly::Presenter) do
4
+ it "compiles context blocks" do
5
+ define_presenter do
8
6
  def form(&block)
9
7
  "<form>".html_safe + block.call("yo") + "</form>".html_safe
10
8
  end
11
-
12
- def invalid
13
- "uh oh!"
14
- end
15
9
  end
16
- end
17
10
 
18
- let(:context_presenter_class) do
19
- Class.new(Curly::Presenter) do
11
+ define_presenter "FormPresenter" do
20
12
  presents :form
21
13
 
22
14
  def text_field(&block)
23
15
  block.call(@form)
24
16
  end
25
17
  end
26
- end
27
18
 
28
- let(:inner_context_presenter_class) do
29
- Class.new(Curly::Presenter) do
19
+ define_presenter "TextFieldPresenter" do
30
20
  presents :text_field
31
21
 
32
22
  def field
33
23
  %(<input type="text" value="#{@text_field.upcase}">).html_safe
34
24
  end
35
25
  end
26
+
27
+ render('{{@form}}{{@text_field}}{{field}}{{/text_field}}{{/form}}').should == '<form><input type="text" value="YO"></form>'
36
28
  end
37
29
 
38
- let(:context) { double("context") }
39
- let(:presenter) { presenter_class.new(context, {}) }
30
+ it "fails if the component is not a context block" do
31
+ define_presenter do
32
+ def form
33
+ end
34
+ end
40
35
 
41
- before do
42
- stub_const("FormPresenter", context_presenter_class)
43
- stub_const("TextFieldPresenter", inner_context_presenter_class)
36
+ expect {
37
+ render('{{@form}}{{/form}}')
38
+ }.to raise_exception(Curly::Error)
44
39
  end
45
40
 
46
- it "compiles context blocks" do
47
- evaluate('{{@form}}{{@text_field}}{{field}}{{/text_field}}{{/form}}').should == '<form><input type="text" value="YO"></form>'
48
- end
41
+ it "fails if the component doesn't match a presenter class" do
42
+ define_presenter do
43
+ def dust(&block)
44
+ end
45
+ end
49
46
 
50
- it "fails if the component is not a context block" do
51
- expect { evaluate('{{@invalid}}yo{{/invalid}}') }.to raise_exception(Curly::Error)
47
+ expect {
48
+ render('{{@dust}}{{/dust}}')
49
+ }.to raise_exception(Curly::Error)
52
50
  end
53
51
  end
@@ -1,69 +1,7 @@
1
- require 'spec_helper'
2
-
3
1
  describe Curly::Compiler do
4
2
  include CompilationSupport
5
3
 
6
- let :presenter_class do
7
- Class.new do
8
- def foo
9
- "FOO"
10
- end
11
-
12
- def high_yield
13
- "#{yield}, motherfucker!"
14
- end
15
-
16
- def yield_value
17
- "#{yield :foo}, please?"
18
- end
19
-
20
- def hello?(value)
21
- value == "world"
22
- end
23
-
24
- def unicorns
25
- "UNICORN"
26
- end
27
-
28
- def dirty
29
- nil
30
- end
31
-
32
- def square?(width:, height:)
33
- width.to_i == height.to_i
34
- end
35
-
36
- def false?
37
- false
38
- end
39
-
40
- def true?
41
- true
42
- end
43
-
44
- def self.component_available?(method)
45
- %w[foo high_yield yield_value dirty false? true? hello? square?].include?(method)
46
- end
47
-
48
- def self.available_components
49
- public_instance_methods
50
- end
51
-
52
- private
53
-
54
- def method_missing(*args)
55
- "BAR"
56
- end
57
- end
58
- end
59
-
60
- let(:presenter) { presenter_class.new }
61
-
62
4
  describe ".compile" do
63
- it "compiles Curly templates to Ruby code" do
64
- evaluate("{{foo}}").should == "FOO"
65
- end
66
-
67
5
  it "raises ArgumentError if the presenter class is nil" do
68
6
  expect do
69
7
  Curly::Compiler.compile("foo", nil)
@@ -71,12 +9,12 @@ describe Curly::Compiler do
71
9
  end
72
10
 
73
11
  it "makes sure only public methods are called on the presenter object" do
74
- expect { evaluate("{{bar}}") }.to raise_exception(Curly::InvalidComponent)
12
+ expect { render("{{bar}}") }.to raise_exception(Curly::InvalidComponent)
75
13
  end
76
14
 
77
15
  it "includes the invalid component when failing to compile" do
78
16
  begin
79
- evaluate("{{bar}}")
17
+ render("{{bar}}")
80
18
  fail
81
19
  rescue Curly::InvalidComponent => e
82
20
  e.component.should == "bar"
@@ -84,107 +22,171 @@ describe Curly::Compiler do
84
22
  end
85
23
 
86
24
  it "propagates yields to the caller" do
87
- evaluate("{{high_yield}}") { "$$$" }.should == "$$$, motherfucker!"
25
+ define_presenter do
26
+ def i_want
27
+ "I want #{yield}!"
28
+ end
29
+ end
30
+
31
+ render("{{i_want}}") { "$$$" }.should == "I want $$$!"
88
32
  end
89
33
 
90
34
  it "sends along arguments passed to yield" do
91
- evaluate("{{yield_value}}") {|v| v.upcase }.should == "FOO, please?"
35
+ define_presenter do
36
+ def hello(&block)
37
+ "Hello, #{block.call('world')}!"
38
+ end
39
+ end
40
+
41
+ render("{{hello}}") {|v| v.upcase }.should == "Hello, WORLD!"
92
42
  end
93
43
 
94
44
  it "escapes non HTML safe strings returned from the presenter" do
95
- presenter.stub(:dirty) { "<p>dirty</p>" }
96
- evaluate("{{dirty}}").should == "&lt;p&gt;dirty&lt;/p&gt;"
45
+ define_presenter do
46
+ def dirty
47
+ "<p>dirty</p>"
48
+ end
49
+ end
50
+
51
+ render("{{dirty}}").should == "&lt;p&gt;dirty&lt;/p&gt;"
97
52
  end
98
53
 
99
54
  it "does not escape HTML safe strings returned from the presenter" do
100
- presenter.stub(:dirty) { "<p>dirty</p>".html_safe }
101
- evaluate("{{dirty}}").should == "<p>dirty</p>"
55
+ define_presenter do
56
+ def dirty
57
+ "<p>dirty</p>".html_safe
58
+ end
59
+ end
60
+
61
+ render("{{dirty}}").should == "<p>dirty</p>"
102
62
  end
103
63
 
104
64
  it "does not escape HTML in the template itself" do
105
- evaluate("<div>").should == "<div>"
65
+ render("<div>").should == "<div>"
106
66
  end
107
67
 
108
68
  it "treats all values returned from the presenter as strings" do
109
- presenter.stub(:foo) { 42 }
110
- evaluate("{{foo}}").should == "42"
69
+ define_presenter do
70
+ def foo; 42; end
71
+ end
72
+
73
+ render("{{foo}}").should == "42"
111
74
  end
112
75
 
113
76
  it "removes comments from the output" do
114
- evaluate("HELO{{! I'm a comment, yo }}WORLD").should == "HELOWORLD"
77
+ render("hello{{! I'm a comment, yo }}world").should == "helloworld"
115
78
  end
116
79
 
117
80
  it "removes text in false blocks" do
118
- evaluate("test{{#false?}}bar{{/false?}}").should == "test"
81
+ define_presenter do
82
+ def false?
83
+ false
84
+ end
85
+ end
86
+
87
+ render("{{#false?}}wut{{/false?}}").should == ""
119
88
  end
120
89
 
121
90
  it "keeps text in true blocks" do
122
- evaluate("test{{#true?}}bar{{/true?}}").should == "testbar"
91
+ define_presenter do
92
+ def true?
93
+ true
94
+ end
95
+ end
96
+
97
+ render("{{#true?}}yello{{/true?}}").should == "yello"
123
98
  end
124
99
 
125
100
  it "removes text in inverse true blocks" do
126
- evaluate("test{{^true?}}bar{{/true?}}").should == "test"
101
+ define_presenter do
102
+ def true?
103
+ true
104
+ end
105
+ end
106
+
107
+ render("{{^true?}}bar{{/true?}}").should == ""
127
108
  end
128
109
 
129
- it "keeps kext in inverse false blocks" do
130
- evaluate("test{{^false?}}bar{{/false?}}").should == "testbar"
110
+ it "keeps text in inverse false blocks" do
111
+ define_presenter do
112
+ def false?
113
+ false
114
+ end
115
+ end
116
+
117
+ render("{{^false?}}yeah!{{/false?}}").should == "yeah!"
131
118
  end
132
119
 
133
120
  it "passes an argument to blocks" do
134
- evaluate("{{#hello.world?}}foo{{/hello.world?}}{{#hello.foo?}}bar{{/hello.foo?}}").should == "foo"
121
+ define_presenter do
122
+ def hello?(value)
123
+ value == "world"
124
+ end
125
+ end
126
+
127
+ render("{{#hello.world?}}foo{{/hello.world?}}").should == "foo"
128
+ render("{{#hello.mars?}}bar{{/hello.mars?}}").should == ""
135
129
  end
136
130
 
137
131
  it "passes attributes to blocks" do
138
- evaluate("{{#square? width=2 height=2}}yeah!{{/square?}}").should == "yeah!"
139
- end
132
+ define_presenter do
133
+ def square?(width:, height:)
134
+ width.to_i == height.to_i
135
+ end
136
+ end
140
137
 
141
- it "gives an error on mismatching blocks" do
142
- expect do
143
- evaluate("test{{#false?}}bar{{/true?}}")
144
- end.to raise_exception(Curly::IncorrectEndingError)
138
+ render("{{#square? width=2 height=2}}yeah!{{/square?}}").should == "yeah!"
145
139
  end
146
140
 
147
141
  it "gives an error on incomplete blocks" do
148
142
  expect do
149
- evaluate("test{{#false?}}bar")
143
+ render("{{#hello?}}")
150
144
  end.to raise_exception(Curly::IncompleteBlockError)
151
145
  end
152
146
 
147
+ it "gives an error when closing unopened blocks" do
148
+ expect do
149
+ render("{{/goodbye?}}")
150
+ end.to raise_exception(Curly::IncorrectEndingError)
151
+ end
152
+
153
153
  it "gives an error on mismatching block ends" do
154
154
  expect do
155
- evaluate("{{#true?}}test{{#false?}}bar{{/true?}}{{/false?}}")
155
+ render("{{#x?}}{{#y?}}{{/x?}}{{/y?}}")
156
156
  end.to raise_exception(Curly::IncorrectEndingError)
157
157
  end
158
158
 
159
159
  it "does not execute arbitrary Ruby code" do
160
- evaluate('#{foo}').should == '#{foo}'
160
+ render('#{foo}').should == '#{foo}'
161
161
  end
162
162
  end
163
163
 
164
164
  describe ".valid?" do
165
165
  it "returns true if only available methods are referenced" do
166
+ define_presenter do
167
+ def foo; end
168
+ end
169
+
166
170
  validate("Hello, {{foo}}!").should == true
167
171
  end
168
172
 
169
173
  it "returns false if a missing method is referenced" do
174
+ define_presenter
170
175
  validate("Hello, {{i_am_missing}}").should == false
171
176
  end
172
177
 
173
178
  it "returns false if an unavailable method is referenced" do
174
- presenter_class.stub(:available_components) { [:foo] }
175
- validate("Hello, {{inspect}}").should == false
176
- end
177
-
178
- it "returns true with a block" do
179
- validate("Hello {{#true?}}world{{/true?}}").should == true
180
- end
179
+ define_presenter do
180
+ def self.available_components
181
+ []
182
+ end
183
+ end
181
184
 
182
- it "returns false with an incomplete block" do
183
- validate("Hello {{#true?}}world").should == false
185
+ validate("Hello, {{inspect}}").should == false
184
186
  end
185
187
 
186
188
  def validate(template)
187
- Curly.valid?(template, presenter_class)
189
+ Curly.valid?(template, ShowPresenter)
188
190
  end
189
191
  end
190
192
  end
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe Curly::ComponentCompiler do
4
2
  describe ".compile" do
5
3
  let(:presenter_class) do
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe Curly::ComponentScanner do
4
2
  it "scans the component name, identifier, and attributes" do
5
3
  scan('hello.world weather="sunny"').should == [
@@ -1,10 +1,8 @@
1
- require 'spec_helper'
2
-
3
1
  describe "Components" do
4
- include RenderingSupport
2
+ include CompilationSupport
5
3
 
6
4
  example "with neither identifier nor attributes" do
7
- presenter do
5
+ define_presenter do
8
6
  def title
9
7
  "A Clockwork Orange"
10
8
  end
@@ -14,7 +12,7 @@ describe "Components" do
14
12
  end
15
13
 
16
14
  example "with an identifier" do
17
- presenter do
15
+ define_presenter do
18
16
  def reverse(str)
19
17
  str.reverse
20
18
  end
@@ -24,7 +22,7 @@ describe "Components" do
24
22
  end
25
23
 
26
24
  example "with attributes" do
27
- presenter do
25
+ define_presenter do
28
26
  def double(number:)
29
27
  number.to_i * 2
30
28
  end
@@ -34,7 +32,7 @@ describe "Components" do
34
32
  end
35
33
 
36
34
  example "with both identifier and attributes" do
37
- presenter do
35
+ define_presenter do
38
36
  def a(href:, title:)
39
37
  content_tag :a, nil, href: href, title: title
40
38
  end
@@ -1,10 +1,8 @@
1
- require 'spec_helper'
2
-
3
1
  describe "Conditional block components" do
4
- include RenderingSupport
2
+ include CompilationSupport
5
3
 
6
4
  example "with neither identifier nor attributes" do
7
- presenter do
5
+ define_presenter do
8
6
  def high?
9
7
  true
10
8
  end
@@ -19,7 +17,7 @@ describe "Conditional block components" do
19
17
  end
20
18
 
21
19
  example "with an identifier" do
22
- presenter do
20
+ define_presenter do
23
21
  def even?(number)
24
22
  number.to_i % 2 == 0
25
23
  end
@@ -30,7 +28,7 @@ describe "Conditional block components" do
30
28
  end
31
29
 
32
30
  example "with attributes" do
33
- presenter do
31
+ define_presenter do
34
32
  def square?(width:, height:)
35
33
  width.to_i == height.to_i
36
34
  end
@@ -13,7 +13,7 @@ Rails.application.configure do
13
13
  config.eager_load = false
14
14
 
15
15
  # Configure static asset server for tests with Cache-Control for performance.
16
- config.serve_static_assets = true
16
+ config.serve_static_files = true
17
17
  config.static_cache_control = 'public, max-age=3600'
18
18
 
19
19
  # Show full error reports and disable caching.
@@ -1,4 +1,3 @@
1
- require 'spec_helper'
2
1
  require 'genspec'
3
2
  require 'generators/curly/controller/controller_generator'
4
3
 
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe "Using Curly for the application layout", type: :request do
4
2
  example "A simple layout view" do
5
3
  get '/'
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe "Collection blocks", type: :request do
4
2
  example "Rendering collections" do
5
3
  get '/collection'
@@ -1,4 +1,3 @@
1
- require 'spec_helper'
2
1
  require 'matchers/have_structure'
3
2
 
4
3
  describe "Context blocks", type: :request do
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe "Using Curly for Rails partials", type: :request do
4
2
  example "Rendering a partial" do
5
3
  get '/partials'
data/spec/parser_spec.rb CHANGED
@@ -1,6 +1,3 @@
1
- require 'spec_helper'
2
- require 'curly/parser'
3
-
4
1
  describe Curly::Parser do
5
2
  it "parses component tokens" do
6
3
  tokens = [
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe Curly::Presenter do
4
2
  class CircusPresenter < Curly::Presenter
5
3
  module MonkeyComponents
data/spec/scanner_spec.rb CHANGED
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe Curly::Scanner, ".scan" do
4
2
  it "returns the tokens in the source" do
5
3
  scan("foo {{bar}} baz").should == [
data/spec/spec_helper.rb CHANGED
@@ -3,44 +3,36 @@ ENV["RAILS_ENV"] = "test"
3
3
  require 'dummy/config/environment'
4
4
  require 'rspec/rails'
5
5
 
6
- if ENV['CI']
7
- begin
8
- require 'coveralls'
9
- Coveralls.wear!
10
- rescue LoadError
11
- STDERR.puts "Failed to load Coveralls"
12
- end
6
+ RSpec.configure do |config|
7
+ config.infer_spec_type_from_file_location!
13
8
  end
14
9
 
15
- module RenderingSupport
16
- def presenter(&block)
17
- @presenter = block
10
+ module CompilationSupport
11
+ def define_presenter(name = "ShowPresenter", &block)
12
+ presenter_class = Class.new(Curly::Presenter, &block)
13
+ stub_const(name, presenter_class)
14
+ presenter_class
18
15
  end
19
16
 
20
- def render(source)
21
- stub_const("TestPresenter", Class.new(Curly::Presenter, &@presenter))
22
- identifier = "test"
17
+ def render(source, locals = {}, presenter_class = nil, &block)
18
+ if presenter_class.nil?
19
+ unless defined?(ShowPresenter)
20
+ define_presenter("ShowPresenter")
21
+ end
22
+
23
+ presenter_class = ShowPresenter
24
+ end
25
+
26
+ identifier = "show"
23
27
  handler = Curly::TemplateHandler
24
- details = { virtual_path: 'test' }
28
+ details = { virtual_path: 'show' }
25
29
  template = ActionView::Template.new(source, identifier, handler, details)
26
- locals = {}
27
30
  view = ActionView::Base.new
28
31
 
29
- template.render(view, locals)
30
- end
31
- end
32
-
33
- module CompilationSupport
34
- def evaluate(template, options = {}, &block)
35
- code = Curly::Compiler.compile(template, presenter_class)
36
- context = double("context")
37
-
38
- context.instance_eval(<<-RUBY)
39
- def self.render(presenter, options)
40
- #{code}
41
- end
42
- RUBY
43
-
44
- context.render(presenter, options, &block)
32
+ begin
33
+ template.render(view, locals, &block)
34
+ rescue ActionView::Template::Error => e
35
+ raise e.original_exception
36
+ end
45
37
  end
46
38
  end
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe Curly::SyntaxError, "#message" do
4
2
  it "includes the context of the error in the message" do
5
3
  source = "I am a very bad error that has snuck in"
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe Curly::TemplateHandler do
4
2
  let :presenter_class do
5
3
  Class.new do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: curly-templates
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.1
4
+ version: 2.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Schierbeck
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-07 00:00:00.000000000 Z
11
+ date: 2015-01-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack