simply 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ pkg
data/README ADDED
@@ -0,0 +1,4 @@
1
+
2
+ == Simply
3
+
4
+ A simple, fast replacement for markaby.
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,5 @@
1
+ ---
2
+ :minor: 1
3
+ :patch: 3
4
+ :major: 0
5
+ :build:
@@ -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
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + "/../lib/simply"
2
+
3
+ TIMES = 1000
4
+
5
+ TIMES.times do
6
+ Simply do
7
+ html do
8
+ head do
9
+ title "happy title"
10
+ end
11
+
12
+ body do
13
+ h1 "happy heading"
14
+ a "a link", :href => "url"
15
+ end
16
+ end
17
+ end
18
+ end