Skip to content

Instantly share code, notes, and snippets.

@burchill
Last active January 27, 2022 19:10
Show Gist options
  • Save burchill/8392b2a753652e24a35a8a1dd707c1b1 to your computer and use it in GitHub Desktop.
Save burchill/8392b2a753652e24a35a8a1dd707c1b1 to your computer and use it in GitHub Desktop.
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 https://www.zachburchill.ml/plotly_with_jekyll/ for background
#' and (https://gist.github.com/burchill/9df0f6245ea7768e5b6bbd0a1c22db08)
#' 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 `yoursite.com/this_post/`, 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)
htmltools::htmlPreserve(l)
}
# 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.
knitr::opts_chunk$set(screenshot.force=FALSE)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment