pubid 2.0.1 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. checksums.yaml +4 -4
  2. data/data/ieee/update_codes.yaml +2 -2
  3. data/data/parg/adobe.json +1 -1
  4. data/data/parg/aiee.json +1 -1
  5. data/data/parg/aiee.parg +99 -9
  6. data/data/parg/amca.json +1 -1
  7. data/data/parg/ansi.json +1 -1
  8. data/data/parg/api.json +1 -1
  9. data/data/parg/ashrae.json +1 -1
  10. data/data/parg/asme.json +1 -1
  11. data/data/parg/astm.json +1 -1
  12. data/data/parg/bipm.json +1 -1
  13. data/data/parg/bsi.json +1 -1
  14. data/data/parg/ccsds.json +1 -1
  15. data/data/parg/cen_cenelec.json +1 -1
  16. data/data/parg/cie.json +1 -1
  17. data/data/parg/csa.json +1 -1
  18. data/data/parg/ecma.json +1 -1
  19. data/data/parg/etsi.json +1 -1
  20. data/data/parg/evs.json +1 -1
  21. data/data/parg/gost.json +1 -1
  22. data/data/parg/iala.json +1 -1
  23. data/data/parg/iana.json +1 -1
  24. data/data/parg/idf.json +1 -1
  25. data/data/parg/iec.json +1 -1
  26. data/data/parg/ieee.json +1 -1
  27. data/data/parg/iho.json +1 -0
  28. data/data/parg/ire.json +1 -1
  29. data/data/parg/ire.parg +51 -12
  30. data/data/parg/isbn.json +1 -1
  31. data/data/parg/iso.json +1 -1
  32. data/data/parg/iso.parg +751 -0
  33. data/data/parg/itu.json +1 -1
  34. data/data/parg/jcgm.json +1 -1
  35. data/data/parg/jis.json +1 -1
  36. data/data/parg/nesc.json +1 -1
  37. data/data/parg/nesc.parg +97 -12
  38. data/data/parg/nist.json +1 -1
  39. data/data/parg/oiml.json +1 -1
  40. data/data/parg/omg.json +1 -1
  41. data/data/parg/parg.json +1 -1
  42. data/data/parg/plateau.json +1 -1
  43. data/data/parg/tgpp.json +1 -1
  44. data/data/parg/un.json +1 -1
  45. data/lib/pubid/adobe/identifier.rb +1 -1
  46. data/lib/pubid/adobe/parser.rb +2 -113
  47. data/lib/pubid/amca/identifiers/base.rb +1 -1
  48. data/lib/pubid/amca/parser.rb +1 -145
  49. data/lib/pubid/ansi/identifier.rb +1 -1
  50. data/lib/pubid/ansi/parser.rb +1 -82
  51. data/lib/pubid/api/builder.rb +32 -1
  52. data/lib/pubid/api/identifier.rb +1 -1
  53. data/lib/pubid/api/parser.rb +1 -131
  54. data/lib/pubid/ashrae/identifiers/base.rb +1 -1
  55. data/lib/pubid/ashrae/parser.rb +3 -710
  56. data/lib/pubid/asme/builder.rb +6 -4
  57. data/lib/pubid/asme/identifier.rb +1 -2
  58. data/lib/pubid/asme/parser.rb +1 -328
  59. data/lib/pubid/astm/builder.rb +12 -3
  60. data/lib/pubid/astm/identifier.rb +1 -2
  61. data/lib/pubid/astm/parser.rb +1 -227
  62. data/lib/pubid/bipm/identifier.rb +8 -1
  63. data/lib/pubid/bipm/parser.rb +2 -224
  64. data/lib/pubid/bsi/builder.rb +2 -4
  65. data/lib/pubid/bsi/parser.rb +1 -666
  66. data/lib/pubid/bsi/single_identifier.rb +38 -1
  67. data/lib/pubid/calconnect/parser.rb +2 -40
  68. data/lib/pubid/ccsds/identifier.rb +1 -1
  69. data/lib/pubid/ccsds/parser.rb +1 -66
  70. data/lib/pubid/cen_cenelec/identifier.rb +16 -1
  71. data/lib/pubid/cen_cenelec/parser.rb +3 -136
  72. data/lib/pubid/cie/identifier.rb +1 -1
  73. data/lib/pubid/cie/parser.rb +3 -378
  74. data/lib/pubid/conformance.rb +1 -1
  75. data/lib/pubid/csa/builder.rb +41 -18
  76. data/lib/pubid/csa/identifier.rb +12 -4
  77. data/lib/pubid/csa/identifiers/amendment.rb +28 -0
  78. data/lib/pubid/csa/identifiers.rb +1 -0
  79. data/lib/pubid/csa/parser.rb +16 -397
  80. data/lib/pubid/doi/parser.rb +2 -37
  81. data/lib/pubid/easc/builder.rb +1 -1
  82. data/lib/pubid/easc/parser.rb +2 -70
  83. data/lib/pubid/ecma/CLAUDE.md +8 -1
  84. data/lib/pubid/ecma/identifier.rb +13 -8
  85. data/lib/pubid/ecma/parser.rb +2 -54
  86. data/lib/pubid/ecma/renderer.rb +3 -7
  87. data/lib/pubid/errors.rb +18 -13
  88. data/lib/pubid/etsi/builder.rb +8 -5
  89. data/lib/pubid/etsi/identifiers/base.rb +1 -1
  90. data/lib/pubid/etsi/parser.rb +1 -132
  91. data/lib/pubid/evs/identifier.rb +7 -0
  92. data/lib/pubid/evs/parser.rb +1 -8
  93. data/lib/pubid/evs.rb +1 -1
  94. data/lib/pubid/gb/identifier.rb +6 -0
  95. data/lib/pubid/gb/parser.rb +2 -51
  96. data/lib/pubid/gost/identifier.rb +9 -1
  97. data/lib/pubid/gost/parser.rb +4 -81
  98. data/lib/pubid/iala/builder.rb +48 -39
  99. data/lib/pubid/iala/identifier.rb +1 -1
  100. data/lib/pubid/iala/parser.rb +2 -121
  101. data/lib/pubid/iana/identifier.rb +1 -1
  102. data/lib/pubid/iana/parser.rb +2 -24
  103. data/lib/pubid/identifier.rb +78 -1
  104. data/lib/pubid/idf/builder.rb +42 -0
  105. data/lib/pubid/idf/identifier.rb +1 -1
  106. data/lib/pubid/idf/parser.rb +1 -137
  107. data/lib/pubid/idf.rb +1 -2
  108. data/lib/pubid/iec/builder.rb +158 -50
  109. data/lib/pubid/iec/identifier.rb +1 -1
  110. data/lib/pubid/iec/parser.rb +3 -430
  111. data/lib/pubid/ieee/CLAUDE.md +2 -0
  112. data/lib/pubid/ieee/aiee/identifier.rb +2 -1
  113. data/lib/pubid/ieee/aiee.rb +0 -1
  114. data/lib/pubid/ieee/builder.rb +177 -30
  115. data/lib/pubid/ieee/components/code.rb +46 -7
  116. data/lib/pubid/ieee/identifiers/base.rb +5 -2
  117. data/lib/pubid/ieee/identifiers/joint_development.rb +7 -3
  118. data/lib/pubid/ieee/ire/identifier.rb +2 -1
  119. data/lib/pubid/ieee/ire.rb +0 -1
  120. data/lib/pubid/ieee/nesc/builder.rb +1 -1
  121. data/lib/pubid/ieee/nesc.rb +0 -1
  122. data/lib/pubid/ieee/parser.rb +1 -1257
  123. data/lib/pubid/ieee/project_renderer.rb +5 -1
  124. data/lib/pubid/ieee/renderer.rb +4 -2
  125. data/lib/pubid/ieee/urn_generator.rb +4 -1
  126. data/lib/pubid/ietf/identifiers/base.rb +17 -1
  127. data/lib/pubid/ietf/parser.rb +2 -47
  128. data/lib/pubid/ietf/renderer.rb +17 -2
  129. data/lib/pubid/iho/CLAUDE.md +98 -0
  130. data/lib/pubid/iho/builder.rb +4 -1
  131. data/lib/pubid/iho/identifiers/base.rb +28 -2
  132. data/lib/pubid/iho/renderer.rb +8 -0
  133. data/lib/pubid/iho/urn_generator.rb +14 -1
  134. data/lib/pubid/iho/urn_parser.rb +45 -32
  135. data/lib/pubid/iho.rb +0 -1
  136. data/lib/pubid/isbn/identifier.rb +1 -1
  137. data/lib/pubid/isbn/parser.rb +2 -31
  138. data/lib/pubid/iso/CLAUDE.md +66 -0
  139. data/lib/pubid/iso/builder.rb +229 -15
  140. data/lib/pubid/iso/identifier.rb +22 -12
  141. data/lib/pubid/iso/identifiers/directives.rb +6 -3
  142. data/lib/pubid/iso/identifiers/guide.rb +6 -3
  143. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +6 -3
  144. data/lib/pubid/iso/normalizer.rb +5 -4
  145. data/lib/pubid/iso/parser.rb +1 -539
  146. data/lib/pubid/iso/supplement_identifier.rb +6 -3
  147. data/lib/pubid/iso/urn_parser.rb +13 -8
  148. data/lib/pubid/iso/utilities.rb +4 -5
  149. data/lib/pubid/iso.rb +1 -19
  150. data/lib/pubid/itu/builder.rb +36 -20
  151. data/lib/pubid/itu/identifiers/base.rb +15 -2
  152. data/lib/pubid/itu/parser.rb +1 -775
  153. data/lib/pubid/jcgm/builder.rb +35 -0
  154. data/lib/pubid/jcgm/parser.rb +1 -151
  155. data/lib/pubid/jcgm.rb +1 -2
  156. data/lib/pubid/jis/CLAUDE.md +36 -0
  157. data/lib/pubid/jis/builder.rb +30 -41
  158. data/lib/pubid/jis/identifier.rb +12 -2
  159. data/lib/pubid/jis/identifiers/welding_engineering_standard.rb +35 -0
  160. data/lib/pubid/jis/identifiers.rb +2 -0
  161. data/lib/pubid/jis/parser.rb +1 -128
  162. data/lib/pubid/jis/renderer.rb +1 -1
  163. data/lib/pubid/jis/supplement_identifier.rb +5 -5
  164. data/lib/pubid/jis/urn_parser.rb +2 -1
  165. data/lib/pubid/jis.rb +3 -2
  166. data/lib/pubid/nist/builder.rb +5 -1
  167. data/lib/pubid/nist/caster.rb +13 -3
  168. data/lib/pubid/nist/identifiers/base.rb +37 -2
  169. data/lib/pubid/nist/identifiers/circular.rb +2 -2
  170. data/lib/pubid/nist/identifiers/circular_supplement.rb +2 -2
  171. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +2 -2
  172. data/lib/pubid/nist/identifiers/crpl_report.rb +2 -2
  173. data/lib/pubid/nist/identifiers/handbook.rb +2 -2
  174. data/lib/pubid/nist/identifiers/internal_report.rb +2 -2
  175. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +2 -2
  176. data/lib/pubid/nist/identifiers/monograph.rb +2 -2
  177. data/lib/pubid/nist/identifiers/report.rb +2 -2
  178. data/lib/pubid/nist/parser.rb +19 -775
  179. data/lib/pubid/nist/router.rb +4 -1
  180. data/lib/pubid/nist/supplement_identifier.rb +2 -2
  181. data/lib/pubid/oasis/parser.rb +2 -16
  182. data/lib/pubid/ogc/parser.rb +2 -26
  183. data/lib/pubid/oiml/identifiers/certification_system.rb +7 -0
  184. data/lib/pubid/oiml/identifiers/dual_published.rb +2 -2
  185. data/lib/pubid/oiml/parser.rb +1 -303
  186. data/lib/pubid/oiml.rb +1 -2
  187. data/lib/pubid/omg/identifier.rb +6 -1
  188. data/lib/pubid/omg/parser.rb +2 -76
  189. data/lib/pubid/parser.rb +5 -4
  190. data/lib/pubid/parsers/mr_string.rb +1 -1
  191. data/lib/pubid/plateau/parser.rb +1 -66
  192. data/lib/pubid/plateau.rb +1 -2
  193. data/lib/pubid/renderers/directives_renderer.rb +1 -1
  194. data/lib/pubid/renderers/iwa_renderer.rb +1 -1
  195. data/lib/pubid/renderers/publisher_stripper.rb +82 -0
  196. data/lib/pubid/renderers/supplement_renderer.rb +1 -1
  197. data/lib/pubid/renderers.rb +1 -0
  198. data/lib/pubid/sae/parser.rb +1 -48
  199. data/lib/pubid/tgpp/identifier.rb +1 -1
  200. data/lib/pubid/tgpp/parser.rb +2 -59
  201. data/lib/pubid/un/identifier.rb +1 -1
  202. data/lib/pubid/un/parser.rb +1 -18
  203. data/lib/pubid/version.rb +1 -1
  204. data/lib/pubid/w3c/parser.rb +2 -27
  205. data/lib/pubid/xsf/identifier.rb +10 -6
  206. data/lib/pubid/xsf/parser.rb +3 -31
  207. data/lib/pubid/xsf/renderer.rb +2 -4
  208. data/lib/pubid.rb +8 -9
  209. metadata +9 -23
  210. data/lib/pubid/ieee/aiee/parser.rb +0 -130
  211. data/lib/pubid/ieee/ire/parser.rb +0 -109
  212. data/lib/pubid/ieee/nesc/parser.rb +0 -155
  213. data/lib/pubid/iho/parser.rb +0 -68
  214. data/lib/pubid/parser/common_parse_methods.rb +0 -13
  215. data/lib/pubid/parser/common_parse_rules.rb +0 -56
  216. data/lib/pubid/parser/grammar.rb +0 -96
data/lib/pubid/plateau.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pubid"
4
- require "parslet"
5
4
 
6
5
  module Pubid
7
6
  module Plateau
@@ -31,7 +30,7 @@ module Pubid
31
30
 
32
31
  # Apply legacy update_codes normalization first
33
32
  normalized = Core::UpdateCodes.apply(input, :plateau)
34
- parsed = Pubid::Parg::Backend.parse(:plateau, normalized)
33
+ parsed = Pubid::Parg::Model.bound(:plateau, normalized)
35
34
  Builder.build(parsed)
36
35
  end
37
36
 
@@ -3,7 +3,7 @@
3
3
  module Pubid
4
4
  module Renderers
5
5
  class DirectivesRenderer < HumanReadable
6
- def render(context:, with_edition: false)
6
+ def render(context:, with_edition: false, **_opts)
7
7
  parts = []
8
8
  parts << render_publisher_portion(context)
9
9
  num_port = render_number_portion(context)
@@ -3,7 +3,7 @@
3
3
  module Pubid
4
4
  module Renderers
5
5
  class IwaRenderer < HumanReadable
6
- def render(context:, with_edition: false)
6
+ def render(context:, with_edition: false, **_opts)
7
7
  parts = []
8
8
  if @id.typed_stage
9
9
  parts << annotate(@id.typed_stage.render(context:),
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Renderers
5
+ # Removes the leading publisher token from an already-rendered identifier,
6
+ # for `to_s(with_publisher: false)`.
7
+ #
8
+ # relaton#49 asks for an internal form of every identifier: the form an SDO
9
+ # uses when it cites its own documents, with the publisher prefix dropped
10
+ # (`NIST SP 800-113` -> `SP 800-113`). Teaching 40-odd flavor renderers to
11
+ # omit the publisher would mean 40 chances to drift, and a flavor added
12
+ # tomorrow would get nothing. This class works from the OUTSIDE instead,
13
+ # the way {Annotator} does: the identifier names the prefixes its rendering
14
+ # can start with (`Pubid::Identifier#publisher_prefixes`), and the prefix
15
+ # is cut off together with the one separator that follows it.
16
+ #
17
+ # Deliberate limits:
18
+ #
19
+ # * A prefix must be followed by a separator (space, `-`, `/` or `.`), so
20
+ # `ISO` never cuts into `ISOFIX`.
21
+ # * When no prefix matches, or cutting it would leave nothing, the input
22
+ # comes back unchanged: the option is ignored rather than producing a
23
+ # broken identifier.
24
+ class PublisherStripper
25
+ SEPARATOR = %r{\A(?:\s+|[-/.]\s*)}
26
+
27
+ def initialize(identifier)
28
+ @id = identifier
29
+ end
30
+
31
+ # A co-published group is not always joined by `/`: CIE prints
32
+ # `CIE ISO 10916:2024`. The cut therefore repeats while a publisher
33
+ # token still leads, so the group drops whole whatever its joiner.
34
+ # The cap only guards against a cycle; no corpus id has more than three.
35
+ MAX_CUTS = 4
36
+
37
+ # @param rendered [String] the default human rendering of the identifier
38
+ # @return [String] the rendering without its leading publisher token
39
+ def strip(rendered)
40
+ return rendered unless rendered.is_a?(String)
41
+
42
+ candidates = prefixes
43
+ MAX_CUTS.times do
44
+ stripped = cut_once(rendered, candidates)
45
+ break if stripped.equal?(rendered)
46
+
47
+ rendered = stripped
48
+ end
49
+ rendered
50
+ end
51
+
52
+ private
53
+
54
+ def cut_once(rendered, candidates)
55
+ candidates.each do |prefix|
56
+ next unless rendered.start_with?(prefix)
57
+
58
+ rest = rendered[prefix.length..]
59
+ next unless rest.match?(SEPARATOR)
60
+
61
+ stripped = rest.sub(SEPARATOR, "")
62
+ return stripped unless stripped.empty?
63
+ end
64
+
65
+ rendered
66
+ end
67
+
68
+ # Longest first, so `ISO/IEC` wins over `ISO`. Each prefix also comes in
69
+ # its annotated spelling: ISO annotates inside its own renderer, so its
70
+ # string already reads `<span class="publisher">ISO</span> …` when it
71
+ # reaches this class.
72
+ def prefixes
73
+ Array(@id.publisher_prefixes)
74
+ .map { |p| p.to_s.strip }
75
+ .reject(&:empty?)
76
+ .flat_map { |p| [%(<span class="publisher">#{p}</span>), p] }
77
+ .uniq
78
+ .sort_by { |p| -p.length }
79
+ end
80
+ end
81
+ end
82
+ end
@@ -3,7 +3,7 @@
3
3
  module Pubid
4
4
  module Renderers
5
5
  class SupplementRenderer < HumanReadable
6
- def render(context:, with_edition: false)
6
+ def render(context:, with_edition: false, **_opts)
7
7
  parts = []
8
8
 
9
9
  base_str = @id.base.to_s(
@@ -3,6 +3,7 @@
3
3
  module Pubid
4
4
  module Renderers
5
5
  autoload :Annotator, "pubid/renderers/annotator"
6
+ autoload :PublisherStripper, "pubid/renderers/publisher_stripper"
6
7
  autoload :Base, "pubid/renderers/base"
7
8
  autoload :DirectivesRenderer, "pubid/renderers/directives_renderer"
8
9
  autoload :GuideRenderer, "pubid/renderers/guide_renderer"
@@ -1,55 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "parslet"
4
-
5
3
  module Pubid
6
4
  module Sae
7
- class Parser < ::Pubid::Parser::Grammar
8
- rule(:space) { str(" ") }
9
- rule(:digit) { match["0-9"] }
10
- rule(:digits) { digit.repeat(1) }
11
- rule(:letter) { match["A-Z"] }
12
- rule(:colon) { str(":") }
13
-
14
- # Publisher
15
- rule(:publisher) { str("SAE").as(:publisher) }
16
-
17
- # Document types with optional number suffix (e.g., J300, J308A)
18
- rule(:doc_type) do
19
- (
20
- str("AMS") | # Aerospace Material Specification
21
- str("AIR") | # Aerospace Information Report
22
- str("ARP") | # Aerospace Recommended Practice
23
- str("AS") | # Aerospace Standard
24
- str("J") | # SAE Standard (e.g., J300)
25
- str("MA") # Material Advisory
26
- ).as(:type)
27
- end
28
-
29
- # Number with optional letter prefix or suffix
30
- rule(:number) do
31
- ((letter.repeat(1,
32
- 1) >> digits) | (digits >> letter.repeat(0,
33
- 1))).as(:number)
34
- end
35
-
36
- # Year
37
- rule(:year) { digit.repeat(4, 4).as(:year) }
38
-
39
- # Date
40
- rule(:date) { colon >> year }
41
-
42
- # Main identifier
43
- rule(:identifier) do
44
- publisher >> space >> doc_type >> space.maybe >>
45
- number >> date.maybe
46
- end
47
-
48
- root(:identifier)
49
-
50
- def self.parse(input)
51
- new.parse(input)
52
- end
5
+ class Parser
53
6
  end
54
7
  end
55
8
  end
@@ -113,7 +113,7 @@ module Pubid
113
113
  raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
114
114
  end
115
115
 
116
- parsed = Pubid::Parg::Backend.parse(:tgpp, identifier)
116
+ parsed = Pubid::Parg::Model.bound(:tgpp, identifier)
117
117
  Builder.build(parsed)
118
118
  end
119
119
  end
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "parslet"
4
-
5
3
  module Pubid
6
4
  module Tgpp
7
- # Parslet grammar for 3GPP identifiers.
5
+ # Grammar for 3GPP identifiers.
8
6
  #
9
7
  # Form: `[3GPP ]<TR|TS> <NN.NNN>[suffix][-part…][:<release>][/<version>]`
10
8
  # TS 23.207:REL-4/2.0.0
@@ -17,62 +15,7 @@ module Pubid
17
15
  # document alone ("3GPP TS 23.207"), and relaton parses that bare form to
18
16
  # search the index. Only the type and the dotted number core are required,
19
17
  # so "TS" and "TS foo" are still rejected.
20
- class Parser < ::Pubid::Parser::Grammar
21
- rule(:digit) { match["0-9"] }
22
- rule(:digits) { digit.repeat(1) }
23
- rule(:space) { str(" ") }
24
-
25
- # Optional leading publisher token.
26
- rule(:publisher_prefix) { str("3GPP") >> space }
27
-
28
- # Document type.
29
- rule(:type) { (str("TR") | str("TS")).as(:type) }
30
-
31
- # Dotted number core, kept as a string (preserves leading zeros).
32
- rule(:number_core) { (digits >> str(".") >> digits).as(:number) }
33
-
34
- # Letter suffix directly after the number ("U"/"dcs"/"ext"…). Generic so
35
- # future controlled-vocabulary values keep round-tripping.
36
- rule(:suffix) { match["A-Za-z"].repeat(1).as(:suffix) }
37
-
38
- # Hyphen parts.
39
- rule(:part) { str("-") >> digits.as(:part) }
40
- rule(:parts) { part.repeat(0).as(:parts) }
41
-
42
- # Release token, stored verbatim: everything up to the version separator.
43
- # Excludes ":" (as well as "/") so the ":"-delimited URN scheme can always
44
- # encode it — every real release ("REL-4", "Ph1", "UMTS", "Release 2000")
45
- # is colon-free.
46
- #
47
- # A trailing segment shaped exactly like a version is a mistyped "/"
48
- # separator ("TS 23.207:2.0.0"), not a release: no release in the 88,464
49
- # published index rows contains a dot at all. Reject it rather than
50
- # silently misfiling the version as the release — which only became
51
- # reachable once the version segment was made optional.
52
- rule(:release) do
53
- (version_core >> any.absent?).absent? >>
54
- match["^/:"].repeat(1).as(:release)
55
- end
56
-
57
- # Three-part version, kept as a string.
58
- rule(:version_core) do
59
- digits >> str(".") >> digits >> str(".") >> digits
60
- end
61
- rule(:version) { version_core.as(:version) }
62
-
63
- rule(:identifier) do
64
- publisher_prefix.maybe >>
65
- type >> space >>
66
- number_core >> suffix.maybe >> parts >>
67
- (str(":") >> release).maybe >>
68
- (str("/") >> version).maybe
69
- end
70
-
71
- rule(:root) { identifier }
72
-
73
- def self.parse(input)
74
- new.parse(input)
75
- end
18
+ class Parser
76
19
  end
77
20
  end
78
21
  end
@@ -32,7 +32,7 @@ module Pubid
32
32
  raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
33
33
  end
34
34
 
35
- parsed = Pubid::Parg::Backend.parse(:un, identifier, merge_top_sequence: false)
35
+ parsed = Pubid::Parg::Model.bound(:un, identifier)
36
36
  Builder.build(parsed)
37
37
  end
38
38
  end
@@ -1,25 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "parslet"
4
-
5
3
  module Pubid
6
4
  module Un
7
- class Parser < ::Pubid::Parser::Grammar
8
- rule(:slash) { str("/") }
9
- rule(:un_prefix) { (str("UN") >> str(" ")).maybe }
10
- rule(:token) { match("[A-Z0-9.]").repeat(1) }
11
-
12
- rule(:identifier) do
13
- un_prefix >>
14
- token.as(:token) >>
15
- (slash >> token.as(:token)).repeat(1)
16
- end
17
-
18
- rule(:root) { identifier }
19
-
20
- def self.parse(input)
21
- new.parse(input)
22
- end
5
+ class Parser
23
6
  end
24
7
  end
25
8
  end
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.1"
4
+ VERSION = "2.0.3"
5
5
  end
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "parslet"
4
-
5
3
  module Pubid
6
4
  module W3c
7
- # Parslet grammar for printed W3C identifiers, e.g.
5
+ # Grammar for printed W3C identifiers, e.g.
8
6
  # "W3C WD-charmod-19991129" (type + code + date)
9
7
  # "W3C NOTE-xml-names" (type + code)
10
8
  # "W3C 2dcontext" (bare code)
@@ -14,30 +12,7 @@ module Pubid
14
12
  # greedily consume the trailing date and make a `.maybe` date rule
15
13
  # unreliable. This is safe: no real W3C code ends in a same-width (4/6/8)
16
14
  # digit run, so the Builder's fixed-width trailing-date test never collides.
17
- class Parser < ::Pubid::Parser::Grammar
18
- rule(:prefix) { str("W3C") >> str(" ") }
19
-
20
- # Known W3C maturity tokens. Order matters for shared prefixes: CRD before
21
- # CR, PER before PR, DNOTE before NOTE.
22
- rule(:type_token) do
23
- str("DNOTE") | str("NOTE") | str("WD") | str("CRD") | str("CR") |
24
- str("REC") | str("PER") | str("PR") | str("SPSD") | str("OBSL")
25
- end
26
-
27
- # A leading token is only a type when immediately followed by "-".
28
- rule(:type_part) { type_token.as(:type) >> str("-") }
29
-
30
- # The remainder: code plus an optional trailing date. Captured whole and
31
- # split in the Builder.
32
- rule(:rest) { any.repeat(1).as(:rest) }
33
-
34
- rule(:identifier) { prefix >> type_part.maybe >> rest }
35
-
36
- rule(:root) { identifier }
37
-
38
- def self.parse(input)
39
- new.parse(input)
40
- end
15
+ class Parser
41
16
  end
42
17
  end
43
18
  end
@@ -30,15 +30,19 @@ module Pubid
30
30
  # publisher name in an identifier — the leading token is "XEP".
31
31
  PUBLISHER = "XSF"
32
32
 
33
- attr_reader :with_publisher
34
-
35
- # Basic string representation. Delegates to renderer; `with_publisher:
36
- # false` yields the bare number.
37
- def to_s(with_publisher: true, **opts)
38
- @with_publisher = with_publisher
33
+ # Basic string representation. Delegates to renderer.
34
+ #
35
+ # `with_publisher:` is accepted and has no effect: `XEP` names the
36
+ # series, and XSF itself cites `XEP 0001`, so the internal form is the
37
+ # external one (see {#publisher_prefixes}).
38
+ def to_s(**opts)
39
39
  render(format: :human, **opts)
40
40
  end
41
41
 
42
+ def publisher_prefixes
43
+ []
44
+ end
45
+
42
46
  # from_hash is the shared polymorphic dispatch on Pubid::Identifier;
43
47
  # XSF_TYPE_MAP remains as the key_value polymorphic_map.
44
48
 
@@ -1,38 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "parslet"
4
-
5
3
  module Pubid
6
4
  module Xsf
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
-
17
- rule(:digit) { match["0-9"] }
18
- rule(:digits) { digit.repeat(1) }
19
-
20
- rule(:special_number) do
21
- SPECIAL_NUMBERS.map { |name| str(name) }.reduce(:|)
22
- end
23
-
24
- # "XEP 0001" — publisher token, a single space, then the number kept as
25
- # a string of digits (leading zeros preserved by the builder), or the
26
- # name of one of the two named documents.
27
- rule(:identifier) do
28
- str("XEP") >> str(" ") >> (digits | special_number).as(:number)
29
- end
30
-
31
- rule(:root) { identifier }
32
-
33
- def self.parse(input)
34
- new.parse(input)
35
- end
5
+ # Grammar for XSF identifiers. Two shapes: "XEP NNNN", and the two
6
+ # named documents (README and the four-x placeholder).
7
+ class Parser
36
8
  end
37
9
  end
38
10
  end
@@ -4,8 +4,8 @@ module Pubid
4
4
  module Xsf
5
5
  # Human-readable renderer for XSF identifiers.
6
6
  #
7
- # Produces strings like "XEP 0001". With `with_publisher: false` it emits
8
- # just the bare number ("0001").
7
+ # Produces strings like "XEP 0001". The `XEP` token is the series and is
8
+ # always rendered.
9
9
  #
10
10
  # Registered as the `:human` format in the XSF format registry and invoked
11
11
  # via `render(format: :human)`.
@@ -14,8 +14,6 @@ module Pubid
14
14
 
15
15
  def render(context: nil, **opts)
16
16
  id = @id
17
- return id.number.to_s if id.with_publisher == false
18
-
19
17
  "#{PUBLISHER} #{id.number}"
20
18
  end
21
19
  end
data/lib/pubid.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "lutaml/model"
4
- require "parslet"
5
4
 
6
5
  # Eagerly load the Lutaml::Model patch (disables reference store to avoid
7
6
  # unbounded memory growth during bulk parsing, and adds a default +to_urn+
@@ -114,7 +113,7 @@ module Pubid
114
113
  #
115
114
  # @param string [String] the identifier string
116
115
  # @return [Pubid::Identifier]
117
- # @raise [Parslet::ParseFailed] when no flavor can parse it
116
+ # @raise [Pubid::Errors::ParseError] when no flavor can parse it
118
117
  def parse(string, **opts)
119
118
  Pubid.parse(string, **opts)
120
119
  end
@@ -238,7 +237,7 @@ module Pubid
238
237
  # @param format [Symbol] :auto, :human, :mr_string, or :urn
239
238
  # @return [Identifier] The parsed identifier
240
239
  # @raise [ArgumentError] for a non-String, or one over {MAX_INPUT_LENGTH}
241
- # @raise [Parslet::ParseFailed] when no flavor can parse the string — the
240
+ # @raise [Pubid::Errors::ParseError] when no flavor can parse the string — the
242
241
  # class every flavor's own +parse+ raises (see the parse-failure contract)
243
242
  def self.parse(string, format: :auto)
244
243
  unless string.is_a?(String)
@@ -259,13 +258,13 @@ module Pubid
259
258
  # standing example. Fall through to prefix routing when the MR parse
260
259
  # fails, rather than reporting an MR error for a string that was never
261
260
  # an MR string. A genuine MR failure still surfaces, from the second
262
- # attempt, as Parslet::ParseFailed.
261
+ # attempt, as Pubid::Errors::ParseError.
263
262
  #
264
263
  # Narrow, for the reason spelled out on {parse_by_prefix}: only a parse
265
264
  # failure means "wrong shape". Anything else is a defect and propagates.
266
265
  begin
267
266
  Parsers::MrString.parse(string)
268
- rescue Parslet::ParseFailed
267
+ rescue Pubid::Errors::ParseError
269
268
  parse_by_prefix(string)
270
269
  end
271
270
  when :urn
@@ -358,7 +357,7 @@ module Pubid
358
357
  #
359
358
  # @param string [String] a human-readable identifier
360
359
  # @return [Identifier]
361
- # @raise [Parslet::ParseFailed] when no flavor accepts the string
360
+ # @raise [Pubid::Errors::ParseError] when no flavor accepts the string
362
361
  # @api private
363
362
  def self.parse_by_prefix(string)
364
363
  eager_load_flavors!
@@ -370,7 +369,7 @@ module Pubid
370
369
  (prefix_owners + other_candidates(prefix_owners)).each do |mod|
371
370
  begin
372
371
  parsed = mod.parse(string)
373
- rescue Parslet::ParseFailed => e
372
+ rescue Pubid::Errors::ParseError => e
374
373
  # ONLY a parse failure means "not this flavor's identifier". Every
375
374
  # other exception is a defect in that flavor and must propagate.
376
375
  #
@@ -411,7 +410,7 @@ module Pubid
411
410
  return fallback if fallback
412
411
  raise first_error if first_error
413
412
 
414
- raise Parslet::ParseFailed,
413
+ raise Pubid::Errors::ParseError,
415
414
  "no registered flavor could parse #{string.inspect}"
416
415
  end
417
416
  private_class_method :parse_by_prefix
@@ -474,7 +473,7 @@ module Pubid
474
473
  begin
475
474
  mod.parse(ROUTING_PROBE)
476
475
  true
477
- rescue StandardError, Parslet::ParseFailed
476
+ rescue StandardError, Pubid::Errors::ParseError
478
477
  false
479
478
  end
480
479
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pubid
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-10-29 00:00:00.000000000 Z
11
+ date: 2026-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lutaml-model
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.8'
27
- - !ruby/object:Gem::Dependency
28
- name: parslet
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: parsanol
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -112,10 +98,12 @@ files:
112
98
  - data/parg/iec.json
113
99
  - data/parg/ieee.json
114
100
  - data/parg/ietf.json
101
+ - data/parg/iho.json
115
102
  - data/parg/ire.json
116
103
  - data/parg/ire.parg
117
104
  - data/parg/isbn.json
118
105
  - data/parg/iso.json
106
+ - data/parg/iso.parg
119
107
  - data/parg/itu.json
120
108
  - data/parg/jcgm.json
121
109
  - data/parg/jis.json
@@ -429,6 +417,7 @@ files:
429
417
  - lib/pubid/csa/composite_identifier.rb
430
418
  - lib/pubid/csa/identifier.rb
431
419
  - lib/pubid/csa/identifiers.rb
420
+ - lib/pubid/csa/identifiers/amendment.rb
432
421
  - lib/pubid/csa/identifiers/base.rb
433
422
  - lib/pubid/csa/identifiers/bundled.rb
434
423
  - lib/pubid/csa/identifiers/canadian_adopted.rb
@@ -627,7 +616,6 @@ files:
627
616
  - lib/pubid/ieee/aiee.rb
628
617
  - lib/pubid/ieee/aiee/builder.rb
629
618
  - lib/pubid/ieee/aiee/identifier.rb
630
- - lib/pubid/ieee/aiee/parser.rb
631
619
  - lib/pubid/ieee/builder.rb
632
620
  - lib/pubid/ieee/compaction.rb
633
621
  - lib/pubid/ieee/components/code.rb
@@ -666,11 +654,9 @@ files:
666
654
  - lib/pubid/ieee/ire.rb
667
655
  - lib/pubid/ieee/ire/builder.rb
668
656
  - lib/pubid/ieee/ire/identifier.rb
669
- - lib/pubid/ieee/ire/parser.rb
670
657
  - lib/pubid/ieee/long_renderer.rb
671
658
  - lib/pubid/ieee/nesc.rb
672
659
  - lib/pubid/ieee/nesc/builder.rb
673
- - lib/pubid/ieee/nesc/parser.rb
674
660
  - lib/pubid/ieee/parser.rb
675
661
  - lib/pubid/ieee/pre_parser.rb
676
662
  - lib/pubid/ieee/project_renderer.rb
@@ -696,6 +682,7 @@ files:
696
682
  - lib/pubid/ietf/urn_generator.rb
697
683
  - lib/pubid/ietf/urn_parser.rb
698
684
  - lib/pubid/iho.rb
685
+ - lib/pubid/iho/CLAUDE.md
699
686
  - lib/pubid/iho/builder.rb
700
687
  - lib/pubid/iho/identifier.rb
701
688
  - lib/pubid/iho/identifiers.rb
@@ -705,7 +692,6 @@ files:
705
692
  - lib/pubid/iho/identifiers/miscellaneous.rb
706
693
  - lib/pubid/iho/identifiers/publication.rb
707
694
  - lib/pubid/iho/identifiers/standard.rb
708
- - lib/pubid/iho/parser.rb
709
695
  - lib/pubid/iho/renderer.rb
710
696
  - lib/pubid/iho/urn_generator.rb
711
697
  - lib/pubid/iho/urn_parser.rb
@@ -807,6 +793,7 @@ files:
807
793
  - lib/pubid/jcgm/urn_generator.rb
808
794
  - lib/pubid/jcgm/urn_parser.rb
809
795
  - lib/pubid/jis.rb
796
+ - lib/pubid/jis/CLAUDE.md
810
797
  - lib/pubid/jis/builder.rb
811
798
  - lib/pubid/jis/identifier.rb
812
799
  - lib/pubid/jis/identifiers.rb
@@ -818,6 +805,7 @@ files:
818
805
  - lib/pubid/jis/identifiers/standard.rb
819
806
  - lib/pubid/jis/identifiers/technical_report.rb
820
807
  - lib/pubid/jis/identifiers/technical_specification.rb
808
+ - lib/pubid/jis/identifiers/welding_engineering_standard.rb
821
809
  - lib/pubid/jis/parser.rb
822
810
  - lib/pubid/jis/renderer.rb
823
811
  - lib/pubid/jis/single_identifier.rb
@@ -941,9 +929,6 @@ files:
941
929
  - lib/pubid/parg/backend.rb
942
930
  - lib/pubid/parg/model.rb
943
931
  - lib/pubid/parser.rb
944
- - lib/pubid/parser/common_parse_methods.rb
945
- - lib/pubid/parser/common_parse_rules.rb
946
- - lib/pubid/parser/grammar.rb
947
932
  - lib/pubid/parsers/base.rb
948
933
  - lib/pubid/parsers/mr_string.rb
949
934
  - lib/pubid/parsers/urn.rb
@@ -970,6 +955,7 @@ files:
970
955
  - lib/pubid/renderers/human_readable.rb
971
956
  - lib/pubid/renderers/iwa_renderer.rb
972
957
  - lib/pubid/renderers/mr_string.rb
958
+ - lib/pubid/renderers/publisher_stripper.rb
973
959
  - lib/pubid/renderers/supplement_renderer.rb
974
960
  - lib/pubid/renderers/urn.rb
975
961
  - lib/pubid/rendering.rb