rmarkdown
rmarkdown copied to clipboard
Resources with a space in name are not copied when using runtime: shiny
Including a .css file via YAML header and runtime: shiny does not work when the filename of the .Rmd contains a space.
After ages of searching for the bug of why I cannot include external .css file and breaking it down to the lowest level (I swapped around between files and with and without runtime: shiny without any other code except for the YAML header), I realised that it works when I remove the space I had in the .Rmd
file. So instead of x y.Rmd
I had to rename it to xy.Rmd
and now it works.
Long story short, the following code only works when the filename of the .Rmd
document does not contain a space character and I think it would be good to add this functionality because I do not think it's obvious for users that they have to use filenames that do not include any spaces.
---
runtime: shiny
title: 'My Title'
output:
html_document:
css: www/style.css
---
Thanks for the report and sorry for the delay.
This was not easy to investigate but I think I have found the issue. Shiny runtime will modify the way the Rmd is rendered as it will be generated in a tmp directory for the app to run from. Resources file like style.css
should be copied there. html_document_base
has a special copy_resources
flag for that, that rmarkdown::run()
will activate, and will set output_dir
, intermediates_dir
. The issue lies with this last one.
It happens when no space in filename but it fails when there is a space. Here is a reprex without shiny
library(rmarkdown)
#> Warning: le package 'rmarkdown' a été compilé avec la version R 4.0.3
dir.create(tmp_dir <- tempfile())
old <- setwd(tmp_dir)
xfun::write_utf8(c(
"---",
"title: something",
"output:",
" html_document:" ,
" css: style.css",
"---",
"",
"# A header"), "test.Rmd")
xfun::write_utf8(c(
"h1 {",
" color: red;",
"}"),
"style.css"
)
render_with_copy <- function(input_file, output_dir = "out") {
render(
input = input_file,
# output_file = dest_file,
output_dir = output_dir,
output_options = list(
self_contained = FALSE,
copy_resources = TRUE),
intermediates_dir = output_dir,
quiet = TRUE
)
}
# base scenario: style.css stays in input dir
render("test.Rmd", output_options = list(self_contained = FALSE), output_dir = "out")
#> processing file: test.Rmd
#> output file: test.knit.md
#> "C:/Users/chris/scoop/apps/rstudio-daily/current/bin/pandoc/pandoc" +RTS -K512m -RTS test.utf8.md --to html4 --from markdown+autolink_bare_uris+tex_math_single_backslash --output pandoc315075df3add.html --lua-filter "C:\Users\chris\Documents\R\win-library\4.0\rmarkdown\rmarkdown\lua\pagebreak.lua" --lua-filter "C:\Users\chris\Documents\R\win-library\4.0\rmarkdown\rmarkdown\lua\latex-div.lua" --email-obfuscation none --standalone --section-divs --template "C:\Users\chris\Documents\R\win-library\4.0\rmarkdown\rmd\h\default.html" --no-highlight --variable highlightjs=1 --css style.css --variable "theme:bootstrap" --include-in-header "C:\Users\chris\AppData\Local\Temp\RtmpwLnWPy\rmarkdown-str3150ffeb38.html" --mathjax --variable "mathjax-url:https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"
#>
#> Output created: out/test.html
fs::file_exists("style.css")
#> style.css
#> TRUE
fs::file_exists("out/test_files/style.css")
#> out/test_files/style.css
#> FALSE
fs::dir_delete("out")
# shiny runtime will copy the resource files
render_with_copy("test.Rmd", "out")
fs::file_exists("out/test_files/style.css")
#> out/test_files/style.css
#> TRUE
fs::dir_delete("out")
fs::file_copy("test.Rmd", "test with space.Rmd")
render_with_copy("test with space.Rmd", "out")
fs::file_exists("out/test-with-space_files/style.css")
#> out/test-with-space_files/style.css
#> FALSE
fs::dir_delete("out")
setwd(old)
fs::dir_delete(tmp_dir)
Created on 2020-10-28 by the reprex package (v0.3.0.9001)
Ok I found know why this happens:
-
We have a special treatment for filename with special character. We rename it without space and put it in the intermediate directory if one is specified. https://github.com/rstudio/rmarkdown/blob/aa180719408cd49913d79717c8c94489148cfd23/R/render.R#L351-L378
-
So if one
intermediates_dir
is specified, the input is changed. Meaning, the working directory from which everything is run is changed: https://github.com/rstudio/rmarkdown/blob/aa180719408cd49913d79717c8c94489148cfd23/R/render.R#L384 -
As the resources are not moved, they are no more relative to the input file. And this is why it fails when they should be copied https://github.com/rstudio/rmarkdown/blob/51224f06906bbc9ba86a627ebce49ecf66a6c941/R/html_resource_copy.R#L38-L43
-
style.css
is correctly detected, butfile_exist("style.css")
(third test above) will fail because we are no more relative to where the css file is. Hence it is not found and not copied to where is should, so not found by the html file that is modified.
@yihui I need to discuss this with you some day before trying to fix this in order to find the correct fix, less impactful. I see several solution.
The issue here can be sum up by :
- local resources file are not found when
- filename has a special char
-
intermediates_dir
is specified. - resources are supposed to be copied (
copy_resources = TRUE
)