Skip to content

Commit

Permalink
Escape Rd comments in markdown (#904)
Browse files Browse the repository at this point in the history
Providing detailed message when you upgrade

Fixes #879
  • Loading branch information
hadley authored Sep 12, 2019
1 parent 5e5f0b3 commit 40f848b
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 35 deletions.
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: roxygen2
Title: In-Line Documentation for R
Version: 6.1.1.9000
Version: 6.1.99.9000
Authors@R:
c(person(given = "Hadley",
family = "Wickham",
Expand Down Expand Up @@ -55,4 +55,4 @@ VignetteBuilder:
knitr
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 6.1.1.9000
RoxygenNote: 6.1.99.9000
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# roxygen2 (development version)

* Rd comments (`%`) are automatically escaped in markdown text. This is
a backward incompatible check that will require that you replace
existing uses of `\%` with `%` (#879).

* `@describeIn` can now be used with any combination of function types
(#666, #848).

Expand Down
24 changes: 19 additions & 5 deletions R/markdown-escaping.R
Original file line number Diff line number Diff line change
Expand Up @@ -220,15 +220,29 @@ make_random_string <- function(length = 32) {
)
}

#' Escape \\% and \\$ and \\_ once more, because commonmark
#' removes the escaping. We do this everywhere currently.
#' Check markdown escaping
#'
#' This is a regression test for Markdown escaping.
#'
#' @details
#' Each of the following bullets should look the same when rendered:
#'
#' * Double escapes: \\, \\%, \\$, \\_
#' * Backticks: `\`, `\%`, `\$`, `\_`
#' * `\verb{}`: \verb{\\}, \verb{\\%}, \verb{\$}, \verb{\_}
#'
#' \[ this isn't a link \]
#' \\[ neither is this \\]
#'
#' @param text Input text.
#' @return Double-escaped text.
#' @keywords internal

double_escape_md <- function(text) {
text <- gsub("\\%", "\\\\%", text, fixed = TRUE)
text <- gsub("\\_", "\\\\_", text, fixed = TRUE)
text <- gsub("\\$", "\\\\$", text, fixed = TRUE)
text <- gsub("\\", "\\\\", text, fixed = TRUE)

# De-dup escaping used to avoid [] creating a link
text <- gsub("\\\\[", "\\[", text, fixed = TRUE)
text <- gsub("\\\\]", "\\]", text, fixed = TRUE)
text
}
2 changes: 1 addition & 1 deletion R/markdown-link.R
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ parse_link <- function(destination, contents) {
)

} else {
contents <- gsub("%", "\\\\%", mdxml_link_text(contents))
contents <- mdxml_link_text(contents)

list(
paste0(
Expand Down
16 changes: 10 additions & 6 deletions R/markdown.R
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ mdxml_node_to_rd <- function(xml, tag) {
unknown = mdxml_children_to_rd(xml, tag),

paragraph = paste0("\n\n", mdxml_children_to_rd(xml, tag)),
text = xml_text(xml),
text = escape_comment(xml_text(xml)),
emph = paste0("\\emph{", mdxml_children_to_rd(xml, tag), "}"),
strong = paste0("\\strong{", mdxml_children_to_rd(xml, tag), "}"),
softbreak = "\n",
Expand All @@ -64,11 +64,11 @@ mdxml_node_to_rd <- function(xml, tag) {

mdxml_unknown <- function(xml, tag) {
roxy_tag_warning(tag, "Unknown xml node: ", xml_name(xml))
xml_text(xml)
escape_comment(xml_text(xml))
}
mdxml_unsupported <- function(xml, tag, feature) {
roxy_tag_warning(tag, "Use of ", feature, " is not currently supported")
xml_text(xml)
escape_comment(xml_text(xml))
}

mdxml_code <- function(xml, tag) {
Expand All @@ -91,7 +91,7 @@ can_parse <- function(x) {
}

escape_verb <- function(x) {
x <- gsub("\\", "\\\\", x, fixed = TRUE)
# Don't need to escape \\ because that's already handled in double_escape_md()
x <- gsub("%", "\\%", x, fixed = TRUE)
x <- gsub("{", "\\{", x, fixed = TRUE)
x <- gsub("}", "\\}", x, fixed = TRUE)
Expand Down Expand Up @@ -135,7 +135,7 @@ mdxml_link <- function(xml) {
if (!is.null(link)) {
paste0(link, collapse = "")
} else if (dest == "" || dest == xml_text(xml)) {
paste0("\\url{", xml_text(xml), "}")
paste0("\\url{", escape_comment(xml_text(xml)), "}")
} else {
paste0("\\href{", dest, "}{", mdxml_link_text(contents), "}")
}
Expand All @@ -147,11 +147,15 @@ mdxml_link <- function(xml) {
mdxml_link_text <- function(xml_contents) {
text <- xml_text(xml_contents)
text[xml_name(xml_contents) %in% c("linebreak", "softbreak")] <- " "
paste0(text, collapse = "")
escape_comment(paste0(text, collapse = ""))
}

mdxml_image = function(xml) {
dest <- xml_attr(xml, "destination")
title <- xml_attr(xml, "title")
paste0("\\figure{", dest, "}{", title, "}")
}

escape_comment <- function(x) {
gsub("%", "\\%", x, fixed = TRUE)
}
15 changes: 15 additions & 0 deletions R/safety.R
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,21 @@ update_roxygen_version <- function(base_path) {
" You only have version ", cur, call. = FALSE, immediate. = TRUE)
} else if (!identical(cur, prev)) {
message("Updating roxygen version in ", desc_path)
upgrade_7_0_0(cur)
desc::desc_set(RoxygenNote = cur, file = desc_path)
}
}

upgrade_7_0_0 <- function(cur_version) {
if (numeric_version(cur_version) > "6.1.99") {
return()
}
rule <- paste0(paste(rep("-", options('width')), collapse = ""))
inform(c(
rule,
"Changes in roxygen2 7.0.0:",
"* `%` is now escaped automatically in Markdown mode.",
"Please carefully check .Rd files for changes",
rule
))
}
18 changes: 14 additions & 4 deletions man/double_escape_md.Rd

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

19 changes: 2 additions & 17 deletions tests/testthat/test-markdown.R
Original file line number Diff line number Diff line change
Expand Up @@ -347,23 +347,8 @@ So far so good. \\preformatted{ *these are not
expect_equal(get_tag(out1, "description")[[2]], desc1)
})

test_that("% and $ and _ are not unescaped", {
out1 <- roc_proc_text(rd_roclet(), "
#' Title
#'
#' Description. It has some \\% and \\$ and also \\_.
#'
#' @param foo Item with \\% characters: \\%. And also \\$ and \\_.
foo <- function(foo) {}")[[1]]
out2 <- roc_proc_text(rd_roclet(), "
#' Title
#'
#' Description. It has some \\% and \\$ and also \\_.
#'
#' @param foo Item with \\% characters: \\%. And also \\$ and \\_.
#' @md
foo <- function(foo) {}")[[1]]
expect_equivalent_rd(out1, out2)
test_that("% is automatically escaped", {
expect_equal(markdown("5%"), "5\\%")
})

test_that("Escaping is kept", {
Expand Down

0 comments on commit 40f848b

Please sign in to comment.