simply 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README +4 -0
- data/Rakefile +17 -0
- data/VERSION.yml +5 -0
- data/benchmarks/001_7a22450a80d6253bf9f0aabb2ee0110c2d67c8a6.out +23 -0
- data/benchmarks/002_e462499cd6bd8dface62e433311b3bc0b0b55a42 +27 -0
- data/benchmarks/comparison.rb +224 -0
- data/lib/simply/html_builder.rb +127 -0
- data/lib/simply/html_tags.rb +126 -0
- data/lib/simply/indentation.rb +37 -0
- data/lib/simply/locals.rb +29 -0
- data/lib/simply/version.rb +12 -0
- data/lib/simply.rb +18 -0
- data/profiling/run_static.rb +18 -0
- data/profiling/run_static_001_0e246c3de41a891c206c8cb5a552d17d78e4b8ec.out +157 -0
- data/reference/ABOUT +5 -0
- data/reference/xhtml1-frameset.xsd +2847 -0
- data/reference/xhtml1-strict.xsd +2211 -0
- data/reference/xhtml1-transitional.xsd +2755 -0
- data/simply.gemspec +58 -0
- data/spec/simply/html_builder/indentation_spec.rb +44 -0
- data/spec/simply/html_builder/locals_spec.rb +60 -0
- data/spec/simply/html_builder_spec.rb +148 -0
- data/spec/simply/indentation_spec.rb +72 -0
- data/spec/simply/simply_spec.rb +45 -0
- data/spec/simply/version_spec.rb +7 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +5 -0
- metadata +88 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg
|
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
PROJECT_NAME = "simply"
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |s|
|
8
|
+
s.name = PROJECT_NAME
|
9
|
+
s.summary = "A markaby-like html builder"
|
10
|
+
s.email = "scott@railsnewbie.com"
|
11
|
+
s.homepage = "http://github.com/smtlaissezfaire/#{PROJECT_NAME.downcase}"
|
12
|
+
s.description = "Cleaner + smaller markaby clone."
|
13
|
+
s.authors = ["Scott Taylor"]
|
14
|
+
end
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
17
|
+
end
|
data/VERSION.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# of iterations = 10000
|
2
|
+
Rehearsal ------------------------------------------------------------------------------
|
3
|
+
counter time 0.000000 0.000000 0.000000 ( 0.001091)
|
4
|
+
counter time + function call overhead time 0.000000 0.000000 0.000000 ( 0.002866)
|
5
|
+
tagz 2.340000 0.020000 2.360000 ( 2.356264)
|
6
|
+
markaby 8.720000 0.030000 8.750000 ( 8.764424)
|
7
|
+
builder 2.140000 0.010000 2.150000 ( 2.154632)
|
8
|
+
haml 5.620000 0.010000 5.630000 ( 5.652289)
|
9
|
+
erb 2.240000 0.010000 2.250000 ( 2.248454)
|
10
|
+
erubis 0.420000 0.000000 0.420000 ( 0.418306)
|
11
|
+
simply 2.010000 0.000000 2.010000 ( 2.018264)
|
12
|
+
-------------------------------------------------------------------- total: 23.570000sec
|
13
|
+
|
14
|
+
user system total real
|
15
|
+
counter time 0.000000 0.000000 0.000000 ( 0.001062)
|
16
|
+
counter time + function call overhead time 0.000000 0.000000 0.000000 ( 0.002849)
|
17
|
+
tagz 2.220000 0.010000 2.230000 ( 2.238662)
|
18
|
+
markaby 9.210000 0.030000 9.240000 ( 9.261845)
|
19
|
+
builder 1.930000 0.000000 1.930000 ( 1.934298)
|
20
|
+
haml 5.220000 0.010000 5.230000 ( 5.235850)
|
21
|
+
erb 2.330000 0.010000 2.340000 ( 2.339981)
|
22
|
+
erubis 0.430000 0.000000 0.430000 ( 0.437849)
|
23
|
+
simply 2.210000 0.010000 2.220000 ( 2.223844)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# of iterations = 10000
|
2
|
+
Rehearsal ------------------------------------------------------------------------------
|
3
|
+
counter time 0.000000 0.000000 0.000000 ( 0.001055)
|
4
|
+
counter time + function call overhead time 0.010000 0.000000 0.010000 ( 0.003877)
|
5
|
+
tagz 2.620000 0.020000 2.640000 ( 2.675130)
|
6
|
+
markaby 10.220000 0.070000 10.290000 ( 10.403767)
|
7
|
+
builder 1.070000 0.000000 1.070000 ( 1.089509)
|
8
|
+
haml 5.690000 0.040000 5.730000 ( 5.770631)
|
9
|
+
erb 2.400000 0.010000 2.410000 ( 2.436488)
|
10
|
+
erubis 0.470000 0.000000 0.470000 ( 0.476391)
|
11
|
+
nokogiri 1.930000 0.010000 1.940000 ( 1.961594)
|
12
|
+
simply 1.450000 0.010000 1.460000 ( 1.465180)
|
13
|
+
erector 0.150000 0.000000 0.150000 ( 0.155925)
|
14
|
+
-------------------------------------------------------------------- total: 26.170000sec
|
15
|
+
|
16
|
+
user system total real
|
17
|
+
counter time 0.000000 0.000000 0.000000 ( 0.001063)
|
18
|
+
counter time + function call overhead time 0.000000 0.000000 0.000000 ( 0.003963)
|
19
|
+
tagz 2.630000 0.020000 2.650000 ( 2.669872)
|
20
|
+
markaby 10.200000 0.060000 10.260000 ( 10.367525)
|
21
|
+
builder 1.070000 0.010000 1.080000 ( 1.093933)
|
22
|
+
haml 5.650000 0.040000 5.690000 ( 5.745920)
|
23
|
+
erb 2.420000 0.020000 2.440000 ( 2.462542)
|
24
|
+
erubis 0.430000 0.000000 0.430000 ( 0.439791)
|
25
|
+
nokogiri 1.930000 0.010000 1.940000 ( 1.967485)
|
26
|
+
simply 1.380000 0.010000 1.390000 ( 1.405759)
|
27
|
+
erector 0.160000 0.000000 0.160000 ( 0.155949)
|
@@ -0,0 +1,224 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'benchmark'
|
3
|
+
require "erb"
|
4
|
+
require 'rubygems'
|
5
|
+
require 'markaby'
|
6
|
+
require 'tagz'
|
7
|
+
require 'builder'
|
8
|
+
require 'haml'
|
9
|
+
require 'erubis'
|
10
|
+
require "nokogiri"
|
11
|
+
require "erector"
|
12
|
+
require File.dirname(__FILE__) + "/../lib/simply"
|
13
|
+
|
14
|
+
MAX = (ARGV.shift || 10_000).to_i
|
15
|
+
|
16
|
+
def do_nothing
|
17
|
+
# do nothing
|
18
|
+
end
|
19
|
+
|
20
|
+
def do_erb
|
21
|
+
str = <<-EOF
|
22
|
+
<html>
|
23
|
+
<head>
|
24
|
+
<title>happy title</title>
|
25
|
+
</head>
|
26
|
+
<body>
|
27
|
+
<h1>happy heading</h1>
|
28
|
+
<a href='<%= 'url' %>'>a link</a>
|
29
|
+
</body>
|
30
|
+
</html>
|
31
|
+
EOF
|
32
|
+
ERB.new(str)
|
33
|
+
end
|
34
|
+
|
35
|
+
def do_erubis
|
36
|
+
str = <<-EOF
|
37
|
+
<html>
|
38
|
+
<head>
|
39
|
+
<title>happy title</title>
|
40
|
+
</head>
|
41
|
+
<body>
|
42
|
+
<h1>happy heading</h1>
|
43
|
+
<a href='<%= 'url' %>'>a link</a>
|
44
|
+
</body>
|
45
|
+
</html>
|
46
|
+
EOF
|
47
|
+
Erubis::Eruby.new(str)
|
48
|
+
end
|
49
|
+
|
50
|
+
def do_haml
|
51
|
+
str = <<-EOF
|
52
|
+
%html
|
53
|
+
%head
|
54
|
+
%title_ "happy title"
|
55
|
+
%body
|
56
|
+
%h1 "happy heading"
|
57
|
+
%a "a link", :href => "url"
|
58
|
+
EOF
|
59
|
+
Haml::Engine.new(str)
|
60
|
+
end
|
61
|
+
|
62
|
+
def do_tagz
|
63
|
+
Tagz {
|
64
|
+
html_ {
|
65
|
+
head_ {
|
66
|
+
title_ "happy title"
|
67
|
+
}
|
68
|
+
body_ {
|
69
|
+
h1_ "happy heading"
|
70
|
+
a_ "a link", :href => "url"
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
def do_builder
|
77
|
+
Builder::XmlMarkup.new.html do |xm|
|
78
|
+
xm.head do
|
79
|
+
xm.title "happy title"
|
80
|
+
end
|
81
|
+
xm.body do
|
82
|
+
xm.h1 "happy heading"
|
83
|
+
xm.a "a link", :href => "url"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def do_markaby
|
89
|
+
mab = Markaby::Builder.new :output_meta_tag => false
|
90
|
+
|
91
|
+
mab.html {
|
92
|
+
head {
|
93
|
+
title "happy title"
|
94
|
+
}
|
95
|
+
body {
|
96
|
+
h1 "happy heading"
|
97
|
+
a "a link", :href => "url"
|
98
|
+
}
|
99
|
+
}.to_s
|
100
|
+
end
|
101
|
+
|
102
|
+
def do_simply
|
103
|
+
Simply do
|
104
|
+
html do
|
105
|
+
head do
|
106
|
+
title "happy title"
|
107
|
+
end
|
108
|
+
|
109
|
+
body do
|
110
|
+
h1 "happy heading"
|
111
|
+
a "a link", :href => "url"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def do_nokogiri
|
118
|
+
Nokogiri do
|
119
|
+
html do
|
120
|
+
head do
|
121
|
+
title "happy title"
|
122
|
+
end
|
123
|
+
|
124
|
+
body do
|
125
|
+
h1 "happy heading"
|
126
|
+
a :href => "url" do
|
127
|
+
text "a link"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def do_erector
|
135
|
+
Erector::Widget.new do
|
136
|
+
html do
|
137
|
+
head do
|
138
|
+
title "happy title"
|
139
|
+
end
|
140
|
+
|
141
|
+
body do
|
142
|
+
h1 "happy heading"
|
143
|
+
a "a link", :href => "url"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
x = do_tagz
|
151
|
+
y = do_markaby
|
152
|
+
z = do_builder
|
153
|
+
|
154
|
+
raise "bad!\n\n#{x}\n\n#{y}" unless x == y
|
155
|
+
raise "bad!\n\n#{x}\n\n#{z}" unless x == z
|
156
|
+
|
157
|
+
puts "# of iterations = #{MAX}"
|
158
|
+
Benchmark.bmbm do |x|
|
159
|
+
x.report("counter time") do
|
160
|
+
for i in 0..MAX
|
161
|
+
# do nothing
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
x.report("counter time + function call overhead time") do
|
166
|
+
for i in 0..MAX do
|
167
|
+
do_nothing
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
x.report("tagz") do
|
172
|
+
for i in 0..MAX do
|
173
|
+
do_tagz
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
x.report("markaby") do
|
178
|
+
for i in 0..MAX do
|
179
|
+
do_markaby
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
x.report("builder") do
|
184
|
+
for i in 0..MAX do
|
185
|
+
do_builder
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
x.report("haml") do
|
190
|
+
for i in 0..MAX do
|
191
|
+
do_haml
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
x.report("erb") do
|
196
|
+
for i in 0..MAX do
|
197
|
+
do_erb
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
x.report("erubis") do
|
202
|
+
for i in 0..MAX do
|
203
|
+
do_erubis
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
x.report("nokogiri") do
|
208
|
+
for i in 0..MAX do
|
209
|
+
do_nokogiri
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
x.report("simply") do
|
214
|
+
for i in 0..MAX do
|
215
|
+
do_simply
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
x.report("erector") do
|
220
|
+
for i in 0..MAX do
|
221
|
+
do_erector
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module Simply
|
2
|
+
class HTMLBuilder
|
3
|
+
include Locals
|
4
|
+
|
5
|
+
unless defined?(SELF_CLOSING_TAGS)
|
6
|
+
SELF_CLOSING_TAGS = HTMLTags::SELF_CLOSING_TAGS
|
7
|
+
BLOCK_TAGS = HTMLTags::BLOCK_TAGS
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(options={ }, &block)
|
11
|
+
@out = ""
|
12
|
+
|
13
|
+
if locals_hash = options[:locals]
|
14
|
+
self.locals = locals_hash
|
15
|
+
end
|
16
|
+
|
17
|
+
@indented = true if options[:indent] == true
|
18
|
+
@out.extend Indentation if indented?
|
19
|
+
|
20
|
+
instance_eval(&block) if block_given?
|
21
|
+
end
|
22
|
+
|
23
|
+
def indented?
|
24
|
+
@indented ? true : false
|
25
|
+
end
|
26
|
+
|
27
|
+
SELF_CLOSING_TAGS.each do |tag|
|
28
|
+
class_eval <<-HERE, __FILE__, __LINE__
|
29
|
+
def #{tag}(attributes={})
|
30
|
+
__self_closing_tag(:#{tag}, attributes)
|
31
|
+
end
|
32
|
+
HERE
|
33
|
+
end
|
34
|
+
|
35
|
+
BLOCK_TAGS.each do |tag|
|
36
|
+
class_eval <<-HERE, __FILE__, __LINE__
|
37
|
+
def #{tag}(*args, &block)
|
38
|
+
raise ArgumentError if !block_given? && args.empty?
|
39
|
+
|
40
|
+
if block_given? || args.first.is_a?(Hash)
|
41
|
+
options = args.first || { }
|
42
|
+
else
|
43
|
+
block = lambda { clean_text args.first.to_s }
|
44
|
+
options = args[1] || { }
|
45
|
+
end
|
46
|
+
|
47
|
+
__tag(:#{tag}, options, &block)
|
48
|
+
end
|
49
|
+
HERE
|
50
|
+
end
|
51
|
+
|
52
|
+
def xhtml_transitional
|
53
|
+
text HTMLTags::XML_ENCODING
|
54
|
+
text HTMLTags::TRANSITIONAL
|
55
|
+
end
|
56
|
+
|
57
|
+
def xhtml_strict
|
58
|
+
text HTMLTags::XML_ENCODING
|
59
|
+
text HTMLTags::STRICT
|
60
|
+
end
|
61
|
+
|
62
|
+
def xhtml_frameset
|
63
|
+
text HTMLTags::XML_ENCODING
|
64
|
+
text HTMLTags::FRAMESET
|
65
|
+
end
|
66
|
+
|
67
|
+
####################
|
68
|
+
#
|
69
|
+
# Utilities
|
70
|
+
#
|
71
|
+
####################
|
72
|
+
|
73
|
+
def text(out)
|
74
|
+
@out << out.to_s
|
75
|
+
end
|
76
|
+
|
77
|
+
def clean_text(out)
|
78
|
+
text html_escape(out)
|
79
|
+
end
|
80
|
+
|
81
|
+
def html_escape(out)
|
82
|
+
out.to_s.to_xs
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_s
|
86
|
+
@out
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def __tag(tag_name, attributes={ }, &block)
|
92
|
+
text __opening_tag(tag_name, attributes)
|
93
|
+
__eval_block(&block)
|
94
|
+
text __closing_tag(tag_name)
|
95
|
+
end
|
96
|
+
|
97
|
+
def __eval_block(&block)
|
98
|
+
@out.indent if indented?
|
99
|
+
instance_eval(&block)
|
100
|
+
@out.outdent if indented?
|
101
|
+
end
|
102
|
+
|
103
|
+
def __opening_tag(tag_name, attributes={ })
|
104
|
+
if attributes.any?
|
105
|
+
"<#{tag_name} #{__expand_attributes(attributes)}>"
|
106
|
+
else
|
107
|
+
"<#{tag_name}>"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def __closing_tag(tag_name)
|
112
|
+
"</#{tag_name}>"
|
113
|
+
end
|
114
|
+
|
115
|
+
def __self_closing_tag(tag_name, attributes={ })
|
116
|
+
if attributes.any?
|
117
|
+
text "<#{tag_name} #{__expand_attributes(attributes)} />"
|
118
|
+
else
|
119
|
+
text "<#{tag_name} />"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def __expand_attributes(attributes)
|
124
|
+
attributes.map { |key, value| "#{key}=\"#{value}\""}.join(" ")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Simply
|
2
|
+
module HTMLTags
|
3
|
+
unless defined?(XML_ENCODING)
|
4
|
+
XML_ENCODING = '<?xml version="1.0" encoding="UTF-8"?>'.freeze
|
5
|
+
|
6
|
+
STRICT = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'.freeze
|
7
|
+
TRANSITIONAL = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'.freeze
|
8
|
+
FRAMESET = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">'.freeze
|
9
|
+
|
10
|
+
SELF_CLOSING_TAGS = [
|
11
|
+
:base,
|
12
|
+
:meta,
|
13
|
+
:link,
|
14
|
+
:hr,
|
15
|
+
:br,
|
16
|
+
:param,
|
17
|
+
:img,
|
18
|
+
:area,
|
19
|
+
:input,
|
20
|
+
:col,
|
21
|
+
:frame
|
22
|
+
]
|
23
|
+
|
24
|
+
BLOCK_TAGS = [
|
25
|
+
:html,
|
26
|
+
:head,
|
27
|
+
:title,
|
28
|
+
:style,
|
29
|
+
:script,
|
30
|
+
:noscript,
|
31
|
+
:body,
|
32
|
+
:div,
|
33
|
+
:p,
|
34
|
+
:ul,
|
35
|
+
:ol,
|
36
|
+
:li,
|
37
|
+
:dl,
|
38
|
+
:dt,
|
39
|
+
:dd,
|
40
|
+
:address,
|
41
|
+
:pre,
|
42
|
+
:blockquote,
|
43
|
+
:ins,
|
44
|
+
:del,
|
45
|
+
:a,
|
46
|
+
:span,
|
47
|
+
:bdo,
|
48
|
+
:em,
|
49
|
+
:strong,
|
50
|
+
:dfn,
|
51
|
+
:code,
|
52
|
+
:samp,
|
53
|
+
:kbd,
|
54
|
+
:var,
|
55
|
+
:cite,
|
56
|
+
:abbr,
|
57
|
+
:acronym,
|
58
|
+
:q,
|
59
|
+
:sub,
|
60
|
+
:sup,
|
61
|
+
:tt,
|
62
|
+
:i,
|
63
|
+
:b,
|
64
|
+
:big,
|
65
|
+
:small,
|
66
|
+
:object,
|
67
|
+
:map,
|
68
|
+
:form,
|
69
|
+
:label,
|
70
|
+
:select,
|
71
|
+
:optgroup,
|
72
|
+
:option,
|
73
|
+
:textarea,
|
74
|
+
:fieldset,
|
75
|
+
:legend,
|
76
|
+
:button,
|
77
|
+
:table,
|
78
|
+
:caption,
|
79
|
+
:colgroup,
|
80
|
+
:thead,
|
81
|
+
:tfoot,
|
82
|
+
:tbody,
|
83
|
+
:tr,
|
84
|
+
:th,
|
85
|
+
:td,
|
86
|
+
:h1,
|
87
|
+
:h2,
|
88
|
+
:h3,
|
89
|
+
:h4,
|
90
|
+
:h5,
|
91
|
+
:h6,
|
92
|
+
:strike,
|
93
|
+
:center,
|
94
|
+
:dir,
|
95
|
+
:noframes,
|
96
|
+
:basefont,
|
97
|
+
:u,
|
98
|
+
:menu,
|
99
|
+
:iframe,
|
100
|
+
:font,
|
101
|
+
:s,
|
102
|
+
:applet,
|
103
|
+
:isindex,
|
104
|
+
:script,
|
105
|
+
:a,
|
106
|
+
:td,
|
107
|
+
:h5,
|
108
|
+
:h3,
|
109
|
+
:li,
|
110
|
+
:div,
|
111
|
+
:pre,
|
112
|
+
:body,
|
113
|
+
:ol,
|
114
|
+
:h4,
|
115
|
+
:h2,
|
116
|
+
:object,
|
117
|
+
:legend,
|
118
|
+
:dl,
|
119
|
+
:h6,
|
120
|
+
:ul,
|
121
|
+
:form,
|
122
|
+
:h1
|
123
|
+
]
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Simply
|
2
|
+
module Indentation
|
3
|
+
class IndentationError < StandardError
|
4
|
+
def message
|
5
|
+
"You can't outdent before the beginning of the page"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
unless defined?(DEFAULT_INDENTATION_LEVEL)
|
10
|
+
DEFAULT_NUM_SPACES_TO_INDENT = 2
|
11
|
+
DEFAULT_INDENTATION_LEVEL = 0
|
12
|
+
end
|
13
|
+
|
14
|
+
def <<(text)
|
15
|
+
out = empty? ? "" : "\n"
|
16
|
+
out << "#{" " * indentation_level}#{text}"
|
17
|
+
|
18
|
+
super(out)
|
19
|
+
end
|
20
|
+
|
21
|
+
def indent(number_of_spaces = DEFAULT_NUM_SPACES_TO_INDENT)
|
22
|
+
@indentation_level ||= DEFAULT_INDENTATION_LEVEL
|
23
|
+
@indentation_level += number_of_spaces
|
24
|
+
end
|
25
|
+
|
26
|
+
def outdent(number_of_spaces = DEFAULT_NUM_SPACES_TO_INDENT)
|
27
|
+
@indentation_level ||= DEFAULT_INDENTATION_LEVEL
|
28
|
+
@indentation_level -= number_of_spaces
|
29
|
+
raise IndentationError if @indentation_level < 0
|
30
|
+
@indentation_level
|
31
|
+
end
|
32
|
+
|
33
|
+
def indentation_level
|
34
|
+
@indentation_level ||= DEFAULT_INDENTATION_LEVEL
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Simply
|
2
|
+
module Locals
|
3
|
+
# Pass in a hash of local variables
|
4
|
+
# which will be available to the template:
|
5
|
+
#
|
6
|
+
# @builder.locals = { :foo => 1, :bar => 2, :baz => 3}
|
7
|
+
# @builder.ul do
|
8
|
+
# li foo
|
9
|
+
# li bar
|
10
|
+
# li baz
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# @builder.to_s #=> "<ul><li>1</li><li>2</li><li>3</li></ul>"
|
14
|
+
def locals=(hash={ })
|
15
|
+
def metaclass(&block)
|
16
|
+
meta = class << self; self; end
|
17
|
+
meta.instance_eval(&block)
|
18
|
+
end
|
19
|
+
|
20
|
+
hash.each do |key, value|
|
21
|
+
metaclass do
|
22
|
+
define_method key do
|
23
|
+
value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Simply
|
2
|
+
module Version
|
3
|
+
unless defined?(Simply::VERSION)
|
4
|
+
version_info = YAML.load(File.read(File.dirname(__FILE__) + "/../../VERSION.yml"))
|
5
|
+
|
6
|
+
MAJOR = version_info[:major]
|
7
|
+
MINOR = version_info[:minor]
|
8
|
+
TINY = version_info[:patch]
|
9
|
+
VERSION = "#{MAJOR}.#{MINOR}.#{TINY}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/simply.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Simply
|
2
|
+
dir = File.dirname(__FILE__) + "/simply"
|
3
|
+
|
4
|
+
require "#{dir}/version"
|
5
|
+
include Version
|
6
|
+
|
7
|
+
require "rubygems"
|
8
|
+
require "builder/xchar"
|
9
|
+
require "#{dir}/locals"
|
10
|
+
require "#{dir}/indentation"
|
11
|
+
require "#{dir}/html_tags"
|
12
|
+
require "#{dir}/html_builder"
|
13
|
+
end
|
14
|
+
|
15
|
+
def Simply(options={}, &block)
|
16
|
+
builder = Simply::HTMLBuilder.new(options, &block)
|
17
|
+
builder.to_s
|
18
|
+
end
|