diff --git a/DESCRIPTION b/DESCRIPTION index 372fcdf02e..f41c25af7d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -42,7 +42,6 @@ Imports: rlang (>= 1.0.2), sass (>= 0.4.1), scales (>= 1.2.0), - stringr (>= 1.4.0), tibble (>= 3.1.6), tidyselect (>= 1.1.1) Suggests: diff --git a/R/format_data.R b/R/format_data.R index d2daf38015..683330e6d4 100644 --- a/R/format_data.R +++ b/R/format_data.R @@ -3686,13 +3686,15 @@ fmt_markdown <- function( markdown_to_xml(x) }, default = function(x) { - vapply( - x, - FUN.VALUE = character(1), - USE.NAMES = FALSE, - commonmark::markdown_text - ) %>% - stringr::str_replace("\n$", "") + sub( + "\n$", "", + vapply( + x, + FUN.VALUE = character(1), + USE.NAMES = FALSE, + commonmark::markdown_text + ) + ) } ) ) diff --git a/R/info_tables.R b/R/info_tables.R index c5d83f84b3..6bde28d98a 100644 --- a/R/info_tables.R +++ b/R/info_tables.R @@ -628,6 +628,22 @@ info_google_fonts <- function() { "Work Sans" ) + to_title_case <- function(x) { + + title_case_i <- function(y) { + + s <- strsplit(y, " ")[[1]] + + paste( + toupper(substring(s, 1,1)), + substring(s, 2), + sep = "", collapse = " " + ) + } + + vapply(x, FUN.VALUE = character(1), USE.NAMES = FALSE, FUN = title_case_i) + } + styles_summary <- google_styles_tbl %>% dplyr::mutate(weight = as.integer(weight)) %>% @@ -662,7 +678,7 @@ info_google_fonts <- function() { dplyr::filter(name %in% recommended) %>% dplyr::left_join(styles_summary, by = "name") %>% dplyr::mutate( - category = stringr::str_to_title(category) %>% + category = to_title_case(tolower(category)) %>% tidy_gsub("_", " ") %>% tidy_gsub("serif", "Serif") ) %>% diff --git a/R/utils.R b/R/utils.R index 1f977d5586..bd1af98c23 100644 --- a/R/utils.R +++ b/R/utils.R @@ -611,7 +611,7 @@ markdown_to_xml <- function(text) { text } -# TODO: Make XML versions of these + cmark_rules_xml <- list( heading = function(x, process) { @@ -672,11 +672,9 @@ cmark_rules_xml <- list( }, html_inline = function(x, process) { - # TODO: make this work for XML - tag <- xml2::xml_text(x) - match <- stringr::str_match(tag, pattern = "^<(/?)([a-zA-Z0-9\\-]+)") + match <- str_get_match(tag, pattern = "^<(/?)([a-zA-Z0-9\\-]+)") if (!is.na(match[1, 1])) { @@ -767,7 +765,9 @@ cmark_rules_xml <- list( ) cmark_rules_rtf <- list( + heading = function(x, process) { + heading_sizes <- c(36, 32, 28, 24, 20, 16) fs <- heading_sizes[as.numeric(xml2::xml_attr(x, attr = "level"))] @@ -833,7 +833,7 @@ cmark_rules_rtf <- list( tag <- xml2::xml_text(x) - match <- stringr::str_match(tag, pattern = "^<(/?)([a-zA-Z0-9\\-]+)") + match <- str_get_match(tag, pattern = "^<(/?)([a-zA-Z0-9\\-]+)") if (!is.na(match[1, 1])) { @@ -1419,16 +1419,16 @@ get_css_tbl <- function(data) { css_tbl, dplyr::tibble( selector = rep( - stringr::str_remove(raw_css_vec[ruleset_start[i]], "\\s*\\{\\s*$"), + str_single_replace(raw_css_vec[ruleset_start[i]], "\\s*\\{\\s*$", ""), (ruleset_end[i] - ruleset_start[i] - 1)), property = raw_css_vec[(ruleset_start[i] + 1):(ruleset_end[i] - 1)] %>% - stringr::str_extract("[a-zA-z-]*?(?=:)") %>% - stringr::str_trim(), + str_single_extract("[a-zA-z-]*?(?=:)") %>% + str_trim_sides(), value = raw_css_vec[(ruleset_start[i] + 1):(ruleset_end[i] - 1)] %>% - stringr::str_extract("(?<=:).*") %>% - stringr::str_remove(pattern = ";\\s*") %>% - stringr::str_remove(pattern = "\\/\\*.*") %>% - stringr::str_trim() + str_single_extract("(?<=:).*") %>% + str_single_replace(pattern = ";\\s*", "") %>% + str_single_replace(pattern = "\\/\\*.*", "") %>% + str_trim_sides() ) %>% dplyr::filter(!is.na(property)) ) @@ -1441,8 +1441,8 @@ get_css_tbl <- function(data) { dplyr::mutate( css_tbl, type = dplyr::case_when( - stringr::str_detect(selector, "^\\.") ~ "class", - !stringr::str_detect(selector, "^\\.") ~ NA_character_ + str_has_match(selector, "^\\.") ~ "class", + !str_has_match(selector, "^\\.") ~ NA_character_ ) ) css_tbl <- dplyr::select(css_tbl, selector, type, property, value) @@ -1465,7 +1465,7 @@ create_inline_styles <- function( extra_style = "" ) { - class_names <- unlist(stringr::str_split(class_names, "\\s+")) + class_names <- unlist(strsplit(class_names, "\\s+")) paste0( "style=\"", @@ -1503,7 +1503,7 @@ inline_html_styles <- function(html, css_tbl) { class_names <- extract_strings(matching_css_style, cls_names_pattern) - existing_style <- stringr::str_match(matching_css_style, sty_exist_pattern)[, 2] + existing_style <- str_get_match(matching_css_style, sty_exist_pattern)[, 2] inline_styles <- create_inline_styles( @@ -1513,7 +1513,7 @@ inline_html_styles <- function(html, css_tbl) { ) html <- - stringr::str_replace( + str_single_replace( html, pattern = cls_sty_pattern, replacement = inline_styles @@ -1522,8 +1522,8 @@ inline_html_styles <- function(html, css_tbl) { repeat { - class_names <- stringr::str_extract(html, pattern = cls_pattern) - class_names <- stringr::str_extract(class_names, pattern = cls_names_pattern) + class_names <- str_single_extract(html, pattern = cls_pattern) + class_names <- str_single_extract(class_names, pattern = cls_names_pattern) if (is.na(class_names)) break @@ -1534,7 +1534,7 @@ inline_html_styles <- function(html, css_tbl) { ) html <- - stringr::str_replace( + str_single_replace( html, pattern = cls_pattern, replacement = inline_styles diff --git a/R/utils_general_str_formatting.R b/R/utils_general_str_formatting.R index dfeb5504cc..82cb32c879 100644 --- a/R/utils_general_str_formatting.R +++ b/R/utils_general_str_formatting.R @@ -379,6 +379,110 @@ str_catalog <- function( } } +str_substitute <- function(string, start = 1L, end = -1L) { + + if (is.matrix(start)) { + end <- start[, 2] + start <- start[, 1] + } + + start <- recycler(start, string) + end <- recycler(end, string) + + n <- nchar(string) + start <- ifelse(start < 0, start + n + 1, start) + end <- ifelse(end < 0, end + n + 1, end) + + substr(string, start, end) +} + +recycler <- function(x, to, arg = deparse(substitute(x))) { + + if (length(x) == length(to)) { + return(x) + } + + if (length(x) != 1) { + stop("Can't recycle `", arg, "` to length ", length(to), call. = FALSE) + } + + rep(x, length(to)) +} + +str_complete_locate <- function(string, pattern) { + out <- gregexpr(pattern, string, perl = TRUE) + lapply(out, location, all = TRUE) +} + +str_single_locate <- function(string, pattern) { + out <- regexpr(pattern, string, perl = TRUE) + location(out) +} + +str_complete_replace <- function(string, pattern, replacement) { + gsub(pattern, replacement, string, perl = TRUE) +} + +str_single_replace <- function(string, pattern, replacement) { + sub(pattern, replacement, string, perl = TRUE) +} + +location <- function(x, all = FALSE) { + + start <- as.vector(x) + if (all && identical(start, -1L)) { + return(cbind(start = integer(), end = integer())) + } + end <- as.vector(x) + attr(x, "match.length") - 1 + + no_match <- start == -1L + start[no_match] <- NA + end[no_match] <- NA + + cbind(start = start, end = end) +} + +str_complete_extract <- function(string, pattern) { + + loc <- str_complete_locate(string, pattern) + lapply(seq_along(string), function(i) { + loc <- loc[[i]] + str_substitute(rep(string[[i]], nrow(loc)), loc) + }) +} + +str_single_extract <- function(string, pattern) { + str_substitute(string, str_single_locate(string, pattern)) +} + +str_get_match <- function(string, pattern) { + + loc <- regexec(pattern, string, perl = TRUE) + loc <- lapply(loc, location) + + out <- lapply(seq_along(string), function(i) { + loc <- loc[[i]] + str_substitute(rep(string[[i]], nrow(loc)), loc) + }) + do.call("rbind", out) +} + +str_has_match <- function(string, pattern, negate = FALSE) { + + out <- grepl(pattern, string, perl = TRUE) + out[is.na(string)] <- NA + + if (negate) { + !out + } else { + out + } +} + +str_trim_sides <- function(string) { + sub("\\s+$", "", sub("^\\s+", "", string)) +} + glue_gt <- function(.x, ...) { glue::glue_data(.x, ..., .transformer = get, .envir = emptyenv()) } diff --git a/R/utils_render_rtf.R b/R/utils_render_rtf.R index 8cb2f6b497..c023868132 100644 --- a/R/utils_render_rtf.R +++ b/R/utils_render_rtf.R @@ -56,7 +56,7 @@ rtf_fonttbl <- function( FUN.VALUE = character(1), USE.NAMES = FALSE, FUN = function(x) { - fonts[x] %>% unlist() %>% gsub("{x}", font_sequence[x], ., fixed = TRUE) + gsub("{x}", font_sequence[x], unlist(fonts[x]), fixed = TRUE) } ) @@ -214,11 +214,10 @@ rtf_file <- function( # Generate the header based on the RTF `document` content # (and also modify the document) # - # Scan for hexadecimal colors in the document; generate # a object matched_colors <- - unique(unlist(stringr::str_extract_all(document, "<>"))) + unique(unlist(str_complete_extract(document, "<>"))) if (length(matched_colors) > 0) { @@ -232,8 +231,9 @@ rtf_file <- function( colortbl <- rtf_colortbl(.hexadecimal_colors = "#FFFFFF") } - # Scan for hexadecimal colors in the document; generate a object - matched_fonts <- unique(unlist(stringr::str_extract_all(document, "<>"))) + # Scan for font declarations in the document; generate a object + matched_fonts <- + unique(unlist(str_complete_extract(document, "<>"))) if (length(matched_fonts) > 0) { @@ -486,54 +486,58 @@ rtf_tbl_row <- function( } tb_borders <- - borders %>% - lapply( - FUN = function(x) { + unlist( + lapply( + borders, + FUN = function(x) { - if (is.numeric(x$color)) { - border_color_value <- x$color - } else { - border_color_value <- rtf_paste0("<>") - } + if (is.numeric(x$color)) { + border_color_value <- x$color + } else { + border_color_value <- rtf_paste0("<>") + } - if (x$direction %in% c("top", "bottom")) { + if (x$direction %in% c("top", "bottom")) { - rtf_paste0( - rtf_key("clbrdr", substr(x$direction, 1, 1)), - rtf_key("brdr", x$style), - rtf_key("brdrw", x$width), - rtf_key("brdrcf", border_color_value) - ) - } else { - "" + rtf_paste0( + rtf_key("clbrdr", substr(x$direction, 1, 1)), + rtf_key("brdr", x$style), + rtf_key("brdrw", x$width), + rtf_key("brdrcf", border_color_value) + ) + } else { + "" + } } - } - ) %>% unlist() + ) + ) lr_borders <- - borders %>% - lapply( - FUN = function(x) { + unlist( + lapply( + borders, + FUN = function(x) { - if (is.numeric(x$color)) { - border_color_value <- x$color - } else { - border_color_value <- rtf_paste0("<>") - } + if (is.numeric(x$color)) { + border_color_value <- x$color + } else { + border_color_value <- rtf_paste0("<>") + } - if (x$direction %in% c("left", "right")) { + if (x$direction %in% c("left", "right")) { - rtf_paste0( - rtf_key("clbrdr", substr(x$direction, 1, 1)), - rtf_key("brdr", x$style), - rtf_key("brdrw", x$width), - rtf_key("brdrcf", border_color_value) - ) - } else { - "" + rtf_paste0( + rtf_key("clbrdr", substr(x$direction, 1, 1)), + rtf_key("brdr", x$style), + rtf_key("brdrw", x$width), + rtf_key("brdrcf", border_color_value) + ) + } else { + "" + } } - } - ) %>% unlist() + ) + ) } else { tb_borders <- "" @@ -558,7 +562,7 @@ rtf_tbl_row <- function( x[[i]][1] <- rtf_paste0(rtf_raw(x[[i]][1]), rtf_raw(row_components[i])) } - x <- lapply(x, FUN = function(x) paste(x, collapse = "\n")) %>% unlist() + x <- unlist(lapply(x, FUN = function(x) paste(x, collapse = "\n"))) # Return a complete row of RTF table cells (marked as `rtf_text`) rtf_paste0( @@ -617,34 +621,37 @@ rtf_tbl_cell <- function( } cell_borders <- - vapply( - borders, - FUN.VALUE = character(1), - USE.NAMES = FALSE, - FUN = function(x) { + paste( + vapply( + borders, + FUN.VALUE = character(1), + USE.NAMES = FALSE, + FUN = function(x) { - if (is.numeric(x$color)) { - border_color_value <- x$color - } else { - border_color_value <- rtf_raw(paste0("<>")) - } + if (is.numeric(x$color)) { + border_color_value <- x$color + } else { + border_color_value <- rtf_raw(paste0("<>")) + } - rtf_paste0( - rtf_key("clbrdr", substr(x$direction, 1, 1)), - rtf_key("brdr", x$style), - rtf_key("brdrw", x$width), - rtf_key("brdrcf", border_color_value) - ) - } - ) %>% - paste(collapse = "") + rtf_paste0( + rtf_key("clbrdr", substr(x$direction, 1, 1)), + rtf_key("brdr", x$style), + rtf_key("brdrw", x$width), + rtf_key("brdrcf", border_color_value) + ) + } + ), + collapse = "" + ) } else { cell_borders <- "" } # Set background color if (!is.null(cell_background_color)) { - cell_background_color <- rtf_key("clcbpat", paste0("<>")) + cell_background_color <- + rtf_key("clcbpat", paste0("<>")) } else { cell_background_color <- "" } @@ -932,12 +939,7 @@ create_heading_component_rtf <- function(data) { unlist() if (is.null(col_widths)) { - - n_cols <- - boxh %>% - dplyr::filter(type %in% c("default", "stub")) %>% - nrow() - + n_cols <- nrow(dplyr::filter(boxh, type %in% c("default", "stub"))) col_widths <- rep("100%", n_cols) } @@ -958,14 +960,14 @@ create_heading_component_rtf <- function(data) { table_border_top_color <- dt_options_get_value(data, option = "table_border_top_color") if ("title" %in% footnotes_tbl$locname) { - footnote_title_marks <- footnotes_tbl %>% coalesce_marks(locname = "title") + footnote_title_marks <- coalesce_marks(fn_tbl = footnotes_tbl, locname = "title") footnote_title_marks <- footnote_title_marks$fs_id_c } else { footnote_title_marks <- "" } if ("subtitle" %in% footnotes_tbl$locname) { - footnote_subtitle_marks <- footnotes_tbl %>% coalesce_marks(locname = "subtitle") + footnote_subtitle_marks <- coalesce_marks(fn_tbl = footnotes_tbl, locname = "subtitle") footnote_subtitle_marks <- footnote_subtitle_marks$fs_id_c } else { footnote_subtitle_marks <- "" @@ -1354,8 +1356,10 @@ create_body_component_rtf <- function(data) { if (any(is.na(groups_rows_df$group_label))) { groups_rows_df <- - groups_rows_df %>% - dplyr::mutate(group_label = ifelse(is.na(group_label), "", group_label)) + dplyr::mutate( + groups_rows_df, + group_label = ifelse(is.na(group_label), "", group_label) + ) } row_groups_present <- nrow(groups_rows_df) > 0 @@ -1529,8 +1533,10 @@ create_body_component_rtf <- function(data) { if (group_id %in% names(list_of_summaries$summary_df_display_list)) { summary_df <- - list_of_summaries$summary_df_display_list[[group_id]] %>% - dplyr::select(.env$rowname_col_private, .env$default_vars) + dplyr::select( + list_of_summaries$summary_df_display_list[[group_id]], + .env$rowname_col_private, .env$default_vars + ) n_summary_rows <- seq_len(nrow(summary_df)) @@ -1604,8 +1610,10 @@ create_body_component_rtf <- function(data) { grand_summary_col %in% names(list_of_summaries$summary_df_display_list)) { grand_summary_df <- - list_of_summaries$summary_df_display_list[[grand_summary_col]] %>% - dplyr::select(.env$rowname_col_private, .env$default_vars) + dplyr::select( + list_of_summaries$summary_df_display_list[[grand_summary_col]], + .env$rowname_col_private, .env$default_vars + ) for (j in seq_len(nrow(grand_summary_df))) {