diff --git a/R/compile_scss.R b/R/compile_scss.R index 0499ddf48..282afd336 100644 --- a/R/compile_scss.R +++ b/R/compile_scss.R @@ -4,8 +4,15 @@ compile_scss <- function(data, id = NULL) { # Obtain the SCSS options table from `data` gt_options_tbl <- dt_options_get(data = data) %>% - subset(scss) %>% - subset(!is.na(value)) + dplyr::filter(scss) %>% + dplyr::filter(!is.na(value)) %>% + dplyr::mutate( + value = { + color_rows <- grepl("_color", .data$parameter) + value[color_rows] <- lapply(value[color_rows], html_color) + value + } + ) has_id <- !is.null(id) diff --git a/R/data_color.R b/R/data_color.R index 92f22d405..2e99b16f0 100644 --- a/R/data_color.R +++ b/R/data_color.R @@ -288,9 +288,20 @@ is_rgba_col <- function(colors) { grepl("^rgba\\(\\s*(?:[0-9]+?\\s*,\\s*){3}[0-9\\.]+?\\s*\\)$", colors) } +#' Are color values in hexadecimal format? +#' +#' This regex checks for valid hexadecimal colors in either the `#RRGGBB` and +#' `#RRGGBBAA` forms (not including shortened form `#RGB` here) +#' +#' @noRd +is_hex_col <- function(colors) { + + grepl("^#[0-9a-fA-F]{6}([0-9a-fA-F]{2})?$", colors) +} + #' For a background color, which foreground color provides better contrast? #' -#' The input for this function is a single color value in rgba() format. The +#' The input for this function is a single color value in 'rgba()' format. The #' output is a single color value in #RRGGBB hexadecimal format #' #' @noRd @@ -298,7 +309,7 @@ ideal_fgnd_color <- function(bgnd_color, light = "#FFFFFF", dark = "#000000") { - # Normalize color to hexadecimal color if it is in the rgba() string format + # Normalize color to hexadecimal color if it is in the 'rgba()' string format bgnd_color <- rgba_to_hex(colors = bgnd_color) # Normalize color to a #RRGGBB (stripping the alpha channel) @@ -314,9 +325,9 @@ ideal_fgnd_color <- function(bgnd_color, #' Convert colors in mixed formats (incl. rgba() strings) format to hexadecimal #' #' This function will accept colors in mixed formats and convert any in the -#' rgba() string format (e.g., "`rgba(255,170,0,0.5)`") to a hexadecimal format -#' the preserves the alpha information (#RRGGBBAA). This function is required -#' for the `ideal_fgnd_color()` function. +#' 'rgba()' string format (e.g., "`rgba(255,170,0,0.5)`") to a hexadecimal +#' format that preserves the alpha information (#RRGGBBAA). This function is +#' required for the `ideal_fgnd_color()` function. #' #' @noRd rgba_to_hex <- function(colors) { @@ -361,7 +372,7 @@ rgba_to_hex <- function(colors) { #' colors in hexadecimal format with or without an alpha component (either #' #RRGGBB or #RRGGBBAA). Output is the same length vector as the #' input but it will contain a mixture of either #RRGGBB colors (if the input -#' alpha value for a color is 1) or rgba() string format colors (if the input +#' alpha value for a color is 1) or 'rgba()' string format colors (if the input #' alpha value for a color is not 1). #' #' @noRd @@ -372,21 +383,67 @@ html_color <- function(colors, alpha = NULL) { stop("No values supplied in `colors` should be NA") } - # Utility function for creating rgba() color values - # from an RGBA color matrix (already subsetted to those - # rows where alpha < 1) - col_matrix_to_rgba <- function(color_matrix) { - - paste0( - "rgba(", - color_matrix[, "red"], ",", - color_matrix[, "green"], ",", - color_matrix[, "blue"], ",", - round(color_matrix[, "alpha"], 2), - ")" - ) + is_rgba <- is_rgba_col(colors) + is_hex <- is_hex_col(colors) + is_named <- !is_rgba & !is_hex + + colors[is_named] <- tolower(colors[is_named]) + + named_colors <- colors[is_named] + + if (length(named_colors) > 0) { + + # Ensure that all color names are in the set of X11/R color + # names or CSS color names + check_named_colors(named_colors) + + # Translate any CSS exclusive colors to hexadecimal values; + # there are nine CSS 3.0 named colors that don't belong to the + # set of X11/R color names (not included numbered variants and + # the numbered grays, those will be handled by `grDevices::col2rgb()`) + is_css_excl_named <- colors %in% names(css_exclusive_colors()) + + if (any(is_css_excl_named)) { + + # The `css_exclusive_colors()` function returns a named vector + # of the CSS colors not in the X11/R set; the names are the hexadecimal + # color values + colors[is_css_excl_named] <- + unname(css_exclusive_colors()[colors[is_css_excl_named]]) + } } + # Normalize all non-'rgba()' color values and combine + # with any preexisting 'rgba()' color values + colors[!is_rgba] <- + normalize_colors( + colors = colors[!is_rgba], + alpha = alpha + ) + + colors +} + +# Utility function for creating 'rgba()' color values +# from an RGBA color matrix (already subsetted to those +# rows where alpha < 1) +col_matrix_to_rgba <- function(color_matrix) { + + paste0( + "rgba(", + color_matrix[, "red"], ",", + color_matrix[, "green"], ",", + color_matrix[, "blue"], ",", + round(color_matrix[, "alpha"], 2), + ")" + ) +} + +# Utility function for generating hexadecimal or 'rgba()' colors (for IE11 +# compatibility with colors having some transparency) from hexadecimal color +# values and X11/R color names +normalize_colors <- function(colors, alpha) { + # Create a color matrix with an `alpha` column color_matrix <- t(grDevices::col2rgb(col = colors, alpha = TRUE)) color_matrix[, "alpha"] <- color_matrix[, "alpha"] / 255 @@ -418,3 +475,43 @@ html_color <- function(colors, alpha = NULL) { colors_html } + +css_exclusive_colors <- function() { + + color_tbl_subset <- css_colors[!css_colors$is_x11_color, ] + + color_values <- color_tbl_subset[["hexadecimal"]] + + color_values <- + stats::setNames( + color_values, + tolower(color_tbl_subset[["color_name"]]) + ) + + color_values +} + +valid_color_names <- function() { + c(tolower(grDevices::colors()), names(css_exclusive_colors())) +} + +check_named_colors <- function(named_colors) { + + named_colors <- tolower(named_colors) + + if (!all(named_colors %in% valid_color_names())) { + + invalid_colors <- base::setdiff(unique(named_colors), valid_color_names()) + + stop( + ifelse( + length(invalid_colors) > 1, + "Several invalid color names were ", + "An invalid color name was " + ), "used (", str_catalog(invalid_colors, conj = "and"), "):\n", + " * Only R/X11 color names and CSS 3.0 color names can be used", + call. = FALSE + ) + } +} + diff --git a/R/helpers.R b/R/helpers.R index 456678257..96d04e426 100644 --- a/R/helpers.R +++ b/R/helpers.R @@ -1790,16 +1790,15 @@ cell_text <- function(color = NULL, transform = NULL) { # Get all assigned values for the functions' arguments - style_names <- formals(cell_text) %>% names() - style_names <- mget(style_names) + style_names <- mget(names(formals(cell_text))) # Filter list by only the non-NULL (e.g., assigned with # value) elements - style_vals <- style_names %>% .[!vapply(., is.null, logical(1))] + style_vals <- style_names[!vapply(style_names, is.null, logical(1))] # Get a vector of argument names (`style_names`) for # validation purposes - style_names <- style_vals %>% names() + style_names <- names(style_vals) # # Validate textual styles values with `validate_style_in()` @@ -1851,12 +1850,18 @@ cell_text <- function(color = NULL, in_vector = c("uppercase", "lowercase", "capitalize") ) + # Transform the `color` value, if present, so that X11 color names + # can be used in all output contexts + if ("color" %in% style_names) { + style_vals$color <- html_color(colors = style_vals$color) + } + cell_style_structure(name = "cell_text", obj = style_vals) } cell_style_to_html.cell_text <- function(style) { - css <- style %>% unclass() + css <- unclass(style) css_names <- c( @@ -1940,9 +1945,9 @@ cell_fill <- function(color = "#D3D3D3", stop("If provided, `alpha` must be a single value", call. = FALSE) } - if (!is_rgba_col(color)) { - color <- html_color(colors = color, alpha = alpha) - } + # Transform the `color` value, if present, so that X11 color names + # can be used in all output contexts + color <- html_color(colors = color, alpha = alpha) style_vals <- list(color = color) @@ -2072,14 +2077,16 @@ cell_borders <- function(sides = "all", "bottom", "b", "all", "everything", "a" ))) { - stop("The `sides` vector for `cell_borders()` has to include one ", - "or more of the following keywords (or short forms):\n", - " * \"left\" (or: \"l\")\n", - " * \"right\" (or: \"r\")\n", - " * \"top\" (or: \"t\")\n", - " * \"bottom\" (or: \"b\")\n", - " * \"all\" (or: \"a\", \"everything\"", - call. = FALSE) + stop( + "The `sides` vector for `cell_borders()` has to include one ", + "or more of the following keywords (or short forms):\n", + " * \"left\" (or: \"l\")\n", + " * \"right\" (or: \"r\")\n", + " * \"top\" (or: \"t\")\n", + " * \"bottom\" (or: \"b\")\n", + " * \"all\" (or: \"a\", \"everything\"", + call. = FALSE + ) } # Resolve the selection of borders into a vector of diff --git a/R/sysdata.rda b/R/sysdata.rda index 408c69cea..9a2af11b9 100644 Binary files a/R/sysdata.rda and b/R/sysdata.rda differ diff --git a/data-raw/X06-css_colors.R b/data-raw/X06-css_colors.R new file mode 100644 index 000000000..58d94ba40 --- /dev/null +++ b/data-raw/X06-css_colors.R @@ -0,0 +1,159 @@ +library(tidyverse) + +css_colors <- + dplyr::tribble( + ~color_name, ~hexadecimal, ~category, + "IndianRed", "#CD5C5C", "Reds", + "LightCoral", "#F08080", "Reds", + "Salmon", "#FA8072", "Reds", + "DarkSalmon", "#E9967A", "Reds", + "LightSalmon", "#FFA07A", "Reds", + "Crimson", "#DC143C", "Reds", + "Red", "#FF0000", "Reds", + "FireBrick", "#B22222", "Reds", + "DarkRed", "#8B0000", "Reds", + "Pink", "#FFC0CB", "Pinks", + "LightPink", "#FFB6C1", "Pinks", + "HotPink", "#FF69B4", "Pinks", + "DeepPink", "#FF1493", "Pinks", + "MediumVioletRed", "#C71585", "Pinks", + "PaleVioletRed", "#DB7093", "Pinks", + "Coral", "#FF7F50", "Oranges", + "Tomato", "#FF6347", "Oranges", + "OrangeRed", "#FF4500", "Oranges", + "DarkOrange", "#FF8C00", "Oranges", + "Orange", "#FFA500", "Oranges", + "Gold", "#FFD700", "Yellows", + "Yellow", "#FFFF00", "Yellows", + "LightYellow", "#FFFFE0", "Yellows", + "LemonChiffon", "#FFFACD", "Yellows", + "LightGoldenrodYellow", "#FAFAD2", "Yellows", + "PapayaWhip", "#FFEFD5", "Yellows", + "Moccasin", "#FFE4B5", "Yellows", + "PeachPuff", "#FFDAB9", "Yellows", + "PaleGoldenrod", "#EEE8AA", "Yellows", + "Khaki", "#F0E68C", "Yellows", + "DarkKhaki", "#BDB76B", "Yellows", + "Lavender", "#E6E6FA", "Purples", + "Thistle", "#D8BFD8", "Purples", + "Plum", "#DDA0DD", "Purples", + "Violet", "#EE82EE", "Purples", + "Orchid", "#DA70D6", "Purples", + "Fuchsia", "#FF00FF", "Purples", + "Magenta", "#FF00FF", "Purples", + "MediumOrchid", "#BA55D3", "Purples", + "MediumPurple", "#9370DB", "Purples", + "BlueViolet", "#8A2BE2", "Purples", + "DarkViolet", "#9400D3", "Purples", + "DarkOrchid", "#9932CC", "Purples", + "DarkMagenta", "#8B008B", "Purples", + "Purple", "#800080", "Purples", + "RebeccaPurple", "#663399", "Purples", + "Indigo", "#4B0082", "Purples", + "MediumSlateBlue", "#7B68EE", "Purples", + "SlateBlue", "#6A5ACD", "Purples", + "DarkSlateBlue", "#483D8B", "Purples", + "GreenYellow", "#ADFF2F", "Greens", + "Chartreuse", "#7FFF00", "Greens", + "LawnGreen", "#7CFC00", "Greens", + "Lime", "#00FF00", "Greens", + "LimeGreen", "#32CD32", "Greens", + "PaleGreen", "#98FB98", "Greens", + "LightGreen", "#90EE90", "Greens", + "MediumSpringGreen", "#00FA9A", "Greens", + "SpringGreen", "#00FF7F", "Greens", + "MediumSeaGreen", "#3CB371", "Greens", + "SeaGreen", "#2E8B57", "Greens", + "ForestGreen", "#228B22", "Greens", + "Green", "#008000", "Greens", + "DarkGreen", "#006400", "Greens", + "YellowGreen", "#9ACD32", "Greens", + "OliveDrab", "#6B8E23", "Greens", + "Olive", "#808000", "Greens", + "DarkOliveGreen", "#556B2F", "Greens", + "MediumAquamarine", "#66CDAA", "Greens", + "DarkSeaGreen", "#8FBC8F", "Greens", + "LightSeaGreen", "#20B2AA", "Greens", + "DarkCyan", "#008B8B", "Greens", + "Teal", "#008080", "Greens", + "Aqua", "#00FFFF", "Blues/Cyans", + "Cyan", "#00FFFF", "Blues/Cyans", + "LightCyan", "#E0FFFF", "Blues/Cyans", + "PaleTurquoise", "#AFEEEE", "Blues/Cyans", + "Aquamarine", "#7FFFD4", "Blues/Cyans", + "Turquoise", "#40E0D0", "Blues/Cyans", + "MediumTurquoise", "#48D1CC", "Blues/Cyans", + "DarkTurquoise", "#00CED1", "Blues/Cyans", + "CadetBlue", "#5F9EA0", "Blues/Cyans", + "SteelBlue", "#4682B4", "Blues/Cyans", + "LightSteelBlue", "#B0C4DE", "Blues/Cyans", + "PowderBlue", "#B0E0E6", "Blues/Cyans", + "LightBlue", "#ADD8E6", "Blues/Cyans", + "SkyBlue", "#87CEEB", "Blues/Cyans", + "LightSkyBlue", "#87CEFA", "Blues/Cyans", + "DeepSkyBlue", "#00BFFF", "Blues/Cyans", + "DodgerBlue", "#1E90FF", "Blues/Cyans", + "CornflowerBlue", "#6495ED", "Blues/Cyans", + "RoyalBlue", "#4169E1", "Blues/Cyans", + "Blue", "#0000FF", "Blues/Cyans", + "MediumBlue", "#0000CD", "Blues/Cyans", + "DarkBlue", "#00008B", "Blues/Cyans", + "Navy", "#000080", "Blues/Cyans", + "MidnightBlue", "#191970", "Blues/Cyans", + "Cornsilk", "#FFF8DC", "Browns", + "BlanchedAlmond", "#FFEBCD", "Browns", + "Bisque", "#FFE4C4", "Browns", + "NavajoWhite", "#FFDEAD", "Browns", + "Wheat", "#F5DEB3", "Browns", + "BurlyWood", "#DEB887", "Browns", + "Tan", "#D2B48C", "Browns", + "RosyBrown", "#BC8F8F", "Browns", + "SandyBrown", "#F4A460", "Browns", + "Goldenrod", "#DAA520", "Browns", + "DarkGoldenrod", "#B8860B", "Browns", + "Peru", "#CD853F", "Browns", + "Chocolate", "#D2691E", "Browns", + "SaddleBrown", "#8B4513", "Browns", + "Sienna", "#A0522D", "Browns", + "Brown", "#A52A2A", "Browns", + "Maroon", "#800000", "Browns", + "White", "#FFFFFF", "Whites", + "Snow", "#FFFAFA", "Whites", + "Honeydew", "#F0FFF0", "Whites", + "MintCream", "#F5FFFA", "Whites", + "Azure", "#F0FFFF", "Whites", + "AliceBlue", "#F0F8FF", "Whites", + "GhostWhite", "#F8F8FF", "Whites", + "WhiteSmoke", "#F5F5F5", "Whites", + "Seashell", "#FFF5EE", "Whites", + "Beige", "#F5F5DC", "Whites", + "OldLace", "#FDF5E6", "Whites", + "FloralWhite", "#FFFAF0", "Whites", + "Ivory", "#FFFFF0", "Whites", + "AntiqueWhite", "#FAEBD7", "Whites", + "Linen", "#FAF0E6", "Whites", + "LavenderBlush", "#FFF0F5", "Whites", + "MistyRose", "#FFE4E1", "Whites", + "Gainsboro", "#DCDCDC", "Greys", + "LightGray", "#D3D3D3", "Greys", + "LightGrey", "#D3D3D3", "Greys", + "Silver", "#C0C0C0", "Greys", + "DarkGray", "#A9A9A9", "Greys", + "DarkGrey", "#A9A9A9", "Greys", + "Gray", "#808080", "Greys", + "Grey", "#808080", "Greys", + "DimGray", "#696969", "Greys", + "DimGrey", "#696969", "Greys", + "LightSlateGray", "#778899", "Greys", + "LightSlateGrey", "#778899", "Greys", + "SlateGray", "#708090", "Greys", + "SlateGrey", "#708090", "Greys", + "DarkSlateGray", "#2F4F4F", "Greys", + "DarkSlateGrey", "#2F4F4F", "Greys", + "Black", "#000000", "Greys" + ) %>% + dplyr::mutate( + is_x11_color = ifelse( + tolower(color_name) %in% grDevices::colors(), TRUE, FALSE + ) + ) diff --git a/data-raw/zz_process_datasets_ext.R b/data-raw/zz_process_datasets_ext.R index 76de11a30..76854648a 100644 --- a/data-raw/zz_process_datasets_ext.R +++ b/data-raw/zz_process_datasets_ext.R @@ -5,10 +5,12 @@ source("data-raw/X02-currency_symbols.R") source("data-raw/X03-locales.R") source("data-raw/X04-palettes_strips.R") source("data-raw/X05-google_fonts.R") +source("data-raw/X06-css_colors.R") # Create internal datasets (`sysdata.rda`) usethis::use_data( currencies, currency_symbols, locales, palettes_strips, google_font_tbl, google_styles_tbl, google_axes_tbl, + css_colors, internal = TRUE, overwrite = TRUE ) diff --git a/tests/testthat/test-data_color.R b/tests/testthat/test-data_color.R index 09139eb40..ced5b4282 100644 --- a/tests/testthat/test-data_color.R +++ b/tests/testthat/test-data_color.R @@ -262,7 +262,7 @@ test_that("the correct color values are obtained when defining a palette", { expect_equal(12) # Expect color values to be of either the #RRGGBB or the - # rgba() CSS value form + # 'rgba()' CSS value form tbl_html_rrggbbaa %>% selection_value("style") %>% gsub("(background-color: |; color: .*)", "", .) %>% @@ -317,7 +317,7 @@ test_that("the correct color values are obtained when defining a palette", { expect_equal(12) # Expect color values to be of either the #RRGGBB or the - # rgba() CSS value form + # 'rgba()' CSS value form tbl_html_rrggbbaa_mixed %>% selection_value("style") %>% gsub("(background-color: |; color: .*)", "", .) %>% @@ -373,7 +373,7 @@ test_that("the correct color values are obtained when defining a palette", { expect_equal(12) # Expect color values to be of either the #RRGGBB or the - # rgba() CSS value form + # 'rgba()' CSS value form tbl_html_rrggbbaa_mixed_2 %>% selection_value("style") %>% gsub("(background-color: |; color: .*)", "", .) %>% @@ -500,7 +500,7 @@ test_that("the correct color values are obtained when defining a palette", { render_as_html() %>% xml2::read_html() - # Expect color values to be entirely in the rgba() CSS value form + # Expect color values to be entirely in the 'rgba()' CSS value form tbl_html_5 %>% selection_value("style") %>% gsub("(background-color: |; color: .*)", "", .) %>% @@ -525,7 +525,7 @@ test_that("the correct color values are obtained when defining a palette", { unique() %>% expect_equal("80") - # Converting the rgba() values back into hexadecimal form and + # Converting the 'rgba()' values back into hexadecimal form and # removing the alpha channel (by use of `html_color()`) is expected # to give us color values in the `pal_12` #RRGGBB color vector ( @@ -717,7 +717,7 @@ test_that("the correct color values are obtained when using a color fn", { render_as_html() %>% xml2::read_html() - # Expect color values to be entirely in the rgba() CSS value form + # Expect color values to be entirely in the 'rgba()' CSS value form tbl_html_2 %>% selection_value("style") %>% gsub("(background-color: |; color: .*)", "", .) %>% @@ -917,7 +917,7 @@ test_that("the correct color values are obtained when using a color fn", { render_as_html() %>% xml2::read_html() - # Expect color values to be entirely in the rgba() CSS value form + # Expect color values to be entirely in the 'rgba()' CSS value form tbl_html_6 %>% selection_value("style") %>% gsub("(background-color: |; color: .*)", "", .) %>% @@ -1039,7 +1039,7 @@ test_that("the various color utility functions work correctly", { c_rgba <- c("rgba(255,170,0,0.5)", "rgba(255,187,52,1)", "rgba(20,255,0,1.0)") # Expect that the `is_rgba_col()` function will identify valid - # color strings in the rgba() CSS format + # color strings in the 'rgba()' CSS format is_rgba_col( colors = c( c_rgba, @@ -1062,14 +1062,14 @@ test_that("the various color utility functions work correctly", { # Expect that the `rgba_to_hex()` function reliably returns # color strings in the hexadecimal format of #RRGGBBAA - # when supplied rgba() format strings + # when supplied 'rgba()' format strings expect_equal( rgba_to_hex(colors = c_rgba), c("#FFAA0080", "#FFBB34FF", "#14FF00FF") ) # Expect that the `rgba_to_hex()` utility function will pass through *any* - # strings that don't conform to the rgba() string format + # strings that don't conform to the 'rgba()' string format expect_equal( rgba_to_hex(colors = c(c_rgba, c_hex, "test")), c("#FFAA0080", "#FFBB34FF", "#14FF00FF", c_hex, "test") @@ -1077,7 +1077,7 @@ test_that("the various color utility functions work correctly", { # Expect that the `html_color()` utility function will reliably return # color strings in either the hexadecimal format of #RRGGBB or as - # rgba() format strings (when `alpha` is NULL, which is the default) + # 'rgba()' format strings (when `alpha` is NULL, which is the default) expect_equal( html_color(colors = c(c_name, c_hex, c_hex_a)), c( @@ -1099,9 +1099,8 @@ test_that("the various color utility functions work correctly", { ) ) - # Expect that the `html_color()` utility function will reliably return - # color strings entirely in the rgba() string format when `alpha` is non-NULL - # and less than `1` + # Expect that `html_color()` will reliably return color strings entirely + # in the 'rgba()' string format when `alpha` is non-NULL and less than `1` expect_equal( html_color(colors = c(c_name, c_hex, c_hex_a), alpha = 0.5), c( @@ -1113,7 +1112,18 @@ test_that("the various color utility functions work correctly", { ) ) - # Furthermore, expect that all alpha values in the rgba() strings are of the + # Expect that `html_color()` won't alter any 'rgba()' strings passed to it + expect_equal( + html_color(colors = c(c_name, c_hex, c_hex_a, c_rgba), alpha = 1), + c( + "#FF0000", "#FF6347", "#CD6889", "#32CD32", "#DBDBDB", "#0000FF", + c_hex, + "#FF235D", "#AA253A", "#F3F300", "#D2D721", + c_rgba + ) + ) + + # Furthermore, expect that all alpha values in the 'rgba()' strings are of the # same value when `alpha` is non-NULL and less than `1` html_color(colors = c(c_name, c_hex, c_hex_a), alpha = 0.5) %>% gsub("(?:^.*,|\\))", "", .) %>% @@ -1121,6 +1131,48 @@ test_that("the various color utility functions work correctly", { length() %>% expect_equal(1) + # Expect that CSS color names not present as an R/X11 color will still work + expect_equal( + html_color(colors = names(css_exclusive_colors())), + c( + "#DC143C", "#FF00FF", "#663399", + "#4B0082", "#00FF00", "#808000", + "#008080", "#00FFFF", "#C0C0C0" + ) + ) + expect_equal( + html_color(colors = rev(names(css_exclusive_colors()))), + c( + "#C0C0C0", "#00FFFF", "#008080", + "#808000", "#00FF00", "#4B0082", + "#663399", "#FF00FF", "#DC143C" + ) + ) + + # Expect that mixed names will work in `html_color()` (all the + # previous types plus the CSS exclusive names here, which are + # 'rebeccapurple' and 'lime') + expect_equal( + html_color(colors = c(c_name, c_hex, c_hex_a, "rebeccapurple", "lime")), + c( + "#FF0000", "#FF6347", "#CD6889", "#32CD32", "#DBDBDB", "#0000FF", + "#FFAA00", "#FFBB34", "#AD552E", "#900019", "rgba(255,35,93,0.38)", + "rgba(170,37,58,0.44)", "#F3F300", "rgba(210,215,33,0.06)", + "#663399", "#00FF00" + ) + ) + + # Expect that the CSS exclusive names will still work if names have mixed case + expect_equal( + html_color(colors = c(c_name, c_hex, c_hex_a, "RebeccaPurple", "Lime")), + c( + "#FF0000", "#FF6347", "#CD6889", "#32CD32", "#DBDBDB", "#0000FF", + "#FFAA00", "#FFBB34", "#AD552E", "#900019", "rgba(255,35,93,0.38)", + "rgba(170,37,58,0.44)", "#F3F300", "rgba(210,215,33,0.06)", + "#663399", "#00FF00" + ) + ) + # Expect an error if an NA value is provided anywhere as input expect_error( html_color(colors = c(c_name, c_hex, c_hex_a, NA_character_)) @@ -1141,10 +1193,56 @@ test_that("the various color utility functions work correctly", { expect_error( html_color(colors = c(c_name, c_hex, "FF04E2", c_hex_a)) ) + + # Don't expect an error if 'rgba()'-format colors are passed to `html_color` expect_error( + regexp = NA, html_color(colors = c(c_name, c_hex, c_hex_a, "rgba(210,215,33,0.5)")) ) + # Expect that the `normalize_colors()` utility function will reliably return + # color strings in the hexadecimal format of #RRGGBB when `alpha` is 1 + # (which needs to be set) + expect_equal( + normalize_colors(colors = c(c_name, c_hex, c_hex_a), alpha = 1), + c( + "#FF0000", "#FF6347", "#CD6889", "#32CD32", "#DBDBDB", "#0000FF", + "#FFAA00", "#FFBB34", "#AD552E", "#900019", "#FF235D", "#AA253A", + "#F3F300", "#D2D721" + ) + ) + + # Expect that the `normalize_colors()` utility function will reliably return + # color strings entirely in the 'rgba()' format of #RRGGBB when `alpha` is + # not `1` + expect_equal( + normalize_colors(colors = c(c_name, c_hex, c_hex_a), alpha = 0.5), + c( + "rgba(255,0,0,0.5)", "rgba(255,99,71,0.5)", "rgba(205,104,137,0.5)", + "rgba(50,205,50,0.5)", "rgba(219,219,219,0.5)", "rgba(0,0,255,0.5)", + "rgba(255,170,0,0.5)", "rgba(255,187,52,0.5)", "rgba(173,85,46,0.5)", + "rgba(144,0,25,0.5)", "rgba(255,35,93,0.5)", "rgba(170,37,58,0.5)", + "rgba(243,243,0,0.5)", "rgba(210,215,33,0.5)" + ) + ) + + # Expect that the `normalize_colors()` utility function will reliably return + # color strings in either hexadecimal or in 'rgba()' when `alpha` is set + # to NULL (any #RRGGBBAA colors will move to 'rgba()') + expect_equal( + normalize_colors(colors = c(c_name, c_hex, c_hex_a), alpha = NULL), + c( + "#FF0000", "#FF6347", "#CD6889", "#32CD32", "#DBDBDB", "#0000FF", + "#FFAA00", "#FFBB34", "#AD552E", "#900019", "rgba(255,35,93,0.38)", + "rgba(170,37,58,0.44)", "#F3F300", "rgba(210,215,33,0.06)" + ) + ) + + # Expect an error if 'rgba()'-format colors are passed to `normalize_colors()` + expect_error( + normalize_colors(colors = c(c_name, c_hex, c_hex_a, "rgba(210,215,33,0.5)")) + ) + # Expect that the `ideal_fgnd_color()` function returns a vector containing # either a light color ("#FFFFFF") or a dark color ("#000000") based on the # input colors; this should work with all of the color formats that @@ -1398,7 +1496,7 @@ test_that("the `cell_fill()` function accepts colors of various types", { length() %>% expect_equal(1) - # Expect all color values to be of the rgba() string format + # Expect all color values to be of the 'rgba()' string format tbl_html_3 %>% selection_value("style") %>% gsub("(?:background-color: |;)", "", .) %>% @@ -1426,7 +1524,7 @@ test_that("the `cell_fill()` function accepts colors of various types", { length() %>% expect_equal(1) - # Expect all color values to be of the rgba() string format + # Expect all color values to be of the 'rgba()' string format tbl_html_4 %>% selection_value("style") %>% gsub("(?:background-color: |;)", "", .) %>% @@ -1466,7 +1564,7 @@ test_that("the `cell_fill()` function accepts colors of various types", { length() %>% expect_equal(1) - # Expect all color values to be of the rgba() string format + # Expect all color values to be of the 'rgba()' string format tbl_html_5 %>% selection_value("style") %>% gsub("(?:background-color: |;)", "", .) %>% diff --git a/tests/testthat/test-location_cells.R b/tests/testthat/test-location_cells.R index d5cda56bf..54e01d00d 100644 --- a/tests/testthat/test-location_cells.R +++ b/tests/testthat/test-location_cells.R @@ -434,7 +434,7 @@ test_that("styles are correctly applied to HTML output with location functions", render_as_html() %>% tidy_grepl( paste0( - "The Title.*", + "The Title.*", "The Subtitle" ) ) %>% @@ -459,7 +459,7 @@ test_that("styles are correctly applied to HTML output with location functions", tidy_grepl( paste0( "The Title.*", - "The Subtitle" + "The Subtitle" ) ) %>% expect_true() @@ -490,8 +490,8 @@ test_that("styles are correctly applied to HTML output with location functions", render_as_html() %>% tidy_grepl( paste0( - "The Title.*", - "The Subtitle" + "The Title.*", + "The Subtitle" ) ) %>% expect_true() @@ -520,7 +520,7 @@ test_that("styles are correctly applied to HTML output with location functions", tidy_grepl( paste0( ".*?", "spanner" ) @@ -552,8 +552,8 @@ test_that("styles are correctly applied to HTML output with location functions", paste0( ".*", "value_2.*", - "value_3.*", - "value_1" + "value_3.*", + "value_1" ) ) %>% expect_true() @@ -579,7 +579,7 @@ test_that("styles are correctly applied to HTML output with location functions", render_as_html() %>% tidy_grepl( paste0( - "A.*", + "A.*", "B" ) ) %>% @@ -603,7 +603,7 @@ test_that("styles are correctly applied to HTML output with location functions", tidy_grepl( paste0( "A.*", - "B" + "B" ) ) %>% expect_true() @@ -625,8 +625,8 @@ test_that("styles are correctly applied to HTML output with location functions", render_as_html() %>% tidy_grepl( paste0( - "A.*", - "B" + "A.*", + "B" ) ) %>% expect_true() @@ -652,7 +652,7 @@ test_that("styles are correctly applied to HTML output with location functions", render_as_html() %>% tidy_grepl( paste0( - "1.*", + "1.*", "2" ) ) %>% @@ -675,7 +675,7 @@ test_that("styles are correctly applied to HTML output with location functions", render_as_html() %>% tidy_grepl( paste0( - "1.*", + "1.*", "2" ) ) %>% @@ -699,7 +699,7 @@ test_that("styles are correctly applied to HTML output with location functions", tidy_grepl( paste0( "1.*", - "2" + "2" ) ) %>% expect_true() @@ -722,7 +722,7 @@ test_that("styles are correctly applied to HTML output with location functions", tidy_grepl( paste0( "1.*", - "2" + "2" ) ) %>% expect_true() @@ -744,8 +744,8 @@ test_that("styles are correctly applied to HTML output with location functions", render_as_html() %>% tidy_grepl( paste0( - "1.*", - "2" + "1.*", + "2" ) ) %>% expect_true() @@ -769,7 +769,7 @@ test_that("styles are correctly applied to HTML output with location functions", xml2::read_html() %>% selection_value("style") %>% expect_equal( - rep("color: white; font-size: 20px; background-color: #FFA500;", 6) + rep("color: #FFFFFF; font-size: 20px; background-color: #FFA500;", 6) ) # diff --git a/tests/testthat/test-tab_options.R b/tests/testthat/test-tab_options.R index 3623b8a9f..ef4bb7b3c 100644 --- a/tests/testthat/test-tab_options.R +++ b/tests/testthat/test-tab_options.R @@ -1558,6 +1558,219 @@ test_that("the row striping options work correctly", { 0) }) +test_that("certain X11 color names are replaced in HTML tables", { + + # Here, the `gray85` color supplied to `heading.background.color` + # is transformed to the #D9D9D9 color and it appears in the rule: + # + # .gt_heading { + # background-color: #D9D9D9; + # ... + # } + # + # and it appears only once in the raw HTML + expect_match( + tbl %>% + gt() %>% + tab_options(heading.background.color = "gray85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + + # Similar testing with the `turquoise2` color, which is replaced + # with a hexadecimal color (#00E5EE) + expect_match( + tbl %>% + gt() %>% + tab_options(heading.background.color = "turquoise2") %>% + as_raw_html(inline_css = FALSE), + "#00E5EE" + ) + + # Testing with `grey85` (synonym of `gray85`) with all possible + # `*.color` options in `tab_options()` + expect_match( + tbl %>% gt() %>% tab_options(table.background.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(table.font.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(table.border.top.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(table.border.right.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(table.border.bottom.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(table.border.left.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(heading.background.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(heading.border.bottom.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(heading.border.lr.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(column_labels.background.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(column_labels.vlines.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(column_labels.border.top.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(column_labels.border.bottom.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(column_labels.border.lr.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(row_group.background.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(row_group.border.top.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(row_group.border.bottom.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(row_group.border.left.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(row_group.border.right.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(table_body.hlines.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(table_body.vlines.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(table_body.border.top.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(table_body.border.bottom.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(stub.background.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(stub.border.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(summary_row.background.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(summary_row.border.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(grand_summary_row.background.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(grand_summary_row.border.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(footnotes.background.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(footnotes.border.bottom.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(footnotes.border.lr.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(source_notes.background.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(source_notes.border.bottom.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(source_notes.border.lr.color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) + expect_match( + tbl %>% gt() %>% tab_options(row.striping.background_color = "grey85") %>% + as_raw_html(inline_css = FALSE), + "#D9D9D9" + ) +}) + test_that("vertical padding across several table parts can be applied", { testthat::local_edition(3) diff --git a/tests/testthat/test-tab_style.R b/tests/testthat/test-tab_style.R index d1762f2f0..15a1763ac 100644 --- a/tests/testthat/test-tab_style.R +++ b/tests/testthat/test-tab_style.R @@ -132,7 +132,7 @@ test_that("a gt table can store the correct style statements", { .[[1]] %>% .$cell_text %>% .$color %>% - expect_equal("white") + expect_equal("#FFFFFF") # Apply left-alignment to the table title tbl_html <- diff --git a/tests/testthat/test-table_parts.R b/tests/testthat/test-table_parts.R index e6e3d71c7..b44e2f20b 100644 --- a/tests/testthat/test-table_parts.R +++ b/tests/testthat/test-table_parts.R @@ -881,7 +881,7 @@ test_that("a gt table contains custom styles at the correct locations", { # Expect that the stubhead label is styled tbl_html %>% - rvest::html_nodes("[style='background-color: #0000FF; color: white;']") %>% + rvest::html_nodes("[style='background-color: #0000FF; color: #FFFFFF;']") %>% rvest::html_text("[class='gt_col_heading gt_columns_bottom_border gt_left]") %>% expect_equal("cars") @@ -899,13 +899,13 @@ test_that("a gt table contains custom styles at the correct locations", { # Expect that the summary cell (`Mercs`::`sum`/`hp`) is styled tbl_html %>% - rvest::html_nodes("[style='background-color: #00FF00; color: white;']") %>% + rvest::html_nodes("[style='background-color: #00FF00; color: #FFFFFF;']") %>% rvest::html_text("[class='gt_row gt_right gt_summary_row']") %>% expect_equal("943.00") # Expect that the grand summary cell (`sum`/`hp`) is styled tbl_html %>% - rvest::html_nodes("[style='background-color: #A020F0; color: white;']") %>% + rvest::html_nodes("[style='background-color: #A020F0; color: #FFFFFF;']") %>% rvest::html_text("[class='gt_row gt_grand_summary_row']") %>% expect_equal("4,694.00") @@ -944,7 +944,7 @@ test_that("a gt table contains custom styles at the correct locations", { # Expect that the row caption `Merc 240D` has a cell background that # is ultimately steelblue, and, the font the white tbl_html %>% - rvest::html_nodes("[style='background-color: #4682B4; color: white;']") %>% + rvest::html_nodes("[style='background-color: #4682B4; color: #FFFFFF;']") %>% rvest::html_text() %>% expect_equal("Merc 240D") @@ -959,7 +959,7 @@ test_that("a gt table contains custom styles at the correct locations", { # Expect that the `Mazdas` row group label # cell has a red background and white text tbl_html %>% - rvest::html_nodes("[style='background-color: #FF0000; color: white;']") %>% + rvest::html_nodes("[style='background-color: #FF0000; color: #FFFFFF;']") %>% rvest::html_text() %>% expect_equal("Mazdas")