Skip to content

Commit

Permalink
Merge pull request #13 from debruine/main
Browse files Browse the repository at this point in the history
quarto stuff
  • Loading branch information
debruine authored May 5, 2023
2 parents 8e55cab + 2f68d81 commit f48b8d2
Show file tree
Hide file tree
Showing 60 changed files with 3,850 additions and 3,143 deletions.
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
^cran-comments\.md$
^README\.html$
^Makefile$
^webexercises\.Rproj$
11 changes: 7 additions & 4 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
Package: webexercises
Version: 1.0.0
Date: 2021-09-06
Version: 1.1.0
Date: 2023-04-18
Title: Create Interactive Web Exercises in 'R Markdown' (Formerly 'webex')
Description: Functions for easily creating interactive web pages using
'R Markdown' that students can use in self-guided learning.
Authors@R: c(
person("Dale","Barr",
email = "[email protected]",
role = c("aut", "cre")),
role = c("aut", "cre")),
person("Lisa", "DeBruine",
email = "[email protected]",
role = "aut"))
Expand All @@ -18,11 +18,14 @@ Imports:
knitr,
yaml,
utils,
grDevices,
rstudioapi,
rmarkdown (>= 2.2)
License: CC BY-SA 4.0
RoxygenNote: 7.1.1
RoxygenNote: 7.2.1
Suggests:
testthat,
bookdown,
quarto,
xfun
Encoding: UTF-8
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Generated by roxygen2: do not edit by hand

export(add_to_bookdown)
export(add_to_quarto)
export(create_quarto_doc)
export(escape_regex)
export(fitb)
export(hide)
Expand Down
8 changes: 8 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# webexercises 1.1.0

* quarto support (`create_quarto_doc()` and `add_to_quarto()`)
* fenced .webex-check sections for self-checking quizzes
* webex.hide knit hooks get set up .onLoad instead of in webex.R
* remove js dependency on jquery
* `total_correct()` deprecated

# webexercises 1.0.0

* new package name: webexercises
Expand Down
50 changes: 23 additions & 27 deletions R/add_to_bookdown.R
Original file line number Diff line number Diff line change
@@ -1,64 +1,60 @@
#' Add webexercises helper files to bookdown
#'
#'
#' Adds the necessary helper files to an existing bookdown project and
#' edits the _output.yml and _bookdown.yml files accordingly. If the
#' directory does not have a bookdown project in it, a template
#' project will be set up.
#'
#' @param bookdown_dir The base directory for your bookdown project
#'
#' @param include_dir The directory where you want to put the css and
#' js files (defaults to "include")
#'
#' @param script_dir The directory where you want to put the .R script
#' (defaults to "R")
#'
#' @param output_format The bookdown format you want to add
#' webexercises to (defaults to "bs4_book") This is typically your
#' default HTML format in the _output.yml file.
#'
#' @param render Whether to render the book after updating (defaults to FALSE).
#'
#' @return No return value, called for side effects.
#' @export
#'
add_to_bookdown <- function(bookdown_dir = ".",
include_dir = "include",
add_to_bookdown <- function(bookdown_dir = ".",
include_dir = "include",
script_dir = "R",
output_format = c("bs4_book",
"gitbook",
"html_book",
output_format = c("bs4_book",
"gitbook",
"html_book",
"tufte_html_book"),

render = FALSE) {
# check inputs
if (bookdown_dir == "") bookdown_dir <- "."
if (include_dir == "") include_dir <- "."
if (script_dir == "") script_dir <- "."
output_format <- paste0("bookdown::", match.arg(output_format))

# get helper files
css <- system.file("reports/default/webex.css", package = "webexercises")
js <- system.file("reports/default/webex.js", package = "webexercises")
script <- system.file("reports/default/webex.R", package = "webexercises")
index <- system.file("reports/default/index.Rmd", package = "webexercises")

# make sure include and script directories exist
incdir <- file.path(bookdown_dir, include_dir)
dir.create(path = incdir, showWarnings = FALSE, recursive = TRUE)

rdir <- file.path(bookdown_dir, script_dir)
dir.create(path = rdir, showWarnings = FALSE, recursive = TRUE)

# add or update helper files
file.copy(css, incdir, overwrite = TRUE)
file.copy(js, incdir, overwrite = TRUE)
file.copy(script, rdir, overwrite = TRUE)
message("webex.css, webex.js, and webex.R updated")

# add index file if needed
file.copy(index, bookdown_dir, overwrite = FALSE)

# update or create _output.yml
output_defaults <- list(
"bookdown::bs4_book" = list(
Expand Down Expand Up @@ -98,7 +94,7 @@ add_to_bookdown <- function(bookdown_dir = ".",
toc = FALSE
)
)

output_file <- file.path(bookdown_dir, "_output.yml")
if (!file.exists(output_file)) {
# add new format with reasonable defaults
Expand All @@ -112,21 +108,21 @@ add_to_bookdown <- function(bookdown_dir = ".",
yml[[output_format]] <- output_defaults[[output_format]]
}
}

# get previous values
old_css <- yml[[output_format]]$css
old_js <- yml[[output_format]]$includes$after_body
old_md <- yml[[output_format]]$md_extensions

# merge with new values
yml[[output_format]]$css <- union(old_css, file.path(include_dir, "webex.css"))
yml[[output_format]]$includes$after_body <- union(old_js, file.path(include_dir, "webex.js"))
yml[[output_format]]$md_extensions <- union(old_md, "-smart")

# write to _output.yml
yaml::write_yaml(yml, output_file)
message(output_file, " updated")

# update or create _bookdown.yml
bookdown_file <- file.path(bookdown_dir, "_bookdown.yml")
if (file.exists(bookdown_file)) {
Expand All @@ -138,14 +134,14 @@ add_to_bookdown <- function(bookdown_dir = ".",
output_dir = "docs",
delete_merged_file = "yes")
}

# get previous values
old_bcs <- yml$before_chapter_script
yml$before_chapter_script <- union(old_bcs, file.path(script_dir, "webex.R"))
# write to _bookdown.yml
yaml::write_yaml(yml, bookdown_file)
message(bookdown_file, " updated")

# render and open site
if (isTRUE(render)) {
if (!requireNamespace("bookdown", quietly = TRUE)) {
Expand All @@ -156,12 +152,12 @@ add_to_bookdown <- function(bookdown_dir = ".",
stop("Package \"xfun\" needed for this function to work. Please install it.",
call. = FALSE)
}

local_path <- xfun::in_dir(bookdown_dir, bookdown::render_book(
input = "index.Rmd",
input = "index.Rmd",
output_format = output_format
))

utils::browseURL(local_path)
}

Expand Down
95 changes: 95 additions & 0 deletions R/add_to_quarto.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#' Add webexercises helper files to quarto
#'
#' Adds the necessary helper files to an existing quarto project and
#' edits the _quarto.yml file accordingly. A demo file for webexercises
#' will be added and optionally rendered.
#'
#' @param quarto_dir The base directory for your quarto project
#' @param include_dir The directory where you want to put the css and
#' js files (defaults to "include")
#' @param output_format The format you want to add
#' webexercises to (only html for now)
#'
#' @return No return value, called for side effects.
#' @export
#'
add_to_quarto <- function(quarto_dir = ".",
include_dir = "include",
output_format = c("html")) {
# check inputs
if (quarto_dir == "") quarto_dir <- "."
if (include_dir == "") include_dir <- "."
output_format <- match.arg(output_format)

# get helper files
css <- system.file("reports/default/webex.css", package = "webexercises")
js <- system.file("reports/default/webex.js", package = "webexercises")
demo <- system.file("reports/default/webexercises.qmd", package = "webexercises")

# make sure include and script directories exist
incdir <- file.path(quarto_dir, include_dir)
dir.create(path = incdir, showWarnings = FALSE, recursive = TRUE)

# add or update helper files
file.copy(css, incdir, overwrite = TRUE)
file.copy(js, incdir, overwrite = TRUE)
file.copy(demo, quarto_dir, overwrite = TRUE)
message("webex.css, webex.js, and webexercises.qmd updated")

# update or create _quarto.yml
css_path <- file.path(include_dir, "webex.css")
js_path <- file.path(include_dir, "webex.js")
quarto_defaults <- list(
"html" = list(
"css" = css_path,
"include-after-body" = js_path
)
)

quarto_file <- file.path(quarto_dir, "_quarto.yml")
if (!file.exists(quarto_file)) {
# add new format with reasonable defaults
yml <- list()
yml[[output_format]] <- quarto_defaults[[output_format]]
} else {
# keep default yml
yml <- yaml::read_yaml(quarto_file)
if ( !is.list(yml$format) || !"format" %in% names(yml)) {
yml$format <- list()
}

if (!output_format %in% names(yml$format)) {
# append output_format
yml$format[[output_format]] <- quarto_defaults[[output_format]]
}
}

# get previous values
old_css <- yml$format[[output_format]]$css
old_js <- yml$format[[output_format]]$`include-after-body`

# merge with new values
yml$format[[output_format]]$css <- union(old_css, css_path)
yml$format[[output_format]]$`include-after-body` <- union(old_js, js_path)

# write to _quarto.yml
# custom handler to stop converting boolean values to yes and no
yaml::write_yaml(yml, quarto_file, handlers = list(
logical = function(x) {
result <- ifelse(x, "true", "false")
class(result) <- "verbatim"
return(result)
}
))
message(quarto_file, " updated")

# update .Rprofile
rprofile <- file.path(quarto_dir, ".Rprofile")

load_txt <- "# load webexercises before each chapter
# needs to check namespace to not bork github actions
if (requireNamespace('webexercises', quietly = TRUE)) library(webexercises)"
write(load_txt, rprofile, append = TRUE)

invisible(NULL)
}
28 changes: 28 additions & 0 deletions R/quarto.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#' Create a quarto document with webexercise
#'
#' Creates a new directory with the file name and copies in a demo qmd file and the necessary helper files.
#'
#' @param name Name of the new document
#' @param open Whether to open the document in RStudio
#'
#' @return The file path to the document
#' @export
#'
create_quarto_doc <- function(name = "Untitled", open = interactive()) {
if (!file.exists(name)) dir.create(name, FALSE, TRUE)
path <- normalizePath(name)
filepath <- file.path(path, paste0(basename(name), ".qmd"))

# get helper files
css <- system.file("reports/default/webex.css", package = "webexercises")
js <- system.file("reports/default/webex.js", package = "webexercises")
index <- system.file("reports/default/index.qmd", package = "webexercises")

file.copy(css, path)
file.copy(js, path)
file.copy(index, filepath)

if (open) rstudioapi::documentOpen(filepath)

invisible(filepath)
}
31 changes: 19 additions & 12 deletions R/webexercises_default.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
#' @details Call this function as the \code{output_format} argument
#' for the \code{\link[rmarkdown]{render}} function when compiling
#' HTML documents from RMarkdown source.
#'
#'
#' @param ... Additional function arguments to pass to
#' \code{\link[rmarkdown]{html_document}}.
#'
#' @return R Markdown output format to pass to 'render'.
#'
#'
#' @seealso \code{\link[rmarkdown]{render}}, \code{\link[rmarkdown]{html_document}}
#'
#'
#' @examples
#' # copy the webexercises 'R Markdown' template to a temporary file
#' \dontrun{
Expand All @@ -23,7 +23,7 @@
#'
#' # compile it
#' rmarkdown::render(my_rmd, webexercises::webexercises_default())
#'
#'
#' # view the result
#' browseURL(sub("\\.Rmd$", ".html", my_rmd))
#' }
Expand All @@ -32,6 +32,19 @@ webexercises_default <- function(...) {
css <- system.file("reports/default/webex.css", package = "webexercises")
js <- system.file("reports/default/webex.js", package = "webexercises")

setup_hide_knithook()

# smart quotes changed in rmarkdown 2.2 / pandoc 2.0.6
rmarkdown::pandoc_available(version = "2.0.6", error = TRUE)

rmarkdown::html_document(css = css,
includes = rmarkdown::includes(after_body = js),
md_extensions = "-smart",
...)
}


setup_hide_knithook <- function() {
knitr::knit_hooks$set(webex.hide = function(before, options, envir) {
if (before) {
if (is.character(options$webex.hide)) {
Expand All @@ -43,12 +56,6 @@ webexercises_default <- function(...) {
unhide()
}
})

# smart quotes changed in rmarkdown 2.2 / pandoc 2.0.6
rmarkdown::pandoc_available(version = "2.0.6", error = TRUE)

rmarkdown::html_document(css = css,
includes = rmarkdown::includes(after_body = js),
md_extensions = "-smart",
...)

invisible()
}
Loading

0 comments on commit f48b8d2

Please sign in to comment.