lift.R 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #' Containerize R Markdown Documents
  2. #'
  3. #' @description
  4. #' Containerize R Markdown documents. This function generates
  5. #' \code{Dockerfile} based on the liftr metadata in the RMD document.
  6. #'
  7. #' @details
  8. #' After running \link{lift}, run \link{render_docker} on the document to
  9. #' render the containerized R Markdown document using Docker containers.
  10. #' See \code{vignette('liftr-intro')} for details about the extended
  11. #' YAML front-matter metadata format used by liftr.
  12. #'
  13. #' @param input Input (R Markdown) file.
  14. #' @param use_config If \code{TRUE}, will parse the liftr metadata from
  15. #' a YAML file, if \code{FALSE}, will parse such information from the
  16. #' metadata section in the R Markdown file. Default is \code{FALSE}.
  17. #' @param config_file Name of the YAML configuration file, under the
  18. #' same directory as the input file. Default is \code{"_liftr.yml"}.
  19. #' @param output_dir Directory to output \code{Dockerfile}.
  20. #' If not provided, will be the same directory as \code{input}.
  21. #'
  22. #' @return \code{Dockerfile}.
  23. #'
  24. #' @export lift
  25. #'
  26. #' @importFrom knitr knit
  27. #' @importFrom yaml yaml.load
  28. #'
  29. #' @examples
  30. #' # copy example file
  31. #' dir_example = paste0(tempdir(), '/liftr-minimal/')
  32. #' dir.create(dir_example)
  33. #' file.copy(system.file("examples/liftr-minimal.Rmd", package = "liftr"), dir_example)
  34. #'
  35. #' # containerization
  36. #' input = paste0(dir_example, "liftr-minimal.Rmd")
  37. #' lift(input)
  38. #'
  39. #' \dontrun{
  40. #' # render the document with Docker
  41. #' render_docker(input)
  42. #'
  43. #' # view rendered document
  44. #' browseURL(paste0(dir_example, "liftr-minimal.html"))
  45. #'
  46. #' # purge the generated Docker image
  47. #' purge_image(paste0(dir_example, "liftr-minimal.docker.yml"))}
  48. lift = function(
  49. input = NULL,
  50. use_config = FALSE, config_file = '_liftr.yml',
  51. output_dir = NULL) {
  52. if (is.null(input))
  53. stop('missing input file')
  54. if (!file.exists(normalizePath(input)))
  55. stop('input file does not exist')
  56. if (!use_config) {
  57. # locate YAML metadata block
  58. doc_content = readLines(normalizePath(input))
  59. header_pos = which(doc_content == '---')
  60. # handling YAML blocks ending with three dots
  61. if (length(header_pos) == 1L) {
  62. header_dot_pos = which(doc_content == '...')
  63. if (length(header_dot_pos) == 0L) {
  64. stop('Cannot correctly locate YAML metadata block.
  65. Please use three hyphens (---) as start line & end line,
  66. or three hyphens (---) as start line with three dots (...)
  67. as end line.')
  68. } else {
  69. header_pos[2L] = header_dot_pos[1L]
  70. }
  71. }
  72. doc_yaml = paste(
  73. doc_content[(header_pos[1L] + 1L):(header_pos[2L] - 1L)],
  74. collapse = '\n')
  75. opt_all_list = yaml.load(doc_yaml)
  76. # liftr options handling
  77. if (is.null(opt_all_list$liftr))
  78. stop('Cannot find `liftr` option in file header')
  79. opt_list = opt_all_list$liftr
  80. }
  81. if (use_config) {
  82. liftrfile_path = paste0(file_dir(input), '/', config_file)
  83. if (!file.exists(normalizePath(liftrfile_path)))
  84. stop('The YAML config file does not exist')
  85. opt_list = yaml.load_file(liftrfile_path)
  86. }
  87. # base image
  88. liftr_from = parse_from(opt_list$from)
  89. # maintainer's name
  90. liftr_maintainer = parse_maintainer(opt_list$maintainer)
  91. # maintainer's email
  92. liftr_email = parse_email(opt_list$email)
  93. # system dependencies
  94. liftr_sysdeps = parse_sysdeps(opt_list$sysdeps)
  95. # texlive
  96. liftr_texlive = parse_texlive(opt_list$texlive)
  97. # pandoc
  98. liftr_pandoc = parse_pandoc(liftr_from, opt_list$pandoc)
  99. # CRAN packages
  100. liftr_cran = parse_cran(opt_list$cran)
  101. # Bioconductor packages
  102. liftr_bioc = parse_bioc(opt_list$bioc)
  103. # remote packages
  104. liftr_remotes = parse_remotes(opt_list$remotes)
  105. # custom Dockerfile snippet
  106. liftr_include = parse_include(input, opt_list$include)
  107. # factory packages
  108. liftr_factory = quote_str(c(
  109. 'devtools', 'knitr', 'rmarkdown', 'shiny', 'RCurl'))
  110. # write output files
  111. if (is.null(output_dir)) output_dir = file_dir(input)
  112. output_dockerfile = paste0(normalizePath(output_dir), '/Dockerfile')
  113. invisible(knit(
  114. system.file('templates/base.Rmd', package = 'liftr'),
  115. output = output_dockerfile, quiet = TRUE))
  116. # remove consecutive blank lines
  117. out = readLines(output_dockerfile)
  118. out = sanitize_blank(out)
  119. writeLines(out, output_dockerfile)
  120. invisible(out)
  121. }