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.
- data/ARCH.md +116 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +20 -4
- data/LICENSE +22 -0
- data/README.md +343 -0
- data/Rakefile +25 -17
- data/bench/bench_runner.rb +132 -12
- data/bench/large.html.erb +9 -13
- data/bench/large.html.haml +11 -0
- data/bench/large.html.rb +8 -12
- data/bench/profiler +1 -1
- data/bench/profiler_runner.rb +2 -5
- data/bench/small.html.erb +9 -13
- data/bench/small.html.haml +11 -0
- data/bench/small.html.rb +8 -12
- data/bench/verylarge.html.erb +9 -13
- data/bench/verylarge.html.haml +11 -0
- data/bench/verylarge.html.rb +8 -12
- data/lib/undies/api.rb +163 -0
- data/lib/undies/element.rb +160 -80
- data/lib/undies/element_node.rb +116 -0
- data/lib/undies/io.rb +43 -0
- data/lib/undies/root_node.rb +62 -0
- data/lib/undies/source.rb +78 -2
- data/lib/undies/template.rb +17 -131
- data/lib/undies/version.rb +1 -1
- data/lib/undies.rb +3 -2
- data/test/element_closed_test.rb +69 -0
- data/test/element_node_test.rb +274 -0
- data/test/element_open_test.rb +101 -0
- data/test/element_test.rb +23 -196
- data/test/fixtures/write_thing.rb +4 -4
- data/test/helper.rb +84 -0
- data/test/io_test.rb +104 -0
- data/test/named_source_test.rb +1 -1
- data/test/raw_test.rb +25 -0
- data/test/root_node_test.rb +108 -0
- data/test/source_stack_test.rb +1 -1
- data/test/template_builder_render_test.rb +4 -9
- data/test/template_source_render_test.rb +16 -20
- data/test/template_test.rb +87 -80
- data/test/templates/content.html.rb +1 -1
- data/test/templates/test.html.rb +1 -1
- data/undies.gemspec +1 -0
- metadata +52 -23
- data/README.rdoc +0 -203
- data/lib/undies/named_source.rb +0 -54
- data/lib/undies/node.rb +0 -87
- data/lib/undies/node_stack.rb +0 -111
- data/lib/undies/output.rb +0 -31
- data/lib/undies/source_stack.rb +0 -22
- data/test/node_stack_test.rb +0 -109
- data/test/node_test.rb +0 -91
- data/test/output_test.rb +0 -69
data/bench/bench_runner.rb
CHANGED
@@ -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::
|
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
|
80
|
-
# :large
|
81
|
-
:verylarge
|
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 |
|
89
|
-
|
202
|
+
SIZES.each do |size_desc|
|
203
|
+
UndiesResults.new(size_desc.first).run
|
90
204
|
puts
|
91
|
-
|
205
|
+
ErectorResults.new(size_desc.first).run
|
92
206
|
puts
|
93
|
-
|
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
|
-
<%
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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>
|
data/bench/large.html.rb
CHANGED
@@ -1,18 +1,14 @@
|
|
1
1
|
_html {
|
2
2
|
_head {}
|
3
3
|
_body {
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
data/bench/profiler_runner.rb
CHANGED
@@ -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
|
-
@
|
13
|
+
@io = Undies::IO.new(@out = "")
|
15
14
|
|
16
15
|
@result = RubyProf.profile do
|
17
|
-
|
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
|
-
<%
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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>
|
data/bench/small.html.rb
CHANGED
@@ -1,18 +1,14 @@
|
|
1
1
|
_html {
|
2
2
|
_head {}
|
3
3
|
_body {
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
}
|
data/bench/verylarge.html.erb
CHANGED
@@ -1,19 +1,15 @@
|
|
1
1
|
<html>
|
2
2
|
<head></head>
|
3
3
|
<body>
|
4
|
-
<%
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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>
|
data/bench/verylarge.html.rb
CHANGED
@@ -1,18 +1,14 @@
|
|
1
1
|
_html {
|
2
2
|
_head {}
|
3
3
|
_body {
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|