diff --git a/DESCRIPTION b/DESCRIPTION index 30e486a2c..7359ee41a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: rticles Type: Package Title: Article Formats for R Markdown -Version: 0.14.3 +Version: 0.14.4 Authors@R: c( person("JJ", "Allaire", role = "aut", email = "jj@rstudio.com"), person("Yihui", "Xie", role = c("aut", "cre"), email = "xie@yihui.name", comment = c(ORCID = "0000-0003-0645-5666")), @@ -40,6 +40,7 @@ Authors@R: c( person("Robrecht", "Cannoodt", role = c("aut", "cph"), email = "rcannood@gmail.com", comment = c(ORCID = "0000-0003-3641-729X", github = "rcannood")), person("Duncan", "Luguern", role = c("aut"), email = "duncan.luguern@gmail.com"), person("David M.", "Kaplan", role = c("aut", "ctb"), email = "dmkaplan2000@gmail.com", comment = c(ORCID = "0000-0001-6087-359X", github = "dmkaplan2000")), + person("Sebastian", "Kreutzer", role = c("aut"), email = "sebastian.kreutzer@aber.ac.uk", comment = c(ORCID = "0000-0002-0734-2199")), person("Shixiang", "Wang", role = c("aut", "ctb"), email = "w_shixiang@163.com", comment = c(ORCID = "0000-0001-9855-7357")), person('Jay', 'Hesselberth', role = c('aut', 'ctb'), email = 'jay.hesselberth@gmail.com', comment = c(ORCID = '0000-0002-6299-179X')), person("Alfredo", "Hernández", role = c("ctb"), email = "aldomann.designs@gmail.com", comment = c(ORCID = "0000-0002-2660-4545")), diff --git a/NEWS.md b/NEWS.md index ff623fedb..13fa15de7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,8 @@ rticles 0.15 --------------------------------------------------------------------- +- Improved the `rjournal_article()` format : Tex, R and PDF files with correct names are generated to match the author's guidelines, two affiliations is now supported for authors, last author is separated by `and` when multiple authors are present, and the documentation has been improved in function's help page and the skeleton document (thanks, @RLumSK, #286) + - Added a `author.affiliation2` field in `jss_article()` template to provide another affiliation to be used in the adress field in place of `author.affiliation`. This allow differently formated affiliation for example. (thanks, @aldomann, #291) - Improved the `jss_article()` format: Short titles can now be provided to headers to escape code/math in section titles, the continuation prompt has been corrected (from `R+` to `+`), and the skeleton document has been updated accordingly (thanks, @statibk #254, @Freguglia #294). diff --git a/R/rjournal_article.R b/R/rjournal_article.R index 9e4fe8f8a..e5e8b8729 100644 --- a/R/rjournal_article.R +++ b/R/rjournal_article.R @@ -1,23 +1,96 @@ #' R Journal format. #' #' Format for creating R Journal articles. Adapted from -#' \url{https://journal.r-project.org/submissions.html}. -#' @param ...,citation_package Arguments to \code{rmarkdown::pdf_document}. +#' . +#' +#' @details +#' +#' This file is only a basic article template. For full details of _The R +#' Journal_ style and information on how to prepare your article for submission, +#' see the [Instructions for Authors](https://journal.r-project.org/share/author-guide.pdf) +#' +#' ## About this format and the R Journal requirements +#' +#' `rticles::rjournal_article` will help you build the correct files requirements: +#' +#' - A R file will be generated automatically using `knitr::purl` - see +#' https://bookdown.org/yihui/rmarkdown-cookbook/purl.html for more information. +#' - A tex file will be generated from this Rmd file and correctly included in +#' `RJwapper.tex` as expected to build `RJwrapper.pdf`. +#' - All figure files will be kept in the default rmarkdown `*_files` folder. This +#' happens because `keep_tex = TRUE` by default in `rticles::rjournal_article` +#' - Only the bib filename is to modifed. An example bib file is included in the +#' template (`RJreferences.bib`) and you will have to name your bib file as the +#' tex, R, and pdf files. +#' +#' # About YAML header fields +#' +#' This section documents some of the YAML fields that can be used with this +#' formats. +#' +#' +#' ## The `author` field in the YAML header +#' +#' | FIELD | TYPE | DESCRIPTION | +#' | ------ | ---- | ----------- | +#' | `name` | *required* | name and surname of the author | +#' | `affiliation` | *required* | name of the author's affiliation | +#' | `address` | *required* | at least one address line for the affiliation | +#' | `url` | *optional* | an additional url for the author or the main affiliation | +#' | `orcid` | *optional* | the authors ORCID if available | +#' | `email` | *required* | the author's e-mail address | +#' | `affiliation2` | *optional* | name of the author's 2nd affiliation | +#' | `address2` | *optional* | address lines belonging to the author's 2nd affiliation | +#' +#' *Please note: Only one `url`, `orcid` and `email` can be provided per author.* +#' +#' ## Other YAML fields +#' +#' | FIELD | TYPE | DESCRIPTION | +#' | ----- | ---- | ----------- | +#' | `bibliography` | *with default* | the BibTeX file with the reference entries | +#' +#' @inheritParams rmarkdown::pdf_document +#' @param ... Arguments to `rmarkdown::pdf_document. +#' +#' @md #' @export -rjournal_article <- function(..., citation_package = 'natbib') { +rjournal_article <- function(..., keep_tex = TRUE, citation_package = 'natbib') { rmarkdown::pandoc_available('2.2', TRUE) base <- pdf_document_format( - "rjournal_article", highlight = NULL, citation_package = citation_package, ... + "rjournal_article", highlight = NULL, citation_package = citation_package, + keep_tex = keep_tex, ... ) - # Render will generate tex file, post-process hook generates appropriate - # RJwrapper.tex and use pandoc to build pdf from that + # Render will generate tex file, post-knit hook gerenates the R file, + # post-process hook generates appropriate RJwrapper.tex and + # use pandoc to build pdf from that base$pandoc$to <- "latex" base$pandoc$ext <- ".tex" - base$post_processor <- function(metadata, utf8_input, output_file, clean, verbose) { + # Generates R file expected by R journal requirement. + # We do that in the post-knit hook do access input file path. + pk <- base$post_knit + output_R <- NULL + base$post_knit <- function(metadata, input_file, runtime, ...) { + # run post_knit it exists + if (is.function(pk)) pk(metadata, input_file, runtime, ...) + + # purl the Rmd file to R code per requirement + temp_R <- tempfile(fileext = ".R") + output_R <<- knitr::purl( + input = input_file, output = temp_R, + documentation = 1, quiet = TRUE + ) + + NULL + } + + base$post_processor <- function( + metadata, utf8_input, output_file, clean, verbose + ) { filename <- basename(output_file) # underscores in the filename will be problematic in \input{filename}; # pandoc will escape underscores but it should not, i.e., should be @@ -25,6 +98,30 @@ rjournal_article <- function(..., citation_package = 'natbib') { if (filename != (filename2 <- gsub('_', '-', filename))) { file.rename(filename, filename2); filename <- filename2 } + + # Copy purl-ed R file with the correct name + file.copy(output_R, xfun::with_ext(filename, "R")) + unlink(output_R) + + # post process TEX file + temp_tex <- xfun::read_utf8(filename) + temp_tex <- post_process_authors(temp_tex) + xfun::write_utf8(text = temp_tex, con = filename) + + # check bibliography name + bib_filename <- metadata$bibliography + if(!is.null(metadata$bibliography) && + xfun::sans_ext(bib_filename) != xfun::sans_ext(filename)) { + msg <- paste( + "Per R journal requirement, bibliography file and tex file should", + "have the same name.\nCurrently, you have a bib file {{bib_filename}} and", + "a tex file {{filename}}.\nDon't forget to rename and change ", + "the bibliography field in YAML header." + ) + warning(knitr::knit_expand(text = msg), call. = FALSE) + } + + # Create RJwrapper.tex per R Journal requirement m <- list(filename = xfun::sans_ext(filename)) h <- get_list_element(metadata, c('output', 'rticles::rjournal_article', 'includes', 'in_header')) h <- c(h, if (length(preamble <- unlist(metadata[c('preamble', 'header-includes')]))) { @@ -48,7 +145,7 @@ rjournal_article <- function(..., citation_package = 'natbib') { } hook_input <- function(x, options) paste(c('\\begin{Sinput}', hilight_source(x, 'sweave', options), '\\end{Sinput}', ''), - collapse = '\n') + collapse = '\n') hook_output <- function(x, options) paste('\\begin{Soutput}\n', x, '\\end{Soutput}\n', sep = '') base$knitr$knit_hooks <- merge_list(base$knitr$knit_hooks, list( @@ -64,3 +161,5 @@ rjournal_article <- function(..., citation_package = 'natbib') { } + + diff --git a/R/utils.R b/R/utils.R index 9c203cc4a..6c2adf6f7 100644 --- a/R/utils.R +++ b/R/utils.R @@ -65,3 +65,37 @@ get_list_element <- function(x, names) { } pkg_file <- function(...) system.file(..., package = "rticles") + +# utils for post processing tex files + +post_process_authors <- function(text) { + + # --- + # correct authors field to have pattern Author 1, Author 2 and Author 3 + # --- + authors_lines_start <- grep(pattern = "^\\\\author\\{", x = text) + # if no author line do nothing + if (length(authors_lines_start) == 0L) return(text) + # if multiple author line, do nothing and warn as it is unusual + if (length(authors_lines_start) > 1L) { + warning( + "There should be only one use of `\\author{}` in the tex file. ", + "Post processing `\\author{}` is cancelled.", + call. = FALSE) + return(text) + } + # find the authors lines range + authors_lines_end <- grep( + pattern = "\\}$", x = text[seq(authors_lines_start, length(text))] + )[1] + authors_lines_end <- authors_lines_end + (authors_lines_start - 1) + authors_lines_range <- seq(authors_lines_start, authors_lines_end) + # combine and write back + authors_lines <- paste0(text[authors_lines_range], collapse = "\n") + new_authors <- knitr::combine_words( + strsplit(authors_lines, split = ", ")[[1]] + ) + text[authors_lines_range] <- xfun::split_lines(new_authors) + # return modified text + text +} diff --git a/inst/rmarkdown/templates/rjournal_article/resources/template.tex b/inst/rmarkdown/templates/rjournal_article/resources/template.tex index 2ffc82a74..1267c918b 100644 --- a/inst/rmarkdown/templates/rjournal_article/resources/template.tex +++ b/inst/rmarkdown/templates/rjournal_article/resources/template.tex @@ -19,9 +19,15 @@ $for(author)$ \address{% $author.name$\\ -$author.affiliation$\\ +$author.affiliation$\\% $for(author.address)$$author.address$$sep$\\ $endfor$\\ +$if(author.affiliation2)$ +$author.affiliation2$\\% +$for(author.address2)$$author.address2$$sep$\\ $endfor$\\ +$endif$% +$if(author.url)$$author.url$$endif$% +$if(author.orcid)$\\\textit{ORCiD: \href{https://orcid.org/$author.orcid$}{$author.orcid$}}$endif$% +$if(author.email)$\\$author.email$$endif$ } -$if(author.email)$$author.email$$endif$ $endfor$ diff --git a/inst/rmarkdown/templates/rjournal_article/skeleton/skeleton.Rmd b/inst/rmarkdown/templates/rjournal_article/skeleton/skeleton.Rmd index f26428e4a..42b9996b2 100644 --- a/inst/rmarkdown/templates/rjournal_article/skeleton/skeleton.Rmd +++ b/inst/rmarkdown/templates/rjournal_article/skeleton/skeleton.Rmd @@ -1,22 +1,43 @@ --- title: Capitalized Title Here author: + # see ?rjournal_article for more information - name: Author One affiliation: Affiliation address: - line 1 - line 2 + url: https://journal.r-project.org + orcid: 0000-0002-9079-593X email: author1@work - name: Author Two + url: https://journal.r-project.org + email: author2@work + orcid: 0000-0002-9079-593X + affiliation: Affiliation 1 + address: + - line 1 affiliation 1 + - line 2 affiliation 1 + affiliation2: Affiliation 2 + address2: + - line 1 affiliation 2 + - line 2 affiliation 2 + - name: Author Three + url: https://journal.r-project.org + email: author3@work affiliation: Affiliation address: - - line 1 - - line 2 - email: author2@work + - line 1 affiliation + - line 2 affiliation abstract: > An abstract of less than 150 words. preamble: | % Any extra LaTeX you need in the preamble + +# per R journal requirement, the bib filename should be the same as the output +# tex file. Don't forget to rename the bib file and change this example value. +bibliography: RJreferences.bib + output: rticles::rjournal_article --- @@ -39,11 +60,23 @@ There will likely be several sections, perhaps including code snippets, such as: ```{r} x <- 1:10 -x +plot(x) ``` ## Summary This file is only a basic article template. For full details of _The R Journal_ style and information on how to prepare your article for submission, see the [Instructions for Authors](https://journal.r-project.org/share/author-guide.pdf). -\bibliography{RJreferences} +### About this format and the R Journal requirements + +`rticles::rjournal_article` will help you build the correct files requirements: + +* A R file will be generated automatically using `knitr::purl` - see +https://bookdown.org/yihui/rmarkdown-cookbook/purl.html for more information. +* A tex file will be generated from this Rmd file and correctly included in +`RJwapper.tex` as expected to build `RJwrapper.pdf`. +* All figure files will be kept in the default rmarkdown `*_files` folder. This +happens because `keep_tex = TRUE` by default in `rticles::rjournal_article` +* Only the bib filename is to modifed. An example bib file is included in the +template (`RJreferences.bib`) and you will have to name your bib file as the +tex, R, and pdf files. diff --git a/man/rjournal_article.Rd b/man/rjournal_article.Rd index 2ceafd8f2..493c5b6a2 100644 --- a/man/rjournal_article.Rd +++ b/man/rjournal_article.Rd @@ -4,12 +4,66 @@ \alias{rjournal_article} \title{R Journal format.} \usage{ -rjournal_article(..., citation_package = "natbib") +rjournal_article(..., keep_tex = TRUE, citation_package = "natbib") } \arguments{ -\item{..., citation_package}{Arguments to \code{rmarkdown::pdf_document}.} +\item{...}{Arguments to `rmarkdown::pdf_document.} + +\item{keep_tex}{Keep the intermediate tex file used in the conversion to PDF} + +\item{citation_package}{The LaTeX package to process citations, \code{natbib} +or \code{biblatex}. Use \code{default} if neither package is to be used, +which means citations will be processed via the command +\command{pandoc-citeproc}.} } \description{ Format for creating R Journal articles. Adapted from \url{https://journal.r-project.org/submissions.html}. } +\details{ +This file is only a basic article template. For full details of \emph{The R +Journal} style and information on how to prepare your article for submission, +see the \href{https://journal.r-project.org/share/author-guide.pdf}{Instructions for Authors} +\subsection{About this format and the R Journal requirements}{ + +\code{rticles::rjournal_article} will help you build the correct files requirements: +\itemize{ +\item A R file will be generated automatically using \code{knitr::purl} - see +https://bookdown.org/yihui/rmarkdown-cookbook/purl.html for more information. +\item A tex file will be generated from this Rmd file and correctly included in +\code{RJwapper.tex} as expected to build \code{RJwrapper.pdf}. +\item All figure files will be kept in the default rmarkdown \verb{*_files} folder. This +happens because \code{keep_tex = TRUE} by default in \code{rticles::rjournal_article} +\item Only the bib filename is to modifed. An example bib file is included in the +template (\code{RJreferences.bib}) and you will have to name your bib file as the +tex, R, and pdf files. +} +} +} +\section{About YAML header fields}{ +This section documents some of the YAML fields that can be used with this +formats. +\subsection{The \code{author} field in the YAML header}{\tabular{lll}{ + FIELD \tab TYPE \tab DESCRIPTION \cr + \code{name} \tab \emph{required} \tab name and surname of the author \cr + \code{affiliation} \tab \emph{required} \tab name of the author's affiliation \cr + \code{address} \tab \emph{required} \tab at least one address line for the affiliation \cr + \code{url} \tab \emph{optional} \tab an additional url for the author or the main affiliation \cr + \code{orcid} \tab \emph{optional} \tab the authors ORCID if available \cr + \code{email} \tab \emph{required} \tab the author's e-mail address \cr + \code{affiliation2} \tab \emph{optional} \tab name of the author's 2nd affiliation \cr + \code{address2} \tab \emph{optional} \tab address lines belonging to the author's 2nd affiliation \cr +} + + +\emph{Please note: Only one \code{url}, \code{orcid} and \code{email} can be provided per author.} +} + +\subsection{Other YAML fields}{\tabular{lll}{ + FIELD \tab TYPE \tab DESCRIPTION \cr + \code{bibliography} \tab \emph{with default} \tab the BibTeX file with the reference entries \cr +} + +} +} + diff --git a/tests/testit/test-utils.R b/tests/testit/test-utils.R new file mode 100644 index 000000000..a7b1577be --- /dev/null +++ b/tests/testit/test-utils.R @@ -0,0 +1,29 @@ +assert("last author is prepend with and ", { + # if no author line, unmodified + unmodified <- c("No author line", "returns unmodified") + (post_process_authors(unmodified) %==% unmodified) + + # one author is unchanged + (post_process_authors("\\author{John Doe}") %==% + "\\author{John Doe}") + + # when 2 or more, add a 'and' + (post_process_authors(c("\\title{title}", "\\author{John, Bob}")) %==% + c("\\title{title}", "\\author{John and Bob}")) + (post_process_authors("\\author{John, Bob, Mary}") %==% + "\\author{John, Bob, and Mary}") + + # Works also if authors on 2 or more lines in the tex file + (post_process_authors( + c("\\author{John, Bob,", "Mary, Dany}", "\\abstract{text}") + ) %==% + c("\\author{John, Bob,", "Mary, and Dany}", "\\abstract{text}")) + (post_process_authors( + c("\\title{title}", "\\author{John, Bob,", "Lucy, Ann,", "Mary, Dany}") + ) %==% + c("\\title{title}", "\\author{John, Bob,", "Lucy, Ann,", "Mary, and Dany}")) + + # handles the weird case where two or more \\authors are used in the document + unmodified <- c("\\author{John, Bob}", "some text", "\\author{Mary, Dany}") + (suppressWarnings(post_process_authors(unmodified)) %==% unmodified) +})