relaton-doi 1.14.1 → 1.14.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 53cd51733991e0f69cc3d0323cd9dff42122523c3a8f2d8e2738b1408da5321b
4
- data.tar.gz: 7de2c0a2b3fa4369a832eaf1d655349bfe1682d86fc833da07be0243fadb7602
3
+ metadata.gz: 8c74297f60135d99153e2e5f7f3c4a1acb3945b43fbcc26868bf900b2e9ec3c0
4
+ data.tar.gz: 6c241a6fc93c87a1751bde8772752c859ee9a000c04729ddc3910386c4827d66
5
5
  SHA512:
6
- metadata.gz: 4981dfeb396011af9fa1773f565009306664828231709d0e9d8ffa939f8e6f170dd09b4fe0793a5abbbcea07d024444737359a21e4e433c1b191f97fa245fc24
7
- data.tar.gz: d599da84e5f7a0468decc094d449e7223dd63b5ff4a615993f34c882f43572fa9bb2287411228de21fc60c37c8c1b3572ae207b142335d4f618c6f8ad0d748c8
6
+ metadata.gz: 74ef5db4deb7ff21ba09e5caa2e98c051549e81fa6d0ea1249787767d19d3cb10af911e1c51a11d6cf965fc856e2cdd7d6538b0eea19200bc43782f707550521
7
+ data.tar.gz: 7b13cd9e6f765f3f0e2fff5c703ae24c9b4c3b98c96a2138b46cb0a969ee64431390a5551696c2a5a2b00b1581b3910988ef3ee40da3a7ad6527174e1660bfc0
data/Gemfile CHANGED
@@ -10,3 +10,5 @@ gem "rake", "~> 13.0"
10
10
  gem "rspec", "~> 3.0"
11
11
 
12
12
  gem "rubocop", "~> 1.7"
13
+
14
+ gem "debug"
@@ -1,53 +1,6 @@
1
1
  module RelatonDoi
2
- class Crossref
3
- TYPES = {
4
- "book-chapter" => "inbook",
5
- "book-part" => "inbook",
6
- "book-section" => "inbook",
7
- "book-series" => "book",
8
- "book-set" => "book",
9
- "book-track" => "inbook",
10
- "component" => "misc",
11
- "database" => "dataset",
12
- "dissertation" => "thesis",
13
- "edited-book" => "book",
14
- "grant" => "misc",
15
- "journal-article" => "article",
16
- "journal-issue" => "journal",
17
- "journal-volume" => "journal",
18
- "monograph" => "book",
19
- "other" => "misc",
20
- "peer-review" => "article",
21
- "posted-content" => "social_media",
22
- "proceedings-article" => "inproceedings",
23
- "proceedings-series" => "proceedings",
24
- "reference-book" => "book",
25
- "reference-entry" => "inbook",
26
- "report-component" => "techreport",
27
- "report-series" => "techreport",
28
- "report" => "techreport",
29
- }.freeze
30
-
31
- REALATION_TYPES = {
32
- "is-preprint-of" => "reprintOf",
33
- "is-review-of" => "reviewOf",
34
- "has-review" => "hasReview",
35
- "is-identical-to" => "identicalTo", # ?
36
- "is-supplement-to" => "complements",
37
- }.freeze
38
-
39
- #
40
- # Get a document by DOI from the CrossRef API.
41
- #
42
- # @param [String] doi The DOI.
43
- #
44
- # @return [RelatonBib::BibliographicItem, RelatonIetf::IetfBibliographicItem,
45
- # RelatonBipm::BipmBibliographicItem, RelatonIeee::IeeeBibliographicItem,
46
- # RelatonNist::NistBibliographicItem] The bibitem.
47
- #
48
- def self.get(doi)
49
- new.get doi
50
- end
2
+ module Crossref
3
+ extend self
51
4
 
52
5
  #
53
6
  # Get a document by DOI from the CrossRef API.
@@ -61,356 +14,21 @@ module RelatonDoi
61
14
  def get(doi)
62
15
  warn "[relaton-doi] [\"#{doi}\"] fetching..."
63
16
  id = doi.sub(%r{^doi:}, "")
64
- resp = Serrano.works ids: id
65
- @message = resp[0]["message"]
66
- warn "[relaton-doi] [\"#{doi}\"] found #{@message['DOI']}"
67
- create_bibitem @message["DOI"], bibitem_hash
68
- end
69
-
70
- #
71
- # Create a bibitem from the bibitem hash.
72
- #
73
- # @param [String] doi The DOI.
74
- # @param [Hash] bibitem The bibitem hash.
75
- #
76
- # @return [RelatonBib::BibliographicItem, RelatonIetf::IetfBibliographicItem,
77
- # RelatonBipm::BipmBibliographicItem, RelatonIeee::IeeeBibliographicItem,
78
- # RelatonNist::NistBibliographicItem] The bibitem.
79
- #
80
- # @raise [RelatonDoi::Error] if the document type is not supported.
81
- #
82
- def create_bibitem(doi, bibitem) # rubocop:disable Metrics/CyclomaticComplexity
83
- # case @message["institution"]&.first&.fetch("acronym")&.first
84
- case doi
85
- when /\/nist/ then RelatonNist::NistBibliographicItem.new(**bibitem)
86
- when /\/rfc\d+/ then RelatonIetf::IetfBibliographicItem.new(**bibitem)
87
- when /\/0026-1394\// then RelatonBipm::BipmBibliographicItem.new(**bibitem)
88
- # when "ISO" then RelatonIso::IsoBibliographicItem.new(**bibitem)
89
- # when "W3C" then RelatonW3c::W3cBibliographicItem.new(**bibitem)
90
- when /\/ieee/ then RelatonIeee::IeeeBibliographicItem.new(**bibitem)
91
- else RelatonBib::BibliographicItem.new(**bibitem)
92
- end
93
- end
94
-
95
- #
96
- # Create a bibitem hash from the message hash.
97
- #
98
- # @return [Hash] The bibitem hash.
99
- #
100
- def bibitem_hash # rubocop:disable Metrics/MethodLength
101
- {
102
- type: parse_type,
103
- fetched: Date.today.to_s,
104
- title: create_title,
105
- docid: create_docid,
106
- date: create_date,
107
- link: create_link,
108
- abstract: create_abstract,
109
- contributor: create_contributors,
110
- doctype: @message["type"],
111
- place: create_place,
112
- relation: create_relation,
113
- extent: create_extent,
114
- }
115
- end
116
-
117
- #
118
- # Parse the document type.
119
- #
120
- # @return [String] The document type.
121
- #
122
- def parse_type
123
- TYPES[@message["type"]] || @message["type"]
124
- end
125
-
126
- #
127
- # Create a title and a subtitle from the message hash.
128
- #
129
- # @return [Array<RelatonBib::TypedTitleString>] The title and subtitle.
130
- #
131
- def create_title
132
- @message["title"].map do |t|
133
- RelatonBib::TypedTitleString.new(
134
- type: "main", content: t, language: "en", script: "Latn",
135
- )
136
- end + @message["subtitle"].map do |t|
137
- RelatonBib::TypedTitleString.new(
138
- type: "subtitle", content: t, language: "en", script: "Latn",
139
- )
140
- end
141
- end
142
-
143
- #
144
- # Create a docid from the message hash.
145
- #
146
- # @return [Array<RelatonBib::DocumentIdentifier>] The docid.
147
- #
148
- def create_docid
149
- %w[DOI ISBN].each_with_object([]) do |type, obj|
150
- id = @message[type].is_a?(Array) ? @message[type].first : @message[type]
151
- next unless id
152
-
153
- primary = type == "DOI"
154
- obj << RelatonBib::DocumentIdentifier.new(type: type, id: id, primary: primary)
155
- end
156
- end
157
-
158
- #
159
- # Create dates from the message hash.
160
- #
161
- # @return [Array<RelatonBib::BibliographicDate>] The dates.
162
- #
163
- def create_date
164
- %w[created issued published approved].each_with_object([]) do |type, obj|
165
- next unless @message[type]
166
-
167
- on = @message[type]["date-parts"][0].map { |d| d.to_s.rjust(2, "0") }.join "-"
168
- obj << RelatonBib::BibliographicDate.new(type: type, on: on)
169
- end
170
- end
171
-
172
- #
173
- # Create a link from the message hash.
174
- #
175
- # @return [Array<RelatonBib::TypedUri>] The link.
176
- #
177
- def create_link
178
- links = []
179
- if @message["URL"]
180
- links << RelatonBib::TypedUri.new(type: "DOI", content: @message["URL"])
181
- end
182
- return links unless @message["link"]&.any?
183
-
184
- link = @message["link"].first
185
- if link["URL"].match?(/\.pdf$/)
186
- links << RelatonBib::TypedUri.new(type: "pdf", content: link["URL"])
187
- end
188
- links
17
+ message = get_by_id id
18
+ warn "[relaton-doi] [\"#{doi}\"] found #{message['DOI']}"
19
+ Parser.parse message
189
20
  end
190
21
 
191
22
  #
192
- # Create an abstract from the message hash.
193
- #
194
- # @return [Array<RelatonBib::FormattedString>] The abstract.
195
- #
196
- def create_abstract
197
- return [] unless @message["abstract"]
198
-
199
- content = @message["abstract"]
200
- abstract = RelatonBib::FormattedString.new(
201
- content: content, language: "en", script: "Latn", format: "text/html",
202
- )
203
- [abstract]
204
- end
205
-
206
- #
207
- # Create contributors from the message hash.
208
- #
209
- # @return [Array<RelatonBib::ContributionInfo>] The contributors.
210
- #
211
- def create_contributors # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
212
- contribs = %w[author editor translator].each_with_object([]) do |type, obj|
213
- @message[type]&.each do |contrib|
214
- obj << contributor(person(contrib), type)
215
- end
216
- end
217
- contribs += fetch_editors if contribs.none? { |e| e.role.any? { |r| r.type == "editor" } }
218
- contribs << contributor(org_publisher, "publisher")
219
- end
220
-
221
- #
222
- # Fetch editors from Crossref.
223
- #
224
- # @return [Array<RelatonBib::ContributionInfo>] The editors.
225
- #
226
- def fetch_editors # rubocop:disable Metrics/AbcSize
227
- title = @message["container-title"].first
228
- year = (@message["published"] || @message["approved"])["date-parts"][0][0]
229
- query = "#{title}, #{@message['publisher']}, #{@message['publisher-location']}, #{year}"
230
- resp = Faraday.get %{http://api.crossref.org/works?query.bibliographic="#{query}"&rows=5&filter=type:book}
231
- json = JSON.parse resp.body
232
- item = json["message"]["items"].detect { |i| i["title"].include?(title) && i["editor"] }
233
- return [] unless item
234
-
235
- item["editor"].map { |a| contributor(person(a), "editor") }
236
- end
237
-
238
- #
239
- # Cerate an organization publisher from the message hash.
240
- #
241
- # @return [RelatonBib::Organization] The organization.
242
- #
243
- def org_publisher
244
- pbr = @message["institution"]&.detect do |i|
245
- @message["publisher"].include?(i["name"]) ||
246
- i["name"].include?(@message["publisher"])
247
- end
248
- a = pbr["acronym"]&.first if pbr
249
- RelatonBib::Organization.new name: @message["publisher"], abbreviation: a
250
- end
251
-
252
- #
253
- # Create contributor from an entity and a role type.
254
- #
255
- # @param [RelatonBib::Person, RelatonBib::Organization] entity The entity.
256
- # @param [String] type The role type.
257
- #
258
- # @return [RelatonBib::ContributionInfo] The contributor.
259
- #
260
- def contributor(entity, type)
261
- RelatonBib::ContributionInfo.new(entity: entity, role: [type: type])
262
- end
263
-
264
- #
265
- # Create a person from a person hash.
266
- #
267
- # @param [Hash] person The person hash.
268
- #
269
- # @return [RelatonBib::Person] The person.
270
- #
271
- def person(person)
272
- RelatonBib::Person.new(
273
- name: person_name(person), affiliation: affiliation(person),
274
- identifier: person_id(person)
275
- )
276
- end
277
-
278
- #
279
- # Create person affiliations from a person hash.
280
- #
281
- # @param [Hash] person The person hash.
282
- #
283
- # @return [Array<RelatonBib::Affiliation>] The affiliations.
284
- #
285
- def affiliation(person)
286
- (person["affiliation"] || []).map do |a|
287
- org = RelatonBib::Organization.new(name: a["name"])
288
- RelatonBib::Affiliation.new organization: org
289
- end
290
- end
291
-
292
- #
293
- # Create a person full name from a person hash.
294
- #
295
- # @param [Hash] person The person hash.
296
- #
297
- # @return [RelatonBib::FullName] The full name.
298
- #
299
- def person_name(person)
300
- sn = RelatonBib::LocalizedString.new(person["family"], "en", "Latn")
301
- RelatonBib::FullName.new(
302
- surname: sn, forename: forename(person), addition: nameaddition(person),
303
- completename: completename(person), prefix: nameprefix(person)
304
- )
305
- end
306
-
307
- #
308
- # Create a person name prefix from a person hash.
309
- #
310
- # @param [Hash] person The person hash.
311
- #
312
- # @return [Array<RelatonBib::LocalizedString>] The name prefix.
313
- #
314
- def nameprefix(person)
315
- return [] unless person["prefix"]
316
-
317
- [RelatonBib::LocalizedString.new(person["prefix"], "en", "Latn")]
318
- end
319
-
320
- #
321
- # Create a complete name from a person hash.
322
- #
323
- # @param [Hash] person The person hash.
324
- #
325
- # @return [RelatonBib::LocalizedString] The complete name.
326
- #
327
- def completename(person)
328
- return unless person["name"]
329
-
330
- RelatonBib::LocalizedString.new(person["name"], "en", "Latn")
331
- end
332
-
333
- #
334
- # Create a forename from a person hash.
335
- #
336
- # @param [Hash] person The person hash.
337
- #
338
- # @return [Array<RelatonBib::LocalizedString>] The forename.
339
- #
340
- def forename(person)
341
- return [] unless person["given"]
342
-
343
- [RelatonBib::Forename.new(content: person["given"], language: "en", script: "Latn")]
344
- end
345
-
346
- #
347
- # Create an addition from a person hash.
348
- #
349
- # @param [Hash] person The person hash.
350
- #
351
- # @return [Array<RelatonBib::LocalizedString>] The addition.
352
- #
353
- def nameaddition(person)
354
- return [] unless person["suffix"]
355
-
356
- [RelatonBib::LocalizedString.new(person["suffix"], "en", "Latn")]
357
- end
358
-
359
- #
360
- # Create a person identifier from a person hash.
361
- #
362
- # @param [Hash] person The person hash.
363
- #
364
- # @return [Array<RelatonBib::PersonIdentifier>] The person identifier.
365
- #
366
- def person_id(person)
367
- return [] unless person["ORCID"]
368
-
369
- [RelatonBib::PersonIdentifier.new("orcid", person["ORCID"])]
370
- end
371
-
372
- #
373
- # Create a place from the message hash.
374
- #
375
- # @return [Array<RelatonBib::Place>] The place.
376
- #
377
- def create_place
378
- return [] unless @message["publisher-location"]
379
-
380
- city, rg = @message["publisher-location"].split(", ")
381
- region = RelatonBib::Place::RegionType.new(name: rg)
382
- [RelatonBib::Place.new(city: city, region: [region])]
383
- end
384
-
385
- #
386
- # Crerate relations from the message hash.
387
- #
388
- # @return [Array<RelatonBib::DocumentRelation>] The relations.
389
- #
390
- def create_relation # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
391
- rels = []
392
- @message["container-title"]&.each do |ct|
393
- bib = RelatonBib::BibliographicItem.new(title: [content: ct])
394
- rels << RelatonBib::DocumentRelation.new(type: "includedIn", bibitem: bib)
395
- end
396
- @message["relation"].each_with_object(rels) do |(k, v), a|
397
- fref = RelatonBib::FormattedRef.new(content: v["id"])
398
- bib = create_bibitem v["id"], formattedref: fref
399
- type = REALATION_TYPES[k] || k
400
- a << RelatonBib::DocumentRelation.new(type: type, bibitem: bib)
401
- end
402
- end
403
-
23
+ # Get a document by DOI from the CrossRef API.
404
24
  #
405
- # Create an extent from the message hash.
25
+ # @param [String] id The DOI.
406
26
  #
407
- # @return [Array<RelatonBib::Locality>] The extent.
27
+ # @return [Hash] The document.
408
28
  #
409
- def create_extent
410
- return [] unless @message["page"]
411
-
412
- from, to = @message["page"].split("-")
413
- [RelatonBib::Locality.new("page", from, to)]
29
+ def get_by_id(id)
30
+ resp = Serrano.works ids: id
31
+ resp[0]["message"]
414
32
  end
415
33
  end
416
34
  end
@@ -0,0 +1,803 @@
1
+ module RelatonDoi
2
+ class Parser
3
+ COUNTRIES = %w[USA].freeze
4
+
5
+ TYPES = {
6
+ "book-chapter" => "inbook",
7
+ "book-part" => "inbook",
8
+ "book-section" => "inbook",
9
+ "book-series" => "book",
10
+ "book-set" => "book",
11
+ "book-track" => "inbook",
12
+ "component" => "misc",
13
+ "database" => "dataset",
14
+ "dissertation" => "thesis",
15
+ "edited-book" => "book",
16
+ "grant" => "misc",
17
+ "journal-article" => "article",
18
+ "journal-issue" => "article",
19
+ "journal-volume" => "journal",
20
+ "monograph" => "book",
21
+ "other" => "misc",
22
+ "peer-review" => "article",
23
+ "posted-content" => "dataset",
24
+ "proceedings-article" => "inproceedings",
25
+ "proceedings-series" => "proceedings",
26
+ "reference-book" => "book",
27
+ "reference-entry" => "inbook",
28
+ "report-component" => "techreport",
29
+ "report-series" => "techreport",
30
+ "report" => "techreport",
31
+ }.freeze
32
+
33
+ REALATION_TYPES = {
34
+ "is-cited-by" => "isCitedIn",
35
+ "belongs-to" => "related",
36
+ "is-child-of" => "includedIn",
37
+ "is-expression-of" => "expressionOf",
38
+ "has-expression" => "hasExpression",
39
+ "is-manifestation-of" => "manifestationOf",
40
+ "is-manuscript-of" => "draftOf",
41
+ "has-manuscript" => "hasDraft",
42
+ "is-preprint-of" => "draftOf",
43
+ "has-preprint" => "hasDraft",
44
+ "is-replaced-by" => "obsoletedBy",
45
+ "replaces" => "obsoletes",
46
+ "is-translation-of" => "translatedFrom",
47
+ "has-translation" => "hasTranslation",
48
+ "is-version-of" => "editionOf",
49
+ "has-version" => "hasEdition",
50
+ "is-based-on" => "updates",
51
+ "is-basis-for" => "updatedBy",
52
+ "is-comment-on" => "commentaryOf",
53
+ "has-comment" => "hasCommentary",
54
+ "is-continued-by" => "hasSuccessor",
55
+ "continues" => "successorOf",
56
+ "is-derived-from" => "derives",
57
+ "has-derivation" => "derivedFrom",
58
+ "is-documented-by" => "describedBy",
59
+ "documents" => "describes",
60
+ "is-part-of" => "partOf",
61
+ "has-part" => "hasPart",
62
+ "is-review-of" => "reviewOf",
63
+ "has-review" => "hasReview",
64
+ "references" => "cites",
65
+ "is-referenced-by" => "isCitedIn",
66
+ "requires" => "hasComplement",
67
+ "is-required-by" => "complementOf",
68
+ "is-supplement-to" => "complementOf",
69
+ "is-supplemented-by" => "hasComplement",
70
+ }.freeze
71
+
72
+ ATTRS = %i[type fetched title docid date link abstract contributor place
73
+ doctype relation extent series medium].freeze
74
+
75
+ #
76
+ # Initialize instance.
77
+ #
78
+ # @param [Hash] src The source hash.
79
+ #
80
+ def initialize(src)
81
+ @src = src
82
+ @item = {}
83
+ end
84
+
85
+ #
86
+ # Initialize instance and parse the source hash.
87
+ #
88
+ # @param [Hash] src The source hash.
89
+ #
90
+ # @return [RelatonBib::BibliographicItem, RelatonIetf::IetfBibliographicItem,
91
+ # RelatonBipm::BipmBibliographicItem, RelatonIeee::IeeeBibliographicItem,
92
+ # RelatonNist::NistBibliographicItem] The bibitem.
93
+ #
94
+ def self.parse(src)
95
+ new(src).parse
96
+ end
97
+
98
+ #
99
+ # Parse the source hash.
100
+ #
101
+ # @return [RelatonBib::BibliographicItem, RelatonIetf::IetfBibliographicItem,
102
+ # RelatonBipm::BipmBibliographicItem, RelatonIeee::IeeeBibliographicItem,
103
+ # RelatonNist::NistBibliographicItem] The bibitem.
104
+ #
105
+ def parse
106
+ ATTRS.each { |m| @item[m] = send "parse_#{m}" }
107
+ create_bibitem @src["DOI"], @item
108
+ end
109
+
110
+ #
111
+ # Create a bibitem from the bibitem hash.
112
+ #
113
+ # @param [String] doi The DOI.
114
+ # @param [Hash] bibitem The bibitem hash.
115
+ #
116
+ # @return [RelatonBib::BibliographicItem, RelatonIetf::IetfBibliographicItem,
117
+ # RelatonBipm::BipmBibliographicItem, RelatonIeee::IeeeBibliographicItem,
118
+ # RelatonNist::NistBibliographicItem] The bibitem.
119
+ #
120
+ def create_bibitem(doi, bibitem) # rubocop:disable Metrics/CyclomaticComplexity
121
+ case doi
122
+ when /\/nist/ then RelatonNist::NistBibliographicItem.new(**bibitem)
123
+ when /\/rfc\d+/ then RelatonIetf::IetfBibliographicItem.new(**bibitem)
124
+ when /\/0026-1394\// then RelatonBipm::BipmBibliographicItem.new(**bibitem)
125
+ when /\/ieee/ then RelatonIeee::IeeeBibliographicItem.new(**bibitem)
126
+ else RelatonBib::BibliographicItem.new(**bibitem)
127
+ end
128
+ end
129
+
130
+ #
131
+ # Parse the type.
132
+ #
133
+ # @return [String] The type.
134
+ #
135
+ def parse_type
136
+ TYPES[@src["type"]] || @src["type"]
137
+ end
138
+
139
+ #
140
+ # Parse the document type
141
+ #
142
+ # @return [String] The document type.
143
+ #
144
+ def parse_doctype
145
+ @src["type"]
146
+ end
147
+
148
+ #
149
+ # Parse the fetched date.
150
+ #
151
+ # @return [String] The fetched date.
152
+ #
153
+ def parse_fetched
154
+ Date.today.to_s
155
+ end
156
+
157
+ #
158
+ # Parse titles from the source hash.
159
+ #
160
+ # @return [Array<Hash>] The titles.
161
+ #
162
+ def parse_title # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
163
+ if @src["title"].is_a?(Array) && @src["title"].any?
164
+ main_sub_titles
165
+ elsif @src["project"].is_a?(Array) && @src["project"].any?
166
+ project_titles
167
+ elsif @src["container-title"].is_a?(Array) && @src["container-title"].size > 1
168
+ @src["container-title"][0..-2].map { |t| create_title t }
169
+ else []
170
+ end
171
+ end
172
+
173
+ #
174
+ # Parse main and subtitle from the source hash.
175
+ #
176
+ # @return [Array<Hash>] The titles.
177
+ #
178
+ def main_sub_titles
179
+ title = @src["title"].map { |t| create_title t }
180
+ RelatonBib.array(@src["subtitle"]).each { |t| title << create_title(t, "subtitle") }
181
+ RelatonBib.array(@src["short-title"]).each { |t| title << create_title(t, "short") }
182
+ title
183
+ end
184
+
185
+ #
186
+ # Fetch titles from the projects.
187
+ #
188
+ # @return [Array<Hash>] The titles.
189
+ #
190
+ def project_titles
191
+ RelatonBib.array(@src["project"]).reduce([]) do |memo, proj|
192
+ memo + RelatonBib.array(proj["project-title"]).map { |t| create_title t["title"] }
193
+ end
194
+ end
195
+
196
+ #
197
+ # Create a title from the title and type.
198
+ #
199
+ # @param [String] title The title content.
200
+ # @param [String] type The title type. Defaults to "main".
201
+ #
202
+ # @return [RelatonBib::TypedTitleString] The title.
203
+ #
204
+ def create_title(title, type = "main")
205
+ cnt = str_cleanup title
206
+ RelatonBib::TypedTitleString.new type: type, content: cnt, script: "Latn"
207
+ end
208
+
209
+ #
210
+ # Parse a docid from the source hash.
211
+ #
212
+ # @return [Array<RelatonBib::DocumentIdentifier>] The docid.
213
+ #
214
+ def parse_docid
215
+ %w[DOI ISBN ISSN].each_with_object([]) do |type, obj|
216
+ prm = type == "DOI"
217
+ RelatonBib.array(@src[type]).each do |id|
218
+ t = issn_type(type, id)
219
+ obj << RelatonBib::DocumentIdentifier.new(type: t, id: id, primary: prm)
220
+ end
221
+ end
222
+ end
223
+
224
+ #
225
+ # Create an ISSN type if it's an ISSN ID.
226
+ #
227
+ # @param [String] type identifier type
228
+ # @param [String] id identifier
229
+ #
230
+ # @return [String] identifier type
231
+ #
232
+ def issn_type(type, id)
233
+ return type unless type == "ISSN"
234
+
235
+ t = @src["issn-type"]&.find { |it| it["value"] == id }&.dig("type")
236
+ t ? "issn.#{t}" : type.downcase
237
+ end
238
+
239
+ #
240
+ # Parce dates from the source hash.
241
+ #
242
+ # @return [Array<RelatonBib::BibliographicDate>] The dates.
243
+ #
244
+ def parse_date # rubocop:disable Metrics/CyclomaticComplexity
245
+ dates = %w[issued published approved].each_with_object([]) do |type, obj|
246
+ next unless @src.dig(type, "date-parts")&.first&.compact&.any?
247
+
248
+ obj << RelatonBib::BibliographicDate.new(type: type, on: date_type(type))
249
+ end
250
+ if dates.none?
251
+ dates << RelatonBib::BibliographicDate.new(type: "created", on: date_type("created"))
252
+ end
253
+ dates
254
+ end
255
+
256
+ #
257
+ # Join date parts into a string.
258
+ #
259
+ # @param [String] type The date type.
260
+ #
261
+ # @return [String] The date string.
262
+ #
263
+ def date_type(type)
264
+ @src[type]["date-parts"][0].map { |d| d.to_s.rjust(2, "0") }.join "-"
265
+ end
266
+
267
+ #
268
+ # Parse links from the source hash.
269
+ #
270
+ # @return [Array<RelatonBib::TypedUri>] The links.
271
+ #
272
+ def parse_link # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
273
+ disprefered_links = %w[similarity-checking text-mining]
274
+ links = []
275
+ if @src["URL"]
276
+ links << RelatonBib::TypedUri.new(type: "DOI", content: @src["URL"])
277
+ end
278
+ [@src["link"], @src.dig("resource", "primary")].flatten.compact.each do |l|
279
+ next if disprefered_links.include? l["intended-application"]
280
+
281
+ type = case l["URL"]
282
+ when /\.pdf$/ then "pdf"
283
+ # when /\/rfc\d+$|iopscience\.iop\.org|ieeexplore\.ieee\.org/
284
+ else "src"
285
+ end
286
+ links << RelatonBib::TypedUri.new(type: type, content: l["URL"]) # if type
287
+ end
288
+ links
289
+ end
290
+
291
+ #
292
+ # Parse abstract from the source hash.
293
+ #
294
+ # @return [Array<RelatonBib::FormattedString>] The abstract.
295
+ #
296
+ def parse_abstract
297
+ return [] unless @src["abstract"]
298
+
299
+ content = @src["abstract"]
300
+ abstract = RelatonBib::FormattedString.new(
301
+ content: content, language: "en", script: "Latn", format: "text/html",
302
+ )
303
+ [abstract]
304
+ end
305
+
306
+ #
307
+ # Parse contributors from the source hash.
308
+ #
309
+ # @return [Array<RelatonBib::ContributionInfo>] The contributors.
310
+ #
311
+ def parse_contributor
312
+ contribs = author_investigators
313
+ contribs += authors_editors_translators
314
+ contribs += contribs_from_parent(contribs)
315
+ contribs << contributor(org_publisher, "publisher")
316
+ contribs += org_aurhorizer
317
+ contribs + org_enabler
318
+ end
319
+
320
+ #
321
+ # Create authors investigators from the source hash.
322
+ #
323
+ # @return [Array<RelatonBib::ContributionInfo>] The authors investigators.
324
+ #
325
+ def author_investigators
326
+ RelatonBib.array(@src["project"]).reduce([]) do |memo, proj|
327
+ memo + create_investigators(proj, "lead-investigator") +
328
+ create_investigators(proj, "investigator")
329
+ end
330
+ end
331
+
332
+ #
333
+ # Create investigators from the project.
334
+ #
335
+ # @param [Hash] project The project hash.
336
+ # @param [String] type The investigator type. "lead-investigator" or "investigator".
337
+ #
338
+ # @return [Array<RelatonBib::ContributionInfo>] The investigators.
339
+ #
340
+ def create_investigators(project, type)
341
+ description = type.gsub("-", " ")
342
+ RelatonBib.array(project[type]).map do |inv|
343
+ contributor(create_person(inv), "author", description)
344
+ end
345
+ end
346
+
347
+ #
348
+ # Create authors editors translators from the source hash.
349
+ #
350
+ # @return [Array<RelatonBib::ContributionInfo>] The authors editors translators.
351
+ #
352
+ def authors_editors_translators
353
+ %w[author editor translator].each_with_object([]) do |type, a|
354
+ @src[type]&.each do |c|
355
+ contrib = if c["family"]
356
+ create_person(c)
357
+ else
358
+ RelatonBib::Organization.new(name: str_cleanup(c["name"]))
359
+ end
360
+ a << contributor(contrib, type)
361
+ end
362
+ end
363
+ end
364
+
365
+ #
366
+ # Fetch authors and editors from parent if they are not present in the book part.
367
+ #
368
+ # @param [Array<RelatonBib::ContributionInfo>] contribs present contributors
369
+ #
370
+ # @return [Array<RelatonBib::ContributionInfo>] contributors with authors and editors from parent
371
+ #
372
+ def contribs_from_parent(contribs) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
373
+ return [] unless %w[inbook inproceedings dataset].include?(parse_type) && @src["container-title"]
374
+
375
+ has_authors = contribs.any? { |c| c.role&.any? { |r| r.type == "author" } }
376
+ has_editors = contribs.any? { |c| c.role&.any? { |r| r.type == "editor" } }
377
+ return [] if has_authors && has_editors
378
+
379
+ item = fetch_parent
380
+ authors = create_authors_editors(has_authors, "author", item)
381
+ editors = create_authors_editors(has_editors, "editor", item)
382
+ authors + editors
383
+ end
384
+
385
+ #
386
+ # Fetch parent item from Crossref.
387
+ #
388
+ # @return [Hash, nil] parent item
389
+ #
390
+ def fetch_parent # rubocop:disable Metrics/AbcSize
391
+ query = [@src["container-title"][0], fetch_year].compact.join "+"
392
+ filter = "type:#{%w[book book-set edited-book monograph reference-book].join ',type:'}"
393
+ resp = Faraday.get "https://api.crossref.org/works?query=#{query}&filter=#{filter}"
394
+ json = JSON.parse resp.body
395
+ json["message"]["items"].detect { |i| i["title"].include? @src["container-title"][0] }
396
+ end
397
+
398
+ #
399
+ # Create authors and editors from parent item.
400
+ #
401
+ # @param [Boolean] has true if authors or editors are present in the book part
402
+ # @param [String] type "author" or "editor"
403
+ # @param [Hash, nil] item parent item
404
+ #
405
+ # @return [Array<RelatonBib::ContributionInfo>] authors or editors
406
+ #
407
+ def create_authors_editors(has, type, item)
408
+ return [] if has || !item
409
+
410
+ RelatonBib.array(item[type]).map { |a| contributor(create_person(a), type) }
411
+ end
412
+
413
+ #
414
+ # Cerate an organization publisher from the source hash.
415
+ #
416
+ # @return [RelatonBib::Organization] The organization.
417
+ #
418
+ def org_publisher
419
+ pbr = @src["institution"]&.detect do |i|
420
+ @src["publisher"].include?(i["name"]) ||
421
+ i["name"].include?(@src["publisher"])
422
+ end
423
+ a = pbr["acronym"]&.first if pbr
424
+ RelatonBib::Organization.new name: str_cleanup(@src["publisher"]), abbreviation: a
425
+ end
426
+
427
+ #
428
+ # Clean up trailing punctuation and whitespace from a string.
429
+ #
430
+ # @param [String] str The string to clean up.
431
+ #
432
+ # @return [String] The cleaned up string.
433
+ #
434
+ def str_cleanup(str)
435
+ str.strip.sub(/[,\/\s]+$/, "").sub(/\s:$/, "")
436
+ end
437
+
438
+ #
439
+ # Parse authorizer contributor from the source hash.
440
+ #
441
+ # @return [Array<RelatonBib::ContributionInfo>] The authorizer contributor.
442
+ #
443
+ def org_aurhorizer
444
+ return [] unless @src["standards-body"]
445
+
446
+ name, acronym = @src["standards-body"].values_at("name", "acronym")
447
+ org = RelatonBib::Organization.new name: name, abbreviation: acronym
448
+ [contributor(org, "authorizer")]
449
+ end
450
+
451
+ #
452
+ # Parse enabler contributor from the source hash.
453
+ #
454
+ # @return [Array<RelatonBib::ContributionInfo>] The enabler contributor.
455
+ #
456
+ def org_enabler
457
+ RelatonBib.array(@src["project"]).each_with_object([]) do |proj, memo|
458
+ proj["funding"].each do |f|
459
+ memo << create_enabler(f.dig("funder", "name"))
460
+ end
461
+ end + RelatonBib.array(@src["funder"]).map { |f| create_enabler f["name"] }
462
+ end
463
+
464
+ #
465
+ # Create enabler contributor with type "enabler".
466
+ #
467
+ # @param [String] name <description>
468
+ #
469
+ # @return [RelatonBib::ContributionInfo] The enabler contributor.
470
+ #
471
+ def create_enabler(name)
472
+ org = RelatonBib::Organization.new name: name
473
+ contributor(org, "enabler")
474
+ end
475
+
476
+ #
477
+ # Create contributor from an entity and a role type.
478
+ #
479
+ # @param [RelatonBib::Person, RelatonBib::Organization] entity The entity.
480
+ # @param [String] type The role type.
481
+ #
482
+ # @return [RelatonBib::ContributionInfo] The contributor.
483
+ #
484
+ def contributor(entity, type, descriprion = nil)
485
+ role = { type: type }
486
+ role[:description] = [descriprion] if descriprion
487
+ RelatonBib::ContributionInfo.new(entity: entity, role: [role])
488
+ end
489
+
490
+ #
491
+ # Create a person from a person hash.
492
+ #
493
+ # @param [Hash] person The person hash.
494
+ #
495
+ # @return [RelatonBib::Person] The person.
496
+ #
497
+ def create_person(person)
498
+ RelatonBib::Person.new(
499
+ name: create_person_name(person),
500
+ affiliation: create_affiliation(person),
501
+ identifier: person_id(person),
502
+ )
503
+ end
504
+
505
+ #
506
+ # Create person affiliations from a person hash.
507
+ #
508
+ # @param [Hash] person The person hash.
509
+ #
510
+ # @return [Array<RelatonBib::Affiliation>] The affiliations.
511
+ #
512
+ def create_affiliation(person)
513
+ (person["affiliation"] || []).map do |a|
514
+ org = RelatonBib::Organization.new(name: a["name"])
515
+ RelatonBib::Affiliation.new organization: org
516
+ end
517
+ end
518
+
519
+ #
520
+ # Create a person full name from a person hash.
521
+ #
522
+ # @param [Hash] person The person hash.
523
+ #
524
+ # @return [RelatonBib::FullName] The full name.
525
+ #
526
+ def create_person_name(person)
527
+ surname = titlecase(person["family"])
528
+ sn = RelatonBib::LocalizedString.new(surname, "en", "Latn")
529
+ RelatonBib::FullName.new(
530
+ surname: sn, forename: forename(person), addition: nameaddition(person),
531
+ completename: completename(person), prefix: nameprefix(person)
532
+ )
533
+ end
534
+
535
+ #
536
+ # Capitalize the first letter of each word in a string except for words that
537
+ # are 2 letters or less.
538
+ #
539
+ # @param [<Type>] str <description>
540
+ #
541
+ # @return [<Type>] <description>
542
+ #
543
+ def titlecase(str)
544
+ str.split.map do |s|
545
+ if s.size > 2 && s.upcase == s && !/\.&/.match?(s)
546
+ s.capitalize
547
+ else
548
+ s
549
+ end
550
+ end.join " "
551
+ end
552
+
553
+ #
554
+ # Create a person name prefix from a person hash.
555
+ #
556
+ # @param [Hash] person The person hash.
557
+ #
558
+ # @return [Array<RelatonBib::LocalizedString>] The name prefix.
559
+ #
560
+ def nameprefix(person)
561
+ return [] unless person["prefix"]
562
+
563
+ [RelatonBib::LocalizedString.new(person["prefix"], "en", "Latn")]
564
+ end
565
+
566
+ #
567
+ # Create a complete name from a person hash.
568
+ #
569
+ # @param [Hash] person The person hash.
570
+ #
571
+ # @return [RelatonBib::LocalizedString] The complete name.
572
+ #
573
+ def completename(person)
574
+ return unless person["name"]
575
+
576
+ RelatonBib::LocalizedString.new(person["name"], "en", "Latn")
577
+ end
578
+
579
+ #
580
+ # Create a forename from a person hash.
581
+ #
582
+ # @param [Hash] person The person hash.
583
+ #
584
+ # @return [Array<RelatonBib::LocalizedString>] The forename.
585
+ #
586
+ def forename(person)
587
+ return [] unless person["given"]
588
+
589
+ fname = titlecase(person["given"])
590
+ [RelatonBib::Forename.new(content: fname, language: "en", script: "Latn")]
591
+ end
592
+
593
+ #
594
+ # Create an addition from a person hash.
595
+ #
596
+ # @param [Hash] person The person hash.
597
+ #
598
+ # @return [Array<RelatonBib::LocalizedString>] The addition.
599
+ #
600
+ def nameaddition(person)
601
+ return [] unless person["suffix"]
602
+
603
+ [RelatonBib::LocalizedString.new(person["suffix"], "en", "Latn")]
604
+ end
605
+
606
+ #
607
+ # Create a person identifier from a person hash.
608
+ #
609
+ # @param [Hash] person The person hash.
610
+ #
611
+ # @return [Array<RelatonBib::PersonIdentifier>] The person identifier.
612
+ #
613
+ def person_id(person)
614
+ return [] unless person["ORCID"]
615
+
616
+ [RelatonBib::PersonIdentifier.new("orcid", person["ORCID"])]
617
+ end
618
+
619
+ #
620
+ # Parse a place from the source hash.
621
+ #
622
+ # @return [Array<RelatonBib::Place>] The place.
623
+ #
624
+ def parse_place # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
625
+ pub_location = @src["publisher-location"] || fetch_location
626
+ return [] unless pub_location
627
+
628
+ pls1, pls2 = pub_location.split(", ")
629
+ pls1 = str_cleanup pls1
630
+ pls2 &&= str_cleanup pls2
631
+ if COUNTRIES.include? pls2
632
+ country = RelatonBib::Place::RegionType.new(name: pls2)
633
+ [RelatonBib::Place.new(city: pls1, country: [country])]
634
+ elsif pls2 && pls2 == pls2&.upcase
635
+ region = RelatonBib::Place::RegionType.new(name: pls2)
636
+ [RelatonBib::Place.new(city: pls1, region: [region])]
637
+ elsif pls1 == pls2 || pls2.nil? || pls2.empty?
638
+ [RelatonBib::Place.new(city: pls1)]
639
+ else
640
+ [RelatonBib::Place.new(city: pls1), RelatonBib::Place.new(city: pls2)]
641
+ end
642
+ end
643
+
644
+ #
645
+ # Fetch location from container.
646
+ #
647
+ # @return [String, nil] The location.
648
+ #
649
+ def fetch_location # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
650
+ title = @item[:title].first&.title&.content
651
+ qparts = [title, fetch_year, @src["publisher"]]
652
+ query = CGI.escape qparts.compact.join("+").gsub(" ", "+")
653
+ filter = "type:#{%w[book-chapter book-part book-section book-track].join(',type:')}"
654
+ resp = Faraday.get "https://api.crossref.org/works?query=#{query}&filter=#{filter}"
655
+ json = JSON.parse resp.body
656
+ json["message"]["items"].detect do |i|
657
+ i["publisher-location"] && i["container-title"].include?(title)
658
+ end&.dig("publisher-location")
659
+ end
660
+
661
+ #
662
+ # Parse relations from the source hash.
663
+ #
664
+ # @return [Array<RelatonBib::DocumentRelation>] The relations.
665
+ #
666
+ def parse_relation # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
667
+ rels = included_in_relation
668
+ @src["relation"].each_with_object(rels) do |(k, v), a|
669
+ type, desc = relation_type k
670
+ RelatonBib.array(v).each do |r|
671
+ rel_item = Crossref.get_by_id r["id"]
672
+ title = rel_item["title"].map { |t| create_title t }
673
+ docid = RelatonBib::DocumentIdentifier.new(id: r["id"], type: "DOI")
674
+ bib = create_bibitem r["id"], title: title, docid: [docid]
675
+ a << RelatonBib::DocumentRelation.new(type: type, description: desc, bibitem: bib)
676
+ end
677
+ end
678
+ end
679
+
680
+ #
681
+ # Transform crossref relation type to relaton relation type.
682
+ #
683
+ # @param [String] crtype The crossref relation type.
684
+ #
685
+ # @return [Array<String>] The relaton relation type and description.
686
+ #
687
+ def relation_type(crtype)
688
+ type = REALATION_TYPES[crtype] || begin
689
+ desc = RelatonBib::FormattedString.new(content: crtype)
690
+ "related"
691
+ end
692
+ [type, desc]
693
+ end
694
+
695
+ #
696
+ # Create included in relation.
697
+ #
698
+ # @return [Array<RelatonBib::DocumentRelation>] The relations.
699
+ #
700
+ def included_in_relation
701
+ types = %w[
702
+ book book-chapter book-part book-section book-track dataset journal-issue
703
+ journal-value proceedings-article reference-entry report-component
704
+ ]
705
+ return [] unless @src["container-title"] && types.include?(@src["type"])
706
+
707
+ @src["container-title"].map do |ct|
708
+ contrib = included_in_editors(ct)
709
+ bib = RelatonBib::BibliographicItem.new(title: [content: ct], contributor: contrib)
710
+ RelatonBib::DocumentRelation.new(type: "includedIn", bibitem: bib)
711
+ end
712
+ end
713
+
714
+ #
715
+ # Fetch included in editors.
716
+ #
717
+ # @param [String] title container-title
718
+ #
719
+ # @return [Array<RelatonBib::ContributionInfo>] The editors contribution info.
720
+ #
721
+ def included_in_editors(title)
722
+ item = fetch_included_in title
723
+ return [] unless item
724
+
725
+ item["editor"].map { |e| contributor(create_person(e), "editor") }
726
+ end
727
+
728
+ #
729
+ # Fetch included in relation.
730
+ #
731
+ # @param [String] title container-title
732
+ #
733
+ # @return [Hash] The included in relation item.
734
+ #
735
+ def fetch_included_in(title)
736
+ query = CGI.escape [title, @src["publisher"], @src["publisher-location"], fetch_year].join(", ")
737
+ resp = Faraday.get %{http://api.crossref.org/works?query.bibliographic="#{query}"&rows=10&filter=type:book}
738
+ json = JSON.parse resp.body
739
+ json["message"]["items"].detect { |i| i["title"].include?(title) && i["editor"] }
740
+ end
741
+
742
+ #
743
+ # Fetch year from the source hash.
744
+ #
745
+ # @return [String] The year.
746
+ #
747
+ def fetch_year
748
+ d = @src["published"] || @src["approved"] || @src["created"]
749
+ d["date-parts"][0][0]
750
+ end
751
+
752
+ #
753
+ # Parse an extent from the source hash.
754
+ #
755
+ # @return [Array<RelatonBib::Locality>] The extent.
756
+ #
757
+ def parse_extent # rubocop:disable Metrics/AbcSize
758
+ extent = []
759
+ extent << RelatonBib::Locality.new("volume", @src["volume"]) if @src["volume"]
760
+ extent << RelatonBib::Locality.new("issue", @src["issue"]) if @src["issue"]
761
+ if @src["page"]
762
+ from, to = @src["page"].split("-")
763
+ extent << RelatonBib::Locality.new("page", from, to)
764
+ end
765
+ extent.any? ? [RelatonBib::LocalityStack.new(extent)] : []
766
+ end
767
+
768
+ #
769
+ # Parse a series from the source hash.
770
+ #
771
+ # @return [Arrey<RelatonBib::Series>] The series.
772
+ #
773
+ def parse_series # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
774
+ types = %w[inbook incollection inproceedings]
775
+ return [] if !@src["container-title"] || types.include?(@item[:type]) || @src["type"] == "report-component"
776
+
777
+ con_ttl = if main_sub_titles.any? || project_titles.any?
778
+ @src["container-title"]
779
+ elsif @src["container-title"].size > 1
780
+ sct = @src["short-container-title"]&.last
781
+ abbrev = RelatonBib::LocalizedString.new sct if sct
782
+ @src["container-title"][-1..-1]
783
+ else []
784
+ end
785
+ con_ttl.map do |ct|
786
+ title = RelatonBib::TypedTitleString.new content: ct
787
+ RelatonBib::Series.new title: title, abbreviation: abbrev
788
+ end
789
+ end
790
+
791
+ #
792
+ # Parse a medium from the source hash.
793
+ #
794
+ # @return [RelatonBib::Mediub, nil] The medium.
795
+ #
796
+ def parse_medium
797
+ genre = @src["degree"]&.first
798
+ return unless genre
799
+
800
+ RelatonBib::Medium.new genre: genre
801
+ end
802
+ end
803
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RelatonDoi
4
- VERSION = "1.14.1"
4
+ VERSION = "1.14.3"
5
5
  end
data/lib/relaton_doi.rb CHANGED
@@ -8,6 +8,7 @@ require "relaton_ietf"
8
8
  require "relaton_ieee"
9
9
  require "relaton_nist"
10
10
  require_relative "relaton_doi/version"
11
+ require_relative "relaton_doi/parser"
11
12
  require_relative "relaton_doi/crossref"
12
13
 
13
14
  Serrano.configuration do |config|
@@ -15,6 +16,4 @@ Serrano.configuration do |config|
15
16
  end
16
17
 
17
18
  module RelatonDoi
18
- class Error < StandardError; end
19
- # Your code goes here...
20
19
  end
data/relaton-doi.gemspec CHANGED
@@ -41,7 +41,7 @@ Gem::Specification.new do |spec|
41
41
  spec.add_development_dependency "vcr"
42
42
  spec.add_development_dependency "webmock"
43
43
 
44
- spec.add_dependency "relaton-bib", "~> 1.14.1"
44
+ spec.add_dependency "relaton-bib", "~> 1.14.3"
45
45
  spec.add_dependency "relaton-bipm", "~> 1.14.0"
46
46
  spec.add_dependency "relaton-ieee", "~> 1.14.0"
47
47
  spec.add_dependency "relaton-ietf", "~> 1.14.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: relaton-doi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.14.1
4
+ version: 1.14.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-12-11 00:00:00.000000000 Z
11
+ date: 2023-01-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: equivalent-xml
@@ -100,14 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 1.14.1
103
+ version: 1.14.3
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 1.14.1
110
+ version: 1.14.3
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: relaton-bipm
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -200,6 +200,7 @@ files:
200
200
  - bin/setup
201
201
  - lib/relaton_doi.rb
202
202
  - lib/relaton_doi/crossref.rb
203
+ - lib/relaton_doi/parser.rb
203
204
  - lib/relaton_doi/processor.rb
204
205
  - lib/relaton_doi/version.rb
205
206
  - relaton-doi.gemspec