Skip to content

Commit 2e71bcb

Browse files
cthoytjezcope
andcommitted
Add CRediT roles to JATS
Enable annotating author roles using the Contribution Role Taxonomy (CRediT) and export this information in conformant JATS Co-Authored-By: Jez Cope <457628+jezcope@users.noreply.github.com>
1 parent b8c2d99 commit 2e71bcb

File tree

5 files changed

+591
-2
lines changed

5 files changed

+591
-2
lines changed

AUTHORS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
- Cezary Drożak
7070
- Chandrahas77
7171
- Charanjit Singh
72+
- Charles Tapley Hoyt
7273
- Charlotte Koch
7374
- Chris Black
7475
- Christian Conkle
@@ -197,6 +198,7 @@
197198
- Jeroen de Haas
198199
- Jerry Sky
199200
- Jesse Rosenthal
201+
- Jez Cope
200202
- Joe Hermaszewski
201203
- Joe Hillenbrand
202204
- John KetzerX

data/templates/article.jats_publishing

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,17 @@ $elseif(author.name)$
109109
$else$
110110
<string-name>$author$</string-name>
111111
$endif$
112+
$for(author.roles)$
113+
$if(it.credit)$
114+
<role vocab="credit"$if(it.degree)$ degree-contribution="$it.degree$"$endif$
115+
vocab-identifier="https://credit.niso.org/"
116+
vocab-term-identifier="https://credit.niso.org/contributor-roles/$it.credit$/"
117+
vocab-term="$it.credit-name$"
118+
>$if(it.name)$$it.name$$else$$it.credit-name$$endif$</role>
119+
$elseif(it.name)$
120+
<role>$it.name$</role>
121+
$endif$
122+
$endfor$
112123
$if(author.email)$
113124
<email>$author.email$</email>
114125
$endif$

doc/jats.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,85 @@ Metadata Values
6161
set it used, as affiliation links are not allowed in that
6262
schema.
6363

64+
`roles`
65+
: a list of dictionaries describing the author's role(s).
66+
Each role is added as an [`<role>`] element to
67+
the author's [`<contrib>`] element. The following examples
68+
illustrate:
69+
70+
An ad-hoc role:
71+
72+
```yaml
73+
roles:
74+
- name: Dolphin Catcher
75+
```
76+
77+
A role specified with CRediT.
78+
79+
```yaml
80+
roles:
81+
- credit: writing-review-editing
82+
```
83+
84+
The `credit-name` is automatically looked up from
85+
the CRediT taxonomy, but you can also specify it
86+
yourself:
87+
88+
```yaml
89+
roles:
90+
- credit: writing-review-editing
91+
credit-name: Writing – review & editing
92+
```
93+
94+
A role specified with CRediT, including an
95+
optional degree of contribution. Note that
96+
specifying the degree only is allowed when
97+
using CRediT roles and not ad-hoc roles.
98+
99+
```yaml
100+
roles:
101+
- credit: writing-review-editing
102+
degree: Lead
103+
```
104+
105+
A role specified with CRediT with a label override,
106+
useful for internationalization:
107+
108+
```yaml
109+
roles:
110+
- credit: writing-review-editing
111+
name: Escrita – revisão e edição
112+
```
113+
114+
The value for `credit` and `credit-name`
115+
must be from one of the 14 terms from the
116+
Contribution Role Taxonomy (CRediT):
117+
118+
| `credit` | `credit-name` |
119+
|--------------------------|----------------------------|
120+
| `conceptualization` | Conceptualization |
121+
| `data-curation` | Data curation |
122+
| `formal-analysis` | Formal analysis |
123+
| `funding-acquisition` | Funding acquisition |
124+
| `investigation` | Investigation |
125+
| `methodology` | Methodology |
126+
| `project-administration` | Project administration |
127+
| `resources` | Resources |
128+
| `software` | Software |
129+
| `supervision` | Supervision |
130+
| `validation` | Validation |
131+
| `visualization` | Visualization |
132+
| `writing-original-draft` | Writing – original draft |
133+
| `writing-review-editing` | Writing – review & editing |
134+
135+
JATS suggests in [`<degree-contribution>`] to use one of
136+
the following three values when specifying the degree of
137+
contribution:
138+
139+
1. `Lead`
140+
2. `Equal`
141+
3. `Supporting`
142+
64143
`equal-contrib`
65144
: boolean attribute used to mark authors who contributed
66145
equally to the work. The
@@ -483,3 +562,5 @@ Required metadata values:
483562
[`<institution-wrap>`]: https://jats.nlm.nih.gov/publishing/tag-library/1.2/element/institution-wrap.html
484563
[`<institution>`]: https://jats.nlm.nih.gov/publishing/tag-library/1.2/element/institution.html
485564
[`<pub-date>`]: https://jats.nlm.nih.gov/publishing/tag-library/1.2/element/pub-date.html
565+
[`<role>`]: https://jats.nlm.nih.gov/publishing/tag-library/1.2/element/role.html
566+
[`<degree-contribution>`]: https://jats.nlm.nih.gov/publishing/tag-library/1.2/attribute/degree-contribution.html

src/Text/Pandoc/Writers/JATS.hs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import Control.Monad.Reader
2727
import Control.Monad.State
2828
import Data.Generics (everywhere, mkT)
2929
import qualified Data.Map as M
30-
import Data.Maybe (fromMaybe, listToMaybe)
30+
import Data.Maybe (fromMaybe, listToMaybe, isNothing)
3131
import Data.Time (toGregorian, Day, parseTimeM, defaultTimeLocale, formatTime)
3232
import qualified Data.Text as T
3333
import Data.Text (Text)
@@ -43,7 +43,7 @@ import Text.DocLayout
4343
import Text.Pandoc.Shared
4444
import Text.Pandoc.URI
4545
import Text.Pandoc.Templates (renderTemplate)
46-
import Text.DocTemplates (Context(..), Val(..))
46+
import Text.DocTemplates (Context(..), Val(..), toVal)
4747
import Text.Pandoc.Writers.JATS.References (referencesToJATS)
4848
import Text.Pandoc.Writers.JATS.Table (tableToJATS)
4949
import Text.Pandoc.Writers.JATS.Types
@@ -54,6 +54,54 @@ import Text.TeXMath
5454
import qualified Text.Pandoc.Writers.AnnotatedTable as Ann
5555
import qualified Text.XML.Light as Xml
5656

57+
-- | Default human-readable names for roles in the Contributor Role
58+
-- Taxonomy (CRediT). This is useful for generating JATS that annotate
59+
-- contributor roles
60+
creditNames :: M.Map Text Text
61+
creditNames = M.fromList [
62+
("conceptualization", "Conceptualization"),
63+
("data-curation", "Data curation"),
64+
("formal-analysis", "Formal analysis"),
65+
("funding-acquisition", "Funding acquisition"),
66+
("investigation", "Investigation"),
67+
("methodology", "Methodology"),
68+
("project-administration", "Project administration"),
69+
("resources", "Resources"),
70+
("software", "Software"),
71+
("supervision", "Supervision"),
72+
("validation", "Validation"),
73+
("visualization", "Visualization"),
74+
("writing-original-draft", "Writing – original draft"),
75+
("writing-review-editing", "Writing – review & editing")]
76+
77+
-- | Ensure every role with a `credit` key also has a `credit-name`,
78+
-- using a default value if necessary
79+
addCreditNames :: Context Text -> Context Text
80+
addCreditNames context =
81+
case getField "author" context of
82+
-- If there is an "authors" key, then we replace the existing value
83+
-- with one we mutate by running the addCreditNamesToAuthor helper
84+
-- function on each
85+
Just (ListVal authors) ->
86+
resetField "author" (map addCreditNamesToAuthor authors) context
87+
-- If there is no "authors" key in the context, then we don't have to do
88+
-- anything, and just return the context as is
89+
_ -> context
90+
where
91+
addCreditNamesToAuthor :: Val Text -> Val Text
92+
addCreditNamesToAuthor val = fromMaybe val $ do
93+
MapVal authorCtx <- pure val
94+
ListVal roles <- getField "roles" authorCtx
95+
return $ toVal $ resetField "roles" (map addCreditNameToRole roles) authorCtx
96+
97+
addCreditNameToRole :: Val Text -> Val Text
98+
addCreditNameToRole val = fromMaybe val $ do
99+
MapVal roleCtx <- pure val
100+
guard $ isNothing (getField "credit-name" roleCtx :: Maybe (Val Text))
101+
creditId <- getField "credit" roleCtx
102+
creditName <- M.lookup creditId creditNames
103+
return $ toVal $ resetField "credit-name" creditName roleCtx
104+
57105
-- | Convert a @'Pandoc'@ document to JATS (Archiving and Interchange
58106
-- Tag Set.)
59107
writeJatsArchiving :: PandocMonad m => WriterOptions -> Pandoc -> m Text
@@ -159,6 +207,7 @@ docToJATS opts (Pandoc meta blocks') = do
159207
(lookupMetaInlines "title" meta)
160208
let context = defField "body" main
161209
$ defField "back" back
210+
$ addCreditNames
162211
$ resetField "title" title'
163212
$ resetField "date" date
164213
$ defField "mathml" (case writerHTMLMathMethod opts of

0 commit comments

Comments
 (0)