😎 Give your xaringan slides some style
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
2.9KB

  1. #' Add Extra CSS Styles
  2. #'
  3. #' Adds css elements to target `outfile`, typically a xaringanthemer css file.
  4. #' The `css` argument takes a list of CSS classes and definitions (see examples below)
  5. #' and appends CSS rules to `outfile`.
  6. #'
  7. #' @section css list:
  8. #' The `css` input must be a named list of css properties and values within a
  9. #' named list of class identifiers, for example
  10. #' `list(".class-id" = list("css-property" = "value"))`.
  11. #'
  12. #' @param css A named list of CSS definitions each containing a named list
  13. #' of CSS property-value pairs, i.e.
  14. #' `list(".class-id" = list("css-property" = "value"))`
  15. #'
  16. #' @examples
  17. #' style_extra_css(
  18. #' outfile = stdout(),
  19. #' css = list(
  20. #' ".red" = list(color = "red"),
  21. #' ".small" = list("font-size" = "90%"),
  22. #' ".full-width" = list(
  23. #' display = "flex",
  24. #' width = "100%",
  25. #' flex = "1 1 auto"
  26. #' )
  27. #' )
  28. #' )
  29. #'
  30. #' @inheritParams style_xaringan
  31. #' @export
  32. style_extra_css <- function(css, outfile = "xaringan-themer.css") {
  33. cat("\n\n/* Extra CSS */", list2css(css), file = outfile,
  34. append = TRUE, sep = "\n")
  35. }
  36. #' @inheritParams style_extra_css
  37. #' @keywords internal
  38. list2css <- function(css) {
  39. `%.%` <- function(x, y) paste0(x, y)
  40. error <- NULL
  41. if (is.null(names(css))) {
  42. stop("All elements in `css` list must be named", call. = FALSE)
  43. }
  44. if (purrr::vec_depth(css) != 3) {
  45. stop("`css` list must be a named list within a named list, e.g.:\n",
  46. ' list(".class-id" = list("css-property" = "value"))')
  47. }
  48. if (any(names(css) == "")) {
  49. not_named <- which(names(css) == "")
  50. if (length(not_named) > 1) stop(call. = FALSE,
  51. "All elements in `css` list must be named. Items ",
  52. paste(not_named, collapse = ", "), " are unnamed."
  53. ) else stop(call. = FALSE,
  54. "All elements in `css` list must be named. Item ", not_named, " is not named.")
  55. }
  56. child_unnamed <- purrr::map_lgl(purrr::map(css, ~ {is.null(names(.)) || names(.) == ""}), ~ any(.))
  57. if (any(child_unnamed)) {
  58. has_unnamed <- names(css)[child_unnamed]
  59. msg <- paste(
  60. "All properties of elements in `css` list must be named.",
  61. if (length(has_unnamed) > 1) "Elements" else "Element",
  62. paste(has_unnamed, collapse = ", "),
  63. if (length(has_unnamed) > 1) "have" else "has",
  64. "unnamed property or properties."
  65. )
  66. stop(msg, call. = FALSE)
  67. }
  68. purrr::map_chr(names(css), function(el) {
  69. paste(sep = "\n",
  70. el %.% " {",
  71. paste(
  72. purrr::map_chr(names(css[[el]]), function(prop) {
  73. " " %.% prop %.% ': ' %.% css[[el]][[prop]] %.% ';'
  74. }),
  75. collapse = "\n"
  76. ),
  77. "}"
  78. )
  79. })
  80. }
  81. list2fonts <- function(fonts) {
  82. if (inherits(fonts, "google_font")) {
  83. fonts <- list(fonts)
  84. }
  85. fonts <- purrr::map_chr(fonts, function(f) {
  86. if (inherits(f, "google_font")) {
  87. f$url
  88. } else if (inherits(f, "character")) {
  89. f
  90. } else NA_character_
  91. })
  92. paste0("@import url(", fonts[!is.na(fonts)], ");")
  93. }