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,26 @@
1
+ class HTMLSchema
2
+ # This model module is the standard API.
3
+ class API
4
+ class Object < HTMLSchema::Object
5
+ def microdata
6
+ @microdata ||= HTMLSchema.instance.microdata[_name]
7
+ end
8
+
9
+ def microformat
10
+ @microformat ||= HTMLSchema.instance.microformat[_name]
11
+ end
12
+
13
+ def to_microdata
14
+ microdata.to_hash
15
+ end
16
+
17
+ def to_microformat
18
+ microformat.to_hash
19
+ end
20
+
21
+ def to_hash
22
+ to_microdata.merge(to_microformat)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,43 @@
1
+ class HTMLSchema
2
+ class Attribute < HTMLSchema::Object
3
+ attr_accessor :type, :value, :options, :required
4
+
5
+ def initialize(name, options = {}, &block)
6
+ @_name = name
7
+ @value = options
8
+ @parent = options[:parent]
9
+ @as = options[:as] || name
10
+ @classes = Array(as).map(&:to_s)
11
+ @required = options[:required] == true
12
+
13
+ @options = options.except(:as, :parent, :required, :type)
14
+ @options.each do |key, value|
15
+ @options[key] = value.to_s
16
+ end
17
+ end
18
+
19
+ def inspect
20
+ "#<#{self.class.name} name: #{_name.inspect}, value: #{value.inspect}>"
21
+ end
22
+
23
+ # ISO 8601 date format
24
+ def format(value)
25
+ case type
26
+ when :date
27
+ ::Date.parse(value)
28
+ else
29
+ value.to_s
30
+ end
31
+ end
32
+
33
+ def value=(value)
34
+ @value = format(value)
35
+ end
36
+
37
+ class << self
38
+ def attribute?
39
+ true
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,10 @@
1
+ class HTMLSchema
2
+ class Configuration
3
+ attr_accessor :microdata, :microformat
4
+
5
+ def initialize
6
+ @microdata = true
7
+ @microformat = true
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,23 @@
1
+ class HTMLSchema
2
+ module DSL
3
+ def type(name, options = {}, &block)
4
+ types[name] = "#{self.name}::Object".constantize.new(name, options, &block)
5
+ end
6
+
7
+ def types
8
+ @types ||= {}
9
+ end
10
+
11
+ def root
12
+ @root ||= types.values.first
13
+ end
14
+
15
+ def [](key)
16
+ types[key]
17
+ end
18
+
19
+ def []=(key, value)
20
+ types[key] = value
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,10 @@
1
+ class HTMLSchema
2
+ module Helper
3
+ def htmlschema(*args)
4
+ options = args.extract_options!
5
+ object = HTMLSchema.instance
6
+ args.each { |i| object = object.send(i) }
7
+ object.to_hash.merge(options)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,450 @@
1
+ class HTMLSchema
2
+ class Microdata
3
+ extend HTMLSchema::DSL
4
+
5
+ type :object do
6
+ attribute :name
7
+ attribute :title
8
+ attribute :url
9
+ attribute :description
10
+ attribute :image
11
+
12
+ type :contact, :as => :Contact do
13
+ attribute :kind, :as => :contactType # sales contact, PR, etc.
14
+ attribute :email
15
+ attribute :fax, :as => :faxNumber
16
+ attribute :phone, :as => :telephone
17
+
18
+ type :address, :as => :PostalAddress do
19
+ attribute :street, :as => :streetAddress
20
+ attribute :city, :as => :addressLocality
21
+ attribute :state, :as => :addressRegion
22
+ attribute :postal_code, :as => :postalCode
23
+ attribute :post_office_box, :as => :postOfficeBoxNumber
24
+ attribute :country, :as => :addressCountry#, :type => :place, :source => :country
25
+ end
26
+ end
27
+
28
+ type :composition, :as => :Composition do
29
+ attribute :abstract, :as => :about, :type => :base
30
+ attribute :average_rating, :as => :aggregateRating, :type => :rating
31
+ attribute :awards
32
+ attribute :rating, :as => :contentRating, :type => :rating
33
+ attribute :genre
34
+ attribute :headline
35
+ # http://tools.ietf.org/html/bcp47
36
+ attribute :language, :as => :inLanguage
37
+ attribute :interaction_count, :as => :interactionCount
38
+ attribute :family_friendly, :as => :isFamilyFriendly, :type => :boolean
39
+ attribute :tag, :as => :keywords
40
+ attribute :offer, :as => :offers, :type => :offer
41
+ attribute :review, :as => :reviews, :type => :review
42
+
43
+ # people and organizations
44
+ attribute :editor, :type => :person
45
+ attribute :author, :type => :person
46
+ attribute :organization, :as => :author, :type => :organization
47
+ attribute :publisher, :type => :organization
48
+
49
+ # addresses
50
+ attribute :location, :as => :contentLocation, :type => :place
51
+
52
+ # media
53
+ attribute :videa, :type => :media, :source => :video
54
+ attribute :encoding, :as => :encodings, :type => :media
55
+ attribute :audio, :type => :media, :source => :audio
56
+
57
+ # dates
58
+ attribute :published_at, :as => :datePublished, :type => :date
59
+
60
+ type :blog, :as => :Blog
61
+ type :book, :as => :Book
62
+ type :list, :as => :ItemList
63
+ type :map, :as => :Map
64
+ type :movie, :as => :Movie
65
+ type :recording, :as => :MusicRecording
66
+ type :painting, :as => :Painting
67
+ type :photo, :as => :Photograph
68
+ type :sculpture, :as => :Sculpture
69
+ type :episode, :as => :TVEpisode
70
+ type :season, :as => :TVSeason
71
+ type :series, :as => :TVSeries
72
+
73
+ type :article, :as => :Article do
74
+ attribute :body, :as => :articleBody
75
+ attribute :section, :as => :articleSection
76
+
77
+ type :article, :as => :Article do
78
+ type :blog_post, :as => :BlogPosting
79
+ type :news_article, :as => :NewsArticle
80
+ type :academic_article, :as => :ScholarlyArticle
81
+ end
82
+ end
83
+
84
+ type :media, :as => :MediaObject do
85
+ attribute :bitrate
86
+ attribute :size, :as => :contentSize
87
+ attribute :url, :as => :contentURL
88
+ attribute :embed_url, :as => :embedURL
89
+ attribute :duration, :as => :measurement
90
+ attribute :composition, :as => :encodesCreativeWork, :type => :composition
91
+ attribute :format, :as => :encodingFormat
92
+ attribute :expiration_date, :as => :expires, :type => :date
93
+ attribute :height, :type => :measurement
94
+ attribute :width, :type => :measurement
95
+ attribute :player, :as => :playerType # flash, silverlight, etc.
96
+ attribute :allowed_in, :as => :regionsAllowed, :type => :place
97
+ attribute :subscription_required, :as => :requiresSubscription, :type => :boolean
98
+ attribute :upload_date, :as => :uploadDate, :type => :date
99
+
100
+ type :audio, :as => :AudioObject
101
+ type :music_video, :as => :MusicVideoObject
102
+ type :video, :as => :VideoObject
103
+
104
+ type :image, :as => :ImageObject do
105
+ attribute :caption
106
+ attribute :exif, :as => :exifData
107
+ attribute :main, :as => :representativeOfPage, :type => :boolean
108
+ attribute :thumbnail, :type => :image
109
+ end
110
+ end
111
+
112
+ type :playlist, :as => :MusicPlaylist do
113
+ type :album, :as => :MusicAlbum
114
+ end
115
+
116
+ type :recipe, :as => :Recipe
117
+ type :review, :as => :Review do
118
+ attribute :item, :as => :itemReviewed, :type => :base
119
+ attribute :content, :as => :reviewBody
120
+ attribute :rating, :as => :reviewRating, :type => :rating
121
+ end
122
+
123
+ type :webpage, :as => :WebPage do
124
+ type :about_page, :as => :AboutPage
125
+ type :checkout_page, :as => :CheckoutPage
126
+ type :index_page, :as => :CollectionPage
127
+ type :contact_page, :as => :ContactPage
128
+ type :show_page, :as => :ItemPage
129
+ type :profile_page, :as => :ProfilePage
130
+ type :search_page, :as => :SearchResultsPage
131
+ end
132
+
133
+ type :widget, :as => :WebPageElement do
134
+ type :menu_item, :as => :SiteNavigationElement
135
+ type :table, :as => :Table
136
+ type :ad, :as => :WPAdBlock
137
+ type :footer, :as => :WPFooter
138
+ type :header, :as => :WPHeader
139
+ type :sidebar, :as => :WPSideBar
140
+ end
141
+ end
142
+
143
+ type :event, :as => :Event do
144
+ type :arts, :as => :VisualArtsEvent
145
+ type :business, :as => :BusinessEvent
146
+ type :chidrens, :as => :ChildrensEvent
147
+ type :comedy, :as => :ComedyEvent
148
+ type :dance, :as => :DanceEvent
149
+ type :education, :as => :EducationEvent
150
+ type :festival, :as => :Festival
151
+ type :food, :as => :FoodEvent
152
+ type :literary, :as => :LiteraryEvent
153
+ type :music, :as => :MusicEvent
154
+ type :sale, :as => :SaleEvent
155
+ type :social, :as => :SocialEvent
156
+ type :sports, :as => :SportsEvent
157
+ type :theater, :as => :TheaterEvent
158
+
159
+ attribute :attendee, :as => :attendees, :type => :person
160
+ attribute :duration, :type => :base, :source => :duration
161
+ attribute :end_date, :as => :endDate, :type => :date
162
+ attribute :start_date, :as => :startDate, :type => :date
163
+ attribute :location, :type => :address
164
+ attribute :place, :as => :location, :type => :place
165
+ attribute :offer, :as => :offers, :type => :offer
166
+ attribute :performer, :as => :performers, :type => :person
167
+ attribute :child_event, :as => :subEvents, :type => :event
168
+ attribute :parent_event, :as => :superEvent, :type => :event
169
+
170
+ type :user_interaction, :as => :UserInteraction do
171
+ type :user_blocks, :as => :UserBlocks
172
+ type :user_checkin, :as => :UserCheckins
173
+ type :user_comments, :as => :UserComments
174
+ type :user_downloads, :as => :UserDownloads
175
+ type :user_likes, :as => :UserLikes
176
+ type :user_page_views, :as => :UserPageVisits
177
+ type :user_plays, :as => :UserPlays
178
+ type :user_votes, :as => :UserPlusOnes
179
+ type :user_tweets, :as => :UserTweets
180
+ end
181
+ end
182
+
183
+ type :intangible, :as => :Intangible do
184
+ type :intangible, :as => :Enumeration do
185
+ type :intangible, :as => :BookFormatType do
186
+ type :intangible, :as => :EBook
187
+ type :intangible, :as => :Hardcover
188
+ type :intangible, :as => :Paperback
189
+ end
190
+ type :intangible, :as => :ItemAvailability do
191
+ type :intangible, :as => :Discontinued
192
+ type :intangible, :as => :InStock
193
+ type :intangible, :as => :InStoreOnly
194
+ type :intangible, :as => :OnlineOnly
195
+ type :intangible, :as => :OutOfStock
196
+ type :intangible, :as => :PreOrder
197
+ end
198
+ type :intangible, :as => :OfferItemCondition do
199
+ type :intangible, :as => :DamagedCondition
200
+ type :intangible, :as => :NewCondition
201
+ type :intangible, :as => :RefurbishedCondition
202
+ type :intangible, :as => :UsedCondition
203
+ end
204
+ end
205
+ type :intangible, :as => :Language
206
+ type :quantity, :as => :Quantity do
207
+ type :quantity, :as => :Distance
208
+ type :quantity, :as => :Duration
209
+ type :quantity, :as => :Energy
210
+ type :quantity, :as => :Mass
211
+ end
212
+
213
+ type :offer, :as => :Offer do
214
+ attribute :rating, :as => :aggregateRating, :type => :rating
215
+ attribute :availability, :source => :item_availability
216
+ attribute :condition, :as => :itemCondition, :source => :offer_item_condition
217
+ attribute :item, :as => :itemOffered, :type => :product
218
+ attribute :price
219
+ attribute :min_price, :as => :lowPrice
220
+ attribute :max_price, :as => :highPrice
221
+ attribute :currency, :as => :priceCurrency # in 3-letter ISO 4217 format
222
+ attribute :valid_until_date, :as => :priceValidUntil, :type => :date
223
+ attribute :review, :as => :reviews, :type => :review
224
+ attribute :seller, :type => :organization
225
+ attribute :count, :as => :offerCount
226
+
227
+ type :aggregate, :as => :AggregateOffer
228
+ end
229
+
230
+ type :intangible, :as => :StructuredValue do
231
+ type :rating do
232
+ attribute :best, :as => :bestRating
233
+ attribute :value, :as => :ratingValue
234
+ attribute :worst, :as => :worstRating
235
+ attribute :item, :as => :itemReviewed, :type => :base
236
+ attribute :rating_count, :as => :ratingCount
237
+ attribute :review_count, :as => :reviewCount
238
+ end
239
+ type :coordinates, :as => :GeoCoordinates do
240
+ attribute :elevation, :type => :measurement
241
+ attribute :latitude, :type => :measurement
242
+ attribute :longitude, :type => :measurement
243
+ end
244
+ end
245
+ end
246
+
247
+ type :organization, :as => :Organization do
248
+ attribute :address, :type => :address
249
+ attribute :average_rating, :as => :aggregateRating, :type => :rating
250
+ attribute :contact, :as => :contactPoints, :type => :contact
251
+ attribute :email
252
+ attribute :employee, :as => :employees, :type => :person
253
+ attribute :event, :as => :events, :type => :event
254
+ attribute :fax, :as => :faxNumber
255
+ attribute :founder, :as => :founders, :type => :person
256
+ attribute :founding_date, :as => :foundingDate, :type => :date
257
+
258
+ type :corporation, :as => :Corporation
259
+ type :educational_institution, :as => :EducationalOrganization do
260
+ type :college, :as => :CollegeOrUniversity
261
+ type :elementary_school, :as => :ElementarySchool
262
+ type :high_school, :as => :HighSchool
263
+ type :middle_school, :as => :MiddleSchool
264
+ type :pre_school, :as => :Preschool
265
+ type :school, :as => :School
266
+ end
267
+
268
+ type :governmental_institution, :as => :GovernmentOrganization
269
+
270
+ type :vendor, :as => :LocalBusiness do
271
+ attribute :branch_of, :as => :branchOf, :type => :organization
272
+ attribute :hours, :as => :openingHours
273
+ attribute :currency, :as => :currenciesAccepted # The currency accepted (in ISO 4217 currency format).
274
+ attribute :payment_method, :as => :paymentAccepted # Cash, credit card, etc.
275
+ attribute :price_range, :as => :priceRange # i.e. "$$$"
276
+ # for restaurant only only
277
+ attribute :menu
278
+ attribute :reservations, :as => :acceptsReservations # Either Yes/No, or a URL at which reservations can be made.
279
+ attribute :cuisine, :as => :servesCuisine
280
+
281
+ type :vendor, :as => :AnimalShelter
282
+ type :vendor, :as => :AutomotiveBusiness do
283
+ type :vendor, :as => :AutoBodyShop
284
+ type :vendor, :as => :AutoDealer
285
+ type :vendor, :as => :AutoPartsStore
286
+ type :vendor, :as => :AutoRental
287
+ type :vendor, :as => :AutoRepair
288
+ type :vendor, :as => :AutoWash
289
+ type :vendor, :as => :GasStation
290
+ type :vendor, :as => :MotorcycleDealer
291
+ type :vendor, :as => :MotorcycleRepair
292
+ end
293
+ type :vendor, :as => :ChildCare
294
+ type :vendor, :as => :DryCleaningOrLaundry
295
+ type :vendor, :as => :EmergencyService do
296
+ type :vendor, :as => :FireStation
297
+ type :vendor, :as => :Hospital
298
+ type :vendor, :as => :PoliceStation
299
+ end
300
+ type :vendor, :as => :EmploymentAgency
301
+ type :vendor, :as => :EntertainmentBusiness
302
+ type :vendor, :as => :FinancialService
303
+ type :vendor, :as => :FoodEstablishment
304
+ type :vendor, :as => :GovernmentOffice
305
+ type :vendor, :as => :HealthAndBeautyBusiness
306
+ type :vendor, :as => :HomeAndConstructionBusiness
307
+ type :vendor, :as => :InternetCafe
308
+ type :vendor, :as => :Library
309
+ type :vendor, :as => :LodgingBusiness
310
+ type :vendor, :as => :MedicalOrganization
311
+ type :vendor, :as => :ProfessionalService
312
+ type :vendor, :as => :RadioStation
313
+ type :vendor, :as => :RealEstateAgent
314
+ type :vendor, :as => :RecyclingCenter
315
+ type :vendor, :as => :SelfStorage
316
+ type :vendor, :as => :ShoppingCenter
317
+ type :vendor, :as => :SportsActivityLocation
318
+ type :vendor, :as => :Store
319
+ type :vendor, :as => :TelevisionStation
320
+ type :vendor, :as => :TouristInformationCenter
321
+ type :vendor, :as => :TravelAgency
322
+ end
323
+
324
+ type :ngo, :as => :NGO
325
+ type :performing_group, :as => :PerformingGroup
326
+ type :sports_team, :as => :SportsTeam
327
+ end
328
+
329
+ type :person, :as => :Person do
330
+ # addresses
331
+ attribute :address, :type => :address
332
+ attribute :home_address, :as => :homeLocation, :type => :place
333
+ attribute :work_address, :as => :workLocation, :type => :place
334
+
335
+ # organizations
336
+ attribute :organization, :type => :organization
337
+ attribute :education, :type => :organization, :source => :education
338
+ attribute :membership, :type => :organization
339
+ attribute :company, :type => :organization, :as => :worksFor
340
+
341
+ # events
342
+ attribute :performer_in, :type => :event, :as => :performerIn
343
+
344
+ # dates
345
+ attribute :born_on, :type => :date, :as => :birthDate
346
+ attribute :died_on, :type => :date, :as => :deathDate
347
+
348
+ # relationships
349
+ attribute :children, :type => :person
350
+ attribute :parents, :type => :person
351
+ attribute :siblings, :type => :person
352
+ attribute :spouse, :type => :person
353
+ attribute :relationship, :type => :person, :as => :relatedTo
354
+ attribute :colleagues, :type => :person
355
+ # unidirectional
356
+ attribute :follows, :type => :person
357
+ # bidirectional
358
+ attribute :knows, :type => :person
359
+
360
+ # info
361
+ attribute :contact_info, :type => :contact, :as => :contactPoints
362
+ attribute :email
363
+ attribute :phone, :as => :telephone
364
+ attribute :fax, :as => :faxNumber
365
+ attribute :gender
366
+ attribute :interaction_count, :as => :interactionCount
367
+ attribute :job_title, :as => :jobTitle
368
+ attribute :nationality, :type => :place, :source => :country
369
+ end
370
+
371
+ type :place, :as => :Place do
372
+ attribute :address, :type => :address
373
+ attribute :rating, :type => :rating, :as => :aggregateRating
374
+ attribute :surrounding, :type => :place, :as => :containedIn
375
+ attribute :event, :type => :event, :as => :events
376
+ attribute :fax, :as => :faxNumber
377
+ attribute :coordinates, :type => :coordinates, :as => :geo
378
+ attribute :interaction_count, :as => :interactionCount
379
+ attribute :map, :as => :maps
380
+ attribute :image, :type => :image, :as => :photos
381
+ attribute :review, :type => :review, :as => :reviews
382
+ attribute :phone, :as => :telephone
383
+
384
+ type :place, :as => :AdministrativeArea do
385
+ type :place, :as => :City
386
+ type :place, :as => :Country
387
+ type :place, :as => :State
388
+ end
389
+
390
+ type :place, :as => :LandmarksOrHistoricalBuildings
391
+ type :place, :as => :TouristAttraction
392
+
393
+ type :place, :as => :CivicStructure do
394
+ attribute :hours, :as => :openingHours
395
+
396
+ type :place, :as => :Airport
397
+ type :place, :as => :Aquarium
398
+ type :place, :as => :Beach
399
+ type :place, :as => :BusStation
400
+ type :place, :as => :BusStop
401
+ type :place, :as => :Campground
402
+ type :place, :as => :Cemetery
403
+ type :place, :as => :Crematorium
404
+ type :place, :as => :EventVenue
405
+ type :place, :as => :FireStation
406
+ type :place, :as => :GovernmentBuilding
407
+ type :place, :as => :Hospital
408
+ type :place, :as => :MovieTheater
409
+ type :place, :as => :Museum
410
+ type :place, :as => :MusicVenue
411
+ type :place, :as => :Park
412
+ type :place, :as => :ParkingFacility
413
+ type :place, :as => :PerformingArtsTheater
414
+ type :place, :as => :PlaceOfWorship
415
+ type :place, :as => :Playground
416
+ type :place, :as => :PoliceStation
417
+ type :place, :as => :RVPark
418
+ type :place, :as => :StadiumOrArena
419
+ type :place, :as => :SubwayStation
420
+ type :place, :as => :TaxiStand
421
+ type :place, :as => :TrainStation
422
+ type :place, :as => :Zoo
423
+ end
424
+
425
+ type :place, :as => :Landform do
426
+ type :place, :as => :BodyOfWater
427
+ type :place, :as => :Continent
428
+ type :place, :as => :Mountain
429
+ type :place, :as => :Volcano
430
+ end
431
+
432
+ type :place, :as => :Residence do
433
+ type :place, :as => :ApartmentComplex
434
+ type :place, :as => :GatedResidenceCommunity
435
+ type :place, :as => :SingleFamilyResidence
436
+ end
437
+ end
438
+
439
+ type :product, :as => :Product do
440
+ attribute :rating, :as => :aggregateRating, :type => :rating
441
+ attribute :brand, :type => :organization
442
+ attribute :manufacturer, :type => :organization
443
+ attribute :model
444
+ attribute :offer, :as => :offers, :type => :offer
445
+ attribute :uid, :as => :productID
446
+ attribute :review, :as => :reviews, :type => :review
447
+ end
448
+ end
449
+ end
450
+ end