Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use here() for paths to css, before_body and after_body?

I have a collection of RMarkdown documents which are distributed over a hierarchy of folders. All of the documents refer to the same CSS and header/footer files. I have the paths to these files hard-coded at present but this is difficult to maintain. I'd prefer to generate the path dynamically.

This works (the date is generated dynamically in code):

---
title: "Untitled"
date: "`r Sys.Date()`"
output: html_document
---

But this does not work:

---
title: "Untitled"
date: "`r Sys.Date()`"
output: 
  html_document:
    css: '`r here::here("styles/styles.css")`'
    includes:
      before_body: '`r here::here("styles/header.html")`'
      after_body: '`r here::here("styles/footer.html")`'
---

The files styles.css, header.html and footer.html are all located in the styles/ folder off the root of the project. When I refer to these files using here::here() from the console it works perfectly.

However, when I compile the RMarkdown I get errors like this:

File `r here::here( not found in resource path
Error: pandoc document conversion failed with error 99

The above error relates to the CSS file. And then for the header and footer:

pandoc: `r here::here("styles/header.html")`: openBinaryFile: does not exist
(No such file or directory)

The fact that this code is getting as far as Pandoc suggests to me that the code chunks are not being evaluated.

Am I doing something silly? Is this the expected behaviour? It seems to me that it would be very helpful to be able to generate the paths dynamically.

like image 400
datawookie Avatar asked Jun 20 '19 08:06

datawookie


1 Answers

The YAML header is parsed using the yaml::yaml.load() function.
The man page of this function explains that

There is a built-in handler that will evaluate expressions that are tagged with the !expr tag. Currently this handler is enabled by default, but the handler is being disabled by default in an upcoming version for safety and security reasons. If you do not explicity set the eval.expr argument to TRUE, you will get a warning if an expression is evaluated. Alternately, you can set the option named yaml.eval.expr via the options function to turn off the warning.

So, you can achieve your goal with this YAML header:

---
title: "Untitled"
date: "`r Sys.Date()`"
output: 
  html_document:
    css: !expr here::here("styles/styles.css")
    includes:
      before_body: !expr here::here("styles/header.html")
      after_body: !expr here::here("styles/footer.html")
---
like image 96
RLesur Avatar answered Oct 22 '22 09:10

RLesur