relaton-ietf 1.8.0 → 1.9.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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