Skip to content

Commit

Permalink
Merge pull request #297 from carpentries/add-markdown-creation
Browse files Browse the repository at this point in the history
add markdown support for create_*() functions
  • Loading branch information
zkamvar authored Jun 10, 2022
2 parents a699171 + 6a9a19c commit 14e7cbc
Show file tree
Hide file tree
Showing 19 changed files with 139 additions and 73 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: sandpaper
Title: Create and Curate Carpentries Lessons
Version: 0.5.9
Version: 0.6.0
Authors@R: c(
person(given = "Zhian N.",
family = "Kamvar",
Expand Down
3 changes: 2 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ export(build_episode_html)
export(build_episode_md)
export(build_handout)
export(build_lesson)
export(check_episode)
export(check_lesson)
export(create_episode)
export(create_episode_md)
export(create_episode_rmd)
export(create_lesson)
export(get_config)
export(get_drafts)
Expand Down
21 changes: 19 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
# sandpaper 0.5.9
# sandpaper 0.6.0

NEW FEATURES
------------

* `create_lesson()` gains the `rmd` parameter, which is a logical indicator that
the lesson should use R Markdown (`TRUE` by default). When this is `FALSE`, a
markdown lesson is created and no package cache is initialised.
* `create_episode()` gains the `ext` parameter, which allows users to create
plain markdown episodes if they do not need R Markdown functionality
(see https://github.com/carpentries/sandpaper/issues/296).

BUG FIX
-------

* `create_episode()` will now slugify titles so that they only contain lowercase
ASCII letters, numbers and UTF-8 characters with words separated by single
hyphens. (see https://github.com/carpentries/sandpaper/issues/294)
hyphens (see https://github.com/carpentries/sandpaper/issues/294).

MISC
----

* The internal `check_episode()` function has been removed as it was over-
engineered with marginal value.



# sandpaper 0.5.8
Expand Down
24 changes: 0 additions & 24 deletions R/check_episode.R

This file was deleted.

25 changes: 21 additions & 4 deletions R/create_episode.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#' Create an Episode from a template
#'
#' @param title the title of the episode
#' @param ext a character. If `ext = "Rmd"` (default), then the new episode will
#' be an R Markdown episode. If `ext = "md"`, then the new episode will be
#' a markdown episode, which can not generate dynamic content.
#' @param make_prefix a logical. If `TRUE`, the prefix for the file will be
#' automatically determined by the files already present. Otherwise, it assumes
#' you have added the prefix.
Expand All @@ -10,9 +13,10 @@
#' @examples
#' tmp <- tempfile()
#' create_lesson(tmp)
#' create_episode("getting-started", path = tmp)
create_episode <- function(title, make_prefix = TRUE, add = FALSE, path = ".") {
#' create_episode_md("getting-started", path = tmp)
create_episode <- function(title, ext = "Rmd", make_prefix = TRUE, add = FALSE, path = ".") {
check_lesson(path)
ext <- switch(match.arg(tolower(ext), c("rmd", "md")), rmd = ".Rmd", md = ".md")
prefix <- ""
if (make_prefix) {
episodes <- fs::path_file(fs::dir_ls(path_episodes(path), regexp = "*.[Rr]?md"))
Expand All @@ -21,11 +25,24 @@ create_episode <- function(title, make_prefix = TRUE, add = FALSE, path = ".") {
prefix <- if (no_prefix) "01-" else sprintf("%02d-", max(prefix, na.rm = TRUE) + 1L)
}
slug <- slugify(title)
ename <- paste0(prefix, slug, ".Rmd")
copy_template("episode", fs::path(path, "episodes"), ename, list(title = siQuote(title)))
ename <- paste0(prefix, slug, ext)
copy_template("episode", fs::path(path, "episodes"), ename,
values = list(title = siQuote(title), md = ext == ".md"))
if (add) {
suppressWarnings(sched <- get_episodes(path))
set_episodes(path, c(sched, ename), write = TRUE)
}
invisible(fs::path(path, "episodes", ename))
}

#' @export
#' @rdname create_episode
create_episode_md <- function(title, make_prefix = TRUE, add = FALSE, path = ".") {
create_episode(title, ext = "md", make_prefix = make_prefix, add = add, path = path)
}

#' @export
#' @rdname create_episode
create_episode_rmd <- function(title, make_prefix = TRUE, add = FALSE, path = ".") {
create_episode(title, ext = "Rmd", make_prefix = make_prefix, add = add, path = path)
}
10 changes: 7 additions & 3 deletions R/create_lesson.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
#'
#' @param path the path to the new lesson folder
#' @param name the name of the lesson. If not provided, the folder name will be used.
#' @param rmd logical indicator if the lesson should use R Markdown (`TRUE`,
#' default), or if it should use Markdown (`FALSE`). Note that lessons can be
#' converted to use R Markdown at any time by adding a file with the `.Rmd`
#' file extension in the lesson.
#' @param rstudio create an RStudio project (defaults to if RStudio exits)
#' @param open if interactive, the lesson will open in a new editor window.
#'
Expand All @@ -15,7 +19,7 @@
#' on.exit(unlink(tmp))
#' lsn <- create_lesson(tmp, name = "This Lesson", open = FALSE)
#' lsn
create_lesson <- function(path, name = fs::path_file(path), rstudio = rstudioapi::isAvailable(), open = rlang::is_interactive()) {
create_lesson <- function(path, name = fs::path_file(path), rmd = TRUE, rstudio = rstudioapi::isAvailable(), open = rlang::is_interactive()) {

path <- fs::path_abs(path)
id <- cli::cli_status("{cli::symbol$arrow_right} Creating Lesson in {.file {path}}...")
Expand Down Expand Up @@ -63,7 +67,7 @@ create_lesson <- function(path, name = fs::path_file(path), rstudio = rstudioapi
create_site(path)

cli::cli_status_update("{cli::symbol$arrow_right} Creating first episode ...")
ep <- create_episode("introduction", path = path)
ep <- create_episode("introduction", ext = if (rmd) "Rmd" else "md", path = path)
cli::cli_alert_success("First episode created in {.file {ep}}")

if (rstudio) {
Expand All @@ -76,7 +80,7 @@ create_lesson <- function(path, name = fs::path_file(path), rstudio = rstudioapi
cli::cli_status_update("{cli::symbol$arrow_right} Inserting GitHub workflows ...")
update_github_workflows(path)

has_consent <- getOption("sandpaper.use_renv")
has_consent <- rmd && getOption("sandpaper.use_renv")
if (has_consent) {
cli::cli_status_update("{cli::symbol$arrow_right} Managing Dependencies ...")
manage_deps(path, snapshot = TRUE)
Expand Down
16 changes: 14 additions & 2 deletions R/template.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,25 @@ generate_template_function <- function(f) {
}
#nocov end

# copy template on disk
#' copy a sandpaper template file to a path with data
#'
#' @param template the base of a valid template function (e.g. "episode" for
#' [template_episode()])
#' @param path the folder in which to write the file. Defaults to `NULL`, which
#' will return the filled template as a character vector
#' @param name the name of the file. Defaults to `NULL`
#' @param values the values to fill in the template (if any). Consult the
#' files in the `templates/` folder of your sandpaper installation for details.
#' @return a character vector if `path` or `name` is `NULL`, otherwise, this is
#' used for its side effect of creating a file.
#' @keywords internal
copy_template <- function(template, path = NULL, name = NULL, values = NULL) {
template <- eval(parse(text = paste0("template_", template, "()")))
out <- if (is.null(path)) NULL else fs::path(path, name)
if (!is.null(values)) {
temp <- readLines(template, encoding = "UTF-8")
res <- whisker::whisker.render(template = temp, data = values)
if (length(out)) writeLines(res, out) else return(out)
if (length(out)) writeLines(res, out) else return(res)
} else {
fs::file_copy(template, new_path = fs::path(path, name))
}
Expand All @@ -29,6 +40,7 @@ copy_template <- function(template, path = NULL, name = NULL, values = NULL) {
#'
#' @rdname template
#' @export
#' @keywords internal
#' @return a character string with the path to the template within the
#' {sandpaper} repo.
#' @examples
Expand Down
8 changes: 0 additions & 8 deletions R/validators.R
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,6 @@ assertthat::on_failure(check_gitignore) <- function(call, env) {
)
}

## lesson name validator -------------------------------------------------------
check_episode_name <- function(path) {
grepl("^[0-9]{2}[-]", fs::path_file(path))
}
assertthat::on_failure(check_episode_name) <- function(call, env) {
paste0("The file '", eval(call$path, env), "' must start with a two-digit number")
}

# reporting of validators ------------------------------------------------------
report_validation <- function(checklist, msg = "There were errors") {
errs <- Filter(Negate(isTRUE), checklist)
Expand Down
3 changes: 3 additions & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,7 @@ articles:
- articles/landscape
- articles/deployment
- articles/toolchain
- title: "In Progress"
contents:
- articles/internationalisation

12 changes: 6 additions & 6 deletions inst/templates/episode-template.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ exercises: 2
## Introduction

This is a lesson created via The Carpentries Workbench. It is written in
[Pandoc-flavored Markdown][pandoc] for static files and
[R Markdown][r-markdown] for dynamic files that can render code into output.
Please refer to the [Introduction to The Carpentries
[Pandoc-flavored Markdown][pandoc] for static files (with extension `.md`) and
[R Markdown][r-markdown] for dynamic files that can render code into output
(with extension `.Rmd`). Please refer to the [Introduction to The Carpentries
Workbench][carpentries-workbench] for full documentation.

What you need to know is that there are three sections required for a valid
Expand Down Expand Up @@ -74,7 +74,8 @@ You can add a line with at least three colons and a `solution` tag.

## Figures

You can also include figures generated from R Markdown:
{{^md}}
You can include figures generated from R Markdown:

```{r pyramid, fig.alt = "pie chart illusion of a pyramid", fig.cap = "Sun arise each and every morning"}
pie(
Expand All @@ -84,8 +85,7 @@ pie(
border = FALSE
)
```

Or you can use standard markdown for static figures with the following syntax:
Or you{{/md}}{{#md}}You{{/md}} can use pandoc markdown for static figures with the following syntax:

`![optional caption that appears below the figure](figure url){alt='alt text for
accessibility purposes'}`
Expand Down
7 changes: 2 additions & 5 deletions man/check_lesson.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions man/copy_template.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 12 additions & 2 deletions man/create_episode.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions man/create_lesson.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/template.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tests/testthat/test-build_lesson.R
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ if (rmarkdown::pandoc_available("2.11")) {
pkg <- pkgdown::as_pkgdown(fs::path_dir(sitepath))

test_that("build_lesson() also builds the extra pages", {
skip_if_not(rmarkdown::pandoc_available("2.11"))
expect_true(fs::dir_exists(sitepath))
expect_true(fs::file_exists(fs::path(sitepath, "instructor-notes.html")))
expect_true(fs::file_exists(fs::path(sitepath, "instructor", "instructor-notes.html")))
Expand Down
Loading

0 comments on commit 14e7cbc

Please sign in to comment.