pubid 2.0.0.pre.alpha.1 → 2.0.0.pre.alpha.3

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 (463) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +5 -1
  3. data/data/nist/update_codes.yaml +27 -0
  4. data/lib/pubid/amca/builder.rb +2 -2
  5. data/lib/pubid/amca/identifier.rb +7 -0
  6. data/lib/pubid/amca/identifiers/base.rb +0 -26
  7. data/lib/pubid/amca/identifiers/interpretation.rb +0 -17
  8. data/lib/pubid/amca/identifiers/publication.rb +0 -13
  9. data/lib/pubid/amca/renderer.rb +82 -0
  10. data/lib/pubid/amca/single_identifier.rb +0 -23
  11. data/lib/pubid/amca/urn_parser.rb +28 -0
  12. data/lib/pubid/amca.rb +42 -1
  13. data/lib/pubid/ansi/builder.rb +5 -3
  14. data/lib/pubid/ansi/identifier.rb +1 -1
  15. data/lib/pubid/ansi/identifiers/american_national_standard.rb +2 -1
  16. data/lib/pubid/ansi/identifiers/standard.rb +2 -3
  17. data/lib/pubid/ansi/renderer.rb +53 -0
  18. data/lib/pubid/ansi/single_identifier.rb +2 -31
  19. data/lib/pubid/ansi/urn_generator.rb +3 -38
  20. data/lib/pubid/ansi/urn_parser.rb +23 -0
  21. data/lib/pubid/ansi.rb +38 -3
  22. data/lib/pubid/api/builder.rb +29 -74
  23. data/lib/pubid/api/identifier.rb +0 -4
  24. data/lib/pubid/api/identifiers/base.rb +0 -2
  25. data/lib/pubid/api/identifiers/bulletin.rb +0 -2
  26. data/lib/pubid/api/identifiers/continuous_operations_standard.rb +0 -2
  27. data/lib/pubid/api/identifiers/mpms.rb +1 -17
  28. data/lib/pubid/api/identifiers/publication.rb +0 -2
  29. data/lib/pubid/api/identifiers/recommended_practice.rb +0 -2
  30. data/lib/pubid/api/identifiers/specification.rb +0 -2
  31. data/lib/pubid/api/identifiers/standard.rb +0 -2
  32. data/lib/pubid/api/identifiers/technical_report.rb +0 -2
  33. data/lib/pubid/api/identifiers/typeless_standard.rb +1 -14
  34. data/lib/pubid/api/identifiers.rb +18 -0
  35. data/lib/pubid/api/renderer.rb +89 -0
  36. data/lib/pubid/api/single_identifier.rb +1 -13
  37. data/lib/pubid/api/urn_generator.rb +0 -18
  38. data/lib/pubid/api/urn_parser.rb +35 -0
  39. data/lib/pubid/api.rb +51 -5
  40. data/lib/pubid/ashrae/builder.rb +3 -3
  41. data/lib/pubid/ashrae/identifier.rb +6 -0
  42. data/lib/pubid/ashrae/identifiers/addenda_package.rb +0 -10
  43. data/lib/pubid/ashrae/identifiers/addendum.rb +0 -19
  44. data/lib/pubid/ashrae/identifiers/base.rb +3 -0
  45. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +0 -15
  46. data/lib/pubid/ashrae/identifiers/errata.rb +0 -10
  47. data/lib/pubid/ashrae/identifiers/interpretation.rb +0 -10
  48. data/lib/pubid/ashrae/renderer.rb +117 -0
  49. data/lib/pubid/ashrae/single_identifier.rb +0 -13
  50. data/lib/pubid/ashrae/urn_generator.rb +0 -8
  51. data/lib/pubid/ashrae/urn_parser.rb +27 -0
  52. data/lib/pubid/ashrae.rb +42 -1
  53. data/lib/pubid/asme/components/code.rb +10 -2
  54. data/lib/pubid/asme/identifiers/base.rb +0 -60
  55. data/lib/pubid/asme/renderer.rb +66 -0
  56. data/lib/pubid/asme/urn_parser.rb +31 -0
  57. data/lib/pubid/asme.rb +42 -1
  58. data/lib/pubid/astm/components/code.rb +9 -0
  59. data/lib/pubid/{jis → astm}/components.rb +1 -1
  60. data/lib/pubid/astm/identifiers/adjunct.rb +0 -8
  61. data/lib/pubid/astm/identifiers/data_series.rb +0 -14
  62. data/lib/pubid/astm/identifiers/iso_dual_published.rb +9 -34
  63. data/lib/pubid/astm/identifiers/manual.rb +0 -27
  64. data/lib/pubid/astm/identifiers/monograph.rb +0 -14
  65. data/lib/pubid/astm/identifiers/research_report.rb +0 -7
  66. data/lib/pubid/astm/identifiers/standard.rb +0 -39
  67. data/lib/pubid/astm/identifiers/technical_report.rb +0 -13
  68. data/lib/pubid/astm/identifiers/work_in_progress.rb +0 -11
  69. data/lib/pubid/astm/identifiers.rb +18 -0
  70. data/lib/pubid/astm/renderer.rb +172 -0
  71. data/lib/pubid/astm/single_identifier.rb +0 -10
  72. data/lib/pubid/astm/urn_parser.rb +30 -0
  73. data/lib/pubid/astm.rb +39 -27
  74. data/lib/pubid/bsi/builder.rb +21 -12
  75. data/lib/pubid/bsi/identifier.rb +8 -2
  76. data/lib/pubid/bsi/identifiers/addendum_document.rb +3 -33
  77. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +11 -47
  78. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +11 -38
  79. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +3 -53
  80. data/lib/pubid/bsi/identifiers/amendment.rb +3 -19
  81. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +2 -4
  82. data/lib/pubid/bsi/identifiers/british_standard.rb +2 -1
  83. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +3 -84
  84. data/lib/pubid/bsi/identifiers/committee_document.rb +1 -14
  85. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +3 -84
  86. data/lib/pubid/bsi/identifiers/corrigendum.rb +3 -7
  87. data/lib/pubid/bsi/identifiers/detailed_specification.rb +1 -34
  88. data/lib/pubid/bsi/identifiers/disc.rb +1 -27
  89. data/lib/pubid/bsi/identifiers/draft_document.rb +3 -44
  90. data/lib/pubid/bsi/identifiers/electronic_book.rb +3 -36
  91. data/lib/pubid/bsi/identifiers/expert_commentary.rb +3 -15
  92. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +1 -45
  93. data/lib/pubid/bsi/identifiers/flex.rb +1 -33
  94. data/lib/pubid/bsi/identifiers/handbook.rb +2 -13
  95. data/lib/pubid/bsi/identifiers/index.rb +1 -30
  96. data/lib/pubid/bsi/identifiers/method.rb +1 -39
  97. data/lib/pubid/bsi/identifiers/national_annex.rb +5 -27
  98. data/lib/pubid/bsi/identifiers/practice_guide.rb +2 -4
  99. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +3 -52
  100. data/lib/pubid/bsi/identifiers/published_document.rb +3 -52
  101. data/lib/pubid/bsi/identifiers/section.rb +1 -28
  102. data/lib/pubid/bsi/identifiers/set.rb +3 -17
  103. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +1 -7
  104. data/lib/pubid/bsi/identifiers/supplement_document.rb +3 -21
  105. data/lib/pubid/bsi/identifiers/supplementary_index.rb +1 -44
  106. data/lib/pubid/bsi/identifiers/technical_specification.rb +3 -45
  107. data/lib/pubid/bsi/identifiers/test_method.rb +1 -30
  108. data/lib/pubid/bsi/identifiers/value_added_publication.rb +3 -14
  109. data/lib/pubid/bsi/identifiers.rb +0 -1
  110. data/lib/pubid/bsi/renderer.rb +1050 -0
  111. data/lib/pubid/bsi/single_identifier.rb +6 -70
  112. data/lib/pubid/bsi/urn_generator.rb +2 -3
  113. data/lib/pubid/bsi/urn_parser.rb +52 -0
  114. data/lib/pubid/bsi.rb +224 -1
  115. data/lib/pubid/builder/base.rb +57 -10
  116. data/lib/pubid/bundled_identifier.rb +0 -1
  117. data/lib/pubid/ccsds/builder.rb +4 -3
  118. data/lib/pubid/ccsds/identifier.rb +66 -1
  119. data/lib/pubid/ccsds/identifiers/base.rb +11 -50
  120. data/lib/pubid/ccsds/identifiers/corrigendum.rb +7 -6
  121. data/lib/pubid/ccsds/parser.rb +4 -2
  122. data/lib/pubid/ccsds/single_identifier.rb +4 -1
  123. data/lib/pubid/ccsds/supplement_identifier.rb +15 -11
  124. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  125. data/lib/pubid/ccsds/urn_parser.rb +20 -0
  126. data/lib/pubid/ccsds.rb +39 -1
  127. data/lib/pubid/cen_cenelec/builder.rb +12 -14
  128. data/lib/pubid/cen_cenelec/identifier.rb +8 -2
  129. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +13 -4
  130. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +2 -8
  131. data/lib/pubid/cen_cenelec/identifiers/base.rb +5 -41
  132. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +2 -1
  133. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +2 -1
  134. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +2 -25
  135. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +2 -13
  136. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +2 -1
  137. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +4 -7
  138. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +2 -1
  139. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +2 -2
  140. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +2 -1
  141. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +2 -1
  142. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +2 -1
  143. data/lib/pubid/cen_cenelec/renderer.rb +261 -0
  144. data/lib/pubid/cen_cenelec/single_identifier.rb +11 -89
  145. data/lib/pubid/cen_cenelec/urn_generator.rb +6 -6
  146. data/lib/pubid/cen_cenelec/urn_parser.rb +28 -0
  147. data/lib/pubid/cen_cenelec.rb +168 -1
  148. data/lib/pubid/cie/components/code.rb +8 -0
  149. data/lib/pubid/cie/identifier.rb +6 -4
  150. data/lib/pubid/cie/urn_parser.rb +28 -0
  151. data/lib/pubid/cie.rb +43 -1
  152. data/lib/pubid/components/adoption.rb +104 -0
  153. data/lib/pubid/components/code.rb +22 -8
  154. data/lib/pubid/components/date.rb +23 -16
  155. data/lib/pubid/components/edition.rb +9 -6
  156. data/lib/pubid/components/iteration.rb +32 -0
  157. data/lib/pubid/components/language.rb +6 -4
  158. data/lib/pubid/components/locality.rb +10 -1
  159. data/lib/pubid/components/publisher.rb +9 -6
  160. data/lib/pubid/components/relationship.rb +151 -0
  161. data/lib/pubid/components/stage.rb +5 -14
  162. data/lib/pubid/components/supplement.rb +184 -0
  163. data/lib/pubid/components/type.rb +5 -15
  164. data/lib/pubid/components/typed_stage.rb +11 -8
  165. data/lib/pubid/components.rb +4 -0
  166. data/lib/pubid/core/update_codes.rb +28 -7
  167. data/lib/pubid/csa/identifier.rb +0 -3
  168. data/lib/pubid/csa/identifiers/base.rb +2 -122
  169. data/lib/pubid/csa/identifiers/cec.rb +2 -101
  170. data/lib/pubid/csa/identifiers/series.rb +2 -102
  171. data/lib/pubid/csa/renderer.rb +292 -0
  172. data/lib/pubid/csa/urn_generator.rb +1 -1
  173. data/lib/pubid/csa/urn_parser.rb +33 -0
  174. data/lib/pubid/csa.rb +42 -1
  175. data/lib/pubid/etsi/components/code.rb +9 -2
  176. data/lib/pubid/etsi/identifiers/base.rb +1 -4
  177. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +2 -9
  178. data/lib/pubid/etsi/renderer.rb +42 -0
  179. data/lib/pubid/etsi/urn_parser.rb +34 -0
  180. data/lib/pubid/etsi.rb +42 -1
  181. data/lib/pubid/export/exporter.rb +4 -46
  182. data/lib/pubid/export/flavor_exporter.rb +111 -278
  183. data/lib/pubid/export.rb +0 -6
  184. data/lib/pubid/identifier.rb +10 -18
  185. data/lib/pubid/identifier_facade.rb +114 -0
  186. data/lib/pubid/identifier_metadata.rb +1 -1
  187. data/lib/pubid/idf/builder.rb +3 -3
  188. data/lib/pubid/idf/identifier.rb +3 -6
  189. data/lib/pubid/idf/identifiers/amendment.rb +2 -1
  190. data/lib/pubid/idf/identifiers/corrigendum.rb +2 -1
  191. data/lib/pubid/idf/identifiers/international_standard.rb +2 -1
  192. data/lib/pubid/idf/identifiers/reviewed_method.rb +2 -1
  193. data/lib/pubid/idf/parser.rb +3 -2
  194. data/lib/pubid/idf/renderer.rb +84 -0
  195. data/lib/pubid/idf/supplement_identifier.rb +2 -10
  196. data/lib/pubid/idf/urn_generator.rb +4 -39
  197. data/lib/pubid/idf/urn_parser.rb +25 -0
  198. data/lib/pubid/idf.rb +51 -1
  199. data/lib/pubid/iec/builder.rb +48 -65
  200. data/lib/pubid/iec/components/code.rb +9 -32
  201. data/lib/pubid/iec/components/publisher.rb +1 -1
  202. data/lib/pubid/iec/components.rb +14 -0
  203. data/lib/pubid/iec/identifier.rb +276 -3
  204. data/lib/pubid/iec/identifiers/amendment.rb +2 -3
  205. data/lib/pubid/iec/identifiers/base.rb +8 -28
  206. data/lib/pubid/iec/identifiers/component_specification.rb +3 -3
  207. data/lib/pubid/iec/identifiers/conformity_assessment.rb +1 -2
  208. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +27 -30
  209. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -3
  210. data/lib/pubid/iec/identifiers/fragment_identifier.rb +37 -26
  211. data/lib/pubid/iec/identifiers/guide.rb +0 -2
  212. data/lib/pubid/iec/identifiers/international_standard.rb +2 -3
  213. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +2 -3
  214. data/lib/pubid/iec/identifiers/operational_document.rb +3 -3
  215. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +2 -3
  216. data/lib/pubid/iec/identifiers/sheet_identifier.rb +21 -15
  217. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +3 -3
  218. data/lib/pubid/iec/identifiers/systems_reference_document.rb +2 -3
  219. data/lib/pubid/iec/identifiers/technical_report.rb +2 -3
  220. data/lib/pubid/iec/identifiers/technical_specification.rb +2 -3
  221. data/lib/pubid/iec/identifiers/technology_report.rb +1 -2
  222. data/lib/pubid/iec/identifiers/test_report_form.rb +5 -34
  223. data/lib/pubid/iec/identifiers/vap_identifier.rb +26 -23
  224. data/lib/pubid/iec/identifiers/white_paper.rb +3 -3
  225. data/lib/pubid/iec/identifiers/working_document.rb +4 -48
  226. data/lib/pubid/iec/identifiers.rb +30 -0
  227. data/lib/pubid/iec/parser.rb +20 -14
  228. data/lib/pubid/iec/renderer.rb +254 -0
  229. data/lib/pubid/iec/single_identifier.rb +6 -12
  230. data/lib/pubid/iec/supplement_identifier.rb +58 -54
  231. data/lib/pubid/iec/urn_generator.rb +57 -171
  232. data/lib/pubid/iec/urn_parser.rb +53 -252
  233. data/lib/pubid/iec.rb +40 -68
  234. data/lib/pubid/ieee/builder.rb +12 -12
  235. data/lib/pubid/ieee/components/code.rb +8 -0
  236. data/lib/pubid/ieee/components/draft.rb +14 -0
  237. data/lib/pubid/ieee/components/relationship.rb +5 -149
  238. data/lib/pubid/ieee/identifier.rb +6 -0
  239. data/lib/pubid/ieee/identifiers/adopted_standard.rb +1 -6
  240. data/lib/pubid/ieee/identifiers/base.rb +101 -458
  241. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +1 -7
  242. data/lib/pubid/ieee/identifiers/corrigendum.rb +1 -9
  243. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +1 -7
  244. data/lib/pubid/ieee/identifiers/dual_identifier.rb +1 -1
  245. data/lib/pubid/ieee/identifiers/dual_published.rb +1 -1
  246. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +1 -6
  247. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +1 -7
  248. data/lib/pubid/ieee/identifiers/joint_development.rb +2 -0
  249. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +1 -15
  250. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +1 -3
  251. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +15 -0
  252. data/lib/pubid/ieee/identifiers/redlined_standard.rb +1 -4
  253. data/lib/pubid/ieee/identifiers/si_standard.rb +1 -35
  254. data/lib/pubid/ieee/identifiers/standard.rb +1 -1
  255. data/lib/pubid/ieee/pre_parser.rb +301 -0
  256. data/lib/pubid/ieee/renderer.rb +307 -0
  257. data/lib/pubid/ieee/urn_parser.rb +34 -0
  258. data/lib/pubid/ieee.rb +62 -1
  259. data/lib/pubid/ieee_debug.rb +0 -1
  260. data/lib/pubid/iho/builder.rb +2 -2
  261. data/lib/pubid/iho/identifier.rb +8 -0
  262. data/lib/pubid/iho/identifiers/base.rb +49 -10
  263. data/lib/pubid/iho/identifiers/bibliographic.rb +0 -4
  264. data/lib/pubid/iho/identifiers/circular_letter.rb +0 -4
  265. data/lib/pubid/iho/identifiers/miscellaneous.rb +0 -4
  266. data/lib/pubid/iho/identifiers/publication.rb +0 -4
  267. data/lib/pubid/iho/identifiers/standard.rb +0 -4
  268. data/lib/pubid/iho/parser.rb +3 -3
  269. data/lib/pubid/iho/renderer.rb +30 -0
  270. data/lib/pubid/iho/urn_generator.rb +3 -3
  271. data/lib/pubid/iho/urn_parser.rb +58 -0
  272. data/lib/pubid/iho.rb +50 -1
  273. data/lib/pubid/iso/builder.rb +59 -53
  274. data/lib/pubid/iso/bundled_identifier.rb +51 -0
  275. data/lib/pubid/iso/components/code.rb +7 -19
  276. data/lib/pubid/iso/components/publisher.rb +10 -8
  277. data/lib/pubid/iso/components.rb +2 -4
  278. data/lib/pubid/iso/identifier.rb +233 -6
  279. data/lib/pubid/iso/identifiers/addendum.rb +9 -6
  280. data/lib/pubid/iso/identifiers/amendment.rb +8 -4
  281. data/lib/pubid/iso/identifiers/corrigendum.rb +4 -4
  282. data/lib/pubid/iso/identifiers/data.rb +0 -1
  283. data/lib/pubid/iso/identifiers/directives.rb +8 -2
  284. data/lib/pubid/iso/identifiers/directives_supplement.rb +43 -14
  285. data/lib/pubid/iso/identifiers/extract.rb +2 -2
  286. data/lib/pubid/iso/identifiers/guide.rb +0 -1
  287. data/lib/pubid/iso/identifiers/international_standard.rb +4 -4
  288. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +4 -4
  289. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +10 -4
  290. data/lib/pubid/iso/identifiers/pas.rb +2 -2
  291. data/lib/pubid/iso/identifiers/recommendation.rb +2 -2
  292. data/lib/pubid/iso/identifiers/supplement.rb +11 -3
  293. data/lib/pubid/iso/identifiers/tc_document.rb +44 -15
  294. data/lib/pubid/iso/identifiers/technical_report.rb +4 -4
  295. data/lib/pubid/iso/identifiers/technical_specification.rb +2 -2
  296. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +2 -2
  297. data/lib/pubid/iso/identifiers.rb +0 -1
  298. data/lib/pubid/iso/normalizer.rb +89 -0
  299. data/lib/pubid/iso/parser.rb +26 -6
  300. data/lib/pubid/iso/single_identifier.rb +6 -3
  301. data/lib/pubid/iso/supplement_identifier.rb +15 -2
  302. data/lib/pubid/iso/urn_generator.rb +74 -176
  303. data/lib/pubid/iso/urn_parser.rb +28 -9
  304. data/lib/pubid/iso.rb +173 -2
  305. data/lib/pubid/itu/builder.rb +0 -12
  306. data/lib/pubid/itu/components/code.rb +8 -0
  307. data/lib/pubid/itu/components.rb +11 -0
  308. data/lib/pubid/itu/identifier.rb +6 -39
  309. data/lib/pubid/itu/identifiers/amendment.rb +0 -2
  310. data/lib/pubid/itu/identifiers/annex.rb +0 -2
  311. data/lib/pubid/itu/identifiers/base.rb +0 -6
  312. data/lib/pubid/itu/identifiers/combined_identifier.rb +0 -2
  313. data/lib/pubid/itu/identifiers/corrigendum.rb +0 -2
  314. data/lib/pubid/itu/identifiers/recommendation.rb +0 -2
  315. data/lib/pubid/itu/identifiers/special_publication.rb +0 -2
  316. data/lib/pubid/itu/identifiers/supplement.rb +0 -2
  317. data/lib/pubid/itu/urn_parser.rb +23 -0
  318. data/lib/pubid/itu.rb +42 -1
  319. data/lib/pubid/jcgm/builder.rb +16 -8
  320. data/lib/pubid/jcgm/identifiers/amendment.rb +2 -7
  321. data/lib/pubid/jcgm/identifiers/gum_guide.rb +2 -10
  322. data/lib/pubid/jcgm/renderer.rb +68 -0
  323. data/lib/pubid/jcgm/single_identifier.rb +1 -5
  324. data/lib/pubid/jcgm/urn_generator.rb +4 -6
  325. data/lib/pubid/jcgm/urn_parser.rb +23 -0
  326. data/lib/pubid/jcgm.rb +43 -2
  327. data/lib/pubid/jis/builder.rb +44 -52
  328. data/lib/pubid/jis/identifier.rb +132 -3
  329. data/lib/pubid/jis/identifiers/amendment.rb +1 -1
  330. data/lib/pubid/jis/identifiers/corrigendum.rb +16 -0
  331. data/lib/pubid/jis/identifiers/standard.rb +2 -1
  332. data/lib/pubid/jis/identifiers/technical_report.rb +2 -1
  333. data/lib/pubid/jis/identifiers/technical_specification.rb +2 -1
  334. data/lib/pubid/jis/identifiers.rb +1 -1
  335. data/lib/pubid/jis/parser.rb +31 -5
  336. data/lib/pubid/jis/renderer.rb +69 -0
  337. data/lib/pubid/jis/single_identifier.rb +6 -12
  338. data/lib/pubid/jis/supplement_identifier.rb +17 -14
  339. data/lib/pubid/jis/urn_parser.rb +23 -0
  340. data/lib/pubid/jis.rb +42 -2
  341. data/lib/pubid/nist/builder.rb +122 -1761
  342. data/lib/pubid/nist/caster.rb +1272 -0
  343. data/lib/pubid/nist/circular_supplement_builder.rb +291 -0
  344. data/lib/pubid/nist/components/code.rb +9 -20
  345. data/lib/pubid/nist/components/edition.rb +16 -0
  346. data/lib/pubid/nist/components/supplement.rb +88 -21
  347. data/lib/pubid/nist/components.rb +0 -1
  348. data/lib/pubid/nist/identifier.rb +25 -0
  349. data/lib/pubid/nist/identifiers/base.rb +206 -64
  350. data/lib/pubid/nist/identifiers/circular.rb +7 -2
  351. data/lib/pubid/nist/identifiers/circular_supplement.rb +3 -2
  352. data/lib/pubid/nist/identifiers/commercial_standard.rb +2 -1
  353. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +6 -4
  354. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +10 -3
  355. data/lib/pubid/nist/identifiers/crpl_report.rb +8 -11
  356. data/lib/pubid/nist/identifiers/dated_document.rb +49 -0
  357. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +17 -16
  358. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +2 -1
  359. data/lib/pubid/nist/identifiers/handbook.rb +2 -1
  360. data/lib/pubid/nist/identifiers/internal_report.rb +2 -1
  361. data/lib/pubid/nist/identifiers/letter_circular.rb +2 -1
  362. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +5 -4
  363. data/lib/pubid/nist/identifiers/monograph.rb +7 -3
  364. data/lib/pubid/nist/identifiers/report.rb +4 -3
  365. data/lib/pubid/nist/identifiers/special_publication.rb +2 -1
  366. data/lib/pubid/nist/identifiers/technical_note.rb +3 -2
  367. data/lib/pubid/nist/identifiers.rb +1 -0
  368. data/lib/pubid/nist/parser.rb +67 -424
  369. data/lib/pubid/nist/parser_output_normalizer.rb +233 -0
  370. data/lib/pubid/nist/preprocessor.rb +416 -0
  371. data/lib/pubid/nist/renderer.rb +43 -0
  372. data/lib/pubid/nist/router.rb +148 -0
  373. data/lib/pubid/nist/series/base.rb +58 -0
  374. data/lib/pubid/nist/series/crpl.rb +13 -0
  375. data/lib/pubid/nist/series/fips.rb +14 -0
  376. data/lib/pubid/nist/series/ir.rb +60 -0
  377. data/lib/pubid/nist/series/letter_preserving.rb +15 -0
  378. data/lib/pubid/nist/series/mono.rb +19 -0
  379. data/lib/pubid/nist/series/ncstar.rb +20 -0
  380. data/lib/pubid/nist/series.rb +49 -0
  381. data/lib/pubid/nist/supplement_identifier.rb +11 -25
  382. data/lib/pubid/nist/urn_generator.rb +14 -8
  383. data/lib/pubid/nist/urn_parser.rb +67 -0
  384. data/lib/pubid/nist.rb +83 -4
  385. data/lib/pubid/oiml/components/code.rb +10 -0
  386. data/lib/pubid/oiml/identifiers/annex.rb +3 -45
  387. data/lib/pubid/oiml/identifiers/base.rb +2 -17
  388. data/lib/pubid/oiml/renderer.rb +161 -0
  389. data/lib/pubid/oiml/single_identifier.rb +6 -45
  390. data/lib/pubid/oiml/supplement_identifier.rb +4 -19
  391. data/lib/pubid/oiml/urn_generator.rb +0 -8
  392. data/lib/pubid/oiml/urn_parser.rb +22 -0
  393. data/lib/pubid/oiml.rb +42 -1
  394. data/lib/pubid/plateau/identifier.rb +23 -0
  395. data/lib/pubid/plateau/identifiers/handbook.rb +1 -3
  396. data/lib/pubid/plateau/identifiers/technical_report.rb +1 -1
  397. data/lib/pubid/plateau/renderer.rb +51 -0
  398. data/lib/pubid/plateau/supplement_identifier.rb +1 -1
  399. data/lib/pubid/plateau/urn_parser.rb +43 -0
  400. data/lib/pubid/plateau.rb +44 -1
  401. data/lib/pubid/renderers/base.rb +34 -0
  402. data/lib/pubid/renderers/directives_renderer.rb +27 -14
  403. data/lib/pubid/renderers/guide_renderer.rb +7 -1
  404. data/lib/pubid/renderers/human_readable.rb +31 -8
  405. data/lib/pubid/renderers/iwa_renderer.rb +5 -1
  406. data/lib/pubid/renderers/supplement_renderer.rb +4 -1
  407. data/lib/pubid/rendering/context.rb +33 -21
  408. data/lib/pubid/rendering.rb +0 -3
  409. data/lib/pubid/sae/components/date.rb +8 -0
  410. data/lib/pubid/sae/components/type.rb +5 -1
  411. data/lib/pubid/sae/identifiers/base.rb +2 -16
  412. data/lib/pubid/sae/renderer.rb +36 -0
  413. data/lib/pubid/sae/urn_generator.rb +2 -10
  414. data/lib/pubid/sae/urn_parser.rb +36 -0
  415. data/lib/pubid/sae.rb +42 -1
  416. data/lib/pubid/urn_generator/base.rb +12 -12
  417. data/lib/pubid/urn_parser/base.rb +81 -0
  418. data/lib/pubid/urn_parser/errors.rb +9 -0
  419. data/lib/pubid/urn_parser.rb +14 -0
  420. data/lib/pubid/version.rb +1 -1
  421. data/lib/pubid.rb +29 -7
  422. data/lib/tasks/website-data.json +1940 -1882
  423. metadata +77 -43
  424. data/lib/pubid/amca/scheme.rb +0 -16
  425. data/lib/pubid/ansi/scheme.rb +0 -15
  426. data/lib/pubid/api/scheme.rb +0 -66
  427. data/lib/pubid/ashrae/scheme.rb +0 -53
  428. data/lib/pubid/asme/scheme.rb +0 -37
  429. data/lib/pubid/astm/scheme.rb +0 -55
  430. data/lib/pubid/bsi/identifiers/base.rb +0 -11
  431. data/lib/pubid/bsi/scheme.rb +0 -243
  432. data/lib/pubid/ccsds/scheme.rb +0 -57
  433. data/lib/pubid/cen_cenelec/scheme.rb +0 -164
  434. data/lib/pubid/cie/scheme.rb +0 -64
  435. data/lib/pubid/csa/scheme.rb +0 -44
  436. data/lib/pubid/etsi/scheme.rb +0 -42
  437. data/lib/pubid/export/data_class_exporter.rb +0 -59
  438. data/lib/pubid/export/ieee_exporter.rb +0 -78
  439. data/lib/pubid/export/itu_exporter.rb +0 -66
  440. data/lib/pubid/export/nist_exporter.rb +0 -64
  441. data/lib/pubid/export/registry_exporter.rb +0 -90
  442. data/lib/pubid/export/scheme_exporter.rb +0 -70
  443. data/lib/pubid/identifier_registry.rb +0 -198
  444. data/lib/pubid/idf/scheme.rb +0 -61
  445. data/lib/pubid/iec/scheme.rb +0 -71
  446. data/lib/pubid/ieee/scheme.rb +0 -90
  447. data/lib/pubid/iho/scheme.rb +0 -29
  448. data/lib/pubid/iso/identifiers/base.rb +0 -115
  449. data/lib/pubid/iso/scheme.rb +0 -187
  450. data/lib/pubid/itu/scheme.rb +0 -174
  451. data/lib/pubid/jcgm/scheme.rb +0 -60
  452. data/lib/pubid/jis/components/code.rb +0 -59
  453. data/lib/pubid/jis/identifiers/base.rb +0 -72
  454. data/lib/pubid/jis/scheme.rb +0 -49
  455. data/lib/pubid/nist/components/publisher.rb +0 -24
  456. data/lib/pubid/nist/scheme.rb +0 -199
  457. data/lib/pubid/oiml/scheme.rb +0 -46
  458. data/lib/pubid/plateau/scheme.rb +0 -45
  459. data/lib/pubid/rendering/base.rb +0 -73
  460. data/lib/pubid/rendering/common.rb +0 -211
  461. data/lib/pubid/rendering/format.rb +0 -25
  462. data/lib/pubid/sae/scheme.rb +0 -47
  463. data/lib/pubid/scheme.rb +0 -207
@@ -20,13 +20,7 @@ module Pubid
20
20
  ].freeze
21
21
 
22
22
  def to_s
23
- return base_identifier.to_s unless base_identifier
24
-
25
- # Format: BASE/INT or BASE/INT-YEAR
26
- result = base_identifier.to_s
27
- result += "/INT"
28
- result += "-#{int_year}" if int_year
29
- result
23
+ render(format: :human)
30
24
  end
31
25
  end
32
26
  end
@@ -79,6 +79,8 @@ module Pubid
79
79
  end
80
80
 
81
81
  # Convert to string representation
82
+ # JointDevelopment has its own dual-format logic (IEEE vs ISO)
83
+ # that doesn't go through the format registry renderer.
82
84
  # @param format [Symbol] :ieee or :iso (defaults to canonical_format)
83
85
  # @return [String] formatted identifier
84
86
  def to_s(format: canonical_format)
@@ -17,21 +17,7 @@ module Pubid
17
17
  attr_accessor :secondary_identifier
18
18
 
19
19
  def to_s
20
- # Format: PRIMARY/SECONDARY or PRIMARY, SECONDARY
21
- # The format depends on the original input
22
- return primary_identifier.to_s unless secondary_identifier
23
-
24
- # Check if the secondary identifier starts with "C" (like C62.22.1)
25
- # If so, use slash format (cross-reference style)
26
- secondary_code = secondary_identifier.code.to_s
27
- if secondary_code.start_with?("C") && secondary_code.match?(/^C\d+\./)
28
- # Cross-reference format: IEEE Std 1299/C62.22.1-1996
29
- "#{primary_identifier}/#{secondary_identifier}"
30
- else
31
- # Comma format: IEEE Std 960-1989, Std 1177-1989
32
- # But we normalize to "and" format for consistency
33
- "#{primary_identifier} and #{secondary_identifier}"
34
- end
20
+ render(format: :human)
35
21
  end
36
22
 
37
23
  def publisher
@@ -10,9 +10,7 @@ module Pubid
10
10
  attribute :parenthetical_identifier, Base, polymorphic: true
11
11
 
12
12
  def to_s
13
- result = base_identifier.to_s
14
- result += " (#{parenthetical_identifier})" if parenthetical_identifier
15
- result
13
+ render(format: :human)
16
14
  end
17
15
  end
18
16
  end
@@ -9,6 +9,21 @@ module Pubid
9
9
  # This is distinct from a StandardIdentifier - the "P" indicates project status,
10
10
  # not a code prefix like "C" in "C57.12"
11
11
  class ProjectDraftIdentifier < Base
12
+ TYPED_STAGES = [
13
+ Components::TypedStage.new(
14
+ abbr: ["P"],
15
+ stage_code: "draft",
16
+ type_code: "draft",
17
+ ieee_draft_equivalent: "P",
18
+ approval_status: "unapproved",
19
+ project_status: true,
20
+ ),
21
+ ].freeze
22
+
23
+ def self.type
24
+ { key: :P, title: "Project Draft", short: "P" }
25
+ end
26
+
12
27
  # Override initialize to strip "P" prefix from code before creating Code object
13
28
  # The "P" is reflected in the typed_stage, not in the Code component itself
14
29
  def initialize(**args)
@@ -18,10 +18,7 @@ module Pubid
18
18
  attribute :redline, :boolean, default: -> { true }
19
19
 
20
20
  def to_s
21
- result = base_identifier.to_s
22
- result += " (Revision of #{revision_of})" if revision_of
23
- result += " - Redline" if redline
24
- result
21
+ render(format: :human)
25
22
  end
26
23
 
27
24
  def publisher
@@ -31,41 +31,7 @@ module Pubid
31
31
  attr_accessor :draft_obj
32
32
 
33
33
  def to_s
34
- parts = []
35
-
36
- # Publisher (IEEE/ASTM)
37
- parts << "IEEE/ASTM"
38
-
39
- # Type (SI or PSI based on typed_stage)
40
- parts << if typed_stage&.abbr&.include?("PSI")
41
- "PSI"
42
- else
43
- "SI"
44
- end
45
-
46
- # Code (number) with draft version for PSI
47
- code_part = code.to_s
48
- if draft_obj
49
- # Use Draft component's version attribute
50
- code_part += "/D#{draft_obj.version}"
51
- end
52
- parts << code_part if code
53
-
54
- # Date
55
- if month && year
56
- parts << ", #{month} #{year}"
57
- elsif year
58
- parts << "-#{year}"
59
- end
60
-
61
- # Relationships (if present)
62
- result = parts.join(" ")
63
- if relationships && !relationships.empty?
64
- rel_strs = relationships.map(&:to_s)
65
- result += " (#{rel_strs.join(' / ')})"
66
- end
67
-
68
- result
34
+ render(format: :human)
69
35
  end
70
36
  end
71
37
  end
@@ -29,7 +29,7 @@ module Pubid
29
29
  ].freeze
30
30
 
31
31
  def self.type
32
- { key: :std, title: "Standard", short: "Std" }
32
+ { key: :std, web: :standard, title: "Standard", short: "Std" }
33
33
  end
34
34
 
35
35
  # Render standard IEEE format
@@ -0,0 +1,301 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Ieee
5
+ # Pre-parser for IEEE identifiers.
6
+ #
7
+ # Owns all regex/scan/dispatch logic that used to live on Identifiers::Base.parse.
8
+ # Base.parse becomes a thin orchestrator that asks PreParser for a decision
9
+ # and then routes to the right builder.
10
+ module PreParser
11
+ # Outcome of preprocessing an input string.
12
+ #
13
+ # dispatch - Symbol naming the construction strategy to use:
14
+ # :standard - single identifier via parse_single
15
+ # :aiee_simple - delegate to Aiee::Identifier.parse
16
+ # :dual_and - split on " and " (top-level, outside parens)
17
+ # :dual_ampersand - split on " & " (top-level, outside parens)
18
+ # :dual_semicolon - split on "; "
19
+ # :dual_space_separated - split at second publisher occurrence
20
+ # :dual_reaffirmed - (R####) (Revision of ...) collapse + reaffirm
21
+ # :dual_ire - (R####) (IRE identifier) split
22
+ # :aiee_asa_adoption - AIEE identifier with (ASA ...) parenthetical
23
+ # :adopted - parenthetical adoption with foreign identifier
24
+ #
25
+ # input - the (possibly rewritten) input string to feed downstream.
26
+ # parts - array of pre-split strings for dual/adopted dispatches.
27
+ # metadata - hash of extracted signals (e.g. reaffirmed: "2010").
28
+ Result = Struct.new(:dispatch, :input, :parts, :metadata,
29
+ keyword_init: true) do
30
+ def initialize(*)
31
+ super
32
+ self.parts ||= []
33
+ self.metadata ||= {}
34
+ end
35
+ end
36
+
37
+ PUBLISHERS = %w[IEEE AIEE ANSI ASA IEC ISO ASTM NACE NSF ASHRAE NCTA
38
+ AESC].freeze
39
+ private_constant :PUBLISHERS
40
+
41
+ ADOPTION_PREFIXES =
42
+ %w[ANSI ISO IEC IEEE AIEE IRE ASA ASTM CSA ASME NACE NSF ASHRAE NCTA
43
+ AESC].freeze
44
+ private_constant :ADOPTION_PREFIXES
45
+
46
+ NON_ADOPTION_KEYWORDS = %w[
47
+ Revision Revison Amendment Corrigendum Corrigenda incorporates Incorporating
48
+ Includes Incorporates Adoption Supplement Draft\ Amendment DRAFT\ Amendment
49
+ Draft\ Revision Reaffirmation Redesignation redesignated\ as Supersedes
50
+ Supercedes Includes Previously\ designated\ as Notebooks Standard\ Newspaper
51
+ ].freeze
52
+ private_constant :NON_ADOPTION_KEYWORDS
53
+
54
+ class << self
55
+ # Run every preprocessing rule against +input+ and return a Result.
56
+ def preprocess(input)
57
+ input = normalize_comma_separated_dual(input)
58
+
59
+ case detect_dispatch(input)
60
+ when :aiee_simple then Result.new(dispatch: :aiee_simple,
61
+ input: input)
62
+ when :iec_ieee_copublished then Result.new(
63
+ dispatch: :iec_ieee_copublished, input: input,
64
+ )
65
+ when :dual_semicolon then build_dual_semicolon(input)
66
+ when :dual_reaffirmed then build_dual_reaffirmed(input)
67
+ when :dual_ire then build_dual_ire(input)
68
+ when :dual_space_separated then build_dual_space_separated(input)
69
+ when :dual_and then build_dual_and(input)
70
+ when :dual_ampersand then build_dual_ampersand(input)
71
+ when :aiee_asa_adoption then build_aiee_asa_adoption(input)
72
+ when :adopted then build_adopted(input)
73
+ else Result.new(dispatch: :standard,
74
+ input: input)
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ # "IEEE Std 960-1989, Std 1177-1989" → "IEEE Std 960-1989 and IEEE Std 1177-1989"
81
+ def normalize_comma_separated_dual(input)
82
+ input.gsub(/(\d{4}),\s+Std\s/, '\1 and IEEE Std ')
83
+ end
84
+
85
+ # Cheap structural detection that runs before the more expensive
86
+ # splitting / parsing attempts. Returns a dispatch symbol or nil.
87
+ def detect_dispatch(input)
88
+ return :aiee_simple if input.start_with?("AIEE ") && !input.include?("(")
89
+ return :iec_ieee_copublished if input.start_with?("IEC/IEEE ")
90
+ return :dual_semicolon if input.include?("; ")
91
+ return :dual_reaffirmed if reaffirmed_revision_pattern?(input)
92
+ return :dual_ire if ire_dual_pattern?(input)
93
+ return :dual_space_separated if space_separated_dual?(input)
94
+ return :dual_and if input.include?(" and ") && and_outside_parens?(input)
95
+ return :dual_ampersand if input.include?(" & ") && ampersand_outside_parens?(input)
96
+ return :aiee_asa_adoption if aiee_asa_pattern?(input)
97
+ return :adopted if adoption_pattern?(input)
98
+
99
+ nil
100
+ end
101
+
102
+ def reaffirmed_revision_pattern?(input)
103
+ input =~ /\(R(\d{4})\)\s*\(Revision of ([^)]+)\)/ ||
104
+ input =~ /\(Reaffirmed\s+(\d{4})\)\s*\(Revision of ([^)]+)\)/
105
+ end
106
+
107
+ def ire_dual_pattern?(input)
108
+ /\(R\d{4}\)\s*\((\d+\s+IRE[^)]+)\)/.match?(input)
109
+ end
110
+
111
+ def space_separated_dual?(input)
112
+ positions = publisher_positions(input).sort_by { |p| p[:pos] }
113
+ return false if positions.length < 2
114
+
115
+ between = input[positions[0][:pos]..(positions[1][:pos] - 1)]
116
+ !between.include?("/") && !between.include?(" and ") && !between.include?(" & ")
117
+ end
118
+
119
+ def and_outside_parens?(input)
120
+ find_top_level(input, " and ")
121
+ end
122
+
123
+ def ampersand_outside_parens?(input)
124
+ find_top_level(input, " & ")
125
+ end
126
+
127
+ def aiee_asa_pattern?(input)
128
+ input.match?(/^AIEE\s+/) && input.include?("(") && input.include?("ASA")
129
+ end
130
+
131
+ def adoption_pattern?(input)
132
+ return false unless input.include?("(") && input.include?(")")
133
+ return false if input.start_with?("IEC/IEEE ")
134
+
135
+ main_part = input.split("(").first&.strip
136
+ adoption_match = input.match(/\(([^)]+)\)/)
137
+ adoption_part = adoption_match&.captures&.first
138
+ return false if main_part.nil? || adoption_part.nil?
139
+
140
+ return false if non_adoption_keyword?(adoption_part)
141
+
142
+ adoption_part.match?(/\b(#{ADOPTION_PREFIXES.join('|')})\s/) ||
143
+ adoption_part.match?(/^\s*(#{ADOPTION_PREFIXES.join('|')})\b/) ||
144
+ adoption_part.match?(/\bStd\s+\d+/)
145
+ end
146
+
147
+ def non_adoption_keyword?(adoption_part)
148
+ adoption_part.match?(/^\s*(#{NON_ADOPTION_KEYWORDS.join('|')})/i)
149
+ end
150
+
151
+ # Locate all positions where a known publisher appears at top level
152
+ # (not nested inside parentheses).
153
+ def publisher_positions(input)
154
+ positions = []
155
+ PUBLISHERS.each do |pub|
156
+ regex = /(?:^|\s)(#{Regexp.escape(pub)})(?:\s|\/)/
157
+ input.scan(regex) do
158
+ match_pos = Regexp.last_match.begin(1)
159
+ before_match = input[0...match_pos]
160
+ next if before_match.count("(") > before_match.count(")")
161
+
162
+ positions << { pos: match_pos, publisher: pub }
163
+ end
164
+ end
165
+ positions
166
+ end
167
+
168
+ # Walk +input+ looking for +marker+ at paren depth zero.
169
+ def find_top_level(input, marker)
170
+ paren_depth = 0
171
+ input.each_char.with_index do |char, i|
172
+ paren_depth += 1 if char == "("
173
+ paren_depth -= 1 if char == ")"
174
+ return true if paren_depth.zero? && input[i..(i + marker.length - 1)] == marker
175
+ end
176
+ false
177
+ end
178
+
179
+ # ---- builders for each dispatch ----
180
+
181
+ def build_dual_semicolon(input)
182
+ parts = input.split("; ")
183
+ unless parts.length == 2
184
+ return Result.new(dispatch: :standard,
185
+ input: input)
186
+ end
187
+
188
+ Result.new(dispatch: :dual_semicolon, input: input,
189
+ parts: [parts[0].strip, parts[1].strip])
190
+ end
191
+
192
+ def build_dual_reaffirmed(input)
193
+ year_match = input.match(/\((?:R|Reaffirmed\s+)(\d{4})\)\s*\(Revision of ([^)]+)\)/)
194
+ return Result.new(dispatch: :standard, input: input) unless year_match
195
+
196
+ year = year_match[1]
197
+ rewritten = input.sub(
198
+ /\((?:R|Reaffirmed\s+)\d{4}\)\s*\(Revision of ([^)]+)\)/, "(Revision of \\1)"
199
+ )
200
+ Result.new(dispatch: :dual_reaffirmed, input: rewritten,
201
+ metadata: { reaffirmed: year })
202
+ end
203
+
204
+ def build_dual_ire(input)
205
+ main_part = input.split(" (R").first&.strip
206
+ reaffirmed_match = input.match(/\(R(\d{4})\)/)
207
+ ire_match = input.match(/\((\d+\s+IRE[^)]+)\)/)
208
+ unless main_part && reaffirmed_match && ire_match
209
+ return Result.new(dispatch: :standard,
210
+ input: input)
211
+ end
212
+
213
+ Result.new(dispatch: :dual_ire, input: input,
214
+ parts: [main_part, ire_match[1]],
215
+ metadata: { reaffirmed: reaffirmed_match[1] })
216
+ end
217
+
218
+ def build_dual_space_separated(input)
219
+ positions = publisher_positions(input).sort_by { |p| p[:pos] }
220
+ if positions.length < 2
221
+ return Result.new(dispatch: :standard,
222
+ input: input)
223
+ end
224
+
225
+ first_pub = positions[0]
226
+ second_pub = positions[1]
227
+ between = input[first_pub[:pos]..(second_pub[:pos] - 1)]
228
+ if between.include?("/") || between.include?(" and ")
229
+ return Result.new(dispatch: :standard,
230
+ input: input)
231
+ end
232
+
233
+ split_pos = second_pub[:pos]
234
+ split_pos -= 1 while split_pos.positive? && input[split_pos - 1] == " "
235
+
236
+ Result.new(dispatch: :dual_space_separated, input: input,
237
+ parts: [input[0...split_pos].strip, input[split_pos..].strip])
238
+ end
239
+
240
+ def build_dual_and(input)
241
+ position = top_level_position(input, " and ")
242
+ return Result.new(dispatch: :standard, input: input) unless position
243
+
244
+ Result.new(dispatch: :dual_and, input: input,
245
+ parts: [input[0...position].strip,
246
+ input[(position + 5)..].strip])
247
+ end
248
+
249
+ def build_dual_ampersand(input)
250
+ parts = input.split(" & ")
251
+ unless parts.length == 2
252
+ return Result.new(dispatch: :standard,
253
+ input: input)
254
+ end
255
+
256
+ Result.new(dispatch: :dual_ampersand, input: input,
257
+ parts: [parts[0].strip, parts[1].strip])
258
+ end
259
+
260
+ def build_aiee_asa_adoption(input)
261
+ main_part = input.split("(").first&.strip
262
+ adoption_match = input.match(/\((ASA[^)]+)\)/)
263
+ unless main_part && adoption_match
264
+ return Result.new(dispatch: :standard,
265
+ input: input)
266
+ end
267
+
268
+ Result.new(dispatch: :aiee_asa_adoption, input: input,
269
+ parts: [main_part, adoption_match.captures.first])
270
+ end
271
+
272
+ def build_adopted(input)
273
+ main_part = input.split("(").first&.strip
274
+ adoption_match = input.match(/\(([^)]+)\)/)
275
+ adoption_part = adoption_match&.captures&.first
276
+ unless main_part && adoption_part
277
+ return Result.new(dispatch: :standard,
278
+ input: input)
279
+ end
280
+
281
+ Result.new(dispatch: :adopted, input: input,
282
+ parts: [main_part, adoption_part])
283
+ end
284
+
285
+ # Return the index where +marker+ first occurs at paren depth zero,
286
+ # or nil if no such occurrence exists.
287
+ def top_level_position(input, marker)
288
+ paren_depth = 0
289
+ input.each_char.with_index do |char, i|
290
+ paren_depth += 1 if char == "("
291
+ paren_depth -= 1 if char == ")"
292
+ if paren_depth.zero? && input[i..(i + marker.length - 1)] == marker
293
+ return i
294
+ end
295
+ end
296
+ nil
297
+ end
298
+ end
299
+ end
300
+ end
301
+ end