pubid 2.0.0.pre.alpha.9 → 2.0.0.pre.alpha.12

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 (461) 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/components/date.rb +10 -4
  82. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +36 -7
  83. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +7 -6
  84. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +1 -2
  85. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +10 -0
  86. data/lib/pubid/bsi/identifiers/committee_document.rb +10 -1
  87. data/lib/pubid/bsi/identifiers/handbook.rb +1 -3
  88. data/lib/pubid/bsi/identifiers/practice_guide.rb +1 -2
  89. data/lib/pubid/bsi/identifiers/set.rb +11 -0
  90. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +10 -1
  91. data/lib/pubid/bsi/parser.rb +1 -1
  92. data/lib/pubid/bsi/renderer.rb +63 -51
  93. data/lib/pubid/bsi/single_identifier.rb +27 -9
  94. data/lib/pubid/bsi/urn_generator.rb +11 -2
  95. data/lib/pubid/bsi.rb +7 -1
  96. data/lib/pubid/builder/base.rb +18 -8
  97. data/lib/pubid/bundled_identifier.rb +16 -6
  98. data/lib/pubid/calconnect/identifier.rb +9 -5
  99. data/lib/pubid/calconnect/parser.rb +1 -1
  100. data/lib/pubid/calconnect.rb +7 -1
  101. data/lib/pubid/ccsds/identifier.rb +13 -2
  102. data/lib/pubid/ccsds/identifiers/base.rb +4 -2
  103. data/lib/pubid/ccsds/identifiers/corrigendum.rb +2 -2
  104. data/lib/pubid/ccsds/parser.rb +1 -1
  105. data/lib/pubid/ccsds/single_identifier.rb +16 -12
  106. data/lib/pubid/ccsds.rb +1 -0
  107. data/lib/pubid/cen_cenelec/builder.rb +101 -76
  108. data/lib/pubid/cen_cenelec/identifier.rb +115 -3
  109. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +27 -16
  110. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +46 -6
  111. data/lib/pubid/cen_cenelec/identifiers/base.rb +8 -9
  112. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +1 -1
  113. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +1 -1
  114. data/lib/pubid/cen_cenelec/identifiers/cenelec_harmonization_document.rb +1 -1
  115. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +29 -20
  116. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +47 -8
  117. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +27 -2
  118. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +1 -1
  119. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +15 -5
  120. data/lib/pubid/cen_cenelec/identifiers/guide.rb +1 -1
  121. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +1 -1
  122. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +1 -1
  123. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +1 -1
  124. data/lib/pubid/cen_cenelec/parser.rb +1 -1
  125. data/lib/pubid/cen_cenelec/renderer.rb +55 -60
  126. data/lib/pubid/cen_cenelec/single_identifier.rb +20 -2
  127. data/lib/pubid/cen_cenelec/urn_generator.rb +66 -44
  128. data/lib/pubid/cen_cenelec.rb +28 -10
  129. data/lib/pubid/cie/builder.rb +10 -0
  130. data/lib/pubid/cie/identifier.rb +6 -1
  131. data/lib/pubid/cie/identifiers/bundle.rb +4 -2
  132. data/lib/pubid/cie/identifiers/conference.rb +2 -2
  133. data/lib/pubid/cie/identifiers/corrigendum.rb +2 -2
  134. data/lib/pubid/cie/identifiers/dual_published.rb +2 -2
  135. data/lib/pubid/cie/identifiers/identical.rb +2 -2
  136. data/lib/pubid/cie/identifiers/joint_published.rb +2 -2
  137. data/lib/pubid/cie/identifiers/proceedings.rb +8 -6
  138. data/lib/pubid/cie/identifiers/standard.rb +22 -13
  139. data/lib/pubid/cie/identifiers/supplement.rb +2 -2
  140. data/lib/pubid/cie/identifiers/tutorial_bundle.rb +2 -2
  141. data/lib/pubid/cie/parser.rb +1 -1
  142. data/lib/pubid/cie.rb +7 -1
  143. data/lib/pubid/conformance/checks.rb +72 -0
  144. data/lib/pubid/conformance/corpus/case.rb +55 -0
  145. data/lib/pubid/conformance/corpus.rb +36 -0
  146. data/lib/pubid/conformance/generator.rb +212 -0
  147. data/lib/pubid/conformance/pending.rb +63 -0
  148. data/lib/pubid/conformance/runner.rb +153 -0
  149. data/lib/pubid/conformance.rb +55 -0
  150. data/lib/pubid/core.rb +2 -0
  151. data/lib/pubid/csa/builder.rb +47 -47
  152. data/lib/pubid/csa/composite_identifier.rb +14 -19
  153. data/lib/pubid/csa/identifier.rb +143 -81
  154. data/lib/pubid/csa/identifiers/bundled.rb +23 -13
  155. data/lib/pubid/csa/identifiers/canadian_adopted.rb +13 -13
  156. data/lib/pubid/csa/identifiers/cec.rb +44 -4
  157. data/lib/pubid/csa/identifiers/combined.rb +95 -73
  158. data/lib/pubid/csa/identifiers/csa_adopted.rb +4 -4
  159. data/lib/pubid/csa/identifiers/package.rb +2 -2
  160. data/lib/pubid/csa/parser.rb +6 -2
  161. data/lib/pubid/csa/renderer.rb +13 -5
  162. data/lib/pubid/csa/single_identifier.rb +93 -4
  163. data/lib/pubid/csa/urn_generator.rb +9 -2
  164. data/lib/pubid/csa/wrapper_identifier.rb +39 -23
  165. data/lib/pubid/csa.rb +7 -1
  166. data/lib/pubid/doi/identifier.rb +6 -3
  167. data/lib/pubid/doi/parser.rb +1 -1
  168. data/lib/pubid/doi.rb +1 -0
  169. data/lib/pubid/easc/identifier.rb +0 -2
  170. data/lib/pubid/easc/parser.rb +10 -2
  171. data/lib/pubid/easc.rb +1 -0
  172. data/lib/pubid/ecma/builder.rb +23 -9
  173. data/lib/pubid/ecma/identifier.rb +81 -10
  174. data/lib/pubid/ecma/parser.rb +39 -4
  175. data/lib/pubid/ecma/renderer.rb +29 -8
  176. data/lib/pubid/ecma/urn_generator.rb +34 -13
  177. data/lib/pubid/ecma/urn_parser.rb +30 -14
  178. data/lib/pubid/ecma.rb +1 -0
  179. data/lib/pubid/errors.rb +80 -0
  180. data/lib/pubid/etsi/builder.rb +6 -1
  181. data/lib/pubid/etsi/identifiers/base.rb +34 -20
  182. data/lib/pubid/etsi/identifiers/etsi_standard.rb +120 -41
  183. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +10 -0
  184. data/lib/pubid/etsi/parser.rb +1 -1
  185. data/lib/pubid/etsi.rb +1 -0
  186. data/lib/pubid/evs/builder.rb +26 -0
  187. data/lib/pubid/evs/identifier.rb +37 -0
  188. data/lib/pubid/evs/identifiers/national_adoption.rb +22 -0
  189. data/lib/pubid/evs/identifiers.rb +9 -0
  190. data/lib/pubid/evs/parser.rb +27 -0
  191. data/lib/pubid/evs/renderer.rb +30 -0
  192. data/lib/pubid/evs/urn_generator.rb +30 -0
  193. data/lib/pubid/evs/urn_parser.rb +80 -0
  194. data/lib/pubid/evs.rb +90 -0
  195. data/lib/pubid/export.rb +1 -0
  196. data/lib/pubid/format_detector.rb +1 -0
  197. data/lib/pubid/gb/builder.rb +14 -9
  198. data/lib/pubid/gb/identifier.rb +29 -7
  199. data/lib/pubid/gb/parser.rb +5 -1
  200. data/lib/pubid/gb/renderer.rb +4 -3
  201. data/lib/pubid/gb.rb +2 -0
  202. data/lib/pubid/gost/builder.rb +46 -9
  203. data/lib/pubid/gost/identifier.rb +0 -2
  204. data/lib/pubid/gost/identifiers/foreign_reference.rb +1 -1
  205. data/lib/pubid/gost/parser.rb +10 -2
  206. data/lib/pubid/gost.rb +1 -0
  207. data/lib/pubid/iala/identifier.rb +9 -6
  208. data/lib/pubid/iala/parser.rb +10 -2
  209. data/lib/pubid/iala/urn_parser.rb +6 -2
  210. data/lib/pubid/iala.rb +1 -0
  211. data/lib/pubid/iana/builder.rb +3 -1
  212. data/lib/pubid/iana/identifier.rb +74 -6
  213. data/lib/pubid/iana/identifiers/registry.rb +36 -0
  214. data/lib/pubid/iana/parser.rb +1 -1
  215. data/lib/pubid/iana/renderer.rb +3 -0
  216. data/lib/pubid/iana/urn_generator.rb +5 -1
  217. data/lib/pubid/iana.rb +1 -0
  218. data/lib/pubid/identifier.rb +605 -13
  219. data/lib/pubid/identifier_metadata.rb +1 -0
  220. data/lib/pubid/idf/builder.rb +3 -3
  221. data/lib/pubid/idf/identifier.rb +25 -9
  222. data/lib/pubid/idf/identifiers/amendment.rb +1 -1
  223. data/lib/pubid/idf/identifiers/corrigendum.rb +1 -1
  224. data/lib/pubid/idf/identifiers/international_standard.rb +1 -1
  225. data/lib/pubid/idf/identifiers/reviewed_method.rb +1 -1
  226. data/lib/pubid/idf/parser.rb +1 -1
  227. data/lib/pubid/idf/renderer.rb +4 -4
  228. data/lib/pubid/idf/single_identifier.rb +1 -1
  229. data/lib/pubid/idf/urn_generator.rb +1 -1
  230. data/lib/pubid/idf.rb +7 -1
  231. data/lib/pubid/iec/builder.rb +14 -7
  232. data/lib/pubid/iec/components.rb +0 -1
  233. data/lib/pubid/iec/identifier.rb +73 -83
  234. data/lib/pubid/iec/identifiers/amendment.rb +6 -2
  235. data/lib/pubid/iec/identifiers/component_specification.rb +0 -10
  236. data/lib/pubid/iec/identifiers/conformity_assessment.rb +0 -10
  237. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -2
  238. data/lib/pubid/iec/identifiers/fragment_identifier.rb +2 -4
  239. data/lib/pubid/iec/identifiers/guide.rb +0 -16
  240. data/lib/pubid/iec/identifiers/international_standard.rb +15 -2
  241. data/lib/pubid/iec/identifiers/operational_document.rb +0 -10
  242. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +0 -12
  243. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +0 -10
  244. data/lib/pubid/iec/identifiers/systems_reference_document.rb +0 -10
  245. data/lib/pubid/iec/identifiers/technical_report.rb +0 -17
  246. data/lib/pubid/iec/identifiers/technical_specification.rb +0 -17
  247. data/lib/pubid/iec/identifiers/technology_report.rb +0 -10
  248. data/lib/pubid/iec/identifiers/test_report_form.rb +0 -11
  249. data/lib/pubid/iec/identifiers/white_paper.rb +0 -10
  250. data/lib/pubid/iec/identifiers/working_document.rb +24 -10
  251. data/lib/pubid/iec/parser.rb +2 -18
  252. data/lib/pubid/iec/renderer.rb +13 -10
  253. data/lib/pubid/iec/single_identifier.rb +33 -10
  254. data/lib/pubid/iec/urn_generator.rb +227 -61
  255. data/lib/pubid/iec/urn_parser.rb +42 -4
  256. data/lib/pubid/iec.rb +1 -0
  257. data/lib/pubid/ieee/aiee/identifier.rb +2 -2
  258. data/lib/pubid/ieee/aiee/parser.rb +1 -1
  259. data/lib/pubid/ieee/builder.rb +87 -3
  260. data/lib/pubid/ieee/identifiers/adopted_standard.rb +32 -0
  261. data/lib/pubid/ieee/identifiers/base.rb +42 -5
  262. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +21 -0
  263. data/lib/pubid/ieee/identifiers/dual_published.rb +55 -0
  264. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +23 -0
  265. data/lib/pubid/ieee/identifiers/joint_development.rb +11 -7
  266. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +57 -5
  267. data/lib/pubid/ieee/identifiers/nesc/base.rb +2 -2
  268. data/lib/pubid/ieee/identifiers/nesc/draft.rb +2 -2
  269. data/lib/pubid/ieee/identifiers/nesc/handbook.rb +2 -2
  270. data/lib/pubid/ieee/identifiers/nesc/redline.rb +2 -2
  271. data/lib/pubid/ieee/identifiers/nesc/standard.rb +2 -2
  272. data/lib/pubid/ieee/identifiers/si_standard.rb +5 -2
  273. data/lib/pubid/ieee/ire/identifier.rb +2 -2
  274. data/lib/pubid/ieee/ire/parser.rb +20 -2
  275. data/lib/pubid/ieee/nesc/parser.rb +1 -1
  276. data/lib/pubid/ieee/parser.rb +208 -33
  277. data/lib/pubid/ieee/project_renderer.rb +46 -0
  278. data/lib/pubid/ieee/renderer.rb +11 -8
  279. data/lib/pubid/ieee/urn_generator.rb +32 -3
  280. data/lib/pubid/ieee.rb +9 -1
  281. data/lib/pubid/ieee_debug.rb +1 -0
  282. data/lib/pubid/ietf/builder.rb +24 -8
  283. data/lib/pubid/ietf/identifiers/base.rb +25 -28
  284. data/lib/pubid/ietf/identifiers/bcp.rb +11 -0
  285. data/lib/pubid/ietf/identifiers/fyi.rb +11 -0
  286. data/lib/pubid/ietf/identifiers/internet_draft.rb +18 -2
  287. data/lib/pubid/ietf/identifiers/rfc.rb +2 -0
  288. data/lib/pubid/ietf/identifiers/serialization.rb +51 -0
  289. data/lib/pubid/ietf/identifiers/std.rb +11 -0
  290. data/lib/pubid/ietf/identifiers.rb +1 -0
  291. data/lib/pubid/ietf/parser.rb +27 -9
  292. data/lib/pubid/ietf/renderer.rb +44 -6
  293. data/lib/pubid/ietf/urn_generator.rb +20 -6
  294. data/lib/pubid/ietf/urn_parser.rb +10 -2
  295. data/lib/pubid/ietf.rb +12 -2
  296. data/lib/pubid/iho/identifiers/base.rb +10 -3
  297. data/lib/pubid/iho/parser.rb +1 -1
  298. data/lib/pubid/iho.rb +1 -0
  299. data/lib/pubid/isbn/identifier.rb +25 -7
  300. data/lib/pubid/isbn/parser.rb +1 -1
  301. data/lib/pubid/isbn.rb +1 -0
  302. data/lib/pubid/iso/builder.rb +10 -11
  303. data/lib/pubid/iso/bundled_identifier.rb +5 -3
  304. data/lib/pubid/iso/combined_identifier.rb +5 -3
  305. data/lib/pubid/iso/components.rb +0 -1
  306. data/lib/pubid/iso/identifier.rb +23 -11
  307. data/lib/pubid/iso/identifiers/directives.rb +7 -4
  308. data/lib/pubid/iso/identifiers/directives_supplement.rb +4 -4
  309. data/lib/pubid/iso/identifiers/tc_document.rb +31 -46
  310. data/lib/pubid/iso/normalizer.rb +1 -1
  311. data/lib/pubid/iso/parser.rb +1 -1
  312. data/lib/pubid/iso/urn_generator.rb +10 -10
  313. data/lib/pubid/iso.rb +12 -5
  314. data/lib/pubid/itu/builder.rb +10 -0
  315. data/lib/pubid/itu/identifiers/addendum.rb +2 -2
  316. data/lib/pubid/itu/identifiers/amendment.rb +2 -2
  317. data/lib/pubid/itu/identifiers/base.rb +29 -5
  318. data/lib/pubid/itu/identifiers/contribution.rb +31 -0
  319. data/lib/pubid/itu/identifiers/corrigendum.rb +2 -2
  320. data/lib/pubid/itu/identifiers/errata.rb +2 -2
  321. data/lib/pubid/itu/identifiers/supplement.rb +2 -2
  322. data/lib/pubid/itu/identifiers.rb +1 -0
  323. data/lib/pubid/itu/parser.rb +20 -3
  324. data/lib/pubid/itu.rb +1 -0
  325. data/lib/pubid/jcgm/builder.rb +1 -1
  326. data/lib/pubid/jcgm/identifier.rb +10 -0
  327. data/lib/pubid/jcgm/identifiers/meeting.rb +1 -1
  328. data/lib/pubid/jcgm/parser.rb +10 -3
  329. data/lib/pubid/jcgm/renderer.rb +10 -3
  330. data/lib/pubid/jcgm/single_identifier.rb +24 -15
  331. data/lib/pubid/jcgm/urn_generator.rb +1 -1
  332. data/lib/pubid/jcgm/urn_parser.rb +156 -14
  333. data/lib/pubid/jcgm.rb +10 -0
  334. data/lib/pubid/jis/identifier.rb +10 -3
  335. data/lib/pubid/jis/parser.rb +1 -1
  336. data/lib/pubid/jis.rb +1 -0
  337. data/lib/pubid/nist/builder.rb +12 -12
  338. data/lib/pubid/nist/components/stage.rb +2 -2
  339. data/lib/pubid/nist/configuration.rb +6 -8
  340. data/lib/pubid/nist/identifiers/base.rb +22 -5
  341. data/lib/pubid/nist/identifiers/circular.rb +9 -2
  342. data/lib/pubid/nist/identifiers/circular_supplement.rb +14 -5
  343. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +1 -1
  344. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +7 -1
  345. data/lib/pubid/nist/identifiers/crpl_report.rb +12 -7
  346. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +2 -2
  347. data/lib/pubid/nist/identifiers/handbook.rb +9 -2
  348. data/lib/pubid/nist/identifiers/internal_report.rb +12 -5
  349. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +16 -8
  350. data/lib/pubid/nist/identifiers/monograph.rb +14 -7
  351. data/lib/pubid/nist/identifiers/report.rb +14 -6
  352. data/lib/pubid/nist/parser.rb +1 -1
  353. data/lib/pubid/nist/series/ir.rb +3 -7
  354. data/lib/pubid/nist/supplement_identifier.rb +16 -1
  355. data/lib/pubid/nist.rb +7 -1
  356. data/lib/pubid/oasis/builder.rb +12 -10
  357. data/lib/pubid/oasis/identifier.rb +89 -11
  358. data/lib/pubid/oasis/parser.rb +1 -1
  359. data/lib/pubid/oasis.rb +7 -1
  360. data/lib/pubid/ogc/identifier.rb +9 -5
  361. data/lib/pubid/ogc/parser.rb +1 -1
  362. data/lib/pubid/ogc.rb +1 -0
  363. data/lib/pubid/oiml/builder.rb +7 -3
  364. data/lib/pubid/oiml/identifiers/basic_publication.rb +2 -0
  365. data/lib/pubid/oiml/identifiers/bulletin.rb +40 -10
  366. data/lib/pubid/oiml/identifiers/code_number.rb +90 -0
  367. data/lib/pubid/oiml/identifiers/document.rb +2 -0
  368. data/lib/pubid/oiml/identifiers/expert_report.rb +2 -0
  369. data/lib/pubid/oiml/identifiers/guide.rb +2 -0
  370. data/lib/pubid/oiml/identifiers/recommendation.rb +2 -0
  371. data/lib/pubid/oiml/identifiers/seminar_report.rb +2 -0
  372. data/lib/pubid/oiml/identifiers/vocabulary.rb +2 -0
  373. data/lib/pubid/oiml/identifiers.rb +1 -0
  374. data/lib/pubid/oiml/parser.rb +8 -3
  375. data/lib/pubid/oiml/renderer.rb +3 -3
  376. data/lib/pubid/oiml/single_identifier.rb +26 -42
  377. data/lib/pubid/oiml/supplement_identifier.rb +27 -0
  378. data/lib/pubid/oiml/urn_generator.rb +4 -4
  379. data/lib/pubid/oiml.rb +7 -1
  380. data/lib/pubid/omg/builder.rb +1 -0
  381. data/lib/pubid/omg/identifier.rb +20 -3
  382. data/lib/pubid/omg/parser.rb +64 -11
  383. data/lib/pubid/omg/renderer.rb +13 -1
  384. data/lib/pubid/omg.rb +2 -1
  385. data/lib/pubid/parser/grammar.rb +74 -0
  386. data/lib/pubid/parser.rb +2 -0
  387. data/lib/pubid/parsers/mr_string.rb +19 -0
  388. data/lib/pubid/plateau/parser.rb +1 -1
  389. data/lib/pubid/plateau.rb +10 -0
  390. data/lib/pubid/prefixes_support.rb +1 -0
  391. data/lib/pubid/renderers/annotator.rb +233 -0
  392. data/lib/pubid/renderers/base.rb +13 -0
  393. data/lib/pubid/renderers/directives_renderer.rb +6 -4
  394. data/lib/pubid/renderers/human_readable.rb +3 -3
  395. data/lib/pubid/renderers/mr_string.rb +15 -9
  396. data/lib/pubid/renderers.rb +1 -0
  397. data/lib/pubid/rendering/numbering.rb +25 -7
  398. data/lib/pubid/rendering.rb +1 -0
  399. data/lib/pubid/sae/builder.rb +1 -1
  400. data/lib/pubid/sae/identifiers/base.rb +13 -3
  401. data/lib/pubid/sae/parser.rb +1 -1
  402. data/lib/pubid/sae/urn_generator.rb +1 -1
  403. data/lib/pubid/sae.rb +1 -0
  404. data/lib/pubid/schema/declaration.rb +33 -0
  405. data/lib/pubid/schema/error.rb +14 -0
  406. data/lib/pubid/schema/identifier_type.rb +23 -0
  407. data/lib/pubid/schema/loader.rb +117 -0
  408. data/lib/pubid/schema/typed_stage.rb +24 -0
  409. data/lib/pubid/schema.rb +25 -0
  410. data/lib/pubid/tgpp/builder.rb +1 -1
  411. data/lib/pubid/tgpp/identifier.rb +21 -5
  412. data/lib/pubid/tgpp/identifiers/technical_report.rb +2 -2
  413. data/lib/pubid/tgpp/identifiers/technical_specification.rb +2 -2
  414. data/lib/pubid/tgpp/parser.rb +22 -6
  415. data/lib/pubid/tgpp/renderer.rb +21 -5
  416. data/lib/pubid/tgpp/urn_generator.rb +27 -8
  417. data/lib/pubid/tgpp/urn_parser.rb +8 -6
  418. data/lib/pubid/tgpp.rb +7 -1
  419. data/lib/pubid/type_resolver.rb +16 -1
  420. data/lib/pubid/un/identifier.rb +6 -3
  421. data/lib/pubid/un/parser.rb +1 -1
  422. data/lib/pubid/un.rb +1 -0
  423. data/lib/pubid/urn_parser/errors.rb +8 -1
  424. data/lib/pubid/urn_parser.rb +1 -0
  425. data/lib/pubid/utils.rb +1 -0
  426. data/lib/pubid/version.rb +1 -1
  427. data/lib/pubid/w3c/builder.rb +5 -5
  428. data/lib/pubid/w3c/identifier.rb +38 -9
  429. data/lib/pubid/w3c/parser.rb +1 -1
  430. data/lib/pubid/w3c/renderer.rb +1 -1
  431. data/lib/pubid/w3c/urn_generator.rb +2 -2
  432. data/lib/pubid/w3c.rb +1 -0
  433. data/lib/pubid/xsf/identifier.rb +9 -5
  434. data/lib/pubid/xsf/parser.rb +17 -4
  435. data/lib/pubid/xsf.rb +7 -1
  436. data/lib/pubid.rb +399 -21
  437. data/lib/tasks/conformance.rake +34 -0
  438. data/lib/tasks/docs.rake +16 -14
  439. data/lib/tasks/schema.rake +88 -0
  440. data/schema/core/joint_prefixes.yaml +24 -0
  441. data/schema/iec.yaml +1017 -0
  442. data/schema/iso.yaml +1586 -0
  443. data/schema/schema.schema.yaml +96 -0
  444. metadata +40 -19
  445. data/archived-gems/pubid-ccsds/update_codes.yaml +0 -1
  446. data/archived-gems/pubid-iec/stages.yaml +0 -129
  447. data/archived-gems/pubid-iec/update_codes.yaml +0 -67
  448. data/archived-gems/pubid-ieee/update_codes.yaml +0 -104
  449. data/archived-gems/pubid-iso/stages.yaml +0 -106
  450. data/archived-gems/pubid-iso/update_codes.yaml +0 -4
  451. data/archived-gems/pubid-itu/i18n.yaml +0 -13
  452. data/archived-gems/pubid-itu/series.yaml +0 -42
  453. data/archived-gems/pubid-nist/publishers.yaml +0 -6
  454. data/archived-gems/pubid-nist/series.yaml +0 -121
  455. data/archived-gems/pubid-nist/update_codes.yaml +0 -93
  456. data/archived-gems/pubid-plateau/update_codes.yaml +0 -6
  457. data/lib/pubid/ccsds/identifiers/base_BASE_88929.rb +0 -70
  458. data/lib/pubid/cen_cenelec/supplement_identifier.rb +0 -48
  459. data/lib/pubid/iec/components/code.rb +0 -36
  460. data/lib/pubid/iso/components/code.rb +0 -24
  461. /data/{archived-gems/pubid-nist → data/nist}/stages.yaml +0 -0
@@ -4,16 +4,35 @@ module Pubid
4
4
  module Tgpp
5
5
  # Emits `urn:3gpp:<type>:<code>:<release>:<version>`, e.g.
6
6
  # `urn:3gpp:ts:23.207:REL-4:2.0.0`. `<code>` is number+suffix+parts.
7
+ #
8
+ # A partial identifier has no release, no version, or neither. Only the
9
+ # TRAILING empty segments are dropped, so a bare reference gets the clean
10
+ # `urn:3gpp:ts:23.207` rather than a malformed `urn:3gpp:ts:23.207::`. An
11
+ # INTERIOR empty segment is kept, so the release-less form keeps the URN it
12
+ # has always emitted: `TS 29.215/2.0.0` -> `urn:3gpp:ts:29.215::2.0.0`.
7
13
  class UrnGenerator < Pubid::UrnGenerator::Base
8
14
  def generate
9
- [
10
- "urn",
11
- "3gpp",
12
- identifier.type_prefix.downcase,
13
- identifier.code,
14
- identifier.release,
15
- identifier.version,
16
- ].join(":")
15
+ (head_segments + tail_segments).join(":")
16
+ end
17
+
18
+ private
19
+
20
+ # The namespace, the document type and the code. Always present.
21
+ def head_segments
22
+ ["urn", "3gpp", identifier.type_prefix.downcase, identifier.code]
23
+ end
24
+
25
+ # The two optional qualifiers, with the trailing empty ones removed.
26
+ def tail_segments
27
+ segments = [identifier.release, identifier.version]
28
+ # NOTE: `empty?`, not `any?` — a bare `Array#any?` tests element
29
+ # truthiness, so `[nil, nil].any?` is false and would strip nothing.
30
+ segments.pop until segments.empty? || !blank?(segments.last)
31
+ segments.map(&:to_s)
32
+ end
33
+
34
+ def blank?(value)
35
+ value.nil? || value.empty?
17
36
  end
18
37
  end
19
38
  end
@@ -16,12 +16,14 @@ module Pubid
16
16
  def parse_urn(urn)
17
17
  body = strip_namespace(urn)
18
18
  type, code, release, version = split_parts(body)
19
- # The rare no-release form (e.g. TS 29.215/2.0.0) serialises with an
20
- # empty release chunk ("urn:3gpp:ts:29.215::2.0.0"); rebuild it without
21
- # the release colon.
22
- head = "#{type.upcase} #{code}"
23
- head += ":#{release}" unless release.nil? || release.empty?
24
- flavor_parse("#{head}/#{version}")
19
+ # A partial identifier drops its trailing segments, and the no-release
20
+ # form (e.g. TS 29.215/2.0.0) serialises with an empty release chunk
21
+ # ("urn:3gpp:ts:29.215::2.0.0"). Rebuild only the segments present, so
22
+ # neither the release colon nor the version slash dangles.
23
+ result = "#{type.upcase} #{code}"
24
+ result += ":#{release}" unless release.nil? || release.empty?
25
+ result += "/#{version}" unless version.nil? || version.empty?
26
+ flavor_parse(result)
25
27
  end
26
28
  end
27
29
  end
data/lib/pubid/tgpp.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  module Pubid
4
5
  # 3GPP (3rd Generation Partnership Project) flavor.
5
6
  #
@@ -25,8 +26,13 @@ module Pubid
25
26
 
26
27
  # Parse a 3GPP identifier string
27
28
  def self.parse(identifier)
29
+ unless identifier.is_a?(String)
30
+ raise Pubid::Errors::InvalidInputError,
31
+ Pubid::INPUT_NOT_A_STRING_MESSAGE
32
+ end
33
+
28
34
  if identifier.length > Pubid::MAX_INPUT_LENGTH
29
- raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
35
+ raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
30
36
  end
31
37
 
32
38
  Identifier.parse(identifier)
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  module Pubid
4
5
  # Resolves a polymorphic `_type` string (e.g. "pubid:iso:technical-report")
5
6
  # to the concrete Ruby class that owns it.
@@ -30,7 +31,8 @@ module Pubid
30
31
  # populated their Identifier base's polymorphic_type_map.
31
32
  ::Pubid.eager_load_flavors!
32
33
 
33
- flavor = ::Pubid::Registry.get(flavor_name)
34
+ flavor = ::Pubid::Registry.get(flavor_name) ||
35
+ flavor_by_module_segment(flavor_name)
34
36
  return nil unless flavor
35
37
 
36
38
  identifier_base = flavor::Identifier
@@ -43,6 +45,19 @@ module Pubid
43
45
 
44
46
  private
45
47
 
48
+ # The registered flavor whose module constant gives +segment+.
49
+ # Identifier.polymorphic_name takes the segment from the module name
50
+ # ("Pubid::CenCenelec" -> "cencenelec"), and a flavor can be registered
51
+ # under other names ("cen_cenelec", "cen"). Without this fallback no
52
+ # CEN/CENELEC `_type` resolved, so the root class and a nested
53
+ # attribute of another flavor (BSI) read a CEN hash as the abstract
54
+ # root.
55
+ def flavor_by_module_segment(segment)
56
+ ::Pubid::Registry.flavors.each_value.find do |flavor_module|
57
+ flavor_module.name.to_s.split("::")[1]&.downcase == segment
58
+ end
59
+ end
60
+
46
61
  # The flavor name is the segment between the leading "pubid:" and the
47
62
  # type-name, e.g. "iso" in "pubid:iso:technical-report".
48
63
  def flavor_segment(type)
@@ -23,14 +23,17 @@ module Pubid
23
23
  end
24
24
 
25
25
  def self.parse(identifier)
26
+ unless identifier.is_a?(String)
27
+ raise Pubid::Errors::InvalidInputError,
28
+ Pubid::INPUT_NOT_A_STRING_MESSAGE
29
+ end
30
+
26
31
  if identifier.length > Pubid::MAX_INPUT_LENGTH
27
- raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
32
+ raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
28
33
  end
29
34
 
30
35
  parsed = Parser.parse(identifier)
31
36
  Builder.build(parsed)
32
- rescue Parslet::ParseFailed => e
33
- raise "Failed to parse UN identifier '#{identifier}': #{e.message}"
34
37
  end
35
38
  end
36
39
  end
@@ -4,7 +4,7 @@ require "parslet"
4
4
 
5
5
  module Pubid
6
6
  module Un
7
- class Parser < Parslet::Parser
7
+ class Parser < ::Pubid::Parser::Grammar
8
8
  rule(:slash) { str("/") }
9
9
  rule(:un_prefix) { (str("UN") >> str(" ")).maybe }
10
10
  rule(:token) { match("[A-Z0-9.]").repeat(1) }
data/lib/pubid/un.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  module Pubid
4
5
  module Un
5
6
  extend Pubid::PrefixesSupport
@@ -1,9 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../errors"
4
+
3
5
  module Pubid
4
6
  module UrnParser
7
+ # Deprecated. The URN error moved to {Pubid::Errors::UrnParseError}, so
8
+ # that every pubid failure lives in one namespace under the marker module
9
+ # {Pubid::Errors::Error}. This alias keeps the nine `raise` sites in the
10
+ # flavor URN parsers, and any consumer rescuing the old name, working
11
+ # unchanged.
5
12
  module Errors
6
- class ParseError < StandardError; end
13
+ ParseError = ::Pubid::Errors::UrnParseError
7
14
  end
8
15
  end
9
16
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  module Pubid
4
5
  # Parses URN strings back into Identifier objects.
5
6
  #
data/lib/pubid/utils.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  module Pubid
4
5
  module Utils
5
6
  autoload :StringNormalizer, "pubid/utils/string_normalizer"
data/lib/pubid/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pubid
4
- VERSION = "2.0.0.pre.alpha.9"
4
+ VERSION = "2.0.0.pre.alpha.12"
5
5
  end
@@ -3,7 +3,7 @@
3
3
  module Pubid
4
4
  module W3c
5
5
  # Turns the parse tree into a concrete identifier: picks the class from the
6
- # leading maturity token and splits the captured remainder into code + date.
6
+ # leading maturity token and splits the captured remainder into slug + date.
7
7
  class Builder
8
8
  # Maturity token -> concrete identifier class name (resolved lazily so the
9
9
  # Identifiers namespace need not be loaded at class-definition time).
@@ -22,7 +22,7 @@ module Pubid
22
22
 
23
23
  # A trailing "-<digits>" group is the date only when the digit run is
24
24
  # exactly 8 (YYYYMMDD), 6 (legacy YYMMDD) or 4 (legacy MMDD) wide. No real
25
- # W3C code ends in such a run, so this never mis-splits a code that merely
25
+ # W3C slug ends in such a run, so this never mis-splits a slug that merely
26
26
  # ends in a short digit run (e.g. "url-1", "ATAG10").
27
27
  DATE_RE = /\A(.+)-(\d{8}|\d{6}|\d{4})\z/
28
28
 
@@ -31,8 +31,8 @@ module Pubid
31
31
  end
32
32
 
33
33
  def build(data)
34
- code, date = split_date(data[:rest].to_s)
35
- klass_for(data[:type]&.to_s).new(code: code, date: date)
34
+ number, date = split_date(data[:rest].to_s)
35
+ klass_for(data[:type]&.to_s).new(number: number, date: date)
36
36
  end
37
37
 
38
38
  private
@@ -42,7 +42,7 @@ module Pubid
42
42
  Identifiers.const_get(name)
43
43
  end
44
44
 
45
- # @return [Array(String, String|nil)] the code and the optional date
45
+ # @return [Array(String, String|nil)] the slug and the optional date
46
46
  def split_date(rest)
47
47
  if (m = DATE_RE.match(rest))
48
48
  [m[1], m[2]]
@@ -7,13 +7,39 @@ module Pubid
7
7
  # this class (one per W3C maturity level), so a parsed W3C id is an
8
8
  # instance of Pubid::W3c::Identifier.
9
9
  #
10
- # W3C identifiers are flat: a slug `code`, an optional publication `date`
10
+ # W3C identifiers are flat: a slug `number`, an optional publication `date`
11
11
  # (kept verbatim as a string — width varies: 8-digit YYYYMMDD, or legacy
12
12
  # 6-digit YYMMDD / 4-digit MMDD), and a document-type carried by the
13
13
  # concrete class (its `type_prefix` returns the printed token, e.g. "WD").
14
14
  class Identifier < ::Pubid::Identifier
15
- # Slug, e.g. "charmod", "css-backgrounds-3", "07-WebData".
16
- attribute :code, :string
15
+ # Document slug, e.g. "charmod", "css-backgrounds-3", "07-WebData".
16
+ #
17
+ # This is the relaton index key: Relaton::Index sorts and bsearches every
18
+ # row on `id.root.number.to_s`, and an empty key degrades that binary
19
+ # search to a linear scan over the whole index — silently, with no error.
20
+ # Every W3C identifier is its own root (the flavor has no supplement or
21
+ # wrapper type), so this attribute is always the key and must never be
22
+ # empty. It was named `code` before; there is no alias.
23
+ #
24
+ # It redefines the parent ::Pubid::Identifier's
25
+ # `attribute :number, Components::Code` as a plain :string. CLAUDE.md
26
+ # records that doing so on a class the concrete types INHERIT from can
27
+ # resolve against the parent definition nondeterministically under
28
+ # multi-flavor load (the IEEE lesson). That hazard does not apply to W3C's
29
+ # shape, and the reason is worth keeping: lutaml's `inherited` hook
30
+ # deep-dups the parent's attribute table into each subclass at
31
+ # class-definition time (serialize/initialization.rb#initialize_attrs), so
32
+ # a subclass holds a SNAPSHOT, not a live view. A base-level override is
33
+ # therefore safe iff every subclass body opens after this body has run —
34
+ # and Ruby resolves the superclass constant, running this file to
35
+ # completion, before opening any leaf body. That holds because this class
36
+ # lives in ONE file, in ONE class body, and is never reopened. Split it
37
+ # the way IEEE splits its base and a leaf can snapshot a half-built
38
+ # parent, silently reverting `number` to Components::Code. The `date`
39
+ # override below has relied on the same property since the flavor landed.
40
+ # spec/pubid/w3c/root_number_spec.rb pins it, and is only meaningful under
41
+ # the FULL suite.
42
+ attribute :number, :string
17
43
  # Publication date verbatim, or nil. Overrides the base Components::Date
18
44
  # attribute with a plain string (same mechanism JIS uses for `number`):
19
45
  # W3C dates are opaque digit runs that must round-trip exactly, and are
@@ -46,7 +72,7 @@ module Pubid
46
72
 
47
73
  key_value do
48
74
  map "_type", to: :_type, polymorphic_map: W3C_TYPE_MAP
49
- map "code", to: :code
75
+ map "number", to: :number
50
76
  map "date", to: :date
51
77
  end
52
78
 
@@ -55,7 +81,7 @@ module Pubid
55
81
  # would otherwise fail serialization type validation.
56
82
  PUBLISHER = "W3C"
57
83
 
58
- # The printed document-type token (e.g. "WD"). nil for the bare-code
84
+ # The printed document-type token (e.g. "WD"). nil for the bare-slug
59
85
  # Standard form; concrete typed subclasses override it.
60
86
  def type_prefix
61
87
  nil
@@ -83,18 +109,21 @@ module Pubid
83
109
  # Parse a W3C identifier string into an identifier object
84
110
  # @param identifier [String] The W3C identifier string to parse
85
111
  # @return [Identifier] The appropriate identifier object
86
- # @raise [RuntimeError] If parsing fails
112
+ # @raise [Pubid::Errors::ParseError] If parsing fails
87
113
  def self.parse(identifier)
88
114
  # Reject pathological inputs before they reach the parser
89
115
  # (CodeQL rb/polynomial-redos barrier — inline .length by design).
116
+ unless identifier.is_a?(String)
117
+ raise Pubid::Errors::InvalidInputError,
118
+ Pubid::INPUT_NOT_A_STRING_MESSAGE
119
+ end
120
+
90
121
  if identifier.length > Pubid::MAX_INPUT_LENGTH
91
- raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
122
+ raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
92
123
  end
93
124
 
94
125
  parsed = Parser.parse(identifier)
95
126
  Builder.build(parsed)
96
- rescue Parslet::ParseFailed => e
97
- raise "Failed to parse W3C identifier '#{identifier}': #{e.message}"
98
127
  end
99
128
  end
100
129
  end
@@ -14,7 +14,7 @@ module Pubid
14
14
  # greedily consume the trailing date and make a `.maybe` date rule
15
15
  # unreliable. This is safe: no real W3C code ends in a same-width (4/6/8)
16
16
  # digit run, so the Builder's fixed-width trailing-date test never collides.
17
- class Parser < Parslet::Parser
17
+ class Parser < ::Pubid::Parser::Grammar
18
18
  rule(:prefix) { str("W3C") >> str(" ") }
19
19
 
20
20
  # Known W3C maturity tokens. Order matters for shared prefixes: CRD before
@@ -19,7 +19,7 @@ module Pubid
19
19
  id = @id
20
20
  body = +""
21
21
  body << "#{id.type_prefix}-" if id.type_prefix
22
- body << id.code.to_s
22
+ body << id.number.to_s
23
23
  body << "-#{id.date}" if id.date
24
24
 
25
25
  with_publisher?(id) ? "#{PUBLISHER} #{body}" : body
@@ -2,14 +2,14 @@
2
2
 
3
3
  module Pubid
4
4
  module W3c
5
- # Emits `urn:w3c:<type-down>:<code>[:<date>]`, e.g.
5
+ # Emits `urn:w3c:<type-down>:<slug>[:<date>]`, e.g.
6
6
  # "W3C WD-charmod-19991129" -> "urn:w3c:wd:charmod:19991129"
7
7
  # "W3C 2dcontext" -> "urn:w3c:2dcontext"
8
8
  class UrnGenerator < Pubid::UrnGenerator::Base
9
9
  def generate
10
10
  parts = ["urn", "w3c"]
11
11
  parts << identifier.type_prefix.downcase if identifier.type_prefix
12
- parts << identifier.code.to_s
12
+ parts << identifier.number.to_s
13
13
  parts << identifier.date.to_s if identifier.date
14
14
  parts.join(":")
15
15
  end
data/lib/pubid/w3c.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  module Pubid
4
5
  module W3c
5
6
  extend Pubid::PrefixesSupport
@@ -45,17 +45,21 @@ module Pubid
45
45
  # Parse an XSF identifier string into an identifier object
46
46
  # @param identifier [String] The XSF identifier string to parse
47
47
  # @return [Identifier] The appropriate identifier object
48
- # @raise [ArgumentError] If the input exceeds the maximum length
49
- # @raise [RuntimeError] If parsing fails
48
+ # @raise [Pubid::Errors::InvalidInputError]
49
+ # If the input exceeds the maximum length
50
+ # @raise [Pubid::Errors::ParseError] If parsing fails
50
51
  def self.parse(identifier)
52
+ unless identifier.is_a?(String)
53
+ raise Pubid::Errors::InvalidInputError,
54
+ Pubid::INPUT_NOT_A_STRING_MESSAGE
55
+ end
56
+
51
57
  if identifier.length > Pubid::MAX_INPUT_LENGTH
52
- raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
58
+ raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
53
59
  end
54
60
 
55
61
  parsed = Parser.parse(identifier)
56
62
  Builder.build(parsed)
57
- rescue Parslet::ParseFailed => e
58
- raise "Failed to parse XSF identifier '#{identifier}': #{e.message}"
59
63
  end
60
64
  end
61
65
  end
@@ -4,15 +4,28 @@ require "parslet"
4
4
 
5
5
  module Pubid
6
6
  module Xsf
7
- # Parslet grammar for XSF identifiers. One fixed shape: "XEP NNNN".
8
- class Parser < Parslet::Parser
7
+ # Parslet grammar for XSF identifiers. Two shapes: "XEP NNNN", and the two
8
+ # named documents in SPECIAL_NUMBERS.
9
+ class Parser < ::Pubid::Parser::Grammar
10
+ # The XMPP extensions repository publishes two documents whose name is
11
+ # not a number: the editor README and the `xep-xxxx` template. Both reach
12
+ # pubid as real primary docids ("XEP README", "XEP xxxx"), so the number
13
+ # rule admits these two literals beside the digits. Exact case, and no
14
+ # other word: the flavor still rejects "XEP foo".
15
+ SPECIAL_NUMBERS = %w[README xxxx].freeze
16
+
9
17
  rule(:digit) { match["0-9"] }
10
18
  rule(:digits) { digit.repeat(1) }
11
19
 
20
+ rule(:special_number) do
21
+ SPECIAL_NUMBERS.map { |name| str(name) }.reduce(:|)
22
+ end
23
+
12
24
  # "XEP 0001" — publisher token, a single space, then the number kept as
13
- # a string of digits (leading zeros preserved by the builder).
25
+ # a string of digits (leading zeros preserved by the builder), or the
26
+ # name of one of the two named documents.
14
27
  rule(:identifier) do
15
- str("XEP") >> str(" ") >> digits.as(:number)
28
+ str("XEP") >> str(" ") >> (digits | special_number).as(:number)
16
29
  end
17
30
 
18
31
  rule(:root) { identifier }
data/lib/pubid/xsf.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  module Pubid
4
5
  # XSF (XMPP Standards Foundation) flavor. Its documents are XEPs — XMPP
5
6
  # Extension Protocols — printed as "XEP NNNN" with a 4-digit zero-padded
@@ -23,8 +24,13 @@ module Pubid
23
24
 
24
25
  # Parse an XSF identifier string
25
26
  def self.parse(identifier)
27
+ unless identifier.is_a?(String)
28
+ raise Pubid::Errors::InvalidInputError,
29
+ Pubid::INPUT_NOT_A_STRING_MESSAGE
30
+ end
31
+
26
32
  if identifier.length > Pubid::MAX_INPUT_LENGTH
27
- raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
33
+ raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
28
34
  end
29
35
 
30
36
  Identifier.parse(identifier)