Supporting R Markdown with Jekyll and knitr
Blogging with Jekyll and Markdown is good, but sometimes R Markdown is necessary.
Based on the following two posts, I figured out how to support R Markdown in the Github pages. The basic idea is to use knitr
to convert R Markdown files to Jekyll friendly markdown files.
- Blogging with Jekyll and R Markdown using knitr by Andrew
- Publishing R Markdown using Jekyll by chepec
The first blog is adapted from the second blog, so their basic idea is the same. Based on their idea, I made some minor changes - all the credit goes to them.
Also, I added some extra features such as auto-rerun bash script whenever we make changes to an R Markdown file, even on Windows.
Use R script to call knitr
Here are the steps:
- Create a directory called
_Rmd
at the root level of the Jekyll directory, which will store all R Markdown files. In_Rmd
, an R script is also created (calledrender_post.R
), which is adapted from the first blog and shown below. - Configure the paths for each directory accordingly, for example,
posts.path
is_posts
. - Create an R Markdown post under
_Rmd
, such as2017-10-23-test-markdown.Rmd
. At the beginning of this file, remember to add proper front matter for Jekyll. - Run
KnitPost
to convert files. For simplicity, in the next section, I created a bash script to convert_Rmd/*.Rmd
to_post/*.md
.
Use bash script to call R script
I created a bash script (called convert_rmd.sh
) under the root level of the Jekyll directory, which is adapted from the second blog.
It can convert a specific R Markdown file under _Rmd/
to Jekyll markdown under _posts/
:
$ ./convert_rmd.sh _Rmd/YYYY-mm-dd-title.Rmd
Alternatively, it can convert all files under _Rmd/
to _posts/
:
$ ./convert_rmd.sh --all
To support Rscript with Cygwin on Windows, I added platform check at the bottom. Customize with your own path to Rscript.exe.
Update: I found that Rscript on Unix and Windows will generate different line endings and figures. It is recommended to use Unix-style line endings to be consistent with GitHub Pages. Otherwise, the carriage return (\r
) on Windows would cause an extra line break in code block when rendering on GitHub Pages.
#!/bin/bash
# Credit: adapted from https://chepec.se/2014/07/16/knitr-jekyll
function show_help {
echo "Usage: convert_rmd.sh [filename.Rmd | --all] ..."
echo "Knit posts, convert Rmd to jekyll blog"
echo "<filename.Rmd> convert a specific _Rmd/*.Rmd file to _posts/*.md (overwrite existing md)"
echo "--all convert all _Rmd/*.Rmd files to _posts/*.md (overwrite existing md)"
}
if [ $# -eq 0 ] ; then
# no args at all? show help
show_help
exit 0
fi
sitepath="./"
cmd="source('./_Rmd/render_post.R')"
if [ "$1" = "--all" ]; then
echo "convert all _Rmd/*.Rmd to _posts/*.md"
cmd="$cmd; KnitPost(site.path='$sitepath', overwriteAll=T)"
else
rmdfile=$1
cmd="$cmd; KnitPost(site.path='$sitepath', overwriteOne='$rmdfile')"
fi
# determine Rscript for different platforms; in particular, for Cygwin on Windows
case "$(uname -s)" in
Darwin|Linux)
# echo 'Mac OS X or Linux'
Rscript -e "$cmd"
;;
CYGWIN*|MINGW32*|MSYS*)
# echo 'Windows'
/cygdrive/c/'Program Files'/R/R-3.3.0/bin/Rscript.exe -e "$cmd"
echo: "Warning: remember to convert line endings to Unix style before publish"
;;
*)
echo 'other OS'
;;
esac
Auto-rerun when .Rmd file changes
It would be cumbersome if we need to manually rerun the above script whenever we make changes to an R Markdown file.
Also, if we could automatically rerun the above script, then we could view the generated html in the browser (locally) immediately.
To achieve this, I’m using a command called when-changed. It is cross-platform and works well on Windows; other possible solutions might be nodemon
or inotifywait
, based on this question.
# install when-changed
$ pip install https://github.com/joh/when-changed/archive/master.zip
# Usage: when-changed FILE -c COMMAND (watch FILE changes and exec COMMAND)
$ when-changed _Rmd/<filename>.rmd -c bash convert_rmd.sh _Rmd/<filename>.rmd
# assume that Jekyll is also running in a different tab
$ bundle exec jekyll serve --livereload # Jekyll v3.7+
In such case, an R Markdown file will be automatically converted to _posts/*.md
, further compiled to html, and live-reloaded in the browser (given Jekyll v3.7+).
Add figure prefix by setting fig.path for each post
So far, the R Markdown could be rendered correctly, including the figures generated by ggplot2. However, those figures are named after the chunk name of each code chunk. For example, a code chunk {r plot_residual}
has the chunk name “plot_residual”, so the generated figures would be named as “plot_residual-1.svg”, “plot_residual-2.svg”, and so on.
It is likely that we have two code chunks with the same name when we have multiple R Markdown files. We have to distinguish the figures from different files by adding a prefix to each figure.
The step is straightforward. Based on Blogging About R Code with R Markdown, Knitr, and Jekyll by Nicole White, we just need to put the following code at the beginning of each post:
Since the prefix is distinct, the generated figures will have distinct names, even though the chunk names are duplicate.
Example
All is done. Here I will show what an R Markdown would look like after being converted to a Jekyll page. The code snippets are copied from example-r-markdown.rmd.
Prepare for analyses
Basic console output
The code chunk input and output is then displayed as follows:
ggplot2
plot
ggplot2 plots work well: