commonmeta-ruby 3.0.5 → 3.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,439 +3,439 @@
3
3
  module Commonmeta
4
4
  module Utils
5
5
  NORMALIZED_LICENSES = {
6
- 'https://creativecommons.org/licenses/by/1.0' => 'https://creativecommons.org/licenses/by/1.0/legalcode',
7
- 'https://creativecommons.org/licenses/by/2.0' => 'https://creativecommons.org/licenses/by/2.0/legalcode',
8
- 'https://creativecommons.org/licenses/by/2.5' => 'https://creativecommons.org/licenses/by/2.5/legalcode',
9
- 'https://creativecommons.org/licenses/by/3.0' => 'https://creativecommons.org/licenses/by/3.0/legalcode',
10
- 'https://creativecommons.org/licenses/by/3.0/us' => 'https://creativecommons.org/licenses/by/3.0/legalcode',
11
- 'https://creativecommons.org/licenses/by/4.0' => 'https://creativecommons.org/licenses/by/4.0/legalcode',
12
- 'https://creativecommons.org/licenses/by-nc/1.0' => 'https://creativecommons.org/licenses/by-nc/1.0/legalcode',
13
- 'https://creativecommons.org/licenses/by-nc/2.0' => 'https://creativecommons.org/licenses/by-nc/2.0/legalcode',
14
- 'https://creativecommons.org/licenses/by-nc/2.5' => 'https://creativecommons.org/licenses/by-nc/2.5/legalcode',
15
- 'https://creativecommons.org/licenses/by-nc/3.0' => 'https://creativecommons.org/licenses/by-nc/3.0/legalcode',
16
- 'https://creativecommons.org/licenses/by-nc/4.0' => 'https://creativecommons.org/licenses/by-nc/4.0/legalcode',
17
- 'https://creativecommons.org/licenses/by-nd-nc/1.0' => 'https://creativecommons.org/licenses/by-nd-nc/1.0/legalcode',
18
- 'https://creativecommons.org/licenses/by-nd-nc/2.0' => 'https://creativecommons.org/licenses/by-nd-nc/2.0/legalcode',
19
- 'https://creativecommons.org/licenses/by-nd-nc/2.5' => 'https://creativecommons.org/licenses/by-nd-nc/2.5/legalcode',
20
- 'https://creativecommons.org/licenses/by-nd-nc/3.0' => 'https://creativecommons.org/licenses/by-nd-nc/3.0/legalcode',
21
- 'https://creativecommons.org/licenses/by-nd-nc/4.0' => 'https://creativecommons.org/licenses/by-nd-nc/4.0/legalcode',
22
- 'https://creativecommons.org/licenses/by-nc-sa/1.0' => 'https://creativecommons.org/licenses/by-nc-sa/1.0/legalcode',
23
- 'https://creativecommons.org/licenses/by-nc-sa/2.0' => 'https://creativecommons.org/licenses/by-nc-sa/2.0/legalcode',
24
- 'https://creativecommons.org/licenses/by-nc-sa/2.5' => 'https://creativecommons.org/licenses/by-nc-sa/2.5/legalcode',
25
- 'https://creativecommons.org/licenses/by-nc-sa/3.0' => 'https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode',
26
- 'https://creativecommons.org/licenses/by-nc-sa/4.0' => 'https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode',
27
- 'https://creativecommons.org/licenses/by-nd/1.0' => 'https://creativecommons.org/licenses/by-nd/1.0/legalcode',
28
- 'https://creativecommons.org/licenses/by-nd/2.0' => 'https://creativecommons.org/licenses/by-nd/2.0/legalcode',
29
- 'https://creativecommons.org/licenses/by-nd/2.5' => 'https://creativecommons.org/licenses/by-nd/2.5/legalcode',
30
- 'https://creativecommons.org/licenses/by-nd/3.0' => 'https://creativecommons.org/licenses/by-nd/3.0/legalcode',
31
- 'https://creativecommons.org/licenses/by-nd/4.0' => 'https://creativecommons.org/licenses/by-nd/2.0/legalcode',
32
- 'https://creativecommons.org/licenses/by-sa/1.0' => 'https://creativecommons.org/licenses/by-sa/1.0/legalcode',
33
- 'https://creativecommons.org/licenses/by-sa/2.0' => 'https://creativecommons.org/licenses/by-sa/2.0/legalcode',
34
- 'https://creativecommons.org/licenses/by-sa/2.5' => 'https://creativecommons.org/licenses/by-sa/2.5/legalcode',
35
- 'https://creativecommons.org/licenses/by-sa/3.0' => 'https://creativecommons.org/licenses/by-sa/3.0/legalcode',
36
- 'https://creativecommons.org/licenses/by-sa/4.0' => 'https://creativecommons.org/licenses/by-sa/4.0/legalcode',
37
- 'https://creativecommons.org/licenses/by-nc-nd/1.0' => 'https://creativecommons.org/licenses/by-nc-nd/1.0/legalcode',
38
- 'https://creativecommons.org/licenses/by-nc-nd/2.0' => 'https://creativecommons.org/licenses/by-nc-nd/2.0/legalcode',
39
- 'https://creativecommons.org/licenses/by-nc-nd/2.5' => 'https://creativecommons.org/licenses/by-nc-nd/2.5/legalcode',
40
- 'https://creativecommons.org/licenses/by-nc-nd/3.0' => 'https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode',
41
- 'https://creativecommons.org/licenses/by-nc-nd/4.0' => 'https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode',
42
- 'https://creativecommons.org/licenses/publicdomain' => 'https://creativecommons.org/licenses/publicdomain/',
43
- 'https://creativecommons.org/publicdomain/zero/1.0' => 'https://creativecommons.org/publicdomain/zero/1.0/legalcode'
6
+ "https://creativecommons.org/licenses/by/1.0" => "https://creativecommons.org/licenses/by/1.0/legalcode",
7
+ "https://creativecommons.org/licenses/by/2.0" => "https://creativecommons.org/licenses/by/2.0/legalcode",
8
+ "https://creativecommons.org/licenses/by/2.5" => "https://creativecommons.org/licenses/by/2.5/legalcode",
9
+ "https://creativecommons.org/licenses/by/3.0" => "https://creativecommons.org/licenses/by/3.0/legalcode",
10
+ "https://creativecommons.org/licenses/by/3.0/us" => "https://creativecommons.org/licenses/by/3.0/legalcode",
11
+ "https://creativecommons.org/licenses/by/4.0" => "https://creativecommons.org/licenses/by/4.0/legalcode",
12
+ "https://creativecommons.org/licenses/by-nc/1.0" => "https://creativecommons.org/licenses/by-nc/1.0/legalcode",
13
+ "https://creativecommons.org/licenses/by-nc/2.0" => "https://creativecommons.org/licenses/by-nc/2.0/legalcode",
14
+ "https://creativecommons.org/licenses/by-nc/2.5" => "https://creativecommons.org/licenses/by-nc/2.5/legalcode",
15
+ "https://creativecommons.org/licenses/by-nc/3.0" => "https://creativecommons.org/licenses/by-nc/3.0/legalcode",
16
+ "https://creativecommons.org/licenses/by-nc/4.0" => "https://creativecommons.org/licenses/by-nc/4.0/legalcode",
17
+ "https://creativecommons.org/licenses/by-nd-nc/1.0" => "https://creativecommons.org/licenses/by-nd-nc/1.0/legalcode",
18
+ "https://creativecommons.org/licenses/by-nd-nc/2.0" => "https://creativecommons.org/licenses/by-nd-nc/2.0/legalcode",
19
+ "https://creativecommons.org/licenses/by-nd-nc/2.5" => "https://creativecommons.org/licenses/by-nd-nc/2.5/legalcode",
20
+ "https://creativecommons.org/licenses/by-nd-nc/3.0" => "https://creativecommons.org/licenses/by-nd-nc/3.0/legalcode",
21
+ "https://creativecommons.org/licenses/by-nd-nc/4.0" => "https://creativecommons.org/licenses/by-nd-nc/4.0/legalcode",
22
+ "https://creativecommons.org/licenses/by-nc-sa/1.0" => "https://creativecommons.org/licenses/by-nc-sa/1.0/legalcode",
23
+ "https://creativecommons.org/licenses/by-nc-sa/2.0" => "https://creativecommons.org/licenses/by-nc-sa/2.0/legalcode",
24
+ "https://creativecommons.org/licenses/by-nc-sa/2.5" => "https://creativecommons.org/licenses/by-nc-sa/2.5/legalcode",
25
+ "https://creativecommons.org/licenses/by-nc-sa/3.0" => "https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode",
26
+ "https://creativecommons.org/licenses/by-nc-sa/4.0" => "https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode",
27
+ "https://creativecommons.org/licenses/by-nd/1.0" => "https://creativecommons.org/licenses/by-nd/1.0/legalcode",
28
+ "https://creativecommons.org/licenses/by-nd/2.0" => "https://creativecommons.org/licenses/by-nd/2.0/legalcode",
29
+ "https://creativecommons.org/licenses/by-nd/2.5" => "https://creativecommons.org/licenses/by-nd/2.5/legalcode",
30
+ "https://creativecommons.org/licenses/by-nd/3.0" => "https://creativecommons.org/licenses/by-nd/3.0/legalcode",
31
+ "https://creativecommons.org/licenses/by-nd/4.0" => "https://creativecommons.org/licenses/by-nd/2.0/legalcode",
32
+ "https://creativecommons.org/licenses/by-sa/1.0" => "https://creativecommons.org/licenses/by-sa/1.0/legalcode",
33
+ "https://creativecommons.org/licenses/by-sa/2.0" => "https://creativecommons.org/licenses/by-sa/2.0/legalcode",
34
+ "https://creativecommons.org/licenses/by-sa/2.5" => "https://creativecommons.org/licenses/by-sa/2.5/legalcode",
35
+ "https://creativecommons.org/licenses/by-sa/3.0" => "https://creativecommons.org/licenses/by-sa/3.0/legalcode",
36
+ "https://creativecommons.org/licenses/by-sa/4.0" => "https://creativecommons.org/licenses/by-sa/4.0/legalcode",
37
+ "https://creativecommons.org/licenses/by-nc-nd/1.0" => "https://creativecommons.org/licenses/by-nc-nd/1.0/legalcode",
38
+ "https://creativecommons.org/licenses/by-nc-nd/2.0" => "https://creativecommons.org/licenses/by-nc-nd/2.0/legalcode",
39
+ "https://creativecommons.org/licenses/by-nc-nd/2.5" => "https://creativecommons.org/licenses/by-nc-nd/2.5/legalcode",
40
+ "https://creativecommons.org/licenses/by-nc-nd/3.0" => "https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode",
41
+ "https://creativecommons.org/licenses/by-nc-nd/4.0" => "https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode",
42
+ "https://creativecommons.org/licenses/publicdomain" => "https://creativecommons.org/licenses/publicdomain/",
43
+ "https://creativecommons.org/publicdomain/zero/1.0" => "https://creativecommons.org/publicdomain/zero/1.0/legalcode",
44
44
  }
45
45
 
46
46
  # source: https://www.bibtex.com/e/entry-types/
47
47
  BIB_TO_CM_TRANSLATIONS = {
48
- 'article' => 'JournalArticle',
49
- 'book' => 'Book',
50
- 'booklet' => 'Book',
51
- 'inbook' => 'BookChapter',
52
- 'inproceedings' => 'ProceedingsArticle',
53
- 'manual' => 'Report',
54
- 'mastersthesis' => 'Dissertation',
55
- 'misc' => 'Other',
56
- 'phdthesis' => 'Dissertation',
57
- 'proceedings' => 'Proceedings',
58
- 'techreport' => 'Report',
59
- 'unpublished' => 'Manuscript'
48
+ "article" => "JournalArticle",
49
+ "book" => "Book",
50
+ "booklet" => "Book",
51
+ "inbook" => "BookChapter",
52
+ "inproceedings" => "ProceedingsArticle",
53
+ "manual" => "Report",
54
+ "mastersthesis" => "Dissertation",
55
+ "misc" => "Other",
56
+ "phdthesis" => "Dissertation",
57
+ "proceedings" => "Proceedings",
58
+ "techreport" => "Report",
59
+ "unpublished" => "Manuscript",
60
60
  }
61
61
 
62
62
  CM_TO_BIB_TRANSLATIONS = {
63
- 'Article' => 'article',
64
- 'Book' => 'book',
65
- 'BookChapter' => 'inbook',
66
- 'Dissertation' => 'phdthesis',
67
- 'JournalArticle' => 'article',
68
- 'Manuscript' => 'unpublished',
69
- 'Other' => 'misc',
70
- 'Proceedings' => 'proceedings',
71
- 'ProceedingsArticle' => 'inproceedings',
72
- 'Report' => 'techreport'
63
+ "Article" => "article",
64
+ "Book" => "book",
65
+ "BookChapter" => "inbook",
66
+ "Dissertation" => "phdthesis",
67
+ "JournalArticle" => "article",
68
+ "Manuscript" => "unpublished",
69
+ "Other" => "misc",
70
+ "Proceedings" => "proceedings",
71
+ "ProceedingsArticle" => "inproceedings",
72
+ "Report" => "techreport",
73
73
  }
74
74
 
75
75
  # source: https://docs.citationstyles.org/en/stable/specification.html?highlight=book#appendix-iii-types
76
76
  CSL_TO_CM_TRANSLATIONS = {
77
- 'article' => 'Article',
78
- 'article-journal' => 'JournalArticle',
79
- 'article-magazine' => 'Article',
80
- 'article-newspaper' => 'Article',
81
- 'bill' => 'LegalDocument',
82
- 'book' => 'Book',
83
- 'broadcast' => 'Audiovisual',
84
- 'chapter' => 'BookChapter',
85
- 'classic' => 'Book',
86
- 'collection' => 'Collection',
87
- 'dataset' => 'Dataset',
88
- 'document' => 'Document',
89
- 'entry' => 'Entry',
90
- 'entry-dictionary' => 'Entry',
91
- 'entry-encyclopedia' => 'Entry',
92
- 'event' => 'Event',
93
- 'figure' => 'Figure',
94
- 'graphic' => 'Image',
95
- 'hearing' => 'LegalDocument',
96
- 'interview' => 'Document',
97
- 'legal_case' => 'LegalDocument',
98
- 'legislation' => 'LegalDocument',
99
- 'manuscript' => 'Manuscript',
100
- 'map' => 'Map',
101
- 'motion_picture' => 'Audiovisual',
102
- 'musical_score' => 'Document',
103
- 'pamphlet' => 'Document',
104
- 'paper-conference' => 'ProceedingsArticle',
105
- 'patent' => 'Patent',
106
- 'performance' => 'Performance',
107
- 'periodical' => 'Journal',
108
- 'personal_communication' => 'PersonalCommunication',
109
- 'post' => 'Post',
110
- 'post-weblog' => 'Article',
111
- 'regulation' => 'LegalDocument',
112
- 'report' => 'Report',
113
- 'review' => 'Review',
114
- 'review-book' => 'Review',
115
- 'software' => 'Software',
116
- 'song' => 'Audiovisual',
117
- 'speech' => 'Speech',
118
- 'standard' => 'Standard',
119
- 'thesis' => 'Dissertation',
120
- 'treaty' => 'LegalDocument',
121
- 'webpage' => 'WebPage'
77
+ "article" => "Article",
78
+ "article-journal" => "JournalArticle",
79
+ "article-magazine" => "Article",
80
+ "article-newspaper" => "Article",
81
+ "bill" => "LegalDocument",
82
+ "book" => "Book",
83
+ "broadcast" => "Audiovisual",
84
+ "chapter" => "BookChapter",
85
+ "classic" => "Book",
86
+ "collection" => "Collection",
87
+ "dataset" => "Dataset",
88
+ "document" => "Document",
89
+ "entry" => "Entry",
90
+ "entry-dictionary" => "Entry",
91
+ "entry-encyclopedia" => "Entry",
92
+ "event" => "Event",
93
+ "figure" => "Figure",
94
+ "graphic" => "Image",
95
+ "hearing" => "LegalDocument",
96
+ "interview" => "Document",
97
+ "legal_case" => "LegalDocument",
98
+ "legislation" => "LegalDocument",
99
+ "manuscript" => "Manuscript",
100
+ "map" => "Map",
101
+ "motion_picture" => "Audiovisual",
102
+ "musical_score" => "Document",
103
+ "pamphlet" => "Document",
104
+ "paper-conference" => "ProceedingsArticle",
105
+ "patent" => "Patent",
106
+ "performance" => "Performance",
107
+ "periodical" => "Journal",
108
+ "personal_communication" => "PersonalCommunication",
109
+ "post" => "Post",
110
+ "post-weblog" => "Article",
111
+ "regulation" => "LegalDocument",
112
+ "report" => "Report",
113
+ "review" => "Review",
114
+ "review-book" => "Review",
115
+ "software" => "Software",
116
+ "song" => "Audiovisual",
117
+ "speech" => "Speech",
118
+ "standard" => "Standard",
119
+ "thesis" => "Dissertation",
120
+ "treaty" => "LegalDocument",
121
+ "webpage" => "WebPage",
122
122
  }
123
123
 
124
124
  CM_TO_CSL_TRANSLATIONS = {
125
- 'Article' => 'article',
126
- 'JournalArticle' => 'article-journal',
127
- 'Book' => 'book',
128
- 'BookChapter' => 'chapter',
129
- 'Collection' => 'collection',
130
- 'Dataset' => 'dataset',
131
- 'Document' => 'document',
132
- 'Entry' => 'entry',
133
- 'Event' => 'event',
134
- 'Figure' => 'figure',
135
- 'Image' => 'graphic',
136
- 'LegalDocument' => 'legal_case',
137
- 'Manuscript' => 'manuscript',
138
- 'Map' => 'map',
139
- 'Audiovisual' => 'motion_picture',
140
- 'Patent' => 'patent',
141
- 'Performance' => 'performance',
142
- 'Journal' => 'periodical',
143
- 'PersonalCommunication' => 'personal_communication',
144
- 'Post' => 'post',
145
- 'Report' => 'report',
146
- 'Review' => 'review',
147
- 'Software' => 'software',
148
- 'Speech' => 'speech',
149
- 'Standard' => 'standard',
150
- 'Dissertation' => 'thesis',
151
- 'WebPage' => 'webpage'
125
+ "Article" => "article",
126
+ "JournalArticle" => "article-journal",
127
+ "Book" => "book",
128
+ "BookChapter" => "chapter",
129
+ "Collection" => "collection",
130
+ "Dataset" => "dataset",
131
+ "Document" => "document",
132
+ "Entry" => "entry",
133
+ "Event" => "event",
134
+ "Figure" => "figure",
135
+ "Image" => "graphic",
136
+ "LegalDocument" => "legal_case",
137
+ "Manuscript" => "manuscript",
138
+ "Map" => "map",
139
+ "Audiovisual" => "motion_picture",
140
+ "Patent" => "patent",
141
+ "Performance" => "performance",
142
+ "Journal" => "periodical",
143
+ "PersonalCommunication" => "personal_communication",
144
+ "Post" => "post",
145
+ "Report" => "report",
146
+ "Review" => "review",
147
+ "Software" => "software",
148
+ "Speech" => "speech",
149
+ "Standard" => "standard",
150
+ "Dissertation" => "thesis",
151
+ "WebPage" => "webpage",
152
152
  }
153
153
 
154
154
  # source: http://api.crossref.org/types
155
155
  CR_TO_CM_TRANSLATIONS = {
156
- 'BookChapter' => 'BookChapter',
157
- 'BookPart' => 'BookPart',
158
- 'BookSection' => 'BookSection',
159
- 'BookSeries' => 'BookSeries',
160
- 'BookSet' => 'BookSet',
161
- 'BookTrack' => 'BookTrack',
162
- 'Book' => 'Book',
163
- 'Component' => 'Component',
164
- 'Database' => 'Database',
165
- 'Dataset' => 'Dataset',
166
- 'Dissertation' => 'Dissertation',
167
- 'EditedBook' => 'EditedBook',
168
- 'Grant' => 'Grant',
169
- 'JournalArticle' => 'JournalArticle',
170
- 'JournalIssue' => 'JournalIssue',
171
- 'JournalVolume' => 'JournalVolume',
172
- 'Journal' => 'Journal',
173
- 'Monograph' => 'Book',
174
- 'Other' => 'Other',
175
- 'PeerReview' => 'PeerReview',
176
- 'PostedContent' => 'Article',
177
- 'ProceedingsArticle' => 'ProceedingsArticle',
178
- 'ProceedingsSeries' => 'ProceedingsSeries',
179
- 'Proceedings' => 'Proceedings',
180
- 'ReferenceBook' => 'ReferenceBook',
181
- 'ReferenceEntry' => 'Entry',
182
- 'ReportComponent' => 'ReportComponent',
183
- 'ReportSeries' => 'ReportSeries',
184
- 'Report' => 'Report',
185
- 'Standard' => 'Standard'
156
+ "BookChapter" => "BookChapter",
157
+ "BookPart" => "BookPart",
158
+ "BookSection" => "BookSection",
159
+ "BookSeries" => "BookSeries",
160
+ "BookSet" => "BookSet",
161
+ "BookTrack" => "BookTrack",
162
+ "Book" => "Book",
163
+ "Component" => "Component",
164
+ "Database" => "Database",
165
+ "Dataset" => "Dataset",
166
+ "Dissertation" => "Dissertation",
167
+ "EditedBook" => "EditedBook",
168
+ "Grant" => "Grant",
169
+ "JournalArticle" => "JournalArticle",
170
+ "JournalIssue" => "JournalIssue",
171
+ "JournalVolume" => "JournalVolume",
172
+ "Journal" => "Journal",
173
+ "Monograph" => "Book",
174
+ "Other" => "Other",
175
+ "PeerReview" => "PeerReview",
176
+ "PostedContent" => "Article",
177
+ "ProceedingsArticle" => "ProceedingsArticle",
178
+ "ProceedingsSeries" => "ProceedingsSeries",
179
+ "Proceedings" => "Proceedings",
180
+ "ReferenceBook" => "ReferenceBook",
181
+ "ReferenceEntry" => "Entry",
182
+ "ReportComponent" => "ReportComponent",
183
+ "ReportSeries" => "ReportSeries",
184
+ "Report" => "Report",
185
+ "Standard" => "Standard",
186
186
  }
187
187
 
188
188
  CM_TO_CR_TRANSLATIONS = {
189
- 'Article' => 'PostedContent',
190
- 'BookChapter' => 'BookChapter',
191
- 'BookSeries' => 'BookSeries',
192
- 'Book' => 'Book',
193
- 'Component' => 'Component',
194
- 'Dataset' => 'Dataset',
195
- 'Dissertation' => 'Dissertation',
196
- 'Grant' => 'Grant',
197
- 'JournalArticle' => 'JournalArticle',
198
- 'JournalIssue' => 'JournalIssue',
199
- 'JournalVolume' => 'JournalVolume',
200
- 'Journal' => 'Journal',
201
- 'ProceedingsArticle' => 'ProceedingsArticle',
202
- 'ProceedingsSeries' => 'ProceedingsSeries',
203
- 'Proceedings' => 'Proceedings',
204
- 'ReportComponent' => 'ReportComponent',
205
- 'ReportSeries' => 'ReportSeries',
206
- 'Report' => 'Report',
207
- 'PeerReview' => 'PeerReview',
208
- 'Other' => 'Other'
189
+ "Article" => "PostedContent",
190
+ "BookChapter" => "BookChapter",
191
+ "BookSeries" => "BookSeries",
192
+ "Book" => "Book",
193
+ "Component" => "Component",
194
+ "Dataset" => "Dataset",
195
+ "Dissertation" => "Dissertation",
196
+ "Grant" => "Grant",
197
+ "JournalArticle" => "JournalArticle",
198
+ "JournalIssue" => "JournalIssue",
199
+ "JournalVolume" => "JournalVolume",
200
+ "Journal" => "Journal",
201
+ "ProceedingsArticle" => "ProceedingsArticle",
202
+ "ProceedingsSeries" => "ProceedingsSeries",
203
+ "Proceedings" => "Proceedings",
204
+ "ReportComponent" => "ReportComponent",
205
+ "ReportSeries" => "ReportSeries",
206
+ "Report" => "Report",
207
+ "PeerReview" => "PeerReview",
208
+ "Other" => "Other",
209
209
  }
210
210
 
211
211
  # source: https://github.com/datacite/schema/blob/master/source/meta/kernel-4/include/datacite-resourceType-v4.xsd
212
212
  DC_TO_CM_TRANSLATIONS = {
213
- 'Audiovisual' => 'Audiovisual',
214
- 'BlogPosting' => 'Article',
215
- 'Book' => 'Book',
216
- 'BookChapter' => 'BookChapter',
217
- 'Collection' => 'Collection',
218
- 'ComputationalNotebook' => 'ComputationalNotebook',
219
- 'ConferencePaper' => 'ProceedingsArticle',
220
- 'ConferenceProceeding' => 'Proceedings',
221
- 'DataPaper' => 'JournalArticle',
222
- 'Dataset' => 'Dataset',
223
- 'Dissertation' => 'Dissertation',
224
- 'Event' => 'Event',
225
- 'Image' => 'Image',
226
- 'InteractiveResource' => 'InteractiveResource',
227
- 'Journal' => 'Journal',
228
- 'JournalArticle' => 'JournalArticle',
229
- 'Model' => 'Model',
230
- 'OutputManagementPlan' => 'OutputManagementPlan',
231
- 'PeerReview' => 'PeerReview',
232
- 'PhysicalObject' => 'PhysicalObject',
233
- 'Poster' => 'Speech',
234
- 'Preprint' => 'Article',
235
- 'Report' => 'Report',
236
- 'Service' => 'Service',
237
- 'Software' => 'Software',
238
- 'Sound' => 'Sound',
239
- 'Standard' => 'Standard',
240
- 'Text' => 'Document',
241
- 'Thesis' => 'Dissertation',
242
- 'Workflow' => 'Workflow',
243
- 'Other' => 'Other'
213
+ "Audiovisual" => "Audiovisual",
214
+ "BlogPosting" => "Article",
215
+ "Book" => "Book",
216
+ "BookChapter" => "BookChapter",
217
+ "Collection" => "Collection",
218
+ "ComputationalNotebook" => "ComputationalNotebook",
219
+ "ConferencePaper" => "ProceedingsArticle",
220
+ "ConferenceProceeding" => "Proceedings",
221
+ "DataPaper" => "JournalArticle",
222
+ "Dataset" => "Dataset",
223
+ "Dissertation" => "Dissertation",
224
+ "Event" => "Event",
225
+ "Image" => "Image",
226
+ "InteractiveResource" => "InteractiveResource",
227
+ "Journal" => "Journal",
228
+ "JournalArticle" => "JournalArticle",
229
+ "Model" => "Model",
230
+ "OutputManagementPlan" => "OutputManagementPlan",
231
+ "PeerReview" => "PeerReview",
232
+ "PhysicalObject" => "PhysicalObject",
233
+ "Poster" => "Speech",
234
+ "Preprint" => "Article",
235
+ "Report" => "Report",
236
+ "Service" => "Service",
237
+ "Software" => "Software",
238
+ "Sound" => "Sound",
239
+ "Standard" => "Standard",
240
+ "Text" => "Document",
241
+ "Thesis" => "Dissertation",
242
+ "Workflow" => "Workflow",
243
+ "Other" => "Other",
244
244
  }
245
245
 
246
246
  CM_TO_DC_TRANSLATIONS = {
247
- 'Article' => 'Preprint',
248
- 'Audiovisual' => 'Audiovisual',
249
- 'Book' => 'Book',
250
- 'BookChapter' => 'BookChapter',
251
- 'Collection' => 'Collection',
252
- 'Dataset' => 'Dataset',
253
- 'Dissertation' => 'Dissertation',
254
- 'Document' => 'Text',
255
- 'Entry' => 'Text',
256
- 'Event' => 'Event',
257
- 'Figure' => 'Image',
258
- 'Image' => 'Image',
259
- 'JournalArticle' => 'JournalArticle',
260
- 'LegalDocument' => 'Text',
261
- 'Manuscript' => 'Text',
262
- 'Map' => 'Image',
263
- 'Patent' => 'Text',
264
- 'Performance' => 'Audiovisual',
265
- 'PersonalCommunication' => 'Text',
266
- 'Post' => 'Text',
267
- 'ProceedingsArticle' => 'ConferencePaper',
268
- 'Proceedings' => 'ConferenceProceeding',
269
- 'Report' => 'Report',
270
- 'PeerReview' => 'PeerReview',
271
- 'Software' => 'Software',
272
- 'Sound' => 'Sound',
273
- 'Standard' => 'Standard',
274
- 'WebPage' => 'Text'
247
+ "Article" => "Preprint",
248
+ "Audiovisual" => "Audiovisual",
249
+ "Book" => "Book",
250
+ "BookChapter" => "BookChapter",
251
+ "Collection" => "Collection",
252
+ "Dataset" => "Dataset",
253
+ "Dissertation" => "Dissertation",
254
+ "Document" => "Text",
255
+ "Entry" => "Text",
256
+ "Event" => "Event",
257
+ "Figure" => "Image",
258
+ "Image" => "Image",
259
+ "JournalArticle" => "JournalArticle",
260
+ "LegalDocument" => "Text",
261
+ "Manuscript" => "Text",
262
+ "Map" => "Image",
263
+ "Patent" => "Text",
264
+ "Performance" => "Audiovisual",
265
+ "PersonalCommunication" => "Text",
266
+ "Post" => "Text",
267
+ "ProceedingsArticle" => "ConferencePaper",
268
+ "Proceedings" => "ConferenceProceeding",
269
+ "Report" => "Report",
270
+ "PeerReview" => "PeerReview",
271
+ "Software" => "Software",
272
+ "Sound" => "Sound",
273
+ "Standard" => "Standard",
274
+ "WebPage" => "Text",
275
275
  }
276
276
 
277
277
  RIS_TO_CM_TRANSLATIONS = {
278
- 'ABST' => 'Text',
279
- 'ADVS' => 'Text',
280
- 'AGGR' => 'Text',
281
- 'ANCIENT' => 'Text',
282
- 'ART' => 'Text',
283
- 'BILL' => 'Text',
284
- 'BLOG' => 'Text',
285
- 'BOOK' => 'Book',
286
- 'CASE' => 'Text',
287
- 'CHAP' => 'BookChapter',
288
- 'CHART' => 'Text',
289
- 'CLSWK' => 'Text',
290
- 'CTLG' => 'Collection',
291
- 'COMP' => 'Software',
292
- 'DATA' => 'Dataset',
293
- 'DBASE' => 'Database',
294
- 'DICT' => 'Dictionary',
295
- 'EBOOK' => 'Book',
296
- 'ECHAP' => 'BookChapter',
297
- 'EDBOOK' => 'Book',
298
- 'EJOUR' => 'JournalArticle',
299
- 'ELEC' => 'Text',
300
- 'ENCYC' => 'Encyclopedia',
301
- 'EQUA' => 'Equation',
302
- 'FIGURE' => 'Image',
303
- 'GEN' => 'CreativeWork',
304
- 'GOVDOC' => 'GovernmentDocument',
305
- 'GRANT' => 'Grant',
306
- 'HEAR' => 'Hearing',
307
- 'ICOMM' => 'Text',
308
- 'INPR' => 'Text',
309
- 'JFULL' => 'JournalArticle',
310
- 'JOUR' => 'JournalArticle',
311
- 'LEGAL' => 'LegalRuleOrRegulation',
312
- 'MANSCPT' => 'Text',
313
- 'MAP' => 'Map',
314
- 'MGZN' => 'MagazineArticle',
315
- 'MPCT' => 'Audiovisual',
316
- 'MULTI' => 'Audiovisual',
317
- 'MUSIC' => 'MusicScore',
318
- 'NEWS' => 'NewspaperArticle',
319
- 'PAMP' => 'Pamphlet',
320
- 'PAT' => 'Patent',
321
- 'PCOMM' => 'PersonalCommunication',
322
- 'RPRT' => 'Report',
323
- 'SER' => 'SerialPublication',
324
- 'SLIDE' => 'Slide',
325
- 'SOUND' => 'SoundRecording',
326
- 'STAND' => 'Standard',
327
- 'THES' => 'Dissertation',
328
- 'UNBILL' => 'UnenactedBill',
329
- 'UNPB' => 'UnpublishedWork',
330
- 'VIDEO' => 'Audiovisual',
331
- 'WEB' => 'WebPage'
278
+ "ABST" => "Text",
279
+ "ADVS" => "Text",
280
+ "AGGR" => "Text",
281
+ "ANCIENT" => "Text",
282
+ "ART" => "Text",
283
+ "BILL" => "Text",
284
+ "BLOG" => "Text",
285
+ "BOOK" => "Book",
286
+ "CASE" => "Text",
287
+ "CHAP" => "BookChapter",
288
+ "CHART" => "Text",
289
+ "CLSWK" => "Text",
290
+ "CTLG" => "Collection",
291
+ "COMP" => "Software",
292
+ "DATA" => "Dataset",
293
+ "DBASE" => "Database",
294
+ "DICT" => "Dictionary",
295
+ "EBOOK" => "Book",
296
+ "ECHAP" => "BookChapter",
297
+ "EDBOOK" => "Book",
298
+ "EJOUR" => "JournalArticle",
299
+ "ELEC" => "Text",
300
+ "ENCYC" => "Encyclopedia",
301
+ "EQUA" => "Equation",
302
+ "FIGURE" => "Image",
303
+ "GEN" => "CreativeWork",
304
+ "GOVDOC" => "GovernmentDocument",
305
+ "GRANT" => "Grant",
306
+ "HEAR" => "Hearing",
307
+ "ICOMM" => "Text",
308
+ "INPR" => "Text",
309
+ "JFULL" => "JournalArticle",
310
+ "JOUR" => "JournalArticle",
311
+ "LEGAL" => "LegalRuleOrRegulation",
312
+ "MANSCPT" => "Text",
313
+ "MAP" => "Map",
314
+ "MGZN" => "MagazineArticle",
315
+ "MPCT" => "Audiovisual",
316
+ "MULTI" => "Audiovisual",
317
+ "MUSIC" => "MusicScore",
318
+ "NEWS" => "NewspaperArticle",
319
+ "PAMP" => "Pamphlet",
320
+ "PAT" => "Patent",
321
+ "PCOMM" => "PersonalCommunication",
322
+ "RPRT" => "Report",
323
+ "SER" => "SerialPublication",
324
+ "SLIDE" => "Slide",
325
+ "SOUND" => "SoundRecording",
326
+ "STAND" => "Standard",
327
+ "THES" => "Dissertation",
328
+ "UNBILL" => "UnenactedBill",
329
+ "UNPB" => "UnpublishedWork",
330
+ "VIDEO" => "Audiovisual",
331
+ "WEB" => "WebPage",
332
332
  }
333
333
 
334
334
  CM_TO_RIS_TRANSLATIONS = {
335
- 'Article' => 'JOUR',
336
- 'Audiovisual' => 'VIDEO',
337
- 'Book' => 'BOOK',
338
- 'BookChapter' => 'CHAP',
339
- 'Collection' => 'CTLG',
340
- 'Dataset' => 'DATA',
341
- 'Dissertation' => 'THES',
342
- 'Document' => 'GEN',
343
- 'Entry' => 'DICT',
344
- 'Event' => 'GEN',
345
- 'Figure' => 'FIGURE',
346
- 'Image' => 'FIGURE',
347
- 'JournalArticle' => 'JOUR',
348
- 'LegalDocument' => 'GEN',
349
- 'Manuscript' => 'GEN',
350
- 'Map' => 'MAP',
351
- 'Patent' => 'PAT',
352
- 'Performance' => 'GEN',
353
- 'PersonalCommunication' => 'PCOMM',
354
- 'Post' => 'GEN',
355
- 'ProceedingsArticle' => 'CPAPER',
356
- 'Proceedings' => 'CONF',
357
- 'Report' => 'RPRT',
358
- 'Review' => 'GEN',
359
- 'Software' => 'COMP',
360
- 'Sound' => 'SOUND',
361
- 'Standard' => 'STAND',
362
- 'WebPage' => 'WEB'
335
+ "Article" => "JOUR",
336
+ "Audiovisual" => "VIDEO",
337
+ "Book" => "BOOK",
338
+ "BookChapter" => "CHAP",
339
+ "Collection" => "CTLG",
340
+ "Dataset" => "DATA",
341
+ "Dissertation" => "THES",
342
+ "Document" => "GEN",
343
+ "Entry" => "DICT",
344
+ "Event" => "GEN",
345
+ "Figure" => "FIGURE",
346
+ "Image" => "FIGURE",
347
+ "JournalArticle" => "JOUR",
348
+ "LegalDocument" => "GEN",
349
+ "Manuscript" => "GEN",
350
+ "Map" => "MAP",
351
+ "Patent" => "PAT",
352
+ "Performance" => "GEN",
353
+ "PersonalCommunication" => "PCOMM",
354
+ "Post" => "GEN",
355
+ "ProceedingsArticle" => "CPAPER",
356
+ "Proceedings" => "CONF",
357
+ "Report" => "RPRT",
358
+ "Review" => "GEN",
359
+ "Software" => "COMP",
360
+ "Sound" => "SOUND",
361
+ "Standard" => "STAND",
362
+ "WebPage" => "WEB",
363
363
  }
364
364
 
365
365
  SO_TO_CM_TRANSLATIONS = {
366
- 'Article' => 'Article',
367
- 'BlogPosting' => 'Article',
368
- 'Book' => 'Book',
369
- 'BookChapter' => 'BookChapter',
370
- 'CreativeWork' => 'Other',
371
- 'Dataset' => 'Dataset',
372
- 'Dissertation' => 'Dissertation',
373
- 'NewsArticle' => 'Article',
374
- 'Legislation' => 'LegalDocument',
375
- 'ScholarlyArticle' => 'JournalArticle',
376
- 'SoftwareSourceCode' => 'Software'
366
+ "Article" => "Article",
367
+ "BlogPosting" => "Article",
368
+ "Book" => "Book",
369
+ "BookChapter" => "BookChapter",
370
+ "CreativeWork" => "Other",
371
+ "Dataset" => "Dataset",
372
+ "Dissertation" => "Dissertation",
373
+ "NewsArticle" => "Article",
374
+ "Legislation" => "LegalDocument",
375
+ "ScholarlyArticle" => "JournalArticle",
376
+ "SoftwareSourceCode" => "Software",
377
377
  }
378
378
 
379
379
  CM_TO_SO_TRANSLATIONS = {
380
- 'Article' => 'Article',
381
- 'Audiovisual' => 'CreativeWork',
382
- 'Book' => 'Book',
383
- 'BookChapter' => 'BookChapter',
384
- 'Collection' => 'CreativeWork',
385
- 'Dataset' => 'Dataset',
386
- 'Dissertation' => 'Dissertation',
387
- 'Document' => 'CreativeWork',
388
- 'Entry' => 'CreativeWork',
389
- 'Event' => 'CreativeWork',
390
- 'Figure' => 'CreativeWork',
391
- 'Image' => 'CreativeWork',
392
- 'JournalArticle' => 'ScholarlyArticle',
393
- 'LegalDocument' => 'Legislation',
394
- 'Software' => 'SoftwareSourceCode'
380
+ "Article" => "Article",
381
+ "Audiovisual" => "CreativeWork",
382
+ "Book" => "Book",
383
+ "BookChapter" => "BookChapter",
384
+ "Collection" => "CreativeWork",
385
+ "Dataset" => "Dataset",
386
+ "Dissertation" => "Dissertation",
387
+ "Document" => "CreativeWork",
388
+ "Entry" => "CreativeWork",
389
+ "Event" => "CreativeWork",
390
+ "Figure" => "CreativeWork",
391
+ "Image" => "CreativeWork",
392
+ "JournalArticle" => "ScholarlyArticle",
393
+ "LegalDocument" => "Legislation",
394
+ "Software" => "SoftwareSourceCode",
395
395
  }
396
396
 
397
397
  CM_TO_JATS_TRANSLATIONS = {
398
- 'Proceedings' => 'working-paper',
399
- 'ReferenceBook' => 'book',
400
- 'JournalIssue' => 'journal',
401
- 'ProceedingsArticle' => 'working-paper',
402
- 'Other' => nil,
403
- 'Dissertation' => nil,
404
- 'Dataset' => 'data',
405
- 'Document' => 'journal',
406
- 'EditedBook' => 'book',
407
- 'JournalArticle' => 'journal',
408
- 'Journal' => 'journal',
409
- 'Report' => 'report',
410
- 'BookSeries' => 'book',
411
- 'ReportSeries' => 'report',
412
- 'BookTrack' => 'book',
413
- 'Standard' => 'standard',
414
- 'BookSection' => 'chapter',
415
- 'BookPart' => 'chapter',
416
- 'Book' => 'book',
417
- 'BookChapter' => 'chapter',
418
- 'StandardSeries' => 'standard',
419
- 'Monograph' => 'book',
420
- 'Component' => nil,
421
- 'ReferenceEntry' => nil,
422
- 'JournalVolume' => 'journal',
423
- 'BookSet' => 'book',
424
- 'Article' => 'journal',
425
- 'Software' => 'software'
398
+ "Proceedings" => "working-paper",
399
+ "ReferenceBook" => "book",
400
+ "JournalIssue" => "journal",
401
+ "ProceedingsArticle" => "working-paper",
402
+ "Other" => nil,
403
+ "Dissertation" => nil,
404
+ "Dataset" => "data",
405
+ "Document" => "journal",
406
+ "EditedBook" => "book",
407
+ "JournalArticle" => "journal",
408
+ "Journal" => "journal",
409
+ "Report" => "report",
410
+ "BookSeries" => "book",
411
+ "ReportSeries" => "report",
412
+ "BookTrack" => "book",
413
+ "Standard" => "standard",
414
+ "BookSection" => "chapter",
415
+ "BookPart" => "chapter",
416
+ "Book" => "book",
417
+ "BookChapter" => "chapter",
418
+ "StandardSeries" => "standard",
419
+ "Monograph" => "book",
420
+ "Component" => nil,
421
+ "ReferenceEntry" => nil,
422
+ "JournalVolume" => "journal",
423
+ "BookSet" => "book",
424
+ "Article" => "journal",
425
+ "Software" => "software",
426
426
  }
427
427
 
428
428
  UNKNOWN_INFORMATION = {
429
- ':unac' => 'temporarily inaccessible',
430
- ':unal' => 'unallowed, suppressed intentionally',
431
- ':unap' => 'not applicable, makes no sense',
432
- ':unas' => 'value unassigned (e.g., Untitled)',
433
- ':unav' => 'value unavailable, possibly unknown',
434
- ':unkn' => 'known to be unknown (e.g., Anonymous, Inconnue)',
435
- ':none' => 'never had a value, never will',
436
- ':null' => 'explicitly and meaningfully empty',
437
- ':tba' => 'to be assigned or announced later',
438
- ':etal' => 'too numerous to list (et alia)'
429
+ ":unac" => "temporarily inaccessible",
430
+ ":unal" => "unallowed, suppressed intentionally",
431
+ ":unap" => "not applicable, makes no sense",
432
+ ":unas" => "value unassigned (e.g., Untitled)",
433
+ ":unav" => "value unavailable, possibly unknown",
434
+ ":unkn" => "known to be unknown (e.g., Anonymous, Inconnue)",
435
+ ":none" => "never had a value, never will",
436
+ ":null" => "explicitly and meaningfully empty",
437
+ ":tba" => "to be assigned or announced later",
438
+ ":etal" => "too numerous to list (et alia)",
439
439
  }
440
440
 
441
441
  def find_from_format(id: nil, string: nil, ext: nil, filename: nil)
@@ -448,7 +448,7 @@ module Commonmeta
448
448
  elsif filename.present?
449
449
  find_from_format_by_filename(filename)
450
450
  else
451
- 'datacite'
451
+ "datacite"
452
452
  end
453
453
  end
454
454
 
@@ -459,35 +459,35 @@ module Commonmeta
459
459
  ra = get_doi_ra(id)
460
460
  %w[DataCite Crossref mEDRA KISTI JaLC OP].include?(ra) ? ra.downcase : nil
461
461
  elsif %r{\A(?:(http|https):/(/)?orcid\.org/)?(\d{4}-\d{4}-\d{4}-\d{3}[0-9X]+)\z}.match?(id)
462
- 'orcid'
462
+ "orcid"
463
463
  elsif %r{\A(http|https):/(/)?github\.com/(.+)/package.json\z}.match?(id)
464
- 'npm'
464
+ "npm"
465
465
  elsif %r{\A(http|https):/(/)?github\.com/(.+)/codemeta.json\z}.match?(id)
466
- 'codemeta'
466
+ "codemeta"
467
467
  elsif %r{\A(http|https):/(/)?github\.com/(.+)/CITATION.cff\z}.match?(id)
468
- 'cff'
468
+ "cff"
469
469
  elsif %r{\A(http|https):/(/)?github\.com/(.+)\z}.match?(id)
470
- 'cff'
470
+ "cff"
471
471
  else
472
- 'schema_org'
472
+ "schema_org"
473
473
  end
474
474
  end
475
475
 
476
476
  def find_from_format_by_filename(filename)
477
- if filename == 'package.json'
478
- 'npm'
479
- elsif filename == 'CITATION.cff'
480
- 'cff'
477
+ if filename == "package.json"
478
+ "npm"
479
+ elsif filename == "CITATION.cff"
480
+ "cff"
481
481
  end
482
482
  end
483
483
 
484
484
  def find_from_format_by_ext(string, options = {})
485
485
  case options[:ext]
486
- when '.bib'
487
- 'bibtex'
488
- when '.ris'
489
- 'ris'
490
- when '.xml', '.json'
486
+ when ".bib"
487
+ "bibtex"
488
+ when ".ris"
489
+ "ris"
490
+ when ".xml", ".json"
491
491
  find_from_format_by_string(string)
492
492
  end
493
493
  end
@@ -495,36 +495,36 @@ module Commonmeta
495
495
  def find_from_format_by_string(string)
496
496
  begin # try to parse as JSON
497
497
  hsh = MultiJson.load(string).to_h
498
- if hsh.dig('@context') && URI.parse(hsh.dig('@context')).host == 'schema.org'
499
- return 'schema_org'
500
- elsif hsh.dig('schemaVersion').to_s.start_with?('http://datacite.org/schema/kernel')
501
- return 'datacite'
502
- elsif hsh.dig('source') == 'Crossref'
503
- return 'crossref'
504
- elsif hsh.dig('issued', 'date-parts').present?
505
- return 'csl'
506
- elsif URI.parse(hsh.dig('@context')).to_s == 'https://raw.githubusercontent.com/codemeta/codemeta/master/codemeta.jsonld'
507
- return 'codemeta'
498
+ if hsh.dig("@context") && URI.parse(hsh.dig("@context")).host == "schema.org"
499
+ return "schema_org"
500
+ elsif hsh.dig("schemaVersion").to_s.start_with?("http://datacite.org/schema/kernel")
501
+ return "datacite"
502
+ elsif hsh.dig("source") == "Crossref"
503
+ return "crossref"
504
+ elsif hsh.dig("issued", "date-parts").present?
505
+ return "csl"
506
+ elsif URI.parse(hsh.dig("@context")).to_s == "https://raw.githubusercontent.com/codemeta/codemeta/master/codemeta.jsonld"
507
+ return "codemeta"
508
508
  end
509
509
  rescue MultiJson::ParseError
510
510
  end
511
511
 
512
512
  begin # try to parse as XML
513
513
  hsh = Hash.from_xml(string)
514
- return 'crossref_xml' if hsh.to_h.dig('crossref_result').present?
514
+ return "crossref_xml" if hsh.to_h.dig("crossref_result").present?
515
515
  rescue Nokogiri::XML::SyntaxError
516
516
  end
517
517
 
518
518
  begin # try to parse as YAML
519
519
  hsh = YAML.load(string, permitted_classes: [Date])
520
- return 'cff' if hsh.is_a?(Hash) && hsh.fetch('cff-version', nil).present?
520
+ return "cff" if hsh.is_a?(Hash) && hsh.fetch("cff-version", nil).present?
521
521
  rescue Psych::SyntaxError
522
522
  end
523
523
 
524
- if string.start_with?('TY - ')
525
- 'ris'
524
+ if string.start_with?("TY - ")
525
+ "ris"
526
526
  elsif BibTeX.parse(string).first
527
- 'bibtex'
527
+ "bibtex"
528
528
  end
529
529
  end
530
530
 
@@ -538,7 +538,7 @@ module Commonmeta
538
538
 
539
539
  def validate_orcid(orcid)
540
540
  orcid = Array(%r{\A(?:(?:http|https)://(?:(?:www|sandbox)?\.)?orcid\.org/)?(\d{4}[[:space:]-]\d{4}[[:space:]-]\d{4}[[:space:]-]\d{3}[0-9X]+)\z}.match(orcid)).last
541
- orcid.gsub(/[[:space:]]/, '-') if orcid.present?
541
+ orcid.gsub(/[[:space:]]/, "-") if orcid.present?
542
542
  end
543
543
 
544
544
  def validate_orcid_scheme(orcid_scheme)
@@ -547,16 +547,16 @@ module Commonmeta
547
547
 
548
548
  def validate_url(str)
549
549
  if %r{\A(?:(http|https)://(dx\.)?doi.org/)?(doi:)?(10\.\d{4,5}/.+)\z}.match?(str)
550
- 'DOI'
550
+ "DOI"
551
551
  elsif %r{\A(http|https)://}.match?(str)
552
- 'URL'
552
+ "URL"
553
553
  elsif /\A(ISSN|eISSN) (\d{4}-\d{3}[0-9X]+)\z/.match?(str)
554
- 'ISSN'
554
+ "ISSN"
555
555
  end
556
556
  end
557
557
 
558
558
  def parse_attributes(element, options = {})
559
- content = options[:content] || '__content__'
559
+ content = options[:content] || "__content__"
560
560
 
561
561
  if element.is_a?(String) && options[:content].nil?
562
562
  CGI.unescapeHTML(element)
@@ -589,7 +589,7 @@ module Commonmeta
589
589
  return nil unless id.present?
590
590
 
591
591
  # handle info URIs
592
- return id if id.to_s.start_with?('info')
592
+ return id if id.to_s.start_with?("info")
593
593
 
594
594
  # check for valid HTTP uri
595
595
  uri = Addressable::URI.parse(id)
@@ -597,7 +597,7 @@ module Commonmeta
597
597
  return nil unless uri && uri.host && %w[http https ftp].include?(uri.scheme)
598
598
 
599
599
  # optionally turn into https URL
600
- uri.scheme = 'https' if options[:https]
600
+ uri.scheme = "https" if options[:https]
601
601
 
602
602
  # clean up URL
603
603
  uri.path = PostRank::URI.clean(uri.path)
@@ -617,52 +617,52 @@ module Commonmeta
617
617
  return nil unless orcid.present?
618
618
 
619
619
  # turn ORCID ID into URL
620
- 'https://orcid.org/' + Addressable::URI.encode(orcid)
620
+ "https://orcid.org/" + Addressable::URI.encode(orcid)
621
621
  end
622
622
 
623
623
  # pick electronic issn if there are multiple
624
624
  # format issn as xxxx-xxxx
625
625
  def normalize_issn(input, options = {})
626
- content = options[:content] || '__content__'
626
+ content = options[:content] || "__content__"
627
627
 
628
628
  issn = if input.blank?
629
- nil
630
- elsif input.is_a?(String) && options[:content].nil?
631
- input
632
- elsif input.is_a?(Hash)
633
- input.fetch(content, nil)
634
- elsif input.is_a?(Array)
635
- a = input.find { |a| a['media_type'] == 'electronic' } || input.first
636
- a.fetch(content, nil)
637
- end
629
+ nil
630
+ elsif input.is_a?(String) && options[:content].nil?
631
+ input
632
+ elsif input.is_a?(Hash)
633
+ input.fetch(content, nil)
634
+ elsif input.is_a?(Array)
635
+ a = input.find { |a| a["media_type"] == "electronic" } || input.first
636
+ a.fetch(content, nil)
637
+ end
638
638
 
639
639
  case issn.to_s.length
640
640
  when 9
641
641
  issn
642
642
  when 8
643
- issn[0..3] + '-' + issn[4..7]
643
+ issn[0..3] + "-" + issn[4..7]
644
644
  end
645
645
  end
646
646
 
647
647
  # find Creative Commons or OSI license in licenses array, normalize url and name
648
648
  def normalize_licenses(licenses)
649
649
  standard_licenses = Array.wrap(licenses).map do |l|
650
- URI.parse(l['url'])
650
+ URI.parse(l["url"])
651
651
  end.select { |li| li.host && li.host[/(creativecommons.org|opensource.org)$/] }
652
652
  return licenses unless standard_licenses.present?
653
653
 
654
654
  # use HTTPS
655
- uri.scheme = 'https'
655
+ uri.scheme = "https"
656
656
 
657
657
  # use host name without subdomain
658
658
  uri.host = Array(/(creativecommons.org|opensource.org)/.match uri.host).last
659
659
 
660
660
  # normalize URLs
661
- if uri.host == 'creativecommons.org'
662
- uri.path = uri.path.split('/')[0..-2].join('/') if uri.path.split('/').last == 'legalcode'
663
- uri.path << '/' unless uri.path.end_with?('/')
661
+ if uri.host == "creativecommons.org"
662
+ uri.path = uri.path.split("/")[0..-2].join("/") if uri.path.split("/").last == "legalcode"
663
+ uri.path << "/" unless uri.path.end_with?("/")
664
664
  else
665
- uri.path = uri.path.gsub(/(-license|\.php|\.html)/, '')
665
+ uri.path = uri.path.gsub(/(-license|\.php|\.html)/, "")
666
666
  uri.path = uri.path.sub(/(mit|afl|apl|osl|gpl|ecl)/) { |match| match.upcase }
667
667
  uri.path = uri.path.sub(/(artistic|apache)/) { |match| match.titleize }
668
668
  uri.path = uri.path.sub(/([^0-9-]+)(-)?([1-9])?(\.)?([0-9])?$/) do
@@ -670,8 +670,8 @@ module Commonmeta
670
670
  text = m[1]
671
671
 
672
672
  if m[3].present?
673
- version = [m[3], m[5].presence || '0'].join('.')
674
- [text, version].join('-')
673
+ version = [m[3], m[5].presence || "0"].join(".")
674
+ [text, version].join("-")
675
675
  else
676
676
  text
677
677
  end
@@ -693,13 +693,13 @@ module Commonmeta
693
693
  end
694
694
 
695
695
  def from_datacite(element)
696
- mapping = { 'nameType' => 'type', 'creatorName' => 'name' }
696
+ mapping = { "nameType" => "type", "creatorName" => "name" }
697
697
 
698
698
  map_hash_keys(element: element, mapping: mapping)
699
699
  end
700
700
 
701
701
  def to_schema_org(element)
702
- mapping = { 'type' => '@type', 'id' => '@id', 'title' => 'name' }
702
+ mapping = { "type" => "@type", "id" => "@id", "title" => "name" }
703
703
 
704
704
  map_hash_keys(element: element, mapping: mapping)
705
705
  end
@@ -707,20 +707,20 @@ module Commonmeta
707
707
  def to_schema_org_container(element, options = {})
708
708
  return nil unless element.is_a?(Hash) || (element.nil? && options[:container_title].present?)
709
709
 
710
- issn = element['identifier'] if element['identifierType'] == 'ISSN'
711
- id = issn.blank? ? element['identifier'] : nil
712
- name = options[:container_title] || element['title']
713
- type = id || name ? options[:type] || element['type'] : nil
710
+ issn = element["identifier"] if element["identifierType"] == "ISSN"
711
+ id = issn.blank? ? element["identifier"] : nil
712
+ name = options[:container_title] || element["title"]
713
+ type = id || name ? options[:type] || element["type"] : nil
714
714
 
715
- { '@id' => id, '@type' => type, 'name' => name, 'issn' => issn }.compact
715
+ { "@id" => id, "@type" => type, "name" => name, "issn" => issn }.compact
716
716
  end
717
717
 
718
718
  def to_schema_org_identifiers(element, _options = {})
719
719
  Array.wrap(element).map do |ai|
720
720
  {
721
- '@type' => 'PropertyValue',
722
- 'propertyID' => ai['alternateIdentifierType'],
723
- 'value' => ai['alternateIdentifier']
721
+ "@type" => "PropertyValue",
722
+ "propertyID" => ai["alternateIdentifierType"],
723
+ "value" => ai["alternateIdentifier"],
724
724
  }
725
725
  end.unwrap
726
726
  end
@@ -728,22 +728,22 @@ module Commonmeta
728
728
  def to_schema_org_relation(related_identifiers: nil, relation_type: nil)
729
729
  return nil unless related_identifiers.present? && relation_type.present?
730
730
 
731
- relation_type = if relation_type == 'References'
732
- %w[References Cites
733
- Documents]
734
- else
735
- [relation_type]
736
- end
731
+ relation_type = if relation_type == "References"
732
+ %w[References Cites
733
+ Documents]
734
+ else
735
+ [relation_type]
736
+ end
737
737
 
738
738
  Array.wrap(related_identifiers).select do |ri|
739
- relation_type.include?(ri['relationType'])
739
+ relation_type.include?(ri["relationType"])
740
740
  end.map do |r|
741
- if r['relatedIdentifierType'] == 'ISSN' && r['relationType'] == 'IsPartOf'
742
- { '@type' => 'Periodical', 'issn' => r['relatedIdentifier'] }.compact
741
+ if r["relatedIdentifierType"] == "ISSN" && r["relationType"] == "IsPartOf"
742
+ { "@type" => "Periodical", "issn" => r["relatedIdentifier"] }.compact
743
743
  else
744
744
  {
745
- '@id' => normalize_id(r['relatedIdentifier']),
746
- '@type' => DC_TO_SO_TRANSLATIONS[r['resourceTypeGeneral']] || 'CreativeWork'
745
+ "@id" => normalize_id(r["relatedIdentifier"]),
746
+ "@type" => DC_TO_SO_TRANSLATIONS[r["resourceTypeGeneral"]] || "CreativeWork",
747
747
  }.compact
748
748
  end
749
749
  end.unwrap
@@ -754,9 +754,9 @@ module Commonmeta
754
754
 
755
755
  Array.wrap(funding_references).map do |fr|
756
756
  {
757
- '@id' => fr['funderIdentifier'],
758
- '@type' => 'Organization',
759
- 'name' => fr['funderName']
757
+ "@id" => fr["funderIdentifier"],
758
+ "@type" => "Organization",
759
+ "name" => fr["funderName"],
760
760
  }.compact
761
761
  end.unwrap
762
762
  end
@@ -765,10 +765,10 @@ module Commonmeta
765
765
  return nil unless reference.present?
766
766
 
767
767
  {
768
- '@type' => 'CreativeWork',
769
- '@id' => reference['doi'] ? normalize_id(reference['doi']) : nil,
770
- 'name' => reference['title'],
771
- 'datePublished' => reference['publicationYear']
768
+ "@type" => "CreativeWork",
769
+ "@id" => reference["doi"] ? normalize_id(reference["doi"]) : nil,
770
+ "name" => reference["title"],
771
+ "datePublished" => reference["publicationYear"],
772
772
  }.compact
773
773
  end
774
774
 
@@ -776,67 +776,67 @@ module Commonmeta
776
776
  return nil unless geo_location.present?
777
777
 
778
778
  Array.wrap(geo_location).each_with_object([]) do |gl, sum|
779
- if gl.fetch('geoLocationPoint', nil)
779
+ if gl.fetch("geoLocationPoint", nil)
780
780
  sum << {
781
- '@type' => 'Place',
782
- 'geo' => {
783
- '@type' => 'GeoCoordinates',
784
- 'address' => gl['geoLocationPlace'],
785
- 'latitude' => gl.dig('geoLocationPoint', 'pointLatitude'),
786
- 'longitude' => gl.dig('geoLocationPoint', 'pointLongitude')
787
- }
781
+ "@type" => "Place",
782
+ "geo" => {
783
+ "@type" => "GeoCoordinates",
784
+ "address" => gl["geoLocationPlace"],
785
+ "latitude" => gl.dig("geoLocationPoint", "pointLatitude"),
786
+ "longitude" => gl.dig("geoLocationPoint", "pointLongitude"),
787
+ },
788
788
  }.compact
789
789
  end
790
790
 
791
- if gl.fetch('geoLocationBox', nil)
791
+ if gl.fetch("geoLocationBox", nil)
792
792
  sum << {
793
- '@type' => 'Place',
794
- 'geo' => {
795
- '@type' => 'GeoShape',
796
- 'address' => gl['geoLocationPlace'],
797
- 'box' => [gl.dig('geoLocationBox', 'southBoundLatitude'),
798
- gl.dig('geoLocationBox', 'westBoundLongitude'),
799
- gl.dig('geoLocationBox', 'northBoundLatitude'),
800
- gl.dig('geoLocationBox', 'eastBoundLongitude')].compact.join(' ').presence
801
- }.compact
793
+ "@type" => "Place",
794
+ "geo" => {
795
+ "@type" => "GeoShape",
796
+ "address" => gl["geoLocationPlace"],
797
+ "box" => [gl.dig("geoLocationBox", "southBoundLatitude"),
798
+ gl.dig("geoLocationBox", "westBoundLongitude"),
799
+ gl.dig("geoLocationBox", "northBoundLatitude"),
800
+ gl.dig("geoLocationBox", "eastBoundLongitude")].compact.join(" ").presence,
801
+ }.compact,
802
802
  }.compact
803
803
  end
804
804
 
805
- if gl.fetch('geoLocationPolygon', nil)
805
+ if gl.fetch("geoLocationPolygon", nil)
806
806
  sum << {
807
- '@type' => 'Place',
808
- 'geo' => {
809
- '@type' => 'GeoShape',
810
- 'address' => gl['geoLocationPlace'],
811
- 'polygon' => Array.wrap(gl.dig('geoLocationPolygon')).map do |glp|
807
+ "@type" => "Place",
808
+ "geo" => {
809
+ "@type" => "GeoShape",
810
+ "address" => gl["geoLocationPlace"],
811
+ "polygon" => Array.wrap(gl.dig("geoLocationPolygon")).map do |glp|
812
812
  Array.wrap(glp).map do |glpp|
813
- [glpp.dig('polygonPoint', 'pointLongitude'),
814
- glpp.dig('polygonPoint', 'pointLatitude')].compact
813
+ [glpp.dig("polygonPoint", "pointLongitude"),
814
+ glpp.dig("polygonPoint", "pointLatitude")].compact
815
815
  end.compact
816
- end.compact.presence
817
- }
816
+ end.compact.presence,
817
+ },
818
818
  }
819
819
  end
820
820
 
821
- next unless gl.fetch('geoLocationPlace',
822
- nil) && !gl.fetch('geoLocationPoint',
823
- nil) && !gl.fetch('geoLocationBox',
821
+ next unless gl.fetch("geoLocationPlace",
822
+ nil) && !gl.fetch("geoLocationPoint",
823
+ nil) && !gl.fetch("geoLocationBox",
824
824
  nil) && !gl.fetch(
825
- 'geoLocationPolygon', nil
826
- )
825
+ "geoLocationPolygon", nil
826
+ )
827
827
 
828
828
  sum << {
829
- '@type' => 'Place',
830
- 'geo' => {
831
- '@type' => 'GeoCoordinates',
832
- 'address' => gl['geoLocationPlace']
833
- }
829
+ "@type" => "Place",
830
+ "geo" => {
831
+ "@type" => "GeoCoordinates",
832
+ "address" => gl["geoLocationPlace"],
833
+ },
834
834
  }.compact
835
835
  end.unwrap
836
836
  end
837
837
 
838
838
  def from_schema_org(element)
839
- mapping = { '@type' => 'type', '@id' => 'id' }
839
+ mapping = { "@type" => "type", "@id" => "id" }
840
840
 
841
841
  map_hash_keys(element: element, mapping: mapping)
842
842
  end
@@ -844,16 +844,16 @@ module Commonmeta
844
844
  def map_hash_keys(element: nil, mapping: nil)
845
845
  Array.wrap(element).map do |a|
846
846
  a.map { |k, v| [mapping.fetch(k, k), v] }.reduce({}) do |hsh, (k, v)|
847
- if k == 'affiliation' && v.is_a?(Array)
847
+ if k == "affiliation" && v.is_a?(Array)
848
848
  hsh[k] = v.map do |affiliation|
849
849
  if affiliation.is_a?(Hash)
850
- affiliation.merge('@type' => 'Organization')
850
+ affiliation.merge("@type" => "Organization")
851
851
  else
852
852
  affiliation
853
853
  end
854
854
  end
855
855
  hsh
856
- elsif k == 'type' && v.is_a?(String)
856
+ elsif k == "type" && v.is_a?(String)
857
857
  hsh[k] = v.capitalize
858
858
  hsh
859
859
  elsif v.is_a?(Hash)
@@ -869,51 +869,51 @@ module Commonmeta
869
869
 
870
870
  def to_identifier(identifier)
871
871
  {
872
- '@type' => 'PropertyValue',
873
- 'propertyID' => identifier['relatedIdentifierType'],
874
- 'value' => identifier['relatedIdentifier']
872
+ "@type" => "PropertyValue",
873
+ "propertyID" => identifier["relatedIdentifierType"],
874
+ "value" => identifier["relatedIdentifier"],
875
875
  }
876
876
  end
877
877
 
878
878
  def from_csl(element)
879
879
  Array.wrap(element).map do |a|
880
- if a['literal'].present?
881
- a['type'] = 'Organization'
882
- a['name'] = a['literal']
883
- elsif a['name'].present?
884
- a['type'] = 'Organization'
885
- elsif a['given'].present? || a['family'].present?
886
- a['type'] = 'Person'
880
+ if a["literal"].present?
881
+ a["type"] = "Organization"
882
+ a["name"] = a["literal"]
883
+ elsif a["name"].present?
884
+ a["type"] = "Organization"
885
+ elsif a["given"].present? || a["family"].present?
886
+ a["type"] = "Person"
887
887
  end
888
- a['givenName'] = a['given']
889
- a['familyName'] = a['family']
890
- a.except('given', 'family', 'literal').compact
888
+ a["givenName"] = a["given"]
889
+ a["familyName"] = a["family"]
890
+ a.except("given", "family", "literal").compact
891
891
  end.unwrap
892
892
  end
893
893
 
894
894
  def to_csl(element)
895
895
  Array.wrap(element).map do |a|
896
- a['family'] = a['familyName']
897
- a['given'] = a['givenName']
898
- a['literal'] = a['name'] unless a['familyName'].present?
899
- a.except('nameType', 'type', '@type', 'id', '@id', 'name', 'familyName', 'givenName',
900
- 'affiliation', 'contributorType').compact
896
+ a["family"] = a["familyName"]
897
+ a["given"] = a["givenName"]
898
+ a["literal"] = a["name"] unless a["familyName"].present?
899
+ a.except("nameType", "type", "@type", "id", "@id", "name", "familyName", "givenName",
900
+ "affiliation", "contributorType").compact
901
901
  end.presence
902
902
  end
903
903
 
904
904
  def to_ris(element)
905
905
  Array.wrap(element).map do |a|
906
- if a['familyName'].present?
907
- [a['familyName'], a['givenName']].join(', ')
906
+ if a["familyName"].present?
907
+ [a["familyName"], a["givenName"]].join(", ")
908
908
  else
909
- a['name']
909
+ a["name"]
910
910
  end
911
911
  end.unwrap
912
912
  end
913
913
 
914
914
  def sanitize(text, options = {})
915
915
  options[:tags] ||= Set.new(%w[strong em b i code pre sub sup br])
916
- content = options[:content] || '__content__'
916
+ content = options[:content] || "__content__"
917
917
  custom_scrubber = Commonmeta::WhitelistScrubber.new(options)
918
918
 
919
919
  if text.is_a?(String)
@@ -930,8 +930,8 @@ module Commonmeta
930
930
  def github_from_url(url)
931
931
  return {} unless %r{\Ahttps://github\.com/(.+)(?:/)?(.+)?(?:/tree/)?(.*)\z}.match?(url)
932
932
 
933
- words = URI.parse(url).path[1..-1].split('/')
934
- path = words.length > 3 ? words[4...words.length].join('/') : nil
933
+ words = URI.parse(url).path[1..-1].split("/")
934
+ path = words.length > 3 ? words[4...words.length].join("/") : nil
935
935
 
936
936
  { owner: words[0], repo: words[1], release: words[3], path: path }.compact
937
937
  end
@@ -970,7 +970,7 @@ module Commonmeta
970
970
  def github_as_codemeta_url(url)
971
971
  github_hash = github_from_url(url)
972
972
 
973
- if github_hash[:path].to_s.end_with?('codemeta.json')
973
+ if github_hash[:path].to_s.end_with?("codemeta.json")
974
974
  "https://raw.githubusercontent.com/#{github_hash[:owner]}/#{github_hash[:repo]}/#{github_hash[:release]}/#{github_hash[:path]}"
975
975
  elsif github_hash[:owner].present?
976
976
  "https://raw.githubusercontent.com/#{github_hash[:owner]}/#{github_hash[:repo]}/master/codemeta.json"
@@ -980,7 +980,7 @@ module Commonmeta
980
980
  def github_as_cff_url(url)
981
981
  github_hash = github_from_url(url)
982
982
 
983
- if github_hash[:path].to_s.end_with?('CITATION.cff')
983
+ if github_hash[:path].to_s.end_with?("CITATION.cff")
984
984
  "https://raw.githubusercontent.com/#{github_hash[:owner]}/#{github_hash[:repo]}/#{github_hash[:release]}/#{github_hash[:path]}"
985
985
  elsif github_hash[:owner].present?
986
986
  "https://raw.githubusercontent.com/#{github_hash[:owner]}/#{github_hash[:repo]}/main/CITATION.cff"
@@ -988,18 +988,18 @@ module Commonmeta
988
988
  end
989
989
 
990
990
  def get_date_parts(iso8601_time)
991
- return { 'date-parts' => [[]] } if iso8601_time.nil?
991
+ return { "date-parts" => [[]] } if iso8601_time.nil?
992
992
 
993
993
  year = iso8601_time[0..3].to_i
994
994
  month = iso8601_time[5..6].to_i
995
995
  day = iso8601_time[8..9].to_i
996
- { 'date-parts' => [[year, month, day].reject { |part| part == 0 }] }
996
+ { "date-parts" => [[year, month, day].reject { |part| part == 0 }] }
997
997
  rescue TypeError
998
998
  nil
999
999
  end
1000
1000
 
1001
1001
  def get_date_from_date_parts(date_as_parts)
1002
- date_parts = date_as_parts.fetch('date-parts', []).first
1002
+ date_parts = date_as_parts.fetch("date-parts", []).first
1003
1003
  return nil if date_parts == [nil]
1004
1004
 
1005
1005
  year = date_parts[0]
@@ -1011,13 +1011,13 @@ module Commonmeta
1011
1011
  end
1012
1012
 
1013
1013
  def get_date_from_parts(year, month = nil, day = nil)
1014
- [year.to_s.rjust(4, '0'), month.to_s.rjust(2, '0'), day.to_s.rjust(2, '0')].reject do |part|
1015
- part == '00'
1016
- end.join('-')
1014
+ [year.to_s.rjust(4, "0"), month.to_s.rjust(2, "0"), day.to_s.rjust(2, "0")].reject do |part|
1015
+ part == "00"
1016
+ end.join("-")
1017
1017
  end
1018
1018
 
1019
1019
  def get_date_parts_from_parts(year, month = nil, day = nil)
1020
- { 'date-parts' => [[year.to_i, month.to_i, day.to_i].reject { |part| part == 0 }] }
1020
+ { "date-parts" => [[year.to_i, month.to_i, day.to_i].reject { |part| part == 0 }] }
1021
1021
  end
1022
1022
 
1023
1023
  def get_iso8601_date(iso8601_time)
@@ -1064,9 +1064,9 @@ module Commonmeta
1064
1064
  # strip milliseconds if there is a time, as it interferes with edtc parsing
1065
1065
  # keep dates unchanged
1066
1066
  def strip_milliseconds(iso8601_time)
1067
- return iso8601_time.split(' ').first if iso8601_time.to_s.include? ' '
1067
+ return iso8601_time.split(" ").first if iso8601_time.to_s.include? " "
1068
1068
 
1069
- return iso8601_time.split('.').first + 'Z' if iso8601_time.to_s.include? '.'
1069
+ return iso8601_time.split(".").first + "Z" if iso8601_time.to_s.include? "."
1070
1070
 
1071
1071
  iso8601_time
1072
1072
  end
@@ -1074,64 +1074,64 @@ module Commonmeta
1074
1074
  # iso8601 datetime without hyphens and colons, used by Crossref
1075
1075
  # return nil if invalid
1076
1076
  def get_datetime_from_time(time)
1077
- DateTime.strptime(time.to_s, '%Y%m%d%H%M%S').strftime('%Y-%m-%dT%H:%M:%SZ')
1077
+ DateTime.strptime(time.to_s, "%Y%m%d%H%M%S").strftime("%Y-%m-%dT%H:%M:%SZ")
1078
1078
  rescue ArgumentError
1079
1079
  nil
1080
1080
  end
1081
1081
 
1082
1082
  def get_date(dates, date_type)
1083
- dd = Array.wrap(dates).find { |d| d['dateType'] == date_type } || {}
1084
- dd.fetch('date', nil)
1083
+ dd = Array.wrap(dates).find { |d| d["dateType"] == date_type } || {}
1084
+ dd.fetch("date", nil)
1085
1085
  end
1086
1086
 
1087
1087
  # convert commonmeta dates to DataCite format
1088
1088
  def get_dates_from_date(date)
1089
1089
  return nil if date.nil?
1090
1090
 
1091
- mapping = { 'published' => 'issued' }
1091
+ mapping = { "published" => "issued" }
1092
1092
 
1093
1093
  date = map_hash_keys(element: date, mapping: mapping)
1094
1094
 
1095
1095
  date.map do |k, v|
1096
- { 'date' => v,
1097
- 'dateType' => k.capitalize }
1096
+ { "date" => v,
1097
+ "dateType" => k.capitalize }
1098
1098
  end
1099
1099
  end
1100
1100
 
1101
1101
  def get_contributor(contributor, contributor_type)
1102
- contributor.select { |c| c['contributorType'] == contributor_type }
1102
+ contributor.select { |c| c["contributorType"] == contributor_type }
1103
1103
  end
1104
1104
 
1105
1105
  def get_identifier(identifiers, identifier_type)
1106
- id = Array.wrap(identifiers).find { |i| i['identifierType'] == identifier_type } || {}
1107
- id.fetch('identifier', nil)
1106
+ id = Array.wrap(identifiers).find { |i| i["identifierType"] == identifier_type } || {}
1107
+ id.fetch("identifier", nil)
1108
1108
  end
1109
1109
 
1110
1110
  def get_identifier_type(identifier_type)
1111
1111
  return nil unless identifier_type.present?
1112
1112
 
1113
1113
  identifierTypes = {
1114
- 'ark' => 'ARK',
1115
- 'arxiv' => 'arXiv',
1116
- 'bibcode' => 'bibcode',
1117
- 'doi' => 'DOI',
1118
- 'ean13' => 'EAN13',
1119
- 'eissn' => 'EISSN',
1120
- 'handle' => 'Handle',
1121
- 'igsn' => 'IGSN',
1122
- 'isbn' => 'ISBN',
1123
- 'issn' => 'ISSN',
1124
- 'istc' => 'ISTC',
1125
- 'lissn' => 'LISSN',
1126
- 'lsid' => 'LSID',
1127
- 'pmid' => 'PMID',
1128
- 'purl' => 'PURL',
1129
- 'upc' => 'UPC',
1130
- 'url' => 'URL',
1131
- 'urn' => 'URN',
1132
- 'md5' => 'md5',
1133
- 'minid' => 'minid',
1134
- 'dataguid' => 'dataguid'
1114
+ "ark" => "ARK",
1115
+ "arxiv" => "arXiv",
1116
+ "bibcode" => "bibcode",
1117
+ "doi" => "DOI",
1118
+ "ean13" => "EAN13",
1119
+ "eissn" => "EISSN",
1120
+ "handle" => "Handle",
1121
+ "igsn" => "IGSN",
1122
+ "isbn" => "ISBN",
1123
+ "issn" => "ISSN",
1124
+ "istc" => "ISTC",
1125
+ "lissn" => "LISSN",
1126
+ "lsid" => "LSID",
1127
+ "pmid" => "PMID",
1128
+ "purl" => "PURL",
1129
+ "upc" => "UPC",
1130
+ "url" => "URL",
1131
+ "urn" => "URN",
1132
+ "md5" => "md5",
1133
+ "minid" => "minid",
1134
+ "dataguid" => "dataguid",
1135
1135
  }
1136
1136
 
1137
1137
  identifierTypes[identifier_type.downcase] || identifier_type
@@ -1140,27 +1140,27 @@ module Commonmeta
1140
1140
  def get_series_information(str)
1141
1141
  return {} unless str.present?
1142
1142
 
1143
- str = str.split(',').map(&:strip)
1143
+ str = str.split(",").map(&:strip)
1144
1144
 
1145
1145
  title = str.first
1146
1146
  volume_issue = str.length > 2 ? str[1].rpartition(/\(([^)]+)\)/) : nil
1147
1147
  volume = volume_issue.present? ? volume_issue[0].presence || volume_issue[2].presence : nil
1148
1148
  issue = volume_issue.present? ? volume_issue[1][1...-1].presence : nil
1149
1149
  pages = str.length > 1 ? str.last : nil
1150
- first_page = pages.present? ? pages.split('-').map(&:strip)[0] : nil
1151
- last_page = pages.present? ? pages.split('-').map(&:strip)[1] : nil
1150
+ first_page = pages.present? ? pages.split("-").map(&:strip)[0] : nil
1151
+ last_page = pages.present? ? pages.split("-").map(&:strip)[1] : nil
1152
1152
 
1153
1153
  {
1154
- 'title' => title,
1155
- 'volume' => volume,
1156
- 'issue' => issue,
1157
- 'firstPage' => first_page,
1158
- 'lastPage' => last_page
1154
+ "title" => title,
1155
+ "volume" => volume,
1156
+ "issue" => issue,
1157
+ "firstPage" => first_page,
1158
+ "lastPage" => last_page,
1159
1159
  }.compact
1160
1160
  end
1161
1161
 
1162
1162
  def jsonlint(json)
1163
- return ['No JSON provided'] unless json.present?
1163
+ return ["No JSON provided"] unless json.present?
1164
1164
 
1165
1165
  error_array = []
1166
1166
  linter = JsonLint::Linter.new
@@ -1169,33 +1169,33 @@ module Commonmeta
1169
1169
  end
1170
1170
 
1171
1171
  def name_to_spdx(name)
1172
- spdx = JSON.load(File.read(File.expand_path('../../resources/spdx/licenses.json',
1173
- __dir__))).fetch('licenses')
1172
+ spdx = JSON.load(File.read(File.expand_path("../../resources/spdx/licenses.json",
1173
+ __dir__))).fetch("licenses")
1174
1174
  license = spdx.find do |l|
1175
- l['name'] == name || l['licenseId'] == name || l['seeAlso'].first == normalize_cc_url(name)
1175
+ l["name"] == name || l["licenseId"] == name || l["seeAlso"].first == normalize_cc_url(name)
1176
1176
  end
1177
1177
 
1178
1178
  if license
1179
- { 'id' => license['licenseId'], 'url' => license['seeAlso'].first }.compact
1179
+ { "id" => license["licenseId"], "url" => license["seeAlso"].first }.compact
1180
1180
  else
1181
- { 'rights' => name }
1181
+ { "rights" => name }
1182
1182
  end
1183
1183
  end
1184
1184
 
1185
1185
  def hsh_to_spdx(hsh)
1186
- spdx = JSON.load(File.read(File.expand_path('../../resources/spdx/licenses.json',
1187
- __dir__))).fetch('licenses')
1188
- hsh['rightsUri'] = hsh.delete('rightsURI') if hsh['rightsUri'].blank?
1186
+ spdx = JSON.load(File.read(File.expand_path("../../resources/spdx/licenses.json",
1187
+ __dir__))).fetch("licenses")
1188
+ hsh["rightsUri"] = hsh.delete("rightsURI") if hsh["rightsUri"].blank?
1189
1189
  license = spdx.find do |l|
1190
- l['licenseId'].casecmp?(hsh['rightsIdentifier']) || l['seeAlso'].first == normalize_cc_url(hsh['rightsUri']) || l['name'] == hsh['rights'] || l['seeAlso'].first == normalize_cc_url(hsh['rights'])
1190
+ l["licenseId"].casecmp?(hsh["rightsIdentifier"]) || l["seeAlso"].first == normalize_cc_url(hsh["rightsUri"]) || l["name"] == hsh["rights"] || l["seeAlso"].first == normalize_cc_url(hsh["rights"])
1191
1191
  end
1192
1192
 
1193
1193
  if license
1194
- { 'id' => license['licenseId'], 'url' => license['seeAlso'].first }.compact
1194
+ { "id" => license["licenseId"], "url" => license["seeAlso"].first }.compact
1195
1195
  else
1196
1196
  {
1197
- 'id' => hsh['rightsIdentifier'].present? ? hsh['rightsIdentifier'].downcase : nil,
1198
- 'url' => hsh['rightsURI'] || hsh['rightsUri']
1197
+ "id" => hsh["rightsIdentifier"].present? ? hsh["rightsIdentifier"].downcase : nil,
1198
+ "url" => hsh["rightsURI"] || hsh["rightsUri"],
1199
1199
  }.compact
1200
1200
  end
1201
1201
  end
@@ -1203,152 +1203,163 @@ module Commonmeta
1203
1203
  def spdx_to_hsh(hsh)
1204
1204
  return nil unless hsh.present? && hsh.is_a?(Hash)
1205
1205
 
1206
- spdx = JSON.load(File.read(File.expand_path('../../resources/spdx/licenses.json',
1207
- __dir__))).fetch('licenses')
1206
+ spdx = JSON.load(File.read(File.expand_path("../../resources/spdx/licenses.json",
1207
+ __dir__))).fetch("licenses")
1208
1208
 
1209
- license = spdx.find { |l| l['licenseId'].casecmp?(hsh['id']) }
1209
+ license = spdx.find { |l| l["licenseId"].casecmp?(hsh["id"]) }
1210
1210
 
1211
1211
  if license
1212
1212
  [{
1213
- 'rightsIdentifier' => license['licenseId'].downcase,
1214
- 'rightsUri' => license['seeAlso'].first,
1215
- 'rights' => license['name'],
1216
- 'rightsIdentifierScheme' => 'SPDX',
1217
- 'schemeUri' => 'https://spdx.org/licenses/'
1213
+ "rightsIdentifier" => license["licenseId"].downcase,
1214
+ "rightsUri" => license["seeAlso"].first,
1215
+ "rights" => license["name"],
1216
+ "rightsIdentifierScheme" => "SPDX",
1217
+ "schemeUri" => "https://spdx.org/licenses/",
1218
1218
  }.compact]
1219
1219
  else
1220
- [{ 'rightsIdentifier' => hsh['id'], 'rightsURI' => hsh['url'] }.compact]
1220
+ [{ "rightsIdentifier" => hsh["id"], "rightsURI" => hsh["url"] }.compact]
1221
1221
  end
1222
1222
  end
1223
1223
 
1224
1224
  def name_to_fos(name)
1225
1225
  # first find subject in Fields of Science (OECD)
1226
- fos = JSON.load(File.read(File.expand_path('../../resources/oecd/fos-mappings.json',
1227
- __dir__))).fetch('fosFields')
1226
+ fos = JSON.load(File.read(File.expand_path("../../resources/oecd/fos-mappings.json",
1227
+ __dir__))).fetch("fosFields")
1228
1228
 
1229
- subject = fos.find { |l| l['fosLabel'] == name || 'FOS: ' + l['fosLabel'] == name }
1229
+ subject = fos.find { |l| l["fosLabel"] == name || "FOS: " + l["fosLabel"] == name }
1230
1230
 
1231
1231
  if subject
1232
1232
  return [{
1233
- 'subject' => sanitize(name).downcase
1234
- },
1233
+ "subject" => sanitize(name).downcase,
1234
+ },
1235
1235
  {
1236
- 'subject' => 'FOS: ' + subject['fosLabel'],
1237
- 'subjectScheme' => 'Fields of Science and Technology (FOS)',
1238
- 'schemeUri' => 'http://www.oecd.org/science/inno/38235147.pdf'
1239
- }]
1236
+ "subject" => "FOS: " + subject["fosLabel"],
1237
+ "subjectScheme" => "Fields of Science and Technology (FOS)",
1238
+ "schemeUri" => "http://www.oecd.org/science/inno/38235147.pdf",
1239
+ }]
1240
1240
  end
1241
1241
 
1242
1242
  # if not found, look in Fields of Research (Australian and New Zealand Standard Research Classification)
1243
1243
  # and map to Fields of Science. Add an extra entry for the latter
1244
- fores = JSON.load(File.read(File.expand_path('../../resources/oecd/for-mappings.json',
1244
+ fores = JSON.load(File.read(File.expand_path("../../resources/oecd/for-mappings.json",
1245
1245
  __dir__)))
1246
- for_fields = fores.fetch('forFields')
1247
- for_disciplines = fores.fetch('forDisciplines')
1246
+ for_fields = fores.fetch("forFields")
1247
+ for_disciplines = fores.fetch("forDisciplines")
1248
1248
 
1249
- subject = for_fields.find { |l| l['forLabel'] == name } ||
1250
- for_disciplines.find { |l| l['forLabel'] == name }
1249
+ subject = for_fields.find { |l| l["forLabel"] == name } ||
1250
+ for_disciplines.find { |l| l["forLabel"] == name }
1251
1251
 
1252
1252
  if subject
1253
1253
  [{
1254
- 'subject' => sanitize(name).downcase
1254
+ "subject" => sanitize(name).downcase,
1255
1255
  },
1256
1256
  {
1257
- 'subject' => 'FOS: ' + subject['fosLabel'],
1258
- 'subjectScheme' => 'Fields of Science and Technology (FOS)',
1259
- 'schemeUri' => 'http://www.oecd.org/science/inno/38235147.pdf'
1260
- }]
1257
+ "subject" => "FOS: " + subject["fosLabel"],
1258
+ "subjectScheme" => "Fields of Science and Technology (FOS)",
1259
+ "schemeUri" => "http://www.oecd.org/science/inno/38235147.pdf",
1260
+ }]
1261
1261
  else
1262
- [{ 'subject' => sanitize(name).downcase }]
1262
+ [{ "subject" => sanitize(name).downcase }]
1263
1263
  end
1264
1264
  end
1265
1265
 
1266
1266
  def hsh_to_fos(hsh)
1267
1267
  # first find subject in Fields of Science (OECD)
1268
- fos = JSON.load(File.read(File.expand_path('../../resources/oecd/fos-mappings.json',
1269
- __dir__))).fetch('fosFields')
1268
+ fos = JSON.load(File.read(File.expand_path("../../resources/oecd/fos-mappings.json",
1269
+ __dir__))).fetch("fosFields")
1270
1270
  subject = fos.find do |l|
1271
- l['fosLabel'] == hsh['__content__'] || 'FOS: ' + l['fosLabel'] == hsh['__content__'] || l['fosLabel'] == hsh['subject']
1271
+ l["fosLabel"] == hsh["__content__"] || "FOS: " + l["fosLabel"] == hsh["__content__"] || l["fosLabel"] == hsh["subject"]
1272
1272
  end
1273
1273
 
1274
1274
  if subject
1275
1275
  return [{
1276
- 'subject' => sanitize(hsh['__content__'] || hsh['subject']),
1277
- 'subjectScheme' => hsh['subjectScheme'],
1278
- 'schemeUri' => hsh['schemeURI'] || hsh['schemeUri'],
1279
- 'valueUri' => hsh['valueURI'] || hsh['valueUri'],
1280
- 'classificationCode' => hsh['classificationCode'],
1281
- 'lang' => hsh['lang']
1282
- }.compact,
1276
+ "subject" => sanitize(hsh["__content__"] || hsh["subject"]),
1277
+ "subjectScheme" => hsh["subjectScheme"],
1278
+ "schemeUri" => hsh["schemeURI"] || hsh["schemeUri"],
1279
+ "valueUri" => hsh["valueURI"] || hsh["valueUri"],
1280
+ "classificationCode" => hsh["classificationCode"],
1281
+ "lang" => hsh["lang"],
1282
+ }.compact,
1283
1283
  {
1284
- 'subject' => 'FOS: ' + subject['fosLabel'],
1285
- 'subjectScheme' => 'Fields of Science and Technology (FOS)',
1286
- 'schemeUri' => 'http://www.oecd.org/science/inno/38235147.pdf'
1287
- }.compact]
1284
+ "subject" => "FOS: " + subject["fosLabel"],
1285
+ "subjectScheme" => "Fields of Science and Technology (FOS)",
1286
+ "schemeUri" => "http://www.oecd.org/science/inno/38235147.pdf",
1287
+ }.compact]
1288
1288
  end
1289
1289
 
1290
1290
  # if not found, look in Fields of Research (Australian and New Zealand Standard Research Classification)
1291
1291
  # and map to Fields of Science. Add an extra entry for the latter
1292
- fores = JSON.load(File.read(File.expand_path('../../resources/oecd/for-mappings.json',
1292
+ fores = JSON.load(File.read(File.expand_path("../../resources/oecd/for-mappings.json",
1293
1293
  __dir__)))
1294
- for_fields = fores.fetch('forFields')
1295
- for_disciplines = fores.fetch('forDisciplines')
1294
+ for_fields = fores.fetch("forFields")
1295
+ for_disciplines = fores.fetch("forDisciplines")
1296
1296
 
1297
1297
  # try to extract forId
1298
- if hsh['subjectScheme'] == 'FOR'
1299
- for_id = hsh['__content__'].to_s.split(' ').first || hsh['subject'].to_s.split(' ').first
1300
- for_id = for_id.rjust(6, '0')
1298
+ if hsh["subjectScheme"] == "FOR"
1299
+ for_id = hsh["__content__"].to_s.split(" ").first || hsh["subject"].to_s.split(" ").first
1300
+ for_id = for_id.rjust(6, "0")
1301
1301
 
1302
- subject = for_fields.find { |l| l['forId'] == for_id } ||
1303
- for_disciplines.find { |l| l['forId'] == for_id[0..3] }
1302
+ subject = for_fields.find { |l| l["forId"] == for_id } ||
1303
+ for_disciplines.find { |l| l["forId"] == for_id[0..3] }
1304
1304
  else
1305
1305
  subject = for_fields.find do |l|
1306
- l['forLabel'] == hsh['__content__'] || l['forLabel'] == hsh['subject']
1306
+ l["forLabel"] == hsh["__content__"] || l["forLabel"] == hsh["subject"]
1307
1307
  end ||
1308
1308
  for_disciplines.find do |l|
1309
- l['forLabel'] == hsh['__content__'] || l['forLabel'] == hsh['subject']
1309
+ l["forLabel"] == hsh["__content__"] || l["forLabel"] == hsh["subject"]
1310
1310
  end
1311
1311
  end
1312
1312
 
1313
1313
  if subject
1314
1314
  [{
1315
- 'subject' => sanitize(hsh['__content__'] || hsh['subject']),
1316
- 'subjectScheme' => hsh['subjectScheme'],
1317
- 'classificationCode' => hsh['classificationCode'],
1318
- 'schemeUri' => hsh['schemeURI'] || hsh['schemeUri'],
1319
- 'valueUri' => hsh['valueURI'] || hsh['valueUri'],
1320
- 'lang' => hsh['lang']
1315
+ "subject" => sanitize(hsh["__content__"] || hsh["subject"]),
1316
+ "subjectScheme" => hsh["subjectScheme"],
1317
+ "classificationCode" => hsh["classificationCode"],
1318
+ "schemeUri" => hsh["schemeURI"] || hsh["schemeUri"],
1319
+ "valueUri" => hsh["valueURI"] || hsh["valueUri"],
1320
+ "lang" => hsh["lang"],
1321
1321
  }.compact,
1322
1322
  {
1323
- 'subject' => 'FOS: ' + subject['fosLabel'],
1324
- 'subjectScheme' => 'Fields of Science and Technology (FOS)',
1325
- 'schemeUri' => 'http://www.oecd.org/science/inno/38235147.pdf'
1326
- }]
1323
+ "subject" => "FOS: " + subject["fosLabel"],
1324
+ "subjectScheme" => "Fields of Science and Technology (FOS)",
1325
+ "schemeUri" => "http://www.oecd.org/science/inno/38235147.pdf",
1326
+ }]
1327
1327
  else
1328
1328
  [{
1329
- 'subject' => sanitize(hsh['__content__'] || hsh['subject']),
1330
- 'subjectScheme' => hsh['subjectScheme'],
1331
- 'classificationCode' => hsh['classificationCode'],
1332
- 'schemeUri' => hsh['schemeURI'] || hsh['schemeUri'],
1333
- 'valueUri' => hsh['valueURI'] || hsh['valueUri'],
1334
- 'lang' => hsh['lang']
1329
+ "subject" => sanitize(hsh["__content__"] || hsh["subject"]),
1330
+ "subjectScheme" => hsh["subjectScheme"],
1331
+ "classificationCode" => hsh["classificationCode"],
1332
+ "schemeUri" => hsh["schemeURI"] || hsh["schemeUri"],
1333
+ "valueUri" => hsh["valueURI"] || hsh["valueUri"],
1334
+ "lang" => hsh["lang"],
1335
1335
  }.compact]
1336
1336
  end
1337
1337
  end
1338
1338
 
1339
1339
  def encode_doi(prefix)
1340
1340
  # DOI suffix is a generated from a random number, encoded in base32
1341
- # suffix has 8 digits plus two checksum digits. With base32 there are
1341
+ # suffix has 8 digits plus two checksum digits. With base32 there are
1342
1342
  # 32 possible digits, so 8 digits gives 32^8 possible combinations
1343
- random_int = SecureRandom.random_number(32**7..(32**8) - 1)
1343
+ random_int = SecureRandom.random_number(32 ** 7..(32 ** 8) - 1)
1344
1344
  suffix = Base32::URL.encode(random_int, checksum: true)
1345
1345
  str = "#{suffix[0, 5]}-#{suffix[5, 10]}"
1346
1346
  "https://doi.org/#{prefix}/#{str}"
1347
1347
  end
1348
1348
 
1349
1349
  def decode_doi(doi)
1350
- suffix = doi.split('/', 5).last
1350
+ suffix = doi.split("/", 5).last
1351
1351
  Base32::URL.decode(suffix)
1352
1352
  end
1353
+
1354
+ def encode_id
1355
+ # suffix has 5 digits plus two checksum digits. With base32 there are
1356
+ # 32 possible digits, so 5 digits gives 32^5 possible combinations
1357
+ random_int = SecureRandom.random_number(32 ** 4..(32 ** 5) - 1)
1358
+ Base32::URL.encode(random_int, checksum: true)
1359
+ end
1360
+
1361
+ def decode_id(id)
1362
+ Base32::URL.decode(id)
1363
+ end
1353
1364
  end
1354
1365
  end