Tips to Reduce the Complexity of Slide Making with Xaringan

[This article was first published on Yongfu's Blog, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Although I’m a strong believer in R Markdown, I’m not so sure about it in the realm of slide making. After using GUI slide making tools such as Powerpoint or Google Slides for years, it is not easy to get used to making slides with markdown, since it requires additional processing in the brain – the conversion between images in the brain and the markup language to create them on the slides.
xaringan::inf_mr() greatly reduces this burden on the brain, but one serious drawback still persists. When making slides with Markdown, the source document often gets very long. I frequently found myself lost in the source document (after scrolling up and down), not knowing which part of the slide is it that I’m looking at1.
To be fair, there are great things about making slides with markdown, for example, it’s easier to manage and reuse images through URLs, and markdown is convenient for formatting code (automatic syntax highlighting).

I have been making a lot of slides with Xaringan lately. After spending hours on Xaringan, I began to have more faith in making slides with markdown because I figured out some tips to reduce the pain caused by markup langauges. The idea is simple – reduce the length and complexity of the source R Markdown document. knitr is my friend here.

Use Several Source Documents

bookdown uses several Rmd files to generate a book. The same idea can be used in Xaringan, and here are some advantages I can think of:

  • By splitting the source document into several meaningful sub-documents, you can locate particular parts of your slide faster (the so-called “chunking”).

  • Your slides can be easily reused, since you can copy a part of your slides by choosing the relevent Rmd file(s). (Not copy-and-pasting text from the parts you want in one lengthy Rmd file)

Child Document

To use several source Rmd documents to generate a single Xaringan (or any R Markdown) output, use knitr chunk option child to include other Rmd files in a Rmd document. For example, I would create one index.Rmd and several Rmd files with meaningful names (e.g., opening.Rmd, intro-github.Rmd, contact.Rmd, etc.):

<span class="s">my-slide/</span>
<span class="s">├── index.Rmd</span>
<span class="s">├── opening.Rmd</span>
<span class="s">├── intro-github.Rmd</span>
<span class="s">├── contact.Rmd</span>
<span class="s">├── html-table.txt</span>
<span class="s">├── img/</span>
<span class="s">└── addons/</span>
 <span class="s">   ├── custom.css</span>
 <span class="s">   └── macros.js</span>

The chunk option child is then used in index.Rmd to include other *.Rmd:

<span class="nn">---</span>
<span class="na">title</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Introduction</span><span class="nv"> </span><span class="s">to</span><span class="nv"> </span><span class="s">R</span><span class="nv"> </span><span class="s">Markdown"</span>
<span class="na">output</span><span class="pi">:</span>
  <span class="s">xaringan::moon_reader</span><span class="pi">:</span>
    <span class="na">nature</span><span class="pi">:</span>
      <span class="na">beforeInit</span><span class="pi">:</span> <span class="pi">[</span><span class="s2">"</span><span class="s">addons/macros.js"</span><span class="pi">,</span> <span class="s2">"</span><span class="s">https://platform.twitter.com/widgets.js"</span><span class="pi">]</span>
    <span class="na">css</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">default</span><span class="pi">,</span> <span class="nv">default-fonts</span><span class="pi">,</span> <span class="nv">addons/custom.css</span><span class="pi">]</span>
<span class="nn">---</span>

<span class="err">```</span><span class="pi">{</span><span class="nv">r setup</span><span class="pi">,</span> <span class="nv">include=FALSE</span><span class="pi">}</span>
<span class="s">knitr::opts_chunk$set(echo = FALSE)</span>
<span class="s">options(knitr.duplicate.label = 'allow')</span>
<span class="err">```</span>

<span class="err">```</span><span class="pi">{</span><span class="nv">r child='opening.Rmd'</span><span class="pi">}</span>
<span class="err">```</span>
<span class="nn">---</span>

<span class="err">```</span><span class="pi">{</span><span class="nv">r child='intro-github.Rmd'</span><span class="pi">}</span>
<span class="err">```</span>
<span class="nn">---</span>

<span class="err">```</span><span class="pi">{</span><span class="nv">r child='contact.Rmd'</span><span class="pi">}</span>
<span class="err">```</span>

Complex Markups in Independent Files

Sometimes we may want to put cool things in the slides that can only be created from HTML syntax, for example, the table below (generated from TablesGenerator.com):

Heuristic
plausible implausible
Syntax-driven plausible P600
N400
implausible P600 N400

This table looks simple, but it is generated by a 2728-character-long HTML code, which greatly increases the length and complexity of the source document. To make the source document cleaner, you can put code of these kinds in separate text files and include them into the R Markdown source document by knitr::asis_output(readLines('html-table.txt'))2 and R Markdown inline code `r `:

A table generated from
<span class="p">[</span><span class="nv">TablesGenerator.com</span><span class="p">](</span><span class="sx">https://www.tablesgenerator.com/html_tables#</span><span class="p">)</span>:

<span class="sb">`r knitr::asis_output(readLines('html-table.txt'))`</span>

remark.js Built-in Functionalities

remark.js actually provides useful functionalities to help reduce the complexity of the slides. READ THE DOCs, and it might save you a great deal of time. Xaringan and remark.js both provide good wiki pages, and I regret I read them too late – after I spent a lot of time copy-and-pasting and made my Rmd source document uglier.

Below are some notes extract from Xaringan & remark.js Wiki pages. They serve as quick references (for myself) and aren’t meant to be detailed. Again, READ THE DOCs!

Configuration

Xaringan Configuration (remark has a more thorough documentation) is set in YAML frontmatter:

<span class="na">output</span><span class="pi">:</span>
  <span class="s">xaringan::moon_reader</span><span class="pi">:</span>
    <span class="na">nature</span><span class="pi">:</span>
      <span class="na">ratio</span><span class="pi">:</span> <span class="s2">"</span><span class="s">16:10"</span>
      <span class="na">beforeInit</span><span class="pi">:</span> <span class="pi">[</span><span class="s2">"</span><span class="s">addons/macros.js"</span><span class="pi">,</span> <span class="s2">"</span><span class="s">https://platform.twitter.com/widgets.js"</span><span class="pi">]</span>
      <span class="na">highlightLines</span><span class="pi">:</span> <span class="no">true</span>
      <span class="na">highlightSpans</span><span class="pi">:</span> <span class="no">false</span>
      <span class="na">navigation</span><span class="pi">:</span>
        <span class="na">scroll</span><span class="pi">:</span> <span class="no">false</span>
    <span class="na">css</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">default</span><span class="pi">,</span> <span class="nv">default-fonts</span><span class="pi">,</span> <span class="nv">addons/custom.css</span><span class="pi">]</span>
    <span class="na">yolo</span><span class="pi">:</span> <span class="no">false</span>
    <span class="na">seal</span><span class="pi">:</span> <span class="no">true</span>

remark Special Syntax

  • name: Adding ID to a slide

    name: about
      
    ## About

    • reference with see [About](#about)
  • count

    count: false
      
    This slide will not be counted.

  • template

    name: template-slide
    
    Some content.
    
    ---
    template: template-slide
    
    Content appended to template-slide's content.

  • layout

Macros

  • Image with Absolute postition:

    Define macros in addons/macros.js:

    <span class="nx">remark</span><span class="p">.</span><span class="nx">macros</span><span class="p">[</span><span class="s1">'abs'</span><span class="p">]</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">width</span><span class="o">=</span><span class="s2">"30%"</span><span class="p">,</span> <span class="nx">left</span><span class="o">=</span><span class="s2">"85%"</span><span class="p">,</span> <span class="nx">top</span><span class="o">=</span><span class="s2">"15%"</span><span class="p">,</span> <span class="nx">cl</span><span class="o">=</span><span class="s2">""</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">url</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
    <span class="k">return</span> <span class="s1">'<img src="'</span> <span class="o">+</span> <span class="nx">url</span> <span class="o">+</span> <span class="s1">'" style="position:absolute;left:'</span> <span class="o">+</span> <span class="nx">left</span> <span class="o">+</span> <span class="s1">';top:'</span> <span class="o">+</span> <span class="nx">top</span> <span class="o">+</span> <span class="s1">';width:'</span> <span class="o">+</span> <span class="nx">width</span> <span class="o">+</span> <span class="s1">'" class="'</span> <span class="o">+</span> <span class="nx">cl</span> <span class="o">+</span> <span class="s1">'" />'</span><span class="p">;</span>
    <span class="p">};</span>

    Use it in markdown:

    <span class="p">![</span><span class="nv">:abs width, left, top</span><span class="p">](</span><span class="sx">url</span><span class="p">)</span>
      
    <span class="p">![</span><span class="nv">:abs 30%, 50%, 0%</span><span class="p">](</span><span class="sx">url</span><span class="p">)</span>
      
    <span class="nt"><img</span> <span class="na">src=</span><span class="s">"url"</span> <span class="na">style=</span><span class="s">"position:absolute; width:30%; left:50%; top:0%;"</span><span class="nt">></span>

  1. This is the major drawback of markup languages compared to GUI authoring tools. Although markdown itself is designed to deal with this drawback (i.e. the too-complicated HTML syntax), the inherently complex structure of slideshows still complicates the source document of the slides writen in markdown. 

  2. Note that there is only one line in html-table.txt so readLines() returns a character vector of length 1. If there are multiple lines in the text file, one needs to use paste(readLines('html-table.txt'), collapse = '\n') to properly print out the text file. 

To leave a comment for the author, please follow the link and comment on their blog: Yongfu's Blog.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)