commonmeta-ruby 3.4.5 → 3.5.1

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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +8 -8
  3. data/csl-data.json +538 -0
  4. data/lib/commonmeta/author_utils.rb +103 -71
  5. data/lib/commonmeta/crossref_utils.rb +31 -25
  6. data/lib/commonmeta/metadata.rb +8 -14
  7. data/lib/commonmeta/metadata_utils.rb +4 -3
  8. data/lib/commonmeta/readers/bibtex_reader.rb +3 -3
  9. data/lib/commonmeta/readers/cff_reader.rb +7 -6
  10. data/lib/commonmeta/readers/codemeta_reader.rb +3 -3
  11. data/lib/commonmeta/readers/crossref_reader.rb +131 -124
  12. data/lib/commonmeta/readers/crossref_xml_reader.rb +7 -6
  13. data/lib/commonmeta/readers/csl_reader.rb +3 -4
  14. data/lib/commonmeta/readers/datacite_reader.rb +5 -5
  15. data/lib/commonmeta/readers/json_feed_reader.rb +8 -4
  16. data/lib/commonmeta/readers/npm_reader.rb +2 -2
  17. data/lib/commonmeta/readers/ris_reader.rb +1 -1
  18. data/lib/commonmeta/readers/schema_org_reader.rb +6 -4
  19. data/lib/commonmeta/schema_utils.rb +1 -1
  20. data/lib/commonmeta/utils.rb +4 -2
  21. data/lib/commonmeta/version.rb +1 -1
  22. data/lib/commonmeta/writers/bibtex_writer.rb +1 -1
  23. data/lib/commonmeta/writers/cff_writer.rb +5 -4
  24. data/lib/commonmeta/writers/codemeta_writer.rb +4 -2
  25. data/lib/commonmeta/writers/csv_writer.rb +4 -2
  26. data/lib/commonmeta/writers/datacite_writer.rb +1 -1
  27. data/lib/commonmeta/writers/jats_writer.rb +9 -5
  28. data/lib/commonmeta/writers/ris_writer.rb +2 -1
  29. data/lib/commonmeta/writers/schema_org_writer.rb +7 -4
  30. data/resources/{commonmeta_v0.9.3.json → commonmeta_v0.10.3.json} +138 -55
  31. data/resources/csl-citation.json +99 -0
  32. data/spec/author_utils_spec.rb +16 -16
  33. data/spec/cli_spec.rb +1 -1
  34. data/spec/fixtures/vcr_cassettes/Commonmeta_Metadata/get_crossref_metadata/missing_contributor.yml +307 -0
  35. data/spec/fixtures/vcr_cassettes/Commonmeta_Metadata/get_datacite_metadata/SoftwareSourceCode.yml +76 -0
  36. data/spec/fixtures/vcr_cassettes/Commonmeta_Metadata/get_json_feed_item_metadata/archived_wordpress_post.yml +119 -0
  37. data/spec/fixtures/vcr_cassettes/Commonmeta_Metadata/write_metadata_as_crossref/book_oup.yml +107 -0
  38. data/spec/fixtures/vcr_cassettes/Commonmeta_Metadata/write_metadata_as_crossref/journal_article_plos.yml +407 -0
  39. data/spec/metadata_spec.rb +2 -2
  40. data/spec/readers/bibtex_reader_spec.rb +5 -5
  41. data/spec/readers/cff_reader_spec.rb +127 -127
  42. data/spec/readers/codemeta_reader_spec.rb +11 -11
  43. data/spec/readers/crossref_reader_spec.rb +844 -835
  44. data/spec/readers/crossref_xml_reader_spec.rb +899 -901
  45. data/spec/readers/csl_reader_spec.rb +33 -33
  46. data/spec/readers/datacite_reader_spec.rb +106 -103
  47. data/spec/readers/json_feed_reader_spec.rb +68 -40
  48. data/spec/readers/npm_reader_spec.rb +32 -33
  49. data/spec/readers/ris_reader_spec.rb +36 -36
  50. data/spec/readers/schema_org_reader_spec.rb +289 -288
  51. data/spec/writers/codemeta_writer_spec.rb +19 -20
  52. data/spec/writers/crossref_xml_writer_spec.rb +73 -37
  53. data/spec/writers/datacite_writer_spec.rb +2 -1
  54. metadata +10 -3
@@ -4,19 +4,19 @@ module Commonmeta
4
4
  module Readers
5
5
  module CrossrefReader
6
6
  def get_crossref(id: nil, **options)
7
- return { 'string' => nil, 'state' => 'not_found' } unless id.present?
7
+ return { "string" => nil, "state" => "not_found" } unless id.present?
8
8
 
9
9
  api_url = crossref_api_url(id, options)
10
10
  response = HTTP.get(api_url)
11
- return { 'string' => nil, 'state' => 'not_found' } unless response.status.success?
11
+ return { "string" => nil, "state" => "not_found" } unless response.status.success?
12
12
 
13
- { 'string' => response.body.to_s }
13
+ { "string" => response.body.to_s }
14
14
  end
15
15
 
16
16
  def read_crossref(string: nil, **options)
17
17
  if string.present?
18
18
  errors = jsonlint(string)
19
- return { 'errors' => errors } if errors.present?
19
+ return { "errors" => errors } if errors.present?
20
20
  end
21
21
 
22
22
  read_options = ActiveSupport::HashWithIndifferentAccess.new(options.except(:doi, :id, :url,
@@ -24,161 +24,168 @@ module Commonmeta
24
24
  meta = string.present? ? JSON.parse(string) : {}
25
25
 
26
26
  # optionally strip out the message wrapper from API
27
- meta = meta.dig('message') if meta.dig('message').present?
27
+ meta = meta.dig("message") if meta.dig("message").present?
28
28
 
29
- resource_type = meta.fetch('type', nil)
29
+ resource_type = meta.fetch("type", nil)
30
30
  resource_type = resource_type.present? ? resource_type.underscore.camelcase : nil
31
- type = Commonmeta::Utils::CR_TO_CM_TRANSLATIONS.fetch(resource_type, 'Other')
31
+ type = Commonmeta::Utils::CR_TO_CM_TRANSLATIONS.fetch(resource_type, "Other")
32
32
 
33
- member_id = meta.fetch('member', nil)
33
+ member_id = meta.fetch("member", nil)
34
34
  # TODO: get publisher from member_id almost always return publisher name, but sometimes does not
35
35
  publisher = if member_id.present?
36
- get_crossref_member(member_id)
37
- else
38
- meta.fetch('publisher', nil)
39
- end
40
-
41
- creators = if meta.fetch('author', nil).present?
42
- get_authors(from_csl(Array.wrap(meta.fetch('author', nil))))
43
- else
44
- []
45
- end
46
- editors = Array.wrap(meta.fetch('editor', nil)).each { |e| e['contributorType'] = 'Editor' }
47
- contributors = get_authors(from_csl(editors))
36
+ get_crossref_member(member_id)
37
+ else
38
+ meta.fetch("publisher", nil)
39
+ end
40
+
41
+ contributors = if meta.fetch("author", nil).present?
42
+ get_authors(from_csl(Array.wrap(meta.fetch("author", nil))))
43
+ else
44
+ []
45
+ end
46
+ editors = Array.wrap(meta.fetch("editor", nil)).each { |e| e["contributorType"] = "Editor" }
47
+ contributors += get_authors(from_csl(editors))
48
48
 
49
49
  date = {}
50
- date['submitted'] = nil
51
- date['accepted'] = meta.dig('accepted', 'date-time')
52
- date['published'] =
53
- meta.dig('issued',
54
- 'date-time') || get_date_from_date_parts(meta.fetch('issued',
50
+ date["submitted"] = nil
51
+ date["accepted"] = meta.dig("accepted", "date-time")
52
+ date["published"] =
53
+ meta.dig("issued",
54
+ "date-time") || get_date_from_date_parts(meta.fetch("issued",
55
55
  nil)) || get_date_from_date_parts(meta.fetch(
56
- 'created', nil
57
- ))
58
- date['updated'] =
59
- meta.dig('updated',
60
- 'date-time') || meta.dig('deposited',
61
- 'date-time') || get_date_from_date_parts(meta.fetch(
62
- 'deposited', nil
63
- ))
56
+ "created", nil
57
+ ))
58
+ date["updated"] =
59
+ meta.dig("updated",
60
+ "date-time") || meta.dig("deposited",
61
+ "date-time") || get_date_from_date_parts(meta.fetch(
62
+ "deposited", nil
63
+ ))
64
64
 
65
65
  # TODO: fix timestamp. Until then, remove time as this is not always stable with Crossref (different server timezones)
66
- date['published'] = get_iso8601_date(date['published']) if date['published'].present?
67
- date['updated'] = get_iso8601_date(date['updated']) if date['updated'].present?
66
+ date["published"] = get_iso8601_date(date["published"]) if date["published"].present?
67
+ date["updated"] = get_iso8601_date(date["updated"]) if date["updated"].present?
68
68
 
69
- license = if meta.fetch('license', nil)
70
- hsh_to_spdx('rightsURI' => meta.dig('license', 0, 'URL'))
71
- end
72
- issn = Array.wrap(meta.fetch('issn-type', nil)).find { |i| i['type'] == 'electronic' } ||
73
- Array.wrap(meta.fetch('issn-type', nil)).find { |i| i['type'] == 'print' } || {}
74
- issn = issn.fetch('value', nil) if issn.present?
69
+ license = if meta.fetch("license", nil)
70
+ hsh_to_spdx("rightsURI" => meta.dig("license", 0, "URL"))
71
+ end
72
+ issn = Array.wrap(meta.fetch("issn-type", nil)).find { |i| i["type"] == "electronic" } ||
73
+ Array.wrap(meta.fetch("issn-type", nil)).find { |i| i["type"] == "print" } || {}
74
+ issn = issn.fetch("value", nil) if issn.present?
75
75
 
76
- references = Array.wrap(meta.fetch('reference', nil)).map { |r| get_reference(r) }
76
+ references = Array.wrap(meta.fetch("reference", nil)).map { |r| get_reference(r) }
77
77
 
78
- funding_references = Array.wrap(meta.fetch('funder', nil)).reduce([]) do |sum, funding|
78
+ funding_references = Array.wrap(meta.fetch("funder", nil)).reduce([]) do |sum, funding|
79
79
  funding_reference = {
80
- 'funderName' => funding['name'],
81
- 'funderIdentifier' => funding['DOI'] ? doi_as_url(funding['DOI']) : nil,
82
- 'funderIdentifierType' => funding['DOI'].to_s.starts_with?('10.13039') ? 'Crossref Funder ID' : nil
80
+ "funderName" => funding["name"],
81
+ "funderIdentifier" => funding["DOI"] ? doi_as_url(funding["DOI"]) : nil,
82
+ "funderIdentifierType" => funding["DOI"].to_s.starts_with?("10.13039") ? "Crossref Funder ID" : nil,
83
83
  }.compact
84
- if funding['name'].present? && funding['award'].present?
85
- Array.wrap(funding['award']).each do |award|
86
- funding_reference['awardNumber'] = award
84
+ if funding["name"].present? && funding["award"].present?
85
+ Array.wrap(funding["award"]).each do |award|
86
+ funding_reference["awardNumber"] = award
87
87
  end
88
88
  end
89
89
 
90
90
  sum += [funding_reference] if funding_reference.present?
91
91
  sum
92
92
  end
93
+ files = Array.wrap(meta.fetch("link", nil)).reduce([]) do |sum, file|
94
+ if file["content-type"] != "unspecified"
95
+ file = { "url" => file.fetch("URL", nil), "mimeType" => file.fetch("content-type", nil) }
96
+ sum += [file]
97
+ end
98
+ sum
99
+ end
100
+
93
101
  container_type = case resource_type
94
- when 'JournalArticle', 'JournalIssue'
95
- 'Journal'
96
- when 'BookChapter'
97
- 'Book'
98
- when 'Monograph'
99
- 'BookSeries'
100
- end
101
-
102
- first_page = if meta.fetch('page', nil).present?
103
- meta.fetch('page').split('-').map(&:strip)[0]
104
- end
105
- last_page = if meta.fetch('page', nil).present?
106
- meta.fetch('page').split('-').map(&:strip)[1]
107
- end
108
-
109
- container = { 'type' => container_type,
110
- 'title' => parse_attributes(meta.fetch('container-title', nil),
102
+ when "JournalArticle", "JournalIssue"
103
+ "Journal"
104
+ when "BookChapter"
105
+ "Book"
106
+ when "Monograph"
107
+ "BookSeries"
108
+ end
109
+
110
+ first_page = if meta.fetch("page", nil).present?
111
+ meta.fetch("page").split("-").map(&:strip)[0]
112
+ end
113
+ last_page = if meta.fetch("page", nil).present?
114
+ meta.fetch("page").split("-").map(&:strip)[1]
115
+ end
116
+
117
+ container = { "type" => container_type,
118
+ "title" => parse_attributes(meta.fetch("container-title", nil),
111
119
  first: true).to_s.squish.presence,
112
- 'identifier' => issn.present? ? issn : nil,
113
- 'identifierType' => issn.present? ? 'ISSN' : nil,
114
- 'volume' => meta.fetch('volume', nil),
115
- 'issue' => meta.fetch('issue', nil),
116
- 'firstPage' => first_page,
117
- 'lastPage' => last_page }.compact
118
-
119
- id = normalize_id(meta.fetch('id', nil) || meta.fetch('DOI', nil))
120
-
121
- id = normalize_doi(options[:doi] || options[:id] || meta.fetch('DOI', nil))
122
- title = if meta.fetch('title', nil).is_a?(Array)
123
- meta.fetch('title', nil)[0]
124
- else
125
- meta.fetch('title', nil)
126
- end
127
- title = title.blank? ? ':(unav)' : title.squish
128
- state = meta.present? || read_options.present? ? 'findable' : 'not_found'
129
- subjects = Array.wrap(meta.fetch('categories', nil)).reduce([]) do |sum, subject|
120
+ "identifier" => issn.present? ? issn : nil,
121
+ "identifierType" => issn.present? ? "ISSN" : nil,
122
+ "volume" => meta.fetch("volume", nil),
123
+ "issue" => meta.fetch("issue", nil),
124
+ "firstPage" => first_page,
125
+ "lastPage" => last_page }.compact
126
+
127
+ id = normalize_id(meta.fetch("id", nil) || meta.fetch("DOI", nil))
128
+
129
+ id = normalize_doi(options[:doi] || options[:id] || meta.fetch("DOI", nil))
130
+ title = if meta.fetch("title", nil).is_a?(Array)
131
+ meta.fetch("title", nil)[0]
132
+ else
133
+ meta.fetch("title", nil)
134
+ end
135
+ title = title.blank? ? ":(unav)" : title.squish
136
+ state = meta.present? || read_options.present? ? "findable" : "not_found"
137
+ subjects = Array.wrap(meta.fetch("categories", nil)).reduce([]) do |sum, subject|
130
138
  sum += name_to_fos(subject)
131
139
 
132
140
  sum
133
141
  end
134
- abstract = meta.fetch('abstract', nil)
142
+ abstract = meta.fetch("abstract", nil)
135
143
  provider = get_doi_ra(id)
136
144
 
137
- { 'id' => id,
138
- 'type' => type,
139
- 'url' => normalize_id(meta.dig('resource', 'primary', 'URL')),
140
- 'titles' => [{ 'title' => title }],
141
- 'creators' => creators,
142
- 'contributors' => contributors,
143
- 'container' => container,
144
- 'publisher' => publisher,
145
- 'references' => references,
146
- 'date' => date.compact,
147
- 'descriptions' => if abstract.present?
148
- [{ 'description' => sanitize(abstract),
149
- 'descriptionType' => 'Abstract' }]
150
- else
151
- []
152
- end,
153
- 'license' => license,
154
- 'alternate_identifiers' => [],
155
- 'funding_references' => funding_references,
156
- 'version' => meta.fetch('version', nil),
157
- 'subjects' => subjects,
158
- 'provider' => provider,
159
- 'schema_version' => 'http://datacite.org/schema/kernel-4',
160
- 'state' => state }.compact.merge(read_options)
145
+ { "id" => id,
146
+ "type" => type,
147
+ "url" => normalize_id(meta.dig("resource", "primary", "URL")),
148
+ "titles" => [{ "title" => title }],
149
+ "contributors" => contributors,
150
+ "container" => container,
151
+ "publisher" => publisher,
152
+ "references" => references,
153
+ "date" => date.compact,
154
+ "descriptions" => if abstract.present?
155
+ [{ "description" => sanitize(abstract),
156
+ "descriptionType" => "Abstract" }]
157
+ else
158
+ []
159
+ end,
160
+ "license" => license,
161
+ "alternate_identifiers" => [],
162
+ "funding_references" => funding_references,
163
+ "files" => files.presence,
164
+ "version" => meta.fetch("version", nil),
165
+ "subjects" => subjects,
166
+ "provider" => provider,
167
+ "schema_version" => "http://datacite.org/schema/kernel-4",
168
+ "state" => state }.compact.merge(read_options)
161
169
  end
162
170
 
163
171
  def get_reference(reference)
164
172
  return nil unless reference.present? || !reference.is_a?(Hash)
165
173
 
166
- doi = reference.dig('DOI')
174
+ doi = reference.dig("DOI")
167
175
  {
168
- 'key' => reference.dig('key'),
169
- 'doi' => doi ? normalize_doi(doi) : nil,
170
- 'creator' => reference.dig('author'),
171
- 'title' => reference.dig('article-title'),
172
- 'publisher' => reference.dig('publisher'),
173
- 'publicationYear' => reference.dig('year'),
174
- 'volume' => reference.dig('volume'),
175
- 'issue' => reference.dig('issue'),
176
- 'firstPage' => reference.dig('first-page'),
177
- 'lastPage' => reference.dig('last-page'),
178
- 'containerTitle' => reference.dig('journal-title'),
179
- 'edition' => nil,
180
- 'contributor' => nil,
181
- 'unstructured' => doi.nil? ? reference.dig('unstructured') : nil
176
+ "key" => reference.dig("key"),
177
+ "doi" => doi ? normalize_doi(doi) : nil,
178
+ "contributor" => reference.dig("author"),
179
+ "title" => reference.dig("article-title"),
180
+ "publisher" => reference.dig("publisher"),
181
+ "publicationYear" => reference.dig("year"),
182
+ "volume" => reference.dig("volume"),
183
+ "issue" => reference.dig("issue"),
184
+ "firstPage" => reference.dig("first-page"),
185
+ "lastPage" => reference.dig("last-page"),
186
+ "containerTitle" => reference.dig("journal-title"),
187
+ "edition" => nil,
188
+ "unstructured" => doi.nil? ? reference.dig("unstructured") : nil,
182
189
  }.compact
183
190
  end
184
191
  end
@@ -101,6 +101,9 @@ module Commonmeta
101
101
  resource_type = resource_type.present? ? resource_type.underscore.camelcase : nil
102
102
  type = Commonmeta::Utils::CR_TO_CM_TRANSLATIONS.fetch(resource_type, 'Other')
103
103
 
104
+ contributors = crossref_people(bibmeta, 'author')
105
+ contributors += crossref_people(bibmeta, 'editor')
106
+
104
107
  titles = if bibmeta['titles'].present?
105
108
  Array.wrap(bibmeta['titles']).map do |r|
106
109
  if r.blank? || (r['title'].blank? && r['original_language_title'].blank?)
@@ -192,8 +195,7 @@ module Commonmeta
192
195
  'url' => url,
193
196
  'titles' => titles,
194
197
  'alternate_identifiers' => alternate_identifiers,
195
- 'creators' => crossref_people(bibmeta, 'author'),
196
- 'contributors' => crossref_people(bibmeta, 'editor'),
198
+ 'contributors' => contributors,
197
199
  'funding_references' => crossref_funding_reference(program_metadata),
198
200
  'publisher' => { 'name' => publisher },
199
201
  'container' => container,
@@ -296,11 +298,11 @@ module Commonmeta
296
298
  'givenName' => given_name,
297
299
  'familyName' => family_name,
298
300
  'affiliation' => affiliation.presence,
299
- 'contributorType' => contributor_role == 'editor' ? 'Editor' : nil }.compact
301
+ 'contributorRoles' => contributor_role == 'editor' ? ['Editor'] : ['Author'] }.compact
300
302
  else
301
303
  { 'type' => 'Organization',
302
304
  'name' => a['name'] || a['__content__'],
303
- 'contributorType' => contributor_role == 'editor' ? 'Editor' : nil }.compact
305
+ 'contributorRoles' => contributor_role == 'editor' ? ['Editor'] : ['Author'] }.compact
304
306
  end
305
307
  end
306
308
  end
@@ -359,7 +361,7 @@ module Commonmeta
359
361
  {
360
362
  'key' => reference.dig('key'),
361
363
  'doi' => doi ? normalize_doi(doi) : nil,
362
- 'creator' => reference.dig('author'),
364
+ 'contributor' => reference.dig('author'),
363
365
  'title' => reference.dig('article_title'),
364
366
  'publisher' => reference.dig('publisher'),
365
367
  'publicationYear' => reference.dig('cYear'),
@@ -369,7 +371,6 @@ module Commonmeta
369
371
  'lastPage' => reference.dig('last_page'),
370
372
  'containerTitle' => reference.dig('journal_title'),
371
373
  'edition' => nil,
372
- 'contributor' => nil,
373
374
  'unstructured' => doi.nil? ? reference.dig('unstructured') : nil
374
375
  }.compact
375
376
  end.unwrap
@@ -17,12 +17,12 @@ module Commonmeta
17
17
  citeproc_type = meta.fetch('type', nil)
18
18
  type = Commonmeta::Utils::CSL_TO_CM_TRANSLATIONS.fetch(citeproc_type, 'Other')
19
19
 
20
- creators = if meta.fetch('author', nil).present?
20
+ contributors = if meta.fetch('author', nil).present?
21
21
  get_authors(from_csl(Array.wrap(meta.fetch('author', nil))))
22
22
  else
23
- [{ 'type' => 'Organization', 'name' => ':(unav)' }]
23
+ [{ 'type' => 'Organization', 'name' => ':(unav)', 'contributorRoles' => ['Author'] }]
24
24
  end
25
- contributors = get_authors(from_csl(Array.wrap(meta.fetch('editor', nil))))
25
+ contributors += get_authors(from_csl(Array.wrap(meta.fetch('editor', nil))))
26
26
 
27
27
  date = {}
28
28
  d = get_date_from_date_parts(meta.fetch('issued', nil))
@@ -62,7 +62,6 @@ module Commonmeta
62
62
  'type' => type,
63
63
  'url' => normalize_id(meta.fetch('URL', nil)),
64
64
  'titles' => [{ 'title' => meta.fetch('title', nil) }],
65
- 'creators' => creators,
66
65
  'contributors' => contributors,
67
66
  'container' => container,
68
67
  'publisher' => if meta.fetch('publisher', nil)
@@ -53,10 +53,10 @@ module Commonmeta
53
53
  titles = Array.wrap(meta.fetch('titles', nil)).map do |title|
54
54
  title.compact
55
55
  end
56
- creators = get_authors(from_datacite(meta.fetch('creators', nil)))
56
+ contributors = get_authors(from_datacite(meta.fetch('creators', nil)))
57
+ contributors += get_authors(from_datacite(meta.fetch('contributors', nil)))
57
58
  publisher = { 'name' => meta.fetch('publisher', nil) }
58
59
 
59
- contributors = get_authors(from_datacite(meta.fetch('contributors', nil)))
60
60
  container = meta.fetch('container', nil)
61
61
  funding_references = meta.fetch('funding_references', nil)
62
62
 
@@ -88,6 +88,7 @@ module Commonmeta
88
88
  end.map do |reference|
89
89
  get_datacite_reference(reference)
90
90
  end
91
+ files = Array.wrap(meta.fetch("content_url", nil)).map { |file| { "url" => file } }
91
92
  formats = meta.fetch('formats', nil)
92
93
  sizes = meta.fetch('sizes', nil)
93
94
  schema_version = meta.fetch('schema_version', nil) || 'http://datacite.org/schema/kernel-4'
@@ -98,7 +99,6 @@ module Commonmeta
98
99
  'additional_type' => resource_type == type ? nil : resource_type,
99
100
  'url' => url,
100
101
  'titles' => titles,
101
- 'creators' => creators,
102
102
  'contributors' => contributors,
103
103
  'container' => container,
104
104
  'publisher' => publisher,
@@ -106,6 +106,7 @@ module Commonmeta
106
106
  'alternate_identifiers' => alternate_identifiers.presence,
107
107
  'references' => references,
108
108
  'funding_references' => funding_references,
109
+ 'files' => files.presence,
109
110
  'date' => date.compact,
110
111
  'descriptions' => descriptions,
111
112
  'license' => license,
@@ -150,7 +151,7 @@ module Commonmeta
150
151
  'key' => key,
151
152
  'doi' => doi,
152
153
  'url' => url,
153
- 'creator' => reference.dig('author'),
154
+ 'contributor' => reference.dig('author'),
154
155
  'title' => reference.dig('article-title'),
155
156
  'publisher' => reference.dig('publisher'),
156
157
  'publicationYear' => reference.dig('year'),
@@ -160,7 +161,6 @@ module Commonmeta
160
161
  'lastPage' => reference.dig('last-page'),
161
162
  'containerTitle' => reference.dig('journal-title'),
162
163
  'edition' => nil,
163
- 'contributor' => nil,
164
164
  'unstructured' => doi.nil? ? reference.dig('unstructured') : nil
165
165
  }.compact
166
166
  end
@@ -20,12 +20,16 @@ module Commonmeta
20
20
 
21
21
  meta = string.present? ? JSON.parse(string) : {}
22
22
 
23
- url = normalize_url(meta.fetch("url", nil))
23
+ if (meta.dig("blog", "status") == "archived")
24
+ url = normalize_url(meta.fetch("archive_url", nil))
25
+ else
26
+ url = normalize_url(meta.fetch("url", nil))
27
+ end
24
28
  id = options[:doi] ? normalize_doi(options[:doi]) : normalize_id(meta.fetch("doi", nil))
25
- id = url if id.blank? && url.present?
29
+ id = normalize_url(meta.fetch("url", nil)) if id.blank?
26
30
 
27
31
  type = "Article"
28
- creators = if meta.fetch("authors", nil).present?
32
+ contributors = if meta.fetch("authors", nil).present?
29
33
  get_authors(from_json_feed(Array.wrap(meta.fetch("authors"))))
30
34
  else
31
35
  [{ "type" => "Organization", "name" => ":(unav)" }]
@@ -70,7 +74,7 @@ module Commonmeta
70
74
  "type" => type,
71
75
  "url" => url,
72
76
  "titles" => titles,
73
- "creators" => creators,
77
+ "contributors" => contributors,
74
78
  "publisher" => publisher,
75
79
  "container" => container,
76
80
  "date" => date,
@@ -26,7 +26,7 @@ module Commonmeta
26
26
 
27
27
  type = 'Software'
28
28
 
29
- creators = get_authors(Array.wrap(meta.fetch('author', nil)))
29
+ contributors = get_authors(Array.wrap(meta.fetch('author', nil)))
30
30
  license = hsh_to_spdx('rightsIdentifier' => meta.fetch('license', nil))
31
31
 
32
32
  # container = if meta.fetch("container-title", nil).present?
@@ -71,7 +71,7 @@ module Commonmeta
71
71
  # "doi" => doi_from_url(doi),
72
72
  # "url" => normalize_id(meta.fetch("URL", nil)),
73
73
  'titles' => [{ 'title' => meta.fetch('name', nil) }],
74
- 'creators' => creators,
74
+ 'contributors' => contributors,
75
75
  # "contributors" => contributors,
76
76
  # "container" => container,
77
77
  # "publisher" => meta.fetch("publisher", nil),
@@ -41,7 +41,7 @@ module Commonmeta
41
41
  'type' => type,
42
42
  'url' => meta.fetch('UR', nil),
43
43
  'titles' => meta.fetch('T1', nil).present? ? [{ 'title' => meta.fetch('T1', nil) }] : nil,
44
- 'creators' => get_authors(author),
44
+ 'contributors' => get_authors(author),
45
45
  'publisher' => { 'name' => meta.fetch('PB', '(:unav)') },
46
46
  'container' => container,
47
47
  'date' => date,
@@ -106,8 +106,9 @@ module Commonmeta
106
106
  additional_type = meta.fetch('additionalType', nil)
107
107
  authors = meta.fetch('author', nil) || meta.fetch('creator', nil)
108
108
  # Authors should be an object, if it's just a plain string don't try and parse it.
109
- creators = get_authors(from_schema_org(Array.wrap(authors))) unless authors.is_a?(String)
110
- contributors = get_authors(from_schema_org(Array.wrap(meta.fetch('editor', nil))))
109
+ contributors = get_authors(from_schema_org(Array.wrap(authors))) unless authors.is_a?(String)
110
+ contributors = [] if contributors.nil?
111
+ contributors += get_authors(from_schema_org(Array.wrap(meta.fetch('editor', nil))))
111
112
  publisher = parse_attributes(meta.fetch('publisher', nil), content: 'name', first: true)
112
113
 
113
114
  ct = schema_org == 'Dataset' ? 'includedInDataCatalog' : 'Periodical'
@@ -206,6 +207,8 @@ module Commonmeta
206
207
  }.compact
207
208
  end
208
209
 
210
+ files = Array.wrap(meta.fetch("contentUrl", nil)).map { |file| { "url" => file } }
211
+
209
212
  # handle keywords as array and as comma-separated string
210
213
  subjects = meta.fetch('keywords', nil)
211
214
  subjects = subjects.to_s.split(', ') if subjects.is_a?(String)
@@ -221,7 +224,7 @@ module Commonmeta
221
224
  'additional_type' => additional_type,
222
225
  'alternate_identifiers' => alternate_identifiers.presence,
223
226
  'url' => normalize_id(meta.fetch('url', nil)),
224
- 'content_url' => Array.wrap(meta.fetch('contentUrl', nil)),
227
+ 'files' => files.presence,
225
228
  'sizes' => Array.wrap(meta.fetch('contenSize', nil)),
226
229
  'formats' => Array.wrap(meta.fetch('encodingFormat',
227
230
  nil) || meta.fetch('fileFormat', nil)),
@@ -230,7 +233,6 @@ module Commonmeta
230
233
  else
231
234
  [{ 'title' => meta.fetch('headline', nil) }]
232
235
  end,
233
- 'creators' => creators,
234
236
  'contributors' => contributors,
235
237
  'publisher' => { 'name' => publisher },
236
238
  'provider' => parse_attributes(meta.fetch('provider', nil), content: 'name', first: true),
@@ -5,7 +5,7 @@ require "pathname"
5
5
 
6
6
  module Commonmeta
7
7
  module SchemaUtils
8
- COMMONMETA = File.read(File.expand_path("../../resources/commonmeta_v0.9.3.json",
8
+ COMMONMETA = File.read(File.expand_path("../../resources/commonmeta_v0.10.3.json",
9
9
  __dir__))
10
10
 
11
11
  def json_schema_errors
@@ -869,7 +869,7 @@ module Commonmeta
869
869
  end
870
870
 
871
871
  def map_hash_keys(element: nil, mapping: nil)
872
- Array.wrap(element).map do |a|
872
+ a = Array.wrap(element).map do |a|
873
873
  a.map { |k, v| [mapping.fetch(k, k), v] }.reduce({}) do |hsh, (k, v)|
874
874
  if k == "affiliation" && v.is_a?(Array)
875
875
  hsh[k] = v.map do |affiliation|
@@ -883,6 +883,8 @@ module Commonmeta
883
883
  elsif k == "type" && v.is_a?(String)
884
884
  hsh[k] = v.capitalize
885
885
  hsh
886
+ elsif k == "contributorRoles"
887
+ hsh
886
888
  elsif v.is_a?(Hash)
887
889
  hsh[k] = to_schema_org(v)
888
890
  hsh
@@ -930,7 +932,7 @@ module Commonmeta
930
932
  a["given"] = a["givenName"]
931
933
  a["literal"] = a["name"] unless a["familyName"].present?
932
934
  a.except("nameType", "type", "@type", "id", "@id", "name", "familyName", "givenName",
933
- "affiliation", "contributorType").compact
935
+ "affiliation", "contributorRoles").compact
934
936
  end.presence
935
937
  end
936
938
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Commonmeta
4
- VERSION = '3.4.5'
4
+ VERSION = '3.5.1'
5
5
  end
@@ -13,7 +13,7 @@ module Commonmeta
13
13
  bibtex_key: normalize_id(id),
14
14
  doi: doi_from_url(id),
15
15
  url: url,
16
- author: authors_as_string(creators),
16
+ author: authors_as_string(contributors),
17
17
  keywords: if subjects.present?
18
18
  Array.wrap(subjects).map do |k|
19
19
  parse_attributes(k, content: 'subject', first: true)
@@ -10,14 +10,15 @@ module Commonmeta
10
10
  return nil unless %w[Software Collection].include?(type)
11
11
 
12
12
  title = parse_attributes(titles, content: 'title', first: true)
13
-
13
+ authors = Array.wrap(contributors).select { |c| c['contributorRoles'] == ['Author'] }
14
+
14
15
  hsh = {
15
16
  'cff-version' => '1.2.0',
16
17
  'message' => "If you use #{title} in your research, please cite it using the following metadata",
17
18
  'doi' => normalize_doi(id),
18
19
  'repository-code' => url,
19
20
  'title' => title,
20
- 'authors' => write_cff_creators(creators),
21
+ 'authors' => write_cff_contributors(authors),
21
22
  'abstract' => parse_attributes(descriptions, content: 'description', first: true),
22
23
  'version' => version,
23
24
  'keywords' => if subjects.present?
@@ -34,8 +35,8 @@ module Commonmeta
34
35
  hsh.to_yaml
35
36
  end
36
37
 
37
- def write_cff_creators(creators)
38
- Array.wrap(creators).map do |a|
38
+ def write_cff_contributors(contributors)
39
+ Array.wrap(contributors).map do |a|
39
40
  if a['givenName'].present? || a['id'].present?
40
41
  { 'given-names' => a['givenName'],
41
42
  'family-names' => a['familyName'],