pubid 2.0.0.pre.alpha.40 → 2.0.0.pre.alpha.42
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/CLAUDE.md +1 -1
- data/lib/pubid/identifier.rb +40 -3
- data/lib/pubid/nist/CLAUDE.md +18 -0
- data/lib/pubid/nist/urn_parser.rb +36 -8
- data/lib/pubid/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 727766fd99f726fa80503d1b6c0a069a889b9837d100508cb94f11989b28c1c4
|
|
4
|
+
data.tar.gz: d748fad2cb8845c858a03b78aa303644f6c6f24eaeb83a3fa0803f56cb6a0039
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 52c2d82f4dd10de849784edc147c35a9747f1c3f77b23f3e971d976bad8f1f930e58f9b99904ed8542c7bed2be7eef94c564ded781283c0f008c9426f42e59ca
|
|
7
|
+
data.tar.gz: 0c614594edcdd773af2d5d4240362fa32ee088625bfa3a8cc819bc40d6c697904c53b0a54ccb5ca47c4f35e1f0f02a711fb55a731d5a05395d455a9b6e0be874
|
data/lib/pubid/bsi/CLAUDE.md
CHANGED
|
@@ -90,4 +90,4 @@ The general fix (`metanorma__pubid__exclude-recursion-depth` hand-off) promotes
|
|
|
90
90
|
|
|
91
91
|
Verified: `spec/pubid/supplement_date_attributes_spec.rb` exercises the mechanism directly; `spec/pubid/bsi/parse_gaps_spec.rb`, `match_primitives_spec.rb` and `adoption_base_spec.rb`, and `spec/pubid/cen_cenelec/relaton_blockers_spec.rb`'s 10 pinned `:supplement_year` cases, all pass unchanged. Because the new logic only fires when `supplement_date_attributes` is non-empty, every other flavor (including ISO/IEC, which deliberately keep a supplement's year in `date` with no protection — see `lib/pubid/cen_cenelec/CLAUDE.md`) is untouched.
|
|
92
92
|
|
|
93
|
-
**Open question, not resolved here: `#dated_version_of?`/`#draft_of?` on a bare BSI supplement.** Both
|
|
93
|
+
**Open question, not resolved here: `#dated_version_of?`/`#draft_of?` on a bare BSI supplement.** Both compare `exclude(:date, :year[, …])`, which — like every other bare `:date`/`:year` exclusion — now protects a supplement's own date unless `:supplement_year` is also passed. Two standalone `BS 7273-4:2015+A1:2021`/`...+A1:2022` objects were `dated_version_of?` each other before this branch (BSI's old `year`-attribute dodge never protected against `exclude(:year)`) and are not after. **Whether that's the right answer is genuinely unclear and deliberately left open pending feedback** — one reading is that this just makes BSI consistent with CEN/CENELEC, which already behaved this way before this branch (its pre-existing per-flavor `#exclude` override had the same protection); the other is that these two generic relational predicates should be widened to accept a `:supplement_year`-aware exclusion set so they can still recognize two differently-dated editions of the *same supplement* as related. (The predicates switched from `matches?(other, ignore: …)` to the equivalent `exclude(…)` comparison so NIST's asymmetric `#matches?` override no longer breaks them; BSI behavior is unchanged.) Locked (as current behavior, not as a verdict) by `spec/pubid/supplement_date_attributes_spec.rb`.
|
data/lib/pubid/identifier.rb
CHANGED
|
@@ -1177,10 +1177,46 @@ module Pubid
|
|
|
1177
1177
|
|
|
1178
1178
|
# Self and +other+ refer to the same document but differ only in the
|
|
1179
1179
|
# trailing date / year — the "dated vs undated" reference pattern.
|
|
1180
|
+
# Compares #exclude, not #matches?: NIST overrides #matches? as an
|
|
1181
|
+
# asymmetric wildcard query (and takes no ignore: keyword).
|
|
1180
1182
|
def dated_version_of?(other)
|
|
1181
1183
|
return false unless other.is_a?(::Pubid::Identifier)
|
|
1182
1184
|
|
|
1183
|
-
|
|
1185
|
+
exclude(:date, :year) == other.exclude(:date, :year) && self != other
|
|
1186
|
+
end
|
|
1187
|
+
|
|
1188
|
+
# The attributes that carry a revision marker. Flavors spell it
|
|
1189
|
+
# differently: OGC and IEEE hold a string (+revision+), NIST folds the
|
|
1190
|
+
# lettered revision and its date into an +update+ component.
|
|
1191
|
+
REVISION_ATTRIBUTES = %i[revision update update_component].freeze
|
|
1192
|
+
|
|
1193
|
+
# The revision marker this identifier carries, or nil. See
|
|
1194
|
+
# REVISION_ATTRIBUTES.
|
|
1195
|
+
# @return [String, Components::Update, nil]
|
|
1196
|
+
def revision_marker
|
|
1197
|
+
REVISION_ATTRIBUTES.each do |name|
|
|
1198
|
+
next unless self.class.attributes.key?(name)
|
|
1199
|
+
|
|
1200
|
+
value = public_send(name)
|
|
1201
|
+
return value unless value.nil? || value == ""
|
|
1202
|
+
end
|
|
1203
|
+
nil
|
|
1204
|
+
end
|
|
1205
|
+
|
|
1206
|
+
# Self is a revision of +other+: the same document, where self carries a
|
|
1207
|
+
# revision marker ("OGC 06-121r9", "NBS LC 800 rJun1992") that +other+
|
|
1208
|
+
# lacks or spells differently. A document whose revision is modelled as
|
|
1209
|
+
# an edition is covered by #edition_of? instead.
|
|
1210
|
+
def revision_of?(other)
|
|
1211
|
+
return false unless other.is_a?(::Pubid::Identifier)
|
|
1212
|
+
return false if self == other
|
|
1213
|
+
return false if revision_marker.nil?
|
|
1214
|
+
|
|
1215
|
+
# #exclude, not #matches?: NIST overrides #matches? as an asymmetric
|
|
1216
|
+
# wildcard query (and takes no ignore: keyword), which would compare a
|
|
1217
|
+
# query against a candidate rather than two concrete documents.
|
|
1218
|
+
exclude(*REVISION_ATTRIBUTES) == other.exclude(*REVISION_ATTRIBUTES) &&
|
|
1219
|
+
revision_marker != other.revision_marker
|
|
1184
1220
|
end
|
|
1185
1221
|
|
|
1186
1222
|
# The document a wrapper stands in front of: a supplement's base, or
|
|
@@ -1289,7 +1325,8 @@ module Pubid
|
|
|
1289
1325
|
|
|
1290
1326
|
root == other.root &&
|
|
1291
1327
|
self != other &&
|
|
1292
|
-
|
|
1328
|
+
exclude(:date, :year, :stage, :typed_stage) ==
|
|
1329
|
+
other.exclude(:date, :year, :stage, :typed_stage)
|
|
1293
1330
|
end
|
|
1294
1331
|
|
|
1295
1332
|
# Self and +other+ are editions of the same document: the edition-year
|
|
@@ -1315,7 +1352,7 @@ module Pubid
|
|
|
1315
1352
|
# Any relational predicate holds.
|
|
1316
1353
|
def related_to?(other)
|
|
1317
1354
|
%i[supplement_of? has_supplement? dated_version_of? edition_of?
|
|
1318
|
-
sibling_of? includes? draft_of?].any? do |m|
|
|
1355
|
+
revision_of? sibling_of? includes? draft_of?].any? do |m|
|
|
1319
1356
|
public_send(m, other)
|
|
1320
1357
|
end
|
|
1321
1358
|
end
|
data/lib/pubid/nist/CLAUDE.md
CHANGED
|
@@ -54,3 +54,21 @@ Read this before you change `lib/pubid/nist/` or `spec/pubid/nist/`. The root
|
|
|
54
54
|
`update`/`update_component` and cleared to `nil` before the object is
|
|
55
55
|
returned. Neither carries live information `edition`/`update` doesn't
|
|
56
56
|
already cover. Locked by `spec/pubid/all_parts_edition_keys_audit_spec.rb`.
|
|
57
|
+
|
|
58
|
+
- **The URN parser must rebuild the human face the generator started from,
|
|
59
|
+
field for field.** `UrnGenerator` dot-joins identity fields after the
|
|
60
|
+
number (`urn:nist:sp:304.e2017.A.supp`), and `UrnParser#parse_payload`
|
|
61
|
+
splits them back: the edition/volume/revision glue onto the number, a
|
|
62
|
+
single capital-letter token is a **part** glued to the code
|
|
63
|
+
(`304A`), an edition's additional text keeps its dot (`13e2.June1908` —
|
|
64
|
+
the token after `eN`), `insert`/`errata`/`add` markers glue verbatim,
|
|
65
|
+
the bare `.supp` is supplementability (non-identity) and a valued
|
|
66
|
+
`.supp-<v>` is `sup<v>`. The rebuild is only correct if the flavor's own
|
|
67
|
+
grammar accepts it, so every branch is measured against the corpus —
|
|
68
|
+
before this, the five rows with a part letter, an edition additional
|
|
69
|
+
text, or an addendum marker failed to re-parse and the reference's own
|
|
70
|
+
`parse_urn` raised on its own output. The ts mirror must reproduce
|
|
71
|
+
Ruby's `String#split` behaviour and drop **trailing** empty fields
|
|
72
|
+
(`"800-38.A.supp.add."` splits with a trailing `""` in JS but not in
|
|
73
|
+
Ruby; keeping it appends a stray `.`). Locked by
|
|
74
|
+
`spec/pubid/nist/urn_parser_spec.rb`.
|
|
@@ -40,10 +40,10 @@ module Pubid
|
|
|
40
40
|
parts = split_parts(body)
|
|
41
41
|
|
|
42
42
|
type_token, payload = parts
|
|
43
|
-
code,
|
|
43
|
+
code, suffix = parse_payload(payload)
|
|
44
44
|
|
|
45
45
|
text = "#{publisher_for(type_token)} #{type_label(type_token)} #{code}"
|
|
46
|
-
text +=
|
|
46
|
+
text += suffix
|
|
47
47
|
flavor_parse(text)
|
|
48
48
|
end
|
|
49
49
|
|
|
@@ -58,14 +58,42 @@ module Pubid
|
|
|
58
58
|
NBS_SERIES.include?(type_token.downcase) ? "NBS" : "NIST"
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
+
# The generator dot-joins the identity's fields after the number
|
|
62
|
+
# ("urn:nist:circ:25.e1924.supp", "urn:nist:circ:539.v10.supp",
|
|
63
|
+
# "urn:nist:circ:24.supp-1"). Reassemble the human spelling the
|
|
64
|
+
# flavor parser reads: the edition and volume glue onto the number,
|
|
65
|
+
# a revision glues after them, the bare ".supp" marks
|
|
66
|
+
# supplementability (non-identity) and a valued ".supp-<v>" is the
|
|
67
|
+
# supplement's "sup<v>" face.
|
|
61
68
|
def parse_payload(payload)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
tokens = payload.split(".")
|
|
70
|
+
code = tokens.shift.to_s
|
|
71
|
+
suffix = +""
|
|
72
|
+
part = nil
|
|
73
|
+
edition = nil
|
|
74
|
+
volume = nil
|
|
75
|
+
revision = nil
|
|
76
|
+
supplement = nil
|
|
67
77
|
|
|
68
|
-
|
|
78
|
+
tokens.each do |token|
|
|
79
|
+
case token
|
|
80
|
+
when /\Ar\d+\z/i then revision = token
|
|
81
|
+
when /\Ae[\w]+\z/i then edition = token
|
|
82
|
+
when /\Av\d+\z/i then volume = token
|
|
83
|
+
when /\Asupp-(.+)\z/im then supplement = Regexp.last_match(1)
|
|
84
|
+
when "supp" then next # supplementability marker, not identity
|
|
85
|
+
when "insert", "errata" then suffix << token # glued in the human
|
|
86
|
+
when /\A[A-Z]\z/ then part = token # part letter, glued to the code
|
|
87
|
+
when /\A[A-Z][a-z]+\d{4}\z/ # edition's additional text ("13e2.June1908")
|
|
88
|
+
edition = "#{edition}.#{token}" if edition
|
|
89
|
+
else suffix << ".#{token}" # unknown marker: keep verbatim
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
code << part.to_s
|
|
94
|
+
suffix << edition.to_s << volume.to_s << revision.to_s
|
|
95
|
+
suffix << "sup#{supplement}" if supplement
|
|
96
|
+
[code, suffix]
|
|
69
97
|
end
|
|
70
98
|
|
|
71
99
|
def type_label(token)
|
data/lib/pubid/version.rb
CHANGED