pubid 2.0.0.alpha.10 → 2.0.0.pre.alpha.1

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 (811) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +51 -54
  3. data/data/iec/update_codes.yaml +0 -3
  4. data/data/ieee/update_codes.yaml +1 -107
  5. data/data/nist/update_codes.yaml +0 -35
  6. data/lib/pubid/amca/builder.rb +6 -6
  7. data/lib/pubid/amca/identifier.rb +16 -2
  8. data/lib/pubid/amca/identifiers/base.rb +46 -74
  9. data/lib/pubid/amca/identifiers/interpretation.rb +30 -17
  10. data/lib/pubid/amca/identifiers/publication.rb +27 -14
  11. data/lib/pubid/amca/identifiers/standard.rb +5 -3
  12. data/lib/pubid/amca/identifiers.rb +1 -0
  13. data/lib/pubid/amca/parser.rb +1 -1
  14. data/lib/pubid/amca/scheme.rb +16 -0
  15. data/lib/pubid/amca/single_identifier.rb +24 -1
  16. data/lib/pubid/amca/urn_generator.rb +3 -4
  17. data/lib/pubid/amca.rb +3 -50
  18. data/lib/pubid/ansi/builder.rb +5 -7
  19. data/lib/pubid/ansi/identifier.rb +1 -19
  20. data/lib/pubid/ansi/identifiers/american_national_standard.rb +1 -2
  21. data/lib/pubid/ansi/identifiers/standard.rb +3 -2
  22. data/lib/pubid/ansi/parser.rb +1 -1
  23. data/lib/pubid/ansi/scheme.rb +15 -0
  24. data/lib/pubid/ansi/single_identifier.rb +31 -2
  25. data/lib/pubid/ansi/urn_generator.rb +38 -3
  26. data/lib/pubid/ansi.rb +6 -47
  27. data/lib/pubid/api/builder.rb +72 -45
  28. data/lib/pubid/api/identifier.rb +9 -30
  29. data/lib/pubid/api/identifiers/base.rb +14 -2
  30. data/lib/pubid/api/identifiers/bulletin.rb +2 -0
  31. data/lib/pubid/api/identifiers/continuous_operations_standard.rb +2 -0
  32. data/lib/pubid/api/identifiers/mpms.rb +28 -10
  33. data/lib/pubid/api/identifiers/publication.rb +2 -0
  34. data/lib/pubid/api/identifiers/recommended_practice.rb +2 -0
  35. data/lib/pubid/api/identifiers/specification.rb +2 -0
  36. data/lib/pubid/api/identifiers/standard.rb +2 -0
  37. data/lib/pubid/api/identifiers/technical_report.rb +2 -0
  38. data/lib/pubid/api/identifiers/typeless_standard.rb +16 -0
  39. data/lib/pubid/api/parser.rb +1 -1
  40. data/lib/pubid/api/scheme.rb +66 -0
  41. data/lib/pubid/api/single_identifier.rb +32 -10
  42. data/lib/pubid/api/urn_generator.rb +18 -0
  43. data/lib/pubid/api.rb +5 -56
  44. data/lib/pubid/ashrae/builder.rb +35 -56
  45. data/lib/pubid/ashrae/identifier.rb +16 -6
  46. data/lib/pubid/ashrae/identifiers/addenda_package.rb +11 -7
  47. data/lib/pubid/ashrae/identifiers/addendum.rb +20 -9
  48. data/lib/pubid/ashrae/identifiers/base.rb +15 -111
  49. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +16 -8
  50. data/lib/pubid/ashrae/identifiers/errata.rb +10 -9
  51. data/lib/pubid/ashrae/identifiers/guideline.rb +0 -3
  52. data/lib/pubid/ashrae/identifiers/interpretation.rb +10 -16
  53. data/lib/pubid/ashrae/identifiers/standard.rb +0 -3
  54. data/lib/pubid/ashrae/identifiers.rb +1 -0
  55. data/lib/pubid/ashrae/parser.rb +16 -40
  56. data/lib/pubid/ashrae/scheme.rb +53 -0
  57. data/lib/pubid/ashrae/single_identifier.rb +14 -1
  58. data/lib/pubid/ashrae/supplement_identifier.rb +6 -21
  59. data/lib/pubid/ashrae/urn_generator.rb +10 -8
  60. data/lib/pubid/ashrae.rb +2 -58
  61. data/lib/pubid/asme/builder.rb +2 -11
  62. data/lib/pubid/asme/components/code.rb +2 -10
  63. data/lib/pubid/asme/identifier.rb +0 -9
  64. data/lib/pubid/asme/identifiers/base.rb +60 -0
  65. data/lib/pubid/asme/identifiers/standard.rb +2 -86
  66. data/lib/pubid/asme/parser.rb +1 -1
  67. data/lib/pubid/asme/scheme.rb +37 -0
  68. data/lib/pubid/asme/single_identifier.rb +2 -11
  69. data/lib/pubid/asme/urn_generator.rb +2 -2
  70. data/lib/pubid/asme.rb +1 -47
  71. data/lib/pubid/astm/builder.rb +3 -10
  72. data/lib/pubid/astm/components/code.rb +0 -9
  73. data/lib/pubid/astm/identifier.rb +0 -9
  74. data/lib/pubid/astm/identifiers/adjunct.rb +9 -16
  75. data/lib/pubid/astm/identifiers/data_series.rb +14 -2
  76. data/lib/pubid/astm/identifiers/iso_dual_published.rb +34 -25
  77. data/lib/pubid/astm/identifiers/manual.rb +25 -8
  78. data/lib/pubid/astm/identifiers/monograph.rb +14 -2
  79. data/lib/pubid/astm/identifiers/research_report.rb +5 -8
  80. data/lib/pubid/astm/identifiers/standard.rb +37 -8
  81. data/lib/pubid/astm/identifiers/technical_report.rb +13 -2
  82. data/lib/pubid/astm/identifiers/work_in_progress.rb +10 -1
  83. data/lib/pubid/astm/parser.rb +1 -1
  84. data/lib/pubid/astm/scheme.rb +55 -0
  85. data/lib/pubid/astm/single_identifier.rb +10 -32
  86. data/lib/pubid/astm/urn_generator.rb +5 -7
  87. data/lib/pubid/astm.rb +27 -44
  88. data/lib/pubid/bsi/builder.rb +107 -119
  89. data/lib/pubid/bsi/identifier.rb +25 -4
  90. data/lib/pubid/bsi/identifiers/addendum_document.rb +37 -3
  91. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +47 -19
  92. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +39 -8
  93. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +55 -2
  94. data/lib/pubid/bsi/identifiers/amendment.rb +22 -30
  95. data/lib/pubid/bsi/identifiers/base.rb +11 -0
  96. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +7 -1
  97. data/lib/pubid/bsi/identifiers/british_standard.rb +1 -2
  98. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +87 -13
  99. data/lib/pubid/bsi/identifiers/committee_document.rb +17 -10
  100. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +87 -19
  101. data/lib/pubid/bsi/identifiers/corrigendum.rb +10 -26
  102. data/lib/pubid/bsi/identifiers/detailed_specification.rb +36 -0
  103. data/lib/pubid/bsi/identifiers/disc.rb +29 -0
  104. data/lib/pubid/bsi/identifiers/draft_document.rb +46 -2
  105. data/lib/pubid/bsi/identifiers/electronic_book.rb +38 -2
  106. data/lib/pubid/bsi/identifiers/expert_commentary.rb +21 -10
  107. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +47 -0
  108. data/lib/pubid/bsi/identifiers/flex.rb +34 -3
  109. data/lib/pubid/bsi/identifiers/handbook.rb +17 -1
  110. data/lib/pubid/bsi/identifiers/index.rb +32 -0
  111. data/lib/pubid/bsi/identifiers/method.rb +41 -0
  112. data/lib/pubid/bsi/identifiers/national_annex.rb +29 -4
  113. data/lib/pubid/bsi/identifiers/practice_guide.rb +7 -1
  114. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +54 -2
  115. data/lib/pubid/bsi/identifiers/published_document.rb +54 -2
  116. data/lib/pubid/bsi/identifiers/section.rb +30 -0
  117. data/lib/pubid/bsi/identifiers/set.rb +20 -14
  118. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +10 -10
  119. data/lib/pubid/bsi/identifiers/supplement_document.rb +25 -3
  120. data/lib/pubid/bsi/identifiers/supplementary_index.rb +46 -0
  121. data/lib/pubid/bsi/identifiers/technical_specification.rb +47 -2
  122. data/lib/pubid/bsi/identifiers/test_method.rb +32 -0
  123. data/lib/pubid/bsi/identifiers/value_added_publication.rb +22 -7
  124. data/lib/pubid/bsi/identifiers.rb +1 -0
  125. data/lib/pubid/bsi/parser.rb +6 -20
  126. data/lib/pubid/bsi/scheme.rb +243 -0
  127. data/lib/pubid/bsi/single_identifier.rb +82 -94
  128. data/lib/pubid/bsi/urn_generator.rb +5 -13
  129. data/lib/pubid/bsi.rb +2 -252
  130. data/lib/pubid/builder/base.rb +13 -62
  131. data/lib/pubid/bundled_identifier.rb +10 -18
  132. data/lib/pubid/ccsds/builder.rb +4 -5
  133. data/lib/pubid/ccsds/identifier.rb +3 -63
  134. data/lib/pubid/ccsds/identifiers/base.rb +51 -14
  135. data/lib/pubid/ccsds/identifiers/corrigendum.rb +8 -9
  136. data/lib/pubid/ccsds/parser.rb +3 -5
  137. data/lib/pubid/ccsds/scheme.rb +57 -0
  138. data/lib/pubid/ccsds/single_identifier.rb +3 -6
  139. data/lib/pubid/ccsds/supplement_identifier.rb +13 -17
  140. data/lib/pubid/ccsds/urn_generator.rb +6 -6
  141. data/lib/pubid/ccsds.rb +1 -44
  142. data/lib/pubid/cen_cenelec/builder.rb +29 -61
  143. data/lib/pubid/cen_cenelec/identifier.rb +5 -28
  144. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +4 -9
  145. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +12 -2
  146. data/lib/pubid/cen_cenelec/identifiers/base.rb +46 -5
  147. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +1 -2
  148. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +1 -2
  149. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +27 -6
  150. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +17 -2
  151. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +4 -62
  152. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +7 -20
  153. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +1 -2
  154. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +6 -2
  155. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +1 -2
  156. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +1 -2
  157. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +1 -2
  158. data/lib/pubid/cen_cenelec/parser.rb +1 -1
  159. data/lib/pubid/cen_cenelec/scheme.rb +164 -0
  160. data/lib/pubid/cen_cenelec/single_identifier.rb +91 -10
  161. data/lib/pubid/cen_cenelec/supplement_identifier.rb +7 -6
  162. data/lib/pubid/cen_cenelec/urn_generator.rb +7 -7
  163. data/lib/pubid/cen_cenelec.rb +1 -188
  164. data/lib/pubid/cie/builder.rb +24 -149
  165. data/lib/pubid/cie/components/code.rb +72 -0
  166. data/lib/pubid/cie/identifier.rb +5 -20
  167. data/lib/pubid/cie/identifiers/bundle.rb +5 -35
  168. data/lib/pubid/cie/identifiers/conference.rb +6 -11
  169. data/lib/pubid/cie/identifiers/corrigendum.rb +23 -17
  170. data/lib/pubid/cie/identifiers/dual_published.rb +6 -6
  171. data/lib/pubid/cie/identifiers/identical.rb +9 -9
  172. data/lib/pubid/cie/identifiers/joint_published.rb +10 -10
  173. data/lib/pubid/cie/identifiers/standard.rb +8 -43
  174. data/lib/pubid/cie/identifiers/supplement.rb +25 -27
  175. data/lib/pubid/cie/identifiers/tutorial_bundle.rb +3 -7
  176. data/lib/pubid/cie/identifiers.rb +0 -2
  177. data/lib/pubid/cie/parser.rb +6 -55
  178. data/lib/pubid/cie/scheme.rb +64 -0
  179. data/lib/pubid/cie/single_identifier.rb +5 -44
  180. data/lib/pubid/cie/supplement_identifier.rb +16 -29
  181. data/lib/pubid/cie/urn_generator.rb +8 -11
  182. data/lib/pubid/cie.rb +2 -57
  183. data/lib/pubid/components/code.rb +8 -22
  184. data/lib/pubid/components/date.rb +18 -41
  185. data/lib/pubid/components/edition.rb +6 -9
  186. data/lib/pubid/components/language.rb +4 -6
  187. data/lib/pubid/components/locality.rb +1 -10
  188. data/lib/pubid/components/publisher.rb +6 -9
  189. data/lib/pubid/components/stage.rb +14 -5
  190. data/lib/pubid/components/type.rb +15 -5
  191. data/lib/pubid/components/typed_stage.rb +8 -11
  192. data/lib/pubid/components.rb +0 -4
  193. data/lib/pubid/core/update_codes.rb +7 -28
  194. data/lib/pubid/csa/builder.rb +48 -48
  195. data/lib/pubid/csa/composite_identifier.rb +7 -18
  196. data/lib/pubid/csa/identifier.rb +78 -191
  197. data/lib/pubid/csa/identifiers/base.rb +123 -0
  198. data/lib/pubid/csa/identifiers/bundled.rb +9 -25
  199. data/lib/pubid/csa/identifiers/canadian_adopted.rb +13 -13
  200. data/lib/pubid/csa/identifiers/cec.rb +103 -40
  201. data/lib/pubid/csa/identifiers/combined.rb +69 -97
  202. data/lib/pubid/csa/identifiers/csa_adopted.rb +4 -4
  203. data/lib/pubid/csa/identifiers/package.rb +4 -4
  204. data/lib/pubid/csa/identifiers/series.rb +104 -0
  205. data/lib/pubid/csa/parser.rb +8 -12
  206. data/lib/pubid/csa/scheme.rb +44 -0
  207. data/lib/pubid/csa/single_identifier.rb +5 -94
  208. data/lib/pubid/csa/urn_generator.rb +2 -9
  209. data/lib/pubid/csa/wrapper_identifier.rb +10 -43
  210. data/lib/pubid/csa.rb +1 -56
  211. data/lib/pubid/etsi/builder.rb +4 -13
  212. data/lib/pubid/etsi/components/code.rb +9 -10
  213. data/lib/pubid/etsi/components/version.rb +5 -0
  214. data/lib/pubid/etsi/identifier.rb +12 -2
  215. data/lib/pubid/etsi/identifiers/base.rb +24 -60
  216. data/lib/pubid/etsi/identifiers/etsi_standard.rb +4 -207
  217. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +14 -46
  218. data/lib/pubid/etsi/identifiers.rb +1 -0
  219. data/lib/pubid/etsi/parser.rb +3 -9
  220. data/lib/pubid/etsi/scheme.rb +42 -0
  221. data/lib/pubid/etsi.rb +2 -52
  222. data/lib/pubid/export/data_class_exporter.rb +59 -0
  223. data/lib/pubid/export/exporter.rb +47 -6
  224. data/lib/pubid/export/flavor_exporter.rb +276 -124
  225. data/lib/pubid/export/ieee_exporter.rb +78 -0
  226. data/lib/pubid/export/itu_exporter.rb +66 -0
  227. data/lib/pubid/export/nist_exporter.rb +64 -0
  228. data/lib/pubid/export/registry_exporter.rb +90 -0
  229. data/lib/pubid/export/scheme_exporter.rb +70 -0
  230. data/lib/pubid/export.rb +6 -0
  231. data/lib/pubid/identifier.rb +37 -920
  232. data/lib/pubid/identifier_metadata.rb +1 -1
  233. data/lib/pubid/identifier_registry.rb +198 -0
  234. data/lib/pubid/idf/builder.rb +7 -7
  235. data/lib/pubid/idf/identifier.rb +13 -23
  236. data/lib/pubid/idf/identifiers/amendment.rb +1 -2
  237. data/lib/pubid/idf/identifiers/corrigendum.rb +1 -2
  238. data/lib/pubid/idf/identifiers/international_standard.rb +1 -2
  239. data/lib/pubid/idf/identifiers/reviewed_method.rb +1 -2
  240. data/lib/pubid/idf/parser.rb +5 -6
  241. data/lib/pubid/idf/scheme.rb +61 -0
  242. data/lib/pubid/idf/supplement_identifier.rb +13 -5
  243. data/lib/pubid/idf/urn_generator.rb +39 -4
  244. data/lib/pubid/idf.rb +1 -65
  245. data/lib/pubid/iec/builder.rb +91 -92
  246. data/lib/pubid/iec/components/code.rb +32 -9
  247. data/lib/pubid/iec/components/publisher.rb +1 -1
  248. data/lib/pubid/iec/identifier.rb +8 -328
  249. data/lib/pubid/iec/identifiers/amendment.rb +5 -8
  250. data/lib/pubid/iec/identifiers/base.rb +31 -7
  251. data/lib/pubid/iec/identifiers/component_specification.rb +13 -3
  252. data/lib/pubid/iec/identifiers/conformity_assessment.rb +12 -1
  253. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +30 -29
  254. data/lib/pubid/iec/identifiers/corrigendum.rb +5 -4
  255. data/lib/pubid/iec/identifiers/fragment_identifier.rb +36 -43
  256. data/lib/pubid/iec/identifiers/guide.rb +18 -0
  257. data/lib/pubid/iec/identifiers/international_standard.rb +9 -24
  258. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +3 -2
  259. data/lib/pubid/iec/identifiers/operational_document.rb +13 -3
  260. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +15 -2
  261. data/lib/pubid/iec/identifiers/sheet_identifier.rb +24 -26
  262. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +13 -3
  263. data/lib/pubid/iec/identifiers/systems_reference_document.rb +13 -2
  264. data/lib/pubid/iec/identifiers/technical_report.rb +21 -3
  265. data/lib/pubid/iec/identifiers/technical_specification.rb +21 -3
  266. data/lib/pubid/iec/identifiers/technology_report.rb +12 -1
  267. data/lib/pubid/iec/identifiers/test_report_form.rb +46 -3
  268. data/lib/pubid/iec/identifiers/vap_identifier.rb +34 -33
  269. data/lib/pubid/iec/identifiers/white_paper.rb +13 -3
  270. data/lib/pubid/iec/identifiers/working_document.rb +60 -26
  271. data/lib/pubid/iec/parser.rb +42 -73
  272. data/lib/pubid/iec/scheme.rb +71 -0
  273. data/lib/pubid/iec/single_identifier.rb +23 -15
  274. data/lib/pubid/iec/supplement_identifier.rb +67 -84
  275. data/lib/pubid/iec/urn_generator.rb +143 -195
  276. data/lib/pubid/iec/urn_parser.rb +246 -85
  277. data/lib/pubid/iec.rb +66 -45
  278. data/lib/pubid/ieee/aiee/builder.rb +3 -17
  279. data/lib/pubid/ieee/aiee/identifier.rb +62 -46
  280. data/lib/pubid/ieee/aiee/parser.rb +1 -1
  281. data/lib/pubid/ieee/builder.rb +81 -398
  282. data/lib/pubid/ieee/components/code.rb +0 -8
  283. data/lib/pubid/ieee/components/draft.rb +0 -54
  284. data/lib/pubid/ieee/components/relationship.rb +149 -5
  285. data/lib/pubid/ieee/identifier.rb +11 -3
  286. data/lib/pubid/ieee/identifiers/adopted_standard.rb +14 -62
  287. data/lib/pubid/ieee/identifiers/base.rb +547 -340
  288. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +12 -6
  289. data/lib/pubid/ieee/identifiers/corrigendum.rb +12 -15
  290. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +13 -24
  291. data/lib/pubid/ieee/identifiers/dual_identifier.rb +7 -3
  292. data/lib/pubid/ieee/identifiers/dual_published.rb +7 -58
  293. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +11 -99
  294. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +11 -25
  295. data/lib/pubid/ieee/identifiers/joint_development.rb +15 -66
  296. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +24 -58
  297. data/lib/pubid/ieee/identifiers/nesc/base.rb +19 -90
  298. data/lib/pubid/ieee/identifiers/nesc/draft.rb +5 -20
  299. data/lib/pubid/ieee/identifiers/nesc/handbook.rb +5 -16
  300. data/lib/pubid/ieee/identifiers/nesc/redline.rb +2 -11
  301. data/lib/pubid/ieee/identifiers/nesc/standard.rb +3 -18
  302. data/lib/pubid/ieee/identifiers/nesc.rb +0 -1
  303. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +9 -3
  304. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +6 -29
  305. data/lib/pubid/ieee/identifiers/redlined_standard.rb +11 -4
  306. data/lib/pubid/ieee/identifiers/si_standard.rb +39 -4
  307. data/lib/pubid/ieee/identifiers/standard.rb +2 -5
  308. data/lib/pubid/ieee/identifiers/supplement_identifier.rb +7 -26
  309. data/lib/pubid/ieee/identifiers.rb +1 -2
  310. data/lib/pubid/ieee/ire/builder.rb +6 -7
  311. data/lib/pubid/ieee/ire/identifier.rb +33 -48
  312. data/lib/pubid/ieee/ire/parser.rb +1 -1
  313. data/lib/pubid/ieee/nesc/builder.rb +20 -33
  314. data/lib/pubid/ieee/nesc/parser.rb +15 -16
  315. data/lib/pubid/ieee/parser.rb +44 -462
  316. data/lib/pubid/ieee/scheme.rb +90 -0
  317. data/lib/pubid/ieee/typed_stages.rb +1 -12
  318. data/lib/pubid/ieee/urn_generator.rb +8 -35
  319. data/lib/pubid/ieee.rb +2 -133
  320. data/lib/pubid/ieee_debug.rb +1 -0
  321. data/lib/pubid/iho/builder.rb +2 -2
  322. data/lib/pubid/iho/identifier.rb +17 -5
  323. data/lib/pubid/iho/identifiers/base.rb +30 -64
  324. data/lib/pubid/iho/identifiers/bibliographic.rb +5 -1
  325. data/lib/pubid/iho/identifiers/circular_letter.rb +5 -1
  326. data/lib/pubid/iho/identifiers/miscellaneous.rb +5 -1
  327. data/lib/pubid/iho/identifiers/publication.rb +5 -1
  328. data/lib/pubid/iho/identifiers/standard.rb +5 -1
  329. data/lib/pubid/iho/identifiers.rb +1 -0
  330. data/lib/pubid/iho/parser.rb +4 -4
  331. data/lib/pubid/iho/scheme.rb +29 -0
  332. data/lib/pubid/iho/urn_generator.rb +3 -3
  333. data/lib/pubid/iho.rb +3 -59
  334. data/lib/pubid/iso/builder.rb +57 -68
  335. data/lib/pubid/iso/bundled_identifier.rb +3 -56
  336. data/lib/pubid/iso/combined_identifier.rb +4 -6
  337. data/lib/pubid/iso/components/code.rb +19 -7
  338. data/lib/pubid/iso/components/publisher.rb +8 -10
  339. data/lib/pubid/iso/components.rb +4 -2
  340. data/lib/pubid/iso/identifier.rb +11 -260
  341. data/lib/pubid/iso/identifiers/addendum.rb +6 -9
  342. data/lib/pubid/iso/identifiers/amendment.rb +4 -8
  343. data/lib/pubid/iso/identifiers/base.rb +115 -0
  344. data/lib/pubid/iso/identifiers/corrigendum.rb +4 -4
  345. data/lib/pubid/iso/identifiers/data.rb +1 -0
  346. data/lib/pubid/iso/identifiers/directives.rb +2 -8
  347. data/lib/pubid/iso/identifiers/directives_supplement.rb +26 -55
  348. data/lib/pubid/iso/identifiers/extract.rb +2 -2
  349. data/lib/pubid/iso/identifiers/guide.rb +1 -0
  350. data/lib/pubid/iso/identifiers/international_standard.rb +4 -4
  351. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +4 -4
  352. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +4 -10
  353. data/lib/pubid/iso/identifiers/pas.rb +2 -2
  354. data/lib/pubid/iso/identifiers/recommendation.rb +2 -2
  355. data/lib/pubid/iso/identifiers/supplement.rb +3 -11
  356. data/lib/pubid/iso/identifiers/tc_document.rb +15 -44
  357. data/lib/pubid/iso/identifiers/technical_report.rb +4 -4
  358. data/lib/pubid/iso/identifiers/technical_specification.rb +2 -2
  359. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +2 -2
  360. data/lib/pubid/iso/identifiers.rb +1 -0
  361. data/lib/pubid/iso/parser.rb +19 -43
  362. data/lib/pubid/iso/scheme.rb +187 -0
  363. data/lib/pubid/iso/single_identifier.rb +7 -6
  364. data/lib/pubid/iso/supplement_identifier.rb +3 -29
  365. data/lib/pubid/iso/urn_generator.rb +177 -78
  366. data/lib/pubid/iso/urn_parser.rb +10 -29
  367. data/lib/pubid/iso.rb +2 -188
  368. data/lib/pubid/itu/builder.rb +41 -230
  369. data/lib/pubid/itu/components/code.rb +12 -57
  370. data/lib/pubid/itu/components/sector.rb +4 -15
  371. data/lib/pubid/itu/components/series.rb +4 -0
  372. data/lib/pubid/itu/identifier.rb +51 -2
  373. data/lib/pubid/itu/identifiers/amendment.rb +31 -7
  374. data/lib/pubid/itu/identifiers/annex.rb +4 -13
  375. data/lib/pubid/itu/identifiers/base.rb +128 -456
  376. data/lib/pubid/itu/identifiers/combined_identifier.rb +25 -99
  377. data/lib/pubid/itu/identifiers/corrigendum.rb +25 -16
  378. data/lib/pubid/itu/identifiers/recommendation.rb +4 -3
  379. data/lib/pubid/itu/identifiers/special_publication.rb +3 -3
  380. data/lib/pubid/itu/identifiers/supplement.rb +16 -119
  381. data/lib/pubid/itu/identifiers.rb +1 -10
  382. data/lib/pubid/itu/model.rb +1 -1
  383. data/lib/pubid/itu/parser.rb +27 -481
  384. data/lib/pubid/itu/scheme.rb +174 -0
  385. data/lib/pubid/itu/urn_generator.rb +6 -36
  386. data/lib/pubid/itu.rb +2 -58
  387. data/lib/pubid/jcgm/builder.rb +19 -37
  388. data/lib/pubid/jcgm/identifier.rb +0 -10
  389. data/lib/pubid/jcgm/identifiers/amendment.rb +11 -0
  390. data/lib/pubid/jcgm/identifiers/gum_guide.rb +15 -3
  391. data/lib/pubid/jcgm/identifiers.rb +0 -2
  392. data/lib/pubid/jcgm/parser.rb +7 -74
  393. data/lib/pubid/jcgm/scheme.rb +60 -0
  394. data/lib/pubid/jcgm/single_identifier.rb +14 -84
  395. data/lib/pubid/jcgm/supplement_identifier.rb +4 -39
  396. data/lib/pubid/jcgm/urn_generator.rb +19 -25
  397. data/lib/pubid/jcgm.rb +2 -57
  398. data/lib/pubid/jis/builder.rb +52 -44
  399. data/lib/pubid/jis/components/code.rb +59 -0
  400. data/lib/pubid/{astm → jis}/components.rb +1 -1
  401. data/lib/pubid/jis/identifier.rb +5 -181
  402. data/lib/pubid/jis/identifiers/amendment.rb +1 -1
  403. data/lib/pubid/jis/identifiers/base.rb +72 -0
  404. data/lib/pubid/jis/identifiers/standard.rb +1 -2
  405. data/lib/pubid/jis/identifiers/technical_report.rb +1 -2
  406. data/lib/pubid/jis/identifiers/technical_specification.rb +1 -2
  407. data/lib/pubid/jis/identifiers.rb +1 -1
  408. data/lib/pubid/jis/parser.rb +6 -32
  409. data/lib/pubid/jis/scheme.rb +49 -0
  410. data/lib/pubid/jis/single_identifier.rb +12 -6
  411. data/lib/pubid/jis/supplement_identifier.rb +14 -17
  412. data/lib/pubid/jis.rb +2 -48
  413. data/lib/pubid/nist/builder.rb +1765 -146
  414. data/lib/pubid/nist/components/code.rb +20 -9
  415. data/lib/pubid/nist/components/edition.rb +0 -16
  416. data/lib/pubid/nist/components/publisher.rb +24 -0
  417. data/lib/pubid/nist/components/supplement.rb +21 -91
  418. data/lib/pubid/nist/components.rb +1 -0
  419. data/lib/pubid/nist/configuration.rb +2 -12
  420. data/lib/pubid/nist/identifiers/base.rb +417 -662
  421. data/lib/pubid/nist/identifiers/circular.rb +5 -17
  422. data/lib/pubid/nist/identifiers/circular_supplement.rb +6 -16
  423. data/lib/pubid/nist/identifiers/commercial_standard.rb +2 -3
  424. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +5 -7
  425. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +5 -18
  426. data/lib/pubid/nist/identifiers/crpl_report.rb +13 -16
  427. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +17 -18
  428. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +2 -3
  429. data/lib/pubid/nist/identifiers/handbook.rb +4 -12
  430. data/lib/pubid/nist/identifiers/internal_report.rb +7 -15
  431. data/lib/pubid/nist/identifiers/letter_circular.rb +2 -3
  432. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +11 -20
  433. data/lib/pubid/nist/identifiers/monograph.rb +11 -22
  434. data/lib/pubid/nist/identifiers/ncstar.rb +2 -2
  435. data/lib/pubid/nist/identifiers/nsrds.rb +1 -1
  436. data/lib/pubid/nist/identifiers/owmwp.rb +1 -1
  437. data/lib/pubid/nist/identifiers/report.rb +10 -19
  438. data/lib/pubid/nist/identifiers/special_publication.rb +2 -12
  439. data/lib/pubid/nist/identifiers/technical_note.rb +3 -4
  440. data/lib/pubid/nist/identifiers.rb +1 -1
  441. data/lib/pubid/nist/parser.rb +429 -97
  442. data/lib/pubid/nist/scheme.rb +199 -0
  443. data/lib/pubid/nist/supplement_identifier.rb +34 -35
  444. data/lib/pubid/nist/urn_generator.rb +8 -14
  445. data/lib/pubid/nist.rb +5 -107
  446. data/lib/pubid/oiml/builder.rb +10 -91
  447. data/lib/pubid/oiml/components/code.rb +0 -17
  448. data/lib/pubid/oiml/identifier.rb +0 -53
  449. data/lib/pubid/oiml/identifiers/annex.rb +46 -13
  450. data/lib/pubid/oiml/identifiers/base.rb +36 -0
  451. data/lib/pubid/oiml/identifiers/basic_publication.rb +0 -2
  452. data/lib/pubid/oiml/identifiers/document.rb +0 -2
  453. data/lib/pubid/oiml/identifiers/expert_report.rb +0 -2
  454. data/lib/pubid/oiml/identifiers/guide.rb +0 -2
  455. data/lib/pubid/oiml/identifiers/recommendation.rb +0 -2
  456. data/lib/pubid/oiml/identifiers/seminar_report.rb +0 -2
  457. data/lib/pubid/oiml/identifiers/vocabulary.rb +0 -2
  458. data/lib/pubid/oiml/identifiers.rb +1 -3
  459. data/lib/pubid/oiml/parser.rb +17 -118
  460. data/lib/pubid/oiml/scheme.rb +46 -0
  461. data/lib/pubid/oiml/single_identifier.rb +43 -66
  462. data/lib/pubid/oiml/supplement_identifier.rb +17 -62
  463. data/lib/pubid/oiml/urn_generator.rb +8 -22
  464. data/lib/pubid/oiml.rb +1 -56
  465. data/lib/pubid/parser.rb +0 -1
  466. data/lib/pubid/parsers/mr_string.rb +7 -120
  467. data/lib/pubid/plateau/builder.rb +4 -8
  468. data/lib/pubid/plateau/identifiers/base.rb +36 -40
  469. data/lib/pubid/plateau/identifiers/handbook.rb +7 -1
  470. data/lib/pubid/plateau/identifiers/technical_report.rb +5 -1
  471. data/lib/pubid/plateau/identifiers.rb +1 -0
  472. data/lib/pubid/plateau/parser.rb +6 -16
  473. data/lib/pubid/plateau/scheme.rb +45 -0
  474. data/lib/pubid/plateau/supplement_identifier.rb +15 -11
  475. data/lib/pubid/plateau.rb +1 -58
  476. data/lib/pubid/renderers/base.rb +0 -47
  477. data/lib/pubid/renderers/directives_renderer.rb +14 -27
  478. data/lib/pubid/renderers/guide_renderer.rb +1 -7
  479. data/lib/pubid/renderers/human_readable.rb +9 -34
  480. data/lib/pubid/renderers/iwa_renderer.rb +1 -5
  481. data/lib/pubid/renderers/mr_string.rb +6 -54
  482. data/lib/pubid/renderers/supplement_renderer.rb +2 -5
  483. data/lib/pubid/renderers.rb +0 -1
  484. data/lib/pubid/rendering/base.rb +73 -0
  485. data/lib/pubid/rendering/common.rb +211 -0
  486. data/lib/pubid/rendering/context.rb +21 -33
  487. data/lib/pubid/rendering/format.rb +25 -0
  488. data/lib/pubid/rendering/numbering.rb +7 -25
  489. data/lib/pubid/rendering/supplement.rb +4 -4
  490. data/lib/pubid/rendering.rb +3 -0
  491. data/lib/pubid/sae/builder.rb +1 -1
  492. data/lib/pubid/sae/components/date.rb +0 -8
  493. data/lib/pubid/sae/components/type.rb +1 -5
  494. data/lib/pubid/sae/identifier.rb +12 -2
  495. data/lib/pubid/sae/identifiers/base.rb +28 -33
  496. data/lib/pubid/sae/identifiers.rb +1 -0
  497. data/lib/pubid/sae/parser.rb +1 -1
  498. data/lib/pubid/sae/scheme.rb +47 -0
  499. data/lib/pubid/sae/urn_generator.rb +10 -2
  500. data/lib/pubid/sae.rb +2 -49
  501. data/lib/pubid/scheme.rb +207 -0
  502. data/lib/pubid/urn_generator/base.rb +12 -12
  503. data/lib/pubid/version.rb +1 -1
  504. data/lib/pubid.rb +10 -424
  505. data/lib/tasks/export.rake +5 -6
  506. data/lib/tasks/website-data.json +1796 -1854
  507. metadata +45 -307
  508. data/data/bipm/update_codes.yaml +0 -9
  509. data/data/nist/series.yaml +0 -155
  510. data/lib/pubid/adobe/builder.rb +0 -52
  511. data/lib/pubid/adobe/identifier.rb +0 -47
  512. data/lib/pubid/adobe/identifiers/publication.rb +0 -31
  513. data/lib/pubid/adobe/identifiers/tech_note.rb +0 -32
  514. data/lib/pubid/adobe/identifiers.rb +0 -10
  515. data/lib/pubid/adobe/parser.rb +0 -136
  516. data/lib/pubid/adobe/renderer.rb +0 -39
  517. data/lib/pubid/adobe/urn_generator.rb +0 -42
  518. data/lib/pubid/adobe/urn_parser.rb +0 -69
  519. data/lib/pubid/adobe.rb +0 -60
  520. data/lib/pubid/amca/renderer.rb +0 -82
  521. data/lib/pubid/amca/urn_parser.rb +0 -28
  522. data/lib/pubid/ansi/renderer.rb +0 -53
  523. data/lib/pubid/ansi/urn_parser.rb +0 -23
  524. data/lib/pubid/api/identifiers.rb +0 -18
  525. data/lib/pubid/api/renderer.rb +0 -98
  526. data/lib/pubid/api/urn_parser.rb +0 -35
  527. data/lib/pubid/ashrae/renderer.rb +0 -117
  528. data/lib/pubid/ashrae/urn_parser.rb +0 -27
  529. data/lib/pubid/asme/renderer.rb +0 -66
  530. data/lib/pubid/asme/urn_parser.rb +0 -31
  531. data/lib/pubid/astm/identifiers/code_number.rb +0 -81
  532. data/lib/pubid/astm/identifiers.rb +0 -19
  533. data/lib/pubid/astm/renderer.rb +0 -172
  534. data/lib/pubid/astm/urn_parser.rb +0 -30
  535. data/lib/pubid/bipm/builder.rb +0 -163
  536. data/lib/pubid/bipm/identifier.rb +0 -285
  537. data/lib/pubid/bipm/identifiers/committee_document.rb +0 -36
  538. data/lib/pubid/bipm/identifiers/guide.rb +0 -35
  539. data/lib/pubid/bipm/identifiers/meeting.rb +0 -53
  540. data/lib/pubid/bipm/identifiers/mep.rb +0 -33
  541. data/lib/pubid/bipm/identifiers/metrologia_article.rb +0 -48
  542. data/lib/pubid/bipm/identifiers/si_brochure.rb +0 -33
  543. data/lib/pubid/bipm/identifiers.rb +0 -15
  544. data/lib/pubid/bipm/parser.rb +0 -237
  545. data/lib/pubid/bipm/renderer.rb +0 -118
  546. data/lib/pubid/bipm/urn_generator.rb +0 -58
  547. data/lib/pubid/bipm/urn_parser.rb +0 -60
  548. data/lib/pubid/bipm.rb +0 -91
  549. data/lib/pubid/bsi/renderer.rb +0 -1064
  550. data/lib/pubid/bsi/urn_parser.rb +0 -52
  551. data/lib/pubid/calconnect/builder.rb +0 -38
  552. data/lib/pubid/calconnect/identifier.rb +0 -121
  553. data/lib/pubid/calconnect/identifiers/standard.rb +0 -29
  554. data/lib/pubid/calconnect/identifiers.rb +0 -9
  555. data/lib/pubid/calconnect/parser.rb +0 -54
  556. data/lib/pubid/calconnect/renderer.rb +0 -36
  557. data/lib/pubid/calconnect/urn_generator.rb +0 -33
  558. data/lib/pubid/calconnect/urn_parser.rb +0 -34
  559. data/lib/pubid/calconnect.rb +0 -82
  560. data/lib/pubid/ccsds/urn_parser.rb +0 -20
  561. data/lib/pubid/cen_cenelec/renderer.rb +0 -261
  562. data/lib/pubid/cen_cenelec/urn_parser.rb +0 -28
  563. data/lib/pubid/cie/identifiers/code_attributes.rb +0 -52
  564. data/lib/pubid/cie/identifiers/proceedings.rb +0 -41
  565. data/lib/pubid/cie/urn_parser.rb +0 -28
  566. data/lib/pubid/components/adoption.rb +0 -104
  567. data/lib/pubid/components/iteration.rb +0 -32
  568. data/lib/pubid/components/relationship.rb +0 -151
  569. data/lib/pubid/components/supplement.rb +0 -184
  570. data/lib/pubid/csa/renderer.rb +0 -300
  571. data/lib/pubid/csa/urn_parser.rb +0 -33
  572. data/lib/pubid/doi/builder.rb +0 -18
  573. data/lib/pubid/doi/identifier.rb +0 -49
  574. data/lib/pubid/doi/identifiers/resource.rb +0 -30
  575. data/lib/pubid/doi/identifiers.rb +0 -9
  576. data/lib/pubid/doi/parser.rb +0 -52
  577. data/lib/pubid/doi/renderer.rb +0 -13
  578. data/lib/pubid/doi.rb +0 -55
  579. data/lib/pubid/easc/builder.rb +0 -55
  580. data/lib/pubid/easc/identifier.rb +0 -59
  581. data/lib/pubid/easc/identifiers/pmg.rb +0 -20
  582. data/lib/pubid/easc/identifiers/rmg.rb +0 -19
  583. data/lib/pubid/easc/identifiers.rb +0 -10
  584. data/lib/pubid/easc/parser.rb +0 -88
  585. data/lib/pubid/easc/renderer.rb +0 -48
  586. data/lib/pubid/easc/urn_generator.rb +0 -46
  587. data/lib/pubid/easc/urn_parser.rb +0 -57
  588. data/lib/pubid/easc.rb +0 -52
  589. data/lib/pubid/ecma/builder.rb +0 -45
  590. data/lib/pubid/ecma/identifier.rb +0 -147
  591. data/lib/pubid/ecma/identifiers/memento.rb +0 -30
  592. data/lib/pubid/ecma/identifiers/standard.rb +0 -31
  593. data/lib/pubid/ecma/identifiers/technical_report.rb +0 -31
  594. data/lib/pubid/ecma/identifiers.rb +0 -11
  595. data/lib/pubid/ecma/parser.rb +0 -76
  596. data/lib/pubid/ecma/renderer.rb +0 -67
  597. data/lib/pubid/ecma/urn_generator.rb +0 -46
  598. data/lib/pubid/ecma/urn_parser.rb +0 -51
  599. data/lib/pubid/ecma.rb +0 -67
  600. data/lib/pubid/errors.rb +0 -79
  601. data/lib/pubid/etsi/renderer.rb +0 -48
  602. data/lib/pubid/etsi/urn_parser.rb +0 -34
  603. data/lib/pubid/gb/builder.rb +0 -45
  604. data/lib/pubid/gb/identifier.rb +0 -67
  605. data/lib/pubid/gb/identifiers/standard.rb +0 -34
  606. data/lib/pubid/gb/identifiers.rb +0 -9
  607. data/lib/pubid/gb/parser.rb +0 -63
  608. data/lib/pubid/gb/renderer.rb +0 -35
  609. data/lib/pubid/gb.rb +0 -87
  610. data/lib/pubid/gost/builder.rb +0 -148
  611. data/lib/pubid/gost/identifier.rb +0 -47
  612. data/lib/pubid/gost/identifiers/foreign_reference.rb +0 -25
  613. data/lib/pubid/gost/identifiers/harmonized.rb +0 -39
  614. data/lib/pubid/gost/identifiers/identical_adoption.rb +0 -39
  615. data/lib/pubid/gost/identifiers/interstate_standard.rb +0 -20
  616. data/lib/pubid/gost/identifiers/national_standard.rb +0 -19
  617. data/lib/pubid/gost/identifiers.rb +0 -13
  618. data/lib/pubid/gost/parser.rb +0 -105
  619. data/lib/pubid/gost/renderer.rb +0 -48
  620. data/lib/pubid/gost/urn_generator.rb +0 -46
  621. data/lib/pubid/gost/urn_parser.rb +0 -52
  622. data/lib/pubid/gost.rb +0 -49
  623. data/lib/pubid/iala/builder.rb +0 -102
  624. data/lib/pubid/iala/identifier.rb +0 -90
  625. data/lib/pubid/iala/identifiers/advice.rb +0 -15
  626. data/lib/pubid/iala/identifiers/annex.rb +0 -57
  627. data/lib/pubid/iala/identifiers/general_assembly.rb +0 -19
  628. data/lib/pubid/iala/identifiers/guideline.rb +0 -17
  629. data/lib/pubid/iala/identifiers/letter.rb +0 -16
  630. data/lib/pubid/iala/identifiers/manual.rb +0 -18
  631. data/lib/pubid/iala/identifiers/model_course.rb +0 -17
  632. data/lib/pubid/iala/identifiers/recommendation.rb +0 -17
  633. data/lib/pubid/iala/identifiers/report.rb +0 -16
  634. data/lib/pubid/iala/identifiers/resolution.rb +0 -16
  635. data/lib/pubid/iala/identifiers/standard.rb +0 -17
  636. data/lib/pubid/iala/identifiers.rb +0 -19
  637. data/lib/pubid/iala/parser.rb +0 -138
  638. data/lib/pubid/iala/renderer.rb +0 -36
  639. data/lib/pubid/iala/urn_generator.rb +0 -49
  640. data/lib/pubid/iala/urn_parser.rb +0 -67
  641. data/lib/pubid/iala.rb +0 -71
  642. data/lib/pubid/iana/builder.rb +0 -22
  643. data/lib/pubid/iana/identifier.rb +0 -140
  644. data/lib/pubid/iana/identifiers/registry.rb +0 -69
  645. data/lib/pubid/iana/identifiers.rb +0 -9
  646. data/lib/pubid/iana/parser.rb +0 -38
  647. data/lib/pubid/iana/renderer.rb +0 -32
  648. data/lib/pubid/iana/urn_generator.rb +0 -19
  649. data/lib/pubid/iana/urn_parser.rb +0 -24
  650. data/lib/pubid/iana.rb +0 -69
  651. data/lib/pubid/idf/renderer.rb +0 -84
  652. data/lib/pubid/idf/urn_parser.rb +0 -25
  653. data/lib/pubid/iec/components.rb +0 -14
  654. data/lib/pubid/iec/identifiers/technical_group.rb +0 -30
  655. data/lib/pubid/iec/identifiers.rb +0 -31
  656. data/lib/pubid/iec/renderer.rb +0 -267
  657. data/lib/pubid/ieee/compaction.rb +0 -121
  658. data/lib/pubid/ieee/identifiers/amendment.rb +0 -40
  659. data/lib/pubid/ieee/identifiers/code_number.rb +0 -82
  660. data/lib/pubid/ieee/identifiers/nesc/edition.rb +0 -32
  661. data/lib/pubid/ieee/pre_parser.rb +0 -301
  662. data/lib/pubid/ieee/renderer.rb +0 -408
  663. data/lib/pubid/ieee/urn_parser.rb +0 -34
  664. data/lib/pubid/ietf/builder.rb +0 -78
  665. data/lib/pubid/ietf/identifier.rb +0 -5
  666. data/lib/pubid/ietf/identifiers/base.rb +0 -72
  667. data/lib/pubid/ietf/identifiers/bcp.rb +0 -36
  668. data/lib/pubid/ietf/identifiers/fyi.rb +0 -36
  669. data/lib/pubid/ietf/identifiers/internet_draft.rb +0 -45
  670. data/lib/pubid/ietf/identifiers/rfc.rb +0 -27
  671. data/lib/pubid/ietf/identifiers/serialization.rb +0 -51
  672. data/lib/pubid/ietf/identifiers/std.rb +0 -36
  673. data/lib/pubid/ietf/identifiers.rb +0 -14
  674. data/lib/pubid/ietf/parser.rb +0 -61
  675. data/lib/pubid/ietf/renderer.rb +0 -64
  676. data/lib/pubid/ietf/urn_generator.rb +0 -37
  677. data/lib/pubid/ietf/urn_parser.rb +0 -43
  678. data/lib/pubid/ietf.rb +0 -85
  679. data/lib/pubid/iho/renderer.rb +0 -30
  680. data/lib/pubid/iho/urn_parser.rb +0 -58
  681. data/lib/pubid/isbn/builder.rb +0 -44
  682. data/lib/pubid/isbn/check_digit.rb +0 -53
  683. data/lib/pubid/isbn/identifier.rb +0 -81
  684. data/lib/pubid/isbn/identifiers/book.rb +0 -30
  685. data/lib/pubid/isbn/identifiers.rb +0 -9
  686. data/lib/pubid/isbn/parser.rb +0 -45
  687. data/lib/pubid/isbn/renderer.rb +0 -16
  688. data/lib/pubid/isbn.rb +0 -52
  689. data/lib/pubid/iso/normalizer.rb +0 -89
  690. data/lib/pubid/itu/components/designation.rb +0 -35
  691. data/lib/pubid/itu/components.rb +0 -12
  692. data/lib/pubid/itu/identifiers/addendum.rb +0 -15
  693. data/lib/pubid/itu/identifiers/annex_of_recommendation.rb +0 -87
  694. data/lib/pubid/itu/identifiers/appendix_of_recommendation.rb +0 -92
  695. data/lib/pubid/itu/identifiers/errata.rb +0 -15
  696. data/lib/pubid/itu/identifiers/handbook.rb +0 -38
  697. data/lib/pubid/itu/identifiers/question.rb +0 -63
  698. data/lib/pubid/itu/identifiers/report.rb +0 -39
  699. data/lib/pubid/itu/identifiers/standard_serialization.rb +0 -58
  700. data/lib/pubid/itu/urn_parser.rb +0 -31
  701. data/lib/pubid/jcgm/identifiers/corrigendum.rb +0 -34
  702. data/lib/pubid/jcgm/identifiers/meeting.rb +0 -47
  703. data/lib/pubid/jcgm/renderer.rb +0 -89
  704. data/lib/pubid/jcgm/urn_parser.rb +0 -177
  705. data/lib/pubid/jis/identifiers/corrigendum.rb +0 -16
  706. data/lib/pubid/jis/renderer.rb +0 -69
  707. data/lib/pubid/jis/urn_parser.rb +0 -23
  708. data/lib/pubid/nist/caster.rb +0 -1234
  709. data/lib/pubid/nist/circular_supplement_builder.rb +0 -293
  710. data/lib/pubid/nist/identifier.rb +0 -8
  711. data/lib/pubid/nist/identifiers/dated_document.rb +0 -49
  712. data/lib/pubid/nist/parser_output_normalizer.rb +0 -233
  713. data/lib/pubid/nist/preprocessor.rb +0 -443
  714. data/lib/pubid/nist/renderer.rb +0 -43
  715. data/lib/pubid/nist/router.rb +0 -149
  716. data/lib/pubid/nist/series/base.rb +0 -58
  717. data/lib/pubid/nist/series/crpl.rb +0 -13
  718. data/lib/pubid/nist/series/fips.rb +0 -14
  719. data/lib/pubid/nist/series/ir.rb +0 -57
  720. data/lib/pubid/nist/series/letter_preserving.rb +0 -15
  721. data/lib/pubid/nist/series/mono.rb +0 -19
  722. data/lib/pubid/nist/series/ncstar.rb +0 -20
  723. data/lib/pubid/nist/series.rb +0 -49
  724. data/lib/pubid/nist/urn_parser.rb +0 -67
  725. data/lib/pubid/oasis/builder.rb +0 -79
  726. data/lib/pubid/oasis/identifier.rb +0 -160
  727. data/lib/pubid/oasis/identifiers/standard.rb +0 -29
  728. data/lib/pubid/oasis/identifiers.rb +0 -9
  729. data/lib/pubid/oasis/parser.rb +0 -34
  730. data/lib/pubid/oasis/renderer.rb +0 -29
  731. data/lib/pubid/oasis/urn_generator.rb +0 -25
  732. data/lib/pubid/oasis/urn_parser.rb +0 -22
  733. data/lib/pubid/oasis.rb +0 -79
  734. data/lib/pubid/ogc/builder.rb +0 -33
  735. data/lib/pubid/ogc/identifier.rb +0 -81
  736. data/lib/pubid/ogc/identifiers/document.rb +0 -26
  737. data/lib/pubid/ogc/identifiers.rb +0 -10
  738. data/lib/pubid/ogc/parser.rb +0 -40
  739. data/lib/pubid/ogc/renderer.rb +0 -33
  740. data/lib/pubid/ogc/urn_generator.rb +0 -14
  741. data/lib/pubid/ogc/urn_parser.rb +0 -22
  742. data/lib/pubid/ogc.rb +0 -71
  743. data/lib/pubid/oiml/identifiers/bulletin.rb +0 -137
  744. data/lib/pubid/oiml/identifiers/code_number.rb +0 -90
  745. data/lib/pubid/oiml/identifiers/errata.rb +0 -15
  746. data/lib/pubid/oiml/renderer.rb +0 -232
  747. data/lib/pubid/oiml/urn_parser.rb +0 -39
  748. data/lib/pubid/omg/builder.rb +0 -19
  749. data/lib/pubid/omg/identifier.rb +0 -47
  750. data/lib/pubid/omg/identifiers/specification.rb +0 -32
  751. data/lib/pubid/omg/identifiers.rb +0 -9
  752. data/lib/pubid/omg/parser.rb +0 -40
  753. data/lib/pubid/omg/renderer.rb +0 -19
  754. data/lib/pubid/omg.rb +0 -51
  755. data/lib/pubid/parser/grammar.rb +0 -74
  756. data/lib/pubid/plateau/identifier.rb +0 -4
  757. data/lib/pubid/plateau/renderer.rb +0 -51
  758. data/lib/pubid/plateau/urn_parser.rb +0 -43
  759. data/lib/pubid/prefixes_support.rb +0 -51
  760. data/lib/pubid/renderers/annotator.rb +0 -233
  761. data/lib/pubid/sae/renderer.rb +0 -36
  762. data/lib/pubid/sae/urn_parser.rb +0 -36
  763. data/lib/pubid/tgpp/builder.rb +0 -41
  764. data/lib/pubid/tgpp/identifier.rb +0 -107
  765. data/lib/pubid/tgpp/identifiers/technical_report.rb +0 -32
  766. data/lib/pubid/tgpp/identifiers/technical_specification.rb +0 -33
  767. data/lib/pubid/tgpp/identifiers.rb +0 -11
  768. data/lib/pubid/tgpp/parser.rb +0 -78
  769. data/lib/pubid/tgpp/renderer.rb +0 -52
  770. data/lib/pubid/tgpp/urn_generator.rb +0 -39
  771. data/lib/pubid/tgpp/urn_parser.rb +0 -30
  772. data/lib/pubid/tgpp.rb +0 -83
  773. data/lib/pubid/type_resolver.rb +0 -59
  774. data/lib/pubid/un/builder.rb +0 -42
  775. data/lib/pubid/un/identifier.rb +0 -40
  776. data/lib/pubid/un/identifiers/document.rb +0 -24
  777. data/lib/pubid/un/identifiers.rb +0 -9
  778. data/lib/pubid/un/parser.rb +0 -25
  779. data/lib/pubid/un/renderer.rb +0 -11
  780. data/lib/pubid/un.rb +0 -46
  781. data/lib/pubid/urn_parser/base.rb +0 -81
  782. data/lib/pubid/urn_parser/errors.rb +0 -16
  783. data/lib/pubid/urn_parser.rb +0 -14
  784. data/lib/pubid/w3c/builder.rb +0 -55
  785. data/lib/pubid/w3c/identifier.rb +0 -130
  786. data/lib/pubid/w3c/identifiers/candidate_recommendation.rb +0 -31
  787. data/lib/pubid/w3c/identifiers/candidate_recommendation_draft.rb +0 -31
  788. data/lib/pubid/w3c/identifiers/draft_note.rb +0 -31
  789. data/lib/pubid/w3c/identifiers/note.rb +0 -30
  790. data/lib/pubid/w3c/identifiers/obsolete_recommendation.rb +0 -31
  791. data/lib/pubid/w3c/identifiers/proposed_edited_recommendation.rb +0 -31
  792. data/lib/pubid/w3c/identifiers/proposed_recommendation.rb +0 -31
  793. data/lib/pubid/w3c/identifiers/recommendation.rb +0 -31
  794. data/lib/pubid/w3c/identifiers/standard.rb +0 -12
  795. data/lib/pubid/w3c/identifiers/superseded_recommendation.rb +0 -31
  796. data/lib/pubid/w3c/identifiers/working_draft.rb +0 -30
  797. data/lib/pubid/w3c/identifiers.rb +0 -25
  798. data/lib/pubid/w3c/parser.rb +0 -43
  799. data/lib/pubid/w3c/renderer.rb +0 -35
  800. data/lib/pubid/w3c/urn_generator.rb +0 -18
  801. data/lib/pubid/w3c/urn_parser.rb +0 -36
  802. data/lib/pubid/w3c.rb +0 -67
  803. data/lib/pubid/xsf/builder.rb +0 -17
  804. data/lib/pubid/xsf/identifier.rb +0 -66
  805. data/lib/pubid/xsf/identifiers/xep.rb +0 -31
  806. data/lib/pubid/xsf/identifiers.rb +0 -9
  807. data/lib/pubid/xsf/parser.rb +0 -25
  808. data/lib/pubid/xsf/renderer.rb +0 -23
  809. data/lib/pubid/xsf/urn_generator.rb +0 -13
  810. data/lib/pubid/xsf/urn_parser.rb +0 -18
  811. data/lib/pubid/xsf.rb +0 -81
@@ -6,379 +6,586 @@ module Pubid
6
6
  # Forward declare component classes
7
7
  end
8
8
 
9
- # Base class for all IEEE identifiers. Canonical name
10
- # Pubid::Ieee::Identifier. IEEE
11
- # builds its identifiers as instances of this class directly.
12
- class Identifier < ::Pubid::Identifier
13
- # Generate URN for this identifier
14
- #
15
- # @return [String] URN representation
16
-
17
- attribute :publisher, :string, default: -> { "IEEE" }
18
- attribute :copublisher, :string, collection: true # IEC, ISO, ANSI, etc.
19
- # NB: there is deliberately NO `attribute :code`. IEEE's document code is
20
- # serialized as the split index columns (number/prefix/parts/separator) on
21
- # concrete leaf types via the CodeNumber mixin; `code`/`code_obj` remain a
22
- # runtime-only representation (built in #initialize, read by the renderer).
23
- # This holds for every IEEE type, including the historical AIEE/IRE and
24
- # the NESC family: all three used to descend from
25
- # Lutaml::Model::Serializable with their own `attribute :code`, and were
26
- # reparented onto this base (with the CodeNumber mixin on their leaves).
27
- attribute :year, :string
28
- attribute :type, :string, default: -> { "Std" } # Std, Draft Std
29
- attribute :draft_status, :string # Unapproved, Approved, Active Unapproved
30
- attribute :draft, :string # Will store draft as object
31
- # Numbered/lettered revision id, e.g. "2" for "P802.16Rev2", "i" for the
32
- # relaton suffix "/R-i". IEEE's native inline "Rev<n>" and relaton's
33
- # synthetic "/R-<x>" both feed this one attribute; rendered inline as
34
- # "Rev<id>". `::Pubid::Identifier` has no `revision` attribute, so this is
35
- # free of the number/stage multi-flavor collision landmine.
36
- attribute :revision, :string
37
- attribute :edition, :string # Edition 1.0
38
- attribute :month, :string
39
- attribute :day, :string
40
- attribute :redline, :boolean, default: -> { false }
41
- attribute :amendments, Identifier, collection: true # Amendment identifiers
42
- attribute :corrigenda, Identifier, collection: true # Corrigendum identifiers
43
- attribute :revision_of, Identifier # Revision relationships
44
- attribute :incorporates, Identifier, collection: true # Incorporated documents
45
- attribute :supersedes, Identifier, collection: true # Superseded documents
46
- attribute :supplement_to, Identifier # For supplements
47
- attribute :iso_identifier, :string # For IEC/IEEE formats
48
- attribute :parenthetical_content, :string # Raw parenthetical content
49
- attribute :note, :string # Parenthetical notes
50
- attribute :adoption, :string # Adoption notes
51
- attribute :amendment_to, :string # Amendment to relationships
52
- attribute :edition_month, :string # Month part from Edition YYYY-MM
53
- attribute :space_before_draft, :boolean, default: -> {
54
- false
55
- } # Track space before /D
56
- attribute :typed_stage, Components::TypedStage # TYPED_STAGE integration
57
- attribute :relationships, Components::Relationship, collection: true # Relationship metadata
58
- attribute :nickname, :string # Book nickname (e.g., "[The Orange Book]")
59
- attribute :interpretation, :boolean, default: -> {
60
- false
61
- } # /INT notation
62
- attribute :ashrae_number, :string # ASHRAE Guideline number
63
- attribute :ashrae_year, :string # ASHRAE Guideline year
64
- attribute :crossref, :string # IEEE cross-reference (e.g., /C62.22.1-1996)
65
- attribute :reaffirmed, :string # Reaffirmed year (e.g., "2010" for (R2010))
66
-
67
- # Store actual component objects
68
- attr_accessor :code_obj, :draft_obj
69
-
70
- # Accept either keyword args (`new(number: "802")`, the normal path) or a
71
- # single positional attribute hash (`new({number: "802"})`). The latter is
72
- # what the base `Pubid::Identifier#exclude`/matching machinery uses when it
73
- # rebuilds via `self.class.new(attrs)`; without it, `exclude`/`matches?`
74
- # raised ArgumentError for every IEEE identifier.
75
- # Constructor parameters that are not lutaml attributes: `code` is
76
- # runtime-only (kept as `code_obj`), and the draft forms are turned into
77
- # component objects below.
78
- def self.extra_init_keys
79
- %i[code draft draft_obj]
80
- end
9
+ module Identifiers
10
+ # Base class for all IEEE identifiers
11
+ class Base < Pubid::Identifier
12
+ # Generate URN for this identifier
13
+ #
14
+ # @return [String] URN representation
15
+
16
+ attribute :publisher, :string, default: -> { "IEEE" }
17
+ attribute :copublisher, :string, collection: true # IEC, ISO, ANSI, etc.
18
+ attribute :code, :string # Will store code as object in initialize
19
+ attribute :year, :string
20
+ attribute :type, :string, default: -> { "Std" } # Std, Draft Std
21
+ attribute :draft_status, :string # Unapproved, Approved, Active Unapproved
22
+ attribute :draft, :string # Will store draft as object
23
+ attribute :edition, :string # Edition 1.0
24
+ attribute :month, :string
25
+ attribute :day, :string
26
+ attribute :redline, :boolean, default: -> { false }
27
+ attribute :amendments, Base, collection: true # Amendment identifiers
28
+ attribute :corrigenda, Base, collection: true # Corrigendum identifiers
29
+ attribute :revision_of, Base # Revision relationships
30
+ attribute :incorporates, Base, collection: true # Incorporated documents
31
+ attribute :supersedes, Base, collection: true # Superseded documents
32
+ attribute :supplement_to, Base # For supplements
33
+ attribute :iso_identifier, :string # For IEC/IEEE formats
34
+ attribute :parenthetical_content, :string # Raw parenthetical content
35
+ attribute :note, :string # Parenthetical notes
36
+ attribute :adoption, :string # Adoption notes
37
+ attribute :amendment_to, :string # Amendment to relationships
38
+ attribute :edition_month, :string # Month part from Edition YYYY-MM
39
+ attribute :space_before_draft, :boolean, default: -> {
40
+ false
41
+ } # Track space before /D
42
+ attribute :typed_stage, Components::TypedStage # TYPED_STAGE integration
43
+ attribute :relationships, Components::Relationship, collection: true # Relationship metadata
44
+ attribute :nickname, :string # Book nickname (e.g., "[The Orange Book]")
45
+ attribute :interpretation, :boolean, default: -> {
46
+ false
47
+ } # /INT notation
48
+ attribute :conf_number, :string # Conformance document number
49
+ attribute :conf_year, :string # Conformance document year
50
+ attribute :ashrae_number, :string # ASHRAE Guideline number
51
+ attribute :ashrae_year, :string # ASHRAE Guideline year
52
+ attribute :crossref, :string # IEEE cross-reference (e.g., /C62.22.1-1996)
53
+ attribute :reaffirmed, :string # Reaffirmed year (e.g., "2010" for (R2010))
54
+
55
+ # Store actual component objects
56
+ attr_accessor :code_obj, :draft_obj
57
+
58
+ def initialize(**args)
59
+ super()
60
+
61
+ # Handle typed_stage if provided
62
+ if args[:typed_stage]
63
+ self.typed_stage = args[:typed_stage]
64
+ end
65
+
66
+ # Handle code as component object
67
+ if args[:code].is_a?(String)
68
+ self.code_obj = Components::Code.parse(args[:code])
69
+ self.code = args[:code]
70
+ elsif args[:code]
71
+ self.code_obj = args[:code]
72
+ self.code = args[:code].to_s
73
+ end
81
74
 
82
- def initialize(args = {}, **kwargs)
83
- args = args.merge(kwargs) unless kwargs.empty?
84
- # This override calls `super()` with no attributes and assigns through
85
- # setters instead, so it bypasses the base constructor's coercion and
86
- # unknown-key check. Apply them here to keep the cross-flavor contract.
87
- args = self.class.normalize_init_attributes(args)
88
- super()
89
-
90
- # Handle typed_stage if provided
91
- if args[:typed_stage]
92
- self.typed_stage = args[:typed_stage]
75
+ # Handle draft as component object
76
+ if args[:draft_obj]
77
+ self.draft_obj = args[:draft_obj]
78
+ self.draft = args[:draft_obj].to_s
79
+ elsif args[:draft]
80
+ # If draft is passed as string, try to create Draft object
81
+ if args[:draft].is_a?(String)
82
+ # Try to parse the string to extract version/revision
83
+ if args[:draft] =~ /^D(\d+)(?:\.(\d+))?/
84
+ version = $1
85
+ revision = $2
86
+ self.draft_obj = Components::Draft.new(version: version,
87
+ revision: revision)
88
+ else
89
+ # Simple case - treat as version
90
+ self.draft_obj = Components::Draft.new(version: args[:draft])
91
+ end
92
+ self.draft = draft_obj.to_s
93
+ else
94
+ self.draft_obj = args[:draft]
95
+ self.draft = args[:draft].to_s
96
+ end
97
+ end
98
+
99
+ # Set other attributes
100
+ attrs = self.class.attributes
101
+ args.each do |key, value|
102
+ next if %i[code draft draft_obj typed_stage].include?(key)
103
+
104
+ setter = :"#{key}="
105
+ public_send(setter, value) if attrs.key?(key)
106
+ end
93
107
  end
94
108
 
95
- # Handle code as component object. `code` is runtime-only (not a lutaml
96
- # attribute) — we keep the parsed Components::Code in code_obj; every
97
- # leaf serializes the split index columns (number/prefix/parts/separator)
98
- # via the CodeNumber mixin instead of a `code` string. The renderer reads
99
- # code_obj (base #code returns it).
100
- if args[:code].is_a?(String)
101
- self.code_obj = Components::Code.parse(args[:code])
102
- elsif args[:code]
103
- self.code_obj = args[:code]
109
+ # Override accessors to return component objects
110
+ def code
111
+ code_obj
104
112
  end
105
113
 
106
- # Handle draft as component object
107
- if args[:draft_obj]
108
- self.draft_obj = args[:draft_obj]
109
- self.draft = args[:draft_obj].to_s
110
- elsif args[:draft].is_a?(String)
111
- self.draft_obj = Components::Draft.parse(args[:draft])
112
- self.draft = draft_obj.to_s
113
- elsif args[:draft]
114
- self.draft_obj = args[:draft]
115
- self.draft = args[:draft].to_s
114
+ def draft
115
+ draft_obj
116
116
  end
117
117
 
118
- # Set other attributes.
119
- #
120
- # A key the class accepts but does not declare as a lutaml attribute
121
- # (see `extra_init_keys`) is assigned through its plain accessor.
122
- # Without that, `CsaDualPublished#csa_identifier` — an `attr_accessor`
123
- # by design, "stored as-is (not a Lutaml model type)" — was never
124
- # assigned at all, and `renderer.rb` read nil from it:
125
- # `IEEE Std 844.1-2017/CSA C22.2 No. 293.1-17` rendered back as
126
- # `IEEE Std 844.1-2017/CSA`, losing the CSA designation entirely.
127
- attrs = self.class.attributes
128
- extra = self.class.extra_init_keys
129
- args.each do |key, value|
130
- next if %i[code draft draft_obj typed_stage].include?(key)
131
-
132
- setter = :"#{key}="
133
- if attrs.key?(key)
134
- public_send(setter, value)
135
- elsif extra.include?(key) && respond_to?(setter)
136
- public_send(setter, value)
137
- end
118
+ # Expose numeric month from draft if available
119
+ def draft_month
120
+ return nil unless draft_obj.is_a?(Components::Draft)
121
+
122
+ draft_obj.numeric_month
138
123
  end
139
- end
140
124
 
141
- # Override accessors to return component objects.
142
- def code
143
- code_obj
144
- end
125
+ # Parse IEEE identifier string
126
+ def self.parse(input)
127
+ # Preprocessing: Convert comma-separated dual standards to "and" format
128
+ # This must happen BEFORE the "and" check below
129
+ # Pattern: "IEEE Std 960-1989, Std 1177-1989" -> "IEEE Std 960-1989 and IEEE Std 1177-1989"
130
+ input = input.gsub(/(\d{4}),\s+Std\s/, '\1 and IEEE Std ')
131
+
132
+ # Check for AIEE identifiers (but NOT those with parentheses which have relationships/adoptions)
133
+ # AIEE has its own parser/builder for simple identifiers
134
+ # AIEE inputs with parentheses are handled by IEEE parser for relationship/adoption parsing
135
+ if input.start_with?("AIEE ") && !input.include?("(")
136
+ return Aiee::Identifier.parse(input)
137
+ end
145
138
 
146
- def draft
147
- draft_obj
148
- end
139
+ # Check for IEC/IEEE copublished patterns first (before other checks)
140
+ if input.start_with?("IEC/IEEE ")
141
+ return parse_single(input)
142
+ end
149
143
 
150
- # Lazily rebuild the parsed component objects from the underlying string
151
- # attributes. After from_hash, lutaml restores the :code/:draft strings
152
- # (@code/@draft) but not these objects; the renderer reads code_obj/
153
- # draft_obj directly, so rebuild on demand to render a deserialized
154
- # identifier identically to the parsed one. On the parse path code_obj/
155
- # draft_obj are already set, so the `||=` returns them unchanged.
156
- def code_obj
157
- @code_obj ||=
158
- (Components::Code.parse(@code.to_s) unless @code.nil? || @code.to_s.empty?)
159
- end
144
+ # Check for semicolon-separated dual identifiers (IEC-first patterns)
145
+ # Pattern: "IEC 61523-3 First edition 2004-09; IEEE 1497"
146
+ if input.include?("; ")
147
+ parts = input.split("; ")
148
+ if parts.length == 2
149
+ # Try to parse both parts
150
+ begin
151
+ first = parse_single(parts[0].strip)
152
+ second = parse_single(parts[1].strip)
153
+
154
+ return Identifiers::DualPublished.new(
155
+ first_identifier: first,
156
+ second_identifier: second,
157
+ )
158
+ rescue Parslet::ParseFailed
159
+ # If parsing fails, continue with normal flow
160
+ end
161
+ end
162
+ end
160
163
 
161
- def draft_obj
162
- @draft_obj ||=
163
- (Components::Draft.parse(@draft.to_s) unless @draft.nil? || @draft.to_s.empty?)
164
- end
164
+ # PREPROCESS: Handle (R####) (Revision of...) pattern
165
+ # Convert to single parenthetical: (Reaffirmed ####, Revision of...)
166
+ # This allows parser to capture both in one parenthetical
167
+ if input =~ /\(R(\d{4})\)\s*\(Revision of ([^)]+)\)/
168
+ year = $1
169
+ $2
170
+ # Replace the two parentheticals with reaffirmed info extracted
171
+ # Parse normally but capture year first
172
+ input_modified = input.sub(
173
+ /\(R(\d{4})\)\s*\(Revision of ([^)]+)\)/, "(Revision of \\2)"
174
+ )
175
+
176
+ # Parse the modified input
177
+ result = parse_single(input_modified)
178
+ # Add reaffirmed attribute
179
+ if result.class.attributes.key?(:reaffirmed)
180
+ result.reaffirmed = year
181
+ end
182
+ return result
183
+ end
165
184
 
166
- # Expose numeric month from draft if available
167
- def draft_month
168
- return nil unless draft_obj.is_a?(Components::Draft)
185
+ # PREPROCESS: Handle (Reaffirmed ####) (Revision of...) pattern (full word format)
186
+ # Pattern: "ANSI/IEEE Std 101-1987 (Reaffirmed 2010) (Revision of IEEE Std 101-1972)"
187
+ if input =~ /\(Reaffirmed\s+(\d{4})\)\s*\(Revision of ([^)]+)\)/
188
+ year = $1
189
+ $2
190
+ # Replace the two parentheticals
191
+ input_modified = input.sub(
192
+ /\(Reaffirmed\s+(\d{4})\)\s*\(Revision of ([^)]+)\)/, "(Revision of \\2)"
193
+ )
194
+
195
+ # Parse the modified input
196
+ result = parse_single(input_modified)
197
+ # Add reaffirmed attribute
198
+ if result.class.attributes.key?(:reaffirmed)
199
+ result.reaffirmed = year
200
+ end
201
+ return result
202
+ end
169
203
 
170
- draft_obj.numeric_month
171
- end
204
+ # NEW Session 174: Check for IRE dual published pattern
205
+ # Pattern after preprocessing: "IEEE Std 218-1956 (R1980) (56 IRE 28.S2)"
206
+ # First parenthetical: (Rxxx) reaffirmed
207
+ # Second parenthetical: IRE identifier
208
+ if /\(R\d{4}\)\s*\((\d+\s+IRE[^)]+)\)/.match?(input)
209
+ main_part = input.split(" (R").first.strip # Get "IEEE Std 218-1956"
210
+ reaffirmed_year = input.match(/\(R(\d{4})\)/)[1]
211
+ ire_part = input.match(/\((\d+\s+IRE[^)]+)\)/)[1]
212
+
213
+ begin
214
+ # Parse main identifier
215
+ ieee_id = parse_single(main_part)
216
+ # Add reaffirmed year
217
+ ieee_id.reaffirmed = reaffirmed_year if ieee_id.class.attributes.key?(:reaffirmed)
218
+
219
+ # Parse IRE identifier
220
+ ire_id = parse_single(ire_part)
221
+
222
+ return Identifiers::DualPublished.new(
223
+ first_identifier: ieee_id,
224
+ second_identifier: ire_id,
225
+ )
226
+ rescue Parslet::ParseFailed
227
+ # If parsing fails, fall through to regular processing
228
+ end
229
+ end
172
230
 
173
- # IEEE stores its publication date as separate `year`/`month`/`day`
174
- # :string attributes, not a Components::Date, so the base #exclude's
175
- # `:year`->`:date` remap can't reach them (it would nil an unused `date`
176
- # component and leave the strings). After the base rebuild, nil the whole
177
- # date cluster when `:year`/`:date` is excluded, so a date-less reference
178
- # matches every date in the bucket (relaton partial-ref matching). NB: the
179
- # base #exclude also previously raised for every IEEE id (positional
180
- # `self.class.new(attrs)` vs the keyword initialize) — fixed by
181
- # Identifier#initialize accepting a positional hash.
182
- def exclude(*args)
183
- result = super
184
- if args.intersect?(%i[year date])
185
- %i[year month day].each do |attr|
186
- result.public_send("#{attr}=", nil) if result.respond_to?("#{attr}=")
231
+ # Check for space-separated dual identifiers (e.g., "IEC 62014-5 IEEE Std 1734-2011")
232
+ # This must be checked before " and " pattern
233
+ # Look for pattern where a second publisher appears after the first complete identifier
234
+ # Publishers: IEEE, AIEE, ANSI, ASA, IEC, ISO, ASTM, NACE, NSF, ASHRAE, NCTA, AESC
235
+ publishers = %w[IEEE AIEE ANSI ASA IEC ISO ASTM NACE NSF ASHRAE NCTA
236
+ AESC]
237
+
238
+ # Find all positions where publishers appear (but NOT inside parentheses)
239
+ # Publishers inside parentheses are part of relationship clauses, not dual published patterns
240
+ publisher_positions = []
241
+ publishers.each do |pub|
242
+ # Look for publisher at word boundaries (preceded by space or start of string)
243
+ regex = /(?:^|\s)(#{Regexp.escape(pub)})(?:\s|\/)/
244
+ input.scan(regex) do
245
+ match_pos = Regexp.last_match.begin(1)
246
+
247
+ # Check if this publisher is inside parentheses (relationship clause)
248
+ # Count parens before this position
249
+ before_match = input[0...match_pos]
250
+ paren_count = before_match.count("(") - before_match.count(")")
251
+
252
+ # Skip publishers inside parentheses - they're part of relationship clauses
253
+ next if paren_count.positive?
254
+
255
+ publisher_positions << { pos: match_pos, publisher: pub }
256
+ end
187
257
  end
188
- end
189
- result
190
- end
191
258
 
192
- # Compact the serialized hash (recursively, so nested Corrigendum bases
193
- # are compacted too) after the normal serialize + canonicalize: collapse
194
- # `typed_stage` to a scalar `stage` and strip the `/` off `draft`. See
195
- # Compaction for why this is a hash transform, not lutaml attributes.
196
- def to_hash(*args)
197
- hash = super
198
- Compaction.collapse(hash) if hash.is_a?(::Hash)
199
- hash
200
- end
259
+ # If we have 2 or more publishers at distinct positions (not co-publishers with /)
260
+ if publisher_positions.length >= 2
261
+ # Sort by position
262
+ publisher_positions.sort_by! { |p| p[:pos] }
263
+
264
+ # Check if they're not part of a co-published pattern (Publisher1/Publisher2)
265
+ # by ensuring there's no slash between them
266
+ first_pub = publisher_positions[0]
267
+ second_pub = publisher_positions[1]
268
+
269
+ # Get the substring between the two publishers
270
+ between = input[first_pub[:pos]..(second_pub[:pos] - 1)]
271
+
272
+ # If there's no slash and no " and ", this might be space-separated dual
273
+ if !between.include?("/") && !between.include?(" and ")
274
+ # Try to split at the second publisher position
275
+ # Back up to find the space before the second publisher
276
+ split_pos = second_pub[:pos]
277
+ while split_pos.positive? && input[split_pos - 1] == " "
278
+ split_pos -= 1
279
+ end
280
+
281
+ first_part = input[0...split_pos].strip
282
+ second_part = input[split_pos..].strip
283
+
284
+ # Try to parse both parts
285
+ begin
286
+ first = parse_single(first_part)
287
+ second = parse_single(second_part)
288
+
289
+ # Only treat as dual if both parse successfully
290
+ return Identifiers::DualPublished.new(
291
+ first_identifier: first,
292
+ second_identifier: second,
293
+ )
294
+ rescue Parslet::ParseFailed
295
+ # If parsing fails, continue with normal flow
296
+ end
297
+ end
298
+ end
201
299
 
202
- # Inverse of the to_hash compaction: expand a scalar `stage` back into the
203
- # `typed_stage` sub-hash (on a deep copy, recursively) before lutaml
204
- # deserializes, so nested bases rebuild their component too. `draft` needs
205
- # no expansion (Draft.parse accepts the slashless form).
206
- def self.from_hash(data, options = {})
207
- data = Compaction.expand(Compaction.deep_dup(data)) if data.is_a?(::Hash)
208
- super
209
- end
300
+ # Check for dual published patterns with " and "
301
+ if input.include?(" and ")
302
+ # DON'T split if " and " is inside parentheses (likely a relationship clause)
303
+ # Check if parentheses are balanced and " and " is inside them
304
+ paren_count = 0
305
+ and_outside_parens = false
306
+ and_position = nil
307
+
308
+ input.each_char.with_index do |char, i|
309
+ paren_count += 1 if char == "("
310
+ paren_count -= 1 if char == ")"
311
+
312
+ # Check if " and " starts at this position and we're outside parens
313
+ if paren_count.zero? && input[i..(i + 4)] == " and "
314
+ and_outside_parens = true
315
+ and_position = i
316
+ break
317
+ end
318
+ end
319
+
320
+ # Only split if " and " is outside parentheses
321
+ if and_outside_parens && and_position
322
+ # Split at the found position only (not at all " and " occurrences)
323
+ first_part = input[0...and_position].strip
324
+ second_part = input[(and_position + 5)..].strip
325
+
326
+ # Parse each part separately
327
+ first = parse_single(first_part)
328
+ second = parse_single(second_part)
329
+
330
+ return Identifiers::DualPublished.new(
331
+ first_identifier: first,
332
+ second_identifier: second,
333
+ )
334
+ end
335
+ end
210
336
 
211
- # Register the identifier classes the automatic `Identifiers::*` scan
212
- # cannot see, so `Pubid::Ieee::Identifier.from_hash` can route their rows
213
- # back. The scan only looks at classes declared *directly* under
214
- # `Identifiers`, which misses both AIEE and IRE (they live under their own
215
- # `Aiee`/`Ire` namespaces) and the whole NESC family (nested one level
216
- # deeper, under `Identifiers::Nesc`).
217
- def self.additional_identifier_classes
218
- [
219
- Aiee::Identifier,
220
- Ire::Identifier,
221
- Identifiers::Nesc::Draft,
222
- Identifiers::Nesc::Edition,
223
- Identifiers::Nesc::Handbook,
224
- Identifiers::Nesc::Redline,
225
- Identifiers::Nesc::Standard,
226
- ]
227
- end
337
+ # NEW Session 171: Check for dual published patterns with " & " (ampersand)
338
+ if input.include?(" & ")
339
+ # DON'T split if " & " is inside parentheses
340
+ paren_count = 0
341
+ ampersand_outside_parens = false
342
+
343
+ input.each_char.with_index do |char, i|
344
+ paren_count += 1 if char == "("
345
+ paren_count -= 1 if char == ")"
346
+
347
+ # Check if " & " starts at this position and we're outside parens
348
+ if paren_count.zero? && input[i..(i + 2)] == " & "
349
+ ampersand_outside_parens = true
350
+ break
351
+ end
352
+ end
353
+
354
+ # Only split if " & " is outside parentheses
355
+ if ampersand_outside_parens
356
+ parts = input.split(" & ")
357
+ if parts.length == 2
358
+ # Parse each part separately
359
+ first = parse_single(parts[0].strip)
360
+ second = parse_single(parts[1].strip)
361
+
362
+ return Identifiers::DualPublished.new(
363
+ first_identifier: first,
364
+ second_identifier: second,
365
+ )
366
+ end
367
+ end
368
+ end
228
369
 
229
- # Parse IEEE identifier string.
230
- #
231
- # PreParser owns all regex/dispatch logic; this method is a thin
232
- # orchestrator that consumes a PreParser::Result and routes to the
233
- # correct builder.
234
- def self.parse(input)
235
- unless input.is_a?(String)
236
- raise Pubid::Errors::InvalidInputError,
237
- Pubid::INPUT_NOT_A_STRING_MESSAGE
238
- end
370
+ # Special case: AIEE identifiers with ASA parenthetical references
371
+ # Pattern: "AIEE No 18-1934 (ASA C55 1934)"
372
+ if input.match?(/^AIEE\s+/) && input.include?("(") && input.include?("ASA")
373
+ main_part = input.split("(").first.strip
374
+ adoption_match = input.match(/\((ASA[^)]+)\)/)
375
+
376
+ if adoption_match
377
+ adoption_part = adoption_match.captures.first
378
+ # Parse the main AIEE identifier
379
+ begin
380
+ aiee_id = parse_single(main_part)
381
+ # Parse the ASA identifier
382
+ asa_id = parse_single(adoption_part)
383
+
384
+ return Identifiers::AdoptedStandard.new(
385
+ ieee_identifier: aiee_id,
386
+ adopted_identifier: asa_id,
387
+ )
388
+ rescue Parslet::ParseFailed
389
+ # If parsing fails, fall through to regular processing
390
+ end
391
+ end
392
+ end
393
+
394
+ # Check for adopted standards (parenthetical adoptions)
395
+ # Only consider it an adoption if the parenthetical content looks like an identifier
396
+ if input.include?("(") && input.include?(")") && !input.start_with?("IEC/IEEE ")
397
+ # Extract the part before parentheses and the adoption part
398
+ main_part = input.split("(").first.strip
399
+ adoption_match = input.match(/\(([^)]+)\)/)
400
+ adoption_part = adoption_match&.captures&.first
401
+
402
+ # Check if adoption_part looks like an identifier (contains publisher or type keywords)
403
+ # BUT exclude revision/amendment/supersedes notes
404
+ # AND exclude Pattern 4 relationship types
405
+ if main_part && adoption_part &&
406
+ !adoption_part.match?(/^\s*(Revision|Revison|Amendment|Corrigendum|Corrigenda|incorporates|Incorporating|Incorporates|Adoption|Supplement|Draft Amendment|DRAFT Amendment|Draft Revision|Reaffirmation|Redesignation|redesignated as|Supersedes|Supercedes|Includes|Previously designated as|Notebooks|Standard Newspaper)/i) &&
407
+ (adoption_part.match?(/\b(ANSI|ISO|IEC|IEEE|AIEE|IRE|ASA|ASTM|CSA|ASME|NACE|NSF|ASHRAE|NCTA|AESC)\s/) ||
408
+ adoption_part.match?(/^\s*(ANSI|ISO|IEC|IEEE|AIEE|IRE|ASA|ASTM|CSA|ASME|NACE|NSF|ASHRAE|NCTA|AESC)\b/) ||
409
+ adoption_part.match?(/\bStd\s+\d+/))
410
+ # Parse the main IEEE identifier
411
+ ieee_id = parse_single(main_part)
412
+
413
+ # Parse comma-separated adopted identifiers
414
+ adopted_parts = adoption_part.split(",").map(&:strip)
415
+ adopted_ids = adopted_parts.map do |part|
416
+ if part.strip.start_with?("IEC")
417
+ # Use IEC parser for IEC adoptions
418
+ # Preprocess to convert "Edition X.Y" to IEC format
419
+ # Pattern: "IEC 60255-24 Edition 2.0 2013-04" → "IEC 60255-24:2013-04 ED2.0"
420
+ iec_part = part.dup
421
+ # Replace " Edition X.Y YYYY-MM" (or similar) with ":YYYY-MM EDX.Y"
422
+ iec_part.gsub!(/\s+Edition\s+([0-9.]+)\s+([0-9-]+)/,
423
+ ':\2 ED\1')
424
+ # Replace " Edition X.Y" at end (no date)
425
+ iec_part.gsub!(/\s+Edition\s+([0-9.]+)\s*$/, ' ED\1')
426
+ Pubid::Iec.parse(iec_part)
427
+ elsif part.strip.start_with?("ANSI")
428
+ # Use ANSI parser for ANSI adoptions
429
+ Pubid::Ansi.parse(part)
430
+ else
431
+ # Use IEEE parser for other adoptions
432
+ parse_single(part)
433
+ end
434
+ end
435
+
436
+ return Identifiers::AdoptedStandard.new(
437
+ ieee_identifier: ieee_id,
438
+ adopted_identifiers: adopted_ids,
439
+ )
440
+ end
441
+ # If it doesn't look like an identifier, let the parser handle it as additional_parameters
442
+ end
239
443
 
240
- if input.length > Pubid::MAX_INPUT_LENGTH
241
- raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
444
+ # Fall back to single identifier parsing
445
+ parse_single(input)
242
446
  end
243
447
 
244
- result = PreParser.preprocess(input)
245
-
246
- case result.dispatch
247
- when :aiee_simple
248
- return Aiee::Identifier.parse(result.input)
249
- when :iec_ieee_copublished
250
- return parse_single(result.input)
251
- when :dual_semicolon
252
- return build_dual(result.parts)
253
- when :dual_reaffirmed
254
- return build_reaffirmed(result)
255
- when :dual_ire
256
- return build_dual_with_reaffirmed(result)
257
- when :dual_space_separated
258
- return build_dual(result.parts)
259
- when :dual_and
260
- return build_dual(result.parts)
261
- when :dual_ampersand
262
- return build_dual(result.parts)
263
- when :aiee_asa_adoption
264
- return build_aiee_asa_adoption(result.parts)
265
- when :adopted
266
- return build_adopted(result.parts)
267
- else
268
- parse_single(result.input)
448
+ # Parse a single IEEE identifier
449
+ def self.parse_single(input)
450
+ # Apply legacy update_codes normalization first, before Parser's extensive preprocessing
451
+ normalized = Core::UpdateCodes.apply(input, :ieee)
452
+ parsed = Parser.parse(normalized) # Use class method for preprocessing
453
+ builder = Builder.new(Base)
454
+ # Pass the original input string to builder for context
455
+ builder.original_input = input
456
+ builder.build(parsed)
269
457
  end
270
- rescue Parslet::ParseFailed
271
- parse_single(input)
272
- end
273
458
 
274
- # ---- dispatch constructors (used by parse) ----
459
+ def to_s
460
+ parts = []
275
461
 
276
- def self.build_dual(parts)
277
- first = parse_single(parts[0])
278
- second = parse_single(parts[1])
279
- Identifiers::DualPublished.new(
280
- first_identifier: first,
281
- second_identifier: second,
282
- )
283
- end
284
- private_class_method :build_dual
285
-
286
- def self.build_reaffirmed(result)
287
- parsed = parse_single(result.input)
288
- parsed.reaffirmed = result.metadata[:reaffirmed] if parsed.class.attributes.key?(:reaffirmed)
289
- parsed
290
- end
291
- private_class_method :build_reaffirmed
292
-
293
- def self.build_dual_with_reaffirmed(result)
294
- ieee_id = parse_single(result.parts[0])
295
- ieee_id.reaffirmed = result.metadata[:reaffirmed] if ieee_id.class.attributes.key?(:reaffirmed)
296
- ire_id = parse_single(result.parts[1])
297
- Identifiers::DualPublished.new(
298
- first_identifier: ieee_id,
299
- second_identifier: ire_id,
300
- )
301
- end
302
- private_class_method :build_dual_with_reaffirmed
303
-
304
- def self.build_aiee_asa_adoption(parts)
305
- aiee_id = parse_single(parts[0])
306
- asa_id = parse_single(parts[1])
307
- # `adopted_identifierS` — AdoptedStandard declares a collection. The
308
- # singular spelling was not an attribute, so lutaml dropped it without
309
- # a word and the ASA half of these 13 identifiers was never stored:
310
- # `AIEE No 18-1934 (ASA C55 1934)` rendered back as `AIEE No 18-1934`.
311
- # The unknown-key contract turned that silent loss into a raise, which
312
- # is how it was found.
313
- Identifiers::AdoptedStandard.new(
314
- ieee_identifier: aiee_id,
315
- adopted_identifiers: [asa_id],
316
- )
317
- end
318
- private_class_method :build_aiee_asa_adoption
319
-
320
- def self.build_adopted(parts)
321
- ieee_id = parse_single(parts[0])
322
- adopted_parts = parts[1].split(",").map(&:strip)
323
- adopted_ids = adopted_parts.map do |part|
324
- if part.start_with?("IEC")
325
- Pubid::Iec.parse(normalize_iec_adoption(part))
326
- elsif part.start_with?("ANSI")
327
- Pubid::Ansi.parse(part)
462
+ # Publisher(s) - handle copublisher array properly
463
+ if copublisher && !copublisher.empty?
464
+ # Copublisher is an array, join all publishers with single slash
465
+ parts << [publisher, *copublisher].join("/")
328
466
  else
329
- parse_single(part)
467
+ parts << publisher
330
468
  end
331
- end
332
- Identifiers::AdoptedStandard.new(
333
- ieee_identifier: ieee_id,
334
- adopted_identifiers: adopted_ids,
335
- )
336
- end
337
- private_class_method :build_adopted
338
-
339
- # "IEC 60255-24 Edition 2.0 2013-04" → "IEC 60255-24:2013-04 ED2.0"
340
- def self.normalize_iec_adoption(part)
341
- iec_part = part.dup
342
- iec_part.gsub!(/\s+Edition\s+([0-9.]+)\s+([0-9-]+)/, ':\2 ED\1')
343
- iec_part.gsub!(/\s+Edition\s+([0-9.]+)\s*$/, ' ED\1')
344
- iec_part
345
- end
346
- private_class_method :normalize_iec_adoption
347
-
348
- # Parse a single IEEE identifier
349
- def self.parse_single(input)
350
- # Apply legacy update_codes normalization first, before Parser's extensive preprocessing
351
- normalized = Core::UpdateCodes.apply(input, :ieee)
352
- parsed = Parser.parse(normalized) # Use class method for preprocessing
353
- builder = Builder.new(Identifier)
354
- # Pass the original input string to builder for context
355
- builder.original_input = input
356
- builder.build(parsed)
357
- end
358
469
 
359
- # IEEE stores identity in `code` (prefix/number/parts) rather than the
360
- # generic `number`, has its own `type` string ("Std", "Draft Std"), and
361
- # carries `year` as a bare string — none of which the generic MrString
362
- # renderer knows about. Override the lossless MR template directly so
363
- # every IEEE identifier round-trips (issue #142). Supplements append
364
- # `_{type}.{number}.{year}` recursively via mr_supplement_suffix.
365
- # Lowercased to match the all-lowercase MR convention.
366
- def mr_publisher
367
- publisher&.to_s&.downcase
368
- end
470
+ # Draft status
471
+ parts << draft_status if draft_status
369
472
 
370
- def mr_type
371
- type&.downcase
372
- end
473
+ # Type - only render for IEEE/AIEE publishers, and only for non-projects
474
+ # Must come BEFORE code
475
+ should_render_type = publisher&.match?(/^(IEEE|AIEE)/)
373
476
 
374
- def mr_number_with_part
375
- code_obj&.to_s&.downcase
376
- end
477
+ if should_render_type && !typed_stage&.project_status && type && !type.to_s.strip.empty? && type != "P"
478
+ # Non-project with explicit type (Std, No, etc.)
479
+ type_str = type.dup
480
+ # Remove P prefix if somehow present
481
+ type_str = type_str.sub(/^P/, "") if type_str.start_with?("P")
482
+ parts << type_str unless type_str.strip.empty?
483
+ end
377
484
 
378
- def mr_year
379
- year&.to_s
485
+ # Code - with P prefix for projects (concatenated, not separated)
486
+ if code_obj
487
+ result = code_obj.to_s
488
+
489
+ # Prepend P if this is a project AND code doesn't already have P
490
+ if typed_stage&.project_status && should_render_type && !result.start_with?("P")
491
+ result = "P#{result}"
492
+ end
493
+
494
+ # Only attach year to code if there's no edition, no month, and no draft
495
+ result += "-#{year}" if year && !draft_obj && !edition && !month
496
+
497
+ # Append draft to code - with or without space based on original format
498
+ if draft_obj
499
+ result += space_before_draft ? " #{draft_obj}" : draft_obj.to_s
500
+ end
501
+
502
+ # Append interpretation notation (/INT)
503
+ result += "/INT" if interpretation
504
+
505
+ # Append conformance notation (/ConformanceNN-YYYY)
506
+ if conf_number
507
+ result += "/Conformance#{conf_number}"
508
+ result += "-#{conf_year}" if conf_year
509
+ end
510
+
511
+ # Append ASHRAE joint publication (/ASHRAE Guideline NN-YYYY)
512
+ if ashrae_number
513
+ result += "/ASHRAE Guideline #{ashrae_number}"
514
+ result += "-#{ashrae_year}" if ashrae_year
515
+ end
516
+
517
+ # Append IEEE cross-reference (/C62.22.1-1996)
518
+ result += crossref if crossref
519
+
520
+ parts << result
521
+ elsif should_render_type && typed_stage&.project_status
522
+ # No code but is a project - add standalone P
523
+ parts << "P"
524
+ end
525
+
526
+ # Edition - with year if present (IEC style)
527
+ if edition
528
+ edition_str = "Edition #{edition}"
529
+ if year
530
+ edition_str += " #{year}"
531
+ edition_str += "-#{edition_month}" if edition_month
532
+ end
533
+ parts << edition_str
534
+ end
535
+
536
+ # Build the main identifier (without month yet)
537
+ result = parts.join(" ")
538
+
539
+ # Month/Day - append directly to avoid extra space before comma
540
+ if month
541
+ # Format: ", Month Day, Year" or ", Month, Year"
542
+ result += ", #{month}"
543
+ result += " #{day}" if day
544
+ if year && !edition
545
+ # Add comma after month if year follows
546
+ result += ", #{year}"
547
+ end
548
+ end
549
+
550
+ # Add parenthetical content if present
551
+ # Handle multiple parenthetical clauses (reaffirmed + relationships/revision)
552
+ parentheticals = []
553
+
554
+ reaff = reaffirmed
555
+ if reaff && !reaff.to_s.strip.empty?
556
+ parentheticals << "(R#{reaff})"
557
+ end
558
+
559
+ # Then add relationships/revision/amendment as second parenthetical
560
+ if parenthetical_content
561
+ parentheticals << "(#{parenthetical_content})"
562
+ elsif relationships && !relationships.empty?
563
+ # Render relationships (multiple separated by /)
564
+ relationship_str = relationships.join(" / ")
565
+ parentheticals << "(#{relationship_str})"
566
+ elsif revision_of
567
+ parentheticals << "(Revision of IEEE Std #{revision_of})"
568
+ elsif amendment_to
569
+ parentheticals << "(Amendment to IEEE Std #{amendment_to})"
570
+ elsif adoption
571
+ parentheticals << "(Adoption of #{adoption})"
572
+ elsif note && !note.to_s.strip.empty?
573
+ # Only add note if it doesn't duplicate other content
574
+ parentheticals << "(#{note})"
575
+ end
576
+
577
+ # Append all parentheticals with space separation
578
+ result += " #{parentheticals.join(' ')}" unless parentheticals.empty?
579
+
580
+ # Book nickname - outside parentheses in square brackets
581
+ result += " [#{nickname}]" if nickname && !nickname.to_s.strip.empty?
582
+
583
+ # Redline suffix
584
+ result += " - Redline" if redline
585
+
586
+ result
587
+ end
380
588
  end
381
589
  end
382
-
383
590
  end
384
591
  end