R/lift.R

Defines functions lift

Documented in lift

#' Containerize R Markdown Documents
#'
#' @description
#' Containerize R Markdown documents. This function generates
#' \code{Dockerfile} based on the liftr metadata in the RMD document.
#'
#' @details
#' After running \link{lift}, run \link{render_docker} on the document to
#' render the containerized R Markdown document using Docker containers.
#' See \code{vignette('liftr-intro')} for details about the extended
#' YAML front-matter metadata format used by liftr.
#'
#' @param input Input (R Markdown) file.
#' @param use_config If \code{TRUE}, will parse the liftr metadata from
#' a YAML file, if \code{FALSE}, will parse such information from the
#' metadata section in the R Markdown file. Default is \code{FALSE}.
#' @param config_file Name of the YAML configuration file, under the
#' same directory as the input file. Default is \code{"_liftr.yml"}.
#' @param output_dir Directory to output \code{Dockerfile}.
#' If not provided, will be the same directory as \code{input}.
#'
#' @return \code{Dockerfile}.
#'
#' @export lift
#'
#' @importFrom knitr knit
#' @importFrom yaml yaml.load
#'
#' @examples
#' # copy example file
#' dir_example = paste0(tempdir(), '/liftr-minimal/')
#' dir.create(dir_example)
#' file.copy(system.file("examples/liftr-minimal.Rmd", package = "liftr"), dir_example)
#'
#' # containerization
#' input = paste0(dir_example, "liftr-minimal.Rmd")
#' lift(input)
#'
#' \dontrun{
#' # render the document with Docker
#' render_docker(input)
#'
#' # view rendered document
#' browseURL(paste0(dir_example, "liftr-minimal.html"))
#'
#' # purge the generated Docker image
#' purge_image(paste0(dir_example, "liftr-minimal.docker.yml"))}

lift = function(
  input = NULL,
  use_config = FALSE, config_file = '_liftr.yml',
  output_dir = NULL) {

  if (is.null(input))
    stop('missing input file')
  if (!file.exists(normalizePath(input)))
    stop('input file does not exist')

  if (!use_config) {
    # locate YAML metadata block
    doc_content = readLines(normalizePath(input))
    header_pos = which(doc_content == '---')

    # handling YAML blocks ending with three dots
    if (length(header_pos) == 1L) {
      header_dot_pos = which(doc_content == '...')
      if (length(header_dot_pos) == 0L) {
        stop('Cannot correctly locate YAML metadata block.
             Please use three hyphens (---) as start line & end line,
             or three hyphens (---) as start line with three dots (...)
             as end line.')
      } else {
        header_pos[2L] = header_dot_pos[1L]
      }
    }

    doc_yaml = paste(
      doc_content[(header_pos[1L] + 1L):(header_pos[2L] - 1L)],
      collapse = '\n')
    opt_all_list = yaml.load(doc_yaml)

    # liftr options handling
    if (is.null(opt_all_list$liftr))
      stop('Cannot find `liftr` option in file header')

    opt_list = opt_all_list$liftr
    }

  if (use_config) {
    liftrfile_path = paste0(file_dir(input), '/', config_file)
    if (!file.exists(normalizePath(liftrfile_path)))
      stop('The YAML config file does not exist')
    opt_list = yaml.load_file(liftrfile_path)
  }

  # base image
  liftr_from       = parse_from(opt_list$from)
  # maintainer's name
  liftr_maintainer = parse_maintainer(opt_list$maintainer)
  # maintainer's email
  liftr_email      = parse_email(opt_list$email)
  # system dependencies
  liftr_sysdeps    = parse_sysdeps(opt_list$sysdeps)
  # texlive
  liftr_texlive    = parse_texlive(opt_list$texlive)
  # pandoc
  liftr_pandoc     = parse_pandoc(liftr_from, opt_list$pandoc)
  # CRAN packages
  liftr_cran       = parse_cran(opt_list$cran)
  # Bioconductor packages
  liftr_bioc       = parse_bioc(opt_list$bioc)
  # remote packages
  liftr_remotes    = parse_remotes(opt_list$remotes)
  # custom Dockerfile snippet
  liftr_include    = parse_include(input, opt_list$include)

  # factory packages
  liftr_factory = quote_str(c(
    'devtools', 'BiocManager','knitr', 'rmarkdown', 'shiny', 'RCurl'))

  # write output files
  if (is.null(output_dir)) output_dir = file_dir(input)
  output_dockerfile = paste0(normalizePath(output_dir), '/Dockerfile')

  invisible(knit(
    system.file('templates/base.Rmd', package = 'liftr'),
    output = output_dockerfile, quiet = TRUE))

  # remove consecutive blank lines
  out = readLines(output_dockerfile)
  out = sanitize_blank(out)
  writeLines(out, output_dockerfile)

  invisible(out)

    }
nanxstats/liftr documentation built on March 12, 2024, 7:36 a.m.