rmarkdown: Fallback fonts not working consistently across output to pdf and html.

I'd like the code which determines fonts for my (huxtable) tables in rmarkdown to work regardless of output to pdf or html, and allow for fallback fonts
For example, formatting the first row of a table called ht with a font is:
font(ht)[1,] <- "Agenda"
which works fine, pdf or html output, if the font is available.

Now I think either of these used to work for pdf output, but don't anymore.
font(ht)[1,] <- "Agenda, san-serif"
font(ht)[1,] <- paste0("Agenda, \"Source Sans Pro\", sans-serif")
I think the problem is fontspec not allowing for the possibility of a string with fallback fonts, which are separated by commas. It's possible fontspec maintainers would say check the font first, and only send it a font option that you know is available. But if you want a portable rmarkdown across users and output formats, that is not so helpful. Thoughts?

I'd upload a minimal RMarkdown file, but not an allowed format. I'll try to upload somewhere else.
[edit]
Here's an rmarkdown example that "should" work, though a few dependencies that most people with rmarkdown would already have installed?

---
title: "test fallback font"
output:
  pdf_document:
    latex_engine: xelatex
header-includes:
  \usepackage[table]{xcolor}
  \usepackage{sectsty}
  \usepackage{fontspec}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(extrafont)
loadfonts()
library(huxtable)
options(huxtable.latex_use_fontspec = TRUE)

```

## R Markdown table with huxtable and formatted fonts


```{r table}
ht <- hux(iris[1:10,], add_colnames = TRUE)
    
#font(ht)[1,]   <- "Agenda"                #works
font(ht)[1,]   <- "Agenda, san-serif"    #doesn't work    
#font(ht)[1,]   <- paste0("Agenda, \"Source Sans Pro\", sans-serif")  #doesn't work

set_background_color(ht, seq(2, 10, 2), 1:5, "#f2f9ec")

```

You can paste the source of a minimal R Markdown file here, following these instructions to keep it formatted correctly: FAQ: How to Format R Markdown Source

1 Like

Thanks, original post edited to include rmarkdown code.

1 Like

It looks to me as if the problem is that tlmgr is trying to install these fonts. Perhaps if you (re)installed them manually the problem might be solved?

I think fontspec has asked it to look for the the font "Agenda, san-serif" which is not a font - i.e. Agenda would be, or san-serif would work (i think), but not the comma separated text string.

I've raised this at fontspec, though they think the appropriate syntax should be worked out earlier in the chain see not fontspec

Apparently we need to find and fix the "something-to-latex convertor" :slight_smile:

Right. To be fair, huxtable doesn't promise that you can use multiple fonts in font(). If you can figure out an easy way to produce the right kind of TeX, then I might consider it as an addition, but only if it doesn't add too much complexity.

While it would solve my issue, I don't think it is the job of packages like huxtable to sort out the fonts - it seems like it should it happen later in the chain, so that any package could send fallback fonts.

Now, if I understand the tool chain, knitr runs the rmarkdown code to make a markdown file (.md).
Pandoc then takes the .md file to the final format, either html, or pdf via latex (in my case xelatex). Fontspec is a package for xelatex to handle fonts.

So, if we want the fallback fonts to continue to work for the html option, the fallback font list must get to the markdown document. So then either:

  1. Is it Pandoc or xelatex that need to accept a fallback fonts list and, if output is going to pdf, just use the first listed font? Or
  2. Can the markdown file take code chunks that can be used selectively depending on output format? i.e. one code chunk with fallbacks for html, and another code chunk with first listed font for pdf.

Below is ugly, but works, using tips from here:
determine output type to select code that is used

>  if (knitr::is_latex_output()==TRUE) {
>    # pdf output
>    font(ht)[1,]   <- "Agenda"
>  }
> 
>  if (knitr::is_latex_output()==FALSE) {
>    # html output etc
>    font(ht)[1,]   <- "Agenda, Sans-Serif"    #works
>  }

Surely there is a neater way?

well, you could make the code a little neater :slight_smile:

font(ht)[1,] <- if (knitr::is_latex_output()) "Agenda" else "Agenda, Sans-Serif"

Thanks @hughjonesd, let's call that close enough to a win!

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