😎 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.

131 lines
3.6KB

  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. #' @param append If `TRUE` output will be appended to `outfile`; otherwise,
  16. #' it will overwrite the contents of `outfile`.
  17. #'
  18. #' @examples
  19. #' style_extra_css(
  20. #' outfile = stdout(),
  21. #' css = list(
  22. #' ".red" = list(color = "red"),
  23. #' ".small" = list("font-size" = "90%"),
  24. #' ".full-width" = list(
  25. #' display = "flex",
  26. #' width = "100%",
  27. #' flex = "1 1 auto"
  28. #' )
  29. #' )
  30. #' )
  31. #' @inheritParams style_xaringan
  32. #' @export
  33. style_extra_css <- function(css, outfile = "xaringan-themer.css", append = TRUE) {
  34. x <- paste("\n\n/* Extra CSS */", list2css(css), sep = "\n")
  35. if (is.null(outfile)) return(x)
  36. cat(
  37. x,
  38. file = outfile,
  39. append = TRUE,
  40. sep = "\n"
  41. )
  42. }
  43. #' @inheritParams style_extra_css
  44. #' @keywords internal
  45. list2css <- function(css) {
  46. `%.%` <- function(x, y) paste0(x, y)
  47. error <- NULL
  48. if (is.null(names(css))) {
  49. stop("All elements in `css` list must be named", call. = FALSE)
  50. }
  51. if (purrr::vec_depth(css) != 3) {
  52. stop(
  53. "`css` list must be a named list within a named list, e.g.:\n",
  54. ' list(".class-id" = list("css-property" = "value"))'
  55. )
  56. }
  57. if (any(names(css) == "")) {
  58. not_named <- which(names(css) == "")
  59. if (length(not_named) > 1) {
  60. stop(
  61. call. = FALSE,
  62. "All elements in `css` list must be named. Items ",
  63. paste(not_named, collapse = ", "),
  64. " are unnamed."
  65. )
  66. } else {
  67. stop(
  68. call. = FALSE,
  69. "All elements in `css` list must be named. Item ",
  70. not_named,
  71. " is not named."
  72. )
  73. }
  74. }
  75. child_unnamed <- purrr::map_lgl(purrr::map(css, ~ {
  76. is.null(names(.)) || any(names(.) == "")
  77. }), ~ any(.))
  78. if (any(child_unnamed)) {
  79. has_unnamed <- names(css)[child_unnamed]
  80. msg <- paste(
  81. "All properties of elements in `css` list must be named.",
  82. if (length(has_unnamed) > 1) "Elements" else "Element",
  83. paste(has_unnamed, collapse = ", "),
  84. if (length(has_unnamed) > 1) "have" else "has",
  85. "unnamed property or properties."
  86. )
  87. stop(msg, call. = FALSE)
  88. }
  89. purrr::map_chr(names(css), function(el) {
  90. paste(
  91. sep = "\n",
  92. el %.% " {",
  93. paste(
  94. purrr::map_chr(names(css[[el]]), function(prop) {
  95. " " %.% prop %.% ": " %.% css[[el]][[prop]] %.% ";"
  96. }),
  97. collapse = "\n"
  98. ),
  99. "}"
  100. )
  101. })
  102. }
  103. list2fonts <- function(fonts) {
  104. if (
  105. length(setdiff(names(google_font('fam')), names(fonts))) == 0 &&
  106. !inherits(fonts, "google_font")
  107. ) {
  108. # concatenating a string and a google_font() provides a wacky list
  109. stop(
  110. "Multiple fonts in `extra_fonts` must be specified inside a `list()`.",
  111. call. = FALSE
  112. )
  113. }
  114. if (inherits(fonts, "google_font")) {
  115. fonts <- list(fonts)
  116. }
  117. fonts <- purrr::map_chr(fonts, function(f) {
  118. if (inherits(f, "google_font")) {
  119. f$url
  120. } else if (inherits(f, "character")) {
  121. f
  122. } else {
  123. NA_character_
  124. }
  125. })
  126. paste0("@import url(", fonts[!is.na(fonts)], ");")
  127. }