pubid 2.0.0.pre.alpha.35 → 2.0.0.pre.alpha.37

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.
@@ -1137,13 +1137,18 @@ module Pubid
1137
1137
  # P15026.2/D=FDIS-201008") captures the stage and the verbatim
1138
1138
  # date token (":2020", "-201008") with no publisher slot; the
1139
1139
  # designator is the IEEE face, so IEEE is the sole publisher.
1140
- if parsed[:iso_stage] && parsed[:draft_stage_year]
1140
+ # The no-year form ("IEEE P12207/D=CD1") rides the same D=
1141
+ # designator when the stage carries the glued iteration digit —
1142
+ # the token boundary only the designation route produces.
1143
+ if parsed[:iso_stage] && (parsed[:draft_stage_year] ||
1144
+ (original_input.to_s.include?("/D=") &&
1145
+ extract_value(parsed[:iso_stage]).to_s.match?(/\A[A-Z]+\d\z/)))
1141
1146
  stage_word = extract_value(parsed[:iso_stage])
1142
1147
  attributes[:publishers] ||= ["IEEE"]
1143
1148
  attributes[:publisher] ||= "IEEE"
1144
1149
  attributes[:copublisher] ||= []
1145
1150
  attributes[:ieee_draft] =
1146
- "D=#{stage_word}#{extract_value(parsed[:draft_stage_year])}"
1151
+ "D=#{stage_word}#{extract_value(parsed[:draft_stage_year]).to_s}"
1147
1152
  attributes[:typed_stage] = Pubid::Ieee.locate_stage(stage_word)
1148
1153
  attributes[:lead_party] = "IEEE"
1149
1154
  attributes.delete(:year)
@@ -664,10 +664,12 @@ module Pubid
664
664
  str("ISO/IEC") | str("IEEE"))
665
665
  # ISO stage codes: FDIS, FCD, CDV; DIS/CD with an optional round
666
666
  # digit (DIS2, CD1..CD4); WD/PWI/NP.
667
- iso_stage = (str("FDIS") | str("FCD") | str("CDV") |
667
+ iso_stage = ((str("FDIS") >> digit.maybe) | (str("FCD") >> digit.maybe) |
668
+ (str("CDV") >> digit.maybe) |
668
669
  (str("DIS") >> digit.maybe) |
669
670
  (str("CD") >> digit.maybe) |
670
- str("WD") | str("PWI") | str("NP")).as(:iso_stage)
671
+ (str("WD") >> digit.maybe) | (str("PWI") >> digit.maybe) |
672
+ (str("NP") >> digit.maybe)).as(:iso_stage)
671
673
  std_noise = (space >> str("Std")).maybe
672
674
  # The empty-string marker distinguishes the stage-less PUBLISHED
673
675
  # tree in the builder (absence of :iso_stage alone means IEEE format).
@@ -719,10 +721,12 @@ module Pubid
719
721
  # D (draft) = the ISO/IEC stage it drafts, with its iteration
720
722
  # (docs/IEEE-DRAFT-STAGES.md §1.2).
721
723
  ((slash >> str("D") >> str("=") >>
722
- (str("FDIS") | str("FCD") | str("CDV") |
724
+ ((str("FDIS") >> digit.maybe) | (str("FCD") >> digit.maybe) |
725
+ (str("CDV") >> digit.maybe) |
723
726
  (str("DIS") >> digit.maybe) |
724
727
  (str("CD") >> digit.maybe) |
725
- str("WD") | str("PWI") | str("NP")).as(:draft_iso_stage) >>
728
+ (str("WD") >> digit.maybe) | (str("PWI") >> digit.maybe) |
729
+ (str("NP") >> digit.maybe)).as(:draft_iso_stage) >>
726
730
  (dot >> (digits >> match("[A-Za-z]").repeat(0, 1)).as(:draft_iso_iteration)).maybe) |
727
731
  (slash >> str("D") >> dash.maybe >>
728
732
  match('[0-9.]').repeat(1).as(:draft_version) >>
@@ -806,10 +810,12 @@ module Pubid
806
810
  # can't match inside a longer token and a glued no-space date
807
811
  # (".DISMay2013") is left to fall through.
808
812
  dot >>
809
- (str("FDIS") | str("FCD") | str("CDV") |
813
+ ((str("FDIS") >> digit.maybe) | (str("FCD") >> digit.maybe) |
814
+ (str("CDV") >> digit.maybe) |
810
815
  (str("DIS") >> digit.maybe) |
811
816
  (str("CD") >> digit.maybe) |
812
- str("WD") | str("PWI") | str("NP")).as(:iso_stage) >>
817
+ (str("WD") >> digit.maybe) | (str("PWI") >> digit.maybe) |
818
+ (str("NP") >> digit.maybe)).as(:iso_stage) >>
813
819
  (digit | match("[A-Za-z]")).absent? >>
814
820
  # optional trailing date: :YYYY, -YYYY[-MM], or text "Month YYYY"
815
821
  (
@@ -151,6 +151,15 @@ module Pubid
151
151
  return { second_number: value }
152
152
  end
153
153
 
154
+ # NEW: Handle second_number with revision_simple ("8278.r1" — the
155
+ # dotted revision spelling): fold to the edition, matching the
156
+ # glued "8278r1" canonical. The former fall-through stringified
157
+ # the raw parser hash into the number.
158
+ if type == :second_number && value.is_a?(Hash) && value[:revision_simple]
159
+ edition_id = value[:revision_simple][:edition_id].to_s
160
+ return { edition: Components::Edition.new(type: "r", id: edition_id) }
161
+ end
162
+
154
163
  # NEW: Handle second_number with revision_letter (hash with :revision_letter containing :number_only and :letter)
155
164
  # This handles "27ra" pattern where parser returns {revision_letter: {number_only: "27", letter: "a"}}
156
165
  # Should be combined to "27rA" format
@@ -294,8 +294,10 @@ module Pubid
294
294
  (digits >> (str(".") >> digits).maybe).as(:edition_id)).as(:revision_simple) |
295
295
  # Special patterns like "NCNR", "PERMIS", "BFRL"
296
296
  str("NCNR") | str("PERMIS") | str("BFRL") |
297
- # Just capital letters (e.g., "A", "B", "C") - standalone
298
- upper_letter.repeat(1, 3) |
297
+ # Just capital letters (e.g., "A", "B", "C") - standalone;
298
+ # a trailing lowercase means a capitalized word ("Suppl"),
299
+ # not a second number.
300
+ upper_letter.repeat(1, 3) >> lower_letter.absent? |
299
301
  # Regular number with optional suffix - but NOT if part of FIPS date (digit-dash-month-digit-slash)
300
302
  (digits_with_suffix >> (dash >> month_abbrev >> digits >> slash).absent?) |
301
303
  # Single lowercase letter (e.g., "a", "b") - but NOT "r" followed by digits (edition marker)
@@ -576,11 +578,20 @@ module Pubid
576
578
  (space | dash).maybe >> (digits | str("")).as(:addendum_number)).as(:addendum)
577
579
  end
578
580
 
581
+ # The capitalized supplement words a letter slot must yield to.
582
+ rule(:supplement_word) do
583
+ str("Suppl") | str("Supp") | str("Sup")
584
+ end
585
+
579
586
  # Supplement - enhanced to support date patterns, year patterns, and combined with revision
580
587
  # Examples: suppJan1924, supp3/1926, supp1925, supJun1925-Jun1927 (date ranges), supprev
581
588
  rule(:supplement) do
582
589
  space.maybe >>
583
- (str("supp") | str("sup")) >>
590
+ dot.maybe >>
591
+ # The capitalized catalogue spellings ("NIST.SP.955.Suppl") ride
592
+ # the same slot; longest-first so "Suppl" is not "Sup"+"p".
593
+ (str("Suppl") | str("Supp") | str("Sup") |
594
+ str("supp") | str("sup")) >>
584
595
  (
585
596
  # Supplement followed by revision: supprev
586
597
  str("rev").as(:supplement_with_rev) |
@@ -684,14 +695,15 @@ module Pubid
684
695
  simple_series >> dot.maybe >> report_number.maybe >>
685
696
  # Edition with underscore separator (MR format: 1648_2009)
686
697
  (str("_") >> digits.as(:edition_year)).maybe >>
687
- # Support letter suffix before update (e.g., 8286C-upd1) - Session 219
688
- upper_letter.maybe >>
698
+ # Support letter suffix before update (e.g., 8286C-upd1) - Session 219;
699
+ # a capitalized supplement word ("Suppl") is not a letter suffix.
700
+ supplement_word.absent?.maybe >> upper_letter.maybe >>
689
701
  # Support revision component (r1, r5, etc.) before update
690
702
  edition.maybe >>
691
703
  update.maybe >>
692
704
  # Additional dot-separated parts (parts, version, volume, etc.)
693
705
  # MUST come before translation to avoid conflicting with language codes
694
- (dot >> (digits | upper_letter)).repeat(0, 3) >>
706
+ (dot >> (digits | (supplement_word.absent? >> upper_letter))).repeat(0, 3) >>
695
707
  # Language codes at end (.spa, .por, .ind)
696
708
  parts.repeat >> draft.maybe
697
709
  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.0.pre.alpha.35"
4
+ VERSION = "2.0.0.pre.alpha.37"
5
5
  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.0.pre.alpha.35
4
+ version: 2.0.0.pre.alpha.37
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-19 00:00:00.000000000 Z
11
+ date: 2026-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lutaml-model