erector 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.txt +14 -0
- data/VERSION.yml +1 -1
- data/bin/erector +9 -4
- data/lib/erector.rb +11 -17
- data/lib/erector/erected.rb +1 -1
- data/lib/erector/externals.rb +19 -16
- data/lib/erector/inline.rb +12 -11
- data/lib/erector/mixin.rb +5 -2
- data/lib/erector/rails.rb +26 -9
- data/lib/erector/rails/extensions/action_controller.rb +2 -14
- data/lib/erector/rails/extensions/rails_widget.rb +65 -25
- data/lib/erector/rails/extensions/rails_widget/rails_helpers.rb +4 -3
- data/lib/erector/rails/template_handlers/ert_handler.rb +1 -1
- data/lib/erector/rails/template_handlers/rb_handler.rb +8 -43
- data/lib/erector/widget.rb +147 -70
- data/lib/erector/widgets.rb +5 -4
- data/lib/erector/widgets/form.rb +30 -0
- data/lib/erector/widgets/page.rb +74 -49
- data/rails/init.rb +4 -0
- data/spec/erect/erect_rails_spec.rb +63 -26
- data/spec/erect/erected_spec.rb +4 -4
- data/spec/erector/external_spec.rb +64 -6
- data/spec/erector/indentation_spec.rb +2 -2
- data/spec/erector/inline_spec.rb +74 -42
- data/spec/erector/mixin_spec.rb +16 -5
- data/spec/erector/widget_spec.rb +184 -7
- data/spec/erector/widgets/form_spec.rb +31 -0
- data/spec/erector/widgets/page_spec.rb +30 -20
- data/spec/spec_suite.rb +4 -3
- metadata +5 -3
- data/lib/erector/rails/extensions/action_view.rb +0 -21
@@ -7,8 +7,8 @@ describe "indentation" do
|
|
7
7
|
widget.instance_eval do
|
8
8
|
@prettyprint = true
|
9
9
|
end
|
10
|
-
widget.newliney
|
11
|
-
widget.newliney
|
10
|
+
widget.send(:newliney?, "i").should == false
|
11
|
+
widget.send(:newliney?, "table").should == true
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should not add newline for non-newliney tags" do
|
data/spec/erector/inline_spec.rb
CHANGED
@@ -1,51 +1,83 @@
|
|
1
1
|
require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
2
|
+
|
3
|
+
describe Erector::Widget do
|
4
|
+
it "provides access to instance variables from the calling context" do
|
5
|
+
@var = "yay"
|
6
|
+
Erector::Widget.new { @var.should == "yay"; @var = "yum" }.to_s
|
7
|
+
@var.should == "yum"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "provides access to bound variables from the calling context" do
|
11
|
+
var = "yay"
|
12
|
+
Erector::Widget.new { var.should == "yay"; var = "yum" }.to_s
|
13
|
+
var.should == "yum"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "doesn't provide access to Erector methods" do
|
17
|
+
Erector::Widget.new { lambda { text "yay" }.should raise_error(NoMethodError) }.to_s
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe Erector::Inline do
|
22
|
+
it "returns an InlineWidget" do
|
23
|
+
Erector.inline.should be_a_kind_of(Erector::InlineWidget)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "doesn't provide access to instance variables from the calling context" do
|
27
|
+
@var = "yay"
|
28
|
+
Erector.inline { text @var }.to_s.should == ""
|
29
|
+
end
|
30
|
+
|
31
|
+
it "provides access to bound variables from the calling context" do
|
32
|
+
var = "yay"
|
33
|
+
Erector.inline { text var }.to_s.should == "yay"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "provides access to explicit assigns" do
|
37
|
+
Erector.inline(:var => "yay") { text @var }.to_s.should == "yay"
|
18
38
|
end
|
19
39
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
@sample_instance_variable = "yum"
|
24
|
-
sample_bound_variable = "yay"
|
25
|
-
Erector.inline do
|
26
|
-
@sample_instance_variable.should be_nil
|
27
|
-
sample_bound_variable.should == "yay"
|
28
|
-
text "you can call Erector methods from in here"
|
29
|
-
# puts "uncomment this to prove this is being executed"
|
30
|
-
end.to_s
|
31
|
-
|
40
|
+
it "provides access to methods from the calling context" do
|
41
|
+
def helper
|
42
|
+
"yay"
|
32
43
|
end
|
44
|
+
|
45
|
+
Erector.inline { text helper }.to_s.should == "yay"
|
33
46
|
end
|
34
|
-
|
35
|
-
describe
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
sample_bound_variable = "yay"
|
41
|
-
erector do
|
42
|
-
@sample_instance_variable.should be_nil
|
43
|
-
sample_bound_variable.should == "yay"
|
44
|
-
text "you can call Erector methods from in here"
|
45
|
-
# puts "uncomment this to prove this is being executed"
|
47
|
+
|
48
|
+
describe "#call_block" do
|
49
|
+
it "calls the block with a pointer to self" do
|
50
|
+
x = Erector::InlineWidget.new do |y|
|
51
|
+
element "arg", y.object_id
|
52
|
+
element "self", self.object_id
|
46
53
|
end
|
47
|
-
|
54
|
+
|
55
|
+
# inside the block...
|
56
|
+
x.to_s.should ==
|
57
|
+
"<arg>#{x.object_id}</arg>" + # the argument is the child
|
58
|
+
"<self>#{x.object_id}</self>" # and self is also the child
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe Erector::Mixin do
|
64
|
+
include Erector::Mixin
|
65
|
+
|
66
|
+
it "doesn't provide access to instance variables from the calling context" do
|
67
|
+
@var = "yay"
|
68
|
+
erector { text @var }.should == ""
|
69
|
+
end
|
70
|
+
|
71
|
+
it "provides access to bound variables from the calling context" do
|
72
|
+
var = "yay"
|
73
|
+
erector { text var }.should == "yay"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "provides access to methods from the calling context" do
|
77
|
+
def helper
|
78
|
+
"yay"
|
48
79
|
end
|
80
|
+
|
81
|
+
erector { text helper }.should == "yay"
|
49
82
|
end
|
50
|
-
|
51
83
|
end
|
data/spec/erector/mixin_spec.rb
CHANGED
@@ -2,15 +2,13 @@ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
|
2
2
|
require 'benchmark'
|
3
3
|
|
4
4
|
module MixinSpec
|
5
|
-
class Thing
|
6
|
-
include Erector::Mixin
|
7
|
-
end
|
8
5
|
|
9
6
|
describe Erector::Mixin do
|
10
7
|
describe "#erector" do
|
11
8
|
it "renders its block to a string" do
|
12
9
|
|
13
|
-
class
|
10
|
+
class Thing
|
11
|
+
include Erector::Mixin
|
14
12
|
def name
|
15
13
|
erector do
|
16
14
|
span :class => "name" do
|
@@ -26,7 +24,8 @@ module MixinSpec
|
|
26
24
|
end
|
27
25
|
|
28
26
|
it "passes its parameters to to_s" do
|
29
|
-
class
|
27
|
+
class Thing
|
28
|
+
include Erector::Mixin
|
30
29
|
def pretty_name
|
31
30
|
erector(:prettyprint => true) do
|
32
31
|
div :class => "name" do
|
@@ -49,6 +48,18 @@ module MixinSpec
|
|
49
48
|
" </ul>\n" +
|
50
49
|
"</div>\n"
|
51
50
|
end
|
51
|
+
|
52
|
+
it "passes its parameters to the widget too" do
|
53
|
+
class Thing
|
54
|
+
include Erector::Mixin
|
55
|
+
def foo
|
56
|
+
erector(:foo => "bar") do
|
57
|
+
div @foo
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
Thing.new.foo.should == "<div>bar</div>"
|
62
|
+
end
|
52
63
|
end
|
53
64
|
end
|
54
65
|
end
|
data/spec/erector/widget_spec.rb
CHANGED
@@ -190,6 +190,40 @@ module WidgetSpec
|
|
190
190
|
end
|
191
191
|
|
192
192
|
end
|
193
|
+
|
194
|
+
it "passes a pointer to the child object back into the parent object's block" do
|
195
|
+
child_widget = Erector::Widget.new
|
196
|
+
|
197
|
+
class Parent < Erector::Widget
|
198
|
+
needs :child_widget
|
199
|
+
def content
|
200
|
+
div do
|
201
|
+
widget @child_widget do |child|
|
202
|
+
b child.dom_id
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
Parent.new(:child_widget => child_widget).to_s.should == "<div><b>#{child_widget.dom_id}</b></div>"
|
209
|
+
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe "#call_block" do
|
216
|
+
it "calls the block with a pointer to self" do
|
217
|
+
inside_arg = nil
|
218
|
+
inside_self = nil
|
219
|
+
x = Erector::Widget.new do |y|
|
220
|
+
inside_arg = y.object_id
|
221
|
+
inside_self = self.object_id
|
222
|
+
end
|
223
|
+
x.call_block
|
224
|
+
# inside the block...
|
225
|
+
inside_arg.should == x.object_id # the argument is the child
|
226
|
+
inside_self.should == self.object_id # and self is the parent
|
193
227
|
end
|
194
228
|
end
|
195
229
|
|
@@ -244,6 +278,14 @@ module WidgetSpec
|
|
244
278
|
end
|
245
279
|
end
|
246
280
|
|
281
|
+
context "with an empty array of CSS classes" do
|
282
|
+
it "does not emit a class attribute" do
|
283
|
+
Erector.inline do
|
284
|
+
element('div', :class => [])
|
285
|
+
end.to_s.should == "<div></div>"
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
247
289
|
context "with many attributes" do
|
248
290
|
it "alphabetize them" do
|
249
291
|
Erector.inline do
|
@@ -441,17 +483,34 @@ module WidgetSpec
|
|
441
483
|
end
|
442
484
|
|
443
485
|
describe "#comment" do
|
444
|
-
it "emits
|
486
|
+
it "emits a single line comment when receiving a string" do
|
445
487
|
Erector.inline do
|
446
488
|
comment "foo"
|
447
|
-
end.to_s.should == "<!--foo
|
489
|
+
end.to_s.should == "<!--foo-->\n"
|
448
490
|
end
|
449
|
-
|
491
|
+
|
492
|
+
it "emits a multiline comment when receiving a block" do
|
493
|
+
Erector.inline do
|
494
|
+
comment do
|
495
|
+
text "Hello"
|
496
|
+
text " world!"
|
497
|
+
end
|
498
|
+
end.to_s.should == "<!--\nHello world!\n-->\n"
|
499
|
+
end
|
500
|
+
|
501
|
+
it "emits a multiline comment when receiving a string and a block" do
|
502
|
+
Erector.inline do
|
503
|
+
comment "Hello" do
|
504
|
+
text " world!"
|
505
|
+
end
|
506
|
+
end.to_s.should == "<!--Hello\n world!\n-->\n"
|
507
|
+
end
|
508
|
+
|
450
509
|
# see http://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2.4
|
451
510
|
it "does not HTML-escape character references" do
|
452
511
|
Erector.inline do
|
453
512
|
comment " "
|
454
|
-
end.to_s.should == "<!-- 
|
513
|
+
end.to_s.should == "<!-- -->\n"
|
455
514
|
end
|
456
515
|
|
457
516
|
# see http://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2.4
|
@@ -460,10 +519,25 @@ module WidgetSpec
|
|
460
519
|
capturing_output do
|
461
520
|
Erector.inline do
|
462
521
|
comment "he was -- awesome!"
|
463
|
-
end.to_s.should == "<!--he was -- awesome
|
522
|
+
end.to_s.should == "<!--he was -- awesome!-->\n"
|
464
523
|
end.should == "Warning: Authors should avoid putting two or more adjacent hyphens inside comments.\n"
|
465
|
-
end
|
466
|
-
|
524
|
+
end
|
525
|
+
|
526
|
+
it "renders an IE conditional comment with endif when receiving an if IE" do
|
527
|
+
Erector.inline do
|
528
|
+
comment "[if IE]" do
|
529
|
+
text "Hello IE!"
|
530
|
+
end
|
531
|
+
end.to_s.should == "<!--[if IE]>\nHello IE!\n<![endif]-->\n"
|
532
|
+
end
|
533
|
+
|
534
|
+
it "doesn't render an IE conditional comment if there's just some text in brackets" do
|
535
|
+
Erector.inline do
|
536
|
+
comment "[puppies are cute]"
|
537
|
+
end.to_s.should == "<!--[puppies are cute]-->\n"
|
538
|
+
end
|
539
|
+
|
540
|
+
end
|
467
541
|
|
468
542
|
describe "#nbsp" do
|
469
543
|
it "turns consecutive spaces into consecutive non-breaking spaces" do
|
@@ -590,6 +664,37 @@ module WidgetSpec
|
|
590
664
|
end
|
591
665
|
end
|
592
666
|
|
667
|
+
describe 'escaping' do
|
668
|
+
plain = 'if (x < y && x > z) alert("don\'t stop");'
|
669
|
+
escaped = "if (x < y && x > z) alert("don't stop");"
|
670
|
+
|
671
|
+
describe "#text" do
|
672
|
+
it "does HTML escape its param" do
|
673
|
+
Erector.inline { text plain }.to_s.should == escaped
|
674
|
+
end
|
675
|
+
end
|
676
|
+
describe "#rawtext" do
|
677
|
+
it "doesn't HTML escape its param" do
|
678
|
+
Erector.inline { rawtext plain }.to_s.should == plain
|
679
|
+
end
|
680
|
+
end
|
681
|
+
describe "#text!" do
|
682
|
+
it "doesn't HTML escape its param" do
|
683
|
+
Erector.inline { text! plain }.to_s.should == plain
|
684
|
+
end
|
685
|
+
end
|
686
|
+
describe "#element" do
|
687
|
+
it "does HTML escape its param" do
|
688
|
+
Erector.inline { element "foo", plain }.to_s.should == "<foo>#{escaped}</foo>"
|
689
|
+
end
|
690
|
+
end
|
691
|
+
describe "#element!" do
|
692
|
+
it "doesn't HTML escape its param" do
|
693
|
+
Erector.inline { element! "foo", plain }.to_s.should == "<foo>#{plain}</foo>"
|
694
|
+
end
|
695
|
+
end
|
696
|
+
end
|
697
|
+
|
593
698
|
describe "#javascript" do
|
594
699
|
context "when receiving a block" do
|
595
700
|
it "renders the content inside of script text/javascript tags" do
|
@@ -662,6 +767,45 @@ module WidgetSpec
|
|
662
767
|
css "erector.css"
|
663
768
|
end.to_s.should == "<link href=\"erector.css\" rel=\"stylesheet\" type=\"text/css\" />"
|
664
769
|
end
|
770
|
+
|
771
|
+
it "accepts a media attribute" do
|
772
|
+
Erector.inline do
|
773
|
+
css "print.css", :media => "print"
|
774
|
+
end.to_s.should == "<link href=\"print.css\" media=\"print\" rel=\"stylesheet\" type=\"text/css\" />"
|
775
|
+
end
|
776
|
+
end
|
777
|
+
|
778
|
+
describe "#to_text" do
|
779
|
+
it "strips tags" do
|
780
|
+
Erector.inline do
|
781
|
+
div "foo"
|
782
|
+
end.to_text.should == "foo"
|
783
|
+
end
|
784
|
+
|
785
|
+
it "unescapes named entities" do
|
786
|
+
s = "my \"dog\" has fleas & <ticks>"
|
787
|
+
Erector.inline do
|
788
|
+
text s
|
789
|
+
end.to_text.should == s
|
790
|
+
end
|
791
|
+
|
792
|
+
it "ignores >s inside attribute strings" do
|
793
|
+
Erector.inline do
|
794
|
+
a "foo", :href => "http://example.com/x>y"
|
795
|
+
end.to_text.should == "foo"
|
796
|
+
end
|
797
|
+
|
798
|
+
it "doesn't inherit unwanted pretty-printed whitespace (i.e. it turns off prettyprinting)" do
|
799
|
+
old_default = Erector::Widget.new.prettyprint_default
|
800
|
+
begin
|
801
|
+
Erector::Widget.prettyprint_default = true
|
802
|
+
Erector.inline do
|
803
|
+
div { div { div "foo" } }
|
804
|
+
end.to_text.should == "foo"
|
805
|
+
ensure
|
806
|
+
Erector::Widget.prettyprint_default = old_default
|
807
|
+
end
|
808
|
+
end
|
665
809
|
end
|
666
810
|
|
667
811
|
describe "#url" do
|
@@ -670,6 +814,12 @@ module WidgetSpec
|
|
670
814
|
url "http://example.com"
|
671
815
|
end.to_s.should == "<a href=\"http://example.com\">http://example.com</a>"
|
672
816
|
end
|
817
|
+
|
818
|
+
it "accepts extra attributes" do
|
819
|
+
Erector.inline do
|
820
|
+
url "http://example.com", :onclick=>"alert('foo')"
|
821
|
+
end.to_s.should == "<a href=\"http://example.com\" onclick=\"alert('foo')\">http://example.com</a>"
|
822
|
+
end
|
673
823
|
end
|
674
824
|
|
675
825
|
describe '#capture' do
|
@@ -685,6 +835,14 @@ module WidgetSpec
|
|
685
835
|
widget.to_s.should == '<div><p>Captured Content</p></div>'
|
686
836
|
end
|
687
837
|
|
838
|
+
it "returns a RawString" do
|
839
|
+
captured = nil
|
840
|
+
Erector.inline do
|
841
|
+
captured = capture {}
|
842
|
+
end.to_s.should == ""
|
843
|
+
captured.should be_a_kind_of Erector::RawString
|
844
|
+
end
|
845
|
+
|
688
846
|
it "works with nested captures" do
|
689
847
|
widget = Erector.inline do
|
690
848
|
captured = capture do
|
@@ -888,5 +1046,24 @@ module WidgetSpec
|
|
888
1046
|
Erector.inline { close_tag :foo; close_tag :bar }.to_s.should == "</foo></bar>"
|
889
1047
|
end
|
890
1048
|
end
|
1049
|
+
|
1050
|
+
describe "#dom_id" do
|
1051
|
+
class NiceWidget < Erector::Widget
|
1052
|
+
def content
|
1053
|
+
div :id => dom_id
|
1054
|
+
end
|
1055
|
+
end
|
1056
|
+
|
1057
|
+
it "makes a unique id based on the widget's class name and object id" do
|
1058
|
+
widget = NiceWidget.new
|
1059
|
+
widget.dom_id.should include("#{widget.object_id}")
|
1060
|
+
widget.dom_id.should include("NiceWidget")
|
1061
|
+
end
|
1062
|
+
|
1063
|
+
it "can be used as an HTML id" do
|
1064
|
+
widget = NiceWidget.new
|
1065
|
+
widget.to_s.should == "<div id=\"#{widget.dom_id}\"></div>"
|
1066
|
+
end
|
1067
|
+
end
|
891
1068
|
end
|
892
1069
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
|
2
|
+
|
3
|
+
describe Form do
|
4
|
+
|
5
|
+
include Erector::Mixin
|
6
|
+
|
7
|
+
it "defaults to POST, with no magic hidden method param" do
|
8
|
+
Form.new(:action => "/foo").to_s.should == "<form action=\"/foo\" method=\"post\"></form>"
|
9
|
+
end
|
10
|
+
|
11
|
+
it "works plainly with GET too" do
|
12
|
+
Form.new(:action => "/foo", :method => "get").to_s.should == "<form action=\"/foo\" method=\"get\"></form>"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "uses POST and adds a magic hidden field with a _method param for DELETE" do
|
16
|
+
Form.new(:action => "/foo", :method => "delete").to_s.should ==
|
17
|
+
"<form action=\"/foo\" method=\"post\">"+
|
18
|
+
"<input name=\"_method\" type=\"hidden\" value=\"delete\" />"+
|
19
|
+
"</form>"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "executes its block in the caller's 'self' context" do
|
23
|
+
erector {
|
24
|
+
@pet = "dog"
|
25
|
+
widget(Form.new(:action => "/foo") do
|
26
|
+
p @pet
|
27
|
+
end)
|
28
|
+
}.should == "<form action=\"/foo\" method=\"post\"><p>dog</p></form>"
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|