undies 2.2.1 → 3.0.0.rc.1

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 (54) hide show
  1. data/ARCH.md +116 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +20 -4
  4. data/LICENSE +22 -0
  5. data/README.md +343 -0
  6. data/Rakefile +25 -17
  7. data/bench/bench_runner.rb +132 -12
  8. data/bench/large.html.erb +9 -13
  9. data/bench/large.html.haml +11 -0
  10. data/bench/large.html.rb +8 -12
  11. data/bench/profiler +1 -1
  12. data/bench/profiler_runner.rb +2 -5
  13. data/bench/small.html.erb +9 -13
  14. data/bench/small.html.haml +11 -0
  15. data/bench/small.html.rb +8 -12
  16. data/bench/verylarge.html.erb +9 -13
  17. data/bench/verylarge.html.haml +11 -0
  18. data/bench/verylarge.html.rb +8 -12
  19. data/lib/undies/api.rb +163 -0
  20. data/lib/undies/element.rb +160 -80
  21. data/lib/undies/element_node.rb +116 -0
  22. data/lib/undies/io.rb +43 -0
  23. data/lib/undies/root_node.rb +62 -0
  24. data/lib/undies/source.rb +78 -2
  25. data/lib/undies/template.rb +17 -131
  26. data/lib/undies/version.rb +1 -1
  27. data/lib/undies.rb +3 -2
  28. data/test/element_closed_test.rb +69 -0
  29. data/test/element_node_test.rb +274 -0
  30. data/test/element_open_test.rb +101 -0
  31. data/test/element_test.rb +23 -196
  32. data/test/fixtures/write_thing.rb +4 -4
  33. data/test/helper.rb +84 -0
  34. data/test/io_test.rb +104 -0
  35. data/test/named_source_test.rb +1 -1
  36. data/test/raw_test.rb +25 -0
  37. data/test/root_node_test.rb +108 -0
  38. data/test/source_stack_test.rb +1 -1
  39. data/test/template_builder_render_test.rb +4 -9
  40. data/test/template_source_render_test.rb +16 -20
  41. data/test/template_test.rb +87 -80
  42. data/test/templates/content.html.rb +1 -1
  43. data/test/templates/test.html.rb +1 -1
  44. data/undies.gemspec +1 -0
  45. metadata +52 -23
  46. data/README.rdoc +0 -203
  47. data/lib/undies/named_source.rb +0 -54
  48. data/lib/undies/node.rb +0 -87
  49. data/lib/undies/node_stack.rb +0 -111
  50. data/lib/undies/output.rb +0 -31
  51. data/lib/undies/source_stack.rb +0 -22
  52. data/test/node_stack_test.rb +0 -109
  53. data/test/node_test.rb +0 -91
  54. data/test/output_test.rb +0 -69
@@ -1,8 +1,10 @@
1
1
  require 'whysoslow'
2
- require 'stringio'
3
2
 
4
3
  require 'erb'
5
4
  require 'erubis'
5
+ require 'haml'
6
+ require 'markaby'
7
+ require 'erector'
6
8
  require 'undies'
7
9
 
8
10
  class UndiesBenchResults
@@ -37,18 +39,130 @@ end
37
39
  class UndiesResults < UndiesBenchResults
38
40
 
39
41
  def initialize(size='large')
40
- @outstream = StringIO.new(@out = "")
41
42
  super(:undies, '.rb', size, Proc.new do
42
43
  Undies::Template.new(
43
44
  Undies::Source.new(self.file),
44
45
  {},
45
- Undies::Output.new(@outstream, :pp => 2)
46
+ Undies::IO.new(@out = "", :pp => 2)
46
47
  )
47
48
  end)
48
49
  end
49
50
 
50
51
  end
51
52
 
53
+ class MarkabyResults < UndiesBenchResults
54
+
55
+ BUILDS = {}
56
+
57
+ BUILDS['small'] = Proc.new do
58
+ head {}
59
+ body do
60
+ 100.times do |n|
61
+ span "Yo", :id => "cool-#{n}!"
62
+ p "Yo", :class => "awesome"
63
+
64
+ br
65
+
66
+ div :class => 'last' do
67
+ span "Hi " + em('there') + '!!'
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ BUILDS['large'] = Proc.new do
74
+ head {}
75
+ body do
76
+ 1000.times do |n|
77
+ span "Yo", :id => "cool-#{n}!"
78
+ p "Yo", :class => "awesome"
79
+
80
+ br
81
+
82
+ div :class => 'last' do
83
+ span "Hi " + em('there') + '!!'
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ BUILDS['verylarge'] = Proc.new do
90
+ head {}
91
+ body do
92
+ 10000.times do |n|
93
+ span "Yo", :id => "cool-#{n}!"
94
+ p "Yo", :class => "awesome"
95
+
96
+ br
97
+
98
+ div :class => 'last' do
99
+ span "Hi " + em('there') + '!!'
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ def initialize(size='large')
106
+ @out = ""
107
+ super(:markaby, '.mab', size, Proc.new do
108
+ mab = Markaby::Builder.new
109
+ mab.html &BUILDS[size.to_s]
110
+ @out = mab.to_s
111
+ end)
112
+ end
113
+
114
+ end
115
+
116
+ class ErectorResults < UndiesBenchResults
117
+
118
+ class Build < Erector::Widget
119
+ def content
120
+ head {}
121
+ body do
122
+ @num.times do |n|
123
+ span "Yo", :id => "cool-#{n}!"
124
+ p "Yo", :class => "awesome"
125
+
126
+ br
127
+
128
+ div :class => 'last' do
129
+ span do
130
+ text "Hi "
131
+ em "there"
132
+ text "!!"
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ BUILDS = {}
141
+
142
+ BUILDS['small'] = Build.new(:num => 100)
143
+ BUILDS['large'] = Build.new(:num => 1000)
144
+ BUILDS['verylarge'] = Build.new(:num => 10000)
145
+
146
+ def initialize(size='large')
147
+ @out = ""
148
+ super(:erector, '.erc', size, Proc.new do
149
+ @out = BUILDS[size.to_s].to_html(:prettyprint => true)
150
+ end)
151
+ end
152
+
153
+ end
154
+
155
+ class HamlResults < UndiesBenchResults
156
+
157
+ def initialize(size='large')
158
+ @out = ""
159
+ super(:haml, '.haml', size, Proc.new do
160
+ @out = ::Haml::Engine.new(File.read(self.file)).to_html
161
+ end)
162
+ end
163
+
164
+ end
165
+
52
166
  class ErbResults < UndiesBenchResults
53
167
 
54
168
  def initialize(size='large')
@@ -75,23 +189,29 @@ end
75
189
 
76
190
  class UndiesBenchRunner
77
191
 
78
- SIZES = {
79
- # :small => "~20 nodes",
80
- # :large => "~2000 nodes",
81
- :verylarge => "~20000 nodes"
82
- }
192
+ SIZES = [
193
+ # [:small , "~500 nodes"],
194
+ # [:large , "~5000 nodes"],
195
+ [:verylarge, "~50000 nodes"]
196
+ ]
83
197
 
84
198
 
85
199
  def initialize
86
200
  puts "Benchmark Results:"
87
201
  puts
88
- SIZES.each do |size, desc|
89
- ErbResults.new(size).run
202
+ SIZES.each do |size_desc|
203
+ UndiesResults.new(size_desc.first).run
90
204
  puts
91
- ErubisResults.new(size).run
205
+ ErectorResults.new(size_desc.first).run
92
206
  puts
93
- UndiesResults.new(size).run
207
+ MarkabyResults.new(size_desc.first).run
94
208
  puts
209
+ # HamlResults.new(size_desc.first).run
210
+ # puts
211
+ # ErbResults.new(size_desc.first).run
212
+ # puts
213
+ # ErubisResults.new(size_desc.first).run
214
+ # puts
95
215
  end
96
216
  puts
97
217
  end
data/bench/large.html.erb CHANGED
@@ -1,19 +1,15 @@
1
1
  <html>
2
2
  <head></head>
3
3
  <body>
4
- <% 100.times do %>
5
- <% 5.times do %>
6
- Yo
7
- <% end %>
8
- <% 5.times do %>
9
- YoYo
10
- <% end %>
11
- <% 5.times do %>
12
- <br />
13
- <% end %>
14
- <% 5.times do %>
15
- <div>Hi</div>
16
- <% end %>
4
+ <% 1000.times do %>
5
+ <span id="cool">Yo</span>
6
+ <p class="awesome">Yo</p>
7
+
8
+ <br />
9
+
10
+ <div class="last">
11
+ <span>Hi</span>
12
+ </div>
17
13
  <% end %>
18
14
  </body>
19
15
  </html>
@@ -0,0 +1,11 @@
1
+ %html
2
+ %head
3
+ %body
4
+ - 1000.times do
5
+ %span#cool "Yo"
6
+ %p.awesome "Yo"
7
+
8
+ %br
9
+
10
+ %div.last
11
+ %span "Hi "
data/bench/large.html.rb CHANGED
@@ -1,18 +1,14 @@
1
1
  _html {
2
2
  _head {}
3
3
  _body {
4
- 100.times do
5
- 5.times do
6
- _ "Yo"
7
- end
8
- 5.times do
9
- __ "YoYo"
10
- end
11
- 5.times do
12
- _br
13
- end
14
- 5.times do
15
- _div { _ "Hi" }
4
+ 1000.times do |n|
5
+ _span "Yo", :id => "cool-#{n}!"
6
+ _p "Yo", :class => "awesome"
7
+
8
+ _br
9
+
10
+ _div :class => 'last' do
11
+ _span "Hi ", em('there'), '!!'
16
12
  end
17
13
  end
18
14
  }
data/bench/profiler CHANGED
@@ -3,4 +3,4 @@
3
3
  require 'bench/profiler_runner'
4
4
 
5
5
  runner = UndiesProfilerRunner.new(ARGV[0] || 'large')
6
- runner.print_flat(STDOUT, :min_percent => 1)
6
+ runner.print_flat(STDOUT)
@@ -1,4 +1,3 @@
1
- require 'stringio'
2
1
  require 'ruby-prof'
3
2
  require 'undies'
4
3
  require 'bench/procs'
@@ -11,12 +10,10 @@ class UndiesProfilerRunner
11
10
  file = "bench/#{size || 'large'}.html.rb"
12
11
  @source = Undies::Source.new(File.expand_path(file))
13
12
  @data = {}
14
- @output = Undies::Output.new(StringIO.new(@out = ""))
13
+ @io = Undies::IO.new(@out = "")
15
14
 
16
15
  @result = RubyProf.profile do
17
- 10.times do
18
- Undies::Template.new(@source, @data, @output)
19
- end
16
+ Undies::Template.new(@source, @data, @io)
20
17
  end
21
18
 
22
19
  end
data/bench/small.html.erb CHANGED
@@ -1,19 +1,15 @@
1
1
  <html>
2
2
  <head></head>
3
3
  <body>
4
- <% 1.times do %>
5
- <% 5.times do %>
6
- Yo
7
- <% end %>
8
- <% 5.times do %>
9
- YoYo
10
- <% end %>
11
- <% 5.times do %>
12
- <br />
13
- <% end %>
14
- <% 5.times do %>
15
- <div>Hi</div>
16
- <% end %>
4
+ <% 100.times do %>
5
+ <span id="cool">Yo</span>
6
+ <p class="awesome">Yo</p>
7
+
8
+ <br />
9
+
10
+ <div class="last">
11
+ <span>Hi</span>
12
+ </div>
17
13
  <% end %>
18
14
  </body>
19
15
  </html>
@@ -0,0 +1,11 @@
1
+ %html
2
+ %head
3
+ %body
4
+ - 100.times do
5
+ %span#cool "Yo"
6
+ %p.awesome "Yo"
7
+
8
+ %br
9
+
10
+ %div.last
11
+ %span "Hi "
data/bench/small.html.rb CHANGED
@@ -1,18 +1,14 @@
1
1
  _html {
2
2
  _head {}
3
3
  _body {
4
- 1.times do
5
- 5.times do
6
- _ "Yo"
7
- end
8
- 5.times do
9
- __ "YoYo"
10
- end
11
- 5.times do
12
- _br
13
- end
14
- 5.times do
15
- _div { _ "Hi" }
4
+ 100.times do |n|
5
+ _span "Yo", :id => "cool-#{n}!"
6
+ _p "Yo", :class => "awesome"
7
+
8
+ _br
9
+
10
+ _div :class => 'last' do
11
+ _span "Hi ", em('there'), '!!'
16
12
  end
17
13
  end
18
14
  }
@@ -1,19 +1,15 @@
1
1
  <html>
2
2
  <head></head>
3
3
  <body>
4
- <% 1000.times do %>
5
- <% 5.times do %>
6
- Yo
7
- <% end %>
8
- <% 5.times do %>
9
- YoYo
10
- <% end %>
11
- <% 5.times do %>
12
- <br />
13
- <% end %>
14
- <% 5.times do %>
15
- <div>Hi</div>
16
- <% end %>
4
+ <% 10000.times do %>
5
+ <span id="cool">Yo</span>
6
+ <p class="awesome">Yo</p>
7
+
8
+ <br />
9
+
10
+ <div class="last">
11
+ <span>Hi</span>
12
+ </div>
17
13
  <% end %>
18
14
  </body>
19
15
  </html>
@@ -0,0 +1,11 @@
1
+ %html
2
+ %head
3
+ %body
4
+ - 10000.times do
5
+ %span#cool "Yo"
6
+ %p.awesome "Yo"
7
+
8
+ %br
9
+
10
+ %div.last
11
+ %span "Hi "
@@ -1,18 +1,14 @@
1
1
  _html {
2
2
  _head {}
3
3
  _body {
4
- 1000.times do
5
- 5.times do
6
- _ "Yo"
7
- end
8
- 5.times do
9
- __ "YoYo"
10
- end
11
- 5.times do
12
- _br
13
- end
14
- 5.times do
15
- _div { _ "Hi" }
4
+ 10000.times do |n|
5
+ _span "Yo", :id => "cool-#{n}!"
6
+ _p "Yo", :class => "awesome"
7
+
8
+ _br
9
+
10
+ _div :class => 'last' do
11
+ _span "Hi ", em('there'), '!!'
16
12
  end
17
13
  end
18
14
  }
data/lib/undies/api.rb ADDED
@@ -0,0 +1,163 @@
1
+ require 'undies/element_node'
2
+ require 'undies/element'
3
+
4
+ module Undies
5
+
6
+ module API
7
+
8
+ # HTML tag helpers
9
+
10
+ SELF_CLOSING_TAGS = [
11
+ :area,
12
+ :base, :br,
13
+ :col,
14
+ :embed,
15
+ :frame,
16
+ :hr,
17
+ :img, :input,
18
+ :link,
19
+ :meta,
20
+ :param
21
+ ]
22
+
23
+ OPEN_TAGS = [
24
+ :a, :abbr, :acronym, :address, :article, :aside, :audio,
25
+ :b, :bdo, :big, :blockquote, :body, :button,
26
+ :canvas, :caption, :center, :cite, :code, :colgroup, :command,
27
+ :datalist, :dd, :del, :details, :dfn, :dialog, :div, :dl, :dt,
28
+ :em,
29
+ :fieldset, :figure, :footer, :form, :frameset,
30
+ :h1, :h2, :h3, :h4, :h5, :h6, :head, :header, :hgroup, :html,
31
+ :i, :iframe, :ins,
32
+ :keygen, :kbd,
33
+ :label, :legend, :li,
34
+ :map, :mark, :meter,
35
+ :nav, :noframes, :noscript,
36
+ :object, :ol, :optgroup, :option,
37
+ :p, :pre, :progress,
38
+ :q,
39
+ :ruby, :rt, :rp,
40
+ :s, :samp, :script, :section, :select, :small, :source, :span, :strike, :strong, :style, :sub, :sup,
41
+ :table, :tbody, :td, :textarea, :tfoot, :th, :thead, :time, :title, :tr, :tt,
42
+ :u, :ul,
43
+ :v, :video
44
+ ]
45
+
46
+ # capture methods
47
+
48
+ def raw(string)
49
+ Raw.new(string)
50
+ end
51
+
52
+ def open_element(name, *args)
53
+ Raw.new(Element::Open.new(name, *args).to_s)
54
+ end
55
+ alias_method :open_tag, :open_element
56
+ alias_method :element, :open_element
57
+ alias_method :tag, :open_element
58
+
59
+ def closed_element(name, *args)
60
+ Raw.new(Element::Closed.new(name, *args).to_s)
61
+ end
62
+ alias_method :closed_tag, :closed_element
63
+
64
+ SELF_CLOSING_TAGS.each do |tag|
65
+ define_method(tag){ |*args| closed_element(tag, *args, &build) }
66
+ end
67
+
68
+ OPEN_TAGS.each do |tag|
69
+ define_method(tag){ |*args| open_element(tag, *args) }
70
+ end
71
+
72
+ # streaming methods
73
+
74
+ # Add a text node (data escaped) to the nodes of the current node
75
+ def _(data="")
76
+ @_undies_io.current.text(self.class.escape_html(data.to_s))
77
+ end
78
+
79
+ def __open_element(name, *args, &build)
80
+ @_undies_io.
81
+ current.
82
+ element_node(ElementNode.new(@_undies_io, Element::Open.new(name, *args, &build))).
83
+ element
84
+ end
85
+ alias_method :__open_tag, :__open_element
86
+ alias_method :__element, :__open_element
87
+ alias_method :__tag, :__open_element
88
+
89
+ def __closed_element(name, *args, &build)
90
+ @_undies_io.
91
+ current.
92
+ element_node(ElementNode.new(@_undies_io, Element::Closed.new(name, *args, &build))).
93
+ element
94
+ end
95
+ alias_method :__closed_tag, :__closed_element
96
+
97
+ SELF_CLOSING_TAGS.each do |tag|
98
+ define_method("_#{tag}") do |*args, &build|
99
+ __closed_element(tag, *args, &build)
100
+ end
101
+ end
102
+
103
+ OPEN_TAGS.each do |tag|
104
+ define_method("_#{tag}") do |*args, &build|
105
+ __open_element(tag, *args, &build)
106
+ end
107
+ end
108
+
109
+ # Manual Builder methods
110
+
111
+ # call this method to manually push the current scope to the previously
112
+ # cached element (if any)
113
+ # - changes the context of template method calls to operate on that element
114
+ def __push
115
+ @_undies_io.current.push
116
+ end
117
+
118
+ # call this method to manually pop the current scope to the previous scope
119
+ # - changes the context of template method calls to operate on the parent
120
+ # element or root node
121
+ def __pop
122
+ @_undies_io.current.pop
123
+ end
124
+
125
+ # call this to manually flush a template
126
+ def __flush
127
+ @_undies_io.current.flush
128
+ end
129
+
130
+ # call this to modify element attrs inside a build block. Once content
131
+ # or child elements have been added, any '__attr' directives will
132
+ # be ignored b/c the elements start_tag has already been flushed
133
+ # to the output
134
+ def __attrs(attrs_hash={})
135
+ @_undies_io.current.attrs(attrs_hash)
136
+ end
137
+
138
+ # Source handling methods
139
+
140
+ # call this to render template source
141
+ # use this method in layouts to insert a layout's content source
142
+ def __yield
143
+ return if (source = @_undies_source_stack.pop).nil?
144
+ if source.file?
145
+ instance_eval(source.data, source.source, 1)
146
+ else
147
+ instance_eval(&source.data)
148
+ end
149
+ end
150
+
151
+ # call this to render partial source embedded in a template
152
+ # partial source is rendered with its own scope/data but shares
153
+ # its parent template's output object
154
+ def __partial(source, data={})
155
+ if source.kind_of?(Source)
156
+ Undies::Template.new(source, data, @_undies_io)
157
+ else
158
+ @_undies_io.current.partial(source.to_s)
159
+ end
160
+ end
161
+
162
+ end
163
+ end