--- title: "How to use colored text in Quarto figure captions" format: html: toc: true pdf: toc: true --- In figure captions, it is often useful to say refer to colored objects by printing the words in their colors. How can I do this with output in HTML or PDF? Define a function to colorize text, that can be used in HTML or PDF output ```{r colorize} # colorize text: use inline as `r colorize(text, color)` to print `text` in a given `color` # can also be used to color a color name, as in r colorize("red")` colorize <- function(text, color) { if (missing(color)) color <- text if (knitr::is_latex_output()) { sprintf("\\textcolor{%s}{%s}", color, text) } else if (knitr::is_html_output()) { sprintf("%s", color, text) } else text } ``` In normal text, I can use `colorize()` to print text in `r colorize("red")`, `r colorize("blue")`, `r colorize("green")`, ... But not in a figure caption. This works but the text is not colored in the caption of @fig-test ````qmd #| label: fig-test #| out-width: "70%" #| fig-cap: Some points should be red, some blue, some green cols <- c("red", "blue", "green") plot(1:10, pch=16, cex = 3, col = cols) ```` ```{r} #| label: fig-test #| out-width: "70%" #| fig-cap: Some points should be red, some blue, some green cols <- c("red", "blue", "green") plot(1:10, pch=16, cex = 3, col = cols) ``` ## Inline expression in a caption `colorize()` doesn't work in a caption. The expression is not evaluated, and just prints in the caption as a literal, in code font. ````qmd #| label: fig-test2 #| out-width: "70%" #| fig-cap: Some points are `r colorize("red")`, some are `r colorize("blue")`, some are `r colorize("green")` cols <- c("red", "blue", "green") plot(1:10, pch=16, cex = 3, col = cols) ```` ```{r} #| label: fig-test2 #| out-width: "70%" #| fig-cap: Some points are `r colorize("red")`, some are `r colorize("blue")`, some are `r colorize("green")` cols <- c("red", "blue", "green") plot(1:10, pch=16, cex = 3, col = cols) ``` ## Try !expr One solution: use the YAML `!expr` "tag" literal in `fig-cap`: ````qmd #| label: fig-test3 #| out-width: "70%" #| fig-cap: !expr paste("Some points are", colorize('red'), "some are", colorize('blue'), "some are", colorize("green")) cols <- c("red", "blue", "green") plot(1:10, pch=16, cex = 3, col = cols) ```` ```{r} #| label: fig-test3 #| out-width: "70%" #| fig-cap: !expr paste("Some points are", colorize('red'), "some are", colorize('blue'), "some are", colorize("green")) cols <- c("red", "blue", "green") plot(1:10, pch=16, cex = 3, col = cols) ``` ## Can we simplify this? Define color names as global variables and use `glue::glue()` ```{r} red <- colorize('red') blue <- colorize('blue') green <- colorize("green") library(glue) ``` ````qmd #| label: fig-test4 #| out-width: "70%" #| fig-cap: !expr glue("Some points are ", {red}, " some are ", {blue}, "some are ", {green}) cols <- c("red", "blue", "green") plot(1:10, pch=16, cex = 3, col = cols) ```` Voila! This is much easier to type in captions, but need to add spaces ```{r} #| label: fig-test4 #| out-width: "70%" #| fig-cap: !expr glue("Some points are ", {red}, " some are ", {blue}, " some are ", {green}) plot(1:10, pch=16, cex = 3, col = cols) ``` ## Final solution Use the color name variables, but just use `paste()` ````qmd #| label: fig-test4 #| out-width: "70%" #| fig-cap: !expr paste("Some points are", red, "some are", blue, "some are", green) plot(1:10, pch=16, cex = 3, col = cols) ````