pubid 2.0.0.pre.alpha.1 → 2.0.0.pre.alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +5 -1
  3. data/data/nist/update_codes.yaml +27 -0
  4. data/lib/pubid/amca/builder.rb +2 -2
  5. data/lib/pubid/amca/identifier.rb +7 -0
  6. data/lib/pubid/amca/identifiers/base.rb +0 -26
  7. data/lib/pubid/amca/identifiers/interpretation.rb +0 -17
  8. data/lib/pubid/amca/identifiers/publication.rb +0 -13
  9. data/lib/pubid/amca/renderer.rb +82 -0
  10. data/lib/pubid/amca/single_identifier.rb +0 -23
  11. data/lib/pubid/amca/urn_parser.rb +28 -0
  12. data/lib/pubid/amca.rb +42 -1
  13. data/lib/pubid/ansi/builder.rb +5 -3
  14. data/lib/pubid/ansi/identifier.rb +1 -1
  15. data/lib/pubid/ansi/identifiers/american_national_standard.rb +2 -1
  16. data/lib/pubid/ansi/identifiers/standard.rb +2 -3
  17. data/lib/pubid/ansi/renderer.rb +53 -0
  18. data/lib/pubid/ansi/single_identifier.rb +2 -31
  19. data/lib/pubid/ansi/urn_generator.rb +3 -38
  20. data/lib/pubid/ansi/urn_parser.rb +23 -0
  21. data/lib/pubid/ansi.rb +38 -3
  22. data/lib/pubid/api/builder.rb +29 -74
  23. data/lib/pubid/api/identifier.rb +0 -4
  24. data/lib/pubid/api/identifiers/base.rb +0 -2
  25. data/lib/pubid/api/identifiers/bulletin.rb +0 -2
  26. data/lib/pubid/api/identifiers/continuous_operations_standard.rb +0 -2
  27. data/lib/pubid/api/identifiers/mpms.rb +1 -17
  28. data/lib/pubid/api/identifiers/publication.rb +0 -2
  29. data/lib/pubid/api/identifiers/recommended_practice.rb +0 -2
  30. data/lib/pubid/api/identifiers/specification.rb +0 -2
  31. data/lib/pubid/api/identifiers/standard.rb +0 -2
  32. data/lib/pubid/api/identifiers/technical_report.rb +0 -2
  33. data/lib/pubid/api/identifiers/typeless_standard.rb +1 -14
  34. data/lib/pubid/api/identifiers.rb +18 -0
  35. data/lib/pubid/api/renderer.rb +89 -0
  36. data/lib/pubid/api/single_identifier.rb +1 -13
  37. data/lib/pubid/api/urn_generator.rb +0 -18
  38. data/lib/pubid/api/urn_parser.rb +35 -0
  39. data/lib/pubid/api.rb +51 -5
  40. data/lib/pubid/ashrae/builder.rb +3 -3
  41. data/lib/pubid/ashrae/identifier.rb +6 -0
  42. data/lib/pubid/ashrae/identifiers/addenda_package.rb +0 -10
  43. data/lib/pubid/ashrae/identifiers/addendum.rb +0 -19
  44. data/lib/pubid/ashrae/identifiers/base.rb +3 -0
  45. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +0 -15
  46. data/lib/pubid/ashrae/identifiers/errata.rb +0 -10
  47. data/lib/pubid/ashrae/identifiers/interpretation.rb +0 -10
  48. data/lib/pubid/ashrae/renderer.rb +117 -0
  49. data/lib/pubid/ashrae/single_identifier.rb +0 -13
  50. data/lib/pubid/ashrae/urn_generator.rb +0 -8
  51. data/lib/pubid/ashrae/urn_parser.rb +27 -0
  52. data/lib/pubid/ashrae.rb +42 -1
  53. data/lib/pubid/asme/components/code.rb +10 -2
  54. data/lib/pubid/asme/identifiers/base.rb +0 -60
  55. data/lib/pubid/asme/renderer.rb +66 -0
  56. data/lib/pubid/asme/urn_parser.rb +31 -0
  57. data/lib/pubid/asme.rb +42 -1
  58. data/lib/pubid/astm/components/code.rb +9 -0
  59. data/lib/pubid/{jis → astm}/components.rb +1 -1
  60. data/lib/pubid/astm/identifiers/adjunct.rb +0 -8
  61. data/lib/pubid/astm/identifiers/data_series.rb +0 -14
  62. data/lib/pubid/astm/identifiers/iso_dual_published.rb +9 -34
  63. data/lib/pubid/astm/identifiers/manual.rb +0 -27
  64. data/lib/pubid/astm/identifiers/monograph.rb +0 -14
  65. data/lib/pubid/astm/identifiers/research_report.rb +0 -7
  66. data/lib/pubid/astm/identifiers/standard.rb +0 -39
  67. data/lib/pubid/astm/identifiers/technical_report.rb +0 -13
  68. data/lib/pubid/astm/identifiers/work_in_progress.rb +0 -11
  69. data/lib/pubid/astm/identifiers.rb +18 -0
  70. data/lib/pubid/astm/renderer.rb +172 -0
  71. data/lib/pubid/astm/single_identifier.rb +0 -10
  72. data/lib/pubid/astm/urn_parser.rb +30 -0
  73. data/lib/pubid/astm.rb +39 -27
  74. data/lib/pubid/bsi/builder.rb +21 -12
  75. data/lib/pubid/bsi/identifier.rb +8 -2
  76. data/lib/pubid/bsi/identifiers/addendum_document.rb +3 -33
  77. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +11 -47
  78. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +11 -38
  79. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +3 -53
  80. data/lib/pubid/bsi/identifiers/amendment.rb +3 -19
  81. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +2 -4
  82. data/lib/pubid/bsi/identifiers/british_standard.rb +2 -1
  83. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +3 -84
  84. data/lib/pubid/bsi/identifiers/committee_document.rb +1 -14
  85. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +3 -84
  86. data/lib/pubid/bsi/identifiers/corrigendum.rb +3 -7
  87. data/lib/pubid/bsi/identifiers/detailed_specification.rb +1 -34
  88. data/lib/pubid/bsi/identifiers/disc.rb +1 -27
  89. data/lib/pubid/bsi/identifiers/draft_document.rb +3 -44
  90. data/lib/pubid/bsi/identifiers/electronic_book.rb +3 -36
  91. data/lib/pubid/bsi/identifiers/expert_commentary.rb +3 -15
  92. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +1 -45
  93. data/lib/pubid/bsi/identifiers/flex.rb +1 -33
  94. data/lib/pubid/bsi/identifiers/handbook.rb +2 -13
  95. data/lib/pubid/bsi/identifiers/index.rb +1 -30
  96. data/lib/pubid/bsi/identifiers/method.rb +1 -39
  97. data/lib/pubid/bsi/identifiers/national_annex.rb +5 -27
  98. data/lib/pubid/bsi/identifiers/practice_guide.rb +2 -4
  99. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +3 -52
  100. data/lib/pubid/bsi/identifiers/published_document.rb +3 -52
  101. data/lib/pubid/bsi/identifiers/section.rb +1 -28
  102. data/lib/pubid/bsi/identifiers/set.rb +3 -17
  103. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +1 -7
  104. data/lib/pubid/bsi/identifiers/supplement_document.rb +3 -21
  105. data/lib/pubid/bsi/identifiers/supplementary_index.rb +1 -44
  106. data/lib/pubid/bsi/identifiers/technical_specification.rb +3 -45
  107. data/lib/pubid/bsi/identifiers/test_method.rb +1 -30
  108. data/lib/pubid/bsi/identifiers/value_added_publication.rb +3 -14
  109. data/lib/pubid/bsi/identifiers.rb +0 -1
  110. data/lib/pubid/bsi/renderer.rb +1050 -0
  111. data/lib/pubid/bsi/single_identifier.rb +6 -70
  112. data/lib/pubid/bsi/urn_generator.rb +2 -3
  113. data/lib/pubid/bsi/urn_parser.rb +52 -0
  114. data/lib/pubid/bsi.rb +224 -1
  115. data/lib/pubid/builder/base.rb +57 -10
  116. data/lib/pubid/bundled_identifier.rb +0 -1
  117. data/lib/pubid/ccsds/builder.rb +4 -3
  118. data/lib/pubid/ccsds/identifier.rb +66 -1
  119. data/lib/pubid/ccsds/identifiers/base.rb +11 -50
  120. data/lib/pubid/ccsds/identifiers/corrigendum.rb +7 -6
  121. data/lib/pubid/ccsds/parser.rb +4 -2
  122. data/lib/pubid/ccsds/single_identifier.rb +4 -1
  123. data/lib/pubid/ccsds/supplement_identifier.rb +15 -11
  124. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  125. data/lib/pubid/ccsds/urn_parser.rb +20 -0
  126. data/lib/pubid/ccsds.rb +39 -1
  127. data/lib/pubid/cen_cenelec/builder.rb +12 -14
  128. data/lib/pubid/cen_cenelec/identifier.rb +8 -2
  129. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +13 -4
  130. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +2 -8
  131. data/lib/pubid/cen_cenelec/identifiers/base.rb +5 -41
  132. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +2 -1
  133. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +2 -1
  134. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +2 -25
  135. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +2 -13
  136. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +2 -1
  137. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +4 -7
  138. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +2 -1
  139. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +2 -2
  140. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +2 -1
  141. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +2 -1
  142. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +2 -1
  143. data/lib/pubid/cen_cenelec/renderer.rb +261 -0
  144. data/lib/pubid/cen_cenelec/single_identifier.rb +11 -89
  145. data/lib/pubid/cen_cenelec/urn_generator.rb +6 -6
  146. data/lib/pubid/cen_cenelec/urn_parser.rb +28 -0
  147. data/lib/pubid/cen_cenelec.rb +168 -1
  148. data/lib/pubid/cie/components/code.rb +8 -0
  149. data/lib/pubid/cie/identifier.rb +6 -4
  150. data/lib/pubid/cie/urn_parser.rb +28 -0
  151. data/lib/pubid/cie.rb +43 -1
  152. data/lib/pubid/components/adoption.rb +104 -0
  153. data/lib/pubid/components/code.rb +22 -8
  154. data/lib/pubid/components/date.rb +23 -16
  155. data/lib/pubid/components/edition.rb +9 -6
  156. data/lib/pubid/components/iteration.rb +32 -0
  157. data/lib/pubid/components/language.rb +6 -4
  158. data/lib/pubid/components/locality.rb +10 -1
  159. data/lib/pubid/components/publisher.rb +9 -6
  160. data/lib/pubid/components/relationship.rb +151 -0
  161. data/lib/pubid/components/stage.rb +5 -14
  162. data/lib/pubid/components/supplement.rb +184 -0
  163. data/lib/pubid/components/type.rb +5 -15
  164. data/lib/pubid/components/typed_stage.rb +11 -8
  165. data/lib/pubid/components.rb +4 -0
  166. data/lib/pubid/core/update_codes.rb +28 -7
  167. data/lib/pubid/csa/identifier.rb +0 -3
  168. data/lib/pubid/csa/identifiers/base.rb +2 -122
  169. data/lib/pubid/csa/identifiers/cec.rb +2 -101
  170. data/lib/pubid/csa/identifiers/series.rb +2 -102
  171. data/lib/pubid/csa/renderer.rb +292 -0
  172. data/lib/pubid/csa/urn_generator.rb +1 -1
  173. data/lib/pubid/csa/urn_parser.rb +33 -0
  174. data/lib/pubid/csa.rb +42 -1
  175. data/lib/pubid/etsi/components/code.rb +9 -2
  176. data/lib/pubid/etsi/identifiers/base.rb +1 -4
  177. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +2 -9
  178. data/lib/pubid/etsi/renderer.rb +42 -0
  179. data/lib/pubid/etsi/urn_parser.rb +34 -0
  180. data/lib/pubid/etsi.rb +42 -1
  181. data/lib/pubid/export/exporter.rb +4 -46
  182. data/lib/pubid/export/flavor_exporter.rb +111 -278
  183. data/lib/pubid/export.rb +0 -6
  184. data/lib/pubid/identifier.rb +10 -18
  185. data/lib/pubid/identifier_facade.rb +114 -0
  186. data/lib/pubid/identifier_metadata.rb +1 -1
  187. data/lib/pubid/idf/builder.rb +3 -3
  188. data/lib/pubid/idf/identifier.rb +3 -6
  189. data/lib/pubid/idf/identifiers/amendment.rb +2 -1
  190. data/lib/pubid/idf/identifiers/corrigendum.rb +2 -1
  191. data/lib/pubid/idf/identifiers/international_standard.rb +2 -1
  192. data/lib/pubid/idf/identifiers/reviewed_method.rb +2 -1
  193. data/lib/pubid/idf/parser.rb +3 -2
  194. data/lib/pubid/idf/renderer.rb +84 -0
  195. data/lib/pubid/idf/supplement_identifier.rb +2 -10
  196. data/lib/pubid/idf/urn_generator.rb +4 -39
  197. data/lib/pubid/idf/urn_parser.rb +25 -0
  198. data/lib/pubid/idf.rb +51 -1
  199. data/lib/pubid/iec/builder.rb +48 -65
  200. data/lib/pubid/iec/components/code.rb +9 -32
  201. data/lib/pubid/iec/components/publisher.rb +1 -1
  202. data/lib/pubid/iec/components.rb +14 -0
  203. data/lib/pubid/iec/identifier.rb +276 -3
  204. data/lib/pubid/iec/identifiers/amendment.rb +2 -3
  205. data/lib/pubid/iec/identifiers/base.rb +8 -28
  206. data/lib/pubid/iec/identifiers/component_specification.rb +3 -3
  207. data/lib/pubid/iec/identifiers/conformity_assessment.rb +1 -2
  208. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +27 -30
  209. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -3
  210. data/lib/pubid/iec/identifiers/fragment_identifier.rb +37 -26
  211. data/lib/pubid/iec/identifiers/guide.rb +0 -2
  212. data/lib/pubid/iec/identifiers/international_standard.rb +2 -3
  213. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +2 -3
  214. data/lib/pubid/iec/identifiers/operational_document.rb +3 -3
  215. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +2 -3
  216. data/lib/pubid/iec/identifiers/sheet_identifier.rb +21 -15
  217. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +3 -3
  218. data/lib/pubid/iec/identifiers/systems_reference_document.rb +2 -3
  219. data/lib/pubid/iec/identifiers/technical_report.rb +2 -3
  220. data/lib/pubid/iec/identifiers/technical_specification.rb +2 -3
  221. data/lib/pubid/iec/identifiers/technology_report.rb +1 -2
  222. data/lib/pubid/iec/identifiers/test_report_form.rb +5 -34
  223. data/lib/pubid/iec/identifiers/vap_identifier.rb +26 -23
  224. data/lib/pubid/iec/identifiers/white_paper.rb +3 -3
  225. data/lib/pubid/iec/identifiers/working_document.rb +4 -48
  226. data/lib/pubid/iec/identifiers.rb +30 -0
  227. data/lib/pubid/iec/parser.rb +20 -14
  228. data/lib/pubid/iec/renderer.rb +254 -0
  229. data/lib/pubid/iec/single_identifier.rb +6 -12
  230. data/lib/pubid/iec/supplement_identifier.rb +58 -54
  231. data/lib/pubid/iec/urn_generator.rb +57 -171
  232. data/lib/pubid/iec/urn_parser.rb +53 -252
  233. data/lib/pubid/iec.rb +40 -68
  234. data/lib/pubid/ieee/builder.rb +12 -12
  235. data/lib/pubid/ieee/components/code.rb +8 -0
  236. data/lib/pubid/ieee/components/draft.rb +14 -0
  237. data/lib/pubid/ieee/components/relationship.rb +5 -149
  238. data/lib/pubid/ieee/identifier.rb +6 -0
  239. data/lib/pubid/ieee/identifiers/adopted_standard.rb +1 -6
  240. data/lib/pubid/ieee/identifiers/base.rb +101 -458
  241. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +1 -7
  242. data/lib/pubid/ieee/identifiers/corrigendum.rb +1 -9
  243. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +1 -7
  244. data/lib/pubid/ieee/identifiers/dual_identifier.rb +1 -1
  245. data/lib/pubid/ieee/identifiers/dual_published.rb +1 -1
  246. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +1 -6
  247. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +1 -7
  248. data/lib/pubid/ieee/identifiers/joint_development.rb +2 -0
  249. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +1 -15
  250. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +1 -3
  251. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +15 -0
  252. data/lib/pubid/ieee/identifiers/redlined_standard.rb +1 -4
  253. data/lib/pubid/ieee/identifiers/si_standard.rb +1 -35
  254. data/lib/pubid/ieee/identifiers/standard.rb +1 -1
  255. data/lib/pubid/ieee/pre_parser.rb +301 -0
  256. data/lib/pubid/ieee/renderer.rb +307 -0
  257. data/lib/pubid/ieee/urn_parser.rb +34 -0
  258. data/lib/pubid/ieee.rb +62 -1
  259. data/lib/pubid/ieee_debug.rb +0 -1
  260. data/lib/pubid/iho/builder.rb +2 -2
  261. data/lib/pubid/iho/identifier.rb +8 -0
  262. data/lib/pubid/iho/identifiers/base.rb +49 -10
  263. data/lib/pubid/iho/identifiers/bibliographic.rb +0 -4
  264. data/lib/pubid/iho/identifiers/circular_letter.rb +0 -4
  265. data/lib/pubid/iho/identifiers/miscellaneous.rb +0 -4
  266. data/lib/pubid/iho/identifiers/publication.rb +0 -4
  267. data/lib/pubid/iho/identifiers/standard.rb +0 -4
  268. data/lib/pubid/iho/parser.rb +3 -3
  269. data/lib/pubid/iho/renderer.rb +30 -0
  270. data/lib/pubid/iho/urn_generator.rb +3 -3
  271. data/lib/pubid/iho/urn_parser.rb +58 -0
  272. data/lib/pubid/iho.rb +50 -1
  273. data/lib/pubid/iso/builder.rb +59 -53
  274. data/lib/pubid/iso/bundled_identifier.rb +51 -0
  275. data/lib/pubid/iso/components/code.rb +7 -19
  276. data/lib/pubid/iso/components/publisher.rb +10 -8
  277. data/lib/pubid/iso/components.rb +2 -4
  278. data/lib/pubid/iso/identifier.rb +233 -6
  279. data/lib/pubid/iso/identifiers/addendum.rb +9 -6
  280. data/lib/pubid/iso/identifiers/amendment.rb +8 -4
  281. data/lib/pubid/iso/identifiers/corrigendum.rb +4 -4
  282. data/lib/pubid/iso/identifiers/data.rb +0 -1
  283. data/lib/pubid/iso/identifiers/directives.rb +8 -2
  284. data/lib/pubid/iso/identifiers/directives_supplement.rb +43 -14
  285. data/lib/pubid/iso/identifiers/extract.rb +2 -2
  286. data/lib/pubid/iso/identifiers/guide.rb +0 -1
  287. data/lib/pubid/iso/identifiers/international_standard.rb +4 -4
  288. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +4 -4
  289. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +10 -4
  290. data/lib/pubid/iso/identifiers/pas.rb +2 -2
  291. data/lib/pubid/iso/identifiers/recommendation.rb +2 -2
  292. data/lib/pubid/iso/identifiers/supplement.rb +11 -3
  293. data/lib/pubid/iso/identifiers/tc_document.rb +44 -15
  294. data/lib/pubid/iso/identifiers/technical_report.rb +4 -4
  295. data/lib/pubid/iso/identifiers/technical_specification.rb +2 -2
  296. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +2 -2
  297. data/lib/pubid/iso/identifiers.rb +0 -1
  298. data/lib/pubid/iso/normalizer.rb +89 -0
  299. data/lib/pubid/iso/parser.rb +26 -6
  300. data/lib/pubid/iso/single_identifier.rb +6 -3
  301. data/lib/pubid/iso/supplement_identifier.rb +15 -2
  302. data/lib/pubid/iso/urn_generator.rb +74 -176
  303. data/lib/pubid/iso/urn_parser.rb +28 -9
  304. data/lib/pubid/iso.rb +173 -2
  305. data/lib/pubid/itu/builder.rb +0 -12
  306. data/lib/pubid/itu/components/code.rb +8 -0
  307. data/lib/pubid/itu/components.rb +11 -0
  308. data/lib/pubid/itu/identifier.rb +6 -39
  309. data/lib/pubid/itu/identifiers/amendment.rb +0 -2
  310. data/lib/pubid/itu/identifiers/annex.rb +0 -2
  311. data/lib/pubid/itu/identifiers/base.rb +0 -6
  312. data/lib/pubid/itu/identifiers/combined_identifier.rb +0 -2
  313. data/lib/pubid/itu/identifiers/corrigendum.rb +0 -2
  314. data/lib/pubid/itu/identifiers/recommendation.rb +0 -2
  315. data/lib/pubid/itu/identifiers/special_publication.rb +0 -2
  316. data/lib/pubid/itu/identifiers/supplement.rb +0 -2
  317. data/lib/pubid/itu/urn_parser.rb +23 -0
  318. data/lib/pubid/itu.rb +42 -1
  319. data/lib/pubid/jcgm/builder.rb +16 -8
  320. data/lib/pubid/jcgm/identifiers/amendment.rb +2 -7
  321. data/lib/pubid/jcgm/identifiers/gum_guide.rb +2 -10
  322. data/lib/pubid/jcgm/renderer.rb +68 -0
  323. data/lib/pubid/jcgm/single_identifier.rb +1 -5
  324. data/lib/pubid/jcgm/urn_generator.rb +4 -6
  325. data/lib/pubid/jcgm/urn_parser.rb +23 -0
  326. data/lib/pubid/jcgm.rb +43 -2
  327. data/lib/pubid/jis/builder.rb +44 -52
  328. data/lib/pubid/jis/identifier.rb +132 -3
  329. data/lib/pubid/jis/identifiers/amendment.rb +1 -1
  330. data/lib/pubid/jis/identifiers/corrigendum.rb +16 -0
  331. data/lib/pubid/jis/identifiers/standard.rb +2 -1
  332. data/lib/pubid/jis/identifiers/technical_report.rb +2 -1
  333. data/lib/pubid/jis/identifiers/technical_specification.rb +2 -1
  334. data/lib/pubid/jis/identifiers.rb +1 -1
  335. data/lib/pubid/jis/parser.rb +31 -5
  336. data/lib/pubid/jis/renderer.rb +69 -0
  337. data/lib/pubid/jis/single_identifier.rb +6 -12
  338. data/lib/pubid/jis/supplement_identifier.rb +17 -14
  339. data/lib/pubid/jis/urn_parser.rb +23 -0
  340. data/lib/pubid/jis.rb +42 -2
  341. data/lib/pubid/nist/builder.rb +122 -1761
  342. data/lib/pubid/nist/caster.rb +1272 -0
  343. data/lib/pubid/nist/circular_supplement_builder.rb +291 -0
  344. data/lib/pubid/nist/components/code.rb +9 -20
  345. data/lib/pubid/nist/components/edition.rb +16 -0
  346. data/lib/pubid/nist/components/supplement.rb +88 -21
  347. data/lib/pubid/nist/components.rb +0 -1
  348. data/lib/pubid/nist/identifier.rb +25 -0
  349. data/lib/pubid/nist/identifiers/base.rb +206 -64
  350. data/lib/pubid/nist/identifiers/circular.rb +7 -2
  351. data/lib/pubid/nist/identifiers/circular_supplement.rb +3 -2
  352. data/lib/pubid/nist/identifiers/commercial_standard.rb +2 -1
  353. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +6 -4
  354. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +10 -3
  355. data/lib/pubid/nist/identifiers/crpl_report.rb +8 -11
  356. data/lib/pubid/nist/identifiers/dated_document.rb +49 -0
  357. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +17 -16
  358. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +2 -1
  359. data/lib/pubid/nist/identifiers/handbook.rb +2 -1
  360. data/lib/pubid/nist/identifiers/internal_report.rb +2 -1
  361. data/lib/pubid/nist/identifiers/letter_circular.rb +2 -1
  362. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +5 -4
  363. data/lib/pubid/nist/identifiers/monograph.rb +7 -3
  364. data/lib/pubid/nist/identifiers/report.rb +4 -3
  365. data/lib/pubid/nist/identifiers/special_publication.rb +2 -1
  366. data/lib/pubid/nist/identifiers/technical_note.rb +3 -2
  367. data/lib/pubid/nist/identifiers.rb +1 -0
  368. data/lib/pubid/nist/parser.rb +67 -424
  369. data/lib/pubid/nist/parser_output_normalizer.rb +233 -0
  370. data/lib/pubid/nist/preprocessor.rb +416 -0
  371. data/lib/pubid/nist/renderer.rb +43 -0
  372. data/lib/pubid/nist/router.rb +148 -0
  373. data/lib/pubid/nist/series/base.rb +58 -0
  374. data/lib/pubid/nist/series/crpl.rb +13 -0
  375. data/lib/pubid/nist/series/fips.rb +14 -0
  376. data/lib/pubid/nist/series/ir.rb +60 -0
  377. data/lib/pubid/nist/series/letter_preserving.rb +15 -0
  378. data/lib/pubid/nist/series/mono.rb +19 -0
  379. data/lib/pubid/nist/series/ncstar.rb +20 -0
  380. data/lib/pubid/nist/series.rb +49 -0
  381. data/lib/pubid/nist/supplement_identifier.rb +11 -25
  382. data/lib/pubid/nist/urn_generator.rb +14 -8
  383. data/lib/pubid/nist/urn_parser.rb +67 -0
  384. data/lib/pubid/nist.rb +83 -4
  385. data/lib/pubid/oiml/components/code.rb +10 -0
  386. data/lib/pubid/oiml/identifiers/annex.rb +3 -45
  387. data/lib/pubid/oiml/identifiers/base.rb +2 -17
  388. data/lib/pubid/oiml/renderer.rb +161 -0
  389. data/lib/pubid/oiml/single_identifier.rb +6 -45
  390. data/lib/pubid/oiml/supplement_identifier.rb +4 -19
  391. data/lib/pubid/oiml/urn_generator.rb +0 -8
  392. data/lib/pubid/oiml/urn_parser.rb +22 -0
  393. data/lib/pubid/oiml.rb +42 -1
  394. data/lib/pubid/plateau/identifier.rb +23 -0
  395. data/lib/pubid/plateau/identifiers/handbook.rb +1 -3
  396. data/lib/pubid/plateau/identifiers/technical_report.rb +1 -1
  397. data/lib/pubid/plateau/renderer.rb +51 -0
  398. data/lib/pubid/plateau/supplement_identifier.rb +1 -1
  399. data/lib/pubid/plateau/urn_parser.rb +43 -0
  400. data/lib/pubid/plateau.rb +44 -1
  401. data/lib/pubid/renderers/base.rb +34 -0
  402. data/lib/pubid/renderers/directives_renderer.rb +27 -14
  403. data/lib/pubid/renderers/guide_renderer.rb +7 -1
  404. data/lib/pubid/renderers/human_readable.rb +31 -8
  405. data/lib/pubid/renderers/iwa_renderer.rb +5 -1
  406. data/lib/pubid/renderers/supplement_renderer.rb +4 -1
  407. data/lib/pubid/rendering/context.rb +33 -21
  408. data/lib/pubid/rendering.rb +0 -3
  409. data/lib/pubid/sae/components/date.rb +8 -0
  410. data/lib/pubid/sae/components/type.rb +5 -1
  411. data/lib/pubid/sae/identifiers/base.rb +2 -16
  412. data/lib/pubid/sae/renderer.rb +36 -0
  413. data/lib/pubid/sae/urn_generator.rb +2 -10
  414. data/lib/pubid/sae/urn_parser.rb +36 -0
  415. data/lib/pubid/sae.rb +42 -1
  416. data/lib/pubid/urn_generator/base.rb +12 -12
  417. data/lib/pubid/urn_parser/base.rb +81 -0
  418. data/lib/pubid/urn_parser/errors.rb +9 -0
  419. data/lib/pubid/urn_parser.rb +14 -0
  420. data/lib/pubid/version.rb +1 -1
  421. data/lib/pubid.rb +29 -7
  422. data/lib/tasks/website-data.json +1940 -1882
  423. metadata +77 -43
  424. data/lib/pubid/amca/scheme.rb +0 -16
  425. data/lib/pubid/ansi/scheme.rb +0 -15
  426. data/lib/pubid/api/scheme.rb +0 -66
  427. data/lib/pubid/ashrae/scheme.rb +0 -53
  428. data/lib/pubid/asme/scheme.rb +0 -37
  429. data/lib/pubid/astm/scheme.rb +0 -55
  430. data/lib/pubid/bsi/identifiers/base.rb +0 -11
  431. data/lib/pubid/bsi/scheme.rb +0 -243
  432. data/lib/pubid/ccsds/scheme.rb +0 -57
  433. data/lib/pubid/cen_cenelec/scheme.rb +0 -164
  434. data/lib/pubid/cie/scheme.rb +0 -64
  435. data/lib/pubid/csa/scheme.rb +0 -44
  436. data/lib/pubid/etsi/scheme.rb +0 -42
  437. data/lib/pubid/export/data_class_exporter.rb +0 -59
  438. data/lib/pubid/export/ieee_exporter.rb +0 -78
  439. data/lib/pubid/export/itu_exporter.rb +0 -66
  440. data/lib/pubid/export/nist_exporter.rb +0 -64
  441. data/lib/pubid/export/registry_exporter.rb +0 -90
  442. data/lib/pubid/export/scheme_exporter.rb +0 -70
  443. data/lib/pubid/identifier_registry.rb +0 -198
  444. data/lib/pubid/idf/scheme.rb +0 -61
  445. data/lib/pubid/iec/scheme.rb +0 -71
  446. data/lib/pubid/ieee/scheme.rb +0 -90
  447. data/lib/pubid/iho/scheme.rb +0 -29
  448. data/lib/pubid/iso/identifiers/base.rb +0 -115
  449. data/lib/pubid/iso/scheme.rb +0 -187
  450. data/lib/pubid/itu/scheme.rb +0 -174
  451. data/lib/pubid/jcgm/scheme.rb +0 -60
  452. data/lib/pubid/jis/components/code.rb +0 -59
  453. data/lib/pubid/jis/identifiers/base.rb +0 -72
  454. data/lib/pubid/jis/scheme.rb +0 -49
  455. data/lib/pubid/nist/components/publisher.rb +0 -24
  456. data/lib/pubid/nist/scheme.rb +0 -199
  457. data/lib/pubid/oiml/scheme.rb +0 -46
  458. data/lib/pubid/plateau/scheme.rb +0 -45
  459. data/lib/pubid/rendering/base.rb +0 -73
  460. data/lib/pubid/rendering/common.rb +0 -211
  461. data/lib/pubid/rendering/format.rb +0 -25
  462. data/lib/pubid/sae/scheme.rb +0 -47
  463. data/lib/pubid/scheme.rb +0 -207
data/lib/pubid/etsi.rb CHANGED
@@ -9,12 +9,53 @@ module Pubid
9
9
  autoload :Identifier, "#{__dir__}/etsi/identifier"
10
10
  autoload :Identifiers, "#{__dir__}/etsi/identifiers"
11
11
  autoload :Parser, "#{__dir__}/etsi/parser"
12
- autoload :Scheme, "#{__dir__}/etsi/scheme"
12
+ autoload :Renderer, "#{__dir__}/etsi/renderer"
13
13
  autoload :UrnGenerator, "#{__dir__}/etsi/urn_generator"
14
+ autoload :UrnParser, "#{__dir__}/etsi/urn_parser"
14
15
 
15
16
  def self.parse(identifier)
16
17
  Identifier.parse(identifier)
17
18
  end
19
+
20
+ # Per-flavor format registry: inherits global formats, overrides :human
21
+ Identifiers::Base.format_registry = FormatRegistry.new(parent: ::Pubid::Identifier.format_registry)
22
+ Identifiers::Base.format_registry.register(:human, renderer: Etsi::Renderer)
23
+
24
+ # Auto-discover all identifier types from the Identifiers namespace
25
+ # @return [Array<Class>] identifier classes (Pubid::Identifier subclasses)
26
+ def self.identifier_types
27
+ @identifier_types ||= Identifiers.constants
28
+ .filter_map { |c| begin; Identifiers.const_get(c); rescue NameError; nil; end }
29
+ .select { |c| c.is_a?(Class) && c < Pubid::Identifier }
30
+ .reject { |c| c.name&.split("::")&.last == "Base" }
31
+ end
32
+
33
+ # Build typed stage index from identifier types
34
+ # @return [Array<Pubid::Components::TypedStage>] all typed stages
35
+ def self.all_typed_stages
36
+ @all_typed_stages ||= identifier_types.flat_map do |klass|
37
+ if klass.const_defined?(:TYPED_STAGES)
38
+ klass.const_get(:TYPED_STAGES)
39
+ else
40
+ []
41
+ end
42
+ end
43
+ end
44
+
45
+ # Lookup: type code -> identifier class
46
+ # @param code [String, Symbol] the type key to find
47
+ # @return [Class, nil] the matching identifier class
48
+ def self.locate_type(code)
49
+ identifier_types.find { |t| t.type[:key].to_s == code.to_s }
50
+ end
51
+
52
+ # Lookup: abbreviation -> typed stage
53
+ # @param abbr [String, Symbol] the abbreviation to find
54
+ # @return [Pubid::Components::TypedStage, nil] the matching typed stage
55
+ def self.locate_stage(abbr)
56
+ abbr_str = abbr.to_s.upcase
57
+ all_typed_stages.find { |s| s.abbr.any? { |a| a.to_s.upcase == abbr_str } }
58
+ end
18
59
  end
19
60
  end
20
61
 
@@ -2,65 +2,23 @@
2
2
 
3
3
  module Pubid
4
4
  module Export
5
- # Top-level orchestrator. Iterates flavors, selects the appropriate
6
- # extraction strategy, and produces the combined result.
5
+ # Top-level orchestrator. Iterates flavors and delegates to FlavorExporter.
7
6
  #
8
- # Open/Closed: Adding a new flavor only requires registering it in
9
- # FLAVOR_STRATEGIES; no existing code changes.
7
+ # Open/Closed: Adding a new flavor only requires adding it to FLAVORS;
8
+ # no existing code changes.
10
9
  class Exporter
11
10
  FLAVORS = %i[
12
11
  iso iec ieee nist bsi itu cen_cenelec etsi ansi astm ashrae asme
13
12
  ccsds cie csa jis jcgm oiml idf api amca plateau sae
14
13
  ].freeze
15
14
 
16
- # Maps each flavor to its extraction strategy class.
17
- # When a flavor follows a new pattern, add a new strategy class here.
18
- FLAVOR_STRATEGIES = {
19
- iso: :scheme,
20
- iec: :scheme,
21
- ieee: :ieee,
22
- nist: :nist,
23
- bsi: :registry,
24
- itu: :itu,
25
- cen_cenelec: :registry,
26
- etsi: :data_class,
27
- ansi: :scheme,
28
- astm: :scheme,
29
- ashrae: :scheme,
30
- asme: :scheme,
31
- ccsds: :scheme,
32
- cie: :scheme,
33
- csa: :scheme,
34
- jis: :scheme,
35
- jcgm: :scheme,
36
- oiml: :scheme,
37
- idf: :scheme,
38
- api: :scheme,
39
- amca: :scheme,
40
- plateau: :data_class,
41
- sae: :scheme,
42
- }.freeze
43
-
44
- STRATEGY_CLASSES = {
45
- scheme: SchemeExporter,
46
- registry: RegistryExporter,
47
- data_class: DataClassExporter,
48
- nist: NistExporter,
49
- ieee: IeeeExporter,
50
- itu: ItuExporter,
51
- }.freeze
52
-
53
15
  # Export all flavors to a hash suitable for JSON serialization.
54
16
  # @return [Hash{String => Hash}]
55
17
  def self.export_all
56
18
  require "pubid"
57
19
 
58
20
  FLAVORS.each_with_object({}) do |flavor, result|
59
- strategy_name = FLAVOR_STRATEGIES[flavor]
60
- strategy_class = STRATEGY_CLASSES[strategy_name]
61
- next unless strategy_class
62
-
63
- exporter = strategy_class.new(flavor)
21
+ exporter = FlavorExporter.new(flavor)
64
22
  flavor_result = exporter.export
65
23
  next unless flavor_result
66
24
 
@@ -4,11 +4,14 @@ require "set"
4
4
 
5
5
  module Pubid
6
6
  module Export
7
- # Abstract base class for per-flavor metadata extraction.
8
- # Subclasses implement strategy for different Scheme patterns.
7
+ # Unified metadata extractor for all flavors.
9
8
  #
10
- # Open/Closed: New flavors add a subclass; no existing code changes.
11
- # Single Responsibility: Each subclass extracts data for one Scheme pattern.
9
+ # Uses the self-describing type interface (identifier_types, all_typed_stages,
10
+ # locate_type, locate_stage) on each flavor module. No Scheme dependency (Scheme class removed).
11
+ #
12
+ # Open/Closed: Adding a new flavor requires only adding it to Exporter::FLAVORS.
13
+ # Single Responsibility: Extracts metadata from flavor modules into value objects.
14
+ # Single Source of Truth: Each identifier class IS the type definition.
12
15
  class FlavorExporter
13
16
  attr_reader :flavor
14
17
 
@@ -22,300 +25,106 @@ module Pubid
22
25
  @flavor = flavor
23
26
  end
24
27
 
25
- # Subclasses must override
26
28
  def export
27
- raise NotImplementedError
28
- end
29
-
30
- protected
29
+ mod = flavor_module
30
+ return nil unless mod
31
31
 
32
- def scheme_module
33
- # const_get doesn't trigger autoload; reference the constant directly
34
- @scheme_module ||= case flavor.to_s
35
- when "iso" then Pubid::Iso
36
- when "iec" then Pubid::Iec
37
- when "ieee" then Pubid::Ieee
38
- when "nist" then Pubid::Nist
39
- when "bsi" then Pubid::Bsi
40
- when "itu" then Pubid::Itu
41
- when "cen_cenelec" then Pubid::CenCenelec
42
- when "etsi" then Pubid::Etsi
43
- when "ansi" then Pubid::Ansi
44
- when "astm" then Pubid::Astm
45
- when "ashrae" then Pubid::Ashrae
46
- when "asme" then Pubid::Asme
47
- when "ccsds" then Pubid::Ccsds
48
- when "cie" then Pubid::Cie
49
- when "csa" then Pubid::Csa
50
- when "jis" then Pubid::Jis
51
- when "jcgm" then Pubid::Jcgm
52
- when "oiml" then Pubid::Oiml
53
- when "idf" then Pubid::Idf
54
- when "api" then Pubid::Api
55
- when "amca" then Pubid::Amca
56
- when "plateau" then Pubid::Plateau
57
- when "sae" then Pubid::Sae
58
- end
59
- end
60
-
61
- def scheme_class
62
- @scheme_class ||= begin
63
- mod = scheme_module
64
- mod&.const_get(:Scheme)
65
- rescue NameError
66
- nil
67
- end
68
- end
32
+ klasses = resolve_identifier_classes(mod)
33
+ return nil if klasses.empty?
69
34
 
70
- def identifier_classes
71
- resolve_identifier_classes
72
- end
35
+ fixture_data = fixture_examples
36
+ seen_keys = Set.new
73
37
 
74
- def resolve_identifier_classes
75
- scheme = scheme_class
76
- scheme_klasses = []
38
+ identifier_types = klasses.filter_map do |klass|
39
+ info = extract_type_info(klass)
40
+ next if seen_keys.include?(info[:key])
77
41
 
78
- # Pattern 1: Class methods (ISO, IEC, ASTM, etc.)
79
- begin
80
- scheme_klasses = scheme.identifiers if scheme
81
- rescue NoMethodError
82
- scheme_klasses = []
83
- end
42
+ seen_keys << info[:key]
84
43
 
85
- # Pattern 2: Instance-based (AMCA, BSI)
86
- if scheme_klasses.empty? && scheme
87
- instance = begin
88
- scheme.new
89
- rescue NoMethodError
90
- nil
91
- end
92
- if instance
93
- ids = begin
94
- instance.identifiers
95
- rescue NoMethodError
96
- nil
97
- end
98
- scheme_klasses = ids if ids && !ids.empty?
99
- end
100
- end
44
+ stages = extract_typed_stages(klass)
45
+ examples = match_examples(fixture_data, info[:key]&.to_s, klass)
101
46
 
102
- # Build set of website keys from Scheme classes to avoid duplicates
103
- known_website_keys = Set.new
104
- scheme_klasses.each do |klass|
105
- info = extract_type_info(klass)
106
- known_website_keys << info[:key].to_s if info[:key]
47
+ IdentifierTypeResult.new(
48
+ key: info[:key],
49
+ title: info[:title],
50
+ short: info[:short],
51
+ abbr: info[:abbr],
52
+ typed_stages: stages,
53
+ examples: examples,
54
+ )
107
55
  end
108
56
 
109
- # Supplement with any typed classes in the Identifiers module
110
- # that weren't returned by Scheme (e.g., supplements, fragments)
111
- additional = discover_additional_typed_classes(scheme_klasses,
112
- known_website_keys)
113
- scheme_klasses + additional
57
+ FlavorResult.new(
58
+ flavor: flavor,
59
+ identifier_types: identifier_types,
60
+ wrapper_types: extract_wrapper_types,
61
+ attributes: extract_attributes(klasses.first),
62
+ )
114
63
  end
115
64
 
116
- # Classes to skip when discovering additional identifier types
117
- SKIP_CLASSES = %w[Base].freeze
118
-
119
- def discover_additional_typed_classes(known_classes,
120
- known_website_keys = Set.new)
121
- mod = scheme_module
122
- return [] unless mod
123
-
124
- idents_mod = mod.const_get(:Identifiers)
125
- known_set = Set.new(known_classes)
126
-
127
- idents_mod.constants.filter_map do |c|
128
- klass = idents_mod.const_get(c)
129
- rescue NameError
130
- next
131
- else
132
- next unless klass.is_a?(Class)
133
- next if known_set.include?(klass)
134
- next if klass <= Exception
135
- next if SKIP_CLASSES.include?(klass.name&.split("::")&.last)
65
+ protected
136
66
 
137
- # Check if this class produces a duplicate website key
138
- info = extract_type_info(klass)
139
- wkey = info[:key]&.to_s
140
- next if wkey && known_website_keys.include?(wkey)
67
+ # Resolve identifier classes from the flavor module.
68
+ # Primary: use the module's self-describing identifier_types method.
69
+ # Fallback: scan the Identifiers namespace directly for Pubid::Identifier
70
+ # subclasses (handles ETSI, ITU, and other non-standard patterns).
71
+ def resolve_identifier_classes(mod)
72
+ klasses = mod.identifier_types
73
+ return klasses if klasses && !klasses.empty?
141
74
 
142
- known_website_keys << wkey if wkey
143
- klass
144
- end
75
+ discover_from_namespace(mod)
145
76
  end
146
77
 
147
- # Explicit overrides mapping (flavor, library_key) website key
148
- # for cases where derived key doesn't match the website convention.
149
- WEBSITE_KEY_OVERRIDES = {
150
- # ISO
151
- [%i[iso], :is] => :international_standard,
152
- [%i[iso], :tr] => :technical_report,
153
- [%i[iso], :ts] => :technical_specification,
154
- [%i[iso], :pas] => :publicly_available_specification,
155
- [%i[iso], :tta] => :technology_trends_assessments,
156
- [%i[iso], :iwa] => :international_workshop_agreement,
157
- [%i[iso], :isp] => :international_standardized_profile,
158
- [%i[iso], :rec] => :recommendation,
159
- [%i[iso], :dir] => :directives,
160
- [%i[iso], :"dir-sup"] => :directives_supplement,
161
- [%i[iso], :amd] => :amendment,
162
- [%i[iso], :cor] => :corrigendum,
163
- [%i[iso], :suppl] => :supplement,
164
- [%i[iso], :ext] => :extract,
165
- [%i[iso], :add] => :addendum,
166
- [%i[iso], :tc] => :tc_document,
167
- # IEC
168
- [%i[iec], :is] => :international_standard,
169
- [%i[iec], :tr] => :technical_report,
170
- [%i[iec], :ts] => :technical_specification,
171
- [%i[iec], :pas] => :publicly_available_specification,
172
- [%i[iec], :trf] => :test_report_form,
173
- [%i[iec], :ish] => :interpretation_sheet,
174
- [%i[iec], :srd] => :systems_reference_document,
175
- [%i[iec], :wd] => :working_document,
176
- [%i[iec], :frag] => :fragment_identifier,
177
- [%i[iec], :amd] => :amendment,
178
- [%i[iec], :cor] => :corrigendum,
179
- [%i[iec], :cs] => :component_specification,
180
- [%i[iec], :od] => :operational_document,
181
- [%i[iec], :sttr] => :societal_technology_trend_report,
182
- [%i[iec], :wp] => :white_paper,
183
- # IEEE
184
- [%i[ieee], :std] => :standard,
185
- # NIST
186
- [%i[nist], :sp] => :special_publication,
187
- [%i[nist], :fips] => :federal_information_processing_standards,
188
- [%i[nist], :ir] => :interagency_report,
189
- [%i[nist], :hb] => :handbook,
190
- [%i[nist], :tn] => :technical_note,
191
- [%i[nist], :circ] => :circular,
192
- [%i[nist], :circ_supp] => :circular_supplement,
193
- [%i[nist], :crpl] => :crpl_report,
194
- [%i[nist], :rpt] => :report,
195
- [%i[nist], :mono] => :monograph,
196
- [%i[nist], :mp] => :miscellaneous_publication,
197
- [%i[nist], :gcr] => :grant_contractor_report,
198
- [%i[nist], :lc] => :letter_circular,
199
- [%i[nist], :cs] => :commercial_standard,
200
- [%i[nist], :cse] => :commercial_standard_emergency,
201
- [%i[nist], :csm] => :commercial_standards_monthly,
202
- # BSI — adopted types share keys with base types, need unique mappings
203
- [%i[bsi], :bs] => :british_standard,
204
- [%i[bsi], :pd] => :published_document,
205
- [%i[bsi], :pas] => :publicly_available_specification,
206
- [%i[bsi], :na] => :national_annex,
207
- [%i[bsi], :dd] => :draft_document,
208
- [%i[bsi], :ep] => :electronic_book,
209
- [%i[bsi], :ts] => :technical_specification,
210
- [%i[bsi], :handbook] => :handbook,
211
- [%i[bsi], :aerospace] => :aerospace_standard,
212
- # CEN-CENELEC
213
- [%i[cen_cenelec], :en] => :european_norm,
214
- [%i[cen_cenelec], :ts] => :technical_specification,
215
- [%i[cen_cenelec], :tr] => :technical_report,
216
- [%i[cen_cenelec], :cwa] => :cen_workshop_agreement,
217
- [%i[cen_cenelec], :hd] => :harmonization_document,
218
- [%i[cen_cenelec], :es] => :european_specification,
219
- [%i[cen_cenelec], :cr] => :cen_report,
220
- [%i[cen_cenelec], :env] => :european_prestandard,
221
- # IDF
222
- [%i[idf], :is] => :international_standard,
223
- [%i[idf], :rm] => :reviewed_method,
224
- [%i[idf], :amd] => :amendment,
225
- [%i[idf], :cor] => :corrigendum,
226
- # CCSDS
227
- [%i[ccsds], :base] => :base,
228
- [%i[ccsds], :cor] => :corrigendum,
229
- # JIS
230
- [%i[jis], :jis] => :japanese_industrial_standard,
231
- [%i[jis], :tr] => :technical_report,
232
- [%i[jis], :ts] => :technical_specification,
233
- # SAE
234
- [%i[sae], :base] => :standard,
235
- # ANSI
236
- [%i[ansi], :ans] => :american_national_standard,
237
- }.freeze
78
+ # Scan Identifiers namespace for all Pubid::Identifier subclasses,
79
+ # excluding structural base classes.
80
+ def discover_from_namespace(mod)
81
+ return [] unless mod.const_defined?(:Identifiers)
238
82
 
239
- # Per-class overrides keyed by class name (for classes that share type keys)
240
- CLASS_KEY_OVERRIDES = {
241
- "Pubid::Bsi::Identifiers::AdoptedEuropeanNorm" => "adopted_european_norm",
242
- "Pubid::Bsi::Identifiers::AdoptedInternationalStandard" => "adopted_international_standard",
243
- "Pubid::CenCenelec::Identifiers::AdoptedEuropeanNorm" => "adopted_european_norm",
244
- "Pubid::Ansi::Identifiers::Standard" => "standard",
245
- "Pubid::Ansi::Identifiers::AmericanNationalStandard" => "american_national_standard",
246
- "Pubid::Jis::Identifiers::Standard" => "standard",
247
- "Pubid::Ieee::Identifiers::Nesc::Standard" => "nesc",
248
- "Pubid::Ieee::Identifiers::Nesc::Draft" => "nesc",
249
- "Pubid::Ieee::Identifiers::Nesc::Handbook" => "nesc",
250
- "Pubid::Ieee::Identifiers::Nesc::Redline" => "nesc",
251
- }.freeze
83
+ idents_mod = mod.const_get(:Identifiers)
84
+ collect_identifier_classes(idents_mod)
85
+ end
252
86
 
253
- def extract_type_info(klass)
254
- # Per-class override takes highest priority
255
- class_key = CLASS_KEY_OVERRIDES[klass.name]
256
- if class_key
257
- type_info = begin
258
- klass.type
259
- rescue NoMethodError, NotImplementedError
260
- nil
261
- end
262
- metadata = begin
263
- klass.metadata
264
- rescue NoMethodError
265
- nil
87
+ # Recursively collect all Pubid::Identifier subclasses from a module,
88
+ # descending into submodules (e.g., IEEE's Nesc namespace).
89
+ def collect_identifier_classes(mod)
90
+ result = []
91
+ mod.constants.each do |c|
92
+ const = begin; mod.const_get(c); rescue NameError; next; end
93
+ if const.is_a?(Module) && !const.is_a?(Class)
94
+ result.concat(collect_identifier_classes(const))
95
+ elsif const.is_a?(Class) && const < Pubid::Identifier
96
+ result << const
266
97
  end
267
- return {
268
- key: class_key,
269
- title: type_info&.dig(:title) || metadata&.title || class_key.tr(
270
- "_", " "
271
- ).capitalize,
272
- short: type_info&.dig(:short) || metadata&.short,
273
- abbr: metadata&.abbr || [],
274
- }
275
98
  end
99
+ result
100
+ end
276
101
 
277
- type_info = begin
278
- klass.type
279
- rescue NoMethodError, NotImplementedError
280
- nil
281
- end
282
- metadata = begin
283
- klass.metadata
284
- rescue NoMethodError
102
+ # Map flavor symbol to the flavor module.
103
+ def flavor_module
104
+ @flavor_module ||= begin
105
+ mod_name = flavor.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }
106
+ Pubid.const_get(mod_name)
107
+ rescue NameError
285
108
  nil
286
109
  end
110
+ end
111
+
112
+ def extract_type_info(klass)
113
+ type_info = safe_type(klass)
114
+ metadata = safe_metadata(klass)
287
115
 
288
- lib_key = type_info&.dig(:key)
116
+ key = type_info&.dig(:web) || type_info&.dig(:key)
289
117
  title = type_info&.dig(:title) || metadata&.title
290
118
  short = type_info&.dig(:short) || metadata&.short
291
119
  abbr = metadata&.abbr || []
292
120
 
293
- # Derive from class name when def self.type is missing
294
- unless lib_key
121
+ unless key
295
122
  class_name = klass.name&.split("::")&.last
296
- lib_key = class_name&.gsub(/([A-Z])/, '_\1')&.downcase&.sub(/^_/,
297
- "")&.to_sym
123
+ key = class_name&.gsub(/([A-Z])/, '_\1')&.downcase&.sub(/^_/, "")
298
124
  title ||= class_name&.gsub(/([A-Z])/, ' \1')&.strip
299
125
  end
300
126
 
301
- # Map library key to website-compatible key
302
- website_key = resolve_website_key(lib_key)
303
-
304
- {
305
- key: website_key,
306
- title: title,
307
- short: short,
308
- abbr: abbr,
309
- }
310
- end
311
-
312
- def resolve_website_key(lib_key)
313
- key_str = lib_key.to_s
314
- WEBSITE_KEY_OVERRIDES.each do |(flavors, from_key), to_key|
315
- next unless flavors.include?(flavor)
316
- return to_key.to_s if from_key.to_s == key_str
317
- end
318
- key_str
127
+ { key: key&.to_s, title: title, short: short, abbr: abbr }
319
128
  end
320
129
 
321
130
  def extract_typed_stages(klass)
@@ -326,14 +135,10 @@ known_website_keys = Set.new)
326
135
  []
327
136
  end
328
137
 
329
- # Map flavor keys to fixture directory names when they differ
330
- FIXTURE_DIR_ALIASES = {}.freeze
331
-
138
+ # Fixture example extraction
332
139
  def fixture_examples
333
- # __dir__ = lib/pubid/export → go up 3 levels to gem root, then spec/fixtures
334
140
  gem_root = File.expand_path("../../..", __dir__)
335
- dir_name = FIXTURE_DIR_ALIASES[flavor] || flavor.to_s
336
- base = File.join(gem_root, "spec", "fixtures", dir_name, "identifiers",
141
+ base = File.join(gem_root, "spec", "fixtures", flavor.to_s, "identifiers",
337
142
  "pass")
338
143
  return {} unless Dir.exist?(base)
339
144
 
@@ -351,10 +156,8 @@ known_website_keys = Set.new)
351
156
  File.readlines(path, chomp: true).each do |line|
352
157
  next if line.start_with?("#") || line.strip.empty?
353
158
 
354
- # Format: "!Type input!expected" or just "input"
355
159
  if line.start_with?("!")
356
160
  parts = line.split("!")
357
- # ["", "Type", "input", "expected"] or ["", "Type", "input"]
358
161
  input = parts[2]&.strip
359
162
  identifiers << input if input && !input.empty?
360
163
  else
@@ -364,8 +167,24 @@ known_website_keys = Set.new)
364
167
  identifiers.uniq.first(10)
365
168
  end
366
169
 
367
- def map_fixture_key_to_type_key(fixture_key)
368
- fixture_key
170
+ def match_examples(fixture_data, type_key, klass)
171
+ return [] unless type_key
172
+
173
+ # Try direct type key match first
174
+ examples = fixture_data[type_key] ||
175
+ fixture_data[type_key.gsub("_", "")] ||
176
+ []
177
+
178
+ return examples if examples.any?
179
+
180
+ # Try class name match
181
+ class_name = klass.name&.split("::")&.last
182
+ snake_name = class_name&.gsub(/([A-Z])/, '_\1')&.downcase&.sub(/^_/, "")
183
+ if snake_name && fixture_data.key?(snake_name)
184
+ fixture_data[snake_name]
185
+ else
186
+ []
187
+ end
369
188
  end
370
189
 
371
190
  def extract_attributes(klass)
@@ -378,7 +197,7 @@ known_website_keys = Set.new)
378
197
  names = WRAPPER_CLASSES[flavor]
379
198
  return [] unless names
380
199
 
381
- mod = scheme_module
200
+ mod = flavor_module
382
201
  return [] unless mod
383
202
 
384
203
  identifiers_mod = mod.const_get(:Identifiers)
@@ -397,6 +216,20 @@ known_website_keys = Set.new)
397
216
  nil
398
217
  end
399
218
  end
219
+
220
+ private
221
+
222
+ def safe_type(klass)
223
+ klass.type
224
+ rescue NoMethodError, NotImplementedError
225
+ nil
226
+ end
227
+
228
+ def safe_metadata(klass)
229
+ klass.metadata
230
+ rescue NoMethodError
231
+ nil
232
+ end
400
233
  end
401
234
  end
402
235
  end
data/lib/pubid/export.rb CHANGED
@@ -6,12 +6,6 @@ module Pubid
6
6
  autoload :TypedStageResult, "#{__dir__}/export/result"
7
7
  autoload :FlavorResult, "#{__dir__}/export/result"
8
8
  autoload :FlavorExporter, "#{__dir__}/export/flavor_exporter"
9
- autoload :SchemeExporter, "#{__dir__}/export/scheme_exporter"
10
- autoload :IeeeExporter, "#{__dir__}/export/ieee_exporter"
11
- autoload :RegistryExporter, "#{__dir__}/export/registry_exporter"
12
- autoload :DataClassExporter, "#{__dir__}/export/data_class_exporter"
13
- autoload :NistExporter, "#{__dir__}/export/nist_exporter"
14
- autoload :ItuExporter, "#{__dir__}/export/itu_exporter"
15
9
  autoload :Auditor, "#{__dir__}/export/auditor"
16
10
  autoload :Exporter, "#{__dir__}/export/exporter"
17
11
  end