pubid 2.0.0.pre.alpha.9 → 2.0.0.pre.alpha.11

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 (432) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +33 -11
  3. data/conformance/pending.yaml +4 -0
  4. data/lib/pubid/adobe/identifier.rb +1 -3
  5. data/lib/pubid/adobe/parser.rb +10 -2
  6. data/lib/pubid/adobe.rb +1 -0
  7. data/lib/pubid/amca/builder.rb +2 -2
  8. data/lib/pubid/amca/identifiers/base.rb +49 -27
  9. data/lib/pubid/amca/identifiers/interpretation.rb +17 -9
  10. data/lib/pubid/amca/identifiers/publication.rb +13 -9
  11. data/lib/pubid/amca/identifiers/standard.rb +2 -0
  12. data/lib/pubid/amca/parser.rb +1 -1
  13. data/lib/pubid/amca/renderer.rb +4 -4
  14. data/lib/pubid/amca/urn_generator.rb +2 -2
  15. data/lib/pubid/amca.rb +2 -1
  16. data/lib/pubid/ansi/builder.rb +2 -2
  17. data/lib/pubid/ansi/identifier.rb +18 -0
  18. data/lib/pubid/ansi/parser.rb +1 -1
  19. data/lib/pubid/ansi/renderer.rb +2 -2
  20. data/lib/pubid/ansi.rb +5 -5
  21. data/lib/pubid/api/builder.rb +16 -2
  22. data/lib/pubid/api/identifier.rb +25 -4
  23. data/lib/pubid/api/identifiers/mpms.rb +10 -8
  24. data/lib/pubid/api/parser.rb +1 -1
  25. data/lib/pubid/api/renderer.rb +16 -7
  26. data/lib/pubid/api/single_identifier.rb +5 -12
  27. data/lib/pubid/api.rb +1 -0
  28. data/lib/pubid/ashrae/builder.rb +31 -10
  29. data/lib/pubid/ashrae/identifiers/addenda_package.rb +6 -0
  30. data/lib/pubid/ashrae/identifiers/addendum.rb +8 -0
  31. data/lib/pubid/ashrae/identifiers/base.rb +81 -5
  32. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +7 -0
  33. data/lib/pubid/ashrae/identifiers/errata.rb +9 -0
  34. data/lib/pubid/ashrae/identifiers/guideline.rb +3 -0
  35. data/lib/pubid/ashrae/identifiers/interpretation.rb +16 -0
  36. data/lib/pubid/ashrae/identifiers/standard.rb +3 -0
  37. data/lib/pubid/ashrae/parser.rb +23 -8
  38. data/lib/pubid/ashrae/renderer.rb +6 -6
  39. data/lib/pubid/ashrae/supplement_identifier.rb +17 -2
  40. data/lib/pubid/ashrae/urn_generator.rb +8 -2
  41. data/lib/pubid/ashrae.rb +7 -1
  42. data/lib/pubid/asme/builder.rb +11 -2
  43. data/lib/pubid/asme/identifier.rb +9 -0
  44. data/lib/pubid/asme/identifiers/standard.rb +86 -2
  45. data/lib/pubid/asme/parser.rb +1 -1
  46. data/lib/pubid/asme/renderer.rb +3 -3
  47. data/lib/pubid/asme/single_identifier.rb +8 -1
  48. data/lib/pubid/asme/urn_generator.rb +2 -2
  49. data/lib/pubid/asme.rb +1 -0
  50. data/lib/pubid/astm/builder.rb +10 -3
  51. data/lib/pubid/astm/identifier.rb +9 -0
  52. data/lib/pubid/astm/identifiers/adjunct.rb +16 -1
  53. data/lib/pubid/astm/identifiers/code_number.rb +81 -0
  54. data/lib/pubid/astm/identifiers/data_series.rb +2 -0
  55. data/lib/pubid/astm/identifiers/iso_dual_published.rb +16 -0
  56. data/lib/pubid/astm/identifiers/manual.rb +10 -0
  57. data/lib/pubid/astm/identifiers/monograph.rb +2 -0
  58. data/lib/pubid/astm/identifiers/research_report.rb +10 -0
  59. data/lib/pubid/astm/identifiers/standard.rb +10 -0
  60. data/lib/pubid/astm/identifiers/technical_report.rb +2 -0
  61. data/lib/pubid/astm/identifiers/work_in_progress.rb +2 -0
  62. data/lib/pubid/astm/identifiers.rb +1 -0
  63. data/lib/pubid/astm/parser.rb +1 -1
  64. data/lib/pubid/astm/renderer.rb +1 -1
  65. data/lib/pubid/astm/single_identifier.rb +31 -1
  66. data/lib/pubid/astm/urn_generator.rb +7 -5
  67. data/lib/pubid/astm.rb +1 -0
  68. data/lib/pubid/bipm/builder.rb +66 -10
  69. data/lib/pubid/bipm/identifier.rb +134 -9
  70. data/lib/pubid/bipm/identifiers/committee_document.rb +12 -0
  71. data/lib/pubid/bipm/identifiers/guide.rb +11 -0
  72. data/lib/pubid/bipm/identifiers/meeting.rb +12 -0
  73. data/lib/pubid/bipm/identifiers/mep.rb +12 -0
  74. data/lib/pubid/bipm/identifiers/metrologia_article.rb +24 -0
  75. data/lib/pubid/bipm/identifiers/si_brochure.rb +13 -0
  76. data/lib/pubid/bipm/parser.rb +65 -12
  77. data/lib/pubid/bipm/renderer.rb +8 -0
  78. data/lib/pubid/bipm/urn_parser.rb +11 -3
  79. data/lib/pubid/bipm.rb +7 -1
  80. data/lib/pubid/bsi/builder.rb +48 -38
  81. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +36 -7
  82. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +7 -6
  83. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +0 -1
  84. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +10 -0
  85. data/lib/pubid/bsi/identifiers/committee_document.rb +10 -1
  86. data/lib/pubid/bsi/identifiers/handbook.rb +0 -2
  87. data/lib/pubid/bsi/identifiers/practice_guide.rb +0 -1
  88. data/lib/pubid/bsi/identifiers/set.rb +11 -0
  89. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +10 -1
  90. data/lib/pubid/bsi/parser.rb +1 -1
  91. data/lib/pubid/bsi/renderer.rb +63 -51
  92. data/lib/pubid/bsi/single_identifier.rb +16 -7
  93. data/lib/pubid/bsi/urn_generator.rb +11 -2
  94. data/lib/pubid/bsi.rb +7 -1
  95. data/lib/pubid/builder/base.rb +18 -8
  96. data/lib/pubid/bundled_identifier.rb +16 -6
  97. data/lib/pubid/calconnect/identifier.rb +9 -5
  98. data/lib/pubid/calconnect/parser.rb +1 -1
  99. data/lib/pubid/calconnect.rb +7 -1
  100. data/lib/pubid/ccsds/identifier.rb +9 -2
  101. data/lib/pubid/ccsds/identifiers/base.rb +4 -2
  102. data/lib/pubid/ccsds/identifiers/corrigendum.rb +2 -2
  103. data/lib/pubid/ccsds/parser.rb +1 -1
  104. data/lib/pubid/ccsds/single_identifier.rb +2 -2
  105. data/lib/pubid/ccsds.rb +1 -0
  106. data/lib/pubid/cen_cenelec/builder.rb +101 -76
  107. data/lib/pubid/cen_cenelec/identifier.rb +115 -3
  108. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +27 -16
  109. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +46 -6
  110. data/lib/pubid/cen_cenelec/identifiers/base.rb +8 -9
  111. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +1 -1
  112. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +1 -1
  113. data/lib/pubid/cen_cenelec/identifiers/cenelec_harmonization_document.rb +1 -1
  114. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +29 -20
  115. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +47 -8
  116. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +27 -2
  117. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +1 -1
  118. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +15 -5
  119. data/lib/pubid/cen_cenelec/identifiers/guide.rb +1 -1
  120. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +1 -1
  121. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +1 -1
  122. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +1 -1
  123. data/lib/pubid/cen_cenelec/parser.rb +1 -1
  124. data/lib/pubid/cen_cenelec/renderer.rb +55 -60
  125. data/lib/pubid/cen_cenelec/single_identifier.rb +20 -2
  126. data/lib/pubid/cen_cenelec/urn_generator.rb +66 -44
  127. data/lib/pubid/cen_cenelec.rb +28 -10
  128. data/lib/pubid/cie/builder.rb +10 -0
  129. data/lib/pubid/cie/identifier.rb +6 -1
  130. data/lib/pubid/cie/identifiers/bundle.rb +4 -2
  131. data/lib/pubid/cie/identifiers/conference.rb +2 -2
  132. data/lib/pubid/cie/identifiers/corrigendum.rb +2 -2
  133. data/lib/pubid/cie/identifiers/dual_published.rb +2 -2
  134. data/lib/pubid/cie/identifiers/identical.rb +2 -2
  135. data/lib/pubid/cie/identifiers/joint_published.rb +2 -2
  136. data/lib/pubid/cie/identifiers/proceedings.rb +8 -6
  137. data/lib/pubid/cie/identifiers/standard.rb +22 -13
  138. data/lib/pubid/cie/identifiers/supplement.rb +2 -2
  139. data/lib/pubid/cie/identifiers/tutorial_bundle.rb +2 -2
  140. data/lib/pubid/cie/parser.rb +1 -1
  141. data/lib/pubid/cie.rb +7 -1
  142. data/lib/pubid/conformance/checks.rb +72 -0
  143. data/lib/pubid/conformance/corpus/case.rb +55 -0
  144. data/lib/pubid/conformance/corpus.rb +36 -0
  145. data/lib/pubid/conformance/generator.rb +212 -0
  146. data/lib/pubid/conformance/pending.rb +63 -0
  147. data/lib/pubid/conformance/runner.rb +153 -0
  148. data/lib/pubid/conformance.rb +55 -0
  149. data/lib/pubid/core.rb +2 -0
  150. data/lib/pubid/csa/builder.rb +47 -47
  151. data/lib/pubid/csa/composite_identifier.rb +14 -19
  152. data/lib/pubid/csa/identifier.rb +143 -81
  153. data/lib/pubid/csa/identifiers/bundled.rb +23 -13
  154. data/lib/pubid/csa/identifiers/canadian_adopted.rb +13 -13
  155. data/lib/pubid/csa/identifiers/cec.rb +44 -4
  156. data/lib/pubid/csa/identifiers/combined.rb +95 -73
  157. data/lib/pubid/csa/identifiers/csa_adopted.rb +4 -4
  158. data/lib/pubid/csa/identifiers/package.rb +2 -2
  159. data/lib/pubid/csa/parser.rb +6 -2
  160. data/lib/pubid/csa/renderer.rb +13 -5
  161. data/lib/pubid/csa/single_identifier.rb +93 -4
  162. data/lib/pubid/csa/urn_generator.rb +9 -2
  163. data/lib/pubid/csa/wrapper_identifier.rb +39 -23
  164. data/lib/pubid/csa.rb +7 -1
  165. data/lib/pubid/doi/identifier.rb +6 -3
  166. data/lib/pubid/doi/parser.rb +1 -1
  167. data/lib/pubid/doi.rb +1 -0
  168. data/lib/pubid/easc/identifier.rb +0 -2
  169. data/lib/pubid/easc/parser.rb +10 -2
  170. data/lib/pubid/easc.rb +1 -0
  171. data/lib/pubid/ecma/builder.rb +23 -9
  172. data/lib/pubid/ecma/identifier.rb +81 -10
  173. data/lib/pubid/ecma/parser.rb +39 -4
  174. data/lib/pubid/ecma/renderer.rb +29 -8
  175. data/lib/pubid/ecma/urn_generator.rb +34 -13
  176. data/lib/pubid/ecma/urn_parser.rb +30 -14
  177. data/lib/pubid/ecma.rb +1 -0
  178. data/lib/pubid/errors.rb +80 -0
  179. data/lib/pubid/etsi/builder.rb +6 -1
  180. data/lib/pubid/etsi/identifiers/base.rb +34 -20
  181. data/lib/pubid/etsi/identifiers/etsi_standard.rb +120 -41
  182. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +10 -0
  183. data/lib/pubid/etsi/parser.rb +1 -1
  184. data/lib/pubid/etsi.rb +1 -0
  185. data/lib/pubid/evs/builder.rb +26 -0
  186. data/lib/pubid/evs/identifier.rb +37 -0
  187. data/lib/pubid/evs/identifiers/national_adoption.rb +17 -0
  188. data/lib/pubid/evs/identifiers.rb +9 -0
  189. data/lib/pubid/evs/parser.rb +27 -0
  190. data/lib/pubid/evs/renderer.rb +30 -0
  191. data/lib/pubid/evs/urn_generator.rb +30 -0
  192. data/lib/pubid/evs/urn_parser.rb +80 -0
  193. data/lib/pubid/evs.rb +90 -0
  194. data/lib/pubid/export.rb +1 -0
  195. data/lib/pubid/format_detector.rb +1 -0
  196. data/lib/pubid/gb/identifier.rb +6 -3
  197. data/lib/pubid/gb/parser.rb +1 -1
  198. data/lib/pubid/gb.rb +1 -0
  199. data/lib/pubid/gost/builder.rb +46 -9
  200. data/lib/pubid/gost/identifier.rb +0 -2
  201. data/lib/pubid/gost/identifiers/foreign_reference.rb +1 -1
  202. data/lib/pubid/gost/parser.rb +10 -2
  203. data/lib/pubid/gost.rb +1 -0
  204. data/lib/pubid/iala/identifier.rb +9 -6
  205. data/lib/pubid/iala/parser.rb +10 -2
  206. data/lib/pubid/iala/urn_parser.rb +6 -2
  207. data/lib/pubid/iala.rb +1 -0
  208. data/lib/pubid/iana/builder.rb +3 -1
  209. data/lib/pubid/iana/identifier.rb +74 -6
  210. data/lib/pubid/iana/identifiers/registry.rb +36 -0
  211. data/lib/pubid/iana/parser.rb +1 -1
  212. data/lib/pubid/iana/renderer.rb +3 -0
  213. data/lib/pubid/iana/urn_generator.rb +5 -1
  214. data/lib/pubid/iana.rb +1 -0
  215. data/lib/pubid/identifier.rb +594 -10
  216. data/lib/pubid/identifier_metadata.rb +1 -0
  217. data/lib/pubid/idf/builder.rb +3 -3
  218. data/lib/pubid/idf/identifier.rb +18 -9
  219. data/lib/pubid/idf/parser.rb +1 -1
  220. data/lib/pubid/idf/renderer.rb +4 -4
  221. data/lib/pubid/idf/urn_generator.rb +1 -1
  222. data/lib/pubid/idf.rb +7 -1
  223. data/lib/pubid/iec/builder.rb +14 -7
  224. data/lib/pubid/iec/components.rb +0 -1
  225. data/lib/pubid/iec/identifier.rb +73 -83
  226. data/lib/pubid/iec/identifiers/amendment.rb +6 -2
  227. data/lib/pubid/iec/identifiers/component_specification.rb +0 -10
  228. data/lib/pubid/iec/identifiers/conformity_assessment.rb +0 -10
  229. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -2
  230. data/lib/pubid/iec/identifiers/fragment_identifier.rb +2 -4
  231. data/lib/pubid/iec/identifiers/guide.rb +0 -16
  232. data/lib/pubid/iec/identifiers/international_standard.rb +15 -2
  233. data/lib/pubid/iec/identifiers/operational_document.rb +0 -10
  234. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +0 -12
  235. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +0 -10
  236. data/lib/pubid/iec/identifiers/systems_reference_document.rb +0 -10
  237. data/lib/pubid/iec/identifiers/technical_report.rb +0 -17
  238. data/lib/pubid/iec/identifiers/technical_specification.rb +0 -17
  239. data/lib/pubid/iec/identifiers/technology_report.rb +0 -10
  240. data/lib/pubid/iec/identifiers/test_report_form.rb +0 -11
  241. data/lib/pubid/iec/identifiers/white_paper.rb +0 -10
  242. data/lib/pubid/iec/identifiers/working_document.rb +24 -10
  243. data/lib/pubid/iec/parser.rb +2 -18
  244. data/lib/pubid/iec/renderer.rb +13 -10
  245. data/lib/pubid/iec/single_identifier.rb +33 -10
  246. data/lib/pubid/iec/urn_generator.rb +227 -61
  247. data/lib/pubid/iec/urn_parser.rb +42 -4
  248. data/lib/pubid/iec.rb +1 -0
  249. data/lib/pubid/ieee/aiee/identifier.rb +2 -2
  250. data/lib/pubid/ieee/aiee/parser.rb +1 -1
  251. data/lib/pubid/ieee/builder.rb +45 -1
  252. data/lib/pubid/ieee/identifiers/adopted_standard.rb +32 -0
  253. data/lib/pubid/ieee/identifiers/base.rb +42 -5
  254. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +21 -0
  255. data/lib/pubid/ieee/identifiers/dual_published.rb +55 -0
  256. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +23 -0
  257. data/lib/pubid/ieee/identifiers/joint_development.rb +11 -7
  258. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +57 -5
  259. data/lib/pubid/ieee/identifiers/nesc/base.rb +2 -2
  260. data/lib/pubid/ieee/identifiers/nesc/draft.rb +2 -2
  261. data/lib/pubid/ieee/identifiers/nesc/handbook.rb +2 -2
  262. data/lib/pubid/ieee/identifiers/nesc/redline.rb +2 -2
  263. data/lib/pubid/ieee/identifiers/nesc/standard.rb +2 -2
  264. data/lib/pubid/ieee/ire/identifier.rb +2 -2
  265. data/lib/pubid/ieee/ire/parser.rb +1 -1
  266. data/lib/pubid/ieee/nesc/parser.rb +1 -1
  267. data/lib/pubid/ieee/parser.rb +1 -1
  268. data/lib/pubid/ieee/renderer.rb +5 -1
  269. data/lib/pubid/ieee/urn_generator.rb +32 -3
  270. data/lib/pubid/ieee.rb +7 -1
  271. data/lib/pubid/ieee_debug.rb +1 -0
  272. data/lib/pubid/ietf/builder.rb +24 -8
  273. data/lib/pubid/ietf/identifiers/base.rb +25 -28
  274. data/lib/pubid/ietf/identifiers/bcp.rb +11 -0
  275. data/lib/pubid/ietf/identifiers/fyi.rb +11 -0
  276. data/lib/pubid/ietf/identifiers/internet_draft.rb +18 -2
  277. data/lib/pubid/ietf/identifiers/rfc.rb +2 -0
  278. data/lib/pubid/ietf/identifiers/serialization.rb +51 -0
  279. data/lib/pubid/ietf/identifiers/std.rb +11 -0
  280. data/lib/pubid/ietf/identifiers.rb +1 -0
  281. data/lib/pubid/ietf/parser.rb +27 -9
  282. data/lib/pubid/ietf/renderer.rb +44 -6
  283. data/lib/pubid/ietf/urn_generator.rb +20 -6
  284. data/lib/pubid/ietf/urn_parser.rb +10 -2
  285. data/lib/pubid/ietf.rb +12 -2
  286. data/lib/pubid/iho/identifiers/base.rb +10 -3
  287. data/lib/pubid/iho/parser.rb +1 -1
  288. data/lib/pubid/iho.rb +1 -0
  289. data/lib/pubid/isbn/identifier.rb +25 -7
  290. data/lib/pubid/isbn/parser.rb +1 -1
  291. data/lib/pubid/isbn.rb +1 -0
  292. data/lib/pubid/iso/bundled_identifier.rb +5 -3
  293. data/lib/pubid/iso/combined_identifier.rb +5 -3
  294. data/lib/pubid/iso/identifier.rb +12 -7
  295. data/lib/pubid/iso/identifiers/directives_supplement.rb +4 -4
  296. data/lib/pubid/iso/parser.rb +1 -1
  297. data/lib/pubid/iso.rb +7 -1
  298. data/lib/pubid/itu/identifiers/addendum.rb +2 -2
  299. data/lib/pubid/itu/identifiers/amendment.rb +2 -2
  300. data/lib/pubid/itu/identifiers/base.rb +19 -5
  301. data/lib/pubid/itu/identifiers/corrigendum.rb +2 -2
  302. data/lib/pubid/itu/identifiers/errata.rb +2 -2
  303. data/lib/pubid/itu/identifiers/supplement.rb +2 -2
  304. data/lib/pubid/itu/parser.rb +1 -1
  305. data/lib/pubid/itu.rb +1 -0
  306. data/lib/pubid/jcgm/builder.rb +1 -1
  307. data/lib/pubid/jcgm/identifier.rb +10 -0
  308. data/lib/pubid/jcgm/identifiers/meeting.rb +1 -1
  309. data/lib/pubid/jcgm/parser.rb +10 -3
  310. data/lib/pubid/jcgm/renderer.rb +10 -3
  311. data/lib/pubid/jcgm/single_identifier.rb +24 -15
  312. data/lib/pubid/jcgm/urn_generator.rb +1 -1
  313. data/lib/pubid/jcgm/urn_parser.rb +156 -14
  314. data/lib/pubid/jcgm.rb +10 -0
  315. data/lib/pubid/jis/identifier.rb +10 -3
  316. data/lib/pubid/jis/parser.rb +1 -1
  317. data/lib/pubid/jis.rb +1 -0
  318. data/lib/pubid/nist/components/stage.rb +2 -2
  319. data/lib/pubid/nist/configuration.rb +6 -8
  320. data/lib/pubid/nist/identifiers/base.rb +12 -2
  321. data/lib/pubid/nist/identifiers/circular.rb +9 -2
  322. data/lib/pubid/nist/identifiers/circular_supplement.rb +14 -5
  323. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +7 -1
  324. data/lib/pubid/nist/identifiers/crpl_report.rb +7 -1
  325. data/lib/pubid/nist/identifiers/handbook.rb +9 -2
  326. data/lib/pubid/nist/identifiers/internal_report.rb +12 -5
  327. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +14 -6
  328. data/lib/pubid/nist/identifiers/monograph.rb +14 -7
  329. data/lib/pubid/nist/identifiers/report.rb +14 -6
  330. data/lib/pubid/nist/parser.rb +1 -1
  331. data/lib/pubid/nist/supplement_identifier.rb +16 -1
  332. data/lib/pubid/nist.rb +7 -1
  333. data/lib/pubid/oasis/builder.rb +12 -10
  334. data/lib/pubid/oasis/identifier.rb +89 -11
  335. data/lib/pubid/oasis/parser.rb +1 -1
  336. data/lib/pubid/oasis.rb +7 -1
  337. data/lib/pubid/ogc/identifier.rb +9 -5
  338. data/lib/pubid/ogc/parser.rb +1 -1
  339. data/lib/pubid/ogc.rb +1 -0
  340. data/lib/pubid/oiml/builder.rb +5 -1
  341. data/lib/pubid/oiml/identifiers/basic_publication.rb +2 -0
  342. data/lib/pubid/oiml/identifiers/bulletin.rb +36 -0
  343. data/lib/pubid/oiml/identifiers/code_number.rb +90 -0
  344. data/lib/pubid/oiml/identifiers/document.rb +2 -0
  345. data/lib/pubid/oiml/identifiers/expert_report.rb +2 -0
  346. data/lib/pubid/oiml/identifiers/guide.rb +2 -0
  347. data/lib/pubid/oiml/identifiers/recommendation.rb +2 -0
  348. data/lib/pubid/oiml/identifiers/seminar_report.rb +2 -0
  349. data/lib/pubid/oiml/identifiers/vocabulary.rb +2 -0
  350. data/lib/pubid/oiml/identifiers.rb +1 -0
  351. data/lib/pubid/oiml/parser.rb +1 -1
  352. data/lib/pubid/oiml/single_identifier.rb +26 -42
  353. data/lib/pubid/oiml/supplement_identifier.rb +27 -0
  354. data/lib/pubid/oiml.rb +7 -1
  355. data/lib/pubid/omg/builder.rb +1 -0
  356. data/lib/pubid/omg/identifier.rb +20 -3
  357. data/lib/pubid/omg/parser.rb +64 -11
  358. data/lib/pubid/omg/renderer.rb +13 -1
  359. data/lib/pubid/omg.rb +2 -1
  360. data/lib/pubid/parser/grammar.rb +74 -0
  361. data/lib/pubid/parser.rb +2 -0
  362. data/lib/pubid/parsers/mr_string.rb +19 -0
  363. data/lib/pubid/plateau/parser.rb +1 -1
  364. data/lib/pubid/plateau.rb +10 -0
  365. data/lib/pubid/prefixes_support.rb +1 -0
  366. data/lib/pubid/renderers/annotator.rb +233 -0
  367. data/lib/pubid/renderers/base.rb +13 -0
  368. data/lib/pubid/renderers/directives_renderer.rb +3 -3
  369. data/lib/pubid/renderers/human_readable.rb +3 -3
  370. data/lib/pubid/renderers/mr_string.rb +15 -9
  371. data/lib/pubid/renderers.rb +1 -0
  372. data/lib/pubid/rendering/numbering.rb +25 -7
  373. data/lib/pubid/rendering.rb +1 -0
  374. data/lib/pubid/sae/identifiers/base.rb +9 -2
  375. data/lib/pubid/sae/parser.rb +1 -1
  376. data/lib/pubid/sae.rb +1 -0
  377. data/lib/pubid/schema/declaration.rb +33 -0
  378. data/lib/pubid/schema/error.rb +14 -0
  379. data/lib/pubid/schema/identifier_type.rb +23 -0
  380. data/lib/pubid/schema/loader.rb +117 -0
  381. data/lib/pubid/schema/typed_stage.rb +24 -0
  382. data/lib/pubid/schema.rb +25 -0
  383. data/lib/pubid/tgpp/builder.rb +1 -1
  384. data/lib/pubid/tgpp/identifier.rb +21 -5
  385. data/lib/pubid/tgpp/identifiers/technical_report.rb +2 -2
  386. data/lib/pubid/tgpp/identifiers/technical_specification.rb +2 -2
  387. data/lib/pubid/tgpp/parser.rb +22 -6
  388. data/lib/pubid/tgpp/renderer.rb +21 -5
  389. data/lib/pubid/tgpp/urn_generator.rb +27 -8
  390. data/lib/pubid/tgpp/urn_parser.rb +8 -6
  391. data/lib/pubid/tgpp.rb +7 -1
  392. data/lib/pubid/type_resolver.rb +16 -1
  393. data/lib/pubid/un/identifier.rb +6 -3
  394. data/lib/pubid/un/parser.rb +1 -1
  395. data/lib/pubid/un.rb +1 -0
  396. data/lib/pubid/urn_parser/errors.rb +8 -1
  397. data/lib/pubid/urn_parser.rb +1 -0
  398. data/lib/pubid/utils.rb +1 -0
  399. data/lib/pubid/version.rb +1 -1
  400. data/lib/pubid/w3c/builder.rb +5 -5
  401. data/lib/pubid/w3c/identifier.rb +38 -9
  402. data/lib/pubid/w3c/parser.rb +1 -1
  403. data/lib/pubid/w3c/renderer.rb +1 -1
  404. data/lib/pubid/w3c/urn_generator.rb +2 -2
  405. data/lib/pubid/w3c.rb +1 -0
  406. data/lib/pubid/xsf/identifier.rb +9 -5
  407. data/lib/pubid/xsf/parser.rb +17 -4
  408. data/lib/pubid/xsf.rb +7 -1
  409. data/lib/pubid.rb +399 -21
  410. data/lib/tasks/conformance.rake +34 -0
  411. data/lib/tasks/docs.rake +3 -3
  412. data/lib/tasks/schema.rake +88 -0
  413. data/schema/core/joint_prefixes.yaml +24 -0
  414. data/schema/iec.yaml +1017 -0
  415. data/schema/iso.yaml +1586 -0
  416. data/schema/schema.schema.yaml +96 -0
  417. metadata +38 -17
  418. data/archived-gems/pubid-ccsds/update_codes.yaml +0 -1
  419. data/archived-gems/pubid-iec/stages.yaml +0 -129
  420. data/archived-gems/pubid-iec/update_codes.yaml +0 -67
  421. data/archived-gems/pubid-ieee/update_codes.yaml +0 -104
  422. data/archived-gems/pubid-iso/stages.yaml +0 -106
  423. data/archived-gems/pubid-iso/update_codes.yaml +0 -4
  424. data/archived-gems/pubid-itu/i18n.yaml +0 -13
  425. data/archived-gems/pubid-itu/series.yaml +0 -42
  426. data/archived-gems/pubid-nist/publishers.yaml +0 -6
  427. data/archived-gems/pubid-nist/series.yaml +0 -121
  428. data/archived-gems/pubid-nist/update_codes.yaml +0 -93
  429. data/archived-gems/pubid-plateau/update_codes.yaml +0 -6
  430. data/lib/pubid/cen_cenelec/supplement_identifier.rb +0 -48
  431. data/lib/pubid/iec/components/code.rb +0 -36
  432. /data/{archived-gems/pubid-nist → data/nist}/stages.yaml +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6d61c7856e3a399a750ea5d73de7d370f32970f68a8dd66cda45a4ea4acc3f9d
4
- data.tar.gz: de8c106c766b93318efde9b250d30b1eb4229d73124bb04741c3503a330c0b50
3
+ metadata.gz: 18402e85b2e19640920f3e216f62f704c6770a840f654d92f96d799b03fbda71
4
+ data.tar.gz: e9b1735e843fe5eb20574749d2581c19192799f86fe3f31a8e72b3d0a00ab047
5
5
  SHA512:
6
- metadata.gz: e8a6e510b3344464c39a245057f0c9dd8819245e8f0dd8d391d814949ba22b678c1942586cb801d831c1c37bc4cadc30549d035ffcb0b148128628861678dfa1
7
- data.tar.gz: af562497969b162c2c4d5a99591eb03c5cc86d3588d487c5ef84407eb6726e53edab78c0e09f090cc1c39386e5113c4b4032ab725f85ed7d881b752d6f358bf0
6
+ metadata.gz: 1cbcaa48b3fb036aca2a62aabe9cdfc4733ad030dc833aa31b5be2dbba433ef6459f87dc22c0b811e707687ce18ee966a2882f928a44d2d0df89e159df5ea837
7
+ data.tar.gz: 0ea8984849aa9f56a400948fb5ab7b29f5de122f70ab036d35fe344655abe70fbe9e34d9cdc04b80673593190b1479d8ac47b31bd21e056ad9b64fa6743e18e6
data/README.adoc CHANGED
@@ -147,18 +147,35 @@ id.to_json
147
147
 
148
148
  === Import from Hash
149
149
 
150
+ `Pubid.from_hash` is the hash counterpart of `Pubid.parse`. It builds the
151
+ correct identifier class from a hash that `#to_hash` emits. You do not name
152
+ the flavor: the `_type` key (`pubid:<flavor>:<type>`) identifies the class.
153
+
150
154
  [source,ruby]
151
155
  ----
152
- require 'pubid/iso'
156
+ require 'pubid'
153
157
 
154
158
  hash = {
155
- flavor: "iso",
156
- publisher: "ISO",
157
- number: "9001",
158
- year: "2015"
159
+ "_type" => "pubid:iso:international-standard",
160
+ "number" => "9001",
161
+ "year" => "2015"
159
162
  }
160
- id = Pubid::Serializable.from_h(hash)
161
- id.to_s # => "ISO 9001:2015"
163
+ id = Pubid.from_hash(hash)
164
+ id.class # => Pubid::Iso::Identifiers::InternationalStandard
165
+ id.to_s # => "ISO 9001:2015"
166
+ ----
167
+
168
+ For a row of a relaton-data `index-v2.yaml` file, give the identifier hash in
169
+ the `:id` key of the row: `Pubid.from_hash(row[:id])`.
170
+
171
+ A hash that is not an identifier hash raises `Pubid::Errors::InvalidInputError`
172
+ (an `ArgumentError`). This occurs when the input is not a Hash, has no `_type`,
173
+ or has a `_type` that no flavor defines.
174
+
175
+ [source,ruby]
176
+ ----
177
+ Pubid.from_hash({ "number" => "9001" })
178
+ # => Pubid::Errors::InvalidInputError: identifier hash has no _type key: ...
162
179
  ----
163
180
 
164
181
  === Import from JSON
@@ -181,11 +198,15 @@ All identifiers support full round-trip conversion preserving all attributes:
181
198
  require 'pubid/iso'
182
199
 
183
200
  original = Pubid::Iso.parse("ISO 9001:2015/Amd 1:2020/Cor 1:2021")
184
- hash = original.to_h
185
- restored = Pubid::Serializable.from_h(hash)
201
+ hash = original.to_hash
202
+ # => {"_type" => "pubid:iso:corrigendum", "number" => "1", "year" => "2021",
203
+ # "base" => {"_type" => "pubid:iso:amendment", "number" => "1", "year" => "2020",
204
+ # "base" => {"_type" => "pubid:iso:international-standard",
205
+ # "number" => "9001", "year" => "2015"}}}
206
+ restored = Pubid.from_hash(hash)
186
207
 
187
208
  restored.to_s # => "ISO 9001:2015/Amd 1:2020/Cor 1:2021"
188
- restored.to_urn # => "urn:iso:std:iso:9001:amd:2020:cor:2021:v1"
209
+ restored.to_urn # => "urn:iso:std:iso:9001:amd:2020:v1:cor:2021:v1"
189
210
  ----
190
211
 
191
212
  == Utility Methods
@@ -1756,7 +1777,8 @@ require 'pubid'
1756
1777
 
1757
1778
  # update_codes.yaml: "NBS HB: NIST HB"
1758
1779
  id = Pubid::Nist.parse("NBS HB 105-1")
1759
- id.to_s # => "NIST HB 105-1" (NBS→NIST correction applied)
1780
+ id.to_s # => "NBS HB 105-1" (NBS identity preserved - documents published
1781
+ # by NBS, i.e. before/equal 1988, keep their NBS identifiers forever)
1760
1782
 
1761
1783
  # update_codes.yaml: "FIPS.140-2: FIPS 140-2" (normalizes dotted format)
1762
1784
  id = Pubid::Nist.parse("FIPS.140-2")
@@ -0,0 +1,4 @@
1
+ # Cases this implementation explicitly cannot handle yet.
2
+ # Rules: entries need reason + ref; a pending case that passes raises
3
+ # the pending-satisfied alarm and MUST be unmarked (TODO.correct-test-suite/04).
4
+ ---
@@ -16,12 +16,10 @@ module Pubid
16
16
  # Parse an Adobe identifier string into an identifier object.
17
17
  # @param identifier [String]
18
18
  # @return [Pubid::Adobe::Identifier]
19
- # @raise [Parslet::ParseFailed] If parsing fails
19
+ # @raise [Pubid::Errors::ParseError] If parsing fails
20
20
  def self.parse(identifier)
21
21
  parsed = Parser.parse(identifier)
22
22
  Builder.build(parsed)
23
- rescue Parslet::ParseFailed => e
24
- raise "Failed to parse Adobe identifier '#{identifier}': #{e.message}"
25
23
  end
26
24
 
27
25
  attribute :publisher, :string, default: "Adobe"
@@ -21,7 +21,7 @@ module Pubid
21
21
  # ATN5014 (short alias)
22
22
  # 5014 (bare number; data-repo context)
23
23
  # adobe-glyph-list (bare slug)
24
- class Parser < Parslet::Parser
24
+ class Parser < ::Pubid::Parser::Grammar
25
25
  include ::Pubid::Parser::CommonParseRules
26
26
 
27
27
  root :identifier
@@ -119,7 +119,15 @@ module Pubid
119
119
  # @param string [String]
120
120
  # @return [Hash]
121
121
  def self.parse(string)
122
- raise ArgumentError, ::Pubid::INPUT_TOO_LONG_MESSAGE if string.length > ::Pubid::MAX_INPUT_LENGTH
122
+ unless string.is_a?(String)
123
+ raise ::Pubid::Errors::InvalidInputError,
124
+ ::Pubid::INPUT_NOT_A_STRING_MESSAGE
125
+ end
126
+
127
+ if string.length > ::Pubid::MAX_INPUT_LENGTH
128
+ raise ::Pubid::Errors::InvalidInputError,
129
+ ::Pubid::INPUT_TOO_LONG_MESSAGE
130
+ end
123
131
 
124
132
  new.parse(string.strip)
125
133
  end
data/lib/pubid/adobe.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  module Pubid
4
5
  module Adobe
5
6
  extend Pubid::PrefixesSupport
@@ -78,7 +78,7 @@ module Pubid
78
78
  if parsed[:code_with_year]
79
79
  code_year_data = parsed[:code_with_year]
80
80
  if code_year_data && code_year_data[:code]
81
- attributes[:code] =
81
+ attributes[:number] =
82
82
  extract_value(code_year_data[:code])
83
83
  end
84
84
  if code_year_data && code_year_data[:year]
@@ -86,7 +86,7 @@ module Pubid
86
86
  extract_value(code_year_data[:year])
87
87
  end
88
88
  elsif parsed[:code]
89
- attributes[:code] = extract_value(parsed[:code])
89
+ attributes[:number] = extract_value(parsed[:code])
90
90
  end
91
91
 
92
92
  # Extract year if not already extracted from code_with_year
@@ -6,12 +6,19 @@ module Pubid
6
6
  # Pubid::Amca::Identifier; common
7
7
  # functionality for all AMCA identifier types.
8
8
  class Identifier < ::Pubid::Identifier
9
- # @raise [Parslet::ParseFailed] If parsing fails
9
+ # @raise [Pubid::Errors::ParseError] If parsing fails
10
10
  def self.parse(identifier)
11
+ unless identifier.is_a?(String)
12
+ raise Pubid::Errors::InvalidInputError,
13
+ Pubid::INPUT_NOT_A_STRING_MESSAGE
14
+ end
15
+
16
+ if identifier.length > Pubid::MAX_INPUT_LENGTH
17
+ raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
18
+ end
19
+
11
20
  parsed = Parser.parse(identifier)
12
21
  Builder.build(parsed)
13
- rescue Parslet::ParseFailed => e
14
- raise "Failed to parse ACMA identifier '#{identifier}': #{e.message}"
15
22
  end
16
23
 
17
24
  # Stored as a plain string (always "AMCA") so it round-trips through
@@ -19,22 +26,40 @@ module Pubid
19
26
  # serialize a String against the Components::Publisher attribute and raise.
20
27
  attribute :publisher, :string, default: -> { "AMCA" }
21
28
  attribute :copublisher, :string
22
- attribute :code, Components::Code
23
- attribute :year, Components::Date
29
+ # The document number used to live in AMCA's own `code` attribute, leaving
30
+ # the `number` inherited from ::Pubid::Identifier nil — so relaton-index,
31
+ # which sorts and bsearches on `id.root.number.to_s`, keyed every AMCA row
32
+ # on "". `code` is gone; each LEAF now declares `attribute :number,
33
+ # :string` (see standard.rb / publication.rb / interpretation.rb).
34
+ #
35
+ # It is declared on the leaves, never here: this class is inherited by all
36
+ # three of them, and redefining the parent's Components::Code-typed
37
+ # `number` on an inherited-from class resolves nondeterministically under
38
+ # multi-flavor load. Do not reintroduce `code`, and do not move `number`
39
+ # up here.
40
+ #
41
+ # A bare 2-digit edition year ("21", "02"). Declared :string, not
42
+ # Components::Date: the builder assigns a String and lutaml does not cast
43
+ # it, so a Date declaration left the PARSE path holding a String while
44
+ # from_hash produced a Components::Date — making
45
+ # `parse(x) == from_hash(parse(x).to_hash)` false for every AMCA id and
46
+ # breaking #matches?, which is built on ==. to_hash and to_s agreed, so
47
+ # the relaton index gate never caught it.
48
+ attribute :year, :string
24
49
  attribute :suffix, :string
25
50
  attribute :reaffirmed, :string
26
51
 
27
52
  # Explicit key_value mapping: only these keys serialize (the inherited
28
53
  # Pubid::Identifier attributes — including :type, which subclasses expose
29
54
  # as a class-metadata Hash via `self.type` — are intentionally dropped).
30
- # code/year are flattened to their scalar value and rebuilt on load, since
31
- # the Builder may store them as either a String or a component.
55
+ # Every mapped attribute is a plain scalar, so no custom converters are
56
+ # needed; the canonical to_hash already drops empty and default values.
32
57
  key_value do
33
58
  map "_type", to: :_type
34
59
  map "publisher", to: :publisher
35
60
  map "copublisher", to: :copublisher
36
- map "code", with: { to: :code_to_kv, from: :code_from_kv }
37
- map "year", with: { to: :year_to_kv, from: :year_from_kv }
61
+ map "number", to: :number
62
+ map "year", to: :year
38
63
  map "suffix", to: :suffix
39
64
  map "reaffirmed", to: :reaffirmed
40
65
  end
@@ -43,28 +68,25 @@ module Pubid
43
68
  UrnGenerator.new(self).generate
44
69
  end
45
70
 
46
- def code_to_kv(model, doc)
47
- v = model.code.is_a?(::Pubid::Components::Code) ? model.code.value : model.code
48
- return if v.nil? || v.to_s.empty?
49
-
50
- doc.add_child(Lutaml::KeyValue::DataModel::Element.new("code", v.to_s))
51
- end
52
-
53
- def code_from_kv(model, value)
54
- model.code = ::Pubid::Components::Code.new(value: value.to_s)
55
- end
56
-
57
- def year_to_kv(model, doc)
58
- y = model.year.is_a?(::Pubid::Components::Date) ? model.year.year : model.year
59
- return if y.nil? || y.to_s.empty?
71
+ # AMCA models its document type as class metadata (`self.type`), not as a
72
+ # `typed_stage`, so the base `mr_type` hook found nothing. Without it an
73
+ # interpretation and the standard it interprets share a slug — and
74
+ # `to_slug` is an output FILENAME. Before the index columns landed the
75
+ # whole flavor collapsed onto two slugs ("amca" and "").
76
+ def mr_type
77
+ return nil unless self.class.respond_to?(:type)
60
78
 
61
- doc.add_child(Lutaml::KeyValue::DataModel::Element.new("year", y.to_s))
79
+ self.class.type[:key]&.to_s
62
80
  end
63
81
 
64
- def year_from_kv(model, value)
65
- model.year = ::Pubid::Components::Date.new(year: value.to_s)
82
+ # AMCA keeps the edition in its own `year` string, not in the inherited
83
+ # `date`, so the base `mr_year` hook read nil and two editions of one
84
+ # standard — "ANSI/AMCA 300-14" and "ANSI/AMCA Standard 300-24" —
85
+ # produced the same slug. Same shape as the BIPM year recorded in
86
+ # CLAUDE.md.
87
+ def mr_year
88
+ year&.to_s
66
89
  end
67
90
  end
68
-
69
91
  end
70
92
  end
@@ -9,16 +9,24 @@ module Pubid
9
9
  # - AMCA 204 – 1
10
10
  # - ANSI/AMCA 204 Interp
11
11
  class Interpretation < Identifier
12
- attr_reader :interpretation_code
12
+ attribute :number, :string
13
13
 
14
- def initialize(code:, year: nil, copublisher: nil, suffix: nil,
15
- reaffirmed: nil, interpretation_code: nil)
16
- @code = Components::Code.new(value: code.to_s)
17
- @year = Components::Date.new(year: year.to_s) if year
18
- @copublisher = copublisher
19
- @suffix = suffix
20
- @reaffirmed = reaffirmed
21
- @interpretation_code = interpretation_code
14
+ # See Publication: the hand-written keyword initializer bypassed lutaml,
15
+ # costing this class its `_type`, its `publisher` default and the
16
+ # serialization of `interpretation_code`.
17
+ attribute :interpretation_code, :string
18
+
19
+ key_value do
20
+ map "interpretation_code", to: :interpretation_code
21
+ end
22
+
23
+ # The interpretation letter is what distinguishes one interpretation of
24
+ # a standard from another ("AMCA 99 JW Interp" vs "AMCA 99 KB Interp" —
25
+ # different documents, and #== agrees). It is in `==` and in `to_s`, so
26
+ # it must reach the slug too, or three interpretations of standard 99
27
+ # share one filename.
28
+ def mr_number_with_part
29
+ mr_join(super, interpretation_code&.to_s&.downcase)
22
30
  end
23
31
 
24
32
  def self.type
@@ -9,16 +9,20 @@ module Pubid
9
9
  # - AMCA Publication 311-16
10
10
  # - AMCA Publication 1011-03 (R2010)
11
11
  class Publication < Identifier
12
- attr_reader :revision
12
+ attribute :number, :string
13
13
 
14
- def initialize(code:, year:, copublisher: nil, suffix: nil,
15
- reaffirmed: nil, revision: nil)
16
- @code = Components::Code.new(value: code.to_s)
17
- @year = Components::Date.new(year: year.to_s) if year
18
- @copublisher = copublisher
19
- @suffix = suffix
20
- @reaffirmed = reaffirmed
21
- @revision = revision
14
+ # Was a hand-written keyword initializer assigning ivars directly,
15
+ # which bypassed lutaml entirely. Three things broke as a result: no
16
+ # `_type` was emitted (so Identifier.from_hash could not route back to
17
+ # this class), the `publisher` default never materialised, and
18
+ # `revision` was a plain attr_reader that to_hash dropped. Removing it
19
+ # and making `revision` a real attribute — is the AIEE/IRE/NESC
20
+ # migration applied here; the builder already calls `new(**attributes)`
21
+ # exactly as it does for Standard, which never had this problem.
22
+ attribute :revision, :string
23
+
24
+ key_value do
25
+ map "revision", to: :revision
22
26
  end
23
27
 
24
28
  def self.type
@@ -9,6 +9,8 @@ module Pubid
9
9
  # - ANSI/AMCA Standard 99-25
10
10
  # - AMCA Standard 803-02 (R2008)
11
11
  class Standard < Identifier
12
+ attribute :number, :string
13
+
12
14
  def self.type
13
15
  { key: :standard, title: "Standard", short: nil }
14
16
  end
@@ -4,7 +4,7 @@ module Pubid
4
4
  module Amca
5
5
  # Parser class for ACMA identifiers
6
6
  # Single Responsibility: Parsing ACMA identifier syntax
7
- class Parser < Parslet::Parser
7
+ class Parser < ::Pubid::Parser::Grammar
8
8
  # Basic building blocks
9
9
  rule(:space) { str(" ") }
10
10
  rule(:space?) { space.maybe }
@@ -35,14 +35,14 @@ module Pubid
35
35
  if t.is_a?(Hash) && t[:title]
36
36
  parts << t[:title].to_s
37
37
  end
38
- parts << id.code.to_s
38
+ parts << id.number.to_s
39
39
  parts << "-#{id.year}" if id.year
40
40
 
41
41
  result = parts.compact.join(" ")
42
42
 
43
43
  if id.copublisher&.include?("/") && id.year
44
44
  type_title = t.is_a?(Hash) ? t[:title].to_s : ""
45
- result = "#{id.copublisher} #{type_title} #{id.code}-#{id.year}"
45
+ result = "#{id.copublisher} #{type_title} #{id.number}-#{id.year}"
46
46
  end
47
47
 
48
48
  result += " (#{id.reaffirmed})" if id.reaffirmed
@@ -54,7 +54,7 @@ module Pubid
54
54
  parts = []
55
55
  parts << id.copublisher if id.copublisher
56
56
  parts << "Publication"
57
- parts << id.code.to_s
57
+ parts << id.number.to_s
58
58
  parts << "-#{id.year}" if id.year
59
59
  parts << " (Rev. #{id.revision})" if id.revision
60
60
  parts << " (#{id.reaffirmed})" if id.reaffirmed && !id.revision
@@ -65,7 +65,7 @@ module Pubid
65
65
  def render_interpretation(id)
66
66
  parts = []
67
67
  parts << id.copublisher if id.copublisher
68
- parts << id.code.to_s
68
+ parts << id.number.to_s
69
69
 
70
70
  if id.interpretation_code
71
71
  parts << "– #{id.interpretation_code}"
@@ -4,9 +4,9 @@ module Pubid
4
4
  module Amca
5
5
  class UrnGenerator < Pubid::UrnGenerator::Base
6
6
  def urn_number
7
- return nil unless identifier.code
7
+ return nil unless identifier.number
8
8
 
9
- identifier.code.to_s
9
+ identifier.number.to_s
10
10
  end
11
11
 
12
12
  def urn_year
data/lib/pubid/amca.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  module Pubid
4
5
  module Amca
5
6
  extend Pubid::PrefixesSupport
@@ -20,7 +21,7 @@ module Pubid
20
21
  # Parse an ACMA identifier string into an identifier object
21
22
  # @param identifier [String] The ACMA identifier string to parse
22
23
  # @return [Pubid::Amca::Identifier] The appropriate identifier object
23
- # @raise [Parslet::ParseFailed] If parsing fails
24
+ # @raise [Pubid::Errors::ParseError] If parsing fails
24
25
  def self.parse(identifier)
25
26
  Identifier.parse(identifier)
26
27
  end
@@ -36,8 +36,8 @@ module Pubid
36
36
  main_number = main_and_parts[0]
37
37
  part_number = main_and_parts[1]
38
38
  {
39
- number: Components::Code.new(value: main_number),
40
- part: part_number ? Components::Code.new(value: part_number) : nil,
39
+ number: main_number,
40
+ part: part_number,
41
41
  }.compact
42
42
  when :date
43
43
  Components::Date.new(year: value.to_s)
@@ -4,7 +4,25 @@ module Pubid
4
4
  module Ansi
5
5
  # Base ANSI identifier class
6
6
  class Identifier < ::Pubid::Identifier
7
+ # `number`/`part`/`subpart` are declared here rather than inherited as a
8
+ # Components::Code: ANSI stores a bare string in every one of them.
9
+ # Declaring on this class is safe because its body lives in this one file
10
+ # and is never reopened, so every subclass body opens after it has run
11
+ # (lutaml deep-dups the parent attribute table at class-definition time).
12
+ attribute :number, :string
13
+ attribute :part, :string
14
+ attribute :subpart, :string
15
+
7
16
  def self.parse(string)
17
+ unless string.is_a?(String)
18
+ raise Pubid::Errors::InvalidInputError,
19
+ Pubid::INPUT_NOT_A_STRING_MESSAGE
20
+ end
21
+
22
+ if string.length > Pubid::MAX_INPUT_LENGTH
23
+ raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
24
+ end
25
+
8
26
  parsed = Pubid::Ansi::Parser.new.parse(string)
9
27
  Pubid::Ansi::Builder.new.build(parsed)
10
28
  end
@@ -4,7 +4,7 @@ module Pubid
4
4
  module Ansi
5
5
  # Parser for ANSI (American National Standards Institute) identifiers
6
6
  # Examples: ANSI X3.4-1986, ANSI C63.4-2014, ANSI/ISO 9899:1990
7
- class Parser < Parslet::Parser
7
+ class Parser < ::Pubid::Parser::Grammar
8
8
  include ::Pubid::Parser::CommonParseRules
9
9
  include ::Pubid::Parser::CommonParseMethods
10
10
 
@@ -37,8 +37,8 @@ module Pubid
37
37
 
38
38
  def number_portion(id, context)
39
39
  [
40
- id.number.render(context:),
41
- (id.part ? "-#{id.part.render(context:)}" : ""),
40
+ id.number,
41
+ (id.part ? "-#{id.part}" : ""),
42
42
  (id.date ? ":#{id.date.render(context:)}" : ""),
43
43
  ].join
44
44
  end
data/lib/pubid/ansi.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  module Pubid
4
5
  module Ansi
5
6
  extend Pubid::PrefixesSupport
@@ -21,12 +22,11 @@ module Pubid
21
22
  # Parse an ANSI identifier string
22
23
  # @param identifier [String] the identifier string to parse
23
24
  # @return [Identifier] the parsed identifier
25
+ # Delegate to the class method rather than repeating the parser/builder
26
+ # sequence, so the input guards live in one place and the two entry points
27
+ # cannot drift apart.
24
28
  def self.parse(identifier)
25
- parser = Parser.new
26
- builder = Builder.new
27
-
28
- parsed = parser.parse(identifier)
29
- builder.build(parsed)
29
+ Identifier.parse(identifier)
30
30
  end
31
31
 
32
32
  # Per-flavor format registry: inherits global formats, overrides :human
@@ -30,15 +30,29 @@ module Pubid
30
30
  # identifier attribute (the concrete class is pinned by `_type`). Drop it
31
31
  # so the raw Parslet::Slice never lands in the inherited :type attribute.
32
32
  when :type then nil
33
- when :number then Components::Code.new(value: value.to_s)
34
33
  when :reaffirmation
35
34
  value.is_a?(Hash) ? (value[:year] || value).to_s : value.to_s
36
- when :part, :chapter, :section, :subsection, :year
35
+ # Every remaining key is a bare scalar. `:chapter` is a PARSE-TREE key
36
+ # and keeps its name in the grammar; the ATTRIBUTE it feeds is `number`
37
+ # (see handle_key below), which this branch retyped from
38
+ # Components::Code to :string — so it now casts like the rest.
39
+ when :number, :chapter, :part, :section, :subsection, :year
37
40
  value.to_s
38
41
  else
39
42
  super
40
43
  end
41
44
  end
45
+
46
+ # Route the MPMS chapter into the `number` attribute. The shared
47
+ # assign_attributes loop uses the parse-tree key as the setter name and
48
+ # silently skips a key that is not an attribute, so without this the
49
+ # chapter would simply vanish once `attribute :chapter` was removed.
50
+ def handle_key(identifier, key, value)
51
+ return super unless key.to_sym == :chapter
52
+
53
+ identifier.number = value
54
+ true
55
+ end
42
56
  end
43
57
  end
44
58
  end
@@ -7,14 +7,35 @@ module Pubid
7
7
  # `is_a?(Pubid::Api::Identifier)` natively and gets the shared polymorphic
8
8
  # `from_hash` (no facade needed).
9
9
  class Identifier < ::Pubid::Identifier
10
+ # `number`/`part`/`subpart` are declared here rather than inherited as a
11
+ # Components::Code: API stores a bare string in every one of them.
12
+ # Declaring on this class is safe because its body lives in this one file
13
+ # and is never reopened, so every subclass body opens after it has run
14
+ # (lutaml deep-dups the parent attribute table at class-definition time).
15
+ # `code` keeps its Components::Code type on SingleIdentifier - it is not
16
+ # one of the three attributes the shared base declares.
17
+ attribute :number, :string
18
+ attribute :part, :string
19
+ attribute :subpart, :string
20
+
10
21
  def self.parse(input)
11
- # Filter out comments
12
- return nil if input.start_with?("#")
22
+ unless input.is_a?(String)
23
+ raise Pubid::Errors::InvalidInputError,
24
+ Pubid::INPUT_NOT_A_STRING_MESSAGE
25
+ end
26
+
27
+ if input.length > Pubid::MAX_INPUT_LENGTH
28
+ raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
29
+ end
13
30
 
31
+ # There used to be a `return nil if input.start_with?("#")` here, to
32
+ # skip the comment lines of a fixture file. A comment is not an
33
+ # identifier, so it must be rejected like any other unparseable string:
34
+ # this was the one public parse in the gem that could return nil, which
35
+ # a caller reading `id.to_s` sees as a NoMethodError far from the cause.
36
+ # Both API fixture loaders already drop `#` lines themselves.
14
37
  tree = Parser.new.parse(input)
15
38
  Builder.new.build(tree)
16
- rescue Parslet::ParseFailed => e
17
- raise e
18
39
  end
19
40
  end
20
41
  end
@@ -4,20 +4,22 @@ module Pubid
4
4
  module Api
5
5
  module Identifiers
6
6
  class Mpms < Base
7
- attribute :chapter, :string
7
+ # The MPMS chapter IS the document number — "API MPMS CH 12.2" is
8
+ # chapter 12, section 2 — so it lives in the `number` inherited from
9
+ # ::Pubid::Identifier, which every other API type already sets. It used
10
+ # to sit in a separate `chapter` :string, leaving `number` nil, so all
11
+ # 30 MPMS ids keyed "" for relaton-index.
12
+ #
13
+ # `section`/`subsection` stay as sibling part columns, which is what
14
+ # gives the bucket semantics a part-less reference needs: every section
15
+ # of chapter 12 shares the key "12". `CH` is a literal marker in the
16
+ # renderer and was never part of the value.
8
17
  attribute :section, :string
9
18
  attribute :subsection, :string
10
19
 
11
20
  def type_string
12
21
  "MPMS"
13
22
  end
14
-
15
- private
16
-
17
- def code_portion
18
- # Override - MPMS doesn't use code_portion
19
- nil
20
- end
21
23
  end
22
24
  end
23
25
  end
@@ -4,7 +4,7 @@ require "parslet"
4
4
 
5
5
  module Pubid
6
6
  module Api
7
- class Parser < Parslet::Parser
7
+ class Parser < ::Pubid::Parser::Grammar
8
8
  # Basic building blocks
9
9
  rule(:space) { str(" ") }
10
10
  rule(:dash) { str("-") }