pubid 2.0.0.pre.alpha.11 → 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.
- checksums.yaml +4 -4
- data/lib/pubid/bsi/components/date.rb +10 -4
- data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +1 -1
- data/lib/pubid/bsi/identifiers/handbook.rb +1 -1
- data/lib/pubid/bsi/identifiers/practice_guide.rb +1 -1
- data/lib/pubid/bsi/single_identifier.rb +11 -2
- data/lib/pubid/ccsds/identifier.rb +4 -0
- data/lib/pubid/ccsds/single_identifier.rb +14 -10
- data/lib/pubid/csa/builder.rb +3 -3
- data/lib/pubid/csa/identifiers/bundled.rb +2 -2
- data/lib/pubid/csa/identifiers/cec.rb +1 -1
- data/lib/pubid/csa/single_identifier.rb +1 -1
- data/lib/pubid/csa/urn_generator.rb +1 -1
- data/lib/pubid/evs/builder.rb +1 -1
- data/lib/pubid/evs/identifier.rb +6 -6
- data/lib/pubid/evs/identifiers/national_adoption.rb +7 -2
- data/lib/pubid/evs/renderer.rb +1 -1
- data/lib/pubid/evs/urn_generator.rb +1 -1
- data/lib/pubid/evs/urn_parser.rb +1 -1
- data/lib/pubid/gb/builder.rb +14 -9
- data/lib/pubid/gb/identifier.rb +23 -4
- data/lib/pubid/gb/parser.rb +4 -0
- data/lib/pubid/gb/renderer.rb +4 -3
- data/lib/pubid/gb.rb +1 -0
- data/lib/pubid/identifier.rb +11 -3
- data/lib/pubid/idf/identifier.rb +7 -0
- data/lib/pubid/idf/identifiers/amendment.rb +1 -1
- data/lib/pubid/idf/identifiers/corrigendum.rb +1 -1
- data/lib/pubid/idf/identifiers/international_standard.rb +1 -1
- data/lib/pubid/idf/identifiers/reviewed_method.rb +1 -1
- data/lib/pubid/idf/single_identifier.rb +1 -1
- data/lib/pubid/ieee/builder.rb +42 -2
- data/lib/pubid/ieee/identifiers/si_standard.rb +5 -2
- data/lib/pubid/ieee/ire/parser.rb +19 -1
- data/lib/pubid/ieee/parser.rb +207 -32
- data/lib/pubid/ieee/project_renderer.rb +46 -0
- data/lib/pubid/ieee/renderer.rb +6 -7
- data/lib/pubid/ieee.rb +2 -0
- data/lib/pubid/iso/builder.rb +10 -11
- data/lib/pubid/iso/components.rb +0 -1
- data/lib/pubid/iso/identifier.rb +11 -4
- data/lib/pubid/iso/identifiers/directives.rb +7 -4
- data/lib/pubid/iso/identifiers/tc_document.rb +31 -46
- data/lib/pubid/iso/normalizer.rb +1 -1
- data/lib/pubid/iso/urn_generator.rb +10 -10
- data/lib/pubid/iso.rb +5 -4
- data/lib/pubid/itu/builder.rb +10 -0
- data/lib/pubid/itu/identifiers/base.rb +10 -0
- data/lib/pubid/itu/identifiers/contribution.rb +31 -0
- data/lib/pubid/itu/identifiers.rb +1 -0
- data/lib/pubid/itu/parser.rb +19 -2
- data/lib/pubid/nist/builder.rb +12 -12
- data/lib/pubid/nist/identifiers/base.rb +10 -3
- data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +1 -1
- data/lib/pubid/nist/identifiers/crpl_report.rb +5 -6
- data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +2 -2
- data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +2 -2
- data/lib/pubid/nist/series/ir.rb +3 -7
- data/lib/pubid/oiml/builder.rb +2 -2
- data/lib/pubid/oiml/identifiers/bulletin.rb +30 -36
- data/lib/pubid/oiml/identifiers/code_number.rb +2 -2
- data/lib/pubid/oiml/parser.rb +7 -2
- data/lib/pubid/oiml/renderer.rb +3 -3
- data/lib/pubid/oiml/single_identifier.rb +1 -1
- data/lib/pubid/oiml/urn_generator.rb +4 -4
- data/lib/pubid/renderers/directives_renderer.rb +3 -1
- data/lib/pubid/sae/builder.rb +1 -1
- data/lib/pubid/sae/identifiers/base.rb +4 -1
- data/lib/pubid/sae/urn_generator.rb +1 -1
- data/lib/pubid/version.rb +1 -1
- data/lib/tasks/docs.rake +13 -11
- metadata +4 -4
- data/lib/pubid/ccsds/identifiers/base_BASE_88929.rb +0 -70
- data/lib/pubid/iso/components/code.rb +0 -24
|
@@ -6,18 +6,15 @@ module Pubid
|
|
|
6
6
|
# Technical Committee Document
|
|
7
7
|
# Format: TC 184/SC 4/WG 3 N 123, JTC 1 N 456, TC 184 N 100
|
|
8
8
|
class TcDocument < Identifier
|
|
9
|
-
#
|
|
10
|
-
|
|
11
|
-
#
|
|
12
|
-
attribute :
|
|
13
|
-
|
|
14
|
-
attribute :sc_type,
|
|
15
|
-
|
|
16
|
-
attribute :
|
|
17
|
-
|
|
18
|
-
attribute :wg_type, ::Pubid::Components::Code
|
|
19
|
-
# WG number
|
|
20
|
-
attribute :wg_number, ::Pubid::Components::Code
|
|
9
|
+
# The committee structure: plain strings ("TC", "184", "SC", "4").
|
|
10
|
+
# Each held a Components::Code carrying nothing but `value`, and the
|
|
11
|
+
# serialized form was already the bare scalar.
|
|
12
|
+
attribute :tc_type, :string
|
|
13
|
+
attribute :tc_number, :string
|
|
14
|
+
attribute :sc_type, :string
|
|
15
|
+
attribute :sc_number, :string
|
|
16
|
+
attribute :wg_type, :string
|
|
17
|
+
attribute :wg_number, :string
|
|
21
18
|
|
|
22
19
|
# TC types from ISO system
|
|
23
20
|
TC_TYPES = %w[TC JTC PC IT CAB CASCO COPOLCO COUNCIL CPSG CS DEVCO GA
|
|
@@ -33,33 +30,21 @@ module Pubid
|
|
|
33
30
|
# TC documents don't use typed stages like other identifiers
|
|
34
31
|
TYPED_STAGES = [].freeze
|
|
35
32
|
|
|
36
|
-
# Serialize the committee structure
|
|
37
|
-
#
|
|
33
|
+
# Serialize the committee structure on top of the inherited ISO
|
|
34
|
+
# mapping; TC documents have no stage. The attributes are plain
|
|
35
|
+
# strings, so lutaml needs no converter (the ETSI/OIML shape).
|
|
38
36
|
key_value do
|
|
39
|
-
map "tc_type",
|
|
40
|
-
map "tc_number",
|
|
41
|
-
map "sc_type",
|
|
42
|
-
map "sc_number",
|
|
43
|
-
map "wg_type",
|
|
44
|
-
map "wg_number",
|
|
37
|
+
map "tc_type", to: :tc_type
|
|
38
|
+
map "tc_number", to: :tc_number
|
|
39
|
+
map "sc_type", to: :sc_type
|
|
40
|
+
map "sc_number", to: :sc_number
|
|
41
|
+
map "wg_type", to: :wg_type
|
|
42
|
+
map "wg_number", to: :wg_number
|
|
45
43
|
end
|
|
46
44
|
|
|
47
45
|
# TC documents have no stage; suppress the inherited stage emission.
|
|
48
46
|
def stage_to_kv(_model, _doc); end
|
|
49
47
|
|
|
50
|
-
def tc_type_to_kv(m, doc) = emit_code(doc, "tc_type", m.tc_type)
|
|
51
|
-
def tc_type_from_kv(m, v) = m.tc_type = build_code(v)
|
|
52
|
-
def tc_number_to_kv(m, doc) = emit_code(doc, "tc_number", m.tc_number)
|
|
53
|
-
def tc_number_from_kv(m, v) = m.tc_number = build_code(v)
|
|
54
|
-
def sc_type_to_kv(m, doc) = emit_code(doc, "sc_type", m.sc_type)
|
|
55
|
-
def sc_type_from_kv(m, v) = m.sc_type = build_code(v)
|
|
56
|
-
def sc_number_to_kv(m, doc) = emit_code(doc, "sc_number", m.sc_number)
|
|
57
|
-
def sc_number_from_kv(m, v) = m.sc_number = build_code(v)
|
|
58
|
-
def wg_type_to_kv(m, doc) = emit_code(doc, "wg_type", m.wg_type)
|
|
59
|
-
def wg_type_from_kv(m, v) = m.wg_type = build_code(v)
|
|
60
|
-
def wg_number_to_kv(m, doc) = emit_code(doc, "wg_number", m.wg_number)
|
|
61
|
-
def wg_number_from_kv(m, v) = m.wg_number = build_code(v)
|
|
62
|
-
|
|
63
48
|
def self.type
|
|
64
49
|
{ key: :tc,
|
|
65
50
|
web: :tc_document, title: "Technical Committee Document", short: "TC" }
|
|
@@ -73,23 +58,23 @@ module Pubid
|
|
|
73
58
|
result = publisher.to_s if publisher
|
|
74
59
|
|
|
75
60
|
# Add TC type and number
|
|
76
|
-
result += "/#{tc_type
|
|
77
|
-
result += tc_number.
|
|
61
|
+
result += "/#{tc_type} " unless tc_type.to_s.empty?
|
|
62
|
+
result += tc_number.to_s unless tc_number.to_s.empty?
|
|
78
63
|
|
|
79
64
|
# Add SC type and number
|
|
80
|
-
|
|
81
|
-
result += "/#{sc_type
|
|
82
|
-
result += sc_number.
|
|
65
|
+
unless sc_type.to_s.empty? || sc_number.to_s.empty?
|
|
66
|
+
result += "/#{sc_type} "
|
|
67
|
+
result += sc_number.to_s
|
|
83
68
|
end
|
|
84
69
|
|
|
85
70
|
# Add WG type and number
|
|
86
|
-
|
|
87
|
-
result += "/#{wg_type
|
|
88
|
-
result += wg_number.
|
|
71
|
+
unless wg_type.to_s.empty? || wg_number.to_s.empty?
|
|
72
|
+
result += "/#{wg_type} "
|
|
73
|
+
result += wg_number.to_s
|
|
89
74
|
end
|
|
90
75
|
|
|
91
76
|
# Add document number
|
|
92
|
-
result += " N #{number
|
|
77
|
+
result += " N #{number}" unless number.to_s.empty?
|
|
93
78
|
|
|
94
79
|
# Add year if present
|
|
95
80
|
result += ":#{date.render}" if date&.year
|
|
@@ -105,16 +90,16 @@ module Pubid
|
|
|
105
90
|
parts << publisher.render(context: urn_ctx) if publisher
|
|
106
91
|
|
|
107
92
|
# Add TC
|
|
108
|
-
parts << "tc:#{tc_number
|
|
93
|
+
parts << "tc:#{tc_number}" unless tc_number.to_s.empty?
|
|
109
94
|
|
|
110
95
|
# Add SC
|
|
111
|
-
parts << "sc-#{sc_number
|
|
96
|
+
parts << "sc-#{sc_number}" unless sc_number.to_s.empty?
|
|
112
97
|
|
|
113
98
|
# Add WG
|
|
114
|
-
parts << "wg-#{wg_number
|
|
99
|
+
parts << "wg-#{wg_number}" unless wg_number.to_s.empty?
|
|
115
100
|
|
|
116
101
|
# Add document number
|
|
117
|
-
parts << number.
|
|
102
|
+
parts << number.to_s unless number.to_s.empty?
|
|
118
103
|
|
|
119
104
|
parts.join(":")
|
|
120
105
|
end
|
data/lib/pubid/iso/normalizer.rb
CHANGED
|
@@ -73,7 +73,7 @@ module Pubid
|
|
|
73
73
|
|
|
74
74
|
addendum = Identifiers::Addendum.new
|
|
75
75
|
addendum.base = base
|
|
76
|
-
addendum.number =
|
|
76
|
+
addendum.number = supplement_number
|
|
77
77
|
addendum.date = Pubid::Components::Date.new(year: supplement_year) if supplement_year
|
|
78
78
|
|
|
79
79
|
typed_stage = Pubid::Iso.locate_stage(stage_abbr)
|
|
@@ -63,7 +63,7 @@ module Pubid
|
|
|
63
63
|
parts << originator_component
|
|
64
64
|
type_comp = type_component
|
|
65
65
|
parts << type_comp if type_comp
|
|
66
|
-
parts << identifier.number.
|
|
66
|
+
parts << identifier.number.to_s if identifier.number
|
|
67
67
|
part_comp = part_component
|
|
68
68
|
parts << part_comp if part_comp
|
|
69
69
|
stage_comp = stage_component
|
|
@@ -95,7 +95,7 @@ module Pubid
|
|
|
95
95
|
parts << base_gen.originator_component
|
|
96
96
|
type_comp = base_gen.type_component
|
|
97
97
|
parts << type_comp if type_comp
|
|
98
|
-
parts << base_id.number.
|
|
98
|
+
parts << base_id.number.to_s if base_id.number
|
|
99
99
|
part_comp = base_gen.part_component
|
|
100
100
|
parts << part_comp if part_comp
|
|
101
101
|
|
|
@@ -138,13 +138,13 @@ module Pubid
|
|
|
138
138
|
parts << supp.date.render(context: URN_CONTEXT)
|
|
139
139
|
if supp.number
|
|
140
140
|
if supp.stage_iteration && !supp.is_a?(Pubid::Iso::Identifiers::Supplement)
|
|
141
|
-
parts << "v#{supp.number
|
|
141
|
+
parts << "v#{supp.number}.#{supp.stage_iteration.render(context: URN_CONTEXT)}"
|
|
142
142
|
else
|
|
143
|
-
parts << "v#{supp.number
|
|
143
|
+
parts << "v#{supp.number}"
|
|
144
144
|
end
|
|
145
145
|
end
|
|
146
146
|
else
|
|
147
|
-
parts << supp.number.
|
|
147
|
+
parts << supp.number.to_s if supp.number
|
|
148
148
|
if supp.stage_iteration && !supp.is_a?(Pubid::Iso::Identifiers::Supplement)
|
|
149
149
|
parts << "v1.#{supp.stage_iteration.render(context: URN_CONTEXT)}"
|
|
150
150
|
else
|
|
@@ -197,8 +197,8 @@ module Pubid
|
|
|
197
197
|
def part_component
|
|
198
198
|
return nil unless identifier.part
|
|
199
199
|
|
|
200
|
-
result = "-#{identifier.part
|
|
201
|
-
result += "-#{identifier.subpart
|
|
200
|
+
result = "-#{identifier.part}"
|
|
201
|
+
result += "-#{identifier.subpart}" if identifier.subpart
|
|
202
202
|
result
|
|
203
203
|
end
|
|
204
204
|
|
|
@@ -292,13 +292,13 @@ module Pubid
|
|
|
292
292
|
parts << identifier.date.render(context: URN_CONTEXT)
|
|
293
293
|
if identifier.number
|
|
294
294
|
parts << if identifier.stage_iteration
|
|
295
|
-
"v#{identifier.number
|
|
295
|
+
"v#{identifier.number}.#{identifier.stage_iteration.render(context: URN_CONTEXT)}"
|
|
296
296
|
else
|
|
297
|
-
"v#{identifier.number
|
|
297
|
+
"v#{identifier.number}"
|
|
298
298
|
end
|
|
299
299
|
end
|
|
300
300
|
else
|
|
301
|
-
parts << identifier.number.
|
|
301
|
+
parts << identifier.number.to_s if identifier.number
|
|
302
302
|
parts << if identifier.stage_iteration
|
|
303
303
|
"v1.#{identifier.stage_iteration.render(context: URN_CONTEXT)}"
|
|
304
304
|
else
|
data/lib/pubid/iso.rb
CHANGED
|
@@ -66,7 +66,7 @@ module Pubid
|
|
|
66
66
|
# @param type [Symbol] the type key (e.g. :is, :tr, :ts, :guide)
|
|
67
67
|
# @param publisher [String, Pubid::Iso::Components::Publisher] primary publisher
|
|
68
68
|
# @param copublishers [Array<String>, Array<Pubid::Components::Publisher>]
|
|
69
|
-
# @param number [String, Integer
|
|
69
|
+
# @param number [String, Integer]
|
|
70
70
|
# @param year [String, Integer, Pubid::Components::Date, nil]
|
|
71
71
|
# @param attrs [Hash] additional identifier attributes
|
|
72
72
|
# @return [Pubid::Iso::Identifier]
|
|
@@ -106,10 +106,11 @@ module Pubid
|
|
|
106
106
|
private_class_method :build_copublishers
|
|
107
107
|
|
|
108
108
|
# @!visibility private
|
|
109
|
+
# number/part/subpart are plain strings. A caller that still passes a
|
|
110
|
+
# Components::Code (another flavor's builder, a hand-built id) is read
|
|
111
|
+
# through its own #to_s rather than refused.
|
|
109
112
|
def self.build_code(value)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
Components::Code.new(value: value.to_s)
|
|
113
|
+
value.to_s
|
|
113
114
|
end
|
|
114
115
|
private_class_method :build_code
|
|
115
116
|
|
data/lib/pubid/itu/builder.rb
CHANGED
|
@@ -68,6 +68,16 @@ module Pubid
|
|
|
68
68
|
return build_question(data)
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
+
# Contribution (Temporary Document) — "ITU-R SG17-C1000" (pubid#340).
|
|
72
|
+
if data[:contribution_marker]
|
|
73
|
+
return Identifiers::Contribution.new(
|
|
74
|
+
sector: Components::Sector.new(sector: data[:sector].to_s),
|
|
75
|
+
series: Components::Series.new(series: data[:series].to_s),
|
|
76
|
+
code: build_code(data),
|
|
77
|
+
language: data[:language]&.to_s,
|
|
78
|
+
)
|
|
79
|
+
end
|
|
80
|
+
|
|
71
81
|
# Build basic recommendation or combined identifier
|
|
72
82
|
sector = Components::Sector.new(sector: data[:sector].to_s)
|
|
73
83
|
series = Components::Series.new(series: data[:series].to_s) if data[:series]
|
|
@@ -37,6 +37,16 @@ module Pubid
|
|
|
37
37
|
end
|
|
38
38
|
private_class_method :normalize_whitespace
|
|
39
39
|
|
|
40
|
+
# The type key used by Pubid::Itu.locate_type — the class name
|
|
41
|
+
# ("Contribution" => :contribution). No ITU leaf ever defined a
|
|
42
|
+
# `type` hash, so locate_type raised NoMethodError on every call;
|
|
43
|
+
# the derived default gives every concrete leaf a key for free
|
|
44
|
+
# (pubid#340's ask). metanorma-itu constructs via this lookup.
|
|
45
|
+
def self.type
|
|
46
|
+
leaf = name.split("::").last
|
|
47
|
+
{ key: leaf.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase.to_sym }
|
|
48
|
+
end
|
|
49
|
+
|
|
40
50
|
# Long-form ↔ ITU single-letter language code map. The parser produces
|
|
41
51
|
# single-letter codes (E/F/S/R/A/C); API callers (e.g. metanorma-itu)
|
|
42
52
|
# pass long-form (en/fr/es/ru/ar/zh). Storage is normalized to the
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Itu
|
|
5
|
+
module Identifiers
|
|
6
|
+
# ITU Contribution (Temporary Document) — the working documents a study
|
|
7
|
+
# group circulates, numbered per study group.
|
|
8
|
+
#
|
|
9
|
+
# Format: ITU-{SECTOR} {SERIES}-C{NUMBER} e.g. ITU-R SG17-C1000
|
|
10
|
+
#
|
|
11
|
+
# Mirrors pubid-itu 1.15's Pubid::Itu::Identifier::Contribution
|
|
12
|
+
# ("%{series}-C%{number}"), which metanorma-itu builds from
|
|
13
|
+
# `:doctype: contribution` documents (pubid#340).
|
|
14
|
+
class Contribution < Identifier
|
|
15
|
+
include StandardSerialization
|
|
16
|
+
|
|
17
|
+
def render_base(**_opts)
|
|
18
|
+
"#{publisher}-#{sector} #{series}-C#{code&.number}"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def ==(other)
|
|
22
|
+
return false unless other.is_a?(Contribution)
|
|
23
|
+
|
|
24
|
+
sector == other.sector &&
|
|
25
|
+
series == other.series &&
|
|
26
|
+
code == other.code
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -11,6 +11,7 @@ module Pubid
|
|
|
11
11
|
autoload :AppendixOfRecommendation,
|
|
12
12
|
"#{__dir__}/identifiers/appendix_of_recommendation"
|
|
13
13
|
autoload :CombinedIdentifier, "#{__dir__}/identifiers/combined_identifier"
|
|
14
|
+
autoload :Contribution, "#{__dir__}/identifiers/contribution"
|
|
14
15
|
autoload :Corrigendum, "#{__dir__}/identifiers/corrigendum"
|
|
15
16
|
autoload :Errata, "#{__dir__}/identifiers/errata"
|
|
16
17
|
autoload :Handbook, "#{__dir__}/identifiers/handbook"
|
data/lib/pubid/itu/parser.rb
CHANGED
|
@@ -323,6 +323,22 @@ module Pubid
|
|
|
323
323
|
(digits | letter.repeat(1)).as(:number) >> parts
|
|
324
324
|
end
|
|
325
325
|
|
|
326
|
+
# ITU Contribution (Temporary Document) — "ITU-R SG17-C1000" (pubid#340).
|
|
327
|
+
# The "-C" marker before the number distinguishes it from every
|
|
328
|
+
# neighbouring shape: a series-code document's post-dash number starts
|
|
329
|
+
# with digits or is all letters (never "C"+digits), and with_series
|
|
330
|
+
# requires a dot after the series.
|
|
331
|
+
rule(:contribution) do
|
|
332
|
+
itu_prefix >>
|
|
333
|
+
sector >>
|
|
334
|
+
space >>
|
|
335
|
+
series >>
|
|
336
|
+
str("-C").as(:contribution_marker) >>
|
|
337
|
+
number >>
|
|
338
|
+
parts >>
|
|
339
|
+
language.maybe
|
|
340
|
+
end
|
|
341
|
+
|
|
326
342
|
rule(:base_series_code) do
|
|
327
343
|
itu_prefix >>
|
|
328
344
|
sector >>
|
|
@@ -656,9 +672,10 @@ module Pubid
|
|
|
656
672
|
numeric_question |
|
|
657
673
|
letter_question |
|
|
658
674
|
with_series |
|
|
675
|
+
contribution |
|
|
659
676
|
# Unreachable earlier: special_publication needs the literal "OB",
|
|
660
|
-
# handbook/numeric_question need leading digits,
|
|
661
|
-
# needs series >> dot
|
|
677
|
+
# handbook/numeric_question need leading digits, letter_question
|
|
678
|
+
# needs series >> dot, and contribution needs "-C" after the series.
|
|
662
679
|
series_code_identifier |
|
|
663
680
|
without_series
|
|
664
681
|
end
|
data/lib/pubid/nist/builder.rb
CHANGED
|
@@ -253,7 +253,7 @@ module Pubid
|
|
|
253
253
|
elsif decimal_num
|
|
254
254
|
decimal_base = decimal_num[:decimal_base].to_s
|
|
255
255
|
decimal_suffix = decimal_num[:decimal_suffix].to_s
|
|
256
|
-
identifier.number =
|
|
256
|
+
identifier.number = "#{first_num.value}-#{decimal_base}.#{decimal_suffix}"
|
|
257
257
|
# NEW: Handle letter number pattern (e.g., 1-1A, 1-3B for NCSTAR identifiers)
|
|
258
258
|
# letter_num is {:letter_base => "1", :letter_suffix => "A"}
|
|
259
259
|
# Also handles IR series "R" suffix: "79-1786R" -> "79-1786r1"
|
|
@@ -268,10 +268,10 @@ module Pubid
|
|
|
268
268
|
# Series-specific handler took ownership (e.g., IR "R" → r1)
|
|
269
269
|
elsif identifier.part
|
|
270
270
|
# SpecialPublication pattern: letter_suffix is separate Part component
|
|
271
|
-
identifier.number =
|
|
271
|
+
identifier.number = "#{first_num.value}-#{letter_base}"
|
|
272
272
|
else
|
|
273
273
|
# NCSTAR pattern: letter_suffix is part of the number
|
|
274
|
-
identifier.number =
|
|
274
|
+
identifier.number = "#{first_num.value}-#{letter_base}#{letter_suffix}"
|
|
275
275
|
end
|
|
276
276
|
elsif second_num
|
|
277
277
|
# Check for special patterns first
|
|
@@ -285,7 +285,7 @@ module Pubid
|
|
|
285
285
|
# Create Edition component
|
|
286
286
|
edition_obj = Components::Edition.new(type: "r", id: edition_id)
|
|
287
287
|
|
|
288
|
-
identifier.number =
|
|
288
|
+
identifier.number = "#{first_num.value}-#{number_part}"
|
|
289
289
|
identifier.edition = edition_obj
|
|
290
290
|
# CS Emergency pattern: e104-43 -> number=104, edition_year=1943
|
|
291
291
|
# Logic: e104-43 means "emergency 104 from 1943" (43 = 1943)
|
|
@@ -300,7 +300,7 @@ module Pubid
|
|
|
300
300
|
# Create Edition component
|
|
301
301
|
edition_obj = Components::Edition.new(type: "e", id: edition_year)
|
|
302
302
|
|
|
303
|
-
identifier.number =
|
|
303
|
+
identifier.number = number_part
|
|
304
304
|
identifier.edition = edition_obj
|
|
305
305
|
elsif first_num.value.to_s.match?(/^(\d+)e(\d+)$/) &&
|
|
306
306
|
second_num.value.to_s.match?(/^\d{2,4}$/)
|
|
@@ -314,7 +314,7 @@ module Pubid
|
|
|
314
314
|
# Expand 2-digit year to 4-digit (50 -> 1950)
|
|
315
315
|
year_part = "19#{year_part}" if year_part.length == 2
|
|
316
316
|
|
|
317
|
-
identifier.number =
|
|
317
|
+
identifier.number = number_part
|
|
318
318
|
|
|
319
319
|
# For edition+year patterns, handling depends on identifier type:
|
|
320
320
|
# - CIRC: edition number + year as additional_text, rendered with dot ("11e2-1915" -> "11e2.1915")
|
|
@@ -329,7 +329,7 @@ module Pubid
|
|
|
329
329
|
number_part = first_num.value.to_s.match(/^(\d+)supp?$/)[1]
|
|
330
330
|
year_part = second_num.value.to_s
|
|
331
331
|
|
|
332
|
-
identifier.number =
|
|
332
|
+
identifier.number = number_part
|
|
333
333
|
supp[:value] = year_part
|
|
334
334
|
supp[:present] = true
|
|
335
335
|
elsif second_num.value.to_s.match?(/^(\d+)supp?$/)
|
|
@@ -337,14 +337,14 @@ module Pubid
|
|
|
337
337
|
# second number. Strip it and isolate as supplement="" (single-p).
|
|
338
338
|
second_part = second_num.value.to_s.match(/^(\d+)supp?$/)[1]
|
|
339
339
|
compound = "#{first_num.value}-#{second_part}"
|
|
340
|
-
identifier.number =
|
|
340
|
+
identifier.number = compound
|
|
341
341
|
supp[:value] = ""
|
|
342
342
|
supp[:present] = true
|
|
343
343
|
elsif identifier.is_a?(Identifiers::TechnicalNote) &&
|
|
344
344
|
second_num.value.to_s.match?(/^(19|20)\d{2}$/)
|
|
345
345
|
# SPECIAL CASE FOR TN: second_num is edition year
|
|
346
346
|
# Following "date IS edition" rule: -1993 becomes Edition(type: "e", id: "1993")
|
|
347
|
-
identifier.number = first_num
|
|
347
|
+
identifier.number = first_num.value.to_s
|
|
348
348
|
edition_obj = Components::Edition.new(type: "e",
|
|
349
349
|
id: second_num.value.to_s)
|
|
350
350
|
identifier.edition = edition_obj
|
|
@@ -354,16 +354,16 @@ module Pubid
|
|
|
354
354
|
# not folded into the compound number.
|
|
355
355
|
identifier.part = Components::Part.new(type: "pt",
|
|
356
356
|
value: part_num)
|
|
357
|
-
identifier.number =
|
|
357
|
+
identifier.number = "#{first_num.value}-#{second_num.value}"
|
|
358
358
|
else
|
|
359
359
|
# For GCR and others, include part number in compound number
|
|
360
360
|
compound_value = "#{first_num.value}-#{second_num.value}"
|
|
361
361
|
compound_value += "-#{part_num}" if part_num
|
|
362
|
-
identifier.number =
|
|
362
|
+
identifier.number = compound_value
|
|
363
363
|
end
|
|
364
364
|
else
|
|
365
365
|
# No second_num, use first_num directly
|
|
366
|
-
identifier.number = first_num
|
|
366
|
+
identifier.number = first_num.value.to_s
|
|
367
367
|
end
|
|
368
368
|
end
|
|
369
369
|
|
|
@@ -27,7 +27,7 @@ module Pubid
|
|
|
27
27
|
# bare { "value" => … } with no part;
|
|
28
28
|
# - drop the redundant build artifacts, decomposed pieces of the
|
|
29
29
|
# canonical number that identity/rendering never read.
|
|
30
|
-
COMPACT_FLAT_CODES = %w[series
|
|
30
|
+
COMPACT_FLAT_CODES = %w[series subseries].freeze
|
|
31
31
|
COMPACT_FLAT_VALUES = %w[volume].freeze
|
|
32
32
|
COMPACT_DROP_ATTRS = %w[first_number second_number].freeze
|
|
33
33
|
|
|
@@ -105,7 +105,14 @@ module Pubid
|
|
|
105
105
|
# equality so a manually-built id (without subseries set) still equals a
|
|
106
106
|
# parsed one.
|
|
107
107
|
attribute :subseries, Components::Code
|
|
108
|
-
|
|
108
|
+
# Plain :string. NIST never populated the Code beyond `value`: `subpart`
|
|
109
|
+
# is set nowhere, and `part` was a reader splitting `value` on "-" that
|
|
110
|
+
# no library code called. `series`, `subseries`, `first_number`,
|
|
111
|
+
# `second_number` and `parts` keep the component.
|
|
112
|
+
attribute :number, :string
|
|
113
|
+
# NIST never uses `subpart`; declare it so the inherited Components::Code
|
|
114
|
+
# does not disagree with this class (the determinism landmine).
|
|
115
|
+
attribute :subpart, :string
|
|
109
116
|
|
|
110
117
|
# V2 COMPONENTS (Lutaml::Model objects) - PROPER SEPARATION
|
|
111
118
|
# `edition` (Components::Edition: type + id + additional_text) is the
|
|
@@ -412,7 +419,7 @@ module Pubid
|
|
|
412
419
|
# "National Institute of Standards and Technology Special Publication 800-27, Revision A"
|
|
413
420
|
result = publisher_full_name
|
|
414
421
|
result += " #{series_full_name}" if series
|
|
415
|
-
result += " #{number
|
|
422
|
+
result += " #{number}" if number
|
|
416
423
|
result += parts.map { |p| "-#{p}" }.join if parts&.any?
|
|
417
424
|
|
|
418
425
|
# Render volume and issue number in long form: "Vol. 6, No. 12"
|
|
@@ -44,7 +44,7 @@ module Pubid
|
|
|
44
44
|
result += " CS-E"
|
|
45
45
|
|
|
46
46
|
# Number (already extracted from e104 → 104 in builder)
|
|
47
|
-
result += " #{number
|
|
47
|
+
result += " #{number}" if number
|
|
48
48
|
|
|
49
49
|
# Edition (e1943 for e104-43 pattern) plus any other component the
|
|
50
50
|
# parser attached (volume, supplement, version, ...).
|
|
@@ -46,7 +46,7 @@ module Pubid
|
|
|
46
46
|
def normalized_number
|
|
47
47
|
return nil unless number
|
|
48
48
|
|
|
49
|
-
num_value = number.
|
|
49
|
+
num_value = number.to_s
|
|
50
50
|
|
|
51
51
|
# Pattern: c4-4 → 4-4 (hide 'c' prefix)
|
|
52
52
|
case num_value
|
|
@@ -64,12 +64,12 @@ module Pubid
|
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
# Override number to return normalized value
|
|
67
|
-
# Tests expect number
|
|
67
|
+
# Tests expect number to be normalized (c4-4 → 4-4, 4-m-5 → 4-M-5)
|
|
68
68
|
def number
|
|
69
69
|
num = super
|
|
70
70
|
return num unless num
|
|
71
71
|
|
|
72
|
-
num_value = num.
|
|
72
|
+
num_value = num.to_s
|
|
73
73
|
|
|
74
74
|
# Pattern: c4-4 → 4-4 (hide 'c' prefix)
|
|
75
75
|
case num_value
|
|
@@ -83,8 +83,7 @@ module Pubid
|
|
|
83
83
|
num_value = num_value.gsub(/^m-/, "M-")
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
Components::Code.new(value: num_value)
|
|
86
|
+
num_value
|
|
88
87
|
end
|
|
89
88
|
|
|
90
89
|
def to_s(format = nil)
|
|
@@ -106,7 +105,7 @@ module Pubid
|
|
|
106
105
|
|
|
107
106
|
if number
|
|
108
107
|
# Normalize number value for CRPL patterns
|
|
109
|
-
num_value = number.
|
|
108
|
+
num_value = number.to_s
|
|
110
109
|
|
|
111
110
|
# Pattern: c4-4 → 4-4 (hide 'c' prefix)
|
|
112
111
|
case num_value
|
|
@@ -66,14 +66,14 @@ module Pubid
|
|
|
66
66
|
# Convert dash-year patterns to edition format for FIPS
|
|
67
67
|
# Pattern: "14-1971" → "14e1971" (edition year format)
|
|
68
68
|
# But preserve dash for parts: "140-3" stays as-is
|
|
69
|
-
if number
|
|
69
|
+
if number =~ /^(\d{1,3})-(\d{4})$/
|
|
70
70
|
# This is a number-year pattern (e.g., "14-1971")
|
|
71
71
|
# Convert to edition format: "14e1971"
|
|
72
72
|
number_part = $1
|
|
73
73
|
year_part = $2
|
|
74
74
|
result += " #{number_part}e#{year_part}"
|
|
75
75
|
else
|
|
76
|
-
result += " #{number
|
|
76
|
+
result += " #{number}"
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
|
|
@@ -57,14 +57,14 @@ module Pubid
|
|
|
57
57
|
|
|
58
58
|
def to_short_style
|
|
59
59
|
result = "#{default_publisher} #{series_code}"
|
|
60
|
-
result += " #{number
|
|
60
|
+
result += " #{number}" if number
|
|
61
61
|
result += append_short_components
|
|
62
62
|
result
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
def to_mr_style
|
|
66
66
|
result = "#{default_publisher}.#{series_code}"
|
|
67
|
-
result += ".#{number
|
|
67
|
+
result += ".#{number}" if number
|
|
68
68
|
result += append_mr_components
|
|
69
69
|
result
|
|
70
70
|
end
|
data/lib/pubid/nist/series/ir.rb
CHANGED
|
@@ -31,9 +31,7 @@ module Pubid
|
|
|
31
31
|
letter_suffix:)
|
|
32
32
|
return false unless letter_suffix == "R"
|
|
33
33
|
|
|
34
|
-
identifier.number =
|
|
35
|
-
value: "#{first_num.value}-#{letter_base}",
|
|
36
|
-
)
|
|
34
|
+
identifier.number = "#{first_num.value}-#{letter_base}"
|
|
37
35
|
edition_obj = Components::Edition.new(type: "r", id: "1")
|
|
38
36
|
identifier.edition = edition_obj
|
|
39
37
|
true
|
|
@@ -42,13 +40,11 @@ module Pubid
|
|
|
42
40
|
def self.finalize_identifier(identifier, _parsed_hash)
|
|
43
41
|
return unless identifier.number
|
|
44
42
|
|
|
45
|
-
value = identifier.number.
|
|
43
|
+
value = identifier.number.to_s
|
|
46
44
|
match = value.match(/^(\d+)e(\d{4})$/)
|
|
47
45
|
return unless match
|
|
48
46
|
|
|
49
|
-
identifier.number =
|
|
50
|
-
value: "#{match[1]}-#{match[2]}",
|
|
51
|
-
)
|
|
47
|
+
identifier.number = "#{match[1]}-#{match[2]}"
|
|
52
48
|
identifier.edition = nil
|
|
53
49
|
end
|
|
54
50
|
end
|
data/lib/pubid/oiml/builder.rb
CHANGED
|
@@ -228,13 +228,13 @@ module Pubid
|
|
|
228
228
|
article_id = parsed_hash[:article_id].to_s
|
|
229
229
|
identifier.date ||= Pubid::Components::Date.new
|
|
230
230
|
identifier.date.year = article_id[0, 4]
|
|
231
|
-
identifier.
|
|
231
|
+
identifier.number = article_id[4, 2]
|
|
232
232
|
identifier.sequence = article_id[6, 2]
|
|
233
233
|
warn_on_volume_mismatch(identifier, parsed_hash[:volume_roman])
|
|
234
234
|
return
|
|
235
235
|
end
|
|
236
236
|
|
|
237
|
-
identifier.
|
|
237
|
+
identifier.number = parsed_hash[:issue].to_s if parsed_hash[:issue]
|
|
238
238
|
identifier.sequence = parsed_hash[:sequence].to_s if parsed_hash[:sequence]
|
|
239
239
|
end
|
|
240
240
|
|