BodyBuilder 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{BodyBuilder}
5
+ s.version = "0.2.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Exiquio Cooper-Anderson"]
9
+ s.date = %q{2010-12-12}
10
+ s.description = %q{XHMTL 1.1 generator}
11
+ s.email = %q{exiquio @nospam@ gmail.com}
12
+ s.extra_rdoc_files = ["README", "lib/body_builder.rb", "lib/hash.rb", "lib/object.rb"]
13
+ s.files = ["BodyBuilder.gemspec", "Manifest", "README", "Rakefile", "lib/body_builder.rb", "lib/hash.rb", "lib/object.rb"]
14
+ s.homepage = %q{http://www.github.com/exiquio/BodyBuilder}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "BodyBuilder", "--main", "README"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{bodybuilder}
18
+ s.rubygems_version = %q{1.3.7}
19
+ s.summary = %q{XHMTL 1.1 generator}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
26
+ else
27
+ end
28
+ else
29
+ end
30
+ end
@@ -0,0 +1,7 @@
1
+ BodyBuilder.gemspec
2
+ Manifest
3
+ README
4
+ Rakefile
5
+ lib/body_builder.rb
6
+ lib/hash.rb
7
+ lib/object.rb
data/README ADDED
@@ -0,0 +1,74 @@
1
+ BodyBuilder (Version 0.1.9)
2
+
3
+ Ruby XHTML 1.1 Generator
4
+
5
+ Author: Exiquio Cooper-Anderson (exiquio [at] gmail [dot] com)
6
+ Copyright: (C) 2010 Exiquio Cooper-Anderson
7
+ License: GPLv3 (www.gnu.org/licenses/gpl.html)
8
+
9
+ Requirements:
10
+ Ruby 1.9.*
11
+
12
+ Installation:
13
+ gem install BodyBuilder
14
+
15
+ Usage:
16
+
17
+ {{{
18
+
19
+ #!/usr/bin/env ruby
20
+
21
+ require 'rubygems'
22
+ require 'body_builder'
23
+
24
+ c = BodyBuilder::HeMan.new
25
+ c.div 'id="main_content"'
26
+ c._p_ '', 'Hello, world!'
27
+ c._hr_
28
+ c._p_ '', 'Generated with BodyBuilder'
29
+ c.div_
30
+
31
+ puts BodyBuilder::Skeletor.new(
32
+ {
33
+ title: 'Hello, world',
34
+ body: c,
35
+ icon: {href: '/public/images/icon.png', type: 'media/png'}
36
+ }
37
+ ).render
38
+
39
+ }}}
40
+
41
+ Results:
42
+
43
+ {{{
44
+
45
+ <?xml version="1.0" encoding="UTF-8"?>
46
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
47
+ <html xmlns="http://www.w3.org/1999/xhtml">
48
+ <head>
49
+ <title>Hello, world</title>
50
+ <link rel="icon" type="media/png" href="/public/images/icon.png"></link>
51
+ </head>
52
+ <body>
53
+ <div id="main_content">
54
+ <p>Hello, world!</p>
55
+ <hr></hr>
56
+ <p>Generated with BodyBuilder</p>
57
+ </div>
58
+ </body>
59
+ </html>
60
+
61
+ }}}
62
+
63
+ Latest change:
64
+ 2010-12-11 - Refactored, XHTML 1.1 implementation complete, brought in ExLib, version changed to 0.1.9, decided against HTML5 implementation
65
+
66
+ Todo 0.3.0:
67
+ Improve performance
68
+ Improve testing of dynamically created methods
69
+
70
+ NOTE:
71
+ 'document type does not allow element 'script' here'
72
+ Validation causes the above error because scripts are loading at the end of the XHTML document for performance.
73
+
74
+ Any questions, conscerns or commments: exiquio [at] gmail [dot] com
@@ -0,0 +1,14 @@
1
+ require 'rake'
2
+ require 'echoe'
3
+
4
+ Echoe.new('BodyBuilder', '0.2.0') do |p|
5
+ p.description = 'XHMTL 1.1 generator'
6
+ p.url = 'http://www.github.com/exiquio/BodyBuilder'
7
+ p.author = 'Exiquio Cooper-Anderson'
8
+ p.email = 'exiquio @nospam@ gmail.com'
9
+ p.ignore_pattern = [
10
+ 'tests/*',
11
+ 'readme_example.rb',
12
+ 'index.html'
13
+ ]
14
+ end
@@ -0,0 +1,267 @@
1
+ # BodyBuilder
2
+ #
3
+ # Ruby XHTML 1.1 generator.
4
+ #
5
+ # Author:: Exiquio Cooper-Anderson (mailto:exiquio@gmail.com)
6
+ # Copyright:: (C) 2010 Exiquio Cooper-Anderson (mailto:exiquio@gmail.com)
7
+ # License:: GPLv3 (http://www.gnu.org/licenses/gpl.html)
8
+ # Version:: 0.2.0
9
+ #
10
+ # Requirements::
11
+ # Ruby 1.9.*
12
+ #
13
+ # Changelog::
14
+ # 2010-04-01 - Initial creation with select XHTML 1.1 tags (mailto:exiquio@gmail.com)
15
+ # 2010-12-09 - Redocumented, refactored for style, exceptions classes added, removed cgi, updated for Ruby 1.9 (mailto:exiquio@gmail.com)
16
+ # 2010-12-10 - Fixed documentation (mailto:exiquio@gmail.com)
17
+ # 2010-12-11 - Refactored, XHTML 1.1 implementation complete, brought in ExLib, version changed to 0.1.9, decided against HTML5 implementation (mailto:exiquio@gmail.com)
18
+ # 2010-12-12 - Refactored, fixed bugs, implmented riot beheavior tests, benchmarke, version upped to 0.2.0 (mailto:exiquio@gmail.com)
19
+ #
20
+ # Reference::
21
+ # XHTML 1.1 - http://learningforlife.fsu.edu/webmaster/references/xhtml/tags/
22
+
23
+
24
+ require_relative 'hash'
25
+ require_relative 'object'
26
+
27
+ module BodyBuilder
28
+
29
+ # Exception to be raised in the context of Skeletor
30
+ class SkeletorException < Exception
31
+ end
32
+
33
+ # Provies framework for quickly building a vailid HTML 5 bareboned document
34
+ class Skeletor
35
+ XML_DECLARATION = '<?xml version="1.0" encoding="UTF-8"?>'
36
+ DOCTYPE = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'
37
+ HTML_DECLARATION = '<html xmlns="http://www.w3.org/1999/xhtml">'
38
+
39
+ # Creates an XHTML 1.1 object
40
+ #
41
+ # options (Hash)
42
+ # {
43
+ # title: String - Title of the XHTML 1.1 Document.,
44
+ # meta: Arrary[Hash,..] <optional> - Array of Hashes containing key value pairs of meta data.,
45
+ # (eg., [{name: 'name', content: 'content'}])
46
+ # base: String <optional> - Base URL for the HTML document. Defaults to noe,
47
+ # favicon: Hash <optional> - Hash with the href and type of your favicon icon. Defualts to none,
48
+ # (eg., {href: String, type: String})
49
+ # stylesheets: Array[Hash] <optional> - List of paths to CSS files and optional media types.,
50
+ # (eg., [{href: 'path\to\stylesheet', {[media: 'screen'],..}},..])
51
+ # body: HeMan or String - Either a HeMan XHTML 1.1 Body Object or String containing markup.,
52
+ # scripts: Array[String] <optional> - List of paths to JavaScript files. Defaults to none.,
53
+ # }
54
+ def initialize options
55
+ # options
56
+ raise SkeletorException, 'You must provide the options Hash.' unless options.is_a? Hash
57
+ raise SkeletorException, 'options must contain the keys :title, and :body' unless options.has_keys? :title, :body
58
+ title, body = options[:title], options[:body]
59
+ raise SkeletorException, 'The value of key :title must be a String.' unless title.is_a? String
60
+ # title
61
+ @title = title
62
+ # meta
63
+ if options.has_key? :meta
64
+ meta = options[:meta]
65
+ raise SkeletorException, 'The value of :meta must be an Arra with a length > 0' unless meta.is_a? Array and meta.length > 0
66
+ @meta = []
67
+ meta.each do |metatag|
68
+ raise SkeletorException, 'Elements of :meta must be Hashes.' unless metatag.is_a? Hash
69
+ raise SkeletorException, 'The Hashes of :meta must contain the keys :name and :content.' unless metatag.has_keys? :name, :content
70
+ metatag.each {|k, v| raise SkeletorException, 'The values of :name and :content must be Strings.with a length > 0' unless v.is_a? String and v.length > 0}
71
+ @meta << %{<meta name="#{metatag[:name]}" content="#{metatag[:content]}"></meta>}
72
+ end
73
+ @meta = @meta.join('')
74
+ else
75
+ @meta = ''
76
+ end
77
+ # base
78
+ if options.has_key? :base
79
+ base = options[:base]
80
+ raise SkeletorException, 'base must be a String with a length > 0' unless base.is_a? String and base.length > 0
81
+ @base = %{<base href="#{base}"></base>}
82
+ else
83
+ @base = ''
84
+ end
85
+ # favicon
86
+ if options.has_key? :favicon
87
+ favicon = options[:favicon]
88
+ raise SkeletorException, 'The value of :favicon must be a Hash' unless favicon.is_a? Hash
89
+ raise SkeletorException, 'favicon must contain the keys :href and :type' unless favicon.has_keys? :href, :type
90
+ favicon_href, favicon_type = favicon[:href], favicon[:type]
91
+ raise SkeletorException, 'favicon[:href] and favicon[:type] must be Strings with a length > 0' unless favicon_href.is_a? String and favicon_href.length > 0 and favicon_type.is_a? String and favicon_type.length > 0
92
+ @favicon = %{<link rel="favicon" type="#{favicon_type}" href="#{favicon_href}" />}
93
+ else
94
+ @favicon = ''
95
+ end
96
+ # stylesheets
97
+ if options.has_key? :stylesheets
98
+ stylesheets = options[:stylesheets]
99
+ raise SkeletorException, 'The value of :stylesheets must be an Array with a length > 0' unless stylesheets.is_a? Array and stylesheets.length > 0
100
+ @stylesheets = []
101
+ stylesheets.each do |stylesheet|
102
+ raise SkeletorException, 'Elements of :stylesheets must be a Hash with a length > 0' unless stylesheet.is_a? Hash and stylesheet.length > 0
103
+ raise SkeletorException, 'Hash must contain the key :href' unless stylesheet.has_key? :href
104
+ stylesheet_href = stylesheet[:href]
105
+ raise SkeletorException, 'href must be a String with a length > 0' unless stylesheet_href.is_a? String and stylesheet_href.length > 0
106
+ if stylesheet.has_key? :media
107
+ stylesheet_media = stylesheet[:media]
108
+ raise SkeletorException, 'media must be a String with a length > 0' unless stylesheet_media.is_a? String and stylesheet_media.length > 0
109
+ else
110
+ stylesheet_media = nil
111
+ end
112
+ @stylesheets << %{<link rel="stylesheet" type="text/css" href="#{stylesheet_href}"}
113
+ @stylesheets << %{ media="#{stylesheet_media}"} if stylesheet_media
114
+ @stylesheets << ' />'
115
+ end
116
+ @stylesheets = @stylesheets.join('')
117
+ else
118
+ @stylesheets = ''
119
+ end
120
+ # body
121
+ raise SkeletorException, 'The value of key :body must be a HeMan object or a String.' unless body.is_one_of? String, HeMan
122
+ @body = options[:body].is_a?(String) ? options[:body] : options[:body].render
123
+ # scripts
124
+ if options.has_key? :scripts
125
+ scripts = options[:scripts]
126
+ raise SkeletorException, 'The value of :scripts must be an Array with a length > 0' unless scripts.is_a? Array and scripts.length > 0
127
+ @scripts = []
128
+ scripts.each do |script|
129
+ raise SkeletorException, 'The values of the :script Array must be Strings with a length > 0.' unless script.is_a? String and script.length > 0
130
+ @scripts << %{<script type="text/javascript" src="#{script}" />}
131
+ end
132
+ @scripts = @scripts.join('')
133
+ else
134
+ @scripts = ''
135
+ end
136
+ @header, @body, @footer = build_header, build_body, build_footer
137
+ @markup = [@header, @body, @footer].join
138
+ end
139
+
140
+ attr_reader :header, :body, :footer
141
+
142
+ public
143
+
144
+ # Returns full XHTML 1.1 document as a String
145
+ def render
146
+ @markup
147
+ end
148
+
149
+ private
150
+
151
+ def build_header
152
+ [
153
+ XML_DECLARATION,
154
+ DOCTYPE,
155
+ HTML_DECLARATION,
156
+ '<head>',
157
+ "<title>#{@title}</title>",
158
+ @meta,
159
+ @base,
160
+ @favicon,
161
+ @stylesheets,
162
+ '</head>',
163
+ ].join('')
164
+ end
165
+
166
+ def build_body
167
+ [
168
+ '<body>',
169
+ @body,
170
+ '</body>'
171
+ ].join('')
172
+ end
173
+
174
+ def build_footer
175
+ [
176
+ @scripts,
177
+ '</html>'
178
+ ].join('')
179
+ end
180
+ end
181
+
182
+ # Exception to be raised in context of HeMan
183
+ class HeManException < Exception
184
+ end
185
+
186
+ # XHTML 1.1 Generation library. Implements all tags that go between the fall under <body> in XHTML 1.1 heiarchy
187
+ class HeMan
188
+ VALID_TAGS = [
189
+ :abbr, :acronym, :address, :blockquote, :br, :cite, :code, :dfn, :div, :em, :h1, :h2, :h3, :h4, :h5, :h6, :kbd, :p, :pre, :q, :samp, :span, :strong, :var, # Text Module
190
+ :a, # Hypertext Module
191
+ :dl, :dd, :dt, :ol, :ul, :l, # List Module
192
+ :object, :param, # Object Module
193
+ :b, :big, :hr, :i, :small, :sub, :sup, :tt, # Presentation Module
194
+ :del, :ins, # Edit Module
195
+ :bdo, # Bidirectional Module
196
+ :button, :fieldset, :form, :input, :label, :legend, :select, :optgroup, :option, :textarea, # Form Module
197
+ :caption, :col, :colgroup, :table, :tbody, :td, :tfoot, :th, :thead, :tr, # Table Module
198
+ :img, # Image Module
199
+ :area, :map, # Client-side Image Map Module
200
+ :noscript, :script, # Scripting Module
201
+ :ruby, :rbc, :rtc, :rb, :rt, :rp # Ruby Module
202
+ ]
203
+
204
+ def initialize
205
+ @markup, @last_open_tag = [], ''
206
+ VALID_TAGS.each do |tag|
207
+ define_singleton_method(tag) do |*optional|
208
+ attrs, str, *ignore = *optional
209
+ open tag, attrs
210
+ text str if str
211
+ end
212
+ define_singleton_method(("#{tag.to_s}_").to_sym) {close tag}
213
+ define_singleton_method(("_#{tag.to_s}_").to_sym) do |*optional|
214
+ attrs, str, *ignore = *optional
215
+ self.send(tag, attrs, str)
216
+ self.send(("#{tag}_").to_sym)
217
+ end
218
+ end
219
+ end
220
+
221
+ public
222
+
223
+ # Return generated markup as a String
224
+ def render
225
+ @markup.join
226
+ end
227
+
228
+ private
229
+
230
+ def open tag, attributes=nil
231
+ validate_tag tag
232
+ @last_open_tag = tag
233
+ if attributes
234
+ raise HeManException, 'attributes must be a String.' unless attributes.is_a? String
235
+ if attributes.length > 0
236
+ @markup << "<#{tag.to_s} #{attributes}>"
237
+ else
238
+ @markup << "<#{tag.to_s}>"
239
+ end
240
+ else
241
+ @markup << "<#{tag.to_s}>"
242
+ end
243
+ end
244
+
245
+ def close tag
246
+ validate_tag tag
247
+ @markup << "</#{tag}>"
248
+ end
249
+
250
+ def close_last
251
+ close @last_open_tag
252
+ end
253
+
254
+ def text str
255
+ raise HeManException, 'str must be a String' unless str.is_a? String
256
+ @markup << str
257
+ end
258
+
259
+ def validate_tag tag
260
+ raise HeManException, 'tag must be a symbol' unless tag.is_a? Symbol
261
+ raise HeManException, "#{tag} is not a valid tag. See HeMan::VALID_TAGS" unless VALID_TAGS.include? tag
262
+ end
263
+ end
264
+ end
265
+
266
+ # TODO 0.3.0
267
+ # Improve performance
@@ -0,0 +1,13 @@
1
+ # hash.rb
2
+ # # TODO
3
+ #
4
+ #
5
+
6
+ class Hash
7
+ def has_keys? *args
8
+ args.each {|arg| raise ArgumentError, '*args must be Symbols' unless arg.is_a? Symbol}
9
+ value = true
10
+ args.each {|arg| value = false unless self.has_key? arg}
11
+ value
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ # TODO
2
+ #
3
+ # Author:: Exiquio Cooper-Anderson (exiquio [at] gmail [dot] com)
4
+ # Copyright:: 2010 (C) Exiqio Cooper-Anderson
5
+ # License:: GPLv3 (http://www.gnu.org/licenses/gpl.html)
6
+ #
7
+ # Changelog::
8
+ # 2010-12-11 - Added :is_on_of?
9
+
10
+ class Object
11
+ public
12
+
13
+ def is_boolean?
14
+ self.is_a? TrueClass or self.is_a? FalseClass
15
+ end
16
+
17
+ def is_one_of? *args
18
+ args.each {|arg| raise ArgumentError, '*args must be Classes' unless arg.is_a? Class}
19
+ args.include? self.class
20
+ end
21
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: BodyBuilder
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
+ platform: ruby
11
+ authors:
12
+ - Exiquio Cooper-Anderson
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-12-12 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: XHMTL 1.1 generator
22
+ email: exiquio @nospam@ gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - README
29
+ - lib/body_builder.rb
30
+ - lib/hash.rb
31
+ - lib/object.rb
32
+ files:
33
+ - BodyBuilder.gemspec
34
+ - Manifest
35
+ - README
36
+ - Rakefile
37
+ - lib/body_builder.rb
38
+ - lib/hash.rb
39
+ - lib/object.rb
40
+ has_rdoc: true
41
+ homepage: http://www.github.com/exiquio/BodyBuilder
42
+ licenses: []
43
+
44
+ post_install_message:
45
+ rdoc_options:
46
+ - --line-numbers
47
+ - --inline-source
48
+ - --title
49
+ - BodyBuilder
50
+ - --main
51
+ - README
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ segments:
68
+ - 1
69
+ - 2
70
+ version: "1.2"
71
+ requirements: []
72
+
73
+ rubyforge_project: bodybuilder
74
+ rubygems_version: 1.3.7
75
+ signing_key:
76
+ specification_version: 3
77
+ summary: XHMTL 1.1 generator
78
+ test_files: []
79
+