Inserting “Edit on GitHub” Buttons in a Single R Markdown Document
As the R Markdown ecosystem becomes larger, users now may encounter situations where they have to make decisions on which output format of R Markdown to use. One may found none of the formats suitable – the features essential to the output document one wants may scatter across different output formats of R Markdown.
Here is a real example I encountered. I wanted to create a document that:
- supports bookdown syntax, e.g. text references
- has an “Edit on GitHub” button for every chapter that links to the edit page of the source
The two features above can be obtained easily with bookdown’s default GitBook output format, but one more feature is essential to the document I want:
Now I have to find a way, not provided by the default output formats of R Markdown, to create a document with the above three features.
My first thought was to find out how to add the tabbed sections feature to
I turned to
bookdown::html_document2, which is based on
rmarkdown::html_document (supports tabbed sections).
The source repo of my document is a bookdown project, which has several
.Rmd file starts with a level-one heading and defines a single chapter. Since I wanted tabbed sections from
rmarkdown::html_document, I have to use
bookdown::html_document2 as the output format, which creates a single HTML output file.
Adding to Level-one Headings
bookdown::html_document2 as the output format creates a single document output (as opposed to
bookdown::gitbook which creates several HTML files by default),
so if I want to add an “Edit on GitHub” button for every chapter, I have to track the original
.Rmd that generates the particular chapter.
“Merge and Knit” vs. “Knit and Merge”
There are two rendering approaches in bookdown. The default is Merge and Knit, which combines all source
.Rmd files into one single
.Rmd file then knits the document.
In this case, it would be impossible to track the source
.Rmd file for each chapter (unless I create a lookup table manually).
I can track the source
.Rmd files easily, however, if the document is rendered using the Knit and Merge approach. When using the Knit and Merge approach, the code chunks in the source
.Rmd files are run and the results embedded before the documents get combined together in a single output file. This mean that I can retrieve the source
.Rmd file name while knitting the file (by
knitr::current_input()). This gives me all I need to create the link to the edit page of the
.Rmd source file on GitHub.
To switch from the default “Merge and Knit” to “Knit and Merge”, set
new_session: yes in
new_session: yes before_chapter_script: 'addons/pre_chap.R'
To insert the link to the edit page on GitHub, put
`r edit_btn` (inline R code) at the end of the h1 heading of each
.Rmd file, for example:
# Function Factories `r edit_btn`
edit_btn is a string variable holding the link2 to GitHub. It is computed in the R script
addons/pre_chap.R, which is run every time before knitting a
url <- 'https://github.com/liao961120/parallelCode/edit/master/' gh_edit_path <- paste0(url, knitr::current_input()) edit_btn <- paste0('<a href="', gh_edit_path, '">', '<img src="https://bit.ly/2RRirG7" ', 'alt="fa-edit" ', 'class="edit"></a>')
addons/pre_chap.R run every time before knitting a
.Rmd file, include it in the
before_chapter_script field in
_bookdown.yml, as shown in the section, Setting up:
This is the output format I set in
bookdown::html_document2: theme: readable highlight: default toc: true toc_depth: 2 toc_float: collapsed: false css: addons/style.css self_contained: false
Path Problems Caused by
You may notice that I set
self_contained: false in
_output.yml. This isn’t necessary3 and it actually makes things a little more complicated, since, when using
bookdown::html_document2 as the output format, bookdown generates all its dependencies (CSS, JS libraries, figures, etc) in
_bookdown_files and generates its ouput HTML file in the project root directory but doesn’t move the dependencies and the output HTML to the output directory (defaults to
_book) nor modify the relative path to dependency files in the output HTML. This causes the links in the output HTML to break.
mv out.html _bookdown_files/index.html [[ -e out.rds ]] && mv out.rds _bookdown_files/ cp -r addons/ _bookdown_files/ [[ -d docs ]] && rm -r docs mv _bookdown_files docs
For users who don’t use bash, R can be used instead. Check out this post about file manipulation in R.
The reason I wanted this feature is that I’m writing a document that works like a parallel text.
I know three programming languages – R, Bash, and Python, but I’m only familiar with R, struggle with the weird syntax of Bash sometimes (that said, I like Bash pretty much, for its power to do quick and dirty works), and don’t use Python often enough to memorize commonly used syntax.
By creating a parallel text for R, Bash, and Python, I can write down the code to deal with some common tasks in these three langauges, so I don’t have to look it up on google every time I forgot the syntax of the langauge.
I planned to write this document myself initially. But why not do a little more work to make it convenient for others to contribute to this document? This is why I decided to add an “Edit on GitHub” button at the start of every chapter of the document.↩
<img>tag in it. The style of
img.editis defined in
addons/style.css. I didn’t use fontawesome for the edit icon , since
bookdown::html_document2doesn’t support it and I don’t want to introduce another dependency. I use
<img>tag to source the edit icon from wikimedia instead.↩
falsebecause I didn’t want a large output file that takes too much time to load in the browser.↩
Note that I changed some default filenames by adding some lines in
book_filename: "out" # output HTML filename output_dir: "docs" # output dir, defaults to `_book`
Last updated: 2019-02-10