8

I created my own format in Rmarkdown based on this blogpost. I implemented it in my personal package and it works great. I also added custom files in includes argument of html_document.

My question is whether it's possible to store my custom files (included in includes argument) after I click Knit button. Similarly to self_contained = F option which allows storing all Rmarkdown dependencies.

Update

I should give you some context first. Let’s say I used my html format to create a report two months ago. Two weeks later I decided to implement major changes in my html format and updated my package.

After next two weeks, my boss came to me asking for adding minor changes in old report. Then, by clicking Knit button, the report was not able to create, because there was a new version of my html format, which was significantly different.

I see three possibilities how to deal with this request. Either I can install old version of my package (suboptimal), create a new html format every time I implement major changes or I can store my dependencies (header, footer, css files) in a separate subdirectory (like a packrat). Then each report would be independent and immune to changes in my custom format.

Let me know if there is any better solution.

3
  • Are you open to embedding your includes as base64? It will add a fair amount of bloat to the document, but provided you ensure backwards compatibility with your package that is one way to ensure they render in future. Thinking through your solution design in your package to allow greater flexibility is most likely a more robust fix Commented Nov 26, 2017 at 3:24
  • 2
    Side thought: instead of trying to pack dependencies within the Rmd file, if your workflow included version control (e.g., git or subversion), you could go "back in time" to when the report was generated, branch (in order to make those tweaks), and then return to the master's "HEAD". Not an answer, sorry for the tangent. Commented Nov 26, 2017 at 7:41
  • @r2evans Obviously it's one way to solve it but only if I am the only person who use custom format. But when other people use it, it's hard to expect from them, to always remember about changes. Commented Dec 2, 2017 at 18:03

1 Answer 1

1

Basic example

Assume that you have a myreport.Rmd file with the following header:

---
title: "Untitled"
author: "Romain Lesur"
date: "27 janvier 2018"
output: 
  html_document:
    includes:
      in_header: inheader.html
---

Using a hacky rmarkdown preprocessor, you can copy inheader.html file.
The following code is intended to be run in R console:

pre_processor <- function(metadata, 
                          input_file, 
                          runtime, 
                          knit_meta, 
                          files_dir, 
                          output_dir) {

  in_header <- metadata$output$html_document$includes$in_header
  if (!is.null(in_header)) file.copy(in_header, output_dir)

  invisible(NULL)
}

custom_output_format <- function() {
  rmarkdown::output_format(
    knitr = NULL,
    pandoc = NULL,
    pre_processor = pre_processor,
    base_format = rmarkdown::html_document()
  )
}

rmarkdown::render('myreport.Rmd', 
                   output_format = custom_output_format(), 
                   output_dir = 'output')

You get a output directory with the rendered report and inheader.html file inside.

In order to run a similar preprocessor on clicking Knit button, you have to include it in your personal package's output_format (see below).

Turning in a package

As the question mentions this blogpost, here is an adaptation of the quarterly_report function:

quarterly_report <- function(toc = TRUE) {

  # get the locations of resource files located within the package
  css <- system.file("reports/styles.css", package = "mypackage")
  header <- system.file("reports/quarterly/header.html", package = "mypackage")

  # call the base html_document function
  base_format <-
    rmarkdown::html_document(toc = toc,
                             fig_width = 6.5,
                             fig_height = 4,
                             theme = NULL,
                             css = css,
                             includes = includes(before_body = header))

  pre_processor <- function(metadata,
                            input_file,
                            runtime,
                            knit_meta,
                            files_dir,
                            output_dir) {
    purrr::walk(c(css, header), file.copy, output_dir)

    invisible(NULL)
  }

  rmarkdown::output_format(
    knitr = NULL,
    pandoc = NULL,
    pre_processor = pre_processor,
    base_format = base_format
  )
}

This solution is not 100% satisfying because I don't think that rmarkdown pre_processor was created for having side-effects. But it works.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.