simply 0.1.3

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/.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