Home > Software design >  render a markdown file to pdf with rmarkdown::render() and adjust page margins and font
render a markdown file to pdf with rmarkdown::render() and adjust page margins and font

Time:01-19

I'd like to render a simple markdown file, that has been created by another process before, into a pdf file.

The command:

rmarkdown::render(input = "my_report.md", 
                  output_format = rmarkdown::pdf_document(latex_engine = "xelatex"))

just does this job.

However I would like to change the margins and the main font. With an .Rmd file one would define these settings in the Yaml header like this:

---
output: 
  pdf_document:
    latex_engine: xelatex
mainfont: LiberationSans
geometry: "left=5cm,right=3cm,top=2cm,bottom=2cm"
---

But the markdown files I'd like to convert don't have a Yaml header. Is there a way to pass these Yaml options to the render function as function parameters or in an indirect way?

CodePudding user response:

It's possible, but only using some trickery, and it might not work for all possible arguments. It does seem to work for mainfont and geometry.

The way those settings are passed to LaTeX is as Pandoc variables which are inserted into the template. The trouble is, the pdf_document driver hardcodes margins of 1in if you don't have them in your YAML, and those are added to the Pandoc command line right near the end. You need to override that setting even later.

Here's one way to do it. Create your own output format that is based on pdf_document, but which adds its own variable settings right at the end. For example,

my_pdf_document <- function(geometry, mainfont, ...) {
  force(geometry)
  force(mainfont)
  result <- rmarkdown::pdf_document(...)
  oldpreproc <- result$pre_processor
  result$pre_processor <- function(...) {
    c(oldpreproc(...),
      "--variable",
      paste0("geometry:", geometry),
      "--variable",
      paste0("mainfont:", mainfont))
  }
  result
}

When you want to render using this preprocessor, give the arguments you would have given to pdf_document as well as the ones being set using Pandoc variables, e.g.

rmarkdown::render("test.md",
              output_format = my_pdf_document(
                geometry = "left=5cm,right=3cm,top=2cm,bottom=2cm", 
                mainfont = "Helvetica", 
                latex_engine="xelatex")
             )

When I make the call above, I see a Pandoc command that looks like this:

/Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/pandoc
   RTS -K512m -RTS test.md --to latex --from
  markdown autolink_bare_uris tex_math_single_backslash 
  --output test.tex 
  --lua-filter /Library/Frameworks/R.framework/Versions/4.2/Resources/library/rmarkdown/rmarkdown/lua/pagebreak.lua 
  --lua-filter /Library/Frameworks/R.framework/Versions/4.2/Resources/library/rmarkdown/rmarkdown/lua/latex-div.lua 
  --embed-resources --standalone --highlight-style tango 
  --pdf-engine xelatex --variable graphics 
  --variable 'geometry:margin=1in' 
  --variable 'geometry:left=5cm,right=3cm,top=2cm,bottom=2cm' 
  --variable 'mainfont:Helvetica' 

(though it's all on one long line, not wrapped so neatly). The 3rd last line is the problematic margin setting, and the last two lines are the result of our special output format.

EDITED to add:

An easier, less hacky approach to this would be to read the entire Markdown file and write it out again with a YAML header. Then you can put whatever you like in the header, and it'll work if a hard coded version would work.

CodePudding user response:

Option 01

geometry, mainfont are pdf output

Output from 2nd option

pdf output

  • Related