relaton 2.2.0.pre.alpha.1 → 3.0.0.pre.alpha.2

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 (702) hide show
  1. checksums.yaml +4 -4
  2. data/{docs/README.adoc → README.adoc} +165 -38
  3. data/bin/console +0 -1
  4. data/lib/relaton/3gpp/bibdata.rb +9 -0
  5. data/lib/relaton/3gpp/bibitem.rb +9 -0
  6. data/lib/relaton/3gpp/bibliography.rb +123 -0
  7. data/lib/relaton/3gpp/data_fetcher.rb +303 -0
  8. data/lib/relaton/3gpp/docidentifier.rb +114 -0
  9. data/lib/relaton/3gpp/doctype.rb +9 -0
  10. data/lib/relaton/3gpp/ext.rb +31 -0
  11. data/lib/relaton/3gpp/item.rb +18 -0
  12. data/lib/relaton/3gpp/item_data.rb +15 -0
  13. data/lib/relaton/3gpp/parser.rb +400 -0
  14. data/lib/relaton/3gpp/processor.rb +71 -0
  15. data/lib/relaton/3gpp/release.rb +34 -0
  16. data/lib/relaton/3gpp/util.rb +8 -0
  17. data/lib/relaton/3gpp.rb +29 -0
  18. data/lib/relaton/adobe/bibdata.rb +8 -0
  19. data/lib/relaton/adobe/bibitem.rb +8 -0
  20. data/lib/relaton/adobe/bibliography.rb +92 -0
  21. data/lib/relaton/adobe/docidentifier.rb +49 -0
  22. data/lib/relaton/adobe/doctype.rb +14 -0
  23. data/lib/relaton/adobe/ext.rb +32 -0
  24. data/lib/relaton/adobe/item.rb +15 -0
  25. data/lib/relaton/adobe/item_base.rb +18 -0
  26. data/lib/relaton/adobe/item_data.rb +6 -0
  27. data/lib/relaton/adobe/processor.rb +45 -0
  28. data/lib/relaton/adobe/util.rb +8 -0
  29. data/lib/relaton/adobe.rb +37 -0
  30. data/lib/relaton/bib/converter/asciibib/to_asciibib.rb +663 -0
  31. data/lib/relaton/bib/converter/asciibib.rb +13 -0
  32. data/lib/relaton/bib/converter/bibtex/from_bibtex.rb +245 -0
  33. data/lib/relaton/bib/converter/bibtex/to_bibtex.rb +341 -0
  34. data/lib/relaton/bib/converter/bibtex.rb +23 -0
  35. data/lib/relaton/bib/converter/bibxml/from_rfcxml.rb +386 -0
  36. data/lib/relaton/bib/converter/bibxml/from_rfcxml_referencegroup.rb +71 -0
  37. data/lib/relaton/bib/converter/bibxml/to_rfcxml.rb +308 -0
  38. data/lib/relaton/bib/converter/bibxml/to_rfcxml_referencegroup.rb +52 -0
  39. data/lib/relaton/bib/converter/bibxml.rb +51 -0
  40. data/lib/relaton/bib/hash_parser_v1.rb +767 -0
  41. data/lib/relaton/bib/item_data.rb +229 -0
  42. data/lib/relaton/bib/model/abstract.rb +16 -0
  43. data/lib/relaton/bib/model/address.rb +22 -0
  44. data/lib/relaton/bib/model/affiliation.rb +16 -0
  45. data/lib/relaton/bib/model/bibdata.rb +11 -0
  46. data/lib/relaton/bib/model/bibdata_shared.rb +12 -0
  47. data/lib/relaton/bib/model/bibitem.rb +11 -0
  48. data/lib/relaton/bib/model/bibitem_shared.rb +12 -0
  49. data/lib/relaton/bib/model/contact.rb +18 -0
  50. data/lib/relaton/bib/model/contribution_info.rb +15 -0
  51. data/lib/relaton/bib/model/contributor.rb +29 -0
  52. data/lib/relaton/bib/model/copyright.rb +27 -0
  53. data/lib/relaton/bib/model/date.rb +31 -0
  54. data/lib/relaton/bib/model/depiction.rb +16 -0
  55. data/lib/relaton/bib/model/docidentifier.rb +49 -0
  56. data/lib/relaton/bib/model/doctype.rb +14 -0
  57. data/lib/relaton/bib/model/edition.rb +14 -0
  58. data/lib/relaton/bib/model/ext.rb +39 -0
  59. data/lib/relaton/bib/model/extent.rb +16 -0
  60. data/lib/relaton/bib/model/formattedref.rb +43 -0
  61. data/lib/relaton/bib/model/full_name_type.rb +64 -0
  62. data/lib/relaton/bib/model/fullname.rb +11 -0
  63. data/lib/relaton/bib/model/ics.rb +49 -0
  64. data/lib/relaton/bib/model/image.rb +28 -0
  65. data/lib/relaton/bib/model/item.rb +96 -0
  66. data/lib/relaton/bib/model/item_base.rb +20 -0
  67. data/lib/relaton/bib/model/item_shared.rb +88 -0
  68. data/lib/relaton/bib/model/keyword.rb +30 -0
  69. data/lib/relaton/bib/model/locality.rb +18 -0
  70. data/lib/relaton/bib/model/locality_stack.rb +14 -0
  71. data/lib/relaton/bib/model/localized_string.rb +48 -0
  72. data/lib/relaton/bib/model/localized_string_attrs.rb +24 -0
  73. data/lib/relaton/bib/model/logo.rb +14 -0
  74. data/lib/relaton/bib/model/medium.rb +22 -0
  75. data/lib/relaton/bib/model/note.rb +16 -0
  76. data/lib/relaton/bib/model/organization.rb +13 -0
  77. data/lib/relaton/bib/model/organization_type.rb +42 -0
  78. data/lib/relaton/bib/model/person.rb +36 -0
  79. data/lib/relaton/bib/model/phone.rb +14 -0
  80. data/lib/relaton/bib/model/place.rb +33 -0
  81. data/lib/relaton/bib/model/price.rb +14 -0
  82. data/lib/relaton/bib/model/relation.rb +43 -0
  83. data/lib/relaton/bib/model/series.rb +34 -0
  84. data/lib/relaton/bib/model/size.rb +23 -0
  85. data/lib/relaton/bib/model/source_locality_stack.rb +14 -0
  86. data/lib/relaton/bib/model/status.rb +27 -0
  87. data/lib/relaton/bib/model/structured_identifier.rb +49 -0
  88. data/lib/relaton/bib/model/subdivision.rb +16 -0
  89. data/lib/relaton/bib/model/title.rb +56 -0
  90. data/lib/relaton/bib/model/type/plain_date.rb +16 -0
  91. data/lib/relaton/bib/model/type/string_date.rb +48 -0
  92. data/lib/relaton/bib/model/uri.rb +18 -0
  93. data/lib/relaton/bib/model/validity.rb +16 -0
  94. data/lib/relaton/bib/model/version.rb +43 -0
  95. data/lib/relaton/bib/namespace_helper.rb +21 -0
  96. data/lib/relaton/bib/sanitizer.rb +264 -0
  97. data/lib/relaton/bib/util.rb +18 -0
  98. data/lib/relaton/bib/versions.json +35 -0
  99. data/lib/relaton/bib.rb +46 -0
  100. data/lib/relaton/bipm/bibliography.rb +231 -0
  101. data/lib/relaton/bipm/converter/asciibib.rb +64 -0
  102. data/lib/relaton/bipm/data_fetcher.rb +81 -0
  103. data/lib/relaton/bipm/data_outcomes_parser.rb +656 -0
  104. data/lib/relaton/bipm/id_parser.rb +278 -0
  105. data/lib/relaton/bipm/item_data.rb +47 -0
  106. data/lib/relaton/bipm/model/bibdata.rb +9 -0
  107. data/lib/relaton/bipm/model/bibitem.rb +9 -0
  108. data/lib/relaton/bipm/model/comment_period.rb +13 -0
  109. data/lib/relaton/bipm/model/doctype.rb +12 -0
  110. data/lib/relaton/bipm/model/ext.rb +38 -0
  111. data/lib/relaton/bipm/model/item.rb +11 -0
  112. data/lib/relaton/bipm/model/structured_identifier.rb +36 -0
  113. data/lib/relaton/bipm/processor.rb +69 -0
  114. data/lib/relaton/bipm/rawdata_bipm_metrologia/affiliations.rb +111 -0
  115. data/lib/relaton/bipm/rawdata_bipm_metrologia/fetcher.rb +172 -0
  116. data/lib/relaton/bipm/rawdata_bipm_metrologia/niso_jats_parser.rb +353 -0
  117. data/lib/relaton/bipm/si_brochure_parser.rb +188 -0
  118. data/lib/relaton/bipm/util.rb +8 -0
  119. data/lib/relaton/bipm.rb +38 -0
  120. data/lib/relaton/bsi/bibliography.rb +196 -0
  121. data/lib/relaton/bsi/hit.rb +28 -0
  122. data/lib/relaton/bsi/hit_collection.rb +113 -0
  123. data/lib/relaton/bsi/item_data.rb +13 -0
  124. data/lib/relaton/bsi/model/bibdata.rb +8 -0
  125. data/lib/relaton/bsi/model/bibitem.rb +8 -0
  126. data/lib/relaton/bsi/model/docidentifier.rb +107 -0
  127. data/lib/relaton/bsi/model/doctype.rb +14 -0
  128. data/lib/relaton/bsi/model/ext.rb +17 -0
  129. data/lib/relaton/bsi/model/item.rb +17 -0
  130. data/lib/relaton/bsi/model/item_base.rb +22 -0
  131. data/lib/relaton/bsi/model/relation.rb +9 -0
  132. data/lib/relaton/bsi/processor.rb +43 -0
  133. data/lib/relaton/bsi/schema.json +24882 -0
  134. data/lib/relaton/bsi/scraper.rb +288 -0
  135. data/lib/relaton/bsi/util.rb +8 -0
  136. data/lib/relaton/bsi.rb +25 -0
  137. data/lib/relaton/calconnect/bibliography.rb +93 -0
  138. data/lib/relaton/calconnect/data_fetcher.rb +174 -0
  139. data/lib/relaton/calconnect/docidentifier.rb +80 -0
  140. data/lib/relaton/calconnect/hit.rb +14 -0
  141. data/lib/relaton/calconnect/hit_collection.rb +92 -0
  142. data/lib/relaton/calconnect/item_data.rb +12 -0
  143. data/lib/relaton/calconnect/model/bibdata.rb +8 -0
  144. data/lib/relaton/calconnect/model/bibitem.rb +8 -0
  145. data/lib/relaton/calconnect/model/doctype.rb +11 -0
  146. data/lib/relaton/calconnect/model/ext.rb +11 -0
  147. data/lib/relaton/calconnect/model/item.rb +20 -0
  148. data/lib/relaton/calconnect/processor.rb +72 -0
  149. data/lib/relaton/calconnect/scraper.rb +87 -0
  150. data/lib/relaton/calconnect/util.rb +8 -0
  151. data/lib/relaton/calconnect.rb +36 -0
  152. data/lib/relaton/ccsds/bibliography.rb +63 -0
  153. data/lib/relaton/ccsds/data/fetcher.rb +252 -0
  154. data/lib/relaton/ccsds/data/iso_references.rb +30 -0
  155. data/lib/relaton/ccsds/data/parser.rb +194 -0
  156. data/lib/relaton/ccsds/hit.rb +24 -0
  157. data/lib/relaton/ccsds/hit_collection.rb +47 -0
  158. data/lib/relaton/ccsds/item_data.rb +9 -0
  159. data/lib/relaton/ccsds/model/bibdata.rb +8 -0
  160. data/lib/relaton/ccsds/model/bibitem.rb +8 -0
  161. data/lib/relaton/ccsds/model/docidentifier.rb +121 -0
  162. data/lib/relaton/ccsds/model/doctype.rb +9 -0
  163. data/lib/relaton/ccsds/model/ext.rb +19 -0
  164. data/lib/relaton/ccsds/model/item.rb +15 -0
  165. data/lib/relaton/ccsds/processor.rb +68 -0
  166. data/lib/relaton/ccsds/util.rb +10 -0
  167. data/lib/relaton/ccsds.rb +33 -0
  168. data/lib/relaton/cen/bibliography.rb +149 -0
  169. data/lib/relaton/cen/committees.yaml +66 -0
  170. data/lib/relaton/cen/hit.rb +31 -0
  171. data/lib/relaton/cen/hit_collection.rb +116 -0
  172. data/lib/relaton/cen/item_data.rb +7 -0
  173. data/lib/relaton/cen/model/bibdata.rb +8 -0
  174. data/lib/relaton/cen/model/bibitem.rb +8 -0
  175. data/lib/relaton/cen/model/docidentifier.rb +100 -0
  176. data/lib/relaton/cen/model/ext.rb +11 -0
  177. data/lib/relaton/cen/model/item.rb +14 -0
  178. data/lib/relaton/cen/model/structured_identifier.rb +9 -0
  179. data/lib/relaton/cen/processor.rb +45 -0
  180. data/lib/relaton/cen/scraper.rb +218 -0
  181. data/lib/relaton/cen/util.rb +8 -0
  182. data/lib/relaton/cen.rb +30 -0
  183. data/lib/relaton/cie/bibdata.rb +8 -0
  184. data/lib/relaton/cie/bibitem.rb +8 -0
  185. data/lib/relaton/cie/bibliography.rb +31 -0
  186. data/lib/relaton/cie/data_fetcher.rb +540 -0
  187. data/lib/relaton/cie/ext.rb +7 -0
  188. data/lib/relaton/cie/item.rb +11 -0
  189. data/lib/relaton/cie/item_data.rb +6 -0
  190. data/lib/relaton/cie/processor.rb +68 -0
  191. data/lib/relaton/cie/scrapper.rb +52 -0
  192. data/lib/relaton/cie/util.rb +8 -0
  193. data/lib/relaton/cie.rb +29 -0
  194. data/lib/relaton/core/array_wrapper.rb +20 -0
  195. data/lib/relaton/core/data_fetcher.rb +244 -0
  196. data/lib/relaton/core/date_parser.rb +42 -0
  197. data/lib/relaton/core/governor.rb +320 -0
  198. data/lib/relaton/core/hash_keys_sybolizer.rb +19 -0
  199. data/lib/relaton/core/hit.rb +49 -0
  200. data/lib/relaton/core/hit_collection.rb +118 -0
  201. data/lib/relaton/core/pacer.rb +134 -0
  202. data/lib/relaton/core/processor.rb +67 -0
  203. data/lib/relaton/core/request_error.rb +14 -0
  204. data/lib/relaton/core/workers_pool.rb +45 -0
  205. data/lib/relaton/core.rb +12 -0
  206. data/lib/relaton/db/registry.rb +44 -4
  207. data/lib/relaton/db.rb +0 -1
  208. data/lib/relaton/doi/crossref.rb +89 -0
  209. data/lib/relaton/doi/parser.rb +921 -0
  210. data/lib/relaton/doi/processor.rb +65 -0
  211. data/lib/relaton/doi/util.rb +8 -0
  212. data/lib/relaton/doi.rb +20 -0
  213. data/lib/relaton/easc/bibdata.rb +8 -0
  214. data/lib/relaton/easc/bibitem.rb +8 -0
  215. data/lib/relaton/easc/bibliography.rb +95 -0
  216. data/lib/relaton/easc/docidentifier.rb +100 -0
  217. data/lib/relaton/easc/doctype.rb +14 -0
  218. data/lib/relaton/easc/ext.rb +44 -0
  219. data/lib/relaton/easc/item.rb +13 -0
  220. data/lib/relaton/easc/item_base.rb +18 -0
  221. data/lib/relaton/easc/item_data.rb +6 -0
  222. data/lib/relaton/easc/processor.rb +46 -0
  223. data/lib/relaton/easc/util.rb +8 -0
  224. data/lib/relaton/easc.rb +35 -0
  225. data/lib/relaton/ecma/bibdata.rb +8 -0
  226. data/lib/relaton/ecma/bibitem.rb +8 -0
  227. data/lib/relaton/ecma/bibliography.rb +149 -0
  228. data/lib/relaton/ecma/data_fetcher.rb +162 -0
  229. data/lib/relaton/ecma/data_parser.rb +49 -0
  230. data/lib/relaton/ecma/docidentifier.rb +124 -0
  231. data/lib/relaton/ecma/edition_parser.rb +80 -0
  232. data/lib/relaton/ecma/ext.rb +7 -0
  233. data/lib/relaton/ecma/item.rb +13 -0
  234. data/lib/relaton/ecma/item_data.rb +6 -0
  235. data/lib/relaton/ecma/memento_parser.rb +60 -0
  236. data/lib/relaton/ecma/page_fetcher.rb +39 -0
  237. data/lib/relaton/ecma/parser_common.rb +33 -0
  238. data/lib/relaton/ecma/processor.rb +69 -0
  239. data/lib/relaton/ecma/standard_parser.rb +134 -0
  240. data/lib/relaton/ecma/util.rb +8 -0
  241. data/lib/relaton/ecma.rb +33 -0
  242. data/lib/relaton/etsi/bibdata.rb +10 -0
  243. data/lib/relaton/etsi/bibitem.rb +10 -0
  244. data/lib/relaton/etsi/bibliography.rb +111 -0
  245. data/lib/relaton/etsi/data_fetcher.rb +167 -0
  246. data/lib/relaton/etsi/data_parser.rb +208 -0
  247. data/lib/relaton/etsi/doctype.rb +30 -0
  248. data/lib/relaton/etsi/ext.rb +31 -0
  249. data/lib/relaton/etsi/item.rb +15 -0
  250. data/lib/relaton/etsi/item_data.rb +6 -0
  251. data/lib/relaton/etsi/processor.rb +71 -0
  252. data/lib/relaton/etsi/pubid.rb +37 -0
  253. data/lib/relaton/etsi/status.rb +13 -0
  254. data/lib/relaton/etsi/util.rb +8 -0
  255. data/lib/relaton/etsi.rb +26 -0
  256. data/lib/relaton/gb/bibdata.rb +8 -0
  257. data/lib/relaton/gb/bibitem.rb +8 -0
  258. data/lib/relaton/gb/bibliography.rb +171 -0
  259. data/lib/relaton/gb/ccs.rb +14 -0
  260. data/lib/relaton/gb/committee.rb +13 -0
  261. data/lib/relaton/gb/docidentifier.rb +72 -0
  262. data/lib/relaton/gb/doctype.rb +9 -0
  263. data/lib/relaton/gb/ext.rb +36 -0
  264. data/lib/relaton/gb/gb_scraper.rb +61 -0
  265. data/lib/relaton/gb/gb_type.rb +20 -0
  266. data/lib/relaton/gb/hit.rb +48 -0
  267. data/lib/relaton/gb/hit_collection.rb +19 -0
  268. data/lib/relaton/gb/item.rb +13 -0
  269. data/lib/relaton/gb/item_data.rb +6 -0
  270. data/lib/relaton/gb/processor.rb +49 -0
  271. data/lib/relaton/gb/project_number.rb +38 -0
  272. data/lib/relaton/gb/scraper.rb +221 -0
  273. data/lib/relaton/gb/sec_scraper.rb +92 -0
  274. data/lib/relaton/gb/stage_name.rb +13 -0
  275. data/lib/relaton/gb/structured_identifier.rb +26 -0
  276. data/lib/relaton/gb/t_scraper.rb +126 -0
  277. data/lib/relaton/gb/util.rb +8 -0
  278. data/lib/relaton/gb/yaml/prefixes.yaml +200 -0
  279. data/lib/relaton/gb.rb +33 -0
  280. data/lib/relaton/gost/bibdata.rb +8 -0
  281. data/lib/relaton/gost/bibitem.rb +8 -0
  282. data/lib/relaton/gost/bibliography.rb +107 -0
  283. data/lib/relaton/gost/docidentifier.rb +80 -0
  284. data/lib/relaton/gost/doctype.rb +16 -0
  285. data/lib/relaton/gost/ext.rb +46 -0
  286. data/lib/relaton/gost/item.rb +15 -0
  287. data/lib/relaton/gost/item_base.rb +18 -0
  288. data/lib/relaton/gost/item_data.rb +6 -0
  289. data/lib/relaton/gost/processor.rb +49 -0
  290. data/lib/relaton/gost/util.rb +8 -0
  291. data/lib/relaton/gost.rb +36 -0
  292. data/lib/relaton/iala/bibdata.rb +8 -0
  293. data/lib/relaton/iala/bibitem.rb +8 -0
  294. data/lib/relaton/iala/bibliography.rb +146 -0
  295. data/lib/relaton/iala/docidentifier.rb +89 -0
  296. data/lib/relaton/iala/doctype.rb +18 -0
  297. data/lib/relaton/iala/ext.rb +32 -0
  298. data/lib/relaton/iala/item.rb +21 -0
  299. data/lib/relaton/iala/item_base.rb +18 -0
  300. data/lib/relaton/iala/item_data.rb +6 -0
  301. data/lib/relaton/iala/processor.rb +43 -0
  302. data/lib/relaton/iala/relation.rb +7 -0
  303. data/lib/relaton/iala/util.rb +8 -0
  304. data/lib/relaton/iala.rb +35 -0
  305. data/lib/relaton/iana/bibdata.rb +8 -0
  306. data/lib/relaton/iana/bibitem.rb +8 -0
  307. data/lib/relaton/iana/bibliography.rb +100 -0
  308. data/lib/relaton/iana/data_fetcher.rb +101 -0
  309. data/lib/relaton/iana/item.rb +7 -0
  310. data/lib/relaton/iana/item_data.rb +6 -0
  311. data/lib/relaton/iana/parser.rb +146 -0
  312. data/lib/relaton/iana/processor.rb +70 -0
  313. data/lib/relaton/iana/util.rb +8 -0
  314. data/lib/relaton/iana.rb +40 -0
  315. data/lib/relaton/iec/bibliography.rb +283 -0
  316. data/lib/relaton/iec/data_fetcher.rb +222 -0
  317. data/lib/relaton/iec/data_parser.rb +391 -0
  318. data/lib/relaton/iec/hit.rb +26 -0
  319. data/lib/relaton/iec/hit_collection.rb +138 -0
  320. data/lib/relaton/iec/item_data.rb +7 -0
  321. data/lib/relaton/iec/model/bibdata.rb +8 -0
  322. data/lib/relaton/iec/model/bibitem.rb +8 -0
  323. data/lib/relaton/iec/model/docidentifier.rb +135 -0
  324. data/lib/relaton/iec/model/doctype.rb +12 -0
  325. data/lib/relaton/iec/model/ext.rb +53 -0
  326. data/lib/relaton/iec/model/item.rb +20 -0
  327. data/lib/relaton/iec/model/item_base.rb +12 -0
  328. data/lib/relaton/iec/model/relation.rb +7 -0
  329. data/lib/relaton/iec/model/stage_name.rb +13 -0
  330. data/lib/relaton/iec/processor.rb +74 -0
  331. data/lib/relaton/iec/statuses.yml +199 -0
  332. data/lib/relaton/iec/util.rb +8 -0
  333. data/lib/relaton/iec.rb +98 -0
  334. data/lib/relaton/ieee/balloting_group.rb +13 -0
  335. data/lib/relaton/ieee/bibdata.rb +8 -0
  336. data/lib/relaton/ieee/bibitem.rb +8 -0
  337. data/lib/relaton/ieee/bibliography.rb +73 -0
  338. data/lib/relaton/ieee/converter/bibxml/from_rfcxml.rb +10 -0
  339. data/lib/relaton/ieee/converter/bibxml/from_rfcxml_referencegroup.rb +10 -0
  340. data/lib/relaton/ieee/converter/bibxml.rb +20 -0
  341. data/lib/relaton/ieee/data_fetcher.rb +771 -0
  342. data/lib/relaton/ieee/doctype.rb +9 -0
  343. data/lib/relaton/ieee/editorial_group.rb +19 -0
  344. data/lib/relaton/ieee/ext.rb +36 -0
  345. data/lib/relaton/ieee/idams_parser.rb +330 -0
  346. data/lib/relaton/ieee/item.rb +11 -0
  347. data/lib/relaton/ieee/item_data.rb +7 -0
  348. data/lib/relaton/ieee/processor.rb +71 -0
  349. data/lib/relaton/ieee/rawbib_id_parser.rb +753 -0
  350. data/lib/relaton/ieee/util.rb +8 -0
  351. data/lib/relaton/ieee.rb +30 -0
  352. data/lib/relaton/ietf/bibdata.rb +8 -0
  353. data/lib/relaton/ietf/bibitem.rb +8 -0
  354. data/lib/relaton/ietf/bibliography.rb +35 -0
  355. data/lib/relaton/ietf/bibxml_parser.rb +232 -0
  356. data/lib/relaton/ietf/data_fetcher.rb +561 -0
  357. data/lib/relaton/ietf/doctype.rb +9 -0
  358. data/lib/relaton/ietf/ext.rb +63 -0
  359. data/lib/relaton/ietf/item.rb +16 -0
  360. data/lib/relaton/ietf/item_base.rb +18 -0
  361. data/lib/relaton/ietf/item_data.rb +6 -0
  362. data/lib/relaton/ietf/processing_instructions.rb +79 -0
  363. data/lib/relaton/ietf/processor.rb +72 -0
  364. data/lib/relaton/ietf/relation.rb +9 -0
  365. data/lib/relaton/ietf/rfc/abstract.rb +19 -0
  366. data/lib/relaton/ietf/rfc/author.rb +21 -0
  367. data/lib/relaton/ietf/rfc/entry.rb +446 -0
  368. data/lib/relaton/ietf/rfc/entry_date.rb +21 -0
  369. data/lib/relaton/ietf/rfc/format.rb +19 -0
  370. data/lib/relaton/ietf/rfc/index.rb +46 -0
  371. data/lib/relaton/ietf/rfc/is_also.rb +21 -0
  372. data/lib/relaton/ietf/rfc/keywords.rb +19 -0
  373. data/lib/relaton/ietf/rfc/rfc_index_namespace.rb +11 -0
  374. data/lib/relaton/ietf/scraper.rb +101 -0
  375. data/lib/relaton/ietf/util.rb +8 -0
  376. data/lib/relaton/ietf/wg_name_resolver.rb +42 -0
  377. data/lib/relaton/ietf.rb +30 -0
  378. data/lib/relaton/iho/bibdata.rb +8 -0
  379. data/lib/relaton/iho/bibitem.rb +8 -0
  380. data/lib/relaton/iho/bibliography.rb +114 -0
  381. data/lib/relaton/iho/comment_period.rb +13 -0
  382. data/lib/relaton/iho/docidentifier.rb +31 -0
  383. data/lib/relaton/iho/doctype.rb +10 -0
  384. data/lib/relaton/iho/ext.rb +20 -0
  385. data/lib/relaton/iho/hash_parser_v1.rb +144 -0
  386. data/lib/relaton/iho/item.rb +20 -0
  387. data/lib/relaton/iho/item_base.rb +18 -0
  388. data/lib/relaton/iho/item_data.rb +6 -0
  389. data/lib/relaton/iho/processor.rb +54 -0
  390. data/lib/relaton/iho/relation.rb +9 -0
  391. data/lib/relaton/iho/structured_identifier.rb +20 -0
  392. data/lib/relaton/iho/util.rb +8 -0
  393. data/lib/relaton/iho.rb +27 -0
  394. data/lib/relaton/index/config.rb +52 -0
  395. data/lib/relaton/index/file_io.rb +305 -0
  396. data/lib/relaton/index/file_storage.rb +66 -0
  397. data/lib/relaton/index/pool.rb +46 -0
  398. data/lib/relaton/index/shard_source.rb +201 -0
  399. data/lib/relaton/index/type.rb +210 -0
  400. data/lib/relaton/index/util.rb +18 -0
  401. data/lib/relaton/index.rb +61 -0
  402. data/lib/relaton/isbn/isbn.rb +61 -0
  403. data/lib/relaton/isbn/open_library.rb +43 -0
  404. data/lib/relaton/isbn/parser.rb +88 -0
  405. data/lib/relaton/isbn/processor.rb +48 -0
  406. data/lib/relaton/isbn/util.rb +8 -0
  407. data/lib/relaton/isbn.rb +19 -0
  408. data/lib/relaton/iso/bibliography.rb +412 -0
  409. data/lib/relaton/iso/data_fetcher.rb +338 -0
  410. data/lib/relaton/iso/data_parser.rb +458 -0
  411. data/lib/relaton/iso/hash_parser_v1.rb +177 -0
  412. data/lib/relaton/iso/hit.rb +57 -0
  413. data/lib/relaton/iso/hit_collection.rb +196 -0
  414. data/lib/relaton/iso/item_data.rb +50 -0
  415. data/lib/relaton/iso/model/bibdata.rb +10 -0
  416. data/lib/relaton/iso/model/bibitem.rb +8 -0
  417. data/lib/relaton/iso/model/contributor.rb +6 -0
  418. data/lib/relaton/iso/model/contributor_info.rb +9 -0
  419. data/lib/relaton/iso/model/docidentifier.rb +146 -0
  420. data/lib/relaton/iso/model/doctype.rb +13 -0
  421. data/lib/relaton/iso/model/ext.rb +35 -0
  422. data/lib/relaton/iso/model/item.rb +17 -0
  423. data/lib/relaton/iso/model/item_base.rb +22 -0
  424. data/lib/relaton/iso/model/organization.rb +9 -0
  425. data/lib/relaton/iso/model/project_number.rb +22 -0
  426. data/lib/relaton/iso/model/relation.rb +9 -0
  427. data/lib/relaton/iso/model/stagename.rb +14 -0
  428. data/lib/relaton/iso/model/structured_identifier.rb +31 -0
  429. data/lib/relaton/iso/processor.rb +85 -0
  430. data/lib/relaton/iso/scraper.rb +635 -0
  431. data/lib/relaton/iso/type/pubid.rb +50 -0
  432. data/lib/relaton/iso/util.rb +8 -0
  433. data/lib/relaton/iso.rb +30 -0
  434. data/lib/relaton/itu/bibliography.rb +95 -0
  435. data/lib/relaton/itu/data_crawler_r.rb +664 -0
  436. data/lib/relaton/itu/data_fetcher.rb +550 -0
  437. data/lib/relaton/itu/data_merge_r.rb +149 -0
  438. data/lib/relaton/itu/data_parser_r.rb +214 -0
  439. data/lib/relaton/itu/data_parser_t.rb +228 -0
  440. data/lib/relaton/itu/family_cache.rb +177 -0
  441. data/lib/relaton/itu/governor.rb +56 -0
  442. data/lib/relaton/itu/hit.rb +28 -0
  443. data/lib/relaton/itu/hit_collection.rb +299 -0
  444. data/lib/relaton/itu/item_data.rb +6 -0
  445. data/lib/relaton/itu/model/approval_stage.rb +13 -0
  446. data/lib/relaton/itu/model/bibdata.rb +8 -0
  447. data/lib/relaton/itu/model/bibitem.rb +8 -0
  448. data/lib/relaton/itu/model/docidentifier.rb +75 -0
  449. data/lib/relaton/itu/model/doctype.rb +13 -0
  450. data/lib/relaton/itu/model/ext.rb +47 -0
  451. data/lib/relaton/itu/model/item.rb +13 -0
  452. data/lib/relaton/itu/model/meeting.rb +13 -0
  453. data/lib/relaton/itu/model/meeting_date.rb +15 -0
  454. data/lib/relaton/itu/model/question.rb +13 -0
  455. data/lib/relaton/itu/model/recommendation_status.rb +11 -0
  456. data/lib/relaton/itu/model/structured_identifier.rb +38 -0
  457. data/lib/relaton/itu/processor.rb +72 -0
  458. data/lib/relaton/itu/pubid.rb +199 -0
  459. data/lib/relaton/itu/radio_regulations_parser.rb +70 -0
  460. data/lib/relaton/itu/recommendation_fields.rb +334 -0
  461. data/lib/relaton/itu/recommendation_parser.rb +30 -0
  462. data/lib/relaton/itu/scraper.rb +203 -0
  463. data/lib/relaton/itu/util.rb +8 -0
  464. data/lib/relaton/itu.rb +34 -0
  465. data/lib/relaton/jcgm/bibdata.rb +8 -0
  466. data/lib/relaton/jcgm/bibitem.rb +8 -0
  467. data/lib/relaton/jcgm/bibliography.rb +97 -0
  468. data/lib/relaton/jcgm/data_fetcher.rb +81 -0
  469. data/lib/relaton/jcgm/docidentifier.rb +102 -0
  470. data/lib/relaton/jcgm/doctype.rb +12 -0
  471. data/lib/relaton/jcgm/ext.rb +23 -0
  472. data/lib/relaton/jcgm/item.rb +20 -0
  473. data/lib/relaton/jcgm/item_base.rb +18 -0
  474. data/lib/relaton/jcgm/item_data.rb +6 -0
  475. data/lib/relaton/jcgm/meetings_parser.rb +175 -0
  476. data/lib/relaton/jcgm/processor.rb +71 -0
  477. data/lib/relaton/jcgm/relation.rb +9 -0
  478. data/lib/relaton/jcgm/structured_identifier.rb +40 -0
  479. data/lib/relaton/jcgm/util.rb +8 -0
  480. data/lib/relaton/jcgm.rb +24 -0
  481. data/lib/relaton/jis/bibdata.rb +8 -0
  482. data/lib/relaton/jis/bibitem.rb +8 -0
  483. data/lib/relaton/jis/bibliography.rb +73 -0
  484. data/lib/relaton/jis/data_fetcher.rb +183 -0
  485. data/lib/relaton/jis/docidentifier.rb +120 -0
  486. data/lib/relaton/jis/doctype.rb +9 -0
  487. data/lib/relaton/jis/ext.rb +13 -0
  488. data/lib/relaton/jis/hit.rb +88 -0
  489. data/lib/relaton/jis/hit_collection.rb +128 -0
  490. data/lib/relaton/jis/item.rb +22 -0
  491. data/lib/relaton/jis/item_base.rb +26 -0
  492. data/lib/relaton/jis/item_data.rb +8 -0
  493. data/lib/relaton/jis/processor.rb +55 -0
  494. data/lib/relaton/jis/relation.rb +11 -0
  495. data/lib/relaton/jis/scraper.rb +232 -0
  496. data/lib/relaton/jis/structured_identifier.rb +13 -0
  497. data/lib/relaton/jis/util.rb +8 -0
  498. data/lib/relaton/jis.rb +32 -0
  499. data/lib/relaton/logger/channels/gh_issue.rb +143 -0
  500. data/lib/relaton/logger/config.rb +34 -0
  501. data/lib/relaton/logger/formatter_json.rb +8 -0
  502. data/lib/relaton/logger/formatter_string.rb +12 -0
  503. data/lib/relaton/logger/log.rb +64 -0
  504. data/lib/relaton/logger/log_device.rb +27 -0
  505. data/lib/relaton/logger/pool.rb +24 -0
  506. data/lib/relaton/logger.rb +18 -0
  507. data/lib/relaton/nist/bibdata.rb +8 -0
  508. data/lib/relaton/nist/bibitem.rb +8 -0
  509. data/lib/relaton/nist/bibliography.rb +191 -0
  510. data/lib/relaton/nist/comment_period.rb +15 -0
  511. data/lib/relaton/nist/data_fetcher.rb +134 -0
  512. data/lib/relaton/nist/date.rb +7 -0
  513. data/lib/relaton/nist/docidentifier.rb +165 -0
  514. data/lib/relaton/nist/doctype.rb +7 -0
  515. data/lib/relaton/nist/ext.rb +16 -0
  516. data/lib/relaton/nist/hit.rb +18 -0
  517. data/lib/relaton/nist/hit_collection.rb +362 -0
  518. data/lib/relaton/nist/item.rb +19 -0
  519. data/lib/relaton/nist/item_base.rb +16 -0
  520. data/lib/relaton/nist/item_data.rb +6 -0
  521. data/lib/relaton/nist/mods_parser.rb +302 -0
  522. data/lib/relaton/nist/processor.rb +69 -0
  523. data/lib/relaton/nist/pubs_export.rb +69 -0
  524. data/lib/relaton/nist/relation.rb +10 -0
  525. data/lib/relaton/nist/scraper.rb +293 -0
  526. data/lib/relaton/nist/series.yaml +49 -0
  527. data/lib/relaton/nist/util.rb +8 -0
  528. data/lib/relaton/nist.rb +34 -0
  529. data/lib/relaton/oasis/bibdata.rb +8 -0
  530. data/lib/relaton/oasis/bibitem.rb +8 -0
  531. data/lib/relaton/oasis/bibliography.rb +201 -0
  532. data/lib/relaton/oasis/browser_agent.rb +71 -0
  533. data/lib/relaton/oasis/data_fetcher.rb +130 -0
  534. data/lib/relaton/oasis/data_parser.rb +305 -0
  535. data/lib/relaton/oasis/data_parser_utils.rb +330 -0
  536. data/lib/relaton/oasis/data_part_parser.rb +239 -0
  537. data/lib/relaton/oasis/docidentifier.rb +54 -0
  538. data/lib/relaton/oasis/doctype.rb +7 -0
  539. data/lib/relaton/oasis/ext.rb +19 -0
  540. data/lib/relaton/oasis/item.rb +14 -0
  541. data/lib/relaton/oasis/item_data.rb +6 -0
  542. data/lib/relaton/oasis/processor.rb +74 -0
  543. data/lib/relaton/oasis/util.rb +8 -0
  544. data/lib/relaton/oasis.rb +41 -0
  545. data/lib/relaton/ogc/bibdata.rb +8 -0
  546. data/lib/relaton/ogc/bibitem.rb +8 -0
  547. data/lib/relaton/ogc/bibliography.rb +64 -0
  548. data/lib/relaton/ogc/data_fetcher.rb +131 -0
  549. data/lib/relaton/ogc/docidentifier.rb +111 -0
  550. data/lib/relaton/ogc/doctype.rb +12 -0
  551. data/lib/relaton/ogc/ext.rb +15 -0
  552. data/lib/relaton/ogc/hit.rb +18 -0
  553. data/lib/relaton/ogc/hit_collection.rb +111 -0
  554. data/lib/relaton/ogc/item.rb +13 -0
  555. data/lib/relaton/ogc/item_data.rb +6 -0
  556. data/lib/relaton/ogc/processor.rb +59 -0
  557. data/lib/relaton/ogc/scraper.rb +225 -0
  558. data/lib/relaton/ogc/util.rb +8 -0
  559. data/lib/relaton/ogc.rb +30 -0
  560. data/lib/relaton/oiml/bibdata.rb +8 -0
  561. data/lib/relaton/oiml/bibitem.rb +8 -0
  562. data/lib/relaton/oiml/bibliography.rb +169 -0
  563. data/lib/relaton/oiml/docidentifier.rb +48 -0
  564. data/lib/relaton/oiml/doctype.rb +13 -0
  565. data/lib/relaton/oiml/ext.rb +42 -0
  566. data/lib/relaton/oiml/item.rb +20 -0
  567. data/lib/relaton/oiml/item_base.rb +18 -0
  568. data/lib/relaton/oiml/item_data.rb +6 -0
  569. data/lib/relaton/oiml/processor.rb +54 -0
  570. data/lib/relaton/oiml/relation.rb +9 -0
  571. data/lib/relaton/oiml/util.rb +8 -0
  572. data/lib/relaton/oiml.rb +24 -0
  573. data/lib/relaton/omg/bibdata.rb +8 -0
  574. data/lib/relaton/omg/bibitem.rb +8 -0
  575. data/lib/relaton/omg/bibliography.rb +31 -0
  576. data/lib/relaton/omg/docidentifier.rb +67 -0
  577. data/lib/relaton/omg/ext.rb +7 -0
  578. data/lib/relaton/omg/item.rb +9 -0
  579. data/lib/relaton/omg/item_data.rb +6 -0
  580. data/lib/relaton/omg/processor.rb +35 -0
  581. data/lib/relaton/omg/scraper.rb +186 -0
  582. data/lib/relaton/omg/util.rb +8 -0
  583. data/lib/relaton/omg.rb +25 -0
  584. data/lib/relaton/plateau/bibdata.rb +8 -0
  585. data/lib/relaton/plateau/bibitem.rb +8 -0
  586. data/lib/relaton/plateau/bibliography.rb +31 -0
  587. data/lib/relaton/plateau/data_fetcher.rb +176 -0
  588. data/lib/relaton/plateau/doctype.rb +7 -0
  589. data/lib/relaton/plateau/ext.rb +23 -0
  590. data/lib/relaton/plateau/handbook_parser.rb +102 -0
  591. data/lib/relaton/plateau/hit.rb +21 -0
  592. data/lib/relaton/plateau/hit_collection.rb +79 -0
  593. data/lib/relaton/plateau/item.rb +12 -0
  594. data/lib/relaton/plateau/item_data.rb +6 -0
  595. data/lib/relaton/plateau/parser.rb +101 -0
  596. data/lib/relaton/plateau/processor.rb +51 -0
  597. data/lib/relaton/plateau/technical_report_parser.rb +98 -0
  598. data/lib/relaton/plateau/util.rb +8 -0
  599. data/lib/relaton/plateau.rb +29 -0
  600. data/lib/relaton/sdo/config.rb +34 -0
  601. data/lib/relaton/sdo/fetcher.rb +52 -0
  602. data/lib/relaton/sdo/logo.rb +95 -0
  603. data/lib/relaton/sdo/name.rb +26 -0
  604. data/lib/relaton/sdo/organization.rb +71 -0
  605. data/lib/relaton/sdo/store.rb +49 -0
  606. data/lib/relaton/sdo.rb +29 -0
  607. data/lib/relaton/un/bibdata.rb +8 -0
  608. data/lib/relaton/un/bibitem.rb +8 -0
  609. data/lib/relaton/un/bibliography.rb +48 -0
  610. data/lib/relaton/un/doctype.rb +10 -0
  611. data/lib/relaton/un/ext.rb +30 -0
  612. data/lib/relaton/un/hit.rb +56 -0
  613. data/lib/relaton/un/hit_collection.rb +61 -0
  614. data/lib/relaton/un/item.rb +11 -0
  615. data/lib/relaton/un/item_data.rb +6 -0
  616. data/lib/relaton/un/parser.rb +108 -0
  617. data/lib/relaton/un/processor.rb +38 -0
  618. data/lib/relaton/un/session.rb +25 -0
  619. data/lib/relaton/un/token_generator.rb +105 -0
  620. data/lib/relaton/un/util.rb +8 -0
  621. data/lib/relaton/un/wasm/decoder.rb +434 -0
  622. data/lib/relaton/un/wasm/instance.rb +101 -0
  623. data/lib/relaton/un/wasm/interpreter.rb +613 -0
  624. data/lib/relaton/un/wasm/memory.rb +112 -0
  625. data/lib/relaton/un/wasm/module.rb +47 -0
  626. data/lib/relaton/un/wasm.rb +17 -0
  627. data/lib/relaton/un/wasm_v_bg.wasm +0 -0
  628. data/lib/relaton/un.rb +28 -0
  629. data/lib/relaton/version.rb +1 -1
  630. data/lib/relaton/w3c/bibdata.rb +8 -0
  631. data/lib/relaton/w3c/bibitem.rb +8 -0
  632. data/lib/relaton/w3c/bibliography.rb +174 -0
  633. data/lib/relaton/w3c/data_fetcher.rb +487 -0
  634. data/lib/relaton/w3c/data_parser.rb +379 -0
  635. data/lib/relaton/w3c/docidentifier.rb +48 -0
  636. data/lib/relaton/w3c/doctype.rb +7 -0
  637. data/lib/relaton/w3c/ext.rb +11 -0
  638. data/lib/relaton/w3c/governor.rb +32 -0
  639. data/lib/relaton/w3c/item.rb +15 -0
  640. data/lib/relaton/w3c/item_data.rb +6 -0
  641. data/lib/relaton/w3c/processor.rb +49 -0
  642. data/lib/relaton/w3c/pubid.rb +85 -0
  643. data/lib/relaton/w3c/safe_realize.rb +148 -0
  644. data/lib/relaton/w3c/util.rb +8 -0
  645. data/lib/relaton/w3c.rb +36 -0
  646. data/lib/relaton/xsf/bibdata.rb +8 -0
  647. data/lib/relaton/xsf/bibitem.rb +8 -0
  648. data/lib/relaton/xsf/bibliography.rb +84 -0
  649. data/lib/relaton/xsf/data_fetcher.rb +106 -0
  650. data/lib/relaton/xsf/docidentifier.rb +46 -0
  651. data/lib/relaton/xsf/hit.rb +17 -0
  652. data/lib/relaton/xsf/hit_collection.rb +52 -0
  653. data/lib/relaton/xsf/item.rb +13 -0
  654. data/lib/relaton/xsf/item_data.rb +6 -0
  655. data/lib/relaton/xsf/processor.rb +51 -0
  656. data/lib/relaton/xsf/util.rb +9 -0
  657. data/lib/relaton/xsf.rb +34 -0
  658. data/lib/relaton-core.rb +1 -0
  659. data/lib/relaton.rb +85 -0
  660. metadata +775 -161
  661. data/.github/workflows/rake.yml +0 -14
  662. data/.github/workflows/release.yml +0 -24
  663. data/.github/workflows/rubocop.yml +0 -48
  664. data/.gitignore +0 -12
  665. data/.rspec +0 -3
  666. data/CLAUDE.md +0 -78
  667. data/Gemfile +0 -29
  668. data/Rakefile +0 -6
  669. data/docs/CHANGELOG.adoc +0 -16
  670. data/docs/VERSIONING_POLICY.adoc +0 -38
  671. data/docs/navigation.adoc +0 -6
  672. data/lib/relaton/db/version.rb +0 -5
  673. data/relaton.gemspec +0 -72
  674. data/spec/relaton/config_spec.rb +0 -10
  675. data/spec/relaton/db_cache_spec.rb +0 -51
  676. data/spec/relaton/db_spec.rb +0 -567
  677. data/spec/relaton/registry_spec.rb +0 -178
  678. data/spec/relaton/util_spec.rb +0 -3
  679. data/spec/relaton_meta_spec.rb +0 -25
  680. data/spec/relaton_spec.rb +0 -800
  681. data/spec/spec_helper.rb +0 -45
  682. data/spec/support/gb_t_20223_2006.xml +0 -33
  683. data/spec/support/iso_111111119115_1.xml +0 -0
  684. data/spec/support/iso_19115_1.xml +0 -115
  685. data/spec/support/iso_19115_2.xml +0 -95
  686. data/spec/support/rfc_8341.xml +0 -46
  687. data/spec/vcr_cassetes/api_relaton_org.yml +0 -121
  688. data/spec/vcr_cassetes/api_relaton_org_unavailable.yml +0 -140
  689. data/spec/vcr_cassetes/cc_dir_10005_2019.yml +0 -202
  690. data/spec/vcr_cassetes/cipm_meeting_43.yml +0 -1505
  691. data/spec/vcr_cassetes/gb_t_20223_2006.yml +0 -729
  692. data/spec/vcr_cassetes/iso_111111119115_1.yml +0 -12951
  693. data/spec/vcr_cassetes/iso_19115_1.yml +0 -17334
  694. data/spec/vcr_cassetes/iso_19115_1_2.yml +0 -322
  695. data/spec/vcr_cassetes/iso_19115_1_std.yml +0 -17334
  696. data/spec/vcr_cassetes/iso_19115_all_parts.yml +0 -185
  697. data/spec/vcr_cassetes/iso_19133_2005.yml +0 -144
  698. data/spec/vcr_cassetes/iso_combined_applied.yml +0 -318
  699. data/spec/vcr_cassetes/iso_combined_included.yml +0 -318
  700. data/spec/vcr_cassetes/ogc_19_025r1.yml +0 -374
  701. data/spec/vcr_cassetes/omg_ami4ccm_1_0.yml +0 -317
  702. data/spec/vcr_cassetes/rfc_8341.yml +0 -1278
@@ -0,0 +1,753 @@
1
+ module Relaton
2
+ module Ieee
3
+ module RawbibIdParser
4
+ STAGE = '(?<stage>DIS\d?|PSI|FCD|FDIS|CD\d?|Pub2|CDV|TS|SI)'.freeze
5
+ APPROVAL = '(?:\s(?<approval>Unapproved|Approved))'.freeze
6
+ APPROV = '(?:\s(?:Unapproved|Approved))?'.freeze
7
+ STD = "(?<std>\s(?i)Std.?(?-i))?".freeze
8
+
9
+ # Recurring OCR/spelling variants of month names seen in the raw IEEE
10
+ # dataset, mapped to a name Ruby's Date tables recognise.
11
+ MONTH_TYPOS = {
12
+ "sept" => "sep", "feburary" => "february", "novemer" => "november",
13
+ "octobor" => "october", "janurary" => "january"
14
+ }.freeze
15
+
16
+ #
17
+ # Parse a raw IEEE `normtitle` into a pubid identifier.
18
+ #
19
+ # pubid-first: most normtitles are canonical enough that
20
+ # `::Pubid::Ieee::Identifier.parse` handles them directly. The bespoke
21
+ # `#parse_fallback` regex pipeline only runs for the messy remainder — it
22
+ # normalizes the vendor string into a canonical form (via the private
23
+ # `Renderer`) that pubid can then parse. Either way the return value is a
24
+ # `::Pubid::Ieee::Identifier` (or nil when neither can make sense of it).
25
+ #
26
+ # @param [String] normtitle document element "normtitle"
27
+ # @param [String] stdnumber document element "stdnumber"
28
+ #
29
+ # @return [::Pubid::Ieee::Identifier, nil]
30
+ #
31
+ def parse(normtitle, stdnumber)
32
+ # Bespoke canonical string is the faithfulness reference: for the ~6% of
33
+ # normtitles pubid can't parse directly it's the recovery source, and for
34
+ # the rest it guards against pubid parsing but silently dropping a digit.
35
+ rendered = parse_fallback(normtitle, stdnumber)
36
+ ref = rendered&.to_id
37
+ [pubid_parse(normtitle), (ref && pubid_parse(ref))].compact.each do |pid|
38
+ return pid if ref.nil? || faithful?(pid.to_s, ref)
39
+ end
40
+ rendered # neither pubid parse kept every digit — keep the bespoke id
41
+ end
42
+
43
+ #
44
+ # True when `pid` is not a real IEEE designation but a leading fragment
45
+ # of the document's own title, coined by a generic {#parse_fallback}
46
+ # branch built for a genuine catalog number (e.g. "IEEE 802.3") that
47
+ # also happens to match a short title's opening words ("WEB 3.0: The
48
+ # Evolution of ..." -> `WEB 3.0`). Restricting this to the unvalidated
49
+ # `Renderer` fallback (never a pubid grammar match) is what keeps a
50
+ # genuine, correctly-resolved standard safe: measured over 9,091
51
+ # successfully-parsed records in the raw corpus, 7 real standards whose
52
+ # title happens to literally start with their own real designation
53
+ # (`IEEE Std 1636.99-2013, IEEE Standard for ...`) resolve to a real
54
+ # `::Pubid::Ieee::Identifier`, never a `Renderer`, so they are never
55
+ # flagged. `DataFetcher#no_standard_number?` catches most title-fragment
56
+ # records upfront by `publicationsubtype`, but that list can't cover
57
+ # every vendor subtype spelling, so this is a second, subtype-agnostic
58
+ # guard on the resolved id itself. Requiring a real ISBN keeps a
59
+ # genuine `Renderer` id (the ~1.3% that miss the faithfulness guard;
60
+ # see {#parse}) whose title coincidentally starts with it from being
61
+ # discarded.
62
+ #
63
+ # @param [::Pubid::Ieee::Identifier, Renderer, nil] pid
64
+ # @param [String, nil] title the document's own (non-normtitle) title
65
+ # @param [Boolean] isbn_present whether the document carries a real ISBN
66
+ #
67
+ # @return [Boolean]
68
+ #
69
+ def fabricated_title_id?(pid, title, isbn_present)
70
+ return false unless pid.is_a?(Renderer)
71
+
72
+ !!(title && isbn_present && title.start_with?(pid.to_s))
73
+ end
74
+
75
+ # Parse a canonical id string into a pubid identifier, or nil on failure.
76
+ def pubid_parse(str)
77
+ ::Pubid::Ieee::Identifier.parse(str)
78
+ rescue StandardError
79
+ nil
80
+ end
81
+
82
+ MONTHS_RE = /\b(?:jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|jun(?:e)?|jul(?:y)?|aug(?:ust)?|sep(?:t)?(?:ember)?|oct(?:ober)?|nov(?:ember)?|dec(?:ember)?)\b/i # rubocop:disable Layout/LineLength
83
+
84
+ # Date-independent digit multiset of an id (strips month names, years, and a
85
+ # trailing numeric month), so date reformatting doesn't count as a change.
86
+ def id_digits(str)
87
+ t = str.gsub(MONTHS_RE, " ").gsub(/(?:19|20)\d{2}/, " ").gsub(/-\s*\d{1,2}(?=\D*\z)/, " ")
88
+ t.gsub(/\D/, "").chars
89
+ end
90
+
91
+ # True when the pubid rendering kept every (non-date) digit of the bespoke
92
+ # reference — i.e. pubid didn't drop a draft/part/number digit. Digit-level
93
+ # (not token-level) so a benign re-split like `P1476/D4` vs `P14764` counts
94
+ # as faithful (same digits) while a real loss (`/D3.0` -> `/D.0`) does not.
95
+ def faithful?(pubid_str, ref_str)
96
+ have = id_digits(pubid_str).tally
97
+ id_digits(ref_str).tally.all? { |d, c| have.fetch(d, 0) >= c }
98
+ end
99
+
100
+ #
101
+ # Fallback: map a messy normtitle to an internal {Renderer} whose `.to_id`
102
+ # is a canonical string pubid can parse. Only the ~12% of normtitles pubid
103
+ # can't parse directly reach here.
104
+ #
105
+ # @return [Renderer, nil]
106
+ #
107
+ def parse_fallback(normtitle, stdnumber) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
108
+ case normtitle.sub(/^ISO\s(?=\/)/, "ISO").sub(/^ANSI\/\s(?=IEEE)/, "ANSI/")
109
+ # when "2012 NESC Handbook, Seventh Edition" then "NESC HBK ED7.2012"
110
+ # when "2017 NESC(R) Handbook, Premier Edition" then "NESC HBK ED1.2017"
111
+ # when "2017 National Electrical Safety Code(R) (NESC(R)) - Redline" then "NESC C2R.2017"
112
+ # when "2017 National Electrical Safety Code(R) (NESC(R))" then "NESC C2.2017"
113
+ # when /^(\d+HistoricalData)-(\d{4})/ then "IEEE #{$1}.#{$2}"
114
+ # when /^(\d+)\.(\w+)\sBattery\sLife\sImprovement/ then "IEEE #{$1}-#{$2}"
115
+ # when /^(\d+)\.(\w+)-(\d{4})\s\(Amendment/ then "IEEE #{$1}-#{$2}.#{$3}"
116
+ when "A.I.E.E. No. 15 May-1928" then Renderer.new(publisher: "AIEE", number: "15", year: "1928", month: "05")
117
+ # when "AIEE Nos 72 and 73 - 1932" then "AIEE 72_73.1932"
118
+ when "IEEE Std P1073.1.3.4/D3.0" then Renderer.new(publisher: "IEEE", std: true, number: "P11073", part: "00101") # "IEEE Std P11073-00101"
119
+ # when "P1073.1.3.4/D3.0" then Renderer.new(publisher: "IEEE", number: "P1073", part: "1-3-4", draft: "3.0") # "IEEE P1073-1-3-4/D3.0"
120
+ when "IEEE P1073.2.1.1/D08" then Renderer.new(publisher: "ISO/IEEE", number: "P1073", part: "2-1-1", draft: "08") # "ISO/IEEE P1073-2-1-1/D08"
121
+ when "IEEE P802.1Qbu/03.0, July 2015" # "IEEE P802.1Qbu/D3.0.2015"
122
+ Renderer.new(publisher: "IEEE", number: "P802", part: "1Qbu", draft: "3.0", year: "2015")
123
+ when "IEEE P11073-10422/04, November 2015" # "IEEE P11073-10422/D04.2015"
124
+ Renderer.new(publisher: "IEEE", number: "P11073", part: "10422", draft: "04", year: "2015")
125
+ when "IEEE P802.11aqTM/013.0 October 2017" # "IEEE P802-11aqTM/D13.0.2017"
126
+ Renderer.new(publisher: "IEEE", number: "P802", part: "11aqTM", draft: "13.0", year: "2017")
127
+ when "IEEE P844.3/C22.2 293.3/D0, August 2018" # "IEEE P844-3/C22.2-293.3/D0.2018"
128
+ Renderer.new([{ publisher: "IEEE", number: "P844", part: "3" },
129
+ { number: "C22.2", part: "293.3", dtaft: "0", year: "2018" }])
130
+ when "IEEE P844.3/C22.2 293.3/D1, November 2018" # "IEEE P844.3/C22.2 293.3/D1.2018"
131
+ Renderer.new([{ publisher: "IEEE", number: "P844", part: "3" },
132
+ { number: "C22.2", part: "293.3", draft: "1", year: "2018" }])
133
+ when "AIEE No 431 (105) -1958" then Renderer.new(publisher: "AIEE", number: "431", year: "1958") # "AIEE 431.1958"
134
+ when "IEEE 1076-CONC-I99O" then Renderer.new(publisher: "IEEE", number: "1076", year: "199O") # "IEEE 1076.199O"
135
+ when "IEEE Std 960-1993, IEEE Std 1177-1993" # "IEEE 960/1177.1993"
136
+ Renderer.new([{ publisher: "IEEE", std: true, number: "960" }, { number: "1177", year: "1993" }])
137
+ when "IEEE P802.11ajD8.0, August 2017" # "IEEE P802-11aj/D8.0.2017"
138
+ Renderer.new(publisher: "IEEE", number: "P802", part: "11aj", draft: "8.0", year: "2017")
139
+ when "IEEE P802.11ajD9.0, November 2017" # "IEEE P802-11aj/D9.0.2017"
140
+ Renderer.new(publisher: "IEEE", number: "P802", part: "11aj", draft: "9.0", year: "2017")
141
+ when "ISO/IEC/IEEE P29119-4-DISMay2013" # "ISO/IEC/IEEE DIS P29119-4.2013"
142
+ Renderer.new(publisher: "ISO/IEC/IEEE", stage: "DIS", number: "P29119", part: "4", year: "2013")
143
+ when "IEEE-P15026-3-DIS-January 2015" # "IEEE DIS P15026-3.2015"
144
+ Renderer.new(publisher: "IEEE", stage: "DIS", number: "P15026", year: "2015")
145
+ when "ANSI/IEEE PC63.7/D rev17, December 2014" # "ANSI/IEEE PC63-7/D/REV-17.2014"
146
+ Renderer.new(publisher: "ANSI/IEEE", number: "PC63", part: "7", draft: "", rev: "17", year: "2014")
147
+ when "IEC/IEEE P62271-37-013:2015 D13.4" # "IEC/IEEE P62271-37-013/D13.4.2015"
148
+ Renderer.new(publisher: "IEC/IEEE", number: "P62271", part: "37-013", draft: "13.4", year: "2015")
149
+ when "PC37.30.2/D043 Rev 18, May 2015" # "IEEE PC37-30-2/D043/REV-18.2015"
150
+ Renderer.new(publisher: "IEEE", number: "PC37", part: "30-2", draft: "043", rev: "18", year: "2015")
151
+ when "IEC/IEEE FDIS 62582-5 IEC/IEEE 2015" # "IEC/IEEE FDIS 62582-5.2015"
152
+ Renderer.new(publisher: "IEC/IEEE", stage: "FDIS", number: "62582", part: "5", year: "2015")
153
+ when "ISO/IEC/IEEE P15289:2016, 3rd Ed FDIS/D2" # "ISO/IEC/IEEE FDIS P15289/E3/D2.2016"
154
+ Renderer.new(publisher: "ISO/IEC/IEEE", stage: "FDIS", number: "P15289", part: "", edition: "3", draft: "2", year: "2016")
155
+ when "IEEE P802.15.4REVi/D09, April 2011 (Revision of IEEE Std 802.15.4-2006)"
156
+ Renderer.new(publisher: "IEEE", number: "P802", part: "15.4", rev: "i", draft: "09", year: "2013", month: "04", approval: "Approved")
157
+ when "Draft IEEE P802.15.4REVi/D09, April 2011 (Revision of IEEE Std 802.15.4-2006)"
158
+ Renderer.new(publisher: "IEEE", number: "P802", part: "15.4", rev: "i", draft: "09", year: "2011", month: "04")
159
+ when "ISO/IEC/IEEE DIS P42020:201x(E), June 2017"
160
+ Renderer.new(publisher: "ISO/IEC/IEEE", stage: "DIS", number: "P42020", year: "2017", month: "06")
161
+ when "IEEE/IEC P62582 CD2 proposal, May 2017"
162
+ Renderer.new(publisher: "IEEE/IEC", number: "P62582", stage: "CD2", year: "2017", month: "05")
163
+ when "ISO/IEC/IEEE P16326:201x WD.4a, July 2017"
164
+ Renderer.new(publisher: "ISO/IEC/IEEE", number: "P16326", draft: "4a", year: "2017", month: "07")
165
+ when "ISO/IEC/IEEE CD.1 P21839, October 2017"
166
+ Renderer.new(publisher: "ISO/IEC/IEEE", stage: "CD1", number: "P21839", year: "2017", month: "10")
167
+ when "IEEE P3001.2/D5, August 2017"
168
+ Renderer.new(publisher: "IEEE", number: "P3001", part: "2", draft: "5", year: "2017", month: "01")
169
+ when "P3001.2/D5, August 2017"
170
+ Renderer.new(publisher: "IEEE", number: "P3001", part: "2", draft: "5", year: "2017", month: "12")
171
+ when "ISO/IEC/IEEE P16326:201x WD5, December 2017"
172
+ Renderer.new(publisher: "ISO/IEC/IEEE", number: "P16326", draft: "5", year: "2017", month: "12")
173
+ when "ISO/IEC/IEEE DIS P16326/201x, December 2018"
174
+ Renderer.new(publisher: "ISO/IEC/IEEE", stage: "DIS", number: "P16326", year: "2018", month: "12")
175
+ when "ISO/IEC/IEEE/P21839, 2019(E)"
176
+ Renderer.new(publisher: "ISO/IEC/IEEE", number: "P21839", year: "2019")
177
+ when "ISO/IEC/IEEE P42020/V1.9, August 2018"
178
+ Renderer.new(publisher: "ISO/IEC/IEEE", number: "P42020", year: "2018", month: "08")
179
+ when "ISO/IEC/IEEE CD2 P12207-2: 201x(E), February 2019"
180
+ Renderer.new(publisher: "ISO/IEC/IEEE", stage: "CD2", number: "P12207", part: "2", year: "2019", month: "02")
181
+ when "ISO/IEC/IEEE P42010.WD4:2019(E)"
182
+ Renderer.new(publisher: "ISO/IEC/IEEE", number: "P42010", draft: "4", year: "2019")
183
+ when "IEC/IEEE P63195_CDV/V3, February 2020"
184
+ Renderer.new(publisher: "IEC/IEEE", number: "P63195", stage: "CDV", year: "2020", month: "02")
185
+ when "IEEE/ISO/IEC P42010.CD1-V1.0, April 2020"
186
+ Renderer.new(publisher: "IEEE/ISO/IEC", number: "P42010", stage: "CD1", year: "2020", month: "04")
187
+ when "ISO/IEC/IEEE/P16085_DIS, March 2020"
188
+ Renderer.new(publisher: "ISO/IEC/IEEE", stage: "DIS", number: "P16085", year: "2020", month: "03")
189
+ when "ANSI/IEEE Std: Outdoor Apparatus Bushings"
190
+ Renderer.new(publisher: "ANSI/IEEE", std: true, number: "21", year: "1976", month: "11")
191
+ when "Unapproved Draft Std ISO/IEC FDIS 15288:2007(E) IEEE P15288/D3,"
192
+ Renderer.new(publisher: "ISO/IEC/IEEE", stage: "FDIS", std: true, number: "P15288", draft: "3", year: "2007")
193
+ when "Draft National Electrical Safety Code, January 2016"
194
+ Renderer.new(publisher: "IEEE", number: "PC2", year: "2016", month: "01")
195
+ when "ANSI/IEEE-ANS-7-4.3.2-1982" then Renderer.new(publisher: "ANSI/IEEE/ANS", number: "7", part: "4-3-2", year: "1982")
196
+ when "IEEE Unapproved Draft Std P802.1AB/REVD2.2, Dec 2007" # "IEEE P802.1AB/REV/D2.2.2007"
197
+ Renderer.new(publisher: "IEEE", std: true, number: "P802", part: "1AB", rev: "", draft: "2.2", year: "2007", month: "12")
198
+ when "International Standard ISO/IEC 8802-9: 1996(E) ANSI/IEEE Std 802.9, 1996 Edition"
199
+ Renderer.new(publisher: "ISO/IEC/IEEE", std: true, number: "802", part: "9", year: "1996")
200
+ when "ISO/IEC13210: 1994 (E) ANSI/IEEE Std 1003.3-1991"
201
+ Renderer.new(publisher: "ISO/IEC/IEEE", number: "13210", year: "1994")
202
+ when "J-STD-016-1995" then Renderer.new(publisher: "IEEE", number: "016", year: "1995")
203
+ when "Std 802.1ak-2007 (Amendment to IEEE Std 802.1QTM-2005)"
204
+ Renderer.new(publisher: "IEEE", std: true, number: "802", part: "1ak", year: "2007")
205
+ when "IS0/IEC/IEEE 8802-11:2012/Amd.5:2015(E) (Adoption of IEEE Std 802.11af-2014)"
206
+ Renderer.new(publisher: "ISO/IEC/IEEE", number: "802", part: "11", year: "2012", amd: "5", year_amendment: "2015")
207
+ when "National Electrical Safety Code, C2-2012 - Redline"
208
+ Renderer.new(publisher: "IEEE", number: "C2", year: "2012", redline: "true")
209
+ when "National Electrical Safety Code, C2-2012" then Renderer.new(publisher: "IEEE", number: "C2", year: "2012")
210
+ when "2012 NESC Handbook, Seventh Edition" then Renderer.new(publisher: "NESC", number: "HBK", year: "2012")
211
+ when /^Amendment to IEEE Std 802\.11-2007 as amended by IEEE Std 802\.11k-2008/
212
+ Renderer.new(publisher: "IEEE", std: true, number: "802", part: "11u", year: "2007")
213
+ when "Std 11073-10417-2009" then Renderer.new(publisher: "IEEE", std: true, number: "11073", part: "10417", year: "2009")
214
+ when "Nuclear EQ Sourcebook and Supplement" then Renderer.new publisher: "IEEE", number: "7438946"
215
+
216
+ # drop all with <standard_id>0</standard_id>
217
+ # when "IEEE Std P1671/D5, June 2006", "IEEE Std PC37.100.1/D8, Dec 2006",
218
+ # "IEEE Unapproved Draft Std P1578/D17, Mar 2007", "IEEE Approved Draft Std P1115a/D4, Feb 2007",
219
+ # "IEEE Std P802.16g/D6, Nov 06", "IEEE Unapproved Draft Std P1588_D2.2, Jan 2008",
220
+ # "IEEE Unapproved Std P90003/D1, Feb 2007.pdf", "IEEE Unapproved Draft Std PC37.06/D10 Dec 2008",
221
+ # "IEEE P1451.2/D20, February 2011", "IEEE Std P1641.1/D3, July 2006",
222
+ # "IEEE P802.1AR-Rev/D2.2, September 2017 (Draft Revision of IEEE Std 802.1AR\u20132009)",
223
+ # "IEEE Std 108-1955; AIEE No.450-April 1955", "IEEE Std 85-1973 (Revision of IEEE Std 85-1965)",
224
+ # "IEEE Std 1003.1/2003.l/lNT, March 1994 Edition" then nil
225
+
226
+ # publisher1, number1, part1, publisher2, number2, part2, draft, year
227
+ when /^([A-Z\/]+)\s(\w+)[-.](\d+)\/(\w+)\s(\w+)[-.](\d+)_D([\d.]+),\s\w+\s(\d{4})/
228
+ Renderer.new([{ publisher: $1, number: $2, part: $3 },
229
+ { publisher: $4, number: $5, part: $6, draft: dn($7), year: $8 }])
230
+
231
+ # publisher1, number1, part1, number2, part2, draft, year, month
232
+ when /^([A-Z\/]+)\s(\w+)[.-]([\w.-]+)\/(\w+)[.-]([[:alnum:].-]+)[\/_]D([\w.]+),\s(\w+)\s(\d{4})/
233
+ Renderer.new([{ publisher: $1, number: $2, part: sp($3) }, { number: $4, part: sp($5), draft: dn($6), year: $8, month: mn($7) }])
234
+
235
+ # publisher, approval, number, part, corrigendum, draft, year
236
+ when /^(?<publisher>[A-Z\/]+)#{APPROVAL}(?:\sDraft)?\sStd\s(?<number>\w+)\.(?<part>\d+)-\d{4}[^\/]*\/Cor\s?(?<corr>\d)\/(?<draft>D[\d\.]+),\s(?:\w+\s)?(?<year>\d{4})/o
237
+ create_pubid(Regexp.last_match)
238
+
239
+ # publisher, number, part, corrigendum, draft, year, month
240
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)\.(?<part>\w+)-\d{4}\/Cor\s?(?<corr>\d(?:-\d+x)?)[\/_]D(?<draft>[\d\.]+),\s?(?<month>\w+)\s(?<year>\d{4})/o
241
+ create_pubid(Regexp.last_match)
242
+
243
+ # publidsher1, number1, year1 publisher2, number2, draft, year2
244
+ when /^([A-Z\/]+)\s(\w+)-(\d{4})\/([A-Z]+)\s([[:alnum:]]+)_D([\w.]+),\s(\d{4})/
245
+ Renderer.new([{ publisher: $1, number: $2, year: $3 }, { publisher: $4, number: $5, draft: dn($6), year: $7 }])
246
+
247
+ when /^(?<publisher>[A-Z\/]+)\s#{STAGE}\s(?<number>\w+)[.-](?<part>[[:alnum:].-]+)[\s\/_]ED(?<edition>[\w.]+),\s(?<month>\w+)\s(?<year>\d{4})/o
248
+ create_pubid(Regexp.last_match)
249
+
250
+ # publidsher1, number1, publisher2, number2, draft, year
251
+ when /^(?<publisher1>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number1>\w+)\/(?<publisher2>[A-Z]+)\s(?<number2>[[:alnum:]]+)_D(?<draft>[\d\.]+),\s\w+\s(?<year>\d{4})/o,
252
+ /^(?<publisher1>[A-Z\/]+)\s(?<number1>\w+)\sand\s(?<publisher2>[A-Z]+)(?:\sGuideline)?\s(?<number2>[[:alnum:]]+)\/D(?<draft>[\d\.]+),\s\w+\s(?<year>\d{4})/o
253
+ nc = Regexp.last_match.named_captures
254
+ Renderer.new([{ publisher: nc["publisher1"], std: !!nc["std"], number: nc["number1"] },
255
+ { publisher: nc["publisher2"], number: nc["number2"], draft: dn(nc["draft"]), year: nc["year"] }])
256
+
257
+ # publidsher1, number1, part, publisher2, number2, year
258
+ when /^([A-Z\/]+)\s(\w+)\.(\d+)_(\w+)\s(\w+),\s(\d{4})/ # "#{$1} #{$2}-#{$3}/#{$4} #{$5}.#{$6}"
259
+ Renderer.new([{ publisher: $1, number: $2, part: $3 }, { publisher: $4, number: $5, year: $6 }])
260
+
261
+ # publisher, number1, part1, number2, part2, draft
262
+ when /^([A-Z\/]+)\s(\w+)[.-](\d+)\/(\w+)\.(\d+)[\/_]D([\d.]+)/ # "#{$1} #{$2}-#{$3}/#{$4}-#{$5}/D#{$6}"
263
+ Renderer.new([{ publisher: $1, number: $2, part: $3 }, { number: $4, part: $5, draft: dn($6) }])
264
+
265
+ # publidsher, number1, part1, number2, part2, year
266
+ when /^([A-Z\/]+)\sStd\s(\w+)\.(\w+)\/(\w+)\.(\w+)\/INT\s\w+\s(\d{4})/
267
+ Renderer.new([{ publisher: $1, number: $2, part: $3 }, { number: $4, part: $5, year: $6 }])
268
+
269
+ # publisher, number, part, corrigendum, draft, year
270
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)[.-](?<part>[\d-]+)\/Cor\s?(?<corr>\d)[\/_]D(?<draft>[\d\.]+),\s(?:\w+\s)?(?<year>\d{4})/o,
271
+ /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)[.-](?<part>\d+)-\d{4}\/Cor\s?(?<corr>\d)(?:-|,\s|\/)D(?<draft>[\d.]+),?\s\w+\s(?<year>\d{4})/,
272
+ /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)\.(?<part>[[:alnum:].]+)[-_]Cor[\s-]?(?<corr>\d)\/D(?<draft>[\d.]+),?\s\w+\s(?<year>\d{4})/
273
+ create_pubid(Regexp.last_match)
274
+ when /^([A-Z\/]+)\s(\w+)\.(\d+)-\d{4}\/Cor(\d)-(\d{4})\/D([\d.]+)/ # "#{$1} #{$2}-#{$3}/Cor#{$4}/D#{$6}.#{$5}"
275
+ Renderer.new(publisher: $1, number: $2, part: $3, corr: $4, draft: dn($6), year: $5)
276
+
277
+ # publisher, number, part, draft, year, month. The bare "Active" status
278
+ # word is matched but NOT captured — folding it into the id rendered a
279
+ # stray token and a double space (`IEEE Active Std ...`) pubid rejects.
280
+ when /^(?<publisher>[A-Z\/]+)(?:\sActive)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)[.-](?<part>[[:alnum:]\.]+)\s?[\/_]D(?<draft>[\w\.]+),?\s(?<month>\w+)(?:\s\d{1,2},)?\s?(?<year>\d{2,4})/o
281
+ create_pubid(Regexp.last_match)
282
+
283
+ # publisher, approval, number, part, draft, year, month
284
+ when /^(?<publisher>[A-Z\/]+)(?:\sActive)?#{APPROVAL}(?:\sDraft)?#{STD}\s(?<number>\w+)[.-](?<part>[[:alnum:]\.]+)\s?[\/_]D(?<draft>[\w\.-]+),?\s(?<month>\w+)(?:\s\d{1,2},)?\s?(?<year>\d{2,4})/o,
285
+ /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)\.(?<part>[\w.]+)\/D(?<draft>[\w.]+),?\s(?<month>\w+)[\s_](?<year>\d{4})(?:\s-\s\(|\s\(|_)#{APPROVAL}/
286
+ create_pubid(Regexp.last_match)
287
+
288
+ # publisher, approval, number, draft, year, month
289
+ when /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)\/D(?<draft>[\w.]+),\s(?<month>\w+)\s(?<year>\d{4})\s-\s\(?#{APPROVAL}/
290
+ create_pubid(Regexp.last_match)
291
+
292
+ # publisher, approval, number, part, draft, year
293
+ when /^(?<publisher>[A-Z\/]+)#{APPROVAL}(?:\sDraft)?#{STD}\s(?<number>\w+)[.-](?<part>[\w.]+)\s?[\/_\s]D(?<draft>[\w\.]+),?\s\w+\s?(?<year>\d{4})/o,
294
+ /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)\.(?<part>[\w.]+)\/D(?<draft>[\d.]+),?\s\w+[\s_](?<year>\d{4})(?:\s-\s\(|_|\s\()?#{APPROVAL}/o
295
+ create_pubid(Regexp.last_match)
296
+
297
+ # publisher, stage, number, part, edition, year, month
298
+ when /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)[.-](?<part>[[:alnum:].-]+)[\/_]#{STAGE}\s(?<edition>\w+)\sedition,\s(?<month>\w+)\s(?<year>\d{4})/o
299
+ create_pubid(Regexp.last_match)
300
+
301
+ # number, part, corrigendum, draft, year
302
+ when /^(?<number>\w+)\.(?<part>[\w.]+)-\d{4}[_\/]Cor\s?(?<corr>\d)\/D(?<draft>[\w.]+),?\s\w+\s(?:\d{2},\s)?(?<year>\d{4})/
303
+ create_pubid(Regexp.last_match)
304
+
305
+ # publisher, approval, number, part, draft
306
+ when /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)\.(?<part>\d+)\/D(?<draft>[\d.]+)\s\([^)]+\)\s-#{APPROVAL}/o
307
+ create_pubid(Regexp.last_match)
308
+
309
+ # publisher, number, part1, rev, draft, part2
310
+ when /^(?<publisher>[A-Z\/]+)#{STD}\s(?<number>\w+)\.(?<part>[\d.]+)REV(?<rev>[a-z]+)_D(?<draft>[\w.]+)\sPart\s(?<part2>\d)/o
311
+ create_pubid(Regexp.last_match)
312
+
313
+ # publisher, number, part, draft, year, month
314
+ when /^(?<publisher>[A-Z\/]+)#{STD}\s(?<number>\w+)[.-](?<part>[[:alnum:].]+)[\/\s_]D(?<draft>[\d.]+)(?:,?\s|_)(?<month>[[:alpha:]]+)[\s_]?(?<year>\d{4})/o
315
+ create_pubid(Regexp.last_match)
316
+
317
+ # publisher, stage, number, part, draft, year
318
+ when /^(?<publisher>[\w\/]+)\s(?<stage>#{STAGE})\s(?<number>\w+)-(?<part>[[:alnum:]]+)[\/_\s]D(?<draft>[\d.]+),\s\w+\s(?<year>\d{4})/o
319
+ create_pubid(Regexp.last_match)
320
+
321
+ # publisher, number, part, rev, draft, year, month
322
+ when /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)\.(?<part>[\w.]+)-Rev\/D(?<draft>[\w.]+),\s(?<month>\w+)\s(?<year>\d{4})/
323
+ create_pubid(Regexp.last_match)
324
+
325
+ # publisher, number, part, rev, draft, year
326
+ when /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)\.(?<part>[\d.]+)Rev(?<rev>\w+)-D(?<draft>[\w.]+),\s\w+\s(?<year>\d{4})/
327
+ create_pubid(Regexp.last_match)
328
+
329
+ # publisher, stage, number, part, edition, year
330
+ when /^(?<publisher>[A-Z\/]+)\s(?<stage>#{STAGE})\s(?<number>\w+)[.-](?<part>[[:alnum:].-]+)[\/\s_]ED(?<edition>[\d.]+),\s(?<year>\d{4})/o
331
+ create_pubid(Regexp.last_match)
332
+
333
+ # publisher, stage, number, draft, year, month
334
+ when /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)\/(?<stage>#{STAGE})[\/_]D(?<draft>[\w.]+),\s(?<month>\w+)\s(?<year>\d{4})/o
335
+ create_pubid(Regexp.last_match)
336
+
337
+ # number, part, draft, year, month
338
+ when /(\w+)[.-]([[:alnum:].]+)[\/\s_]D([\d.]+)(?:,?\s|_)([[:alpha:]]+)[\s_]?(\d{4})/
339
+ Renderer.new(publisher: "IEEE", number: $1, part: sp($2), draft: dn($3), year: $5, month: mn($4))
340
+
341
+ # number, corrigendum, draft, year, month
342
+ when /^(\w+)-\d{4}[\/_]Cor\s?(\d)[\/_]D([\w.]+),\s(\w+)\s(\d{4})/
343
+ Renderer.new(publisher: "IEEE", number: $1, corr: $2, draft: dn($3), month: mn($4), year: $5)
344
+
345
+ # publisher, number, corrigendum, draft, year
346
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?\sStd\s(?<number>\w+)(?:-\d{4})?[\/_]Cor\s?(?<corr>\d)\/D(?<draft>[\d\.]+),\s\w+\s(?<year>\d{4})/o
347
+ create_pubid(Regexp.last_match)
348
+
349
+ # publisher, number, part, rev, corrigendum, draft
350
+ when /^([A-Z\/]+)\s(\w+)\.(\w+)-\d{4}-Rev\/Cor(\d)\/D([\d.]+)/
351
+ Renderer.new(publisher: $1, number: $2, part: $3, rev: "", corr: $4, draft: dn($5))
352
+
353
+ # publisher, number, part, corrigendum, draft
354
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)\.(?<part>[\w.]+)\/[Cc]or\s?(?<corr>\d)\/D(?<draft>[\w\.]+)/o,
355
+ /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)\.(?<part>\w+)-\d{4}\/Cor\s?(?<corr>\d)[\/_]D(?<draft>[\d\.]+)/o
356
+ create_pubid(Regexp.last_match)
357
+
358
+ # publisher, number, part, corrigendum, year
359
+ when /^(?<publisher>[A-Z\/]+)#{STD}\s(?<number>\w+)[.-](?<part>[\w.]+)[:-]\d{4}[\/-]Cor[\s.]?(?<corr>\d)[:-](?<year>\d{4})/o
360
+ create_pubid(Regexp.last_match)
361
+
362
+ # publisher, number, part, draft, year
363
+ when /^(?<publisher>[A-Z\/]+)(?:\sActive)?#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)[.-](?<part>[[:alnum:]\.]+)(?:\s?\/\s?|_|,\s|-)D(?<draft>[\w\.]+)\s?,?\s\w+(?:\s\d{1,2},)?\s?(?<year>\d{2,4})/o,
364
+ /^(?<publisher>[A-Z\/]+)#{STD}\s(?<number>\w+)[.-](?<part>[\w.-]+)[\/\s]D(?<draft>[\w.]*)(?:-|,\s?\w+\s|\s\w+:|,\s)(?<year>\d{4})/o,
365
+ /^(?<publisher>[\w\/]+)(?:\sActive)?#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)[.-](?<part>[[:alnum:]\.]+)\sDraft\s(?<draft>[\w\.]+),\s\w+\s(?<year>\d{4})/o
366
+ create_pubid(Regexp.last_match)
367
+
368
+ # publisher, approval, number, draft, year
369
+ when /^(?<publisher>[A-Z\/]+)#{APPROVAL}(?:\sDraft)?#{STD}\s(?<number>[[:alnum:]]+)\s?[\/_]\s?D(?<draft>[\w\.]+),?\s\w+\s(?<year>\d{2,4})/o,
370
+ /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)\/D(?<draft>[\d.]+),\s\w+[\s_](?<year>\d{4})(?:\s-\s\(?|_)?#{APPROVAL}/o
371
+ create_pubid(Regexp.last_match)
372
+
373
+ # publisher, number, part, rev, draft
374
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)\.(?<part>[\w.]+)[-\s\/]?REV-?(?<rev>\w+)\/D(?<draft>[\d.]+)/o,
375
+ /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)\.(?<part>[\w.]+)-REV\/D(?<draft>[\d.]+)/o
376
+ create_pubid(Regexp.last_match)
377
+
378
+ # publisher, number, part, rev, year
379
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?\sStd\s(?<number>\w+)\.(?<part>\d+)\/rev(?<rev>\d+),\s\w+\s(?<year>\d+)/o
380
+ create_pubid(Regexp.last_match)
381
+
382
+ # publisher, stage, number, draft, year
383
+ when /^(?<publisher>[\w\/]+)\s#{STAGE}\s(?<number>[[:alnum:]]+)[\/_]D(?<draft>[\w.]+),(?:\s\w+)?\s(?<year>\d{4})/o
384
+ create_pubid(Regexp.last_match)
385
+
386
+ # publisher, stage, number, part, year, month
387
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)[.-](?<part>[[:alnum:].-]+)(?:[\/_-]|,\s)#{STAGE},?\s(?<month>\w+)\s(?<year>\d{4})/o,
388
+ /^(?<publisher>[A-Z\/]+)\s(?<stage>#{STAGE})\s(?<number>\w+)[.-](?<part>\w+),\s(?<month>\w+)\s(?<year>\d{4})/o
389
+ create_pubid(Regexp.last_match)
390
+
391
+ # publisher, number, part, edition, year, month
392
+ when /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)[.-](?<part>[\w.-]+)[\/\s]ED(?<edition>[\d+]),\s(?<month>\w+)\s(?<year>\d{4})/
393
+ create_pubid(Regexp.last_match)
394
+
395
+ # publisher, stage, number, part, year
396
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)[.-](?<part>\d+)[\/_-]#{STAGE},?\s\w+\s(?<year>\d{4})/o,
397
+ /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)-(?<part>\d+)[\/-]#{STAGE}(?:_|,\s|-)\w+\s?(?<year>\d{4})/o,
398
+ /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)[.-](?<part>\d+)[\/-_]#{STAGE}[\s-](?<year>\d{4})/o,
399
+ /^(?<publisher>[A-Z\/]+)\s(?<stage>#{STAGE})\s(?<number>\w+)-(?<part>[\w-]+),\s(?<year>\d{4})/o
400
+ create_pubid(Regexp.last_match)
401
+
402
+ # publisher, stage, number, year, month
403
+ when /^(?<publisher>[A-Z\/]+)\s#{STAGE}\s(?<number>\w+)(?:\s\g<stage>)?,\s(?<month>\w+)\s(?<year>\d{4})/o,
404
+ /^(?<publisher>[A-Z\/]+)\s(?<number>[[:alnum:]]+)(?:\s|_|\/\s?)?#{STAGE},?\s(?<month>\w+)\s(?<year>\d{4})/o
405
+ create_pubid(Regexp.last_match)
406
+
407
+ # publisher, stage, number, part, draft
408
+ when /^(?<publisher>[A-Z\/]+)[.-](?<part>[[:alnum:].-]+)[\/_]D(?<draft>[[:alnum:].]+)[\/_]#{STAGE}/o,
409
+ /^(?<number>\w+)[.-](?<part>[[:alnum:].]+)[\/\s_]D(?<draft>[\d.]+)_(?<stage>#{STAGE})/o
410
+ create_pubid(Regexp.last_match)
411
+
412
+ # publisher, stage, number, year
413
+ when /^(?<publisher>[A-Z\/]+)\s#{STAGE}\s(?<number>\w+)(?:,\s\w+\s|:)(?<year>\d{4})/o,
414
+ /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)(?:\/|,\s)(?<stage>#{STAGE})-(?<year>\d{4})/o
415
+ create_pubid(Regexp.last_match)
416
+
417
+ # publisher, stage, number, part
418
+ when /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)-(?<part>[\w-]+)[\s-]#{STAGE}/o,
419
+ /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)-#{STAGE}-(?<part>\w+)/o,
420
+ /^(?<publisher>[A-Z\/]+)\s#{STAGE}\s(?<number>\w+)[.-](?<part>[[:alnum:].-]+)/o
421
+ create_pubid(Regexp.last_match)
422
+
423
+ # publisher, number, corrigendum, year
424
+ when /^(?<publisher>[A-Z\/]+)#{STD}\s(?<number>\w+)-\d{4}\/Cor\s?(?<corr>\d)-(?<year>\d{4})/o
425
+ create_pubid(Regexp.last_match)
426
+
427
+ # publisher, number, rev, draft
428
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)-REV\/D(?<draft>[\d.]+)/o
429
+ create_pubid(Regexp.last_match)
430
+
431
+ # publisher, number, part, year, month
432
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)-(?<part>[\w-]+),\s(?<month>\w+)\s?(?<year>\d{4})/o,
433
+ /^(?<publisher>[A-Z\/]+)\sStd\s(?<number>\w+)\.(?<part>\w+)-\d{4}\/INT,?\s(?<month>\w+)\.?\s(?<year>\d{4})/
434
+ create_pubid(Regexp.last_match)
435
+
436
+ # publisher, number, part, amendment, year
437
+ when /^(?<publisher>[A-Z\/]+)#{STD}\s(?<number>\w+)-(?<part>\w+)[:-](?<year>\d{4})\/Amd(?:\s|.\s?)?(?<amd>\d)/o
438
+ create_pubid(Regexp.last_match)
439
+
440
+ # publisher, number, part, year, redline
441
+ when /^(?<publisher>[A-Z\/]+)#{STD}\s(?<number>\w+)[.-](?<part>[\w.]+)[:-](?<year>\d{4}).*?\s-\s(?<redline>Redline)/o,
442
+ /^(?<publisher>[A-Z\/]+)#{STD}\s(?<number>\w+)[.-](?<part>[\w.-]+):(?<year>\d{4}).*?\s-\s(?<redline>Redline)/o
443
+ create_pubid(Regexp.last_match)
444
+
445
+ # publisher, number, part, year
446
+ when /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)-(?<part>\d{1,3}),\s\w+\s(?<year>\d{4})/,
447
+ /^(?<publisher>[A-Z\/]+)#{STD}\s(?<number>\w+)[.-](?!(?:19|20)\d{2}\D)(?<part>[\w.]+)(?:,\s\w+\s|-|:|,\s|\.|:)(?<year>\d{4})/o,
448
+ /^(?<publisher>[A-Z\/]+)#{STD}\s(?<number>\w+)[.-](?!(?:19|20)\d{2}\D)(?<part>[\w.-]+)(?:,\s\w+\s|:|,\s|\.|:)(?<year>\d{4})/o,
449
+ /^(?<publisher>[A-Z\/]+)#{STD}\sNo(?:\.?\s|\.)(?<number>\w+)\.(?<part>\d+)\s?-(?:\w+\s)?(?<year>\d{4})/o
450
+ create_pubid(Regexp.last_match)
451
+
452
+ # publisher, number, edition, year
453
+ when /^([A-Z\/]+)\s(\w+)\s(\w+)\sEdition,\s\w+\s(\d+)/,
454
+ /^([A-Z\/]+)\s(\w+)[\/_]ED([\d.]+),\s(\d{4})/
455
+ Renderer.new(publisher: $1, number: $2, edition: en($3), year: $4)
456
+
457
+ # publisher, number, part, conformance, draft
458
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)\.(?<part>[[:alnum:].]+)[\/-]Conformance(?<conformance>\d+)[\/_]D(?<draft>[\w\.]+)/o
459
+ create_pubid(Regexp.last_match)
460
+
461
+ # publisher, number, part, conformance, year
462
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)\.(?<part>[[:alnum:].]+)\s?\/\s?Conformance(?<conformance>\d+)-(?<year>\d{4})/o
463
+ create_pubid(Regexp.last_match)
464
+
465
+ # publisher, number, part, draft
466
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)\.(?<part>[[:alnum:].]+)[^\/]*\/D(?<draft>[[:alnum:]\.]+)/o,
467
+ /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)[.-](?<part>[[:alnum:]-]+)[\s_]D(?<draft>[\d.]+)/,
468
+ /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)-(?<part>\w+)\/D(?<draft>[\w.]+)/
469
+ create_pubid(Regexp.last_match)
470
+
471
+ # number, part, draft, year
472
+ when /^(?<number>\w+)[.-](?<part>[[:alnum:].-]+)(?:\/|,\s|_)D(?<draft>[\d.]+),?\s(?:\w+,?\s)?(?<year>\d{4})/
473
+ create_pubid(Regexp.last_match)
474
+
475
+ # publisher, number, draft, year, month
476
+ when /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)[\/_]D(?<draft>[\d.]+),\s(?<month>\w+)\s(?<year>\d{4})/
477
+ create_pubid(Regexp.last_match)
478
+
479
+ # publisher, number, draft, year
480
+ when /^(?<publisher>[\w\/]+)(?:\sActive)?#{APPROV}(?:\sDraft)?#{STD}\s(?<number>[[:alnum:]]+)\s?[\/_]\s?D(?<draft>[\w\.-]+),?\s(?:\w+\s)?(?<year>\d{2,4})/o,
481
+ /^(?<publisher>[\w\/]+)(?:\sActive)?#{APPROV}(?:\sDraft)?#{STD}\s(?<number>[[:alnum:]]+)\/?D?(?<draft>[\d\.]+),?\s\w+\s(?<year>\d{4})/o,
482
+ /^(?<publisher>[A-Z\/]+)\s(?<number>\w+)\/Draft\s(?<draft>[\d.]+),\s\w+\s(?<year>\d{4})/,
483
+ /^(?<publisher>[A-Z\/]+)\sStd\s(?<number>\w+)-(?<year>\d{4})\sDraft\s(?<draft>[\d.]+)/
484
+ create_pubid(Regexp.last_match)
485
+
486
+ # publisher, approval, number, draft
487
+ when /^(?<publisher>[A-Z\/]+)#{APPROVAL}(?:\sDraft)?#{STD}\s(?<number>[[:alnum:]]+)[\/_]D(?<draft>[\w.]+)/o
488
+ create_pubid(Regexp.last_match)
489
+
490
+ # number, draft, year
491
+ when /^(?<number>\w+)\/D(?<draft>[\w.+]+),?\s\w+,?\s(?<year>\d{4})/
492
+ create_pubid(Regexp.last_match)
493
+
494
+ # number, rev, draft
495
+ when /^(?<number>\w+)-REV\/D(?<draft>[\d.]+)/o
496
+ create_pubid(Regexp.last_match)
497
+
498
+ # publisher, number, draft
499
+ when /^(?<publisher>[\w\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>[[:alnum:]]+)[\/_]D(?<draft>[\w.]+)/o
500
+ create_pubid(Regexp.last_match)
501
+
502
+ # publisher, number, year, month
503
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)(?:-\d{4})?,\s(?<month>\w+)\s(?<year>\d{4})/o
504
+ create_pubid(Regexp.last_match)
505
+
506
+ # publisher, number, year, redline
507
+ when /^(?<publisher>[A-Z\/]+)#{STD}\s(?<number>\w+)[:-](?<year>\d{4}).*?\s-\s(?<redline>Redline)/o
508
+ create_pubid(Regexp.last_match)
509
+
510
+ # publisher, number, year
511
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)(?:-|:|,\s(?:\w+\s)?)(?<year>\d{2,4})/o,
512
+ /^(?<publisher>\w+)#{APPROV}(?:\sDraft)?\sStd\s(?<number>\w+)\/\w+\s(?<year>\d{4})/o,
513
+ /^(?<publisher>[\w\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)\/FCD-\w+(?<year>\d{4})/o,
514
+ /^(?<publisher>\w+)#{STD}\sNo(?:\.?\s|\.)(?<number>\w+)\s?(?:-|,\s)(?:\w+\s)?(?<year>\d{4})/o,
515
+ /^(?<publisher>[A-Z\/]+)\sStd\s(?<number>\w+)\/INT-(?<year>\d{4})/,
516
+ /^(?<publisher>ANSI\/\sIEEE)#{STD}\s(?<number>\w+)-(?<year>\d{4})/o
517
+ create_pubid(Regexp.last_match)
518
+
519
+ # publisher, number, part
520
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}\s(?<number>\w+)[.-](?<part>[\d.]+)/o
521
+ create_pubid(Regexp.last_match)
522
+
523
+ # number, part, draft
524
+ when /^(?<number>\w+)\.(?<part>[\w.]+)\/D(?<draft>[\w.]+)/
525
+ create_pubid(Regexp.last_match)
526
+
527
+ # number, part, year
528
+ when /^(\d{2})\sIRE\s(\w+)[\s.](\w+)/ # "IRE #{$2}-#{$3}.#{yn $1}"
529
+ Renderer.new(publisher: "IRE", number: $2, part: $3, year: yn($1))
530
+ when /^(\w+)\.(\w+)-(|d{4})/ then Renderer.new(publisher: "IEEE", number: $1, part: $2, year: $3)
531
+
532
+ # number, year
533
+ when /^(\w+)-(\d{4})\D/ then Renderer.new(publisher: "IEEE", number: $1, year: $2)
534
+
535
+ # publisher, number. The number must have a digit: otherwise a title
536
+ # such as "A Call to Action ..." gives the id `A Call`.
537
+ when /^(?<publisher>[A-Z\/]+)#{APPROV}(?:\sDraft)?#{STD}(?:\sNo\.?)?\s(?<number>[[:alpha:]]*\d\w*)/o
538
+ create_pubid(Regexp.last_match)
539
+
540
+ else
541
+ # Last resort: fall back to the raw stdnumber. (#parse runs this for
542
+ # every doc as the faithfulness reference, so no warning here — an
543
+ # unparseable id surfaces downstream as a nil docnumber.) A record
544
+ # with no standard number (a white paper, a research document) has a
545
+ # category here, e.g. "White Paper". It gets no id, because all such
546
+ # records would otherwise share one id, and so one output file.
547
+ if stdnumber.to_s.match?(/\d/)
548
+ Renderer.new(publisher: "IEEE", number: stdnumber)
549
+ end
550
+ end
551
+ rescue ArgumentError
552
+ nil
553
+ end
554
+
555
+ def create_pubid(regex_match)
556
+ args = regex_match.named_captures
557
+ Renderer.new(
558
+ publisher: args["publisher"] || "IEEE",
559
+ std: !!args["std"],
560
+ number: args["number"],
561
+ part: part(args),
562
+ draft: dn(args["draft"]),
563
+ year: yn(args["year"]),
564
+ month: mn(args["month"]),
565
+ stage: args["stage"],
566
+ rev: args["rev"],
567
+ corr: args["corr"],
568
+ edition: en(args["edition"]),
569
+ amd: args["amd"],
570
+ redline: args["redline"],
571
+ approval: args["approval"],
572
+ status: args["status"]
573
+ )
574
+ end
575
+
576
+ def part(args)
577
+ return unless args.key?("part")
578
+
579
+ [args["part"], args["conformance"]].compact.join("-")
580
+ end
581
+
582
+ # replace subpart's delimiter
583
+ #
584
+ # @param parts [Strong]
585
+ #
586
+ # @return [String]
587
+ def sp(parts)
588
+ parts # .gsub ".", "-"
589
+ end
590
+
591
+ #
592
+ # Convert 2 digits year to 4 digits
593
+ #
594
+ # @param [String] year
595
+ #
596
+ # @return [String, nil] nil if string's length isn't 2 or 4
597
+ #
598
+ def yn(year)
599
+ return year if year.nil? || year.size == 4
600
+
601
+ y = Date.today.year.to_s[2..4].to_i + 1
602
+ case year.to_i
603
+ when 0...y then "20#{year}"
604
+ when y..99 then "19#{year}"
605
+ end
606
+ end
607
+
608
+ #
609
+ # Return number of month
610
+ #
611
+ # @param [String] month monthname
612
+ #
613
+ # @return [String] 2 digits month number
614
+ #
615
+ def mn(month)
616
+ return if month.nil?
617
+
618
+ s = month.to_s.strip
619
+ return s.rjust(2, "0") if s.match?(/\A\d{1,2}\z/) # already numeric
620
+
621
+ # Letters only — drops trailing day/garble digits (e.g. "Sep20" -> "sep").
622
+ key = s.downcase[/\A[a-z]+/]
623
+ return unless key
624
+
625
+ key = MONTH_TYPOS[key] || key
626
+ cap = key.capitalize
627
+ n = Date::ABBR_MONTHNAMES.index(cap) || Date::MONTHNAMES.index(cap)
628
+ # Genuine miss: omit the month (a date-less id parses; a name-suffixed
629
+ # one does not) rather than leak an unparseable name into the id.
630
+ n&.to_s&.rjust(2, "0")
631
+ end
632
+
633
+ #
634
+ # Convert edition name to number
635
+ #
636
+ # @param [Strin] edition
637
+ #
638
+ # @return [String, Integer]
639
+ #
640
+ def en(edition)
641
+ case edition
642
+ when "First" then 1
643
+ when "Second" then 2
644
+ else edition
645
+ end
646
+ end
647
+
648
+ def dn(draftnum)
649
+ draftnum && draftnum.sub(/^\./, "").gsub("-", ".")
650
+ end
651
+
652
+ # Internal fallback renderer. Turns the fields extracted by #parse_fallback
653
+ # into the canonical relaton id string that #parse hands to pubid — it is
654
+ # NOT a public identifier type (pubid's `::Pubid::Ieee::Identifier` is the
655
+ # identifier abstraction). Kept private because the fallback still needs to
656
+ # normalize the ~12% of normtitles pubid can't parse directly.
657
+ class Renderer
658
+ class Id
659
+ # Series IEEE registers as trademarks, so they take ® rather than ™.
660
+ # Mirrors pubid's rule (metanorma/pubid#322): the series is read off
661
+ # the *number*, with a leading project `P` stripped, so `P802.8` counts
662
+ # as 802 while a letter series like `C802.1` does not.
663
+ REGISTERED_SERIES = %w[802 8802 2030].freeze
664
+ # 8802 is the ISO-adopted form of 802 and carries ® on the number
665
+ # alone; every other registered series also needs IEEE as (co)publisher,
666
+ # so `AIEE Std No. 802` and `ANSI 802.1-1985` stay ™.
667
+ ISO_ADOPTED_SERIES = "8802".freeze
668
+
669
+ attr_reader :number, :publisher, :std, :stage, :part, :status, :approval,
670
+ :edition, :draft, :rev, :corr, :amd, :redline, :year, :month
671
+
672
+ def initialize(number:, **args) # rubocop:disable Metrics/AbcSize
673
+ @number = number
674
+ @publisher = args[:publisher]
675
+ @std = args[:std]
676
+ @stage = args[:stage]
677
+ @part = args[:part]
678
+ @status = args[:status]
679
+ @approval = args[:approval]
680
+ @edition = args[:edition]
681
+ @draft = args[:draft]
682
+ @rev = args[:rev]
683
+ @corr = args[:corr]
684
+ @amd = args[:amd]
685
+ @year = args[:year]
686
+ @month = args[:month]
687
+ @redline = args[:redline]
688
+ end
689
+
690
+ def to_s(trademark: false) # rubocop:disable Metrics/AbcSize
691
+ out = number
692
+ out = "Std #{out}" if std
693
+ out = "#{stage} #{out}" if stage
694
+ out = "#{approval} #{out}" if approval
695
+ out = "#{status} #{out}" if status
696
+ out = "#{publisher} #{out}" if publisher
697
+ out += ".#{part}" if part
698
+ out += trademark_symbol if trademark
699
+ out += edition_to_s + draft_to_s + rev_to_s + corr_to_s + amd_to_s
700
+ out + year_to_s + month_to_s + redline_to_s
701
+ end
702
+
703
+ # ® for a registered series, ™ otherwise. See REGISTERED_SERIES.
704
+ def trademark_symbol
705
+ series = number.to_s.sub(/\AP/, "")[/\A\d+/]
706
+ return "™" unless REGISTERED_SERIES.include?(series)
707
+ return "®" if series == ISO_ADOPTED_SERIES
708
+
709
+ publisher.to_s.split("/").include?("IEEE") ? "®" : "™"
710
+ end
711
+
712
+ def edition_to_s = edition ? "/E-#{edition}" : ""
713
+ def draft_to_s = draft ? "/D-#{draft}" : ""
714
+ def rev_to_s = rev ? "/R-#{rev}" : ""
715
+ def corr_to_s = corr ? "/Cor#{corr}" : ""
716
+ def amd_to_s = amd ? "/Amd #{amd}" : ""
717
+ def year_to_s = year ? "-#{year}" : ""
718
+ def month_to_s = month ? "-#{month}" : ""
719
+ def redline_to_s = redline ? " Redline" : ""
720
+ end
721
+
722
+ def initialize(pubid)
723
+ @pubid = (pubid.is_a?(Array) ? pubid : [pubid]).map { |id| Id.new(**id) }
724
+ end
725
+
726
+ # Full id string (all numbers joined). Used when the faithfulness guard
727
+ # keeps the bespoke id because pubid dropped a digit.
728
+ def to_s(trademark: false)
729
+ @pubid.map { |id| id.to_s(trademark: trademark) }.join("/")
730
+ end
731
+
732
+ # Canonical id string. For a dual-numbered id, the second number
733
+ # contributes only the suffix components the first one lacks.
734
+ def to_id # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
735
+ out = @pubid[0].to_s
736
+ if @pubid.size > 1
737
+ out += @pubid[1].edition_to_s if @pubid[0].edition.nil?
738
+ out += @pubid[1].draft_to_s if @pubid[0].draft.nil?
739
+ out += @pubid[1].rev_to_s if @pubid[0].rev.nil?
740
+ out += @pubid[1].corr_to_s if @pubid[0].corr.nil?
741
+ out += @pubid[1].amd_to_s if @pubid[0].amd.nil?
742
+ out += @pubid[1].year_to_s if @pubid[0].year.nil?
743
+ out += @pubid[1].month_to_s if @pubid[0].month.nil?
744
+ out += @pubid[1].redline_to_s unless @pubid[0].redline
745
+ end
746
+ out
747
+ end
748
+ end
749
+
750
+ extend RawbibIdParser
751
+ end
752
+ end
753
+ end