BodyBuilder 0.2.0

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.
@@ -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
+