Так получилось, что за всё время, что я использую в работе R, мне не доводилось рендерить markdown-файлы в формат PDF. Иногда я хранил наработки просто в фалах .R, а исследования оформлял в Google Docs, накидывая туда скринов из viewer-а. Иногда это был рендер в .html, с интерактивной графикой, или проекты Shiny в облаке Posit. Да мало ли вариантов.
Но в связи с некоторыми изменениями в форматах хранения аналитических артефактов, судьба привела меня к PDF.
“Дело-то не хитрое, просто меняем формат вывода в markdown” — подумал я. Однако всё оказалось не так просто: и тексты и ggplot не видят кириллицу, движок xelatex не находит кастомные шрифты, LaTeX вообще бесится на всё.
Каждая проблема отдельно худо-бедно гуглится или решается через chatGPT, но в интернетах намного больше информации как посадить markdown-PDF на китайский, чем на кириллицу.
Расс��отрим на примере классического markdown, а в конце реализация для Quarto.
В общем, по порядку.
В качестве IDE я использую RStudio.
Для рендера в PDF, в первую очередь нужно поставить LaTeX, я не изучал там нюансы движков, а выбрал наиболее цитируемый TinyTex. Устанавливается через CRAN или через Git, кому как нравится:
install.packages('tinytex') tinytex::install_tinytex() #после этой команды нужно полностью перезапустить ваш R-клиент
За основу возьмём вот такой файл .Rmd, с базовым набором элементов: заголовок, текст, код и график.
--- title: "Cyrillic markdown" date: "`r Sys.Date()`" output: pdf_document --- ```{r include = F} library(tidyverse) ``` ```{r include = F} # Создаём датасет dates <- rep(seq(as.Date("2023-01-01"), length.out = 7, by = "days"), each = 2) values <- sample(100:130, 14, replace = TRUE) categories <- rep(c("Cat_A", "Cat_B"), 7) df <- data.frame(date = dates, value = values, category = categories) ``` ## Заголовок Тут у нас кириллический текст с некоторыми вставками english words. ```{r} head(df) ``` Ну и график прилагается: ```{r} # plot 1 ggplot(df, aes(x = date, y = value, col = category)) + geom_line() + labs(title = "График", x = "Дата", y = "Метрика") + theme_minimal() ```
При попытке рендера, если у вас локаль RU, консоль выкатит первую ошибку (или отрендерит без кириллического текста и с кучей warning-ов):
! LaTeX Error: Unicode character З (U+0417) not set up for use with LaTeX.
Решается она, например, таким способом:
В YAML-заголовке указываем движок и включаем дополнения в виде файла header.tex:
--- title: "Cyrillic markdown" date: "`r Sys.Date()`" output: pdf_document: latex_engine: xelatex includes: in_header: header.tex ---
2. Сам файл header.tex лежит в папке с нашим markdown-файлом и выглядит примерно так:
\usepackage{fontspec} \setmainfont{Segoe UI} \setsansfont{Segoe UI} \setmonofont{Segoe UI} \usepackage{polyglossia} \setmainlanguage{russian} \setotherlanguage{english}
Теперь LaTeX перестанет ругаться и кое-как, но PDF-ку соберёт.

Кириллица в тексте обрабатывается, а вот ggplot форматирует даты в текст и ломается.
Если вы не любитель описывать labs в графиках, а уж тем более кириллицей, то тут можно ограничиться сменой локали прям в markdown-файле, добавив куда-нибудь в начало такую строку:
Sys.setlocale("LC_TIME", "en_US.UTF-8")
Второй вариант — использовать библиотеку showtext:
install.packages("showtext") library(showtext) # после загрузки библиотеки, отдаём распознавание на откуп движку showtext_auto()
Предупреждения ушли, график видит кириллицу как в лабсах, так и в датах:

В целом готово. Но мне вообще не нравится как выглядят блоки с кодом. Я люблю для этого использовать шрифты Cascadia Mono PL Light или Cascadia Code Light. Но если шрифт кастомный, просто переписать header.tex не поможет. Я перепробовал разные варианты, и переустановить шрифты, и прописать полное название, и скормить ему весь путь к файлу шрифта — безрезультатно.
В итоге помогла смена движка на lualatex, который тоже поддерживает fontscpec.
--- title: "Cyrillic markdown" date: "`r Sys.Date()`" output: pdf_document: latex_engine: lualatex includes: in_header: header.tex ---
Ну другое дело же)

На этом, пожалуй, и все нюансы рендера markdown в PDF.
Я потратил на это пару вечеров (а мог пить пиво), надеюсь кому-нибудь поможет сэкономить время.
Quarto
Тут намного всё проще, никаких костылей с header.tex не нужно, шрифты прописываются прям в YAML, кириллица на графике лечится тем же showtext:
--- title: "Cyrillic markdown" format: pdf pdf-engine: lualatex mainfont: Segoe UI sansfont: Segoe UI monofont: Cascadia Mono PL Light editor: visual --- ```{r include = F} library(showtext) showtext_auto() ```
По традиции, приглашаю вас в свой ТГ-канал. Там я пишу о продуктовой аналитке, в основном для ребят, которые уже работают, но только начинают свой карьерный путь.
