cff 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ba4e9410b991789174bfa5cff1b448600aceb46a
4
- data.tar.gz: ac13ec2b66c63edeaa5eb721b88fec6a4b7fd0da
3
+ metadata.gz: 330c0177c6b7fed7915ddeddbc8ba68a9eb9f9e3
4
+ data.tar.gz: '089cd1ad45d23af25bc1ccbac3b0ffffceedb570'
5
5
  SHA512:
6
- metadata.gz: 807b056534179b4ae578259ef0c8fcc0a6a07d2782b4b134f9a790e99a682a82c9c632008ac8e76afbdd238b060f13c583b30bdb8b1c30c30a6c471230bf9661
7
- data.tar.gz: 2caf814fc16b88fc4d9d70ce664d9a233e258c4460cce6547cca02fe424a5ee4d8d0fcc0bc2309045477901130f0cad97f5fbfce9aaba3b0067ecc4113c1a1b8
6
+ metadata.gz: 290ee6b5066a2f5d016ceff0416faf00f8f12df42c72e62b4642efa2a4d5afa64b32fc1a8e7843d3aec8a4165359445e7a2fd940e523a069a6f6509b181797d3
7
+ data.tar.gz: 0a99851ff3c46441be5fc86d3317bb2bc1828c5f4e5d15dbb8e507541feb9a73e4ff751a7fbd9355a8097ae42db3ac9bfb38428bd28aa5b981b8cb42a74b4cb9
data/CHANGES.md ADDED
@@ -0,0 +1,137 @@
1
+ # Changes log for the Ruby CFF Library
2
+
3
+ ## Version 0.3.0
4
+
5
+ * Update badges for new repo location.
6
+ * Add back the coveralls badge for new repo location.
7
+ * Update gemspec with new repo location.
8
+ * Bump version number for 0.3.0 release.
9
+ * Add a Reference model to represent references.
10
+ * Wire the Reference model into Model and File.
11
+ * Add authors field to Reference.
12
+ * Read the author field properly when parsing a Reference.
13
+ * Remove the ModelPart constructor.
14
+ * Add the DOI badge to the README.
15
+ * Add the simple string fields to Reference.
16
+ * Add format field to Reference.
17
+ * Move duplicated builder methods to Util module.
18
+ * Remove the Util module from the public API.
19
+ * Restrict reference type to the defined set.
20
+ * Add Date type fields to the Reference model.
21
+ * Add contact to the Reference model.
22
+ * Add editors to the Reference model.
23
+ * Add editors-series to the Reference model.
24
+ * Add recipients to the Reference model.
25
+ * Add senders to the Reference model.
26
+ * Add translators to the Reference model.
27
+ * Refactor the Reference#fields method for complexity.
28
+ * Refactor the Model#to_yaml method for complexity.
29
+ * Restrict reference status to the defined set.
30
+ * Add languages to the Reference model.
31
+ * Restrict reference licence to the SPDX Licence List.
32
+ * Rename Util array_to_fields to expand_array_field.
33
+ * Add a Util method expand_field.
34
+ * Correctly read in the actor lists from a file.
35
+ * Update quick start example in the README.
36
+ * Add the integer fields to the Reference model.
37
+ * Refactor Reference#fields to cope with single Entities.
38
+ * Add the singular Entity fields to the Reference model.
39
+ * Add issue-date field to the Reference model.
40
+ * Add the keywords field to the Reference model.
41
+ * Refactor keyword list initialization in Reference.
42
+ * Add patent-states field to the Reference model.
43
+ * Refactor Reference#keywords to be a standard field.
44
+ * Refactor Reference#patent_states to be a field.
45
+ * Extend the tests for Reference after the refactor.
46
+ * Normalize Reference types when they are set.
47
+ * Normalize the Reference status when set.
48
+ * Add a note to the README about versioning.
49
+ * Add a CHANGES file.
50
+
51
+ ## Version 0.2.0
52
+
53
+ * Add a rubygems version badge to the README.
54
+ * Add older rubies to the CI, but allow failures.
55
+ * Add the licence to the gemspec.
56
+ * Rename the ALLOWED_METHODS list to FIELDS.
57
+ * Send missing methods straight to Model, from File.
58
+ * Fix passing through arguments for missing methods (File).
59
+ * Add a Util module with delete_from_hash as first utility.
60
+ * Move method_to_field to the Util module.
61
+ * Refactor for more complete parsing ability.
62
+ * Freeze the allowed fields constant in Model.
63
+ * Change allowed fields to be more flexible
64
+ * Add abstract to Model.
65
+ * Factor out the process of converting array fields to yaml.
66
+ * Fix test for authors that was split incorrectly.
67
+ * Add contact to Model.
68
+ * Add tests to check capitalized fields are rejected.
69
+ * Refactor model building for maintainability.
70
+ * Add commit to the Model.
71
+ * Add doi to the Model.
72
+ * Add keywords to Model.
73
+ * Fix #11: prevent serialization of empty collections.
74
+ * Add license to Model.
75
+ * Refactor testing simple fields.
76
+ * Add license-url to Model.
77
+ * Simplify parsing the keywords in Model.
78
+ * Refactor testing reading complete CFF file.
79
+ * Add repository* to Model.
80
+ * Add url to Model.
81
+ * Fix #12: typo in README example usage.
82
+ * Add to the quick start example in the README.
83
+ * Create a new base class (ModelPart) for parts of the model.
84
+ * Add ModelPart#method_missing.
85
+ * Add affiliation to Person, and tests for it too.
86
+ * Add address to Entity, and tests for it too.
87
+ * Add accessors for required fields on Person, Entity.
88
+ * Add the rest of the optional fields in Person.
89
+ * Add the rest of the simple fields in Entity.
90
+ * Add the date fields in Entity.
91
+ * Test dates in Entity with text inputs.
92
+
93
+ ## Version 0.1.0
94
+
95
+ * Add a code of conduct.
96
+ * Add Travis configuration.
97
+ * Add licence text to all source files.
98
+ * Add a Travis badge to the README.
99
+ * Add a CodeClimate badge to the README.
100
+ * Set up coveralls integration.
101
+ * Add a coveralls badge to the README.
102
+ * Add the current CFF spec version as the default.
103
+ * Add a simple model class.
104
+ * Message doesn't need to be passed to new.
105
+ * Add title to model and wire into default message.
106
+ * Add a method to set the message.
107
+ * Remove the default values on ingestion.
108
+ * Swap requires in main cff file.
109
+ * Only set a default message on construction.
110
+ * Add a File class to read and write CFF files.
111
+ * Switch to using standard accessor for message field.
112
+ * Streamline title output tests.
113
+ * Add a set title method to Model and test it.
114
+ * Turn off line wrapping in Model yaml output.
115
+ * Fix #2. Don't include title in the default message.
116
+ * Test that yaml output doesn't include the header.
117
+ * Write cff from a String or Model.
118
+ * Fix #3. Create a File from either a model or title.
119
+ * When testing file loading, compare to yaml directly.
120
+ * Test the message is loaded correctly into a File.
121
+ * Add version to the Model and File APIs.
122
+ * Add date-released to the Model and File APIs.
123
+ * Fix cff_version test.
124
+ * Move the Model class to a Hash-based implementation.
125
+ * Initialize Model with a title or a Hash.
126
+ * Update the File class to use the new Model class.
127
+ * Use a method whitelist for Model and File.
128
+ * Add a Person model to represent authors.
129
+ * Add an Entity model to represent authors.
130
+
131
+ ## About this file
132
+
133
+ This file is, at least in part, generated by the following command:
134
+
135
+ ```shell
136
+ $ git log --pretty=format:"* %s" --reverse --no-merges <commit-hash>..
137
+ ```
data/README.md CHANGED
@@ -3,10 +3,11 @@
3
3
 
4
4
  A Ruby library for manipulating CITATION.cff files.
5
5
 
6
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1184077.svg)](https://doi.org/10.5281/zenodo.1184077)
6
7
  [![Gem Version](https://badge.fury.io/rb/cff.svg)](https://badge.fury.io/rb/cff)
7
- [![Build Status](https://travis-ci.org/hainesr/ruby-cff.svg?branch=master)](https://travis-ci.org/hainesr/ruby-cff)
8
- [![Maintainability](https://api.codeclimate.com/v1/badges/7eaa3890f17664e10bc6/maintainability)](https://codeclimate.com/github/hainesr/ruby-cff/maintainability)
9
- [![Coverage Status](https://coveralls.io/repos/github/hainesr/ruby-cff/badge.svg)](https://coveralls.io/github/hainesr/ruby-cff)
8
+ [![Build Status](https://travis-ci.org/citation-file-format/ruby-cff.svg?branch=master)](https://travis-ci.org/citation-file-format/ruby-cff)
9
+ [![Maintainability](https://api.codeclimate.com/v1/badges/6bb4c661bfb4971260ba/maintainability)](https://codeclimate.com/github/citation-file-format/ruby-cff/maintainability)
10
+ [![Coverage Status](https://coveralls.io/repos/github/citation-file-format/ruby-cff/badge.svg)](https://coveralls.io/github/citation-file-format/ruby-cff)
10
11
 
11
12
  ### Synopsis
12
13
 
@@ -18,7 +19,7 @@ See the [CITATION.cff documentation](https://citation-file-format.github.io/) fo
18
19
 
19
20
  ```ruby
20
21
  cff = CFF::Model.new("Ruby CFF Library")
21
- cff.version = "0.1.0"
22
+ cff.version = CFF::VERSION
22
23
  cff.date_released = Date.today
23
24
  cff.authors << CFF::Person.new("Robert", "Haines")
24
25
  cff.license = "Apache-2.0"
@@ -34,8 +35,8 @@ Will produce a file that looks something like this:
34
35
  cff-version: 1.0.3
35
36
  message: If you use this software in your work, please cite it using the following metadata
36
37
  title: Ruby CFF Library
37
- version: 0.1.0
38
- date-released: 2018-02-24
38
+ version: 0.3.0
39
+ date-released: 2018-03-04
39
40
  license: Apache-2.0
40
41
  repository-artifact: https://rubygems.org/gems/cff
41
42
  authors:
@@ -47,6 +48,10 @@ keywords:
47
48
  - citation
48
49
  ```
49
50
 
51
+ ### Library versions
52
+
53
+ Until this library reaches version 1.0.0 the API may be subject to breaking changes. When version 1.0.0 is released, then the principles of [semantic versioning](https://semver.org/) will be applied.
54
+
50
55
  ### Licence
51
56
 
52
57
  [Apache 2.0](http://www.apache.org/licenses/). See LICENCE for details.
data/Rakefile CHANGED
@@ -26,7 +26,7 @@ end
26
26
 
27
27
  RDoc::Task.new do |r|
28
28
  r.main = "README.md"
29
- r.rdoc_files.include("README.md", "LICENCE", "lib/**/*.rb")
29
+ r.rdoc_files.include("README.md", "LICENCE", "CHANGES.md", "lib/**/*.rb")
30
30
  r.options << "--markup=markdown"
31
31
  r.options << "--tab-width=2"
32
32
  r.options << "-t Ruby CFF Library version #{::CFF::VERSION}"
data/cff.gemspec CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.summary = "A Ruby library for manipulating CITATION.cff files."
26
26
  spec.description = "See https://citation-file-format.github.io/ for more info."
27
- spec.homepage = "https://github.com/hainesr/ruby-cff"
27
+ spec.homepage = "https://github.com/citation-file-format/ruby-cff"
28
28
  spec.license = "Apache-2.0"
29
29
 
30
30
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
@@ -36,6 +36,9 @@ Gem::Specification.new do |spec|
36
36
 
37
37
  spec.required_ruby_version = ">= 2.2.0"
38
38
 
39
+ spec.add_runtime_dependency "language_list", "~> 1.2"
40
+ spec.add_runtime_dependency "spdx-licenses", "~> 1.1"
41
+
39
42
  spec.add_development_dependency "bundler", "~> 1.16"
40
43
  spec.add_development_dependency "rake", "~> 10.0"
41
44
  spec.add_development_dependency "minitest", "~> 5.0"
data/lib/cff/entity.rb CHANGED
@@ -43,7 +43,7 @@ module CFF
43
43
  # Create a new Entity with the supplied name.
44
44
  def initialize(param)
45
45
  if Hash === param
46
- super(param)
46
+ @fields = param
47
47
  else
48
48
  @fields = Hash.new('')
49
49
  @fields['name'] = param
@@ -21,10 +21,6 @@ module CFF
21
21
 
22
22
  attr_reader :fields
23
23
 
24
- def initialize(fields)
25
- @fields = fields
26
- end
27
-
28
24
  def method_missing(name, *args) # :nodoc:
29
25
  n = method_to_field(name.id2name)
30
26
  super unless self.class::ALLOWED_FIELDS.include?(n.chomp('='))
data/lib/cff/model.rb CHANGED
@@ -49,6 +49,7 @@ module CFF
49
49
  @authors = []
50
50
  @contact = []
51
51
  @keywords = []
52
+ @references = []
52
53
 
53
54
  if Hash === param
54
55
  build_model(param)
@@ -118,6 +119,19 @@ module CFF
118
119
  @keywords
119
120
  end
120
121
 
122
+ # :call-seq:
123
+ # references -> Array
124
+ #
125
+ # Return the list of references for this citation. To add a reference to the
126
+ # list, use:
127
+ #
128
+ # ```
129
+ # model.references << reference
130
+ # ```
131
+ def references
132
+ @references
133
+ end
134
+
121
135
  # :call-seq:
122
136
  # version = version
123
137
  #
@@ -127,11 +141,6 @@ module CFF
127
141
  end
128
142
 
129
143
  def to_yaml # :nodoc:
130
- fields = @fields.dup
131
- fields['authors'] = array_field_to_yaml(@authors) unless @authors.empty?
132
- fields['contact'] = array_field_to_yaml(@contact) unless @contact.empty?
133
- fields['keywords'] = @keywords.map { |k| k.to_s } unless @keywords.empty?
134
-
135
144
  YAML.dump fields, :line_width => -1, :indentation => 2
136
145
  end
137
146
 
@@ -148,24 +157,29 @@ module CFF
148
157
 
149
158
  private
150
159
 
151
- def build_model(fields)
152
- build_entity_collection(@authors, fields['authors'])
153
- build_entity_collection(@contact, fields['contact'])
154
- @keywords = fields['keywords']
160
+ def fields
161
+ model = @fields.dup
162
+ [
163
+ ['authors', @authors],
164
+ ['contact', @contact],
165
+ ['references', @references]
166
+ ].each do |field, var|
167
+ model[field] = expand_array_field(var) unless var.empty?
168
+ end
169
+ model['keywords'] = @keywords.map { |k| k.to_s } unless @keywords.empty?
155
170
 
156
- @fields = delete_from_hash(fields, 'authors', 'contact', 'keywords')
171
+ model
157
172
  end
158
173
 
159
- def build_entity_collection(field, source)
160
- source.each do |s|
161
- field << (s.has_key?('given-names') ? Person.new(s) : Entity.new(s))
174
+ def build_model(fields)
175
+ build_actor_collection(@authors, fields['authors'])
176
+ build_actor_collection(@contact, fields['contact'])
177
+ @keywords = fields['keywords']
178
+ fields['references'].each do |r|
179
+ @references << Reference.new(r)
162
180
  end
163
- end
164
181
 
165
- def array_field_to_yaml(field)
166
- field.reject do |f|
167
- !f.respond_to?(:fields)
168
- end.map { |f| f.fields }
182
+ @fields = delete_from_hash(fields, 'authors', 'contact', 'keywords', 'references')
169
183
  end
170
184
 
171
185
  end
data/lib/cff/person.rb CHANGED
@@ -43,7 +43,7 @@ module CFF
43
43
  # Create a new Person with the supplied given and family names.
44
44
  def initialize(param, *more)
45
45
  if Hash === param
46
- super(param)
46
+ @fields = param
47
47
  else
48
48
  @fields = Hash.new('')
49
49
  @fields['family-names'] = more[0]
@@ -0,0 +1,502 @@
1
+ # Copyright (c) 2018 Robert Haines.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ #
16
+ module CFF
17
+
18
+ # Reference provides a reference pertaining to the software version or the
19
+ # software itself, e.g., a software paper describing the abstract concepts of
20
+ # the software, a paper describing an algorithm that has been implemented in
21
+ # the software version, etc.
22
+ class Reference < ModelPart
23
+
24
+ ALLOWED_FIELDS = [
25
+ 'abbreviation',
26
+ 'abstract',
27
+ 'collection-doi',
28
+ 'collection-title',
29
+ 'collection-type',
30
+ 'commit',
31
+ 'conference',
32
+ 'copyright',
33
+ 'data-type',
34
+ 'database',
35
+ 'database-provider',
36
+ 'date-accessed',
37
+ 'date-downloaded',
38
+ 'date-published',
39
+ 'date-released',
40
+ 'department',
41
+ 'doi',
42
+ 'edition',
43
+ 'end',
44
+ 'entry',
45
+ 'filename',
46
+ 'institution',
47
+ 'isbn',
48
+ 'issn',
49
+ 'issue',
50
+ 'issue-date',
51
+ 'issue-title',
52
+ 'journal',
53
+ 'keywords',
54
+ 'license',
55
+ 'license-url',
56
+ 'loc-end',
57
+ 'loc-start',
58
+ 'location',
59
+ 'medium',
60
+ 'month',
61
+ 'nihmsid',
62
+ 'notes',
63
+ 'number',
64
+ 'number-volumes',
65
+ 'pages',
66
+ 'patent-states',
67
+ 'pmcid',
68
+ 'publisher',
69
+ 'repository',
70
+ 'repository-code',
71
+ 'repository-artifact',
72
+ 'scope',
73
+ 'section',
74
+ 'start',
75
+ 'status',
76
+ 'thesis-type',
77
+ 'title',
78
+ 'type',
79
+ 'url',
80
+ 'version',
81
+ 'volume',
82
+ 'volume-title',
83
+ 'year',
84
+ 'year-original'
85
+ ].freeze # :nodoc:
86
+
87
+ # The [defined set of reference types](https://citation-file-format.github.io/1.0.3/specifications/#/reference-types).
88
+ REFERENCE_TYPES = [
89
+ 'art',
90
+ 'article',
91
+ 'audiovisual',
92
+ 'bill',
93
+ 'blog',
94
+ 'book',
95
+ 'catalogue',
96
+ 'conference',
97
+ 'conference-paper',
98
+ 'data',
99
+ 'database',
100
+ 'dictionary',
101
+ 'edited-work',
102
+ 'encyclopedia',
103
+ 'film-broadcast',
104
+ 'generic',
105
+ 'government-document',
106
+ 'grant',
107
+ 'hearing',
108
+ 'historical-work',
109
+ 'legal-case',
110
+ 'legal-rule',
111
+ 'magazine-article',
112
+ 'manual',
113
+ 'map',
114
+ 'multimedia',
115
+ 'music',
116
+ 'newspaper-article',
117
+ 'pamphlet',
118
+ 'patent',
119
+ 'personal-communication',
120
+ 'proceedings',
121
+ 'report',
122
+ 'serial',
123
+ 'slides',
124
+ 'software',
125
+ 'software-code',
126
+ 'software-container',
127
+ 'software-executable',
128
+ 'software-virtual-machine',
129
+ 'sound-recording',
130
+ 'standard',
131
+ 'statute',
132
+ 'thesis',
133
+ 'unpublished',
134
+ 'video',
135
+ 'website'
136
+ ].freeze
137
+
138
+ # The [defined set of reference status types](https://citation-file-format.github.io/1.0.3/specifications/#/status-strings).
139
+ REFERENCE_STATUS_TYPES = [
140
+ 'abstract',
141
+ 'advance-online',
142
+ 'in-preparation',
143
+ 'in-press',
144
+ 'pre-print',
145
+ 'submitted'
146
+ ].freeze
147
+
148
+ # :call-seq:
149
+ # new(title, type) -> Reference
150
+ #
151
+ # Create a new Reference with the supplied title and type. If type is not one of the [defined set of reference types](https://citation-file-format.github.io/1.0.3/specifications/#/reference-types), 'generic' will be used by default.
152
+ def initialize(param, *more)
153
+ @authors = []
154
+ @contact = []
155
+ @editors = []
156
+ @editors_series = []
157
+ @recipients = []
158
+ @senders = []
159
+ @translators = []
160
+
161
+ if Hash === param
162
+ build_model(param)
163
+ else
164
+ @fields = Hash.new('')
165
+ type = more[0].downcase
166
+ @fields['type'] = REFERENCE_TYPES.include?(type) ? type : 'generic'
167
+ @fields['title'] = param
168
+ end
169
+
170
+ [
171
+ 'keywords',
172
+ 'patent-states'
173
+ ].each { |field| @fields[field] = [] if @fields[field].empty? }
174
+ end
175
+
176
+ # :call-seq:
177
+ # authors -> Array
178
+ #
179
+ # Return the list of authors for this Reference. To add an author to the
180
+ # list, use:
181
+ #
182
+ # ```
183
+ # reference.authors << author
184
+ # ```
185
+ #
186
+ # Authors can be a Person or Entity.
187
+ def authors
188
+ @authors
189
+ end
190
+
191
+ # :call-seq:
192
+ # contact -> Array
193
+ #
194
+ # Return the list of contacts for this Reference. To add a contact to the
195
+ # list, use:
196
+ #
197
+ # ```
198
+ # reference.contact << contact
199
+ # ```
200
+ #
201
+ # Contacts can be a Person or Entity.
202
+ def contact
203
+ @contact
204
+ end
205
+
206
+ # :call-seq:
207
+ # editors -> Array
208
+ #
209
+ # Return the list of editors for this Reference. To add an editor to the
210
+ # list, use:
211
+ #
212
+ # ```
213
+ # reference.editors << editor
214
+ # ```
215
+ #
216
+ # An editor can be a Person or Entity.
217
+ def editors
218
+ @editors
219
+ end
220
+
221
+ # :call-seq:
222
+ # editors_series -> Array
223
+ #
224
+ # Return the list of series editors for this Reference. To add a series
225
+ # editor to the list, use:
226
+ #
227
+ # ```
228
+ # reference.editors_series << editor
229
+ # ```
230
+ #
231
+ # An editor can be a Person or Entity.
232
+ def editors_series
233
+ @editors_series
234
+ end
235
+
236
+ # :call-seq:
237
+ # recipients -> Array
238
+ #
239
+ # Return the list of recipients for this Reference. To add a recipient
240
+ # to the list, use:
241
+ #
242
+ # ```
243
+ # reference.recipients << recipient
244
+ # ```
245
+ #
246
+ # Recipients can be a Person or Entity.
247
+ def recipients
248
+ @recipients
249
+ end
250
+
251
+ # :call-seq:
252
+ # senders -> Array
253
+ #
254
+ # Return the list of senders for this Reference. To add a sender to the
255
+ # list, use:
256
+ #
257
+ # ```
258
+ # reference.senders << sender
259
+ # ```
260
+ #
261
+ # Senders can be a Person or Entity.
262
+ def senders
263
+ @senders
264
+ end
265
+
266
+ # :call-seq:
267
+ # translators -> Array
268
+ #
269
+ # Return the list of translators for this Reference. To add a translator
270
+ # to the list, use:
271
+ #
272
+ # ```
273
+ # reference.translators << translator
274
+ # ```
275
+ #
276
+ # Translators can be a Person or Entity.
277
+ def translators
278
+ @translators
279
+ end
280
+
281
+ # :call-seq:
282
+ # add_language language
283
+ #
284
+ # Add a language to this Reference. Input is converted to the ISO 639-3
285
+ # three letter language code, so `GER` becomes `deu`, `french` becomes
286
+ # `fra` and `en` becomes `eng`.
287
+ def add_language(lang)
288
+ @fields['languages'] = [] if @fields['languages'].empty?
289
+ lang = LanguageList::LanguageInfo.find(lang)
290
+ return if lang.nil?
291
+ lang = lang.iso_639_3
292
+ @fields['languages'] << lang unless @fields['languages'].include? lang
293
+ end
294
+
295
+ # :call-seq:
296
+ # reset_languages
297
+ #
298
+ # Reset the list of languages for this Reference to be empty.
299
+ def reset_languages
300
+ @fields.delete('languages')
301
+ end
302
+
303
+ # :call-seq:
304
+ # languages -> Array
305
+ #
306
+ # Return the list of languages associated with this Reference.
307
+ def languages
308
+ @fields['languages'].empty? ? [] : @fields['languages'].dup
309
+ end
310
+
311
+ # :call-seq:
312
+ # license = license
313
+ #
314
+ # Set the license of this Reference. Only licenses that conform to the
315
+ # [SPDX License List](https://spdx.org/licenses/) will be accepted. If you
316
+ # need specify a different license you should set `license-url` with a link
317
+ # to the license instead.
318
+ def license=(lic)
319
+ @fields['license'] = lic unless SpdxLicenses.lookup(lic).nil?
320
+ end
321
+
322
+ # :call-seq:
323
+ # date_accessed = date
324
+ #
325
+ # Set the `date-accessed` field. If a non-Date object is passed in it will
326
+ # be parsed into a Date.
327
+ def date_accessed=(date)
328
+ unless Date === date
329
+ date = Date.parse(date)
330
+ end
331
+
332
+ @fields['date-accessed'] = date
333
+ end
334
+
335
+ # :call-seq:
336
+ # date_downloaded = date
337
+ #
338
+ # Set the `date-downloaded` field. If a non-Date object is passed in it will
339
+ # be parsed into a Date.
340
+ def date_downloaded=(date)
341
+ unless Date === date
342
+ date = Date.parse(date)
343
+ end
344
+
345
+ @fields['date-downloaded'] = date
346
+ end
347
+
348
+ # :call-seq:
349
+ # date_published = date
350
+ #
351
+ # Set the `date-published` field. If a non-Date object is passed in it will
352
+ # be parsed into a Date.
353
+ def date_published=(date)
354
+ unless Date === date
355
+ date = Date.parse(date)
356
+ end
357
+
358
+ @fields['date-published'] = date
359
+ end
360
+
361
+ # :call-seq:
362
+ # date_released = date
363
+ #
364
+ # Set the `date-released` field. If a non-Date object is passed in it will
365
+ # be parsed into a Date.
366
+ def date_released=(date)
367
+ unless Date === date
368
+ date = Date.parse(date)
369
+ end
370
+
371
+ @fields['date-released'] = date
372
+ end
373
+
374
+ # :call-seq:
375
+ # format -> String
376
+ #
377
+ # Returns the format of this Reference.
378
+ def format
379
+ @fields['format']
380
+ end
381
+
382
+ # :call-seq:
383
+ # format = format
384
+ #
385
+ # Sets the format of this Reference.
386
+ def format=(fmt)
387
+ @fields['format'] = fmt
388
+ end
389
+
390
+ # :call-seq:
391
+ # status = status
392
+ #
393
+ # Sets the status of this Reference. The status is restricted to a
394
+ # [defined set of status types](https://citation-file-format.github.io/1.0.3/specifications/#/status-strings).
395
+ def status=(status)
396
+ status.downcase!
397
+ @fields['status'] = status if REFERENCE_STATUS_TYPES.include?(status)
398
+ end
399
+
400
+ # :call-seq:
401
+ # type = type
402
+ #
403
+ # Sets the type of this Reference. The type is restricted to a
404
+ # [defined set of reference types](https://citation-file-format.github.io/1.0.3/specifications/#/reference-types).
405
+ def type=(type)
406
+ type.downcase!
407
+ @fields['type'] = type if REFERENCE_TYPES.include?(type)
408
+ end
409
+
410
+ # Override superclass #fields as References contain model parts too.
411
+ def fields # :nodoc:
412
+ ref = {}
413
+
414
+ @fields.each do |field, value|
415
+ if value.respond_to?(:map)
416
+ ref[field] = value.map { |v| v.to_s } unless value.empty?
417
+ else
418
+ ref[field] = value.respond_to?(:fields) ? value.fields : value
419
+ end
420
+ end
421
+
422
+ [
423
+ ['authors', @authors],
424
+ ['contact', @contact],
425
+ ['editors', @editors],
426
+ ['editors-series', @editors_series],
427
+ ['recipients', @recipients],
428
+ ['senders', @senders],
429
+ ['translators', @translators]
430
+ ].each do |field, var|
431
+ ref[field] = expand_array_field(var) unless var.empty?
432
+ end
433
+
434
+ ref
435
+ end
436
+
437
+ private
438
+
439
+ def build_model(fields)
440
+ build_actor_collection(@authors, fields['authors'])
441
+ build_actor_collection(@contact, fields['contact'])
442
+ build_actor_collection(@editors, fields['editors'])
443
+ build_actor_collection(@editors_series, fields['editors-series'])
444
+ build_actor_collection(@recipients, fields['recipients'])
445
+ build_actor_collection(@senders, fields['senders'])
446
+ build_actor_collection(@translators, fields['translators'])
447
+
448
+ @fields = delete_from_hash(fields, 'authors', 'contact', 'editors', 'editors-series', 'recipients', 'senders', 'translators')
449
+ end
450
+
451
+ public
452
+
453
+ # Some documentation of "hidden" methods is provided here, out of the
454
+ # way of the main class code.
455
+
456
+ ##
457
+ # :method: keywords
458
+ # :call-seq:
459
+ # keywords -> Array
460
+ #
461
+ # Return the list of keywords for this reference. To add a keyword to the
462
+ # list, use:
463
+ #
464
+ # ```
465
+ # model.keywords << keyword
466
+ # ```
467
+ #
468
+ # Keywords will be converted to Strings on output.
469
+
470
+ ##
471
+ # :method: keywords=
472
+ # :call-seq:
473
+ # keywords = array_of_keywords -> Array
474
+ #
475
+ # Replace the list of keywords for this reference.
476
+ #
477
+ # Keywords will be converted to Strings on output.
478
+
479
+ ##
480
+ # :method: patent_states
481
+ # :call-seq:
482
+ # patent_states -> Array
483
+ #
484
+ # Return the list of patent states for this reference. To add a patent
485
+ # state to the list, use:
486
+ #
487
+ # ```
488
+ # model.patent_states << patent_state
489
+ # ```
490
+ #
491
+ # Patent states will be converted to Strings on output.
492
+
493
+ ##
494
+ # :method: patent_states=
495
+ # :call-seq:
496
+ # patent_states = array_of_states -> Array
497
+ #
498
+ # Replace the list of patent states for this reference.
499
+ #
500
+ # Patent states will be converted to Strings on output.
501
+ end
502
+ end
data/lib/cff/util.rb CHANGED
@@ -15,27 +15,37 @@
15
15
  #
16
16
  module CFF
17
17
 
18
+ # :stopdoc:
18
19
  # Utility methods useful throughout the rest of the CFF library.
20
+ # This module is not in the public API.
19
21
  module Util
20
22
 
21
- # :call-seq:
22
- # delete_from_hash(hash, keys...) -> Hash
23
- #
24
- # Returns a hash that includes everything but the given keys.
25
23
  def delete_from_hash(hash, *keys)
26
24
  h = hash.dup
27
25
  keys.each { |key| h.delete(key) }
28
26
  h
29
27
  end
30
28
 
31
- # :call-seq:
32
- # method_to_field(name) -> converted name
33
- #
34
- # Return the supplied name with underscores converted to dashes.
35
29
  def method_to_field(name)
36
30
  name.gsub('_', '-')
37
31
  end
38
32
 
39
- end
33
+ def build_actor_collection(field, source)
34
+ source.each do |s|
35
+ field << (s.has_key?('given-names') ? Person.new(s) : Entity.new(s))
36
+ end
37
+ end
38
+
39
+ def expand_field(field)
40
+ field.fields if field.respond_to?(:fields)
41
+ end
40
42
 
43
+ def expand_array_field(field)
44
+ field.reject do |f|
45
+ !f.respond_to?(:fields)
46
+ end.map { |f| f.fields }
47
+ end
48
+
49
+ end
50
+ # :startdoc:
41
51
  end
data/lib/cff/version.rb CHANGED
@@ -15,6 +15,6 @@
15
15
  #
16
16
  module CFF
17
17
  # :nodoc:
18
- VERSION = "0.2.0"
18
+ VERSION = "0.3.0"
19
19
  DEFAULT_SPEC_VERSION = "1.0.3"
20
20
  end
data/lib/cff.rb CHANGED
@@ -14,12 +14,15 @@
14
14
 
15
15
  require "date"
16
16
  require "yaml"
17
+ require "language_list"
18
+ require "spdx-licenses"
17
19
 
18
20
  require "cff/version"
19
21
  require "cff/util"
20
22
  require "cff/model-part"
21
23
  require "cff/person"
22
24
  require "cff/entity"
25
+ require "cff/reference"
23
26
  require "cff/model"
24
27
  require "cff/file"
25
28
 
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Haines
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-02-25 00:00:00.000000000 Z
11
+ date: 2018-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: language_list
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: spdx-licenses
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.1'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: bundler
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -105,6 +133,7 @@ files:
105
133
  - ".ruby-gemset"
106
134
  - ".ruby-version"
107
135
  - ".travis.yml"
136
+ - CHANGES.md
108
137
  - CODE_OF_CONDUCT.md
109
138
  - Gemfile
110
139
  - LICENCE
@@ -119,9 +148,10 @@ files:
119
148
  - lib/cff/model-part.rb
120
149
  - lib/cff/model.rb
121
150
  - lib/cff/person.rb
151
+ - lib/cff/reference.rb
122
152
  - lib/cff/util.rb
123
153
  - lib/cff/version.rb
124
- homepage: https://github.com/hainesr/ruby-cff
154
+ homepage: https://github.com/citation-file-format/ruby-cff
125
155
  licenses:
126
156
  - Apache-2.0
127
157
  metadata: {}