When can I use a prefix created with `shiny::addResourcePath()` to access shared resources?

Hi everyone

I am currently working on a package that contains multiple learnr tutorials. Here is a simplified version of the package layout (here called {tutorialpackage}):

.
├── DESCRIPTION
├── NAMESPACE
├── R
│   └── hello.R
├── inst
│   ├── resources
│   │   ├── child_Rmds
│   │   │   └── formatting.Rmd
│   │   ├── css
│   │   │   └── style.css
│   │   ├── images
│   │   │   └── rstudio_logo.png
│   │   └── scripts
│   │       └── example_script.R
│   └── tutorials
│       └── first_tutorial
│           └── first_tutorial.Rmd
├── man
│   └── hello.Rd
└── tutorialpackage.Rproj

I would like to manage all resources used by the tutorials in a central directory inst/resources (corresponding to resources of the installed package), using shiny::addResourcePath(). For example, CSS files whould be in resources/css and accessed with /css.

---
title: "First tutorial"
output:
  learnr::tutorial:
    css: /css/style.css # works
runtime: shiny_prerendered
---

```{r setup, include=FALSE}
library(learnr)
knitr::opts_chunk$set(echo = FALSE)
# Link to static resources to Shiny's web server
list.dirs(system.file("resources", package = "tutorialpackage"),
          recursive = FALSE) |>
  purrr::walk(\(x) shiny::addResourcePath(basename(x), x))
# Steps above equivalent to
# shiny::addResourcePath("css",
#                        system.file("resources", "css"
#                        package = "tutorialpackage"))
# repeated for all other directories in `resources`
```

## Topic 1

::: exercise <!-- works -->
Testing `div` definition from `style.css`.
:::

Adding image:
![](/images/rstudio_logo.png){width=5%} <!-- works here -->

```{r}
knitr::include_graphics("/images/rstudio_logo.png") # Does not work
test <- readr::read_file("/scripts/example_script.R") # Does not work
```
<!-- Loading child document below does not work -->
```{r child = "/child_Rmds/formatting.Rmd"}

I am unclear in what context the prefix path to a file works. For example, why does /images/rstudio_logo.png work with ![](/images/rstudio_logo.png) but not knitr::include_graphics("/images/rstudio_logo.png")? Why does css: /css/style.css in the YAML header work but not test <- readr::read_file("/scripts/example_script.R")? Is there a way to explicitly tell R that the path provided is a prefix path?

Thanks,

Stephan

Edit: Added comment to explain purrr:walk(); fixed code example

A learnr tutorial involves two primary contexts:

  1. The pre-render step that generates static content and prepares the tutorial content.
  2. The Shiny app step that runs the tutorial interactively for the user.

Since shiny::addResourcePath() is a function that has an affect on files and folders served by Shiny apps, it only affects the second context. In other words, you can expect

![](/images/rstudio_logo.png)

to work because the image is found by the user's browser when they interact with the running tutorial, after you've configured Shiny to make those images available at /images/.

OTOH, the examples in this R chunk do not work

```{r}
knitr::include_graphics("/images/rstudio_logo.png") # Does not work
test <- readr::read_file("/scripts/example_script.R") # Does not work
```

because, as standard R chunks, they are evaluated during the pre-render step just as if you were running those commands in your R console. In those cases ,you'll need to adjust the file paths to locate the image and script on your disk relative to the source Rmd file.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.