Skip to content

Commit

Permalink
Turn on underlying support for YAML anchors/aliases.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
hainesr committed Oct 26, 2024
1 parent 8b9b63d commit 1b52f86
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 4 deletions.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,30 @@ CFF::File.open('CITATION.cff') do |cff|
end
```

#### Notes on CFF files with YAML anchors and aliases

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:

```yaml
cff-version: 1.2.0
title: Ruby CFF Library
authors: &authors
- family-names: Haines
given-names: Robert
affiliation: The University of Manchester, UK
...
references:
- type: software
title: Citation File Format
authors: *authors
```

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.

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`.

### Validating CFF files

To quickly validate a file and raise an error on failure, you can use `CFF::File` directly:
Expand Down
4 changes: 3 additions & 1 deletion lib/cff/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module Util
module_function

def parse_yaml(string)
YAML.safe_load(string, permitted_classes: [Date, Time])
YAML.safe_load(string, aliases: true, permitted_classes: [Date, Time])
end

def update_cff_version(version)
Expand All @@ -49,6 +49,8 @@ def update_cff_version(version)
# is a Person or Entity. This isn't perfect, but works 99.99% I think.
def build_actor_collection!(source)
source.map! do |s|
next s if s.is_a?(Person) || s.is_a?(Entity)

s.has_key?('name') ? Entity.new(s) : Person.new(s)
end
end
Expand Down
1 change: 1 addition & 0 deletions test/files/formatted/short-with-aliases.apa
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Haines, R. (2018). Ruby CFF Library (Version 0.4.0) [Computer software]
8 changes: 8 additions & 0 deletions test/files/formatted/short-with-aliases.bibtex
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@software{Haines_Ruby_CFF_Library_2018,
author = {Haines, Robert},
license = {Apache-2.0},
month = jul,
title = {{Ruby CFF Library}},
version = {0.4.0},
year = {2018}
}
23 changes: 23 additions & 0 deletions test/files/formatter/short-with-aliases.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# An incomplete CFF file with aliases

cff-version: 1.2.0
message: If you use this software in your work, please cite it using the following metadata
title: Ruby CFF Library
authors: &authors
- family-names: Haines
given-names: Robert
affiliation: The University of Manchester, UK
keywords: &keywords
- ruby
- credit
- citation
version: 0.4.0
date-released: 2018-07-22
license: Apache-2.0
repository-artifact: https://rubygems.org/gems/cff
type: software
references:
- type: software
title: Citation File Format
authors: *authors
keywords: *keywords
23 changes: 23 additions & 0 deletions test/files/validation/aliases.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# An incomplete CFF file with aliases

cff-version: 1.2.0
message: If you use this software in your work, please cite it using the following metadata
title: Ruby CFF Library
authors: &authors
- family-names: Haines
given-names: Robert
affiliation: The University of Manchester, UK
keywords: &keywords
- ruby
- credit
- citation
version: 0.4.0
date-released: 2018-07-22
license: Apache-2.0
repository-artifact: https://rubygems.org/gems/cff
type: software
references:
- type: software
title: Citation File Format
authors: *authors
keywords: *keywords
12 changes: 9 additions & 3 deletions test/util_test.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

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

build_actor_collection!(array)
assert_equal(2, array.length)
assert_equal(4, array.length)
assert_instance_of ::CFF::Person, array[0]
assert_equal('First', array[0].given_names)
assert_instance_of ::CFF::Entity, array[1]
assert_equal('Company', array[1].name)
assert_instance_of ::CFF::Person, array[2]
assert_equal('Firstname', array[2].given_names)
assert_instance_of ::CFF::Entity, array[3]
assert_equal('Company Inc.', array[3].name)
end

def test_normalize_modelpart_array
Expand Down

0 comments on commit 1b52f86

Please sign in to comment.