Skip to content

Commit 1b52f86

Browse files
committed
Turn on underlying support for YAML anchors/aliases.
This commit adds support for using YAML anchors and aliases in CFF files. With this in place the underlying Ruby YAML library will load and reference anchors/aliases as expected, and Ruby CFF will process and validate such files as expected too. Links between anchors/aliases are preserved in line with expectations. Fixes #130
1 parent 8b9b63d commit 1b52f86

File tree

7 files changed

+91
-4
lines changed

7 files changed

+91
-4
lines changed

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,30 @@ CFF::File.open('CITATION.cff') do |cff|
122122
end
123123
```
124124

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+
125149
### Validating CFF files
126150

127151
To quickly validate a file and raise an error on failure, you can use `CFF::File` directly:

lib/cff/util.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ module Util
3232
module_function
3333

3434
def parse_yaml(string)
35-
YAML.safe_load(string, permitted_classes: [Date, Time])
35+
YAML.safe_load(string, aliases: true, permitted_classes: [Date, Time])
3636
end
3737

3838
def update_cff_version(version)
@@ -49,6 +49,8 @@ def update_cff_version(version)
4949
# is a Person or Entity. This isn't perfect, but works 99.99% I think.
5050
def build_actor_collection!(source)
5151
source.map! do |s|
52+
next s if s.is_a?(Person) || s.is_a?(Entity)
53+
5254
s.has_key?('name') ? Entity.new(s) : Person.new(s)
5355
end
5456
end
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Haines, R. (2018). Ruby CFF Library (Version 0.4.0) [Computer software]
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@software{Haines_Ruby_CFF_Library_2018,
2+
author = {Haines, Robert},
3+
license = {Apache-2.0},
4+
month = jul,
5+
title = {{Ruby CFF Library}},
6+
version = {0.4.0},
7+
year = {2018}
8+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# An incomplete CFF file with aliases
2+
3+
cff-version: 1.2.0
4+
message: If you use this software in your work, please cite it using the following metadata
5+
title: Ruby CFF Library
6+
authors: &authors
7+
- family-names: Haines
8+
given-names: Robert
9+
affiliation: The University of Manchester, UK
10+
keywords: &keywords
11+
- ruby
12+
- credit
13+
- citation
14+
version: 0.4.0
15+
date-released: 2018-07-22
16+
license: Apache-2.0
17+
repository-artifact: https://rubygems.org/gems/cff
18+
type: software
19+
references:
20+
- type: software
21+
title: Citation File Format
22+
authors: *authors
23+
keywords: *keywords

test/files/validation/aliases.cff

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# An incomplete CFF file with aliases
2+
3+
cff-version: 1.2.0
4+
message: If you use this software in your work, please cite it using the following metadata
5+
title: Ruby CFF Library
6+
authors: &authors
7+
- family-names: Haines
8+
given-names: Robert
9+
affiliation: The University of Manchester, UK
10+
keywords: &keywords
11+
- ruby
12+
- credit
13+
- citation
14+
version: 0.4.0
15+
date-released: 2018-07-22
16+
license: Apache-2.0
17+
repository-artifact: https://rubygems.org/gems/cff
18+
type: software
19+
references:
20+
- type: software
21+
title: Citation File Format
22+
authors: *authors
23+
keywords: *keywords

test/util_test.rb

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# frozen_string_literal: true
22

3-
# Copyright (c) 2018-2022 The Ruby Citation File Format Developers.
3+
# Copyright (c) 2018-2024 The Ruby Citation File Format Developers.
44
#
55
# Licensed under the Apache License, Version 2.0 (the "License");
66
# you may not use this file except in compliance with the License.
@@ -32,15 +32,21 @@ def test_update_cff_version
3232
def test_build_actor_collection
3333
array = [
3434
{ 'family-names' => 'Second', 'given-names' => 'First' },
35-
{ 'name' => 'Company' }
35+
{ 'name' => 'Company' },
36+
::CFF::Person.new('Firstname', 'Secondname'),
37+
::CFF::Entity.new('Company Inc.')
3638
]
3739

3840
build_actor_collection!(array)
39-
assert_equal(2, array.length)
41+
assert_equal(4, array.length)
4042
assert_instance_of ::CFF::Person, array[0]
4143
assert_equal('First', array[0].given_names)
4244
assert_instance_of ::CFF::Entity, array[1]
4345
assert_equal('Company', array[1].name)
46+
assert_instance_of ::CFF::Person, array[2]
47+
assert_equal('Firstname', array[2].given_names)
48+
assert_instance_of ::CFF::Entity, array[3]
49+
assert_equal('Company Inc.', array[3].name)
4450
end
4551

4652
def test_normalize_modelpart_array

0 commit comments

Comments
 (0)