bolognese 0.8.5 → 0.8.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +10 -9
  3. data/README.md +15 -1
  4. data/lib/bolognese.rb +2 -0
  5. data/lib/bolognese/bibtex.rb +57 -1
  6. data/lib/bolognese/citeproc.rb +116 -0
  7. data/lib/bolognese/codemeta.rb +9 -1
  8. data/lib/bolognese/crossref.rb +20 -0
  9. data/lib/bolognese/datacite.rb +9 -1
  10. data/lib/bolognese/datacite_json.rb +9 -1
  11. data/lib/bolognese/datacite_utils.rb +1 -1
  12. data/lib/bolognese/metadata.rb +185 -1
  13. data/lib/bolognese/ris.rb +117 -0
  14. data/lib/bolognese/schema_org.rb +8 -0
  15. data/lib/bolognese/utils.rb +84 -17
  16. data/lib/bolognese/version.rb +1 -1
  17. data/resources/kernel-3/metadata.xsd +3 -3
  18. data/spec/bibtex_spec.rb +34 -0
  19. data/spec/citeproc_spec.rb +48 -0
  20. data/spec/codemeta_spec.rb +33 -3
  21. data/spec/crossref_spec.rb +80 -2
  22. data/spec/datacite_json_spec.rb +28 -12
  23. data/spec/datacite_spec.rb +72 -0
  24. data/spec/datacite_utils_spec.rb +1 -1
  25. data/spec/fixtures/citeproc.json +21 -0
  26. data/spec/fixtures/vcr_cassettes/Bolognese_Codemeta/get_metadata_as_citeproc/maremma.yml +100 -0
  27. data/spec/fixtures/vcr_cassettes/Bolognese_Codemeta/get_metadata_as_ris/BlogPosting.yml +100 -0
  28. data/spec/fixtures/vcr_cassettes/Bolognese_Codemeta/get_metadata_as_ris/maremma.yml +100 -0
  29. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_citeproc/journal_article.yml +723 -0
  30. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_citeproc/with_pages.yml +370 -0
  31. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_ris/journal_article.yml +723 -0
  32. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_ris/with_pages.yml +370 -0
  33. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata/Citeproc_JSON.yml +173 -0
  34. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata_as_citeproc/BlogPosting.yml +155 -0
  35. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata_as_citeproc/Dataset.yml +173 -0
  36. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata_as_ris/BlogPosting.yml +155 -0
  37. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata_as_ris/Dataset.yml +173 -0
  38. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/read/datacite.yml +173 -0
  39. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/write/datacite_to_bibtex.yml +173 -0
  40. data/spec/fixtures/vcr_cassettes/Bolognese_SchemaOrg/get_metadata_as_citeproc/BlogPosting.yml +653 -0
  41. data/spec/fixtures/vcr_cassettes/Bolognese_SchemaOrg/get_metadata_as_ris/BlogPosting.yml +653 -0
  42. data/spec/schema_org_spec.rb +30 -0
  43. data/spec/utils_spec.rb +50 -0
  44. metadata +22 -2
@@ -0,0 +1,117 @@
1
+ module Bolognese
2
+ class Ris < Metadata
3
+
4
+ BIB_TO_SO_TRANSLATIONS = {
5
+ "article" => "ScholarlyArticle"
6
+ }
7
+
8
+ SO_TO_BIB_TRANSLATIONS = {
9
+ "Article" => "article",
10
+ "AudioObject" => "misc",
11
+ "Blog" => "misc",
12
+ "BlogPosting" => "article",
13
+ "Collection" => "misc",
14
+ "CreativeWork" => "misc",
15
+ "DataCatalog" => "misc",
16
+ "Dataset" => "misc",
17
+ "Event" => "misc",
18
+ "ImageObject" => "misc",
19
+ "Movie" => "misc",
20
+ "PublicationIssue" => "misc",
21
+ "ScholarlyArticle" => "article",
22
+ "Service" => "misc",
23
+ "SoftwareSourceCode" => "misc",
24
+ "VideoObject" => "misc",
25
+ "WebPage" => "misc",
26
+ "WebSite" => "misc"
27
+ }
28
+
29
+ BIB_TO_CP_TRANSLATIONS = {
30
+ "article" => "article-journal"
31
+ }
32
+
33
+ def initialize(string: nil)
34
+ @raw = string
35
+ end
36
+
37
+ def metadata
38
+ @metadata ||= raw.present? ? BibTeX.parse(raw).first : {}
39
+ end
40
+
41
+ def exists?
42
+ metadata.present?
43
+ end
44
+
45
+ def valid?
46
+ bibtex.present?
47
+ end
48
+
49
+ def type
50
+ BIB_TO_SO_TRANSLATIONS[metadata.type.to_s] || "ScholarlyArticle"
51
+ end
52
+
53
+ def citeproc_type
54
+ BIB_TO_CP_TRANSLATIONS[metadata.type.to_s] || "misc"
55
+ end
56
+
57
+ def resource_type_general
58
+ SO_TO_DC_TRANSLATIONS[type]
59
+ end
60
+
61
+ def doi
62
+ metadata.doi
63
+ end
64
+
65
+ def url
66
+ metadata.url
67
+ end
68
+
69
+ def id
70
+ normalize_doi(doi)
71
+ end
72
+
73
+ def author
74
+ Array(metadata.author).map do |a|
75
+ { "@type" => "Person",
76
+ "givenName" => a.first,
77
+ "familyName" => a.last }.compact
78
+ end
79
+ end
80
+
81
+ def title
82
+ metadata.title
83
+ end
84
+
85
+ def container_title
86
+ metadata.journal.to_s.presence || metadata.publisher.to_s
87
+ end
88
+
89
+ alias_method :journal, :container_title
90
+
91
+ def date_published
92
+ metadata.date.to_s.presence
93
+ end
94
+
95
+ def publication_year
96
+ metadata.year.to_s.presence
97
+ end
98
+
99
+ def is_part_of
100
+ if metadata.journal.present?
101
+ { "type" => "Periodical",
102
+ "name" => metadata.journal.to_s,
103
+ "issn" => metadata.issn.to_s.presence }.compact
104
+ else
105
+ nil
106
+ end
107
+ end
108
+
109
+ def description
110
+ { "text" => metadata.field?(:abstract) && metadata.abstract.to_s.presence }
111
+ end
112
+
113
+ def license
114
+ { "id" => metadata.field?(:copyright) && metadata.copyright.to_s.presence }
115
+ end
116
+ end
117
+ end
@@ -54,6 +54,14 @@ module Bolognese
54
54
  metadata.fetch("@type", nil)
55
55
  end
56
56
 
57
+ def citeproc_type
58
+ SO_TO_CP_TRANSLATIONS[type] || "article-journal"
59
+ end
60
+
61
+ def ris_type
62
+ SO_TO_RIS_TRANSLATIONS[resource_type_general.to_s.dasherize] || "GEN"
63
+ end
64
+
57
65
  def additional_type
58
66
  metadata.fetch("additionalType", nil)
59
67
  end
@@ -41,30 +41,44 @@ module Bolognese
41
41
  "datacite"
42
42
  elsif options[:ext] == ".json" && Maremma.from_json(string).dig("resource", "xmlns").to_s.start_with?("http://datacite.org/schema/kernel")
43
43
  "datacite_json"
44
+ elsif options[:ext] == ".json" && Maremma.from_json(string).dig("resource", "xmlns").to_s.start_with?("http://datacite.org/schema/kernel")
45
+ "citeproc"
46
+ elsif options[:ext] == ".ris"
47
+ "ris"
44
48
  elsif options[:filename] == "codemeta.json"
45
49
  "codemeta"
46
50
  end
47
51
  end
48
52
 
49
- def write(id: nil, string: nil, from: nil, to: nil, **options)
50
- if from.present?
51
- p = case from
52
- when "crossref" then Crossref.new(id: id, string: string)
53
- when "datacite" then Datacite.new(id: id, string: string, regenerate: options[:regenerate])
54
- when "codemeta" then Codemeta.new(id: id, string: string)
55
- when "datacite_json" then DataciteJson.new(string: string)
56
- when "bibtex" then Bibtex.new(string: string)
57
- else SchemaOrg.new(id: id)
58
- end
59
-
60
- if p.valid?
61
- puts p.send(to)
62
- else
63
- $stderr.puts p.errors.colorize(:red)
64
- end
65
- else
53
+ def read(id: nil, string: nil, from: nil, **options)
54
+ if from.nil?
66
55
  puts "not implemented"
56
+ return nil
67
57
  end
58
+
59
+ p = case from
60
+ when "crossref" then Crossref.new(id: id, string: string)
61
+ when "datacite" then Datacite.new(id: id, string: string, regenerate: options[:regenerate])
62
+ when "codemeta" then Codemeta.new(id: id, string: string)
63
+ when "datacite_json" then DataciteJson.new(string: string)
64
+ when "citeproc" then Citeproc.new(id: id, string: string)
65
+ when "bibtex" then Bibtex.new(string: string)
66
+ when "ris" then Ris.new(string: string)
67
+ else SchemaOrg.new(id: id)
68
+ end
69
+
70
+ unless p.valid?
71
+ $stderr.puts p.errors.colorize(:red)
72
+ end
73
+
74
+ p
75
+ end
76
+
77
+ def write(id: nil, string: nil, from: nil, to: nil, **options)
78
+ metadata = read(id: id, string: string, from: from, **options)
79
+ return nil if metadata.nil?
80
+
81
+ puts metadata.send(to)
68
82
  end
69
83
 
70
84
  def orcid_from_url(url)
@@ -189,6 +203,40 @@ module Bolognese
189
203
  end.unwrap
190
204
  end
191
205
 
206
+ def from_citeproc(element)
207
+ Array.wrap(element).map do |a|
208
+ if a["literal"].present?
209
+ a["@type"] = "Organization"
210
+ a["name"] = a["literal"]
211
+ else
212
+ a["@type"] = "Person"
213
+ a["name"] = [a["given"], a["family"]].compact.join(" ")
214
+ end
215
+ a["givenName"] = a["given"]
216
+ a["familyName"] = a["family"]
217
+ a.except("given", "family", "literal").compact
218
+ end.unwrap
219
+ end
220
+
221
+ def to_citeproc(element)
222
+ Array.wrap(element).map do |a|
223
+ a["family"] = a["familyName"]
224
+ a["given"] = a["givenName"]
225
+ a["literal"] = a["name"] unless a["familyName"].present?
226
+ a.except("type", "@type", "id", "@id", "name", "familyName", "givenName").compact
227
+ end.unwrap
228
+ end
229
+
230
+ def to_ris(element)
231
+ Array.wrap(element).map do |a|
232
+ if a["familyName"].present?
233
+ [a["familyName"], a["givenName"]].join(", ")
234
+ else
235
+ a["name"]
236
+ end
237
+ end.unwrap
238
+ end
239
+
192
240
  def sanitize(text, options={})
193
241
  options[:tags] ||= Set.new(%w(strong em b i code pre sub sup br))
194
242
  custom_scrubber = Bolognese::WhitelistScrubber.new(options)
@@ -236,5 +284,24 @@ module Bolognese
236
284
  github_hash = github_from_url(url)
237
285
  "https://raw.githubusercontent.com/#{github_hash[:owner]}/#{github_hash[:repo]}/master/codemeta.json" if github_hash[:owner].present?
238
286
  end
287
+
288
+ def get_date_parts(iso8601_time)
289
+ return nil if iso8601_time.nil?
290
+
291
+ year = iso8601_time[0..3].to_i
292
+ month = iso8601_time[5..6].to_i
293
+ day = iso8601_time[8..9].to_i
294
+ { 'date-parts' => [[year, month, day].reject { |part| part == 0 }] }
295
+ end
296
+
297
+ def get_date_from_date_parts(date_as_parts)
298
+ date_parts = date_as_parts.fetch("date-parts", []).first
299
+ year, month, day = date_parts[0], date_parts[1], date_parts[2]
300
+ get_date_from_parts(year, month, day)
301
+ end
302
+
303
+ def get_date_from_parts(year, month = nil, day = nil)
304
+ [year.to_s.rjust(4, '0'), month.to_s.rjust(2, '0'), day.to_s.rjust(2, '0')].reject { |part| part == "00" }.join("-")
305
+ end
239
306
  end
240
307
  end
@@ -1,3 +1,3 @@
1
1
  module Bolognese
2
- VERSION = "0.8.5"
2
+ VERSION = "0.8.7"
3
3
  end
@@ -1,12 +1,12 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <!-- Revision history
3
3
  2010-08-26 Complete revision according to new common specification by the metadata work group after review. AJH, DTIC
4
- 2010-11-17 Revised to current state of kernel review, FZ, TIB
4
+ 2010-11-17 Revised to current state of kernel review, FZ, TIB
5
5
  2011-01-17 Complete revsion after community review. FZ, TIB
6
6
  2011-03-17 Release of v2.1: added a namespace; mandatory properties got minLength; changes in the definitions of relationTypes
7
7
  IsDocumentedBy/Documents and isCompiledBy/Compiles; changes type of property "Date" from xs:date to xs:string. FZ, TIB
8
8
  2011-06-27 v2.2: namespace: kernel-2.2, additions to controlled lists "resourceType", "contributorType", "relatedIdentifierType", and "descriptionType". Removal of intermediate include-files.
9
- 2013-05 v3.0: namespace: kernel-3.0; delete LastMetadataUpdate & MetadateVersionNumber; additions to controlled lists "contributorType", "dateType", "descriptionType", "relationType", "relatedIdentifierType" & "resourceType"; deletion of "StartDate" & "EndDate" from list "dateType" and "Film" from "resourceType"; allow arbitrary order of elements; allow optional wrapper elements to be empty; include xml:lang attribute for title, subject & description; include attribute schemeURI for nameIdentifier of creator, contributor & subject; added new attributes "relatedMetadataScheme", "schemeURI" & "schemeType" to relatedIdentifier; included new property "geoLocation"
9
+ 2013-05 v3.0: namespace: kernel-3.0; delete LastMetadataUpdate & MetadateVersionNumber; additions to controlled lists "contributorType", "dateType", "descriptionType", "relationType", "relatedIdentifierType" & "resourceType"; deletion of "StartDate" & "EndDate" from list "dateType" and "Film" from "resourceType"; allow arbitrary order of elements; allow optional wrapper elements to be empty; include xml:lang attribute for title, subject & description; include attribute schemeURI for nameIdentifier of creator, contributor & subject; added new attributes "relatedMetadataScheme", "schemeURI" & "schemeType" to relatedIdentifier; included new property "geoLocation"
10
10
  2014-08-20 v3.1: additions to controlled lists "relationType", contributorType" and "relatedIdentifierType"; introduction of new child element "affiliation" to "creator" and "contributor"-->
11
11
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://datacite.org/schema/kernel-3" targetNamespace="http://datacite.org/schema/kernel-3" elementFormDefault="qualified" xml:lang="EN">
12
12
  <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
@@ -277,7 +277,7 @@
277
277
  <xs:sequence>
278
278
  <xs:element name="rights" minOccurs="0" maxOccurs="unbounded">
279
279
  <xs:annotation>
280
- <xs:documentation>Any rights information for this resource. Provide a rights management statement for the resource or reference a service providing such information. Include embargo information if applicable.
280
+ <xs:documentation>Any rights information for this resource. Provide a rights management statement for the resource or reference a service providing such information. Include embargo information if applicable.
281
281
  Use the complete title of a license and include version information if applicable.</xs:documentation>
282
282
  </xs:annotation>
283
283
  <xs:complexType>
data/spec/bibtex_spec.rb CHANGED
@@ -35,4 +35,38 @@ describe Bolognese::Bibtex, vcr: true do
35
35
  expect(datacite.dig("creators", "creator").first).to eq("creatorName"=>"Sankar, Martial", "givenName"=>"Martial", "familyName"=>"Sankar")
36
36
  end
37
37
  end
38
+
39
+ context "get metadata as citeproc" do
40
+ it "Crossref DOI" do
41
+ json = JSON.parse(subject.citeproc)
42
+ expect(json["type"]).to eq("article-journal")
43
+ expect(json["id"]).to eq("https://doi.org/10.7554/elife.01567")
44
+ expect(json["DOI"]).to eq("10.7554/elife.01567")
45
+ expect(json["URL"]).to eq("http://elifesciences.org/lookup/doi/10.7554/eLife.01567")
46
+ expect(json["title"]).to eq("Automated quantitative histology reveals vascular morphodynamics during Arabidopsis hypocotyl secondary growth")
47
+ expect(json["author"]).to eq([{"family"=>"Sankar", "given"=>"Martial"},
48
+ {"family"=>"Nieminen", "given"=>"Kaisa"},
49
+ {"family"=>"Ragni", "given"=>"Laura"},
50
+ {"family"=>"Xenarios", "given"=>"Ioannis"},
51
+ {"family"=>"Hardtke", "given"=>"Christian S"}])
52
+ expect(json["container-title"]).to eq("eLife")
53
+ expect(json["issued"]).to eq("date-parts" => [[2014]])
54
+ end
55
+ end
56
+
57
+ context "get metadata as ris" do
58
+ it "Crossref DOI" do
59
+ ris = subject.ris.split("\r\n")
60
+ expect(ris[0]).to eq("TY - JOUR")
61
+ expect(ris[1]).to eq("T1 - Automated quantitative histology reveals vascular morphodynamics during Arabidopsis hypocotyl secondary growth")
62
+ expect(ris[2]).to eq("T2 - eLife")
63
+ expect(ris[3]).to eq("AU - Sankar, Martial")
64
+ expect(ris[8]).to eq("DO - 10.7554/elife.01567")
65
+ expect(ris[9]).to eq("UR - http://elifesciences.org/lookup/doi/10.7554/eLife.01567")
66
+ expect(ris[10]).to eq("AB - Among various advantages, their small size makes model organisms preferred subjects of investigation. Yet, even in model systems detailed analysis of numerous developmental processes at cellular level is severely hampered by their scale.")
67
+ expect(ris[11]).to eq("PY - 2014")
68
+ expect(ris[12]).to eq("VL - 3")
69
+ expect(ris[13]).to eq("ER - ")
70
+ end
71
+ end
38
72
  end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bolognese::Citeproc, vcr: true do
4
+ let(:string) { IO.read(fixture_path + "citeproc.json") }
5
+
6
+ subject { Bolognese::Citeproc.new(string: string) }
7
+
8
+ context "get metadata" do
9
+ it "BlogPosting" do
10
+ expect(subject.valid?).to be true
11
+ expect(subject.id).to eq("https://doi.org/10.5438/4k3m-nyvg")
12
+ expect(subject.type).to eq("BlogPosting")
13
+ expect(subject.url).to eq("https://blog.datacite.org/eating-your-own-dog-food")
14
+ expect(subject.resource_type_general).to eq("Text")
15
+ expect(subject.author).to eq("type"=>"Person", "name"=>"Martin Fenner", "givenName"=>"Martin", "familyName"=>"Fenner")
16
+ expect(subject.title).to eq("Eating your own Dog Food")
17
+ expect(subject.description["text"]).to start_with("Eating your own dog food")
18
+ expect(subject.date_published).to eq("2016-12-20")
19
+ expect(subject.is_part_of).to eq("type"=>"Periodical", "name"=>"DataCite Blog")
20
+ end
21
+ end
22
+
23
+ context "get metadata as datacite xml" do
24
+ it "BlogPosting" do
25
+ datacite = Maremma.from_xml(subject.datacite).fetch("resource", {})
26
+ expect(datacite.dig("resourceType", "resourceTypeGeneral")).to eq("Text")
27
+ expect(datacite.dig("titles", "title")).to eq("Eating your own Dog Food")
28
+ expect(datacite.dig("descriptions", "description", "__content__")).to start_with("Eating your own dog food")
29
+ expect(datacite.dig("creators", "creator")).to eq("creatorName"=>"Fenner, Martin", "givenName"=>"Martin", "familyName"=>"Fenner")
30
+ end
31
+ end
32
+
33
+ context "get metadata as ris" do
34
+ it "BlogPosting" do
35
+ ris = subject.ris.split("\r\n")
36
+ expect(ris[0]).to eq("TY - GEN")
37
+ expect(ris[1]).to eq("T1 - Eating your own Dog Food")
38
+ expect(ris[2]).to eq("T2 - DataCite Blog")
39
+ expect(ris[3]).to eq("AU - Fenner, Martin")
40
+ expect(ris[4]).to eq("DO - 10.5438/4k3m-nyvg")
41
+ expect(ris[5]).to eq("UR - https://blog.datacite.org/eating-your-own-dog-food")
42
+ expect(ris[6]).to eq("AB - Eating your own dog food is a slang term to describe that an organization should itself use the products and services it provides. For DataCite this means that we should use DOIs with appropriate metadata and strategies for long-term preservation for...")
43
+ expect(ris[7]).to eq("PY - 2016")
44
+ expect(ris[8]).to eq("PB - DataCite")
45
+ expect(ris[9]).to eq("ER - ")
46
+ end
47
+ end
48
+ end
@@ -98,14 +98,14 @@ describe Bolognese::Codemeta, vcr: true do
98
98
  subject = Bolognese::Codemeta.new(string: string)
99
99
  datacite = Maremma.from_xml(subject.datacite).fetch("resource", {})
100
100
  expect(datacite.dig("titles", "title")).to eq("R Interface to the DataONE REST API")
101
- expect(datacite.dig("creators", "creator")).to eq([{"creatorName"=>"Matt Jones",
101
+ expect(datacite.dig("creators", "creator")).to eq([{"creatorName"=>"Jones, Matt",
102
102
  "givenName"=>"Matt",
103
103
  "familyName"=>"Jones",
104
104
  "nameIdentifier"=>
105
105
  {"schemeURI"=>"http://orcid.org/",
106
106
  "nameIdentifierScheme"=>"ORCID",
107
107
  "__content__"=>"http://orcid.org/0000-0003-0077-4738"}},
108
- {"creatorName"=>"Peter Slaughter",
108
+ {"creatorName"=>"Slaughter, Peter",
109
109
  "givenName"=>"Peter",
110
110
  "familyName"=>"Slaughter",
111
111
  "nameIdentifier"=>
@@ -119,7 +119,7 @@ describe Bolognese::Codemeta, vcr: true do
119
119
  it "maremma" do
120
120
  datacite = Maremma.from_xml(subject.datacite).fetch("resource", {})
121
121
  expect(datacite.dig("titles", "title")).to eq("Maremma: a Ruby library for simplified network calls")
122
- expect(datacite.dig("creators", "creator")).to eq("creatorName"=>"Martin Fenner", "givenName"=>"Martin", "familyName"=>"Fenner", "nameIdentifier"=>{"schemeURI"=>"http://orcid.org/", "nameIdentifierScheme"=>"ORCID", "__content__"=>"http://orcid.org/0000-0003-0077-4738"})
122
+ expect(datacite.dig("creators", "creator")).to eq("creatorName"=>"Fenner, Martin", "givenName"=>"Martin", "familyName"=>"Fenner", "nameIdentifier"=>{"schemeURI"=>"http://orcid.org/", "nameIdentifierScheme"=>"ORCID", "__content__"=>"http://orcid.org/0000-0003-0077-4738"})
123
123
  end
124
124
  end
125
125
 
@@ -168,4 +168,34 @@ describe Bolognese::Codemeta, vcr: true do
168
168
  expect(bibtex[:year]).to eq("2017")
169
169
  end
170
170
  end
171
+
172
+ context "get metadata as citeproc" do
173
+ it "maremma" do
174
+ json = JSON.parse(subject.citeproc)
175
+ expect(json["type"]).to eq("computer_program")
176
+ expect(json["id"]).to eq("https://doi.org/10.5438/qeg0-3gm3")
177
+ expect(json["DOI"]).to eq("10.5438/qeg0-3gm3")
178
+ expect(json["title"]).to eq("Maremma: a Ruby library for simplified network calls")
179
+ expect(json["author"]).to eq("family" => "Fenner", "given" => "Martin")
180
+ expect(json["publisher"]).to eq("DataCite")
181
+ expect(json["issued"]).to eq("date-parts" => [[2017, 2, 24]])
182
+ end
183
+ end
184
+
185
+ context "get metadata as ris" do
186
+ it "maremma" do
187
+ ris = subject.ris.split("\r\n")
188
+ expect(ris[0]).to eq("TY - COMP")
189
+ expect(ris[1]).to eq("T1 - Maremma: a Ruby library for simplified network calls")
190
+ expect(ris[2]).to eq("T2 - DataCite")
191
+ expect(ris[3]).to eq("AU - Fenner, Martin")
192
+ expect(ris[4]).to eq("DO - 10.5438/qeg0-3gm3")
193
+ expect(ris[5]).to eq("UR - https://github.com/datacite/maremma")
194
+ expect(ris[6]).to eq("AB - Ruby utility library for network requests. Based on Faraday and Excon, provides a wrapper for XML/JSON parsing and error handling. All successful responses are returned as hash with key data, all errors in a JSONAPI-friendly hash with key errors.")
195
+ expect(ris[7]).to eq("KW - faraday")
196
+ expect(ris[10]).to eq("PY - 2017")
197
+ expect(ris[11]).to eq("PB - DataCite")
198
+ expect(ris[12]).to eq("ER - ")
199
+ end
200
+ end
171
201
  end
@@ -181,7 +181,7 @@ describe Bolognese::Crossref, vcr: true do
181
181
  datacite = Maremma.from_xml(subject.datacite).fetch("resource", {})
182
182
  expect(datacite.dig("resourceType", "resourceTypeGeneral")).to eq("Text")
183
183
  expect(datacite.dig("creators", "creator").count).to eq(7)
184
- expect(datacite.dig("creators", "creator")[2]).to eq("creatorName" => "Beatriz Hernandez",
184
+ expect(datacite.dig("creators", "creator")[2]).to eq("creatorName" => "Hernandez, Beatriz",
185
185
  +"familyName" => "Hernandez",
186
186
  +"givenName" => "Beatriz",
187
187
  "nameIdentifier" => {"schemeURI"=>"http://orcid.org/", "nameIdentifierScheme"=>"ORCID", "__content__"=>"http://orcid.org/0000-0003-2043-4925"})
@@ -191,7 +191,7 @@ describe Bolognese::Crossref, vcr: true do
191
191
  id = "https://doi.org/10.1371/journal.pone.0000030"
192
192
  subject = Bolognese::Crossref.new(id: id)
193
193
  datacite = Maremma.from_xml(subject.datacite).fetch("resource", {})
194
- expect(datacite.dig("contributors", "contributor")).to eq("contributorType"=>"Editor", "contributorName"=>"Guilhem Janbon", "givenName"=>"Guilhem", "familyName"=>"Janbon")
194
+ expect(datacite.dig("contributors", "contributor")).to eq("contributorType"=>"Editor", "contributorName"=>"Janbon, Guilhem", "givenName"=>"Guilhem", "familyName"=>"Janbon")
195
195
  end
196
196
  end
197
197
 
@@ -223,4 +223,82 @@ describe Bolognese::Crossref, vcr: true do
223
223
  expect(bibtex[:year]).to eq("2012")
224
224
  end
225
225
  end
226
+
227
+ context "get metadata as citeproc" do
228
+ it "journal article" do
229
+ id = "10.7554/eLife.01567"
230
+ subject = Bolognese::Crossref.new(id: id)
231
+ expect(subject.valid?).to be true
232
+ json = JSON.parse(subject.citeproc)
233
+ expect(json["type"]).to eq("article-journal")
234
+ expect(json["id"]).to eq("https://doi.org/10.7554/elife.01567")
235
+ expect(json["DOI"]).to eq("10.7554/eLife.01567")
236
+ expect(json["title"]).to eq("Automated quantitative histology reveals vascular morphodynamics during Arabidopsis hypocotyl secondary growth")
237
+ expect(json["author"]).to eq([{"family"=>"Sankar", "given"=>"Martial"},
238
+ {"family"=>"Nieminen", "given"=>"Kaisa"},
239
+ {"family"=>"Ragni", "given"=>"Laura"},
240
+ {"family"=>"Xenarios", "given"=>"Ioannis"},
241
+ {"family"=>"Hardtke", "given"=>"Christian S"}])
242
+ expect(json["container-title"]).to eq("eLife")
243
+ expect(json["volume"]).to eq("3")
244
+ expect(json["issued"]).to eq("date-parts" => [[2014, 2, 11]])
245
+ end
246
+
247
+ it "with pages" do
248
+ id = "https://doi.org/10.1155/2012/291294"
249
+ subject = Bolognese::Crossref.new(id: id)
250
+ expect(subject.valid?).to be true
251
+ json = JSON.parse(subject.citeproc)
252
+ expect(json["type"]).to eq("article-journal")
253
+ expect(json["id"]).to eq("https://doi.org/10.1155/2012/291294")
254
+ expect(json["DOI"]).to eq("10.1155/2012/291294")
255
+ expect(json["title"]).to eq("Delineating a Retesting Zone Using Receiver Operating Characteristic Analysis on Serial QuantiFERON Tuberculosis Test Results in US Healthcare Workers")
256
+ expect(json["author"]).to eq([{"family"=>"Thanassi", "given"=>"Wendy"},
257
+ {"family"=>"Noda", "given"=>"Art"},
258
+ {"family"=>"Hernandez", "given"=>"Beatriz"},
259
+ {"family"=>"Newell", "given"=>"Jeffery"},
260
+ {"family"=>"Terpeluk", "given"=>"Paul"},
261
+ {"family"=>"Marder", "given"=>"David"},
262
+ {"family"=>"Yesavage", "given"=>"Jerome A."}])
263
+ expect(json["container-title"]).to eq("Pulmonary Medicine")
264
+ expect(json["volume"]).to eq("2012")
265
+ expect(json["page"]).to eq("1-7")
266
+ expect(json["issued"]).to eq("date-parts"=>[[2012]])
267
+ end
268
+ end
269
+
270
+ context "get metadata as ris" do
271
+ it "journal article" do
272
+ id = "10.7554/eLife.01567"
273
+ subject = Bolognese::Crossref.new(id: id)
274
+ expect(subject.valid?).to be true
275
+ ris = subject.ris.split("\r\n")
276
+ expect(ris[0]).to eq("TY - JOUR")
277
+ expect(ris[1]).to eq("T1 - Automated quantitative histology reveals vascular morphodynamics during Arabidopsis hypocotyl secondary growth")
278
+ expect(ris[2]).to eq("T2 - eLife")
279
+ expect(ris[3]).to eq("AU - Sankar, Martial")
280
+ expect(ris[8]).to eq("DO - 10.7554/eLife.01567")
281
+ expect(ris[9]).to eq("UR - http://elifesciences.org/lookup/doi/10.7554/eLife.01567")
282
+ expect(ris[10]).to eq("PY - 2014")
283
+ expect(ris[11]).to eq("VL - 3")
284
+ expect(ris[12]).to eq("ER - ")
285
+ end
286
+
287
+ it "with pages" do
288
+ id = "https://doi.org/10.1155/2012/291294"
289
+ subject = Bolognese::Crossref.new(id: id)
290
+ expect(subject.valid?).to be true
291
+ ris = subject.ris.split("\r\n")
292
+ expect(ris[0]).to eq("TY - JOUR")
293
+ expect(ris[1]).to eq("T1 - Delineating a Retesting Zone Using Receiver Operating Characteristic Analysis on Serial QuantiFERON Tuberculosis Test Results in US Healthcare Workers")
294
+ expect(ris[2]).to eq("T2 - Pulmonary Medicine")
295
+ expect(ris[3]).to eq("AU - Thanassi, Wendy")
296
+ expect(ris[10]).to eq("DO - 10.1155/2012/291294")
297
+ expect(ris[11]).to eq("UR - http://www.hindawi.com/journals/pm/2012/291294/")
298
+ expect(ris[12]).to eq("PY - 2012")
299
+ expect(ris[13]).to eq("VL - 2012")
300
+ expect(ris[14]).to eq("SP - 1-7")
301
+ expect(ris[15]).to eq("ER - ")
302
+ end
303
+ end
226
304
  end