Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Make htmlwidgets work with knitr-powered Jekyll and GitHub Pages
#' Set knitr hooks for htmlwidgets with Jekyll/GitHub Pages
#' This functions sets a `knitr` hook so that any HTML widgets that were
#' printed (i.e., objects that inherit the `'htmlwidget'`, like those from
#' the `htmlwidgets` or `plotly` packages) will work with a Jekyll system,
#' like the one used for GitHub Pages.
#' It essentially sets a hook so that, when the document is finished being
#' knitted, it moves all the dependencies necessary for the widgets to a
#' directory, and then adds HTML code to the document to load those files
#' from their new location. Additionally, it sets the default
#' `screenshot.force` chunk option to `FALSE`, so `knitr` doesn't try to
#' use a screenshot instead of the widget.
#' See for background
#' and (
#' for the old, bad version of this script.
#' @param dep_dir The directory you want to save the dependencies to.
#' @param base_path The directory you want to make the dependency links relative to.
#' For example, if your post is at the url ``, then you'll
#' want to make `base_path` the home directory of your project.
#' @param hrefFilter This function lets you perform any additional manipulations
#' to the dependency links. For some reason, when I give my base directory as my
#' project's home directory, the links come back without the necessary "/" in front
#' of them. This function adds that to each link.
#' @export
set_widget_hooks <- function(dep_dir, base_path,
hrefFilter = function(x) paste0("/", x)) {
# Move the dependencies into the specified folder,
# makes them relative to the base directory,
# and outputs the HTML that loads them.
render_deps <- function() {
l <- knitr::knit_meta(class = "html_dependency",
clean = FALSE)
if (length(l) > 0)
dir.create(dep_dir, showWarnings = FALSE, recursive = TRUE)
l <- lapply(unique(l), function(dep) {
dep <- htmltools::copyDependencyToDir(dep, dep_dir, FALSE)
dep <- htmltools::makeDependencyRelative(dep, base_path, FALSE)
dep } )
l <- htmltools::renderDependencies(l, hrefFilter=hrefFilter)
# Adds the dependency-loading HTML at the end of the doc,
# without upsetting the previous doc-hook.
prev_doc_hook <- knitr::knit_hooks$get("document")
knitr::knit_hooks$set(document = function(x) {
prev_doc_hook(append(x, render_deps()))
# Sets the default of all chunks to not force
# screenshots. You can change it to `TRUE`
# on the chunks you want it to screenshot.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.