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
@@ -4,8 +4,92 @@ module Pubid
4
4
  module Asme
5
5
  module Identifiers
6
6
  class Standard < Base
7
- # Standard extends Base with no additional attributes
8
- # All functionality inherited from Base
7
+ # --- Index columns -------------------------------------------------
8
+ #
9
+ # relaton-index sorts and bsearches every row on
10
+ # `id.root.number.to_s`. ASME used to keep the code inside an
11
+ # Asme::Components::Code under a `code` attribute, leaving the
12
+ # inherited `number` nil and every row keyed "".
13
+ #
14
+ # `number` holds the WHOLE printed code — "B18.3", "A112.19.12",
15
+ # "BPVC-CC-BPV" — not a designator/number split.
16
+ #
17
+ # The split looks tempting (it is what IEEE does) but it cannot key
18
+ # this corpus: 152 of the 731 fixture ids are Boiler and Pressure
19
+ # Vessel Code documents whose entire identity IS the designator
20
+ # ("BPVC COMPLETE CODE BIND", "BPVC.CC.BPV") with no numeric part at
21
+ # all. Splitting leaves every one of them with an empty key, and
22
+ # inventing a number for them would be inventing data.
23
+ #
24
+ # Nothing is lost by joining: Components::Code#render is a plain
25
+ # concatenation of designator and number, and the only readers of
26
+ # `code` anywhere in lib/pubid/asme are `code.to_s` (renderer.rb,
27
+ # urn_generator.rb). Keying on the whole code also clusters editions of
28
+ # one document, which is what relaton narrows on — an ASME reference is
29
+ # always written "ASME B18.3", never "18.3" alone.
30
+ #
31
+ # LANDMINE: `number` redefines the Components::Code attribute inherited
32
+ # from ::Pubid::Identifier, which resolves nondeterministically when
33
+ # declared on a class others inherit from. Standard is the only
34
+ # concrete ASME type and has no subclasses, so it is declared here and
35
+ # never on SingleIdentifier / Identifiers::Base.
36
+ # spec/pubid/asme/root_number_spec.rb carries the tripwire and is only
37
+ # meaningful under the full `rake` suite.
38
+ # There is deliberately no `#code` reader here. An earlier draft had one
39
+ # composing `Components::Code.new(number: number)` so the renderer and
40
+ # the URN generator would not have to change — but because `number`
41
+ # holds the whole printed code, that Code never carried a designator and
42
+ # `code.to_s` equalled `number` for all 731 corpus ids. It wrapped a
43
+ # string in an object whose only job was to unwrap to the same string.
44
+ # Both readers now use `number` directly.
45
+ #
46
+ # ASTM keeps its composed `#code` (Identifiers::CodeNumber) for the
47
+ # opposite reason: its renderer reads `code.letter` / `code.dual_m`
48
+ # field-by-field, so the component there carries real structure.
49
+ attribute :number, :string
50
+
51
+ # MR slug. Before the index column landed, every ASME slug was just
52
+ # "asme": 722 of 731 documents shared one filename, and `to_slug` is
53
+ # what consumers use as an output filename.
54
+ #
55
+ # `handbook` is identity-bearing — it is in the serialized hash and in
56
+ # `==`, and "ASME A17.1/CSA B44-2019" and "ASME A17.1/CSA B44
57
+ # Handbook-2019" are different documents — so it has to reach the slug
58
+ # too. CLAUDE.md's rule: a marker that only reaches `==` still lets two
59
+ # documents share a filename.
60
+ def mr_number_with_part
61
+ mr_join(mr_sanitize(number), (handbook ? "handbook" : nil))
62
+ end
63
+
64
+ # ASME keeps its edition in a plain `year` string, not the inherited
65
+ # `date`, so the base `mr_year` hook read nil and every edition of one
66
+ # standard shared a slug.
67
+ def mr_year
68
+ year&.to_s
69
+ end
70
+
71
+ # ASME keeps a translation marker in a plain `language` string, not the
72
+ # inherited `languages` collection the base hook reads. Without this,
73
+ # "ASME B31.8-2016" and its Spanish edition "ASME B31.8 (SPANISH)-2016"
74
+ # — different documents, and #== agrees — share one filename.
75
+ def mr_languages
76
+ language&.to_s&.downcase
77
+ end
78
+
79
+ # An ASME code legitimately contains "." (B18.3), "-" (BPVC-CC-BPV),
80
+ # "&" (V&V) and spaces ("BPVC COMPLETE CODE BIND"). Renderers::MrString
81
+ # joins SEGMENTS with ".", so a dot inside one breaks that structure —
82
+ # filter by charset, the BIPM `mr_slug` precedent, rather than by an
83
+ # enumerated escape list. The output emptiness check matters: a value
84
+ # made only of out-of-charset characters collapses to "", which is
85
+ # truthy in Ruby and would reach the renderer as a blank segment.
86
+ def mr_sanitize(value)
87
+ return nil if value.nil? || value.to_s.empty?
88
+
89
+ sanitized = value.to_s.downcase
90
+ .gsub(/[^a-z0-9-]+/, "-").gsub(/\A-+|-+\z/, "")
91
+ sanitized.empty? ? nil : sanitized
92
+ end
9
93
  end
10
94
  end
11
95
  end
@@ -4,7 +4,7 @@ require "parslet"
4
4
 
5
5
  module Pubid
6
6
  module Asme
7
- class Parser < Parslet::Parser
7
+ class Parser < ::Pubid::Parser::Grammar
8
8
  # Basic building blocks
9
9
  rule(:space) { str(" ") }
10
10
  # Regular dash, en-dash, em-dash
@@ -22,15 +22,15 @@ module Pubid
22
22
  parts << id.first_publisher
23
23
  parts << id.first_code
24
24
  parts << "/#{id.second_publisher}" if id.second_publisher
25
- parts << id.code.to_s if id.code && id.code.to_s != ""
25
+ parts << id.number.to_s if id.number && id.number.to_s != ""
26
26
  elsif id.joint_publisher
27
27
  # ISO/ASME or ASME/ANS format
28
28
  parts << id.joint_publisher
29
- parts << id.code.to_s if id.code && id.code.to_s != ""
29
+ parts << id.number.to_s if id.number && id.number.to_s != ""
30
30
  else
31
31
  # Standard ASME format
32
32
  parts << id.publisher if id.publisher
33
- parts << id.code.to_s if id.code
33
+ parts << id.number.to_s if id.number
34
34
  end
35
35
 
36
36
  result = parts.join(" ")
@@ -10,7 +10,14 @@ module Pubid
10
10
  # @return [String] URN representation
11
11
 
12
12
  attribute :publisher, :string
13
- attribute :code, Components::Code
13
+ # The document code lives on the concrete leaf as a single `number`
14
+ # column holding the WHOLE printed code ("B18.3", "BPVC-CC-BPV") — see
15
+ # Identifiers::Standard, which explains why it is not split into
16
+ # designator + number. It cannot be declared here: SingleIdentifier is
17
+ # inherited by Identifiers::Base and Identifiers::Standard, and
18
+ # redefining the `number` that ::Pubid::Identifier types as a
19
+ # Components::Code on an inherited-from class resolves
20
+ # nondeterministically under multi-flavor load.
14
21
  attribute :year, :string
15
22
  attribute :reaffirmation, :string # R2020
16
23
  attribute :language, :string # (SPANISH)
@@ -11,8 +11,8 @@ module Pubid
11
11
 
12
12
  parts << publisher_component
13
13
 
14
- if identifier.code
15
- parts << identifier.code.to_s
14
+ if identifier.number
15
+ parts << identifier.number.to_s
16
16
  end
17
17
 
18
18
  part = maybe(:part)
data/lib/pubid/asme.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  module Pubid
4
5
  module Asme
5
6
  extend Pubid::PrefixesSupport
@@ -8,9 +8,16 @@ module Pubid
8
8
  identifier_class = determine_identifier_class(parsed_hash)
9
9
  identifier = identifier_class.new
10
10
 
11
- # Build code component if present
11
+ # The code is stored as flat index columns on every concrete class (see
12
+ # Identifiers::CodeNumber) — `number` is what relaton-index keys on —
13
+ # so the Code built below is unpacked rather than assigned.
12
14
  if parsed_hash[:letter] || parsed_hash[:number]
13
- identifier.code = build_code(parsed_hash)
15
+ code = build_code(parsed_hash)
16
+ identifier.letter = code.letter
17
+ identifier.number = code.number
18
+ identifier.suffix = code.suffix
19
+ identifier.subseries = code.subseries
20
+ identifier.dual_m = code.dual_m || false
14
21
  end
15
22
 
16
23
  # Set publisher
@@ -119,7 +126,7 @@ module Pubid
119
126
 
120
127
  # Adjunct
121
128
  if identifier.is_a?(Identifiers::Adjunct)
122
- identifier.designation = parsed_hash[:designation].to_s if parsed_hash[:designation]
129
+ identifier.number = parsed_hash[:designation].to_s if parsed_hash[:designation]
123
130
  identifier.ea_suffix = true if parsed_hash[:ea_suffix]
124
131
  identifier.dvd_suffix = true if parsed_hash[:dvd_suffix]
125
132
  end
@@ -4,6 +4,15 @@ module Pubid
4
4
  module Astm
5
5
  class Identifier < Pubid::Identifier
6
6
  def self.parse(str)
7
+ unless str.is_a?(String)
8
+ raise Pubid::Errors::InvalidInputError,
9
+ Pubid::INPUT_NOT_A_STRING_MESSAGE
10
+ end
11
+
12
+ if str.length > Pubid::MAX_INPUT_LENGTH
13
+ raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
14
+ end
15
+
7
16
  parser = Parser.new
8
17
  builder = Builder.new
9
18
 
@@ -4,7 +4,22 @@ module Pubid
4
4
  module Astm
5
5
  module Identifiers
6
6
  class Adjunct < SingleIdentifier
7
- attribute :designation, :string # D2148, F3504, G0088, C062702
7
+ include CodeNumber
8
+
9
+ # An adjunct carries no code at all — its whole identity is the
10
+ # designation ("ADJD2148"). relaton-index keys on
11
+ # `id.root.number.to_s`, so the designation IS the number here, the
12
+ # same reasoning that makes a registry slug IANA's number and a draft
13
+ # slug IETF's.
14
+ #
15
+ # It is stored in `number` itself rather than in a separate
16
+ # `designation` attribute shadowed by a `def number`. Two reasons, both
17
+ # from CLAUDE.md: defining a `#number` method alongside the attribute is
18
+ # the construct that corrupts lutaml's accessor resolution, and keeping
19
+ # both columns made `to_hash` emit the same string twice
20
+ # ({"number" => "D2148", "designation" => "D2148"}) — the duplication
21
+ # the BIPM note warns against. The builder assigns `number` and the
22
+ # renderer reads it; nothing else referenced `designation`.
8
23
  attribute :ea_suffix, :boolean # -EA
9
24
  attribute :dvd_suffix, :boolean # DVD
10
25
  end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Astm
5
+ module Identifiers
6
+ # Installs the flat, index-friendly code columns on every CONCRETE ASTM
7
+ # identifier class.
8
+ #
9
+ # Why every concrete class and not Pubid::Astm::SingleIdentifier, which
10
+ # they all inherit from: `number` redefines the parent
11
+ # ::Pubid::Identifier's `attribute :number, Components::Code` as a plain
12
+ # :string (Astm::Components::Code is not a subclass of it). Declaring that
13
+ # on a class the concrete types INHERIT from resolves against the parent
14
+ # definition nondeterministically under multi-flavor load — it passes an
15
+ # ASTM-only run and can flip `root.number` to "" under the full suite (the
16
+ # IEEE lesson; see lib/pubid/ieee/identifiers/code_number.rb and
17
+ # CLAUDE.md).
18
+ #
19
+ # NOTE the module is included by `Standard` AND by `IsoDualPublished`,
20
+ # which inherits from Standard. That is deliberate, not redundant: a class
21
+ # that is itself inherited from must still declare the columns so its
22
+ # subclass holds its own snapshot rather than relying on the parent's.
23
+ # Every instantiable ASTM class declares them for itself.
24
+ #
25
+ # This matters because relaton-index sorts and bsearches every row on
26
+ # `id.root.number.to_s`, and ASTM kept identity in an
27
+ # Astm::Components::Code under a `code` attribute, so all 248 parseable
28
+ # fixture ids keyed "".
29
+ module CodeNumber
30
+ def self.included(base)
31
+ # Bare document number ("2938"), the relaton index key. `letter` is a
32
+ # sibling column, so E2938 and D2938 narrow to the same bucket and
33
+ # are then separated by the full hash — the IEEE prefix/number split.
34
+ base.attribute :number, :string
35
+ base.attribute :letter, :string
36
+ base.attribute :suffix, :string
37
+ base.attribute :subseries, :string
38
+ # Named for the RARE case with a false default, so the canonical
39
+ # to_hash drops it from every ordinary row.
40
+ base.attribute :dual_m, :boolean, default: -> { false }
41
+ end
42
+
43
+ # The composed document code, rebuilt on demand from the split columns.
44
+ # ASTM's renderer reads the individual fields (`code.letter`,
45
+ # `code.number`, `code.dual_m`) in several places, so the component has
46
+ # to keep its structure rather than collapsing to a string as ASME's
47
+ # does.
48
+ #
49
+ # Deliberately NOT an attribute and NOT memoised: the columns are
50
+ # writable (the base #exclude rebuilds through them), so a cached Code
51
+ # would go stale. nil when there is no number and no letter, preserving
52
+ # the nil-`code` branches the renderer and URN generator both test.
53
+ def code
54
+ return nil if number.nil? && letter.nil?
55
+
56
+ Components::Code.new(
57
+ letter: letter,
58
+ number: number,
59
+ suffix: suffix,
60
+ subseries: subseries,
61
+ dual_m: dual_m,
62
+ )
63
+ end
64
+
65
+ # Every field of the code is identity-bearing — Code#to_s renders all
66
+ # of them and they are all in the serialized hash — so all of them must
67
+ # reach the slug, or two distinct documents share a filename.
68
+ # CLAUDE.md's rule: a marker that only reaches `==` is not enough.
69
+ def mr_number_with_part
70
+ segments = [letter, number, suffix].compact
71
+ segments << "s#{subseries}" if subseries
72
+ segments << "m" if dual_m
73
+ return nil if segments.empty?
74
+
75
+ segments.join("-").downcase.gsub(/[^a-z0-9-]+/, "-")
76
+ .gsub(/\A-+|-+\z/, "")
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -4,6 +4,8 @@ module Pubid
4
4
  module Astm
5
5
  module Identifiers
6
6
  class DataSeries < Base
7
+ include CodeNumber
8
+
7
9
  attribute :hol_suffix, :boolean # HOL suffix
8
10
  end
9
11
  end
@@ -12,6 +12,22 @@ module Pubid
12
12
  # Distinguishing feature: Starts with digit (typically 5xxxx series)
13
13
  # These are ASTM's version of standards jointly developed with ISO
14
14
  class IsoDualPublished < Standard
15
+ # Re-included even though Standard already does. DO NOT "clean this
16
+ # up" — it compiles fine without it, passes most tests, and silently
17
+ # reintroduces the multi-flavor `number` determinism landmine for this
18
+ # class alone, visible only under the full suite.
19
+ #
20
+ # Two Ruby facts make the repeat both necessary and safe:
21
+ # * `included(base)` fires on EVERY `include` call, so this gives
22
+ # IsoDualPublished its own `attribute :number` resolved against its
23
+ # own table rather than a snapshot inherited from Standard;
24
+ # * `Module#include` does NOT re-insert a module already present via
25
+ # a superclass, so CodeNumber keeps the ancestor position Standard
26
+ # gave it — still BELOW Standard. That is what lets
27
+ # Standard#mr_number_with_part's `super` reach CodeNumber's
28
+ # implementation instead of being shadowed here.
29
+ include CodeNumber
30
+
15
31
  # Inherits all behavior from Standard:
16
32
  # - sub_year (a, b, c)
17
33
  # - reapproval ((2023))
@@ -4,9 +4,19 @@ module Pubid
4
4
  module Astm
5
5
  module Identifiers
6
6
  class Manual < Base
7
+ include CodeNumber
8
+
7
9
  attribute :edition, :string # 9TH, 2ND
8
10
  attribute :supplement, :boolean # -SUP-
9
11
  attribute :tp_designation, :string # TP for technical publications
12
+
13
+ # Both markers distinguish real documents that share a number —
14
+ # "ASTM MNL15-EB" vs "ASTM MNLTP15-EB", and "ASTM MNL20-2ND-EB" vs
15
+ # "ASTM MNL20-2ND-SUP-EB" — so both must reach the slug, not just the
16
+ # hash.
17
+ def mr_number_with_part
18
+ mr_join(tp_designation&.downcase, super, (supplement ? "sup" : nil))
19
+ end
10
20
  end
11
21
  end
12
22
  end
@@ -4,6 +4,8 @@ module Pubid
4
4
  module Astm
5
5
  module Identifiers
6
6
  class Monograph < Base
7
+ include CodeNumber
8
+
7
9
  attribute :edition, :string # 2ND, 4TH
8
10
  end
9
11
  end
@@ -4,7 +4,17 @@ module Pubid
4
4
  module Astm
5
5
  module Identifiers
6
6
  class ResearchReport < Base
7
+ include CodeNumber
8
+
7
9
  attribute :committee, :string # A01, C09
10
+
11
+ # Research-report numbers restart per committee, so the committee is
12
+ # part of the identity: "ASTM RR:A01-1001" and "ASTM RR:C09-1001" are
13
+ # different documents. The renderer already prints it; the slug has to
14
+ # carry it too or they share a filename.
15
+ def mr_number_with_part
16
+ mr_join(committee&.downcase, super)
17
+ end
8
18
  end
9
19
  end
10
20
  end
@@ -4,9 +4,19 @@ module Pubid
4
4
  module Astm
5
5
  module Identifiers
6
6
  class Standard < Base
7
+ include CodeNumber
8
+
7
9
  attribute :sub_year, :string # a, b, c
8
10
  attribute :reapproval, :string # (2023)
11
+
9
12
  attribute :edition, :string # e1
13
+
14
+ # A reapproved edition is a distinct document — "ASTM C1870-18(2024)"
15
+ # and "ASTM C1870-18" have different hashes — so the marker has to
16
+ # reach the slug as well as `==`, or they share a filename.
17
+ def mr_number_with_part
18
+ mr_join(super, (reapproval ? "r#{reapproval}" : nil))
19
+ end
10
20
  end
11
21
  end
12
22
  end
@@ -4,6 +4,8 @@ module Pubid
4
4
  module Astm
5
5
  module Identifiers
6
6
  class TechnicalReport < Base
7
+ include CodeNumber
8
+
7
9
  end
8
10
  end
9
11
  end
@@ -4,6 +4,8 @@ module Pubid
4
4
  module Astm
5
5
  module Identifiers
6
6
  class WorkInProgress < Base
7
+ include CodeNumber
8
+
7
9
  end
8
10
  end
9
11
  end
@@ -4,6 +4,7 @@ module Pubid
4
4
  module Astm
5
5
  module Identifiers
6
6
  autoload :Base, "#{__dir__}/identifiers/base"
7
+ autoload :CodeNumber, "#{__dir__}/identifiers/code_number"
7
8
  autoload :Standard, "#{__dir__}/identifiers/standard"
8
9
  autoload :IsoDualPublished, "#{__dir__}/identifiers/iso_dual_published"
9
10
  autoload :Manual, "#{__dir__}/identifiers/manual"
@@ -4,7 +4,7 @@ require "parslet"
4
4
 
5
5
  module Pubid
6
6
  module Astm
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("-") }
@@ -131,7 +131,7 @@ module Pubid
131
131
  def render_adjunct(id)
132
132
  result = []
133
133
  result << id.publisher if id.publisher && !id.ea_suffix && !id.dvd_suffix
134
- result << "ADJ#{id.designation}#{'-EA' if id.ea_suffix}#{'DVD' if id.dvd_suffix}"
134
+ result << "ADJ#{id.number}#{'-EA' if id.ea_suffix}#{'DVD' if id.dvd_suffix}"
135
135
  result.compact.join(" ")
136
136
  end
137
137
 
@@ -9,9 +9,39 @@ module Pubid
9
9
  #
10
10
  # @return [String] URN representation
11
11
  attribute :publisher, :string, default: -> { "ASTM" }
12
- attribute :code, Components::Code
12
+ # The document code lives on every concrete class as flat index columns
13
+ # (Identifiers::CodeNumber) — `number` is what relaton-index keys on. It
14
+ # cannot be declared here: SingleIdentifier is inherited by every ASTM
15
+ # type, and retyping the inherited `number` on an inherited-from class
16
+ # resolves nondeterministically under multi-flavor load.
13
17
  attribute :year, :string
14
18
  attribute :format_suffix, :string # -EB for eBook
19
+
20
+ # --- MR slug hooks -------------------------------------------------
21
+ #
22
+ # ASTM defined none, so the base hooks looked for an inherited
23
+ # `typed_stage`, `date` and `Components::Edition` that ASTM does not use.
24
+ # Two consequences, both measured on the corpus before this change:
25
+ # 201 of 248 ids shared the single slug "astm", and 40 of them RAISED —
26
+ # `mr_edition` calls `edition.number`, but ASTM's `edition` is a plain
27
+ # String. That is the same crash BIPM had, recorded in CLAUDE.md.
28
+ # `to_slug` is what consumers use as an output filename.
29
+ def mr_edition
30
+ edition&.to_s&.downcase
31
+ end
32
+
33
+ # ASTM keeps its edition year in a plain `year` string, not the
34
+ # inherited `date`.
35
+ def mr_year
36
+ year&.to_s
37
+ end
38
+
39
+ # The document type is the class, not a typed_stage: without it a
40
+ # Manual, a DataSeries and a Standard numbered alike share a filename.
41
+ def mr_type
42
+ self.class.name.split("::").last
43
+ .gsub(/([a-z])([A-Z])/, '\1-\2').downcase
44
+ end
15
45
  end
16
46
  end
17
47
  end
@@ -17,11 +17,13 @@ module Pubid
17
17
  parts << identifier.code.to_s
18
18
  end
19
19
 
20
- number = maybe(:number)
21
- if number
22
- num = number.to_s
23
- parts << num
24
- end
20
+ # `number` is deliberately NOT emitted here. It used to be dead code —
21
+ # ASTM kept everything in `code` and never set the `number` inherited
22
+ # from ::Pubid::Identifier, so `maybe(:number)` always returned nil.
23
+ # Now that `number` is the real index column and `code` is composed
24
+ # from it, emitting both would double the segment
25
+ # ("urn:astm:std:D2148:2148:22"). `code` already renders the number
26
+ # along with the letter and the suffixes.
25
27
 
26
28
  part = maybe(:part)
27
29
  if part
data/lib/pubid/astm.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  module Pubid
4
5
  module Astm
5
6
  extend Pubid::PrefixesSupport