relaton-doi 1.14.1 → 1.14.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.
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