pubid 2.0.0.pre.alpha.8 → 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 (672) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +33 -11
  3. data/conformance/pending.yaml +4 -0
  4. data/data/bipm/update_codes.yaml +9 -0
  5. data/data/iec/update_codes.yaml +3 -0
  6. data/data/ieee/update_codes.yaml +107 -1
  7. data/{archived-gems/pubid-nist → data/nist}/series.yaml +34 -0
  8. data/data/nist/update_codes.yaml +8 -0
  9. data/lib/pubid/adobe/builder.rb +52 -0
  10. data/lib/pubid/adobe/identifier.rb +47 -0
  11. data/lib/pubid/adobe/identifiers/publication.rb +31 -0
  12. data/lib/pubid/adobe/identifiers/tech_note.rb +32 -0
  13. data/lib/pubid/adobe/identifiers.rb +10 -0
  14. data/lib/pubid/adobe/parser.rb +136 -0
  15. data/lib/pubid/adobe/renderer.rb +39 -0
  16. data/lib/pubid/adobe/urn_generator.rb +42 -0
  17. data/lib/pubid/adobe/urn_parser.rb +69 -0
  18. data/lib/pubid/adobe.rb +61 -0
  19. data/lib/pubid/amca/builder.rb +4 -4
  20. data/lib/pubid/amca/identifier.rb +1 -3
  21. data/lib/pubid/amca/identifiers/base.rb +50 -33
  22. data/lib/pubid/amca/identifiers/interpretation.rb +18 -10
  23. data/lib/pubid/amca/identifiers/publication.rb +14 -10
  24. data/lib/pubid/amca/identifiers/standard.rb +3 -1
  25. data/lib/pubid/amca/identifiers.rb +0 -1
  26. data/lib/pubid/amca/parser.rb +1 -1
  27. data/lib/pubid/amca/renderer.rb +4 -4
  28. data/lib/pubid/amca/single_identifier.rb +1 -1
  29. data/lib/pubid/amca/urn_generator.rb +2 -2
  30. data/lib/pubid/amca.rb +5 -4
  31. data/lib/pubid/ansi/builder.rb +2 -2
  32. data/lib/pubid/ansi/identifier.rb +18 -0
  33. data/lib/pubid/ansi/parser.rb +1 -1
  34. data/lib/pubid/ansi/renderer.rb +2 -2
  35. data/lib/pubid/ansi.rb +5 -5
  36. data/lib/pubid/api/builder.rb +16 -2
  37. data/lib/pubid/api/identifier.rb +25 -4
  38. data/lib/pubid/api/identifiers/mpms.rb +10 -8
  39. data/lib/pubid/api/parser.rb +1 -1
  40. data/lib/pubid/api/renderer.rb +16 -7
  41. data/lib/pubid/api/single_identifier.rb +5 -12
  42. data/lib/pubid/api.rb +1 -0
  43. data/lib/pubid/ashrae/builder.rb +53 -32
  44. data/lib/pubid/ashrae/identifier.rb +3 -4
  45. data/lib/pubid/ashrae/identifiers/addenda_package.rb +7 -1
  46. data/lib/pubid/ashrae/identifiers/addendum.rb +9 -1
  47. data/lib/pubid/ashrae/identifiers/base.rb +94 -12
  48. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +8 -1
  49. data/lib/pubid/ashrae/identifiers/errata.rb +9 -0
  50. data/lib/pubid/ashrae/identifiers/guideline.rb +3 -0
  51. data/lib/pubid/ashrae/identifiers/interpretation.rb +16 -0
  52. data/lib/pubid/ashrae/identifiers/standard.rb +3 -0
  53. data/lib/pubid/ashrae/identifiers.rb +0 -1
  54. data/lib/pubid/ashrae/parser.rb +37 -17
  55. data/lib/pubid/ashrae/renderer.rb +20 -20
  56. data/lib/pubid/ashrae/single_identifier.rb +1 -1
  57. data/lib/pubid/ashrae/supplement_identifier.rb +21 -6
  58. data/lib/pubid/ashrae/urn_generator.rb +8 -2
  59. data/lib/pubid/ashrae.rb +10 -4
  60. data/lib/pubid/asme/builder.rb +11 -2
  61. data/lib/pubid/asme/identifier.rb +9 -0
  62. data/lib/pubid/asme/identifiers/standard.rb +86 -2
  63. data/lib/pubid/asme/parser.rb +1 -1
  64. data/lib/pubid/asme/renderer.rb +3 -3
  65. data/lib/pubid/asme/single_identifier.rb +8 -1
  66. data/lib/pubid/asme/urn_generator.rb +2 -2
  67. data/lib/pubid/asme.rb +1 -0
  68. data/lib/pubid/astm/builder.rb +10 -3
  69. data/lib/pubid/astm/identifier.rb +9 -0
  70. data/lib/pubid/astm/identifiers/adjunct.rb +16 -1
  71. data/lib/pubid/astm/identifiers/code_number.rb +81 -0
  72. data/lib/pubid/astm/identifiers/data_series.rb +2 -0
  73. data/lib/pubid/astm/identifiers/iso_dual_published.rb +16 -0
  74. data/lib/pubid/astm/identifiers/manual.rb +10 -0
  75. data/lib/pubid/astm/identifiers/monograph.rb +2 -0
  76. data/lib/pubid/astm/identifiers/research_report.rb +10 -0
  77. data/lib/pubid/astm/identifiers/standard.rb +10 -0
  78. data/lib/pubid/astm/identifiers/technical_report.rb +2 -0
  79. data/lib/pubid/astm/identifiers/work_in_progress.rb +2 -0
  80. data/lib/pubid/astm/identifiers.rb +1 -0
  81. data/lib/pubid/astm/parser.rb +1 -1
  82. data/lib/pubid/astm/renderer.rb +1 -1
  83. data/lib/pubid/astm/single_identifier.rb +31 -1
  84. data/lib/pubid/astm/urn_generator.rb +7 -5
  85. data/lib/pubid/astm.rb +1 -0
  86. data/lib/pubid/bipm/builder.rb +163 -0
  87. data/lib/pubid/bipm/identifier.rb +285 -0
  88. data/lib/pubid/bipm/identifiers/committee_document.rb +36 -0
  89. data/lib/pubid/bipm/identifiers/guide.rb +35 -0
  90. data/lib/pubid/bipm/identifiers/meeting.rb +53 -0
  91. data/lib/pubid/bipm/identifiers/mep.rb +33 -0
  92. data/lib/pubid/bipm/identifiers/metrologia_article.rb +48 -0
  93. data/lib/pubid/bipm/identifiers/si_brochure.rb +33 -0
  94. data/lib/pubid/bipm/identifiers.rb +15 -0
  95. data/lib/pubid/bipm/parser.rb +237 -0
  96. data/lib/pubid/bipm/renderer.rb +118 -0
  97. data/lib/pubid/bipm/urn_generator.rb +58 -0
  98. data/lib/pubid/bipm/urn_parser.rb +60 -0
  99. data/lib/pubid/bipm.rb +92 -0
  100. data/lib/pubid/bsi/builder.rb +62 -52
  101. data/lib/pubid/bsi/identifier.rb +0 -1
  102. data/lib/pubid/bsi/identifiers/addendum_document.rb +2 -2
  103. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +36 -7
  104. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +7 -6
  105. data/lib/pubid/bsi/identifiers/amendment.rb +4 -4
  106. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +0 -1
  107. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +10 -0
  108. data/lib/pubid/bsi/identifiers/committee_document.rb +10 -1
  109. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +6 -0
  110. data/lib/pubid/bsi/identifiers/corrigendum.rb +4 -4
  111. data/lib/pubid/bsi/identifiers/expert_commentary.rb +5 -5
  112. data/lib/pubid/bsi/identifiers/handbook.rb +0 -2
  113. data/lib/pubid/bsi/identifiers/practice_guide.rb +0 -1
  114. data/lib/pubid/bsi/identifiers/set.rb +11 -0
  115. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +10 -1
  116. data/lib/pubid/bsi/identifiers/supplement_document.rb +2 -2
  117. data/lib/pubid/bsi/identifiers/value_added_publication.rb +6 -6
  118. data/lib/pubid/bsi/parser.rb +1 -1
  119. data/lib/pubid/bsi/renderer.rb +71 -59
  120. data/lib/pubid/bsi/single_identifier.rb +64 -7
  121. data/lib/pubid/bsi/urn_generator.rb +11 -2
  122. data/lib/pubid/bsi.rb +7 -1
  123. data/lib/pubid/builder/base.rb +23 -11
  124. data/lib/pubid/bundled_identifier.rb +19 -9
  125. data/lib/pubid/calconnect/builder.rb +38 -0
  126. data/lib/pubid/calconnect/identifier.rb +121 -0
  127. data/lib/pubid/calconnect/identifiers/standard.rb +29 -0
  128. data/lib/pubid/calconnect/identifiers.rb +9 -0
  129. data/lib/pubid/calconnect/parser.rb +54 -0
  130. data/lib/pubid/calconnect/renderer.rb +36 -0
  131. data/lib/pubid/calconnect/urn_generator.rb +33 -0
  132. data/lib/pubid/calconnect/urn_parser.rb +34 -0
  133. data/lib/pubid/calconnect.rb +83 -0
  134. data/lib/pubid/ccsds/builder.rb +1 -1
  135. data/lib/pubid/ccsds/identifier.rb +10 -3
  136. data/lib/pubid/ccsds/identifiers/base.rb +4 -2
  137. data/lib/pubid/ccsds/identifiers/corrigendum.rb +4 -4
  138. data/lib/pubid/ccsds/parser.rb +1 -1
  139. data/lib/pubid/ccsds/single_identifier.rb +2 -2
  140. data/lib/pubid/ccsds/supplement_identifier.rb +6 -6
  141. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  142. data/lib/pubid/ccsds.rb +1 -0
  143. data/lib/pubid/cen_cenelec/builder.rb +131 -72
  144. data/lib/pubid/cen_cenelec/identifier.rb +115 -3
  145. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +27 -16
  146. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +46 -6
  147. data/lib/pubid/cen_cenelec/identifiers/base.rb +8 -9
  148. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +1 -1
  149. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +1 -1
  150. data/lib/pubid/cen_cenelec/identifiers/cenelec_harmonization_document.rb +1 -1
  151. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +29 -14
  152. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +47 -8
  153. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +60 -3
  154. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +27 -2
  155. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +1 -1
  156. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +15 -5
  157. data/lib/pubid/cen_cenelec/identifiers/guide.rb +1 -1
  158. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +1 -1
  159. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +1 -1
  160. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +1 -1
  161. data/lib/pubid/cen_cenelec/parser.rb +1 -1
  162. data/lib/pubid/cen_cenelec/renderer.rb +55 -60
  163. data/lib/pubid/cen_cenelec/single_identifier.rb +20 -2
  164. data/lib/pubid/cen_cenelec/urn_generator.rb +66 -44
  165. data/lib/pubid/cen_cenelec.rb +104 -82
  166. data/lib/pubid/cie/builder.rb +149 -24
  167. data/lib/pubid/cie/identifier.rb +13 -4
  168. data/lib/pubid/cie/identifiers/bundle.rb +35 -5
  169. data/lib/pubid/cie/identifiers/code_attributes.rb +52 -0
  170. data/lib/pubid/cie/identifiers/conference.rb +11 -6
  171. data/lib/pubid/cie/identifiers/corrigendum.rb +17 -23
  172. data/lib/pubid/cie/identifiers/dual_published.rb +6 -6
  173. data/lib/pubid/cie/identifiers/identical.rb +9 -9
  174. data/lib/pubid/cie/identifiers/joint_published.rb +10 -10
  175. data/lib/pubid/cie/identifiers/proceedings.rb +41 -0
  176. data/lib/pubid/cie/identifiers/standard.rb +43 -8
  177. data/lib/pubid/cie/identifiers/supplement.rb +27 -25
  178. data/lib/pubid/cie/identifiers/tutorial_bundle.rb +7 -3
  179. data/lib/pubid/cie/identifiers.rb +2 -0
  180. data/lib/pubid/cie/parser.rb +55 -6
  181. data/lib/pubid/cie/single_identifier.rb +40 -1
  182. data/lib/pubid/cie/supplement_identifier.rb +29 -16
  183. data/lib/pubid/cie/urn_generator.rb +11 -8
  184. data/lib/pubid/cie.rb +7 -2
  185. data/lib/pubid/components/date.rb +21 -5
  186. data/lib/pubid/conformance/checks.rb +72 -0
  187. data/lib/pubid/conformance/corpus/case.rb +55 -0
  188. data/lib/pubid/conformance/corpus.rb +36 -0
  189. data/lib/pubid/conformance/generator.rb +212 -0
  190. data/lib/pubid/conformance/pending.rb +63 -0
  191. data/lib/pubid/conformance/runner.rb +153 -0
  192. data/lib/pubid/conformance.rb +55 -0
  193. data/lib/pubid/core.rb +2 -0
  194. data/lib/pubid/csa/builder.rb +48 -48
  195. data/lib/pubid/csa/composite_identifier.rb +18 -7
  196. data/lib/pubid/csa/identifier.rb +187 -80
  197. data/lib/pubid/csa/identifiers/bundled.rb +25 -9
  198. data/lib/pubid/csa/identifiers/canadian_adopted.rb +13 -13
  199. data/lib/pubid/csa/identifiers/cec.rb +44 -4
  200. data/lib/pubid/csa/identifiers/combined.rb +97 -69
  201. data/lib/pubid/csa/identifiers/csa_adopted.rb +4 -4
  202. data/lib/pubid/csa/identifiers/package.rb +4 -4
  203. data/lib/pubid/csa/parser.rb +12 -8
  204. data/lib/pubid/csa/renderer.rb +13 -5
  205. data/lib/pubid/csa/single_identifier.rb +93 -4
  206. data/lib/pubid/csa/urn_generator.rb +9 -2
  207. data/lib/pubid/csa/wrapper_identifier.rb +43 -10
  208. data/lib/pubid/csa.rb +7 -1
  209. data/lib/pubid/doi/builder.rb +18 -0
  210. data/lib/pubid/doi/identifier.rb +49 -0
  211. data/lib/pubid/doi/identifiers/resource.rb +30 -0
  212. data/lib/pubid/doi/identifiers.rb +9 -0
  213. data/lib/pubid/doi/parser.rb +52 -0
  214. data/lib/pubid/doi/renderer.rb +13 -0
  215. data/lib/pubid/doi.rb +56 -0
  216. data/lib/pubid/easc/builder.rb +55 -0
  217. data/lib/pubid/easc/identifier.rb +59 -0
  218. data/lib/pubid/easc/identifiers/pmg.rb +20 -0
  219. data/lib/pubid/easc/identifiers/rmg.rb +19 -0
  220. data/lib/pubid/easc/identifiers.rb +10 -0
  221. data/lib/pubid/easc/parser.rb +88 -0
  222. data/lib/pubid/easc/renderer.rb +48 -0
  223. data/lib/pubid/easc/urn_generator.rb +46 -0
  224. data/lib/pubid/easc/urn_parser.rb +57 -0
  225. data/lib/pubid/easc.rb +53 -0
  226. data/lib/pubid/ecma/builder.rb +45 -0
  227. data/lib/pubid/ecma/identifier.rb +147 -0
  228. data/lib/pubid/ecma/identifiers/memento.rb +30 -0
  229. data/lib/pubid/ecma/identifiers/standard.rb +31 -0
  230. data/lib/pubid/ecma/identifiers/technical_report.rb +31 -0
  231. data/lib/pubid/ecma/identifiers.rb +11 -0
  232. data/lib/pubid/ecma/parser.rb +76 -0
  233. data/lib/pubid/ecma/renderer.rb +67 -0
  234. data/lib/pubid/ecma/urn_generator.rb +46 -0
  235. data/lib/pubid/ecma/urn_parser.rb +51 -0
  236. data/lib/pubid/ecma.rb +68 -0
  237. data/lib/pubid/errors.rb +80 -0
  238. data/lib/pubid/etsi/builder.rb +13 -4
  239. data/lib/pubid/etsi/identifier.rb +1 -3
  240. data/lib/pubid/etsi/identifiers/base.rb +43 -11
  241. data/lib/pubid/etsi/identifiers/etsi_standard.rb +207 -4
  242. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +45 -3
  243. data/lib/pubid/etsi/identifiers.rb +0 -1
  244. data/lib/pubid/etsi/parser.rb +9 -3
  245. data/lib/pubid/etsi/renderer.rb +8 -2
  246. data/lib/pubid/etsi.rb +6 -5
  247. data/lib/pubid/evs/builder.rb +26 -0
  248. data/lib/pubid/evs/identifier.rb +37 -0
  249. data/lib/pubid/evs/identifiers/national_adoption.rb +17 -0
  250. data/lib/pubid/evs/identifiers.rb +9 -0
  251. data/lib/pubid/evs/parser.rb +27 -0
  252. data/lib/pubid/evs/renderer.rb +30 -0
  253. data/lib/pubid/evs/urn_generator.rb +30 -0
  254. data/lib/pubid/evs/urn_parser.rb +80 -0
  255. data/lib/pubid/evs.rb +90 -0
  256. data/lib/pubid/export/exporter.rb +2 -1
  257. data/lib/pubid/export/flavor_exporter.rb +18 -3
  258. data/lib/pubid/export.rb +1 -0
  259. data/lib/pubid/format_detector.rb +1 -0
  260. data/lib/pubid/gb/builder.rb +45 -0
  261. data/lib/pubid/gb/identifier.rb +67 -0
  262. data/lib/pubid/gb/identifiers/standard.rb +34 -0
  263. data/lib/pubid/gb/identifiers.rb +9 -0
  264. data/lib/pubid/gb/parser.rb +63 -0
  265. data/lib/pubid/gb/renderer.rb +35 -0
  266. data/lib/pubid/gb.rb +88 -0
  267. data/lib/pubid/gost/builder.rb +185 -0
  268. data/lib/pubid/gost/identifier.rb +47 -0
  269. data/lib/pubid/gost/identifiers/foreign_reference.rb +25 -0
  270. data/lib/pubid/gost/identifiers/harmonized.rb +39 -0
  271. data/lib/pubid/gost/identifiers/identical_adoption.rb +39 -0
  272. data/lib/pubid/gost/identifiers/interstate_standard.rb +20 -0
  273. data/lib/pubid/gost/identifiers/national_standard.rb +19 -0
  274. data/lib/pubid/gost/identifiers.rb +13 -0
  275. data/lib/pubid/gost/parser.rb +105 -0
  276. data/lib/pubid/gost/renderer.rb +48 -0
  277. data/lib/pubid/gost/urn_generator.rb +46 -0
  278. data/lib/pubid/gost/urn_parser.rb +52 -0
  279. data/lib/pubid/gost.rb +50 -0
  280. data/lib/pubid/iala/builder.rb +22 -27
  281. data/lib/pubid/iala/identifier.rb +36 -8
  282. data/lib/pubid/iala/identifiers/advice.rb +1 -1
  283. data/lib/pubid/iala/identifiers/annex.rb +10 -10
  284. data/lib/pubid/iala/identifiers/general_assembly.rb +5 -2
  285. data/lib/pubid/iala/identifiers/guideline.rb +3 -1
  286. data/lib/pubid/iala/identifiers/letter.rb +1 -1
  287. data/lib/pubid/iala/identifiers/manual.rb +3 -1
  288. data/lib/pubid/iala/identifiers/model_course.rb +3 -1
  289. data/lib/pubid/iala/identifiers/recommendation.rb +3 -1
  290. data/lib/pubid/iala/identifiers/report.rb +1 -1
  291. data/lib/pubid/iala/identifiers/resolution.rb +1 -1
  292. data/lib/pubid/iala/identifiers/standard.rb +3 -1
  293. data/lib/pubid/iala/identifiers.rb +0 -1
  294. data/lib/pubid/iala/parser.rb +10 -2
  295. data/lib/pubid/iala/renderer.rb +1 -1
  296. data/lib/pubid/iala/urn_generator.rb +1 -1
  297. data/lib/pubid/iala/urn_parser.rb +24 -3
  298. data/lib/pubid/iala.rb +5 -4
  299. data/lib/pubid/iana/builder.rb +22 -0
  300. data/lib/pubid/iana/identifier.rb +140 -0
  301. data/lib/pubid/iana/identifiers/registry.rb +69 -0
  302. data/lib/pubid/iana/identifiers.rb +9 -0
  303. data/lib/pubid/iana/parser.rb +38 -0
  304. data/lib/pubid/iana/renderer.rb +32 -0
  305. data/lib/pubid/iana/urn_generator.rb +19 -0
  306. data/lib/pubid/iana/urn_parser.rb +24 -0
  307. data/lib/pubid/iana.rb +70 -0
  308. data/lib/pubid/identifier.rb +797 -26
  309. data/lib/pubid/identifier_metadata.rb +1 -0
  310. data/lib/pubid/idf/builder.rb +4 -4
  311. data/lib/pubid/idf/identifier.rb +18 -9
  312. data/lib/pubid/idf/parser.rb +3 -3
  313. data/lib/pubid/idf/renderer.rb +5 -5
  314. data/lib/pubid/idf/supplement_identifier.rb +3 -3
  315. data/lib/pubid/idf/urn_generator.rb +1 -1
  316. data/lib/pubid/idf.rb +7 -1
  317. data/lib/pubid/iec/builder.rb +49 -32
  318. data/lib/pubid/iec/components.rb +0 -1
  319. data/lib/pubid/iec/identifier.rb +112 -77
  320. data/lib/pubid/iec/identifiers/amendment.rb +6 -2
  321. data/lib/pubid/iec/identifiers/base.rb +2 -2
  322. data/lib/pubid/iec/identifiers/component_specification.rb +0 -10
  323. data/lib/pubid/iec/identifiers/conformity_assessment.rb +0 -10
  324. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +6 -0
  325. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -2
  326. data/lib/pubid/iec/identifiers/fragment_identifier.rb +13 -15
  327. data/lib/pubid/iec/identifiers/guide.rb +0 -16
  328. data/lib/pubid/iec/identifiers/international_standard.rb +22 -6
  329. data/lib/pubid/iec/identifiers/operational_document.rb +0 -10
  330. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +0 -12
  331. data/lib/pubid/iec/identifiers/sheet_identifier.rb +12 -12
  332. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +0 -10
  333. data/lib/pubid/iec/identifiers/systems_reference_document.rb +0 -10
  334. data/lib/pubid/iec/identifiers/technical_group.rb +30 -0
  335. data/lib/pubid/iec/identifiers/technical_report.rb +1 -18
  336. data/lib/pubid/iec/identifiers/technical_specification.rb +1 -18
  337. data/lib/pubid/iec/identifiers/technology_report.rb +0 -10
  338. data/lib/pubid/iec/identifiers/test_report_form.rb +0 -11
  339. data/lib/pubid/iec/identifiers/vap_identifier.rb +12 -12
  340. data/lib/pubid/iec/identifiers/white_paper.rb +0 -10
  341. data/lib/pubid/iec/identifiers/working_document.rb +24 -10
  342. data/lib/pubid/iec/identifiers.rb +1 -0
  343. data/lib/pubid/iec/parser.rb +53 -28
  344. data/lib/pubid/iec/renderer.rb +31 -18
  345. data/lib/pubid/iec/single_identifier.rb +34 -11
  346. data/lib/pubid/iec/supplement_identifier.rb +32 -19
  347. data/lib/pubid/iec/urn_generator.rb +227 -61
  348. data/lib/pubid/iec/urn_parser.rb +42 -4
  349. data/lib/pubid/iec.rb +2 -6
  350. data/lib/pubid/ieee/aiee/builder.rb +17 -3
  351. data/lib/pubid/ieee/aiee/identifier.rb +46 -62
  352. data/lib/pubid/ieee/aiee/parser.rb +1 -1
  353. data/lib/pubid/ieee/builder.rb +386 -69
  354. data/lib/pubid/ieee/compaction.rb +121 -0
  355. data/lib/pubid/ieee/components/draft.rb +47 -7
  356. data/lib/pubid/ieee/identifier.rb +1 -3
  357. data/lib/pubid/ieee/identifiers/adopted_standard.rb +62 -5
  358. data/lib/pubid/ieee/identifiers/amendment.rb +40 -0
  359. data/lib/pubid/ieee/identifiers/base.rb +148 -18
  360. data/lib/pubid/ieee/identifiers/code_number.rb +82 -0
  361. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +6 -2
  362. data/lib/pubid/ieee/identifiers/corrigendum.rb +17 -2
  363. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +24 -3
  364. data/lib/pubid/ieee/identifiers/dual_identifier.rb +3 -3
  365. data/lib/pubid/ieee/identifiers/dual_published.rb +58 -3
  366. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +102 -5
  367. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +25 -1
  368. data/lib/pubid/ieee/identifiers/joint_development.rb +64 -15
  369. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +58 -6
  370. data/lib/pubid/ieee/identifiers/nesc/base.rb +90 -19
  371. data/lib/pubid/ieee/identifiers/nesc/draft.rb +20 -5
  372. data/lib/pubid/ieee/identifiers/nesc/edition.rb +32 -0
  373. data/lib/pubid/ieee/identifiers/nesc/handbook.rb +16 -5
  374. data/lib/pubid/ieee/identifiers/nesc/redline.rb +11 -2
  375. data/lib/pubid/ieee/identifiers/nesc/standard.rb +18 -3
  376. data/lib/pubid/ieee/identifiers/nesc.rb +1 -0
  377. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +3 -3
  378. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +14 -6
  379. data/lib/pubid/ieee/identifiers/redlined_standard.rb +4 -4
  380. data/lib/pubid/ieee/identifiers/si_standard.rb +4 -1
  381. data/lib/pubid/ieee/identifiers/standard.rb +4 -1
  382. data/lib/pubid/ieee/identifiers/supplement_identifier.rb +26 -7
  383. data/lib/pubid/ieee/identifiers.rb +2 -1
  384. data/lib/pubid/ieee/ire/builder.rb +7 -6
  385. data/lib/pubid/ieee/ire/identifier.rb +48 -33
  386. data/lib/pubid/ieee/ire/parser.rb +1 -1
  387. data/lib/pubid/ieee/nesc/builder.rb +33 -20
  388. data/lib/pubid/ieee/nesc/parser.rb +16 -15
  389. data/lib/pubid/ieee/parser.rb +462 -44
  390. data/lib/pubid/ieee/pre_parser.rb +1 -1
  391. data/lib/pubid/ieee/renderer.rb +158 -57
  392. data/lib/pubid/ieee/typed_stages.rb +12 -1
  393. data/lib/pubid/ieee/urn_generator.rb +35 -8
  394. data/lib/pubid/ieee.rb +63 -4
  395. data/lib/pubid/ieee_debug.rb +1 -0
  396. data/lib/pubid/ietf/builder.rb +78 -0
  397. data/lib/pubid/ietf/identifier.rb +5 -0
  398. data/lib/pubid/ietf/identifiers/base.rb +72 -0
  399. data/lib/pubid/ietf/identifiers/bcp.rb +36 -0
  400. data/lib/pubid/ietf/identifiers/fyi.rb +36 -0
  401. data/lib/pubid/ietf/identifiers/internet_draft.rb +45 -0
  402. data/lib/pubid/ietf/identifiers/rfc.rb +27 -0
  403. data/lib/pubid/ietf/identifiers/serialization.rb +51 -0
  404. data/lib/pubid/ietf/identifiers/std.rb +36 -0
  405. data/lib/pubid/ietf/identifiers.rb +14 -0
  406. data/lib/pubid/ietf/parser.rb +61 -0
  407. data/lib/pubid/ietf/renderer.rb +64 -0
  408. data/lib/pubid/ietf/urn_generator.rb +37 -0
  409. data/lib/pubid/ietf/urn_parser.rb +43 -0
  410. data/lib/pubid/ietf.rb +86 -0
  411. data/lib/pubid/iho/identifier.rb +1 -3
  412. data/lib/pubid/iho/identifiers/base.rb +11 -10
  413. data/lib/pubid/iho/identifiers/bibliographic.rb +1 -1
  414. data/lib/pubid/iho/identifiers/circular_letter.rb +1 -1
  415. data/lib/pubid/iho/identifiers/miscellaneous.rb +1 -1
  416. data/lib/pubid/iho/identifiers/publication.rb +1 -1
  417. data/lib/pubid/iho/identifiers/standard.rb +1 -1
  418. data/lib/pubid/iho/identifiers.rb +0 -1
  419. data/lib/pubid/iho/parser.rb +1 -1
  420. data/lib/pubid/iho.rb +8 -7
  421. data/lib/pubid/isbn/builder.rb +44 -0
  422. data/lib/pubid/isbn/check_digit.rb +53 -0
  423. data/lib/pubid/isbn/identifier.rb +81 -0
  424. data/lib/pubid/isbn/identifiers/book.rb +30 -0
  425. data/lib/pubid/isbn/identifiers.rb +9 -0
  426. data/lib/pubid/isbn/parser.rb +45 -0
  427. data/lib/pubid/isbn/renderer.rb +16 -0
  428. data/lib/pubid/isbn.rb +53 -0
  429. data/lib/pubid/iso/builder.rb +9 -4
  430. data/lib/pubid/iso/bundled_identifier.rb +5 -3
  431. data/lib/pubid/iso/combined_identifier.rb +6 -4
  432. data/lib/pubid/iso/identifier.rb +29 -8
  433. data/lib/pubid/iso/identifiers/directives_supplement.rb +12 -12
  434. data/lib/pubid/iso/normalizer.rb +2 -2
  435. data/lib/pubid/iso/parser.rb +17 -13
  436. data/lib/pubid/iso/supplement_identifier.rb +19 -6
  437. data/lib/pubid/iso/urn_generator.rb +4 -1
  438. data/lib/pubid/iso/urn_parser.rb +1 -1
  439. data/lib/pubid/iso.rb +7 -1
  440. data/lib/pubid/itu/builder.rb +230 -29
  441. data/lib/pubid/itu/components/code.rb +48 -5
  442. data/lib/pubid/itu/components/designation.rb +35 -0
  443. data/lib/pubid/itu/components.rb +1 -0
  444. data/lib/pubid/itu/identifier.rb +1 -3
  445. data/lib/pubid/itu/identifiers/addendum.rb +15 -0
  446. data/lib/pubid/itu/identifiers/amendment.rb +7 -29
  447. data/lib/pubid/itu/identifiers/annex.rb +13 -2
  448. data/lib/pubid/itu/identifiers/annex_of_recommendation.rb +87 -0
  449. data/lib/pubid/itu/identifiers/appendix_of_recommendation.rb +92 -0
  450. data/lib/pubid/itu/identifiers/base.rb +357 -25
  451. data/lib/pubid/itu/identifiers/combined_identifier.rb +99 -23
  452. data/lib/pubid/itu/identifiers/corrigendum.rb +16 -23
  453. data/lib/pubid/itu/identifiers/errata.rb +15 -0
  454. data/lib/pubid/itu/identifiers/handbook.rb +38 -0
  455. data/lib/pubid/itu/identifiers/question.rb +63 -0
  456. data/lib/pubid/itu/identifiers/recommendation.rb +3 -2
  457. data/lib/pubid/itu/identifiers/report.rb +39 -0
  458. data/lib/pubid/itu/identifiers/special_publication.rb +3 -1
  459. data/lib/pubid/itu/identifiers/standard_serialization.rb +58 -0
  460. data/lib/pubid/itu/identifiers/supplement.rb +119 -14
  461. data/lib/pubid/itu/identifiers.rb +10 -1
  462. data/lib/pubid/itu/model.rb +1 -1
  463. data/lib/pubid/itu/parser.rb +481 -27
  464. data/lib/pubid/itu/urn_generator.rb +36 -6
  465. data/lib/pubid/itu/urn_parser.rb +8 -0
  466. data/lib/pubid/itu.rb +12 -3
  467. data/lib/pubid/jcgm/builder.rb +24 -14
  468. data/lib/pubid/jcgm/identifier.rb +10 -0
  469. data/lib/pubid/jcgm/identifiers/amendment.rb +0 -2
  470. data/lib/pubid/jcgm/identifiers/corrigendum.rb +34 -0
  471. data/lib/pubid/jcgm/identifiers/gum_guide.rb +3 -3
  472. data/lib/pubid/jcgm/identifiers/meeting.rb +47 -0
  473. data/lib/pubid/jcgm/identifiers.rb +2 -0
  474. data/lib/pubid/jcgm/parser.rb +74 -7
  475. data/lib/pubid/jcgm/renderer.rb +33 -12
  476. data/lib/pubid/jcgm/single_identifier.rb +84 -6
  477. data/lib/pubid/jcgm/supplement_identifier.rb +39 -4
  478. data/lib/pubid/jcgm/urn_generator.rb +21 -13
  479. data/lib/pubid/jcgm/urn_parser.rb +164 -10
  480. data/lib/pubid/jcgm.rb +10 -0
  481. data/lib/pubid/jis/identifier.rb +62 -3
  482. data/lib/pubid/jis/parser.rb +1 -1
  483. data/lib/pubid/jis.rb +1 -0
  484. data/lib/pubid/nist/builder.rb +29 -9
  485. data/lib/pubid/nist/caster.rb +7 -45
  486. data/lib/pubid/nist/circular_supplement_builder.rb +7 -5
  487. data/lib/pubid/nist/components/stage.rb +2 -2
  488. data/lib/pubid/nist/components/supplement.rb +5 -2
  489. data/lib/pubid/nist/configuration.rb +6 -2
  490. data/lib/pubid/nist/identifier.rb +1 -3
  491. data/lib/pubid/nist/identifiers/base.rb +133 -39
  492. data/lib/pubid/nist/identifiers/circular.rb +10 -3
  493. data/lib/pubid/nist/identifiers/circular_supplement.rb +14 -5
  494. data/lib/pubid/nist/identifiers/commercial_standard.rb +1 -1
  495. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +1 -1
  496. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +8 -2
  497. data/lib/pubid/nist/identifiers/crpl_report.rb +8 -2
  498. data/lib/pubid/nist/identifiers/dated_document.rb +1 -1
  499. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +1 -1
  500. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +1 -1
  501. data/lib/pubid/nist/identifiers/handbook.rb +10 -3
  502. data/lib/pubid/nist/identifiers/internal_report.rb +13 -6
  503. data/lib/pubid/nist/identifiers/letter_circular.rb +1 -1
  504. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +15 -7
  505. data/lib/pubid/nist/identifiers/monograph.rb +15 -8
  506. data/lib/pubid/nist/identifiers/ncstar.rb +2 -2
  507. data/lib/pubid/nist/identifiers/nsrds.rb +1 -1
  508. data/lib/pubid/nist/identifiers/owmwp.rb +1 -1
  509. data/lib/pubid/nist/identifiers/report.rb +15 -7
  510. data/lib/pubid/nist/identifiers/special_publication.rb +10 -1
  511. data/lib/pubid/nist/identifiers/technical_note.rb +1 -1
  512. data/lib/pubid/nist/identifiers.rb +0 -1
  513. data/lib/pubid/nist/parser.rb +27 -4
  514. data/lib/pubid/nist/preprocessor.rb +15 -0
  515. data/lib/pubid/nist/router.rb +2 -2
  516. data/lib/pubid/nist/series/ir.rb +0 -3
  517. data/lib/pubid/nist/supplement_identifier.rb +24 -9
  518. data/lib/pubid/nist.rb +19 -13
  519. data/lib/pubid/oasis/builder.rb +79 -0
  520. data/lib/pubid/oasis/identifier.rb +160 -0
  521. data/lib/pubid/oasis/identifiers/standard.rb +29 -0
  522. data/lib/pubid/oasis/identifiers.rb +9 -0
  523. data/lib/pubid/oasis/parser.rb +34 -0
  524. data/lib/pubid/oasis/renderer.rb +29 -0
  525. data/lib/pubid/oasis/urn_generator.rb +25 -0
  526. data/lib/pubid/oasis/urn_parser.rb +22 -0
  527. data/lib/pubid/oasis.rb +80 -0
  528. data/lib/pubid/ogc/builder.rb +33 -0
  529. data/lib/pubid/ogc/identifier.rb +81 -0
  530. data/lib/pubid/ogc/identifiers/document.rb +26 -0
  531. data/lib/pubid/ogc/identifiers.rb +10 -0
  532. data/lib/pubid/ogc/parser.rb +40 -0
  533. data/lib/pubid/ogc/renderer.rb +33 -0
  534. data/lib/pubid/ogc/urn_generator.rb +14 -0
  535. data/lib/pubid/ogc/urn_parser.rb +22 -0
  536. data/lib/pubid/ogc.rb +72 -0
  537. data/lib/pubid/oiml/builder.rb +36 -8
  538. data/lib/pubid/oiml/identifier.rb +9 -1
  539. data/lib/pubid/oiml/identifiers/basic_publication.rb +2 -0
  540. data/lib/pubid/oiml/identifiers/bulletin.rb +36 -0
  541. data/lib/pubid/oiml/identifiers/code_number.rb +90 -0
  542. data/lib/pubid/oiml/identifiers/document.rb +2 -0
  543. data/lib/pubid/oiml/identifiers/expert_report.rb +2 -0
  544. data/lib/pubid/oiml/identifiers/guide.rb +2 -0
  545. data/lib/pubid/oiml/identifiers/recommendation.rb +2 -0
  546. data/lib/pubid/oiml/identifiers/seminar_report.rb +2 -0
  547. data/lib/pubid/oiml/identifiers/vocabulary.rb +2 -0
  548. data/lib/pubid/oiml/identifiers.rb +1 -0
  549. data/lib/pubid/oiml/parser.rb +12 -13
  550. data/lib/pubid/oiml/renderer.rb +13 -13
  551. data/lib/pubid/oiml/single_identifier.rb +41 -37
  552. data/lib/pubid/oiml/supplement_identifier.rb +36 -9
  553. data/lib/pubid/oiml/urn_parser.rb +23 -6
  554. data/lib/pubid/oiml.rb +10 -0
  555. data/lib/pubid/omg/builder.rb +20 -0
  556. data/lib/pubid/omg/identifier.rb +61 -0
  557. data/lib/pubid/omg/identifiers/specification.rb +32 -0
  558. data/lib/pubid/omg/identifiers.rb +9 -0
  559. data/lib/pubid/omg/parser.rb +93 -0
  560. data/lib/pubid/omg/renderer.rb +31 -0
  561. data/lib/pubid/omg.rb +52 -0
  562. data/lib/pubid/parser/grammar.rb +74 -0
  563. data/lib/pubid/parser.rb +2 -0
  564. data/lib/pubid/parsers/mr_string.rb +120 -7
  565. data/lib/pubid/plateau/builder.rb +8 -4
  566. data/lib/pubid/plateau/identifier.rb +1 -3
  567. data/lib/pubid/plateau/identifiers/base.rb +1 -6
  568. data/lib/pubid/plateau/identifiers/handbook.rb +1 -1
  569. data/lib/pubid/plateau/identifiers/technical_report.rb +1 -1
  570. data/lib/pubid/plateau/identifiers.rb +0 -1
  571. data/lib/pubid/plateau/parser.rb +16 -6
  572. data/lib/pubid/plateau/renderer.rb +1 -1
  573. data/lib/pubid/plateau/supplement_identifier.rb +11 -11
  574. data/lib/pubid/plateau.rb +14 -4
  575. data/lib/pubid/prefixes_support.rb +1 -0
  576. data/lib/pubid/renderers/annotator.rb +233 -0
  577. data/lib/pubid/renderers/base.rb +13 -0
  578. data/lib/pubid/renderers/directives_renderer.rb +3 -3
  579. data/lib/pubid/renderers/human_readable.rb +6 -4
  580. data/lib/pubid/renderers/mr_string.rb +54 -6
  581. data/lib/pubid/renderers/supplement_renderer.rb +1 -1
  582. data/lib/pubid/renderers.rb +1 -0
  583. data/lib/pubid/rendering/numbering.rb +25 -7
  584. data/lib/pubid/rendering/supplement.rb +4 -4
  585. data/lib/pubid/rendering.rb +1 -0
  586. data/lib/pubid/sae/builder.rb +1 -1
  587. data/lib/pubid/sae/identifier.rb +1 -3
  588. data/lib/pubid/sae/identifiers/base.rb +19 -9
  589. data/lib/pubid/sae/identifiers.rb +0 -1
  590. data/lib/pubid/sae/parser.rb +1 -1
  591. data/lib/pubid/sae.rb +4 -3
  592. data/lib/pubid/schema/declaration.rb +33 -0
  593. data/lib/pubid/schema/error.rb +14 -0
  594. data/lib/pubid/schema/identifier_type.rb +23 -0
  595. data/lib/pubid/schema/loader.rb +117 -0
  596. data/lib/pubid/schema/typed_stage.rb +24 -0
  597. data/lib/pubid/schema.rb +25 -0
  598. data/lib/pubid/tgpp/builder.rb +41 -0
  599. data/lib/pubid/tgpp/identifier.rb +107 -0
  600. data/lib/pubid/tgpp/identifiers/technical_report.rb +32 -0
  601. data/lib/pubid/tgpp/identifiers/technical_specification.rb +33 -0
  602. data/lib/pubid/tgpp/identifiers.rb +11 -0
  603. data/lib/pubid/tgpp/parser.rb +78 -0
  604. data/lib/pubid/tgpp/renderer.rb +52 -0
  605. data/lib/pubid/tgpp/urn_generator.rb +39 -0
  606. data/lib/pubid/tgpp/urn_parser.rb +30 -0
  607. data/lib/pubid/tgpp.rb +84 -0
  608. data/lib/pubid/type_resolver.rb +74 -0
  609. data/lib/pubid/un/builder.rb +42 -0
  610. data/lib/pubid/un/identifier.rb +40 -0
  611. data/lib/pubid/un/identifiers/document.rb +24 -0
  612. data/lib/pubid/un/identifiers.rb +9 -0
  613. data/lib/pubid/un/parser.rb +25 -0
  614. data/lib/pubid/un/renderer.rb +11 -0
  615. data/lib/pubid/un.rb +47 -0
  616. data/lib/pubid/urn_parser/errors.rb +8 -1
  617. data/lib/pubid/urn_parser.rb +1 -0
  618. data/lib/pubid/utils.rb +1 -0
  619. data/lib/pubid/version.rb +1 -1
  620. data/lib/pubid/w3c/builder.rb +55 -0
  621. data/lib/pubid/w3c/identifier.rb +130 -0
  622. data/lib/pubid/w3c/identifiers/candidate_recommendation.rb +31 -0
  623. data/lib/pubid/w3c/identifiers/candidate_recommendation_draft.rb +31 -0
  624. data/lib/pubid/w3c/identifiers/draft_note.rb +31 -0
  625. data/lib/pubid/w3c/identifiers/note.rb +30 -0
  626. data/lib/pubid/w3c/identifiers/obsolete_recommendation.rb +31 -0
  627. data/lib/pubid/w3c/identifiers/proposed_edited_recommendation.rb +31 -0
  628. data/lib/pubid/w3c/identifiers/proposed_recommendation.rb +31 -0
  629. data/lib/pubid/w3c/identifiers/recommendation.rb +31 -0
  630. data/lib/pubid/w3c/identifiers/standard.rb +12 -0
  631. data/lib/pubid/w3c/identifiers/superseded_recommendation.rb +31 -0
  632. data/lib/pubid/w3c/identifiers/working_draft.rb +30 -0
  633. data/lib/pubid/w3c/identifiers.rb +25 -0
  634. data/lib/pubid/w3c/parser.rb +43 -0
  635. data/lib/pubid/w3c/renderer.rb +35 -0
  636. data/lib/pubid/w3c/urn_generator.rb +18 -0
  637. data/lib/pubid/w3c/urn_parser.rb +36 -0
  638. data/lib/pubid/w3c.rb +68 -0
  639. data/lib/pubid/xsf/builder.rb +17 -0
  640. data/lib/pubid/xsf/identifier.rb +66 -0
  641. data/lib/pubid/xsf/identifiers/xep.rb +31 -0
  642. data/lib/pubid/xsf/identifiers.rb +9 -0
  643. data/lib/pubid/xsf/parser.rb +38 -0
  644. data/lib/pubid/xsf/renderer.rb +23 -0
  645. data/lib/pubid/xsf/urn_generator.rb +13 -0
  646. data/lib/pubid/xsf/urn_parser.rb +18 -0
  647. data/lib/pubid/xsf.rb +82 -0
  648. data/lib/pubid.rb +424 -22
  649. data/lib/tasks/conformance.rake +34 -0
  650. data/lib/tasks/docs.rake +3 -3
  651. data/lib/tasks/schema.rake +88 -0
  652. data/schema/core/joint_prefixes.yaml +24 -0
  653. data/schema/iec.yaml +1017 -0
  654. data/schema/iso.yaml +1586 -0
  655. data/schema/schema.schema.yaml +96 -0
  656. metadata +241 -19
  657. data/archived-gems/pubid-ccsds/update_codes.yaml +0 -1
  658. data/archived-gems/pubid-iec/stages.yaml +0 -129
  659. data/archived-gems/pubid-iec/update_codes.yaml +0 -67
  660. data/archived-gems/pubid-ieee/update_codes.yaml +0 -104
  661. data/archived-gems/pubid-iso/stages.yaml +0 -106
  662. data/archived-gems/pubid-iso/update_codes.yaml +0 -4
  663. data/archived-gems/pubid-itu/i18n.yaml +0 -13
  664. data/archived-gems/pubid-itu/series.yaml +0 -42
  665. data/archived-gems/pubid-nist/publishers.yaml +0 -6
  666. data/archived-gems/pubid-nist/update_codes.yaml +0 -93
  667. data/archived-gems/pubid-plateau/update_codes.yaml +0 -6
  668. data/lib/pubid/cen_cenelec/supplement_identifier.rb +0 -48
  669. data/lib/pubid/cie/components/code.rb +0 -80
  670. data/lib/pubid/iala/identifiers/base.rb +0 -14
  671. data/lib/pubid/iec/components/code.rb +0 -36
  672. /data/{archived-gems/pubid-nist → data/nist}/stages.yaml +0 -0
@@ -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("-") }
@@ -30,10 +30,11 @@ module Pubid
30
30
  def render_default(id)
31
31
  parts = ["API"]
32
32
 
33
- # Add type if available
34
- if id.class.attributes.key?(:type_string) && id.type_string
35
- parts << id.type_string
36
- end
33
+ # Add the type token (RP, STD, BULL, PUBL, SPEC, TR ...) if the leaf
34
+ # defines one. `type_string` is a plain METHOD on each leaf, never a
35
+ # lutaml attribute, so the old `attributes.key?(:type_string)` guard
36
+ # was always false and the token was dropped from every rendering.
37
+ parts << id.type_string if id.respond_to?(:type_string) && id.type_string
37
38
 
38
39
  # Add code/number with part as one token
39
40
  parts << code_portion(id) if code_portion(id)
@@ -48,7 +49,7 @@ module Pubid
48
49
  parts = ["API", "MPMS"]
49
50
 
50
51
  # Add chapter
51
- parts << "CH #{id.chapter}" if id.chapter
52
+ parts << "CH #{id.number}" if id.number
52
53
 
53
54
  # Add section/subsection
54
55
  if id.section
@@ -77,10 +78,18 @@ module Pubid
77
78
  parts.join(" ")
78
79
  end
79
80
 
81
+ # The document number plus its part, as one token.
82
+ #
83
+ # This used to read a `code` attribute that NOTHING ever assigned — the
84
+ # parser emits no `:code` key and the builder never sets one — so it
85
+ # always returned nil and 163 of API's 193 corpus identifiers rendered
86
+ # as the bare publisher "API". That string is both the document number
87
+ # and the output filename, so they all collapsed onto each other.
88
+ # `number` is what Builder#cast actually populates.
80
89
  def code_portion(id)
81
- return nil unless id.code
90
+ return nil unless id.number
82
91
 
83
- code_str = id.code.to_s
92
+ code_str = id.number.to_s
84
93
  code_str += "-#{id.part}" if id.part
85
94
  code_str
86
95
  end
@@ -12,20 +12,13 @@ module Pubid
12
12
  # serialize a String against the Components::Publisher attribute.
13
13
  attribute :publisher, :string, default: -> { "API" }
14
14
 
15
- attribute :code, Components::Code
16
- attribute :part, :string
15
+ # `number` and `part` are inherited as :string from
16
+ # Pubid::Api::Identifier. There is deliberately no `code` attribute: one
17
+ # existed here typed Components::Code, but nothing ever assigned it
18
+ # (the parser emits no `:code` key), so it only misdirected
19
+ # Renderer#code_portion away from the `number` the builder populates.
17
20
  attribute :year, :string
18
21
  attribute :reaffirmation, :string
19
-
20
- private
21
-
22
- def code_portion
23
- return nil unless code
24
-
25
- code_str = code.to_s
26
- code_str += "-#{part}" if part
27
- code_str
28
- end
29
22
  end
30
23
  end
31
24
  end
data/lib/pubid/api.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  module Pubid
4
5
  module Api
5
6
  extend Pubid::PrefixesSupport
@@ -7,7 +7,7 @@ module Pubid
7
7
  class Builder
8
8
  attr_reader :identifier_class
9
9
 
10
- def initialize(identifier_class = Identifiers::Base)
10
+ def initialize(identifier_class = Identifier)
11
11
  @identifier_class = identifier_class
12
12
  end
13
13
 
@@ -39,6 +39,18 @@ module Pubid
39
39
  return build_addendum_no_type(parsed_hash[:addendum_no_type])
40
40
  elsif parsed_hash[:standard_addendum]
41
41
  return build_standard_addendum(parsed_hash[:standard_addendum])
42
+ # These two grammar rules had NO dispatch branch, so they fell through
43
+ # to the plain-identifier path below. That path looks for
44
+ # publisher/type/code at the TOP of the hash, finds only the wrapper
45
+ # key, and builds an empty Standard — 123 corpus ids rendered as the
46
+ # bare string "ASHRAE Standard ". Both subtrees are flat and carry
47
+ # exactly the keys #build_addendum_from_identifier already reads.
48
+ elsif parsed_hash[:addendum]
49
+ return build_addendum_from_identifier(parsed_hash[:addendum])
50
+ elsif parsed_hash[:publisher_base_addendum]
51
+ return build_addendum_from_identifier(
52
+ parsed_hash[:publisher_base_addendum],
53
+ )
42
54
  end
43
55
 
44
56
  # Handle base identifier
@@ -53,7 +65,7 @@ module Pubid
53
65
 
54
66
  # Class method to build an identifier from parsed data
55
67
  # @param parsed [Hash, Array] the parsed identifier data
56
- # @return [Identifiers::Base] the constructed identifier object
68
+ # @return [Identifier] the constructed identifier object
57
69
  def self.build(parsed)
58
70
  new.build(parsed)
59
71
  end
@@ -89,7 +101,7 @@ module Pubid
89
101
  # code_with_year contains both code and year
90
102
  code_year_data = parsed[:code_with_year]
91
103
  if code_year_data && code_year_data[:code]
92
- attributes[:code] =
104
+ attributes[:number] =
93
105
  extract_value(code_year_data[:code])
94
106
  end
95
107
  if code_year_data && code_year_data[:year]
@@ -97,7 +109,7 @@ module Pubid
97
109
  extract_value(code_year_data[:year])
98
110
  end
99
111
  elsif parsed[:code]
100
- attributes[:code] = extract_value(parsed[:code])
112
+ attributes[:number] = extract_value(parsed[:code])
101
113
  end
102
114
 
103
115
  # Extract year if not already extracted from code_with_year
@@ -158,12 +170,12 @@ module Pubid
158
170
  def build_errata(parsed)
159
171
  base_attrs = extract_base_attributes(parsed)
160
172
  base_class = determine_identifier_class(base_attrs)
161
- base_identifier = base_class.new(**base_attrs)
173
+ base = base_class.new(**base_attrs)
162
174
 
163
175
  errata_date = extract_errata_date(parsed[:errata_date])
164
176
 
165
177
  Identifiers::Errata.new(
166
- base_identifier: base_identifier,
178
+ base: base,
167
179
  errata_date: errata_date,
168
180
  )
169
181
  end
@@ -174,10 +186,10 @@ module Pubid
174
186
  def build_interpretation(parsed)
175
187
  base_attrs = extract_base_attributes(parsed)
176
188
  base_class = determine_identifier_class(base_attrs)
177
- base_identifier = base_class.new(**base_attrs)
189
+ base = base_class.new(**base_attrs)
178
190
 
179
191
  Identifiers::Interpretation.new(
180
- base_identifier: base_identifier,
192
+ base: base,
181
193
  )
182
194
  end
183
195
 
@@ -187,13 +199,13 @@ module Pubid
187
199
  def build_addendum_from_identifier(parsed)
188
200
  base_attrs = extract_base_attributes(parsed)
189
201
  base_class = determine_identifier_class(base_attrs)
190
- base_identifier = base_class.new(**base_attrs)
202
+ base = base_class.new(**base_attrs)
191
203
 
192
204
  addendum_code = extract_value(parsed[:addendum_code])
193
205
  addendum_date = extract_addendum_date(parsed[:addendum_year])
194
206
 
195
207
  Identifiers::Addendum.new(
196
- base_identifier: base_identifier,
208
+ base: base,
197
209
  addendum_code: addendum_code,
198
210
  addendum_date: addendum_date,
199
211
  )
@@ -205,17 +217,17 @@ module Pubid
205
217
  def build_publisher_addendum(parsed)
206
218
  base_attrs = {
207
219
  type: extract_value(parsed[:type]),
208
- code: extract_value(parsed[:code]),
220
+ number: extract_value(parsed[:code]),
209
221
  year: extract_value(parsed[:year]),
210
222
  }
211
223
  base_class = determine_identifier_class(base_attrs)
212
- base_identifier = base_class.new(**base_attrs)
224
+ base = base_class.new(**base_attrs)
213
225
 
214
226
  addendum_code = extract_value(parsed[:addendum_code])
215
227
  addendum_date = extract_addendum_date(parsed[:addendum_year])
216
228
 
217
229
  Identifiers::Addendum.new(
218
- base_identifier: base_identifier,
230
+ base: base,
219
231
  addendum_code: addendum_code,
220
232
  addendum_date: addendum_date,
221
233
  )
@@ -228,17 +240,17 @@ module Pubid
228
240
  base_attrs = {
229
241
  copublisher: extract_value(parsed[:copublisher]),
230
242
  type: extract_value(parsed[:type]) || "Standard",
231
- code: extract_value(parsed[:code]),
243
+ number: extract_value(parsed[:code]),
232
244
  year: extract_value(parsed[:year]),
233
245
  }
234
246
  base_class = determine_identifier_class(base_attrs)
235
- base_identifier = base_class.new(**base_attrs)
247
+ base = base_class.new(**base_attrs)
236
248
 
237
249
  addendum_code = extract_value(parsed[:addendum_code])
238
250
  addendum_date = extract_addendum_date(parsed[:addendum_year])
239
251
 
240
252
  Identifiers::Addendum.new(
241
- base_identifier: base_identifier,
253
+ base: base,
242
254
  addendum_code: addendum_code,
243
255
  addendum_date: addendum_date,
244
256
  )
@@ -260,7 +272,7 @@ module Pubid
260
272
  if parsed[:code_with_year]
261
273
  code_year_data = parsed[:code_with_year]
262
274
  if code_year_data && code_year_data[:code]
263
- base_attrs[:code] =
275
+ base_attrs[:number] =
264
276
  extract_value(code_year_data[:code])
265
277
  end
266
278
  if code_year_data && code_year_data[:year]
@@ -270,13 +282,13 @@ module Pubid
270
282
  end
271
283
 
272
284
  base_class = determine_identifier_class(base_attrs)
273
- base_identifier = base_class.new(**base_attrs)
285
+ base = base_class.new(**base_attrs)
274
286
 
275
287
  addendum_code = extract_value(parsed[:addendum_code])
276
288
  addendum_date = extract_addendum_date(parsed[:addendum_year])
277
289
 
278
290
  Identifiers::Addendum.new(
279
- base_identifier: base_identifier,
291
+ base: base,
280
292
  addendum_code: addendum_code,
281
293
  addendum_date: addendum_date,
282
294
  )
@@ -298,7 +310,7 @@ module Pubid
298
310
  if parsed[:code_with_year]
299
311
  code_year_data = parsed[:code_with_year]
300
312
  if code_year_data && code_year_data[:code]
301
- base_attrs[:code] =
313
+ base_attrs[:number] =
302
314
  extract_value(code_year_data[:code])
303
315
  end
304
316
  if code_year_data && code_year_data[:year]
@@ -308,13 +320,13 @@ module Pubid
308
320
  end
309
321
 
310
322
  base_class = determine_identifier_class(base_attrs)
311
- base_identifier = base_class.new(**base_attrs)
323
+ base = base_class.new(**base_attrs)
312
324
 
313
325
  addendum_code = extract_value(parsed[:addendum_code])
314
326
  addendum_date = extract_addendum_date(parsed[:addendum_year])
315
327
 
316
328
  Identifiers::Addendum.new(
317
- base_identifier: base_identifier,
329
+ base: base,
318
330
  addendum_code: addendum_code,
319
331
  addendum_date: addendum_date,
320
332
  )
@@ -326,13 +338,13 @@ module Pubid
326
338
  def build_standard_addendum(parsed)
327
339
  base_attrs = extract_base_attributes(parsed)
328
340
  base_class = determine_identifier_class(base_attrs)
329
- base_identifier = base_class.new(**base_attrs)
341
+ base = base_class.new(**base_attrs)
330
342
 
331
343
  addendum_code = extract_value(parsed[:addendum_code])
332
344
  addendum_date = extract_addendum_date(parsed[:addendum_year])
333
345
 
334
346
  Identifiers::Addendum.new(
335
- base_identifier: base_identifier,
347
+ base: base,
336
348
  addendum_code: addendum_code,
337
349
  addendum_date: addendum_date,
338
350
  )
@@ -349,7 +361,7 @@ module Pubid
349
361
  if parsed[:code_with_year]
350
362
  code_year_data = parsed[:code_with_year]
351
363
  if code_year_data && code_year_data[:code]
352
- base_attrs[:code] =
364
+ base_attrs[:number] =
353
365
  extract_value(code_year_data[:code])
354
366
  end
355
367
  if code_year_data && code_year_data[:year]
@@ -358,7 +370,7 @@ module Pubid
358
370
  end
359
371
  else
360
372
  base_attrs[:type] = extract_value(parsed[:type]) || "Standard"
361
- base_attrs[:code] = extract_value(parsed[:code])
373
+ base_attrs[:number] = extract_value(parsed[:code])
362
374
  base_attrs[:year] = extract_value(parsed[:year])
363
375
  end
364
376
 
@@ -372,7 +384,7 @@ module Pubid
372
384
  end
373
385
 
374
386
  base_class = determine_identifier_class(base_attrs)
375
- base_identifier = base_class.new(**base_attrs)
387
+ base = base_class.new(**base_attrs)
376
388
 
377
389
  # Build the addendum_codes string from first code and additional codes
378
390
  first_code = extract_value(parsed[:addendum_code])
@@ -406,7 +418,7 @@ module Pubid
406
418
  end
407
419
 
408
420
  Identifiers::CombinedAddenda.new(
409
- base_identifier: base_identifier,
421
+ base: base,
410
422
  addendum_codes: addendum_codes_str,
411
423
  )
412
424
  end
@@ -417,12 +429,12 @@ module Pubid
417
429
  def build_addenda_package(parsed)
418
430
  base_attrs = extract_base_attributes(parsed)
419
431
  base_class = determine_identifier_class(base_attrs)
420
- base_identifier = base_class.new(**base_attrs)
432
+ base = base_class.new(**base_attrs)
421
433
 
422
434
  package_description = extract_value(parsed[:package_description])
423
435
 
424
436
  Identifiers::AddendaPackage.new(
425
- base_identifier: base_identifier,
437
+ base: base,
426
438
  package_description: package_description,
427
439
  )
428
440
  end
@@ -431,6 +443,15 @@ module Pubid
431
443
  # @param parsed [Hash] the parsed data
432
444
  # @return [Hash] attributes for base identifier
433
445
  def extract_base_attributes(parsed)
446
+ # Unwrap the `:base` subtree the supplement grammars nest the base
447
+ # document under. Builder#build does this for the plain-identifier
448
+ # path, but the five supplement builders that call this method all
449
+ # passed the WHOLE parse hash — so every lookup below missed and the
450
+ # base was built with nothing. 318 Errata rendered as the identical
451
+ # string "ASHRAE Standard Errata"; doing it here fixes all five call
452
+ # sites at once, rather than repeating the unwrap in each.
453
+ parsed = parsed[:base] if parsed.is_a?(Hash) && parsed[:base]
454
+
434
455
  attributes = {}
435
456
 
436
457
  if parsed[:publisher]
@@ -448,7 +469,7 @@ module Pubid
448
469
  if parsed[:code_with_year]
449
470
  code_year_data = parsed[:code_with_year]
450
471
  if code_year_data && code_year_data[:code]
451
- attributes[:code] =
472
+ attributes[:number] =
452
473
  extract_value(code_year_data[:code])
453
474
  end
454
475
  if code_year_data && code_year_data[:year]
@@ -456,7 +477,7 @@ module Pubid
456
477
  extract_value(code_year_data[:year])
457
478
  end
458
479
  else
459
- attributes[:code] = extract_value(parsed[:code]) if parsed[:code]
480
+ attributes[:number] = extract_value(parsed[:code]) if parsed[:code]
460
481
  attributes[:year] = extract_value(parsed[:year]) if parsed[:year]
461
482
  end
462
483
 
@@ -3,7 +3,6 @@
3
3
  # The ASHRAE flavor base class is Pubid::Ashrae::Identifier — a real
4
4
  # Pubid::Identifier subclass that every concrete ASHRAE identifier descends
5
5
  # from, so `is_a?` identity and the shared polymorphic `from_hash` work natively
6
- # (no facade needed). Its body, `.parse`, and the Identifiers::Base back-compat
7
- # alias live in identifiers/base.rb; this file just ensures it is loaded when a
8
- # consumer references Pubid::Ashrae::Identifier directly.
9
- require_relative "identifiers/base"
6
+ # (no facade needed). Its body and `.parse` live in identifiers/base.rb; this
7
+ # file just ensures it is loaded when a consumer references
8
+ # Pubid::Ashrae::Identifier directly.
@@ -14,6 +14,12 @@ module Pubid
14
14
  class AddendaPackage < SupplementIdentifier
15
15
  attribute :package_description, :string # e.g., "Addenda Supplement Package"
16
16
 
17
+ # See Errata.
18
+ def mr_supplement_suffix
19
+ ["pkg", mr_sanitize(package_description)]
20
+ .compact.reject(&:empty?).join(".")
21
+ end
22
+
17
23
  TYPED_STAGES = [
18
24
  Components::TypedStage.new(
19
25
  abbr: ["Addenda Supplement Package", "Addenda Package"],
@@ -28,7 +34,7 @@ module Pubid
28
34
  end
29
35
 
30
36
  def copublisher
31
- base_identifier&.copublisher
37
+ base&.copublisher
32
38
  end
33
39
  end
34
40
  end
@@ -15,6 +15,14 @@ module Pubid
15
15
  attribute :addendum_code, :string # a, b, c, ..., aa, ab, ..., ba, etc.
16
16
  attribute :addendum_date, :string # Optional date (January 22, 2019)
17
17
 
18
+ # See Errata: the renderer must recurse into `base`. The addendum
19
+ # letter is what distinguishes addendum a from addendum b of one
20
+ # standard, so it belongs in the slug as well as in `==`.
21
+ def mr_supplement_suffix
22
+ ["add", addendum_code&.to_s&.downcase]
23
+ .compact.reject(&:empty?).join(".")
24
+ end
25
+
18
26
  TYPED_STAGES = [
19
27
  Components::TypedStage.new(
20
28
  abbr: ["Addendum", "Addenda"],
@@ -28,7 +36,7 @@ module Pubid
28
36
  end
29
37
 
30
38
  def copublisher
31
- base_identifier&.copublisher
39
+ base&.copublisher
32
40
  end
33
41
  end
34
42
  end
@@ -3,35 +3,117 @@
3
3
  module Pubid
4
4
  module Ashrae
5
5
  # Base class for all ASHRAE identifiers. Canonical name
6
- # Pubid::Ashrae::Identifier; every concrete ASHRAE identifier descends from
7
- # it, and Identifiers::Base — aliased at the foot of this file — points back
8
- # to it.
6
+ # Pubid::Ashrae::Identifier; every concrete ASHRAE identifier descends from it.
9
7
  class Identifier < ::Pubid::Identifier
10
8
  # Parse an ASHRAE identifier string into an identifier object
11
9
  # @param identifier [String] The ASHRAE identifier string to parse
12
10
  # @return [Pubid::Ashrae::Identifier] The appropriate identifier object
13
- # @raise [Parslet::ParseFailed] If parsing fails
11
+ # @raise [Pubid::Errors::ParseError] If parsing fails
14
12
  def self.parse(identifier)
15
13
  parsed = Parser.parse(identifier)
16
14
  Builder.build(parsed)
17
- rescue Parslet::ParseFailed => e
18
- raise "Failed to parse ASHRAE identifier '#{identifier}': #{e.message}"
19
15
  end
20
16
 
21
17
  attribute :publisher, :string, default: "ASHRAE"
22
- attribute :code, :string
18
+ # The document number used to live here as `attribute :code, :string`,
19
+ # leaving the `number` inherited from ::Pubid::Identifier nil — so
20
+ # relaton-index, which sorts and bsearches on `id.root.number.to_s`,
21
+ # keyed all 3,619 ASHRAE rows on "".
22
+ #
23
+ # It is now `attribute :number, :string` on the two single-document
24
+ # LEAVES (Identifiers::Standard and Identifiers::Guideline), never here:
25
+ # this class is inherited by BOTH SingleIdentifier and
26
+ # SupplementIdentifier, and redefining the parent's Components::Code-typed
27
+ # `number` on an inherited-from class resolves nondeterministically under
28
+ # multi-flavor load. The supplement types carry no number of their own —
29
+ # they reach it through #root, which walks `base`.
23
30
  attribute :year, :string
24
31
  attribute :type, :string
25
32
  attribute :suffix, :string # R (revision), P (proposed), etc.
26
33
  attribute :amendment, :string
27
34
  attribute :reaffirmed, :string
28
35
  attribute :copublisher, :string
29
- end
30
36
 
31
- module Identifiers
32
- # Backward-compatible alias: ASHRAE's base class used to be
33
- # Pubid::Ashrae::Identifiers::Base. It is now Pubid::Ashrae::Identifier.
34
- Base = Pubid::Ashrae::Identifier
37
+ # --- MR slug hooks -------------------------------------------------
38
+ #
39
+ # ASHRAE supplied none, and every base hook looks for something ASHRAE
40
+ # does not use: `mr_type` reads a typed_stage, `mr_year` reads a
41
+ # Components::Date. With `number` nil too, ALL 3,619 ids collapsed onto
42
+ # the single slug "ashrae" — the worst collapse measured in the gem, and
43
+ # `to_slug` is what consumers use as an output FILENAME.
44
+ #
45
+ # `type` distinguishes a Guideline from a Standard of the same number
46
+ # (Guideline 0 and Standard 0 are different documents), so it has to
47
+ # reach the slug and not only `==`.
48
+ def mr_type
49
+ type&.to_s&.downcase
50
+ end
51
+
52
+ # ASHRAE keeps its edition in a plain `year` string, not the inherited
53
+ # `date`, so the base hook read nil and every edition of one standard
54
+ # shared a slug.
55
+ def mr_year
56
+ year&.to_s
57
+ end
58
+
59
+ # `copublisher` is in `==` and in `to_s`, so by the project rule it has to
60
+ # reach the slug too: "ASHRAE Standard 15-2019 Addendum a" and
61
+ # "ANSI/ASHRAE Addendum a to ANSI/ASHRAE Standard 15-2019" have different
62
+ # hashes and would otherwise share a filename. (Whether those two strings
63
+ # ought to normalise to ONE identifier is a separate question, and not one
64
+ # the slug should paper over.)
65
+ def mr_publisher
66
+ mr_sanitize(copublisher || publisher)
67
+ end
68
+
69
+ # Both trailing markers are identity-bearing and must reach the slug, not
70
+ # only `==`: `reaffirmed` ("RA 2017") separates "ANSI/ASHRAE Standard
71
+ # 206-2013 (RA 2017)" from the plain "…206-2013", and `suffix` ("R" for
72
+ # revision, "P" for proposed) separates "ASHRAE Guideline 27-2019" from
73
+ # "…27-2019R". Their hashes differ, so their filenames must too.
74
+ # Uses the shared #mr_join rather than a bare `compact.join("-")`, so it
75
+ # returns nil instead of "" when nothing survives: MrString's own
76
+ # `compact` drops nil but not the empty string, and a blank segment
77
+ # yields a double dot in the joined slug.
78
+ def mr_number_with_part
79
+ mr_join(mr_sanitize(number),
80
+ (reaffirmed ? "ra#{mr_sanitize(reaffirmed)}" : nil),
81
+ mr_sanitize(suffix))
82
+ end
83
+
84
+ # An ASHRAE value can carry characters outside the [a-z0-9.-] charset
85
+ # Renderers::MrString documents: a comma in the code "90A,B,C", a slash
86
+ # in the copublisher "ANSI/ASHRAE", spaces in a package description.
87
+ # Filter BY CHARSET (the BIPM `mr_slug` precedent) rather than by an
88
+ # enumerated escape list, so a character introduced later cannot reach a
89
+ # filename.
90
+ #
91
+ # Public alongside the hooks above rather than tucked behind `private`,
92
+ # since the whole MR surface here is public, and the supplement types
93
+ # call it from their own mr_supplement_suffix. The output emptiness check
94
+ # matters: a value made only of out-of-charset characters collapses to
95
+ # "", which is truthy in Ruby and would reach the renderer as a blank
96
+ # segment, producing a double dot in the joined slug.
97
+ def mr_sanitize(value)
98
+ return nil if value.nil? || value.to_s.empty?
99
+
100
+ sanitized = value.to_s.downcase
101
+ .gsub(%r{[^a-z0-9.-]+}, "-").gsub(%r{\A-+|-+\z}, "")
102
+ sanitized.empty? ? nil : sanitized
103
+ end
104
+
105
+ # ASHRAE stores the publication year in a plain :string scalar, not a
106
+ # Components::Date, so the base #exclude's :year->:date remap cannot nil
107
+ # it. Reset the scalar directly (mirroring CSA/BIPM) so a year-less
108
+ # partial reference is a year wildcard under
109
+ # matches?(other, ignore: [:year]). super still recurses into the nested
110
+ # `base` of wrapper types (Errata/Addendum/…), which carry no year scalar.
111
+ def exclude(*args)
112
+ result = super
113
+ year_keys = args & %i[year date]
114
+ result.year = nil if !year_keys.empty? && result.respond_to?(:year=)
115
+ result
116
+ end
35
117
  end
36
118
  end
37
119
  end
@@ -14,6 +14,13 @@ module Pubid
14
14
  attribute :addendum_codes, :string # Multiple codes like "c and d"
15
15
  attribute :connector, :string # "and" or ","
16
16
 
17
+ # See Errata. The whole letter list is the identity here — "Addenda a,
18
+ # b" and "Addenda c, d" of one standard are different documents.
19
+ def mr_supplement_suffix
20
+ ["adds", mr_sanitize(addendum_codes)]
21
+ .compact.reject(&:empty?).join(".")
22
+ end
23
+
17
24
  TYPED_STAGES = [
18
25
  Components::TypedStage.new(
19
26
  abbr: ["Addenda", "Combined Addenda"],
@@ -28,7 +35,7 @@ module Pubid
28
35
  end
29
36
 
30
37
  def copublisher
31
- base_identifier&.copublisher
38
+ base&.copublisher
32
39
  end
33
40
  end
34
41
  end