microformats2 2.9.0 → 3.0.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.
Files changed (313) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +125 -25
  3. data/Rakefile +0 -60
  4. data/lib/microformats2.rb +7 -15
  5. data/lib/microformats2/absolute_uri.rb +5 -1
  6. data/lib/microformats2/format_parser.rb +321 -46
  7. data/lib/microformats2/parser.rb +86 -6
  8. data/lib/microformats2/parser_core.rb +343 -0
  9. data/lib/microformats2/property_parser.rb +104 -34
  10. data/lib/microformats2/results/collection.rb +121 -0
  11. data/lib/microformats2/results/parser_result.rb +111 -0
  12. data/lib/microformats2/results/property_set.rb +87 -0
  13. data/lib/microformats2/time_property_parser.rb +161 -0
  14. data/lib/microformats2/version.rb +1 -1
  15. data/microformats2.gemspec +2 -1
  16. data/spec/lib/microformats2/absolute_uri_spec.rb +2 -2
  17. data/spec/lib/microformats2/parser_spec.rb +36 -5
  18. data/spec/lib/microformats2_spec.rb +5 -5
  19. data/spec/spec_helper.rb +0 -1
  20. data/vendor/tests/.gitignore +25 -0
  21. data/vendor/tests/LICENSE.md +36 -0
  22. data/vendor/tests/README.md +48 -0
  23. data/vendor/tests/app.js +84 -0
  24. data/vendor/tests/composer.json +5 -0
  25. data/vendor/tests/css/testsuite.css +159 -0
  26. data/vendor/tests/interface.js +18 -0
  27. data/vendor/tests/package.json +27 -0
  28. data/vendor/tests/tests/microformats-mixed/h-card/change-log.html +63 -0
  29. data/vendor/tests/tests/microformats-mixed/h-card/mixedpropertries.html +14 -0
  30. data/vendor/tests/tests/microformats-mixed/h-card/mixedpropertries.json +22 -0
  31. data/vendor/tests/tests/microformats-mixed/h-card/tworoots.html +1 -0
  32. data/vendor/tests/tests/microformats-mixed/h-card/tworoots.json +10 -0
  33. data/vendor/tests/tests/microformats-mixed/h-entry/mixedroots.html +16 -0
  34. data/vendor/tests/tests/microformats-mixed/h-entry/mixedroots.json +38 -0
  35. data/vendor/tests/tests/microformats-mixed/h-resume/change-log.html +68 -0
  36. data/vendor/tests/tests/microformats-mixed/h-resume/mixedroots.html +16 -0
  37. data/vendor/tests/tests/microformats-mixed/h-resume/mixedroots.json +31 -0
  38. data/vendor/tests/tests/microformats-v1/adr/change-log.html +63 -0
  39. data/vendor/tests/tests/microformats-v1/adr/simpleproperties.html +8 -0
  40. data/vendor/tests/tests/microformats-v1/adr/simpleproperties.json +15 -0
  41. data/vendor/tests/tests/microformats-v1/geo/abbrpattern.html +5 -0
  42. data/vendor/tests/tests/microformats-v1/geo/abbrpattern.json +11 -0
  43. data/vendor/tests/tests/microformats-v1/geo/change-log.1.html +78 -0
  44. data/vendor/tests/tests/microformats-v1/geo/change-log.html +63 -0
  45. data/vendor/tests/tests/microformats-v1/geo/hidden.html +10 -0
  46. data/vendor/tests/tests/microformats-v1/geo/hidden.json +11 -0
  47. data/vendor/tests/tests/microformats-v1/geo/simpleproperties.html +6 -0
  48. data/vendor/tests/tests/microformats-v1/geo/simpleproperties.json +11 -0
  49. data/vendor/tests/tests/microformats-v1/geo/valuetitleclass.html +11 -0
  50. data/vendor/tests/tests/microformats-v1/geo/valuetitleclass.json +11 -0
  51. data/vendor/tests/tests/microformats-v1/hcalendar/ampm.html +41 -0
  52. data/vendor/tests/tests/microformats-v1/hcalendar/ampm.json +21 -0
  53. data/vendor/tests/tests/microformats-v1/hcalendar/attendees.html +13 -0
  54. data/vendor/tests/tests/microformats-v1/hcalendar/attendees.json +37 -0
  55. data/vendor/tests/tests/microformats-v1/hcalendar/change-log.html +68 -0
  56. data/vendor/tests/tests/microformats-v1/hcalendar/combining.html +15 -0
  57. data/vendor/tests/tests/microformats-v1/hcalendar/combining.json +31 -0
  58. data/vendor/tests/tests/microformats-v1/hcalendar/concatenate.html +7 -0
  59. data/vendor/tests/tests/microformats-v1/hcalendar/concatenate.json +12 -0
  60. data/vendor/tests/tests/microformats-v1/hcalendar/time.html +44 -0
  61. data/vendor/tests/tests/microformats-v1/hcalendar/time.json +22 -0
  62. data/vendor/tests/tests/microformats-v1/hcard/change-log.html +68 -0
  63. data/vendor/tests/tests/microformats-v1/hcard/email.html +14 -0
  64. data/vendor/tests/tests/microformats-v1/hcard/email.json +11 -0
  65. data/vendor/tests/tests/microformats-v1/hcard/format.html +6 -0
  66. data/vendor/tests/tests/microformats-v1/hcard/format.json +11 -0
  67. data/vendor/tests/tests/microformats-v1/hcard/hyperlinkedphoto.html +3 -0
  68. data/vendor/tests/tests/microformats-v1/hcard/hyperlinkedphoto.json +8 -0
  69. data/vendor/tests/tests/microformats-v1/hcard/justahyperlink.html +1 -0
  70. data/vendor/tests/tests/microformats-v1/hcard/justahyperlink.json +8 -0
  71. data/vendor/tests/tests/microformats-v1/hcard/justaname.html +1 -0
  72. data/vendor/tests/tests/microformats-v1/hcard/justaname.json +8 -0
  73. data/vendor/tests/tests/microformats-v1/hcard/multiple.html +74 -0
  74. data/vendor/tests/tests/microformats-v1/hcard/multiple.json +65 -0
  75. data/vendor/tests/tests/microformats-v1/hcard/name.html +11 -0
  76. data/vendor/tests/tests/microformats-v1/hcard/name.json +15 -0
  77. data/vendor/tests/tests/microformats-v1/hcard/single.html +14 -0
  78. data/vendor/tests/tests/microformats-v1/hcard/single.json +24 -0
  79. data/vendor/tests/tests/microformats-v1/hentry/change-log.html +73 -0
  80. data/vendor/tests/tests/microformats-v1/hentry/summarycontent.html +20 -0
  81. data/vendor/tests/tests/microformats-v1/hentry/summarycontent.json +24 -0
  82. data/vendor/tests/tests/microformats-v1/hfeed/simple.html +30 -0
  83. data/vendor/tests/tests/microformats-v1/hfeed/simple.json +49 -0
  84. data/vendor/tests/tests/microformats-v1/hnews/all.html +37 -0
  85. data/vendor/tests/tests/microformats-v1/hnews/all.json +74 -0
  86. data/vendor/tests/tests/microformats-v1/hnews/change-log.html +72 -0
  87. data/vendor/tests/tests/microformats-v1/hnews/minimum.html +25 -0
  88. data/vendor/tests/tests/microformats-v1/hnews/minimum.json +48 -0
  89. data/vendor/tests/tests/microformats-v1/hproduct/aggregate.html +26 -0
  90. data/vendor/tests/tests/microformats-v1/hproduct/aggregate.json +52 -0
  91. data/vendor/tests/tests/microformats-v1/hproduct/change-log.html +62 -0
  92. data/vendor/tests/tests/microformats-v1/hproduct/simpleproperties.html +13 -0
  93. data/vendor/tests/tests/microformats-v1/hproduct/simpleproperties.json +33 -0
  94. data/vendor/tests/tests/microformats-v1/hresume/affiliation.html +12 -0
  95. data/vendor/tests/tests/microformats-v1/hresume/affiliation.json +25 -0
  96. data/vendor/tests/tests/microformats-v1/hresume/change-log.html +73 -0
  97. data/vendor/tests/tests/microformats-v1/hresume/contact.html +18 -0
  98. data/vendor/tests/tests/microformats-v1/hresume/contact.json +32 -0
  99. data/vendor/tests/tests/microformats-v1/hresume/education.html +13 -0
  100. data/vendor/tests/tests/microformats-v1/hresume/education.json +29 -0
  101. data/vendor/tests/tests/microformats-v1/hresume/skill.html +12 -0
  102. data/vendor/tests/tests/microformats-v1/hresume/skill.json +33 -0
  103. data/vendor/tests/tests/microformats-v1/hresume/work.html +16 -0
  104. data/vendor/tests/tests/microformats-v1/hresume/work.json +30 -0
  105. data/vendor/tests/tests/microformats-v1/hreview-aggregate/change-log.html +67 -0
  106. data/vendor/tests/tests/microformats-v1/hreview-aggregate/hcard.html +18 -0
  107. data/vendor/tests/tests/microformats-v1/hreview-aggregate/hcard.json +31 -0
  108. data/vendor/tests/tests/microformats-v1/hreview-aggregate/justahyperlink.html +6 -0
  109. data/vendor/tests/tests/microformats-v1/hreview-aggregate/justahyperlink.json +19 -0
  110. data/vendor/tests/tests/microformats-v1/hreview-aggregate/vevent.html +13 -0
  111. data/vendor/tests/tests/microformats-v1/hreview-aggregate/vevent.json +22 -0
  112. data/vendor/tests/tests/microformats-v1/hreview/change-log.html +73 -0
  113. data/vendor/tests/tests/microformats-v1/hreview/item.html +8 -0
  114. data/vendor/tests/tests/microformats-v1/hreview/item.json +19 -0
  115. data/vendor/tests/tests/microformats-v1/hreview/vcard.html +23 -0
  116. data/vendor/tests/tests/microformats-v1/hreview/vcard.json +58 -0
  117. data/vendor/tests/tests/microformats-v1/includes/change-log.html +72 -0
  118. data/vendor/tests/tests/microformats-v1/includes/hcarditemref.html +16 -0
  119. data/vendor/tests/tests/microformats-v1/includes/hcarditemref.json +49 -0
  120. data/vendor/tests/tests/microformats-v1/includes/heventitemref.html +25 -0
  121. data/vendor/tests/tests/microformats-v1/includes/heventitemref.json +33 -0
  122. data/vendor/tests/tests/microformats-v1/includes/hyperlink.html +18 -0
  123. data/vendor/tests/tests/microformats-v1/includes/hyperlink.json +43 -0
  124. data/vendor/tests/tests/microformats-v1/includes/object.html +23 -0
  125. data/vendor/tests/tests/microformats-v1/includes/object.json +42 -0
  126. data/vendor/tests/tests/microformats-v1/includes/table.html +12 -0
  127. data/vendor/tests/tests/microformats-v1/includes/table.json +19 -0
  128. data/vendor/tests/tests/microformats-v2/h-adr/change-log.html +62 -0
  129. data/vendor/tests/tests/microformats-v2/h-adr/geo.html +10 -0
  130. data/vendor/tests/tests/microformats-v2/h-adr/geo.json +16 -0
  131. data/vendor/tests/tests/microformats-v2/h-adr/geourl.html +4 -0
  132. data/vendor/tests/tests/microformats-v2/h-adr/geourl.json +13 -0
  133. data/vendor/tests/tests/microformats-v2/h-adr/justaname.html +1 -0
  134. data/vendor/tests/tests/microformats-v2/h-adr/justaname.json +10 -0
  135. data/vendor/tests/tests/microformats-v2/h-adr/lettercase.html +21 -0
  136. data/vendor/tests/tests/microformats-v2/h-adr/lettercase.json +12 -0
  137. data/vendor/tests/tests/microformats-v2/h-adr/simpleproperties.html +8 -0
  138. data/vendor/tests/tests/microformats-v2/h-adr/simpleproperties.json +16 -0
  139. data/vendor/tests/tests/microformats-v2/h-as-note/note.html +56 -0
  140. data/vendor/tests/tests/microformats-v2/h-as-note/note.json +98 -0
  141. data/vendor/tests/tests/microformats-v2/h-card/baseurl.html +6 -0
  142. data/vendor/tests/tests/microformats-v2/h-card/baseurl.json +26 -0
  143. data/vendor/tests/tests/microformats-v2/h-card/change-log.html +100 -0
  144. data/vendor/tests/tests/microformats-v2/h-card/childimplied.html +7 -0
  145. data/vendor/tests/tests/microformats-v2/h-card/childimplied.json +12 -0
  146. data/vendor/tests/tests/microformats-v2/h-card/extendeddescription.html +10 -0
  147. data/vendor/tests/tests/microformats-v2/h-card/extendeddescription.json +15 -0
  148. data/vendor/tests/tests/microformats-v2/h-card/hcard.html +4 -0
  149. data/vendor/tests/tests/microformats-v2/h-card/hcard.json +19 -0
  150. data/vendor/tests/tests/microformats-v2/h-card/horghcard.html +4 -0
  151. data/vendor/tests/tests/microformats-v2/h-card/horghcard.json +19 -0
  152. data/vendor/tests/tests/microformats-v2/h-card/hyperlinkedphoto.html +3 -0
  153. data/vendor/tests/tests/microformats-v2/h-card/hyperlinkedphoto.json +12 -0
  154. data/vendor/tests/tests/microformats-v2/h-card/impliedname.html +15 -0
  155. data/vendor/tests/tests/microformats-v2/h-card/impliedname.json +90 -0
  156. data/vendor/tests/tests/microformats-v2/h-card/impliedphoto.html +11 -0
  157. data/vendor/tests/tests/microformats-v2/h-card/impliedphoto.json +72 -0
  158. data/vendor/tests/tests/microformats-v2/h-card/impliedurl.html +5 -0
  159. data/vendor/tests/tests/microformats-v2/h-card/impliedurl.json +45 -0
  160. data/vendor/tests/tests/microformats-v2/h-card/justahyperlink.html +1 -0
  161. data/vendor/tests/tests/microformats-v2/h-card/justahyperlink.json +11 -0
  162. data/vendor/tests/tests/microformats-v2/h-card/justaname.html +1 -0
  163. data/vendor/tests/tests/microformats-v2/h-card/justaname.json +10 -0
  164. data/vendor/tests/tests/microformats-v2/h-card/nested.html +4 -0
  165. data/vendor/tests/tests/microformats-v2/h-card/nested.json +18 -0
  166. data/vendor/tests/tests/microformats-v2/h-card/p-property.html +21 -0
  167. data/vendor/tests/tests/microformats-v2/h-card/p-property.json +15 -0
  168. data/vendor/tests/tests/microformats-v2/h-card/relativeurls.html +6 -0
  169. data/vendor/tests/tests/microformats-v2/h-card/relativeurls.json +29 -0
  170. data/vendor/tests/tests/microformats-v2/h-entry/change-log.html +90 -0
  171. data/vendor/tests/tests/microformats-v2/h-entry/encoding.html +3 -0
  172. data/vendor/tests/tests/microformats-v2/h-entry/encoding.json +14 -0
  173. data/vendor/tests/tests/microformats-v2/h-entry/impliedvalue-nested.html +9 -0
  174. data/vendor/tests/tests/microformats-v2/h-entry/impliedvalue-nested.json +27 -0
  175. data/vendor/tests/tests/microformats-v2/h-entry/justahyperlink.html +1 -0
  176. data/vendor/tests/tests/microformats-v2/h-entry/justahyperlink.json +11 -0
  177. data/vendor/tests/tests/microformats-v2/h-entry/justaname.html +1 -0
  178. data/vendor/tests/tests/microformats-v2/h-entry/justaname.json +10 -0
  179. data/vendor/tests/tests/microformats-v2/h-entry/scriptstyletags.html +4 -0
  180. data/vendor/tests/tests/microformats-v2/h-entry/scriptstyletags.json +14 -0
  181. data/vendor/tests/tests/microformats-v2/h-entry/summarycontent.html +20 -0
  182. data/vendor/tests/tests/microformats-v2/h-entry/summarycontent.json +25 -0
  183. data/vendor/tests/tests/microformats-v2/h-entry/u-property.html +33 -0
  184. data/vendor/tests/tests/microformats-v2/h-entry/u-property.json +12 -0
  185. data/vendor/tests/tests/microformats-v2/h-entry/urlincontent.html +13 -0
  186. data/vendor/tests/tests/microformats-v2/h-entry/urlincontent.json +14 -0
  187. data/vendor/tests/tests/microformats-v2/h-event/ampm.html +41 -0
  188. data/vendor/tests/tests/microformats-v2/h-event/ampm.json +21 -0
  189. data/vendor/tests/tests/microformats-v2/h-event/attendees.html +13 -0
  190. data/vendor/tests/tests/microformats-v2/h-event/attendees.json +37 -0
  191. data/vendor/tests/tests/microformats-v2/h-event/change-log.html +82 -0
  192. data/vendor/tests/tests/microformats-v2/h-event/combining.html +13 -0
  193. data/vendor/tests/tests/microformats-v2/h-event/combining.json +25 -0
  194. data/vendor/tests/tests/microformats-v2/h-event/concatenate.html +8 -0
  195. data/vendor/tests/tests/microformats-v2/h-event/concatenate.json +12 -0
  196. data/vendor/tests/tests/microformats-v2/h-event/dates.html +13 -0
  197. data/vendor/tests/tests/microformats-v2/h-event/dates.json +26 -0
  198. data/vendor/tests/tests/microformats-v2/h-event/dt-property.html +23 -0
  199. data/vendor/tests/tests/microformats-v2/h-event/dt-property.json +20 -0
  200. data/vendor/tests/tests/microformats-v2/h-event/justahyperlink.html +1 -0
  201. data/vendor/tests/tests/microformats-v2/h-event/justahyperlink.json +11 -0
  202. data/vendor/tests/tests/microformats-v2/h-event/justaname.html +1 -0
  203. data/vendor/tests/tests/microformats-v2/h-event/justaname.json +10 -0
  204. data/vendor/tests/tests/microformats-v2/h-event/time.html +47 -0
  205. data/vendor/tests/tests/microformats-v2/h-event/time.json +25 -0
  206. data/vendor/tests/tests/microformats-v2/h-feed/implied-title.html +30 -0
  207. data/vendor/tests/tests/microformats-v2/h-feed/implied-title.json +23 -0
  208. data/vendor/tests/tests/microformats-v2/h-feed/simple.html +26 -0
  209. data/vendor/tests/tests/microformats-v2/h-feed/simple.json +33 -0
  210. data/vendor/tests/tests/microformats-v2/h-geo/abbrpattern.html +5 -0
  211. data/vendor/tests/tests/microformats-v2/h-geo/abbrpattern.json +12 -0
  212. data/vendor/tests/tests/microformats-v2/h-geo/altitude.html +8 -0
  213. data/vendor/tests/tests/microformats-v2/h-geo/altitude.json +13 -0
  214. data/vendor/tests/tests/microformats-v2/h-geo/change-log.html +67 -0
  215. data/vendor/tests/tests/microformats-v2/h-geo/hidden.html +10 -0
  216. data/vendor/tests/tests/microformats-v2/h-geo/hidden.json +12 -0
  217. data/vendor/tests/tests/microformats-v2/h-geo/justaname.html +3 -0
  218. data/vendor/tests/tests/microformats-v2/h-geo/justaname.json +10 -0
  219. data/vendor/tests/tests/microformats-v2/h-geo/simpleproperties.html +5 -0
  220. data/vendor/tests/tests/microformats-v2/h-geo/simpleproperties.json +12 -0
  221. data/vendor/tests/tests/microformats-v2/h-geo/valuetitleclass.html +11 -0
  222. data/vendor/tests/tests/microformats-v2/h-geo/valuetitleclass.json +12 -0
  223. data/vendor/tests/tests/microformats-v2/h-news/all.html +35 -0
  224. data/vendor/tests/tests/microformats-v2/h-news/all.json +51 -0
  225. data/vendor/tests/tests/microformats-v2/h-news/change-log.html +78 -0
  226. data/vendor/tests/tests/microformats-v2/h-news/minimum.html +24 -0
  227. data/vendor/tests/tests/microformats-v2/h-news/minimum.json +40 -0
  228. data/vendor/tests/tests/microformats-v2/h-org/change-log.html +57 -0
  229. data/vendor/tests/tests/microformats-v2/h-org/hyperlink.html +1 -0
  230. data/vendor/tests/tests/microformats-v2/h-org/hyperlink.json +11 -0
  231. data/vendor/tests/tests/microformats-v2/h-org/simple.html +1 -0
  232. data/vendor/tests/tests/microformats-v2/h-org/simple.json +10 -0
  233. data/vendor/tests/tests/microformats-v2/h-org/simpleproperties.html +4 -0
  234. data/vendor/tests/tests/microformats-v2/h-org/simpleproperties.json +12 -0
  235. data/vendor/tests/tests/microformats-v2/h-product/aggregate.html +21 -0
  236. data/vendor/tests/tests/microformats-v2/h-product/aggregate.json +45 -0
  237. data/vendor/tests/tests/microformats-v2/h-product/change-log.html +62 -0
  238. data/vendor/tests/tests/microformats-v2/h-product/justahyperlink.html +1 -0
  239. data/vendor/tests/tests/microformats-v2/h-product/justahyperlink.json +11 -0
  240. data/vendor/tests/tests/microformats-v2/h-product/justaname.html +1 -0
  241. data/vendor/tests/tests/microformats-v2/h-product/justaname.json +10 -0
  242. data/vendor/tests/tests/microformats-v2/h-product/simpleproperties.html +10 -0
  243. data/vendor/tests/tests/microformats-v2/h-product/simpleproperties.json +26 -0
  244. data/vendor/tests/tests/microformats-v2/h-recipe/all.html +63 -0
  245. data/vendor/tests/tests/microformats-v2/h-recipe/all.json +54 -0
  246. data/vendor/tests/tests/microformats-v2/h-recipe/change-log.html +62 -0
  247. data/vendor/tests/tests/microformats-v2/h-recipe/minimum.html +7 -0
  248. data/vendor/tests/tests/microformats-v2/h-recipe/minimum.json +17 -0
  249. data/vendor/tests/tests/microformats-v2/h-resume/affiliation.html +12 -0
  250. data/vendor/tests/tests/microformats-v2/h-resume/affiliation.json +20 -0
  251. data/vendor/tests/tests/microformats-v2/h-resume/change-log.html +78 -0
  252. data/vendor/tests/tests/microformats-v2/h-resume/contact.html +17 -0
  253. data/vendor/tests/tests/microformats-v2/h-resume/contact.json +26 -0
  254. data/vendor/tests/tests/microformats-v2/h-resume/education.html +13 -0
  255. data/vendor/tests/tests/microformats-v2/h-resume/education.json +30 -0
  256. data/vendor/tests/tests/microformats-v2/h-resume/justaname.html +1 -0
  257. data/vendor/tests/tests/microformats-v2/h-resume/justaname.json +10 -0
  258. data/vendor/tests/tests/microformats-v2/h-resume/skill.html +12 -0
  259. data/vendor/tests/tests/microformats-v2/h-resume/skill.json +12 -0
  260. data/vendor/tests/tests/microformats-v2/h-resume/work.html +16 -0
  261. data/vendor/tests/tests/microformats-v2/h-resume/work.json +31 -0
  262. data/vendor/tests/tests/microformats-v2/h-review-aggregate/change-log.html +78 -0
  263. data/vendor/tests/tests/microformats-v2/h-review-aggregate/hevent.html +13 -0
  264. data/vendor/tests/tests/microformats-v2/h-review-aggregate/hevent.json +23 -0
  265. data/vendor/tests/tests/microformats-v2/h-review-aggregate/justahyperlink.html +8 -0
  266. data/vendor/tests/tests/microformats-v2/h-review-aggregate/justahyperlink.json +19 -0
  267. data/vendor/tests/tests/microformats-v2/h-review-aggregate/simpleproperties.html +18 -0
  268. data/vendor/tests/tests/microformats-v2/h-review-aggregate/simpleproperties.json +26 -0
  269. data/vendor/tests/tests/microformats-v2/h-review/change-log.html +84 -0
  270. data/vendor/tests/tests/microformats-v2/h-review/hyperlink.html +1 -0
  271. data/vendor/tests/tests/microformats-v2/h-review/hyperlink.json +11 -0
  272. data/vendor/tests/tests/microformats-v2/h-review/implieditem.html +4 -0
  273. data/vendor/tests/tests/microformats-v2/h-review/implieditem.json +19 -0
  274. data/vendor/tests/tests/microformats-v2/h-review/item.html +8 -0
  275. data/vendor/tests/tests/microformats-v2/h-review/item.json +20 -0
  276. data/vendor/tests/tests/microformats-v2/h-review/justaname.html +1 -0
  277. data/vendor/tests/tests/microformats-v2/h-review/justaname.json +10 -0
  278. data/vendor/tests/tests/microformats-v2/h-review/photo.html +1 -0
  279. data/vendor/tests/tests/microformats-v2/h-review/photo.json +11 -0
  280. data/vendor/tests/tests/microformats-v2/h-review/vcard.html +23 -0
  281. data/vendor/tests/tests/microformats-v2/h-review/vcard.json +48 -0
  282. data/vendor/tests/tests/microformats-v2/rel/change-log.html +67 -0
  283. data/vendor/tests/tests/microformats-v2/rel/duplicate-rels.html +10 -0
  284. data/vendor/tests/tests/microformats-v2/rel/duplicate-rels.json +75 -0
  285. data/vendor/tests/tests/microformats-v2/rel/license.html +1 -0
  286. data/vendor/tests/tests/microformats-v2/rel/license.json +12 -0
  287. data/vendor/tests/tests/microformats-v2/rel/nofollow.html +1 -0
  288. data/vendor/tests/tests/microformats-v2/rel/nofollow.json +12 -0
  289. data/vendor/tests/tests/microformats-v2/rel/rel-urls.html +8 -0
  290. data/vendor/tests/tests/microformats-v2/rel/rel-urls.json +33 -0
  291. data/vendor/tests/tests/microformats-v2/rel/varying-text-duplicate-rels.html +4 -0
  292. data/vendor/tests/tests/microformats-v2/rel/varying-text-duplicate-rels.json +20 -0
  293. data/vendor/tests/tests/microformats-v2/rel/xfn-all.html +19 -0
  294. data/vendor/tests/tests/microformats-v2/rel/xfn-all.json +92 -0
  295. data/vendor/tests/tests/microformats-v2/rel/xfn-elsewhere.html +10 -0
  296. data/vendor/tests/tests/microformats-v2/rel/xfn-elsewhere.json +40 -0
  297. metadata +285 -37
  298. data/lib/microformats2/collection.rb +0 -136
  299. data/lib/microformats2/format.rb +0 -151
  300. data/lib/microformats2/implied_property/foundation.rb +0 -59
  301. data/lib/microformats2/implied_property/name.rb +0 -34
  302. data/lib/microformats2/implied_property/photo.rb +0 -28
  303. data/lib/microformats2/implied_property/url.rb +0 -24
  304. data/lib/microformats2/property.rb +0 -21
  305. data/lib/microformats2/property/date_time.rb +0 -28
  306. data/lib/microformats2/property/embedded.rb +0 -9
  307. data/lib/microformats2/property/foundation.rb +0 -143
  308. data/lib/microformats2/property/text.rb +0 -16
  309. data/lib/microformats2/property/url.rb +0 -26
  310. data/spec/lib/microformats2/collection_spec.rb +0 -252
  311. data/spec/lib/microformats2/implied_property/name_spec.rb +0 -31
  312. data/spec/lib/microformats2/implied_property/photo_spec.rb +0 -31
  313. data/spec/lib/microformats2/implied_property/url_spec.rb +0 -58
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7cd6cf3a5932b16cf908e76912361c306a1c9191
4
- data.tar.gz: 59a40a924d3a3ee9222f344459a445bd5925aefd
3
+ metadata.gz: c9559a7a2de17e3e15bebace4a04244e39fc5688
4
+ data.tar.gz: 341621db907b4ed4048a460e1c51e01ac3d26918
5
5
  SHA512:
6
- metadata.gz: af7fd7f90d0031996b8164b934877f3168d8b6c6f348055332defd395313a332392ae5a626166911335443b78f8ded3ae4fbd40f5c1ec914d79b95d288337286
7
- data.tar.gz: 12bf5d0b7122ef5d551b16ff0ee4aca635d94f92958bc65565283d2de3689ceecedfe8ad9d82c923032b4216dbaa907fd8273010e13b9d2e6df28ab913ea2934
6
+ metadata.gz: '07972e3897374e29c5244bd21663df40c202d01c2e22894c668832dc4c9f1b1763898f5614876f82b21b44c4a27d09822421c68e5ca1b78c8fa073e0770523a2'
7
+ data.tar.gz: 545a71b67fca0e7ccb1714b6155f0a89a358b5a5bc75509c371a72f7937ce593f2011a41ca48311b9fe41922b0552a0315cfd500dc52b55ff429e2befbbbe0f2
data/README.md CHANGED
@@ -9,9 +9,8 @@ and return a collection of dynamically defined Ruby objects.
9
9
 
10
10
  ## Development Status
11
11
 
12
- This gem sat unmaintained for quite a long time. It's now under new management. Work will begin shortly on getting it on par with the other Microformats2 parsers and the current state of the spec. (2015-12-23)
12
+ This gem has been almost completely rewritten and now supports almost all aspects of the Microformats2 parsing spec. As such a few things have changed, however there is a 2.9.0 release that will add a few new features and slightly improved parsing without breaking any of your existing code. (2017-05-12)
13
13
 
14
- A work in progress.
15
14
 
16
15
  Implemented:
17
16
 
@@ -26,28 +25,44 @@ Implemented:
26
25
  * dynamic creation of properties
27
26
  * [rel](http://microformats.org/wiki/rel)
28
27
  * [normalize u-* property values](http://microformats.org/wiki/microformats2-parsing-faq#normalizing_u-.2A_property_values)
29
-
30
- Not Implemented:
31
-
32
28
  * nested microformat without associated property
33
29
  * [value-class-pattern](http://microformats.org/wiki/value-class-pattern)
34
- * [include-pattern](http://microformats.org/wiki/include-pattern)
35
30
  * recognition of [vendor extensions](http://microformats.org/wiki/microformats2#VENDOR_EXTENSIONS)
36
31
  * backwards compatible support for microformats v1
37
32
 
33
+ Not Implemented:
34
+
35
+ * [include-pattern](http://microformats.org/wiki/include-pattern)
36
+
38
37
 
39
38
  ## Current Version
40
39
 
41
- 2.9.0
40
+ 3.0.0
41
+
42
+ ![Version 3.0.0](https://img.shields.io/badge/VERSION-3.0.0-green.svg)
42
43
 
43
- ![Version 2.9.0](https://img.shields.io/badge/VERSION-2.9.0-green.svg)
44
+ ### Differences to 2.x
44
45
 
46
+ Version 3 of the microformats2 parsing library makes several significant changes from version 2.
47
+ Version 2 of the parser created new ruby objects for every root format and every property it parsed, this is no longer the case.
48
+ Instead, all parsing is done in to a hash and results are wrapped in a few different objects classes which will respond to many of the function calls that the old classes would.
49
+ This means that the to_hash/to_h output is really the safest way to handle output data.
50
+
51
+ The ParserResult class (akin to the old Format class) takes several steps to guess at what function is wanted when it is called.
52
+ For of of the following, if the result is an array it will return the first item in the array unless it is passed the argument :all.
53
+
54
+ 1. If the function called is a key of the current object, return the contents of that key.
55
+ 2. If the function called is a key of the 'properties' array of the current object, return the contents.
56
+ 3. Repeat #1 and #2, replacing underscores with hyphens.
57
+
58
+ This drops the need for a .format function as the result is always a ParserResult object.
59
+
60
+ Finally this also means that nokogiri elements are no longer accessible from the results of the parser.
45
61
 
46
62
  ## Requirements
47
63
 
48
64
  * [nokogiri](https://github.com/sparklemotion/nokogiri)
49
65
  * [json](https://github.com/flori/json)
50
- * [activesupport](https://github.com/rails/rails/tree/master/activesupport)
51
66
 
52
67
 
53
68
  ## Installation
@@ -78,31 +93,114 @@ require "microformats2"
78
93
 
79
94
  source = "<div class='h-card'><p class='p-name'>Jessica Lynn Suttles</p></div>"
80
95
  collection = Microformats2.parse(source)
81
- # using singular accessors
82
- collection.card.name.to_s #=> "Jessica Lynn Suttles"
83
- # using :all returns an array
84
- collection.card(:all)[0].name(:all).first.to_s #=> "Jessica Lynn Suttles"
96
+
97
+ # getting a copy of the canonical microformats2 hash structure
98
+ collection.to_hash
99
+
100
+ # the above, as JSON in a string
101
+ collection.to_json
102
+
103
+ # shortcuts
104
+
105
+ # return a string if there is only one item found
106
+ collection.card.name #=> "Jessica Lynn Suttles"
85
107
 
86
108
  source = "<article class='h-entry'>
87
109
  <h1 class='p-name'>Microformats 2</h1>
88
- <div class='h-card p-author'><p class='p-name'>Jessica Lynn Suttles</p></div>
110
+ <div class='h-card p-author'><p class='p-name'><span class='p-first-name'>Jessica</span> Lynn Suttles</p></div>
89
111
  </article>"
90
112
  collection = Microformats2.parse(source)
91
113
  collection.entry.name.to_s #=> "Microformats 2"
114
+
92
115
  # accessing nested microformats
93
116
  collection.entry.author.name.to_s #=> "Jessica Lynn Suttles"
94
117
 
95
- # getting a copy of the canonical microformats2 hash structure
96
- collection.to_hash
118
+ # accessing nested microformats can use shortcuts or more expanded method
119
+ collection.entry.author.name #=> "Jessica Lynn Suttles"
120
+ collection.entry.properties.author.properties.name.to_s #=> "Jessica Lynn Suttles"
121
+
122
+ # use _ instead of - to get these items
123
+ collection.entry.author.first_name #=> "Jessica"
124
+ collection.rel_urls #=> {}
125
+
126
+ source = "<article class='h-entry'>
127
+ <h1 class='p-name'>Microformats 2</h1>
128
+ <div class='h-card p-author'><p class='p-name'><span class='p-first-name'>Jessica</span> Lynn Suttles</p></div>
129
+ <div class='h-card p-author'><p class='p-name'><span class='p-first-name'>Brandon</span> Edens</p></div>
130
+ </article>"
131
+ collection = Microformats2.parse(source)
132
+
133
+ # arrays of items with always take the first item by default
134
+ collection.entry.author.name #=> "Jessica Lynn Suttles"
135
+ collection.entry.author(1).name #=> "Brandon Edens"
136
+
137
+ # get the actual array with :all
138
+ collection.entry.author(:all).count #=> 2
139
+ collection.entry.author(:all)[1].name #=> "Brandon Edens"
97
140
 
98
- # the above, as JSON in a string
99
- collection.to_json
100
141
  ```
101
142
 
102
143
  * `source` can be a URL, filepath, or HTML
103
144
 
145
+
146
+ ## Ruby Gem release process
147
+
148
+ Check out latest code from GitHub repo.
149
+
150
+ ```
151
+ git pull origin master
152
+ ```
153
+
154
+ Make sure the version has been bumped up in all four places:
155
+
156
+ - [lib/microformats2/version.rb](https://github.com/indieweb/microformats2-ruby/blob/master/lib/microformats2/version.rb#L2)
157
+ - [README.md (three places)](https://github.com/indieweb/microformats2-ruby/blob/master/README.md)
158
+
159
+ Do a test build locally to make sure it builds properly.
160
+
161
+ ```
162
+ rake build
163
+ ```
164
+
165
+ If that works, then do a test install locally.
166
+
167
+ ```
168
+ rake install
169
+ ```
170
+
171
+ If that works, uninstall the gem.
172
+
173
+ ```
174
+ gem uninstall microformats2
175
+ ```
176
+
177
+ Clean up any mess made from testing.
178
+
179
+ ```
180
+ rake clean
181
+ rake clobber
182
+ ```
183
+
184
+ Assuming your one of the gem owners and have release privileges, release the gem!
185
+
186
+ ```
187
+ rake release
188
+ ```
189
+
190
+ If that works, you’ve just release a new version of the gem! Yay! You can see it at:
191
+
192
+ [https://rubygems.org/gems/microformats2](https://rubygems.org/gems/microformats2)
193
+
194
+ If `rake release` failed because of an error with your authentication to rubygems.org, follow their instructions in the error message. Then repeat the `rake release` step.
195
+
196
+ If any other errors failed along the way before `rake release`, try to figure them out or reach out to the IRC/Slack channel for help.
197
+
198
+ Good luck.
199
+
200
+
104
201
  ## Authors
105
202
 
203
+ - Ben Roberts / [@dissolve](https://github.com/dissolve)
106
204
  - Jessica Lynn Suttles / [@jlsuttles](https://github.com/jlsuttles)
107
205
  - Shane Becker / [@veganstraightedge](https://github.com/veganstraightedge)
108
206
  - Chris Stringer / [@jcstringer](https://github.com/jcstringer)
@@ -125,21 +223,23 @@ If you find bugs, have feature requests or questions, please
125
223
  [file an issue](https://github.com/indieweb/microformats2-ruby/issues).
126
224
 
127
225
 
128
- ## Specs
226
+ ## Testing
129
227
 
130
- **TODO** remove this and use the [microformats tests repo](https://github.com/microformats/tests) instead.
228
+ ### Specs
131
229
 
132
- To update spec cases that are scraped from other sites.
133
- **Warning:** This could break specs.
134
- ```
135
- rake specs:update
136
- ```
230
+ This uses a copy of [microformats tests repo](https://github.com/microformats/tests).
137
231
 
138
232
  To run specs
139
233
  ```
140
234
  rake spec
141
235
  ```
142
236
 
237
+ ###Interactive
238
+
239
+ You can use the code interacively for testing but running
240
+ ```
241
+ bundle console
242
+ ```
143
243
 
144
244
  ## License
145
245
 
data/Rakefile CHANGED
@@ -7,63 +7,3 @@ require "pp"
7
7
  RSpec::Core::RakeTask.new(:spec)
8
8
  task :default => [:spec]
9
9
 
10
- namespace :specs do
11
- task :update do
12
- sources = [
13
- { dir: "microformats.org",
14
- urls: ["http://microformats.org/wiki/microformats-2"],
15
- html_selector: ".source-html4strict",
16
- json_selector: ".source-javascript",
17
- html_method: "inner_text"
18
- },
19
- { dir: "microformat2-node.jit.su",
20
- urls: [
21
- "http://microformat2-node.jit.su/h-adr.html",
22
- "http://microformat2-node.jit.su/h-card.html",
23
- "http://microformat2-node.jit.su/h-entry.html",
24
- "http://microformat2-node.jit.su/h-event.html",
25
- "http://microformat2-node.jit.su/h-geo.html",
26
- "http://microformat2-node.jit.su/h-news.html",
27
- "http://microformat2-node.jit.su/h-org.html",
28
- "http://microformat2-node.jit.su/h-product.html",
29
- "http://microformat2-node.jit.su/h-recipe.html",
30
- "http://microformat2-node.jit.su/h-resume.html",
31
- "http://microformat2-node.jit.su/h-review-aggregate.html",
32
- "http://microformat2-node.jit.su/h-review.html",
33
- "http://microformat2-node.jit.su/rel.html",
34
- "http://microformat2-node.jit.su/includes.html",
35
- ],
36
- html_selector: ".e-x-microformat",
37
- json_selector: ".language-json",
38
- html_method: "inner_html"
39
- }
40
- ]
41
-
42
- sources.each do |source|
43
- source[:urls].each do |url|
44
- document = Nokogiri::HTML(open(url).read)
45
- html = document.css(source[:html_selector]).map { |e| e.send(source[:html_method]) }
46
- json = document.css(source[:json_selector]).map { |e| e.inner_text }
47
-
48
- name = url.split("/").last.gsub(/[.]\w+/, "")
49
- path = File.join "spec/support/cases", source[:dir], name
50
-
51
- FileUtils.mkdir_p(path)
52
-
53
- ([html.length, json.length].min).times do |index|
54
-
55
- File.open(File.join(path, "#{name}-#{index}.html"), "w") do |f|
56
- f.write "<!-- #{url} -->\n"
57
- f.write html[index]
58
- end
59
-
60
- File.open(File.join(path, "#{name}-#{index}.js"), "w") do |f|
61
- f.write "// #{url}\n"
62
- f.write json[index]
63
- end
64
- end
65
-
66
- end
67
- end
68
- end
69
- end
@@ -1,30 +1,22 @@
1
1
  require "nokogiri"
2
2
  require "open-uri"
3
3
  require "json"
4
- require "active_support/inflector"
5
4
 
6
5
  require "microformats2/version"
7
6
  require "microformats2/absolute_uri"
7
+ require "microformats2/parser_core"
8
8
  require "microformats2/parser"
9
9
  require "microformats2/format_parser"
10
10
  require "microformats2/property_parser"
11
- require "microformats2/collection"
12
- require "microformats2/format"
13
- require "microformats2/property/foundation"
14
- require "microformats2/property/text"
15
- require "microformats2/property/url"
16
- require "microformats2/property/date_time"
17
- require "microformats2/property/embedded"
18
- require "microformats2/property"
19
- require "microformats2/implied_property/foundation"
20
- require "microformats2/implied_property/name"
21
- require "microformats2/implied_property/photo"
22
- require "microformats2/implied_property/url"
11
+ require "microformats2/time_property_parser"
12
+ require "microformats2/results/parser_result"
13
+ require "microformats2/results/collection"
14
+ require "microformats2/results/property_set"
23
15
 
24
16
  module Microformats2
25
17
  class << self
26
- def parse(html)
27
- Parser.new.parse(html)
18
+ def parse(html, base: nil)
19
+ Parser.new.parse(html, base: base)
28
20
  end
29
21
 
30
22
  def read_html(html)
@@ -2,13 +2,17 @@ module Microformats2
2
2
  class AbsoluteUri
3
3
  attr_accessor :base, :relative
4
4
 
5
- def initialize(base, relative)
5
+ def initialize(relative, base: nil)
6
6
  @base = base
7
7
  @relative = relative
8
+ @base.strip! unless @base.nil?
9
+ @relative.strip! unless @relative.nil?
8
10
  end
9
11
 
10
12
  def absolutize
13
+ #TODO: i'm sure this could be improved a bit
11
14
  return nil if relative.nil? or relative == ""
15
+ return relative if relative =~ /^https?:\/\//
12
16
 
13
17
  uri = URI.parse(relative)
14
18
 
@@ -1,68 +1,343 @@
1
1
  module Microformats2
2
- class FormatParser
3
- class << self
4
- def parse(element, base=nil, parsing_children = false)
5
- @@base = base
6
- parse_node(element, parsing_children).flatten.compact
7
- end
2
+ class FormatParser < ParserCore
8
3
 
9
- def parse_node(node, parsing_children=false)
10
- case
11
- when node.is_a?(Nokogiri::HTML::Document) then parse_node(node.children, parsing_children)
12
- when node.is_a?(Nokogiri::XML::NodeSet) then parse_nodeset(node, parsing_children)
13
- when node.is_a?(Nokogiri::XML::Element) then [parse_for_microformats(node, parsing_children)]
14
- end
15
- end
4
+ def parse(element, base:nil, element_type:nil, format_class_array:[], backcompat:false)
5
+ @base = base
16
6
 
17
- def parse_nodeset(nodeset, parsing_children=false)
18
- nodeset.map { |node| parse_node(node, parsing_children) }
19
- end
7
+ @mode_backcompat = backcompat
20
8
 
21
- def parse_for_microformats(element, parsing_children=false)
22
- if property_classes(element).length >= 1 and parsing_children
23
- #do nothing because we don't want properties obj in children
24
- elsif format_classes(element).length >= 1
25
- parse_microformat(element)
26
- else
27
- parse_nodeset(element.children, parsing_children)
9
+ @properties = {}
10
+ @children = []
11
+
12
+ @format_property_type = element_type
13
+ @value = nil
14
+
15
+ @mode_backcompat = backcompat
16
+
17
+ @fmt_classes = format_class_array
18
+
19
+ parse_node(element.children)
20
+
21
+ ##### Implied Properties######
22
+ #NOTE: much of this code may be simplified by using element.css, not sure yet, but coding to have passing tests first
23
+ # can optimize this later
24
+ unless @mode_backcompat
25
+ if @properties['name'].nil?
26
+
27
+ if element.name == 'img' and not element.attribute('alt').nil?
28
+ @properties['name'] = [element.attribute('alt').value.strip]
29
+ elsif element.name == 'area' and not element.attribute('alt').nil?
30
+ @properties['name'] = [element.attribute('alt').value.strip]
31
+ elsif element.name == 'abbr' and not element.attribute('title').nil?
32
+ @properties['name'] = [element.attribute('title').value.strip]
33
+
34
+ else
35
+ child_nodes = element.children.select{|n| not n.is_a?(Nokogiri::XML::Text)}
36
+
37
+ if child_nodes.count == 1 and child_nodes.first.is_a?(Nokogiri::XML::Element) and format_classes(child_nodes.first).empty?
38
+ node = child_nodes.first
39
+
40
+ #else if .h-x>img:only-child[alt]:not([alt=""]):not[.h-*] then use that img’s alt for name
41
+ if node.name == 'img' and not node.attribute('alt').nil? and not node.attribute('alt').value.empty?
42
+ @properties['name'] = [node.attribute('alt').value.strip]
43
+
44
+ #else if .h-x>area:only-child[alt]:not([alt=""]):not[.h-*] then use that area’s alt for name
45
+ elsif node.name == 'area' and not node.attribute('alt').nil? and not node.attribute('alt').value.empty?
46
+ @properties['name'] = [node.attribute('alt').value.strip]
47
+
48
+ #else if .h-x>abbr:only-child[title]:not([title=""]):not[.h-*] then use that abbr title for name
49
+ elsif node.name == 'abbr' and not node.attribute('title').nil? and not node.attribute('title').value.empty?
50
+ @properties['name'] = [node.attribute('title').value.strip]
51
+
52
+ else
53
+ child_nodes = node.children.select{|n| not n.is_a?(Nokogiri::XML::Text)}
54
+ if child_nodes.count == 1 and child_nodes.first.is_a?(Nokogiri::XML::Element) and format_classes(child_nodes.first).empty?
55
+ node = child_nodes.first
56
+
57
+ #else if .h-x>:only-child:not[.h-*]>img:only-child[alt]:not([alt=""]):not[.h-*] then use that img’s alt for name
58
+ if node.name == 'img' and not node.attribute('alt').nil? and not node.attribute('alt').value.empty?
59
+ @properties['name'] = [node.attribute('alt').value.strip]
60
+
61
+ #else if .h-x>:only-child:not[.h-*]>area:only-child[alt]:not([alt=""]):not[.h-*] then use that area’s alt for name
62
+ elsif node.name == 'area' and not node.attribute('alt').nil? and not node.attribute('alt').value.empty?
63
+ @properties['name'] = [node.attribute('alt').value.strip]
64
+
65
+ #else if .h-x>:only-child:not[.h-*]>abbr:only-child[title]:not([title=""]):not[.h-*] use that abbr’s title for name
66
+ elsif node.name == 'abbr' and not node.attribute('title').nil? and not node.attribute('title').value.empty?
67
+ @properties['name'] = [node.attribute('title').value.strip]
68
+
69
+ else
70
+ @properties['name'] = [element.text.strip]
71
+
72
+ end
73
+ else
74
+ @properties['name'] = [element.text.strip]
75
+ end
76
+ end
77
+ else
78
+ @properties['name'] = [element.text.strip]
79
+ end
80
+ end
81
+ end # end implied name
82
+
83
+
84
+ if @properties['photo'].nil?
85
+ if element.name == 'img' and not element.attribute('src').nil?
86
+ @properties['photo'] = [element.attribute('src').value]
87
+ elsif element.name == 'object' and not element.attribute('data').nil?
88
+ @properties['photo'] = [element.attribute('data').value]
89
+ else
90
+
91
+ #else if .h-x>img[src]:only-of-type:not[.h-*] then use that img src for photo
92
+
93
+ child_img_tags_with_src = element.children.select do |child|
94
+ child.is_a?(Nokogiri::XML::Element) and child.name == 'img' and not child.attribute('src').nil?
95
+ end
96
+ if child_img_tags_with_src.count == 1
97
+ node = child_img_tags_with_src.first
98
+ if format_classes(node).empty?
99
+ @properties['photo'] = [node.attribute('src').value.strip]
100
+ end
101
+ end
102
+
103
+ if @properties['photo'].nil?
104
+
105
+ #else if .h-x>object[data]:only-of-type:not[.h-*] then use that object’s data for photo
106
+
107
+ child_object_tags_with_data = element.children.select do |child|
108
+ child.is_a?(Nokogiri::XML::Element) and child.name == 'object' and not child.attribute('data').nil?
109
+ end
110
+ if child_object_tags_with_data.count == 1
111
+ node = child_object_tags_with_data.first
112
+ if format_classes(node).empty?
113
+ @properties['photo'] = [node.attribute('data').value.strip]
114
+ end
115
+ end
116
+ end
117
+
118
+ child_elements = element.children.select do |child| not child.is_a?(Nokogiri::XML::Text) end
119
+
120
+ if @properties['photo'].nil? and child_elements.count == 1 and format_classes(child_elements.first).empty?
121
+
122
+ #else if .h-x>:only-child:not[.h-*]>img[src]:only-of-type:not[.h-*], then use that img’s src for photo
123
+
124
+ child_img_tags_with_src = child_elements.first.children.select do |child|
125
+ child.is_a?(Nokogiri::XML::Element) and child.name == 'img' and not child.attribute('src').nil?
126
+ end
127
+ if child_img_tags_with_src.count == 1
128
+ node = child_img_tags_with_src.first
129
+ if format_classes(node).empty?
130
+ @properties['photo'] = [node.attribute('src').value.strip]
131
+ end
132
+ end
133
+
134
+ if @properties['photo'].nil?
135
+
136
+ #else if .h-x>:only-child:not[.h-*]>object[data]:only-of-type:not[.h-*], then use that object’s data for photo
137
+ #
138
+ child_object_tags_with_data = child_elements.first.children.select do |child|
139
+ child.is_a?(Nokogiri::XML::Element) and child.name == 'object' and not child.attribute('data').nil?
140
+ end
141
+ if child_object_tags_with_data.count == 1
142
+ node = child_object_tags_with_data.first
143
+ if format_classes(node).empty?
144
+ @properties['photo'] = [node.attribute('data').value.strip]
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ end
151
+ unless @properties['photo'].nil?
152
+ @properties['photo'] = [ Microformats2::AbsoluteUri.new(@properties['photo'].first, base: @base).absolutize ]
153
+ end
28
154
  end
29
- end
30
155
 
31
- def parse_microformat(element)
32
- # only create ruby object for first format class
33
- html_class = format_classes(element).first
34
- const_name = constant_name(html_class)
35
- klass = find_or_create_ruby_class(const_name)
156
+ if @properties['url'].nil?
157
+ if element.name == 'a' and not element.attribute('href').nil?
158
+ @properties['url'] = [element.attribute('href').value]
159
+ elsif element.name == 'area' and not element.attribute('href').nil?
160
+ @properties['url'] = [element.attribute('href').value]
161
+ else
162
+ #else if .h-x>a[href]:only-of-type:not[.h-*], then use that [href] for url
163
+ child_a_tags_with_href = element.children.select do |child|
164
+ child.is_a?(Nokogiri::XML::Element) and child.name == 'a' and not child.attribute('href').nil?
165
+ end
166
+ if child_a_tags_with_href.count == 1
167
+ node = child_a_tags_with_href.first
168
+ if format_classes(node).empty?
169
+ @properties['url'] = [node.attribute('href').value.strip]
170
+ end
171
+ end
172
+
173
+ if @properties['url'].nil?
174
+
175
+ #else if .h-x>area[href]:only-of-type:not[.h-*], then use that [href] for url
176
+ child_area_tags_with_href = element.children.select do |child|
177
+ child.is_a?(Nokogiri::XML::Element) and child.name == 'area' and not child.attribute('href').nil?
178
+ end
179
+ if child_area_tags_with_href.count == 1
180
+ node = child_area_tags_with_href.first
181
+ if format_classes(node).empty?
182
+ @properties['url'] = [node.attribute('href').value.strip]
183
+ end
184
+ end
185
+ end
186
+
187
+ child_elements = element.children.select do |child| not child.is_a?(Nokogiri::XML::Text) end
188
+
189
+ if @properties['url'].nil? and child_elements.count == 1 and format_classes(child_elements.first).empty?
190
+ child_element = child_elements.first
191
+
192
+ #else if .h-x>:only-child:not[.h-*]>a[href]:only-of-type:not[.h-*], then use that [href] for url
193
+ child_a_tags_with_href = child_element.children.select do |child|
194
+ child.is_a?(Nokogiri::XML::Element) and child.name == 'a' and not child.attribute('href').nil?
195
+ end
196
+ if child_a_tags_with_href.count == 1
197
+ node = child_a_tags_with_href.first
198
+ if format_classes(node).empty?
199
+ @properties['url'] = [node.attribute('href').value.strip]
200
+ end
201
+ end
202
+
203
+ if @properties['url'].nil?
204
+
205
+ #else if .h-x>:only-child:not[.h-*]>area[href]:only-of-type:not[.h-*], then use that [href] for url
206
+ child_area_tags_with_href = child_element.children.select do |child|
207
+ child.is_a?(Nokogiri::XML::Element) and child.name == 'area' and not child.attribute('href').nil?
208
+ end
209
+ if child_area_tags_with_href.count == 1
210
+ node = child_area_tags_with_href.first
211
+ if format_classes(node).empty?
212
+ @properties['url'] = [node.attribute('href').value.strip]
213
+ end
214
+ end
215
+ end
216
+ end
217
+ end
218
+
219
+ unless @properties['url'].nil?
220
+ @properties['url'] = [ Microformats2::AbsoluteUri.new(@properties['url'].first, base: @base).absolutize ]
221
+ end
222
+ end
36
223
 
37
- klass.new(element, @@base).parse
38
224
  end
225
+ ##### END Implied Properties when not in backcompat mode######
39
226
 
40
- def property_classes(element)
41
- element.attribute("class").to_s.split.select do |html_class|
42
- html_class =~ Property::CLASS_REG_EXP
227
+ ### imply date for dt-end if dt-start is defined with a date ###
228
+ if not @properties['end'].nil? and not @properties['start'].nil?
229
+ start_date = nil
230
+ @properties['start'].each do |start_val|
231
+ if start_val =~ /^(\d{4}-[01]\d-[0-3]\d)/
232
+ start_date = $1 if start_date.nil?
233
+ elsif start_val =~ /^(\d{4}-[0-3]\d\d)/
234
+ start_date = $1 if start_date.nil?
235
+ end
236
+ end
237
+ unless start_date.nil?
238
+ @properties['end'].map! do |end_val|
239
+ if end_val=~ /^\d{4}-[01]\d-[0-3]\d/
240
+ end_val
241
+ elsif end_val=~ /^\d{4}-[0-3]\d\d/
242
+ end_val
243
+ else
244
+ start_date + ' ' + end_val
245
+ end
246
+ end
43
247
  end
44
248
  end
45
249
 
46
- def format_classes(element)
47
- element.attribute("class").to_s.split.select do |html_class|
48
- html_class =~ Format::CLASS_REG_EXP
250
+ if @value.nil? or @value.empty?
251
+ if element_type == 'p' and not @properties['name'].nil? and not @properties['name'].empty?
252
+ @value = @properties['name'].first
253
+ elsif element_type == 'u' and not @properties['url'].nil? and not @properties['url'].empty?
254
+ @value = @properties['url'].first
255
+ elsif not element_type.nil?
256
+ @value = PropertyParser.new.parse(element, base: @base, element_type: element_type, backcompat: @mode_backcompat)
49
257
  end
50
258
  end
51
259
 
52
- def constant_name(html_class)
53
- # html-Class -> html-class -> html_class -> Html_class -> HtmlClass
54
- html_class.downcase.gsub("-","_").gsub(/^([a-z])/){$1.upcase}.gsub(/_(.)/){$1.upcase}
260
+ h_object = {}
261
+
262
+ h_object['value'] = @value unless @value.nil?
263
+ h_object['type'] = format_class_array
264
+ h_object['properties'] = @properties
265
+
266
+ h_object['children'] = @children unless @children.empty?
267
+
268
+ if @format_property_type == 'e'
269
+ h_object['value'] = element.text.strip
270
+ h_object['html'] = element.inner_html
55
271
  end
56
272
 
57
- def find_or_create_ruby_class(const_name)
58
- if Object.const_defined?(const_name)
59
- klass = Object.const_get(const_name)
273
+ ##todo fall back to p- dt- u- parsing if value still not set?
274
+ # not sure that is correct by the spec actually
275
+
276
+ h_object
277
+
278
+ end
279
+
280
+
281
+ def parse_element(element)
282
+
283
+ prop_classes = property_classes(element)
284
+ prop_classes = backcompat_property_classes(element) if @mode_backcompat
285
+
286
+ bc_classes_found = false
287
+ fmt_classes = format_classes(element)
288
+
289
+ if fmt_classes.empty?
290
+ fmt_classes = backcompat_format_classes(element)
291
+ bc_classes_found = true unless fmt_classes.empty?
292
+ end
293
+
294
+ if prop_classes.length >= 1
295
+
296
+ if fmt_classes.length >= 1
297
+
298
+ prop_classes.each do |element_class|
299
+ element_type = element_class.downcase.split('-')[0]
300
+ property_name = element_class.downcase.split('-')[1..-1].join('-')
301
+
302
+ parsed_format = FormatParser.new.parse(element, base:@base, element_type: element_type, format_class_array: fmt_classes, backcompat: bc_classes_found )
303
+
304
+ if @value.nil?
305
+ if @format_property_type == 'p' and property_name == 'name'
306
+ @value = parsed_format['value']
307
+ #elsif @format_property_type == 'dt' and property_name == '???'
308
+ #@value = parsed_format['value']
309
+ elsif @format_property_type == 'u' and property_name == 'url'
310
+ @value = parsed_format['value']
311
+ end
312
+ end
313
+
314
+ @properties[property_name] = [] if @properties[property_name].nil?
315
+ @properties[property_name] << parsed_format
316
+
317
+ end
318
+
60
319
  else
61
- klass = Class.new(Microformats2::Format)
62
- Object.const_set const_name, klass
320
+
321
+ prop_classes.each do |element_class|
322
+ element_type = element_class.downcase.split('-')[0]
323
+ property_name = element_class.downcase.split('-')[1..-1].join('-')
324
+
325
+ parsed_property = PropertyParser.new.parse(element, base: @base, element_type: element_type, backcompat: @mode_backcompat)
326
+
327
+ if not parsed_property.nil? and not parsed_property.empty?
328
+ @properties[property_name] = [] if @properties[property_name].nil?
329
+ @properties[property_name] << parsed_property
330
+ end
331
+ end
332
+ parse_nodeset(element.children)
63
333
  end
64
- klass
334
+
335
+ elsif fmt_classes.length >= 1
336
+ @children << FormatParser.new.parse(element, base: @base, format_class_array: fmt_classes, backcompat: bc_classes_found )
337
+ else
338
+ parse_nodeset(element.children)
65
339
  end
66
- end # class << self
340
+ end
341
+
67
342
  end
68
343
  end