relaton-ietf 1.8.0 → 1.9.3

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.
@@ -5,365 +5,373 @@ 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
15
+ GH_URL = "https://raw.githubusercontent.com/relaton/relaton-data-ietf/master/data/reference."
270
16
 
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
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
277
31
 
278
- # @param author [Nokogiri::XML::Document]
279
- # @return [Hash]
280
- def contributor_role(author)
281
- { type: author[:role] || "author" }
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"]
282
93
  end
94
+ RelatonIetf::IetfBibliographicItem.new(**attrs)
95
+ end
283
96
 
284
- def month(mon)
285
- return 1 if !mon || mon.empty?
286
- return mon if /^\d+$/.match? mon
287
-
288
- Date::MONTHNAMES.index(mon)
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-/, "")
289
105
  end
290
106
 
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)]
304
- 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
305
113
 
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
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
333
130
 
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
131
+ # @param [RelatonBib::WorkGroup]
132
+ # @return [RelatonIetf::Committee]
133
+ def committee(wgr)
134
+ Committee.new wgr
135
+ end
353
136
 
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
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
+ [{ entity: new_org("Internet Engineering Task Force", "IETF"), role: [type: "publisher"] }] + super
179
+ # persons(reference) + organizations(reference)
366
180
  end
181
+
182
+ # @param reference [Nokogiri::XML::Element]
183
+ # @return [Array<Hash{Symbol=>RelatonBib::Person,Symbol=>Array<String>}>]
184
+ # def persons(reference)
185
+ # reference.xpath("./front/author[@surname]|./front/author[@fullname]")
186
+ # .map do |author|
187
+ # entity = RelatonBib::Person.new(
188
+ # name: full_name(author, reference),
189
+ # affiliation: affiliation(author),
190
+ # contact: contacts(author.at("./address")),
191
+ # )
192
+ # { entity: entity, role: [contributor_role(author)] }
193
+ # end
194
+ # end
195
+
196
+ # @param reference [Nokogiri::XML::Element]
197
+ # @return [Array<Hash{Symbol=>RelatonBib::Organization,
198
+ # Symbol=>Array<String>}>]
199
+ # def organizations(reference)
200
+ # publisher = { entity: new_org, role: [type: "publisher"] }
201
+ # orgs = reference.xpath("./seriesinfo").reduce([publisher]) do |mem, si|
202
+ # next mem unless si[:stream]
203
+
204
+ # mem << { entity: new_org(si[:stream], nil), role: [type: "author"] }
205
+ # end
206
+ # orgs + reference.xpath(
207
+ # "front/author[not(@surname)][not(@fullname)]/organization",
208
+ # ).map do |org|
209
+ # { entity: new_org(org.text, nil), role: [type: "author"] }
210
+ # end
211
+ # end
212
+
213
+ # @param author [Nokogiri::XML::Element]
214
+ # @param ref [Nokogiri::XML::Element]
215
+ # @return [RelatonBib::FullName]
216
+ # def full_name(author, ref)
217
+ # lang = language ref
218
+ # RelatonBib::FullName.new(
219
+ # completename: localized_string(author[:fullname], lang),
220
+ # initial: [localized_string(author[:initials], lang)].compact,
221
+ # surname: localized_string(author[:surname], lang),
222
+ # )
223
+ # end
224
+
225
+ # @param content [String]
226
+ # @param lang [String]
227
+ # @return [RelatonBib::LocalizedString]
228
+ # def localized_string(content, lang)
229
+ # return unless content
230
+
231
+ # RelatonBib::LocalizedString.new(content, lang)
232
+ # end
233
+
234
+ # @param postal [Nokogiri::XML::Element]
235
+ # @return [Array<RelatonBib::Address, RelatonBib::Phone>]
236
+ # def contacts(addr)
237
+ # contacts = []
238
+ # return contacts unless addr
239
+
240
+ # postal = addr.at("./postal")
241
+ # contacts << address(postal) if postal
242
+ # add_contact(contacts, "phone", addr.at("./phone"))
243
+ # add_contact(contacts, "email", addr.at("./email"))
244
+ # add_contact(contacts, "uri", addr.at("./uri"))
245
+ # contacts
246
+ # end
247
+
248
+ # @param postal [Nokogiri::XML::Element]
249
+ # @rerurn [RelatonBib::Address]
250
+ # def address(postal) # rubocop:disable Metrics/CyclomaticComplexity
251
+ # RelatonBib::Address.new(
252
+ # street: [(postal.at("./postalLine") || postal.at("./street"))&.text],
253
+ # city: postal.at("./city")&.text,
254
+ # postcode: postal.at("./code")&.text,
255
+ # country: postal.at("./country")&.text,
256
+ # state: postal.at("./region")&.text,
257
+ # )
258
+ # end
259
+
260
+ # @param type [String] allowed "phone", "email" or "uri"
261
+ # @param value [String]
262
+ # def add_contact(contacts, type, value)
263
+ # return unless value
264
+
265
+ # contacts << RelatonBib::Contact.new(type: type, value: value.text)
266
+ # end
267
+
268
+ # @param author [Nokogiri::XML::Element]
269
+ # @return [RelatonBib::Affiliation]
270
+ # def affiliation(author)
271
+ # organization = author.at("./organization")
272
+ # org = if organization.nil? || organization&.text&.empty?
273
+ # new_org
274
+ # else
275
+ # new_org organization.text, organization[:abbrev]
276
+ # end
277
+ # RelatonBib::Affiliation.new organization: org
278
+ # end
279
+
280
+ # @param name [String]
281
+ # @param abbr [String]
282
+ # @return [RelatonBib::Organization]
283
+ # def new_org(name = "Internet Engineering Task Force", abbr = "IETF")
284
+ # RelatonBib::Organization.new name: name, abbreviation: abbr
285
+ # end
286
+
287
+ # @param author [Nokogiri::XML::Document]
288
+ # @return [Hash]
289
+ # def contributor_role(author)
290
+ # { type: author[:role] || "author" }
291
+ # end
292
+
293
+ # def month(mon)
294
+ # return 1 if !mon || mon.empty?
295
+ # return mon if /^\d+$/.match? mon
296
+
297
+ # Date::MONTHNAMES.index(mon)
298
+ # end
299
+
300
+ #
301
+ # Extract date from reference.
302
+ #
303
+ # @param reference [Nokogiri::XML::Element]
304
+ # @return [Array<RelatonBib::BibliographicDate>] published data.
305
+ #
306
+ # def dates(reference)
307
+ # return unless (date = reference.at "./front/date")
308
+
309
+ # d = [date[:year], month(date[:month]),
310
+ # (date[:day] || 1)].compact.join "-"
311
+ # date = Time.parse(d).strftime "%Y-%m-%d"
312
+ # [RelatonBib::BibliographicDate.new(type: "published", on: date)]
313
+ # end
314
+
315
+ #
316
+ # Extract document identifiers from reference
317
+ #
318
+ # @param reference [Nokogiri::XML::Element]
319
+ # @param ver [String, NilClass] Internet Draft version
320
+ #
321
+ # @return [Array<RelatonBib::DocumentIdentifier>]
322
+ #
323
+ # def docids(reference, ver) # rubocop:disable Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/AbcSize
324
+ # id = (reference[:anchor] || reference[:docName] || reference[:number])
325
+ # ret = []
326
+ # if id
327
+ # ret << RelatonBib::DocumentIdentifier.new(
328
+ # type: "IETF", id: id.sub(/^(RFC)/, "\\1 "),
329
+ # )
330
+ # end
331
+ # if (id = reference[:anchor])
332
+ # ret << RelatonBib::DocumentIdentifier.new(type: "rfc-anchor", id: id)
333
+ # end
334
+ # names = ["DOI", "Internet-Draft"]
335
+ # ret + reference.xpath("./seriesInfo").map do |si|
336
+ # next unless names.include? si[:name]
337
+
338
+ # id = si[:value]
339
+ # id.sub!(/(?<=-)\d{2}$/, ver) if ver && si[:name] == "Internet-Draft"
340
+ # RelatonBib::DocumentIdentifier.new(id: id, type: si[:name])
341
+ # end.compact
342
+ # end
343
+
344
+ #
345
+ # Extract series form reference
346
+ # @param reference [Nokogiri::XML::Element]
347
+ #
348
+ # @return [Array<RelatonBib::Series>]
349
+ #
350
+ # def series(reference)
351
+ # reference.xpath("./seriesInfo").map do |si|
352
+ # next if si[:name] == "DOI" || si[:stream] || si[:status]
353
+
354
+ # RelatonBib::Series.new(
355
+ # title: RelatonBib::TypedTitleString.new(
356
+ # content: si[:name], language: language(reference), script: "Latn",
357
+ # ),
358
+ # number: si[:value],
359
+ # type: "main",
360
+ # )
361
+ # end.compact
362
+ # end
363
+
364
+ #
365
+ # extract status
366
+ # @param reference [Nokogiri::XML::Element]
367
+ #
368
+ # @return [RelatonBib::DocumentStatus]
369
+ #
370
+ # def status(reference)
371
+ # st = reference.at("./seriesinfo[@status]")
372
+ # return unless st
373
+
374
+ # RelatonBib::DocumentStatus.new(stage: st[:status])
375
+ # end
367
376
  end
368
- # rubocop:enable Metrics/ModuleLength
369
377
  end