pubid 2.0.0.pre.alpha.2 → 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 (458) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +5 -1
  3. data/data/nist/update_codes.yaml +25 -0
  4. data/lib/pubid/amca/builder.rb +2 -2
  5. data/lib/pubid/amca/identifier.rb +7 -39
  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 -43
  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 -51
  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 -39
  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/identifier.rb +0 -46
  55. data/lib/pubid/asme/identifiers/base.rb +0 -60
  56. data/lib/pubid/asme/renderer.rb +66 -0
  57. data/lib/pubid/asme/urn_parser.rb +31 -0
  58. data/lib/pubid/asme.rb +42 -1
  59. data/lib/pubid/astm/components/code.rb +9 -0
  60. data/lib/pubid/{jis → astm}/components.rb +1 -1
  61. data/lib/pubid/astm/identifier.rb +0 -77
  62. data/lib/pubid/astm/identifiers/adjunct.rb +0 -8
  63. data/lib/pubid/astm/identifiers/data_series.rb +0 -14
  64. data/lib/pubid/astm/identifiers/iso_dual_published.rb +9 -34
  65. data/lib/pubid/astm/identifiers/manual.rb +0 -27
  66. data/lib/pubid/astm/identifiers/monograph.rb +0 -14
  67. data/lib/pubid/astm/identifiers/research_report.rb +0 -7
  68. data/lib/pubid/astm/identifiers/standard.rb +0 -39
  69. data/lib/pubid/astm/identifiers/technical_report.rb +0 -13
  70. data/lib/pubid/astm/identifiers/work_in_progress.rb +0 -11
  71. data/lib/pubid/astm/identifiers.rb +18 -0
  72. data/lib/pubid/astm/renderer.rb +172 -0
  73. data/lib/pubid/astm/single_identifier.rb +0 -10
  74. data/lib/pubid/astm/urn_parser.rb +30 -0
  75. data/lib/pubid/astm.rb +39 -27
  76. data/lib/pubid/bsi/builder.rb +21 -12
  77. data/lib/pubid/bsi/identifier.rb +8 -62
  78. data/lib/pubid/bsi/identifiers/addendum_document.rb +3 -33
  79. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +11 -47
  80. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +11 -38
  81. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +3 -53
  82. data/lib/pubid/bsi/identifiers/amendment.rb +3 -19
  83. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +2 -4
  84. data/lib/pubid/bsi/identifiers/british_standard.rb +2 -1
  85. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +3 -84
  86. data/lib/pubid/bsi/identifiers/committee_document.rb +1 -14
  87. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +3 -84
  88. data/lib/pubid/bsi/identifiers/corrigendum.rb +3 -7
  89. data/lib/pubid/bsi/identifiers/detailed_specification.rb +1 -34
  90. data/lib/pubid/bsi/identifiers/disc.rb +1 -27
  91. data/lib/pubid/bsi/identifiers/draft_document.rb +3 -44
  92. data/lib/pubid/bsi/identifiers/electronic_book.rb +3 -36
  93. data/lib/pubid/bsi/identifiers/expert_commentary.rb +3 -15
  94. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +1 -45
  95. data/lib/pubid/bsi/identifiers/flex.rb +1 -33
  96. data/lib/pubid/bsi/identifiers/handbook.rb +2 -13
  97. data/lib/pubid/bsi/identifiers/index.rb +1 -30
  98. data/lib/pubid/bsi/identifiers/method.rb +1 -39
  99. data/lib/pubid/bsi/identifiers/national_annex.rb +5 -27
  100. data/lib/pubid/bsi/identifiers/practice_guide.rb +2 -4
  101. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +3 -52
  102. data/lib/pubid/bsi/identifiers/published_document.rb +3 -52
  103. data/lib/pubid/bsi/identifiers/section.rb +1 -28
  104. data/lib/pubid/bsi/identifiers/set.rb +3 -17
  105. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +1 -7
  106. data/lib/pubid/bsi/identifiers/supplement_document.rb +3 -21
  107. data/lib/pubid/bsi/identifiers/supplementary_index.rb +1 -44
  108. data/lib/pubid/bsi/identifiers/technical_specification.rb +3 -45
  109. data/lib/pubid/bsi/identifiers/test_method.rb +1 -30
  110. data/lib/pubid/bsi/identifiers/value_added_publication.rb +3 -14
  111. data/lib/pubid/bsi/identifiers.rb +0 -1
  112. data/lib/pubid/bsi/renderer.rb +1050 -0
  113. data/lib/pubid/bsi/single_identifier.rb +6 -70
  114. data/lib/pubid/bsi/urn_generator.rb +2 -3
  115. data/lib/pubid/bsi/urn_parser.rb +52 -0
  116. data/lib/pubid/bsi.rb +224 -1
  117. data/lib/pubid/builder/base.rb +57 -10
  118. data/lib/pubid/bundled_identifier.rb +0 -1
  119. data/lib/pubid/ccsds/builder.rb +4 -3
  120. data/lib/pubid/ccsds/identifier.rb +63 -66
  121. data/lib/pubid/ccsds/identifiers/base.rb +11 -61
  122. data/lib/pubid/ccsds/identifiers/corrigendum.rb +7 -6
  123. data/lib/pubid/ccsds/parser.rb +4 -2
  124. data/lib/pubid/ccsds/supplement_identifier.rb +15 -11
  125. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  126. data/lib/pubid/ccsds/urn_parser.rb +20 -0
  127. data/lib/pubid/ccsds.rb +39 -1
  128. data/lib/pubid/cen_cenelec/builder.rb +12 -14
  129. data/lib/pubid/cen_cenelec/identifier.rb +7 -38
  130. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +13 -4
  131. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +2 -8
  132. data/lib/pubid/cen_cenelec/identifiers/base.rb +5 -41
  133. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +2 -1
  134. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +2 -1
  135. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +2 -25
  136. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +2 -13
  137. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +2 -1
  138. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +4 -7
  139. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +2 -1
  140. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +2 -2
  141. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +2 -1
  142. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +2 -1
  143. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +2 -1
  144. data/lib/pubid/cen_cenelec/renderer.rb +261 -0
  145. data/lib/pubid/cen_cenelec/single_identifier.rb +11 -89
  146. data/lib/pubid/cen_cenelec/urn_generator.rb +6 -6
  147. data/lib/pubid/cen_cenelec/urn_parser.rb +28 -0
  148. data/lib/pubid/cen_cenelec.rb +168 -1
  149. data/lib/pubid/cie/components/code.rb +8 -0
  150. data/lib/pubid/cie/identifier.rb +6 -57
  151. data/lib/pubid/cie/urn_parser.rb +28 -0
  152. data/lib/pubid/cie.rb +43 -1
  153. data/lib/pubid/components/adoption.rb +104 -0
  154. data/lib/pubid/components/code.rb +22 -8
  155. data/lib/pubid/components/date.rb +23 -16
  156. data/lib/pubid/components/edition.rb +9 -6
  157. data/lib/pubid/components/iteration.rb +32 -0
  158. data/lib/pubid/components/language.rb +6 -4
  159. data/lib/pubid/components/locality.rb +10 -1
  160. data/lib/pubid/components/publisher.rb +9 -6
  161. data/lib/pubid/components/relationship.rb +151 -0
  162. data/lib/pubid/components/stage.rb +5 -14
  163. data/lib/pubid/components/supplement.rb +184 -0
  164. data/lib/pubid/components/type.rb +5 -15
  165. data/lib/pubid/components/typed_stage.rb +10 -11
  166. data/lib/pubid/components.rb +4 -1
  167. data/lib/pubid/core/update_codes.rb +28 -7
  168. data/lib/pubid/csa/identifier.rb +0 -59
  169. data/lib/pubid/csa/identifiers/base.rb +2 -122
  170. data/lib/pubid/csa/identifiers/cec.rb +2 -101
  171. data/lib/pubid/csa/identifiers/series.rb +2 -102
  172. data/lib/pubid/csa/renderer.rb +292 -0
  173. data/lib/pubid/csa/urn_generator.rb +1 -1
  174. data/lib/pubid/csa/urn_parser.rb +33 -0
  175. data/lib/pubid/csa.rb +42 -1
  176. data/lib/pubid/etsi/components/code.rb +9 -2
  177. data/lib/pubid/etsi/identifier.rb +0 -43
  178. data/lib/pubid/etsi/identifiers/base.rb +1 -4
  179. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +2 -9
  180. data/lib/pubid/etsi/renderer.rb +42 -0
  181. data/lib/pubid/etsi/urn_parser.rb +34 -0
  182. data/lib/pubid/etsi.rb +42 -1
  183. data/lib/pubid/export/exporter.rb +4 -46
  184. data/lib/pubid/export/flavor_exporter.rb +111 -278
  185. data/lib/pubid/export.rb +0 -6
  186. data/lib/pubid/identifier.rb +2 -17
  187. data/lib/pubid/identifier_facade.rb +114 -0
  188. data/lib/pubid/identifier_metadata.rb +1 -1
  189. data/lib/pubid/idf/builder.rb +3 -3
  190. data/lib/pubid/idf/identifier.rb +3 -66
  191. data/lib/pubid/idf/identifiers/amendment.rb +2 -1
  192. data/lib/pubid/idf/identifiers/corrigendum.rb +2 -1
  193. data/lib/pubid/idf/identifiers/international_standard.rb +2 -1
  194. data/lib/pubid/idf/identifiers/reviewed_method.rb +2 -1
  195. data/lib/pubid/idf/parser.rb +3 -2
  196. data/lib/pubid/idf/renderer.rb +84 -0
  197. data/lib/pubid/idf/supplement_identifier.rb +2 -10
  198. data/lib/pubid/idf/urn_generator.rb +4 -39
  199. data/lib/pubid/idf/urn_parser.rb +25 -0
  200. data/lib/pubid/idf.rb +51 -1
  201. data/lib/pubid/iec/builder.rb +46 -64
  202. data/lib/pubid/iec/components/code.rb +8 -32
  203. data/lib/pubid/iec/components/publisher.rb +0 -1
  204. data/lib/pubid/iec/components.rb +14 -0
  205. data/lib/pubid/iec/identifier.rb +251 -213
  206. data/lib/pubid/iec/identifiers/amendment.rb +2 -3
  207. data/lib/pubid/iec/identifiers/base.rb +8 -32
  208. data/lib/pubid/iec/identifiers/component_specification.rb +3 -3
  209. data/lib/pubid/iec/identifiers/conformity_assessment.rb +1 -2
  210. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +27 -26
  211. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -3
  212. data/lib/pubid/iec/identifiers/fragment_identifier.rb +37 -22
  213. data/lib/pubid/iec/identifiers/guide.rb +0 -2
  214. data/lib/pubid/iec/identifiers/international_standard.rb +2 -3
  215. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +2 -3
  216. data/lib/pubid/iec/identifiers/operational_document.rb +3 -3
  217. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +2 -3
  218. data/lib/pubid/iec/identifiers/sheet_identifier.rb +21 -11
  219. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +3 -3
  220. data/lib/pubid/iec/identifiers/systems_reference_document.rb +2 -3
  221. data/lib/pubid/iec/identifiers/technical_report.rb +2 -3
  222. data/lib/pubid/iec/identifiers/technical_specification.rb +2 -3
  223. data/lib/pubid/iec/identifiers/technology_report.rb +1 -2
  224. data/lib/pubid/iec/identifiers/test_report_form.rb +5 -34
  225. data/lib/pubid/iec/identifiers/vap_identifier.rb +26 -19
  226. data/lib/pubid/iec/identifiers/white_paper.rb +3 -3
  227. data/lib/pubid/iec/identifiers/working_document.rb +4 -48
  228. data/lib/pubid/iec/identifiers.rb +30 -0
  229. data/lib/pubid/iec/parser.rb +13 -12
  230. data/lib/pubid/iec/renderer.rb +254 -0
  231. data/lib/pubid/iec/single_identifier.rb +6 -12
  232. data/lib/pubid/iec/supplement_identifier.rb +58 -54
  233. data/lib/pubid/iec/urn_generator.rb +3 -3
  234. data/lib/pubid/iec/urn_parser.rb +3 -3
  235. data/lib/pubid/iec.rb +40 -68
  236. data/lib/pubid/ieee/builder.rb +12 -12
  237. data/lib/pubid/ieee/components/code.rb +8 -0
  238. data/lib/pubid/ieee/components/draft.rb +14 -0
  239. data/lib/pubid/ieee/components/relationship.rb +5 -149
  240. data/lib/pubid/ieee/identifier.rb +6 -41
  241. data/lib/pubid/ieee/identifiers/adopted_standard.rb +1 -6
  242. data/lib/pubid/ieee/identifiers/base.rb +101 -458
  243. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +1 -7
  244. data/lib/pubid/ieee/identifiers/corrigendum.rb +1 -9
  245. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +1 -7
  246. data/lib/pubid/ieee/identifiers/dual_identifier.rb +1 -1
  247. data/lib/pubid/ieee/identifiers/dual_published.rb +1 -1
  248. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +1 -6
  249. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +1 -7
  250. data/lib/pubid/ieee/identifiers/joint_development.rb +2 -0
  251. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +1 -15
  252. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +1 -3
  253. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +15 -0
  254. data/lib/pubid/ieee/identifiers/redlined_standard.rb +1 -4
  255. data/lib/pubid/ieee/identifiers/si_standard.rb +1 -35
  256. data/lib/pubid/ieee/identifiers/standard.rb +1 -1
  257. data/lib/pubid/ieee/pre_parser.rb +301 -0
  258. data/lib/pubid/ieee/renderer.rb +307 -0
  259. data/lib/pubid/ieee/urn_parser.rb +34 -0
  260. data/lib/pubid/ieee.rb +62 -1
  261. data/lib/pubid/ieee_debug.rb +0 -1
  262. data/lib/pubid/iho/builder.rb +2 -2
  263. data/lib/pubid/iho/identifier.rb +8 -42
  264. data/lib/pubid/iho/identifiers/base.rb +49 -10
  265. data/lib/pubid/iho/parser.rb +3 -3
  266. data/lib/pubid/iho/renderer.rb +30 -0
  267. data/lib/pubid/iho/urn_generator.rb +2 -2
  268. data/lib/pubid/iho/urn_parser.rb +58 -0
  269. data/lib/pubid/iho.rb +50 -1
  270. data/lib/pubid/iso/builder.rb +55 -53
  271. data/lib/pubid/iso/bundled_identifier.rb +51 -0
  272. data/lib/pubid/iso/components/code.rb +7 -19
  273. data/lib/pubid/iso/components/publisher.rb +10 -8
  274. data/lib/pubid/iso/components.rb +2 -4
  275. data/lib/pubid/iso/identifier.rb +218 -252
  276. data/lib/pubid/iso/identifiers/addendum.rb +9 -6
  277. data/lib/pubid/iso/identifiers/amendment.rb +8 -4
  278. data/lib/pubid/iso/identifiers/corrigendum.rb +4 -4
  279. data/lib/pubid/iso/identifiers/data.rb +0 -1
  280. data/lib/pubid/iso/identifiers/directives.rb +8 -2
  281. data/lib/pubid/iso/identifiers/directives_supplement.rb +43 -14
  282. data/lib/pubid/iso/identifiers/extract.rb +2 -2
  283. data/lib/pubid/iso/identifiers/guide.rb +0 -1
  284. data/lib/pubid/iso/identifiers/international_standard.rb +4 -4
  285. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +4 -4
  286. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +10 -4
  287. data/lib/pubid/iso/identifiers/pas.rb +2 -2
  288. data/lib/pubid/iso/identifiers/recommendation.rb +2 -2
  289. data/lib/pubid/iso/identifiers/supplement.rb +11 -3
  290. data/lib/pubid/iso/identifiers/tc_document.rb +44 -15
  291. data/lib/pubid/iso/identifiers/technical_report.rb +4 -4
  292. data/lib/pubid/iso/identifiers/technical_specification.rb +2 -2
  293. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +2 -2
  294. data/lib/pubid/iso/identifiers.rb +0 -1
  295. data/lib/pubid/iso/normalizer.rb +89 -0
  296. data/lib/pubid/iso/parser.rb +22 -4
  297. data/lib/pubid/iso/supplement_identifier.rb +15 -2
  298. data/lib/pubid/iso/urn_generator.rb +66 -182
  299. data/lib/pubid/iso/urn_parser.rb +12 -7
  300. data/lib/pubid/iso.rb +173 -2
  301. data/lib/pubid/itu/builder.rb +0 -12
  302. data/lib/pubid/itu/components/code.rb +8 -0
  303. data/lib/pubid/itu/components.rb +11 -0
  304. data/lib/pubid/itu/identifier.rb +6 -104
  305. data/lib/pubid/itu/identifiers/amendment.rb +0 -2
  306. data/lib/pubid/itu/identifiers/annex.rb +0 -2
  307. data/lib/pubid/itu/identifiers/base.rb +0 -6
  308. data/lib/pubid/itu/identifiers/combined_identifier.rb +0 -2
  309. data/lib/pubid/itu/identifiers/corrigendum.rb +0 -2
  310. data/lib/pubid/itu/identifiers/recommendation.rb +0 -2
  311. data/lib/pubid/itu/identifiers/special_publication.rb +0 -2
  312. data/lib/pubid/itu/identifiers/supplement.rb +0 -2
  313. data/lib/pubid/itu/urn_parser.rb +23 -0
  314. data/lib/pubid/itu.rb +42 -1
  315. data/lib/pubid/jcgm/builder.rb +16 -8
  316. data/lib/pubid/jcgm/identifier.rb +0 -43
  317. data/lib/pubid/jcgm/identifiers/amendment.rb +2 -7
  318. data/lib/pubid/jcgm/identifiers/gum_guide.rb +2 -10
  319. data/lib/pubid/jcgm/renderer.rb +68 -0
  320. data/lib/pubid/jcgm/single_identifier.rb +1 -5
  321. data/lib/pubid/jcgm/urn_generator.rb +4 -6
  322. data/lib/pubid/jcgm/urn_parser.rb +23 -0
  323. data/lib/pubid/jcgm.rb +43 -2
  324. data/lib/pubid/jis/builder.rb +44 -52
  325. data/lib/pubid/jis/identifier.rb +132 -46
  326. data/lib/pubid/jis/identifiers/amendment.rb +1 -1
  327. data/lib/pubid/jis/identifiers/corrigendum.rb +16 -0
  328. data/lib/pubid/jis/identifiers/standard.rb +2 -1
  329. data/lib/pubid/jis/identifiers/technical_report.rb +2 -1
  330. data/lib/pubid/jis/identifiers/technical_specification.rb +2 -1
  331. data/lib/pubid/jis/identifiers.rb +1 -1
  332. data/lib/pubid/jis/parser.rb +31 -5
  333. data/lib/pubid/jis/renderer.rb +69 -0
  334. data/lib/pubid/jis/single_identifier.rb +6 -12
  335. data/lib/pubid/jis/supplement_identifier.rb +17 -14
  336. data/lib/pubid/jis/urn_parser.rb +23 -0
  337. data/lib/pubid/jis.rb +42 -2
  338. data/lib/pubid/nist/builder.rb +63 -1871
  339. data/lib/pubid/nist/caster.rb +1272 -0
  340. data/lib/pubid/nist/circular_supplement_builder.rb +291 -0
  341. data/lib/pubid/nist/components/code.rb +9 -20
  342. data/lib/pubid/nist/components/supplement.rb +2 -2
  343. data/lib/pubid/nist/components.rb +0 -1
  344. data/lib/pubid/nist/identifier.rb +11 -48
  345. data/lib/pubid/nist/identifiers/base.rb +110 -47
  346. data/lib/pubid/nist/identifiers/circular.rb +7 -2
  347. data/lib/pubid/nist/identifiers/circular_supplement.rb +2 -1
  348. data/lib/pubid/nist/identifiers/commercial_standard.rb +2 -1
  349. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +6 -4
  350. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +10 -3
  351. data/lib/pubid/nist/identifiers/crpl_report.rb +8 -8
  352. data/lib/pubid/nist/identifiers/dated_document.rb +49 -0
  353. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +15 -24
  354. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +2 -1
  355. data/lib/pubid/nist/identifiers/handbook.rb +2 -1
  356. data/lib/pubid/nist/identifiers/internal_report.rb +2 -1
  357. data/lib/pubid/nist/identifiers/letter_circular.rb +2 -1
  358. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +5 -4
  359. data/lib/pubid/nist/identifiers/monograph.rb +7 -3
  360. data/lib/pubid/nist/identifiers/report.rb +4 -2
  361. data/lib/pubid/nist/identifiers/special_publication.rb +2 -1
  362. data/lib/pubid/nist/identifiers/technical_note.rb +3 -2
  363. data/lib/pubid/nist/identifiers.rb +1 -0
  364. data/lib/pubid/nist/parser.rb +62 -452
  365. data/lib/pubid/nist/parser_output_normalizer.rb +233 -0
  366. data/lib/pubid/nist/preprocessor.rb +416 -0
  367. data/lib/pubid/nist/renderer.rb +43 -0
  368. data/lib/pubid/nist/router.rb +148 -0
  369. data/lib/pubid/nist/series/base.rb +58 -0
  370. data/lib/pubid/nist/series/crpl.rb +13 -0
  371. data/lib/pubid/nist/series/fips.rb +14 -0
  372. data/lib/pubid/nist/series/ir.rb +60 -0
  373. data/lib/pubid/nist/series/letter_preserving.rb +15 -0
  374. data/lib/pubid/nist/series/mono.rb +19 -0
  375. data/lib/pubid/nist/series/ncstar.rb +20 -0
  376. data/lib/pubid/nist/series.rb +49 -0
  377. data/lib/pubid/nist/supplement_identifier.rb +3 -1
  378. data/lib/pubid/nist/urn_parser.rb +67 -0
  379. data/lib/pubid/nist.rb +82 -4
  380. data/lib/pubid/oiml/components/code.rb +10 -0
  381. data/lib/pubid/oiml/identifier.rb +0 -50
  382. data/lib/pubid/oiml/identifiers/annex.rb +3 -45
  383. data/lib/pubid/oiml/identifiers/base.rb +2 -17
  384. data/lib/pubid/oiml/renderer.rb +161 -0
  385. data/lib/pubid/oiml/single_identifier.rb +6 -45
  386. data/lib/pubid/oiml/supplement_identifier.rb +4 -19
  387. data/lib/pubid/oiml/urn_generator.rb +0 -8
  388. data/lib/pubid/oiml/urn_parser.rb +22 -0
  389. data/lib/pubid/oiml.rb +42 -1
  390. data/lib/pubid/plateau/identifier.rb +7 -41
  391. data/lib/pubid/plateau/identifiers/handbook.rb +1 -3
  392. data/lib/pubid/plateau/identifiers/technical_report.rb +1 -1
  393. data/lib/pubid/plateau/renderer.rb +51 -0
  394. data/lib/pubid/plateau/supplement_identifier.rb +1 -1
  395. data/lib/pubid/plateau/urn_parser.rb +43 -0
  396. data/lib/pubid/plateau.rb +43 -1
  397. data/lib/pubid/renderers/directives_renderer.rb +22 -8
  398. data/lib/pubid/renderers/guide_renderer.rb +4 -2
  399. data/lib/pubid/renderers/human_readable.rb +18 -7
  400. data/lib/pubid/rendering/context.rb +28 -19
  401. data/lib/pubid/rendering.rb +0 -3
  402. data/lib/pubid/sae/components/date.rb +8 -0
  403. data/lib/pubid/sae/components/type.rb +5 -1
  404. data/lib/pubid/sae/identifier.rb +0 -23
  405. data/lib/pubid/sae/identifiers/base.rb +2 -16
  406. data/lib/pubid/sae/renderer.rb +36 -0
  407. data/lib/pubid/sae/urn_generator.rb +2 -10
  408. data/lib/pubid/sae/urn_parser.rb +36 -0
  409. data/lib/pubid/sae.rb +42 -1
  410. data/lib/pubid/urn_generator/base.rb +12 -12
  411. data/lib/pubid/urn_parser/base.rb +81 -0
  412. data/lib/pubid/urn_parser/errors.rb +9 -0
  413. data/lib/pubid/urn_parser.rb +14 -0
  414. data/lib/pubid/version.rb +1 -1
  415. data/lib/pubid.rb +29 -7
  416. data/lib/tasks/website-data.json +1940 -1882
  417. metadata +75 -44
  418. data/lib/pubid/amca/scheme.rb +0 -16
  419. data/lib/pubid/ansi/scheme.rb +0 -15
  420. data/lib/pubid/api/scheme.rb +0 -66
  421. data/lib/pubid/ashrae/scheme.rb +0 -53
  422. data/lib/pubid/asme/scheme.rb +0 -37
  423. data/lib/pubid/astm/scheme.rb +0 -55
  424. data/lib/pubid/bsi/identifiers/base.rb +0 -11
  425. data/lib/pubid/bsi/scheme.rb +0 -243
  426. data/lib/pubid/ccsds/scheme.rb +0 -57
  427. data/lib/pubid/cen_cenelec/scheme.rb +0 -164
  428. data/lib/pubid/cie/scheme.rb +0 -64
  429. data/lib/pubid/components/factory.rb +0 -50
  430. data/lib/pubid/csa/scheme.rb +0 -44
  431. data/lib/pubid/etsi/scheme.rb +0 -42
  432. data/lib/pubid/export/data_class_exporter.rb +0 -59
  433. data/lib/pubid/export/ieee_exporter.rb +0 -78
  434. data/lib/pubid/export/itu_exporter.rb +0 -66
  435. data/lib/pubid/export/nist_exporter.rb +0 -64
  436. data/lib/pubid/export/registry_exporter.rb +0 -90
  437. data/lib/pubid/export/scheme_exporter.rb +0 -70
  438. data/lib/pubid/identifier_registry.rb +0 -198
  439. data/lib/pubid/idf/scheme.rb +0 -61
  440. data/lib/pubid/iec/scheme.rb +0 -71
  441. data/lib/pubid/ieee/scheme.rb +0 -90
  442. data/lib/pubid/iho/scheme.rb +0 -29
  443. data/lib/pubid/iso/identifiers/base.rb +0 -115
  444. data/lib/pubid/iso/scheme.rb +0 -193
  445. data/lib/pubid/itu/scheme.rb +0 -174
  446. data/lib/pubid/jcgm/scheme.rb +0 -60
  447. data/lib/pubid/jis/components/code.rb +0 -59
  448. data/lib/pubid/jis/identifiers/base.rb +0 -72
  449. data/lib/pubid/jis/scheme.rb +0 -49
  450. data/lib/pubid/nist/components/publisher.rb +0 -24
  451. data/lib/pubid/nist/scheme.rb +0 -199
  452. data/lib/pubid/oiml/scheme.rb +0 -46
  453. data/lib/pubid/plateau/scheme.rb +0 -45
  454. data/lib/pubid/rendering/base.rb +0 -73
  455. data/lib/pubid/rendering/common.rb +0 -211
  456. data/lib/pubid/rendering/format.rb +0 -25
  457. data/lib/pubid/sae/scheme.rb +0 -47
  458. data/lib/pubid/scheme.rb +0 -219
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Pubid
6
+ module Components
7
+ # Relationship component — captures how one identifier relates to others.
8
+ #
9
+ # Originally modeled as IEEE's Components::Relationship; promoted to the
10
+ # shared namespace because the same relationship vocabulary applies to
11
+ # ISO, IEC, and other flavors that need to express "revises", "amends",
12
+ # "incorporates", "adopts", etc.
13
+ #
14
+ # Shape:
15
+ # - relationship_type: one of the VALID_TYPES constants below.
16
+ # - related_identifiers: array of identifier objects the relationship
17
+ # points at (e.g., the standards being revised).
18
+ # - intermediate_amendments: optional array of identifiers that amended
19
+ # the related identifier between its original publication and the
20
+ # current revision (renders as "... as amended by ...").
21
+ # - approved_amendments_flag: when true and no intermediate_amendments
22
+ # are listed, renders "... and its approved amendments".
23
+ class Relationship < Lutaml::Model::Serializable
24
+ REVISION_OF = "revision_of"
25
+ AMENDMENT_TO = "amendment_to"
26
+ CORRIGENDUM_TO = "corrigendum_to"
27
+ INCORPORATES = "incorporates"
28
+ INCORPORATING = "incorporating"
29
+ ADOPTION_OF = "adoption_of"
30
+ SUPPLEMENT_TO = "supplement_to"
31
+ DRAFT_AMENDMENT_TO = "draft_amendment_to"
32
+ DRAFT_REVISION_OF = "draft_revision_of"
33
+ REAFFIRMATION_OF = "reaffirmation_of"
34
+ REDESIGNATION_OF = "redesignation_of"
35
+ SUPERSEDES = "supersedes"
36
+ PREVIOUSLY_DESIGNATED_AS = "previously_designated_as"
37
+ INCLUDES = "includes"
38
+
39
+ VALID_TYPES = [
40
+ REVISION_OF,
41
+ AMENDMENT_TO,
42
+ CORRIGENDUM_TO,
43
+ INCORPORATES,
44
+ INCORPORATING,
45
+ ADOPTION_OF,
46
+ SUPPLEMENT_TO,
47
+ DRAFT_AMENDMENT_TO,
48
+ DRAFT_REVISION_OF,
49
+ REAFFIRMATION_OF,
50
+ REDESIGNATION_OF,
51
+ SUPERSEDES,
52
+ PREVIOUSLY_DESIGNATED_AS,
53
+ INCLUDES,
54
+ ].freeze
55
+
56
+ attribute :relationship_type, :string
57
+
58
+ attr_accessor :related_identifiers, :intermediate_amendments,
59
+ :approved_amendments_flag
60
+
61
+ PREFIXES = {
62
+ REVISION_OF => "Revision of",
63
+ AMENDMENT_TO => "Amendment to",
64
+ CORRIGENDUM_TO => "Corrigendum to",
65
+ INCORPORATES => "incorporates",
66
+ ADOPTION_OF => "Adoption of",
67
+ SUPPLEMENT_TO => "Supplement to",
68
+ DRAFT_AMENDMENT_TO => "Draft Amendment to",
69
+ DRAFT_REVISION_OF => "Draft Revision of",
70
+ REAFFIRMATION_OF => "Reaffirmation of",
71
+ REDESIGNATION_OF => "Redesignation of",
72
+ SUPERSEDES => "Supersedes",
73
+ PREVIOUSLY_DESIGNATED_AS => "Previously designated as",
74
+ INCLUDES => "Includes",
75
+ }.freeze
76
+
77
+ def initialize(**args)
78
+ @related_identifiers = args.delete(:related_identifiers)
79
+ @intermediate_amendments = args.delete(:intermediate_amendments)
80
+ @approved_amendments_flag = args.delete(:approved_amendments_flag)
81
+ super
82
+ normalize_incorporating!
83
+ validate_relationship_type if relationship_type
84
+ end
85
+
86
+ def normalize_incorporating!
87
+ return unless relationship_type == INCORPORATING
88
+
89
+ self.relationship_type = INCORPORATES
90
+ end
91
+
92
+ def validate_relationship_type
93
+ return if VALID_TYPES.include?(relationship_type)
94
+
95
+ raise ArgumentError,
96
+ "Invalid relationship type: #{relationship_type}. " \
97
+ "Valid types: #{VALID_TYPES.join(', ')}"
98
+ end
99
+
100
+ def to_s
101
+ return "" if related_identifiers.nil? || related_identifiers.empty?
102
+
103
+ prefix = format_relationship_prefix
104
+ ids = format_identifier_list(related_identifiers)
105
+ return "#{prefix} #{ids}" unless intermediate_clause?
106
+
107
+ "#{prefix} #{ids} #{intermediate_clause}"
108
+ end
109
+
110
+ def render(context: nil)
111
+ to_s
112
+ end
113
+
114
+ private
115
+
116
+ def intermediate_clause?
117
+ (intermediate_amendments && !intermediate_amendments.empty?) ||
118
+ approved_amendments_flag
119
+ end
120
+
121
+ def intermediate_clause
122
+ if intermediate_amendments && !intermediate_amendments.empty?
123
+ "as amended by #{format_identifier_list(intermediate_amendments)}"
124
+ else
125
+ "and its approved amendments"
126
+ end
127
+ end
128
+
129
+ def format_relationship_prefix
130
+ PREFIXES.fetch(relationship_type, relationship_type)
131
+ end
132
+
133
+ # Format a list of identifiers using proper English grammar:
134
+ # - Single: "IEEE Std X"
135
+ # - Two: "IEEE Std X and IEEE Std Y"
136
+ # - Three+: "IEEE Std X, IEEE Std Y, and IEEE Std Z" (Oxford comma)
137
+ def format_identifier_list(identifiers)
138
+ return "" if identifiers.nil? || identifiers.empty?
139
+
140
+ case identifiers.length
141
+ when 1
142
+ identifiers.first.to_s
143
+ when 2
144
+ "#{identifiers.first} and #{identifiers.last}"
145
+ else
146
+ "#{identifiers[0..-2].join(', ')}, and #{identifiers.last}"
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -1,23 +1,19 @@
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
  # Stage component (a set of defined stages)
8
+ #
9
+ # Human render: abbreviation with flavor-specific separator.
10
+ # URN render: stage abbreviation alone (no separator).
10
11
  class Stage < Lutaml::Model::Serializable
11
12
  attribute :name, :string
12
13
  attribute :stage_code, :string
13
14
  attribute :harmonized_stages, :string, collection: true
14
15
  attribute :abbr, :string
15
16
 
16
- # Render stage with optional context for flavor-specific separators
17
- #
18
- # @param context [RenderingContext] rendering context for flavor rules
19
- # @param has_copublisher [Boolean] whether identifier has copublisher
20
- # @return [String] rendered stage string
21
17
  def to_s(context: nil, has_copublisher: false)
22
18
  return "" unless abbr
23
19
 
@@ -25,25 +21,20 @@ module Pubid
25
21
  sep = context.stage_separator_for(has_copublisher:)
26
22
  sep == "" ? abbr : "#{sep}#{abbr}"
27
23
  else
28
- # Default behavior: space after copublisher, slash otherwise
29
24
  has_copublisher ? " #{abbr}" : "/#{abbr}"
30
25
  end
31
26
  end
32
27
 
33
28
  def render(context: nil)
29
+ return abbr.to_s if context&.urn?
30
+
34
31
  abbr.to_s
35
32
  end
36
33
 
37
- # Returns hash code for stage component
38
- # @return [Integer] hash code
39
- # @note Memoized for performance
40
34
  def hash
41
35
  @hash ||= [stage_code, abbr].compact.map(&:hash).hash
42
36
  end
43
37
 
44
- # Checks equality with another stage component
45
- # @param other [Object] object to compare with
46
- # @return [Boolean] true if equal
47
38
  def eql?(other)
48
39
  return false unless other.is_a?(self.class)
49
40
 
@@ -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,22 +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
9
- # Unique per-typed-stage code (e.g. :dtr, :fdisp). Distinct from the
10
- # generic stage_code (e.g. :draft, :fdis) which is shared across types.
11
- # Some index data serializes this code, so it must be resolvable.
12
11
  attribute :code, :string
13
12
  attribute :type_code, :string
14
13
  attribute :stage_code, :string
15
14
  attribute :abbr, :string, collection: true
16
15
  attribute :harmonized_stages, :string, collection: true
17
- attribute :original_abbr, :string # Store the actual parsed abbreviation
18
- attribute :short_abbr, :string # Short form: DAM, COR, FDAM
19
- attribute :long_abbr, :string # Long form: DAmd, Cor, FDAmd
16
+ attribute :original_abbr, :string
17
+ attribute :short_abbr, :string
18
+ attribute :long_abbr, :string
20
19
 
21
20
  def to_stage
22
21
  Stage.new(
@@ -36,21 +35,21 @@ module Pubid
36
35
  end
37
36
 
38
37
  def render(context: nil)
38
+ return code.to_s if context&.urn? && code
39
+
39
40
  abbreviation(format_long: context&.stage_format_long || false)
40
41
  end
41
42
 
42
43
  def abbreviation(format_long: true)
43
- # Use format preference
44
44
  if format_long && long_abbr
45
45
  long_abbr
46
46
  elsif !format_long && short_abbr
47
47
  short_abbr
48
48
  else
49
- abbr.first # Fallback to canonical
49
+ abbr.first
50
50
  end
51
51
  end
52
52
 
53
- # Returns the canonical (normalized) abbreviation, always abbr.first
54
53
  def canonical_abbreviation
55
54
  abbr.first
56
55
  end
@@ -2,14 +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"
8
- autoload :Factory, "pubid/components/factory"
9
+ autoload :Iteration, "pubid/components/iteration"
9
10
  autoload :Language, "pubid/components/language"
10
11
  autoload :Locality, "pubid/components/locality"
11
12
  autoload :Publisher, "pubid/components/publisher"
13
+ autoload :Relationship, "pubid/components/relationship"
12
14
  autoload :Stage, "pubid/components/stage"
15
+ autoload :Supplement, "pubid/components/supplement"
13
16
  autoload :Type, "pubid/components/type"
14
17
  autoload :TypedStage, "pubid/components/typed_stage"
15
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)
@@ -3,62 +3,6 @@
3
3
  module Pubid
4
4
  module Csa
5
5
  class Identifier
6
- # Factory that builds a CSA identifier from a hash of primitives.
7
- # Default is {Identifiers::Standard}.
8
- TYPE_KEY_TO_KLASS = {
9
- standard: "Standard",
10
- bundled: "Bundled",
11
- canadian_adopted: "CanadianAdopted",
12
- cec: "Cec",
13
- combined: "Combined",
14
- csa_adopted: "CsaAdopted",
15
- package: "Package",
16
- series: "Series",
17
- }.freeze
18
-
19
- def self.create(type: nil, **opts)
20
- klass = resolve_create_class(type)
21
- klass.new(**coerce_create_attrs(opts, klass: klass))
22
- end
23
-
24
- def self.resolve_create_class(type)
25
- return Identifiers::Standard if type.nil?
26
-
27
- klass_name = TYPE_KEY_TO_KLASS[type.to_sym]
28
- raise ArgumentError, "Unknown CSA type: #{type.inspect}" unless klass_name
29
-
30
- Identifiers.const_get(klass_name)
31
- end
32
-
33
- def self.coerce_create_attrs(opts, klass:)
34
- attrs = {}
35
-
36
- if (v = opts[:code] || opts[:number])
37
- attrs[:code] = Pubid::Components::Code.new(value: v.to_s)
38
- end
39
-
40
- if opts[:year]
41
- year_str = opts[:year].to_s
42
- attrs[:year] = year_str
43
- # Preserve 4-digit year rendering (e.g. "B51:2024") rather than
44
- # collapsing to "B51:24".
45
- attrs[:original_year_4digit] = year_str.length == 4 unless opts.key?(:original_year_4digit)
46
- end
47
- attrs[:original_year_4digit] = opts[:original_year_4digit] if opts.key?(:original_year_4digit)
48
- attrs[:year_format] = opts[:year_format].to_s if opts[:year_format]
49
- attrs[:year_prefix] = opts[:year_prefix].to_s if opts[:year_prefix]
50
- attrs[:reaffirmation] = opts[:reaffirmation].to_s if opts[:reaffirmation]
51
- attrs[:french] = opts[:french] if opts.key?(:french)
52
- attrs[:has_publisher] = opts.fetch(:has_publisher, true)
53
- attrs[:publisher_prefix] = opts[:publisher_prefix].to_s if opts[:publisher_prefix]
54
- attrs[:series_prefix] = opts[:series_prefix].to_s if opts[:series_prefix]
55
- attrs[:series] = opts[:series] if opts.key?(:series) && [true, false].include?(opts[:series])
56
- attrs[:package] = opts[:package].to_s if opts[:package]
57
- attrs[:no_number] = opts[:no_number].to_s if opts[:no_number]
58
- attrs
59
- end
60
- private_class_method :resolve_create_class, :coerce_create_attrs
61
-
62
6
  def self.parse(input)
63
7
  # Filter out comments
64
8
  return nil if input.start_with?("#")
@@ -483,9 +427,6 @@ module Pubid
483
427
  end
484
428
 
485
429
  def self.parse_external_standard(input)
486
- # Ensure full Pubid is loaded (handles Scheme and all flavors)
487
- require_relative "../../pubid" unless defined?(Pubid::Iso) && defined?(Pubid::Iec)
488
-
489
430
  # Try ISO/IEC first (most common)
490
431
  if input.match?(/^(ISO\/IEC|ISO|IEC|CEI|CEI\/IEC)\s/)
491
432
  begin