erector-rails4 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +2 -0
  3. data/.gitignore +10 -0
  4. data/.rspec +1 -0
  5. data/.ruby-gemset +1 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +5 -0
  8. data/Gemfile +6 -0
  9. data/Gemfile.lock +143 -0
  10. data/README.md +4 -0
  11. data/Rakefile +24 -0
  12. data/erector-rails4.gemspec +36 -0
  13. data/erector-rails4.sublimeproject +20 -0
  14. data/lib/erector/abstract_widget.rb +231 -0
  15. data/lib/erector/after_initialize.rb +29 -0
  16. data/lib/erector/attributes.rb +29 -0
  17. data/lib/erector/cache.rb +37 -0
  18. data/lib/erector/caching.rb +65 -0
  19. data/lib/erector/convenience.rb +98 -0
  20. data/lib/erector/dependencies.rb +24 -0
  21. data/lib/erector/dependency.rb +31 -0
  22. data/lib/erector/element.rb +113 -0
  23. data/lib/erector/externals.rb +104 -0
  24. data/lib/erector/html.rb +12 -0
  25. data/lib/erector/html_widget.rb +220 -0
  26. data/lib/erector/inline.rb +37 -0
  27. data/lib/erector/jquery.rb +28 -0
  28. data/lib/erector/mixin.rb +12 -0
  29. data/lib/erector/needs.rb +95 -0
  30. data/lib/erector/output.rb +144 -0
  31. data/lib/erector/promise.rb +141 -0
  32. data/lib/erector/rails/form_builder.rb +44 -0
  33. data/lib/erector/rails/railtie.rb +13 -0
  34. data/lib/erector/rails/template_handler.rb +16 -0
  35. data/lib/erector/rails/widget_renderer.rb +6 -0
  36. data/lib/erector/rails.rb +221 -0
  37. data/lib/erector/raw_string.rb +12 -0
  38. data/lib/erector/sass.rb +32 -0
  39. data/lib/erector/tag.rb +66 -0
  40. data/lib/erector/text.rb +123 -0
  41. data/lib/erector/unicode.rb +18185 -0
  42. data/lib/erector/unicode_builder.rb +67 -0
  43. data/lib/erector/version.rb +5 -0
  44. data/lib/erector/widget.rb +94 -0
  45. data/lib/erector/widgets.rb +5 -0
  46. data/lib/erector/xml_widget.rb +131 -0
  47. data/lib/erector.rb +28 -0
  48. data/spec/dummy/Rakefile +7 -0
  49. data/spec/dummy/app/controllers/application.rb +6 -0
  50. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  51. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  52. data/spec/dummy/app/views/layouts/erb_as_layout.html.erb +2 -0
  53. data/spec/dummy/app/views/layouts/widget_as_layout.rb +8 -0
  54. data/spec/dummy/app/views/test/_erb.erb +1 -0
  55. data/spec/dummy/app/views/test/_erector.rb +5 -0
  56. data/spec/dummy/app/views/test/_partial_with_locals.rb +7 -0
  57. data/spec/dummy/app/views/test/bare.rb +5 -0
  58. data/spec/dummy/app/views/test/erb_from_erector.html.rb +5 -0
  59. data/spec/dummy/app/views/test/erector_from_erb.html.erb +1 -0
  60. data/spec/dummy/app/views/test/erector_with_locals_from_erb.html.erb +6 -0
  61. data/spec/dummy/app/views/test/implicit_assigns.html.rb +5 -0
  62. data/spec/dummy/app/views/test/needs.html.rb +7 -0
  63. data/spec/dummy/app/views/test/needs_subclass.html.rb +5 -0
  64. data/spec/dummy/app/views/test/protected_instance_variable.html.rb +5 -0
  65. data/spec/dummy/app/views/test/render_default.html.rb +5 -0
  66. data/spec/dummy/app/views/test/render_default_erb_with_layout.html.erb +1 -0
  67. data/spec/dummy/app/views/test/render_default_widget_with_layout.html.rb +5 -0
  68. data/spec/dummy/app/views/test/render_partial.html.rb +5 -0
  69. data/spec/dummy/app/views/test/render_with_widget_as_layout.rb +5 -0
  70. data/spec/dummy/app/views/test/render_with_widget_as_layout_using_content_for.rb +8 -0
  71. data/spec/dummy/config/application.rb +44 -0
  72. data/spec/dummy/config/boot.rb +10 -0
  73. data/spec/dummy/config/database.yml +22 -0
  74. data/spec/dummy/config/environment.rb +5 -0
  75. data/spec/dummy/config/environments/development.rb +22 -0
  76. data/spec/dummy/config/environments/production.rb +49 -0
  77. data/spec/dummy/config/environments/test.rb +36 -0
  78. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  79. data/spec/dummy/config/initializers/inflections.rb +10 -0
  80. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  81. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  82. data/spec/dummy/config/initializers/session_store.rb +8 -0
  83. data/spec/dummy/config/locales/en.yml +5 -0
  84. data/spec/dummy/config/routes.rb +3 -0
  85. data/spec/dummy/config.ru +4 -0
  86. data/spec/dummy/db/seeds.rb +7 -0
  87. data/spec/dummy/script/rails +6 -0
  88. data/spec/dummy/spec/form_builder_spec.rb +21 -0
  89. data/spec/dummy/spec/rails_helpers_spec.rb +236 -0
  90. data/spec/dummy/spec/rails_spec_helper.rb +10 -0
  91. data/spec/dummy/spec/rails_widget_spec.rb +83 -0
  92. data/spec/dummy/spec/render_spec.rb +369 -0
  93. data/spec/erector/after_initialize_spec.rb +45 -0
  94. data/spec/erector/cache_spec.rb +133 -0
  95. data/spec/erector/caching_spec.rb +184 -0
  96. data/spec/erector/convenience_spec.rb +250 -0
  97. data/spec/erector/dependency_spec.rb +67 -0
  98. data/spec/erector/hello_from_readme.rb +18 -0
  99. data/spec/erector/hello_from_readme_spec.rb +11 -0
  100. data/spec/erector/html_spec.rb +585 -0
  101. data/spec/erector/indentation_spec.rb +211 -0
  102. data/spec/erector/inline_spec.rb +94 -0
  103. data/spec/erector/jquery_spec.rb +35 -0
  104. data/spec/erector/mixin_spec.rb +65 -0
  105. data/spec/erector/needs_spec.rb +141 -0
  106. data/spec/erector/output_spec.rb +293 -0
  107. data/spec/erector/promise_spec.rb +173 -0
  108. data/spec/erector/sample-file.txt +1 -0
  109. data/spec/erector/sass_spec.rb +57 -0
  110. data/spec/erector/tag_spec.rb +67 -0
  111. data/spec/erector/unicode_builder_spec.rb +75 -0
  112. data/spec/erector/widget_spec.rb +310 -0
  113. data/spec/erector/xml_widget_spec.rb +73 -0
  114. data/spec/spec_helper.rb +31 -0
  115. metadata +368 -0
@@ -0,0 +1 @@
1
+ sample file contents, 2 + 2 = #{2 + 2}
@@ -0,0 +1,57 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ module CacheSpec
4
+ describe Erector::Sass do
5
+ include Erector::Mixin
6
+ describe 'the #sass method' do
7
+ it "renders SCSS by default, since that's what Sass recommends these days" do
8
+ erector {sass SAMPLE_SCSS}.should == SAMPLE_CSS
9
+ end
10
+ it "renders SASS with explicit option" do
11
+ erector {sass SAMPLE_SASS, :syntax => :sass}.should == SAMPLE_CSS
12
+ end
13
+ it "renders SCSS with explicit option" do
14
+ erector {sass SAMPLE_SCSS, :syntax => :scss}.should == SAMPLE_CSS
15
+ end
16
+ end
17
+
18
+ describe 'the #scss method' do
19
+ it "renders SCSS" do
20
+ erector {scss SAMPLE_SCSS}.should == SAMPLE_CSS
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ SAMPLE_SASS =<<-SASS.strip
27
+ h1
28
+ height: 118px
29
+ margin-top: 1em
30
+
31
+ .tagline
32
+ font-size: 26px
33
+ text-align: right
34
+ SASS
35
+
36
+ SAMPLE_SCSS =<<-CSS.strip
37
+ h1 {
38
+ height: 118px;
39
+ margin-top: 1em;
40
+ }
41
+
42
+ .tagline {
43
+ font-size: 26px;
44
+ text-align: right;
45
+ }
46
+ CSS
47
+
48
+ SAMPLE_CSS =<<-CSS.strip
49
+ <style>h1 {
50
+ height: 118px;
51
+ margin-top: 1em; }
52
+
53
+ .tagline {
54
+ font-size: 26px;
55
+ text-align: right; }
56
+ </style>
57
+ CSS
@@ -0,0 +1,67 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+ require "erector/tag"
3
+
4
+ module Erector
5
+ describe Tag do
6
+ it "takes a name" do
7
+ t = Tag.new("foo")
8
+ t.name.should == "foo"
9
+ end
10
+
11
+ it "has default values for its options" do
12
+ t = Tag.new("foo")
13
+ t.self_closing?.should == false
14
+ t.inline?.should == false
15
+ end
16
+
17
+ it "can take any combination of options" do
18
+ t = Tag.new("foo", :self_closing)
19
+ t.self_closing?.should == true
20
+ t.inline?.should == false
21
+
22
+ t = Tag.new("foo", :inline)
23
+ t.self_closing?.should == false
24
+ t.inline?.should == true
25
+
26
+ t = Tag.new("foo", :self_closing, :inline)
27
+ t.self_closing?.should == true
28
+ t.inline?.should == true
29
+
30
+ t = Tag.new("foo", :inline, :self_closing)
31
+ t.self_closing?.should == true
32
+ t.inline?.should == true
33
+ end
34
+
35
+ it "can take a method name" do
36
+ t = Tag.new("foo", "bar")
37
+ t.name.should == "foo"
38
+ t.method_name.should == "bar"
39
+ t.self_closing?.should == false
40
+ t.inline?.should == false
41
+ end
42
+
43
+ it "can take a method name and options" do
44
+ t = Tag.new("foo", "bar", :self_closing, :inline)
45
+ t.name.should == "foo"
46
+ t.method_name.should == "bar"
47
+ t.self_closing?.should == true
48
+ t.inline?.should == true
49
+ end
50
+
51
+ it "can underscorize its method name" do
52
+ t = Tag.new("InclusiveLowerBound", :snake_case)
53
+ t.name.should == "InclusiveLowerBound"
54
+ t.method_name.should == "inclusive_lower_bound"
55
+ end
56
+
57
+ it "is smart about acronyms" do
58
+ t = Tag.new("WatchCNNToday", :snake_case)
59
+ t.name.should == "WatchCNNToday"
60
+ t.method_name.should == "watch_cnn_today"
61
+ end
62
+
63
+
64
+ end
65
+ end
66
+
67
+
@@ -0,0 +1,75 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+ require File.expand_path("#{File.dirname(__FILE__)}/../../lib/erector/unicode_builder")
3
+
4
+ describe "build unicode" do
5
+
6
+ def make_builder(input_string)
7
+ @output = ""
8
+ Erector::UnicodeBuilder.new(
9
+ StringIO.new(input_string),
10
+ StringIO.new(@output))
11
+ end
12
+
13
+ it "#generate generates header and footer" do
14
+ make_builder("").generate()
15
+ @output.should == "Erector::CHARACTERS = {\n}\n"
16
+ end
17
+
18
+ it "generates nothing from empty file" do
19
+ make_builder("").process_file()
20
+ @output.should == ""
21
+ end
22
+
23
+ it "generates nothing from blank line" do
24
+ make_builder("\n").process_file()
25
+ @output.should == ""
26
+ end
27
+
28
+ it "generates entry from a simple line" do
29
+ make_builder(%q{
30
+ 0025;PERCENT SIGN;Po;0;ET;;;;;N;;;;;
31
+ }).process_file()
32
+ @output.should == " :percent_sign => 0x0025\n"
33
+ end
34
+
35
+ it "can process two lines" do
36
+ make_builder(%q{
37
+ 0906;DEVANAGARI LETTER AA;Lo;0;L;;;;;N;;;;;
38
+ 237E;BELL SYMBOL;So;0;ON;;;;;N;;;;;
39
+ }).process_file()
40
+ @output.should == " :devanagari_letter_aa => 0x0906,\n" +
41
+ " :bell_symbol => 0x237e\n"
42
+ end
43
+
44
+ it "also adds an entry for an alias" do
45
+ make_builder(%q{
46
+ 2192;RIGHTWARDS ARROW;Sm;0;ON;;;;;N;RIGHT ARROW;;;;
47
+ }).process_file()
48
+ @output.should == " :rightwards_arrow => 0x2192,\n" +
49
+ " :right_arrow => 0x2192\n"
50
+ end
51
+
52
+ it "can handle hyphen in name" do
53
+ make_builder(%q{
54
+ 2673;RECYCLING SYMBOL FOR TYPE-1 PLASTICS;So;0;ON;;;;;N;;pete;;;
55
+ }).process_file()
56
+ @output.should == " :recycling_symbol_for_type_1_plastics => 0x2673\n"
57
+ end
58
+
59
+ it "can handle characters above 0xffff" do
60
+ make_builder(%q{
61
+ 10400;DESERET CAPITAL LETTER LONG I;Lu;0;L;;;;;N;;;;10428;
62
+ }).process_file()
63
+ @output.should == " :deseret_capital_letter_long_i => 0x10400\n"
64
+ end
65
+
66
+ it "ignores entries whose names start with less than" do
67
+ make_builder(%q{
68
+ F0000;<Plane 15 Private Use, First>;Co;0;L;;;;;N;;;;;
69
+ FFFFD;<Plane 15 Private Use, Last>;Co;0;L;;;;;N;;;;;
70
+ }).process_file()
71
+ @output.should == ""
72
+ end
73
+
74
+ end
75
+
@@ -0,0 +1,310 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+ require 'benchmark'
3
+ require 'nokogiri'
4
+
5
+ module WidgetSpec
6
+ describe Erector::Widget do
7
+ include Erector::Mixin
8
+
9
+ describe "#to_html" do
10
+ it "invokes #content and returns the string representation of the rendered widget" do
11
+ Class.new(Erector::Widget) do
12
+ def content
13
+ text "Hello"
14
+ end
15
+ end.new.to_html.should == "Hello"
16
+ end
17
+
18
+ it "supports other content methods via :content_method_name" do
19
+ Class.new(Erector::Widget) do
20
+ def alternate
21
+ text "Alternate"
22
+ end
23
+ end.new.to_html(:content_method_name => :alternate).should == "Alternate"
24
+ end
25
+
26
+ it "returns an HTML-safe string" do
27
+ Erector::Widget.new.to_html.should be_html_safe
28
+ end
29
+
30
+ it "accepts an existing string as an output buffer" do
31
+ s = "foo"
32
+ Erector.inline { text "bar" }.to_html(:output => s)
33
+ s.should == "foobar"
34
+ end
35
+
36
+ it "accepts an existing Output as an output buffer" do
37
+ output = Erector::Output.new
38
+ output << "foo"
39
+ Erector.inline { text "bar" }.to_html(:output => output)
40
+ output.to_s.should == "foobar"
41
+ end
42
+ end
43
+
44
+ describe "#to_a" do
45
+ it "returns an array" do
46
+ a = Erector.inline { div "Hello" }.to_a
47
+ a.should be_an(Array)
48
+ a.join.should == "<div>Hello</div>"
49
+ end
50
+ end
51
+
52
+ describe '#widget' do
53
+ class Orphan < Erector::Widget
54
+ def content
55
+ p @name
56
+ end
57
+ end
58
+
59
+ it "renders a widget class" do
60
+ erector do
61
+ div do
62
+ widget Orphan, :name => "Annie"
63
+ end
64
+ end.should == "<div><p>Annie</p></div>"
65
+ end
66
+
67
+ it "renders a widget instance" do
68
+ erector do
69
+ div do
70
+ widget Orphan.new(:name => "Oliver")
71
+ end
72
+ end.should == "<div><p>Oliver</p></div>"
73
+ end
74
+
75
+ it "adds the widget to the parent's output widgets" do
76
+ inner = Class.new(Erector::Widget)
77
+ outer = Erector.inline { widget inner }
78
+ outer.to_html
79
+ outer.output.widgets.should include(inner)
80
+ end
81
+
82
+ it "supports specifying content_method_name" do
83
+ inner = Class.new(Erector::Widget) do
84
+ def foo; text "foo"; end
85
+ end
86
+ erector do
87
+ widget inner, {}, :content_method_name => :foo
88
+ end.should == "foo"
89
+ end
90
+
91
+ it "renders nested widgets in the correct order" do
92
+ class Parent < Erector::Widget
93
+ def content
94
+ text 1
95
+ widget Erector::Widget do
96
+ text 2
97
+ third
98
+ end
99
+ end
100
+
101
+ def third
102
+ text 3
103
+ end
104
+ end
105
+
106
+ Parent.new.to_html.should == '123'
107
+ end
108
+
109
+ context "when nested" do
110
+ module WhenNested
111
+ class Parent < Erector::Widget
112
+ def content
113
+ div :id => "parent_widget" do
114
+ super
115
+ end
116
+ end
117
+ end
118
+
119
+ class Child < Erector::Widget
120
+ def content
121
+ div :id => "child_widget" do
122
+ super
123
+ end
124
+ end
125
+ end
126
+
127
+ class Grandchild < Erector::Widget
128
+ needs :parent_widget, :child_widget
129
+ def content
130
+ widget(@parent_widget) do
131
+ widget(@child_widget) do
132
+ div :id => "grandchild"
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ it "renders the tag around the rest of the block" do
140
+ WhenNested::Grandchild.new(
141
+ :parent_widget => WhenNested::Parent,
142
+ :child_widget => WhenNested::Child
143
+ ).to_html.should == '<div id="parent_widget"><div id="child_widget"><div id="grandchild"></div></div></div>'
144
+ end
145
+
146
+ it "renders the tag around the rest of the block with proper indentation" do
147
+ WhenNested::Grandchild.new(
148
+ :parent_widget => WhenNested::Parent,
149
+ :child_widget => WhenNested::Child
150
+ ).to_pretty.should ==
151
+ "<div id=\"parent_widget\">\n" +
152
+ " <div id=\"child_widget\">\n" +
153
+ " <div id=\"grandchild\"></div>\n" +
154
+ " </div>\n" +
155
+ "</div>\n"
156
+ end
157
+
158
+ it "passes a pointer to the child object back into the parent object's block" do
159
+ child_widget = Erector::Widget.new
160
+
161
+ class Parent2 < Erector::Widget
162
+ needs :child_widget
163
+ def content
164
+ div do
165
+ widget @child_widget do |child|
166
+ b child.dom_id
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ Parent2.new(:child_widget => child_widget).to_html.should == "<div><b>#{child_widget.dom_id}</b></div>"
173
+ end
174
+ end
175
+ end
176
+
177
+ describe "#call_block" do
178
+ it "calls the block with a pointer to self" do
179
+ inside_arg = nil
180
+ inside_self = nil
181
+ x = Erector::Widget.new do |y|
182
+ inside_arg = y.object_id
183
+ inside_self = self.object_id
184
+ end
185
+ x.call_block
186
+ # inside the block...
187
+ inside_arg.should == x.object_id # the argument is the child
188
+ inside_self.should == self.object_id # and self is the parent
189
+ end
190
+ end
191
+
192
+ describe '#capture' do
193
+ it "should return content rather than write it to the buffer" do
194
+ erector do
195
+ captured = capture_content do
196
+ p 'Captured Content'
197
+ end
198
+ div do
199
+ text captured
200
+ end
201
+ end.should == '<div><p>Captured Content</p></div>'
202
+ end
203
+
204
+ it "returns a RawString" do
205
+ captured = nil
206
+ erector do
207
+ captured = capture_content {}
208
+ end.should == ""
209
+ captured.should be_a_kind_of(Erector::RawString)
210
+ end
211
+
212
+ it "works with nested captures" do
213
+ erector do
214
+ captured = capture_content do
215
+ captured = capture_content do
216
+ p 'Nested Capture'
217
+ end
218
+ p 'Captured Content'
219
+ text captured
220
+ end
221
+ div do
222
+ text captured
223
+ end
224
+ end.should == '<div><p>Captured Content</p><p>Nested Capture</p></div>'
225
+ end
226
+
227
+ it "also is callable as #capture_content in case someone stole the capture name (I'm talking to you, rails 3.1)" do
228
+ captured = nil
229
+ erector do
230
+ captured = capture_content { text "A" }
231
+ end.should == ""
232
+ captured.should == "A"
233
+ end
234
+ end
235
+
236
+ describe '#widget' do
237
+ it "renders a widget" do
238
+ erector do
239
+ text "B"
240
+ widget Erector.inline { p "A" }
241
+ text "B"
242
+ end.should == "B<p>A</p>B"
243
+ end
244
+ end
245
+
246
+ describe '#text' do
247
+ it "fails to render a widget" do
248
+ lambda do
249
+ erector do
250
+ text "B"
251
+ text Erector.inline { p "A" }
252
+ text "B"
253
+ end
254
+ end.should raise_error
255
+ end
256
+
257
+ it "can take several text values" do
258
+ erector do
259
+ text "a", "b", "c"
260
+ end.should == "abc"
261
+ end
262
+
263
+ it "can take several text values with a text delimiter" do
264
+ erector do
265
+ text "a", "b", "c", :join => " "
266
+ end.should == "a b c"
267
+ end
268
+
269
+ it "can take several text values including a promise" do
270
+ erector do
271
+ text "i ", b("love"), " cheese"
272
+ end.should == "i <b>love</b> cheese"
273
+ end
274
+
275
+ it "can take several text values including several promises and a delimiter" do
276
+ erector do
277
+ text "i", b("love"), i("green"), "cheese", :join => " "
278
+ end.should == "i <b>love</b> <i>green</i> cheese"
279
+ end
280
+
281
+ it "can take several text values including a dot-class promise" do
282
+ erector do
283
+ text "i ", b.wow("love"), " cheese"
284
+ end.should == "i <b class=\"wow\">love</b> cheese"
285
+ end
286
+
287
+ end
288
+
289
+
290
+ describe "assigning instance variables" do
291
+ it "handles instance variable names with and without '@' in the beginning" do
292
+ html = Erector.inline(:foo => "bar", '@baz' => 'quux') do
293
+ div do
294
+ p @foo
295
+ p @baz
296
+ end
297
+ end.to_html
298
+ doc = Nokogiri::HTML(html)
299
+ doc.css("p").map {|p| p.inner_html}.should == ["bar", "quux"]
300
+ end
301
+ end
302
+
303
+ describe "named elements" do
304
+ it "can emit boolean values" do
305
+ erector { div true }.should == "<div>true</div>"
306
+ erector { div false }.should == "<div>false</div>"
307
+ end
308
+ end
309
+ end
310
+ end