cff 1.1.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +10 -0
- data/CITATION.cff +3 -3
- data/LICENCE +1 -1
- data/README.md +25 -1
- data/lib/cff/file.rb +3 -6
- data/lib/cff/formatters/bibtex.rb +21 -11
- data/lib/cff/formatters/formatter.rb +4 -11
- data/lib/cff/index.rb +2 -4
- data/lib/cff/model_part.rb +49 -15
- data/lib/cff/util.rb +8 -1
- data/lib/cff/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa0896639724d0e82551bf84fde9801a00974dac14e120dafa51b53bc07c33cb
|
4
|
+
data.tar.gz: 0ef577895dff069272703c4c063dc5a84e1e484be6c23ce696592803093c43f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63ae9c19849721bb92af374493b8930d75d7bb3bfbbc6e14a8f1fad0bbbf39064c635f5c03f5d2828bc507b33f65dea69d194a640f6be212bf6088fc3238b9f0
|
7
|
+
data.tar.gz: 5101768a4a0ab8de6176ba2506c98ad5efce62f517f34146feaa8a114939e2154f415ac1cdb4162e4b7407c7bdf3e3bdba1f8c7b06c4b5f714b68f620f402bc6
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Changes log for the Ruby CFF Library
|
2
2
|
|
3
|
+
## 1.3.0
|
4
|
+
|
5
|
+
* Abstract out parsing YAML.
|
6
|
+
* Turn on underlying support for YAML anchors/aliases.
|
7
|
+
|
8
|
+
## 1.2.0
|
9
|
+
|
10
|
+
* Always treat dates as Ruby Date objects.
|
11
|
+
* BibTeX: escape special characters ($%&_#{}).
|
12
|
+
|
3
13
|
## 1.1.0
|
4
14
|
|
5
15
|
* BibTeX: output months as three letter abbreviations.
|
data/CITATION.cff
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# This CITATION.cff file was created by ruby-cff (v 1.
|
1
|
+
# This CITATION.cff file was created by ruby-cff (v 1.3.0).
|
2
2
|
# Gem: https://rubygems.org/gems/cff
|
3
3
|
# CFF: https://citation-file-format.github.io/
|
4
4
|
|
@@ -21,9 +21,9 @@ keywords:
|
|
21
21
|
- metadata
|
22
22
|
- citation file format
|
23
23
|
- CFF
|
24
|
-
version: 1.
|
24
|
+
version: 1.3.0
|
25
25
|
doi: 10.5281/zenodo.1184077
|
26
|
-
date-released:
|
26
|
+
date-released: 2024-10-26
|
27
27
|
license: Apache-2.0
|
28
28
|
repository-artifact: https://rubygems.org/gems/cff
|
29
29
|
repository-code: https://github.com/citation-file-format/ruby-cff
|
data/LICENCE
CHANGED
@@ -186,7 +186,7 @@
|
|
186
186
|
same "printed page" as the copyright notice for easier
|
187
187
|
identification within third-party archives.
|
188
188
|
|
189
|
-
Copyright (c) 2018-
|
189
|
+
Copyright (c) 2018-2024 The Ruby Citation File Format Developers.
|
190
190
|
|
191
191
|
Licensed under the Apache License, Version 2.0 (the "License");
|
192
192
|
you may not use this file except in compliance with the License.
|
data/README.md
CHANGED
@@ -122,6 +122,30 @@ CFF::File.open('CITATION.cff') do |cff|
|
|
122
122
|
end
|
123
123
|
```
|
124
124
|
|
125
|
+
#### Notes on CFF files with YAML anchors and aliases
|
126
|
+
|
127
|
+
Ruby CFF can read files that use YAML anchors and aliases. An anchor (`&<label>`) identifies a section of your file for reuse elsewhere. An alias (`*<label>`) is then used to mark where you want that section to be repeated. In this example, the `&authors` anchor marks an author list for reuse wherever the `*authors` alias is used:
|
128
|
+
|
129
|
+
```yaml
|
130
|
+
cff-version: 1.2.0
|
131
|
+
title: Ruby CFF Library
|
132
|
+
authors: &authors
|
133
|
+
- family-names: Haines
|
134
|
+
given-names: Robert
|
135
|
+
affiliation: The University of Manchester, UK
|
136
|
+
|
137
|
+
...
|
138
|
+
|
139
|
+
references:
|
140
|
+
- type: software
|
141
|
+
title: Citation File Format
|
142
|
+
authors: *authors
|
143
|
+
```
|
144
|
+
|
145
|
+
Ruby uses a single object to represent all aliases of an anchor. This means that once the above has been read in by Ruby CFF, if you add an author to either the top-level author list, or the author list in the reference, the new author will appear in both places. With this in mind, you should only use anchors and aliases where the relationship between sections is such that you are sure that exact repetition will always make sense.
|
146
|
+
|
147
|
+
When saving CFF files that use anchors and aliases the underlying YAML library will not preserve their names. For example, if the above is loaded into Ruby CFF and then immediately saved `&authors`/`*authors` will most likely become `&1`/`*1`.
|
148
|
+
|
125
149
|
### Validating CFF files
|
126
150
|
|
127
151
|
To quickly validate a file and raise an error on failure, you can use `CFF::File` directly:
|
@@ -203,7 +227,7 @@ cff.to_apalike(preferred_citation: false)
|
|
203
227
|
|
204
228
|
#### A note on citation formats
|
205
229
|
|
206
|
-
Due to the different expectations of different publication venues, the citation text may need minor tweaking to be used in specific situations. If you spot a major, or general, error in the output do [let us know](https://github.com/citation-file-format/ruby-cff/issues), but please check against the [
|
230
|
+
Due to the different expectations of different publication venues, the citation text may need minor tweaking to be used in specific situations. If you spot a major, or general, error in the output do [let us know](https://github.com/citation-file-format/ruby-cff/issues), but please check against the [BibTeX](https://www.bibtex.com/format/) and [APA](https://apastyle.apa.org/style-grammar-guidelines/references) standards first.
|
207
231
|
|
208
232
|
### Library versions
|
209
233
|
|
data/lib/cff/file.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright (c) 2018-
|
3
|
+
# Copyright (c) 2018-2024 The Ruby Citation File Format Developers.
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
@@ -19,7 +19,6 @@ require_relative 'index'
|
|
19
19
|
require_relative 'version'
|
20
20
|
|
21
21
|
require 'date'
|
22
|
-
require 'yaml'
|
23
22
|
|
24
23
|
##
|
25
24
|
module CFF
|
@@ -71,9 +70,7 @@ module CFF
|
|
71
70
|
content = ::File.read(file)
|
72
71
|
comment = File.parse_comment(content)
|
73
72
|
|
74
|
-
new(
|
75
|
-
file, YAML.safe_load(content, permitted_classes: [Date, Time]), comment
|
76
|
-
)
|
73
|
+
new(file, Util.parse_yaml(content), comment)
|
77
74
|
end
|
78
75
|
|
79
76
|
# :call-seq:
|
@@ -91,7 +88,7 @@ module CFF
|
|
91
88
|
if ::File.exist?(file)
|
92
89
|
content = ::File.read(file)
|
93
90
|
comment = File.parse_comment(content)
|
94
|
-
yaml =
|
91
|
+
yaml = Util.parse_yaml(content)
|
95
92
|
else
|
96
93
|
comment = CFF_COMMENT
|
97
94
|
yaml = ''
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright (c) 2018-
|
3
|
+
# Copyright (c) 2018-2024 The Ruby Citation File Format Developers.
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
@@ -45,13 +45,17 @@ module CFF
|
|
45
45
|
month.downcase unless month.nil?
|
46
46
|
end.freeze
|
47
47
|
|
48
|
+
# We need to escape these characters in titles and names, as per
|
49
|
+
# https://tex.stackexchange.com/questions/34580/escape-character-in-latex
|
50
|
+
ESCAPE_CHARS = Regexp.new(/([&%$#_{}])/)
|
51
|
+
|
48
52
|
def self.format(model:, preferred_citation: true) # rubocop:disable Metrics
|
49
53
|
model = select_and_check_model(model, preferred_citation)
|
50
54
|
return if model.nil?
|
51
55
|
|
52
56
|
values = {}
|
53
57
|
values['author'] = actor_list(model.authors)
|
54
|
-
values['title'] = "{#{model.title}}"
|
58
|
+
values['title'] = "{#{l(model.title)}}"
|
55
59
|
|
56
60
|
publication_type = bibtex_type(model)
|
57
61
|
publication_data_from_model(model, publication_type, values)
|
@@ -79,7 +83,7 @@ module CFF
|
|
79
83
|
def self.publication_data_from_model(model, type, fields)
|
80
84
|
ENTRY_TYPE_MAP[type].each do |field|
|
81
85
|
if model.respond_to?(field)
|
82
|
-
fields[field] = model.send(field).to_s
|
86
|
+
fields[field] = l(model.send(field).to_s)
|
83
87
|
else
|
84
88
|
field = field.chomp('!')
|
85
89
|
fields[field] = send("#{field}_from_model", model)
|
@@ -108,9 +112,9 @@ module CFF
|
|
108
112
|
# BibTeX 'institution' could be grabbed from an author's affiliation, or
|
109
113
|
# provided explicitly.
|
110
114
|
def self.institution_from_model(model)
|
111
|
-
return model.institution.name unless model.institution.empty?
|
115
|
+
return l(model.institution.name) unless model.institution.empty?
|
112
116
|
|
113
|
-
model.authors.first.affiliation
|
117
|
+
l(model.authors.first.affiliation)
|
114
118
|
end
|
115
119
|
|
116
120
|
# BibTeX 'school' is CFF 'institution'.
|
@@ -125,7 +129,7 @@ module CFF
|
|
125
129
|
|
126
130
|
# BibTeX 'booktitle' is CFF 'collection-title'.
|
127
131
|
def self.booktitle_from_model(model)
|
128
|
-
model.collection_title
|
132
|
+
l(model.collection_title)
|
129
133
|
end
|
130
134
|
|
131
135
|
# BibTeX 'editor' is CFF 'editors' or 'editors-series'.
|
@@ -138,11 +142,11 @@ module CFF
|
|
138
142
|
end
|
139
143
|
|
140
144
|
def self.publisher_from_model(model)
|
141
|
-
model.publisher.empty? ? '' : model.publisher.name
|
145
|
+
model.publisher.empty? ? '' : l(model.publisher.name)
|
142
146
|
end
|
143
147
|
|
144
148
|
def self.series_from_model(model)
|
145
|
-
model.conference.empty? ? '' : model.conference.name
|
149
|
+
model.conference.empty? ? '' : l(model.conference.name)
|
146
150
|
end
|
147
151
|
|
148
152
|
# If we're citing a conference paper, try and use the date of the
|
@@ -182,9 +186,9 @@ module CFF
|
|
182
186
|
end
|
183
187
|
end
|
184
188
|
|
185
|
-
def self.format_actor(author)
|
186
|
-
return "{#{author.name}}" if author.is_a?(Entity)
|
187
|
-
return author.alias if author.family_names.empty? && author.given_names.empty?
|
189
|
+
def self.format_actor(author) # rubocop:disable Metrics/AbcSize
|
190
|
+
return "{#{l(author.name)}}" if author.is_a?(Entity)
|
191
|
+
return l(author.alias) if author.family_names.empty? && author.given_names.empty?
|
188
192
|
|
189
193
|
particle =
|
190
194
|
author.name_particle.empty? ? '' : "#{author.name_particle} "
|
@@ -209,6 +213,12 @@ module CFF
|
|
209
213
|
|
210
214
|
Util.parameterize(reference)
|
211
215
|
end
|
216
|
+
|
217
|
+
# Escape a string to preserve special characters in LaTeX output.
|
218
|
+
# Used in many places, so short method name to preserve reading flow.
|
219
|
+
def self.l(string)
|
220
|
+
string.gsub(ESCAPE_CHARS, '\\\\\1')
|
221
|
+
end
|
212
222
|
end
|
213
223
|
end
|
214
224
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright (c) 2018-
|
3
|
+
# Copyright (c) 2018-2023 The Ruby Citation File Format Developers.
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
@@ -67,16 +67,9 @@ module CFF
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def self.month_and_year_from_date(value)
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
begin
|
74
|
-
date = Date.parse(value.to_s)
|
75
|
-
[date.month, date.year].map(&:to_s)
|
76
|
-
rescue ArgumentError
|
77
|
-
['', '']
|
78
|
-
end
|
79
|
-
end
|
70
|
+
return ['', ''] unless value.is_a?(Date)
|
71
|
+
|
72
|
+
[value.month, value.year].map(&:to_s)
|
80
73
|
end
|
81
74
|
|
82
75
|
# CFF 'pages' is the number of pages, which has no equivalent in BibTeX
|
data/lib/cff/index.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright (c) 2018-
|
3
|
+
# Copyright (c) 2018-2024 The Ruby Citation File Format Developers.
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
@@ -25,8 +25,6 @@ require_relative 'schema'
|
|
25
25
|
require_relative 'validatable'
|
26
26
|
require_relative 'citable'
|
27
27
|
|
28
|
-
require 'yaml'
|
29
|
-
|
30
28
|
##
|
31
29
|
module CFF
|
32
30
|
# Index is the core data structure for a CITATION.cff file. It can be
|
@@ -100,7 +98,7 @@ module CFF
|
|
100
98
|
#
|
101
99
|
# Read a CFF Index from a String and parse it for subsequent manipulation.
|
102
100
|
def self.read(index)
|
103
|
-
new(
|
101
|
+
new(Util.parse_yaml(index))
|
104
102
|
end
|
105
103
|
|
106
104
|
# :call-seq:
|
data/lib/cff/model_part.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright (c) 2018-
|
3
|
+
# Copyright (c) 2018-2023 The Ruby Citation File Format Developers.
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
@@ -59,23 +59,57 @@ module CFF
|
|
59
59
|
symbols.each do |symbol|
|
60
60
|
field = symbol.to_s.tr('_', '-')
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
# date = (date.is_a?(Date) ? date.dup : Date.parse(date))
|
65
|
-
#
|
66
|
-
# @fields['date-end'] = date
|
67
|
-
# end
|
68
|
-
<<-END_SETTER, __FILE__, __LINE__ + 1
|
69
|
-
def #{symbol}=(date)
|
70
|
-
date = (date.is_a?(Date) ? date.dup : Date.parse(date))
|
71
|
-
|
72
|
-
@fields['#{field}'] = date
|
73
|
-
end
|
74
|
-
END_SETTER
|
75
|
-
)
|
62
|
+
date_getter(symbol, field)
|
63
|
+
date_setter(symbol, field)
|
76
64
|
end
|
77
65
|
end
|
78
66
|
|
67
|
+
def self.date_getter(symbol, field)
|
68
|
+
class_eval(
|
69
|
+
# def date_end
|
70
|
+
# date = @fields['date-end']
|
71
|
+
# return date if date.is_a?(Date)
|
72
|
+
#
|
73
|
+
# begin
|
74
|
+
# Date.parse(date)
|
75
|
+
# rescue
|
76
|
+
# ''
|
77
|
+
# end
|
78
|
+
# end
|
79
|
+
<<-END_GETTER, __FILE__, __LINE__ + 1
|
80
|
+
def #{symbol}
|
81
|
+
date = @fields['#{field}']
|
82
|
+
return date if date.is_a?(Date)
|
83
|
+
|
84
|
+
begin
|
85
|
+
Date.parse(date)
|
86
|
+
rescue
|
87
|
+
''
|
88
|
+
end
|
89
|
+
end
|
90
|
+
END_GETTER
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.date_setter(symbol, field)
|
95
|
+
class_eval(
|
96
|
+
# def date_end=(date)
|
97
|
+
# date = (date.is_a?(Date) ? date.dup : Date.parse(date))
|
98
|
+
#
|
99
|
+
# @fields['date-end'] = date
|
100
|
+
# end
|
101
|
+
<<-END_SETTER, __FILE__, __LINE__ + 1
|
102
|
+
def #{symbol}=(date)
|
103
|
+
date = (date.is_a?(Date) ? date.dup : Date.parse(date))
|
104
|
+
|
105
|
+
@fields['#{field}'] = date
|
106
|
+
end
|
107
|
+
END_SETTER
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
private_class_method :date_getter, :date_setter
|
112
|
+
|
79
113
|
private
|
80
114
|
|
81
115
|
def method_to_field(name)
|
data/lib/cff/util.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright (c) 2018-
|
3
|
+
# Copyright (c) 2018-2024 The Ruby Citation File Format Developers.
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
@@ -19,6 +19,7 @@ require_relative 'person'
|
|
19
19
|
require_relative 'version'
|
20
20
|
|
21
21
|
require 'rubygems'
|
22
|
+
require 'yaml'
|
22
23
|
|
23
24
|
##
|
24
25
|
module CFF
|
@@ -30,6 +31,10 @@ module CFF
|
|
30
31
|
|
31
32
|
module_function
|
32
33
|
|
34
|
+
def parse_yaml(string)
|
35
|
+
YAML.safe_load(string, aliases: true, permitted_classes: [Date, Time])
|
36
|
+
end
|
37
|
+
|
33
38
|
def update_cff_version(version)
|
34
39
|
return '' if version.nil? || version.empty?
|
35
40
|
|
@@ -44,6 +49,8 @@ module CFF
|
|
44
49
|
# is a Person or Entity. This isn't perfect, but works 99.99% I think.
|
45
50
|
def build_actor_collection!(source)
|
46
51
|
source.map! do |s|
|
52
|
+
next s if s.is_a?(Person) || s.is_a?(Entity)
|
53
|
+
|
47
54
|
s.has_key?('name') ? Entity.new(s) : Person.new(s)
|
48
55
|
end
|
49
56
|
end
|
data/lib/cff/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Haines
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-10-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json_schema
|
@@ -242,7 +242,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
242
242
|
- !ruby/object:Gem::Version
|
243
243
|
version: '0'
|
244
244
|
requirements: []
|
245
|
-
rubygems_version: 3.
|
245
|
+
rubygems_version: 3.4.1
|
246
246
|
signing_key:
|
247
247
|
specification_version: 4
|
248
248
|
summary: A Ruby library for manipulating CITATION.cff files.
|