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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b4e0a5a8d4b5c1410b934712637a882a703f34ded60d92ed1d8f0a6465974396
|
|
4
|
+
data.tar.gz: 35bf6a1a075f68f35c682a3cfdde6bd5166523535491a74f1cb3473abcfaacec
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7dcd7c3d8f91d1ef5fa1ab296e4f922b435b04b70a06d184e6d2449d32a270bf31b14f352523686921072aac37bd0f91e0b6f62a6d44c28349b04ca7079092ed
|
|
7
|
+
data.tar.gz: ff8bc5531169fa3dace613d7369e656fdc2418f559adf3b527722e80144fd5a7aaa2db28da23979b2e3b8bc5af31132dca631e955a454d6262ad6a3ddf459b77
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string: true
|
|
2
2
|
|
|
3
3
|
module Pubid
|
|
4
4
|
module Bsi
|
|
5
5
|
module Components
|
|
6
|
-
#
|
|
7
|
-
class Date <
|
|
8
|
-
|
|
6
|
+
# BSI has no date semantics of its own, so this is the shared
|
|
7
|
+
# component, not a subclass: an empty `class Date <
|
|
8
|
+
# Pubid::Components::Date` rejected the shared instances a nested
|
|
9
|
+
# cross-flavor adopted identifier carries (pubid#379 — the adoption
|
|
10
|
+
# wrappers delegate `date` to the foreign object), and made `==`
|
|
11
|
+
# compare the parsed instance against the deserialized one by class.
|
|
12
|
+
# Aliased so the builder's `Components::Date.new` call sites construct
|
|
13
|
+
# the shared class.
|
|
14
|
+
Date = ::Pubid::Components::Date
|
|
9
15
|
end
|
|
10
16
|
end
|
|
11
17
|
end
|
|
@@ -50,9 +50,18 @@ module Pubid
|
|
|
50
50
|
attribute :part, :string
|
|
51
51
|
attribute :subpart, :string
|
|
52
52
|
attribute :second_number, Bsi::Components::Code # For collections like PAS 2035/2030
|
|
53
|
-
|
|
53
|
+
# The shared component, not Bsi::Components::Date: the adoption wrappers
|
|
54
|
+
# (AdoptedEuropeanNorm, AdoptedInternationalStandard) delegate `date` to
|
|
55
|
+
# the foreign identifier they wrap, whose date is a plain
|
|
56
|
+
# ::Pubid::Components::Date — the empty BSI subclass rejected it and
|
|
57
|
+
# to_hash/from_hash raised on every "BS EN …"/"BS ISO …" (pubid#379,
|
|
58
|
+
# the same shape as the bsi-set-cross-flavor-type fix).
|
|
59
|
+
attribute :date, ::Pubid::Components::Date
|
|
54
60
|
attribute :stage, Pubid::Components::Stage
|
|
55
|
-
|
|
61
|
+
# Shared Type too: the leaf builders reach for ::Pubid::Components::Type
|
|
62
|
+
# (e.g. a default materialized from self.type), which the empty BSI
|
|
63
|
+
# subclass rejected — "BIP 2225:2022" et al. failed to_hash on `type`.
|
|
64
|
+
attribute :type, ::Pubid::Components::Type
|
|
56
65
|
attribute :typed_stage, Pubid::Components::TypedStage
|
|
57
66
|
attribute :edition, :string
|
|
58
67
|
attribute :month, :integer
|
|
@@ -22,6 +22,10 @@ module Pubid
|
|
|
22
22
|
# are likewise CCSDS-specific plain strings.
|
|
23
23
|
attribute :number, :string
|
|
24
24
|
attribute :part, :string
|
|
25
|
+
# CCSDS never populates `subpart`, but the inherited declaration is a
|
|
26
|
+
# Components::Code, and a parent that disagrees with its leaves is the
|
|
27
|
+
# determinism landmine. Declare it here, like every converted flavor.
|
|
28
|
+
attribute :subpart, :string
|
|
25
29
|
attribute :edition, :string
|
|
26
30
|
attribute :type, :string
|
|
27
31
|
attribute :suffix, :string
|
|
@@ -9,10 +9,14 @@ module Pubid
|
|
|
9
9
|
attribute :publisher, Components::Publisher, default: -> {
|
|
10
10
|
Components::Publisher.new(body: "CCSDS")
|
|
11
11
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
# Plain :string, like the live Pubid::Ccsds::Identifier hierarchy, which
|
|
13
|
+
# already declared these as strings. This class is otherwise
|
|
14
|
+
# unreferenced — nothing inherits it and no builder instantiates it — but
|
|
15
|
+
# it is public API, so it is retyped rather than deleted.
|
|
16
|
+
attribute :series, :string
|
|
17
|
+
attribute :number, :string
|
|
18
|
+
attribute :part, :string
|
|
19
|
+
attribute :book_color, :string
|
|
16
20
|
attribute :edition, Components::Edition
|
|
17
21
|
attribute :retired, :boolean, default: -> { false }
|
|
18
22
|
attribute :language, Components::Language
|
|
@@ -29,14 +33,14 @@ module Pubid
|
|
|
29
33
|
result += " "
|
|
30
34
|
|
|
31
35
|
# Series (optional single letter before number)
|
|
32
|
-
result += series.
|
|
36
|
+
result += series.to_s if series
|
|
33
37
|
|
|
34
38
|
# Number with part (using dot notation)
|
|
35
|
-
result += number.
|
|
36
|
-
result += ".#{part
|
|
39
|
+
result += number.to_s
|
|
40
|
+
result += ".#{part}" if part
|
|
37
41
|
|
|
38
42
|
# Book color (required) - no space before dash
|
|
39
|
-
result += "-#{book_color
|
|
43
|
+
result += "-#{book_color}" if book_color
|
|
40
44
|
|
|
41
45
|
# Edition (optional)
|
|
42
46
|
result += "-#{edition.number}" if edition
|
|
@@ -54,11 +58,11 @@ module Pubid
|
|
|
54
58
|
return nil unless other.is_a?(SingleIdentifier)
|
|
55
59
|
|
|
56
60
|
# Compare by number first
|
|
57
|
-
num_cmp = number.
|
|
61
|
+
num_cmp = number.to_i <=> other.number.to_i
|
|
58
62
|
return num_cmp unless num_cmp.zero?
|
|
59
63
|
|
|
60
64
|
# Then by part
|
|
61
|
-
part_cmp =
|
|
65
|
+
part_cmp = part.to_i <=> other.part.to_i
|
|
62
66
|
return part_cmp unless part_cmp.zero?
|
|
63
67
|
|
|
64
68
|
# Then by edition
|
data/lib/pubid/csa/builder.rb
CHANGED
|
@@ -253,7 +253,7 @@ module Pubid
|
|
|
253
253
|
|
|
254
254
|
# Code
|
|
255
255
|
if parsed_hash[:code]
|
|
256
|
-
series.number =
|
|
256
|
+
series.number = parsed_hash[:code].to_s
|
|
257
257
|
end
|
|
258
258
|
|
|
259
259
|
# Year format and year
|
|
@@ -520,13 +520,13 @@ module Pubid
|
|
|
520
520
|
# Pattern: "C22.1-15" should become code="C22.1", year="2015"
|
|
521
521
|
if !data[:year] && code_value =~ /^(.+)-(\d{2})$/
|
|
522
522
|
# Split code and year
|
|
523
|
-
identifier.number =
|
|
523
|
+
identifier.number = $1
|
|
524
524
|
# Convert 2-digit year to 4-digit
|
|
525
525
|
year_2digit = $2
|
|
526
526
|
identifier.year = "20#{year_2digit}"
|
|
527
527
|
identifier.year_format = "dash"
|
|
528
528
|
else
|
|
529
|
-
identifier.number =
|
|
529
|
+
identifier.number = code_value
|
|
530
530
|
end
|
|
531
531
|
end
|
|
532
532
|
|
|
@@ -47,7 +47,7 @@ module Pubid
|
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
base_str = (needs_space ? "#{prefix} " : prefix) +
|
|
50
|
-
base.number.
|
|
50
|
+
base.number.to_s + # Normalized code (e.g. "C22.2-1")
|
|
51
51
|
":#{year_display}"
|
|
52
52
|
parts = [base_str]
|
|
53
53
|
else
|
|
@@ -60,7 +60,7 @@ module Pubid
|
|
|
60
60
|
bundled_with.each do |bundled|
|
|
61
61
|
# For Cec identifiers, use normalized code format
|
|
62
62
|
if bundled.is_a?(Cec)
|
|
63
|
-
bundled_part = bundled.number.
|
|
63
|
+
bundled_part = bundled.number.to_s # e.g. "C22.2-2"
|
|
64
64
|
if bundled.year
|
|
65
65
|
# Use dash if year_format is dash, otherwise colon
|
|
66
66
|
separator = bundled.year_format == "dash" ? "-" : ":"
|
data/lib/pubid/evs/builder.rb
CHANGED
data/lib/pubid/evs/identifier.rb
CHANGED
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
module Pubid
|
|
4
4
|
module Evs
|
|
5
5
|
# An EVS national adoption wraps a CEN identifier the same way BSI's
|
|
6
|
-
# AdoptedEuropeanNorm does — polymorphic `
|
|
6
|
+
# AdoptedEuropeanNorm does — polymorphic `base` so the
|
|
7
7
|
# wrapped object stays a real Pubid::CenCenelec identifier.
|
|
8
8
|
#
|
|
9
9
|
# Examples:
|
|
10
|
-
# "EVS-EN 18216:2026" (
|
|
11
|
-
# "EVS-EN ISO 14001:2026" (
|
|
12
|
-
# "EVS-EN ISO/IEC 27017:2026" (
|
|
13
|
-
# "EVS-EN ISO 9001:2015/A1:2024" (
|
|
10
|
+
# "EVS-EN 18216:2026" (base: EN 18216:2026)
|
|
11
|
+
# "EVS-EN ISO 14001:2026" (base: EN ISO 14001:2026)
|
|
12
|
+
# "EVS-EN ISO/IEC 27017:2026" (base: EN ISO/IEC 27017:2026)
|
|
13
|
+
# "EVS-EN ISO 9001:2015/A1:2024" (base: EN ISO 9001:2015/A1:2024)
|
|
14
14
|
class Identifier < ::Pubid::Identifier
|
|
15
|
-
attribute :
|
|
15
|
+
attribute :base, ::Pubid::Identifier, polymorphic: true
|
|
16
16
|
# "-" or " " — preserves the printed separator ("EVS-EN" vs "EVS EN")
|
|
17
17
|
attribute :separator, :string, default: -> { "-" }
|
|
18
18
|
|
|
@@ -6,10 +6,15 @@ module Pubid
|
|
|
6
6
|
# The EVS national adoption of a European Standard.
|
|
7
7
|
# Example: "EVS-EN 18216:2026"
|
|
8
8
|
class NationalAdoption < ::Pubid::Evs::Identifier
|
|
9
|
-
attribute :type, Components::Type, default: -> { self.class.
|
|
9
|
+
attribute :type, Components::Type, default: -> { self.class.default_type }
|
|
10
|
+
|
|
11
|
+
def self.default_type
|
|
12
|
+
Components::Type.new(abbr: type[:short])
|
|
13
|
+
end
|
|
10
14
|
|
|
11
15
|
def self.type
|
|
12
|
-
{ key: :evs_en,
|
|
16
|
+
{ key: :evs_en, short: "EN",
|
|
17
|
+
title: "EVS National Adoption of a European Standard" }
|
|
13
18
|
end
|
|
14
19
|
end
|
|
15
20
|
end
|
data/lib/pubid/evs/renderer.rb
CHANGED
|
@@ -17,7 +17,7 @@ module Pubid
|
|
|
17
17
|
EVS_NAMESPACE = "urn:evs:"
|
|
18
18
|
|
|
19
19
|
def generate
|
|
20
|
-
adopted_urn = identifier.
|
|
20
|
+
adopted_urn = identifier.base.to_urn
|
|
21
21
|
unless adopted_urn.start_with?(CEN_NAMESPACE)
|
|
22
22
|
raise Errors::ParseError,
|
|
23
23
|
"expected adopted CEN URN, got #{adopted_urn.inspect}"
|
data/lib/pubid/evs/urn_parser.rb
CHANGED
data/lib/pubid/gb/builder.rb
CHANGED
|
@@ -6,31 +6,36 @@ module Pubid
|
|
|
6
6
|
#
|
|
7
7
|
# The parser captures the publisher code verbatim (which may already
|
|
8
8
|
# include the "/T" or "/Z" suffix). The builder normalizes: if the
|
|
9
|
-
# suffix is in the
|
|
10
|
-
#
|
|
11
|
-
# the
|
|
9
|
+
# suffix is in the code, it is split out into the separate +mandate+
|
|
10
|
+
# attribute so the renderer can recompose either the inline or split
|
|
11
|
+
# form. The code itself goes into the inherited +publisher+ component.
|
|
12
12
|
class Builder
|
|
13
13
|
def self.build(parsed_data)
|
|
14
14
|
new.build(parsed_data)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def build(data)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
mandate ||= data[:mandate]&.to_s
|
|
18
|
+
code, mandate = split_mandate(data[:publisher_code].to_s)
|
|
21
19
|
|
|
22
20
|
Identifiers::Standard.new(
|
|
23
|
-
|
|
24
|
-
mandate: mandate,
|
|
21
|
+
publisher: ::Pubid::Components::Publisher.new(body: code),
|
|
22
|
+
mandate: mandate || data[:mandate]&.to_s,
|
|
25
23
|
number: data[:number].to_s,
|
|
26
24
|
part: data[:part]&.to_s,
|
|
27
|
-
date:
|
|
25
|
+
date: date_for(data[:year]),
|
|
28
26
|
all_parts: !data[:all_parts].to_s.empty?,
|
|
29
27
|
)
|
|
30
28
|
end
|
|
31
29
|
|
|
32
30
|
private
|
|
33
31
|
|
|
32
|
+
# The publication year, or nil for a partial reference.
|
|
33
|
+
def date_for(year)
|
|
34
|
+
return nil unless year
|
|
35
|
+
|
|
36
|
+
::Pubid::Components::Date.new(year: year.to_s)
|
|
37
|
+
end
|
|
38
|
+
|
|
34
39
|
# If the publisher code carries an inline /T or /Z suffix, split it off
|
|
35
40
|
# and return the cleaned code + extracted mandate.
|
|
36
41
|
def split_mandate(code)
|
data/lib/pubid/gb/identifier.rb
CHANGED
|
@@ -7,9 +7,11 @@ module Pubid
|
|
|
7
7
|
# descend from this class, so a parsed GB id is always an instance of
|
|
8
8
|
# Pubid::Gb::Identifier.
|
|
9
9
|
class Identifier < ::Pubid::Identifier
|
|
10
|
-
# The issuing body code as printed
|
|
11
|
-
#
|
|
12
|
-
|
|
10
|
+
# The issuing body code as printed — "GB", "JB", "GBn", "T/GZAEPI" —
|
|
11
|
+
# lives in the `publisher` attribute inherited from ::Pubid::Identifier.
|
|
12
|
+
# The flat-scalar hooks below serialize it as a bare string, and the
|
|
13
|
+
# shared URN generator renders it lowercase, so the series is part of
|
|
14
|
+
# the URN identity (GB 20223 and GBn 20223 are two documents).
|
|
13
15
|
|
|
14
16
|
# Mandate category: "T" (recommended), "Z" (guideline), or nil
|
|
15
17
|
# (mandatory). Carried after the "/" in the printed form.
|
|
@@ -31,17 +33,34 @@ module Pubid
|
|
|
31
33
|
"pubid:gb:standard" => "Pubid::Gb::Identifiers::Standard",
|
|
32
34
|
}.freeze
|
|
33
35
|
|
|
36
|
+
# This block REPLACES the maps of ::Pubid::Identifier, so every
|
|
37
|
+
# attribute the flavor uses must appear here — "date" included, or the
|
|
38
|
+
# publication year is lost in to_hash. The shared flat-scalar rules
|
|
39
|
+
# (Identifier#to_hash / .from_hash) write it as a bare "year" scalar.
|
|
34
40
|
key_value do
|
|
35
41
|
map "_type", to: :_type, polymorphic_map: GB_TYPE_MAP
|
|
36
|
-
map "
|
|
42
|
+
map "publisher", to: :publisher
|
|
37
43
|
map "mandate", to: :mandate
|
|
38
44
|
map "number", to: :number
|
|
39
45
|
map "part", to: :part
|
|
46
|
+
map "date", to: :date
|
|
40
47
|
map "all_parts", to: :all_parts, render_default: false
|
|
41
48
|
end
|
|
42
49
|
|
|
43
50
|
PUBLISHER = "CN"
|
|
44
51
|
|
|
52
|
+
# Serialize `publisher` as a bare string instead of a nested
|
|
53
|
+
# {"body" => "GB"}, the CEN/CENELEC precedent. The entry is added for
|
|
54
|
+
# GB's own classes only: a shared entry would change the wire format of
|
|
55
|
+
# every flavor that publishes an index.
|
|
56
|
+
def self.flat_scalar_components
|
|
57
|
+
super.merge(publisher: "publisher")
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.flat_scalar_fields
|
|
61
|
+
super.merge(publisher: :body)
|
|
62
|
+
end
|
|
63
|
+
|
|
45
64
|
def to_s(**opts)
|
|
46
65
|
render(format: :human, **opts)
|
|
47
66
|
end
|
data/lib/pubid/gb/parser.rb
CHANGED
|
@@ -25,6 +25,10 @@ module Pubid
|
|
|
25
25
|
rule(:publisher_code) do
|
|
26
26
|
# Social-group form: "T/" then 2+ uppercase letters/digits.
|
|
27
27
|
(str("T/") >> match("[A-Z0-9]").repeat(1)).as(:publisher_code) |
|
|
28
|
+
# Confidential national series. The lowercase "n" is part of the
|
|
29
|
+
# code, so it comes before the uppercase-only rule below: a PEG
|
|
30
|
+
# takes the first branch that matches and does not backtrack.
|
|
31
|
+
(str("GBn") >> (str("/T") | str("/Z")).maybe).as(:publisher_code) |
|
|
28
32
|
# Standard form: 1-3 letters, optional slash-T-or-Z.
|
|
29
33
|
(match("[A-Z]").repeat(1, 3) >>
|
|
30
34
|
(str("/T") | str("/Z")).maybe).as(:publisher_code)
|
data/lib/pubid/gb/renderer.rb
CHANGED
|
@@ -8,7 +8,8 @@ module Pubid
|
|
|
8
8
|
# "GB/T 20223-2006"
|
|
9
9
|
# "GB/T 5606.1-2004"
|
|
10
10
|
# "GB/T 5606 (all parts)"
|
|
11
|
-
# "T/GZAEPI 001
|
|
11
|
+
# "T/GZAEPI 001-2018" (social-group form; an em-dash year
|
|
12
|
+
# separator in the input renders as a hyphen)
|
|
12
13
|
class Renderer < ::Pubid::Renderers::Base
|
|
13
14
|
def render(**_opts)
|
|
14
15
|
parts = [publisher_portion, " #{number_portion}"]
|
|
@@ -19,8 +20,8 @@ module Pubid
|
|
|
19
20
|
private
|
|
20
21
|
|
|
21
22
|
def publisher_portion
|
|
22
|
-
code = @id.
|
|
23
|
-
code += "/#{@id.mandate}" if @id.mandate &&
|
|
23
|
+
code = @id.publisher.to_s
|
|
24
|
+
code += "/#{@id.mandate}" if @id.mandate && !code.include?("/")
|
|
24
25
|
code
|
|
25
26
|
end
|
|
26
27
|
|
data/lib/pubid/gb.rb
CHANGED
data/lib/pubid/identifier.rb
CHANGED
|
@@ -498,9 +498,17 @@ module Pubid
|
|
|
498
498
|
end
|
|
499
499
|
|
|
500
500
|
attribute :_type, :string, polymorphic_class: true
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
501
|
+
# Plain strings, for every flavor. A Components::Code here held nothing
|
|
502
|
+
# but its `value` on the identifier path, and the disagreement between
|
|
503
|
+
# this declaration and the leaves that redeclared a scalar was the
|
|
504
|
+
# determinism landmine: a redeclaration on an inherited-from class
|
|
505
|
+
# resolves nondeterministically under multi-flavor load. With the base
|
|
506
|
+
# declaring the scalar, no flavor redeclares and the bug class is gone.
|
|
507
|
+
# A flavor that needs structure keeps its own attributes (ISO's committee
|
|
508
|
+
# codes, NIST's series/subseries, ITU's code), never a boxed `number`.
|
|
509
|
+
attribute :number, :string
|
|
510
|
+
attribute :part, :string
|
|
511
|
+
attribute :subpart, :string
|
|
504
512
|
attribute :stage_iteration, Components::Iteration
|
|
505
513
|
attribute :date, Components::Date
|
|
506
514
|
attribute :edition, Components::Edition
|
data/lib/pubid/idf/identifier.rb
CHANGED
|
@@ -5,6 +5,13 @@ module Pubid
|
|
|
5
5
|
module Idf
|
|
6
6
|
# An IDF identifier has no copublisher
|
|
7
7
|
class Identifier < ::Pubid::Identifier
|
|
8
|
+
# A Type INSTANCE, never the raw :key symbol - lutaml materializes
|
|
9
|
+
# defaults during from_hash; casting a Symbol into the
|
|
10
|
+
# component raises InvalidFormatError (pubid#383).
|
|
11
|
+
def self.default_type
|
|
12
|
+
Components::Type.new(abbr: type[:short])
|
|
13
|
+
end
|
|
14
|
+
|
|
8
15
|
attribute :typed_stage, Components::TypedStage
|
|
9
16
|
|
|
10
17
|
# `number`/`part`/`subpart` are declared here rather than inherited as a
|
|
@@ -4,7 +4,7 @@ module Pubid
|
|
|
4
4
|
module Idf
|
|
5
5
|
module Identifiers
|
|
6
6
|
class Amendment < SupplementIdentifier
|
|
7
|
-
attribute :type, Components::Type, default: -> { self.class.
|
|
7
|
+
attribute :type, Components::Type, default: -> { self.class.default_type }
|
|
8
8
|
|
|
9
9
|
TYPED_STAGES = [
|
|
10
10
|
Components::TypedStage.new(
|
|
@@ -4,7 +4,7 @@ module Pubid
|
|
|
4
4
|
module Idf
|
|
5
5
|
module Identifiers
|
|
6
6
|
class Corrigendum < SupplementIdentifier
|
|
7
|
-
attribute :type, Components::Type, default: -> { self.class.
|
|
7
|
+
attribute :type, Components::Type, default: -> { self.class.default_type }
|
|
8
8
|
|
|
9
9
|
TYPED_STAGES = [
|
|
10
10
|
Components::TypedStage.new(
|
|
@@ -5,7 +5,7 @@ module Pubid
|
|
|
5
5
|
module Identifiers
|
|
6
6
|
# International Standard Identifier
|
|
7
7
|
class InternationalStandard < SingleIdentifier
|
|
8
|
-
attribute :type, Components::Type, default: -> { self.class.
|
|
8
|
+
attribute :type, Components::Type, default: -> { self.class.default_type }
|
|
9
9
|
|
|
10
10
|
TYPED_STAGES = [
|
|
11
11
|
Components::TypedStage.new(
|
|
@@ -4,7 +4,7 @@ module Pubid
|
|
|
4
4
|
module Idf
|
|
5
5
|
module Identifiers
|
|
6
6
|
class ReviewedMethod < SingleIdentifier
|
|
7
|
-
attribute :type, Components::Type, default: -> { self.class.
|
|
7
|
+
attribute :type, Components::Type, default: -> { self.class.default_type }
|
|
8
8
|
TYPED_STAGES = [
|
|
9
9
|
Components::TypedStage.new(
|
|
10
10
|
code: :pwirm,
|
|
@@ -12,7 +12,7 @@ module Pubid
|
|
|
12
12
|
#
|
|
13
13
|
# Note: The type attribute is inherited from the base Identifier class.
|
|
14
14
|
# Concrete classes should add their own default value like:
|
|
15
|
-
# attribute :type, Components::Type, default: -> { self.class.
|
|
15
|
+
# attribute :type, Components::Type, default: -> { self.class.default_type }
|
|
16
16
|
class SingleIdentifier < Identifier
|
|
17
17
|
end
|
|
18
18
|
end
|
data/lib/pubid/ieee/builder.rb
CHANGED
|
@@ -669,7 +669,14 @@ module Pubid
|
|
|
669
669
|
# Extract publishers from joint_publishers
|
|
670
670
|
if parsed[:joint_publishers]
|
|
671
671
|
joint_pub_str = extract_value(parsed[:joint_publishers])
|
|
672
|
-
|
|
672
|
+
pubs = joint_pub_str.split("/")
|
|
673
|
+
attributes[:publishers] = pubs
|
|
674
|
+
# lutaml materializes attribute defaults during from_hash, so the
|
|
675
|
+
# deserialized joint carries publisher/copublisher alongside
|
|
676
|
+
# publishers; set the same shape on the parse path or the
|
|
677
|
+
# amendment-wrapped round-trip diverges on exactly those keys.
|
|
678
|
+
attributes[:publisher] = pubs.first
|
|
679
|
+
attributes[:copublisher] = pubs.drop(1)
|
|
673
680
|
end
|
|
674
681
|
|
|
675
682
|
# Build code with parts if present
|
|
@@ -693,6 +700,15 @@ module Pubid
|
|
|
693
700
|
end
|
|
694
701
|
attributes[:month] = extract_value(parsed[:month]) if parsed[:month]
|
|
695
702
|
|
|
703
|
+
# A text date trailing the DRAFT (pubid#216: "CD P26515/D1, March
|
|
704
|
+
# 2017") reaches the builder under :draft_month/:draft_year — the
|
|
705
|
+
# grammar captures them separately to avoid the :month/:year
|
|
706
|
+
# duplicate-subtree collision with the date clause.
|
|
707
|
+
if parsed[:draft_year]
|
|
708
|
+
attributes[:year] ||= extract_value(parsed[:draft_year])
|
|
709
|
+
attributes[:month] ||= extract_value(parsed[:draft_month])
|
|
710
|
+
end
|
|
711
|
+
|
|
696
712
|
# Extract edition, from relaton's "/E-<n>" suffix (normalized to
|
|
697
713
|
# "Edition <n>.0"). nil-residue hand-off item 1.
|
|
698
714
|
attributes[:edition] = extract_value(parsed[:edition]) if parsed[:edition]
|
|
@@ -722,6 +738,10 @@ module Pubid
|
|
|
722
738
|
attributes[:typed_stage] =
|
|
723
739
|
Pubid::Ieee.locate_stage(stage_abbr)
|
|
724
740
|
end
|
|
741
|
+
elsif parsed[:iso_published]
|
|
742
|
+
# Stage-less PUBLISHED joint form (pubid#317): ISO-led spelling,
|
|
743
|
+
# no project marker, no typed stage - renders as printed.
|
|
744
|
+
attributes[:lead_party] = "ISO"
|
|
725
745
|
else
|
|
726
746
|
# IEEE format - lead party is IEEE
|
|
727
747
|
attributes[:lead_party] = "IEEE"
|
|
@@ -734,7 +754,19 @@ module Pubid
|
|
|
734
754
|
Pubid::Ieee.locate_stage("P")
|
|
735
755
|
end
|
|
736
756
|
|
|
737
|
-
Identifiers::JointDevelopment.new(**attributes)
|
|
757
|
+
joint = Identifiers::JointDevelopment.new(**attributes)
|
|
758
|
+
|
|
759
|
+
# Amendment tail on the joint ISO-format form (pubid#317:
|
|
760
|
+
# "8802-11:2012/Amd.1:2014(E)"): wrap the joint id, mirroring
|
|
761
|
+
# build_flat_amendment.
|
|
762
|
+
return joint unless parsed[:amd_number]
|
|
763
|
+
|
|
764
|
+
amd_year = extract_value(parsed[:amd_year]) if parsed[:amd_year]
|
|
765
|
+
Identifiers::Amendment.new(
|
|
766
|
+
base: joint,
|
|
767
|
+
number: extract_value(parsed[:amd_number]),
|
|
768
|
+
year: amd_year,
|
|
769
|
+
)
|
|
738
770
|
end
|
|
739
771
|
|
|
740
772
|
# Build SI/PSI identifier from parsed data
|
|
@@ -1189,6 +1221,14 @@ module Pubid
|
|
|
1189
1221
|
return "P"
|
|
1190
1222
|
elsif type_value == "Std"
|
|
1191
1223
|
return "Std"
|
|
1224
|
+
elsif type_value == "Draft Std" && parsed[:draft].nil? && parsed[:digit_draft].nil?
|
|
1225
|
+
# A version-less "Draft Std" fabricates /D1 (issue #205);
|
|
1226
|
+
# deriving the stage from that fabricated version renders the
|
|
1227
|
+
# same P-prefixed form as an explicit "/D1" spelling, so the
|
|
1228
|
+
# render reaches its fixed point in one round (pubid#318).
|
|
1229
|
+
# Gated on no-draft: a dotted version ("D2.0") fails the registry
|
|
1230
|
+
# lookup above and must fall through, keeping "Draft Std".
|
|
1231
|
+
return "D1"
|
|
1192
1232
|
elsif type_value.match?(/^No\.?$/)
|
|
1193
1233
|
return type_value
|
|
1194
1234
|
end
|
|
@@ -30,8 +30,11 @@ module Pubid
|
|
|
30
30
|
# Format: "IEEE/ASTM SI 10-1997" (published)
|
|
31
31
|
# or: "IEEE/ASTM PSI 10/D2, October 2015" (draft)
|
|
32
32
|
|
|
33
|
-
#
|
|
34
|
-
|
|
33
|
+
# NOTE: no `attr_accessor :draft_obj` here — it would shadow the
|
|
34
|
+
# base's lazy `draft_obj` reader (base.rb), which rebuilds the
|
|
35
|
+
# component from the `draft` attribute after from_hash. The plain
|
|
36
|
+
# accessor made every deserialized PSI draft render (and re-emit
|
|
37
|
+
# in to_hash) without its "/D<n>".
|
|
35
38
|
end
|
|
36
39
|
end
|
|
37
40
|
end
|