microformats2 1.0.2 → 2.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (205) hide show
  1. data/.gitignore +18 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +4 -0
  5. data/Guardfile +5 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +117 -26
  8. data/Rakefile +65 -9
  9. data/lib/microformats2.rb +30 -115
  10. data/lib/microformats2/collection.rb +71 -0
  11. data/lib/microformats2/format.rb +101 -0
  12. data/lib/microformats2/format_parser.rb +59 -0
  13. data/lib/microformats2/implied_property/foundation.rb +58 -0
  14. data/lib/microformats2/implied_property/name.rb +34 -0
  15. data/lib/microformats2/implied_property/photo.rb +24 -0
  16. data/lib/microformats2/implied_property/url.rb +20 -0
  17. data/lib/microformats2/property.rb +10 -0
  18. data/lib/microformats2/property/date_time.rb +31 -0
  19. data/lib/microformats2/property/embedded.rb +9 -0
  20. data/lib/microformats2/property/foundation.rb +80 -0
  21. data/lib/microformats2/property/text.rb +16 -0
  22. data/lib/microformats2/property/url.rb +18 -0
  23. data/lib/microformats2/property_parser.rb +54 -0
  24. data/lib/microformats2/version.rb +3 -0
  25. data/microformats2.gemspec +30 -0
  26. data/spec/lib/microformats2/collection_spec.rb +181 -0
  27. data/spec/lib/microformats2/implied_property/name_spec.rb +31 -0
  28. data/spec/lib/microformats2/implied_property/photo_spec.rb +31 -0
  29. data/spec/lib/microformats2/implied_property/url_spec.rb +31 -0
  30. data/spec/lib/microformats2_spec.rb +30 -0
  31. data/spec/spec_helper.rb +10 -0
  32. data/spec/support/cases/microformat2-node.jit.su/h-adr/h-adr-0.html +3 -0
  33. data/spec/support/cases/microformat2-node.jit.su/h-adr/h-adr-0.js +10 -0
  34. data/spec/support/cases/microformat2-node.jit.su/h-adr/h-adr-1.html +10 -0
  35. data/spec/support/cases/microformat2-node.jit.su/h-adr/h-adr-1.js +16 -0
  36. data/spec/support/cases/microformat2-node.jit.su/h-adr/h-adr-2.html +12 -0
  37. data/spec/support/cases/microformat2-node.jit.su/h-adr/h-adr-2.js +16 -0
  38. data/spec/support/cases/microformat2-node.jit.su/h-adr/h-adr-3.html +6 -0
  39. data/spec/support/cases/microformat2-node.jit.su/h-adr/h-adr-3.js +12 -0
  40. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-0.html +3 -0
  41. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-0.js +10 -0
  42. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-1.html +3 -0
  43. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-1.js +11 -0
  44. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-2.html +4 -0
  45. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-2.js +12 -0
  46. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-3.html +11 -0
  47. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-3.js +15 -0
  48. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-4.html +6 -0
  49. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-4.js +26 -0
  50. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-5.html +6 -0
  51. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-5.js +30 -0
  52. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-6.html +6 -0
  53. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-6.js +29 -0
  54. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-7.html +16 -0
  55. data/spec/support/cases/microformat2-node.jit.su/h-card/h-card-7.js +15 -0
  56. data/spec/support/cases/microformat2-node.jit.su/h-entry/h-entry-0.html +4 -0
  57. data/spec/support/cases/microformat2-node.jit.su/h-entry/h-entry-0.js +10 -0
  58. data/spec/support/cases/microformat2-node.jit.su/h-entry/h-entry-1.html +3 -0
  59. data/spec/support/cases/microformat2-node.jit.su/h-entry/h-entry-1.js +11 -0
  60. data/spec/support/cases/microformat2-node.jit.su/h-entry/h-entry-2.html +21 -0
  61. data/spec/support/cases/microformat2-node.jit.su/h-entry/h-entry-2.js +28 -0
  62. data/spec/support/cases/microformat2-node.jit.su/h-entry/h-entry-3.html +22 -0
  63. data/spec/support/cases/microformat2-node.jit.su/h-entry/h-entry-3.js +21 -0
  64. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-0.html +3 -0
  65. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-0.js +10 -0
  66. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-1.html +3 -0
  67. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-1.js +11 -0
  68. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-2.html +14 -0
  69. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-2.js +57 -0
  70. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-3.html +15 -0
  71. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-3.js +35 -0
  72. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-4.html +9 -0
  73. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-4.js +12 -0
  74. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-5.html +45 -0
  75. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-5.js +22 -0
  76. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-6.html +51 -0
  77. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-6.js +21 -0
  78. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-7.html +22 -0
  79. data/spec/support/cases/microformat2-node.jit.su/h-event/h-event-7.js +20 -0
  80. data/spec/support/cases/microformat2-node.jit.su/h-geo/h-geo-0.html +5 -0
  81. data/spec/support/cases/microformat2-node.jit.su/h-geo/h-geo-0.js +10 -0
  82. data/spec/support/cases/microformat2-node.jit.su/h-geo/h-geo-1.html +7 -0
  83. data/spec/support/cases/microformat2-node.jit.su/h-geo/h-geo-1.js +12 -0
  84. data/spec/support/cases/microformat2-node.jit.su/h-geo/h-geo-2.html +10 -0
  85. data/spec/support/cases/microformat2-node.jit.su/h-geo/h-geo-2.js +13 -0
  86. data/spec/support/cases/microformat2-node.jit.su/h-geo/h-geo-3.html +12 -0
  87. data/spec/support/cases/microformat2-node.jit.su/h-geo/h-geo-3.js +12 -0
  88. data/spec/support/cases/microformat2-node.jit.su/h-geo/h-geo-4.html +12 -0
  89. data/spec/support/cases/microformat2-node.jit.su/h-geo/h-geo-4.js +12 -0
  90. data/spec/support/cases/microformat2-node.jit.su/h-geo/h-geo-5.html +6 -0
  91. data/spec/support/cases/microformat2-node.jit.su/h-geo/h-geo-5.js +12 -0
  92. data/spec/support/cases/microformat2-node.jit.su/h-news/h-news-0.html +26 -0
  93. data/spec/support/cases/microformat2-node.jit.su/h-news/h-news-0.js +37 -0
  94. data/spec/support/cases/microformat2-node.jit.su/h-news/h-news-1.html +37 -0
  95. data/spec/support/cases/microformat2-node.jit.su/h-news/h-news-1.js +48 -0
  96. data/spec/support/cases/microformat2-node.jit.su/h-org/h-org-0.html +3 -0
  97. data/spec/support/cases/microformat2-node.jit.su/h-org/h-org-0.js +10 -0
  98. data/spec/support/cases/microformat2-node.jit.su/h-org/h-org-1.html +3 -0
  99. data/spec/support/cases/microformat2-node.jit.su/h-org/h-org-1.js +11 -0
  100. data/spec/support/cases/microformat2-node.jit.su/h-org/h-org-2.html +6 -0
  101. data/spec/support/cases/microformat2-node.jit.su/h-org/h-org-2.js +12 -0
  102. data/spec/support/cases/microformat2-node.jit.su/h-product/h-product-0.html +3 -0
  103. data/spec/support/cases/microformat2-node.jit.su/h-product/h-product-0.js +10 -0
  104. data/spec/support/cases/microformat2-node.jit.su/h-product/h-product-1.html +3 -0
  105. data/spec/support/cases/microformat2-node.jit.su/h-product/h-product-1.js +11 -0
  106. data/spec/support/cases/microformat2-node.jit.su/h-product/h-product-2.html +11 -0
  107. data/spec/support/cases/microformat2-node.jit.su/h-product/h-product-2.js +23 -0
  108. data/spec/support/cases/microformat2-node.jit.su/h-product/h-product-3.html +22 -0
  109. data/spec/support/cases/microformat2-node.jit.su/h-product/h-product-3.js +42 -0
  110. data/spec/support/cases/microformat2-node.jit.su/h-recipe/h-recipe-0.html +9 -0
  111. data/spec/support/cases/microformat2-node.jit.su/h-recipe/h-recipe-0.js +11 -0
  112. data/spec/support/cases/microformat2-node.jit.su/h-recipe/h-recipe-1.html +67 -0
  113. data/spec/support/cases/microformat2-node.jit.su/h-recipe/h-recipe-1.js +51 -0
  114. data/spec/support/cases/microformat2-node.jit.su/h-resume/h-resume-0.html +3 -0
  115. data/spec/support/cases/microformat2-node.jit.su/h-resume/h-resume-0.js +10 -0
  116. data/spec/support/cases/microformat2-node.jit.su/h-resume/h-resume-1.html +20 -0
  117. data/spec/support/cases/microformat2-node.jit.su/h-resume/h-resume-1.js +39 -0
  118. data/spec/support/cases/microformat2-node.jit.su/h-resume/h-resume-2.html +17 -0
  119. data/spec/support/cases/microformat2-node.jit.su/h-resume/h-resume-2.js +54 -0
  120. data/spec/support/cases/microformat2-node.jit.su/h-resume/h-resume-3.html +15 -0
  121. data/spec/support/cases/microformat2-node.jit.su/h-resume/h-resume-3.js +54 -0
  122. data/spec/support/cases/microformat2-node.jit.su/h-resume/h-resume-4.html +15 -0
  123. data/spec/support/cases/microformat2-node.jit.su/h-resume/h-resume-4.js +12 -0
  124. data/spec/support/cases/microformat2-node.jit.su/h-resume/h-resume-5.html +13 -0
  125. data/spec/support/cases/microformat2-node.jit.su/h-resume/h-resume-5.js +27 -0
  126. data/spec/support/cases/microformat2-node.jit.su/h-review-aggregate/h-review-aggregate-0.html +10 -0
  127. data/spec/support/cases/microformat2-node.jit.su/h-review-aggregate/h-review-aggregate-0.js +19 -0
  128. data/spec/support/cases/microformat2-node.jit.su/h-review-aggregate/h-review-aggregate-1.html +20 -0
  129. data/spec/support/cases/microformat2-node.jit.su/h-review-aggregate/h-review-aggregate-1.js +26 -0
  130. data/spec/support/cases/microformat2-node.jit.su/h-review-aggregate/h-review-aggregate-2.html +15 -0
  131. data/spec/support/cases/microformat2-node.jit.su/h-review-aggregate/h-review-aggregate-2.js +23 -0
  132. data/spec/support/cases/microformat2-node.jit.su/h-review/h-review-0.html +3 -0
  133. data/spec/support/cases/microformat2-node.jit.su/h-review/h-review-0.js +10 -0
  134. data/spec/support/cases/microformat2-node.jit.su/h-review/h-review-1.html +3 -0
  135. data/spec/support/cases/microformat2-node.jit.su/h-review/h-review-1.js +11 -0
  136. data/spec/support/cases/microformat2-node.jit.su/h-review/h-review-2.html +3 -0
  137. data/spec/support/cases/microformat2-node.jit.su/h-review/h-review-2.js +11 -0
  138. data/spec/support/cases/microformat2-node.jit.su/h-review/h-review-3.html +6 -0
  139. data/spec/support/cases/microformat2-node.jit.su/h-review/h-review-3.js +19 -0
  140. data/spec/support/cases/microformat2-node.jit.su/h-review/h-review-4.html +8 -0
  141. data/spec/support/cases/microformat2-node.jit.su/h-review/h-review-4.js +20 -0
  142. data/spec/support/cases/microformat2-node.jit.su/h-review/h-review-5.html +24 -0
  143. data/spec/support/cases/microformat2-node.jit.su/h-review/h-review-5.js +37 -0
  144. data/spec/support/cases/microformat2-node.jit.su/includes/includes-0.html +18 -0
  145. data/spec/support/cases/microformat2-node.jit.su/includes/includes-0.js +43 -0
  146. data/spec/support/cases/microformat2-node.jit.su/includes/includes-1.html +26 -0
  147. data/spec/support/cases/microformat2-node.jit.su/includes/includes-1.js +54 -0
  148. data/spec/support/cases/microformat2-node.jit.su/includes/includes-2.html +13 -0
  149. data/spec/support/cases/microformat2-node.jit.su/includes/includes-2.js +20 -0
  150. data/spec/support/cases/microformat2-node.jit.su/includes/includes-3.html +20 -0
  151. data/spec/support/cases/microformat2-node.jit.su/includes/includes-3.js +40 -0
  152. data/spec/support/cases/microformat2-node.jit.su/includes/includes-4.html +23 -0
  153. data/spec/support/cases/microformat2-node.jit.su/includes/includes-4.js +42 -0
  154. data/spec/support/cases/microformat2-node.jit.su/rel/rel-0.html +3 -0
  155. data/spec/support/cases/microformat2-node.jit.su/rel/rel-0.js +10 -0
  156. data/spec/support/cases/microformat2-node.jit.su/rel/rel-1.html +3 -0
  157. data/spec/support/cases/microformat2-node.jit.su/rel/rel-1.js +10 -0
  158. data/spec/support/cases/microformat2-node.jit.su/rel/rel-2.html +12 -0
  159. data/spec/support/cases/microformat2-node.jit.su/rel/rel-2.js +19 -0
  160. data/spec/support/cases/microformat2-node.jit.su/rel/rel-3.html +21 -0
  161. data/spec/support/cases/microformat2-node.jit.su/rel/rel-3.js +26 -0
  162. data/spec/support/cases/microformat2-node.jit.su/rel/rel-4.html +15 -0
  163. data/spec/support/cases/microformat2-node.jit.su/rel/rel-4.js +42 -0
  164. data/spec/support/cases/microformats.org/microformats-2/microformats-2-0.html +2 -0
  165. data/spec/support/cases/microformats.org/microformats-2/microformats-2-0.js +9 -0
  166. data/spec/support/cases/microformats.org/microformats-2/microformats-2-1.html +2 -0
  167. data/spec/support/cases/microformats.org/microformats-2/microformats-2-1.js +10 -0
  168. data/spec/support/cases/microformats.org/microformats-2/microformats-2-2.html +5 -0
  169. data/spec/support/cases/microformats.org/microformats-2/microformats-2-2.js +11 -0
  170. data/spec/support/cases/microformats.org/microformats-2/microformats-2-3.html +17 -0
  171. data/spec/support/cases/microformats.org/microformats-2/microformats-2-3.js +20 -0
  172. data/spec/support/cases/microformats.org/microformats-2/microformats-2-4.html +16 -0
  173. data/spec/support/cases/microformats.org/microformats-2/microformats-2-4.js +24 -0
  174. data/spec/support/cases/microformats.org/microformats-2/microformats-2-5.html +7 -0
  175. data/spec/support/cases/microformats.org/microformats-2/microformats-2-5.js +11 -0
  176. data/spec/support/cases/microformats.org/microformats-2/microformats-2-6.html +9 -0
  177. data/spec/support/cases/microformats.org/microformats-2/microformats-2-6.js +18 -0
  178. data/spec/support/cases/microformats.org/microformats-2/microformats-2-7.html +9 -0
  179. data/spec/support/cases/microformats.org/microformats-2/microformats-2-7.js +18 -0
  180. data/spec/support/cases/microformats.org/microformats-2/microformats-2-8.html +9 -0
  181. data/spec/support/cases/microformats.org/microformats-2/microformats-2-8.js +17 -0
  182. data/spec/support/cases/microformats.org/microformats-2/microformats-2-9.html +9 -0
  183. data/spec/support/cases/microformats.org/microformats-2/microformats-2-9.js +17 -0
  184. data/spec/support/lib/microformats2/implied_property/name-fail.html +60 -0
  185. data/spec/support/lib/microformats2/implied_property/name-pass.html +30 -0
  186. data/spec/support/lib/microformats2/implied_property/photo-fail.html +60 -0
  187. data/spec/support/lib/microformats2/implied_property/photo-pass.html +30 -0
  188. data/spec/support/lib/microformats2/implied_property/url-fail.html +18 -0
  189. data/spec/support/lib/microformats2/implied_property/url-pass.html +12 -0
  190. data/spec/support/lib/microformats2/nested-format-with-property.html +12 -0
  191. data/spec/support/lib/microformats2/nested-format-with-property.js +15 -0
  192. data/spec/support/lib/microformats2/nested-format-without-property.html +13 -0
  193. data/spec/support/lib/microformats2/nested-property.html +12 -0
  194. data/spec/support/lib/microformats2/nested-property.js +9 -0
  195. data/spec/support/lib/microformats2/simple.html +19 -0
  196. data/spec/support/lib/microformats2/simple.js +10 -0
  197. metadata +535 -85
  198. data/.autotest +0 -23
  199. data/.gemtest +0 -0
  200. data/History.txt +0 -19
  201. data/Manifest.txt +0 -10
  202. data/bin/microformats2 +0 -3
  203. data/test/IndieWebCamp.html +0 -351
  204. data/test/simple.html +0 -30
  205. data/test/test_microformats2.rb +0 -185
@@ -0,0 +1,71 @@
1
+ module Microformats2
2
+ class Collection
3
+ attr_reader :all
4
+
5
+ def initialize(element)
6
+ @element = element
7
+ @format_names = []
8
+ end
9
+
10
+ def parse
11
+ all
12
+ self
13
+ end
14
+
15
+ def all
16
+ @all ||= FormatParser.parse(@element).each do |format|
17
+ save_format_name(format.method_name)
18
+ define_method(format.method_name)
19
+ set_value(format.method_name, format)
20
+ end
21
+ end
22
+
23
+ def first
24
+ all.first
25
+ end
26
+
27
+ def last
28
+ all.last
29
+ end
30
+
31
+ def to_hash
32
+ hash = { items: [] }
33
+ all.each do |format|
34
+ hash[:items] << format.to_hash
35
+ end
36
+ hash
37
+ end
38
+
39
+ def to_json
40
+ to_hash.to_json
41
+ end
42
+
43
+ private
44
+
45
+ def save_format_name(format_name)
46
+ unless @format_names.include?(format_name)
47
+ @format_names << format_name
48
+ end
49
+ end
50
+
51
+ def define_method(mn)
52
+ unless respond_to?(mn)
53
+ self.class.class_eval { attr_accessor mn }
54
+ end
55
+ unless respond_to?(mn.pluralize)
56
+ self.class.class_eval { attr_accessor mn.pluralize }
57
+ end
58
+ end
59
+
60
+ def set_value(mn, value)
61
+ unless current = send(mn)
62
+ send("#{mn}=", value)
63
+ end
64
+ if current = send(mn.pluralize)
65
+ current << value
66
+ else
67
+ send("#{mn.pluralize}=", [value])
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,101 @@
1
+ module Microformats2
2
+ class Format
3
+ CLASS_REG_EXP = /^(h-)/
4
+
5
+ attr_reader :method_name
6
+
7
+ def initialize(element)
8
+ @element = element
9
+ @method_name = to_method_name(format_types.first)
10
+ @property_names = []
11
+ end
12
+
13
+ def parse
14
+ format_types
15
+ properties
16
+ self
17
+ end
18
+
19
+ def format_types
20
+ @format_types ||= @element.attribute("class").to_s.split.select do |html_class|
21
+ html_class =~ Format::CLASS_REG_EXP
22
+ end
23
+ end
24
+
25
+ def properties
26
+ @properties ||= parse_properties.concat parse_implied_properties
27
+ end
28
+
29
+ def parse_properties
30
+ PropertyParser.parse(@element.children).each do |property|
31
+ save_property_name(property.method_name)
32
+ define_method(property.method_name)
33
+ set_value(property.method_name, property)
34
+ end
35
+ end
36
+
37
+ def parse_implied_properties
38
+ ip = []
39
+ ip << ImpliedProperty::Name.new(@element).parse unless property_present?(:name)
40
+ ip << ImpliedProperty::Url.new(@element).parse unless property_present?(:url)
41
+ ip << ImpliedProperty::Photo.new(@element).parse unless property_present?(:photo)
42
+ ip.compact.each do |property|
43
+ save_property_name(property.method_name)
44
+ define_method(property.method_name)
45
+ set_value(property.method_name, property)
46
+ end
47
+ end
48
+
49
+ def property_present?(property)
50
+ !! respond_to?(property) && send(property)
51
+ end
52
+
53
+ def to_hash
54
+ hash = { type: format_types, properties: {} }
55
+ @property_names.each do |method_name|
56
+ hash[:properties][method_name.to_sym] = send(method_name.pluralize).map(&:to_hash)
57
+ end
58
+ hash
59
+ end
60
+
61
+ def to_json
62
+ to_hash.to_json
63
+ end
64
+
65
+ private
66
+
67
+ def to_method_name(html_class)
68
+ # p-class-name -> class_name
69
+ mn = html_class.downcase.split("-")[1..-1].join("_")
70
+ # avoid overriding Object#class
71
+ mn = "klass" if mn == "class"
72
+ mn
73
+ end
74
+
75
+ def save_property_name(property_name)
76
+ unless @property_names.include?(property_name)
77
+ @property_names << property_name
78
+ end
79
+ end
80
+
81
+ def define_method(mn)
82
+ unless respond_to?(mn)
83
+ self.class.class_eval { attr_accessor mn }
84
+ end
85
+ unless respond_to?(mn.pluralize)
86
+ self.class.class_eval { attr_accessor mn.pluralize }
87
+ end
88
+ end
89
+
90
+ def set_value(mn, value)
91
+ unless current = send(mn)
92
+ send("#{mn}=", value)
93
+ end
94
+ if current = send(mn.pluralize)
95
+ current << value
96
+ else
97
+ send("#{mn.pluralize}=", [value])
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,59 @@
1
+ module Microformats2
2
+ class FormatParser
3
+ class << self
4
+ def parse(element)
5
+ parse_node(element).flatten.compact
6
+ end
7
+
8
+ def parse_node(node)
9
+ case
10
+ when node.is_a?(Nokogiri::HTML::Document) then parse_node(node.children)
11
+ when node.is_a?(Nokogiri::XML::NodeSet) then parse_nodeset(node)
12
+ when node.is_a?(Nokogiri::XML::Element) then [parse_for_microformats(node)]
13
+ end
14
+ end
15
+
16
+ def parse_nodeset(nodeset)
17
+ nodeset.map { |node| parse_node(node) }
18
+ end
19
+
20
+ def parse_for_microformats(element)
21
+ if format_classes(element).length >= 1
22
+ parse_microformat(element)
23
+ else
24
+ parse_nodeset(element.children)
25
+ end
26
+ end
27
+
28
+ def parse_microformat(element)
29
+ # only create ruby object for first format class
30
+ html_class = format_classes(element).first
31
+ const_name = constant_name(html_class)
32
+ klass = find_or_create_ruby_class(const_name)
33
+
34
+ klass.new(element).parse
35
+ end
36
+
37
+ def format_classes(element)
38
+ element.attribute("class").to_s.split.select do |html_class|
39
+ html_class =~ Format::CLASS_REG_EXP
40
+ end
41
+ end
42
+
43
+ def constant_name(html_class)
44
+ # html-Class -> html-class -> html_class -> Html_class -> HtmlClass
45
+ html_class.downcase.gsub("-","_").gsub(/^([a-z])/){$1.upcase}.gsub(/_(.)/){$1.upcase}
46
+ end
47
+
48
+ def find_or_create_ruby_class(const_name)
49
+ if Object.const_defined?(const_name)
50
+ klass = Object.const_get(const_name)
51
+ else
52
+ klass = Class.new(Microformats2::Format)
53
+ Object.const_set const_name, klass
54
+ end
55
+ klass
56
+ end
57
+ end # class << self
58
+ end
59
+ end
@@ -0,0 +1,58 @@
1
+ module Microformats2
2
+ module ImpliedProperty
3
+ class Foundation
4
+
5
+ def initialize(element)
6
+ @element = element
7
+ end
8
+
9
+ def parse
10
+ self if to_s
11
+ end
12
+
13
+ def method_name
14
+ "foundation"
15
+ end
16
+
17
+ def to_s
18
+ @to_s ||= element_value || selector_value
19
+ end
20
+
21
+ def to_hash
22
+ to_s
23
+ end
24
+
25
+ def to_json
26
+ to_hash.to_json
27
+ end
28
+
29
+ protected
30
+
31
+ def element_value
32
+ name_map.each_pair do |elname, attr|
33
+ if elname == @element.name && @element.attribute(attr)
34
+ return @element.attribute(attr).to_s
35
+ end
36
+ end
37
+ nil
38
+ end
39
+
40
+ def name_map
41
+ {}
42
+ end
43
+
44
+ def selector_value
45
+ selector_map.each_pair do |sel, attr|
46
+ if selected_element = @element.css(sel).first
47
+ return selected_element.attribute(attr).to_s
48
+ end
49
+ end
50
+ nil
51
+ end
52
+
53
+ def selector_map
54
+ {}
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,34 @@
1
+ module Microformats2
2
+ module ImpliedProperty
3
+ class Name < Foundation
4
+
5
+ def method_name
6
+ "name"
7
+ end
8
+
9
+ def to_s
10
+ @to_s ||= element_value || selector_value || text_value
11
+ end
12
+
13
+ protected
14
+
15
+ def name_map
16
+ { "img" => "alt",
17
+ "abbr" => "title" }
18
+ end
19
+
20
+ def selector_map
21
+ { ">img[alt]:only-of-type" => "alt",
22
+ ">abbr[title]:only-of-type" => "title",
23
+ ">:only-of-type>img[alt]:only-of-type" => "alt",
24
+ ">:only-of-type>abbr[title]:only-of-type" => "title" }
25
+ end
26
+
27
+ private
28
+
29
+ def text_value
30
+ @element.inner_text.gsub(/\n+/, " ").gsub(/\s+/, " ").strip
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+ module Microformats2
2
+ module ImpliedProperty
3
+ class Photo < Foundation
4
+
5
+ def method_name
6
+ "photo"
7
+ end
8
+
9
+ protected
10
+
11
+ def name_map
12
+ { "img" => "src",
13
+ "object" => "data" }
14
+ end
15
+
16
+ def selector_map
17
+ { ">img[src]:only-of-type" => "src",
18
+ ">object[data]:only-of-type" => "data",
19
+ ">:only-child>img[src]:only-of-type" => "src",
20
+ ">:only-child>object[data]:only-of-type" => "data" }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ module Microformats2
2
+ module ImpliedProperty
3
+ class Url < Foundation
4
+
5
+ def method_name
6
+ "url"
7
+ end
8
+
9
+ protected
10
+
11
+ def name_map
12
+ { "a" => "href" }
13
+ end
14
+
15
+ def selector_map
16
+ { ">a[href]:only-of-type" => "href" }
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ module Microformats2
2
+ module Property
3
+ CLASS_REG_EXP = /^(p-|u-|dt-|e-)/
4
+ PREFIX_CLASS_MAP = {
5
+ "p" => Text,
6
+ "u" => Url,
7
+ "dt" => DateTime,
8
+ "e" => Embedded }
9
+ end
10
+ end
@@ -0,0 +1,31 @@
1
+ module Microformats2
2
+ module Property
3
+ class DateTime < Foundation
4
+ def to_s
5
+ @to_s ||= value_class_pattern || element_value || text_value
6
+ end
7
+
8
+ def value
9
+ ::DateTime.parse(to_s)
10
+ end
11
+
12
+ def to_hash
13
+ if formats.empty?
14
+ to_s
15
+ else
16
+ { value: to_s }.merge(formats.first.to_hash)
17
+ end
18
+ end
19
+
20
+ protected
21
+
22
+ def attr_map
23
+ @attr_map ||= {
24
+ "time" => "datetime",
25
+ "ins" => "datetime",
26
+ "abbr" => "title",
27
+ "data" => "value" }
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,9 @@
1
+ module Microformats2
2
+ module Property
3
+ class Embedded < Foundation
4
+ def to_s
5
+ @to_s ||= @element.inner_html.strip
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,80 @@
1
+ module Microformats2
2
+ module Property
3
+ class Foundation
4
+ attr_reader :method_name
5
+
6
+ def initialize(element, html_class)
7
+ @element = element
8
+ @method_name = to_method_name(html_class)
9
+ end
10
+
11
+ def parse
12
+ to_s
13
+ formats
14
+ self
15
+ end
16
+
17
+ def to_s
18
+ @to_s ||= value_class_pattern || element_value || text_value
19
+ end
20
+
21
+ def format
22
+ formats.first
23
+ end
24
+
25
+ def formats
26
+ @formats ||= format_classes.length >=1 ? FormatParser.parse(@element) : []
27
+ end
28
+
29
+ def to_hash
30
+ if formats.empty?
31
+ to_s
32
+ else
33
+ { value: to_s }.merge(formats.first.to_hash)
34
+ end
35
+ end
36
+
37
+ def to_json
38
+ to_hash.to_json
39
+ end
40
+
41
+ protected
42
+
43
+ def value_class_pattern
44
+ # TODO
45
+ end
46
+
47
+ def element_value
48
+ @element.attribute(attribute).to_s if attribute && @element.attribute(attribute)
49
+ end
50
+
51
+ def text_value
52
+ @element.inner_text.gsub(/\n+/, " ").gsub(/\s+/, " ").strip
53
+ end
54
+
55
+ def attribute
56
+ attr_map[@element.name]
57
+ end
58
+
59
+ def attr_map
60
+ {}
61
+ end
62
+
63
+ private
64
+
65
+ def to_method_name(html_class)
66
+ # p-class-name -> class_name
67
+ mn = html_class.downcase.split("-")[1..-1].join("_")
68
+ # avoid overriding Object#class
69
+ mn = "klass" if mn == "class"
70
+ mn
71
+ end
72
+
73
+ def format_classes
74
+ @format_classes = @element.attribute("class").to_s.split.select do |html_class|
75
+ html_class =~ Format::CLASS_REG_EXP
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end