curly-templates 2.3.1 → 2.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 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