From 4fc0a3abc34b5049bc29df6611a187b2cd2de821 Mon Sep 17 00:00:00 2001 From: Salim B Date: Tue, 22 Apr 2025 23:05:43 +0200 Subject: [PATCH 1/4] style: Fix coding style, spelling and indentation --- R/markdown-link.R | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/R/markdown-link.R b/R/markdown-link.R index c846e647..48de5432 100644 --- a/R/markdown-link.R +++ b/R/markdown-link.R @@ -1,4 +1,4 @@ -#' Add link reference definitions for functions to a markdown text. +#' Add link reference definitions for functions to a Markdown text. #' #' We find the `[text][ref]` and the `[ref]` forms. There must be no #' spaces between the closing and opening bracket in the `[text][ref]` @@ -43,7 +43,7 @@ #' In the link references, we need to URL encode the reference, #' otherwise commonmark does not use it (see issue #518). #' -#' @param text Input markdown text. +#' @param text Input Markdown text. #' @return The input text and all dummy reference link definitions #' appended. #' @@ -58,7 +58,7 @@ get_md_linkrefs <- function(text) { (?<=[^\\]\\\\]|^) # must not be preceded by ] or \ \\[([^\\]\\[]+)\\] # match anything inside of [] (?:\\[([^\\]\\[]+)\\])? # match optional second pair of [] - (?=[^\\[{]|$) # must not be followed by [ or { + (?=[^\\[{]|$) # must not be followed by [ or { " ) )[[1]] @@ -83,11 +83,11 @@ add_linkrefs_to_md <- function(text) { paste0(text, "\n\n", ref_text, "\n") } -#' Parse a MarkDown link, to see if we should create an Rd link +#' Parse a Markdown link, to see if we should create an Rd link #' #' See the table above. #' -#' @param destination string constant, the "url" of the link +#' @param destination String constant, the "URL" of the link. #' @param contents An XML node, containing the contents of the link. #' #' @noRd @@ -95,7 +95,7 @@ add_linkrefs_to_md <- function(text) { parse_link <- function(destination, contents, state) { ## Not a [] or [][] type link, remove prefix if it is - if (! grepl("^R:", destination)) return(NULL) + if (!grepl("^R:", destination)) return(NULL) destination <- sub("^R:", "", URLdecode(destination)) ## if contents is a `code tag`, then we need to move this outside @@ -132,19 +132,19 @@ parse_link <- function(destination, contents, state) { ## `fun` is fun() or obj (fun is with parens) ## `is_fun` is TRUE for fun(), FALSE for obj ## `obj` is fun or obj (fun is without parens) - ## `s4` is TRUE if we link to an S4 class (i.e. have -class suffix) + ## `is_s4` is TRUE if we link to an S4 class (i.e. have -class suffix) ## `noclass` is fun with -class removed ## `file` is the file name of the linked topic. thispkg <- roxy_meta_get("current_package") %||% "" - is_code <- is_code || (grepl("[(][)]$", destination) && ! has_link_text) + is_code <- is_code || (grepl("[(][)]$", destination) && !has_link_text) pkg <- str_match(destination, "^(.*)::")[1,2] pkg <- gsub("%", "\\\\%", pkg) fun <- utils::tail(strsplit(destination, "::", fixed = TRUE)[[1]], 1) fun <- gsub("%", "\\\\%", fun) is_fun <- grepl("[(][)]$", fun) obj <- sub("[(][)]$", "", fun) - s4 <- str_detect(destination, "-class$") + is_s4 <- str_detect(destination, "-class$") noclass <- str_match(fun, "^(.*)-class$")[1,2] if (is.na(pkg)) pkg <- resolve_link_package(obj, thispkg, state = state) @@ -155,14 +155,14 @@ parse_link <- function(destination, contents, state) { if (!has_link_text) { paste0( if (is_code) "\\code{", - if (s4 && is.na(pkg)) "\\linkS4class" else "\\link", - if (is_fun || ! is.na(pkg)) "[", + if (is_s4 && is.na(pkg)) "\\linkS4class" else "\\link", + if (is_fun || !is.na(pkg)) "[", if (is_fun && is.na(pkg)) "=", - if (! is.na(pkg)) paste0(pkg, ":"), - if (is_fun || ! is.na(pkg)) paste0(if (is.na(pkg)) obj else file, "]"), + if (!is.na(pkg)) paste0(pkg, ":"), + if (is_fun || !is.na(pkg)) paste0(if (is.na(pkg)) obj else file, "]"), "{", if (!is.na(pkg)) paste0(pkg, "::"), - if (s4) noclass else fun, + if (is_s4) noclass else fun, "}", if (is_code) "}" else "" ) @@ -282,7 +282,7 @@ find_reexport_source <- function(topic, package) { } } -#' Dummy page to test roxygen's markdown formatting +#' Dummy page to test roxygen's Markdown formatting #' #' Links are very tricky, so I'll put in some links here: #' Link to a function: [roxygenize()]. From bd6ba1afae406d2f10834ca59f4c7cae2ef85a95 Mon Sep 17 00:00:00 2001 From: Salim B Date: Tue, 22 Apr 2025 23:06:55 +0200 Subject: [PATCH 2/4] chore: update test snapshots output changed due to upstream changes --- tests/testthat/_snaps/markdown-code.md | 2 +- tests/testthat/_snaps/object-package.md | 9 +++++++++ tests/testthat/_snaps/rd-include-rmd.md | 4 ++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/testthat/_snaps/markdown-code.md b/tests/testthat/_snaps/markdown-code.md index 2be064a7..30e29fbc 100644 --- a/tests/testthat/_snaps/markdown-code.md +++ b/tests/testthat/_snaps/markdown-code.md @@ -15,7 +15,7 @@ Message - Quitting from lines 1-1 + Quitting from :1-1 x :4: @description failed to evaluate inline markdown code. Caused by error in `map_chr()`: i In index: 1. diff --git a/tests/testthat/_snaps/object-package.md b/tests/testthat/_snaps/object-package.md index 6d8469f0..b6cc9735 100644 --- a/tests/testthat/_snaps/object-package.md +++ b/tests/testthat/_snaps/object-package.md @@ -13,14 +13,23 @@ Code # ORCID comments person_desc(comment = c(ORCID = "1234")) + Condition + Warning in `person1()`: + Invalid ORCID iD: '1234'. Output [1] "H W \\email{h@w.com} (\\href{https://orcid.org/1234}{ORCID})" Code person_desc(comment = c(ORCID = "https://orcid.org/1234")) + Condition + Warning in `person1()`: + Invalid ORCID iD: 'https://orcid.org/1234'. Output [1] "H W \\email{h@w.com} (\\href{https://orcid.org/1234}{ORCID})" Code person_desc(comment = c(ORCID = "1234", "extra")) + Condition + Warning in `person1()`: + Invalid ORCID iD: '1234'. Output [1] "H W \\email{h@w.com} (\\href{https://orcid.org/1234}{ORCID}) (extra)" diff --git a/tests/testthat/_snaps/rd-include-rmd.md b/tests/testthat/_snaps/rd-include-rmd.md index e7b7e4f7..111e9cb5 100644 --- a/tests/testthat/_snaps/rd-include-rmd.md +++ b/tests/testthat/_snaps/rd-include-rmd.md @@ -20,9 +20,9 @@ Message - Quitting from lines 2-3 [unnamed-chunk-2] () + Quitting from :1-3 [unnamed-chunk-2] - Quitting from lines 2-2 [unnamed-chunk-1] () + Quitting from :1-2 [unnamed-chunk-1] x :3: @includeRmd failed to evaluate ''. Caused by error: ! Error From 6778edad64574f7c24c81394c3d5ab037f7086b3 Mon Sep 17 00:00:00 2001 From: Salim B Date: Tue, 22 Apr 2025 23:12:51 +0200 Subject: [PATCH 3/4] feat: Support markup in link text for R >= 4.5 --- R/markdown-link.R | 20 ++++++++++++-------- tests/testthat/test-markdown-link.R | 4 +++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/R/markdown-link.R b/R/markdown-link.R index 48de5432..c6422a2b 100644 --- a/R/markdown-link.R +++ b/R/markdown-link.R @@ -98,7 +98,8 @@ parse_link <- function(destination, contents, state) { if (!grepl("^R:", destination)) return(NULL) destination <- sub("^R:", "", URLdecode(destination)) - ## if contents is a `code tag`, then we need to move this outside + ## If contents is a single \code tag, we move it outside + ## (still necessary in R >= 4.5 to support the short "[`obj_name`]" syntax) is_code <- FALSE if (length(contents) == 1 && xml_name(contents) == "code") { is_code <- TRUE @@ -109,14 +110,17 @@ parse_link <- function(destination, contents, state) { local_bindings(.env = state, in_link_code = TRUE) } - if (!all(xml_name(contents) %in% c("text", "softbreak", "linebreak"))) { - incorrect <- setdiff(unique(xml_name(contents)), c("text", "softbreak", "linebreak")) + # In R < 4.5.0, the Rd link macro didn't allow markup in the link text + if (getRversion() < "4.5.0") { + if (!all(xml_name(contents) %in% c("text", "softbreak", "linebreak"))) { + incorrect <- setdiff(unique(xml_name(contents)), c("text", "softbreak", "linebreak")) - warn_roxy_tag(state$tag, c( - "markdown links must contain plain text", - i = "Problematic link: {destination}" - )) - return("") + warn_roxy_tag(state$tag, c( + "Markdown links in R < 4.5 must contain plain text only", + i = "Problematic link: {destination}" + )) + return("") + } } ## If the supplied link text is the same as the reference text, diff --git a/tests/testthat/test-markdown-link.R b/tests/testthat/test-markdown-link.R index 80d648c0..5b0125c9 100644 --- a/tests/testthat/test-markdown-link.R +++ b/tests/testthat/test-markdown-link.R @@ -62,7 +62,9 @@ test_that("{ and } in links are escaped (#1259)", { expect_equal(markdown("[foo({ bar })][x]"), "\\link[=x]{foo({ bar })}") }) -test_that("non-text nodes in links fails", { +test_that("non-text nodes in links fails for R < 4.5.0", { + skip_if(getRversion() >= "4.5.0") + tag <- roxy_tag("title", NULL, NULL, file = "foo.R", line = 10) expect_snapshot({ From 01392ac4e207731e4efe452b1de6c4fc68b5f4d0 Mon Sep 17 00:00:00 2001 From: Salim B Date: Tue, 22 Apr 2025 23:46:34 +0200 Subject: [PATCH 4/4] docs: Add NEWS bullet for #1712 --- NEWS.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index c198e575..e62a0ce8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -13,7 +13,12 @@ automatically resolved (#1612). * `@examplesIf` always uses `withAutoprint()` (@MichaelChirico, #1581). The raw Rd - will be cleaner, but such examples will now only run under R>=3.4.0 (2017). + will be cleaner, but such examples will now only run under R >= 3.4.0 (2017). + +* R 4.5.0 added support for markup in Rd `\link` texts and roxygen2 now properly + supports this. This means now you can for example write + `` A [link *with* markup to `roxygen2::roxygenize()`][roxygen2::roxygenize]! `` + in roxygen2 documentation. (#1712, @salim-b) # roxygen2 7.3.2