diff --git a/AUTHORS.md b/AUTHORS.md index e11e98885..4e762fd08 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -69,6 +69,7 @@ - Cezary Drożak - Chandrahas77 - Charanjit Singh +- Charles Tapley Hoyt - Charlotte Koch - Chris Black - Christian Conkle @@ -197,6 +198,7 @@ - Jeroen de Haas - Jerry Sky - Jesse Rosenthal +- Jez Cope - Joe Hermaszewski - Joe Hillenbrand - John KetzerX diff --git a/data/templates/article.jats_publishing b/data/templates/article.jats_publishing index 981f86762..d402b8bbd 100644 --- a/data/templates/article.jats_publishing +++ b/data/templates/article.jats_publishing @@ -109,6 +109,17 @@ $elseif(author.name)$ $else$ $author$ $endif$ +$for(author.roles)$ +$if(it.credit)$ +$if(it.name)$$it.name$$else$$it.credit-name$$endif$ +$elseif(it.name)$ +$it.name$ +$endif$ +$endfor$ $if(author.email)$ $author.email$ $endif$ diff --git a/doc/jats.md b/doc/jats.md index 4ac54f25b..a723ccce5 100644 --- a/doc/jats.md +++ b/doc/jats.md @@ -61,6 +61,85 @@ Metadata Values set it used, as affiliation links are not allowed in that schema. + `roles` + : a list of dictionaries describing the author's role(s). + Each role is added as an [``] element to + the author's [``] element. The following examples + illustrate: + + An ad-hoc role: + + ```yaml + roles: + - name: Dolphin Catcher + ``` + + A role specified with CRediT. + + ```yaml + roles: + - credit: writing-review-editing + ``` + + The `credit-name` is automatically looked up from + the CRediT taxonomy, but you can also specify it + yourself: + + ```yaml + roles: + - credit: writing-review-editing + credit-name: Writing – review & editing + ``` + + A role specified with CRediT, including an + optional degree of contribution. Note that + specifying the degree only is allowed when + using CRediT roles and not ad-hoc roles. + + ```yaml + roles: + - credit: writing-review-editing + degree: Lead + ``` + + A role specified with CRediT with a label override, + useful for internationalization: + + ```yaml + roles: + - credit: writing-review-editing + name: Escrita – revisão e edição + ``` + + The value for `credit` and `credit-name` + must be from one of the 14 terms from the + Contribution Role Taxonomy (CRediT): + + | `credit` | `credit-name` | + |--------------------------|----------------------------| + | `conceptualization` | Conceptualization | + | `data-curation` | Data curation | + | `formal-analysis` | Formal analysis | + | `funding-acquisition` | Funding acquisition | + | `investigation` | Investigation | + | `methodology` | Methodology | + | `project-administration` | Project administration | + | `resources` | Resources | + | `software` | Software | + | `supervision` | Supervision | + | `validation` | Validation | + | `visualization` | Visualization | + | `writing-original-draft` | Writing – original draft | + | `writing-review-editing` | Writing – review & editing | + + JATS suggests in [``] to use one of + the following three values when specifying the degree of + contribution: + + 1. `Lead` + 2. `Equal` + 3. `Supporting` + `equal-contrib` : boolean attribute used to mark authors who contributed equally to the work. The @@ -483,3 +562,5 @@ Required metadata values: [``]: https://jats.nlm.nih.gov/publishing/tag-library/1.2/element/institution-wrap.html [``]: https://jats.nlm.nih.gov/publishing/tag-library/1.2/element/institution.html [``]: https://jats.nlm.nih.gov/publishing/tag-library/1.2/element/pub-date.html +[``]: https://jats.nlm.nih.gov/publishing/tag-library/1.2/element/role.html +[``]: https://jats.nlm.nih.gov/publishing/tag-library/1.2/attribute/degree-contribution.html diff --git a/src/Text/Pandoc/Writers/JATS.hs b/src/Text/Pandoc/Writers/JATS.hs index e09738908..dc288c6c0 100644 --- a/src/Text/Pandoc/Writers/JATS.hs +++ b/src/Text/Pandoc/Writers/JATS.hs @@ -27,7 +27,7 @@ import Control.Monad.Reader import Control.Monad.State import Data.Generics (everywhere, mkT) import qualified Data.Map as M -import Data.Maybe (fromMaybe, listToMaybe) +import Data.Maybe (fromMaybe, listToMaybe, isNothing) import Data.Time (toGregorian, Day, parseTimeM, defaultTimeLocale, formatTime) import qualified Data.Text as T import Data.Text (Text) @@ -43,7 +43,7 @@ import Text.DocLayout import Text.Pandoc.Shared import Text.Pandoc.URI import Text.Pandoc.Templates (renderTemplate) -import Text.DocTemplates (Context(..), Val(..)) +import Text.DocTemplates (Context(..), Val(..), toVal) import Text.Pandoc.Writers.JATS.References (referencesToJATS) import Text.Pandoc.Writers.JATS.Table (tableToJATS) import Text.Pandoc.Writers.JATS.Types @@ -54,6 +54,54 @@ import Text.TeXMath import qualified Text.Pandoc.Writers.AnnotatedTable as Ann import qualified Text.XML.Light as Xml +-- | Default human-readable names for roles in the Contributor Role +-- Taxonomy (CRediT). This is useful for generating JATS that annotate +-- contributor roles +creditNames :: M.Map Text Text +creditNames = M.fromList [ + ("conceptualization", "Conceptualization"), + ("data-curation", "Data curation"), + ("formal-analysis", "Formal analysis"), + ("funding-acquisition", "Funding acquisition"), + ("investigation", "Investigation"), + ("methodology", "Methodology"), + ("project-administration", "Project administration"), + ("resources", "Resources"), + ("software", "Software"), + ("supervision", "Supervision"), + ("validation", "Validation"), + ("visualization", "Visualization"), + ("writing-original-draft", "Writing – original draft"), + ("writing-review-editing", "Writing – review & editing")] + +-- | Ensure every role with a `credit` key also has a `credit-name`, +-- using a default value if necessary +addCreditNames :: Context Text -> Context Text +addCreditNames context = + case getField "author" context of + -- If there is an "authors" key, then we replace the existing value + -- with one we mutate by running the addCreditNamesToAuthor helper + -- function on each + Just (ListVal authors) -> + resetField "author" (map addCreditNamesToAuthor authors) context + -- If there is no "authors" key in the context, then we don't have to do + -- anything, and just return the context as is + _ -> context + where + addCreditNamesToAuthor :: Val Text -> Val Text + addCreditNamesToAuthor val = fromMaybe val $ do + MapVal authorCtx <- pure val + ListVal roles <- getField "roles" authorCtx + return $ toVal $ resetField "roles" (map addCreditNameToRole roles) authorCtx + + addCreditNameToRole :: Val Text -> Val Text + addCreditNameToRole val = fromMaybe val $ do + MapVal roleCtx <- pure val + guard $ isNothing (getField "credit-name" roleCtx :: Maybe (Val Text)) + creditId <- getField "credit" roleCtx + creditName <- M.lookup creditId creditNames + return $ toVal $ resetField "credit-name" creditName roleCtx + -- | Convert a @'Pandoc'@ document to JATS (Archiving and Interchange -- Tag Set.) writeJatsArchiving :: PandocMonad m => WriterOptions -> Pandoc -> m Text @@ -159,6 +207,7 @@ docToJATS opts (Pandoc meta blocks') = do (lookupMetaInlines "title" meta) let context = defField "body" main $ defField "back" back + $ addCreditNames $ resetField "title" title' $ resetField "date" date $ defField "mathml" (case writerHTMLMathMethod opts of diff --git a/test/command/10152.md b/test/command/10152.md new file mode 100644 index 000000000..44c5df625 --- /dev/null +++ b/test/command/10152.md @@ -0,0 +1,446 @@ +# CRediT Roles + +This document contains tests and examples for enabling +export of roles to JATS. It was added for +[Issue #10152](https://github.com/jgm/pandoc/issues/10152) +and corresponding [Pull Request #10153](https://github.com/jgm/pandoc/pull/10153). + +In the first example, we show a fully qualified CRediT role. +An explicit name isn't given, so the CRediT name is used. + +``` +% pandoc -s -t jats +--- +title: CRediT Test +author: + - name: Max Mustermann + affiliation: [ 1 ] + roles: + - credit: software + credit-name: Software + degree: Lead +affiliation: +- id: 1 + name: Silverlight University +--- +^D + + +
+ + + + + + + + + + + + +CRediT Test + + + +Max Mustermann +Software + + + + +Silverlight University + + + + + + + + + + + + +
+``` + +In the second example, we show a fully qualified CRediT role. +An explicit name is given in a different language. + +``` +% pandoc -s -t jats +--- +title: CRediT Test +author: + - name: Max Mustermann + affiliation: [ 1 ] + roles: + - credit: software + credit-name: Software + degree: Lead + name: Programas +affiliation: +- id: 1 + name: Silverlight University +--- +^D + + +
+ + + + + + + + + + + + +CRediT Test + + + +Max Mustermann +Programas + + + + +Silverlight University + + + + + + + + + + + + +
+``` + +In this example, we show a partially qualified CRediT role +that does not have a `degree`: + +``` +% pandoc -s -t jats +--- +title: CRediT Test +author: + - name: Max Mustermann + affiliation: [ 1 ] + roles: + - credit: software + credit-name: Software +affiliation: +- id: 1 + name: Silverlight University +--- +^D + + +
+ + + + + + + + + + + + +CRediT Test + + + +Max Mustermann +Software + + + + +Silverlight University + + + + + + + + + + + + +
+``` + +In this example, we show a more stripped-down data that requires automatic lookup of the +`credit-name`. + +``` +% pandoc -s -t jats +--- +title: CRediT Test +author: + - name: Max Mustermann + affiliation: [ 1 ] + roles: + - credit: software +affiliation: +- id: 1 + name: Silverlight University +--- +^D + + +
+ + + + + + + + + + + + +CRediT Test + + + +Max Mustermann +Software + + + + +Silverlight University + + + + + + + + + + + + +
+``` + +In this example, we test the correct XML encoding of +the CRediT role [Writing – review & editing](https://credit.niso.org/contributor-roles/writing-review-editing/), +which annoyingly contains an ampersand in its label. + +``` +% pandoc -s -t jats +--- +title: CRediT Test +author: + - name: Max Mustermann + affiliation: [ 1 ] + roles: + - credit: writing-review-editing + credit-name: Writing – review & editing + degree: Lead +affiliation: +- id: 1 + name: Silverlight University +--- +^D + + +
+ + + + + + + + + + + + +CRediT Test + + + +Max Mustermann +Writing – review & editing + + + + +Silverlight University + + + + + + + + + + + + +
+``` + +In this example, we show a role that isn't qualified with CRediT. + +``` +% pandoc -s -t jats +--- +title: CRediT Test +author: + - name: Max Mustermann + affiliation: [ 1 ] + roles: + - name: Dolphin Catcher +affiliation: +- id: 1 + name: Silverlight University +--- +^D + + +
+ + + + + + + + + + + + +CRediT Test + + + +Max Mustermann +Dolphin Catcher + + + + +Silverlight University + + + + + + + + + + + + +
+``` + +In this example, we show a role that neither has a CRediT identifer, +nor a name, so it's ignored. + +``` +% pandoc -s -t jats +--- +title: CRediT Test +author: + - name: Max Mustermann + affiliation: [ 1 ] + roles: + - irrelevant-key: Dolphin Catcher +affiliation: +- id: 1 + name: Silverlight University +--- +^D + + +
+ + + + + + + + + + + + +CRediT Test + + + +Max Mustermann + + + + +Silverlight University + + + + + + + + + + + + +
+```