R/rj_pdf_article.R

Defines functions rjournal_pdf_article

Documented in rjournal_pdf_article

# Adapted from rticles::rjournal_article
#' @export
#' @rdname rjournal_article
rjournal_pdf_article <- function(..., self_contained = FALSE) {
  fmt <- bookdown::pdf_document2(
    ...,
    highlight = NULL,
    template = system.file("rmarkdown/templates/rjournal/resources/template.tex",
                           package = "rjtools", mustWork = TRUE)
  )

  # 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
  fmt$pandoc$to <- "latex"
  fmt$pandoc$ext <- ".tex"

  output_R <- NULL
  fmt$post_knit <- function(metadata, input_file, runtime, ...) {
    # purl the Rmd file to R code per requirement
    output_R <<- knitr::purl(input_file, tempfile(fileext = ".R"),
                            documentation = 1, quiet = TRUE)
    # Add magic comment about '"do not edit" (rstudio/rstudio#2082)
    xfun::write_utf8(c(
      "# Generated by `rjournal_pdf_article()` using `knitr::purl()`: do not edit by hand",
      sprintf("# Please edit %s to modify this file", input_file),
      "",
      xfun::read_utf8(output_R)
    ), output_R)

    NULL
  }
  pre_processor <- fmt$pre_processor
  fmt$pre_processor <- function(front_matter, input, ...) {
    if(!is.null(front_matter$bibliography) && !isTRUE(front_matter$tex_native)) {
      xfun::write_utf8(
        c(xfun::read_utf8(input), "\n# References\n"),
        input
      )
    }
    pre_processor(front_matter, input, ...)

  }
  post_process <- fmt$post_processor
  fmt$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
    # \input{foo_bar} instead of \input{foo\_bar}
    if (filename != (filename2 <- gsub("_", "-", filename))) {
      file.rename(filename, filename2)
      filename <- filename2
    }
    # Copy purl-ed R file with the correct name
    dest_file <- xfun::with_ext(filename, "R")
    our_file <- TRUE
    if (file.exists(dest_file)) {
      # we check this file is generated by us
      # otherwise we leave it as is and warn
      current_r <- xfun::read_utf8(dest_file)
      our_file <- grepl("Generated.*rjournal_pdf_article.*do not edit by hand", current_r[1])
      if (!our_file) {
        warning(
          sprintf("R file with name '%s' already exists.", dest_file),
          "\nIt will not be overwritten by the one generated",
          " during rendering using `knitr::purl()`.",
          "\nRemove the existing file to obtain the generated one.",
          call. = FALSE
        )
      }
    }
    if (our_file) {
      # we only overwrite if it is our file
      file.copy(output_R, xfun::with_ext(filename, "R"), overwrite = TRUE)
    }
    unlink(output_R)

    temp_tex <- xfun::read_utf8(output_file)
    # Add author line
    temp_tex <- post_process_authors(temp_tex)
    ## remove CLS references if we are using native ones
    ## coversely, if CLS is already included, don't add TeX ones
    if (isTRUE(metadata$tex_native)) {
        cls.b <- grep("^\\\\begin\\{CSLReferences\\}", temp_tex)
        cls.e <- grep("^\\\\end\\{CSLReferences\\}", temp_tex)
        if (length(cls.b) == 1 && length(cls.e) == 1 && cls.b < cls.e)
            temp_tex <- temp_tex[-(cls.b:cls.e)]
    } else if (length(grep("^\\\\begin\\{CSLReferences\\}", temp_tex)) &&
               length(bil <- grep("^\\\\bibliography", temp_tex)))
	temp_tex <- temp_tex[-bil]
    xfun::write_utf8(temp_tex, output_file)

    # Bookdown post-processing, silently capture error as it will attempt to
    # render without the wrapper.
    tryCatch(
      post_process(metadata, utf8_input, output_file, clean, verbose),
      message = function(...) NULL,
      error = function(e) invisible(NULL)
    )
    # temp_tex <- resolve_refs_latex(temp_tex)

    # Update wrapper metadata
    if(!is.null(metadata$volume)) {
      issue_months <- if(metadata$volume < 14) {
        c("June", "December")
      } else {
        c("March", "June", "September", "December")
      }
    }
    metadata$journal$section <- metadata$journal$section %||% "Contributed research article"
    m <- list(
      filename = xfun::sans_ext(filename),
      volume = metadata$volume %||% "XX",
      issue = metadata$issue %||% "YY",
      issueyear = if(is.null(metadata$volume)) "20ZZ" else 2008 + metadata$volume,
      issuemonth = if(is.null(metadata$volume)) "AAAA" else issue_months[metadata$issue],
      journal = metadata$journal
    )

    get_field <- function(x, field) {
      if(!is.list(x)) return(NULL)
      if(length(field) == 1L) return(x[[field]])
      get_field(x[[field[1]]], field[-1])
    }
    pdf_header <- get_field(metadata, c("output", "rjtools::rjournal_pdf_article", "includes", "in_header"))
    pdf_header <- c(
      pdf_header,
      if (length(preamble <- unlist(metadata[c("preamble", "header-includes")]))) {
        f <- tempfile(fileext = ".tex")
        on.exit(unlink(f), add = TRUE)
        xfun::write_utf8(preamble, f)
        f
      }
    )
    wrapper_template <- system.file(
      file.path("tex", "RJwrapper.tex"),
      package = "rjtools"
    )

    wrapper_md <- tempfile(fileext = ".md")
    on.exit(unlink(wrapper_md), add = TRUE)
    xfun::write_utf8(c("---", yaml::as.yaml(m), "---\n"), wrapper_md)

    rmarkdown::pandoc_convert(
      wrapper_md, output = "RJwrapper.tex",
      verbose = verbose, wd = ".",
      options = c(
        "--template", rmarkdown::pandoc_path_arg(wrapper_template),
        rmarkdown::pandoc_include_args(pdf_header)
      )
    )

    # Replace style file
    sty_origin <- list.files(system.file("tex", package = "rjtools"),
                             full.names = TRUE)
    sty_dest <- file.path(".", basename(sty_origin))
    copied <- file.copy(sty_origin, sty_dest)
    # on.exit(unlink(sty_dest[copied]), add = TRUE)

    tinytex::latexmk(
      "RJwrapper.tex", fmt$pandoc$latex_engine,
      pdf_file = xfun::with_ext(basename(output_file), ".pdf"),
      clean = clean
    )
  }

  fmt$knitr$opts_chunk$comment <- "#>"

  fmt
}

Try the rjtools package in your browser

Any scripts or data that you put into this service are public.

rjtools documentation built on May 29, 2024, 9:57 a.m.