relaton-ietf 1.9.0 → 1.9.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de34f43de3864f7494ab3931162ecff103d9f2f66828374bc26ccc91da3c3295
4
- data.tar.gz: 84f76c4b573041e55f60efdf208480c6832129a9a094bc3c12205bc19ba42552
3
+ metadata.gz: 5ed659b3ac3a91f53fa5872cb839be97adeba30e6eba56f211f140e55b5836d8
4
+ data.tar.gz: 8b1c58e40158c126f11ab25c92ca99230a3e00064b8d0fb20ad250c51c01e7b8
5
5
  SHA512:
6
- metadata.gz: d6f0c509201f46a402655f2ea4d75b678cb6c4638715a07cd637c8b5c8fa3dc04254ea914dfcd27eebe024231b8caec5b2435f944bc5d8185622b1b515dff3ab
7
- data.tar.gz: bd93874e76dad53e998abd0988aba64354a7a5d011141f57e945bb2a2e7c690e0b790c58a343070160bee77d2e8cb7332fe5b2a59d2c983b3222e9bc55db09f7
6
+ metadata.gz: 163f11e5a49d8dd44d6592c1741281b8756f505ac49feb59d3a508ec2ad7340498db0a5d71a1ccfbbc8c4de385ee967388119238f0c4f94641a839623fe19c65
7
+ data.tar.gz: 0a86ac885aca2d200e5d64cdee74e0b4b5e6d42f77a5e9fb60c233e77e19c176137ebc8220a7397e56e6564edcd58c09933553810a4265597fbc7e64c02a173b
data/README.adoc CHANGED
@@ -90,6 +90,21 @@ item.to_xml bibdata: true
90
90
  </bibdata>"
91
91
  ----
92
92
 
93
+ === Typed links
94
+
95
+ IETF documents may have `src`, `xml`, and `doi` link type.
96
+
97
+ * `src` - web pulication
98
+ * `xml` - BibXML publication
99
+ * `doi` - DOI reference
100
+
101
+ [source,ruby]
102
+ ----
103
+ item.link
104
+ => [#<RelatonBib::TypedUri:0x00007fe8b287a120 @content=#<Addressable::URI:0x7e4 URI:https://raw.githubusercontent.com/relaton/relaton-data-ietf/master/data/reference.RFC.8341.xml>, @type="xml">,
105
+ #<RelatonBib::TypedUri:0x00007fe8b2237ec0 @content=#<Addressable::URI:0x7f8 URI:https://www.rfc-editor.org/info/rfc8341>, @type="src">]
106
+ ----
107
+
93
108
  === Parse a file locally
94
109
 
95
110
  [source,ruby]
@@ -0,0 +1,8 @@
1
+ module RelatonIetf
2
+ class Committee < RelatonBib::TechnicalCommittee
3
+ # @param builder [Nokogiri::XML::Builder]
4
+ def to_xml(builder)
5
+ builder.committee { |b| workgroup.to_xml b }
6
+ end
7
+ end
8
+ end
@@ -21,7 +21,7 @@ module RelatonIetf
21
21
  # @return [RelatonIetf::IetfBibliographicItem]
22
22
  def self.from_hash(hash)
23
23
  item_hash = ::RelatonIetf::HashConverter.hash_to_bib(hash)
24
- new **item_hash
24
+ new(**item_hash)
25
25
  end
26
26
 
27
27
  # @param opts [Hash]
@@ -32,7 +32,7 @@ module RelatonIetf
32
32
  # @return [String] XML
33
33
  def to_xml(**opts)
34
34
  opts[:date_format] ||= :short
35
- super **opts
35
+ super(**opts)
36
36
  end
37
37
  end
38
38
  end
@@ -5,365 +5,372 @@ require "relaton_bib"
5
5
  require "relaton_ietf/ietf_bibliographic_item"
6
6
 
7
7
  module RelatonIetf
8
- # rubocop:disable Metrics/ModuleLength
9
-
10
8
  # Scrapper module
11
9
  module Scrapper
12
- GH_URL = "https://raw.githubusercontent.com/relaton/relaton-data-ietf/master/data/reference."
13
- BCP_URI_PATTERN = "https://www.rfc-editor.org/info/CODE"
14
-
15
- class << self
16
- # @param text [String]
17
- # @param is_relation [TrueClass, FalseClass]
18
- # @return [RelatonIetf::IetfBibliographicItem]
19
- def scrape_page(text, is_relation: false)
20
- # Remove initial "IETF " string if specified
21
- ref = text.gsub(/^IETF /, "")
22
- /^(?:RFC|BCP|FYI|STD)\s(?<num>\d+)/ =~ ref
23
- ref.sub! /(?<=^(?:RFC|BCP|FYI|STD)\s)(\d+)/, num.rjust(4, "0") if num
24
- rfc_item ref, is_relation
25
- rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
26
- Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
27
- Net::ProtocolError, SocketError
28
- raise RelatonBib::RequestError, "No document found for #{ref} reference"
29
- end
30
-
31
- # @param reference [Nokogiri::XML::Element, nil]
32
- # @param is_relation [TrueClass, FalseClass]
33
- # @param url [String, NilClass]
34
- # @param ver [String, NilClass] Internet Draft version
35
- # @return [RelatonIetf::IetfBibliographicItem]
36
- def fetch_rfc(reference, is_relation: false, url: nil, ver: nil) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
37
- return unless reference
38
-
39
- ietf_item(
40
- is_relation: is_relation,
41
- id: reference[:anchor],
42
- type: "standard",
43
- docid: docids(reference, ver),
44
- status: status(reference),
45
- language: [language(reference)],
46
- link: link(reference, url, ver),
47
- title: titles(reference),
48
- formattedref: formattedref(reference),
49
- abstract: abstracts(reference),
50
- contributor: contributors(reference),
51
- relation: relations(reference),
52
- date: dates(reference),
53
- series: series(reference),
54
- place: ["Fremont, CA"],
55
- keyword: reference.xpath("front/keyword").map(&:text),
56
- doctype: doctype(reference[:anchor]),
57
- )
58
- end
59
-
60
- private
61
-
62
- # @param anchor [String]
63
- # @return [String]
64
- def doctype(anchor)
65
- anchor&.include?("I-D") ? "internet-draft" : "rfc"
66
- end
67
-
68
- # @param reference [Nokogiri::XML::Element]
69
- # @param url [String]
70
- # @param ver [String, NilClass] Internet Draft version
71
- # @return [Array<Hash>]
72
- def link(reference, url, ver)
73
- l = []
74
- l << { type: "xml", content: url } if url
75
- l << { type: "src", content: reference[:target] } if reference[:target]
76
- if /^I-D/.match? reference[:anchor]
77
- reference.xpath("format").each do |f|
78
- c = ver ? f[:target].sub(/(?<=-)\d{2}(?=\.)/, ver) : f[:target]
79
- l << { type: f[:type], content: c }
80
- end
81
- end
82
- l
83
- end
84
-
85
- # @param attrs [Hash]
86
- # @return [RelatonIetf::IetfBibliographicItem]
87
- def ietf_item(**attrs)
88
- attrs[:fetched] = Date.today.to_s unless attrs.delete(:is_relation)
89
- attrs[:script] = ["Latn"]
90
- RelatonIetf::IetfBibliographicItem.new **attrs
91
- end
92
-
93
- # @param ref [String]
94
- # @param is_relation [Boolen, nil]
95
- # @return [RelatonIetf::IetfBibliographicItem]
96
- def rfc_item(ref, is_relation)
97
- /(?<=-)(?<ver>\d{2})$/ =~ ref
98
- if /^I-D/.match? ref
99
- ref.sub! /-\d{2}/, "" if ver
100
- ref.sub! /(?<=I-D\.)draft-/, ""
101
- end
102
-
103
- uri = "#{GH_URL}#{ref.sub(/\s|\u00a0/, '.')}.xml"
104
- doc = Nokogiri::XML get_page(uri)
105
- r = doc.at("/referencegroup", "/reference")
106
- fetch_rfc r, is_relation: is_relation, url: uri, ver: ver
107
- end
108
-
109
- # @param reference [Nokogiri::XML::Element]
110
- # @return [Hash]
111
- def relations(reference)
112
- reference.xpath("reference").map do |ref|
113
- { type: "includes", bibitem: fetch_rfc(ref, is_relation: true) }
114
- end
115
- end
116
-
117
- # @param uri [String]
118
- # @return [String] HTTP response body
119
- def get_page(uri)
120
- res = Net::HTTP.get_response(URI(uri))
121
- return unless res.code == "200"
122
-
123
- # raise RelatonBib::RequestError, "No document found at #{uri}"
124
- # end
125
-
126
- res.body
127
- end
128
-
129
- # @param reference [Nokogiri::XML::Element]
130
- # @return [String]
131
- def language(reference)
132
- reference[:lang] || "en"
133
- end
10
+ extend RelatonBib::BibXMLParser
11
+ extend Scrapper
134
12
 
135
- # @param reference [Nokogiri::XML::Element]
136
- # @return [Array<Hash>]
137
- def titles(reference)
138
- reference.xpath("./front/title").map do |title|
139
- { content: title.text, language: language(reference), script: "Latn" }
140
- end
141
- end
13
+ FLAVOR = "IETF"
142
14
 
143
- # @param reference [Nokogiri::XML::Element]
144
- # @return [RelatonBib::FormattedRef, nil]
145
- def formattedref(reference)
146
- return if reference.at "./fornt/title"
147
-
148
- cont = (reference[:anchor] || reference[:docName] || reference[:number])
149
- if cont
150
- RelatonBib::FormattedRef.new(
151
- content: cont, language: language(reference), script: "Latn",
152
- )
153
- end
154
- end
155
-
156
- # @param reference [Nokogiri::XML::Element]
157
- # @return [Array<RelatonBib::FormattedString>]
158
- def abstracts(ref)
159
- ref.xpath("./front/abstract").map do |a|
160
- RelatonBib::FormattedString.new(
161
- content: a.text.gsub(/\\n\\t{2,4}/, " ").strip,
162
- language: language(ref), script: "Latn"
163
- )
164
- end
165
- end
166
-
167
- # @param reference [Nokogiri::XML::Element]
168
- # @return [Array<Hash>]
169
- def contributors(reference)
170
- persons(reference) + organizations(reference)
171
- end
172
-
173
- # @param reference [Nokogiri::XML::Element]
174
- # @return [Array<Hash{Symbol=>RelatonBib::Person,Symbol=>Array<String>}>]
175
- def persons(reference)
176
- reference.xpath("./front/author[@surname]|./front/author[@fullname]")
177
- .map do |author|
178
- entity = RelatonBib::Person.new(
179
- name: full_name(author, reference),
180
- affiliation: [affiliation(author)],
181
- contact: contacts(author.at("./address")),
182
- )
183
- { entity: entity, role: [contributor_role(author)] }
184
- end
185
- end
186
-
187
- # @param reference [Nokogiri::XML::Element]
188
- # @return [Array<Hash{Symbol=>RelatonBib::Organization,
189
- # Symbol=>Array<String>}>]
190
- def organizations(reference)
191
- publisher = { entity: new_org, role: [type: "publisher"] }
192
- orgs = reference.xpath("./seriesinfo").reduce([publisher]) do |mem, si|
193
- next mem unless si[:stream]
194
-
195
- mem << { entity: new_org(si[:stream], nil), role: [type: "author"] }
196
- end
197
- orgs + reference.xpath(
198
- "front/author[not(@surname)][not(@fullname)]/organization",
199
- ).map do |org|
200
- { entity: new_org(org.text, nil), role: [type: "author"] }
201
- end
202
- end
203
-
204
- # @param author [Nokogiri::XML::Element]
205
- # @param ref [Nokogiri::XML::Element]
206
- # @return [RelatonBib::FullName]
207
- def full_name(author, ref)
208
- lang = language ref
209
- RelatonBib::FullName.new(
210
- completename: localized_string(author[:fullname], lang),
211
- initial: [localized_string(author[:initials], lang)].compact,
212
- surname: localized_string(author[:surname], lang),
213
- )
214
- end
215
-
216
- # @param content [String]
217
- # @param lang [String]
218
- # @return [RelatonBib::LocalizedString]
219
- def localized_string(content, lang)
220
- return unless content
221
-
222
- RelatonBib::LocalizedString.new(content, lang)
223
- end
224
-
225
- # @param postal [Nokogiri::XML::Element]
226
- # @return [Array<RelatonBib::Address, RelatonBib::Phone>]
227
- def contacts(addr)
228
- contacts = []
229
- return contacts unless addr
230
-
231
- postal = addr.at("./postal")
232
- contacts << address(postal) if postal
233
- add_contact(contacts, "phone", addr.at("./phone"))
234
- add_contact(contacts, "email", addr.at("./email"))
235
- add_contact(contacts, "uri", addr.at("./uri"))
236
- contacts
237
- end
238
-
239
- # @param postal [Nokogiri::XML::Element]
240
- # @rerurn [RelatonBib::Address]
241
- def address(postal) # rubocop:disable Metrics/CyclomaticComplexity
242
- RelatonBib::Address.new(
243
- street: [(postal.at("./postalLine") || postal.at("./street"))&.text],
244
- city: postal.at("./city")&.text,
245
- postcode: postal.at("./code")&.text,
246
- country: postal.at("./country")&.text,
247
- state: postal.at("./region")&.text,
248
- )
249
- end
250
-
251
- # @param type [String] allowed "phone", "email" or "uri"
252
- # @param value [String]
253
- def add_contact(contacts, type, value)
254
- return unless value
255
-
256
- contacts << RelatonBib::Contact.new(type: type, value: value.text)
257
- end
258
-
259
- # @param author [Nokogiri::XML::Element]
260
- # @return [RelatonBib::Affiliation]
261
- def affiliation(author)
262
- organization = author.at("./organization")
263
- org = if organization.nil? || organization&.text&.empty?
264
- new_org
265
- else
266
- new_org organization.text, organization[:abbrev]
267
- end
268
- RelatonBib::Affiliation.new organization: org
269
- end
270
-
271
- # @param name [String]
272
- # @param abbr [String]
273
- # @return [RelatonBib::Organization]
274
- def new_org(name = "Internet Engineering Task Force", abbr = "IETF")
275
- RelatonBib::Organization.new name: name, abbreviation: abbr
276
- end
277
-
278
- # @param author [Nokogiri::XML::Document]
279
- # @return [Hash]
280
- def contributor_role(author)
281
- { type: author[:role] || "author" }
282
- end
15
+ GH_URL = "https://raw.githubusercontent.com/relaton/relaton-data-ietf/master/data/reference."
283
16
 
284
- def month(mon)
285
- return 1 if !mon || mon.empty?
286
- return mon if /^\d+$/.match? mon
17
+ # @param text [String]
18
+ # @param is_relation [TrueClass, FalseClass]
19
+ # @return [RelatonIetf::IetfBibliographicItem]
20
+ def scrape_page(text, is_relation: false)
21
+ # Remove initial "IETF " string if specified
22
+ ref = text.gsub(/^IETF /, "")
23
+ /^(?:RFC|BCP|FYI|STD)\s(?<num>\d+)/ =~ ref
24
+ ref.sub!(/(?<=^(?:RFC|BCP|FYI|STD)\s)(\d+)/, num.rjust(4, "0")) if num
25
+ rfc_item ref, is_relation
26
+ rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
27
+ Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
28
+ Net::ProtocolError, SocketError
29
+ raise RelatonBib::RequestError, "No document found for #{ref} reference"
30
+ end
287
31
 
288
- Date::MONTHNAMES.index(mon)
32
+ # @param reference [Nokogiri::XML::Element, nil]
33
+ # @param is_relation [Boolean] don't add fetched date for relation
34
+ # @param url [String, NilClass]
35
+ # @param ver [String, NilClass] Internet Draft version
36
+ # @return [RelatonBib::tfBibliographicItem]
37
+ # def fetch_rfc(reference, is_relation: false, url: nil, ver: nil) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
38
+ # return unless reference
39
+
40
+ # hash = {
41
+ # id: reference[:anchor],
42
+ # type: "standard",
43
+ # docid: docids(reference, ver),
44
+ # status: status(reference),
45
+ # language: [language(reference)],
46
+ # script: ["Latn"],
47
+ # link: link(reference, url, ver),
48
+ # title: titles(reference),
49
+ # formattedref: formattedref(reference),
50
+ # abstract: abstracts(reference),
51
+ # contributor: contributors(reference),
52
+ # relation: relations(reference),
53
+ # date: dates(reference),
54
+ # series: series(reference),
55
+ # keyword: reference.xpath("front/keyword").map(&:text),
56
+ # doctype: doctype(reference[:anchor]),
57
+ # }
58
+ # hash[:fetched] = Date.today.to_s unless is_relation
59
+ # bib_item(**hash)
60
+ # end
61
+
62
+ private
63
+
64
+ # @param anchor [String]
65
+ # @return [String]
66
+ # def doctype(anchor)
67
+ # anchor&.include?("I-D") ? "internet-draft" : "rfc"
68
+ # end
69
+
70
+ # @param reference [Nokogiri::XML::Element]
71
+ # @param url [String]
72
+ # @param ver [String, NilClass] Internet Draft version
73
+ # @return [Array<Hash>]
74
+ # def link(reference, url, ver)
75
+ # l = []
76
+ # l << { type: "xml", content: url } if url
77
+ # l << { type: "src", content: reference[:target] } if reference[:target]
78
+ # if /^I-D/.match? reference[:anchor]
79
+ # reference.xpath("format").each do |f|
80
+ # c = ver ? f[:target].sub(/(?<=-)\d{2}(?=\.)/, ver) : f[:target]
81
+ # l << { type: f[:type], content: c }
82
+ # end
83
+ # end
84
+ # l
85
+ # end
86
+
87
+ # @param attrs [Hash]
88
+ # @return [RelatonIetf::IetfBibliographicItem]
89
+ def bib_item(**attrs)
90
+ unless attrs.delete(:is_relation)
91
+ attrs[:fetched] = Date.today.to_s
92
+ attrs[:place] = ["Fremont, CA"]
289
93
  end
94
+ RelatonIetf::IetfBibliographicItem.new(**attrs)
95
+ end
290
96
 
291
- #
292
- # Extract date from reference.
293
- #
294
- # @param reference [Nokogiri::XML::Element]
295
- # @return [Array<RelatonBib::BibliographicDate>] published data.
296
- #
297
- def dates(reference)
298
- return unless (date = reference.at "./front/date")
299
-
300
- d = [date[:year], month(date[:month]),
301
- (date[:day] || 1)].compact.join "-"
302
- date = Time.parse(d).strftime "%Y-%m-%d"
303
- [RelatonBib::BibliographicDate.new(type: "published", on: date)]
97
+ # @param ref [String]
98
+ # @param is_relation [Boolen, nil]
99
+ # @return [RelatonIetf::IetfBibliographicItem]
100
+ def rfc_item(ref, is_relation)
101
+ /(?<=-)(?<ver>\d{2})$/ =~ ref
102
+ if /^I-D/.match? ref
103
+ ref.sub!(/-\d{2}/, "") if ver
104
+ ref.sub!(/(?<=I-D\.)draft-/, "")
304
105
  end
305
106
 
306
- #
307
- # Extract document identifiers from reference
308
- #
309
- # @param reference [Nokogiri::XML::Element]
310
- # @param ver [String, NilClass] Internet Draft version
311
- #
312
- # @return [Array<RelatonBib::DocumentIdentifier>]
313
- #
314
- def docids(reference, ver) # rubocop:disable Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/AbcSize
315
- id = (reference[:anchor] || reference[:docName] || reference[:number])
316
- ret = []
317
- if id
318
- ret << RelatonBib::DocumentIdentifier.new(
319
- type: "IETF", id: id.sub(/^(RFC)/, "\\1 "),
320
- )
321
- end
322
- if (id = reference[:anchor])
323
- ret << RelatonBib::DocumentIdentifier.new(type: "rfc-anchor", id: id)
324
- end
325
- ret + reference.xpath("./seriesInfo").map do |si|
326
- next unless ["DOI", "Internet-Draft"].include? si[:name]
327
-
328
- id = si[:value]
329
- id.sub! /(?<=-)\d{2}$/, ver if ver && si[:name] == "Internet-Draft"
330
- RelatonBib::DocumentIdentifier.new(id: id, type: si[:name])
331
- end.compact
332
- end
107
+ uri = "#{GH_URL}#{ref.sub(/\s|\u00a0/, '.')}.xml"
108
+ # doc = Nokogiri::XML get_page(uri)
109
+ # r = doc.at("/referencegroup", "/reference")
110
+ # fetch_rfc r, is_relation: is_relation, url: uri, ver: ver
111
+ parse get_page(uri), url: uri, is_relation: is_relation, ver: ver
112
+ end
333
113
 
334
- #
335
- # Extract series form reference
336
- # @param reference [Nokogiri::XML::Element]
337
- #
338
- # @return [Array<RelatonBib::Series>]
339
- #
340
- def series(reference)
341
- reference.xpath("./seriesInfo").map do |si|
342
- next if si[:name] == "DOI" || si[:stream] || si[:status]
343
-
344
- RelatonBib::Series.new(
345
- title: RelatonBib::TypedTitleString.new(
346
- content: si[:name], language: language(reference), script: "Latn",
347
- ),
348
- number: si[:value],
349
- type: "main",
350
- )
351
- end.compact
352
- end
114
+ # @param reference [Nokogiri::XML::Element]
115
+ # @return [Hash]
116
+ # def relations(reference)
117
+ # reference.xpath("reference").map do |ref|
118
+ # { type: "includes", bibitem: fetch_rfc(ref, is_relation: true) }
119
+ # end
120
+ # end
121
+
122
+ # @param uri [String]
123
+ # @return [String] HTTP response body
124
+ def get_page(uri)
125
+ res = Net::HTTP.get_response(URI(uri))
126
+ return unless res.code == "200"
127
+
128
+ res.body
129
+ end
353
130
 
354
- #
355
- # extract status
356
- # @param reference [Nokogiri::XML::Element]
357
- #
358
- # @return [RelatonBib::DocumentStatus]
359
- #
360
- def status(reference)
361
- st = reference.at("./seriesinfo[@status]")
362
- return unless st
363
-
364
- RelatonBib::DocumentStatus.new(stage: st[:status])
365
- end
131
+ # @param [RelatonBib::WorkGroup]
132
+ # @return [RelatonIetf::Committee]
133
+ def committee(wgr)
134
+ Committee.new wgr
366
135
  end
136
+
137
+ # @param reference [Nokogiri::XML::Element]
138
+ # @return [String]
139
+ # def language(reference)
140
+ # reference[:lang] || "en"
141
+ # end
142
+
143
+ # @param reference [Nokogiri::XML::Element]
144
+ # @return [Array<Hash>]
145
+ # def titles(reference)
146
+ # reference.xpath("./front/title").map do |title|
147
+ # { content: title.text, language: language(reference), script: "Latn" }
148
+ # end
149
+ # end
150
+
151
+ # @param reference [Nokogiri::XML::Element]
152
+ # @return [RelatonBib::FormattedRef, nil]
153
+ # def formattedref(reference)
154
+ # return if reference.at "./front/title"
155
+
156
+ # cont = (reference[:anchor] || reference[:docName] || reference[:number])
157
+ # if cont
158
+ # RelatonBib::FormattedRef.new(
159
+ # content: cont, language: language(reference), script: "Latn",
160
+ # )
161
+ # end
162
+ # end
163
+
164
+ # @param reference [Nokogiri::XML::Element]
165
+ # @return [Array<RelatonBib::FormattedString>]
166
+ # def abstracts(ref)
167
+ # ref.xpath("./front/abstract").map do |a|
168
+ # RelatonBib::FormattedString.new(
169
+ # content: a.text.gsub(/\\n\\t{2,4}/, " ").strip,
170
+ # language: language(ref), script: "Latn"
171
+ # )
172
+ # end
173
+ # end
174
+
175
+ # @param reference [Nokogiri::XML::Element]
176
+ # @return [Array<Hash>]
177
+ # def contributors(reference)
178
+ # persons(reference) + organizations(reference)
179
+ # end
180
+
181
+ # @param reference [Nokogiri::XML::Element]
182
+ # @return [Array<Hash{Symbol=>RelatonBib::Person,Symbol=>Array<String>}>]
183
+ # def persons(reference)
184
+ # reference.xpath("./front/author[@surname]|./front/author[@fullname]")
185
+ # .map do |author|
186
+ # entity = RelatonBib::Person.new(
187
+ # name: full_name(author, reference),
188
+ # affiliation: [affiliation(author)],
189
+ # contact: contacts(author.at("./address")),
190
+ # )
191
+ # { entity: entity, role: [contributor_role(author)] }
192
+ # end
193
+ # end
194
+
195
+ # @param reference [Nokogiri::XML::Element]
196
+ # @return [Array<Hash{Symbol=>RelatonBib::Organization,
197
+ # Symbol=>Array<String>}>]
198
+ # def organizations(reference)
199
+ # publisher = { entity: new_org, role: [type: "publisher"] }
200
+ # orgs = reference.xpath("./seriesinfo").reduce([publisher]) do |mem, si|
201
+ # next mem unless si[:stream]
202
+
203
+ # mem << { entity: new_org(si[:stream], nil), role: [type: "author"] }
204
+ # end
205
+ # orgs + reference.xpath(
206
+ # "front/author[not(@surname)][not(@fullname)]/organization",
207
+ # ).map do |org|
208
+ # { entity: new_org(org.text, nil), role: [type: "author"] }
209
+ # end
210
+ # end
211
+
212
+ # @param author [Nokogiri::XML::Element]
213
+ # @param ref [Nokogiri::XML::Element]
214
+ # @return [RelatonBib::FullName]
215
+ # def full_name(author, ref)
216
+ # lang = language ref
217
+ # RelatonBib::FullName.new(
218
+ # completename: localized_string(author[:fullname], lang),
219
+ # initial: [localized_string(author[:initials], lang)].compact,
220
+ # surname: localized_string(author[:surname], lang),
221
+ # )
222
+ # end
223
+
224
+ # @param content [String]
225
+ # @param lang [String]
226
+ # @return [RelatonBib::LocalizedString]
227
+ # def localized_string(content, lang)
228
+ # return unless content
229
+
230
+ # RelatonBib::LocalizedString.new(content, lang)
231
+ # end
232
+
233
+ # @param postal [Nokogiri::XML::Element]
234
+ # @return [Array<RelatonBib::Address, RelatonBib::Phone>]
235
+ # def contacts(addr)
236
+ # contacts = []
237
+ # return contacts unless addr
238
+
239
+ # postal = addr.at("./postal")
240
+ # contacts << address(postal) if postal
241
+ # add_contact(contacts, "phone", addr.at("./phone"))
242
+ # add_contact(contacts, "email", addr.at("./email"))
243
+ # add_contact(contacts, "uri", addr.at("./uri"))
244
+ # contacts
245
+ # end
246
+
247
+ # @param postal [Nokogiri::XML::Element]
248
+ # @rerurn [RelatonBib::Address]
249
+ # def address(postal) # rubocop:disable Metrics/CyclomaticComplexity
250
+ # RelatonBib::Address.new(
251
+ # street: [(postal.at("./postalLine") || postal.at("./street"))&.text],
252
+ # city: postal.at("./city")&.text,
253
+ # postcode: postal.at("./code")&.text,
254
+ # country: postal.at("./country")&.text,
255
+ # state: postal.at("./region")&.text,
256
+ # )
257
+ # end
258
+
259
+ # @param type [String] allowed "phone", "email" or "uri"
260
+ # @param value [String]
261
+ # def add_contact(contacts, type, value)
262
+ # return unless value
263
+
264
+ # contacts << RelatonBib::Contact.new(type: type, value: value.text)
265
+ # end
266
+
267
+ # @param author [Nokogiri::XML::Element]
268
+ # @return [RelatonBib::Affiliation]
269
+ # def affiliation(author)
270
+ # organization = author.at("./organization")
271
+ # org = if organization.nil? || organization&.text&.empty?
272
+ # new_org
273
+ # else
274
+ # new_org organization.text, organization[:abbrev]
275
+ # end
276
+ # RelatonBib::Affiliation.new organization: org
277
+ # end
278
+
279
+ # @param name [String]
280
+ # @param abbr [String]
281
+ # @return [RelatonBib::Organization]
282
+ # def new_org(name = "Internet Engineering Task Force", abbr = "IETF")
283
+ # RelatonBib::Organization.new name: name, abbreviation: abbr
284
+ # end
285
+
286
+ # @param author [Nokogiri::XML::Document]
287
+ # @return [Hash]
288
+ # def contributor_role(author)
289
+ # { type: author[:role] || "author" }
290
+ # end
291
+
292
+ # def month(mon)
293
+ # return 1 if !mon || mon.empty?
294
+ # return mon if /^\d+$/.match? mon
295
+
296
+ # Date::MONTHNAMES.index(mon)
297
+ # end
298
+
299
+ #
300
+ # Extract date from reference.
301
+ #
302
+ # @param reference [Nokogiri::XML::Element]
303
+ # @return [Array<RelatonBib::BibliographicDate>] published data.
304
+ #
305
+ # def dates(reference)
306
+ # return unless (date = reference.at "./front/date")
307
+
308
+ # d = [date[:year], month(date[:month]),
309
+ # (date[:day] || 1)].compact.join "-"
310
+ # date = Time.parse(d).strftime "%Y-%m-%d"
311
+ # [RelatonBib::BibliographicDate.new(type: "published", on: date)]
312
+ # end
313
+
314
+ #
315
+ # Extract document identifiers from reference
316
+ #
317
+ # @param reference [Nokogiri::XML::Element]
318
+ # @param ver [String, NilClass] Internet Draft version
319
+ #
320
+ # @return [Array<RelatonBib::DocumentIdentifier>]
321
+ #
322
+ # def docids(reference, ver) # rubocop:disable Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/AbcSize
323
+ # id = (reference[:anchor] || reference[:docName] || reference[:number])
324
+ # ret = []
325
+ # if id
326
+ # ret << RelatonBib::DocumentIdentifier.new(
327
+ # type: "IETF", id: id.sub(/^(RFC)/, "\\1 "),
328
+ # )
329
+ # end
330
+ # if (id = reference[:anchor])
331
+ # ret << RelatonBib::DocumentIdentifier.new(type: "rfc-anchor", id: id)
332
+ # end
333
+ # names = ["DOI", "Internet-Draft"]
334
+ # ret + reference.xpath("./seriesInfo").map do |si|
335
+ # next unless names.include? si[:name]
336
+
337
+ # id = si[:value]
338
+ # id.sub!(/(?<=-)\d{2}$/, ver) if ver && si[:name] == "Internet-Draft"
339
+ # RelatonBib::DocumentIdentifier.new(id: id, type: si[:name])
340
+ # end.compact
341
+ # end
342
+
343
+ #
344
+ # Extract series form reference
345
+ # @param reference [Nokogiri::XML::Element]
346
+ #
347
+ # @return [Array<RelatonBib::Series>]
348
+ #
349
+ # def series(reference)
350
+ # reference.xpath("./seriesInfo").map do |si|
351
+ # next if si[:name] == "DOI" || si[:stream] || si[:status]
352
+
353
+ # RelatonBib::Series.new(
354
+ # title: RelatonBib::TypedTitleString.new(
355
+ # content: si[:name], language: language(reference), script: "Latn",
356
+ # ),
357
+ # number: si[:value],
358
+ # type: "main",
359
+ # )
360
+ # end.compact
361
+ # end
362
+
363
+ #
364
+ # extract status
365
+ # @param reference [Nokogiri::XML::Element]
366
+ #
367
+ # @return [RelatonBib::DocumentStatus]
368
+ #
369
+ # def status(reference)
370
+ # st = reference.at("./seriesinfo[@status]")
371
+ # return unless st
372
+
373
+ # RelatonBib::DocumentStatus.new(stage: st[:status])
374
+ # end
367
375
  end
368
- # rubocop:enable Metrics/ModuleLength
369
376
  end
@@ -1,3 +1,3 @@
1
1
  module RelatonIetf
2
- VERSION = "1.9.0".freeze
2
+ VERSION = "1.9.1".freeze
3
3
  end
@@ -9,7 +9,7 @@ module RelatonIetf
9
9
  # @param item_hash [Hash]
10
10
  # @return [RelatonIetf::IetfBibliographicItem]
11
11
  def bib_item(item_hash)
12
- IetfBibliographicItem.new **item_hash
12
+ IetfBibliographicItem.new(**item_hash)
13
13
  end
14
14
  end
15
15
  end
data/lib/relaton_ietf.rb CHANGED
@@ -5,6 +5,7 @@ require "relaton_ietf/ietf_bibliography"
5
5
  require "relaton_ietf/ietf_bibliographic_item"
6
6
  require "relaton_ietf/xml_parser"
7
7
  require "relaton_ietf/hash_converter"
8
+ require "relaton_ietf/committee"
8
9
 
9
10
  require "relaton/provider_ietf"
10
11
 
data/relaton_ietf.gemspec CHANGED
@@ -38,5 +38,5 @@ Gem::Specification.new do |spec|
38
38
  spec.add_development_dependency "vcr"
39
39
  spec.add_development_dependency "webmock"
40
40
 
41
- spec.add_dependency "relaton-bib", "~> 1.9.0"
41
+ spec.add_dependency "relaton-bib", ">= 1.9.5"
42
42
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: relaton-ietf
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.0
4
+ version: 1.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-26 00:00:00.000000000 Z
11
+ date: 2021-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: equivalent-xml
@@ -126,16 +126,16 @@ dependencies:
126
126
  name: relaton-bib
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - "~>"
129
+ - - ">="
130
130
  - !ruby/object:Gem::Version
131
- version: 1.9.0
131
+ version: 1.9.5
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - "~>"
136
+ - - ">="
137
137
  - !ruby/object:Gem::Version
138
- version: 1.9.0
138
+ version: 1.9.5
139
139
  description: "RelatonIetf: retrieve IETF Standards for bibliographic use \nusing the
140
140
  BibliographicItem model.\n\nFormerly known as rfcbib.\n"
141
141
  email:
@@ -163,6 +163,7 @@ files:
163
163
  - grammars/reqt.rng
164
164
  - lib/relaton/provider_ietf.rb
165
165
  - lib/relaton_ietf.rb
166
+ - lib/relaton_ietf/committee.rb
166
167
  - lib/relaton_ietf/hash_converter.rb
167
168
  - lib/relaton_ietf/ietf_bibliographic_item.rb
168
169
  - lib/relaton_ietf/ietf_bibliography.rb