html-schema 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,76 @@
1
+ require 'rake'
2
+ require "rake/rdoctask"
3
+ require 'rake/gempackagetask'
4
+
5
+ spec = Gem::Specification.new do |s|
6
+ s.name = "html-schema"
7
+ s.authors = ["Lance Pollard"]
8
+ s.version = "0.2.0"
9
+ s.description = "Unified Ruby API for HTML5 Microdata and Microformats"
10
+ s.summary = "Unified Ruby API for HTML5 Microdata and Microformats"
11
+ s.homepage = "http://github.com/viatropos/html-schema"
12
+ s.email = "lancejpollard@gmail.com"
13
+ s.rubyforge_project = "html-schema"
14
+ s.platform = Gem::Platform::RUBY
15
+ s.files = %w(Rakefile) + Dir["{lib,rails,spec}/**/*"] - Dir["spec/tmp"]
16
+ s.require_path = "lib"
17
+ end
18
+
19
+ Rake::GemPackageTask.new(spec) do |pkg|
20
+ pkg.gem_spec = spec
21
+ end
22
+
23
+ desc 'run unit tests'
24
+ task :test do
25
+ Dir["test/**/*"].each do |file|
26
+ next unless File.basename(file) =~ /test_/
27
+ next unless File.extname(file) == ".rb"
28
+ system "ruby #{file}"
29
+ end
30
+ end
31
+
32
+ desc "Create .gemspec file (useful for github)"
33
+ task :gemspec do
34
+ File.open("#{spec.name}.gemspec", "w") do |f|
35
+ f.puts spec.to_ruby
36
+ end
37
+ end
38
+
39
+ desc "Build the gem into the current directory"
40
+ task :gem => :gemspec do
41
+ `gem build #{spec.name}.gemspec`
42
+ end
43
+
44
+ desc "Publish gem to rubygems"
45
+ task :publish => [:package] do
46
+ %x[gem push #{spec.name}-#{spec.version}.gem]
47
+ end
48
+
49
+ desc "Print a list of the files to be put into the gem"
50
+ task :manifest do
51
+ File.open("Manifest", "w") do |f|
52
+ spec.files.each do |file|
53
+ f.puts file
54
+ end
55
+ end
56
+ end
57
+
58
+ desc "Install the gem locally"
59
+ task :install => [:package] do
60
+ File.mkdir("pkg") unless File.exists?("pkg")
61
+ command = "gem install pkg/#{spec.name}-#{spec.version} --no-ri --no-rdoc"
62
+ command = "sudo #{command}" if ENV["SUDO"] == true
63
+ sh %{#{command}}
64
+ end
65
+
66
+ desc "Generate the rdoc"
67
+ Rake::RDocTask.new do |rdoc|
68
+ files = ["README.md", "lib/**/*.rb"]
69
+ rdoc.rdoc_files.add(files)
70
+ rdoc.main = "README.md"
71
+ rdoc.title = spec.summary
72
+ end
73
+
74
+ task :yank do
75
+ `gem yank #{spec.name} -v #{spec.version}`
76
+ end
@@ -0,0 +1,83 @@
1
+ require 'active_support/core_ext'
2
+
3
+ $:.unshift File.dirname(File.expand_path(__FILE__)) + "/html-schema"
4
+
5
+ class HTMLSchema
6
+ class << self
7
+ def root
8
+ @root ||= File.dirname(File.expand_path(__FILE__))
9
+ end
10
+
11
+ def configure(&block)
12
+ yield configuration
13
+ end
14
+
15
+ def configuration
16
+ @configuration ||= HTMLSchema::Configuration.new
17
+ end
18
+
19
+ def [](key)
20
+ api[key]
21
+ end
22
+
23
+ def instance
24
+ @instance ||= new
25
+ end
26
+
27
+ def instance=(value)
28
+ @instance = value
29
+ end
30
+
31
+ def bootstrap!(format)
32
+ format_name = format == :api ? "API" : format.to_s.camelize
33
+ Dir["#{HTMLSchema.root}/html-schema/#{format}/**/*.rb"].inject({}) do |hash, file|
34
+ name = ::File.basename(file, File.extname(file))
35
+ hash[name.to_sym] = "::HTMLSchema::#{format_name}::#{name.camelize}".constantize.new if name !~ /^(base|feed|attribute)$/
36
+ hash
37
+ end
38
+ end
39
+ end
40
+
41
+ def initialize(types = {})
42
+ self.class.instance = self
43
+ api.types.keys.each { |key| define_api_method(key) }
44
+ end
45
+
46
+ def api
47
+ @api ||= HTMLSchema::API
48
+ end
49
+
50
+ def microdata
51
+ @microdata ||= HTMLSchema::Microdata
52
+ end
53
+
54
+ def microformat
55
+ @microformat ||= HTMLSchema::Microformat
56
+ end
57
+
58
+ # todo, iterate through tree, so you can visualize it however you want.
59
+ def each(&block)
60
+
61
+ end
62
+
63
+ protected
64
+ def define_api_method(name)
65
+ self.class.send :define_method, name do
66
+ self.api[name]
67
+ end unless self.respond_to?(name)
68
+ end
69
+ end
70
+
71
+ require 'object'
72
+ require 'attribute'
73
+ require 'configuration'
74
+ require 'dsl'
75
+ require 'api/object'
76
+ require 'api/attribute'
77
+ require 'microdata/object'
78
+ require 'microdata/attribute'
79
+ require 'microformat/object'
80
+ require 'microformat/attribute'
81
+ require 'api'
82
+ require 'microdata'
83
+ require 'microformat'
@@ -0,0 +1,253 @@
1
+ class HTMLSchema
2
+ class API
3
+ extend HTMLSchema::DSL
4
+
5
+ type :object do
6
+ attribute :id
7
+ attribute :title
8
+ attribute :name
9
+ attribute :url
10
+ attribute :description
11
+ attribute :image
12
+
13
+ type :address do
14
+ attribute :street
15
+ attribute :suite
16
+ attribute :city
17
+ attribute :state
18
+ attribute :country
19
+ attribute :postal_code
20
+ attribute :post_office_box
21
+ end
22
+
23
+ type :composition do
24
+ attribute :abstract, :type => [:person, :organization]
25
+ attribute :average_rating, :type => :rating
26
+ attribute :award
27
+ attribute :rating, :type => :rating
28
+ attribute :genre
29
+ attribute :headline
30
+ attribute :language
31
+ attribute :interaction_count
32
+ attribute :family_friendly, :type => :boolean
33
+ attribute :keyword
34
+ attribute :offer, :type => :offer
35
+ attribute :review, :type => :review
36
+ attribute :editor, :type => :person
37
+ attribute :author, :type => :person
38
+ attribute :organization, :type => :organization
39
+ attribute :publisher, :type => :organization
40
+ attribute :location, :type => :address
41
+ attribute :videa, :type => :media
42
+ attribute :encoding, :type => :media
43
+ attribute :audio, :type => :media
44
+ attribute :tag
45
+ attribute :published_at, :type => :date
46
+
47
+ type :article do
48
+ attribute :body
49
+ attribute :section
50
+ end
51
+
52
+ type :media do
53
+ attribute :bitrate
54
+ attribute :size
55
+ attribute :url
56
+ attribute :embed_url
57
+ attribute :composition, :type => :article
58
+ attribute :format
59
+ attribute :player
60
+ attribute :allowed_in, :type => :address
61
+ attribute :subscription_required, :type => :boolean
62
+ attribute :expires_at, :type => :date
63
+ attribute :uploaded_at, :type => :date
64
+ attribute :duration, :as => :measurement
65
+ attribute :height, :type => :measurement
66
+ attribute :width, :type => :measurement
67
+
68
+ type :audio
69
+ type :image
70
+ type :video
71
+ end
72
+ end
73
+
74
+ type :coordinates do
75
+ attribute :elevation, :type => :measurement
76
+ attribute :latitude
77
+ attribute :longitude
78
+ end
79
+
80
+ type :event do
81
+ attribute :child_event, :type => :event
82
+ attribute :parent_event, :type => :event
83
+ attribute :start_date, :type => :date
84
+ attribute :end_date, :type => :date
85
+ attribute :location, :type => :address
86
+ attribute :duration, :type => :measurement
87
+ attribute :offer, :type => :offer
88
+ attribute :attendee, :type => :person
89
+ attribute :performer, :type => :person
90
+ attribute :organization, :type => :organization
91
+ end
92
+
93
+ type :figure do
94
+ attribute :image
95
+ attribute :legend
96
+ attribute :author, :type => [:person, :organization]
97
+ attribute :subject
98
+ end
99
+
100
+ type :item do
101
+ attribute :type
102
+ attribute :value
103
+ end
104
+
105
+ type :measurement do
106
+ attribute :value
107
+ attribute :unit
108
+ attribute :item, :type => [:text, :person, :organization, :media, :event]
109
+ end
110
+
111
+ type :offer do
112
+ attribute :rating, :type => :rating
113
+ attribute :availability
114
+ attribute :condition
115
+ attribute :item, :type => :product
116
+ attribute :price, :type => :measurement
117
+ attribute :min_price, :type => :measurement
118
+ attribute :max_price, :type => :measurement
119
+ attribute :currency
120
+ attribute :valid_until_date, :type => :date
121
+ attribute :review, :type => :review
122
+ attribute :seller, :type => :organization
123
+ attribute :count
124
+ end
125
+
126
+ type :organization do
127
+ attribute :address, :type => :address
128
+ attribute :average_rating, :type => :rating
129
+ attribute :contact, :type => [:person, :organization]
130
+ attribute :email
131
+ attribute :employee, :type => :person
132
+ attribute :event, :type => :event
133
+ attribute :fax
134
+ attribute :founder, :type => :person
135
+ attribute :founded_at, :type => :date
136
+
137
+ type :vendor do
138
+ attribute :branch_of, :type => :organization
139
+ attribute :hours
140
+ attribute :currency
141
+ attribute :payment_method
142
+ attribute :price_range
143
+ attribute :menu
144
+ attribute :reservations
145
+ attribute :cuisine
146
+ end
147
+ end
148
+
149
+ type :person do
150
+ attribute :address, :type => :address
151
+ attribute :home_address, :type => :address
152
+ attribute :work_address, :type => :address
153
+
154
+ # organizations
155
+ attribute :organization, :type => :organization
156
+ attribute :education, :type => :organization
157
+ attribute :membership, :type => :organization
158
+ attribute :company, :type => :organization
159
+
160
+ # events
161
+ attribute :performer_in, :type => :event
162
+
163
+ # dates
164
+ attribute :born_at, :type => :date
165
+ attribute :died_at, :type => :date
166
+
167
+ # relationships
168
+ attribute :children, :type => :person
169
+ attribute :parents, :type => :person
170
+ attribute :siblings, :type => :person
171
+ attribute :spouse, :type => :person
172
+ attribute :relationship, :type => :person
173
+ attribute :colleagues, :type => :person
174
+ # unidirectional
175
+ attribute :follows, :type => :person
176
+ # bidirectional
177
+ attribute :knows, :type => :person
178
+
179
+ # info
180
+ attribute :contact_info, :type => :contact
181
+ attribute :email
182
+ attribute :phone
183
+ attribute :fax
184
+ attribute :gender
185
+ attribute :interaction_count
186
+ attribute :job_title
187
+ attribute :nationality, :type => :place
188
+
189
+ type :author
190
+ type :acquaintance
191
+ type :child
192
+ type :colleague
193
+ type :contact
194
+ type :roommate
195
+ type :coworker
196
+ type :crush
197
+ type :date
198
+ type :editor
199
+ type :fan
200
+ type :friend
201
+ type :kin
202
+ type :me
203
+ type :met
204
+ type :muse
205
+ type :neighbor
206
+ type :sibling
207
+ type :spouse
208
+ type :sweetheart
209
+ type :member
210
+ type :sponsor
211
+ type :user
212
+ end
213
+
214
+ type :place do
215
+ attribute :address, :type => :address
216
+ attribute :rating, :type => :rating
217
+ attribute :surrounding, :type => :place
218
+ attribute :event, :type => :event
219
+ attribute :fax
220
+ attribute :coordinates, :type => :coordinates
221
+ attribute :interaction_count
222
+ attribute :map
223
+ attribute :image, :type => :media
224
+ attribute :review, :type => :review
225
+ attribute :phone
226
+ end
227
+
228
+ type :product do
229
+ attribute :rating, :type => :rating
230
+ attribute :brand, :type => :organization
231
+ attribute :manufacturer, :type => :organization
232
+ attribute :model
233
+ attribute :offer, :type => :offer
234
+ attribute :review, :type => :review
235
+ end
236
+
237
+ type :rating do
238
+ attribute :best
239
+ attribute :value
240
+ attribute :worst
241
+ attribute :item, :type => [:person, :event, :media, :place, :organization]
242
+ attribute :rating_count
243
+ attribute :review_count
244
+ end
245
+
246
+ type :review do
247
+ attribute :body
248
+ attribute :item, :type => [:person, :event, :media, :place, :organization]
249
+ attribute :rating, :type => :rating
250
+ end
251
+ end
252
+ end
253
+ end
@@ -0,0 +1,54 @@
1
+ class HTMLSchema
2
+ class API
3
+ class Attribute < HTMLSchema::Attribute
4
+ def microdata
5
+ if @microdata.nil?
6
+ object = HTMLSchema.instance.microdata[parent]
7
+ object = object[_name] if object
8
+ object = false if object.blank?
9
+ @microdata = object
10
+ end
11
+
12
+ @microdata
13
+ end
14
+
15
+ def microdata?
16
+ !!microdata
17
+ end
18
+
19
+ def microformat
20
+ if @microformat.nil?
21
+ object = HTMLSchema.instance.microformat[parent]
22
+ object = object[_name] if object
23
+ object = false if object.blank?
24
+ @microformat = object
25
+ end
26
+ @microformat
27
+ end
28
+
29
+ def microformat?
30
+ !!microformat
31
+ end
32
+
33
+ def to_microdata
34
+ microdata.to_hash
35
+ end
36
+
37
+ def to_microformat
38
+ microformat.to_hash
39
+ end
40
+
41
+ def to_hash
42
+ if microdata? && microformat?
43
+ to_microdata.merge(to_microformat)
44
+ elsif microdata?
45
+ to_microdata
46
+ elsif microformat?
47
+ to_microformat
48
+ else
49
+ {}
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end