arbo 1.2.0

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.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yaml +21 -0
  3. data/.github/workflows/daily.yaml +23 -0
  4. data/.gitignore +11 -0
  5. data/CHANGELOG.md +95 -0
  6. data/CONTRIBUTING.md +3 -0
  7. data/Gemfile +17 -0
  8. data/LICENSE +20 -0
  9. data/README.md +29 -0
  10. data/Rakefile +18 -0
  11. data/arbo.gemspec +25 -0
  12. data/docs/Gemfile +2 -0
  13. data/docs/_config.yml +7 -0
  14. data/docs/_includes/footer.html +8 -0
  15. data/docs/_includes/google-analytics.html +16 -0
  16. data/docs/_includes/head.html +7 -0
  17. data/docs/_includes/toc.html +12 -0
  18. data/docs/_includes/top-menu.html +8 -0
  19. data/docs/_layouts/default.html +21 -0
  20. data/docs/index.md +106 -0
  21. data/docs/stylesheets/main.css +1152 -0
  22. data/lib/arbo/component.rb +22 -0
  23. data/lib/arbo/context.rb +118 -0
  24. data/lib/arbo/element/builder_methods.rb +83 -0
  25. data/lib/arbo/element/proxy.rb +28 -0
  26. data/lib/arbo/element.rb +225 -0
  27. data/lib/arbo/element_collection.rb +31 -0
  28. data/lib/arbo/html/attributes.rb +41 -0
  29. data/lib/arbo/html/class_list.rb +28 -0
  30. data/lib/arbo/html/document.rb +31 -0
  31. data/lib/arbo/html/html5_elements.rb +47 -0
  32. data/lib/arbo/html/tag.rb +220 -0
  33. data/lib/arbo/html/text_node.rb +43 -0
  34. data/lib/arbo/rails/forms.rb +101 -0
  35. data/lib/arbo/rails/rendering.rb +17 -0
  36. data/lib/arbo/rails/template_handler.rb +35 -0
  37. data/lib/arbo/rails.rb +5 -0
  38. data/lib/arbo/version.rb +3 -0
  39. data/lib/arbo.rb +21 -0
  40. data/spec/arbo/integration/html_spec.rb +307 -0
  41. data/spec/arbo/unit/component_spec.rb +54 -0
  42. data/spec/arbo/unit/context_spec.rb +35 -0
  43. data/spec/arbo/unit/element_finder_methods_spec.rb +116 -0
  44. data/spec/arbo/unit/element_spec.rb +272 -0
  45. data/spec/arbo/unit/html/class_list_spec.rb +16 -0
  46. data/spec/arbo/unit/html/tag_attributes_spec.rb +104 -0
  47. data/spec/arbo/unit/html/tag_spec.rb +124 -0
  48. data/spec/arbo/unit/html/text_node_spec.rb +5 -0
  49. data/spec/rails/integration/forms_spec.rb +117 -0
  50. data/spec/rails/integration/rendering_spec.rb +98 -0
  51. data/spec/rails/rails_spec_helper.rb +46 -0
  52. data/spec/rails/stub_app/config/database.yml +3 -0
  53. data/spec/rails/stub_app/config/routes.rb +3 -0
  54. data/spec/rails/stub_app/db/schema.rb +3 -0
  55. data/spec/rails/stub_app/log/.gitignore +1 -0
  56. data/spec/rails/stub_app/public/favicon.ico +0 -0
  57. data/spec/rails/support/mock_person.rb +15 -0
  58. data/spec/rails/templates/arbo/_partial.arb +1 -0
  59. data/spec/rails/templates/arbo/_partial_with_assignment.arb +1 -0
  60. data/spec/rails/templates/arbo/empty.arb +0 -0
  61. data/spec/rails/templates/arbo/page_with_arb_partial_and_assignment.arb +3 -0
  62. data/spec/rails/templates/arbo/page_with_assignment.arb +1 -0
  63. data/spec/rails/templates/arbo/page_with_erb_partial.arb +3 -0
  64. data/spec/rails/templates/arbo/page_with_helpers.arb +7 -0
  65. data/spec/rails/templates/arbo/page_with_partial.arb +3 -0
  66. data/spec/rails/templates/arbo/simple_page.arb +8 -0
  67. data/spec/rails/templates/erb/_partial.erb +1 -0
  68. data/spec/spec_helper.rb +7 -0
  69. data/spec/support/bundle.rb +4 -0
  70. metadata +169 -0
@@ -0,0 +1,307 @@
1
+ require 'spec_helper'
2
+
3
+ describe Arbo do
4
+
5
+ let(:helpers){ nil }
6
+ let(:assigns){ {} }
7
+
8
+ def output_buffer(actx)
9
+ actx.render_in(actx) && actx.output_buffer
10
+ end
11
+
12
+ it "should render a single element" do
13
+ actx = arbo {
14
+ span "Hello World"
15
+ }
16
+ html = "<span>Hello World</span>\n"
17
+ expect(actx.to_s).to eq(html)
18
+ expect(output_buffer actx).to eq(html)
19
+ end
20
+
21
+ it "should render a child element" do
22
+ actx = arbo {
23
+ span do
24
+ span "Hello World"
25
+ end
26
+ }
27
+ html = <<-HTML
28
+ <span>
29
+ <span>Hello World</span>
30
+ </span>
31
+ HTML
32
+ expect(actx.to_s).to eq(html)
33
+ expect(output_buffer actx).to eq(html)
34
+ end
35
+
36
+ it "should render an unordered list" do
37
+ actx = arbo {
38
+ ul do
39
+ li "First"
40
+ li "Second"
41
+ li "Third"
42
+ end
43
+ }
44
+ html = <<-HTML
45
+ <ul>
46
+ <li>First</li>
47
+ <li>Second</li>
48
+ <li>Third</li>
49
+ </ul>
50
+ HTML
51
+ expect(actx.to_s).to eq(html)
52
+ expect(output_buffer actx).to eq(html)
53
+ end
54
+
55
+ it "should allow local variables inside the tags" do
56
+ actx = arbo {
57
+ first = "First"
58
+ second = "Second"
59
+ ul do
60
+ li first
61
+ li second
62
+ end
63
+ }
64
+ html = <<-HTML
65
+ <ul>
66
+ <li>First</li>
67
+ <li>Second</li>
68
+ </ul>
69
+ HTML
70
+ expect(actx.to_s).to eq(html)
71
+ expect(output_buffer actx).to eq(html)
72
+ end
73
+
74
+
75
+ it "should add children and nested" do
76
+ actx = arbo {
77
+ div do
78
+ ul
79
+ li do
80
+ li
81
+ end
82
+ end
83
+ }
84
+ html = <<-HTML
85
+ <div>
86
+ <ul></ul>
87
+ <li>
88
+ <li></li>
89
+ </li>
90
+ </div>
91
+ HTML
92
+ expect(actx.to_s).to eq(html)
93
+ expect(output_buffer actx).to eq(html)
94
+ end
95
+
96
+
97
+ it "should pass the element in to the block if asked for" do
98
+ actx = arbo {
99
+ div do |d|
100
+ d.ul do
101
+ li
102
+ end
103
+ end
104
+ }
105
+ html = <<-HTML
106
+ <div>
107
+ <ul>
108
+ <li></li>
109
+ </ul>
110
+ </div>
111
+ HTML
112
+ expect(actx.to_s).to eq(html)
113
+ expect(output_buffer actx).to eq(html)
114
+ end
115
+
116
+
117
+ it "should move content tags between parents" do
118
+ actx = arbo {
119
+ div do
120
+ span(ul(li))
121
+ end
122
+ }
123
+ html = <<-HTML
124
+ <div>
125
+ <span>
126
+ <ul>
127
+ <li></li>
128
+ </ul>
129
+ </span>
130
+ </div>
131
+ HTML
132
+ expect(actx.to_s).to eq(html)
133
+ expect(output_buffer actx).to eq(html)
134
+ end
135
+
136
+ it "should add content to the parent if the element is passed into block" do
137
+ actx = arbo {
138
+ div do |d|
139
+ d.id = "my-tag"
140
+ ul do
141
+ li
142
+ end
143
+ end
144
+ }
145
+ html = <<-HTML
146
+ <div id="my-tag">
147
+ <ul>
148
+ <li></li>
149
+ </ul>
150
+ </div>
151
+ HTML
152
+ expect(actx.to_s).to eq(html)
153
+ expect(output_buffer actx).to eq(html)
154
+ end
155
+
156
+ it "should have the parent set on it" do
157
+ list, item = nil
158
+ arbo {
159
+ list = ul do
160
+ li "Hello"
161
+ item = li "World"
162
+ end
163
+ }
164
+ expect(item.parent).to eq list
165
+ end
166
+
167
+ it "should set a string content return value with no children" do
168
+ actx = arbo {
169
+ li do
170
+ "Hello World"
171
+ end
172
+ }
173
+ html = <<-HTML
174
+ <li>Hello World</li>
175
+ HTML
176
+ expect(actx.to_s).to eq(html)
177
+ expect(output_buffer actx).to eq(html)
178
+ end
179
+
180
+ it "should turn string return values into text nodes" do
181
+ node = nil
182
+ arbo {
183
+ list = li do
184
+ "Hello World"
185
+ end
186
+ node = list.children.first
187
+ }
188
+ expect(node).to be_a Arbo::HTML::TextNode
189
+ end
190
+
191
+ it "should not render blank arrays" do
192
+ actx = arbo {
193
+ tbody do
194
+ []
195
+ end
196
+ }
197
+ html = <<-HTML
198
+ <tbody></tbody>
199
+ HTML
200
+ expect(actx.to_s).to eq(html)
201
+ expect(output_buffer actx).to eq(html)
202
+ end
203
+
204
+ describe "self-closing nodes" do
205
+
206
+ it "should not self-close script tags" do
207
+ actx = arbo {
208
+ script type: 'text/javascript'
209
+ }
210
+ html = "<script type=\"text/javascript\"></script>\n"
211
+ expect(actx.to_s).to eq(html)
212
+ expect(output_buffer actx).to eq(html)
213
+ end
214
+
215
+ it "should self-close meta tags" do
216
+ actx = arbo {
217
+ meta content: "text/html; charset=utf-8"
218
+ }
219
+ html = "<meta content=\"text/html; charset=utf-8\"/>\n"
220
+ expect(actx.to_s).to eq(html)
221
+ expect(output_buffer actx).to eq(html)
222
+ end
223
+
224
+ it "should self-close link tags" do
225
+ actx = arbo {
226
+ link rel: "stylesheet"
227
+ }
228
+ html = "<link rel=\"stylesheet\"/>\n"
229
+ expect(actx.to_s).to eq(html)
230
+ expect(output_buffer actx).to eq(html)
231
+ end
232
+
233
+ Arbo::HTML::Tag::SELF_CLOSING_ELEMENTS.each do |tag|
234
+ it "should self-close #{tag} tags" do
235
+ actx = arbo {
236
+ send(tag)
237
+ }
238
+ html = "<#{tag}/>\n"
239
+ expect(actx.to_s).to eq(html)
240
+ expect(output_buffer actx).to eq(html)
241
+ end
242
+ end
243
+
244
+ end
245
+
246
+ describe "html safe" do
247
+
248
+ it "should escape the contents" do
249
+ actx = arbo {
250
+ span("<br />")
251
+ }
252
+ html = <<-HTML
253
+ <span>&lt;br /&gt;</span>
254
+ HTML
255
+ expect(actx.to_s).to eq(html)
256
+ expect(output_buffer actx).to eq(html)
257
+ end
258
+
259
+ it "should return html safe strings" do
260
+ expect(arbo {
261
+ span("<br />")
262
+ }.to_s).to be_html_safe
263
+ end
264
+
265
+ it "should not escape html passed in" do
266
+ actx = arbo {
267
+ span(span("<br />"))
268
+ }
269
+ html = <<-HTML
270
+ <span>
271
+ <span>&lt;br /&gt;</span>
272
+ </span>
273
+ HTML
274
+ expect(actx.to_s).to eq(html)
275
+ expect(output_buffer actx).to eq(html)
276
+ end
277
+
278
+ it "should escape string contents when passed in block" do
279
+ actx = arbo {
280
+ span {
281
+ span {
282
+ "<br />"
283
+ }
284
+ }
285
+ }
286
+ html = <<-HTML
287
+ <span>
288
+ <span>&lt;br /&gt;</span>
289
+ </span>
290
+ HTML
291
+ expect(actx.to_s).to eq(html)
292
+ expect(output_buffer actx).to eq(html)
293
+ end
294
+
295
+ it "should escape the contents of attributes" do
296
+ actx = arbo {
297
+ span(class: "<br />")
298
+ }
299
+ html = <<-HTML
300
+ <span class="&lt;br /&gt;"></span>
301
+ HTML
302
+ expect(actx.to_s).to eq(html)
303
+ end
304
+
305
+ end
306
+
307
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ # A mock subclass to play with
4
+ class MockComponent < Arbo::Component
5
+
6
+ builder_method :mock_component
7
+
8
+ def build
9
+ h2 "Hello World"
10
+ end
11
+
12
+ end
13
+
14
+ describe Arbo::Component do
15
+
16
+ let(:assigns) { {} }
17
+ let(:helpers) { nil }
18
+
19
+ let(:component_class){ MockComponent }
20
+ let(:component){ component_class.new }
21
+
22
+ it "should be a subclass of an html div" do
23
+ expect(Arbo::Component.ancestors).to include(Arbo::HTML::Div)
24
+ end
25
+
26
+ it "should render to a div, even as a subclass" do
27
+ expect(component.tag_name).to eq('div')
28
+ end
29
+
30
+ it "should add a class by default" do
31
+ expect(component.class_list).to include("mock_component")
32
+ end
33
+
34
+ it "should render (to_s) the object using the builder method name" do
35
+ comp = expect(arbo {
36
+ mock_component
37
+ }.to_s).to eq <<-HTML
38
+ <div class="mock_component">
39
+ <h2>Hello World</h2>
40
+ </div>
41
+ HTML
42
+ end
43
+
44
+ it "should render (render_in) the object using the builder method name" do
45
+ context = arbo { mock_component }
46
+ output_buffer = context.render_in(context)
47
+
48
+ expect(output_buffer).to eq <<-HTML
49
+ <div class="mock_component">
50
+ <h2>Hello World</h2>
51
+ </div>
52
+ HTML
53
+ end
54
+ end
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Arbo::Context do
5
+
6
+ let(:context) do
7
+ Arbo::Context.new do
8
+ h1 "札幌市北区" # Add some HTML to the context
9
+ end
10
+ end
11
+
12
+ it "should not increment the indent_level" do
13
+ expect(context.indent_level).to eq(-1)
14
+ end
15
+
16
+ it "should return a bytesize" do
17
+ expect(context.bytesize).to eq(25)
18
+ end
19
+
20
+ it "should return a length" do
21
+ expect(context.length).to eq(25)
22
+ end
23
+
24
+ it "should delegate missing methods to the html string" do
25
+ expect(context).to respond_to(:index)
26
+ expect(context.index('<')).to eq(0)
27
+ end
28
+
29
+ it "should use a cached version of the HTML for method delegation" do
30
+ expect(context).to receive(:render_in).once.and_return("<h1>札幌市北区</h1>")
31
+ expect(context.index('<')).to eq(0)
32
+ expect(context.index('<')).to eq(0)
33
+ end
34
+
35
+ end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ describe Arbo::Element, "Finder Methods" do
4
+ let(:assigns){ {} }
5
+ let(:helpers){ {} }
6
+
7
+ describe "finding elements by tag name" do
8
+
9
+ it "should return 0 when no elements exist" do
10
+ expect(arbo {
11
+ div
12
+ }.get_elements_by_tag_name("li").size).to eq(0)
13
+ end
14
+
15
+ it "should return a child element" do
16
+ html = arbo do
17
+ ul
18
+ li
19
+ ul
20
+ end
21
+ elements = html.get_elements_by_tag_name("li")
22
+ expect(elements.size).to eq(1)
23
+ expect(elements[0]).to be_instance_of(Arbo::HTML::Li)
24
+ end
25
+
26
+ it "should return multple child elements" do
27
+ html = arbo do
28
+ ul
29
+ li
30
+ ul
31
+ li
32
+ end
33
+ elements = html.get_elements_by_tag_name("li")
34
+ expect(elements.size).to eq(2)
35
+ expect(elements[0]).to be_instance_of(Arbo::HTML::Li)
36
+ expect(elements[1]).to be_instance_of(Arbo::HTML::Li)
37
+ end
38
+
39
+ it "should return children's child elements" do
40
+ html = arbo do
41
+ ul
42
+ li do
43
+ li
44
+ end
45
+ end
46
+ elements = html.get_elements_by_tag_name("li")
47
+ expect(elements.size).to eq(2)
48
+ expect(elements[0]).to be_instance_of(Arbo::HTML::Li)
49
+ expect(elements[1]).to be_instance_of(Arbo::HTML::Li)
50
+ expect(elements[1].parent).to eq(elements[0])
51
+ end
52
+ end
53
+
54
+ #TODO: describe "finding an element by id"
55
+
56
+ describe "finding an element by a class name" do
57
+
58
+ it "should return 0 when no elements exist" do
59
+ expect(arbo {
60
+ div
61
+ }.get_elements_by_class_name("my_class").size).to eq(0)
62
+ end
63
+
64
+ it "should allow text nodes on tree" do
65
+ expect(arbo {
66
+ text_node "text"
67
+ }.get_elements_by_class_name("my_class").size).to eq(0)
68
+ end
69
+
70
+ it "should return a child element" do
71
+ html = arbo do
72
+ div class: "some_class"
73
+ div class: "my_class"
74
+ end
75
+ elements = html.get_elements_by_class_name("my_class")
76
+ expect(elements.size).to eq(1)
77
+ expect(elements[0]).to be_instance_of(Arbo::HTML::Div)
78
+ end
79
+
80
+ it "should return multple child elements" do
81
+ html = arbo do
82
+ div class: "some_class"
83
+ div class: "my_class"
84
+ div class: "my_class"
85
+ end
86
+ elements = html.get_elements_by_class_name("my_class")
87
+ expect(elements.size).to eq(2)
88
+ expect(elements[0]).to be_instance_of(Arbo::HTML::Div)
89
+ expect(elements[1]).to be_instance_of(Arbo::HTML::Div)
90
+ end
91
+
92
+ it "should return elements that match one of several classes" do
93
+ html = arbo do
94
+ div class: "some_class this_class"
95
+ div class: "some_class"
96
+ div class: "other_class"
97
+
98
+ end
99
+ elements = html.get_elements_by_class_name("this_class")
100
+ expect(elements.size).to eq(1)
101
+ expect(elements[0]).to be_instance_of(Arbo::HTML::Div)
102
+ end
103
+
104
+ it "should return a grandchild element" do
105
+ html = arbo do
106
+ div class: "some_class" do
107
+ div class: "my_class"
108
+ end
109
+ end
110
+ elements = html.get_elements_by_class_name("my_class")
111
+ expect(elements.size).to eq(1)
112
+ expect(elements[0]).to be_instance_of(Arbo::HTML::Div)
113
+ end
114
+
115
+ end
116
+ end