rsvgr-markdownknitrpandoc

RMarkdown figures render as HTML instead of SVG after recent change


I’m using RMarkdown to generate an HTML document with knitr. I previously set all my ggplot2 figures to render as SVG using this yaml and chunk options:

output:
  html_document:
    self_contained: yes

knitr::opts_chunk$set(dev = 'svglite', fig.ext = 'svg')

This used to work perfectly, and I could right-click on the figures to save them as SVG. Recently, however, the figures seem to be rendered as HTML instead of SVG, and now I can no longer right-click them to save, plus the text inside the figures is selectable. Furthermore, some figures are not being rendered properly, for instance some error bars go off the plot margin.

I’ve found that when I set self_contained: no, the SVGs are rendered properly, but it’s crucial for me to still be able to use self_contained: yes.

Also, I noticed that previously, the SVGs were rendered as <img> elements with the src attribute pointing to a base64-encoded version of the SVG file. However, now the figures are embedded directly using the <svg> tag, which changes how the browser handles them, making the SVGs part of the HTML structure rather than separate image files.

This issue seems to be related to a recent update in Pandoc (2.19+).

How can I revert to the previous behavior where figures are saved as standalone SVG files that can be right-clicked and saved?


Solution

  • Inline SVG replaced data URIs for SVG images in Pandoc 3.1.6, in 3.2.1 they introduced inline-svg class to control this behaviour and defaulted back to data URIs. Current RStudio (2024.09 & 2024.11 dailies) still bundle Pandoc 3.2, but you could probably just replace pandoc binary manually.

    Or perhaps install and use 3.2.1 through pandoc package as described in https://bookdown.org/yihui/rmarkdown-cookbook/install-pandoc.html :

    pandoc::pandoc_install("3.2.1")
    pandoc::with_pandoc_version(
      version = '3.2.1',
      rmarkdown::render('rmd_svglite.Rmd')
    )
    

    img in resulting document:

    <img role="img" src="data:image/svg+xml;base64,PD94...==" width="672">
    

    rmd_svglite.Rmd for reference:

    ---
    output:
      html_document:
        self_contained: yes
    ---
    
    ```{r setup, include=FALSE}
    knitr::opts_chunk$set(echo = TRUE, dev = 'svglite', fig.ext = 'svg')
    library(ggplot2)
    ```
    
    ```{r pressure, echo=FALSE}
    pressure |> 
      ggplot(aes(temperature, pressure)) +
      geom_point()
    ```