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
@@ -6,6 +6,13 @@ module Pubid
6
6
  # Base NIST/NBS identifier class
7
7
  # Each series type inherits from this and overrides series_code
8
8
  class Base < Pubid::Identifier
9
+ # Mark every NIST identifier as a member of the Pubid::Nist::Identifier
10
+ # facade module so `id.is_a?(Pubid::Nist::Identifier)` and
11
+ # `Pubid::Nist::Identifier === id` hold. The module carries only
12
+ # singleton methods (parse/from_hash), so this adds ancestry for the
13
+ # identity check without injecting any instance behavior.
14
+ include Pubid::Nist::Identifier
15
+
9
16
  # Default: no typed stages. Subclasses override as needed.
10
17
  def self.typed_stages
11
18
  []
@@ -15,7 +22,11 @@ module Pubid
15
22
  #
16
23
  # @return [String] URN representation
17
24
 
18
- attribute :publisher, Components::Publisher
25
+ # Plain string ("NIST"/"NBS"), not a Components::Publisher wrapper: the
26
+ # value is a single token, so a string serializes flat
27
+ # (`publisher: NBS`, not `publisher: {publisher: NBS}`) and accepts the
28
+ # raw string the circular/supplement builders pass straight through.
29
+ attribute :publisher, :string
19
30
  attribute :series, Components::Code # Set by Builder from parsed data
20
31
  attribute :number, Components::Code
21
32
 
@@ -30,7 +41,13 @@ module Pubid
30
41
  attribute :translation_component, Components::Translation
31
42
  attribute :issue_number, Components::IssueNumber
32
43
  attribute :parsed_format, :string # :mr, :short, :long, :abbrev
33
- attribute :publisher_was_parsed, :boolean, default: -> { false }
44
+ # Whether the publisher prefix (NIST/NBS) should be rendered. Defaults
45
+ # to true so the common publisher-bearing id need not serialize the
46
+ # flag at all — the Builder only assigns it (false) for prefix-less
47
+ # inputs, so `to_hash` carries `publisher_was_parsed: false` only in
48
+ # that case and omits it otherwise. (lutaml emits a boolean iff it was
49
+ # explicitly assigned; an omitted key loads as this default.)
50
+ attribute :publisher_was_parsed, :boolean, default: -> { true }
34
51
 
35
52
  # LEGACY attributes (keep for backward compatibility during migration)
36
53
  attribute :parts, Components::Code, collection: true
@@ -50,10 +67,13 @@ module Pubid
50
67
  attribute :update_year, :string
51
68
  attribute :addendum, :string
52
69
  attribute :addendum_number, :string
53
- attribute :supplement, :string
54
- attribute :supplement_date_range_start, :string # For date ranges like Jan1924-Jan1926
55
- attribute :supplement_date_range_end, :string
56
- attribute :supplement_has_revision, :boolean, default: -> { false }
70
+ # Single source of truth for the supplement: a structured component with
71
+ # isolated parts (number / year / month / date-range / revision), so a
72
+ # supplement's year is queryable independently of its number. Presence
73
+ # (non-nil) means "is a supplement"; an all-empty component is a bare
74
+ # "sup" marker. Replaces the former flat :supplement string plus the
75
+ # separate date-range/has_revision fields.
76
+ attribute :supplement, Components::Supplement
57
77
  attribute :errata, :string
58
78
  attribute :index, :string
59
79
  attribute :insert, :string
@@ -84,6 +104,91 @@ module Pubid
84
104
  # See lib/pubid/nist/builder.rb lines 368-472 for compound number logic
85
105
  end
86
106
 
107
+ # Attributes that are build artifacts or rendering aliases, not part
108
+ # of an identifier's logical identity. They diverge between equally-
109
+ # valid spellings of the same id (e.g. long "Rev. 1" vs short "r1"):
110
+ # - edition_component: redundant alias of :edition
111
+ # - first_number/second_number: decomposed parts of the canonical
112
+ # :number, retained from the parse for building
113
+ # - parsed_format: records the input format for round-trip rendering
114
+ EQUALITY_IGNORED_ATTRS = %i[
115
+ edition_component first_number second_number parsed_format
116
+ ].freeze
117
+
118
+ # Logical identity comparison: equal when every attribute except the
119
+ # build artifacts/aliases above matches. (Edition#== already ignores
120
+ # its rendering-only original_prefix.)
121
+ def ==(other)
122
+ return false unless other.instance_of?(self.class)
123
+
124
+ self.class.attributes.each_key.all? do |name|
125
+ EQUALITY_IGNORED_ATTRS.include?(name) || public_send(name) == other.public_send(name)
126
+ end
127
+ end
128
+
129
+ alias eql? ==
130
+
131
+ def hash
132
+ vals = self.class.attributes.each_key.reject do |name|
133
+ EQUALITY_IGNORED_ATTRS.include?(name)
134
+ end.map { |name| public_send(name) }
135
+ [self.class, *vals].hash
136
+ end
137
+
138
+ # Wildcard / partial-identifier match. Treats +self+ as a QUERY pattern
139
+ # and +candidate+ as a concrete document: every ID part SET on the query
140
+ # must equal the candidate's, while parts left unset (nil/empty) are
141
+ # wildcards that match any value. So a query carrying no edition and no
142
+ # supplement matches that document across ALL editions, years, and
143
+ # supplements — the basis for "select docs by ID parts".
144
+ #
145
+ # Asymmetric (unlike ==): "NBS CIRC 25".matches?("NBS CIRC 25sup1924")
146
+ # is true, but not the reverse. The candidate must be the same class or
147
+ # a subclass so series-level identity still holds.
148
+ def matches?(candidate)
149
+ return false unless candidate.is_a?(self.class)
150
+
151
+ self.class.attributes.each_key.all? do |name|
152
+ next true if EQUALITY_IGNORED_ATTRS.include?(name)
153
+
154
+ query_val = public_send(name)
155
+ next true if query_val.nil?
156
+ next true if query_val.is_a?(String) && query_val.empty?
157
+ next true if query_val.is_a?(Array) && query_val.empty?
158
+
159
+ query_val == candidate.public_send(name)
160
+ end
161
+ end
162
+
163
+ # Return a copy with the named attributes nil'd. Overrides
164
+ # Pubid::Identifier#exclude because NIST's initialize is keyword-only
165
+ # (initialize(**attributes)) while the inherited exclude rebuilds via
166
+ # the positional self.class.new(attrs) form — passing a positional
167
+ # hash to a keyword-only initializer raises ArgumentError. Rebuild
168
+ # with the keyword splat instead.
169
+ def exclude(*args)
170
+ excluded_args = args.dup
171
+ excluded_args << :date if excluded_args.delete(:year)
172
+
173
+ attrs = self.class.attributes.each_with_object({}) do |(name, _), h|
174
+ h[name] = excluded_args.include?(name) ? nil : public_send(name)
175
+ end
176
+ self.class.new(**attrs)
177
+ end
178
+
179
+ # Short-form supplement fragment ("sup", "sup1924", "supJan1924",
180
+ # "suprev", " supJun1925-Jun1926"), rendered from the structured
181
+ # component. A present-but-empty component is the bare "sup" marker; a
182
+ # number-less date range gets the leading space the number would have
183
+ # supplied. Shared by base and the per-series to_short_style overrides.
184
+ def supplement_short
185
+ return "" unless supplement
186
+
187
+ prefix = supplement.range? && !number ? " " : ""
188
+ rendered = supplement.to_s(:short)
189
+ prefix + (rendered.empty? ? "sup" : rendered)
190
+ end
191
+
87
192
  # Compute revision from edition component for backward compatibility
88
193
  # @return [String, nil] revision string (e.g., "r5") or nil
89
194
  def revision
@@ -107,6 +212,23 @@ module Pubid
107
212
  translation_component
108
213
  end
109
214
 
215
+ # Override parent render to pass NIST-specific format option through
216
+ # to the renderer. Pubid::Identifier#render only forwards
217
+ # :with_edition; NIST needs :nist_format for multi-format support.
218
+ def render(format: :human, **opts)
219
+ registry = self.class.format_registry
220
+ unless registry
221
+ raise ArgumentError, "No format registry configured on #{self.class}"
222
+ end
223
+
224
+ renderer = registry.renderer_for(format)
225
+ unless renderer
226
+ raise ArgumentError, "No renderer registered for format: #{format}"
227
+ end
228
+
229
+ renderer.new(self).render(**opts)
230
+ end
231
+
110
232
  # Generate identifier string in specified format
111
233
  # @param format [:full, :long, :abbreviated, :short, :mr] output format
112
234
  def to_s(format = nil)
@@ -116,20 +238,7 @@ module Pubid
116
238
  # Default to parsed_format if available (preserves input format on round-trip)
117
239
  # Falls back to :short format for output (normalization)
118
240
  # Explicit format parameter always overrides parsed_format
119
- effective_format = format || parsed_format&.to_sym || :short
120
- effective_format = effective_format.to_sym if effective_format.is_a?(String)
121
- case effective_format
122
- when :full, :long
123
- to_full_style
124
- when :abbreviated, :abbrev
125
- to_abbreviated_style
126
- when :short
127
- to_short_style
128
- when :mr
129
- to_mr_style
130
- else
131
- to_short_style
132
- end
241
+ render(format: :human, nist_format: format || parsed_format&.to_sym || :short)
133
242
  end
134
243
 
135
244
  # Returns weight based on amount of defined attributes
@@ -198,7 +307,7 @@ module Pubid
198
307
  match ? match[1].to_i : nil
199
308
  end
200
309
 
201
- private
310
+ public
202
311
 
203
312
  def to_full_style
204
313
  # "National Institute of Standards and Technology Special Publication 800-27, Revision A"
@@ -300,15 +409,37 @@ module Pubid
300
409
  result += " #{number}" if number
301
410
  result += parts.map { |p| "-#{p}" }.join if parts&.any?
302
411
 
303
- # NEW: Use Volume and Part components (v6n1 notation for CSM, pt1 for SP)
304
- if volume.is_a?(Components::Volume) && part.is_a?(Components::Part)
412
+ # Append every optional component the parser may have attached
413
+ # (volume, part, edition, version, supplement, update, stage, ...).
414
+ # Shared with the lossy subclasses so they cannot silently drop a
415
+ # distinguishing component and collide with another document.
416
+ result += append_short_components
417
+
418
+ result
419
+ end
420
+
421
+ # Render the optional component "tail" that follows
422
+ # publisher/series/number in short (human) form. Extracted from
423
+ # #to_short_style so subclasses that build a series-specific prefix can
424
+ # reuse it instead of hand-listing components (and forgetting some).
425
+ #
426
+ # skip_part: true lets a series that renders its part differently
427
+ # (e.g. FIPS uses dash "-1", not "pt1") emit the part itself and skip
428
+ # the generic part rendering here, while still getting volume/edition/
429
+ # supplement/etc.
430
+ def append_short_components(skip_part: false)
431
+ result = ""
432
+ effective_part = skip_part ? nil : part
433
+
434
+ # Volume and Part components (v6n1 notation for CSM, pt1 for SP)
435
+ if volume.is_a?(Components::Volume) && effective_part.is_a?(Components::Part)
305
436
  # CSM series: v#n# notation
306
- result += " #{volume}#{part}"
307
- elsif part.is_a?(Components::Part)
437
+ result += " #{volume}#{effective_part}"
438
+ elsif effective_part.is_a?(Components::Part)
308
439
  # SP and other series: use Part.type to determine format
309
- result += part.to_s
440
+ result += effective_part.to_s
310
441
  # Legacy: Render standalone volume (not part of v#n#)
311
- elsif volume && !issue_number && !part
442
+ elsif volume && !issue_number && !effective_part
312
443
  vol_str = volume.is_a?(Components::Volume) ? volume.to_s : "v#{volume}"
313
444
  result += vol_str
314
445
  elsif volume && issue_number
@@ -317,7 +448,7 @@ module Pubid
317
448
  result += "#{vol_str}n#{issue_number.number}"
318
449
  end
319
450
 
320
- # NEW: Use edition component properly (e2, e2021, r5, -3)
451
+ # Use edition component properly (e2, e2021, r5, -3)
321
452
  # NO space before edition when number present (per NIST spec)
322
453
  # Only add space for bare edition (no number case) or if original_prefix has specific format
323
454
  if edition
@@ -333,30 +464,22 @@ module Pubid
333
464
  end
334
465
  end
335
466
 
336
- # V2: Use version_component if available, else use version string
467
+ # Use version_component if available, else use version string.
468
+ # Attach directly (no leading space) to match edition rendering
469
+ # (e.g. "800-53r5"), so version reads "800-45ver2" not
470
+ # "800-45 ver2".
337
471
  if version_component
338
- result += " #{version_component.to_s(:short)}"
472
+ result += version_component.to_s(:short)
339
473
  elsif version
340
- result += " Ver. #{version}"
474
+ result += "ver#{version}"
341
475
  end
342
476
 
343
- # Add supplement with date range support - FIX: proper spacing
344
- if supplement_date_range_start && supplement_date_range_end
345
- result += "supp#{supplement_date_range_start}-#{supplement_date_range_end}"
346
- elsif supplement_has_revision
347
- result += "supprev"
348
- elsif supplement && !supplement.empty?
349
- # Smart dash logic:
350
- # - If supplement starts with letter (month like "Jan1924"), NO dash
351
- # - If supplement is digits only (year like "1924"), WITH dash
352
- result += if supplement.match?(/^[A-Z]/)
353
- "supp#{supplement}"
354
- else
355
- "supp-#{supplement}"
356
- end
357
- elsif supplement
358
- result += "supp"
359
- end
477
+ # Add supplement. NIST/NBS canonical short form is single-p "sup"
478
+ # with the suffix attached directly, no dash (relaton-data-nist
479
+ # uses "sup2", "sup1940", "supA"); date-range keeps its inner dash.
480
+ # Rendered from the structured component; a present-but-empty
481
+ # component is the bare "sup" marker.
482
+ result += supplement_short
360
483
 
361
484
  # Add other attributes
362
485
  result += errata.to_s if errata
@@ -370,7 +493,7 @@ module Pubid
370
493
  result += " Add."
371
494
  end
372
495
 
373
- # V2: Use update_component if available, else use update string
496
+ # Use update_component if available, else use update string
374
497
  if update_component
375
498
  result += update_component.to_s(:short)
376
499
  elsif update
@@ -384,12 +507,12 @@ module Pubid
384
507
  result += "-draft"
385
508
  end
386
509
 
387
- # V2: Add stage component (at end, before translation)
510
+ # Add stage component (at end, before translation)
388
511
  if stage
389
512
  result += " #{stage.to_s(:short)}"
390
513
  end
391
514
 
392
- # V2: Use translation_component if available, else use translation string
515
+ # Use translation_component if available, else use translation string
393
516
  # Note: translation_component.to_s already includes the space prefix
394
517
  if translation_component
395
518
  result += translation_component.to_s(:short)
@@ -416,25 +539,44 @@ module Pubid
416
539
  result += ".#{number}" if number
417
540
  result += parts.map { |p| "-#{p}" }.join if parts&.any?
418
541
 
419
- # Part component (pt1, v6n1, etc.)
420
- result += part.to_s if part.is_a?(Components::Part)
542
+ result += append_mr_components
421
543
 
422
- # NEW: Use edition component - NO space before edition in MR format (per NIST spec)
423
- if edition
424
- # If edition has original_prefix set (e.g., verbose " Rev. "), use it as-is
425
- # Otherwise, no space needed in MR format: ".800-53r5"
426
- if edition.original_prefix && !edition.original_prefix.empty?
427
- end
428
- result += edition.to_s
544
+ result
545
+ end
546
+
547
+ # Render the optional component tail for machine-readable (MR) form.
548
+ # Mirrors #append_short_components so the MR output is just as lossless;
549
+ # subclasses that override #to_mr_style reuse this instead of
550
+ # hand-listing components. skip_part: behaves as in the short helper.
551
+ def append_mr_components(skip_part: false)
552
+ result = ""
553
+ effective_part = skip_part ? nil : part
554
+
555
+ # Volume / Part components (pt1, v6n1, etc.)
556
+ if volume.is_a?(Components::Volume) && effective_part.is_a?(Components::Part)
557
+ result += "#{volume}#{effective_part}"
558
+ elsif effective_part.is_a?(Components::Part)
559
+ result += effective_part.to_s
560
+ elsif volume && !issue_number && !effective_part
561
+ result += (volume.is_a?(Components::Volume) ? volume.to_s : "v#{volume}")
562
+ elsif volume && issue_number
563
+ vol_str = volume.is_a?(Components::Volume) ? volume.to_s : "v#{volume}"
564
+ result += "#{vol_str}n#{issue_number.number}"
429
565
  end
430
566
 
431
- # V2: Use version_component
567
+ # Use edition component - NO space before edition in MR format (per NIST spec)
568
+ result += edition.to_s if edition
569
+
570
+ # Use version_component
432
571
  result += version_component.to_s(:mr) if version_component
433
572
 
434
- # V2: Use update_component
573
+ # Supplement (e.g. ".9981sup7") - keep distinct documents distinct
574
+ result += supplement_short
575
+
576
+ # Use update_component
435
577
  result += update_component.to_s(:mr) if update_component
436
578
 
437
- # V2: Use stage
579
+ # Use stage
438
580
  result += ".#{stage.to_s(:mr)}" if stage
439
581
 
440
582
  # Add addendum - render as ".Add." suffix in MR format
@@ -442,7 +584,7 @@ module Pubid
442
584
  result += ".Add."
443
585
  end
444
586
 
445
- # V2: Use translation_component
587
+ # Use translation_component
446
588
  result += translation_component.to_s(:mr) if translation_component
447
589
 
448
590
  result
@@ -22,7 +22,8 @@ module Pubid
22
22
  end
23
23
 
24
24
  def type
25
- { key: :circ, title: "NBS Circular", short: "CIRC" }
25
+ { key: :circ,
26
+ web: :circular, title: "NBS Circular", short: "CIRC" }
26
27
  end
27
28
  end
28
29
 
@@ -41,8 +42,12 @@ module Pubid
41
42
  super&.to_s || default_publisher
42
43
  end
43
44
 
45
+ # Return the stored Code, or a default Code built from series_code when
46
+ # unset. Must return Components::Code (not a String): the lutaml-model
47
+ # key-value serializer reads attributes through this public getter, so a
48
+ # String here breaks to_hash for the Code-typed :series attribute.
44
49
  def series
45
- super&.to_s || series_code
50
+ super || Components::Code.new(value: series_code)
46
51
  end
47
52
 
48
53
  # Override to_s for CIRC-specific edition+year rendering
@@ -27,7 +27,8 @@ module Pubid
27
27
  end
28
28
 
29
29
  def type
30
- { key: :circ_supp, title: "NBS Circular Supplement", short: "CIRC" }
30
+ { key: :circ_supp,
31
+ web: :circular_supplement, title: "NBS Circular Supplement", short: "CIRC" }
31
32
  end
32
33
  end
33
34
 
@@ -38,7 +39,7 @@ module Pubid
38
39
  def to_s(format = :short)
39
40
  # Handle date range supplements (no base identifier)
40
41
  if supplement_date_range_start && supplement_date_range_end
41
- return "NBS CIRC supp#{supplement_date_range_start}-#{supplement_date_range_end}"
42
+ return "NBS CIRC sup#{supplement_date_range_start}-#{supplement_date_range_end}"
42
43
  end
43
44
 
44
45
  # Use parent's rendering for base + supplement
@@ -24,7 +24,8 @@ module Pubid
24
24
  end
25
25
 
26
26
  def type
27
- { key: :cs, title: "Commercial Standard", short: "CS" }
27
+ { key: :cs,
28
+ web: :commercial_standard, title: "Commercial Standard", short: "CS" }
28
29
  end
29
30
  end
30
31
 
@@ -21,7 +21,8 @@ module Pubid
21
21
  end
22
22
 
23
23
  def type
24
- { key: :cse, title: "NBS Commercial Standard Emergency",
24
+ { key: :cse,
25
+ web: :commercial_standard_emergency, title: "NBS Commercial Standard Emergency",
25
26
  short: "CS-E" }
26
27
  end
27
28
  end
@@ -30,7 +31,7 @@ module Pubid
30
31
  "CS-E"
31
32
  end
32
33
 
33
- private
34
+ public
34
35
 
35
36
  def to_short_style
36
37
  result = ""
@@ -45,8 +46,9 @@ module Pubid
45
46
  # Number (already extracted from e104 → 104 in builder)
46
47
  result += " #{number.value}" if number
47
48
 
48
- # Edition (e1943 for e104-43 pattern)
49
- result += edition.to_s if edition
49
+ # Edition (e1943 for e104-43 pattern) plus any other component the
50
+ # parser attached (volume, supplement, version, ...).
51
+ result += append_short_components
50
52
 
51
53
  result
52
54
  end
@@ -21,7 +21,8 @@ module Pubid
21
21
  end
22
22
 
23
23
  def type
24
- { key: :csm, title: "Commercial Standards Monthly", short: "CSM" }
24
+ { key: :csm,
25
+ web: :commercial_standards_monthly, title: "Commercial Standards Monthly", short: "CSM" }
25
26
  end
26
27
  end
27
28
 
@@ -29,11 +30,17 @@ module Pubid
29
30
  "NBS"
30
31
  end
31
32
 
33
+ # Always the normalized "CSM" code, regardless of the parsed series
34
+ # (CS vNnN variants are routed here and stored with series "CS", but
35
+ # must still render/serialize as CSM). Returns a Components::Code (not a
36
+ # bare String): the lutaml-model key-value serializer reads attributes
37
+ # through this public getter, so a String breaks to_hash for the
38
+ # Code-typed :series attribute.
32
39
  def series
33
- "CSM"
40
+ Components::Code.new(value: "CSM")
34
41
  end
35
42
 
36
- def to_s
43
+ def to_s(format = nil)
37
44
  result = "#{publisher} #{series}"
38
45
 
39
46
  # Proper Volume and Part components
@@ -24,7 +24,8 @@ module Pubid
24
24
  end
25
25
 
26
26
  def type
27
- { key: :crpl, title: "NBS CRPL Report", short: "CRPL" }
27
+ { key: :crpl,
28
+ web: :crpl_report, title: "NBS CRPL Report", short: "CRPL" }
28
29
  end
29
30
  end
30
31
 
@@ -83,10 +84,10 @@ module Pubid
83
84
  end
84
85
 
85
86
  # Return new Code object with normalized value
86
- Components::Code.new(number: num_value)
87
+ Components::Code.new(value: num_value)
87
88
  end
88
89
 
89
- def to_s
90
+ def to_s(format = nil)
90
91
  # Use actual series attribute if it contains subseries (e.g., "CRPL-F-B")
91
92
  # Otherwise use default series_code ("CRPL")
92
93
  series_to_render = if series&.value&.include?("CRPL-F-")
@@ -117,14 +118,10 @@ module Pubid
117
118
  result += " #{num_value}"
118
119
  end
119
120
 
120
- # Add part component (pt3-1)
121
- result += part.to_s if part
122
-
123
- # Add supplement with "sup" prefix for CRPL identifiers
124
- if supplement
125
- # Check if supplement already has "sup" prefix (for backward compatibility)
126
- result += (supplement.start_with?("sup") ? supplement : "sup#{supplement}")
127
- end
121
+ # Append the shared component tail (part, supplement, edition,
122
+ # index, section, ...) so distinct CRPL reports do not collide.
123
+ # range_notation is CRPL-specific and always trails the identifier.
124
+ result += append_short_components
128
125
 
129
126
  result += range_notation if range_notation
130
127
  result
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Nist
5
+ module Identifiers
6
+ # NIST date-style identifier with no series.
7
+ # Examples:
8
+ # - "NIST 2022-04-15 001" (short) / "NIST.2022-04-15.001" (mr/doi)
9
+ # DOI 10.6028/NIST.2022-04-15.001
10
+ class DatedDocument < Base
11
+ # Empty so the bare "NIST" abbr never shadows a series lookup; the
12
+ # Router guard (parsed_hash[:dated_date] && :dated_seq) is the dispatch path.
13
+ TYPED_STAGES = [].freeze
14
+
15
+ attribute :date_year, :string
16
+ attribute :date_month, :string
17
+ attribute :date_day, :string
18
+ attribute :dated_seq, :string
19
+
20
+ class << self
21
+ def typed_stages
22
+ TYPED_STAGES
23
+ end
24
+
25
+ def type
26
+ { key: :dated, title: "NIST Dated Document" }
27
+ end
28
+ end
29
+
30
+ def to_short_style
31
+ "#{publisher || 'NIST'} #{date_year}-#{date_month}-#{date_day} #{dated_seq}"
32
+ end
33
+
34
+ def to_mr_style
35
+ "#{publisher || 'NIST'}.#{date_year}-#{date_month}-#{date_day}.#{dated_seq}"
36
+ end
37
+
38
+ # No series/number to expand; non-default formats fall back to short.
39
+ def to_full_style
40
+ to_short_style
41
+ end
42
+
43
+ def to_abbreviated_style
44
+ to_short_style
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -22,7 +22,8 @@ module Pubid
22
22
  end
23
23
 
24
24
  def type
25
- { key: :fips, title: "Federal Information Processing Standards",
25
+ { key: :fips,
26
+ web: :federal_information_processing_standards, title: "Federal Information Processing Standards",
26
27
  short: "FIPS" }
27
28
  end
28
29
  end
@@ -41,21 +42,20 @@ module Pubid
41
42
  # "FIPS.46e1977" (machine-readable with dots, no publisher prefix)
42
43
  # Note: edition is appended directly to number without dot for FIPS
43
44
  result = series_code
45
+ result += ".#{number}" if number
44
46
 
45
- if number
46
- result += ".#{number}"
47
- # Append edition directly to number (no dot) for FIPS MR format
48
- if edition
49
- result += edition.to_s
50
- end
51
- end
52
-
47
+ # FIPS uses dash notation for parts; render here and skip the generic
48
+ # part rendering in the shared tail (which appends volume, edition,
49
+ # supplement, version, update, etc.).
50
+ result += "-#{part.value}" if part.is_a?(Components::Part)
53
51
  result += parts.map { |p| "-#{p}" }.join if parts&.any?
54
52
 
53
+ result += append_mr_components(skip_part: true)
54
+
55
55
  result
56
56
  end
57
57
 
58
- private
58
+ public
59
59
 
60
60
  def to_short_style
61
61
  # FIPS format: "FIPS 14e1971" or "NIST FIPS 140-3" (preserve publisher if set)
@@ -77,15 +77,16 @@ module Pubid
77
77
  end
78
78
  end
79
79
 
80
- # FIPS uses dash notation for parts: -1, -2, -3 (not pt1, pt2, pt3)
80
+ # FIPS uses dash notation for parts: -1, -2, -3 (not pt1, pt2, pt3),
81
+ # so render the part here and skip the generic part rendering in the
82
+ # shared tail. The tail still appends volume, edition, version,
83
+ # supplement, update, etc. — components FIPS previously dropped.
81
84
  if part.is_a?(Components::Part)
82
85
  result += "-#{part.value}"
83
86
  end
84
- # Render edition for FIPS
85
- # FIPS editions use "e" prefix: e1971, e198503, e19770930
86
- if edition
87
- result += "#{edition.type}#{edition.id}"
88
- end
87
+
88
+ result += append_short_components(skip_part: true)
89
+
89
90
  result
90
91
  end
91
92
  end
@@ -22,7 +22,8 @@ module Pubid
22
22
  end
23
23
 
24
24
  def type
25
- { key: :gcr, title: "NIST Grant/Contractor Report", short: "GCR" }
25
+ { key: :gcr,
26
+ web: :grant_contractor_report, title: "NIST Grant/Contractor Report", short: "GCR" }
26
27
  end
27
28
  end
28
29