pubid 2.0.24 → 2.0.25
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/jis/CLAUDE.md +35 -0
- data/lib/pubid/jis/builder.rb +33 -2
- data/lib/pubid/jis/identifier.rb +24 -4
- data/lib/pubid/jis/identifiers/welding_engineering_standard.rb +21 -2
- data/lib/pubid/jis/identifiers/welding_engineering_technical_report.rb +13 -0
- data/lib/pubid/jis/identifiers/welding_engineering_technical_specification.rb +14 -0
- data/lib/pubid/jis/identifiers.rb +5 -0
- data/lib/pubid/jis/parser.rb +30 -0
- data/lib/pubid/jis/pubid_urn_schema.rb +14 -3
- data/lib/pubid/jis/renderer.rb +1 -2
- data/lib/pubid/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e4c2df973dfad39ae259a1f12504977716b523133f7ba6e98f86dc1359274206
|
|
4
|
+
data.tar.gz: c4c7e18a50914f61ca002b3ce53d00b4b7dcdfdcac33168b34e6109f8f6b2890
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1224c069ca1bc1caa4ca1968252a4686dff6a99ac99b167e65546a800f0b1067e88e807dbb87da80db18744bdde4a1c3aee630da35d4610cefa7d36d52a055fc
|
|
7
|
+
data.tar.gz: d9091695721ae3b73953f550b5515b598c7328875fc1c679f549e339d0de2daa517ed0412bcf33fe3c04568cd1522a0635f9033ba79983981cacbc04dbedd1cf
|
data/lib/pubid/jis/CLAUDE.md
CHANGED
|
@@ -29,6 +29,41 @@
|
|
|
29
29
|
`UrnParser` does not prepend `JIS ` to a code that starts with `WES `.
|
|
30
30
|
- `PREFIXES` includes `"WES"`, so `Pubid.parse("WES …")` routes to JIS.
|
|
31
31
|
|
|
32
|
+
## WES `(E)` before the year, `WES TR`, `WES TS` (relaton-jis#18)
|
|
33
|
+
|
|
34
|
+
- JSA Webdesk lists 14 WES ids that the grammar does not read:
|
|
35
|
+
`WES 1112(E):2022`, `WES TR 2032:2024`, `WES TS 2816(E):2015`.
|
|
36
|
+
- **A Ruby shim reads them, not the grammar.** `Parser.ingest` cuts
|
|
37
|
+
the `TR`/`TS` token and a `(E)`/`(J)` that comes before `:year`, and
|
|
38
|
+
binds them as `wes_type` and `wes_language`. Other input passes unchanged.
|
|
39
|
+
The hand-off `pubid__pubid-grammar__jis-wes-language-tr-ts` asks
|
|
40
|
+
pubid-grammar to bind the same two captures. After that lands, re-vendor
|
|
41
|
+
`jis.json`, re-pin `parg_reaffirmed_spec.rb`, and delete the shim. The
|
|
42
|
+
builder does not change.
|
|
43
|
+
- **`WES TR`/`WES TS` are classes**: `WeldingEngineeringTechnicalReport`
|
|
44
|
+
and `…TechnicalSpecification` < `WeldingEngineeringStandard`, with
|
|
45
|
+
`WES_TYPE` in `code` (`WES TR 2032`) and in `mr_type`. Class-strict `==`
|
|
46
|
+
keeps them apart from `WES 2032` and `JIS TR Z 2032`.
|
|
47
|
+
- **`language_before_year`** records where the source put the language. It
|
|
48
|
+
is spelling only (`equality_ignored`, a `langfirst` facet in the pubid
|
|
49
|
+
URN): `WES 1112(E):2022 == WES 1112:2022(E)`, and each renders as written.
|
|
50
|
+
The language itself is identity, so the `(E)` edition is not the Japanese
|
|
51
|
+
one. JIS ids never set the flag; `JIS X 0208(E):1997` still fails.
|
|
52
|
+
- The pubid URN schema now places `language` and the supplement ordinal
|
|
53
|
+
(`core: [["number", :int]]`; an `EXPL` number is the atom `n`). Before,
|
|
54
|
+
every `(E)` id and every supplement raised in `to_pubid_urn`, and no
|
|
55
|
+
supplement was in the fixture corpus to show it.
|
|
56
|
+
- **`Builder` reads both parse shapes.** The typed bindings
|
|
57
|
+
(`Parg::Model.bound`) carry a supplement flat (`amd_type`, …); the raw
|
|
58
|
+
tree (`Parg::Backend.parse`) nests it under `:amendment`/`:explanation`/
|
|
59
|
+
`:corrigendum`. `flatten_supplement` folds the nested form. Before, the
|
|
60
|
+
tree path dropped every supplement silently (`…/AMD 1:2000` built as the
|
|
61
|
+
bare base). `typed_binding_parity_spec.rb` found it when the first
|
|
62
|
+
supplement entered the pass corpus.
|
|
63
|
+
- **The shim lives in `Parser.ingest`** and returns `[face, bindings]`.
|
|
64
|
+
`typed_binding_parity_spec.rb` calls it on the tree path too and merges
|
|
65
|
+
the bindings, as `Identifier.parse` does.
|
|
66
|
+
|
|
32
67
|
## Equality includes the class
|
|
33
68
|
|
|
34
69
|
- `Identifier#==` requires `other.instance_of?(self.class)`: `JIS TR X
|
data/lib/pubid/jis/builder.rb
CHANGED
|
@@ -8,6 +8,7 @@ module Pubid
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def build(data)
|
|
11
|
+
data = flatten_supplement(data)
|
|
11
12
|
# Handle supplement case first; the SYMBOL clause (if any) attaches to
|
|
12
13
|
# the outermost identifier, be it the base or the supplement. The
|
|
13
14
|
# bindings bind the supplement's fields flat (amd_type/amd_number/…),
|
|
@@ -29,6 +30,19 @@ module Pubid
|
|
|
29
30
|
|
|
30
31
|
private
|
|
31
32
|
|
|
33
|
+
SUPPLEMENT_KEYS = %i[amendment explanation corrigendum].freeze
|
|
34
|
+
|
|
35
|
+
# The typed bindings carry a supplement's fields flat (amd_type, …).
|
|
36
|
+
# The raw parse tree nests them under :amendment, :explanation or
|
|
37
|
+
# :corrigendum. Read both shapes, or the tree path drops the
|
|
38
|
+
# supplement.
|
|
39
|
+
def flatten_supplement(data)
|
|
40
|
+
key = SUPPLEMENT_KEYS.find { |k| data[k].is_a?(Hash) }
|
|
41
|
+
return data unless key
|
|
42
|
+
|
|
43
|
+
data.except(key).merge(data[key].compact)
|
|
44
|
+
end
|
|
45
|
+
|
|
32
46
|
# nil => no SYMBOL clause; "" => bare "SYMBOL" keyword; otherwise value.
|
|
33
47
|
def attach_symbol(identifier, data)
|
|
34
48
|
identifier.symbol = data[:symbol_value].to_s if data[:symbol_present]
|
|
@@ -44,13 +58,30 @@ module Pubid
|
|
|
44
58
|
reaffirmed: (true if data[:reaffirmed]),
|
|
45
59
|
}
|
|
46
60
|
# A WES id carries no series letter, so its series stays nil.
|
|
47
|
-
|
|
48
|
-
return wes.new(**attrs) if data[:wes]
|
|
61
|
+
return build_wes(data, attrs) if data[:wes]
|
|
49
62
|
|
|
50
63
|
jis_class_for_type(data[:type]&.to_s)
|
|
51
64
|
.new(series: data[:series].to_s, **attrs)
|
|
52
65
|
end
|
|
53
66
|
|
|
67
|
+
# `wes_type` ("TR"/"TS") picks the WES class. `wes_language` is a
|
|
68
|
+
# language printed before the year ("WES 1112(E):2022").
|
|
69
|
+
def build_wes(data, attrs)
|
|
70
|
+
attrs = attrs.merge(wes_language_attrs(data)) if data[:wes_language]
|
|
71
|
+
Identifiers::WeldingEngineeringStandard
|
|
72
|
+
.class_for_type(data[:wes_type]&.to_s).new(**attrs)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def wes_language_attrs(data)
|
|
76
|
+
if data[:language]
|
|
77
|
+
raise Pubid::Errors::ParseError.new(
|
|
78
|
+
"a WES id carries one language, not two", nil
|
|
79
|
+
)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
{ language: data[:wes_language].to_s, language_before_year: true }
|
|
83
|
+
end
|
|
84
|
+
|
|
54
85
|
def jis_class_for_type(type)
|
|
55
86
|
case type
|
|
56
87
|
when "TR" then Identifiers::TechnicalReport
|
data/lib/pubid/jis/identifier.rb
CHANGED
|
@@ -21,6 +21,11 @@ module Pubid
|
|
|
21
21
|
attribute :parts, :string, collection: true # Optional multi-level parts
|
|
22
22
|
attribute :year, :integer
|
|
23
23
|
attribute :language, :string # "E" or "J"
|
|
24
|
+
# A WES id can print its language before the year ("WES 1112(E):2022")
|
|
25
|
+
# or after it ("WES 1112:2022(E)"). This records the source position.
|
|
26
|
+
# It is spelling only, so `==` does not read it.
|
|
27
|
+
attribute :language_before_year, :boolean
|
|
28
|
+
equality_ignored :language_before_year
|
|
24
29
|
# Reaffirmation (再確認): a trailing "R" on the year marks an edition
|
|
25
30
|
# that was reaffirmed without revision (e.g. ":2019R").
|
|
26
31
|
attribute :reaffirmed, :boolean
|
|
@@ -45,6 +50,10 @@ module Pubid
|
|
|
45
50
|
"pubid:jis:explanation" => "Pubid::Jis::Identifiers::Explanation",
|
|
46
51
|
"pubid:jis:welding-engineering-standard" =>
|
|
47
52
|
"Pubid::Jis::Identifiers::WeldingEngineeringStandard",
|
|
53
|
+
"pubid:jis:welding-engineering-technical-report" =>
|
|
54
|
+
"Pubid::Jis::Identifiers::WeldingEngineeringTechnicalReport",
|
|
55
|
+
"pubid:jis:welding-engineering-technical-specification" =>
|
|
56
|
+
"Pubid::Jis::Identifiers::WeldingEngineeringTechnicalSpecification",
|
|
48
57
|
}.freeze
|
|
49
58
|
|
|
50
59
|
key_value do
|
|
@@ -54,6 +63,7 @@ module Pubid
|
|
|
54
63
|
map "parts", to: :parts
|
|
55
64
|
map "year", to: :year
|
|
56
65
|
map "language", to: :language
|
|
66
|
+
map "language_before_year", to: :language_before_year
|
|
57
67
|
map "reaffirmed", to: :reaffirmed
|
|
58
68
|
# render_empty keeps a bare "SYMBOL" (empty-string value) in the hash so
|
|
59
69
|
# it round-trips distinctly from "no symbol" (nil).
|
|
@@ -75,6 +85,17 @@ module Pubid
|
|
|
75
85
|
reaffirmed == true
|
|
76
86
|
end
|
|
77
87
|
|
|
88
|
+
def language_before_year?
|
|
89
|
+
language_before_year == true
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# The ":year[R]" and "(lang)" tail, in the order the source used.
|
|
93
|
+
def year_and_language
|
|
94
|
+
year_part = year ? ":#{year_with_reaffirmation}" : ""
|
|
95
|
+
lang_part = language ? "(#{language})" : ""
|
|
96
|
+
language_before_year? ? lang_part + year_part : year_part + lang_part
|
|
97
|
+
end
|
|
98
|
+
|
|
78
99
|
# Render a year with its reaffirmation marker, e.g. "2019R".
|
|
79
100
|
def year_with_reaffirmation
|
|
80
101
|
"#{year}#{'R' if reaffirmed?}"
|
|
@@ -184,10 +205,9 @@ module Pubid
|
|
|
184
205
|
raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
185
206
|
end
|
|
186
207
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
parsed
|
|
190
|
-
Builder.build(parsed)
|
|
208
|
+
face, bindings = Parser.ingest(::Pubid.utf8_input(identifier))
|
|
209
|
+
parsed = Pubid::Parg::Model.bound(:jis, face)
|
|
210
|
+
Builder.build(parsed.merge(bindings))
|
|
191
211
|
end
|
|
192
212
|
end
|
|
193
213
|
end
|
|
@@ -6,9 +6,20 @@ module Pubid
|
|
|
6
6
|
# Japan Welding Engineering Society standard. JSA sells WES next to JIS,
|
|
7
7
|
# so it parses through the JIS flavor, but the id carries no series
|
|
8
8
|
# letter and no JIS prefix.
|
|
9
|
-
# Examples: WES 7700-1:2019, WES 7301:2020R
|
|
9
|
+
# Examples: WES 7700-1:2019, WES 7301:2020R, WES 1112(E):2022
|
|
10
10
|
class WeldingEngineeringStandard < SingleIdentifier
|
|
11
11
|
PUBLISHER = "WES"
|
|
12
|
+
# The type token after the WES root: "TR", "TS", or nil.
|
|
13
|
+
WES_TYPE = nil
|
|
14
|
+
|
|
15
|
+
# The WES class for a type token ("TR", "TS" or nil).
|
|
16
|
+
def self.class_for_type(type)
|
|
17
|
+
case type
|
|
18
|
+
when "TR" then WeldingEngineeringTechnicalReport
|
|
19
|
+
when "TS" then WeldingEngineeringTechnicalSpecification
|
|
20
|
+
else WeldingEngineeringStandard
|
|
21
|
+
end
|
|
22
|
+
end
|
|
12
23
|
|
|
13
24
|
def type_prefix
|
|
14
25
|
nil
|
|
@@ -20,8 +31,12 @@ module Pubid
|
|
|
20
31
|
nil
|
|
21
32
|
end
|
|
22
33
|
|
|
34
|
+
def wes_type
|
|
35
|
+
self.class::WES_TYPE
|
|
36
|
+
end
|
|
37
|
+
|
|
23
38
|
def code
|
|
24
|
-
result =
|
|
39
|
+
result = [PUBLISHER, wes_type, number].compact.join(" ")
|
|
25
40
|
result += parts.map { |p| "-#{p}" }.join if parts&.any?
|
|
26
41
|
result
|
|
27
42
|
end
|
|
@@ -29,6 +44,10 @@ module Pubid
|
|
|
29
44
|
def mr_publisher
|
|
30
45
|
PUBLISHER.downcase
|
|
31
46
|
end
|
|
47
|
+
|
|
48
|
+
def mr_type
|
|
49
|
+
wes_type&.downcase
|
|
50
|
+
end
|
|
32
51
|
end
|
|
33
52
|
end
|
|
34
53
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Jis
|
|
5
|
+
module Identifiers
|
|
6
|
+
# WES technical report. The type token follows the WES root.
|
|
7
|
+
# Example: WES TR 2032:2024
|
|
8
|
+
class WeldingEngineeringTechnicalReport < WeldingEngineeringStandard
|
|
9
|
+
WES_TYPE = "TR"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Jis
|
|
5
|
+
module Identifiers
|
|
6
|
+
# WES technical specification. The type token follows the WES root.
|
|
7
|
+
# Examples: WES TS 2816:2015, WES TS 2816(E):2015
|
|
8
|
+
class WeldingEngineeringTechnicalSpecification <
|
|
9
|
+
WeldingEngineeringStandard
|
|
10
|
+
WES_TYPE = "TS"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -15,6 +15,11 @@ module Pubid
|
|
|
15
15
|
"#{__dir__}/identifiers/technical_specification"
|
|
16
16
|
autoload :WeldingEngineeringStandard,
|
|
17
17
|
"#{__dir__}/identifiers/welding_engineering_standard"
|
|
18
|
+
autoload :WeldingEngineeringTechnicalReport,
|
|
19
|
+
"#{__dir__}/identifiers/welding_engineering_technical_report"
|
|
20
|
+
autoload :WeldingEngineeringTechnicalSpecification,
|
|
21
|
+
"#{__dir__}/identifiers/" \
|
|
22
|
+
"welding_engineering_technical_specification"
|
|
18
23
|
end
|
|
19
24
|
end
|
|
20
25
|
end
|
data/lib/pubid/jis/parser.rb
CHANGED
|
@@ -2,7 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
module Pubid
|
|
4
4
|
module Jis
|
|
5
|
+
# The JIS grammar is the vendored artifact data/parg/jis.json. This class
|
|
6
|
+
# holds only the Ruby ingestion in front of it.
|
|
5
7
|
class Parser
|
|
8
|
+
# A WES type token or a language before the year. Full-width forms
|
|
9
|
+
# are accepted, as in the grammar.
|
|
10
|
+
WES_SHIM = /
|
|
11
|
+
\A(?<root>WES[ ])
|
|
12
|
+
(?:(?<type>TR|TS)[ ])?
|
|
13
|
+
(?<number>\d+(?:[-ー]\d+)*)
|
|
14
|
+
(?:[((](?<lang>[EJ])[))](?=[::]))?
|
|
15
|
+
/x
|
|
16
|
+
|
|
17
|
+
# The vendored grammar (pubid-grammar artifacts/jis.json) reads neither
|
|
18
|
+
# "WES TR 2032" nor "WES 1112(E):2022". Until it does, cut those tokens
|
|
19
|
+
# from the input and bind them as `wes_type` and `wes_language`, the
|
|
20
|
+
# captures the grammar is to bind (hand-off
|
|
21
|
+
# pubid__pubid-grammar__jis-wes-language-tr-ts). Other input passes
|
|
22
|
+
# unchanged.
|
|
23
|
+
# @param input [String]
|
|
24
|
+
# @return [Array(String, Hash)] the input for the grammar, the bindings
|
|
25
|
+
# to merge into what the grammar binds
|
|
26
|
+
def self.ingest(input)
|
|
27
|
+
match = WES_SHIM.match(input)
|
|
28
|
+
return [input, {}] unless match && (match[:type] || match[:lang])
|
|
29
|
+
|
|
30
|
+
bindings = {}
|
|
31
|
+
bindings[:wes_type] = match[:type] if match[:type]
|
|
32
|
+
bindings[:wes_language] = match[:lang] if match[:lang]
|
|
33
|
+
rest = input[match.end(0)..]
|
|
34
|
+
["#{match[:root]}#{match[:number]}#{rest}", bindings]
|
|
35
|
+
end
|
|
6
36
|
end
|
|
7
37
|
end
|
|
8
38
|
end
|
|
@@ -13,17 +13,28 @@ module Pubid
|
|
|
13
13
|
atom "parts", "part", kind: :list
|
|
14
14
|
atom "year", "year", kind: :int
|
|
15
15
|
atom "reaffirmed", "reaffirmed", kind: :bool
|
|
16
|
+
atom "language", "lang"
|
|
17
|
+
# Where a WES id prints its language: "WES 1112(E):2022" against
|
|
18
|
+
# "WES 1112:2022(E)". Spelling only.
|
|
19
|
+
facet "language_before_year", "langfirst", kind: :bool
|
|
16
20
|
|
|
17
21
|
type "pubid:jis:all-parts", "all"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
# A supplement's number is its Integer ordinal. The document it
|
|
23
|
+
# supplements comes first, along +base+. An explanation can have no
|
|
24
|
+
# number ("…/EXPL"), so its number is an atom.
|
|
25
|
+
supplement = [["number", :int]]
|
|
26
|
+
type "pubid:jis:amendment", "amd", core: supplement
|
|
27
|
+
type "pubid:jis:corrigendum", "cor", core: supplement
|
|
28
|
+
type "pubid:jis:explanation", "e", core: [],
|
|
29
|
+
atoms: [["number", "n", :int]]
|
|
21
30
|
type "pubid:jis:identifier", "id"
|
|
22
31
|
type "pubid:jis:japanese-industrial-standard", "jis"
|
|
23
32
|
type "pubid:jis:standard", "std"
|
|
24
33
|
type "pubid:jis:technical-report", "tr"
|
|
25
34
|
type "pubid:jis:technical-specification", "ts"
|
|
26
35
|
type "pubid:jis:welding-engineering-standard", "wes"
|
|
36
|
+
type "pubid:jis:welding-engineering-technical-report", "westr"
|
|
37
|
+
type "pubid:jis:welding-engineering-technical-specification", "wests"
|
|
27
38
|
end
|
|
28
39
|
end
|
|
29
40
|
end
|
data/lib/pubid/jis/renderer.rb
CHANGED
|
@@ -49,8 +49,7 @@ module Pubid
|
|
|
49
49
|
result = parts.join(" ")
|
|
50
50
|
result += " " if result.length.positive?
|
|
51
51
|
result += id.code.to_s
|
|
52
|
-
result +=
|
|
53
|
-
result += "(#{id.language})" if id.language
|
|
52
|
+
result += id.year_and_language
|
|
54
53
|
result += id.symbol_suffix
|
|
55
54
|
result
|
|
56
55
|
end
|
data/lib/pubid/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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.25
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -897,6 +897,8 @@ files:
|
|
|
897
897
|
- lib/pubid/jis/identifiers/technical_report.rb
|
|
898
898
|
- lib/pubid/jis/identifiers/technical_specification.rb
|
|
899
899
|
- lib/pubid/jis/identifiers/welding_engineering_standard.rb
|
|
900
|
+
- lib/pubid/jis/identifiers/welding_engineering_technical_report.rb
|
|
901
|
+
- lib/pubid/jis/identifiers/welding_engineering_technical_specification.rb
|
|
900
902
|
- lib/pubid/jis/parser.rb
|
|
901
903
|
- lib/pubid/jis/pubid_urn_schema.rb
|
|
902
904
|
- lib/pubid/jis/renderer.rb
|