microformats 4.0.6 → 4.2.1

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 (364) hide show
  1. checksums.yaml +5 -5
  2. data/.editorconfig +10 -0
  3. data/.gitignore +33 -15
  4. data/.rspec +3 -2
  5. data/.rubocop +3 -0
  6. data/.rubocop.yml +22 -0
  7. data/.ruby-version +1 -0
  8. data/.simplecov +11 -0
  9. data/.travis.yml +16 -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 +39 -39
  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 +130 -104
  26. data/lib/microformats/version.rb +1 -1
  27. data/logo.svg +23 -0
  28. data/microformats.gemspec +35 -33
  29. metadata +122 -445
  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/microformats/blank_href.html +0 -23
  66. data/spec/support/lib/microformats/blank_href.js +0 -11
  67. data/spec/support/lib/microformats/implied_property/name-fail.html +0 -60
  68. data/spec/support/lib/microformats/implied_property/name-pass.html +0 -30
  69. data/spec/support/lib/microformats/implied_property/photo-fail.html +0 -60
  70. data/spec/support/lib/microformats/implied_property/photo-pass.html +0 -30
  71. data/spec/support/lib/microformats/implied_property/url-fail.html +0 -18
  72. data/spec/support/lib/microformats/implied_property/url-pass.html +0 -12
  73. data/spec/support/lib/microformats/implied_property/url-relative.html +0 -13
  74. data/spec/support/lib/microformats/implied_property/url-unnormalized.html +0 -12
  75. data/spec/support/lib/microformats/nested-format-with-property-of-same-name.html +0 -13
  76. data/spec/support/lib/microformats/nested-format-with-property-of-same-name.js +0 -16
  77. data/spec/support/lib/microformats/nested-format-with-property.html +0 -12
  78. data/spec/support/lib/microformats/nested-format-with-property.js +0 -16
  79. data/spec/support/lib/microformats/nested-format-without-property.html +0 -13
  80. data/spec/support/lib/microformats/nested-property.html +0 -12
  81. data/spec/support/lib/microformats/nested-property.js +0 -10
  82. data/spec/support/lib/microformats/rels-that-drop-the-base.html +0 -11
  83. data/spec/support/lib/microformats/rels-with-unnormalized-urls.html +0 -11
  84. data/spec/support/lib/microformats/rels.html +0 -12
  85. data/spec/support/lib/microformats/rels.js +0 -13
  86. data/spec/support/lib/microformats/simple.html +0 -23
  87. data/spec/support/lib/microformats/simple.js +0 -11
  88. data/vendor/tests/.gitignore +0 -25
  89. data/vendor/tests/LICENSE.md +0 -36
  90. data/vendor/tests/README.md +0 -48
  91. data/vendor/tests/app.js +0 -84
  92. data/vendor/tests/composer.json +0 -5
  93. data/vendor/tests/css/testsuite.css +0 -159
  94. data/vendor/tests/interface.js +0 -18
  95. data/vendor/tests/package.json +0 -27
  96. data/vendor/tests/tests/microformats-mixed/h-card/change-log.html +0 -63
  97. data/vendor/tests/tests/microformats-mixed/h-card/mixedpropertries.html +0 -14
  98. data/vendor/tests/tests/microformats-mixed/h-card/mixedpropertries.json +0 -22
  99. data/vendor/tests/tests/microformats-mixed/h-card/tworoots.html +0 -1
  100. data/vendor/tests/tests/microformats-mixed/h-card/tworoots.json +0 -10
  101. data/vendor/tests/tests/microformats-mixed/h-entry/mixedroots.html +0 -16
  102. data/vendor/tests/tests/microformats-mixed/h-entry/mixedroots.json +0 -38
  103. data/vendor/tests/tests/microformats-mixed/h-resume/change-log.html +0 -68
  104. data/vendor/tests/tests/microformats-mixed/h-resume/mixedroots.html +0 -16
  105. data/vendor/tests/tests/microformats-mixed/h-resume/mixedroots.json +0 -31
  106. data/vendor/tests/tests/microformats-v1/adr/change-log.html +0 -63
  107. data/vendor/tests/tests/microformats-v1/adr/simpleproperties.html +0 -8
  108. data/vendor/tests/tests/microformats-v1/adr/simpleproperties.json +0 -15
  109. data/vendor/tests/tests/microformats-v1/geo/abbrpattern.html +0 -5
  110. data/vendor/tests/tests/microformats-v1/geo/abbrpattern.json +0 -11
  111. data/vendor/tests/tests/microformats-v1/geo/change-log.1.html +0 -78
  112. data/vendor/tests/tests/microformats-v1/geo/change-log.html +0 -63
  113. data/vendor/tests/tests/microformats-v1/geo/hidden.html +0 -10
  114. data/vendor/tests/tests/microformats-v1/geo/hidden.json +0 -11
  115. data/vendor/tests/tests/microformats-v1/geo/simpleproperties.html +0 -6
  116. data/vendor/tests/tests/microformats-v1/geo/simpleproperties.json +0 -11
  117. data/vendor/tests/tests/microformats-v1/geo/valuetitleclass.html +0 -11
  118. data/vendor/tests/tests/microformats-v1/geo/valuetitleclass.json +0 -11
  119. data/vendor/tests/tests/microformats-v1/hcalendar/ampm.html +0 -41
  120. data/vendor/tests/tests/microformats-v1/hcalendar/ampm.json +0 -21
  121. data/vendor/tests/tests/microformats-v1/hcalendar/attendees.html +0 -13
  122. data/vendor/tests/tests/microformats-v1/hcalendar/attendees.json +0 -37
  123. data/vendor/tests/tests/microformats-v1/hcalendar/change-log.html +0 -68
  124. data/vendor/tests/tests/microformats-v1/hcalendar/combining.html +0 -15
  125. data/vendor/tests/tests/microformats-v1/hcalendar/combining.json +0 -31
  126. data/vendor/tests/tests/microformats-v1/hcalendar/concatenate.html +0 -7
  127. data/vendor/tests/tests/microformats-v1/hcalendar/concatenate.json +0 -12
  128. data/vendor/tests/tests/microformats-v1/hcalendar/time.html +0 -44
  129. data/vendor/tests/tests/microformats-v1/hcalendar/time.json +0 -22
  130. data/vendor/tests/tests/microformats-v1/hcard/change-log.html +0 -68
  131. data/vendor/tests/tests/microformats-v1/hcard/email.html +0 -14
  132. data/vendor/tests/tests/microformats-v1/hcard/email.json +0 -11
  133. data/vendor/tests/tests/microformats-v1/hcard/format.html +0 -6
  134. data/vendor/tests/tests/microformats-v1/hcard/format.json +0 -11
  135. data/vendor/tests/tests/microformats-v1/hcard/hyperlinkedphoto.html +0 -3
  136. data/vendor/tests/tests/microformats-v1/hcard/hyperlinkedphoto.json +0 -8
  137. data/vendor/tests/tests/microformats-v1/hcard/justahyperlink.html +0 -1
  138. data/vendor/tests/tests/microformats-v1/hcard/justahyperlink.json +0 -8
  139. data/vendor/tests/tests/microformats-v1/hcard/justaname.html +0 -1
  140. data/vendor/tests/tests/microformats-v1/hcard/justaname.json +0 -8
  141. data/vendor/tests/tests/microformats-v1/hcard/multiple.html +0 -74
  142. data/vendor/tests/tests/microformats-v1/hcard/multiple.json +0 -65
  143. data/vendor/tests/tests/microformats-v1/hcard/name.html +0 -11
  144. data/vendor/tests/tests/microformats-v1/hcard/name.json +0 -15
  145. data/vendor/tests/tests/microformats-v1/hcard/single.html +0 -14
  146. data/vendor/tests/tests/microformats-v1/hcard/single.json +0 -24
  147. data/vendor/tests/tests/microformats-v1/hentry/change-log.html +0 -73
  148. data/vendor/tests/tests/microformats-v1/hentry/summarycontent.html +0 -20
  149. data/vendor/tests/tests/microformats-v1/hentry/summarycontent.json +0 -24
  150. data/vendor/tests/tests/microformats-v1/hfeed/simple.html +0 -30
  151. data/vendor/tests/tests/microformats-v1/hfeed/simple.json +0 -49
  152. data/vendor/tests/tests/microformats-v1/hnews/all.html +0 -37
  153. data/vendor/tests/tests/microformats-v1/hnews/all.json +0 -74
  154. data/vendor/tests/tests/microformats-v1/hnews/change-log.html +0 -72
  155. data/vendor/tests/tests/microformats-v1/hnews/minimum.html +0 -25
  156. data/vendor/tests/tests/microformats-v1/hnews/minimum.json +0 -48
  157. data/vendor/tests/tests/microformats-v1/hproduct/aggregate.html +0 -26
  158. data/vendor/tests/tests/microformats-v1/hproduct/aggregate.json +0 -52
  159. data/vendor/tests/tests/microformats-v1/hproduct/change-log.html +0 -62
  160. data/vendor/tests/tests/microformats-v1/hproduct/simpleproperties.html +0 -13
  161. data/vendor/tests/tests/microformats-v1/hproduct/simpleproperties.json +0 -33
  162. data/vendor/tests/tests/microformats-v1/hresume/affiliation.html +0 -12
  163. data/vendor/tests/tests/microformats-v1/hresume/affiliation.json +0 -25
  164. data/vendor/tests/tests/microformats-v1/hresume/change-log.html +0 -73
  165. data/vendor/tests/tests/microformats-v1/hresume/contact.html +0 -18
  166. data/vendor/tests/tests/microformats-v1/hresume/contact.json +0 -32
  167. data/vendor/tests/tests/microformats-v1/hresume/education.html +0 -13
  168. data/vendor/tests/tests/microformats-v1/hresume/education.json +0 -29
  169. data/vendor/tests/tests/microformats-v1/hresume/skill.html +0 -12
  170. data/vendor/tests/tests/microformats-v1/hresume/skill.json +0 -33
  171. data/vendor/tests/tests/microformats-v1/hresume/work.html +0 -16
  172. data/vendor/tests/tests/microformats-v1/hresume/work.json +0 -30
  173. data/vendor/tests/tests/microformats-v1/hreview-aggregate/change-log.html +0 -67
  174. data/vendor/tests/tests/microformats-v1/hreview-aggregate/hcard.html +0 -18
  175. data/vendor/tests/tests/microformats-v1/hreview-aggregate/hcard.json +0 -31
  176. data/vendor/tests/tests/microformats-v1/hreview-aggregate/justahyperlink.html +0 -6
  177. data/vendor/tests/tests/microformats-v1/hreview-aggregate/justahyperlink.json +0 -19
  178. data/vendor/tests/tests/microformats-v1/hreview-aggregate/vevent.html +0 -13
  179. data/vendor/tests/tests/microformats-v1/hreview-aggregate/vevent.json +0 -22
  180. data/vendor/tests/tests/microformats-v1/hreview/change-log.html +0 -73
  181. data/vendor/tests/tests/microformats-v1/hreview/item.html +0 -8
  182. data/vendor/tests/tests/microformats-v1/hreview/item.json +0 -19
  183. data/vendor/tests/tests/microformats-v1/hreview/vcard.html +0 -23
  184. data/vendor/tests/tests/microformats-v1/hreview/vcard.json +0 -58
  185. data/vendor/tests/tests/microformats-v1/includes/change-log.html +0 -72
  186. data/vendor/tests/tests/microformats-v1/includes/hcarditemref.html +0 -16
  187. data/vendor/tests/tests/microformats-v1/includes/hcarditemref.json +0 -49
  188. data/vendor/tests/tests/microformats-v1/includes/heventitemref.html +0 -25
  189. data/vendor/tests/tests/microformats-v1/includes/heventitemref.json +0 -33
  190. data/vendor/tests/tests/microformats-v1/includes/hyperlink.html +0 -18
  191. data/vendor/tests/tests/microformats-v1/includes/hyperlink.json +0 -43
  192. data/vendor/tests/tests/microformats-v1/includes/object.html +0 -23
  193. data/vendor/tests/tests/microformats-v1/includes/object.json +0 -42
  194. data/vendor/tests/tests/microformats-v1/includes/table.html +0 -12
  195. data/vendor/tests/tests/microformats-v1/includes/table.json +0 -19
  196. data/vendor/tests/tests/microformats-v2/h-adr/change-log.html +0 -62
  197. data/vendor/tests/tests/microformats-v2/h-adr/geo.html +0 -10
  198. data/vendor/tests/tests/microformats-v2/h-adr/geo.json +0 -16
  199. data/vendor/tests/tests/microformats-v2/h-adr/geourl.html +0 -4
  200. data/vendor/tests/tests/microformats-v2/h-adr/geourl.json +0 -13
  201. data/vendor/tests/tests/microformats-v2/h-adr/justaname.html +0 -1
  202. data/vendor/tests/tests/microformats-v2/h-adr/justaname.json +0 -10
  203. data/vendor/tests/tests/microformats-v2/h-adr/lettercase.html +0 -21
  204. data/vendor/tests/tests/microformats-v2/h-adr/lettercase.json +0 -12
  205. data/vendor/tests/tests/microformats-v2/h-adr/simpleproperties.html +0 -8
  206. data/vendor/tests/tests/microformats-v2/h-adr/simpleproperties.json +0 -16
  207. data/vendor/tests/tests/microformats-v2/h-as-note/note.html +0 -56
  208. data/vendor/tests/tests/microformats-v2/h-as-note/note.json +0 -98
  209. data/vendor/tests/tests/microformats-v2/h-card/baseurl.html +0 -6
  210. data/vendor/tests/tests/microformats-v2/h-card/baseurl.json +0 -26
  211. data/vendor/tests/tests/microformats-v2/h-card/change-log.html +0 -100
  212. data/vendor/tests/tests/microformats-v2/h-card/childimplied.html +0 -7
  213. data/vendor/tests/tests/microformats-v2/h-card/childimplied.json +0 -12
  214. data/vendor/tests/tests/microformats-v2/h-card/extendeddescription.html +0 -10
  215. data/vendor/tests/tests/microformats-v2/h-card/extendeddescription.json +0 -15
  216. data/vendor/tests/tests/microformats-v2/h-card/hcard.html +0 -4
  217. data/vendor/tests/tests/microformats-v2/h-card/hcard.json +0 -19
  218. data/vendor/tests/tests/microformats-v2/h-card/horghcard.html +0 -4
  219. data/vendor/tests/tests/microformats-v2/h-card/horghcard.json +0 -19
  220. data/vendor/tests/tests/microformats-v2/h-card/hyperlinkedphoto.html +0 -3
  221. data/vendor/tests/tests/microformats-v2/h-card/hyperlinkedphoto.json +0 -12
  222. data/vendor/tests/tests/microformats-v2/h-card/impliedname.html +0 -15
  223. data/vendor/tests/tests/microformats-v2/h-card/impliedname.json +0 -90
  224. data/vendor/tests/tests/microformats-v2/h-card/impliedphoto.html +0 -11
  225. data/vendor/tests/tests/microformats-v2/h-card/impliedphoto.json +0 -72
  226. data/vendor/tests/tests/microformats-v2/h-card/impliedurl.html +0 -5
  227. data/vendor/tests/tests/microformats-v2/h-card/impliedurl.json +0 -45
  228. data/vendor/tests/tests/microformats-v2/h-card/justahyperlink.html +0 -1
  229. data/vendor/tests/tests/microformats-v2/h-card/justahyperlink.json +0 -11
  230. data/vendor/tests/tests/microformats-v2/h-card/justaname.html +0 -1
  231. data/vendor/tests/tests/microformats-v2/h-card/justaname.json +0 -10
  232. data/vendor/tests/tests/microformats-v2/h-card/nested.html +0 -4
  233. data/vendor/tests/tests/microformats-v2/h-card/nested.json +0 -18
  234. data/vendor/tests/tests/microformats-v2/h-card/p-property.html +0 -21
  235. data/vendor/tests/tests/microformats-v2/h-card/p-property.json +0 -15
  236. data/vendor/tests/tests/microformats-v2/h-card/relativeurls.html +0 -6
  237. data/vendor/tests/tests/microformats-v2/h-card/relativeurls.json +0 -29
  238. data/vendor/tests/tests/microformats-v2/h-entry/change-log.html +0 -90
  239. data/vendor/tests/tests/microformats-v2/h-entry/encoding.html +0 -3
  240. data/vendor/tests/tests/microformats-v2/h-entry/encoding.json +0 -14
  241. data/vendor/tests/tests/microformats-v2/h-entry/impliedvalue-nested.html +0 -9
  242. data/vendor/tests/tests/microformats-v2/h-entry/impliedvalue-nested.json +0 -27
  243. data/vendor/tests/tests/microformats-v2/h-entry/justahyperlink.html +0 -1
  244. data/vendor/tests/tests/microformats-v2/h-entry/justahyperlink.json +0 -11
  245. data/vendor/tests/tests/microformats-v2/h-entry/justaname.html +0 -1
  246. data/vendor/tests/tests/microformats-v2/h-entry/justaname.json +0 -10
  247. data/vendor/tests/tests/microformats-v2/h-entry/scriptstyletags.html +0 -4
  248. data/vendor/tests/tests/microformats-v2/h-entry/scriptstyletags.json +0 -14
  249. data/vendor/tests/tests/microformats-v2/h-entry/summarycontent.html +0 -20
  250. data/vendor/tests/tests/microformats-v2/h-entry/summarycontent.json +0 -25
  251. data/vendor/tests/tests/microformats-v2/h-entry/u-property.html +0 -33
  252. data/vendor/tests/tests/microformats-v2/h-entry/u-property.json +0 -12
  253. data/vendor/tests/tests/microformats-v2/h-entry/urlincontent.html +0 -13
  254. data/vendor/tests/tests/microformats-v2/h-entry/urlincontent.json +0 -14
  255. data/vendor/tests/tests/microformats-v2/h-event/ampm.html +0 -41
  256. data/vendor/tests/tests/microformats-v2/h-event/ampm.json +0 -21
  257. data/vendor/tests/tests/microformats-v2/h-event/attendees.html +0 -13
  258. data/vendor/tests/tests/microformats-v2/h-event/attendees.json +0 -37
  259. data/vendor/tests/tests/microformats-v2/h-event/change-log.html +0 -82
  260. data/vendor/tests/tests/microformats-v2/h-event/combining.html +0 -13
  261. data/vendor/tests/tests/microformats-v2/h-event/combining.json +0 -25
  262. data/vendor/tests/tests/microformats-v2/h-event/concatenate.html +0 -8
  263. data/vendor/tests/tests/microformats-v2/h-event/concatenate.json +0 -12
  264. data/vendor/tests/tests/microformats-v2/h-event/dates.html +0 -13
  265. data/vendor/tests/tests/microformats-v2/h-event/dates.json +0 -26
  266. data/vendor/tests/tests/microformats-v2/h-event/dt-property.html +0 -23
  267. data/vendor/tests/tests/microformats-v2/h-event/dt-property.json +0 -20
  268. data/vendor/tests/tests/microformats-v2/h-event/justahyperlink.html +0 -1
  269. data/vendor/tests/tests/microformats-v2/h-event/justahyperlink.json +0 -11
  270. data/vendor/tests/tests/microformats-v2/h-event/justaname.html +0 -1
  271. data/vendor/tests/tests/microformats-v2/h-event/justaname.json +0 -10
  272. data/vendor/tests/tests/microformats-v2/h-event/time.html +0 -47
  273. data/vendor/tests/tests/microformats-v2/h-event/time.json +0 -25
  274. data/vendor/tests/tests/microformats-v2/h-feed/implied-title.html +0 -30
  275. data/vendor/tests/tests/microformats-v2/h-feed/implied-title.json +0 -23
  276. data/vendor/tests/tests/microformats-v2/h-feed/simple.html +0 -26
  277. data/vendor/tests/tests/microformats-v2/h-feed/simple.json +0 -33
  278. data/vendor/tests/tests/microformats-v2/h-geo/abbrpattern.html +0 -5
  279. data/vendor/tests/tests/microformats-v2/h-geo/abbrpattern.json +0 -12
  280. data/vendor/tests/tests/microformats-v2/h-geo/altitude.html +0 -8
  281. data/vendor/tests/tests/microformats-v2/h-geo/altitude.json +0 -13
  282. data/vendor/tests/tests/microformats-v2/h-geo/change-log.html +0 -67
  283. data/vendor/tests/tests/microformats-v2/h-geo/hidden.html +0 -10
  284. data/vendor/tests/tests/microformats-v2/h-geo/hidden.json +0 -12
  285. data/vendor/tests/tests/microformats-v2/h-geo/justaname.html +0 -3
  286. data/vendor/tests/tests/microformats-v2/h-geo/justaname.json +0 -10
  287. data/vendor/tests/tests/microformats-v2/h-geo/simpleproperties.html +0 -5
  288. data/vendor/tests/tests/microformats-v2/h-geo/simpleproperties.json +0 -12
  289. data/vendor/tests/tests/microformats-v2/h-geo/valuetitleclass.html +0 -11
  290. data/vendor/tests/tests/microformats-v2/h-geo/valuetitleclass.json +0 -12
  291. data/vendor/tests/tests/microformats-v2/h-news/all.html +0 -35
  292. data/vendor/tests/tests/microformats-v2/h-news/all.json +0 -51
  293. data/vendor/tests/tests/microformats-v2/h-news/change-log.html +0 -78
  294. data/vendor/tests/tests/microformats-v2/h-news/minimum.html +0 -24
  295. data/vendor/tests/tests/microformats-v2/h-news/minimum.json +0 -40
  296. data/vendor/tests/tests/microformats-v2/h-org/change-log.html +0 -57
  297. data/vendor/tests/tests/microformats-v2/h-org/hyperlink.html +0 -1
  298. data/vendor/tests/tests/microformats-v2/h-org/hyperlink.json +0 -11
  299. data/vendor/tests/tests/microformats-v2/h-org/simple.html +0 -1
  300. data/vendor/tests/tests/microformats-v2/h-org/simple.json +0 -10
  301. data/vendor/tests/tests/microformats-v2/h-org/simpleproperties.html +0 -4
  302. data/vendor/tests/tests/microformats-v2/h-org/simpleproperties.json +0 -12
  303. data/vendor/tests/tests/microformats-v2/h-product/aggregate.html +0 -21
  304. data/vendor/tests/tests/microformats-v2/h-product/aggregate.json +0 -45
  305. data/vendor/tests/tests/microformats-v2/h-product/change-log.html +0 -62
  306. data/vendor/tests/tests/microformats-v2/h-product/justahyperlink.html +0 -1
  307. data/vendor/tests/tests/microformats-v2/h-product/justahyperlink.json +0 -11
  308. data/vendor/tests/tests/microformats-v2/h-product/justaname.html +0 -1
  309. data/vendor/tests/tests/microformats-v2/h-product/justaname.json +0 -10
  310. data/vendor/tests/tests/microformats-v2/h-product/simpleproperties.html +0 -10
  311. data/vendor/tests/tests/microformats-v2/h-product/simpleproperties.json +0 -26
  312. data/vendor/tests/tests/microformats-v2/h-recipe/all.html +0 -63
  313. data/vendor/tests/tests/microformats-v2/h-recipe/all.json +0 -54
  314. data/vendor/tests/tests/microformats-v2/h-recipe/change-log.html +0 -62
  315. data/vendor/tests/tests/microformats-v2/h-recipe/minimum.html +0 -7
  316. data/vendor/tests/tests/microformats-v2/h-recipe/minimum.json +0 -17
  317. data/vendor/tests/tests/microformats-v2/h-resume/affiliation.html +0 -12
  318. data/vendor/tests/tests/microformats-v2/h-resume/affiliation.json +0 -20
  319. data/vendor/tests/tests/microformats-v2/h-resume/change-log.html +0 -78
  320. data/vendor/tests/tests/microformats-v2/h-resume/contact.html +0 -17
  321. data/vendor/tests/tests/microformats-v2/h-resume/contact.json +0 -26
  322. data/vendor/tests/tests/microformats-v2/h-resume/education.html +0 -13
  323. data/vendor/tests/tests/microformats-v2/h-resume/education.json +0 -30
  324. data/vendor/tests/tests/microformats-v2/h-resume/justaname.html +0 -1
  325. data/vendor/tests/tests/microformats-v2/h-resume/justaname.json +0 -10
  326. data/vendor/tests/tests/microformats-v2/h-resume/skill.html +0 -12
  327. data/vendor/tests/tests/microformats-v2/h-resume/skill.json +0 -12
  328. data/vendor/tests/tests/microformats-v2/h-resume/work.html +0 -16
  329. data/vendor/tests/tests/microformats-v2/h-resume/work.json +0 -31
  330. data/vendor/tests/tests/microformats-v2/h-review-aggregate/change-log.html +0 -78
  331. data/vendor/tests/tests/microformats-v2/h-review-aggregate/hevent.html +0 -13
  332. data/vendor/tests/tests/microformats-v2/h-review-aggregate/hevent.json +0 -23
  333. data/vendor/tests/tests/microformats-v2/h-review-aggregate/justahyperlink.html +0 -8
  334. data/vendor/tests/tests/microformats-v2/h-review-aggregate/justahyperlink.json +0 -19
  335. data/vendor/tests/tests/microformats-v2/h-review-aggregate/simpleproperties.html +0 -18
  336. data/vendor/tests/tests/microformats-v2/h-review-aggregate/simpleproperties.json +0 -26
  337. data/vendor/tests/tests/microformats-v2/h-review/change-log.html +0 -84
  338. data/vendor/tests/tests/microformats-v2/h-review/hyperlink.html +0 -1
  339. data/vendor/tests/tests/microformats-v2/h-review/hyperlink.json +0 -11
  340. data/vendor/tests/tests/microformats-v2/h-review/implieditem.html +0 -4
  341. data/vendor/tests/tests/microformats-v2/h-review/implieditem.json +0 -19
  342. data/vendor/tests/tests/microformats-v2/h-review/item.html +0 -8
  343. data/vendor/tests/tests/microformats-v2/h-review/item.json +0 -20
  344. data/vendor/tests/tests/microformats-v2/h-review/justaname.html +0 -1
  345. data/vendor/tests/tests/microformats-v2/h-review/justaname.json +0 -10
  346. data/vendor/tests/tests/microformats-v2/h-review/photo.html +0 -1
  347. data/vendor/tests/tests/microformats-v2/h-review/photo.json +0 -11
  348. data/vendor/tests/tests/microformats-v2/h-review/vcard.html +0 -23
  349. data/vendor/tests/tests/microformats-v2/h-review/vcard.json +0 -48
  350. data/vendor/tests/tests/microformats-v2/rel/change-log.html +0 -67
  351. data/vendor/tests/tests/microformats-v2/rel/duplicate-rels.html +0 -10
  352. data/vendor/tests/tests/microformats-v2/rel/duplicate-rels.json +0 -75
  353. data/vendor/tests/tests/microformats-v2/rel/license.html +0 -1
  354. data/vendor/tests/tests/microformats-v2/rel/license.json +0 -12
  355. data/vendor/tests/tests/microformats-v2/rel/nofollow.html +0 -1
  356. data/vendor/tests/tests/microformats-v2/rel/nofollow.json +0 -12
  357. data/vendor/tests/tests/microformats-v2/rel/rel-urls.html +0 -8
  358. data/vendor/tests/tests/microformats-v2/rel/rel-urls.json +0 -33
  359. data/vendor/tests/tests/microformats-v2/rel/varying-text-duplicate-rels.html +0 -4
  360. data/vendor/tests/tests/microformats-v2/rel/varying-text-duplicate-rels.json +0 -20
  361. data/vendor/tests/tests/microformats-v2/rel/xfn-all.html +0 -19
  362. data/vendor/tests/tests/microformats-v2/rel/xfn-all.json +0 -92
  363. data/vendor/tests/tests/microformats-v2/rel/xfn-elsewhere.html +0 -10
  364. 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