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
@@ -0,0 +1,184 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Pubid
6
+ module Components
7
+ # Supplement component — a structured value-object representing the
8
+ # supplement-specific data (number, date, stage, iteration, type) of a
9
+ # supplement identifier.
10
+ #
11
+ # Union shape across flavors:
12
+ # - type: "amd" (amendment), "cor" (corrigendum), "err" (errata),
13
+ # "sup" (supplement), or a flavor-specific marker.
14
+ # - number: bare sequence number (string preserves leading zeros, "1A"
15
+ # combos, etc.).
16
+ # - date: publication date of the supplement (Components::Date).
17
+ # - range_end_date: end of a date range; presence of this marks the
18
+ # supplement as a range. (NIST/NBS uses supJan1924-Jun1925.)
19
+ # - stage: the stage the supplement is in (e.g., WD Amd, CD Amd).
20
+ # - iteration: stage iteration (e.g., the ".2" in "WD.2 Amd").
21
+ # - has_revision: "suprev" marker — supplement that itself carries a
22
+ # revision. (NIST-specific.)
23
+ # - suffix: escape hatch for patterns not yet modeled.
24
+ #
25
+ # Format-aware via render(context:). The human form stacks fields in the
26
+ # order they appear in the printed supplement; the URN form joins number
27
+ # and year with ":".
28
+ class Supplement < Lutaml::Model::Serializable
29
+ DEFAULT_TYPE = "sup"
30
+
31
+ attribute :type, :string, default: -> { DEFAULT_TYPE }
32
+ attribute :number, :string
33
+ attribute :date, Date
34
+ attribute :range_end_date, Date
35
+ attribute :stage, Stage
36
+ attribute :iteration, Components::Iteration
37
+ attribute :has_revision, :boolean, default: false
38
+ attribute :suffix, :string
39
+
40
+ IDENTITY_FIELDS = %i[
41
+ type number date range_end_date stage iteration has_revision suffix
42
+ ].freeze
43
+
44
+ # Fields whose presence indicates the supplement carries data.
45
+ # `type` is excluded — it always has a value (the default "sup") but
46
+ # doesn't mean the supplement carries content.
47
+ CONTENT_FIELDS = %i[
48
+ number date range_end_date stage iteration has_revision suffix
49
+ ].freeze
50
+
51
+ # True when the supplement carries any data. Distinguishes a present-
52
+ # but-empty supplement (bare marker, "sup") from no supplement at all.
53
+ def present?
54
+ CONTENT_FIELDS.any? { |f| present_value?(public_send(f)) }
55
+ end
56
+
57
+ # True when this supplement spans a date range (start + end set).
58
+ def range?
59
+ date&.present? && range_end_date&.present?
60
+ end
61
+
62
+ def render(context: nil)
63
+ return render_urn if context&.format == :urn
64
+
65
+ render_human
66
+ end
67
+
68
+ def to_s(**opts)
69
+ render(context: opts[:context])
70
+ end
71
+
72
+ def ==(other)
73
+ return false unless other.is_a?(self.class)
74
+
75
+ identity_fields.all? { |f| public_send(f) == other.public_send(f) }
76
+ end
77
+
78
+ alias eql? ==
79
+
80
+ def hash
81
+ @hash ||= [self.class, *identity_fields.map { |f| public_send(f) }].hash
82
+ end
83
+
84
+ private
85
+
86
+ def identity_fields
87
+ IDENTITY_FIELDS
88
+ end
89
+
90
+ def non_empty?(value)
91
+ return false if value.nil?
92
+
93
+ value.is_a?(String) ? !value.empty? : value.present?
94
+ end
95
+
96
+ def present_value?(value)
97
+ return value if [true, false].include?(value)
98
+ return false if value.nil?
99
+
100
+ value.is_a?(String) ? !value.empty? : value.present?
101
+ end
102
+
103
+ def number?
104
+ non_empty?(number)
105
+ end
106
+
107
+ def suffix?
108
+ non_empty?(suffix)
109
+ end
110
+
111
+ def stage_abbr
112
+ return nil if stage.nil? || stage.abbr.nil?
113
+
114
+ abbr = stage.abbr.to_s
115
+ abbr.empty? ? nil : abbr
116
+ end
117
+
118
+ # Human / mr: stack fields in canonical order.
119
+ # "1924" (year)
120
+ # "Jan1924" (month + year)
121
+ # "3/1926" (number + year)
122
+ # "1" (number)
123
+ # "A" (suffix)
124
+ # "Jan1924-Jun1925" (range)
125
+ def render_human
126
+ return early_marker if has_revision || suffix?
127
+ return date_range_string if range?
128
+
129
+ assemble_body
130
+ end
131
+
132
+ def early_marker
133
+ has_revision ? "rev" : suffix.to_s
134
+ end
135
+
136
+ def assemble_body
137
+ body = number_or_date_string
138
+ body += iteration_suffix if include_iteration?
139
+ stage_abbr ? "#{stage_abbr}#{body}" : body
140
+ end
141
+
142
+ def include_iteration?
143
+ iteration && stage_abbr.nil?
144
+ end
145
+
146
+ def render_urn
147
+ return "" unless present?
148
+
149
+ [number&.to_s, date&.year&.to_s].compact.reject(&:empty?).join(":")
150
+ end
151
+
152
+ def iteration_suffix
153
+ "-#{iteration.number}"
154
+ end
155
+
156
+ def date_range_string
157
+ "#{date_string(date)}-#{date_string(range_end_date)}"
158
+ end
159
+
160
+ def number_or_date_string
161
+ return date_string(date) unless number?
162
+
163
+ date&.present? ? "#{number}/#{date_string(date)}" : number.to_s
164
+ end
165
+
166
+ # Render the body of a date fragment preserving the original month
167
+ # abbreviation when month is a non-numeric string. Falls back to
168
+ # Components::Date#render when month is numeric.
169
+ def date_string(date_value)
170
+ return "" unless date_value&.present?
171
+
172
+ if month_abbreviation?(date_value)
173
+ "#{date_value.month}#{date_value.year}"
174
+ else
175
+ date_value.render(context: nil)
176
+ end
177
+ end
178
+
179
+ def month_abbreviation?(date_value)
180
+ date_value.month && !date_value.month.match?(/^\d+$/)
181
+ end
182
+ end
183
+ end
184
+ end
@@ -1,26 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "lutaml/model"
4
- require_relative "../rendering/context" if File.exist?(File.join(__dir__,
5
- "../../rendering/context.rb"))
6
4
 
7
5
  module Pubid
8
6
  module Components
9
7
  # Resource type component (a set of defined resource types)
8
+ #
9
+ # Human render: abbreviation with flavor-specific separator.
10
+ # URN render: type code (e.g. "tr", "ts") per RFC 5141-bis.
10
11
  class Type < Lutaml::Model::Serializable
11
12
  attribute :name, :string
12
13
  attribute :abbr, :string
13
14
  attribute :type_code, :string
14
15
 
15
- # Render type with optional context for flavor-specific separators and default handling
16
- #
17
- # @param context [RenderingContext] rendering context for flavor rules
18
- # @param has_prefix [Boolean] whether there's a prefix (stage or copublisher)
19
- # @return [String] rendered type string
20
16
  def to_s(context: nil, has_prefix: false)
21
17
  return "" unless abbr
22
18
 
23
- # Check if this type should be rendered (not the default)
24
19
  if context && !context.should_render_type?(abbr)
25
20
  return ""
26
21
  end
@@ -29,25 +24,20 @@ module Pubid
29
24
  sep = context.type_separator_for(has_prefix)
30
25
  sep == "" ? abbr : "#{sep}#{abbr}"
31
26
  else
32
- # Default behavior: space after prefix, slash otherwise
33
27
  has_prefix ? " #{abbr}" : "/#{abbr}"
34
28
  end
35
29
  end
36
30
 
37
31
  def render(context: nil)
32
+ return type_code.to_s if context&.urn? && type_code
33
+
38
34
  name.to_s
39
35
  end
40
36
 
41
- # Returns hash code for type component
42
- # @return [Integer] hash code
43
- # @note Memoized for performance
44
37
  def hash
45
38
  @hash ||= [type_code, abbr].compact.map(&:hash).hash
46
39
  end
47
40
 
48
- # Checks equality with another type component
49
- # @param other [Object] object to compare with
50
- # @return [Boolean] true if equal
51
41
  def eql?(other)
52
42
  return false unless other.is_a?(self.class)
53
43
 
@@ -1,18 +1,21 @@
1
- require_relative "stage"
2
1
  # frozen_string_literal: true
3
- require_relative "type"
4
2
 
5
3
  module Pubid
6
4
  module Components
5
+ # TypedStage component (combined stage + type, e.g. "DTR", "FDIS")
6
+ #
7
+ # Human render: typed-stage abbreviation with flavor-specific separator.
8
+ # URN render: stage code (RFC 5141-bis: stage-XX.XX format handled by urn_generator).
7
9
  class TypedStage < Lutaml::Model::Serializable
8
10
  attribute :name, :string
11
+ attribute :code, :string
9
12
  attribute :type_code, :string
10
13
  attribute :stage_code, :string
11
14
  attribute :abbr, :string, collection: true
12
15
  attribute :harmonized_stages, :string, collection: true
13
- attribute :original_abbr, :string # Store the actual parsed abbreviation
14
- attribute :short_abbr, :string # Short form: DAM, COR, FDAM
15
- attribute :long_abbr, :string # Long form: DAmd, Cor, FDAmd
16
+ attribute :original_abbr, :string
17
+ attribute :short_abbr, :string
18
+ attribute :long_abbr, :string
16
19
 
17
20
  def to_stage
18
21
  Stage.new(
@@ -32,21 +35,21 @@ module Pubid
32
35
  end
33
36
 
34
37
  def render(context: nil)
38
+ return code.to_s if context&.urn? && code
39
+
35
40
  abbreviation(format_long: context&.stage_format_long || false)
36
41
  end
37
42
 
38
43
  def abbreviation(format_long: true)
39
- # Use format preference
40
44
  if format_long && long_abbr
41
45
  long_abbr
42
46
  elsif !format_long && short_abbr
43
47
  short_abbr
44
48
  else
45
- abbr.first # Fallback to canonical
49
+ abbr.first
46
50
  end
47
51
  end
48
52
 
49
- # Returns the canonical (normalized) abbreviation, always abbr.first
50
53
  def canonical_abbreviation
51
54
  abbr.first
52
55
  end
@@ -2,13 +2,17 @@
2
2
 
3
3
  module Pubid
4
4
  module Components
5
+ autoload :Adoption, "pubid/components/adoption"
5
6
  autoload :Code, "pubid/components/code"
6
7
  autoload :Date, "pubid/components/date"
7
8
  autoload :Edition, "pubid/components/edition"
9
+ autoload :Iteration, "pubid/components/iteration"
8
10
  autoload :Language, "pubid/components/language"
9
11
  autoload :Locality, "pubid/components/locality"
10
12
  autoload :Publisher, "pubid/components/publisher"
13
+ autoload :Relationship, "pubid/components/relationship"
11
14
  autoload :Stage, "pubid/components/stage"
15
+ autoload :Supplement, "pubid/components/supplement"
12
16
  autoload :Type, "pubid/components/type"
13
17
  autoload :TypedStage, "pubid/components/typed_stage"
14
18
  end
@@ -15,18 +15,24 @@ module Pubid
15
15
  #
16
16
  # Format in YAML files:
17
17
  # plain string match: "IEC 60285-/1:1989" → "IEC 60285-1:1989"
18
- # regex match: "/^NBS CIRC sup$/" → "NBS CIRC 24e7sup"
18
+ # regex match: "/^NBS CIRC sup$/" → "NBS CIRC 24e7sup"
19
+ # regex with flags: "/^nbs\\b/i" → "NBS"
19
20
  #
20
21
  # Plain strings use full-line anchoring (^pattern$).
21
- # Regex patterns are wrapped in /.../ slashes.
22
+ # Regex patterns are wrapped in /.../ slashes with optional trailing flags
23
+ # (i = IGNORECASE, m = MULTILINE, x = EXTENDED) and applied via gsub.
22
24
  class UpdateCodes
23
25
  DATA_DIR = Pathname.new(__dir__).join("../../../data").expand_path
24
26
 
27
+ # Regex literal: /body/flags where flags is optional (i, m, x).
28
+ REGEX_LITERAL = %r{\A/(.*)/([imx]*)\z}m
29
+
25
30
  class << self
26
31
  # Apply update_codes substitutions for the given flavor.
27
32
  #
28
33
  # @param code [String] identifier string to normalize
29
- # @param flavor [Symbol, String] flavor name (e.g., :iso, :iec, :ieee, :nist)
34
+ # @param flavor [Symbol, String] flavor name
35
+ # (e.g., :iso, :iec, :ieee, :nist)
30
36
  # @return [String] normalized identifier string
31
37
  #
32
38
  # @example
@@ -37,9 +43,7 @@ module Pubid
37
43
  return code if codes.nil? || codes.empty?
38
44
 
39
45
  codes.each do |from, to|
40
- code = code.gsub(
41
- from.match?(%r{^/.*/$}) ? Regexp.new(from[1..-2]) : /^#{Regexp.escape(from)}$/, to
42
- )
46
+ code = code.gsub(compile_pattern(from), to.to_s)
43
47
  end
44
48
  code
45
49
  end
@@ -56,13 +60,30 @@ module Pubid
56
60
 
57
61
  # Available flavors that have update_codes files.
58
62
  #
59
- # @return [Array<Symbol>] list of flavors with data/{flavor}/update_codes.yaml
63
+ # @return [Array<Symbol>] flavors with data/{flavor}/update_codes.yaml
60
64
  def flavors
61
65
  @flavors ||= DATA_DIR.children.select(&:directory?).map do |dir|
62
66
  dir.basename.to_s.to_sym
63
67
  end.select { |f| (DATA_DIR / f.to_s / "update_codes.yaml").exist? }
64
68
  end
65
69
 
70
+ # Compile a YAML key into a Regexp. Plain strings are anchored to the
71
+ # full line; regex literals support optional trailing flags.
72
+ def compile_pattern(from)
73
+ match = from.to_s.match(REGEX_LITERAL)
74
+ return /^#{Regexp.escape(from.to_s)}$/ unless match
75
+
76
+ Regexp.new(match[1], compile_options(match[2]))
77
+ end
78
+
79
+ def compile_options(flags)
80
+ options = 0
81
+ options |= Regexp::IGNORECASE if flags.include?("i")
82
+ options |= Regexp::MULTILINE if flags.include?("m")
83
+ options |= Regexp::EXTENDED if flags.include?("x")
84
+ options
85
+ end
86
+
66
87
  private
67
88
 
68
89
  def load_yaml(flavor)
@@ -427,9 +427,6 @@ module Pubid
427
427
  end
428
428
 
429
429
  def self.parse_external_standard(input)
430
- # Ensure full Pubid is loaded (handles Scheme and all flavors)
431
- require_relative "../../pubid" unless defined?(Pubid::Iso) && defined?(Pubid::Iec)
432
-
433
430
  # Try ISO/IEC first (most common)
434
431
  if input.match?(/^(ISO\/IEC|ISO|IEC|CEI|CEI\/IEC)\s/)
435
432
  begin
@@ -4,128 +4,8 @@ module Pubid
4
4
  module Csa
5
5
  module Identifiers
6
6
  class Base < SingleIdentifier
7
- def to_s
8
- prefix = publisher_prefix || "CSA"
9
-
10
- # Handle code_only identifiers (empty string means no prefix)
11
- if prefix == ""
12
- # No prefix for code_only identifiers
13
- parts = []
14
- else
15
- # Determine if we need space after prefix
16
- # CAN/CSA- and CAN3- end with dash, so no space needed
17
- needs_space = !prefix.end_with?("-")
18
-
19
- parts = []
20
- parts << prefix
21
- end
22
-
23
- # Code and year together
24
- code_part = code.to_s if code
25
-
26
- # NO. keyword
27
- if no_number
28
- code_part += " NO. #{no_number}"
29
- end
30
-
31
- # Series prefix and keyword (before year)
32
- if series_prefix
33
- code_part += " #{series_prefix} SERIES"
34
- elsif series
35
- # SERIES without prefix
36
- code_part += " SERIES"
37
- end
38
-
39
- parts << code_part if code_part
40
-
41
- # Year with proper format (colon or dash)
42
- if year
43
- # Use dash if year_format is dash, otherwise colon
44
- separator = year_format == "dash" ? "-" : ":"
45
- year_part = separator
46
- year_part += year_prefix if year_prefix # Add M or F prefix
47
- year_part += "F" if french && year_format != "dash" && !year_prefix # Only add F if no prefix
48
- # Convert 4-digit year back to 2-digit for M/F prefix preservation
49
- # M1983 → M83, F1983 → F83, 1983 → 83, 20xx → xx
50
- # However, preserve original 4-digit format if the input was 4-digit (original_year_4digit)
51
- year_str = year.to_s
52
- year_part += if original_year_4digit
53
- # Preserve 4-digit format (e.g., "M1981" stays "M1981")
54
- year_str
55
- elsif year_prefix&.match?(/^[MF]$/) && year_str.length == 4 && year_str.start_with?("19")
56
- # M/F + 4-digit year (1900s) → convert to 2-digit with prefix
57
- year_str[2..3]
58
- elsif year_str.length == 4 && year_str.start_with?("20")
59
- # 2000s → just last 2 digits
60
- year_str[2..3]
61
- elsif year_str.length == 4 && year_str.start_with?("19") && !original_year_4digit
62
- # 1900s with no M/F prefix, but original was 2-digit (e.g., CAN3-Z299.0-86)
63
- # Convert back to 2-digit
64
- year_str[2..3]
65
- else
66
- # Other formats - keep as-is
67
- year_str
68
- end
69
- parts[-1] += year_part
70
- end
71
-
72
- result = if prefix == ""
73
- # No prefix, just join parts
74
- parts.join(" ")
75
- elsif needs_space
76
- parts.join(" ")
77
- elsif parts.length == 2
78
- # No space after dash-ending prefix - join first two parts directly
79
- # If there are more parts after code, they should still have spaces
80
- parts.join
81
- else
82
- # More than 2 parts shouldn't happen in current design
83
- parts.join
84
- end
85
-
86
- # Reaffirmation - preserve original format and determine spacing
87
- if reaffirmation
88
- # Check if year was originally 2-digit (original_year_4digit flag)
89
- year_was_2digit = !original_year_4digit
90
-
91
- # Check if reaffirmation was originally 4-digit (original_reaffirmation_4digit flag)
92
- reaffirmation_was_4digit = original_reaffirmation_4digit
93
-
94
- # Preserve original reaffirmation format
95
- # If original was 4-digit, keep as 4-digit
96
- # If original was 2-digit, convert from 4-digit storage back to 2-digit
97
- reaffirmation_str = if reaffirmation_was_4digit
98
- # Original was 4-digit, keep as-is
99
- reaffirmation.to_s
100
- elsif reaffirmation.to_s.length == 4 && reaffirmation.to_s.start_with?(
101
- "19", "20"
102
- )
103
- # Original was 2-digit, convert 4-digit storage back to 2-digit
104
- # (R2004) → (R04), (R1994) → (R94)
105
- reaffirmation.to_s[2..3]
106
- else
107
- # Already 2-digit or other format
108
- reaffirmation.to_s
109
- end
110
-
111
- # Determine spacing based on original formats
112
- # Space needed if year is 2-digit and reaffirmation is 4-digit (original format)
113
- # No space if both year and reaffirmation are 2-digit, or both are 4-digit
114
- if year_was_2digit && reaffirmation_was_4digit
115
- # Year was 2-digit, reaffirmation was 4-digit → add space
116
- result += " (R#{reaffirmation_str})"
117
- else
118
- # Both 2-digit, both 4-digit, or other cases → no space
119
- result += "(R#{reaffirmation_str})"
120
- end
121
- end
122
-
123
- # Package (already has leading space from parser)
124
- if package
125
- result += package
126
- end
127
-
128
- result
7
+ def to_s(**opts)
8
+ render(format: :human, **opts)
129
9
  end
130
10
  end
131
11
  end
@@ -21,107 +21,8 @@ module Pubid
21
21
  @code ||= Components::Code.new(value: "#{cec_part.value}-#{no_number.value}")
22
22
  end
23
23
 
24
- def to_s
25
- parts = []
26
-
27
- # Publisher prefix (CSA, CAN/CSA-, CAN3-)
28
- prefix = publisher_prefix || "CSA"
29
-
30
- # Determine if we need space after prefix
31
- # CAN/CSA- and CAN3- end with dash, so no space needed
32
- needs_space = !prefix.end_with?("-")
33
-
34
- parts << prefix unless prefix == ""
35
-
36
- # CEC Part (C22.2, C22.3, etc.)
37
- parts << cec_part.value if cec_part
38
-
39
- # NO. notation - this is the key semantic component
40
- parts << "NO."
41
-
42
- # Number after NO.
43
- parts << no_number.value if no_number
44
-
45
- # Determine separator based on prefix ending
46
- result = if prefix == ""
47
- parts.join(" ")
48
- elsif needs_space
49
- parts.join(" ")
50
- elsif parts.length <= 2
51
- # No space after dash-ending prefix (CAN/CSA-, CAN3-)
52
- # Join first two parts directly, rest with spaces
53
- parts.join
54
- else
55
- parts[0] + parts[1..].join(" ")
56
- end
57
-
58
- # Year with proper format (colon or dash)
59
- if year
60
- # Use dash if year_format is dash, otherwise colon
61
- separator = year_format == "dash" ? "-" : ":"
62
- year_part = separator
63
-
64
- # Convert 4-digit year back to 2-digit for display
65
- year_str = year.to_s
66
- display_year = if year_str.length == 4 && year_str.start_with?("20")
67
- year_str[2..3]
68
- elsif year_str.length == 4 && year_str.start_with?("19")
69
- year_str[2..3]
70
- else
71
- year_str
72
- end
73
-
74
- # Add prefix if present
75
- year_part += if year_prefix
76
- year_prefix + display_year
77
- elsif french && year_format != "dash"
78
- # Only add F if no prefix already set
79
- "F#{display_year}"
80
- else
81
- display_year
82
- end
83
-
84
- result += year_part
85
- end
86
-
87
- # Reaffirmation - preserve original format and determine spacing
88
- if reaffirmation
89
- # Check if year was originally 2-digit (original_year_4digit flag)
90
- year_was_2digit = !original_year_4digit
91
-
92
- # Check if reaffirmation was originally 4-digit (original_reaffirmation_4digit flag)
93
- reaffirmation_was_4digit = original_reaffirmation_4digit
94
-
95
- # Preserve original reaffirmation format
96
- # If original was 4-digit, keep as 4-digit
97
- # If original was 2-digit, convert from 4-digit storage back to 2-digit
98
- reaffirmation_str = if reaffirmation_was_4digit
99
- # Original was 4-digit, keep as-is
100
- reaffirmation.to_s
101
- elsif reaffirmation.to_s.length == 4 && reaffirmation.to_s.start_with?(
102
- "19", "20"
103
- )
104
- # Original was 2-digit, convert 4-digit storage back to 2-digit
105
- # (R2004) → (R04), (R1994) → (R94)
106
- reaffirmation.to_s[2..3]
107
- else
108
- # Already 2-digit or other format
109
- reaffirmation.to_s
110
- end
111
-
112
- # Determine spacing based on original formats
113
- # Space needed if year is 2-digit and reaffirmation is 4-digit (original format)
114
- # No space if both year and reaffirmation are 2-digit, or both are 4-digit
115
- if year_was_2digit && reaffirmation_was_4digit
116
- # Year was 2-digit, reaffirmation was 4-digit → add space
117
- result += " (R#{reaffirmation_str})"
118
- else
119
- # Both 2-digit, both 4-digit, or other cases → no space
120
- result += "(R#{reaffirmation_str})"
121
- end
122
- end
123
-
124
- result
24
+ def to_s(**opts)
25
+ render(format: :human, **opts)
125
26
  end
126
27
  end
127
28
  end