diff --git a/DESCRIPTION b/DESCRIPTION
index 21724330..759aebe8 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -7,7 +7,8 @@ Authors@R: c(
comment = c(ORCID = "0000-0003-3925-190X")),
person("Joe", "Cheng", role = "aut", email = "joe@rstudio.com"),
person("Jeroen", "Ooms", role = "ctb", email = "jeroen@berkeley.edu",
- comment = c(ORCID = "0000-0002-4035-0289"))
+ comment = c(ORCID = "0000-0002-4035-0289")),
+ person("Salim", "Brüggemann", role = "ctb", email = "salim-b@pm.me")
)
Description: Compose and send out responsive HTML email messages that render
perfectly across a range of email clients and device sizes. Helper functions
@@ -32,10 +33,12 @@ Imports:
jsonlite (>= 1.6),
magrittr (>= 1.5),
mime (>= 0.6),
+ processx (>= 3.4.1),
rlang (>= 0.4.1),
rmarkdown,
stringr (>= 1.4.0),
- uuid (>= 0.1-2)
+ uuid (>= 0.1-2),
+ xfun (>= 0.11)
Suggests:
covr,
ggplot2,
@@ -48,7 +51,7 @@ Suggests:
SystemRequirements: pandoc (>= 1.12.3) - http://pandoc.org
Encoding: UTF-8
LazyData: true
-RoxygenNote: 6.1.1
+RoxygenNote: 7.0.2
Roxygen: list(markdown = TRUE)
VignetteBuilder: knitr
Language: en-US
diff --git a/NAMESPACE b/NAMESPACE
index c17ee376..e10dc56b 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -28,6 +28,7 @@ export(creds_file)
export(creds_key)
export(get_html_str)
export(md)
+export(minify)
export(prepare_rsc_example_files)
export(prepare_test_message)
export(render_connect_email)
diff --git a/R/minify.R b/R/minify.R
new file mode 100644
index 00000000..90adb45b
--- /dev/null
+++ b/R/minify.R
@@ -0,0 +1,166 @@
+#' Minify an email
+#'
+#' Minify a blastula `email_message` object.
+#'
+#' The [minification](https://en.wikipedia.org/wiki/Minification_(programming))
+#' relies on the binary
+#' [**minify**](https://github.com/tdewolff/minify/tree/master/cmd/minify)
+#' which is cross-platform and works on Windows, macOS, Linux and BSD.
+#' Pre-built binaries can be downloaded from
+#' [here](https://github.com/tdewolff/minify/releases). Alternatively,
+#' instructions to build minify from source are available
+#' [here](https://github.com/tdewolff/minify/tree/master/cmd/minify#installation).
+#'
+#' @param email The email message object, as created by the [compose_email()]
+#' function. The object's class is `email_message`.
+#' @param binary_loc An option to supply the location of the `minify`
+#' binary file should it not be on the system path or in the working
+#' directory.
+#' @param minify_opts A list of additional options to pass to the `minify` CLI
+#' command. Only the following sensible subset of
+#' [all possible minify options](https://github.com/tdewolff/minify/tree/master/cmd/minify#usage)
+#' is supported, listed with their default values:
+#' - \code{`html-keep-conditional-comments` = FALSE}: Preserve all IE conditional comments
+#' - \code{`html-keep-default-attrvals` = FALSE}: Preserve default attribute values
+#' - \code{`html-keep-document-tags` = FALSE}: Preserve ``, `
` and `` tags
+#' - \code{`html-keep-end-tags` = FALSE}: Preserve all end tags
+#' - \code{`html-keep-quotes` = FALSE}: Preserve quotes around attribute values
+#' - \code{`html-keep-whitespace` = FALSE}: Preserve whitespace characters but still collapse multiple into one
+#' - \code{`css-decimals` = -1L}: Number of decimals to preserve in CSS numbers,
+#' `-1L` means all
+#' - \code{`svg-decimals` = -1L}: Number of decimals to preserve in SVG numbers,
+#' `-1L` means all
+#' - `verbose = FALSE`: Print informative messages about minification details.
+#' @param echo If set to `TRUE`, the command to minify the `email_message`
+#' object's HTML via `minify` will be printed to the console. By default,
+#' this is `FALSE`.
+#'
+#' @examples
+#' \donttest{# Create a simple test email
+#' test_mail <- prepare_test_message()
+#'
+#' # Minify the test email
+#' minify(test_mail)
+#'
+#' # The command used to minify can be printed
+#' minify(email = test_mail,
+#' echo = TRUE)
+#'
+#' # We can also provide options to the
+#' # underlying minify command
+#' minify(email = test_mail,
+#' minify_opts = list(`html-keep-conditional-comments` = TRUE,
+#' `html-keep-default-attrvals` = TRUE,
+#' verbose = TRUE),
+#' echo = TRUE)
+#' }
+#'
+#' @return An `email_message` object.
+#' @export
+minify <- function(email,
+ binary_loc = NULL,
+ minify_opts = NULL,
+ echo = FALSE) {
+
+ # Verify that the `email` object
+ # is of the class `email_message`
+ if (!inherits(email, "email_message")) {
+ stop("The object provided in `email` must be an ",
+ "`email_message` object.\n",
+ " * This can be created with the `compose_email()` function.",
+ call. = FALSE)
+ }
+
+ # Determine the location of the `minify` binary
+ if (is.null(binary_loc)) {
+ binary_loc <- find_binary("minify")
+ if (is.null(binary_loc)) {
+ stop("The binary file `minify` is not in the system path or \n",
+ "in the working directory:\n",
+ " * download a pre-built binary from https://github.com/tdewolff/minify/releases\n",
+ " * or follow the installation instructions at https://github.com/tdewolff/minify/tree/master/cmd/minify#installation",
+ call. = FALSE)
+ }
+ }
+
+ # Ensure provided minify options are valid
+ # and collect arguments and options for for `processx::run()` as a list
+ run_args <- character(0)
+
+ if (!is.null(minify_opts)) {
+ binary_opts <-
+ c("html-keep-conditional-comments",
+ "html-keep-default-attrvals",
+ "html-keep-document-tags",
+ "html-keep-end-tags",
+ "html-keep-quotes",
+ "html-keep-whitespace",
+ "verbose") %>%
+ intersect(y = names(minify_opts))
+
+ int_opts <-
+ c("css-decimals",
+ "svg-decimals") %>%
+ intersect(y = names(minify_opts))
+
+ invalid_opts_i <- which(
+ !(names(minify_opts) %in% c(binary_opts, int_opts))
+ )
+
+ if (length(invalid_opts_i) > 0) {
+ stop("Unknown options provided in `minify_opts`: ", names(minify_opts[invalid_opts_i]),
+ call. = FALSE)
+ }
+
+ if (length(binary_opts) > 0) {
+ invalid_opts_i <- which(
+ names(minify_opts) %in% binary_opts & !sapply(minify_opts[binary_opts], is.logical)
+ )
+
+ if (length(invalid_opts_i) > 0) {
+ stop("The following `minify_opts` must be of type logical: ",
+ names(minify_opts[invalid_opts_i]),
+ call. = FALSE)
+ }
+
+ run_args <- c(names(minify_opts[sapply(minify_opts, isTRUE)])) %>% paste0("--", .)
+ }
+
+ if (length(int_opts) > 0) {
+ minify_opts[int_opts] <- as.integer(minify_opts[int_opts])
+
+ invalid_opts_i <-
+ names(minify_opts) %in% int_opts %>%
+ magrittr::and(!sapply(minify_opts[int_opts],
+ function(x) x >= -1L)) %>%
+ which()
+
+ if (length(invalid_opts_i) > 0) {
+ stop("The following `minify_opts` must be >= -1: ", names(minify_opts[invalid_opts_i]),
+ call. = FALSE)
+ }
+
+ run_args <- minify_opts[int_opts] %>% paste0(names(.), "=", .)
+ }
+ }
+
+ # Write the inlined HTML message out to a file
+ # and remove the file after the function exits
+ tempfile_ <- tempfile(fileext = ".html") %>% tidy_gsub("\\\\", "/")
+ email$html_str %>% writeLines(con = tempfile_, useBytes = TRUE)
+ on.exit(file.remove(tempfile_))
+
+ # add input and file type
+ run_args <- c("--type=html", run_args, tempfile_)
+
+ # Minify via `processx::run()` and assign the result
+ minify_result <- processx::run(command = binary_loc,
+ args = run_args,
+ echo_cmd = echo,
+ timeout = 60L)
+
+ if (isTRUE(minify_opts$verbose)) message(minify_result$stderr)
+
+ email$html_str <- minify_result$stdout
+ email
+}
diff --git a/R/utils.R b/R/utils.R
index e0e8d242..daba7198 100644
--- a/R/utils.R
+++ b/R/utils.R
@@ -101,6 +101,66 @@ imgur_upload <- function(file, client_id) {
)
}
+#' An upgraded version of `Sys.which()` that returns a better Windows path
+#'
+#' @param name A single-length character vector with the executable name.
+#' @noRd
+sys_which <- function(name) {
+
+ # Only accept a vector of length 1
+ stopifnot(length(name) == 1)
+
+ # Get the
+ if (xfun::is_windows()) {
+
+ suppressWarnings({
+ pathname <-
+ system(sprintf("where %s 2> NUL", name), intern = TRUE)[1]
+ })
+
+ if (!is.na(pathname)) {
+
+ pathname <- pathname %>% tidy_gsub("\\\\", "/")
+
+ return(stats::setNames(pathname, name))
+ }
+ }
+
+ Sys.which(name) %>% tidy_gsub("\\\\", "/")
+}
+
+#' Find a binary on the system path or working directory
+#'
+#' @param bin_name The name of the binary to search for.
+#' @noRd
+find_binary <- function(bin_name) {
+
+ # Find binary on path with `sys_which()`
+ which_result <- sys_which(name = bin_name) %>% unname()
+
+ if (which_result != "") {
+ return(which_result)
+ }
+
+ # Try to locate the binary in working directory
+ which_result <-
+ tryCatch(
+ {
+ processx::run(command = "ls", args = bin_name)
+ file.path(getwd(), bin_name)
+ },
+ error = function(cond) ""
+ )
+
+ if (which_result != "") {
+ return(which_result)
+ }
+
+ # If the binary isn't found in these locations,
+ # return `NULL`
+ NULL
+}
+
# nocov end
#' Prepend a element to a list at a given position
diff --git a/man/add_attachment.Rd b/man/add_attachment.Rd
index dd568a1f..b513995d 100644
--- a/man/add_attachment.Rd
+++ b/man/add_attachment.Rd
@@ -4,8 +4,12 @@
\alias{add_attachment}
\title{Add a file attachment to an email message}
\usage{
-add_attachment(email, file, content_type = mime::guess_type(file),
- filename = basename(file))
+add_attachment(
+ email,
+ file,
+ content_type = mime::guess_type(file),
+ filename = basename(file)
+)
}
\arguments{
\item{email}{The email message object, as created by the \code{\link[=compose_email]{compose_email()}}
diff --git a/man/add_ggplot.Rd b/man/add_ggplot.Rd
index 8c64e547..77c281aa 100644
--- a/man/add_ggplot.Rd
+++ b/man/add_ggplot.Rd
@@ -14,7 +14,7 @@ add_ggplot(plot_object, width = 5, height = 5, alt = NULL)
\item{height}{The height of the output plot in inches.}
\item{alt}{Text description of image passed to the \code{alt} attribute inside of
-the image (\code{
}) tag for use when image loading is disabled and on
+the image (\verb{
}) tag for use when image loading is disabled and on
screen readers. Defaults to the \code{ggplot2} plot object's title, if exists.
Override by passing a custom character string or \code{""} for no text.}
}
@@ -52,7 +52,7 @@ email <-
"Hello!
Here is a plot that will change
-the way you look at cars forever.\\n",
+the way you look at cars forever.\n",
plot_html,
"Let me know what you think
about it!"
diff --git a/man/add_image.Rd b/man/add_image.Rd
index 4b6a506b..2623eeff 100644
--- a/man/add_image.Rd
+++ b/man/add_image.Rd
@@ -10,7 +10,7 @@ add_image(file, alt = NULL)
\item{file}{A path to an image file.}
\item{alt}{Text description of image passed to the \code{alt} attribute inside of
-the image (\code{
}) tag for use when image loading is disabled and on
+the image (\verb{
}) tag for use when image loading is disabled and on
screen readers. \code{NULL} default produces blank (\code{""}) alt text.}
}
\value{
@@ -42,7 +42,7 @@ email <-
c(
"Hello,
-Here is an image:\\n",
+Here is an image:\n",
img_file_html
)
)
diff --git a/man/add_imgur_image.Rd b/man/add_imgur_image.Rd
index bc244ca3..d5d9e86c 100644
--- a/man/add_imgur_image.Rd
+++ b/man/add_imgur_image.Rd
@@ -13,7 +13,7 @@ for which we'd like an image tag.}
\item{client_id}{The Imgur Client ID value.}
\item{alt}{Text description of image passed to the \code{alt} attribute inside of
-the image (\code{
}) tag for use when image loading is disabled and on
+the image (\verb{
}) tag for use when image loading is disabled and on
screen readers. \code{NULL} default produces blank (\code{""}) alt text.}
}
\value{
@@ -26,13 +26,13 @@ the recipient) can be a harrowing experience. External images (i.e.,
available at public URLs) work exceedingly well and most email clients will
faithfully display these images. With the \code{imgur_image()} function, we can
take a local image file or a \code{ggplot2} plot object and send it to the Imgur
-service, and finally receive an image (\code{
}) tag that can be directly
+service, and finally receive an image (\verb{
}) tag that can be directly
inserted into an email message using \code{compose_email()}.
}
\details{
To take advantage of this, we need to first have an account with Imgur and
then obtain a \code{Client-ID} key for the Imgur API. This can be easily done by
-going to \code{https://api.imgur.com/oauth2/addclient} and registering an
+going to \verb{https://api.imgur.com/oauth2/addclient} and registering an
application. Be sure to select the OAuth 2 authorization type without a
callback URL.
}
diff --git a/man/add_readable_time.Rd b/man/add_readable_time.Rd
index ef6c0b7a..d817ea63 100644
--- a/man/add_readable_time.Rd
+++ b/man/add_readable_time.Rd
@@ -4,8 +4,7 @@
\alias{add_readable_time}
\title{Create a string with a more readable date/time}
\usage{
-add_readable_time(time = NULL, use_date = TRUE, use_time = TRUE,
- use_tz = TRUE)
+add_readable_time(time = NULL, use_date = TRUE, use_time = TRUE, use_tz = TRUE)
}
\arguments{
\item{time}{The \code{POSIXct} time to use, and to make more readable for email
diff --git a/man/attach_connect_email.Rd b/man/attach_connect_email.Rd
index 31e187a1..dac1c50a 100644
--- a/man/attach_connect_email.Rd
+++ b/man/attach_connect_email.Rd
@@ -4,9 +4,14 @@
\alias{attach_connect_email}
\title{Associate an email when publishing an R Markdown document to RStudio Connect}
\usage{
-attach_connect_email(email = NULL, subject = NULL,
- attachments = NULL, attach_output = FALSE, text = NULL,
- preview = TRUE)
+attach_connect_email(
+ email = NULL,
+ subject = NULL,
+ attachments = NULL,
+ attach_output = FALSE,
+ text = NULL,
+ preview = TRUE
+)
}
\arguments{
\item{email}{A rendered email message. Normally, we'd want to use an
diff --git a/man/blastula_email.Rd b/man/blastula_email.Rd
index 4bb8b77d..5c436726 100644
--- a/man/blastula_email.Rd
+++ b/man/blastula_email.Rd
@@ -4,12 +4,26 @@
\alias{blastula_email}
\title{The R Markdown \code{blastula_email} output format}
\usage{
-blastula_email(toc = FALSE, toc_depth = 3, toc_float = FALSE,
- number_sections = FALSE, section_divs = TRUE, fig_width = 5.35,
- fig_height = 5, fig_retina = 2, fig_caption = TRUE, dev = "png",
- smart = TRUE, self_contained = TRUE, template = "blastula",
- includes = NULL, keep_md = FALSE, md_extensions = NULL,
- connect_footer = FALSE, ...)
+blastula_email(
+ toc = FALSE,
+ toc_depth = 3,
+ toc_float = FALSE,
+ number_sections = FALSE,
+ section_divs = TRUE,
+ fig_width = 5.35,
+ fig_height = 5,
+ fig_retina = 2,
+ fig_caption = TRUE,
+ dev = "png",
+ smart = TRUE,
+ self_contained = TRUE,
+ template = "blastula",
+ includes = NULL,
+ keep_md = FALSE,
+ md_extensions = NULL,
+ connect_footer = FALSE,
+ ...
+)
}
\arguments{
\item{toc}{If you would like an automatically-generated table of contents in
@@ -25,8 +39,8 @@ main document content. By default, this is \code{FALSE}.}
\item{number_sections}{Sections can be sequentially numbered if this is set
to \code{TRUE}. By default, this is \code{FALSE}.}
-\item{section_divs}{This wraps sections in \code{} tags and attaches
-identifiers to the enclosing \code{}s. This is set to \code{TRUE}.}
+\item{section_divs}{This wraps sections in \verb{} tags and attaches
+identifiers to the enclosing \verb{}s. This is set to \code{TRUE}.}
\item{fig_width, fig_height}{The figure width and height in units of inches.}
@@ -42,7 +56,7 @@ this is set to \code{TRUE}.}
device.}
\item{smart}{An option to produce typographically correct output. This will
-convert straight quotes to curly quotes, \code{---} to em dashes, \code{--} to en
+convert straight quotes to curly quotes, \verb{---} to em dashes, \verb{--} to en
dashes, and instances of \code{...} to ellipses. By default, this is \code{TRUE}.}
\item{self_contained}{Should a self-contained output file be generated. By
diff --git a/man/block_articles.Rd b/man/block_articles.Rd
index 3d0cef13..10eda349 100644
--- a/man/block_articles.Rd
+++ b/man/block_articles.Rd
@@ -14,7 +14,7 @@ With \code{block_articles()}, we can create a single- or multi-column layout of
articles. The articles are responsive to the screen width, so side-by-side
articles will collapse and any of the optional images will resize
accordingly. The function can accept one to three \code{article()} calls, each
-with varying amounts of text and imagery. Like all \code{block_*()} functions,
+with varying amounts of text and imagery. Like all \verb{block_*()} functions,
\code{block_articles()} must be placed inside of \code{blocks()} and the resultant
\code{blocks} object can be provided to the \code{body}, \code{header}, or \code{footer}
arguments of \code{compose_email()}.
diff --git a/man/block_social_links.Rd b/man/block_social_links.Rd
index 60cfc2c9..2d42cd8b 100644
--- a/man/block_social_links.Rd
+++ b/man/block_social_links.Rd
@@ -12,7 +12,7 @@ block_social_links(...)
\description{
With \code{block_social_links()}, we can create a block of social sharing links
and links to websites, email, or RSS feeds. The function can accept as many
-\code{social_link()} calls as seen fit to email. Like all \code{block_*()} functions,
+\code{social_link()} calls as seen fit to email. Like all \verb{block_*()} functions,
\code{block_social_links()} must be placed inside of \code{blocks()} and the resultant
\code{blocks} object can be provided to the \code{body}, \code{header}, or \code{footer}
arguments of \code{compose_email()}.
diff --git a/man/block_spacer.Rd b/man/block_spacer.Rd
index a937e232..a7b28ec4 100644
--- a/man/block_spacer.Rd
+++ b/man/block_spacer.Rd
@@ -9,7 +9,7 @@ block_spacer()
\description{
With \code{block_spacer()} we can more easily define an area of whitespace in a
block-based layout. This function is meant to be easily combined with other
-\code{block_*()} functions. Like all \code{block_*()} functions, \code{block_spacer()} must
+\verb{block_*()} functions. Like all \verb{block_*()} functions, \code{block_spacer()} must
be placed inside of \code{blocks()} and the resultant \code{blocks} object can be
provided to the \code{body}, \code{header}, or \code{footer} arguments of \code{compose_email()}.
}
diff --git a/man/block_text.Rd b/man/block_text.Rd
index 64287f3b..12f377ad 100644
--- a/man/block_text.Rd
+++ b/man/block_text.Rd
@@ -11,8 +11,8 @@ block_text(text)
}
\description{
With \code{block_text()} we can define a text area and this can be easily combined
-with other \code{block_*()} functions. The text will take the entire width of the
-block and will resize according to screen width. Like all \code{block_*()}
+with other \verb{block_*()} functions. The text will take the entire width of the
+block and will resize according to screen width. Like all \verb{block_*()}
functions, \code{block_text()} must be placed inside of \code{blocks()} and the
resultant \code{blocks} object can be provided to the \code{body}, \code{header}, or
\code{footer} arguments of \code{compose_email()}.
diff --git a/man/block_title.Rd b/man/block_title.Rd
index c1a6cdbe..de6b8e98 100644
--- a/man/block_title.Rd
+++ b/man/block_title.Rd
@@ -11,9 +11,9 @@ block_title(title)
}
\description{
With \code{block_title()} we can define a title text area and this can be easily
-combined with other \code{block_*()} functions. The title will take the entire
+combined with other \verb{block_*()} functions. The title will take the entire
width of the block and will resize according to screen width. Like all
-\code{block_*()} functions, \code{block_title()} must be placed inside of \code{blocks()}
+\verb{block_*()} functions, \code{block_title()} must be placed inside of \code{blocks()}
and the resultant \code{blocks} object can be provided to the \code{body}, \code{header}, or
\code{footer} arguments of \code{compose_email()}.
}
diff --git a/man/blocks.Rd b/man/blocks.Rd
index 465ac4cf..9f1c0e16 100644
--- a/man/blocks.Rd
+++ b/man/blocks.Rd
@@ -7,10 +7,10 @@
blocks(...)
}
\arguments{
-\item{...}{One or more \code{block_*()} calls.}
+\item{...}{One or more \verb{block_*()} calls.}
}
\description{
-To contain all of the block-based HTML \code{block_*()} calls, we should use
+To contain all of the block-based HTML \verb{block_*()} calls, we should use
the \code{blocks()} function. We can pass the resulting \code{blocks} object to either
of the \code{body}, \code{header}, and \code{footer} arguments of \code{compose_email()}.
}
diff --git a/man/compose_email.Rd b/man/compose_email.Rd
index 6122b909..8e345fed 100644
--- a/man/compose_email.Rd
+++ b/man/compose_email.Rd
@@ -4,14 +4,13 @@
\alias{compose_email}
\title{Create the email message body}
\usage{
-compose_email(body = NULL, header = NULL, footer = NULL,
- title = NULL)
+compose_email(body = NULL, header = NULL, footer = NULL, title = NULL)
}
\arguments{
\item{header, body, footer}{The three layout sections for an email message
(ordered from top to bottom). Markdown text can be supplied to each of
these by using the \code{\link[=md]{md()}} text helper function. Alternatively, we can
-supply a set of \code{block_*()} calls enclosed within the \code{\link[=blocks]{blocks()}} function
+supply a set of \verb{block_*()} calls enclosed within the \code{\link[=blocks]{blocks()}} function
to take advantage of precomposed HTML blocks.}
\item{title}{The title of the email message. This is not the subject but the
diff --git a/man/create_smtp_creds_file.Rd b/man/create_smtp_creds_file.Rd
index 95b83ad2..44afdd12 100644
--- a/man/create_smtp_creds_file.Rd
+++ b/man/create_smtp_creds_file.Rd
@@ -4,8 +4,14 @@
\alias{create_smtp_creds_file}
\title{Store SMTP credentials in a file}
\usage{
-create_smtp_creds_file(file, user = NULL, provider = NULL,
- host = NULL, port = NULL, use_ssl = NULL)
+create_smtp_creds_file(
+ file,
+ user = NULL,
+ provider = NULL,
+ host = NULL,
+ port = NULL,
+ use_ssl = NULL
+)
}
\arguments{
\item{file}{The output filename for the credentials file.}
diff --git a/man/create_smtp_creds_key.Rd b/man/create_smtp_creds_key.Rd
index 8c7f7a39..ac30ee70 100644
--- a/man/create_smtp_creds_key.Rd
+++ b/man/create_smtp_creds_key.Rd
@@ -4,12 +4,18 @@
\alias{create_smtp_creds_key}
\title{Store SMTP credentials in the system's key-value store}
\usage{
-create_smtp_creds_key(id, user = NULL, provider = NULL, host = NULL,
- port = NULL, use_ssl = NULL)
+create_smtp_creds_key(
+ id,
+ user = NULL,
+ provider = NULL,
+ host = NULL,
+ port = NULL,
+ use_ssl = NULL
+)
}
\arguments{
\item{id}{An identifying label for the keyname. The full key name is
-constructed in the following way: \code{blastula-v1-}.}
+constructed in the following way: \verb{blastula-v1-}.}
\item{user}{The username for the email account. Typically, this is the email
address associated with the account.}
diff --git a/man/credential_helpers.Rd b/man/credential_helpers.Rd
index 2a693100..c3c39265 100644
--- a/man/credential_helpers.Rd
+++ b/man/credential_helpers.Rd
@@ -8,11 +8,9 @@
\alias{creds_file}
\title{Helpers for supplying SMTP credentials}
\usage{
-creds(user = NULL, provider = NULL, host = NULL, port = NULL,
- use_ssl = TRUE)
+creds(user = NULL, provider = NULL, host = NULL, port = NULL, use_ssl = TRUE)
-creds_anonymous(provider = NULL, host = NULL, port = NULL,
- use_ssl = TRUE)
+creds_anonymous(provider = NULL, host = NULL, port = NULL, use_ssl = TRUE)
creds_key(id)
diff --git a/man/minify.Rd b/man/minify.Rd
new file mode 100644
index 00000000..0b2f0013
--- /dev/null
+++ b/man/minify.Rd
@@ -0,0 +1,75 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/minify.R
+\name{minify}
+\alias{minify}
+\title{Minify an email}
+\usage{
+minify(email, binary_loc = NULL, minify_opts = NULL, echo = FALSE)
+}
+\arguments{
+\item{email}{The email message object, as created by the \code{\link[=compose_email]{compose_email()}}
+function. The object's class is \code{email_message}.}
+
+\item{binary_loc}{An option to supply the location of the \code{minify}
+binary file should it not be on the system path or in the working
+directory.}
+
+\item{minify_opts}{A list of additional options to pass to the \code{minify} CLI
+command. Only the following sensible subset of
+\href{https://github.com/tdewolff/minify/tree/master/cmd/minify#usage}{all possible minify options}
+is supported, listed with their default values:
+\itemize{
+\item \code{`html-keep-conditional-comments` = FALSE}: Preserve all IE conditional comments
+\item \code{`html-keep-default-attrvals` = FALSE}: Preserve default attribute values
+\item \code{`html-keep-document-tags` = FALSE}: Preserve \verb{}, \verb{} and \verb{} tags
+\item \code{`html-keep-end-tags` = FALSE}: Preserve all end tags
+\item \code{`html-keep-quotes` = FALSE}: Preserve quotes around attribute values
+\item \code{`html-keep-whitespace` = FALSE}: Preserve whitespace characters but still collapse multiple into one
+\item \code{`css-decimals` = -1L}: Number of decimals to preserve in CSS numbers,
+\code{-1L} means all
+\item \code{`svg-decimals` = -1L}: Number of decimals to preserve in SVG numbers,
+\code{-1L} means all
+\item \code{verbose = FALSE}: Print informative messages about minification details.
+}}
+
+\item{echo}{If set to \code{TRUE}, the command to minify the \code{email_message}
+object's HTML via \code{minify} will be printed to the console. By default,
+this is \code{FALSE}.}
+}
+\value{
+An \code{email_message} object.
+}
+\description{
+Minify a blastula \code{email_message} object.
+}
+\details{
+The \href{https://en.wikipedia.org/wiki/Minification_(programming)}{minification}
+relies on the binary
+\href{https://github.com/tdewolff/minify/tree/master/cmd/minify}{\strong{minify}}
+which is cross-platform and works on Windows, macOS, Linux and BSD.
+Pre-built binaries can be downloaded from
+\href{https://github.com/tdewolff/minify/releases}{here}. Alternatively,
+instructions to build minify from source are available
+\href{https://github.com/tdewolff/minify/tree/master/cmd/minify#installation}{here}.
+}
+\examples{
+\donttest{# Create a simple test email
+test_mail <- prepare_test_message()
+
+# Minify the test email
+minify(test_mail)
+
+# The command used to minify can be printed
+minify(email = test_mail,
+ echo = TRUE)
+
+# We can also provide options to the
+# underlying minify command
+minify(email = test_mail,
+ minify_opts = list(`html-keep-conditional-comments` = TRUE,
+ `html-keep-default-attrvals` = TRUE,
+ verbose = TRUE),
+ echo = TRUE)
+}
+
+}
diff --git a/man/pipe.Rd b/man/pipe.Rd
index 7e26451d..232f49ed 100644
--- a/man/pipe.Rd
+++ b/man/pipe.Rd
@@ -4,6 +4,6 @@
\alias{\%>\%}
\title{The magrittr pipe}
\description{
-The \code{blastula} package uses the pipe function, \code{\\\%>\\\%}, to turn function
+The \code{blastula} package uses the pipe function, \verb{\\\%>\\\%}, to turn function
composition into a series of imperative statements.
}
diff --git a/man/render_email.Rd b/man/render_email.Rd
index 70adb8fc..8eba4f4c 100644
--- a/man/render_email.Rd
+++ b/man/render_email.Rd
@@ -5,12 +5,22 @@
\alias{render_connect_email}
\title{R Markdown render functions for the \code{blastula_email} output format}
\usage{
-render_email(input, envir = parent.frame(), quiet = TRUE,
- output_options = list(), render_options = list())
+render_email(
+ input,
+ envir = parent.frame(),
+ quiet = TRUE,
+ output_options = list(),
+ render_options = list()
+)
-render_connect_email(input, connect_footer = TRUE,
- envir = parent.frame(), quiet = TRUE, output_options = list(),
- render_options = list())
+render_connect_email(
+ input,
+ connect_footer = TRUE,
+ envir = parent.frame(),
+ quiet = TRUE,
+ output_options = list(),
+ render_options = list()
+)
}
\arguments{
\item{input}{The input file to be rendered. This should be an R Markdown
diff --git a/man/send_by_mailgun.Rd b/man/send_by_mailgun.Rd
index 2af11cf0..a46e6519 100644
--- a/man/send_by_mailgun.Rd
+++ b/man/send_by_mailgun.Rd
@@ -37,9 +37,9 @@ Mailgun.
#
# ## This a section heading
#
-# We can use Markdown formatting \\\\
-# to **embolden** text or to add \\\\
-# *emphasis*. This is exciting, \\\\
+# We can use Markdown formatting \\
+# to **embolden** text or to add \\
+# *emphasis*. This is exciting, \\
# right?
#
# Cheers")
diff --git a/man/smtp_send.Rd b/man/smtp_send.Rd
index 42cda775..3e71f1ad 100644
--- a/man/smtp_send.Rd
+++ b/man/smtp_send.Rd
@@ -4,8 +4,17 @@
\alias{smtp_send}
\title{Send an email message through SMTP}
\usage{
-smtp_send(email, to, from, subject = NULL, cc = NULL, bcc = NULL,
- credentials = NULL, creds_file = "deprecated", verbose = FALSE)
+smtp_send(
+ email,
+ to,
+ from,
+ subject = NULL,
+ cc = NULL,
+ bcc = NULL,
+ credentials = NULL,
+ creds_file = "deprecated",
+ verbose = FALSE
+)
}
\arguments{
\item{email}{The email message object, as created by the \code{\link[=compose_email]{compose_email()}}
@@ -46,7 +55,7 @@ store, through use of the \code{\link[=create_smtp_creds_key]{create_smtp_creds_
Such a file is created using the \code{\link[=create_smtp_creds_file]{create_smtp_creds_file()}} function.}
\item{creds_file}{An option to specify a credentials file. As this argument
-is deprecated, please consider using \code{credentials = creds_file()}
+is deprecated, please consider using \verb{credentials = creds_file()}
instead.}
\item{verbose}{Should verbose output from the internal curl \code{send_mail()}
diff --git a/man/social_link.Rd b/man/social_link.Rd
index 2edb2544..c077aaec 100644
--- a/man/social_link.Rd
+++ b/man/social_link.Rd
@@ -16,7 +16,7 @@ social_link(service, link, variant = NULL, alt = NULL)
and white, the default), \code{color}, \code{dark_gray}, \code{gray}, and \code{light_gray}.}
\item{alt}{Text description of image passed to the \code{alt} attribute inside of
-the image (\code{
}) tag for use when image loading is disabled and on
+the image (\verb{
}) tag for use when image loading is disabled and on
screen readers. If not supplied, then the name of the \code{service} will be
used as alt text.}
}