Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support custom highlight theme in other formats #2285

Merged
merged 13 commits into from
Jan 14, 2022
4 changes: 2 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
rmarkdown 2.12
================================================================================

- Improved the highlighting mechanism for HTML outputs:
- Improved the highlighting mechanism in formats that supports `highlight` argument:
* It is now possible to pass a custom theme file `.theme` in `highlight` argument for customizing the [syntax highlighting style used by Pandoc](https://pandoc.org/MANUAL.html#syntax-highlighting).
* In addition to Pandoc's own supported themes, two more themes are bundled in the package: `highlight: arrow` a theme [optimized for accessibility and color constrast](https://www.a11yproject.com/) (thanks to @apreshill), and `highlight: rstudio` to mimic the RStudio editor theme.
* Added optional [downlit](https://downlit.r-lib.org/) support in `html_document()` for R syntax highlighting and autolinking. Use `highlight_downlit = TRUE` to activate it (same argument as in **distill**). This features require the **downlit** package.
* For HTML output only, added optional [downlit](https://downlit.r-lib.org/) support in `html_document()` for R syntax highlighting and autolinking. Use `highlight_downlit = TRUE` to activate it (same argument as in **distill**). This features require the **downlit** package.

- Added a global option `rmarkdown.html_dependency.header_attr` (`TRUE` by default). It can be set to `FALSE` to opt-out the HTML dependency `html_dependency_header_attrs()` in documents based on `html_document_base()` (thanks, @salim-b rstudio/bookdown#865, @maelle r-lib/downlit#1538).

Expand Down
3 changes: 1 addition & 2 deletions R/beamer_presentation.R
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,7 @@ beamer_presentation <- function(toc = FALSE,
args <- c(args, pandoc_variable_arg("fonttheme", fonttheme))

# highlighting
if (!is.null(highlight))
highlight <- match.arg(highlight, highlighters())
if (!is.null(highlight)) highlight <- resolve_highlight(highlight, highlighters())
args <- c(args, pandoc_highlight_args(highlight))

# latex engine
Expand Down
12 changes: 6 additions & 6 deletions R/html_document.R
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,15 @@
#' "default" (and "textmate") will use highlightjs as syntax highlighting
#' engine instead of Pandoc.
#'
#' Any other value will be passed to Pandoc's
#' \href{https://pandoc.org/MANUAL.html#syntax-highlighting}{highlighting
#' style}. Pandoc's built-in styles include "tango", "pygments", "kate",
#' "monochrome", "espresso", "zenburn", "haddock" and "breezedark".
#' Any other value will be passed as Pandoc's highlighting style. Pandoc's
#' built-in styles include "tango", "pygments", "kate", "monochrome",
#' "espresso", "zenburn", "haddock" and "breezedark".
#'
#' Two custom styles are also included, "arrow", an accessible color scheme,
#' and "rstudio", which mimics the default IDE theme. Alternatively, supply a
#' path to a \samp{.theme} to use a custom Pandoc style. Note that custom theme
#' requires Pandoc 2.0+.
#' path to a \samp{.theme} to use
#' \href{https://pandoc.org/MANUAL.html#syntax-highlighting}{a custom Pandoc
#' style}. Note that custom theme requires Pandoc 2.0+.
#'
#' Pass \code{NULL} to prevent syntax highlighting.
#'
Expand Down
57 changes: 37 additions & 20 deletions R/pandoc.R
Original file line number Diff line number Diff line change
Expand Up @@ -564,26 +564,7 @@ pandoc_html_highlight_args <- function(template,
# no highlighting engine
if (is.null(highlight)) return(pandoc_highlight_args(NULL))

# TODO: move out so that it works also for other formats
resolve_highlight <- function(highlight) {
# if Pandoc built-in highlighter, do no nothing
if (highlight %in% highlighters()) return(highlight)
if (!pandoc2.0()) {
stop("Using a custom highlighting style requires Pandoc 2.0 and above",
call. = FALSE)
}
custom <- list(
# from distill
# https://raw.githubusercontent.com/apreshill/distill/arrow/inst/rmarkdown/templates/distill_article/resources/arrow.theme
arrow = pkg_file_highlight("arrow.theme"),
# from distill
# https://github.com/rstudio/distill/blob/c98d332192ff75f268ddf69bddace34e4db6d89b/inst/rmarkdown/templates/distill_article/resources/rstudio.theme
rstudio = pkg_file_highlight("rstudio.theme")
)
# if not an alias use the provided custom path
custom[[highlight]] %||% highlight
}
highlight <- resolve_highlight(highlight)
highlight <- resolve_highlight(highlight, html_highlighters())

check_highlightjs <- function(highlight, engine) {
if (highlight != "default" && is_highlightjs(highlight)) {
Expand Down Expand Up @@ -624,6 +605,42 @@ is_highlightjs <- function(highlight) {
!is.null(highlight) && (highlight %in% c("default", "textmate"))
}

resolve_highlight <- function(highlight, supported = highlighters()) {
is_supported <- TRUE
# for backward compatibility, partial match still need to work
highlight <- tryCatch(
error = function(e) { is_supported <<- FALSE; highlight },
match.arg(highlight, supported)
cderv marked this conversation as resolved.
Show resolved Hide resolved
)
if (is_supported) return(highlight)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this change to bring back the partial matching feature that was there when match.arg() was used. Meaning
this would work.

output:
  html_document: 
    highlight: breez

It was not following my other PR.


# Otherwise it could be a custom (built-in) .theme file
if (!pandoc2.0()) {
stop("Using a custom highlighting style requires Pandoc 2.0 and above",
call. = FALSE)
}
custom <- list(
# from distill
# https://raw.githubusercontent.com/apreshill/distill/arrow/inst/rmarkdown/templates/distill_article/resources/arrow.theme
arrow = pkg_file_highlight("arrow.theme"),
# from distill
# https://github.com/rstudio/distill/blob/c98d332192ff75f268ddf69bddace34e4db6d89b/inst/rmarkdown/templates/distill_article/resources/rstudio.theme
rstudio = pkg_file_highlight("rstudio.theme")
)
# if not an alias use the provided custom path
highlight <- custom[[highlight]] %||% highlight
# Check for extension or give informative error otherwise
if (!identical(xfun::file_ext(highlight), "theme")) {
msg <- c(
sprintf("`highlight` argument must be one of %s",
knitr::combine_words(c(supported, names(custom)), and = " or ", before = "`")),
" or a file with extension `.theme`."
)
stop(msg, call. = FALSE)
}
highlight
Comment on lines +627 to +637
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I then added that to throw early a useful message if the highlight value is not one of the expected (either one supported theme or a file path to a .theme file).

This makes code less simple than in the other PR but it brings back useful message.

}

#' Find the \command{pandoc} executable
#'
#' Searches for the \command{pandoc} executable in a few places and use the
Expand Down
18 changes: 13 additions & 5 deletions R/pdf_document.R
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,18 @@
#' \command{ghostscript} to be installed. By default, \code{fig_crop = TRUE}
#' if these two tools are available.
#' @param dev Graphics device to use for figure output (defaults to pdf)
#' @param highlight Syntax highlighting style. Supported styles include
#' "default", "tango", "pygments", "kate", "monochrome", "espresso",
#' "zenburn", and "haddock". Pass \code{NULL} to prevent syntax highlighting.
#' @param highlight Syntax highlighting style passed to Pandoc.
#'
#' Supported built-in styles include "default", "tango", "pygments", "kate",
#' "monochrome", "espresso", "zenburn", "haddock", and "breezedark".
#'
#' Two custom styles are also included, "arrow", an accessible color scheme,
#' and "rstudio", which mimics the default IDE theme. Alternatively, supply a
#' path to a \samp{.theme} file to use
#' \href{https://pandoc.org/MANUAL.html#syntax-highlighting}{a custom Pandoc
#' style}. Note that custom theme requires Pandoc 2.0+.
#'
#' Pass \code{NULL} to prevent syntax highlighting.
#' @param keep_tex Keep the intermediate tex file used in the conversion to PDF
#' @param latex_engine LaTeX engine for producing PDF output. Options are
#' "pdflatex", "lualatex", "xelatex" and "tectonic".
Expand Down Expand Up @@ -127,8 +136,7 @@ pdf_document <- function(toc = FALSE,
args <- c(args, "--number-sections")

# highlighting
if (!is.null(highlight))
highlight <- match.arg(highlight, highlighters())
if (!is.null(highlight)) highlight <- resolve_highlight(highlight, highlighters())
args <- c(args, pandoc_highlight_args(highlight))

# latex engine
Expand Down
1 change: 1 addition & 0 deletions R/slidy_presentation.R
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ slidy_presentation <- function(number_sections = FALSE,
args <- c()

# highlight
if (!is.null(highlight)) highlight <- resolve_highlight(highlight, highlighters())
args <- c(args, pandoc_highlight_args(highlight, default = "pygments"))

# return additional args
Expand Down
3 changes: 1 addition & 2 deletions R/word_document.R
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ word_document <- function(toc = FALSE,
}

# highlighting
if (!is.null(highlight))
highlight <- match.arg(highlight, highlighters())
if (!is.null(highlight)) highlight <- resolve_highlight(highlight, highlighters())
args <- c(args, pandoc_highlight_args(highlight))

# reference docx
Expand Down
15 changes: 12 additions & 3 deletions man/beamer_presentation.Rd

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

12 changes: 6 additions & 6 deletions man/html_document.Rd

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

12 changes: 6 additions & 6 deletions man/html_notebook.Rd

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

15 changes: 12 additions & 3 deletions man/pdf_document.Rd

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

15 changes: 12 additions & 3 deletions man/slidy_presentation.Rd

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

15 changes: 12 additions & 3 deletions man/tufte_handout.Rd

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

15 changes: 12 additions & 3 deletions man/word_document.Rd

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

16 changes: 16 additions & 0 deletions tests/testthat/test-pandoc.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,22 @@ test_that("build highlight args for pandoc correctly", {
expect_equal(pandoc_highlight_args("zenburn"), hl_style("zenburn"))
})

test_that("Detect if a theme file is providing in highlight", {
expect_equal(resolve_highlight("default"), "default")
expect_equal(resolve_highlight("breezedark"), "breezedark")
expect_equal(resolve_highlight("breez"), "breezedark")
expect_error(resolve_highlight("textmate"), "must be one of")
expect_equal(
resolve_highlight("textmate", html_highlighters()), "textmate"
)
if (pandoc_available("2.0")) {
expect_equal(resolve_highlight("arrow"), pkg_file_highlight("arrow.theme"))
expect_equal(resolve_highlight("custom.theme"), "custom.theme")
expect_error(resolve_highlight("custom.json"), "a file with extension")
} else {
expect_error(resolve_highlight("arrow"), "requires Pandoc 2.0")
}
})

test_that("Correct HTML highlighting argument as requested", {
# helpers
Expand Down