microformats 4.0.7 → 4.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (366) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +10 -0
  3. data/.gitignore +33 -15
  4. data/.rspec +3 -2
  5. data/.rubocop +3 -0
  6. data/.rubocop.yml +25 -0
  7. data/.ruby-version +1 -0
  8. data/.simplecov +11 -0
  9. data/.travis.yml +14 -2
  10. data/CONTRIBUTING.md +103 -0
  11. data/Guardfile +2 -2
  12. data/LICENSE +116 -0
  13. data/README.md +112 -172
  14. data/Rakefile +6 -7
  15. data/bin/microformats +10 -9
  16. data/lib/microformats.rb +15 -14
  17. data/lib/microformats/absolute_uri.rb +4 -8
  18. data/lib/microformats/format_parser.rb +271 -251
  19. data/lib/microformats/parser.rb +38 -38
  20. data/lib/microformats/parser_core.rb +142 -109
  21. data/lib/microformats/property_parser.rb +42 -65
  22. data/lib/microformats/results/collection.rb +19 -38
  23. data/lib/microformats/results/parser_result.rb +25 -37
  24. data/lib/microformats/results/property_set.rb +24 -31
  25. data/lib/microformats/time_property_parser.rb +122 -118
  26. data/lib/microformats/version.rb +1 -1
  27. data/logo.svg +23 -0
  28. data/microformats.gemspec +35 -33
  29. metadata +140 -442
  30. data/LICENSE.md +0 -36
  31. data/spec/lib/microformats/absolute_uri_spec.rb +0 -56
  32. data/spec/lib/microformats/parser_spec.rb +0 -132
  33. data/spec/lib/microformats_spec.rb +0 -33
  34. data/spec/spec_helper.rb +0 -10
  35. data/spec/support/cases/microformats.org/microformats-2/microformats-2-0.html +0 -2
  36. data/spec/support/cases/microformats.org/microformats-2/microformats-2-0.js +0 -9
  37. data/spec/support/cases/microformats.org/microformats-2/microformats-2-1.html +0 -2
  38. data/spec/support/cases/microformats.org/microformats-2/microformats-2-1.js +0 -10
  39. data/spec/support/cases/microformats.org/microformats-2/microformats-2-2.html +0 -5
  40. data/spec/support/cases/microformats.org/microformats-2/microformats-2-2.js +0 -11
  41. data/spec/support/cases/microformats.org/microformats-2/microformats-2-3.html +0 -17
  42. data/spec/support/cases/microformats.org/microformats-2/microformats-2-3.js +0 -20
  43. data/spec/support/cases/microformats.org/microformats-2/microformats-2-4.html +0 -16
  44. data/spec/support/cases/microformats.org/microformats-2/microformats-2-4.js +0 -24
  45. data/spec/support/cases/microformats.org/microformats-2/microformats-2-5.html +0 -7
  46. data/spec/support/cases/microformats.org/microformats-2/microformats-2-5.js +0 -11
  47. data/spec/support/cases/microformats.org/microformats-2/microformats-2-6.html +0 -9
  48. data/spec/support/cases/microformats.org/microformats-2/microformats-2-6.js +0 -18
  49. data/spec/support/cases/microformats.org/microformats-2/microformats-2-7.html +0 -9
  50. data/spec/support/cases/microformats.org/microformats-2/microformats-2-7.js +0 -18
  51. data/spec/support/cases/microformats.org/microformats-2/microformats-2-8.html +0 -9
  52. data/spec/support/cases/microformats.org/microformats-2/microformats-2-8.js +0 -17
  53. data/spec/support/cases/microformats.org/microformats-2/microformats-2-9.html +0 -9
  54. data/spec/support/cases/microformats.org/microformats-2/microformats-2-9.js +0 -17
  55. data/spec/support/lib/edge_cases/blank_href.html +0 -23
  56. data/spec/support/lib/edge_cases/blank_href.js +0 -15
  57. data/spec/support/lib/edge_cases/blank_rel.html +0 -23
  58. data/spec/support/lib/edge_cases/blank_rel.js +0 -41
  59. data/spec/support/lib/edge_cases/blank_src.html +0 -24
  60. data/spec/support/lib/edge_cases/blank_src.js +0 -16
  61. data/spec/support/lib/edge_cases/blank_value.html +0 -5
  62. data/spec/support/lib/edge_cases/blank_value.js +0 -19
  63. data/spec/support/lib/edge_cases/relative.html +0 -29
  64. data/spec/support/lib/edge_cases/relative.js +0 -15
  65. data/spec/support/lib/edge_cases/vcp-dates.html +0 -13
  66. data/spec/support/lib/edge_cases/vcp-dates.js +0 -30
  67. data/spec/support/lib/microformats/blank_href.html +0 -23
  68. data/spec/support/lib/microformats/blank_href.js +0 -11
  69. data/spec/support/lib/microformats/implied_property/name-fail.html +0 -60
  70. data/spec/support/lib/microformats/implied_property/name-pass.html +0 -30
  71. data/spec/support/lib/microformats/implied_property/photo-fail.html +0 -60
  72. data/spec/support/lib/microformats/implied_property/photo-pass.html +0 -30
  73. data/spec/support/lib/microformats/implied_property/url-fail.html +0 -18
  74. data/spec/support/lib/microformats/implied_property/url-pass.html +0 -12
  75. data/spec/support/lib/microformats/implied_property/url-relative.html +0 -13
  76. data/spec/support/lib/microformats/implied_property/url-unnormalized.html +0 -12
  77. data/spec/support/lib/microformats/nested-format-with-property-of-same-name.html +0 -13
  78. data/spec/support/lib/microformats/nested-format-with-property-of-same-name.js +0 -16
  79. data/spec/support/lib/microformats/nested-format-with-property.html +0 -12
  80. data/spec/support/lib/microformats/nested-format-with-property.js +0 -16
  81. data/spec/support/lib/microformats/nested-format-without-property.html +0 -13
  82. data/spec/support/lib/microformats/nested-property.html +0 -12
  83. data/spec/support/lib/microformats/nested-property.js +0 -10
  84. data/spec/support/lib/microformats/rels-that-drop-the-base.html +0 -11
  85. data/spec/support/lib/microformats/rels-with-unnormalized-urls.html +0 -11
  86. data/spec/support/lib/microformats/rels.html +0 -12
  87. data/spec/support/lib/microformats/rels.js +0 -13
  88. data/spec/support/lib/microformats/simple.html +0 -23
  89. data/spec/support/lib/microformats/simple.js +0 -11
  90. data/vendor/tests/.gitignore +0 -25
  91. data/vendor/tests/LICENSE.md +0 -36
  92. data/vendor/tests/README.md +0 -48
  93. data/vendor/tests/app.js +0 -84
  94. data/vendor/tests/composer.json +0 -5
  95. data/vendor/tests/css/testsuite.css +0 -159
  96. data/vendor/tests/interface.js +0 -18
  97. data/vendor/tests/package.json +0 -27
  98. data/vendor/tests/tests/microformats-mixed/h-card/change-log.html +0 -63
  99. data/vendor/tests/tests/microformats-mixed/h-card/mixedpropertries.html +0 -14
  100. data/vendor/tests/tests/microformats-mixed/h-card/mixedpropertries.json +0 -22
  101. data/vendor/tests/tests/microformats-mixed/h-card/tworoots.html +0 -1
  102. data/vendor/tests/tests/microformats-mixed/h-card/tworoots.json +0 -10
  103. data/vendor/tests/tests/microformats-mixed/h-entry/mixedroots.html +0 -16
  104. data/vendor/tests/tests/microformats-mixed/h-entry/mixedroots.json +0 -38
  105. data/vendor/tests/tests/microformats-mixed/h-resume/change-log.html +0 -68
  106. data/vendor/tests/tests/microformats-mixed/h-resume/mixedroots.html +0 -16
  107. data/vendor/tests/tests/microformats-mixed/h-resume/mixedroots.json +0 -31
  108. data/vendor/tests/tests/microformats-v1/adr/change-log.html +0 -63
  109. data/vendor/tests/tests/microformats-v1/adr/simpleproperties.html +0 -8
  110. data/vendor/tests/tests/microformats-v1/adr/simpleproperties.json +0 -15
  111. data/vendor/tests/tests/microformats-v1/geo/abbrpattern.html +0 -5
  112. data/vendor/tests/tests/microformats-v1/geo/abbrpattern.json +0 -11
  113. data/vendor/tests/tests/microformats-v1/geo/change-log.1.html +0 -78
  114. data/vendor/tests/tests/microformats-v1/geo/change-log.html +0 -63
  115. data/vendor/tests/tests/microformats-v1/geo/hidden.html +0 -10
  116. data/vendor/tests/tests/microformats-v1/geo/hidden.json +0 -11
  117. data/vendor/tests/tests/microformats-v1/geo/simpleproperties.html +0 -6
  118. data/vendor/tests/tests/microformats-v1/geo/simpleproperties.json +0 -11
  119. data/vendor/tests/tests/microformats-v1/geo/valuetitleclass.html +0 -11
  120. data/vendor/tests/tests/microformats-v1/geo/valuetitleclass.json +0 -11
  121. data/vendor/tests/tests/microformats-v1/hcalendar/ampm.html +0 -41
  122. data/vendor/tests/tests/microformats-v1/hcalendar/ampm.json +0 -21
  123. data/vendor/tests/tests/microformats-v1/hcalendar/attendees.html +0 -13
  124. data/vendor/tests/tests/microformats-v1/hcalendar/attendees.json +0 -37
  125. data/vendor/tests/tests/microformats-v1/hcalendar/change-log.html +0 -68
  126. data/vendor/tests/tests/microformats-v1/hcalendar/combining.html +0 -15
  127. data/vendor/tests/tests/microformats-v1/hcalendar/combining.json +0 -31
  128. data/vendor/tests/tests/microformats-v1/hcalendar/concatenate.html +0 -7
  129. data/vendor/tests/tests/microformats-v1/hcalendar/concatenate.json +0 -12
  130. data/vendor/tests/tests/microformats-v1/hcalendar/time.html +0 -44
  131. data/vendor/tests/tests/microformats-v1/hcalendar/time.json +0 -22
  132. data/vendor/tests/tests/microformats-v1/hcard/change-log.html +0 -68
  133. data/vendor/tests/tests/microformats-v1/hcard/email.html +0 -14
  134. data/vendor/tests/tests/microformats-v1/hcard/email.json +0 -11
  135. data/vendor/tests/tests/microformats-v1/hcard/format.html +0 -6
  136. data/vendor/tests/tests/microformats-v1/hcard/format.json +0 -11
  137. data/vendor/tests/tests/microformats-v1/hcard/hyperlinkedphoto.html +0 -3
  138. data/vendor/tests/tests/microformats-v1/hcard/hyperlinkedphoto.json +0 -8
  139. data/vendor/tests/tests/microformats-v1/hcard/justahyperlink.html +0 -1
  140. data/vendor/tests/tests/microformats-v1/hcard/justahyperlink.json +0 -8
  141. data/vendor/tests/tests/microformats-v1/hcard/justaname.html +0 -1
  142. data/vendor/tests/tests/microformats-v1/hcard/justaname.json +0 -8
  143. data/vendor/tests/tests/microformats-v1/hcard/multiple.html +0 -74
  144. data/vendor/tests/tests/microformats-v1/hcard/multiple.json +0 -65
  145. data/vendor/tests/tests/microformats-v1/hcard/name.html +0 -11
  146. data/vendor/tests/tests/microformats-v1/hcard/name.json +0 -15
  147. data/vendor/tests/tests/microformats-v1/hcard/single.html +0 -14
  148. data/vendor/tests/tests/microformats-v1/hcard/single.json +0 -24
  149. data/vendor/tests/tests/microformats-v1/hentry/change-log.html +0 -73
  150. data/vendor/tests/tests/microformats-v1/hentry/summarycontent.html +0 -20
  151. data/vendor/tests/tests/microformats-v1/hentry/summarycontent.json +0 -24
  152. data/vendor/tests/tests/microformats-v1/hfeed/simple.html +0 -30
  153. data/vendor/tests/tests/microformats-v1/hfeed/simple.json +0 -49
  154. data/vendor/tests/tests/microformats-v1/hnews/all.html +0 -37
  155. data/vendor/tests/tests/microformats-v1/hnews/all.json +0 -74
  156. data/vendor/tests/tests/microformats-v1/hnews/change-log.html +0 -72
  157. data/vendor/tests/tests/microformats-v1/hnews/minimum.html +0 -25
  158. data/vendor/tests/tests/microformats-v1/hnews/minimum.json +0 -48
  159. data/vendor/tests/tests/microformats-v1/hproduct/aggregate.html +0 -26
  160. data/vendor/tests/tests/microformats-v1/hproduct/aggregate.json +0 -52
  161. data/vendor/tests/tests/microformats-v1/hproduct/change-log.html +0 -62
  162. data/vendor/tests/tests/microformats-v1/hproduct/simpleproperties.html +0 -13
  163. data/vendor/tests/tests/microformats-v1/hproduct/simpleproperties.json +0 -33
  164. data/vendor/tests/tests/microformats-v1/hresume/affiliation.html +0 -12
  165. data/vendor/tests/tests/microformats-v1/hresume/affiliation.json +0 -25
  166. data/vendor/tests/tests/microformats-v1/hresume/change-log.html +0 -73
  167. data/vendor/tests/tests/microformats-v1/hresume/contact.html +0 -18
  168. data/vendor/tests/tests/microformats-v1/hresume/contact.json +0 -32
  169. data/vendor/tests/tests/microformats-v1/hresume/education.html +0 -13
  170. data/vendor/tests/tests/microformats-v1/hresume/education.json +0 -29
  171. data/vendor/tests/tests/microformats-v1/hresume/skill.html +0 -12
  172. data/vendor/tests/tests/microformats-v1/hresume/skill.json +0 -33
  173. data/vendor/tests/tests/microformats-v1/hresume/work.html +0 -16
  174. data/vendor/tests/tests/microformats-v1/hresume/work.json +0 -30
  175. data/vendor/tests/tests/microformats-v1/hreview-aggregate/change-log.html +0 -67
  176. data/vendor/tests/tests/microformats-v1/hreview-aggregate/hcard.html +0 -18
  177. data/vendor/tests/tests/microformats-v1/hreview-aggregate/hcard.json +0 -31
  178. data/vendor/tests/tests/microformats-v1/hreview-aggregate/justahyperlink.html +0 -6
  179. data/vendor/tests/tests/microformats-v1/hreview-aggregate/justahyperlink.json +0 -19
  180. data/vendor/tests/tests/microformats-v1/hreview-aggregate/vevent.html +0 -13
  181. data/vendor/tests/tests/microformats-v1/hreview-aggregate/vevent.json +0 -22
  182. data/vendor/tests/tests/microformats-v1/hreview/change-log.html +0 -73
  183. data/vendor/tests/tests/microformats-v1/hreview/item.html +0 -8
  184. data/vendor/tests/tests/microformats-v1/hreview/item.json +0 -19
  185. data/vendor/tests/tests/microformats-v1/hreview/vcard.html +0 -23
  186. data/vendor/tests/tests/microformats-v1/hreview/vcard.json +0 -58
  187. data/vendor/tests/tests/microformats-v1/includes/change-log.html +0 -72
  188. data/vendor/tests/tests/microformats-v1/includes/hcarditemref.html +0 -16
  189. data/vendor/tests/tests/microformats-v1/includes/hcarditemref.json +0 -49
  190. data/vendor/tests/tests/microformats-v1/includes/heventitemref.html +0 -25
  191. data/vendor/tests/tests/microformats-v1/includes/heventitemref.json +0 -33
  192. data/vendor/tests/tests/microformats-v1/includes/hyperlink.html +0 -18
  193. data/vendor/tests/tests/microformats-v1/includes/hyperlink.json +0 -43
  194. data/vendor/tests/tests/microformats-v1/includes/object.html +0 -23
  195. data/vendor/tests/tests/microformats-v1/includes/object.json +0 -42
  196. data/vendor/tests/tests/microformats-v1/includes/table.html +0 -12
  197. data/vendor/tests/tests/microformats-v1/includes/table.json +0 -19
  198. data/vendor/tests/tests/microformats-v2/h-adr/change-log.html +0 -62
  199. data/vendor/tests/tests/microformats-v2/h-adr/geo.html +0 -10
  200. data/vendor/tests/tests/microformats-v2/h-adr/geo.json +0 -16
  201. data/vendor/tests/tests/microformats-v2/h-adr/geourl.html +0 -4
  202. data/vendor/tests/tests/microformats-v2/h-adr/geourl.json +0 -13
  203. data/vendor/tests/tests/microformats-v2/h-adr/justaname.html +0 -1
  204. data/vendor/tests/tests/microformats-v2/h-adr/justaname.json +0 -10
  205. data/vendor/tests/tests/microformats-v2/h-adr/lettercase.html +0 -21
  206. data/vendor/tests/tests/microformats-v2/h-adr/lettercase.json +0 -12
  207. data/vendor/tests/tests/microformats-v2/h-adr/simpleproperties.html +0 -8
  208. data/vendor/tests/tests/microformats-v2/h-adr/simpleproperties.json +0 -16
  209. data/vendor/tests/tests/microformats-v2/h-as-note/note.html +0 -56
  210. data/vendor/tests/tests/microformats-v2/h-as-note/note.json +0 -98
  211. data/vendor/tests/tests/microformats-v2/h-card/baseurl.html +0 -6
  212. data/vendor/tests/tests/microformats-v2/h-card/baseurl.json +0 -26
  213. data/vendor/tests/tests/microformats-v2/h-card/change-log.html +0 -100
  214. data/vendor/tests/tests/microformats-v2/h-card/childimplied.html +0 -7
  215. data/vendor/tests/tests/microformats-v2/h-card/childimplied.json +0 -12
  216. data/vendor/tests/tests/microformats-v2/h-card/extendeddescription.html +0 -10
  217. data/vendor/tests/tests/microformats-v2/h-card/extendeddescription.json +0 -15
  218. data/vendor/tests/tests/microformats-v2/h-card/hcard.html +0 -4
  219. data/vendor/tests/tests/microformats-v2/h-card/hcard.json +0 -19
  220. data/vendor/tests/tests/microformats-v2/h-card/horghcard.html +0 -4
  221. data/vendor/tests/tests/microformats-v2/h-card/horghcard.json +0 -19
  222. data/vendor/tests/tests/microformats-v2/h-card/hyperlinkedphoto.html +0 -3
  223. data/vendor/tests/tests/microformats-v2/h-card/hyperlinkedphoto.json +0 -12
  224. data/vendor/tests/tests/microformats-v2/h-card/impliedname.html +0 -15
  225. data/vendor/tests/tests/microformats-v2/h-card/impliedname.json +0 -90
  226. data/vendor/tests/tests/microformats-v2/h-card/impliedphoto.html +0 -11
  227. data/vendor/tests/tests/microformats-v2/h-card/impliedphoto.json +0 -72
  228. data/vendor/tests/tests/microformats-v2/h-card/impliedurl.html +0 -5
  229. data/vendor/tests/tests/microformats-v2/h-card/impliedurl.json +0 -45
  230. data/vendor/tests/tests/microformats-v2/h-card/justahyperlink.html +0 -1
  231. data/vendor/tests/tests/microformats-v2/h-card/justahyperlink.json +0 -11
  232. data/vendor/tests/tests/microformats-v2/h-card/justaname.html +0 -1
  233. data/vendor/tests/tests/microformats-v2/h-card/justaname.json +0 -10
  234. data/vendor/tests/tests/microformats-v2/h-card/nested.html +0 -4
  235. data/vendor/tests/tests/microformats-v2/h-card/nested.json +0 -18
  236. data/vendor/tests/tests/microformats-v2/h-card/p-property.html +0 -21
  237. data/vendor/tests/tests/microformats-v2/h-card/p-property.json +0 -15
  238. data/vendor/tests/tests/microformats-v2/h-card/relativeurls.html +0 -6
  239. data/vendor/tests/tests/microformats-v2/h-card/relativeurls.json +0 -29
  240. data/vendor/tests/tests/microformats-v2/h-entry/change-log.html +0 -90
  241. data/vendor/tests/tests/microformats-v2/h-entry/encoding.html +0 -3
  242. data/vendor/tests/tests/microformats-v2/h-entry/encoding.json +0 -14
  243. data/vendor/tests/tests/microformats-v2/h-entry/impliedvalue-nested.html +0 -9
  244. data/vendor/tests/tests/microformats-v2/h-entry/impliedvalue-nested.json +0 -27
  245. data/vendor/tests/tests/microformats-v2/h-entry/justahyperlink.html +0 -1
  246. data/vendor/tests/tests/microformats-v2/h-entry/justahyperlink.json +0 -11
  247. data/vendor/tests/tests/microformats-v2/h-entry/justaname.html +0 -1
  248. data/vendor/tests/tests/microformats-v2/h-entry/justaname.json +0 -10
  249. data/vendor/tests/tests/microformats-v2/h-entry/scriptstyletags.html +0 -4
  250. data/vendor/tests/tests/microformats-v2/h-entry/scriptstyletags.json +0 -14
  251. data/vendor/tests/tests/microformats-v2/h-entry/summarycontent.html +0 -20
  252. data/vendor/tests/tests/microformats-v2/h-entry/summarycontent.json +0 -25
  253. data/vendor/tests/tests/microformats-v2/h-entry/u-property.html +0 -33
  254. data/vendor/tests/tests/microformats-v2/h-entry/u-property.json +0 -12
  255. data/vendor/tests/tests/microformats-v2/h-entry/urlincontent.html +0 -13
  256. data/vendor/tests/tests/microformats-v2/h-entry/urlincontent.json +0 -14
  257. data/vendor/tests/tests/microformats-v2/h-event/ampm.html +0 -41
  258. data/vendor/tests/tests/microformats-v2/h-event/ampm.json +0 -21
  259. data/vendor/tests/tests/microformats-v2/h-event/attendees.html +0 -13
  260. data/vendor/tests/tests/microformats-v2/h-event/attendees.json +0 -37
  261. data/vendor/tests/tests/microformats-v2/h-event/change-log.html +0 -82
  262. data/vendor/tests/tests/microformats-v2/h-event/combining.html +0 -13
  263. data/vendor/tests/tests/microformats-v2/h-event/combining.json +0 -25
  264. data/vendor/tests/tests/microformats-v2/h-event/concatenate.html +0 -8
  265. data/vendor/tests/tests/microformats-v2/h-event/concatenate.json +0 -12
  266. data/vendor/tests/tests/microformats-v2/h-event/dates.html +0 -13
  267. data/vendor/tests/tests/microformats-v2/h-event/dates.json +0 -26
  268. data/vendor/tests/tests/microformats-v2/h-event/dt-property.html +0 -23
  269. data/vendor/tests/tests/microformats-v2/h-event/dt-property.json +0 -20
  270. data/vendor/tests/tests/microformats-v2/h-event/justahyperlink.html +0 -1
  271. data/vendor/tests/tests/microformats-v2/h-event/justahyperlink.json +0 -11
  272. data/vendor/tests/tests/microformats-v2/h-event/justaname.html +0 -1
  273. data/vendor/tests/tests/microformats-v2/h-event/justaname.json +0 -10
  274. data/vendor/tests/tests/microformats-v2/h-event/time.html +0 -47
  275. data/vendor/tests/tests/microformats-v2/h-event/time.json +0 -25
  276. data/vendor/tests/tests/microformats-v2/h-feed/implied-title.html +0 -30
  277. data/vendor/tests/tests/microformats-v2/h-feed/implied-title.json +0 -23
  278. data/vendor/tests/tests/microformats-v2/h-feed/simple.html +0 -26
  279. data/vendor/tests/tests/microformats-v2/h-feed/simple.json +0 -33
  280. data/vendor/tests/tests/microformats-v2/h-geo/abbrpattern.html +0 -5
  281. data/vendor/tests/tests/microformats-v2/h-geo/abbrpattern.json +0 -12
  282. data/vendor/tests/tests/microformats-v2/h-geo/altitude.html +0 -8
  283. data/vendor/tests/tests/microformats-v2/h-geo/altitude.json +0 -13
  284. data/vendor/tests/tests/microformats-v2/h-geo/change-log.html +0 -67
  285. data/vendor/tests/tests/microformats-v2/h-geo/hidden.html +0 -10
  286. data/vendor/tests/tests/microformats-v2/h-geo/hidden.json +0 -12
  287. data/vendor/tests/tests/microformats-v2/h-geo/justaname.html +0 -3
  288. data/vendor/tests/tests/microformats-v2/h-geo/justaname.json +0 -10
  289. data/vendor/tests/tests/microformats-v2/h-geo/simpleproperties.html +0 -5
  290. data/vendor/tests/tests/microformats-v2/h-geo/simpleproperties.json +0 -12
  291. data/vendor/tests/tests/microformats-v2/h-geo/valuetitleclass.html +0 -11
  292. data/vendor/tests/tests/microformats-v2/h-geo/valuetitleclass.json +0 -12
  293. data/vendor/tests/tests/microformats-v2/h-news/all.html +0 -35
  294. data/vendor/tests/tests/microformats-v2/h-news/all.json +0 -51
  295. data/vendor/tests/tests/microformats-v2/h-news/change-log.html +0 -78
  296. data/vendor/tests/tests/microformats-v2/h-news/minimum.html +0 -24
  297. data/vendor/tests/tests/microformats-v2/h-news/minimum.json +0 -40
  298. data/vendor/tests/tests/microformats-v2/h-org/change-log.html +0 -57
  299. data/vendor/tests/tests/microformats-v2/h-org/hyperlink.html +0 -1
  300. data/vendor/tests/tests/microformats-v2/h-org/hyperlink.json +0 -11
  301. data/vendor/tests/tests/microformats-v2/h-org/simple.html +0 -1
  302. data/vendor/tests/tests/microformats-v2/h-org/simple.json +0 -10
  303. data/vendor/tests/tests/microformats-v2/h-org/simpleproperties.html +0 -4
  304. data/vendor/tests/tests/microformats-v2/h-org/simpleproperties.json +0 -12
  305. data/vendor/tests/tests/microformats-v2/h-product/aggregate.html +0 -21
  306. data/vendor/tests/tests/microformats-v2/h-product/aggregate.json +0 -45
  307. data/vendor/tests/tests/microformats-v2/h-product/change-log.html +0 -62
  308. data/vendor/tests/tests/microformats-v2/h-product/justahyperlink.html +0 -1
  309. data/vendor/tests/tests/microformats-v2/h-product/justahyperlink.json +0 -11
  310. data/vendor/tests/tests/microformats-v2/h-product/justaname.html +0 -1
  311. data/vendor/tests/tests/microformats-v2/h-product/justaname.json +0 -10
  312. data/vendor/tests/tests/microformats-v2/h-product/simpleproperties.html +0 -10
  313. data/vendor/tests/tests/microformats-v2/h-product/simpleproperties.json +0 -26
  314. data/vendor/tests/tests/microformats-v2/h-recipe/all.html +0 -63
  315. data/vendor/tests/tests/microformats-v2/h-recipe/all.json +0 -54
  316. data/vendor/tests/tests/microformats-v2/h-recipe/change-log.html +0 -62
  317. data/vendor/tests/tests/microformats-v2/h-recipe/minimum.html +0 -7
  318. data/vendor/tests/tests/microformats-v2/h-recipe/minimum.json +0 -17
  319. data/vendor/tests/tests/microformats-v2/h-resume/affiliation.html +0 -12
  320. data/vendor/tests/tests/microformats-v2/h-resume/affiliation.json +0 -20
  321. data/vendor/tests/tests/microformats-v2/h-resume/change-log.html +0 -78
  322. data/vendor/tests/tests/microformats-v2/h-resume/contact.html +0 -17
  323. data/vendor/tests/tests/microformats-v2/h-resume/contact.json +0 -26
  324. data/vendor/tests/tests/microformats-v2/h-resume/education.html +0 -13
  325. data/vendor/tests/tests/microformats-v2/h-resume/education.json +0 -30
  326. data/vendor/tests/tests/microformats-v2/h-resume/justaname.html +0 -1
  327. data/vendor/tests/tests/microformats-v2/h-resume/justaname.json +0 -10
  328. data/vendor/tests/tests/microformats-v2/h-resume/skill.html +0 -12
  329. data/vendor/tests/tests/microformats-v2/h-resume/skill.json +0 -12
  330. data/vendor/tests/tests/microformats-v2/h-resume/work.html +0 -16
  331. data/vendor/tests/tests/microformats-v2/h-resume/work.json +0 -31
  332. data/vendor/tests/tests/microformats-v2/h-review-aggregate/change-log.html +0 -78
  333. data/vendor/tests/tests/microformats-v2/h-review-aggregate/hevent.html +0 -13
  334. data/vendor/tests/tests/microformats-v2/h-review-aggregate/hevent.json +0 -23
  335. data/vendor/tests/tests/microformats-v2/h-review-aggregate/justahyperlink.html +0 -8
  336. data/vendor/tests/tests/microformats-v2/h-review-aggregate/justahyperlink.json +0 -19
  337. data/vendor/tests/tests/microformats-v2/h-review-aggregate/simpleproperties.html +0 -18
  338. data/vendor/tests/tests/microformats-v2/h-review-aggregate/simpleproperties.json +0 -26
  339. data/vendor/tests/tests/microformats-v2/h-review/change-log.html +0 -84
  340. data/vendor/tests/tests/microformats-v2/h-review/hyperlink.html +0 -1
  341. data/vendor/tests/tests/microformats-v2/h-review/hyperlink.json +0 -11
  342. data/vendor/tests/tests/microformats-v2/h-review/implieditem.html +0 -4
  343. data/vendor/tests/tests/microformats-v2/h-review/implieditem.json +0 -19
  344. data/vendor/tests/tests/microformats-v2/h-review/item.html +0 -8
  345. data/vendor/tests/tests/microformats-v2/h-review/item.json +0 -20
  346. data/vendor/tests/tests/microformats-v2/h-review/justaname.html +0 -1
  347. data/vendor/tests/tests/microformats-v2/h-review/justaname.json +0 -10
  348. data/vendor/tests/tests/microformats-v2/h-review/photo.html +0 -1
  349. data/vendor/tests/tests/microformats-v2/h-review/photo.json +0 -11
  350. data/vendor/tests/tests/microformats-v2/h-review/vcard.html +0 -23
  351. data/vendor/tests/tests/microformats-v2/h-review/vcard.json +0 -48
  352. data/vendor/tests/tests/microformats-v2/rel/change-log.html +0 -67
  353. data/vendor/tests/tests/microformats-v2/rel/duplicate-rels.html +0 -10
  354. data/vendor/tests/tests/microformats-v2/rel/duplicate-rels.json +0 -75
  355. data/vendor/tests/tests/microformats-v2/rel/license.html +0 -1
  356. data/vendor/tests/tests/microformats-v2/rel/license.json +0 -12
  357. data/vendor/tests/tests/microformats-v2/rel/nofollow.html +0 -1
  358. data/vendor/tests/tests/microformats-v2/rel/nofollow.json +0 -12
  359. data/vendor/tests/tests/microformats-v2/rel/rel-urls.html +0 -8
  360. data/vendor/tests/tests/microformats-v2/rel/rel-urls.json +0 -33
  361. data/vendor/tests/tests/microformats-v2/rel/varying-text-duplicate-rels.html +0 -4
  362. data/vendor/tests/tests/microformats-v2/rel/varying-text-duplicate-rels.json +0 -20
  363. data/vendor/tests/tests/microformats-v2/rel/xfn-all.html +0 -19
  364. data/vendor/tests/tests/microformats-v2/rel/xfn-all.json +0 -92
  365. data/vendor/tests/tests/microformats-v2/rel/xfn-elsewhere.html +0 -10
  366. data/vendor/tests/tests/microformats-v2/rel/xfn-elsewhere.json +0 -40
data/Rakefile CHANGED
@@ -1,9 +1,8 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
- require "nokogiri"
4
- require "open-uri"
5
- require "pp"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
6
4
 
7
- RSpec::Core::RakeTask.new(:spec)
8
- task :default => [:spec]
5
+ RSpec::Core::RakeTask.new
6
+ RuboCop::RakeTask.new
9
7
 
8
+ task default: :spec
@@ -4,25 +4,26 @@ require 'microformats'
4
4
  require 'json'
5
5
 
6
6
  def print_usage
7
- puts "Usage: microformats (URL, filepath, or HTML)"
7
+ puts 'Usage: microformats (URL, filepath, or HTML)'
8
8
  end
9
9
 
10
10
  def process_html(html)
11
- collection = Microformats.parse(html)
12
- puts JSON.pretty_generate(JSON[collection.to_json.to_s])
11
+ collection = Microformats.parse(html)
12
+ puts JSON.pretty_generate(JSON[collection.to_json.to_s])
13
13
  end
14
14
 
15
15
  if STDIN.tty?
16
- unless ARGV[0].nil?
17
- process_html(ARGV[0])
18
- else
16
+ if ARGV[0].nil?
19
17
  print_usage
18
+ else
19
+ process_html(ARGV[0])
20
20
  end
21
21
  else
22
22
  html = STDIN.read
23
- unless html.nil?
24
- process_html(html)
25
- else
23
+
24
+ if html.nil?
26
25
  print_usage
26
+ else
27
+ process_html(html)
27
28
  end
28
29
  end
@@ -1,17 +1,18 @@
1
- require "nokogiri"
2
- require "open-uri"
3
- require "json"
1
+ require 'nokogiri'
2
+ require 'open-uri'
3
+ require 'json'
4
+ require 'set'
4
5
 
5
- require "microformats/version"
6
- require "microformats/absolute_uri"
7
- require "microformats/parser_core"
8
- require "microformats/parser"
9
- require "microformats/format_parser"
10
- require "microformats/property_parser"
11
- require "microformats/time_property_parser"
12
- require "microformats/results/parser_result"
13
- require "microformats/results/collection"
14
- require "microformats/results/property_set"
6
+ require 'microformats/version'
7
+ require 'microformats/absolute_uri'
8
+ require 'microformats/parser_core'
9
+ require 'microformats/parser'
10
+ require 'microformats/format_parser'
11
+ require 'microformats/property_parser'
12
+ require 'microformats/time_property_parser'
13
+ require 'microformats/results/parser_result'
14
+ require 'microformats/results/collection'
15
+ require 'microformats/results/property_set'
15
16
 
16
17
  module Microformats
17
18
  class << self
@@ -22,7 +23,7 @@ module Microformats
22
23
  def read_html(html)
23
24
  Parser.new.read_html(html)
24
25
  end
25
- end # class << self
26
+ end
26
27
 
27
28
  class InvalidPropertyPrefix < StandardError; end
28
29
  end
@@ -11,20 +11,16 @@ module Microformats
11
11
 
12
12
  def absolutize
13
13
  return relative if base.nil?
14
- return base if relative.nil? or relative == ""
15
- return relative if relative =~ /^https?:\/\//
14
+ return base if relative.nil? || relative == ''
15
+ return relative if relative =~ %r{^https?://}
16
16
  return base + relative if relative =~ /^#/
17
17
 
18
18
  uri = URI.parse(relative)
19
-
20
- if base && !uri.absolute?
21
- uri = URI.join(base.to_s, relative.to_s)
22
- end
19
+ uri = URI.join(base.to_s, relative.to_s) if base && !uri.absolute?
23
20
 
24
21
  uri.normalize!
25
22
  uri.to_s
26
-
27
- rescue URI::BadURIError, URI::InvalidURIError => e
23
+ rescue URI::BadURIError, URI::InvalidURIError
28
24
  relative.to_s
29
25
  end
30
26
  end
@@ -1,343 +1,363 @@
1
1
  module Microformats
2
2
  class FormatParser < ParserCore
3
-
4
- def parse(element, base:nil, element_type:nil, format_class_array:[], backcompat:false)
3
+ def parse(element, base: nil, element_type: nil, format_class_array: [], backcompat: false)
5
4
  @base = base
6
5
 
7
6
  @mode_backcompat = backcompat
8
7
 
9
8
  @properties = {}
10
9
  @children = []
10
+ @found_prefixes = Set.new
11
11
 
12
12
  @format_property_type = element_type
13
13
  @value = nil
14
14
 
15
15
  @mode_backcompat = backcompat
16
16
 
17
- @fmt_classes = format_class_array
17
+ @fmt_classes = format_class_array
18
18
 
19
19
  parse_node(element.children)
20
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)}
21
+ # check properties for any missing h-* so we know not to imply anything
22
+ check_for_h_properties
36
23
 
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
24
+ imply_properties(element)
39
25
 
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]
26
+ if @value.nil? || @value.empty?
27
+ if element_type == 'p' && !@properties['name'].nil? && !@properties['name'].empty?
28
+ @value = @properties['name'].first
29
+ elsif element_type == 'u' && !@properties['url'].nil? && !@properties['url'].empty?
30
+ @value = @properties['url'].first
31
+ elsif !element_type.nil?
32
+ @value = PropertyParser.new.parse(element, base: @base, element_type: element_type, backcompat: @mode_backcompat)
33
+ end
34
+ end
43
35
 
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]
36
+ h_object = {}
47
37
 
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]
38
+ h_object['value'] = @value unless @value.nil?
39
+ h_object['type'] = format_class_array
40
+ h_object['properties'] = @properties
51
41
 
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
42
+ h_object['children'] = @children unless @children.empty?
56
43
 
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]
44
+ if @format_property_type == 'e'
45
+ h_object['value'] = render_text(element)
46
+ h_object['html'] = element.inner_html.strip
47
+ end
60
48
 
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]
49
+ # TODO: fall back to p- dt- u- parsing if value still not set?
50
+ # not sure that is correct by the spec actually
51
+ h_object
52
+ end
64
53
 
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]
54
+ def parse_element(element)
55
+ prop_classes = property_classes(element)
56
+ prop_classes = backcompat_property_classes(element) if @mode_backcompat
68
57
 
69
- else
70
- @properties['name'] = [element.text.strip]
58
+ bc_classes_found = false
59
+ fmt_classes = format_classes(element)
71
60
 
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
61
+ prop_classes.each do |p_class|
62
+ element_type = prefix_from_class(p_class)
63
+ @found_prefixes.add(element_type.to_sym)
64
+ end
65
+ fmt_classes.each do |p_class|
66
+ element_type = prefix_from_class(p_class)
67
+ @found_prefixes.add(element_type.to_sym)
68
+ end
82
69
 
70
+ if fmt_classes.empty?
71
+ fmt_classes = backcompat_format_classes(element)
72
+ bc_classes_found = true unless fmt_classes.empty?
73
+ end
83
74
 
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
75
+ if prop_classes.length >= 1
76
+ if fmt_classes.length >= 1
77
+ prop_classes.each do |element_class|
78
+ element_type = prefix_from_class(element_class)
79
+ property_name = property_from_class(element_class)
90
80
 
91
- #else if .h-x>img[src]:only-of-type:not[.h-*] then use that img src for photo
81
+ parsed_format = FormatParser.new.parse(element, base: @base, element_type: element_type, format_class_array: fmt_classes, backcompat: bc_classes_found)
92
82
 
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]
83
+ if @value.nil?
84
+ if @format_property_type == 'p' && property_name == 'name'
85
+ @value = parsed_format['value']
86
+ # elsif @format_property_type == 'dt' and property_name == '???'
87
+ # @value = parsed_format['value']
88
+ elsif @format_property_type == 'u' && property_name == 'url'
89
+ @value = parsed_format['value']
100
90
  end
101
91
  end
102
92
 
103
- if @properties['photo'].nil?
93
+ @properties[property_name] = [] if @properties[property_name].nil?
94
+ @properties[property_name] << parsed_format
95
+ end
96
+ else
97
+ prop_classes.each do |element_class|
98
+ element_type = prefix_from_class(element_class)
99
+ property_name = property_from_class(element_class)
104
100
 
105
- #else if .h-x>object[data]:only-of-type:not[.h-*] then use that object’s data for photo
101
+ parsed_property = PropertyParser.new.parse(element, base: @base, element_type: element_type, backcompat: @mode_backcompat)
106
102
 
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
103
+ unless parsed_property.nil?
104
+ @properties[property_name] = [] if @properties[property_name].nil?
105
+ @properties[property_name] << parsed_property
116
106
  end
107
+ end
117
108
 
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
109
+ parse_nodeset(element.children)
110
+ end
111
+ elsif fmt_classes.length >= 1
112
+ @children << FormatParser.new.parse(element, base: @base, format_class_array: fmt_classes, backcompat: bc_classes_found)
113
+ else
114
+ parse_nodeset(element.children)
115
+ end
116
+ end
123
117
 
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
118
+ def check_for_h_properties
119
+ @properties.each do |_, prop|
120
+ prop.each do |prop_entry|
121
+ next unless prop_entry.respond_to?(:key) && prop_entry.key?('type')
122
+ next if prop_entry['type'].nil?
133
123
 
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'] = [ Microformats::AbsoluteUri.new(@properties['photo'].first, base: @base).absolutize ]
124
+ prop_entry['type'].each do |type|
125
+ @found_prefixes.add(prefix_from_class(type).to_sym)
153
126
  end
154
127
  end
128
+ end
129
+ end
155
130
 
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]
131
+ def imply_name(element)
132
+ return unless @properties['name'].nil? && !@found_prefixes.include?(:e) && !@found_prefixes.include?(:p) && !@found_prefixes.include?(:h) && @children.empty?
133
+
134
+ if element.name == 'img' && !element.attribute('alt').nil?
135
+ @properties['name'] = [element.attribute('alt').value.strip]
136
+ elsif element.name == 'area' && !element.attribute('alt').nil?
137
+ @properties['name'] = [element.attribute('alt').value.strip]
138
+ elsif element.name == 'abbr' && !element.attribute('title').nil?
139
+ @properties['name'] = [element.attribute('title').value.strip]
140
+ else
141
+ child_nodes = element.children.reject { |n| n.is_a?(Nokogiri::XML::Text) }
142
+
143
+ if child_nodes.count == 1 && child_nodes.first.is_a?(Nokogiri::XML::Element) && format_classes(child_nodes.first).empty?
144
+ node = child_nodes.first
145
+
146
+ # else if .h-x>img:only-child[alt]:not([alt=""]):not[.h-*] then use that img's alt for name
147
+ if node.name == 'img' && !node.attribute('alt').nil? && !node.attribute('alt').value.empty?
148
+ @properties['name'] = [node.attribute('alt').value.strip]
149
+ # else if .h-x>area:only-child[alt]:not([alt=""]):not[.h-*] then use that area's alt for name
150
+ elsif node.name == 'area' && !node.attribute('alt').nil? && !node.attribute('alt').value.empty?
151
+ @properties['name'] = [node.attribute('alt').value.strip]
152
+ # else if .h-x>abbr:only-child[title]:not([title=""]):not[.h-*] then use that abbr title for name
153
+ elsif node.name == 'abbr' && !node.attribute('title').nil? && !node.attribute('title').value.empty?
154
+ @properties['name'] = [node.attribute('title').value.strip]
161
155
  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
156
+ child_nodes = node.children.reject { |n| n.is_a?(Nokogiri::XML::Text) }
172
157
 
173
- if @properties['url'].nil?
158
+ if child_nodes.count == 1 && child_nodes.first.is_a?(Nokogiri::XML::Element) && format_classes(child_nodes.first).empty?
159
+ node = child_nodes.first
174
160
 
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
161
+ # else if .h-x>:only-child:not[.h-*]>img:only-child[alt]:not([alt=""]):not[.h-*] then use that img's alt for name
162
+ if node.name == 'img' && !node.attribute('alt').nil? && !node.attribute('alt').value.empty?
163
+ @properties['name'] = [node.attribute('alt').value.strip]
164
+ # else if .h-x>:only-child:not[.h-*]>area:only-child[alt]:not([alt=""]):not[.h-*] then use that area's alt for name
165
+ elsif node.name == 'area' && !node.attribute('alt').nil? && !node.attribute('alt').value.empty?
166
+ @properties['name'] = [node.attribute('alt').value.strip]
167
+ # else if .h-x>:only-child:not[.h-*]>abbr:only-child[title]:not([title=""]):not[.h-*] use that abbr's title for name
168
+ elsif node.name == 'abbr' && !node.attribute('title').nil? && !node.attribute('title').value.empty?
169
+ @properties['name'] = [node.attribute('title').value.strip]
170
+ else
171
+ @properties['name'] = [render_text(element)]
184
172
  end
173
+ else
174
+ @properties['name'] = [render_text(element)]
185
175
  end
176
+ end
177
+ else
178
+ @properties['name'] = [render_text(element)]
179
+ end
180
+ end
181
+ end
186
182
 
187
- child_elements = element.children.select do |child| not child.is_a?(Nokogiri::XML::Text) end
183
+ def imply_photo(element)
184
+ return unless @properties['photo'].nil?
188
185
 
189
- if @properties['url'].nil? and child_elements.count == 1 and format_classes(child_elements.first).empty?
190
- child_element = child_elements.first
186
+ if element.name == 'img' && !element.attribute('src').nil?
187
+ @properties['photo'] = [element.attribute('src').value]
188
+ elsif element.name == 'object' && !element.attribute('data').nil?
189
+ @properties['photo'] = [element.attribute('data').value]
190
+ else
191
+ # else if .h-x>img[src]:only-of-type:not[.h-*] then use that img src for photo
192
+ child_img_tags_with_src = element.children.select do |child|
193
+ child.is_a?(Nokogiri::XML::Element) && child.name == 'img' && !child.attribute('src').nil?
194
+ end
191
195
 
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
196
+ if child_img_tags_with_src.count == 1
197
+ node = child_img_tags_with_src.first
202
198
 
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
199
+ @properties['photo'] = [node.attribute('src').value.strip] if format_classes(node).empty?
200
+ end
218
201
 
219
- unless @properties['url'].nil?
220
- @properties['url'] = [ Microformats::AbsoluteUri.new(@properties['url'].first, base: @base).absolutize ]
202
+ if @properties['photo'].nil?
203
+ # else if .h-x>object[data]:only-of-type:not[.h-*] then use that object's data for photo
204
+ child_object_tags_with_data = element.children.select do |child|
205
+ child.is_a?(Nokogiri::XML::Element) && child.name == 'object' && !child.attribute('data').nil?
221
206
  end
222
- end
223
207
 
224
- end
225
- ##### END Implied Properties when not in backcompat mode######
208
+ if child_object_tags_with_data.count == 1
209
+ node = child_object_tags_with_data.first
226
210
 
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
211
+ if format_classes(node).empty?
212
+ @properties['photo'] = [node.attribute('data').value.strip]
245
213
  end
246
214
  end
247
215
  end
248
- end
249
216
 
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)
257
- end
258
- end
217
+ child_elements = element.children.reject { |child| child.is_a?(Nokogiri::XML::Text) }
259
218
 
260
- h_object = {}
219
+ if @properties['photo'].nil? && child_elements.count == 1 && format_classes(child_elements.first).empty?
220
+ # else if .h-x>:only-child:not[.h-*]>img[src]:only-of-type:not[.h-*], then use that img's src for photo
221
+ child_img_tags_with_src = child_elements.first.children.select do |child|
222
+ child.is_a?(Nokogiri::XML::Element) && child.name == 'img' && !child.attribute('src').nil?
223
+ end
261
224
 
262
- h_object['value'] = @value unless @value.nil?
263
- h_object['type'] = format_class_array
264
- h_object['properties'] = @properties
225
+ if child_img_tags_with_src.count == 1
226
+ node = child_img_tags_with_src.first
265
227
 
266
- h_object['children'] = @children unless @children.empty?
228
+ if format_classes(node).empty?
229
+ @properties['photo'] = [node.attribute('src').value.strip]
230
+ end
231
+ end
267
232
 
268
- if @format_property_type == 'e'
269
- h_object['value'] = element.text.strip
270
- h_object['html'] = element.inner_html
271
- end
233
+ if @properties['photo'].nil?
234
+ # else if .h-x>:only-child:not[.h-*]>object[data]:only-of-type:not[.h-*], then use that object's data for photo
235
+ child_object_tags_with_data = child_elements.first.children.select do |child|
236
+ child.is_a?(Nokogiri::XML::Element) && child.name == 'object' && !child.attribute('data').nil?
237
+ end
272
238
 
273
- ##todo fall back to p- dt- u- parsing if value still not set?
274
- # not sure that is correct by the spec actually
239
+ if child_object_tags_with_data.count == 1
240
+ node = child_object_tags_with_data.first
275
241
 
276
- h_object
242
+ if format_classes(node).empty?
243
+ @properties['photo'] = [node.attribute('data').value.strip]
244
+ end
245
+ end
246
+ end
247
+ end
248
+ end
277
249
 
250
+ @properties['photo'] = [Microformats::AbsoluteUri.new(@properties['photo'].first, base: @base).absolutize] unless @properties['photo'].nil?
278
251
  end
279
252
 
253
+ def imply_url(element)
254
+ return unless @properties['url'].nil? && !@found_prefixes.include?(:u) && !@found_prefixes.include?(:h) && @children.empty?
280
255
 
281
- def parse_element(element)
256
+ if element.name == 'a' && !element.attribute('href').nil?
257
+ @properties['url'] = [element.attribute('href').value]
258
+ elsif element.name == 'area' && !element.attribute('href').nil?
259
+ @properties['url'] = [element.attribute('href').value]
260
+ else
261
+ # else if .h-x>a[href]:only-of-type:not[.h-*], then use that [href] for url
262
+ child_a_tags_with_href = element.children.select do |child|
263
+ child.is_a?(Nokogiri::XML::Element) && child.name == 'a' && !child.attribute('href').nil?
264
+ end
282
265
 
283
- prop_classes = property_classes(element)
284
- prop_classes = backcompat_property_classes(element) if @mode_backcompat
266
+ if child_a_tags_with_href.count == 1
267
+ node = child_a_tags_with_href.first
268
+ @properties['url'] = [node.attribute('href').value.strip] if format_classes(node).empty?
269
+ end
285
270
 
286
- bc_classes_found = false
287
- fmt_classes = format_classes(element)
271
+ if @properties['url'].nil?
272
+ # else if .h-x>area[href]:only-of-type:not[.h-*], then use that [href] for url
273
+ child_area_tags_with_href = element.children.select do |child|
274
+ child.is_a?(Nokogiri::XML::Element) && child.name == 'area' && !child.attribute('href').nil?
275
+ end
288
276
 
289
- if fmt_classes.empty?
290
- fmt_classes = backcompat_format_classes(element)
291
- bc_classes_found = true unless fmt_classes.empty?
292
- end
277
+ if child_area_tags_with_href.count == 1
278
+ node = child_area_tags_with_href.first
279
+ @properties['url'] = [node.attribute('href').value.strip] if format_classes(node).empty?
280
+ end
281
+ end
293
282
 
294
- if prop_classes.length >= 1
283
+ child_elements = element.children.reject { |child| child.is_a?(Nokogiri::XML::Text) }
295
284
 
296
- if fmt_classes.length >= 1
285
+ if @properties['url'].nil? && child_elements.count == 1 && format_classes(child_elements.first).empty?
286
+ child_element = child_elements.first
287
+ # else if .h-x>:only-child:not[.h-*]>a[href]:only-of-type:not[.h-*], then use that [href] for url
288
+ child_a_tags_with_href = child_element.children.select do |child|
289
+ child.is_a?(Nokogiri::XML::Element) && child.name == 'a' && !child.attribute('href').nil?
290
+ end
297
291
 
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('-')
292
+ if child_a_tags_with_href.count == 1
293
+ node = child_a_tags_with_href.first
294
+ @properties['url'] = [node.attribute('href').value.strip] if format_classes(node).empty?
295
+ end
301
296
 
302
- parsed_format = FormatParser.new.parse(element, base:@base, element_type: element_type, format_class_array: fmt_classes, backcompat: bc_classes_found )
297
+ if @properties['url'].nil?
298
+ # else if .h-x>:only-child:not[.h-*]>area[href]:only-of-type:not[.h-*], then use that [href] for url
299
+ child_area_tags_with_href = child_element.children.select do |child|
300
+ child.is_a?(Nokogiri::XML::Element) && child.name == 'area' && !child.attribute('href').nil?
301
+ end
303
302
 
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
303
+ if child_area_tags_with_href.count == 1
304
+ node = child_area_tags_with_href.first
305
+ @properties['url'] = [node.attribute('href').value.strip] if format_classes(node).empty?
312
306
  end
307
+ end
308
+ end
309
+ end
313
310
 
314
- @properties[property_name] = [] if @properties[property_name].nil?
315
- @properties[property_name] << parsed_format
311
+ @properties['url'] = [Microformats::AbsoluteUri.new(@properties['url'].first, base: @base).absolutize] unless @properties['url'].nil?
312
+ end
316
313
 
317
- end
314
+ def prefix_from_class(class_name)
315
+ class_name.downcase.split('-')[0]
316
+ end
318
317
 
319
- else
318
+ def property_from_class(class_name)
319
+ class_name.downcase.split('-')[1..-1].join('-')
320
+ end
320
321
 
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('-')
322
+ # imply date for dt-end if dt-start is defined with a date ###
323
+ def imply_dates
324
+ return unless !@properties['end'].nil? && !@properties['start'].nil?
324
325
 
325
- parsed_property = PropertyParser.new.parse(element, base: @base, element_type: element_type, backcompat: @mode_backcompat)
326
+ start_date = nil
326
327
 
327
- if not parsed_property.nil?
328
- @properties[property_name] = [] if @properties[property_name].nil?
329
- @properties[property_name] << parsed_property
330
- end
331
- end
332
- parse_nodeset(element.children)
328
+ @properties['start'].each do |start_val|
329
+ if start_val =~ /^(\d{4}-[01]\d-[0-3]\d)/
330
+ start_date = Regexp.last_match(1) if start_date.nil?
331
+ elsif start_val =~ /^(\d{4}-[0-3]\d\d)/
332
+ start_date = Regexp.last_match(1) if start_date.nil?
333
333
  end
334
+ end
334
335
 
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)
336
+ unless start_date.nil?
337
+ @properties['end'].map! do |end_val|
338
+ if end_val.match?(/^\d{4}-[01]\d-[0-3]\d/)
339
+ end_val
340
+ elsif end_val.match?(/^\d{4}-[0-3]\d\d/)
341
+ end_val
342
+ else
343
+ start_date + ' ' + end_val
344
+ end
345
+ end
339
346
  end
340
347
  end
341
348
 
349
+ def imply_properties(element)
350
+ ##### Implied Properties ######
351
+ # NOTE: much of this code may be simplified by using element.css, not sure yet, but coding to have passing tests first
352
+ # can optimize this later
353
+ unless @mode_backcompat
354
+ imply_name(element)
355
+ imply_photo(element)
356
+ imply_url(element)
357
+ end
358
+ ##### END Implied Properties when not in backcompat mode######
359
+
360
+ imply_dates
361
+ end
342
362
  end
343
363
  end