rstudio / bookdown

Authoring Books and Technical Documents with R Markdown
https://pkgs.rstudio.com/bookdown/
GNU General Public License v3.0
3.79k stars 1.27k forks source link

Leaflet not rendering based on value of new_session #1339

Open gregmacfarlane opened 2 years ago

gregmacfarlane commented 2 years ago

I have a book written in Bookdown, in which I would like to include Leaflet maps. I have noticed that my ability to print these maps in the interactive html is a function of

  1. the value of the new_session bookdown parameter, which determines whether each Rmd file should be rendered in a new R session.
  2. the use of the book_filename bookdown parameter.

Perhaps these are two completely separate issues, but I discovered one while looking for the other and I don't know how intertwined they are.

MWE

---
title: "A Book"
author: "Frida Gomam"
site: bookdown::bookdown_site
documentclass: book
output:
  bookdown::gitbook: default
  #bookdown::pdf_book: default
---

# Test

```{r setup}
library(leaflet)
```

Don't miss Figure \@ref(fig:nice-tab).

```{r nice-tab, fig.cap="Figure"}
leaflet() %>%
  addProviderTiles(providers$CartoDB) %>%
  addMarkers(lng=174.768, lat=-36.852, popup="The birthplace of R")
```

As posted, this renders correctly (as expected) using bookdown::render_book(). Expected rendering

Issue 1: HTML dependency based on background layer

If I render as bookdown::render_book(new_session = TRUE) however, I get the following error:

Error: path for html_dependency not found: /var/folders/0f/f4v60fbn6psdh5r_wlqz0qvm0000gn/T//RtmpsCf5pj
Please delete _main.md after you finish debugging the error.

This persists even after clearing the knitr cache and restarting R, as suggested on StackOverflow

I can avoid this error, however, by using a different map tiles layer. I feel like this is a bookdown issue and not a leaflet issue because the performance changes based on a bookdown flag.

New session, with different background layer.

Issue 2: Not printing leaflet with named file

If I call the build using bookdown::render_book(config_file = "_bookdown.yml") and alter the name following _bookdown.yml config file:

new_session: yes
book_filename: "mydoc.Rmd"

then the leaflet map is completely empty, regardless of the background map used. empty leaflet

Viewing the page in the debugger shows that there is an htmlwidget in the proper place, but I don't know enough to tell where exactly this is a problem.

Developer pane with htmlwidget error

session info

R version 4.2.0 (2022-04-22)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Monterey 12.3.1, RStudio 2022.2.1.461

Locale: en_US.UTF-8 / en_US.UTF-8 / en_US.UTF-8 / C / en_US.UTF-8 / en_US.UTF-8

Package version:
  base64enc_0.1.3 bookdown_0.26.3 bslib_0.3.1     digest_0.6.29   evaluate_0.15  
  fastmap_1.1.0   fs_1.5.2        glue_1.6.2      graphics_4.2.0  grDevices_4.2.0
  highr_0.9       htmltools_0.5.2 jquerylib_0.1.4 jsonlite_1.8.0  knitr_1.39     
  magrittr_2.0.3  methods_4.2.0   R6_2.5.1        rappdirs_0.3.3  rlang_1.0.2    
  rmarkdown_2.14  sass_0.4.1      stats_4.2.0     stringi_1.7.6   stringr_1.4.0  
  tinytex_0.39    tools_4.2.0     utils_4.2.0     xfun_0.31       yaml_2.3.5  
cderv commented 2 years ago

Thanks for the report.

Regarding issue 1

Error: path for html_dependency not found: /var/folders/0f/f4v60fbn6psdh5r_wlqz0qvm0000gn/T//RtmpsCf5pj

It seems the html dependency is downloaded / put into a temp folder for the R session. Using new_session: true will run each file in a different R session, so this can cause issue. I am surprised that it happens only now. I'll see if there were some changes somewhere.

Regarding issue2, we'll see after understanding more about issue 1, unless it happens also when new_session: false

yihui commented 2 years ago

I am surprised that it happens only now.

I'm surprised, too. I did save and restore the HTML dependencies: https://github.com/rstudio/bookdown/blob/169c43b6bb95213f2af63a95acd4e977a58a3e1f/R/render.R#L225 Not sure why or when that stopped working.

cderv commented 2 years ago

So after debugging, here is the story:

Traceback for the issue is this one:

<error/rlang_error>
Error:
! path for html_dependency not found: C:/Users/chris/AppData/Local/Temp/Rtmpk1vYTY
---
Backtrace:
  1. bookdown::render_book()
  2. bookdown:::render_new_session(...)
  3. rmarkdown::render(...)
  4. output_format$pre_processor(...)
  5. rmarkdown base(...)
  6. rmarkdown:::html_extras_for_document(...)
  7. rmarkdown dependency_resolver(all_dependencies)
  8. base::lapply(dependencies, validate_html_dependency)
  9. rmarkdown FUN(X[[i]], ...)
 10. rmarkdown:::stop2("path for html_dependency not found: ", file)
Run `rlang::last_trace()` to see the full context.

So issue happens during validation of dependencies in rmarkdown where we check for file existence when a src$file dependency is provided https://github.com/rstudio/rmarkdown/blob/1ca8a87cc9a6bd009543e636cbd1f253c8d5539f/R/html_dependencies.R#L374

When using leaflet::addProvidersTiles(), it will load a specific HTML dependencies that leaflet creates in a R temp folder https://github.com/rstudio/leaflet/blob/main/R/plugin-providers.R#L92-L107 This lead to this html dependencies that will be validated by R Markdown:

List of 10
 $ name      : chr "leaflet-providers"
 $ version   : chr "1.9.0"
 $ src       :List of 1
  ..$ file: chr "C:/Users/chris/AppData/Local/Temp/Rtmp618RtY"
 $ meta      : NULL
 $ script    : chr "leaflet-providers_1.9.0.js"
 $ stylesheet: NULL
 $ head      : NULL
 $ attachment: NULL
 $ package   : NULL
 $ all_files : logi FALSE
 - attr(*, "class")= chr "html_dependency"

This temp folder is the one that was set from the R session where the Rmd file containing the leaflet code was knitted. So at the validation stage, it does not exist anymore.

I don't really know if this is expected that leaflet is setting a dependency in an absolute path which is temporary to a R session. Doesn't seem so right, but could be understandable when used in an R session. Probably we should handle this better on our side.

Regarding why not before: We have touch this validate_html_dependency function in https://github.com/rstudio/rmarkdown/pull/2151 so maybe we missed a edge case.

@yihui do you have insights on this ?

gregmacfarlane commented 2 years ago

Thanks for looking into this. As far as I can tell, the issue with leaflet maps not being included in the output HTML only occurs when the output document is renamed and new_session: yes

yihui commented 2 years ago

@cderv Oh, this reminded me that I had investigated this issue two years ago, which I have totally forgotten: https://github.com/rstudio/bookdown/issues/15#issuecomment-573776659 I'm afraid that this won't be easy to fix for new_session: yes...

cderv commented 2 years ago

Oh thanks. Did not thought to look into old issues. I think our best shots is to work with our colleague on leaflet to stabilize the dependency. I'll see what we can do on leaflet side.

@gregmacfarlane unfortunately current state is that the tile provides feature of leaflet won't work with bookdown knit and merge approach. You'll have to use new_session: false.