Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add contributor roles #87

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

`Inara` uses [SemVer][] (semantic versioning).

## UNRELEASED

- Support for annotating author roles with the Contribution Role Taxonomy (CRediT) (https://github.com/openjournals/inara/pull/87)

## Inara v1.1.3

Released 2024-10-24.
Expand Down
2 changes: 2 additions & 0 deletions data/defaults/pdf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ filters:
path: self-citation.lua
- type: lua
path: fix-bibentry-spacing.lua
- type: lua
path: prepare-credit.lua
variables:
# styling options
colorlinks: true
Expand Down
3 changes: 3 additions & 0 deletions data/defaults/preprint.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
to: latex
output-file: paper.preprint.tex
template: preprint.latex
filters:
- type: lua
path: prepare-credit.lua
variables:
# styling options
colorlinks: true
Expand Down
2 changes: 2 additions & 0 deletions data/defaults/tex.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ filters:
path: self-citation.lua
- type: lua
path: fix-bibentry-spacing.lua
- type: lua
path: prepare-credit.lua
variables:
# styling options
colorlinks: true
Expand Down
218 changes: 218 additions & 0 deletions data/filters/prepare-credit.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
-- Checks if any contributor information is available

local roles = {
["conceptualization"] = {
name = "Conceptualization",
id = "8b73531f-db56-4914-9502-4cc4d4d8ed73",
uri = "https://credit.niso.org/contributor-roles/conceptualization/"
},
["data-curation"] = {
name = "Data curation",
id = "f93e0f44-f2a4-4ea1-824a-4e0853b05c9d",
uri = "https://credit.niso.org/contributor-roles/data-curation/"
},
["formal-analysis"] = {
name = "Formal analysis",
id = "95394cbd-4dc8-4735-b589-7e5f9e622b3f",
uri = "https://credit.niso.org/contributor-roles/formal-analysis/"
},
["funding-acquisition"] = {
name = "Funding acquisition",
id = "34ff6d68-132f-4438-a1f4-fba61ccf364a",
uri = "https://credit.niso.org/contributor-roles/funding-acquisition/"
},
["investigation"] = {
name = "Investigation",
id = "2451924d-425e-4778-9f4c-36c848ca70c2",
uri = "https://credit.niso.org/contributor-roles/investigation/"
},
["methodology"] = {
name = "Methodology",
id = "f21e2be9-4e38-4ab7-8691-d6f72d5d5843",
uri = "https://credit.niso.org/contributor-roles/methodology/"
},
["project-administration"] = {
name = "Project administration",
id = "a693fe76-ea33-49ad-9dcc-5e4f3ac5f938",
uri = "https://credit.niso.org/contributor-roles/project-administration/"
},
["resources"] = {
name = "Resources",
id = "ebd781f0-bf79-492c-ac21-b31b9c3c990c",
uri = "https://credit.niso.org/contributor-roles/resources/"
},
["software"] = {
name = "Software",
id = "f89c5233-01b0-4778-93e9-cc7d107aa2c8",
uri = "https://credit.niso.org/contributor-roles/software/"
},
["supervision"] = {
name = "Supervision",
id = "0c8ca7d4-06ad-4527-9cea-a8801fcb8746",
uri = "https://credit.niso.org/contributor-roles/supervision/"
},
["validation"] = {
name = "Validation",
id = "4b1bf348-faf2-4fc4-bd66-4cd3a84b9d44",
uri = "https://credit.niso.org/contributor-roles/validation/"
},
["visualization"] = {
name = "Visualization",
id = "76b9d56a-e430-4e0a-84c9-59c11be343ae",
uri = "https://credit.niso.org/contributor-roles/visualization/"
},
["writing-original-draft"] = {
name = "Writing – original draft",
id = "43ebbd94-98b4-42f1-866b-c930cef228ca",
uri = "https://credit.niso.org/contributor-roles/writing-original-draft/"
},
["writing-review-editing"] = {
name = "Writing – review & editing",
id = "d3aead86-f2a2-47f7-bb99-79de6421164d",
uri = "https://credit.niso.org/contributor-roles/writing-review-editing/"
}
}

degrees = pandoc.List {
"Lead",
"Supporting",
"Equal"
}

function invalidRole(str)
return roles[str] == nil
end

function invalidDegree(str)
return not degrees:includes(str)
end

function join_with_commas_and(list)
local len = #list
if len == 0 then
return ""
elseif len == 1 then
return list[1]
elseif len == 2 then
return list[1] .. " and " .. list[2]
else
local result = table.concat(list, ", ", 1, len - 1)
return result .. ", and " .. list[len]
end
cthoyt marked this conversation as resolved.
Show resolved Hide resolved
end

function capitalize_first_letter(str)
return str:sub(1, 1):upper() .. str:sub(2)
end

function clean_role_dict(d)
if d.type then
return d
else
return { ["type"] = pandoc.utils.stringify(d) }
end
end

local function prepare_credit (meta)
meta.hasRoles = false
for _, author in ipairs(meta.authors or {}) do
if author.roles then
roleList = {}
for _, roleDict in ipairs(author.roles) do
roleDict = clean_role_dict(roleDict)
role = pandoc.utils.stringify(roleDict.type)
if invalidRole(role) then
print("invalid role for author " .. author.name .. ": " .. role)
elseif roleDict.degree then
degree = capitalize_first_letter(pandoc.utils.stringify(roleDict.degree))
if invalidDegree(degree) then
print("invalid degree for author " .. author.name .. ": " .. degree)
-- even though the degree is invalid, add the role anyway
table.insert(roleList, roles[role].name)
else
table.insert(roleList, roles[role].name .. " (" .. degree .. ")")
end
else
table.insert(roleList, roles[role].name)
end
end
if #roleList > 0 then
meta.hasRoles = true
author.rolesString = join_with_commas_and(roleList)
end
end
end
return meta
end

function Meta (meta)
local ok, result = pcall(prepare_credit, meta)
if ok then
return result
end
end

function assertEqual(expected, actual)
assert(expected == actual, "got \"" .. actual .. "\", expected \"" .. expected .. "\"")
end

function tests()
assert("" == join_with_commas_and({ }))
assert("foo" == join_with_commas_and({ "foo" }))
assert("foo and bar" == join_with_commas_and({ "foo", "bar" }))
assert("foo, bar, and baz" == join_with_commas_and({ "foo", "bar", "baz" }))

local m1 = {
["authors"] = {
{
["name"] = "Author 1",
["roles"] = {
"methodology"
}
},
{
["name"] = "Author 2",
['roles'] = {
{ ["type"] = "methodology" }
}
},
{
["name"] = "Author 3",
['roles'] = {
{ ["type"] = "methodology" },
{ ["type"] = "data-curation" },
{ ["type"] = "conceptualization" },
}
},
{
["name"] = "Author 4",
['roles'] = {
{ ["type"] = "methodology", ["degree"] = "lead" },
{ ["type"] = "data-curation", ["degree"] = "supporting" },
{ ["type"] = "conceptualization" },
}
},
}
}
local m1t = prepare_credit(m1)
assert(m1t.hasRoles, "hasRoles should be set to true")
assertEqual("Methodology", m1t['authors'][1].rolesString)
assertEqual("Methodology", m1t['authors'][2].rolesString)
assertEqual("Methodology, Data curation, and Conceptualization", m1t['authors'][3].rolesString)
assertEqual("Methodology (Lead), Data curation (Supporting), and Conceptualization", m1t['authors'][4].rolesString)

local m2 = {
["authors"] = {
{
["name"] = "Author 1"
},
{
["name"] = "Author 2"
}
}
}
local m2t = prepare_credit(m2)
assert(not m2t.hasRoles, "hasRoles should be set to false")
end

tests()
11 changes: 11 additions & 0 deletions data/templates/default.latex
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,17 @@ $if(lof)$
$endif$
$body$

$if(hasRoles)$
\section{Author Contributions}\label{author-contributions}
\begin{enumerate}
$for(authors)$
$if(it.rolesString)$
\item $it.name$ - $it.rolesString$
$endif$
$endfor$
\end{enumerate}
$endif$

$if(natbib)$
$if(bibliography)$
$if(biblio-title)$
Expand Down
11 changes: 11 additions & 0 deletions data/templates/preprint.latex
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,17 @@ $if(has-frontmatter)$
$endif$
$body$

$if(hasRoles)$
\section{Author Contributions}\label{author-contributions}
\begin{enumerate}
$for(authors)$
$if(it.rolesString)$
\item $it.name$ - $it.rolesString$
$endif$
$endfor$
\end{enumerate}
$endif$

$if(has-frontmatter)$
\backmatter
$endif$
Expand Down
79 changes: 79 additions & 0 deletions example/paper.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,27 @@ authors:
affiliation: "1, 2, 4"
orcid: 0000-0002-9455-0796
corresponding: true
roles:
- type: software
degree: equal
- 'methodology'
- name: Juanjo Bazán
orcid: 0000-0001-7699-3983
affiliation: [1]
equal-contrib: true
roles:
- type: software
degree: equal
- name: Arfon M. Smith
orcid: 0000-0002-3957-2474
affiliation: [1, 3]
equal-contrib: true
roles:
- type: software
degree: equal
- type: supervision
degree: lead

affiliations:
- index: 1
name: Open Journals
Expand Down Expand Up @@ -365,6 +378,72 @@ authors:
<!-- given-names: 瀧 -->
<!-- surname: 立花 -->

## Contributor Roles

The [Contribution Role Taxonomy (CRediT)](https://credit.niso.org/contributor-roles) defines
fourteen standard roles of authors. Each author can be annotated with one or more contribution
roles.

1. [conceptualization](https://credit.niso.org/contributor-roles/conceptualization)
2. [data-curation](https://credit.niso.org/contributor-roles/data-curation)
3. [formal-analysis](https://credit.niso.org/contributor-roles/formal-analysis)
4. [funding-acquisition](https://credit.niso.org/contributor-roles/funding-acquisition)
5. [investigation](https://credit.niso.org/contributor-roles/investigation)
6. [methodology](https://credit.niso.org/contributor-roles/methodology)
7. [project-administration](https://credit.niso.org/contributor-roles/project-administration)
8. [resources](https://credit.niso.org/contributor-roles/resources)
9. [software](https://credit.niso.org/contributor-roles/software)
10. [supervision](https://credit.niso.org/contributor-roles/supervision)
11. [validation](https://credit.niso.org/contributor-roles/validation)
12. [visualization](https://credit.niso.org/contributor-roles/visualization)
13. [writing-original-draft](https://credit.niso.org/contributor-roles/writing-original-draft)
14. [writing-review-editing](https://credit.niso.org/contributor-roles/writing-review-editing)

JATS also specifies three degrees which can be used to quantify the impact of a contribution:

1. `Lead`
2. `Supporting`
3. `Equal` - for use if multiple equivalent leads

Together, these can be used to identify which authors materially contributed to the paper,
such as through `formal-analysis` or `data-curation` and which authors contributed immaterially,
such as through `supervision`. It also allows for saying if multiple people made the same
kind of contribution, who took the lead.

```yaml
authors:
- name: John Doe
affiliation: [ 1 ]
roles:
- type: 'formal-analysis'
degree: 'lead'

- name: John Boss
affiliation: [ 1 ]
roles:
- type: 'funding-acquisition'
degree: 'lead'
- type: 'supervision'
degree: 'lead'
```

Roles are optional, and within roles, degrees are optional. It's possible to shorthand
roles by using strings directly:

```yaml
authors:
- name: John Doe
affiliation: [ 1 ]
roles:
- 'formal-analysis'

- name: John Boss
affiliation: [ 1 ]
roles:
- 'funding-acquisition'
- 'supervision'
```

## Affiliations

Each affiliation requires an `index` and `name`.
Expand Down
Loading
Loading