pubid 2.0.21 → 2.0.22
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/README.adoc +73 -31
- data/data/iec/legacy-notation.md +298 -0
- data/data/iso/historic-schemes.md +368 -0
- data/data/parg/iec.json +1 -1
- data/data/parg/iso.json +1 -1
- data/data/parg/iso.parg +142 -2
- data/data/parg/tables/iec_typed_stages.yaml +3 -0
- data/data/parg/tables/typed_stages_ballots.yaml +6 -0
- data/data/parg/tables/typed_stages_supplements.yaml +1 -0
- data/lib/pubid/iec/CLAUDE.md +5 -1
- data/lib/pubid/iec/builder.rb +47 -0
- data/lib/pubid/iec/identifiers/amendment.rb +34 -0
- data/lib/pubid/iec/identifiers/corrigendum.rb +6 -1
- data/lib/pubid/iec/supplement_identifier.rb +55 -25
- data/lib/pubid/iho/CLAUDE.md +2 -1
- data/lib/pubid/iho/pubid_urn_schema.rb +2 -1
- data/lib/pubid/iso/CLAUDE.md +49 -0
- data/lib/pubid/iso/builder.rb +77 -0
- data/lib/pubid/iso/identifiers/amendment.rb +1 -1
- data/lib/pubid/iso/single_identifier.rb +7 -1
- data/lib/pubid/nist/CLAUDE.md +48 -10
- data/lib/pubid/nist/builder.rb +5 -0
- data/lib/pubid/nist/identifiers/base.rb +42 -1
- data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +44 -5
- data/lib/pubid/nist/preprocessor.rb +14 -12
- data/lib/pubid/nist/urn_parser.rb +1 -1
- data/lib/pubid/version.rb +1 -1
- metadata +5 -2
data/lib/pubid/iso/builder.rb
CHANGED
|
@@ -151,6 +151,16 @@ module Pubid
|
|
|
151
151
|
# reason). The document itself holds no all-parts mark.
|
|
152
152
|
all_parts = parsed_hash.delete(:all_parts)
|
|
153
153
|
|
|
154
|
+
# Historic TYPE-first ballot face ("ISO/IEC FDAM 1 14496-12:2004",
|
|
155
|
+
# "ISO/PDAM 19973-2", "ISO 15877-5:2009 FDAM 1"): the ballot_* keys
|
|
156
|
+
# are one amendment layer over the whole base, never a second
|
|
157
|
+
# supplement layer (the stored twins keep one level), so the layer
|
|
158
|
+
# is assembled here, before the supplement-prefix peel could read
|
|
159
|
+
# the ballot token as an outer wrapper.
|
|
160
|
+
if parsed_hash.key?(:ballot_type_with_stage)
|
|
161
|
+
return build_ballot_supplement(parsed_hash, all_parts)
|
|
162
|
+
end
|
|
163
|
+
|
|
154
164
|
# The copublisher tail captures as one scalar span ("/IEC/IEEE");
|
|
155
165
|
# split it into the {copublisher:} element hashes the merge and
|
|
156
166
|
# the :copublishers cast consume. A pre-built array (the URN
|
|
@@ -261,6 +271,10 @@ module Pubid
|
|
|
261
271
|
identifier.type = default_typed_stage.to_type
|
|
262
272
|
end
|
|
263
273
|
|
|
274
|
+
# The owner's no-number rule: a numberless DAM-family ballot-stage
|
|
275
|
+
# amendment is Amendment 1 (see the method comment).
|
|
276
|
+
apply_implied_amendment_number(identifier)
|
|
277
|
+
|
|
264
278
|
all_parts ? identifier.to_all_parts : identifier
|
|
265
279
|
end
|
|
266
280
|
|
|
@@ -306,6 +320,69 @@ module Pubid
|
|
|
306
320
|
build(inner)
|
|
307
321
|
end
|
|
308
322
|
|
|
323
|
+
# Historic TYPE-first ballot face (owner ruling 2026-11-12, Option B
|
|
324
|
+
# decode-to-modern): "[P|F]?DAM [N] BASE [stamp]" decodes to ONE
|
|
325
|
+
# amendment over the WHOLE base, rendered as the canonical on-base
|
|
326
|
+
# slash face. The stage comes from the ballot token; the number from
|
|
327
|
+
# the TYPE token, then the on-base stamp, then the owner's no-number
|
|
328
|
+
# rule (a ballot face with no number anywhere names Amendment 1 —
|
|
329
|
+
# identity-bearing, so it is set here at build time and serialized,
|
|
330
|
+
# not at render time); the stamp's date is the ballot supplement's
|
|
331
|
+
# date. The base keeps every component it carried: a legacy
|
|
332
|
+
# slash-part stays a part of the base number ("ISO/IEC FPDAM 9075/1"
|
|
333
|
+
# → base "9075-1"), and the base's own type token stays the base's
|
|
334
|
+
# ("ISO/IEC PDAM TR 9573-11" → base "TR 9573-11") — nothing migrates
|
|
335
|
+
# into the supplement slot. The stamp's token letters (Amd/Am/…) are
|
|
336
|
+
# decode-away: the ballot's stage is the TYPE token's.
|
|
337
|
+
#
|
|
338
|
+
# The rest of the hash — prefix, copublishers, the base's
|
|
339
|
+
# type_with_stage / number_with_part / date — is exactly the builder
|
|
340
|
+
# input of the base document, so it nests as :base and re-enters
|
|
341
|
+
# build.
|
|
342
|
+
def build_ballot_supplement(hash, all_parts)
|
|
343
|
+
fields = { type_with_stage: hash.fetch(:ballot_type_with_stage) }
|
|
344
|
+
|
|
345
|
+
number = hash[:ballot_number] ||
|
|
346
|
+
hash[:ballot_stamp_number] ||
|
|
347
|
+
hash[:ballot_stamp_dot_number] ||
|
|
348
|
+
"1"
|
|
349
|
+
fields[:number_with_part] = number
|
|
350
|
+
|
|
351
|
+
if (stamp_date = hash[:ballot_stamp_date])
|
|
352
|
+
fields[:date] = stamp_date
|
|
353
|
+
end
|
|
354
|
+
if hash[:ballot_stamp_undated_marker]
|
|
355
|
+
fields[:undated_marker] = hash[:ballot_stamp_undated_marker]
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
rest = hash.except(:ballot_type_with_stage, :ballot_number,
|
|
359
|
+
:ballot_stamp_number, :ballot_stamp_dot_number,
|
|
360
|
+
:ballot_stamp_date, :ballot_stamp_undated_marker)
|
|
361
|
+
|
|
362
|
+
inner = { **fields, base: rest }
|
|
363
|
+
inner[:all_parts] = all_parts if all_parts
|
|
364
|
+
build(inner)
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
# The owner's no-number rule, applied on every construction path that
|
|
368
|
+
# routes through this builder (parse, URN, joint/bundle members): a
|
|
369
|
+
# DAM-family ballot-stage amendment token with no number anywhere
|
|
370
|
+
# names Amendment 1 ("ISO 19973-2/PDAM", "ISO/IEC PDAM 12207"). The
|
|
371
|
+
# number is identity-bearing, so the default lands at build time and
|
|
372
|
+
# to_hash serializes it — parse and from_hash(to_hash) agree because
|
|
373
|
+
# both carry the filled number. The ballot stages are matched by
|
|
374
|
+
# TypedStage#code (the per-typed-stage key) — PDAM's #stage_code is
|
|
375
|
+
# :cd, the harmonized range it lives in.
|
|
376
|
+
BALLOT_STAGE_CODES = %i[pdam damd fdamd fpdam].freeze
|
|
377
|
+
|
|
378
|
+
def apply_implied_amendment_number(identifier)
|
|
379
|
+
return unless identifier.is_a?(Identifiers::Amendment)
|
|
380
|
+
return unless identifier.number.nil?
|
|
381
|
+
return unless BALLOT_STAGE_CODES.include?(identifier.typed_stage&.code&.to_sym)
|
|
382
|
+
|
|
383
|
+
identifier.number = "1"
|
|
384
|
+
end
|
|
385
|
+
|
|
309
386
|
def build_directive_supplement(hash, all_parts)
|
|
310
387
|
fields = rekey_prefix(hash.slice(*DSUPP_KEYS), "dsupp_")
|
|
311
388
|
rest = hash.except(*DSUPP_KEYS)
|
|
@@ -36,7 +36,13 @@ module Pubid
|
|
|
36
36
|
return false unless typed_stage
|
|
37
37
|
|
|
38
38
|
ts = typed_stage
|
|
39
|
-
|
|
39
|
+
original = ts.original_abbr
|
|
40
|
+
if ts.long_abbr && original && (original.start_with?(ts.long_abbr) ||
|
|
41
|
+
ts.long_abbr.start_with?(original))
|
|
42
|
+
# The long family: the canonical long spelling, its punctuated
|
|
43
|
+
# forms ("Amd." of "Amd"), and shorter long-family spellings
|
|
44
|
+
# ("Am" — the alias of "Amd" the owner ruled renders canonical).
|
|
45
|
+
# The short family ("AMD") matches neither direction.
|
|
40
46
|
true
|
|
41
47
|
elsif ts.long_abbr && ts.original_abbr&.include?("Directives")
|
|
42
48
|
true
|
data/lib/pubid/nist/CLAUDE.md
CHANGED
|
@@ -136,13 +136,51 @@ Read this before you change `lib/pubid/nist/` or `spec/pubid/nist/`. The root
|
|
|
136
136
|
the six rows (`NBS CS`, `NBS CSM`, `NBS CIS`, `NBS CS-E`, `NIST PS`,
|
|
137
137
|
`NIST DCI`) into the testsuite with the gem twin in lockstep.
|
|
138
138
|
|
|
139
|
-
- **"FIPS PUB <number>" is
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
139
|
+
- **"FIPS PUB <number>" is the official RENDER face; the preprocessor
|
|
140
|
+
alias exists so the spellings parse (pubid#697; owner ruling
|
|
141
|
+
2026-11-12).** FIPS is government-published and "PUB" (Federal
|
|
142
|
+
Information Processing Standards PUBlication) is part of the official
|
|
143
|
+
designation, so
|
|
144
|
+
`FederalInformationProcessingStandards#fips_render_lead` renders the
|
|
145
|
+
spelled-NIST-publisher rows as "FIPS PUB <number>" with the tails
|
|
146
|
+
riding the lead; the lead reads `printed_publisher`, so the
|
|
147
|
+
series-default NIST a bare parse fills (#704) is not a printed
|
|
148
|
+
publisher and the bare face stays bare. The grammar reads "NIST FIPS
|
|
149
|
+
<number>", so `normalize_fips_pub_alias!` (head-anchored, immediately
|
|
150
|
+
after the publisher/series stage) folds every printed spelling —
|
|
151
|
+
"FIPS PUB 205" and the publisher-prefixed "NIST FIPS PUB 205"
|
|
152
|
+
(pubid#702) — onto that canonical model, and all the spellings
|
|
153
|
+
converge on one identity: hash-, URN- and MR-identical, and one
|
|
154
|
+
render. The hyphenated numbers and the revision forms the grammar
|
|
155
|
+
models ("FIPS PUB 199 Rev. 1" with its `original_prefix` facet,
|
|
156
|
+
compact "rev1") ride the prefix alias; bare "FIPS <number>"
|
|
157
|
+
(publisher_was_parsed: false), the historical NBS-prefixed rows, and
|
|
158
|
+
the MR face ("NIST.FIPS.197", an identity surface) are untouched.
|
|
159
|
+
|
|
160
|
+
- **A bare "FIPS <number>" carries the series' NIST publisher (hand-off
|
|
161
|
+
nist-bare-fips-publisher, metanorma-pdfa#114).** relaton keeps a CSRC hit
|
|
162
|
+
only when the parsed citation is `==` to the row, and every row is
|
|
163
|
+
"NIST FIPS …", so a bare "FIPS 197" (publisher nil) answered "Not found".
|
|
164
|
+
The Builder now fills `identifier.class.series_default_publisher`
|
|
165
|
+
("NIST" on `FederalInformationProcessingStandards`, nil on the base)
|
|
166
|
+
**after** it records `publisher_was_parsed: false`. The flag is
|
|
167
|
+
`equality_ignored`, so the two spellings are `==`; the short and MR faces
|
|
168
|
+
print the publisher only when it was spelled (`printed_publisher`), so the
|
|
169
|
+
bare face still renders `FIPS 197` / `FIPS.197`. The long and abbreviated
|
|
170
|
+
styles now name NIST (before, they began with a stray space). "NBS FIPS"
|
|
171
|
+
keeps its parsed NBS and is not `==` to the bare form. **NBS-era ruling**:
|
|
172
|
+
`#matches?` treats a publisher the query did not spell as a wildcard (and
|
|
173
|
+
no longer compares `publisher_was_parsed`, a spelling), so the query
|
|
174
|
+
"FIPS 46" still finds "NBS FIPS 46" — before this, a bare query matched
|
|
175
|
+
neither the NIST nor the NBS row. `===` needs the same rule
|
|
176
|
+
(`subset_skipped_attributes`), because the filled publisher is no longer
|
|
177
|
+
the nil the subset match read as "anything"; **the two primitives must
|
|
178
|
+
agree, so change them together.** `to_hash` of a bare parse gains
|
|
179
|
+
`publisher: NIST`; the 21,365-id `full/` corpus has no bare FIPS row, so
|
|
180
|
+
no fixture output moved. `from_hash` fills the default by the same rule
|
|
181
|
+
(`apply_series_default_publisher`, shared with the Builder), so a row
|
|
182
|
+
stored before this change (`publisher_was_parsed: false`, no publisher)
|
|
183
|
+
is still `==` to the parse. Not covered: `new(series:, number:)` fills
|
|
184
|
+
nothing (its flag defaults to true, so it means a spelled form anyway).
|
|
185
|
+
Locked by
|
|
186
|
+
`spec/pubid/nist/bare_fips_publisher_spec.rb`.
|
data/lib/pubid/nist/builder.rb
CHANGED
|
@@ -422,6 +422,11 @@ module Pubid
|
|
|
422
422
|
# to_hash) when one was. Keeps the common publisher-bearing id lean.
|
|
423
423
|
identifier.publisher_was_parsed = false unless identifier.publisher
|
|
424
424
|
|
|
425
|
+
# A series that implies its publisher (bare "FIPS 197" is
|
|
426
|
+
# "NIST FIPS 197") gets it now, after the flag above, so the two
|
|
427
|
+
# spellings are == while the bare face keeps rendering bare.
|
|
428
|
+
identifier.apply_series_default_publisher
|
|
429
|
+
|
|
425
430
|
# NEW: Convert revision with month+year to update component (V1 compatibility)
|
|
426
431
|
# Patterns like "NIST IR 4743rJun1992" should be rendered as "NIST IR 4743/Upd1-199206"
|
|
427
432
|
if parsed_hash[:revision_month] && parsed_hash[:revision_year]
|
|
@@ -39,6 +39,10 @@ module Pubid
|
|
|
39
39
|
id = super(normalize_deserialized_shapes(expand_compact_hash(data)),
|
|
40
40
|
options)
|
|
41
41
|
derive_subseries(id)
|
|
42
|
+
# A bare-FIPS row written before the series default existed holds
|
|
43
|
+
# `publisher_was_parsed: false` and no publisher; parse now fills
|
|
44
|
+
# it, so from_hash must too, or the row is no longer == the parse.
|
|
45
|
+
id.apply_series_default_publisher if id.is_a?(Identifier)
|
|
42
46
|
id
|
|
43
47
|
end
|
|
44
48
|
|
|
@@ -291,6 +295,29 @@ module Pubid
|
|
|
291
295
|
super + %i[update update_component]
|
|
292
296
|
end
|
|
293
297
|
|
|
298
|
+
# The publisher a series implies when the input spells none. The
|
|
299
|
+
# Builder fills it after it records `publisher_was_parsed: false`, so
|
|
300
|
+
# the bare face still renders without the prefix. nil: no default.
|
|
301
|
+
def self.series_default_publisher
|
|
302
|
+
nil
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# Fill the series default publisher on an id whose input spelled
|
|
306
|
+
# none. Shared by the Builder and from_hash, so both construction
|
|
307
|
+
# paths agree.
|
|
308
|
+
def apply_series_default_publisher
|
|
309
|
+
return if publisher || publisher_was_parsed
|
|
310
|
+
|
|
311
|
+
self.publisher = self.class.series_default_publisher
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
# `===` (subset match) follows #matches?: a publisher the reference
|
|
315
|
+
# did not spell is a wildcard, so bare "FIPS 46" finds "NBS FIPS 46".
|
|
316
|
+
def subset_skipped_attributes
|
|
317
|
+
skipped = super
|
|
318
|
+
publisher_was_parsed ? skipped : skipped | [:publisher]
|
|
319
|
+
end
|
|
320
|
+
|
|
294
321
|
# Wildcard / partial-identifier match. Treats +self+ as a QUERY pattern
|
|
295
322
|
# and +candidate+ as a concrete document: every ID part SET on the query
|
|
296
323
|
# must equal the candidate's, while parts left unset (nil/empty) are
|
|
@@ -301,11 +328,16 @@ module Pubid
|
|
|
301
328
|
# Asymmetric (unlike ==): "NBS CIRC 25".matches?("NBS CIRC 25sup1924")
|
|
302
329
|
# is true, but not the reverse. The candidate must be the same class or
|
|
303
330
|
# a subclass so series-level identity still holds.
|
|
331
|
+
#
|
|
332
|
+
# `publisher_was_parsed` records only how the query was spelled, so it
|
|
333
|
+
# is never a criterion; and a publisher the query did not spell (the
|
|
334
|
+
# series default a bare "FIPS 46" fills in) is a wildcard, so the bare
|
|
335
|
+
# query still finds the NBS-era "NBS FIPS 46".
|
|
304
336
|
def matches?(candidate)
|
|
305
337
|
return false unless candidate.is_a?(self.class)
|
|
306
338
|
|
|
307
339
|
self.class.attributes.each_key.all? do |name|
|
|
308
|
-
next true
|
|
340
|
+
next true unless match_criterion?(name)
|
|
309
341
|
|
|
310
342
|
query_val = public_send(name)
|
|
311
343
|
next true if query_val.nil?
|
|
@@ -316,6 +348,15 @@ module Pubid
|
|
|
316
348
|
end
|
|
317
349
|
end
|
|
318
350
|
|
|
351
|
+
# Whether #matches? compares attribute +name+ at all.
|
|
352
|
+
def match_criterion?(name)
|
|
353
|
+
return false if EQUALITY_IGNORED_ATTRS.include?(name)
|
|
354
|
+
return false if name == :publisher_was_parsed
|
|
355
|
+
|
|
356
|
+
name != :publisher || publisher_was_parsed
|
|
357
|
+
end
|
|
358
|
+
private :match_criterion?
|
|
359
|
+
|
|
319
360
|
# NIST inherits Pubid::Identifier#exclude directly: it now rebuilds via
|
|
320
361
|
# `self.class.new(**attrs)`, so NIST's keyword-only initialize
|
|
321
362
|
# (initialize(**attributes)) works without a local override, and the base
|
|
@@ -6,7 +6,9 @@ module Pubid
|
|
|
6
6
|
# NIST Federal Information Processing Standards (FIPS)
|
|
7
7
|
# Examples:
|
|
8
8
|
# - "FIPS 140-3" (no NIST prefix)
|
|
9
|
-
# - "NIST FIPS 140-3" (also accepted
|
|
9
|
+
# - "NIST FIPS 140-3" / "FIPS PUB 140-3" (also accepted; both parse
|
|
10
|
+
# to the same identity, and the NIST-published face renders as
|
|
11
|
+
# "FIPS PUB 140-3")
|
|
10
12
|
class FederalInformationProcessingStandards < Identifier
|
|
11
13
|
TYPED_STAGES = [
|
|
12
14
|
Pubid::Components::TypedStage.new(
|
|
@@ -21,6 +23,13 @@ module Pubid
|
|
|
21
23
|
TYPED_STAGES
|
|
22
24
|
end
|
|
23
25
|
|
|
26
|
+
# Bare "FIPS 197" names the NIST document (NIST/CSRC list every
|
|
27
|
+
# FIPS, NBS-era ones included, as "NIST FIPS"). A parsed "NBS"
|
|
28
|
+
# stays NBS.
|
|
29
|
+
def series_default_publisher
|
|
30
|
+
"NIST"
|
|
31
|
+
end
|
|
32
|
+
|
|
24
33
|
def type
|
|
25
34
|
{ key: :fips,
|
|
26
35
|
web: :federal_information_processing_standards, title: "Federal Information Processing Standards",
|
|
@@ -41,8 +50,10 @@ module Pubid
|
|
|
41
50
|
def to_mr_style
|
|
42
51
|
# "NIST.FIPS.197" keeps a parsed publisher (the DOI suffix NIST
|
|
43
52
|
# publishes); "FIPS.46e1977" has none and invents none.
|
|
53
|
+
# A bare "FIPS 197" carries the series default publisher NIST but
|
|
54
|
+
# did not spell it, so it prints no prefix either.
|
|
44
55
|
# Note: edition is appended directly to number without dot for FIPS
|
|
45
|
-
result = [
|
|
56
|
+
result = [printed_publisher, series_code].compact.join(".")
|
|
46
57
|
result += ".#{number}" if number
|
|
47
58
|
|
|
48
59
|
# FIPS uses dash notation for parts; render here and skip the generic
|
|
@@ -58,10 +69,30 @@ module Pubid
|
|
|
58
69
|
|
|
59
70
|
public
|
|
60
71
|
|
|
72
|
+
# The short-face lead: the official printed "FIPS PUB" for a spelled
|
|
73
|
+
# NIST publisher (owner ruling 2026-11-12), the spelled historical
|
|
74
|
+
# publisher for NBS rows, and the bare series code when the input
|
|
75
|
+
# spelled no publisher — the series-default NIST a bare parse fills
|
|
76
|
+
# (#704) is not a printed publisher, so the bare face stays bare.
|
|
77
|
+
def fips_render_lead
|
|
78
|
+
lead_publisher = printed_publisher
|
|
79
|
+
return "FIPS PUB" if lead_publisher == "NIST"
|
|
80
|
+
|
|
81
|
+
spelled = lead_publisher && !lead_publisher.empty?
|
|
82
|
+
return "#{lead_publisher} #{series_code}" if spelled
|
|
83
|
+
|
|
84
|
+
series_code.to_s
|
|
85
|
+
end
|
|
86
|
+
|
|
61
87
|
def to_short_style
|
|
62
|
-
#
|
|
63
|
-
|
|
64
|
-
|
|
88
|
+
# The official published face is "FIPS PUB <number>": FIPS is
|
|
89
|
+
# government-published, and "PUB" (Federal Information Processing
|
|
90
|
+
# Standards PUBlication) is part of the official designation
|
|
91
|
+
# (owner ruling 2026-11-12). The tail (volume/part/edition/
|
|
92
|
+
# supplement/update/draft) rides the lead unchanged, and the MR
|
|
93
|
+
# face ("NIST.FIPS.197") is an identity surface that does not
|
|
94
|
+
# move.
|
|
95
|
+
result = fips_render_lead
|
|
65
96
|
|
|
66
97
|
if number
|
|
67
98
|
# Convert dash-year patterns to edition format for FIPS
|
|
@@ -90,6 +121,14 @@ module Pubid
|
|
|
90
121
|
|
|
91
122
|
result
|
|
92
123
|
end
|
|
124
|
+
|
|
125
|
+
private
|
|
126
|
+
|
|
127
|
+
# The publisher the short and MR faces print: only one the input
|
|
128
|
+
# spelled, never the series default.
|
|
129
|
+
def printed_publisher
|
|
130
|
+
publisher if publisher_was_parsed
|
|
131
|
+
end
|
|
93
132
|
end
|
|
94
133
|
end
|
|
95
134
|
end
|
|
@@ -125,19 +125,21 @@ module Pubid
|
|
|
125
125
|
@cleaned = @cleaned.gsub(/\bLC\b(?!IRC)/, "LCIRC")
|
|
126
126
|
end
|
|
127
127
|
|
|
128
|
-
# The FIPS series'
|
|
129
|
-
# "
|
|
130
|
-
#
|
|
131
|
-
#
|
|
132
|
-
#
|
|
133
|
-
#
|
|
134
|
-
#
|
|
135
|
-
#
|
|
136
|
-
#
|
|
137
|
-
#
|
|
138
|
-
#
|
|
128
|
+
# The FIPS series' official printed face: FIPS is government-published
|
|
129
|
+
# and "PUB" (Federal Information Processing Standards PUBlication) is
|
|
130
|
+
# part of the official designation, so the RENDERER emits
|
|
131
|
+
# "FIPS PUB <number>" directly (owner ruling 2026-11-12). The grammar
|
|
132
|
+
# itself reads the publisher-bearing spelling only through this alias
|
|
133
|
+
# (pubid#697): it folds the printed spellings — "FIPS PUB 205" and the
|
|
134
|
+
# publisher-prefixed "NIST FIPS PUB 205" (pubid#702/#703) — onto the
|
|
135
|
+
# one model "NIST FIPS <number>" the grammar already builds (same
|
|
136
|
+
# to_hash, same URN, same MR string; revision spellings like
|
|
137
|
+
# "FIPS PUB 199 Rev. 1" included), while the renderer owns the printed
|
|
138
|
+
# face the fold converges to. Anchored at the head and run before
|
|
139
|
+
# every other stage so later digit/marker stages see the canonical
|
|
140
|
+
# spelling; "FIPS" alone (publisher_was_parsed: false) is untouched.
|
|
139
141
|
def normalize_fips_pub_alias!
|
|
140
|
-
@cleaned = @cleaned.sub(/\
|
|
142
|
+
@cleaned = @cleaned.sub(/\A(?:NIST )?FIPS PUB\b/i, "NIST FIPS")
|
|
141
143
|
end
|
|
142
144
|
|
|
143
145
|
# LCIRC series: combine with NBS prefix when a supplement marker
|
|
@@ -14,7 +14,7 @@ module Pubid
|
|
|
14
14
|
# Examples:
|
|
15
15
|
# - urn:nist:sp:800-53.supp → NIST SP 800-53
|
|
16
16
|
# - urn:nist:sp:800-53.r5.supp → NIST SP 800-53r5
|
|
17
|
-
# - urn:nist:fips:199.supp →
|
|
17
|
+
# - urn:nist:fips:199.supp → FIPS PUB 199
|
|
18
18
|
class UrnParser < Pubid::UrnParser::Base
|
|
19
19
|
TYPE_UPCASE = {
|
|
20
20
|
"sp" => "SP",
|
data/lib/pubid/version.rb
CHANGED
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.
|
|
4
|
+
version: 2.0.22
|
|
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-11-
|
|
11
|
+
date: 2026-11-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: lutaml-model
|
|
@@ -68,10 +68,12 @@ files:
|
|
|
68
68
|
- conformance/pending.yaml
|
|
69
69
|
- data/bipm/update_codes.yaml
|
|
70
70
|
- data/ccsds/update_codes.yaml
|
|
71
|
+
- data/iec/legacy-notation.md
|
|
71
72
|
- data/iec/stage-codes.md
|
|
72
73
|
- data/iec/update_codes.yaml
|
|
73
74
|
- data/ieee/update_codes.yaml
|
|
74
75
|
- data/iho/s4-reserved-specs.yaml
|
|
76
|
+
- data/iso/historic-schemes.md
|
|
75
77
|
- data/iso/update_codes.yaml
|
|
76
78
|
- data/nist/series.yaml
|
|
77
79
|
- data/nist/stages.yaml
|
|
@@ -142,6 +144,7 @@ files:
|
|
|
142
144
|
- data/parg/tables/organizations.yaml
|
|
143
145
|
- data/parg/tables/tc_types.yaml
|
|
144
146
|
- data/parg/tables/typed_stages.yaml
|
|
147
|
+
- data/parg/tables/typed_stages_ballots.yaml
|
|
145
148
|
- data/parg/tables/typed_stages_supplements.yaml
|
|
146
149
|
- data/parg/tables/wg_types.yaml
|
|
147
150
|
- data/parg/tgpp.json
|