pubid 2.0.0.pre.alpha.7 → 2.0.0.pre.alpha.9

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 (485) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +9 -50
  3. data/data/bipm/update_codes.yaml +9 -0
  4. data/data/iec/update_codes.yaml +3 -0
  5. data/data/ieee/update_codes.yaml +107 -1
  6. data/data/nist/series.yaml +155 -0
  7. data/data/nist/update_codes.yaml +8 -0
  8. data/lib/pubid/adobe/builder.rb +52 -0
  9. data/lib/pubid/adobe/identifier.rb +49 -0
  10. data/lib/pubid/adobe/identifiers/publication.rb +31 -0
  11. data/lib/pubid/adobe/identifiers/tech_note.rb +32 -0
  12. data/lib/pubid/adobe/identifiers.rb +10 -0
  13. data/lib/pubid/adobe/parser.rb +128 -0
  14. data/lib/pubid/adobe/renderer.rb +39 -0
  15. data/lib/pubid/adobe/urn_generator.rb +42 -0
  16. data/lib/pubid/adobe/urn_parser.rb +69 -0
  17. data/lib/pubid/adobe.rb +60 -0
  18. data/lib/pubid/amca/builder.rb +2 -2
  19. data/lib/pubid/amca/identifier.rb +1 -3
  20. data/lib/pubid/amca/identifiers/base.rb +1 -6
  21. data/lib/pubid/amca/identifiers/interpretation.rb +1 -1
  22. data/lib/pubid/amca/identifiers/publication.rb +1 -1
  23. data/lib/pubid/amca/identifiers/standard.rb +1 -1
  24. data/lib/pubid/amca/identifiers.rb +0 -1
  25. data/lib/pubid/amca/single_identifier.rb +1 -1
  26. data/lib/pubid/amca.rb +3 -3
  27. data/lib/pubid/ashrae/builder.rb +22 -22
  28. data/lib/pubid/ashrae/identifier.rb +3 -4
  29. data/lib/pubid/ashrae/identifiers/addenda_package.rb +1 -1
  30. data/lib/pubid/ashrae/identifiers/addendum.rb +1 -1
  31. data/lib/pubid/ashrae/identifiers/base.rb +14 -8
  32. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +1 -1
  33. data/lib/pubid/ashrae/identifiers.rb +0 -1
  34. data/lib/pubid/ashrae/parser.rb +14 -9
  35. data/lib/pubid/ashrae/renderer.rb +19 -19
  36. data/lib/pubid/ashrae/single_identifier.rb +1 -1
  37. data/lib/pubid/ashrae/supplement_identifier.rb +6 -6
  38. data/lib/pubid/ashrae.rb +3 -3
  39. data/lib/pubid/bipm/builder.rb +107 -0
  40. data/lib/pubid/bipm/identifier.rb +160 -0
  41. data/lib/pubid/bipm/identifiers/committee_document.rb +24 -0
  42. data/lib/pubid/bipm/identifiers/guide.rb +24 -0
  43. data/lib/pubid/bipm/identifiers/meeting.rb +41 -0
  44. data/lib/pubid/bipm/identifiers/mep.rb +21 -0
  45. data/lib/pubid/bipm/identifiers/metrologia_article.rb +24 -0
  46. data/lib/pubid/bipm/identifiers/si_brochure.rb +20 -0
  47. data/lib/pubid/bipm/identifiers.rb +15 -0
  48. data/lib/pubid/bipm/parser.rb +184 -0
  49. data/lib/pubid/bipm/renderer.rb +110 -0
  50. data/lib/pubid/bipm/urn_generator.rb +58 -0
  51. data/lib/pubid/bipm/urn_parser.rb +52 -0
  52. data/lib/pubid/bipm.rb +86 -0
  53. data/lib/pubid/bsi/builder.rb +14 -14
  54. data/lib/pubid/bsi/identifier.rb +0 -1
  55. data/lib/pubid/bsi/identifiers/addendum_document.rb +2 -2
  56. data/lib/pubid/bsi/identifiers/amendment.rb +4 -4
  57. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +6 -0
  58. data/lib/pubid/bsi/identifiers/corrigendum.rb +4 -4
  59. data/lib/pubid/bsi/identifiers/expert_commentary.rb +5 -5
  60. data/lib/pubid/bsi/identifiers/supplement_document.rb +2 -2
  61. data/lib/pubid/bsi/identifiers/value_added_publication.rb +6 -6
  62. data/lib/pubid/bsi/renderer.rb +8 -8
  63. data/lib/pubid/bsi/single_identifier.rb +48 -0
  64. data/lib/pubid/builder/base.rb +5 -3
  65. data/lib/pubid/bundled_identifier.rb +3 -3
  66. data/lib/pubid/calconnect/builder.rb +38 -0
  67. data/lib/pubid/calconnect/identifier.rb +117 -0
  68. data/lib/pubid/calconnect/identifiers/standard.rb +29 -0
  69. data/lib/pubid/calconnect/identifiers.rb +9 -0
  70. data/lib/pubid/calconnect/parser.rb +54 -0
  71. data/lib/pubid/calconnect/renderer.rb +36 -0
  72. data/lib/pubid/calconnect/urn_generator.rb +33 -0
  73. data/lib/pubid/calconnect/urn_parser.rb +34 -0
  74. data/lib/pubid/calconnect.rb +77 -0
  75. data/lib/pubid/ccsds/builder.rb +1 -1
  76. data/lib/pubid/ccsds/identifier.rb +1 -1
  77. data/lib/pubid/ccsds/identifiers/corrigendum.rb +2 -2
  78. data/lib/pubid/ccsds/supplement_identifier.rb +6 -6
  79. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  80. data/lib/pubid/cen_cenelec/builder.rb +46 -12
  81. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +2 -2
  82. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +6 -0
  83. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +2 -2
  84. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +60 -3
  85. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +2 -2
  86. data/lib/pubid/cen_cenelec/renderer.rb +5 -5
  87. data/lib/pubid/cen_cenelec/supplement_identifier.rb +5 -5
  88. data/lib/pubid/cen_cenelec/urn_generator.rb +1 -1
  89. data/lib/pubid/cen_cenelec.rb +76 -72
  90. data/lib/pubid/cie/builder.rb +139 -24
  91. data/lib/pubid/cie/identifier.rb +7 -3
  92. data/lib/pubid/cie/identifiers/bundle.rb +32 -4
  93. data/lib/pubid/cie/identifiers/code_attributes.rb +52 -0
  94. data/lib/pubid/cie/identifiers/conference.rb +9 -4
  95. data/lib/pubid/cie/identifiers/corrigendum.rb +17 -23
  96. data/lib/pubid/cie/identifiers/dual_published.rb +4 -4
  97. data/lib/pubid/cie/identifiers/identical.rb +7 -7
  98. data/lib/pubid/cie/identifiers/joint_published.rb +8 -8
  99. data/lib/pubid/cie/identifiers/proceedings.rb +39 -0
  100. data/lib/pubid/cie/identifiers/standard.rb +33 -7
  101. data/lib/pubid/cie/identifiers/supplement.rb +24 -22
  102. data/lib/pubid/cie/identifiers/tutorial_bundle.rb +6 -2
  103. data/lib/pubid/cie/identifiers.rb +2 -0
  104. data/lib/pubid/cie/parser.rb +54 -5
  105. data/lib/pubid/cie/single_identifier.rb +40 -1
  106. data/lib/pubid/cie/supplement_identifier.rb +29 -16
  107. data/lib/pubid/cie/urn_generator.rb +11 -8
  108. data/lib/pubid/cie.rb +0 -1
  109. data/lib/pubid/components/date.rb +21 -5
  110. data/lib/pubid/csa/builder.rb +1 -1
  111. data/lib/pubid/csa/composite_identifier.rb +17 -1
  112. data/lib/pubid/csa/identifier.rb +48 -3
  113. data/lib/pubid/csa/identifiers/bundled.rb +6 -0
  114. data/lib/pubid/csa/identifiers/combined.rb +6 -0
  115. data/lib/pubid/csa/identifiers/package.rb +2 -2
  116. data/lib/pubid/csa/parser.rb +6 -6
  117. data/lib/pubid/csa/wrapper_identifier.rb +17 -0
  118. data/lib/pubid/doi/builder.rb +18 -0
  119. data/lib/pubid/doi/identifier.rb +46 -0
  120. data/lib/pubid/doi/identifiers/resource.rb +30 -0
  121. data/lib/pubid/doi/identifiers.rb +9 -0
  122. data/lib/pubid/doi/parser.rb +52 -0
  123. data/lib/pubid/doi/renderer.rb +13 -0
  124. data/lib/pubid/doi.rb +55 -0
  125. data/lib/pubid/easc/builder.rb +55 -0
  126. data/lib/pubid/easc/identifier.rb +61 -0
  127. data/lib/pubid/easc/identifiers/pmg.rb +20 -0
  128. data/lib/pubid/easc/identifiers/rmg.rb +19 -0
  129. data/lib/pubid/easc/identifiers.rb +10 -0
  130. data/lib/pubid/easc/parser.rb +80 -0
  131. data/lib/pubid/easc/renderer.rb +48 -0
  132. data/lib/pubid/easc/urn_generator.rb +46 -0
  133. data/lib/pubid/easc/urn_parser.rb +57 -0
  134. data/lib/pubid/easc.rb +52 -0
  135. data/lib/pubid/ecma/builder.rb +31 -0
  136. data/lib/pubid/ecma/identifier.rb +76 -0
  137. data/lib/pubid/ecma/identifiers/memento.rb +30 -0
  138. data/lib/pubid/ecma/identifiers/standard.rb +31 -0
  139. data/lib/pubid/ecma/identifiers/technical_report.rb +31 -0
  140. data/lib/pubid/ecma/identifiers.rb +11 -0
  141. data/lib/pubid/ecma/parser.rb +41 -0
  142. data/lib/pubid/ecma/renderer.rb +46 -0
  143. data/lib/pubid/ecma/urn_generator.rb +25 -0
  144. data/lib/pubid/ecma/urn_parser.rb +35 -0
  145. data/lib/pubid/ecma.rb +67 -0
  146. data/lib/pubid/etsi/builder.rb +7 -3
  147. data/lib/pubid/etsi/identifier.rb +1 -3
  148. data/lib/pubid/etsi/identifiers/base.rb +28 -10
  149. data/lib/pubid/etsi/identifiers/etsi_standard.rb +128 -4
  150. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +35 -3
  151. data/lib/pubid/etsi/identifiers.rb +0 -1
  152. data/lib/pubid/etsi/parser.rb +8 -2
  153. data/lib/pubid/etsi/renderer.rb +8 -2
  154. data/lib/pubid/etsi.rb +5 -5
  155. data/lib/pubid/export/exporter.rb +2 -1
  156. data/lib/pubid/export/flavor_exporter.rb +18 -3
  157. data/lib/pubid/gb/builder.rb +45 -0
  158. data/lib/pubid/gb/identifier.rb +64 -0
  159. data/lib/pubid/gb/identifiers/standard.rb +34 -0
  160. data/lib/pubid/gb/identifiers.rb +9 -0
  161. data/lib/pubid/gb/parser.rb +63 -0
  162. data/lib/pubid/gb/renderer.rb +35 -0
  163. data/lib/pubid/gb.rb +87 -0
  164. data/lib/pubid/gost/builder.rb +148 -0
  165. data/lib/pubid/gost/identifier.rb +49 -0
  166. data/lib/pubid/gost/identifiers/foreign_reference.rb +25 -0
  167. data/lib/pubid/gost/identifiers/harmonized.rb +39 -0
  168. data/lib/pubid/gost/identifiers/identical_adoption.rb +39 -0
  169. data/lib/pubid/gost/identifiers/interstate_standard.rb +20 -0
  170. data/lib/pubid/gost/identifiers/national_standard.rb +19 -0
  171. data/lib/pubid/gost/identifiers.rb +13 -0
  172. data/lib/pubid/gost/parser.rb +97 -0
  173. data/lib/pubid/gost/renderer.rb +48 -0
  174. data/lib/pubid/gost/urn_generator.rb +46 -0
  175. data/lib/pubid/gost/urn_parser.rb +52 -0
  176. data/lib/pubid/gost.rb +49 -0
  177. data/lib/pubid/iala/builder.rb +22 -27
  178. data/lib/pubid/iala/identifier.rb +27 -2
  179. data/lib/pubid/iala/identifiers/advice.rb +1 -1
  180. data/lib/pubid/iala/identifiers/annex.rb +14 -12
  181. data/lib/pubid/iala/identifiers/general_assembly.rb +5 -2
  182. data/lib/pubid/iala/identifiers/guideline.rb +3 -1
  183. data/lib/pubid/iala/identifiers/letter.rb +1 -1
  184. data/lib/pubid/iala/identifiers/manual.rb +3 -1
  185. data/lib/pubid/iala/identifiers/model_course.rb +3 -1
  186. data/lib/pubid/iala/identifiers/recommendation.rb +3 -1
  187. data/lib/pubid/iala/identifiers/report.rb +1 -1
  188. data/lib/pubid/iala/identifiers/resolution.rb +1 -1
  189. data/lib/pubid/iala/identifiers/standard.rb +3 -1
  190. data/lib/pubid/iala/identifiers.rb +0 -1
  191. data/lib/pubid/iala/renderer.rb +1 -1
  192. data/lib/pubid/iala/urn_generator.rb +1 -1
  193. data/lib/pubid/iala/urn_parser.rb +19 -2
  194. data/lib/pubid/iala.rb +4 -4
  195. data/lib/pubid/iana/builder.rb +20 -0
  196. data/lib/pubid/iana/identifier.rb +72 -0
  197. data/lib/pubid/iana/identifiers/registry.rb +33 -0
  198. data/lib/pubid/iana/identifiers.rb +9 -0
  199. data/lib/pubid/iana/parser.rb +38 -0
  200. data/lib/pubid/iana/renderer.rb +29 -0
  201. data/lib/pubid/iana/urn_generator.rb +15 -0
  202. data/lib/pubid/iana/urn_parser.rb +24 -0
  203. data/lib/pubid/iana.rb +69 -0
  204. data/lib/pubid/identifier.rb +210 -23
  205. data/lib/pubid/idf/builder.rb +1 -1
  206. data/lib/pubid/idf/parser.rb +2 -2
  207. data/lib/pubid/idf/renderer.rb +1 -1
  208. data/lib/pubid/idf/supplement_identifier.rb +3 -3
  209. data/lib/pubid/iec/builder.rb +35 -25
  210. data/lib/pubid/iec/identifier.rb +47 -2
  211. data/lib/pubid/iec/identifiers/base.rb +2 -2
  212. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +6 -0
  213. data/lib/pubid/iec/identifiers/fragment_identifier.rb +11 -11
  214. data/lib/pubid/iec/identifiers/international_standard.rb +8 -5
  215. data/lib/pubid/iec/identifiers/sheet_identifier.rb +12 -12
  216. data/lib/pubid/iec/identifiers/technical_group.rb +30 -0
  217. data/lib/pubid/iec/identifiers/technical_report.rb +1 -1
  218. data/lib/pubid/iec/identifiers/technical_specification.rb +1 -1
  219. data/lib/pubid/iec/identifiers/vap_identifier.rb +12 -12
  220. data/lib/pubid/iec/identifiers.rb +1 -0
  221. data/lib/pubid/iec/parser.rb +51 -10
  222. data/lib/pubid/iec/renderer.rb +18 -8
  223. data/lib/pubid/iec/single_identifier.rb +1 -1
  224. data/lib/pubid/iec/supplement_identifier.rb +32 -19
  225. data/lib/pubid/iec.rb +1 -6
  226. data/lib/pubid/ieee/aiee/builder.rb +17 -3
  227. data/lib/pubid/ieee/aiee/identifier.rb +45 -61
  228. data/lib/pubid/ieee/builder.rb +341 -68
  229. data/lib/pubid/ieee/compaction.rb +121 -0
  230. data/lib/pubid/ieee/components/draft.rb +47 -7
  231. data/lib/pubid/ieee/identifier.rb +1 -3
  232. data/lib/pubid/ieee/identifiers/adopted_standard.rb +30 -5
  233. data/lib/pubid/ieee/identifiers/amendment.rb +40 -0
  234. data/lib/pubid/ieee/identifiers/base.rb +106 -13
  235. data/lib/pubid/ieee/identifiers/code_number.rb +82 -0
  236. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +6 -2
  237. data/lib/pubid/ieee/identifiers/corrigendum.rb +17 -2
  238. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +3 -3
  239. data/lib/pubid/ieee/identifiers/dual_identifier.rb +3 -3
  240. data/lib/pubid/ieee/identifiers/dual_published.rb +3 -3
  241. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +102 -5
  242. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +2 -1
  243. data/lib/pubid/ieee/identifiers/joint_development.rb +56 -11
  244. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +1 -1
  245. data/lib/pubid/ieee/identifiers/nesc/base.rb +90 -19
  246. data/lib/pubid/ieee/identifiers/nesc/draft.rb +20 -5
  247. data/lib/pubid/ieee/identifiers/nesc/edition.rb +32 -0
  248. data/lib/pubid/ieee/identifiers/nesc/handbook.rb +16 -5
  249. data/lib/pubid/ieee/identifiers/nesc/redline.rb +11 -2
  250. data/lib/pubid/ieee/identifiers/nesc/standard.rb +18 -3
  251. data/lib/pubid/ieee/identifiers/nesc.rb +1 -0
  252. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +3 -3
  253. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +14 -6
  254. data/lib/pubid/ieee/identifiers/redlined_standard.rb +4 -4
  255. data/lib/pubid/ieee/identifiers/si_standard.rb +4 -1
  256. data/lib/pubid/ieee/identifiers/standard.rb +4 -1
  257. data/lib/pubid/ieee/identifiers/supplement_identifier.rb +26 -7
  258. data/lib/pubid/ieee/identifiers.rb +2 -1
  259. data/lib/pubid/ieee/ire/builder.rb +7 -6
  260. data/lib/pubid/ieee/ire/identifier.rb +48 -33
  261. data/lib/pubid/ieee/nesc/builder.rb +33 -20
  262. data/lib/pubid/ieee/nesc/parser.rb +15 -14
  263. data/lib/pubid/ieee/parser.rb +461 -43
  264. data/lib/pubid/ieee/pre_parser.rb +1 -1
  265. data/lib/pubid/ieee/renderer.rb +154 -57
  266. data/lib/pubid/ieee/typed_stages.rb +12 -1
  267. data/lib/pubid/ieee/urn_generator.rb +3 -5
  268. data/lib/pubid/ieee.rb +56 -3
  269. data/lib/pubid/ietf/builder.rb +62 -0
  270. data/lib/pubid/ietf/identifier.rb +5 -0
  271. data/lib/pubid/ietf/identifiers/base.rb +75 -0
  272. data/lib/pubid/ietf/identifiers/bcp.rb +25 -0
  273. data/lib/pubid/ietf/identifiers/fyi.rb +25 -0
  274. data/lib/pubid/ietf/identifiers/internet_draft.rb +29 -0
  275. data/lib/pubid/ietf/identifiers/rfc.rb +25 -0
  276. data/lib/pubid/ietf/identifiers/std.rb +25 -0
  277. data/lib/pubid/ietf/identifiers.rb +13 -0
  278. data/lib/pubid/ietf/parser.rb +43 -0
  279. data/lib/pubid/ietf/renderer.rb +26 -0
  280. data/lib/pubid/ietf/urn_generator.rb +23 -0
  281. data/lib/pubid/ietf/urn_parser.rb +35 -0
  282. data/lib/pubid/ietf.rb +76 -0
  283. data/lib/pubid/iho/identifier.rb +1 -3
  284. data/lib/pubid/iho/identifiers/base.rb +1 -7
  285. data/lib/pubid/iho/identifiers/bibliographic.rb +1 -1
  286. data/lib/pubid/iho/identifiers/circular_letter.rb +1 -1
  287. data/lib/pubid/iho/identifiers/miscellaneous.rb +1 -1
  288. data/lib/pubid/iho/identifiers/publication.rb +1 -1
  289. data/lib/pubid/iho/identifiers/standard.rb +1 -1
  290. data/lib/pubid/iho/identifiers.rb +0 -1
  291. data/lib/pubid/iho.rb +7 -7
  292. data/lib/pubid/isbn/builder.rb +44 -0
  293. data/lib/pubid/isbn/check_digit.rb +53 -0
  294. data/lib/pubid/isbn/identifier.rb +63 -0
  295. data/lib/pubid/isbn/identifiers/book.rb +30 -0
  296. data/lib/pubid/isbn/identifiers.rb +9 -0
  297. data/lib/pubid/isbn/parser.rb +45 -0
  298. data/lib/pubid/isbn/renderer.rb +16 -0
  299. data/lib/pubid/isbn.rb +52 -0
  300. data/lib/pubid/iso/builder.rb +9 -4
  301. data/lib/pubid/iso/combined_identifier.rb +2 -2
  302. data/lib/pubid/iso/identifier.rb +17 -1
  303. data/lib/pubid/iso/identifiers/directives_supplement.rb +8 -8
  304. data/lib/pubid/iso/normalizer.rb +2 -2
  305. data/lib/pubid/iso/parser.rb +16 -12
  306. data/lib/pubid/iso/supplement_identifier.rb +19 -6
  307. data/lib/pubid/iso/urn_generator.rb +4 -1
  308. data/lib/pubid/iso/urn_parser.rb +1 -1
  309. data/lib/pubid/itu/builder.rb +230 -29
  310. data/lib/pubid/itu/components/code.rb +48 -5
  311. data/lib/pubid/itu/components/designation.rb +35 -0
  312. data/lib/pubid/itu/components.rb +1 -0
  313. data/lib/pubid/itu/identifier.rb +1 -3
  314. data/lib/pubid/itu/identifiers/addendum.rb +15 -0
  315. data/lib/pubid/itu/identifiers/amendment.rb +6 -28
  316. data/lib/pubid/itu/identifiers/annex.rb +13 -2
  317. data/lib/pubid/itu/identifiers/annex_of_recommendation.rb +87 -0
  318. data/lib/pubid/itu/identifiers/appendix_of_recommendation.rb +92 -0
  319. data/lib/pubid/itu/identifiers/base.rb +341 -23
  320. data/lib/pubid/itu/identifiers/combined_identifier.rb +99 -23
  321. data/lib/pubid/itu/identifiers/corrigendum.rb +16 -23
  322. data/lib/pubid/itu/identifiers/errata.rb +15 -0
  323. data/lib/pubid/itu/identifiers/handbook.rb +38 -0
  324. data/lib/pubid/itu/identifiers/question.rb +63 -0
  325. data/lib/pubid/itu/identifiers/recommendation.rb +3 -2
  326. data/lib/pubid/itu/identifiers/report.rb +39 -0
  327. data/lib/pubid/itu/identifiers/special_publication.rb +3 -1
  328. data/lib/pubid/itu/identifiers/standard_serialization.rb +58 -0
  329. data/lib/pubid/itu/identifiers/supplement.rb +119 -14
  330. data/lib/pubid/itu/identifiers.rb +10 -1
  331. data/lib/pubid/itu/model.rb +1 -1
  332. data/lib/pubid/itu/parser.rb +480 -26
  333. data/lib/pubid/itu/urn_generator.rb +36 -6
  334. data/lib/pubid/itu/urn_parser.rb +8 -0
  335. data/lib/pubid/itu.rb +11 -3
  336. data/lib/pubid/jcgm/builder.rb +23 -13
  337. data/lib/pubid/jcgm/identifiers/amendment.rb +0 -2
  338. data/lib/pubid/jcgm/identifiers/corrigendum.rb +34 -0
  339. data/lib/pubid/jcgm/identifiers/gum_guide.rb +3 -3
  340. data/lib/pubid/jcgm/identifiers/meeting.rb +47 -0
  341. data/lib/pubid/jcgm/identifiers.rb +2 -0
  342. data/lib/pubid/jcgm/parser.rb +66 -6
  343. data/lib/pubid/jcgm/renderer.rb +26 -12
  344. data/lib/pubid/jcgm/single_identifier.rb +74 -5
  345. data/lib/pubid/jcgm/supplement_identifier.rb +39 -4
  346. data/lib/pubid/jcgm/urn_generator.rb +21 -13
  347. data/lib/pubid/jcgm/urn_parser.rb +15 -3
  348. data/lib/pubid/jis/identifier.rb +52 -0
  349. data/lib/pubid/nist/builder.rb +29 -9
  350. data/lib/pubid/nist/caster.rb +7 -45
  351. data/lib/pubid/nist/circular_supplement_builder.rb +7 -5
  352. data/lib/pubid/nist/components/supplement.rb +5 -2
  353. data/lib/pubid/nist/configuration.rb +7 -1
  354. data/lib/pubid/nist/identifier.rb +1 -3
  355. data/lib/pubid/nist/identifiers/base.rb +121 -37
  356. data/lib/pubid/nist/identifiers/circular.rb +1 -1
  357. data/lib/pubid/nist/identifiers/commercial_standard.rb +1 -1
  358. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +1 -1
  359. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +1 -1
  360. data/lib/pubid/nist/identifiers/crpl_report.rb +1 -1
  361. data/lib/pubid/nist/identifiers/dated_document.rb +1 -1
  362. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +1 -1
  363. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +1 -1
  364. data/lib/pubid/nist/identifiers/handbook.rb +1 -1
  365. data/lib/pubid/nist/identifiers/internal_report.rb +1 -1
  366. data/lib/pubid/nist/identifiers/letter_circular.rb +1 -1
  367. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +1 -1
  368. data/lib/pubid/nist/identifiers/monograph.rb +1 -1
  369. data/lib/pubid/nist/identifiers/ncstar.rb +2 -2
  370. data/lib/pubid/nist/identifiers/nsrds.rb +1 -1
  371. data/lib/pubid/nist/identifiers/owmwp.rb +1 -1
  372. data/lib/pubid/nist/identifiers/report.rb +1 -1
  373. data/lib/pubid/nist/identifiers/special_publication.rb +10 -1
  374. data/lib/pubid/nist/identifiers/technical_note.rb +1 -1
  375. data/lib/pubid/nist/identifiers.rb +0 -1
  376. data/lib/pubid/nist/parser.rb +29 -4
  377. data/lib/pubid/nist/preprocessor.rb +15 -0
  378. data/lib/pubid/nist/router.rb +3 -2
  379. data/lib/pubid/nist/series/ir.rb +0 -3
  380. data/lib/pubid/nist/supplement_identifier.rb +9 -9
  381. data/lib/pubid/nist.rb +13 -12
  382. data/lib/pubid/oasis/builder.rb +77 -0
  383. data/lib/pubid/oasis/identifier.rb +82 -0
  384. data/lib/pubid/oasis/identifiers/standard.rb +29 -0
  385. data/lib/pubid/oasis/identifiers.rb +9 -0
  386. data/lib/pubid/oasis/parser.rb +34 -0
  387. data/lib/pubid/oasis/renderer.rb +29 -0
  388. data/lib/pubid/oasis/urn_generator.rb +25 -0
  389. data/lib/pubid/oasis/urn_parser.rb +22 -0
  390. data/lib/pubid/oasis.rb +74 -0
  391. data/lib/pubid/ogc/builder.rb +33 -0
  392. data/lib/pubid/ogc/identifier.rb +77 -0
  393. data/lib/pubid/ogc/identifiers/document.rb +26 -0
  394. data/lib/pubid/ogc/identifiers.rb +10 -0
  395. data/lib/pubid/ogc/parser.rb +40 -0
  396. data/lib/pubid/ogc/renderer.rb +33 -0
  397. data/lib/pubid/ogc/urn_generator.rb +14 -0
  398. data/lib/pubid/ogc/urn_parser.rb +22 -0
  399. data/lib/pubid/ogc.rb +71 -0
  400. data/lib/pubid/oiml/builder.rb +31 -7
  401. data/lib/pubid/oiml/identifier.rb +9 -1
  402. data/lib/pubid/oiml/parser.rb +11 -12
  403. data/lib/pubid/oiml/renderer.rb +13 -13
  404. data/lib/pubid/oiml/single_identifier.rb +20 -0
  405. data/lib/pubid/oiml/supplement_identifier.rb +9 -9
  406. data/lib/pubid/oiml/urn_parser.rb +23 -6
  407. data/lib/pubid/oiml.rb +4 -0
  408. data/lib/pubid/omg/builder.rb +19 -0
  409. data/lib/pubid/omg/identifier.rb +44 -0
  410. data/lib/pubid/omg/identifiers/specification.rb +32 -0
  411. data/lib/pubid/omg/identifiers.rb +9 -0
  412. data/lib/pubid/omg/parser.rb +40 -0
  413. data/lib/pubid/omg/renderer.rb +19 -0
  414. data/lib/pubid/omg.rb +51 -0
  415. data/lib/pubid/parsers/mr_string.rb +101 -7
  416. data/lib/pubid/plateau/builder.rb +8 -4
  417. data/lib/pubid/plateau/identifier.rb +1 -3
  418. data/lib/pubid/plateau/identifiers/base.rb +1 -6
  419. data/lib/pubid/plateau/identifiers/handbook.rb +1 -1
  420. data/lib/pubid/plateau/identifiers/technical_report.rb +1 -1
  421. data/lib/pubid/plateau/identifiers.rb +0 -1
  422. data/lib/pubid/plateau/parser.rb +15 -5
  423. data/lib/pubid/plateau/renderer.rb +1 -1
  424. data/lib/pubid/plateau/supplement_identifier.rb +11 -11
  425. data/lib/pubid/plateau.rb +4 -4
  426. data/lib/pubid/renderers/human_readable.rb +3 -1
  427. data/lib/pubid/renderers/mr_string.rb +46 -4
  428. data/lib/pubid/renderers/supplement_renderer.rb +1 -1
  429. data/lib/pubid/rendering/supplement.rb +4 -4
  430. data/lib/pubid/sae/builder.rb +1 -1
  431. data/lib/pubid/sae/identifier.rb +1 -3
  432. data/lib/pubid/sae/identifiers/base.rb +10 -7
  433. data/lib/pubid/sae/identifiers.rb +0 -1
  434. data/lib/pubid/sae.rb +3 -3
  435. data/lib/pubid/tgpp/builder.rb +41 -0
  436. data/lib/pubid/tgpp/identifier.rb +91 -0
  437. data/lib/pubid/tgpp/identifiers/technical_report.rb +32 -0
  438. data/lib/pubid/tgpp/identifiers/technical_specification.rb +33 -0
  439. data/lib/pubid/tgpp/identifiers.rb +11 -0
  440. data/lib/pubid/tgpp/parser.rb +62 -0
  441. data/lib/pubid/tgpp/renderer.rb +36 -0
  442. data/lib/pubid/tgpp/urn_generator.rb +20 -0
  443. data/lib/pubid/tgpp/urn_parser.rb +28 -0
  444. data/lib/pubid/tgpp.rb +78 -0
  445. data/lib/pubid/type_resolver.rb +59 -0
  446. data/lib/pubid/un/builder.rb +42 -0
  447. data/lib/pubid/un/identifier.rb +37 -0
  448. data/lib/pubid/un/identifiers/document.rb +24 -0
  449. data/lib/pubid/un/identifiers.rb +9 -0
  450. data/lib/pubid/un/parser.rb +25 -0
  451. data/lib/pubid/un/renderer.rb +11 -0
  452. data/lib/pubid/un.rb +46 -0
  453. data/lib/pubid/version.rb +1 -1
  454. data/lib/pubid/w3c/builder.rb +55 -0
  455. data/lib/pubid/w3c/identifier.rb +101 -0
  456. data/lib/pubid/w3c/identifiers/candidate_recommendation.rb +31 -0
  457. data/lib/pubid/w3c/identifiers/candidate_recommendation_draft.rb +31 -0
  458. data/lib/pubid/w3c/identifiers/draft_note.rb +31 -0
  459. data/lib/pubid/w3c/identifiers/note.rb +30 -0
  460. data/lib/pubid/w3c/identifiers/obsolete_recommendation.rb +31 -0
  461. data/lib/pubid/w3c/identifiers/proposed_edited_recommendation.rb +31 -0
  462. data/lib/pubid/w3c/identifiers/proposed_recommendation.rb +31 -0
  463. data/lib/pubid/w3c/identifiers/recommendation.rb +31 -0
  464. data/lib/pubid/w3c/identifiers/standard.rb +12 -0
  465. data/lib/pubid/w3c/identifiers/superseded_recommendation.rb +31 -0
  466. data/lib/pubid/w3c/identifiers/working_draft.rb +30 -0
  467. data/lib/pubid/w3c/identifiers.rb +25 -0
  468. data/lib/pubid/w3c/parser.rb +43 -0
  469. data/lib/pubid/w3c/renderer.rb +35 -0
  470. data/lib/pubid/w3c/urn_generator.rb +18 -0
  471. data/lib/pubid/w3c/urn_parser.rb +36 -0
  472. data/lib/pubid/w3c.rb +67 -0
  473. data/lib/pubid/xsf/builder.rb +17 -0
  474. data/lib/pubid/xsf/identifier.rb +62 -0
  475. data/lib/pubid/xsf/identifiers/xep.rb +31 -0
  476. data/lib/pubid/xsf/identifiers.rb +9 -0
  477. data/lib/pubid/xsf/parser.rb +25 -0
  478. data/lib/pubid/xsf/renderer.rb +23 -0
  479. data/lib/pubid/xsf/urn_generator.rb +13 -0
  480. data/lib/pubid/xsf/urn_parser.rb +18 -0
  481. data/lib/pubid/xsf.rb +76 -0
  482. data/lib/pubid.rb +25 -1
  483. metadata +205 -4
  484. data/lib/pubid/cie/components/code.rb +0 -80
  485. data/lib/pubid/iala/identifiers/base.rb +0 -14
@@ -3,9 +3,7 @@
3
3
  module Pubid
4
4
  module Nist
5
5
  # NIST/NBS flavor base class. Canonical name Pubid::Nist::Identifier; every
6
- # concrete NIST identifier (Identifiers::*) descends from it, and
7
- # Identifiers::Base — aliased at the foot of this file — points back to it
8
- # for backward compatibility. Being a real Pubid::Identifier subclass gives
6
+ # concrete NIST identifier (Identifiers::*) descends from it. Being a real Pubid::Identifier subclass gives
9
7
  # native `is_a?` identity and the shared polymorphic `from_hash`.
10
8
  class Identifier < ::Pubid::Identifier
11
9
  # Delegate to the flavor module so callers can use
@@ -14,6 +12,77 @@ module Pubid
14
12
  Pubid::Nist.parse(identifier)
15
13
  end
16
14
 
15
+ # Compact, index-friendly serialization (mirrors the key_value flavors
16
+ # ISO/ITU/ETSI, without a 38-field key_value block). Two transforms,
17
+ # applied symmetrically by to_hash/from_hash so the round-trip stays
18
+ # idempotent:
19
+ # - flatten the single-value Code components (series, number) to bare
20
+ # scalars — `value` is the only stored field. NIST's
21
+ # `Components::Code#part` is a *computed* reader
22
+ # (`value.split("-").last`), and prefix/subpart/parts are never
23
+ # assigned on series/number, so the scalar `value` is lossless:
24
+ # expand recomputes exactly what the object would compute anyway;
25
+ # - flatten the plain single-value components (volume) to bare scalars
26
+ # too — `Components::Volume` holds only `value`, so it expands to a
27
+ # bare { "value" => … } with no part;
28
+ # - drop the redundant build artifacts, decomposed pieces of the
29
+ # canonical number that identity/rendering never read.
30
+ COMPACT_FLAT_CODES = %w[series number subseries].freeze
31
+ COMPACT_FLAT_VALUES = %w[volume].freeze
32
+ COMPACT_DROP_ATTRS = %w[first_number second_number].freeze
33
+
34
+ # Deserialize a (possibly compact) hash: expand the flattened scalars
35
+ # back into Code sub-hashes, then let the shared polymorphic from_hash
36
+ # do the real work. Nested `base` documents are expanded recursively by
37
+ # their own from_hash via apply_mappings, so only this level is touched.
38
+ def self.from_hash(data, options = {})
39
+ super(expand_compact_hash(data), options)
40
+ end
41
+
42
+ # Expand a compact hash in place-safe fashion: a scalar series/number
43
+ # becomes { "value" => …, "part" => <last-dash segment> }.
44
+ def self.expand_compact_hash(data)
45
+ return data unless data.is_a?(::Hash)
46
+
47
+ out = data.dup
48
+ COMPACT_FLAT_CODES.each do |key|
49
+ out[key] = expand_code(out[key]) if out[key].is_a?(::String)
50
+ end
51
+ COMPACT_FLAT_VALUES.each do |key|
52
+ out[key] = { "value" => out[key] } if out[key].is_a?(::String)
53
+ end
54
+ out
55
+ end
56
+
57
+ # A flattened Code scalar -> { "value" => …, "part" => <last-dash seg> }.
58
+ def self.expand_code(value)
59
+ code = { "value" => value }
60
+ code["part"] = value.split("-").last if value.include?("-")
61
+ code
62
+ end
63
+
64
+ # Serialize, then apply the compact transforms (recursing into a nested
65
+ # `base`, which lutaml serialized via its own transform — bypassing this
66
+ # override — so it is not compacted otherwise).
67
+ def to_hash(*args)
68
+ hash = super
69
+ compact_hash!(hash) if hash.is_a?(::Hash)
70
+ hash
71
+ end
72
+
73
+ def compact_hash!(hash)
74
+ COMPACT_DROP_ATTRS.each { |key| hash.delete(key) }
75
+ (COMPACT_FLAT_CODES + COMPACT_FLAT_VALUES).each do |key|
76
+ value = hash[key]
77
+ next unless value.is_a?(::Hash) && value.key?("value")
78
+
79
+ hash[key] = value["value"]
80
+ end
81
+ compact_hash!(hash["base"]) if hash["base"].is_a?(::Hash)
82
+ hash
83
+ end
84
+ private :compact_hash!
85
+
17
86
  # Default: no typed stages. Subclasses override as needed.
18
87
  def self.typed_stages
19
88
  []
@@ -29,11 +98,23 @@ module Pubid
29
98
  # raw string the circular/supplement builders pass straight through.
30
99
  attribute :publisher, :string
31
100
  attribute :series, Components::Code # Set by Builder from parsed data
101
+ # SP subseries (Appendix A.2 of the NIST PubID Syntax): for "NIST SP 800-53"
102
+ # the subseries is "800" and the sequence is "53". Populated by the Builder
103
+ # when the series is "SP" and the first number matches a known subseries
104
+ # code. Informational metadata derived from series+number — ignored in
105
+ # equality so a manually-built id (without subseries set) still equals a
106
+ # parsed one.
107
+ attribute :subseries, Components::Code
32
108
  attribute :number, Components::Code
33
109
 
34
110
  # V2 COMPONENTS (Lutaml::Model objects) - PROPER SEPARATION
111
+ # `edition` (Components::Edition: type + id + additional_text) is the
112
+ # single source of truth for edition/revision. The former
113
+ # `edition_component` (a byte-identical duplicate) and the `revision`
114
+ # string (always "#{edition.type}#{edition.id}") were unfinished V1->V2
115
+ # migration aliases; both removed. `#revision` survives as a derived
116
+ # reader below.
35
117
  attribute :edition, Components::Edition # Edition (type + id): e2, e2021, r5, -3
36
- attribute :edition_component, Components::Edition # V2 edition component (alias)
37
118
  attribute :volume, Components::Volume # Volume component (v6)
38
119
  attribute :part, Components::Part # Part component (n1 or pt1)
39
120
  attribute :stage, Components::Stage
@@ -52,7 +133,6 @@ module Pubid
52
133
 
53
134
  # LEGACY attributes (keep for backward compatibility during migration)
54
135
  attribute :parts, Components::Code, collection: true
55
- attribute :revision, :string
56
136
  attribute :revision_year, :string # Year for revision (e.g., r6/1925, r1963, rJun1992)
57
137
  attribute :revision_month, :string # Month for revision (e.g., rJun1992)
58
138
  attribute :edition_year, :string # Legacy edition year for backward compatibility
@@ -108,12 +188,15 @@ module Pubid
108
188
  # Attributes that are build artifacts or rendering aliases, not part
109
189
  # of an identifier's logical identity. They diverge between equally-
110
190
  # valid spellings of the same id (e.g. long "Rev. 1" vs short "r1"):
111
- # - edition_component: redundant alias of :edition
112
191
  # - first_number/second_number: decomposed parts of the canonical
113
192
  # :number, retained from the parse for building
114
193
  # - parsed_format: records the input format for round-trip rendering
194
+ # - subseries: derived from series+number (which SP subseries the
195
+ # document belongs to); populated by the Builder for known SP
196
+ # subseries codes. Ignored in equality so a manually-built id
197
+ # without subseries set still equals a parsed one.
115
198
  EQUALITY_IGNORED_ATTRS = %i[
116
- edition_component first_number second_number parsed_format
199
+ first_number second_number parsed_format subseries
117
200
  ].freeze
118
201
 
119
202
  # Logical identity comparison: equal when every attribute except the
@@ -161,21 +244,11 @@ module Pubid
161
244
  end
162
245
  end
163
246
 
164
- # Return a copy with the named attributes nil'd. Overrides
165
- # Pubid::Identifier#exclude because NIST's initialize is keyword-only
166
- # (initialize(**attributes)) while the inherited exclude rebuilds via
167
- # the positional self.class.new(attrs) form — passing a positional
168
- # hash to a keyword-only initializer raises ArgumentError. Rebuild
169
- # with the keyword splat instead.
170
- def exclude(*args)
171
- excluded_args = args.dup
172
- excluded_args << :date if excluded_args.delete(:year)
173
-
174
- attrs = self.class.attributes.each_with_object({}) do |(name, _), h|
175
- h[name] = excluded_args.include?(name) ? nil : public_send(name)
176
- end
177
- self.class.new(**attrs)
178
- end
247
+ # NIST inherits Pubid::Identifier#exclude directly: it now rebuilds via
248
+ # `self.class.new(**attrs)`, so NIST's keyword-only initialize
249
+ # (initialize(**attributes)) works without a local override, and the base
250
+ # version additionally carries the nested-identifier recursion this class's
251
+ # old copy lacked.
179
252
 
180
253
  # Short-form supplement fragment ("sup", "sup1924", "supJan1924",
181
254
  # "suprev", " supJun1925-Jun1926"), rendered from the structured
@@ -190,15 +263,12 @@ module Pubid
190
263
  prefix + (rendered.empty? ? "sup" : rendered)
191
264
  end
192
265
 
193
- # Compute revision from edition component for backward compatibility
266
+ # Derived, read-only revision string ("r5", "e1979", "-3") for backward
267
+ # compatibility. `edition` is the single stored representation; this is
268
+ # never persisted, compared, or merged — just a convenience view of it.
194
269
  # @return [String, nil] revision string (e.g., "r5") or nil
195
270
  def revision
196
- return @revision if @revision
197
-
198
- # Compute from edition component if available
199
- if edition&.type && edition.id
200
- "#{edition.type}#{edition.id}"
201
- end
271
+ "#{edition.type}#{edition.id}" if edition&.type && edition.id
202
272
  end
203
273
 
204
274
  # Backward compatibility: translation method returns translation_component
@@ -243,11 +313,28 @@ module Pubid
243
313
  nist_format: format || parsed_format&.to_sym || :short)
244
314
  end
245
315
 
316
+ # NIST has its own defined MR format (to_mr_style) used by relaton-nist
317
+ # and downstream tooling. The generic Renderers::MrString does not know
318
+ # about NIST series, revisions, supplements, etc., so delegate to the
319
+ # established style for losslessness (issue #142).
320
+ def to_mr_string
321
+ to_mr_style
322
+ end
323
+
324
+ # NIST's MR shape is fixed by the pubid standard and stays uppercase
325
+ # (e.g. `NIST.SP.800-53`). The slug, however, must be lowercase to
326
+ # match the cross-flavor convention; project the MR through `downcase`.
327
+ def to_slug
328
+ to_mr_string.downcase
329
+ end
330
+
246
331
  # Returns weight based on amount of defined attributes
247
332
  # Used for ranking identifiers by specificity for conflict resolution
248
333
  # @return [Integer] weight score (higher = more specific)
249
334
  def weight
250
335
  self.class.attributes.keys.inject(0) do |sum, key|
336
+ next sum if EQUALITY_IGNORED_ATTRS.include?(key)
337
+
251
338
  val = public_send(key)
252
339
  val && !val.to_s.empty? ? sum + 1 : sum
253
340
  end
@@ -275,7 +362,7 @@ module Pubid
275
362
  when :edition
276
363
  current_val.nil? || edition_greater?(new_val,
277
364
  current_val)
278
- when :volume, :part, :version, :revision
365
+ when :volume, :part, :version
279
366
  current_val.nil? || (new_val.to_s.length > current_val.to_s.length)
280
367
  when :supplement, :errata, :index, :insert, :section, :appendix, :translation
281
368
  true
@@ -411,6 +498,10 @@ module Pubid
411
498
  result += " #{number}" if number
412
499
  result += parts.map { |p| "-#{p}" }.join if parts&.any?
413
500
 
501
+ # "NIST Research Library (YYYY)" — oddball identifier with no number;
502
+ # the year appears in parens rather than as a date component.
503
+ result += " (#{year})" if year && !number
504
+
414
505
  # Append every optional component the parser may have attached
415
506
  # (volume, part, edition, version, supplement, update, stage, ...).
416
507
  # Shared with the lossy subclasses so they cannot silently drop a
@@ -639,12 +730,5 @@ module Pubid
639
730
  end
640
731
  end
641
732
 
642
- module Identifiers
643
- # Backward-compatible alias: NIST's base class used to be
644
- # Pubid::Nist::Identifiers::Base. It is now Pubid::Nist::Identifier; keep
645
- # the old constant working for `class Foo < Base` declarations and any
646
- # external reference.
647
- Base = Pubid::Nist::Identifier
648
- end
649
733
  end
650
734
  end
@@ -7,7 +7,7 @@ module Pubid
7
7
  # Examples:
8
8
  # - "NBS CIRC 13e2revJune1908" = Circular 13, edition 2, revised June 1908
9
9
  # - "NBS CIRC 13" = Circular 13
10
- class Circular < Base
10
+ class Circular < Identifier
11
11
  TYPED_STAGES = [
12
12
  Pubid::Components::TypedStage.new(
13
13
  abbr: ["CIRC", "NBS CIRC"],
@@ -9,7 +9,7 @@ module Pubid
9
9
  # - "NBS CS 102" - Basic commercial standard
10
10
  # - "NBS CS 102E-42" - With letter suffix and number
11
11
  # - "CS 190-58" - With year
12
- class CommercialStandard < Base
12
+ class CommercialStandard < Identifier
13
13
  TYPED_STAGES = [
14
14
  Pubid::Components::TypedStage.new(
15
15
  abbr: ["CS", "NBS CS"],
@@ -6,7 +6,7 @@ module Pubid
6
6
  # NBS Commercial Standard (Emergency) Identifier
7
7
  # Format: NBS CS eNNN-YY where NNN is edition number, YY is 2-digit year
8
8
  # Example: "NBS CS e104-43" = Commercial Standard Emergency edition 104, year 1943
9
- class CommercialStandardEmergency < Base
9
+ class CommercialStandardEmergency < Identifier
10
10
  TYPED_STAGES = [
11
11
  Pubid::Components::TypedStage.new(
12
12
  abbr: ["CS-E", "NBS CS-E"],
@@ -6,7 +6,7 @@ module Pubid
6
6
  # NBS Commercial Standards Monthly Identifier
7
7
  # Format: NBS CSM N where N is simple number
8
8
  # Example: "NBS CSM 1", "NBS CSM 40"
9
- class CommercialStandardsMonthly < Base
9
+ class CommercialStandardsMonthly < Identifier
10
10
  TYPED_STAGES = [
11
11
  Pubid::Components::TypedStage.new(
12
12
  abbr: ["CSM", "NBS CSM"],
@@ -8,7 +8,7 @@ module Pubid
8
8
  # - "NBS CRPL 1-2_3-1" = Reports 1-2 and 3-1 jointly
9
9
  # - "NBS CRPL 4-m-5" = Report 4, month m, issue 5
10
10
  # - "NBS CRPL c4-4" = Report c4, issue 4
11
- class CrplReport < Base
11
+ class CrplReport < Identifier
12
12
  TYPED_STAGES = [
13
13
  Pubid::Components::TypedStage.new(
14
14
  abbr: ["CRPL", "NBS CRPL", "CRPL-F-B", "CRPL-F-A", "NBS CRPL-F-B",
@@ -7,7 +7,7 @@ module Pubid
7
7
  # Examples:
8
8
  # - "NIST 2022-04-15 001" (short) / "NIST.2022-04-15.001" (mr/doi)
9
9
  # DOI 10.6028/NIST.2022-04-15.001
10
- class DatedDocument < Base
10
+ class DatedDocument < Identifier
11
11
  # Empty so the bare "NIST" abbr never shadows a series lookup; the
12
12
  # Router guard (parsed_hash[:dated_date] && :dated_seq) is the dispatch path.
13
13
  TYPED_STAGES = [].freeze
@@ -7,7 +7,7 @@ module Pubid
7
7
  # Examples:
8
8
  # - "FIPS 140-3" (no NIST prefix)
9
9
  # - "NIST FIPS 140-3" (also accepted, normalizes to FIPS 140-3)
10
- class FederalInformationProcessingStandards < Base
10
+ class FederalInformationProcessingStandards < Identifier
11
11
  TYPED_STAGES = [
12
12
  Pubid::Components::TypedStage.new(
13
13
  abbr: ["FIPS", "NIST FIPS"],
@@ -7,7 +7,7 @@ module Pubid
7
7
  # Examples:
8
8
  # - "NIST GCR 17-917-45" - Basic 3-part number
9
9
  # - "NIST GCR 21-917-48v3B" - With volume and letter suffix
10
- class GrantContractorReport < Base
10
+ class GrantContractorReport < Identifier
11
11
  TYPED_STAGES = [
12
12
  Pubid::Components::TypedStage.new(
13
13
  abbr: ["GCR", "NIST GCR"],
@@ -7,7 +7,7 @@ module Pubid
7
7
  # Examples:
8
8
  # - "NIST HB 130" = Handbook 130
9
9
  # - "NBS HB 133" = NBS Handbook 133
10
- class Handbook < Base
10
+ class Handbook < Identifier
11
11
  TYPED_STAGES = [
12
12
  Pubid::Components::TypedStage.new(
13
13
  abbr: ["HB", "NIST HB", "NBS HB"],
@@ -8,7 +8,7 @@ module Pubid
8
8
  # - "NIST IR 8115" = Interagency Report 8115
9
9
  # - "NIST IR 8115r1" = Interagency Report 8115 revision 1
10
10
  # - "NBS IR 73-197" = NBS Interagency Report 73-197
11
- class InteragencyReport < Base
11
+ class InteragencyReport < Identifier
12
12
  TYPED_STAGES = [
13
13
  Pubid::Components::TypedStage.new(
14
14
  abbr: ["IR", "NIST IR", "NBS IR"],
@@ -11,7 +11,7 @@ module Pubid
11
11
  # - "NBS LC 378sup12/1926" - With supplement date
12
12
  # - "NBS LC 378r11/1925" - With revision date
13
13
  # - "NBS LC 378(sp)" - With language code
14
- class LetterCircular < Base
14
+ class LetterCircular < Identifier
15
15
  TYPED_STAGES = [
16
16
  Pubid::Components::TypedStage.new(
17
17
  abbr: ["LCIRC"], # Single definition of truth
@@ -8,7 +8,7 @@ module Pubid
8
8
  # - "NBS MP 39e1" - Edition with "e" notation
9
9
  # - "NBS MP 260e1965" - Edition with year as edition ID
10
10
  # NOTE: Parenthetical edition format (e.g., "39(1)") does NOT exist for MP identifiers
11
- class MiscellaneousPublication < Base
11
+ class MiscellaneousPublication < Identifier
12
12
  TYPED_STAGES = [
13
13
  Pubid::Components::TypedStage.new(
14
14
  abbr: ["MP", "NBS MP"],
@@ -10,7 +10,7 @@ module Pubid
10
10
  # - "NBS MONO 128pt1" - Monograph with part
11
11
  # - "NIST MONO 1-1F" - Monograph with letter suffix
12
12
  # - "NIST MONO 1-2Bv1" - Monograph with letter suffix and volume
13
- class Monograph < Base
13
+ class Monograph < Identifier
14
14
  TYPED_STAGES = [
15
15
  Pubid::Components::TypedStage.new(
16
16
  abbr: ["MONO", "NBS MONO", "NIST MONO"],
@@ -8,7 +8,7 @@ module Pubid
8
8
  # - "NIST NCSTAR 1-1Cv1" → "NIST NCSTAR 1-1Cv1" (round-trips)
9
9
  # - "NIST NCSTAR 1-1b" → "NIST NCSTAR 1-1B" (normalizes letter)
10
10
  # - "NIST NCSTAR 1-1cv1" → "NIST NCSTAR 1-1Cv1" (normalizes letter, keeps v1 format)
11
- class Ncstar < Base
11
+ class Ncstar < Identifier
12
12
  TYPED_STAGES = [
13
13
  Pubid::Components::TypedStage.new(
14
14
  abbr: ["NCSTAR", "NIST NCSTAR"],
@@ -34,7 +34,7 @@ module Pubid
34
34
 
35
35
  # NCSTAR-specific: do NOT expand Cv patterns to ", Volume" format
36
36
  # The base class would render "1-1Cv1" as is, which is correct for NCSTAR
37
- # No custom rendering needed - just inherit from Base
37
+ # No custom rendering needed - just inherit from Identifier
38
38
  end
39
39
  end
40
40
  end
@@ -8,7 +8,7 @@ module Pubid
8
8
  # - "NBS NSRDS 1" - Basic NSRDS
9
9
  # - "NSRDS-NBS 1" - With hyphen prefix
10
10
  # - "NBS NSRDS 1p1" - With part notation
11
- class Nsrds < Base
11
+ class Nsrds < Identifier
12
12
  TYPED_STAGES = [
13
13
  Pubid::Components::TypedStage.new(
14
14
  abbr: ["NSRDS", "NBS NSRDS"],
@@ -6,7 +6,7 @@ module Pubid
6
6
  # NIST OWMWP (Office of Weights and Measures Workshop Proceedings)
7
7
  # Examples:
8
8
  # - "NIST OWMWP 06-13-2018" - Date-based format MM-DD-YYYY
9
- class Owmwp < Base
9
+ class Owmwp < Identifier
10
10
  TYPED_STAGES = [
11
11
  Pubid::Components::TypedStage.new(
12
12
  abbr: ["OWMWP", "NIST OWMWP"],
@@ -11,7 +11,7 @@ module Pubid
11
11
  # - "NBS RPT ADHOC" - Ad hoc report
12
12
  # - "NBS RPT div9" - Division report
13
13
  # - "NBS RPT 4817-A" - Report with letter suffix
14
- class Report < Base
14
+ class Report < Identifier
15
15
  TYPED_STAGES = [
16
16
  Pubid::Components::TypedStage.new(
17
17
  abbr: ["RPT", "NBS RPT"],
@@ -8,7 +8,16 @@ module Pubid
8
8
  # - "NIST SP 800-53" = Special Publication 800-53
9
9
  # - "NIST SP 800-53r5" = Special Publication 800-53 revision 5
10
10
  # - "NIST SP 800-57pt1r4" = Special Publication 800-57 part 1 revision 4
11
- class SpecialPublication < Base
11
+ class SpecialPublication < Identifier
12
+ # Per Appendix A.2 of the NIST PubID Syntax (April 2022), the SP series
13
+ # is subdivided into named subseries. The subseries number is the
14
+ # leading token of a report-num like "800-53" or "1190GB-12". The
15
+ # Builder exposes this as `identifier.subseries` so callers can query
16
+ # which subseries a document belongs to.
17
+ SP_SUBSERIES = %w[
18
+ 250 260 300 400 480 500 700 800 823 960 1190GB 1200 1500 1800 1900 2000 2100
19
+ ].freeze
20
+
12
21
  TYPED_STAGES = [
13
22
  Pubid::Components::TypedStage.new(
14
23
  abbr: ["SP", "NIST SP", "NBS SP"], # Compound series
@@ -7,7 +7,7 @@ module Pubid
7
7
  # Examples:
8
8
  # - "NIST TN 1234" = Technical Note 1234
9
9
  # - "NBS TN 567" = NBS Technical Note 567
10
- class TechnicalNote < Base
10
+ class TechnicalNote < Identifier
11
11
  TYPED_STAGES = [
12
12
  Pubid::Components::TypedStage.new(
13
13
  abbr: ["TN", "NIST TN", "NBS TN"],
@@ -3,7 +3,6 @@
3
3
  module Pubid
4
4
  module Nist
5
5
  module Identifiers
6
- autoload :Base, "#{__dir__}/identifiers/base"
7
6
  autoload :Circular, "#{__dir__}/identifiers/circular"
8
7
  autoload :CircularSupplement, "#{__dir__}/identifiers/circular_supplement"
9
8
  autoload :CommercialStandard, "#{__dir__}/identifiers/commercial_standard"
@@ -116,7 +116,9 @@ module Pubid
116
116
  str("AI") | str("CIRC") | str("CS") | str("CSM") |
117
117
  str("CRPL") | str("LCIRC") | str("OWMWP") | str("PC") | str("RPT") |
118
118
  str("SIBS") | str("TIBM") | str("TTB") | str("EAB") |
119
- str("JPCRD") | str("JRES")
119
+ str("JPCRD") | str("JRES") |
120
+ # NEW - CHIPS Act, NWIRP, and Research Brief series
121
+ str("CHIPS") | str("NWIRP") | str("RB")
120
122
  ).as(:series)
121
123
  end
122
124
 
@@ -344,6 +346,16 @@ module Pubid
344
346
  match("[0-9]").repeat(1).as(:dated_seq)
345
347
  end
346
348
 
349
+ # "NIST Research Library (YYYY)" — one-off NIST publication that doesn't
350
+ # fit the standard series+number shape (no report number, year in parens).
351
+ # See pubid/pubid#151.
352
+ rule(:research_library_identifier) do
353
+ publisher >> space >>
354
+ str("Research Library").as(:series) >>
355
+ (space >> str("(") >>
356
+ match("[0-9]").repeat(4, 4).as(:year) >> str(")")).maybe
357
+ end
358
+
347
359
  # LEGACY EDITION PATTERNS (for backward compatibility during migration)
348
360
  # These will be gradually replaced as we migrate to proper Edition/Date components
349
361
  rule(:legacy_edition) do
@@ -436,7 +448,12 @@ module Pubid
436
448
 
437
449
  # Volume
438
450
  rule(:volume) do
439
- (space.maybe >> (str("v") | str(" Vol. "))) >>
451
+ # Long-form "Vol." comes FIRST so PEG ordered choice doesn't commit to
452
+ # the bare "v" alternative after consuming the leading space via
453
+ # space.maybe (which would then starve the " Vol. " form). Both
454
+ # "Vol. 4" (period + space) and "Vol.4" (period only) are accepted.
455
+ (space.maybe >>
456
+ (str("Vol. ") | str("Vol.") | str("v"))) >>
440
457
  (digits >>
441
458
  # Support letter ranges (lowercase normalized in preprocessing)
442
459
  (str("a-l") | str("m-z") | str("A-L") | str("M-Z")).maybe >>
@@ -446,7 +463,8 @@ module Pubid
446
463
 
447
464
  # Part - enhanced to support patterns like p1adde1 AND pt3r1 (part with revision)
448
465
  rule(:part) do
449
- ((space.maybe >> (str("pt") | str("p") | str("P"))) | str(" Part ")) >>
466
+ (str(" Part. ") | str(" Part.") | str(" Part ") |
467
+ (space.maybe >> (str("pt") | str("p") | str("P")))) >>
450
468
  (digits >>
451
469
  # NEW: Revision after part number: pt3r1, p1r1 (space.maybe for preprocessing)
452
470
  (space.maybe >> str("r") >> digits).maybe >>
@@ -472,7 +490,8 @@ module Pubid
472
490
  # Enhanced to accept letter-only revisions and space before r
473
491
  # ENHANCED: Accept BOTH lowercase and uppercase letters in suffix
474
492
  # ENHANCED: Capture original format prefix for format preservation (e.g., " Rev. 5")
475
- ((str(" rev ") | str("rev") | str(" r") | str("r") | str(" Rev. ") | str(" Revision (r)")).as(:revision_prefix) >>
493
+ ((str(" rev ") | str("rev") | str(" r") | str("r") | str(" Rev. ") | str(" Rev.") | str(" Revision (r)")).as(:revision_prefix) >>
494
+ space.maybe >>
476
495
  ((digits >> match("[a-zA-Z]").maybe) | match("[a-zA-Z]").repeat(1)).as(:revision_id)).as(:revision) |
477
496
  # NEW: Standalone 'r' - MUST BE LAST to avoid consuming from other patterns
478
497
  # Matches " r" at end of input (after preprocessing: "800-56a r", "800-27 r")
@@ -654,6 +673,7 @@ module Pubid
654
673
  circ_supplement_identifier |
655
674
  dated_identifier |
656
675
  mr_identifier |
676
+ research_library_identifier |
657
677
  (
658
678
  # Compound series (includes publisher in series name)
659
679
  compound_series >> (space | dot) >>
@@ -688,6 +708,11 @@ module Pubid
688
708
  # Date range supplement (no base number)
689
709
  (str("supp") >> month_abbrev.as(:supp_month_start) >> digits.as(:supp_year_start) >>
690
710
  dash >> month_abbrev.as(:supp_month_end) >> digits.as(:supp_year_end)).as(:supplement_date_range) |
711
+ # Year-only date range supplement to the whole series, no months
712
+ # (e.g. "NBS CIRC sup1925-1926" — pubid/pubid#152). Requires two
713
+ # 4-digit years so it can't swallow "sup3/1926" or a base number.
714
+ ((str("supp") | str("sup")) >> match("[0-9]").repeat(4, 4).as(:supp_year_start) >>
715
+ dash >> match("[0-9]").repeat(4, 4).as(:supp_year_end)).as(:supplement_date_range) |
691
716
  # With base identifier + supplement
692
717
  (
693
718
  # Capture base portion (everything before "supp" or "sup" or slash+year)
@@ -343,6 +343,21 @@ module Pubid
343
343
  revert_handbook_edition!
344
344
  revert_owmwp_date!
345
345
  revert_report_year_range!
346
+ revert_circ_supplement_year_range!
347
+ end
348
+
349
+ # CIRC/LCIRC year-only series supplements: "NBS CIRC sup1925-1926" is a
350
+ # supplement spanning a year range, so the trailing "-1926" is a range
351
+ # end, not an edition. convert_dashyear_to_edition! would have rewritten
352
+ # it to "sup1925e1926"; restore the dash so the circ_supplement_identifier
353
+ # grammar can read the range (pubid/pubid#152).
354
+ def revert_circ_supplement_year_range!
355
+ return unless @cleaned.include?("CIRC")
356
+
357
+ # Anchor on the series prefix ("CIRC " / "CIRC." / "LCIRC ") so only the
358
+ # whole-series form (sup right after the series, no base number) is
359
+ # reverted — a based "24sup1940e1950" keeps its genuine edition.
360
+ @cleaned = @cleaned.gsub(/(CIRC[ .])(supp?)(\d{4})e(\d{4})(?=\s|$)/, '\1\2\3-\4')
346
361
  end
347
362
 
348
363
  # HB handbooks: "HB 130e1979" → "HB 130-1979" (year is part of
@@ -18,6 +18,7 @@ module Pubid
18
18
  "GCR", "AMS", "BSS", "BMS", "BH", "MONO", "MP",
19
19
  "NCSTAR", "NSRDS", "CSWP", "VTS", "AI", "OWMWP",
20
20
  "PC", "RPT", "SIBS", "TIBM", "TTB", "EAB",
21
+ "CHIPS", "NWIRP", "RB",
21
22
  "JPCRD", "JRES", "CIS", "HR", "IRPL", "IP",
22
23
  "LC", "PS", "LCIRC",
23
24
  # Compound series
@@ -126,10 +127,10 @@ module Pubid
126
127
  # instead of an injected dependency.
127
128
  typed_stage = Pubid::Nist.locate_stage(series)
128
129
  if typed_stage
129
- Pubid::Nist.locate_type(typed_stage.type_code) || Identifiers::Base
130
+ Pubid::Nist.locate_type(typed_stage.type_code) || Identifier
130
131
  else
131
132
  # Fallback to Base for unmapped series (e.g., "AMS", "VTS")
132
- Identifiers::Base
133
+ Identifier
133
134
  end
134
135
  end
135
136
 
@@ -36,8 +36,6 @@ module Pubid
36
36
  )
37
37
  edition_obj = Components::Edition.new(type: "r", id: "1")
38
38
  identifier.edition = edition_obj
39
- identifier.edition_component = edition_obj
40
- identifier.revision = "r1"
41
39
  true
42
40
  end
43
41
 
@@ -52,7 +50,6 @@ module Pubid
52
50
  value: "#{match[1]}-#{match[2]}",
53
51
  )
54
52
  identifier.edition = nil
55
- identifier.edition_component = nil
56
53
  end
57
54
  end
58
55
  end