rstudio / shiny-server

Host Shiny applications over the web.
https://rstudio.com/shiny/server
Other
712 stars 291 forks source link

Recognize qmd extension as quarto #531

Closed jcheng5 closed 1 year ago

jcheng5 commented 1 year ago

This PR allows Shiny Server to treat .qmd files the same as .Rmd files. The only difference is that .qmd files only work in prerendered mode; we go out of our way to prevent document rendering from occurring in any directory that contains .qmd.

Testing notes

Using this file:

---
title: "Old Faithful"
format: html
server: shiny
---

```{r}
sliderInput("bins", "Number of bins:", 
            min = 1, max = 50, value = 30)
plotOutput("distPlot")
#| context: server
output$distPlot <- renderPlot({
  x <- faithful[, 2]  # Old Faithful Geyser data
  bins <- seq(min(x), max(x), length.out = input$bins + 1)
  hist(x, breaks = bins, col = 'darkgray', border = 'white')
})

### Scenario 1: Prerendered

1. Save the document above on a local machine with Quarto installed, with the filename `index.qmd`.
2. In the directory with `index.qmd` run `quarto serve index.qmd`, this should cause a render.
3. Deploy `index.qmd`, `index.html`, and `index_files/` into a Shiny Server site subdirectory.

**Expected:** You can load up the app and interact with it.

### Scenario 2: Not prerendered

1. Put the document above in a Shiny Server site subdirectory as `index.qmd`, with no other contents.

**Expected:** The app should completely fail to load (no UI or anything, just an error message). The app log should say something about "Prerendered HTML file not found" or something.

### Scenario 3: Filename other than index.qmd

1. Save the document above on a local machine with Quarto installed, with the filename `page.qmd`.
2. In the directory with `page.qmd` run `quarto serve page.qmd`, this should cause a render.
3. Deploy `page.qmd`, `page.html`, and `page_files/` into a Shiny Server site subdirectory.
4. In the same site subdirectory, create `index.html`:
  ```html
  <!DOCTYPE html>
  <html>
    <body>
      <a href="page.qmd">Link to app</a>
    </body>
  </html>

Expected: Navigating to the subdirectory should produce a simple page with "Link to app"; clicking that link should bring you to a working app.

Scenarios 4-6

Same as above, but use app_dir instead of site_dir directive in the SSOS config file.

Scenarios 7-9

Same as above, but use user_dirs instead of site_dir and log_dir directive in the SSOS config file. (As of Shiny Server 1.5.20, this isn't working correctly)

jjallaire commented 1 year ago

@jcheng5 The implementation should be exactly the same as for Rmd (save for the fact that you definitely can't render). Here is how we implement quarto serve internally:

Sys.setenv(RMARKDOWN_RUN_PRERENDER = "0")
rmarkdown::run(input, shiny_args = list(host = "127.0.0.1" port = 5555))

https://github.com/quarto-dev/quarto-cli/blob/9d84aeda784f40b1e647bab1a891bc1f7a83b833/src/resources/rmd/rmd.R#L119-L123

jcheng5 commented 1 year ago

@jjallaire If I put the Hello Shiny app at https://quarto.org/docs/interactive/shiny/#hello-shiny into index.qmd and don't prerender, and run this branch as-is, it does seem to render and work correctly (if the R process has permissions to modify the directory). Are you saying we want to explicitly prevent this? (If so--it it because what I've done is actually render it with R Markdown, not Quarto, and it just happened to work because it's a simple document?)

jjallaire commented 1 year ago

Yes correct, it "worked" by treating it as R Markdown so no Quarto feature will work. It would be a separate feature to support Quarto rendering but I think that is unnecessary

jcheng5 commented 1 year ago

@jjallaire It looks like the way this works is that we call rmarkdown::run(file = NULL, dir = "..."), and any requests to any of the Shiny rmd/qmd documents in that directory all go to the same R process.

In the (unlikely? or not?) case of a directory containing both .qmd and .rmd files, do you think I should set RMARKDOWN_RUN_PRERENDER=0?

jjallaire commented 1 year ago

if there are both then yes set RMARKDOWN_RUN_PRERENDER=0 as the qmd will never work as expected unless you set that.

hulihuihong commented 8 months ago

nice