├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ ├── pkg-maintenance.yaml │ └── pkgdown.yaml ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── R ├── color.R ├── css.R ├── ggplot2.R ├── style_duo.R ├── style_duo_accent.R ├── style_duo_accent_inverse.R ├── style_extra_css.R ├── style_font_default.R ├── style_mono_accent.R ├── style_mono_accent_inverse.R ├── style_mono_dark.R ├── style_mono_light.R ├── style_solarized_dark.R ├── style_solarized_light.R ├── style_xaringan.R ├── sysdata.rda ├── utils.R ├── utils_theme-gen.R ├── xaringanthemer-deprecated.R ├── xaringanthemer-package.R └── zzz.R ├── README.Rmd ├── README.md ├── cran-comments.md ├── data-raw └── theme_template_variables.R ├── index.Rmd ├── index.md ├── inst ├── fonts │ ├── GlacialIndifferenceRegular.ttf │ └── OFL.txt ├── resources │ ├── template.css │ └── template_title-slide.css ├── rmarkdown │ └── templates │ │ └── xaringanthemer │ │ ├── skeleton │ │ ├── .gitignore │ │ └── skeleton.Rmd │ │ └── template.yaml └── scripts │ ├── generate_theme_functions.R │ └── style_xaringan_body.R ├── make.R ├── man-roxygen ├── style-usage.R ├── style_duo.R ├── style_duo_accent.R ├── style_duo_accent_inverse.R ├── style_mono_accent.R ├── style_mono_accent_inverse.R ├── style_mono_dark.R ├── style_mono_light.R ├── style_solarized_dark.R ├── style_solarized_light.R ├── style_xaringan.R └── theme_params.R ├── man ├── apply_alpha.Rd ├── choose_dark_or_light.Rd ├── figures │ ├── index-theme_xaringan_demo-1.png │ ├── lifecycle-archived.svg │ ├── lifecycle-defunct.svg │ ├── lifecycle-deprecated.svg │ ├── lifecycle-experimental.svg │ ├── lifecycle-maturing.svg │ ├── lifecycle-questioning.svg │ ├── lifecycle-stable.svg │ ├── lifecycle-superseded.svg │ └── logo.png ├── fragments │ ├── _colors.Rmd │ ├── _fonts.Rmd │ ├── _installation.Rmd │ ├── _quick-intro.Rmd │ ├── _tagline-gif.Rmd │ ├── _thanks.Rmd │ └── _themes.Rmd ├── google_font.Rd ├── google_language_codes.Rd ├── lighten_darken_color.Rd ├── scale_xaringan.Rd ├── style_duo.Rd ├── style_duo_accent.Rd ├── style_duo_accent_inverse.Rd ├── style_extra_css.Rd ├── style_mono_accent.Rd ├── style_mono_accent_inverse.Rd ├── style_mono_dark.Rd ├── style_mono_light.Rd ├── style_solarized_dark.Rd ├── style_solarized_light.Rd ├── style_xaringan.Rd ├── theme_xaringan.Rd ├── theme_xaringan_base.Rd ├── theme_xaringan_get_value.Rd ├── theme_xaringan_inverse.Rd ├── theme_xaringan_set_defaults.Rd ├── xaringanthemer-deprecated.Rd └── xaringanthemer-package.Rd ├── pkgdown ├── _pkgdown.yml ├── extra.css └── favicon │ ├── apple-touch-icon-120x120.png │ ├── apple-touch-icon-152x152.png │ ├── apple-touch-icon-180x180.png │ ├── apple-touch-icon-60x60.png │ ├── apple-touch-icon-76x76.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ └── favicon.ico ├── tests ├── testthat.R └── testthat │ ├── _snaps │ └── utils.md │ ├── css │ ├── duo-header_bg.css │ ├── duo.css │ ├── duo_accent.css │ ├── duo_accent_inverse.css │ ├── google_fonts.css │ ├── mono_accent.css │ ├── mono_accent_inverse.css │ ├── mono_dark.css │ ├── mono_light-header_bg.css │ ├── mono_light.css │ ├── solarized_dark-header_bg.css │ ├── solarized_dark.css │ ├── solarized_light.css │ └── xaringan.css │ ├── helper-session.R │ ├── test-color.R │ ├── test-css.R │ ├── test-ggplot2.R │ ├── test-helpers.R │ ├── test-style_extra_css.R │ ├── test-style_xaringan.R │ ├── test-themes.R │ ├── test-utils.R │ └── test-xaringanthemer-deprecated.R ├── vignettes ├── .gitignore ├── fonts.Rmd ├── ggplot2-themes.Rmd ├── template-variables.Rmd ├── themes.Rmd └── xaringanthemer.Rmd └── xaringanthemer.Rproj /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^README\.Rmd$ 4 | ^LICENSE\.md$ 5 | ^make\.R$ 6 | ^vignettes/singles$ 7 | ^tests_$ 8 | ^_.+$ 9 | ^docs$ 10 | ^index\.Rmd$ 11 | ^man-roxygen$ 12 | ^tic\.R$ 13 | ^appveyor\.yml$ 14 | ^\.travis\.yml$ 15 | ^pkgdown$ 16 | ^vignettes/fonts\.Rmd$ 17 | ^vignettes/themes\.Rmd$ 18 | ^data-raw$ 19 | ^.history$ 20 | ^doc$ 21 | ^Meta$ 22 | ^index\.md$ 23 | ^\.ccache$ 24 | ^\.github$ 25 | ^clang-.* 26 | ^gfortran.* 27 | ^cran-comments\.md$ 28 | ^CRAN-RELEASE$ 29 | ^CRAN-SUBMISSION$ 30 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | r-depends.rds 2 | *.html 3 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - {os: macOS-latest, r: 'release'} 22 | - {os: windows-latest, r: 'release'} 23 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 24 | - {os: ubuntu-latest, r: 'release'} 25 | - {os: ubuntu-latest, r: 'oldrel-1'} 26 | 27 | env: 28 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 29 | R_KEEP_PKG_SOURCE: yes 30 | 31 | steps: 32 | - uses: actions/checkout@v2 33 | 34 | - uses: r-lib/actions/setup-pandoc@v2 35 | 36 | - uses: r-lib/actions/setup-r@v2 37 | with: 38 | r-version: ${{ matrix.config.r }} 39 | http-user-agent: ${{ matrix.config.http-user-agent }} 40 | use-public-rspm: true 41 | 42 | - uses: r-lib/actions/setup-r-dependencies@v2 43 | with: 44 | extra-packages: any::rcmdcheck 45 | needs: check 46 | 47 | - uses: r-lib/actions/check-r-package@v2 48 | with: 49 | upload-snapshots: true 50 | -------------------------------------------------------------------------------- /.github/workflows/pkg-maintenance.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | pull_request: 3 | push: 4 | branches: main 5 | 6 | name: Package Maintenance 7 | 8 | jobs: 9 | auto-pkg-maintenance: 10 | uses: rstudio/education-workflows/.github/workflows/auto-pkg-maintenance.yaml@v1 11 | with: 12 | extra-packages: any::showtext, any::sysfonts, any::ggplot2 13 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | release: 9 | types: [published] 10 | workflow_dispatch: 11 | 12 | name: pkgdown 13 | 14 | jobs: 15 | pkgdown: 16 | runs-on: ubuntu-latest 17 | # Only restrict concurrency for non-PR jobs 18 | concurrency: 19 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} 20 | env: 21 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 22 | steps: 23 | - uses: actions/checkout@v2 24 | 25 | - uses: r-lib/actions/setup-pandoc@v2 26 | 27 | - uses: r-lib/actions/setup-r@v2 28 | with: 29 | use-public-rspm: true 30 | 31 | - uses: r-lib/actions/setup-r-dependencies@v2 32 | with: 33 | extra-packages: any::pkgdown, local::. 34 | needs: website 35 | 36 | - name: Build site 37 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) 38 | shell: Rscript {0} 39 | 40 | - name: Deploy to GitHub pages 🚀 41 | if: github.event_name != 'pull_request' 42 | uses: JamesIves/github-pages-deploy-action@4.1.4 43 | with: 44 | clean: false 45 | branch: gh-pages 46 | folder: docs 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | inst/doc 6 | _tests 7 | _stuff 8 | 9 | .DS_Store 10 | README.html 11 | 12 | # vscode 13 | .history/ 14 | 15 | # Directories that start with _ 16 | /_*/ 17 | 18 | ## https://github.com/github/gitignore/blob/master/R.gitignore 19 | # History files 20 | .Rhistory 21 | .Rapp.history 22 | 23 | # Session Data files 24 | .RData 25 | 26 | # Example code in package build process 27 | *-Ex.R 28 | 29 | # Output files from R CMD build 30 | /*.tar.gz 31 | 32 | # Output files from R CMD check 33 | /*.Rcheck/ 34 | 35 | # RStudio files 36 | .Rproj.user/ 37 | 38 | # produced vignettes 39 | vignettes/*.html 40 | vignettes/*.pdf 41 | 42 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 43 | .httr-oauth 44 | 45 | # knitr and R markdown default cache directories 46 | /*_cache/ 47 | /cache/ 48 | 49 | # Temporary files created by R markdown 50 | *.utf8.md 51 | *.knit.md 52 | 53 | # Shiny token, see https://shiny.rstudio.com/articles/shinyapps.html 54 | rsconnect/ 55 | 56 | ## https://github.com/github/gitignore/blob/master/Global/macOS.gitignore 57 | # General 58 | .DS_Store 59 | .AppleDouble 60 | .LSOverride 61 | 62 | # Icon must end with two \r 63 | Icon 64 | 65 | 66 | # Thumbnails 67 | ._* 68 | 69 | # Files that might appear in the root of a volume 70 | .DocumentRevisions-V100 71 | .fseventsd 72 | .Spotlight-V100 73 | .TemporaryItems 74 | .Trashes 75 | .VolumeIcon.icns 76 | .com.apple.timemachine.donotpresent 77 | 78 | # Directories potentially created on remote AFP share 79 | .AppleDB 80 | .AppleDesktop 81 | Network Trash Folder 82 | Temporary Items 83 | .apdisk 84 | doc 85 | Meta 86 | docs/ 87 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Type: Package 2 | Package: xaringanthemer 3 | Title: Custom 'xaringan' CSS Themes 4 | Version: 0.4.3.9000 5 | Authors@R: 6 | person("Garrick", "Aden-Buie", , "garrick@adenbuie.com", role = c("aut", "cre"), 7 | comment = c(ORCID = "0000-0002-7111-0077")) 8 | Description: Create beautifully color-coordinated and customized themes 9 | for your 'xaringan' slides, without writing any CSS. Complete your 10 | slide theme with 'ggplot2' themes that match the font and colors used 11 | in your slides. Customized styles can be created directly in your 12 | slides' 'R Markdown' source file or in a separate external script. 13 | License: MIT + file LICENSE 14 | URL: https://pkg.garrickadenbuie.com/xaringanthemer/, 15 | https://github.com/gadenbuie/xaringanthemer 16 | BugReports: https://github.com/gadenbuie/xaringanthemer/issues 17 | Depends: 18 | R (>= 2.10) 19 | Imports: 20 | colorspace, 21 | glue, 22 | methods, 23 | purrr, 24 | utils, 25 | whisker 26 | Suggests: 27 | callr, 28 | ggplot2, 29 | knitr, 30 | mockery, 31 | rmarkdown, 32 | scales, 33 | showtext, 34 | sysfonts, 35 | testthat (>= 2.1.0), 36 | xaringan 37 | VignetteBuilder: 38 | knitr 39 | Config/Needs/website: gadenbuie/grkgdown, pkgdown 40 | Config/testthat/edition: 3 41 | Encoding: UTF-8 42 | Roxygen: list(markdown = TRUE) 43 | RoxygenNote: 7.3.2 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2020 2 | COPYRIGHT HOLDER: Garrick Aden-Buie 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2020 Garrick Aden-Buie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(print,google_font) 4 | S3method(print,xaringanthemer_default) 5 | export(apply_alpha) 6 | export(choose_dark_or_light) 7 | export(darken_color) 8 | export(duo) 9 | export(duo_accent) 10 | export(duo_accent_inverse) 11 | export(google_font) 12 | export(google_language_codes) 13 | export(lighten_color) 14 | export(mono_accent) 15 | export(mono_accent_inverse) 16 | export(mono_dark) 17 | export(mono_light) 18 | export(scale_xaringan_color_continuous) 19 | export(scale_xaringan_color_discrete) 20 | export(scale_xaringan_colour_continuous) 21 | export(scale_xaringan_colour_discrete) 22 | export(scale_xaringan_continuous) 23 | export(scale_xaringan_discrete) 24 | export(scale_xaringan_fill_continuous) 25 | export(scale_xaringan_fill_discrete) 26 | export(solarized_dark) 27 | export(solarized_light) 28 | export(style_duo) 29 | export(style_duo_accent) 30 | export(style_duo_accent_inverse) 31 | export(style_extra_css) 32 | export(style_mono_accent) 33 | export(style_mono_accent_inverse) 34 | export(style_mono_dark) 35 | export(style_mono_light) 36 | export(style_solarized_dark) 37 | export(style_solarized_light) 38 | export(style_xaringan) 39 | export(theme_xaringan) 40 | export(theme_xaringan_base) 41 | export(theme_xaringan_get_value) 42 | export(theme_xaringan_inverse) 43 | export(theme_xaringan_restore_defaults) 44 | export(theme_xaringan_set_defaults) 45 | export(write_extra_css) 46 | export(write_xaringan_theme) 47 | export(xaringanthemer_font_default) 48 | importFrom(grDevices,col2rgb) 49 | importFrom(grDevices,hsv) 50 | importFrom(grDevices,rgb) 51 | importFrom(grDevices,rgb2hsv) 52 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # xaringanthemer (development version) 2 | 3 | # xaringanthemer 0.4.3 4 | 5 | - Update the spelling of `colour` for compatibility with ggplot2 >= 3.5.1 (@teunbrand #79). 6 | 7 | # xaringanthemer 0.4.2 8 | 9 | - Use `.table-unshaded` class on a tables to prevent xaringanthemer's table heading and row shading (thanks @dragonattheend, #74) 10 | 11 | - Use `inverse_text_color` as the default for `inverse_header_color` in most places (#60) 12 | 13 | - Fixed a bug that happened when providing named values for key theme colors (#62) 14 | 15 | - Re-document for CRAN 16 | 17 | 18 | # xaringanthemer 0.4.1 19 | 20 | * Text alignment in code blocks in `left`, `center`, or `right` aligned slides 21 | no longer matches the slide text. Instead, the code block width is reduced, 22 | if possible, and the block is pushed to the left, center, or right using 23 | margins (#68). 24 | 25 | * The style functions are now more permissive about color names in the `color` 26 | argument. Color names should be valid CSS classes that can also be used as CSS 27 | variable names, but the `style_` function only stops with an error if the 28 | color name contains spaces. (@jdlom #69) 29 | 30 | * Fixed an issue that caused problems rendering the xaringanthemer R Markdown 31 | template if the showtext package isn't installed (thanks @beatrizmilz, #65). 32 | 33 | # xaringanthemer 0.4.0 34 | 35 | * Added `text_bold_font_weight` argument to xaringanthemer style functions with 36 | a corresponding CSS rule setting the `font-weight` property of `` 37 | elements (thanks @matiasandina, #50). 38 | 39 | * The style functions gain a `link_decoration` argument to set the 40 | [`text-decoration`](https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration) 41 | property for links (#57). 42 | 43 | * Set slide number font size in `rem` so that increasing the font size at the 44 | slide level doesn't result in giant slide numbers (#53). 45 | 46 | * The xaringanthemer slide skeleton (R Markdown template) will now render when 47 | packages that are used in the template but not in xaringanthemer's Imports are 48 | not installed (#52). 49 | 50 | * xaringanthemer no longer sets the `fig.showtext` chunk option when the 51 | showtext package isn't installed and also when `fig.showtext = FALSE` 52 | (thanks @mikedecr #36, #56). 53 | 54 | # xaringanthemes 0.3.4 55 | 56 | * Maintenance release to avoid issues with upcoming R 4.1.0 (#49) 57 | 58 | # xaringanthemer 0.3.3 59 | 60 | * Add `inverse_link_color` to control color of links on inverse slides 61 | (thanks @dmi3kno, #44) 62 | 63 | * .pull-right[] now clears floats just for its immediate sibling 64 | 65 | * Add `header_font_family_fallback` to control fallback fonts for headings 66 | (thanks @mattwarkentin, #41) 67 | 68 | * New xaringanthemer presentation skeleton with a kitchen sink of typical 69 | slide elements with the goal of making it easier to preview new themes 70 | during development. 71 | 72 | # xaringanthemer 0.3.0 73 | 74 | * Adds `theme_xaringan()`, a ggplot2 theme that automatically uses the colors 75 | and font styles of your xaringanthemer style. Also adds 76 | `scale_xaringan_discrete()` and `scale_xaringan_continuous()` functions that 77 | use your slides' primary colors for the color or fill aesthetics. These theme 78 | functions can recover the primary colors used in a xaringanthemer (>= 0.3.0) 79 | CSS file even if you don't call the style function directly in your slides. 80 | 81 | * Renamed all xaringanthemer functions that create CSS styles to use the 82 | prefix "`style_`". For example, `mono_light()` is now `style_mono_light()`. 83 | Additionally, `write_xaringan_theme()` is now `style_xaringan()` and 84 | `write_extra_css()` is `style_extra_css()`. Overall, this change makes the 85 | xarignanthemer API much cleaner and easier to navigate. Previous function 86 | names are deprecated but still work. 87 | 88 | * Added `background_header_auto` parameter that adds a background under the 89 | first `h1` element (i.e. `# Slide Title`) on a slide. When enabled, the 90 | background is added automatically to slides, as long as they aren't 91 | `inverse`, `center`, `middle`, or `bottom`-styled slides. When disabled, 92 | you can still enable slide title headers by adding the `header_background` 93 | class to a slide. (thanks, @Btibert3, #10) 94 | 95 | * The underlying template now uses the `whisker` package. 96 | 97 | * xaringanthemer styles now use CSS variables throughout. Most of the settings 98 | used in defining a style are stored in CSS variables. The variable names are 99 | documented in their corresponding arguments. For example, the color selected 100 | for `background_color` is stored in the variable `--background-color`. These 101 | variables can be used in custom CSS rules or in other arguments in any style 102 | functions, for example as `var(--background-color)`. 103 | 104 | * xaringanthemer now uses a different set of default fonts for heading and body 105 | fonts. The new defaults use [Cabin](https://fonts.google.com/specimen/Cabin) 106 | for headings and [Noto Sans](https://fonts.google.com/specimen/Noto+Sans) for 107 | body text. These fonts are easier to read on screens and at a distance during 108 | presentations, and they support a wide variety of languages and weights. 109 | Another reason for the change is that the xaringan (remarkjs) default body 110 | font, _Droid Serif_, is no longer officially included in Google Fonts. 111 | 112 | * Additional colors can be provided in the `colors` argument, which takes a 113 | named vector of colors. The names become both CSS classes and CSS variables 114 | that can be used throughout your slide styles. For example, 115 | `colors = c(red = "#d34213")` creates a `.red` CSS class for red foreground 116 | text, a `.bg-red` CSS class for a red background, and a `--red` CSS variable 117 | that can be referenced as `var(--red)` in any `_color` argument of your style 118 | function. 119 | 120 | 121 | ## Bugfixes and Improvements 122 | 123 | * Better handling of multiple `extra_fonts`, including improved error messages. 124 | (Thanks @pat-s, #19). 125 | 126 | * `style_extra_css()` (previously `write_extra_css()`) gained an `append` 127 | argument so that it can append to or overwrite an existing file (thanks @pat-s, #17). 128 | 129 | * The underlying tibble holding the theme template variables was updated to 130 | work with `tibble 3.0.0` (thanks @techisdead, @SymbolixAU, #32). 131 | 132 | * The `css-help` vignette was removed and may be re-written in the future. 133 | 134 | * Style function arguments that accept CSS property values are now documented in 135 | the argument documentation, including a link to the MDN web docs page for the 136 | CSS property or value (#33, thanks @TrashBirdEcology #18). 137 | 138 | * Style functions return the CSS text directly when `outfile = NULL`. 139 | -------------------------------------------------------------------------------- /R/color.R: -------------------------------------------------------------------------------- 1 | #' @title Generate lighter or darker version of a color 2 | #' @description Produces a linear blend of the color with white or black. 3 | #' @param color_hex A character string representing a hex color 4 | #' @param strength The "strength" of the blend with white or black, 5 | #' where 0 is entirely the original color and 1 is entirely white 6 | #' (`lighten_color()`) or black (`darken_color()`). 7 | #' @examples 8 | #' blue <- "#0e6ba8" 9 | #' blue_light <- lighten_color(blue, strength = 0.33) 10 | #' blue_dark <- darken_color(blue, strength = 0.33) 11 | #' 12 | #' if (requireNamespace("scales", quietly = TRUE)) { 13 | #' scales::show_col(c(blue_light, blue, blue_dark)) 14 | #' } 15 | #' @return A character string with the lightened or darkened color in 16 | #' hexadecimal format. 17 | #' @name lighten_darken_color 18 | NULL 19 | 20 | #' @rdname lighten_darken_color 21 | #' @export 22 | lighten_color <- function(color_hex, strength = 0.7) { 23 | stopifnot(strength >= 0 && strength <= 1) 24 | color_rgb <- col2rgb(color_hex)[, 1] 25 | color_rgb <- (1 - strength) * color_rgb + strength * 255 26 | rgb(color_rgb[1], color_rgb[2], color_rgb[3], maxColorValue = 255) 27 | } 28 | 29 | #' @rdname lighten_darken_color 30 | #' @export 31 | darken_color <- function(color_hex, strength = 0.8) { 32 | stopifnot(strength >= 0 && strength <= 1) 33 | color_rgb <- col2rgb(color_hex)[, 1] 34 | color_rgb <- (1 - strength) * color_rgb 35 | rgb(color_rgb[1], color_rgb[2], color_rgb[3], maxColorValue = 255) 36 | } 37 | 38 | #' @title Add alpha to hex color 39 | #' @description Applies alpha (or opacity) to a color in hexadecimal form by 40 | #' converting opacity in the `[0, 1]` range to hex in the `[0, 255]` range 41 | #' and appending to the hex color. 42 | #' @inheritParams lighten_darken_color 43 | #' @param opacity Desired opacity of the output color 44 | #' @examples 45 | #' blue <- "#0e6ba8" 46 | #' blue_transparent <- apply_alpha(blue) 47 | #' 48 | #' if (requireNamespace("scales", quietly = TRUE)) { 49 | #' scales::show_col(c(blue, blue_transparent)) 50 | #' } 51 | #' @return A character string with added opacity level as hexadecimal characters. 52 | #' @export 53 | apply_alpha <- function(color_hex, opacity = 0.5) { 54 | paste0(color_hex, as.hexmode(round(255 * opacity, 0))) 55 | } 56 | 57 | adjust_value_color <- function(color_hex, strength = 0.5) { 58 | color_hsv <- rgb2hsv(col2rgb(color_hex))[, 1] 59 | color_hsv["v"] <- strength 60 | hsv(color_hsv[1], color_hsv[2], color_hsv[3]) 61 | } 62 | 63 | #' Choose dark or light color 64 | #' 65 | #' Takes a color input as `x` and returns either the black or white color (or 66 | #' expression) if dark or light text should be used over the input color for 67 | #' best contrast. Follows W3C Recommendations. 68 | #' 69 | #' @references 70 | #' @param x The background color (hex) 71 | #' @param black Text or foreground color, e.g. "#222" or 72 | #' `substitute(darken_color(x, 0.8))`, if black text provides the best contrast. 73 | #' @param white Text or foreground color or expression, e.g. "#EEE" or 74 | #' `substitute(lighten_color(x, 0.8))`, if white text provides the best contrast. 75 | #' @examples 76 | #' light_green <- "#c4d6b0" 77 | #' contrast_green <- choose_dark_or_light(light_green) 78 | #' dark_purple <- "#381d2a" 79 | #' contrast_purple <- choose_dark_or_light(dark_purple) 80 | #' 81 | #' if (requireNamespace("scales", quietly = TRUE)) { 82 | #' scales::show_col(c(light_green, contrast_green, dark_purple, contrast_purple)) 83 | #' } 84 | #' @return The `black` color or `white` color according to which color provides 85 | #' the greates contrast with the input color. 86 | #' 87 | #' @export 88 | choose_dark_or_light <- function(x, black = "#000000", white = "#FFFFFF") { 89 | if (is_light_color(x)) eval(black) else eval(white) 90 | } 91 | 92 | is_light_color <- function(x) { 93 | # this function returns TRUE if the given color 94 | # is light-colored and requires dark text 95 | color_rgb <- col2rgb(x)[, 1] 96 | # from https://stackoverflow.com/a/3943023/2022615 97 | color_rgb <- color_rgb / 255 98 | color_rgb[color_rgb <= 0.03928] <- color_rgb[color_rgb <= 0.03928] / 12.92 99 | color_rgb[color_rgb > 0.03928] <- ((color_rgb[color_rgb > 0.03928] + 0.055) / 1.055)^2.4 100 | lum <- t(c(0.2126, 0.7152, 0.0722)) %*% color_rgb 101 | lum[1, 1] > 0.179 102 | } 103 | 104 | prepare_colors <- function(colors = NULL) { 105 | if (is.null(colors) || length(colors) < 1) return(NULL) 106 | 107 | if (is.null(names(colors))) { 108 | stop( 109 | "`colors` must have names corresponding to valid CSS classes", 110 | call. = FALSE 111 | ) 112 | } 113 | 114 | if (any(grepl("\\s", names(colors)))) { 115 | stop( 116 | "Color names in `colors` must be valid CSS classes", 117 | " and cannot contain spaces", 118 | call. = FALSE) 119 | } 120 | 121 | maybe_bad_css <- unique(grep("^[_-]|[ .>~*:|+}/]", names(colors), value = TRUE)) 122 | if (length(maybe_bad_css) > 0) { 123 | warning( 124 | "Color names in `colors` should be valid CSS classes: ", 125 | paste0("'", maybe_bad_css, "'", collapse = ", "), 126 | call. = FALSE 127 | ) 128 | } 129 | 130 | whisker::iteratelist(colors, "color_name") 131 | } 132 | 133 | full_length_hex <- function(x) { 134 | varname <- substitute(x) 135 | bad_hex_msg <- str_wrap( 136 | "`", deparse(varname), "` is not a hexadecimal color: \"", x, "\". ", 137 | "theme_xaringan() requires colors to be specified in hexadecimal format.", 138 | " If you used valid CSS colors in your xaringan theme, please convert ", 139 | "these colors to hex format, e.g. \"#1a2b3c\"." 140 | ) 141 | check_color_is_hex(x, stop, bad_hex_msg) 142 | x <- sub("^#", "", x) 143 | if (nchar(x) == 3) { 144 | x <- strsplit(x, character(0))[[1]] 145 | x <- rep(x, each = 2) 146 | x <- paste(x, collapse = "") 147 | } 148 | paste0("#", x) 149 | } 150 | 151 | check_color_is_hex <- function( 152 | color, 153 | throw = warning, 154 | msg = "{color} is not a hexadecimal color" 155 | ) { 156 | is_probably_hex <- grepl("^#", color) && 157 | !grepl("[^#0-9a-fA-F]", color) && 158 | nchar(sub("^#", "", color)) %in% c(3, 6) 159 | if (!is_probably_hex) { 160 | msg <- glue::glue(msg) 161 | if (!is.null(throw)) throw(str_wrap(msg), call. = FALSE) 162 | } 163 | is_probably_hex 164 | } 165 | -------------------------------------------------------------------------------- /R/css.R: -------------------------------------------------------------------------------- 1 | read_css_vars <- function(file = NULL) { 2 | if (is.null(file)) { 3 | css_candidates <- find_xaringan_themer_css() 4 | file <- choose_xaringan_themer_css(css_candidates) 5 | } 6 | 7 | css_get_root(file) 8 | } 9 | 10 | find_xaringan_themer_css <- function() { 11 | # finds xaringan themer files within or below current working directory 12 | # and is only ever intended to be called in that situation 13 | css_files <- list.files(pattern = "css$", recursive = TRUE, full.names = TRUE) 14 | css_files_head <- purrr::map(css_files, readLines, n = 5) 15 | is_xt <- grepl(pattern = "generated by xaringanthemer", css_files_head, fixed = TRUE) 16 | 17 | css_files[is_xt] 18 | } 19 | 20 | choose_xaringan_themer_css <- function(css_candidates = character(0)) { 21 | if (!length(css_candidates)) { 22 | stop("Unable to locate a xaringanthemer css file.", call. = FALSE) 23 | } else if (length(css_candidates) == 1) { 24 | file <- css_candidates 25 | } else if (length(css_candidates) > 1) { 26 | is_xaringan_themer_css <- grepl("xaringan-themer.css", css_candidates, fixed = TRUE) 27 | if (any(is_xaringan_themer_css)) { 28 | file <- css_candidates[is_xaringan_themer_css][1] 29 | } else { 30 | file <- css_candidates[1] 31 | message(glue::glue("Using xaringanthemer theme in {file}")) 32 | } 33 | } 34 | file 35 | } 36 | 37 | css_get_root <- function(file) { 38 | x <- readLines(file, warn = FALSE) 39 | x <- paste(x, collapse = "\n") 40 | where <- regexpr(":root\\s*\\{[^}]+\\}", x) 41 | if (where < 0) return(NULL) 42 | x <- substr(x, where, where + attr(where, "match.length")) 43 | x <- strsplit(x, "\n")[[1]] 44 | m <- regexec("--(.+):\\s*(.+?);", x) 45 | x <- regmatches(x, m) 46 | x <- purrr::compact(x) 47 | vars <- gsub("-", "_", purrr::map_chr(x, `[`, 2)) 48 | values <- purrr::map(x, `[`, 3) 49 | names(values) <- vars 50 | for (font_type in c("text", "header", "code")) { 51 | font_is_google <- paste0(font_type, "_font_is_google") 52 | values[[font_is_google]] <- if (!is.null(values[[font_is_google]])) { 53 | values[[font_is_google]] %in% c("1", "TRUE", "true", "yes") 54 | } else FALSE 55 | } 56 | values 57 | } 58 | 59 | css_get_padding <- function(x) { 60 | stopifnot(length(x) == 1) 61 | x <- trimws(x) 62 | x <- as.list(strsplit(x, " ")[[1]]) 63 | stopifnot(length(x) %in% c(1, 2, 4)) 64 | names(x) <- c("top", "right", "bottom", "left")[seq_along(x)] 65 | list( 66 | top = x$top, 67 | right = x$right %||% x$top, 68 | bottom = x$bottom %||% x$top, 69 | left = x$left %||% x$right %||% x$top 70 | ) 71 | } 72 | -------------------------------------------------------------------------------- /R/style_extra_css.R: -------------------------------------------------------------------------------- 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 | #' @param heading Heading added above extra CSS. Use `NULL` to disable. 18 | #' 19 | #' @examples 20 | #' style_extra_css( 21 | #' outfile = stdout(), 22 | #' css = list( 23 | #' ".red" = list(color = "red"), 24 | #' ".small" = list("font-size" = "90%"), 25 | #' ".full-width" = list( 26 | #' display = "flex", 27 | #' width = "100%", 28 | #' flex = "1 1 auto" 29 | #' ) 30 | #' ) 31 | #' ) 32 | #' @inheritParams style_xaringan 33 | #' @export 34 | style_extra_css <- function( 35 | css, 36 | outfile = "xaringan-themer.css", 37 | append = TRUE, 38 | heading = "Extra CSS" 39 | ) { 40 | has_heading <- !is.null(heading) 41 | x <- paste0( 42 | if (has_heading) paste0("/* ", heading, " */\n"), 43 | paste(list2css(css), collapse = "\n") 44 | ) 45 | if (append) x <- paste0(if (has_heading) "\n\n" else "\n", x) 46 | if (is.null(outfile)) return(x) 47 | cat( 48 | x, 49 | file = outfile, 50 | append = append, 51 | sep = "\n" 52 | ) 53 | invisible(x) 54 | } 55 | 56 | #' @inheritParams style_extra_css 57 | #' @keywords internal 58 | list2css <- function(css) { 59 | `%.%` <- function(x, y) paste0(x, y) 60 | error <- NULL 61 | if (is.null(names(css))) { 62 | stop("All elements in `css` list must be named", call. = FALSE) 63 | } 64 | if (purrr::pluck_depth(css) != 3) { 65 | stop(str_wrap( 66 | "`css` list must be a named list within a named list, e.g.:\n", 67 | ' list(".class-id" = list("css-property" = "value"))' 68 | )) 69 | } 70 | if (any(names(css) == "")) { 71 | not_named <- which(names(css) == "") 72 | if (length(not_named) > 1) { 73 | stop(str_wrap( 74 | call. = FALSE, 75 | "All elements in `css` list must be named. Items ", 76 | paste(not_named, collapse = ", "), 77 | " are unnamed." 78 | )) 79 | } else { 80 | stop(str_wrap( 81 | call. = FALSE, 82 | "All elements in `css` list must be named. Item ", 83 | not_named, 84 | " is not named." 85 | )) 86 | } 87 | } 88 | child_unnamed <- purrr::map_lgl(purrr::map(css, ~ { 89 | is.null(names(.)) || any(names(.) == "") 90 | }), ~ any(.)) 91 | if (any(child_unnamed)) { 92 | has_unnamed <- names(css)[child_unnamed] 93 | msg <- paste( 94 | "All properties of elements in `css` list must be named.", 95 | if (length(has_unnamed) > 1) "Elements" else "Element", 96 | paste(has_unnamed, collapse = ", "), 97 | if (length(has_unnamed) > 1) "have" else "has", 98 | "unnamed property or properties." 99 | ) 100 | stop(str_wrap(msg), call. = FALSE) 101 | } 102 | 103 | x <- purrr::imap_chr(css, function(rules, selector) { 104 | paste( 105 | sep = "\n", 106 | selector %.% " {", 107 | paste( 108 | purrr::imap_chr(rules, function(value, prop) { 109 | " " %.% prop %.% ": " %.% value %.% ";" 110 | }), 111 | collapse = "\n" 112 | ), 113 | "}" 114 | ) 115 | }) 116 | unname(x) 117 | } 118 | 119 | list2fonts <- function(fonts) { 120 | if ( 121 | length(setdiff(names(google_font('fam')), names(fonts))) == 0 && 122 | !inherits(fonts, "google_font") 123 | ) { 124 | # concatenating a string and a google_font() provides a wacky list 125 | stop( 126 | "Multiple fonts in `extra_fonts` must be specified inside a `list()`.", 127 | call. = FALSE 128 | ) 129 | } 130 | if (inherits(fonts, "google_font")) { 131 | fonts <- list(fonts) 132 | } 133 | fonts <- purrr::map_chr(fonts, function(f) { 134 | if (inherits(f, "google_font")) { 135 | f$url 136 | } else if (inherits(f, "character")) { 137 | f 138 | } else { 139 | NA_character_ 140 | } 141 | }) 142 | paste0("@import url(", fonts[!is.na(fonts)], ");") 143 | } 144 | -------------------------------------------------------------------------------- /R/style_font_default.R: -------------------------------------------------------------------------------- 1 | #' @describeIn style_xaringan Default values for font family, weight, URLs and 2 | #' font fallbacks. 3 | #' @param font_arg A font argument from the \pkg{xaringanthemer} `style_` 4 | #' function family. 5 | #' @export 6 | xaringanthemer_font_default <- function(font_arg) { 7 | x <- switch( 8 | font_arg, 9 | text_font_family = "Noto Sans", 10 | text_font_weight = "normal", 11 | text_font_url = "https://fonts.googleapis.com/css?family=Noto+Sans:400,400i,700,700i&display=swap", 12 | text_font_family_fallback = "-apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, Ubuntu, roboto, noto, segoe ui, arial", 13 | header_font_family = "Cabin", 14 | header_font_weight = "600", 15 | header_font_url = "https://fonts.googleapis.com/css?family=Cabin:600,600i&display=swap", 16 | code_font_family = "Source Code Pro", 17 | code_font_url = "https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700&display=swap", 18 | code_font_family_fallback = "Menlo, Consolas, Monaco, Liberation Mono, Lucida Console", 19 | stop("unknown font_arg: ", font_arg) 20 | ) 21 | class(x) <- c("xaringanthemer_default", class(x)) 22 | x 23 | } 24 | 25 | #' @export 26 | print.xaringanthemer_default <- function(x, ...) { 27 | print(unclass(x)) 28 | } 29 | -------------------------------------------------------------------------------- /R/sysdata.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/xaringanthemer/51b100a9a42808ae1afc8761dfe262e38845d3e2/R/sysdata.rda -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | `%||%` <- function(x, y) if (is.null(x)) y else x 2 | 3 | `%??%` <- function(x, y) if (!is.null(x)) y else NULL 4 | 5 | requires_package <- function(pkg = "ggplot2", fn = "", required = TRUE) { 6 | raise <- if (required) stop else warning 7 | if (!requireNamespace(pkg, quietly = TRUE)) { 8 | msg <- paste0( 9 | "`", 10 | pkg, 11 | "` is ", 12 | if (required) "required " else "suggested ", 13 | if (fn != "") paste0("by ", fn, "() ")[1], 14 | "but is not installed." 15 | ) 16 | raise(msg, call. = FALSE) 17 | return(invisible(FALSE)) 18 | } 19 | invisible(TRUE) 20 | } 21 | 22 | #' @keywords internal 23 | call_style_xaringan <- function() { 24 | paste0( 25 | "style_xaringan(", 26 | paste(names(formals(style_xaringan)), collapse = ", "), 27 | ")" 28 | ) 29 | } 30 | 31 | #' Specify Google Font 32 | #' 33 | #' Builds Google Fonts URL from family name. Extra weights are given in the 34 | #' `...` parameters. Languages can be specified in `languages` and must one or 35 | #' more of the language codes as given by `google_language_codes()`. 36 | #' 37 | #' @examples 38 | #' google_font("Josefin Sans", "400", "400i", "600i", "700") 39 | #' google_font("Josefin Sans", languages = c("latin-ext", "vietnamese")) 40 | #' @param family Font family 41 | #' @param ... Font weights to include, example "400", "400i" 42 | #' @param languages Font languages to include (dependent on the font.) See 43 | #' [google_language_codes()]. 44 | #' @return A `"google_font"` object. 45 | #' @export 46 | google_font <- function(family, ..., languages = NULL) { 47 | base <- "https://fonts.googleapis.com/css?family=" 48 | weights <- if (length(list(...))) paste(c(...), collapse = ",") 49 | languages <- if (!is.null(languages)) paste(google_language_codes(languages), collapse = ",") 50 | structure( 51 | list( 52 | family = family, 53 | weights = weights, 54 | languages = languages, 55 | url = paste0( 56 | base, 57 | gsub(" ", "+", family), 58 | if (!is.null(weights)) paste0(":", weights), 59 | if (!is.null(languages)) paste0("&subset=", languages), 60 | "&display=swap" 61 | ) 62 | ), 63 | class = "google_font" 64 | ) 65 | } 66 | 67 | is_google_font <- function(x) inherits(x, "google_font") 68 | 69 | #' @title List Valid Google Language Codes 70 | #' @description Gives a list of valid Language Codes for Google Fonts, or 71 | #' validates that the language codes given are valid. 72 | #' @seealso [google_font()] 73 | #' @param language_codes Vector of potential Google language codes 74 | #' @return A vector of Google Font language codes matching `language_codes`. 75 | #' @export 76 | google_language_codes <- function( 77 | language_codes = c( 78 | "latin", 79 | "latin-ext", 80 | "sinhala", 81 | "greek", 82 | "hebrew", 83 | "vietnamese", 84 | "cyrillic", 85 | "cyrillic-ext", 86 | "devanagari", 87 | "arabic", 88 | "khmer", 89 | "tamil", 90 | "greek-ext", 91 | "thai", 92 | "bengali", 93 | "gujarati", 94 | "oriya", 95 | "malayalam", 96 | "gurmukhi", 97 | "kannada", 98 | "telugu", 99 | "myanmar" 100 | )) { 101 | unique(match.arg(language_codes, several.ok = TRUE)) 102 | } 103 | 104 | #' @export 105 | print.google_font <- function(x, ...) { 106 | cat( 107 | "Family: ", 108 | x$family, 109 | if (!is.null(x$weights)) paste("\nWeights:", x$weights), 110 | if (!is.null(x$languages)) paste("\nLangs: ", x$languages), 111 | "\nURL: ", 112 | x$url 113 | ) 114 | } 115 | 116 | quote_elements_w_spaces <- function(x) { 117 | x <- strsplit(x, ", ?")[[1]] 118 | has_space <- grepl("\\w \\w", x) 119 | not_quoted <- grepl("^\\w.+\\w$", x) 120 | x[has_space & not_quoted] <- paste0("'", x[has_space & not_quoted], "'") 121 | paste(x, collapse = ", ") 122 | } 123 | 124 | str_wrap <- function(...) { 125 | paste(strwrap(paste0(...)), collapse = "\n") 126 | } 127 | -------------------------------------------------------------------------------- /R/utils_theme-gen.R: -------------------------------------------------------------------------------- 1 | # nocov start 2 | # Theme Generating Helpers ---------------------------------------------- 3 | 4 | plural_element <- function(css_name) { 5 | is_mult <- grepl(",|and|or", css_name) 6 | is_class <- grepl("^\\.", css_name) 7 | ifelse(is_class, 8 | ifelse(is_mult, "classes", "class"), 9 | ifelse(is_mult, "elements", "element") 10 | ) 11 | } 12 | 13 | element_description <- function(element) { 14 | out <- rep("", length(element)) 15 | multiple <- grepl("multiple", element) 16 | out[multiple] <- "Used in multiple CSS rules." 17 | 18 | ifelse( 19 | multiple | is.na(element) | element == "", 20 | out, 21 | glue::glue("Modifies the `{element}` {plural_element(element)}.") 22 | ) 23 | } 24 | 25 | describe_css_variable <- function(css_variable = NULL) { 26 | if (is.null(css_variable)) return("") 27 | ifelse( 28 | is.na(css_variable), 29 | "", 30 | glue::glue( 31 | " The value of this variable is also stored as a CSS variable that can be ", 32 | "referenced with `var({css_variable})` in any argument of a style ", 33 | "function or in custom CSS." 34 | ) 35 | ) 36 | } 37 | 38 | describe_css_property <- function(css_property = NULL) { 39 | if (is.null(css_property)) return("") 40 | ifelse( 41 | is.na(css_property), 42 | "", 43 | glue::glue(" Accepts CSS {css_property} property values.") 44 | ) 45 | } 46 | 47 | # nocov end 48 | -------------------------------------------------------------------------------- /R/xaringanthemer-deprecated.R: -------------------------------------------------------------------------------- 1 | #' Deprecated or renamed functions 2 | #' 3 | #' These functions in xaringanthemer have been deprecated or renamed. 4 | #' 5 | #' @param ... Argumets passed to the new or renamed functions. 6 | #' @return The result of the new or renamed function. 7 | #' @name xaringanthemer-deprecated 8 | NULL 9 | 10 | #' @description 11 | #' Use [style_xaringan()] instead of `write_xaringan_theme()`. 12 | #' 13 | #' @export 14 | #' @keywords internal 15 | #' @rdname xaringanthemer-deprecated 16 | write_xaringan_theme <- function(...) { 17 | .Deprecated(msg = "write_xaringan_theme() was renamed. Please use `style_xaringan()` instead.") 18 | style_xaringan(...) 19 | } 20 | 21 | #' @description 22 | #' Use [style_extra_css()] instead of `write_extra_css()`. 23 | #' 24 | #' @export 25 | #' @keywords internal 26 | #' @rdname xaringanthemer-deprecated 27 | write_extra_css <- function(...) { 28 | .Deprecated(msg = "write_extra_css() was renamed. Please use `style_extra_css()` instead.") 29 | style_extra_css(...) 30 | } 31 | 32 | 33 | #' @description 34 | #' Use [style_mono_light()] instead of `mono_light()`. 35 | #' 36 | #' @export 37 | #' @keywords internal 38 | #' @rdname xaringanthemer-deprecated 39 | mono_light <- function(...) { 40 | .Deprecated(msg = "mono_light() was renamed. Please use `style_mono_light()` instead.") 41 | style_mono_light(...) 42 | } 43 | 44 | #' @description 45 | #' Use [style_mono_dark()] instead of `mono_dark()`. 46 | #' 47 | #' @export 48 | #' @keywords internal 49 | #' @rdname xaringanthemer-deprecated 50 | mono_dark <- function(...) { 51 | .Deprecated(msg = "mono_dark() was renamed. Please use `style_mono_dark()` instead.") 52 | style_mono_dark(...) 53 | } 54 | 55 | #' @description 56 | #' Use [style_mono_accent()] instead of `mono_accent()`. 57 | #' 58 | #' @export 59 | #' @keywords internal 60 | #' @rdname xaringanthemer-deprecated 61 | mono_accent <- function(...) { 62 | .Deprecated(msg = "mono_accent() was renamed. Please use `style_mono_accent()` instead.") 63 | style_mono_accent(...) 64 | } 65 | 66 | #' @description 67 | #' Use [style_mono_accent_inverse()] instead of `mono_accent_inverse()`. 68 | #' 69 | #' @export 70 | #' @keywords internal 71 | #' @rdname xaringanthemer-deprecated 72 | mono_accent_inverse <- function(...) { 73 | .Deprecated(msg = "mono_accent_inverse() was renamed. Please use `style_mono_accent_inverse()` instead.") 74 | style_mono_accent_inverse(...) 75 | } 76 | 77 | #' @description 78 | #' Use [style_duo()] instead of `duo()`. 79 | #' 80 | #' @export 81 | #' @keywords internal 82 | #' @rdname xaringanthemer-deprecated 83 | duo <- function(...) { 84 | .Deprecated(msg = "duo() was renamed. Please use `style_duo()` instead.") 85 | style_duo(...) 86 | } 87 | 88 | #' @description 89 | #' Use [style_duo_accent()] instead of `duo_accent()`. 90 | #' 91 | #' @export 92 | #' @keywords internal 93 | #' @rdname xaringanthemer-deprecated 94 | duo_accent <- function(...) { 95 | .Deprecated(msg = "duo_accent() was renamed. Please use `style_duo_accent()` instead.") 96 | style_duo_accent(...) 97 | } 98 | 99 | #' @description 100 | #' Use [style_duo_accent_inverse()] instead of `duo_accent_inverse()`. 101 | #' 102 | #' @export 103 | #' @keywords internal 104 | #' @rdname xaringanthemer-deprecated 105 | duo_accent_inverse <- function(...) { 106 | .Deprecated(msg = "duo_accent_inverse() was renamed. Please use `style_duo_accent_inverse()` instead.") 107 | style_duo_accent_inverse(...) 108 | } 109 | 110 | #' @description 111 | #' Use [style_solarized_light()] instead of `solarized_light()`. 112 | #' 113 | #' @export 114 | #' @keywords internal 115 | #' @rdname xaringanthemer-deprecated 116 | solarized_light <- function(...) { 117 | .Deprecated(msg = "solarized_light() was renamed. Please use `style_solarized_light()` instead.") 118 | style_solarized_light(...) 119 | } 120 | 121 | #' @description 122 | #' Use [style_solarized_dark()] instead of `solarized_dark()`. 123 | #' 124 | #' @export 125 | #' @keywords internal 126 | #' @rdname xaringanthemer-deprecated 127 | solarized_dark <- function(...) { 128 | .Deprecated(msg = "solarized_dark() was renamed. Please use `style_solarized_dark()` instead.") 129 | style_solarized_dark(...) 130 | } 131 | -------------------------------------------------------------------------------- /R/xaringanthemer-package.R: -------------------------------------------------------------------------------- 1 | #' @importFrom grDevices col2rgb rgb rgb2hsv hsv 2 | #' @keywords internal 3 | "_PACKAGE" 4 | 5 | xaringanthemer_env <- new.env(parent = emptyenv()) 6 | 7 | # I looked up these ggplot geom aesthetic defaults manually via e.g. 8 | # ggplot2::geom_line()$geom$default_aes 9 | xaringanthemer_env$std_ggplot_defaults <- list( 10 | "line" = list(colour = "black"), 11 | "vline" = list(colour = "black"), 12 | "hline" = list(colour = "black"), 13 | "abline" = list(colour = "black"), 14 | "segment" = list(colour = "black"), 15 | "bar" = list(fill = "grey35"), 16 | "col" = list(fill = "grey35"), 17 | "boxplot" = list(colour = "grey20", fill = "white"), 18 | "contour" = list(colour = "#3366FF"), 19 | "density" = list(colour = "black", 20 | fill = NA, 21 | alpha = NA), 22 | "dotplot" = list(colour = "black"), 23 | "errorbarh" = list(colour = "black"), 24 | "crossbar" = list(colour = "black"), 25 | "errorbar" = list(colour = "black"), 26 | "linerange" = list(colour = "black"), 27 | "pointrange" = list(colour = "black"), 28 | "map" = list(colour = "black"), 29 | "path" = list(colour = "black"), 30 | "line" = list(colour = "black"), 31 | "step" = list(colour = "black"), 32 | "point" = list(colour = "black"), 33 | "polygon" = list(colour = NA, 34 | fill = "grey20"), 35 | "quantile" = list(colour = "#3366FF"), 36 | "rug" = list(colour = "black"), 37 | "segment" = list(colour = "black"), 38 | "smooth" = list(fill = "grey60", 39 | colour = "#3366FF"), 40 | "spoke" = list(colour = "black"), 41 | "label" = list(colour = "black", 42 | family = ""), 43 | "text" = list(colour = "black", 44 | family = ""), 45 | "rect" = list(fill = "grey35"), 46 | "tile" = list(fill = "grey20"), 47 | "violin" = list(fill = "white", colour = "grey20") 48 | ) 49 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | # nocov start 2 | .onLoad <- function(libname, pkgname, ...) { 3 | 4 | if ("knitr" %in% loadedNamespaces()) { 5 | set_fig_showtext() 6 | } 7 | 8 | setHook( 9 | packageEvent("knitr", "onLoad"), 10 | function(...) { 11 | set_fig_showtext() 12 | } 13 | ) 14 | 15 | invisible() 16 | } 17 | # nocov end 18 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r setup, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | results = "asis", 11 | echo = FALSE, 12 | comment = "#>", 13 | fig.path = "man/figures/index-", 14 | out.width = "100%" 15 | ) 16 | IS_README <- TRUE 17 | library(xaringanthemer) 18 | ``` 19 | 20 | # xaringanthemer 21 | 22 | 23 | [![CRAN status](https://www.r-pkg.org/badges/version/xaringanthemer)](https://CRAN.R-project.org/package=xaringanthemer) 24 | [![xaringanthemer status badge](https://gadenbuie.r-universe.dev/badges/xaringanthemer)](https://gadenbuie.r-universe.dev) 25 | [![Lifecycle: stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html) 26 | [![R-CMD-Check status badge](https://github.com/gadenbuie/xaringanthemer/workflows/R-CMD-check/badge.svg?branch=main)](https://github.com/gadenbuie/xaringanthemer/actions) 27 | [![Codecov](https://img.shields.io/codecov/c/github/gadenbuie/xaringanthemer)](https://app.codecov.io/github/gadenbuie/xaringanthemer) 28 | 29 | 30 | ```{r child="man/fragments/_tagline-gif.Rmd"} 31 | ``` 32 | 33 | ## Installation 34 | 35 | ```{r child="man/fragments/_installation.Rmd"} 36 | ``` 37 | 38 | ## Features 39 | 40 | There's a lot more that **xaringanthemer** can do! 41 | [Discover xaringanthemer's features.](https://pkg.garrickadenbuie.com/xaringanthemer/articles/xaringanthemer.html) 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # xaringanthemer 5 | 6 | 7 | 8 | [![CRAN 9 | status](https://www.r-pkg.org/badges/version/xaringanthemer)](https://CRAN.R-project.org/package=xaringanthemer) 10 | [![xaringanthemer status 11 | badge](https://gadenbuie.r-universe.dev/badges/xaringanthemer)](https://gadenbuie.r-universe.dev) 12 | [![Lifecycle: 13 | stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html) 14 | [![R-CMD-Check status 15 | badge](https://github.com/gadenbuie/xaringanthemer/workflows/R-CMD-check/badge.svg?branch=main)](https://github.com/gadenbuie/xaringanthemer/actions) 16 | [![Codecov](https://img.shields.io/codecov/c/github/gadenbuie/xaringanthemer)](https://app.codecov.io/github/gadenbuie/xaringanthemer) 17 | 18 | 19 | Give your [xaringan](https://github.com/yihui/xaringan) slides some 20 | style with **xaringanthemer** within your `slides.Rmd` file without 21 | (much) CSS. 22 | 23 | Animation previewing many xaringanthemer themes 24 | 25 | ## Installation 26 | 27 | You can install **xaringanthemer** from CRAN 28 | 29 | ``` r 30 | install.packages("xaringanthemer") 31 | ``` 32 | 33 | or you can install the development version of xaringanthemer from 34 | [GitHub](https://github.com/gadenbuie/xaringanthemer). 35 | 36 | ``` r 37 | # install.packages("remotes") 38 | remotes::install_github("gadenbuie/xaringanthemer") 39 | ``` 40 | 41 | ## Features 42 | 43 | There’s a lot more that **xaringanthemer** can do! [Discover 44 | xaringanthemer’s 45 | features.](https://pkg.garrickadenbuie.com/xaringanthemer/articles/xaringanthemer.html) 46 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## R CMD check results 2 | 3 | 0 errors | 0 warnings | 0 note 4 | 5 | This is a minor maintenance release to address changes in ggplot2. 6 | -------------------------------------------------------------------------------- /index.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r setup, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | results = "asis", 11 | echo = FALSE, 12 | comment = "#>", 13 | fig.path = "man/figures/index-", 14 | out.width = "100%" 15 | ) 16 | IS_README <- TRUE 17 | library(xaringanthemer) 18 | ``` 19 | 20 | # xaringanthemer 21 | 22 | 23 | [![CRAN status](https://www.r-pkg.org/badges/version/xaringanthemer)](https://CRAN.R-project.org/package=xaringanthemer) 24 | [![xaringanthemer status badge](https://gadenbuie.r-universe.dev/badges/xaringanthemer)](https://gadenbuie.r-universe.dev) 25 | [![Lifecycle: stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html) 26 | [![R-CMD-Check status badge](https://github.com/gadenbuie/xaringanthemer/workflows/R-CMD-check/badge.svg?branch=main)](https://github.com/gadenbuie/xaringanthemer/actions) 27 | [![Codecov](https://img.shields.io/codecov/c/github/gadenbuie/xaringanthemer)](https://codecov.io/github/gadenbuie/xaringanthemer) 28 | 29 | 30 | ```{r child="man/fragments/_tagline-gif.Rmd"} 31 | ``` 32 | 33 | ## Installation 34 | 35 | ```{r child="man/fragments/_installation.Rmd"} 36 | ``` 37 | 38 | ## Quick Intro 39 | 40 | [theme-functions]: #themes 41 | [theme-settings]: #theme-settings 42 | [template-variables]: vignettes/template-variables.md 43 | [ggplot2]: https://ggplot2.tidyverse.org 44 | 45 | ```{r child="man/fragments/_quick-intro.Rmd"} 46 | ``` 47 | 48 | ## Features 49 | 50 | There's a lot more that **xaringanthemer** can do! 51 | [Discover xaringanthemer's features.](https://pkg.garrickadenbuie.com/xaringanthemer/articles/xaringanthemer.html) 52 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # xaringanthemer 5 | 6 | 7 | 8 | [![CRAN 9 | status](https://www.r-pkg.org/badges/version/xaringanthemer)](https://CRAN.R-project.org/package=xaringanthemer) 10 | [![xaringanthemer status 11 | badge](https://gadenbuie.r-universe.dev/badges/xaringanthemer)](https://gadenbuie.r-universe.dev) 12 | [![Lifecycle: 13 | stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html) 14 | [![R-CMD-Check status 15 | badge](https://github.com/gadenbuie/xaringanthemer/workflows/R-CMD-check/badge.svg?branch=main)](https://github.com/gadenbuie/xaringanthemer/actions) 16 | [![Codecov](https://img.shields.io/codecov/c/github/gadenbuie/xaringanthemer)](https://codecov.io/github/gadenbuie/xaringanthemer) 17 | 18 | 19 | Give your [xaringan](https://github.com/yihui/xaringan) slides some 20 | style with **xaringanthemer** within your `slides.Rmd` file without 21 | (much) CSS. 22 | 23 | Animation previewing many xaringanthemer themes 24 | 25 | ## Installation 26 | 27 | You can install **xaringanthemer** from CRAN 28 | 29 | ``` r 30 | install.packages("xaringanthemer") 31 | ``` 32 | 33 | or you can install the development version of xaringanthemer from 34 | [GitHub](https://github.com/gadenbuie/xaringanthemer). 35 | 36 | ``` r 37 | # install.packages("remotes") 38 | remotes::install_github("gadenbuie/xaringanthemer") 39 | ``` 40 | 41 | ## Quick Intro 42 | 43 | 44 | 45 | First, add the `xaringan-themer.css` file to the YAML header of your 46 | xaringan slides. 47 | 48 | ``` yaml 49 | output: 50 | xaringan::moon_reader: 51 | css: xaringan-themer.css 52 | ``` 53 | 54 | Then, in a hidden chunk just after the knitr setup chunk, load 55 | **xaringanthemer** and try one of the [theme functions](#themes). 56 | 57 | ```` markdown 58 | ```{r xaringan-themer, include=FALSE, warning=FALSE} 59 | library(xaringanthemer) 60 | style_mono_accent( 61 | base_color = "#1c5253", 62 | header_font_google = google_font("Josefin Sans"), 63 | text_font_google = google_font("Montserrat", "300", "300i"), 64 | code_font_google = google_font("Fira Mono") 65 | ) 66 | ``` 67 | ```` 68 | 69 | Example title and normal slides using a green xaringanthemer theme 70 | 71 | ### Matching ggplot Themes 72 | 73 | **xaringanthemer** even provides a 74 | [ggplot2](https://ggplot2.tidyverse.org) theme with `theme_xaringan()` 75 | that uses the colors and fonts from your slide theme. Built on the 76 | [showtext](https://github.com/yixuan/showtext) package, and designed to 77 | work seamlessly with [Google Fonts](https://fonts.google.com). 78 | 79 | Color and fill scales are also provided for matching sequential color 80 | scales based on the primary color used in your slides. See 81 | `?scale_xaringan` for more details. 82 | 83 | More details and examples can be found in `vignette("ggplot2-themes")`. 84 | 85 | ``` r 86 | library(ggplot2) 87 | ggplot(diamonds) + 88 | aes(cut, fill = cut) + 89 | geom_bar(show.legend = FALSE) + 90 | labs( 91 | x = "Cut", 92 | y = "Count", 93 | title = "A Fancy diamonds Plot" 94 | ) + 95 | theme_xaringan(background_color = "#FFFFFF") + 96 | scale_xaringan_fill_discrete() 97 | ``` 98 | 99 | 100 | 101 | ### Tab Completion 102 | 103 | **xaringanthemer** is Tab friendly – [use autocomplete to 104 | explore](#theme-settings) the [template 105 | variables](vignettes/template-variables.md) that you can adjust in each 106 | of the themes! 107 | 108 | Demonstration of argument auto-completion with RStudio 109 | 110 | ### R Markdown Template in RStudio 111 | 112 | You can also skip the above and just create a *Ninja Themed 113 | Presentation* from the New R Markdown Document menu in RStudio. 114 | 115 |
116 | The 'New R Markdown Document' menu in RStudio 117 |
118 | 119 | ## Features 120 | 121 | There’s a lot more that **xaringanthemer** can do! [Discover 122 | xaringanthemer’s 123 | features.](https://pkg.garrickadenbuie.com/xaringanthemer/articles/xaringanthemer.html) 124 | -------------------------------------------------------------------------------- /inst/fonts/GlacialIndifferenceRegular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/xaringanthemer/51b100a9a42808ae1afc8761dfe262e38845d3e2/inst/fonts/GlacialIndifferenceRegular.ttf -------------------------------------------------------------------------------- /inst/fonts/OFL.txt: -------------------------------------------------------------------------------- 1 | Copyright 2019 Alfredo Marco Pradil (https://hanken.co/), with Reserved Font Name "Glacial Indifference". 2 | 3 | 4 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 5 | This license is copied below, and is also available with a FAQ at: 6 | http://scripts.sil.org/OFL 7 | 8 | 9 | ----------------------------------------------------------- 10 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 11 | ----------------------------------------------------------- 12 | 13 | PREAMBLE 14 | The goals of the Open Font License (OFL) are to stimulate worldwide 15 | development of collaborative font projects, to support the font creation 16 | efforts of academic and linguistic communities, and to provide a free and 17 | open framework in which fonts may be shared and improved in partnership 18 | with others. 19 | 20 | The OFL allows the licensed fonts to be used, studied, modified and 21 | redistributed freely as long as they are not sold by themselves. The 22 | fonts, including any derivative works, can be bundled, embedded, 23 | redistributed and/or sold with any software provided that any reserved 24 | names are not used by derivative works. The fonts and derivatives, 25 | however, cannot be released under any other type of license. The 26 | requirement for fonts to remain under this license does not apply 27 | to any document created using the fonts or their derivatives. 28 | 29 | DEFINITIONS 30 | "Font Software" refers to the set of files released by the Copyright 31 | Holder(s) under this license and clearly marked as such. This may 32 | include source files, build scripts and documentation. 33 | 34 | "Reserved Font Name" refers to any names specified as such after the 35 | copyright statement(s). 36 | 37 | "Original Version" refers to the collection of Font Software components as 38 | distributed by the Copyright Holder(s). 39 | 40 | "Modified Version" refers to any derivative made by adding to, deleting, 41 | or substituting -- in part or in whole -- any of the components of the 42 | Original Version, by changing formats or by porting the Font Software to a 43 | new environment. 44 | 45 | "Author" refers to any designer, engineer, programmer, technical 46 | writer or other person who contributed to the Font Software. 47 | 48 | PERMISSION & CONDITIONS 49 | Permission is hereby granted, free of charge, to any person obtaining 50 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 51 | redistribute, and sell modified and unmodified copies of the Font 52 | Software, subject to the following conditions: 53 | 54 | 1) Neither the Font Software nor any of its individual components, 55 | in Original or Modified Versions, may be sold by itself. 56 | 57 | 2) Original or Modified Versions of the Font Software may be bundled, 58 | redistributed and/or sold with any software, provided that each copy 59 | contains the above copyright notice and this license. These can be 60 | included either as stand-alone text files, human-readable headers or 61 | in the appropriate machine-readable metadata fields within text or 62 | binary files as long as those fields can be easily viewed by the user. 63 | 64 | 3) No Modified Version of the Font Software may use the Reserved Font 65 | Name(s) unless explicit written permission is granted by the corresponding 66 | Copyright Holder. This restriction only applies to the primary font name as 67 | presented to the users. 68 | 69 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 70 | Software shall not be used to promote, endorse or advertise any 71 | Modified Version, except to acknowledge the contribution(s) of the 72 | Copyright Holder(s) and the Author(s) or with their explicit written 73 | permission. 74 | 75 | 5) The Font Software, modified or unmodified, in part or in whole, 76 | must be distributed entirely under this license, and must not be 77 | distributed under any other license. The requirement for fonts to 78 | remain under this license does not apply to any document created 79 | using the Font Software. 80 | 81 | TERMINATION 82 | This license becomes null and void if any of the above conditions are 83 | not met. 84 | 85 | DISCLAIMER 86 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 87 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 88 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 89 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 90 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 91 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 92 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 93 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 94 | OTHER DEALINGS IN THE FONT SOFTWARE. 95 | -------------------------------------------------------------------------------- /inst/resources/template_title-slide.css: -------------------------------------------------------------------------------- 1 | .title-slide, .title-slide h1, .title-slide h2, .title-slide h3 { 2 | background-color: #fff !important; 3 | color: #222 !important; 4 | } 5 | .title-slide h3 { 6 | font-family: 'Roboto Condensed', 'Avenir Next', 'Helvetica Neue', 'Helvetica', sans-serif; 7 | font-weight: 400; 8 | padding-top: 15px; 9 | font-size: 28px; 10 | } 11 | .title-slide h3:nth-of-type(2) { 12 | margin-top: 10px; 13 | font-size: 28px; 14 | } 15 | .title-slide table { 16 | padding-top: 35px !important; 17 | } 18 | .title-slide i.fa { 19 | font-size: 2em; 20 | } 21 | -------------------------------------------------------------------------------- /inst/rmarkdown/templates/xaringanthemer/skeleton/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !skeleton.Rmd 3 | -------------------------------------------------------------------------------- /inst/rmarkdown/templates/xaringanthemer/template.yaml: -------------------------------------------------------------------------------- 1 | name: Ninja Themed Presentation 2 | description: > 3 | Create a themed presentation using the xaringanthemer package, to make a 4 | xaringan presentation based on remark.js. 5 | create_dir: false 6 | -------------------------------------------------------------------------------- /inst/scripts/generate_theme_functions.R: -------------------------------------------------------------------------------- 1 | source(here::here("R/utils_theme-gen.R")) 2 | load(here::here("R/sysdata.rda")) 3 | # R/theme_settings.R contains element_description() and plural_elements() 4 | 5 | setup_theme_function <- function( 6 | f_name = "style_xaringan", 7 | template = template_variables, 8 | ..., 9 | file = "", 10 | body = " eval(parse(text = call_style_xaringan()))", 11 | theme_colors = NULL 12 | ) { 13 | if (file == "clip" && !requireNamespace("clipr", quietly = TRUE)) file <- "" 14 | f_body_theme_colors <- include_theme_colors(theme_colors) 15 | f_body <- c( 16 | " # DO NOT EDIT - Generated from inst/scripts/generate_theme_functions.R", 17 | f_body_theme_colors, 18 | body 19 | ) 20 | tv <- template 21 | f_def <- c( 22 | "# Generated by inst/scripts/generate_theme_functions.R: do not edit by hand\n", 23 | as.character( 24 | glue::glue_data( 25 | tv, 26 | "#' @param {variable} {description}. ", 27 | "Defaults to {gsub('[{{}}]', '`', default)}. ", 28 | "{element_description(element)}", 29 | "{describe_css_property(css_property)}", 30 | "{describe_css_variable(css_variable)}" 31 | ) 32 | ), 33 | "#' @template theme_params", 34 | "#' @template style-usage", 35 | ..., 36 | glue::glue("{f_name} <- function("), 37 | as.character( 38 | glue::glue_data( 39 | tv, 40 | " {variable} = {ifelse(!grepl('^[{].+[}]$', default), paste0('\"', default, '\"'), gsub('[{}]', '', default))}," 41 | ) 42 | ), 43 | " colors = NULL,", 44 | " extra_css = NULL,", 45 | " extra_fonts = NULL,", 46 | " outfile = \"xaringan-themer.css\"", 47 | ") {" 48 | ) 49 | if (!is.null(f_body)) f_def <- c(f_def, f_body, "}") 50 | if (file == "clip") { 51 | clipr::write_clip(f_def) 52 | message("Wrote ", f_name, " function signature to clipboard.") 53 | } else { 54 | cat(reflow_roxygen(f_def), sep = "\n", file = file) 55 | message("Wrote ", f_name, " to ", file) 56 | } 57 | invisible() 58 | } 59 | 60 | reflow_roxygen <- function(x) { 61 | is_roxy_tag <- grepl("^#' @", x) 62 | roxy_tags <- x[is_roxy_tag] 63 | roxy_tags <- sub("^#' ", "", roxy_tags) 64 | roxy_tags <- purrr::map_chr( 65 | roxy_tags, 66 | ~ paste( 67 | "#'", strwrap( 68 | pack_inline_code(.x), 69 | width = 77, 70 | exdent = 2 71 | ), collapse = "\n") 72 | ) 73 | roxy_tags <- gsub("\u00A0", " ", roxy_tags) 74 | x[is_roxy_tag] <- roxy_tags 75 | x 76 | } 77 | 78 | pack_inline_code <- function(x) { 79 | stopifnot(length(x) == 1, is.character(x)) 80 | x <- strsplit(x, "")[[1]] 81 | inline_code <- FALSE 82 | for (i in seq_along(x)) { 83 | if (identical(x[i], "`")) { 84 | inline_code <- !inline_code 85 | } else if (inline_code && identical(x[i], " ")) { 86 | x[i] <- "\u00A0" 87 | } 88 | } 89 | paste(x, collapse = "") 90 | } 91 | 92 | include_theme_colors <- function(theme_colors = NULL) { 93 | if (is.null(theme_colors)) return(NULL) 94 | unname <- glue::glue("{theme_colors} <- unname({theme_colors})") 95 | unname <- paste(unname, collapse = "\n ") 96 | x <- glue::glue('{names(theme_colors)} = {theme_colors}') 97 | x <- paste(x, collapse = ", ") 98 | glue::glue(" {unname}\n colors <- c({x}, colors)", .trim = FALSE) 99 | } 100 | 101 | # ---- Write Xaringan Theme Function ---- 102 | setup_theme_function( 103 | "style_xaringan", 104 | template_variables, 105 | "#' @template style_xaringan", 106 | "#' @export", 107 | body = paste0(" ", readLines(here::here("inst/scripts/style_xaringan_body.R"))), 108 | file = here::here("R/style_xaringan.R") 109 | ) 110 | 111 | # ---- Monotone Light ---- 112 | setup_theme_function( 113 | "style_mono_light", 114 | template_mono_light, 115 | "#' @template style_mono_light", 116 | "#' @family Monotone themes", 117 | "#' @export", 118 | file = here::here("R/style_mono_light.R"), 119 | theme_colors = c(base = "base_color", white = "white_color", black = "black_color") 120 | ) 121 | 122 | # ---- Monotone Dark ---- 123 | setup_theme_function( 124 | "style_mono_dark", 125 | template_mono_dark, 126 | "#' @template style_mono_dark", 127 | "#' @family Monotone themes", 128 | "#' @export", 129 | file = here::here("R/style_mono_dark.R"), 130 | theme_colors = c(base = "base_color", white = "white_color", black = "black_color") 131 | ) 132 | 133 | # ---- Monotone Accent ---- 134 | setup_theme_function( 135 | "style_mono_accent", 136 | template_mono_accent, 137 | "#' @template style_mono_accent", 138 | "#' @family Monotone themes", 139 | "#' @export", 140 | file = here::here("R/style_mono_accent.R"), 141 | theme_colors = c(base = "base_color", white = "white_color", black = "black_color") 142 | ) 143 | 144 | # ---- Monotone Accent Inverse ---- 145 | setup_theme_function( 146 | "style_mono_accent_inverse", 147 | template_mono_accent_inverse, 148 | "#' @template style_mono_accent_inverse", 149 | "#' @family Monotone themes", 150 | "#' @export", 151 | file = here::here("R/style_mono_accent_inverse.R"), 152 | theme_colors = c(base = "base_color", white = "white_color", black = "black_color") 153 | ) 154 | 155 | # ---- Duotone ---- 156 | setup_theme_function( 157 | "style_duo", 158 | template_duo, 159 | "#' @template style_duo", 160 | "#' @family Duotone themes", 161 | "#' @export", 162 | file = here::here("R/style_duo.R"), 163 | theme_colors = c(primary = "primary_color", secondary = "secondary_color") 164 | ) 165 | 166 | # ---- Duotone Accent ---- 167 | setup_theme_function( 168 | "style_duo_accent", 169 | template_duo_accent, 170 | "#' @template style_duo_accent", 171 | "#' @family Duotone themes", 172 | "#' @export", 173 | file = here::here("R/style_duo_accent.R"), 174 | theme_colors = c(primary = "primary_color", secondary = "secondary_color", 175 | white = "white_color", black = "black_color") 176 | ) 177 | 178 | # ---- Duotone Accent Inverse ---- 179 | setup_theme_function( 180 | "style_duo_accent_inverse", 181 | template_duo_accent_inverse, 182 | "#' @template style_duo_accent_inverse", 183 | "#' @family Duotone themes", 184 | "#' @export", 185 | file = here::here("R/style_duo_accent_inverse.R"), 186 | theme_colors = c(primary = "primary_color", secondary = "secondary_color", 187 | white = "white_color", black = "black_color") 188 | ) 189 | 190 | # ---- Solarized Light ---- 191 | setup_theme_function( 192 | "style_solarized_light", 193 | template_solarized_light, 194 | "#' @template style_solarized_light", 195 | "#' @family Solarized themes", 196 | "#' @export", 197 | file = here::here("R/style_solarized_light.R") 198 | ) 199 | 200 | # ---- Solarized Dark ---- 201 | setup_theme_function( 202 | "style_solarized_dark", 203 | template_solarized_dark, 204 | "#' @template style_solarized_dark", 205 | "#' @family Solarized themes", 206 | "#' @export", 207 | file = here::here("R/style_solarized_dark.R") 208 | ) 209 | -------------------------------------------------------------------------------- /inst/scripts/style_xaringan_body.R: -------------------------------------------------------------------------------- 1 | force(text_font_family) 2 | force(text_font_weight) 3 | force(text_font_url) 4 | force(text_font_family_fallback) 5 | force(header_font_family) 6 | force(header_font_weight) 7 | force(header_font_url) 8 | force(code_font_family) 9 | force(code_font_url) 10 | force(code_font_family_fallback) 11 | 12 | # the defaults are google fonts 13 | is_default <- function(type, suffix) { 14 | # check if font arg value is from xaringanthemer_font_default 15 | var <- paste0(type, "_", suffix) 16 | inherits( 17 | get(var, envir = parent.frame(2), inherits = FALSE), 18 | "xaringanthemer_default" 19 | ) 20 | } 21 | for (var in c("text", "header", "code")) { 22 | suffixes <- c("font_family", "font_weight", "font_url") 23 | if (var == "code") suffixes <- setdiff(suffixes, "font_weight") 24 | var_is_google <- all(vapply(suffixes, is_default, logical(1), type = var)) 25 | var_is_google <- as.integer(var_is_google) 26 | r_set_font_is_google <- glue::glue("{var}_font_is_google <- {var_is_google}") 27 | eval(parse(text = r_set_font_is_google)) 28 | } 29 | 30 | # Make sure font names are wrapped in quotes if they have spaces 31 | f_args <- names(formals(sys.function())) 32 | for (var in f_args[grepl("font_family$", f_args)]) { 33 | var_value <- get(var, inherits = FALSE) 34 | if (!is.null(var_value)) { 35 | eval(parse(text = paste0(var, "<-quote_elements_w_spaces(", var, ")"))) 36 | } 37 | } 38 | 39 | # Warn if base_font_size isn't absolute 40 | css_abs_units <- c("cm", "mm", "Q", "in", "pc", "pt", "px") 41 | if (!grepl(paste(tolower(css_abs_units), collapse = "|"), tolower(base_font_size))) { 42 | warning( 43 | glue::glue( 44 | "Base font size '{base_font_size}' is not in absolute units. ", 45 | "For best results, specify the `base_font_size` using absolute CSS units: ", 46 | "{paste(css_abs_units, collapse = ', ')}" 47 | ), 48 | call. = FALSE, 49 | immediate. = TRUE 50 | ) 51 | } 52 | 53 | # If certain colors aren't in hexadecimal it may cause problems with theme_xaringan() 54 | # TODO: at some point I'd rather be able to process CSS colors or variables 55 | colors_used_by_theme_xaringan <- list( 56 | background_color = background_color, 57 | text_color = text_color, 58 | header_color = header_color, 59 | text_bold_color = text_bold_color, 60 | inverse_background_color = inverse_background_color, 61 | inverse_text_color = inverse_text_color, 62 | inverse_header_color = inverse_header_color 63 | ) 64 | colors_used_by_theme_xaringan <- purrr::discard(colors_used_by_theme_xaringan, is.null) 65 | colors_are_hex <- purrr::map_lgl(colors_used_by_theme_xaringan, check_color_is_hex, throw = NULL) 66 | 67 | if (any(!colors_are_hex)) { 68 | colors_better_as_hex <- names(colors_used_by_theme_xaringan)[!colors_are_hex] 69 | colors_better_as_hex <- paste(colors_better_as_hex, collapse = ", ") 70 | warning( 71 | glue::glue("Colors that will be used by `theme_xaringan()` need to be in ", 72 | "hexadecimal format: {colors_better_as_hex}"), 73 | immediate. = TRUE, 74 | call. = FALSE 75 | ) 76 | } 77 | 78 | # Use font_..._google args to overwrite font args 79 | for (var in f_args[grepl("font_google$", f_args)]) { 80 | gf <- eval(parse(text = var)) 81 | if (is.null(gf)) next 82 | if (!inherits(gf, "google_font")) { 83 | stop("`", var, "` must be set using `google_font()`.") 84 | } 85 | group <- strsplit(var, "_")[[1]][1] 86 | if (group == "text") { 87 | text_font_family <- quote_elements_w_spaces(gf$family) 88 | text_font_weight <- gf$weights %||% "normal" 89 | if (grepl(",", text_font_weight)) { 90 | # Use first font weight if multiple are imported 91 | text_font_weight <- substr(text_font_weight, 1, regexpr(",", text_font_weight)[1] - 1) 92 | } 93 | text_font_url <- gf$url 94 | } else { 95 | eval(parse(text = paste0(group, "_font_family <- quote_elements_w_spaces(gf$family)"))) 96 | eval(parse(text = paste0(group, "_font_url <- gf$url"))) 97 | } 98 | eval(parse(text = paste0(group, "_font_is_google <- 1"))) 99 | } 100 | 101 | extra_font_imports <- if (is.null(extra_fonts)) "" else list2fonts(extra_fonts) 102 | extra_font_imports <- paste(extra_font_imports, collapse = "\n") 103 | 104 | # convert NA arguments to NULL 105 | for (var in f_args) { 106 | val <- eval(parse(text = var)) 107 | if (is.null(val)) next 108 | val <- val[!is.na(val)] 109 | is_na <- length(val) == 0 110 | if (is_na) assign(var, NULL, envir = sys.frame(sys.nframe())) 111 | } 112 | 113 | # prepare variables for template 114 | body_font_family <- paste(c(text_font_family, text_font_family_fallback, text_font_base), collapse = ", ") 115 | background_size_fallback <- if (is.null(background_position)) "cover" else "100%" 116 | background_size <- background_image %??% (background_size %||% background_size_fallback) 117 | title_slide_background_size <- title_slide_background_size %||% ( 118 | title_slide_background_image %??% "cover" 119 | ) 120 | table_row_even_background_color <- table_row_even_background_color %||% background_color 121 | 122 | # stash theme settings in package env 123 | lapply(f_args, function(n) assign(n, get(n), envir = xaringanthemer_env)) 124 | for (font_is_google in paste0(c("text", "code", "header"), "_font_is_google")) { 125 | assign( 126 | font_is_google, 127 | get(font_is_google, inherits = FALSE) == 1, 128 | envir = xaringanthemer_env 129 | ) 130 | } 131 | 132 | xaringanthemer_version <- utils::packageVersion("xaringanthemer") 133 | 134 | # prepare header background object 135 | needs_leading_dot <- !grepl("^\\.", header_background_ignore_classes) 136 | header_background_ignore_classes[needs_leading_dot] <- paste0( 137 | ".", 138 | header_background_ignore_classes[needs_leading_dot] 139 | ) 140 | header_background_ignore_classes <- purrr::map( 141 | header_background_ignore_classes, 142 | ~ list(class = .) 143 | ) 144 | if (is.null(header_background_padding)) { 145 | slide_padding <- css_get_padding(padding) 146 | header_background_padding <- paste( 147 | "2rem", slide_padding$right, "1.5rem", slide_padding$left 148 | ) 149 | } 150 | header_background <- list( 151 | auto = header_background_auto, 152 | background_color = header_background_color, 153 | text_color = header_background_text_color, 154 | padding = header_background_padding, 155 | content_padding_top = header_background_content_padding_top, 156 | ignore = header_background_ignore_classes 157 | ) 158 | 159 | colors <- prepare_colors(colors) 160 | 161 | tf <- system.file("resources", "template.css", package = "xaringanthemer") 162 | template <- readLines(tf, warn = FALSE) 163 | template <- paste(template, collapse = "\n") 164 | x <- whisker::whisker.render(template) 165 | if (!is.null(extra_css)) { 166 | x <- c(x, style_extra_css(extra_css, outfile = NULL)) 167 | } 168 | if (is.null(outfile)) { 169 | return(x) 170 | } 171 | writeLines(x, con = outfile) 172 | invisible(outfile) 173 | -------------------------------------------------------------------------------- /make.R: -------------------------------------------------------------------------------- 1 | callr::rscript("data-raw/theme_template_variables.R") 2 | message("Building theme functions") 3 | callr::rscript("generate_theme_functions.R", wd = here::here("inst/scripts")) 4 | message("Writing documentation") 5 | devtools::document() 6 | 7 | message("Rendering README.Rmd for GitHub") 8 | rmarkdown::render("README.Rmd", quiet = TRUE) 9 | unlink("README.html") 10 | 11 | message("Checking package") 12 | devtools::check(document = FALSE) 13 | 14 | message("Checking urls") 15 | urlchecker::url_check() 16 | 17 | message("Building and Installing Package with Vignettes") 18 | devtools::install(build_vignettes = TRUE) 19 | -------------------------------------------------------------------------------- /man-roxygen/style-usage.R: -------------------------------------------------------------------------------- 1 | #' @section Usage: To use the styles created by this theme function, make sure 2 | #' that you use `xaringan-themer.css` as your CSS file in your slides' YAML 3 | #' header. If you change the name of the output file using the `outfile` 4 | #' argument, use that name instead of the default file name. 5 | #' 6 | #' ```yaml 7 | #' output: 8 | #' xaringan::moon_reader: 9 | #' css: xaringan-themer.css 10 | #' ```` 11 | #' 12 | #' @return The CSS styles are written to the file path provided in `outfile` 13 | #' (by default to `xaringan-themer.css`). If `outfile` is `NULL`, the CSS is 14 | #' returned directly as a character string. 15 | #' 16 | -------------------------------------------------------------------------------- /man-roxygen/style_duo.R: -------------------------------------------------------------------------------- 1 | #' @title Duotone Theme 2 | #' @description A duotone theme designed to work well with two complementary 3 | #' colors. 4 | #' @examples 5 | #' # Create a xaringan style in a temporary file 6 | #' xaringan_themer_css <- tempfile("xaringan-themer-", fileext = ".css") 7 | #' 8 | #' style_duo( 9 | #' primary_color = "#1f4257", 10 | #' secondary_color = "#f97b64", 11 | #' outfile = xaringan_themer_css # omit in your slides to write the 12 | #' # styles to xaringan-themer.css 13 | #' ) 14 | #' 15 | #' # View the CSS: 16 | #' # file.edit(xaringan_themer_css) 17 | -------------------------------------------------------------------------------- /man-roxygen/style_duo_accent.R: -------------------------------------------------------------------------------- 1 | #' @title Duotone Accent Theme 2 | #' @description An default xaringan theme with a two colors used for color 3 | #' accents on select elements (headers, bold text, etc.). 4 | #' @examples 5 | #' # Create a xaringan style in a temporary file 6 | #' xaringan_themer_css <- tempfile("xaringan-themer-", fileext = ".css") 7 | #' 8 | #' style_duo_accent( 9 | #' primary_color = "#006747", 10 | #' secondary_color = "#cfc493", 11 | #' outfile = xaringan_themer_css # omit in your slides to write the 12 | #' # styles to xaringan-themer.css 13 | #' ) 14 | #' 15 | #' # View the CSS: 16 | #' # file.edit(xaringan_themer_css) 17 | -------------------------------------------------------------------------------- /man-roxygen/style_duo_accent_inverse.R: -------------------------------------------------------------------------------- 1 | #' @title Duotone Accent Inverse Theme 2 | #' @description An "inverted" default xaringan theme with a two colors used 3 | #' for color accents on select elements (headers, bold text, etc.). 4 | #' @examples 5 | #' # Create a xaringan style in a temporary file 6 | #' xaringan_themer_css <- tempfile("xaringan-themer-", fileext = ".css") 7 | #' 8 | #' style_duo_accent_inverse( 9 | #' primary_color = "#006747", 10 | #' secondary_color = "#cfc493", 11 | #' outfile = xaringan_themer_css # omit in your slides to write the 12 | #' # styles to xaringan-themer.css 13 | #' ) 14 | #' 15 | #' # View the CSS: 16 | #' # file.edit(xaringan_themer_css) 17 | -------------------------------------------------------------------------------- /man-roxygen/style_mono_accent.R: -------------------------------------------------------------------------------- 1 | #' @title Monotone Accent Theme 2 | #' @description The default xaringan theme with a single color used for color 3 | #' accents on select elements (headers, bold text, etc.). 4 | #' @examples 5 | #' # Create a xaringan style in a temporary file 6 | #' xaringan_themer_css <- tempfile("xaringan-themer-", fileext = ".css") 7 | #' 8 | #' style_mono_accent( 9 | #' base_color = "#43418A", 10 | #' outfile = xaringan_themer_css # omit in your slides to write the 11 | #' # styles to xaringan-themer.css 12 | #' ) 13 | #' 14 | #' # View the CSS: 15 | #' # file.edit(xaringan_themer_css) 16 | -------------------------------------------------------------------------------- /man-roxygen/style_mono_accent_inverse.R: -------------------------------------------------------------------------------- 1 | #' @title Monotone Accent Inverse Theme 2 | #' @description An "inverted" default xaringan theme with a single color used 3 | #' for color accents on select elements (headers, bold text, etc.). 4 | #' @examples 5 | #' # Create a xaringan style in a temporary file 6 | #' xaringan_themer_css <- tempfile("xaringan-themer-", fileext = ".css") 7 | #' 8 | #' style_mono_accent_inverse( 9 | #' base_color = "#3c989e", 10 | #' outfile = xaringan_themer_css # omit in your slides to write the 11 | #' # styles to xaringan-themer.css 12 | #' ) 13 | #' 14 | #' # View the CSS: 15 | #' # file.edit(xaringan_themer_css) 16 | -------------------------------------------------------------------------------- /man-roxygen/style_mono_dark.R: -------------------------------------------------------------------------------- 1 | #' @title Monotone Dark Theme 2 | #' @description A dark monotone theme based around a single color. 3 | #' @examples 4 | #' # Create a xaringan style in a temporary file 5 | #' xaringan_themer_css <- tempfile("xaringan-themer-", fileext = ".css") 6 | #' 7 | #' style_mono_dark( 8 | #' base_color = "#cbf7ed", 9 | #' outfile = xaringan_themer_css # omit in your slides to write the 10 | #' # styles to xaringan-themer.css 11 | #' ) 12 | #' 13 | #' # View the CSS: 14 | #' # file.edit(xaringan_themer_css) 15 | -------------------------------------------------------------------------------- /man-roxygen/style_mono_light.R: -------------------------------------------------------------------------------- 1 | #' @title Monotone Light Theme 2 | #' @description A light monotone theme based around a single color. 3 | #' @examples 4 | #' # Create a xaringan style in a temporary file 5 | #' xaringan_themer_css <- tempfile("xaringan-themer-", fileext = ".css") 6 | #' 7 | #' style_mono_light( 8 | #' base_color = "#23395b", 9 | #' outfile = xaringan_themer_css # omit in your slides to write the 10 | #' # styles to xaringan-themer.css 11 | #' ) 12 | #' 13 | #' # View the CSS: 14 | #' # file.edit(xaringan_themer_css) 15 | -------------------------------------------------------------------------------- /man-roxygen/style_solarized_dark.R: -------------------------------------------------------------------------------- 1 | #' @title Solarized Dark Theme 2 | #' @description A dark theme based around on the solarized color scheme. 3 | #' Works well with "\code{highlightStyle: solarized-dark}" or 4 | #' "\code{highlighStyle: solarized-light}". 5 | #' @references \url{https://ethanschoonover.com/solarized/} 6 | #' @examples 7 | #' # Create a xaringan style in a temporary file 8 | #' xaringan_themer_css <- tempfile("xaringan-themer-", fileext = ".css") 9 | #' 10 | #' style_solarized_dark( 11 | #' outfile = xaringan_themer_css # omit in your slides to write the 12 | #' # styles to xaringan-themer.css 13 | #' ) 14 | #' 15 | #' # View the CSS: 16 | #' # file.edit(xaringan_themer_css) 17 | -------------------------------------------------------------------------------- /man-roxygen/style_solarized_light.R: -------------------------------------------------------------------------------- 1 | #' @title Solarized Light Theme 2 | #' @description A light theme based around on the solarized color scheme. 3 | #' Works well with "\code{highlightStyle: solarized-dark}" or 4 | #' "\code{highlighStyle: solarized-light}". 5 | #' @references \url{https://ethanschoonover.com/solarized/} 6 | #' @examples 7 | #' # Create a xaringan style in a temporary file 8 | #' xaringan_themer_css <- tempfile("xaringan-themer-", fileext = ".css") 9 | #' 10 | #' style_solarized_light( 11 | #' outfile = xaringan_themer_css # omit in your slides to write the 12 | #' # styles to xaringan-themer.css 13 | #' ) 14 | #' 15 | #' # View the CSS: 16 | #' # file.edit(xaringan_themer_css) 17 | -------------------------------------------------------------------------------- /man-roxygen/style_xaringan.R: -------------------------------------------------------------------------------- 1 | #' @title Write A Customized Xaringan Theme 2 | #' @description Creates a customized Xaringan theme CSS file. 3 | #' @examples 4 | #' # Create a xaringan style in a temporary file 5 | #' xaringan_themer_css <- tempfile("xaringan-themer-", fileext = ".css") 6 | #' 7 | #' style_xaringan( 8 | #' text_color = "#002b3", 9 | #' inverse_background_color = "#31b09e", 10 | #' inverse_text_color = "#002b3", 11 | #' outfile = xaringan_themer_css # omit in your slides to write the 12 | #' # styles to xaringan-themer.css 13 | #' ) 14 | #' 15 | #' # View the CSS: 16 | #' # file.edit(xaringan_themer_css) 17 | -------------------------------------------------------------------------------- /man-roxygen/theme_params.R: -------------------------------------------------------------------------------- 1 | #' @param extra_css A named list of CSS definitions each containing a named list 2 | #' of CSS property-value pairs, i.e. 3 | #' \code{list(".class-id" = list("css-property" = "value"))}. 4 | #' @param extra_fonts A list of additional fonts to import, each list element 5 | #' can be either a URL as a character string or a call to 6 | #' \code{\link{google_font}()}. To use a font imported in `extra_fonts`, you 7 | #' will need to write custom CSS rules that apply the font to an element or 8 | #' class with the `font-family` property. See the **Fonts** section of 9 | #' `vignette("xaringanthemer")` for an example. 10 | #' @param colors A named vector of custom colors. The names of the colors 11 | #' become CSS variables and classes that can be used within your slides. 12 | #' For example, `colors = c(blue = "#bad4ed")` adds a CSS variable 13 | #' `--blue`, a `.blue` CSS class that applies the color to the text or 14 | #' foreground color, and a `.bg-blue` CSS class that applies the color 15 | #' to the background. 16 | #' @param outfile Customized xaringan CSS output file name, default is "xaringan-themer.css" 17 | #' @family themes 18 | -------------------------------------------------------------------------------- /man/apply_alpha.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/color.R 3 | \name{apply_alpha} 4 | \alias{apply_alpha} 5 | \title{Add alpha to hex color} 6 | \usage{ 7 | apply_alpha(color_hex, opacity = 0.5) 8 | } 9 | \arguments{ 10 | \item{color_hex}{A character string representing a hex color} 11 | 12 | \item{opacity}{Desired opacity of the output color} 13 | } 14 | \value{ 15 | A character string with added opacity level as hexadecimal characters. 16 | } 17 | \description{ 18 | Applies alpha (or opacity) to a color in hexadecimal form by 19 | converting opacity in the \verb{[0, 1]} range to hex in the \verb{[0, 255]} range 20 | and appending to the hex color. 21 | } 22 | \examples{ 23 | blue <- "#0e6ba8" 24 | blue_transparent <- apply_alpha(blue) 25 | 26 | if (requireNamespace("scales", quietly = TRUE)) { 27 | scales::show_col(c(blue, blue_transparent)) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /man/choose_dark_or_light.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/color.R 3 | \name{choose_dark_or_light} 4 | \alias{choose_dark_or_light} 5 | \title{Choose dark or light color} 6 | \usage{ 7 | choose_dark_or_light(x, black = "#000000", white = "#FFFFFF") 8 | } 9 | \arguments{ 10 | \item{x}{The background color (hex)} 11 | 12 | \item{black}{Text or foreground color, e.g. "#222" or 13 | \code{substitute(darken_color(x, 0.8))}, if black text provides the best contrast.} 14 | 15 | \item{white}{Text or foreground color or expression, e.g. "#EEE" or 16 | \code{substitute(lighten_color(x, 0.8))}, if white text provides the best contrast.} 17 | } 18 | \value{ 19 | The \code{black} color or \code{white} color according to which color provides 20 | the greates contrast with the input color. 21 | } 22 | \description{ 23 | Takes a color input as \code{x} and returns either the black or white color (or 24 | expression) if dark or light text should be used over the input color for 25 | best contrast. Follows W3C Recommendations. 26 | } 27 | \examples{ 28 | light_green <- "#c4d6b0" 29 | contrast_green <- choose_dark_or_light(light_green) 30 | dark_purple <- "#381d2a" 31 | contrast_purple <- choose_dark_or_light(dark_purple) 32 | 33 | if (requireNamespace("scales", quietly = TRUE)) { 34 | scales::show_col(c(light_green, contrast_green, dark_purple, contrast_purple)) 35 | } 36 | } 37 | \references{ 38 | \url{https://stackoverflow.com/a/3943023/2022615} 39 | } 40 | -------------------------------------------------------------------------------- /man/figures/index-theme_xaringan_demo-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/xaringanthemer/51b100a9a42808ae1afc8761dfe262e38845d3e2/man/figures/index-theme_xaringan_demo-1.png -------------------------------------------------------------------------------- /man/figures/lifecycle-archived.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecyclearchivedarchived -------------------------------------------------------------------------------- /man/figures/lifecycle-defunct.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecycledefunctdefunct -------------------------------------------------------------------------------- /man/figures/lifecycle-deprecated.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecycledeprecateddeprecated -------------------------------------------------------------------------------- /man/figures/lifecycle-experimental.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecycleexperimentalexperimental -------------------------------------------------------------------------------- /man/figures/lifecycle-maturing.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecyclematuringmaturing -------------------------------------------------------------------------------- /man/figures/lifecycle-questioning.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecyclequestioningquestioning -------------------------------------------------------------------------------- /man/figures/lifecycle-stable.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecyclestablestable -------------------------------------------------------------------------------- /man/figures/lifecycle-superseded.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecyclesupersededsuperseded -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/xaringanthemer/51b100a9a42808ae1afc8761dfe262e38845d3e2/man/figures/logo.png -------------------------------------------------------------------------------- /man/fragments/_colors.Rmd: -------------------------------------------------------------------------------- 1 | When designing your xaringan theme, 2 | you may have additional colors in your desired color palette 3 | beyond those used in the accent colors of the mono and duotone styles. 4 | 5 | The `style*()` functions in xaringanthemer 6 | include a `colors` argument that lets you 7 | quickly define additional colors to use in your slides. 8 | This argument takes a vector of named colors 9 | 10 | ```r 11 | colors = c( 12 | red = "#f34213", 13 | purple = "#3e2f5b", 14 | orange = "#ff8811", 15 | green = "#136f63", 16 | white = "#FFFFFF" 17 | ) 18 | ``` 19 | 20 | and creates CSS classes from the color name 21 | that set the text color — e.g. `.red` — 22 | or that set the background color — e.g. `.bg-red`. 23 | If you use custom CSS in your slides, 24 | the color name is also stored in a CSS variable — 25 | e.g. `var(--red)`. 26 | 27 | So slide text like this 28 | 29 | ```markdown 30 | This **.red[simple]** .white.bg-purple[demo] 31 | _.orange[shows]_ the colors .green[in action]. 32 | ``` 33 | 34 | will be rendered in HTML as 35 | 36 |
37 | This simple 38 | demo 39 | shows 40 | the colors 41 | in action. 42 |
43 | 44 | Note that the color names in `colors` 45 | need to be valid CSS names, 46 | so `"purple-light"` will work, 47 | but `"purple light"` will not. 48 | -------------------------------------------------------------------------------- /man/fragments/_fonts.Rmd: -------------------------------------------------------------------------------- 1 | 2 | 3 | [google-fonts]: https://fonts.google.com 4 | 5 | 6 | 7 | ```{css echo=FALSE} 8 | .cabin { 9 | font-family: Cabin; 10 | font-weight: 600 11 | } 12 | .noto-sans { 13 | font-family: 'Noto Sans'; 14 | } 15 | .font-preview { 16 | padding: 1em; 17 | margin-top: 1em; 18 | margin-bottom: 1em; 19 | border: 1px solid #dddddd; 20 | border-radius: 3px; 21 | font-size: 1.25em; 22 | } 23 | ``` 24 | 25 | ### Default Fonts 26 | 27 | The default heading and body fonts used in **xaringanthemer** 28 | are different than the xaringan default fonts. 29 | In xaringanthemer, 30 | [Cabin](https://fonts.google.com/specimen/Cabin) 31 | is used for headings and 32 | [Noto Sans](https://fonts.google.com/specimen/Noto+Sans) 33 | for body text. 34 | 35 |
36 |

A Cabin in the Clearing

37 |

Pack my box with five dozen liquor jugs. Amazingly few discotheques provide jukeboxes.

38 |
39 | 40 | 41 | These fonts are easier to read on screens and at a distance during presentations, 42 | and they support a wide variety of languages and weights. 43 | Another reason for the change is that the xaringan (remarkjs) default body font, 44 | _Droid Serif_, 45 | is no longer officially included in Google Fonts. 46 | 47 | If you would like to use the fonts from the 48 | [default xaringan theme](https://slides.yihui.org/xaringan/), 49 | you can use the following arguments in your style function. 50 | 51 | ```{r eval=FALSE, echo=TRUE} 52 | style_xaringan( 53 | text_font_family = "Droid Serif", 54 | text_font_url = "https://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic", 55 | header_font_google = google_font("Yanone Kaffeesatz") 56 | ) 57 | ``` 58 | 59 | ### Custom and _Google Font_ Fonts 60 | 61 | **xaringanthemer** makes it easy to use 62 | [Google Fonts][google-fonts] 63 | in your presentations 64 | (provided you have an internet connection during the presentation) 65 | or to fully specify your font files. 66 | 67 | To use [Google Fonts][google-fonts], 68 | set the `_font_google` theme arguments -- 69 | ```{r results='asis', echo=FALSE} 70 | cat(paste0("`", tvv[grepl("_font_google$", tvv)], "`", collapse = ", ")) 71 | ``` 72 | --- using the `google_font()` helper. 73 | The help documentation in `?google_font` provides more info. 74 | 75 | ```{r eval=FALSE, echo=TRUE} 76 | style_mono_light( 77 | header_font_google = google_font("Josefin Slab", "600"), 78 | text_font_google = google_font("Work Sans", "300", "300i"), 79 | code_font_google = google_font("IBM Plex Mono") 80 | ) 81 | ``` 82 | 83 | If you set an `_font_google` theme arguments, 84 | then `_font_family`, `_font_weight` and `_font_url` 85 | are overwritten -- 86 | where `` is one of `header`, `text`, or `code`. 87 | 88 | To use a font hosted outside of Google fonts, 89 | you need to provide both `_font_family` and `_font_url`. 90 | For example, 91 | suppose you want to use a code font with ligatures for your code chunks, 92 | such as 93 | [Fira Code](https://github.com/tonsky/FiraCode), 94 | which would be declared with `code_font_family`. 95 | The 96 | [browser usage](https://github.com/tonsky/FiraCode#browser-support) 97 | section of the Fira Code README 98 | provides a CSS URL to be used with an `@import` statement 99 | that you can use with the `code_font_url` argument. 100 | 101 | ```{r eval=FALSE, echo=TRUE} 102 | style_solarized_dark( 103 | code_font_family = "Fira Code", 104 | code_font_url = "https://cdn.jsdelivr.net/gh/tonsky/FiraCode@2/distr/fira_code.css" 105 | ) 106 | ``` 107 | 108 | Remember that you need to supply either 109 | `_google_font` using the `google_font()` helper 110 | _or both_ `_font_family` and `_font_url`. 111 | 112 | ### Using Additional Fonts 113 | 114 | If you want to use additional fonts for use in [custom CSS definitions][adding-custom-css], 115 | use the `extra_fonts` argument to pass a list of URLs or `google_font()`s. 116 | Notice that you will need to add custom CSS (for example, via `extra_css`) 117 | to use the fonts imported in `extra_fonts`. 118 | 119 | ```{r eval=FALSE, echo=TRUE} 120 | style_mono_light( 121 | extra_fonts = list( 122 | google_font("Sofia"), 123 | # Young Serif by uplaod.fr 124 | "https://cdn.jsdelivr.net/gh/uplaod/YoungSerif/fonts/webfonts/fontface.css", 125 | ), 126 | extra_css = list( 127 | ".title-slide h2" = list("font-family" = "Sofia"), 128 | blockquote = list("font-family" = "youngserifregular") 129 | ) 130 | ) 131 | ``` 132 | -------------------------------------------------------------------------------- /man/fragments/_installation.Rmd: -------------------------------------------------------------------------------- 1 | You can install **xaringanthemer** from CRAN 2 | 3 | ```r 4 | install.packages("xaringanthemer") 5 | ``` 6 | 7 | or you can install the development version of xaringanthemer from [GitHub](https://github.com/gadenbuie/xaringanthemer). 8 | 9 | ```r 10 | # install.packages("remotes") 11 | remotes::install_github("gadenbuie/xaringanthemer") 12 | ``` 13 | -------------------------------------------------------------------------------- /man/fragments/_quick-intro.Rmd: -------------------------------------------------------------------------------- 1 | 2 | 3 | ```{r include=FALSE} 4 | IN_PKGDOWN <- identical(Sys.getenv("IN_PKGDOWN"), "true") 5 | ``` 6 | 7 | First, add the `xaringan-themer.css` file to the YAML header of your xaringan slides. 8 | 9 | ```yaml 10 | output: 11 | xaringan::moon_reader: 12 | css: xaringan-themer.css 13 | ``` 14 | 15 | Then, in a hidden chunk just after the knitr setup chunk, load **xaringanthemer** and try one of the [theme functions][theme-functions]. 16 | 17 | ````markdown 18 | ```{r xaringan-themer, include=FALSE, warning=FALSE}`r ""` 19 | library(xaringanthemer) 20 | style_mono_accent( 21 | base_color = "#1c5253", 22 | header_font_google = google_font("Josefin Sans"), 23 | text_font_google = google_font("Montserrat", "300", "300i"), 24 | code_font_google = google_font("Fira Mono") 25 | ) 26 | ``` 27 | ```` 28 | 29 | Example title and normal slides using a green xaringanthemer theme 30 | 31 | ### Matching ggplot Themes 32 | 33 | [showtext]: https://github.com/yixuan/showtext 34 | 35 | **xaringanthemer** even provides a [ggplot2] theme 36 | with `theme_xaringan()` 37 | that uses the colors and fonts from your slide theme. 38 | Built on the [showtext] package, 39 | and designed to work seamlessly with [Google Fonts](https://fonts.google.com). 40 | 41 | Color and fill scales are also provided 42 | for matching sequential color scales based on 43 | the primary color used in your slides. 44 | See `?scale_xaringan` for more details. 45 | 46 | More details and examples can be found in `vignette("ggplot2-themes")`. 47 | 48 | ```{r xaringanthemer-ggplot-setup, include=FALSE, eval=!IN_PKGDOWN} 49 | style_mono_accent( 50 | base_color = "#1c5253", 51 | header_font_google = google_font("Josefin Sans"), 52 | text_font_google = google_font("Montserrat", "300", "300i"), 53 | code_font_google = google_font("Fira Mono"), 54 | outfile = NULL 55 | ) 56 | ``` 57 | 58 | ```{r theme_xaringan_demo, echo=TRUE, warning=FALSE, fig.width=13, fig.height=5.5, eval=!IN_PKGDOWN, fig.showtext=TRUE} 59 | library(ggplot2) 60 | ggplot(diamonds) + 61 | aes(cut, fill = cut) + 62 | geom_bar(show.legend = FALSE) + 63 | labs( 64 | x = "Cut", 65 | y = "Count", 66 | title = "A Fancy diamonds Plot" 67 | ) + 68 | theme_xaringan(background_color = "#FFFFFF") + 69 | scale_xaringan_fill_discrete() 70 | ``` 71 | 72 | ```{r link-to-plot-image, echo=FALSE, eval=IN_PKGDOWN, results='asis'} 73 | cat("![](../reference/figures/index-theme_xaringan_demo-1.png)") 74 | ``` 75 | 76 | 77 | ### Tab Completion 78 | 79 | **xaringanthemer** is Tab friendly -- [use autocomplete to explore][theme-settings] the [template variables][template-variables] that you can adjust in each of the themes! 80 | 81 | Demonstration of argument auto-completion with RStudio 82 | 83 | ### R Markdown Template in RStudio 84 | 85 | You can also skip the above and just create a *Ninja Themed Presentation* from the New R Markdown Document menu in RStudio. 86 | 87 |
88 | The 'New R Markdown Document' menu in RStudio 89 |
90 | -------------------------------------------------------------------------------- /man/fragments/_tagline-gif.Rmd: -------------------------------------------------------------------------------- 1 | [xaringan]: https://github.com/yihui/xaringan 2 | 3 | Give your [xaringan] slides some style with **xaringanthemer** within your `slides.Rmd` file without (much) CSS. 4 | 5 | Animation previewing many xaringanthemer themes 6 | -------------------------------------------------------------------------------- /man/fragments/_thanks.Rmd: -------------------------------------------------------------------------------- 1 | *** 2 | 3 | [xaringan]: https://github.com/yihui/xaringan 4 | [remarkjs]: https://github.com/gnab/remark 5 | 6 | **xaringanthemer** was built by [Garrick Aden-Buie](https://www.garrickadenbuie.com) ([@grrrck](https://twitter.com/grrrck)). 7 | 8 | Big thank you to [Yihui Xie](https://yihui.org/), especially for [xaringan]. 9 | Also thanks to [Ole Petter Bang](https://gnab.org/) for [remark.js][remarkjs]. 10 | 11 | Feel free to [file an issue](https://github.com/gadenbuie/xaringanthemer/issues) 12 | if you find a bug or have a theme suggestion -- or better yet, submit a pull request! 13 | -------------------------------------------------------------------------------- /man/fragments/_themes.Rmd: -------------------------------------------------------------------------------- 1 | **xaringanthemer** includes a number of functions that provide 2 | themed **xaringan** styles. 3 | All of the styling functions start with the `style_` prefix. 4 | 5 | The goal of each style function is to 6 | quickly set up a coordinated color palette for your slides 7 | based on one or two starter colors. 8 | Styles based on one color start with `style_mono_` 9 | and styles based on two colors start with `style_duo_`. 10 | How the starter colors are used is described 11 | in the final portion of the style function name. 12 | For example, `style_mono_accent()` uses a single color as an accent color. 13 | 14 | Note that the colors used below are for demonstration only, 15 | the point of the `style_` functions is for you to choose your own color palette! 16 | 17 | If your color palette uses more than two colors, 18 | you can add additional colors with the `colors` argument. 19 | See the [Colors](#colors) section for more information. 20 | 21 | ### Monotone 22 | 23 | ```{r include=FALSE} 24 | IS_README <- exists("IS_README") && IS_README 25 | include_graphic <- function(img_path) { 26 | glue::glue( 27 | '' 29 | ) 30 | } 31 | ``` 32 | 33 | Use these functions to automatically create a consistent color palette for your slides, based around a single color. 34 | 35 | #### `style_mono_light()` 36 | 37 | A light theme based around a single color. 38 | 39 | ```{r style_mono_light} 40 | demo_function_call <- function(f, n_params = 1) { 41 | cat(sep = "", 42 | "```r\n", 43 | paste(substitute(f)), "(", 44 | if (n_params > 0) paste(collapse = ", ", 45 | sapply(1:n_params, function(i) { 46 | paste0(names(formals(f))[i], ' = "', formals(f)[[i]], '"')})), 47 | ")\n```" 48 | ) 49 | } 50 | demo_function_call(style_mono_light, 1) 51 | ``` 52 | 53 | `r include_graphic("example_mono_light.png")` 54 | 55 | #### `style_mono_dark()` 56 | 57 | A dark theme based around a single color. 58 | 59 | ```{r style_mono_dark} 60 | demo_function_call(style_mono_dark, 1) 61 | ``` 62 | 63 | `r include_graphic("example_mono_dark.png")` 64 | 65 | #### `style_mono_accent()` 66 | 67 | The default xaringan theme with a single color used for color accents on select elements (headers, bold text, etc.). 68 | 69 | ```{r style_mono_accent} 70 | demo_function_call(style_mono_accent, 1) 71 | ``` 72 | 73 | `r include_graphic("example_mono_accent.png")` 74 | 75 | #### `style_mono_accent_inverse()` 76 | 77 | An "inverted" default xaringan theme with a single color used for color accents on select elements (headers, bold text, etc.). 78 | 79 | ```{r style_mono_accent_inverse} 80 | demo_function_call(style_mono_accent_inverse, 1) 81 | ``` 82 | 83 | `r include_graphic("example_mono_accent_inverse.png")` 84 | 85 | 86 | ### Duotone 87 | 88 | These themes build from two (ideally) complementary colors. 89 | 90 | #### `style_duo()` 91 | 92 | A two-colored theme based on a primary and secondary color. 93 | 94 | ```{r style_duo} 95 | demo_function_call(style_duo, 2) 96 | ``` 97 | 98 | `r include_graphic("example_duo.png")` 99 | 100 | #### `style_duo_accent()` 101 | 102 | The default Xaringan theme with two accent colors. 103 | 104 | ```{r style_duo_accent} 105 | demo_function_call(style_duo_accent, 2) 106 | ``` 107 | 108 | `r include_graphic("example_duo_accent.png")` 109 | 110 | #### `style_duo_accent_inverse()` 111 | 112 | An "inverted" default Xaringan theme with two accent colors. 113 | 114 | ```{r style_duo_accent_inverse} 115 | demo_function_call(style_duo_accent_inverse, 2) 116 | ``` 117 | 118 | `r include_graphic("example_duo_accent_inverse.png")` 119 | 120 | ### Solarized 121 | 122 | There are also two themes based around the [solarized color palette](https://ethanschoonover.com/solarized/), `style_solarized_light()` and `style_solarized_dark()`. 123 | For both themes, it is advisted to change the syntax highlighting theme to `solarized-light` or `solarized-dark` (looks great paired or constrasted). 124 | 125 | #### `style_solarized_light()` 126 | 127 | ```{r style_solarized_light} 128 | demo_function_call(style_solarized_light, 0) 129 | ``` 130 | 131 | `r include_graphic("example_solarized_light.png")` 132 | 133 | #### `style_solarized_dark()` 134 | 135 | ```{r style_solarized_dark} 136 | demo_function_call(style_solarized_dark, 0) 137 | ``` 138 | 139 | `r include_graphic("example_solarized_dark.png")` 140 | 141 | 142 | To do this, your YAML header should look more-or-less like this: 143 | 144 | ```yaml 145 | output: 146 | xaringan::moon_reader: 147 | css: ["xaringan-themer.css"] 148 | nature: 149 | highlightStyle: solarized-dark 150 | highlightLines: true 151 | countIncrementalSlides: false 152 | ``` 153 | -------------------------------------------------------------------------------- /man/google_font.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{google_font} 4 | \alias{google_font} 5 | \title{Specify Google Font} 6 | \usage{ 7 | google_font(family, ..., languages = NULL) 8 | } 9 | \arguments{ 10 | \item{family}{Font family} 11 | 12 | \item{...}{Font weights to include, example "400", "400i"} 13 | 14 | \item{languages}{Font languages to include (dependent on the font.) See 15 | \code{\link[=google_language_codes]{google_language_codes()}}.} 16 | } 17 | \value{ 18 | A \code{"google_font"} object. 19 | } 20 | \description{ 21 | Builds Google Fonts URL from family name. Extra weights are given in the 22 | \code{...} parameters. Languages can be specified in \code{languages} and must one or 23 | more of the language codes as given by \code{google_language_codes()}. 24 | } 25 | \examples{ 26 | google_font("Josefin Sans", "400", "400i", "600i", "700") 27 | google_font("Josefin Sans", languages = c("latin-ext", "vietnamese")) 28 | } 29 | -------------------------------------------------------------------------------- /man/google_language_codes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{google_language_codes} 4 | \alias{google_language_codes} 5 | \title{List Valid Google Language Codes} 6 | \usage{ 7 | google_language_codes( 8 | language_codes = c("latin", "latin-ext", "sinhala", "greek", "hebrew", "vietnamese", 9 | "cyrillic", "cyrillic-ext", "devanagari", "arabic", "khmer", "tamil", "greek-ext", 10 | "thai", "bengali", "gujarati", "oriya", "malayalam", "gurmukhi", "kannada", "telugu", 11 | "myanmar") 12 | ) 13 | } 14 | \arguments{ 15 | \item{language_codes}{Vector of potential Google language codes} 16 | } 17 | \value{ 18 | A vector of Google Font language codes matching \code{language_codes}. 19 | } 20 | \description{ 21 | Gives a list of valid Language Codes for Google Fonts, or 22 | validates that the language codes given are valid. 23 | } 24 | \seealso{ 25 | \code{\link[=google_font]{google_font()}} 26 | } 27 | -------------------------------------------------------------------------------- /man/lighten_darken_color.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/color.R 3 | \name{lighten_darken_color} 4 | \alias{lighten_darken_color} 5 | \alias{lighten_color} 6 | \alias{darken_color} 7 | \title{Generate lighter or darker version of a color} 8 | \usage{ 9 | lighten_color(color_hex, strength = 0.7) 10 | 11 | darken_color(color_hex, strength = 0.8) 12 | } 13 | \arguments{ 14 | \item{color_hex}{A character string representing a hex color} 15 | 16 | \item{strength}{The "strength" of the blend with white or black, 17 | where 0 is entirely the original color and 1 is entirely white 18 | (\code{lighten_color()}) or black (\code{darken_color()}).} 19 | } 20 | \value{ 21 | A character string with the lightened or darkened color in 22 | hexadecimal format. 23 | } 24 | \description{ 25 | Produces a linear blend of the color with white or black. 26 | } 27 | \examples{ 28 | blue <- "#0e6ba8" 29 | blue_light <- lighten_color(blue, strength = 0.33) 30 | blue_dark <- darken_color(blue, strength = 0.33) 31 | 32 | if (requireNamespace("scales", quietly = TRUE)) { 33 | scales::show_col(c(blue_light, blue, blue_dark)) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /man/scale_xaringan.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggplot2.R 3 | \name{scale_xaringan} 4 | \alias{scale_xaringan} 5 | \alias{scale_xaringan_discrete} 6 | \alias{scale_xaringan_fill_discrete} 7 | \alias{scale_xaringan_color_discrete} 8 | \alias{scale_xaringan_colour_discrete} 9 | \alias{scale_xaringan_continuous} 10 | \alias{scale_xaringan_fill_continuous} 11 | \alias{scale_xaringan_color_continuous} 12 | \alias{scale_xaringan_colour_continuous} 13 | \title{Themed ggplot2 Scales} 14 | \usage{ 15 | scale_xaringan_discrete( 16 | aes_type = c("color", "colour", "fill"), 17 | ..., 18 | color = NULL, 19 | direction = 1, 20 | inverse = FALSE 21 | ) 22 | 23 | scale_xaringan_fill_discrete(..., color = NULL, direction = 1, inverse = FALSE) 24 | 25 | scale_xaringan_color_discrete( 26 | ..., 27 | color = NULL, 28 | direction = 1, 29 | inverse = FALSE 30 | ) 31 | 32 | scale_xaringan_colour_discrete( 33 | ..., 34 | color = NULL, 35 | direction = 1, 36 | inverse = FALSE 37 | ) 38 | 39 | scale_xaringan_continuous( 40 | aes_type = c("color", "colour", "fill"), 41 | ..., 42 | color = NULL, 43 | begin = 0, 44 | end = 1, 45 | inverse = FALSE 46 | ) 47 | 48 | scale_xaringan_fill_continuous( 49 | ..., 50 | color = NULL, 51 | begin = 0, 52 | end = 1, 53 | inverse = FALSE 54 | ) 55 | 56 | scale_xaringan_color_continuous( 57 | ..., 58 | color = NULL, 59 | begin = 0, 60 | end = 1, 61 | inverse = FALSE 62 | ) 63 | 64 | scale_xaringan_colour_continuous( 65 | ..., 66 | color = NULL, 67 | begin = 0, 68 | end = 1, 69 | inverse = FALSE 70 | ) 71 | } 72 | \arguments{ 73 | \item{aes_type}{The type of aesthetic to which the scale is being applied. 74 | One of "color", "colour", or "fill".} 75 | 76 | \item{...}{Arguments passed on to either the \pkg{colorspace} scale 77 | functions — one of \code{\link[colorspace:scale_colour_discrete_sequential]{colorspace::scale_color_discrete_sequential()}}, 78 | \code{\link[colorspace:scale_colour_continuous_sequential]{colorspace::scale_color_continuous_sequential()}}, 79 | \code{\link[colorspace:scale_colour_discrete_sequential]{colorspace::scale_fill_discrete_sequential()}}, or 80 | \code{\link[colorspace:scale_colour_continuous_sequential]{colorspace::scale_fill_continuous_sequential()}} — or to 81 | \link[ggplot2:continuous_scale]{ggplot2::continuous_scale} or \link[ggplot2:discrete_scale]{ggplot2::discrete_scale}.} 82 | 83 | \item{color}{A color value, in hex, to override the default color. Otherwise, 84 | the primary color of the resulting scale is chosen from the xaringanthemer 85 | slide styles.} 86 | 87 | \item{direction}{Direction of the discrete scale. Use values less than 0 to 88 | reverse the direction, e.g. \code{direction = -1}.} 89 | 90 | \item{inverse}{If \code{color} is not supplied and \code{inverse = TRUE}, a primary 91 | color is chosen to work well with the inverse slide styles, namely the 92 | value of \code{inverse_header_color}} 93 | 94 | \item{begin}{Number in the range of \code{[0, 1]} indicating to which point in the color scale the smallest data value should be mapped.} 95 | 96 | \item{end}{Number in the range of \code{[0, 1]} indicating to which point in the color scale the largest data value should be mapped.} 97 | } 98 | \description{ 99 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#maturing}{\figure{lifecycle-maturing.svg}{options: alt='[Maturing]'}}}{\strong{[Maturing]}} 100 | 101 | Color and fill single-color scales for discrete and continuous values, 102 | created using the primary accent color of the xaringanthemer styles. See 103 | \code{vignette("ggplot2-themes")} for more information and examples of 104 | \pkg{xaringanthemer}'s \pkg{ggplot2}-related functions. 105 | } 106 | \examples{ 107 | # Requires ggplot2 108 | has_ggplot2 <- requireNamespace("ggplot2", quietly = TRUE) 109 | 110 | if (has_ggplot2) { 111 | library(ggplot2) 112 | # Saving the theme to a temp file because this is an example 113 | path_to_css_file <- tempfile(fileext = ".css") 114 | 115 | # Create the xaringan theme: dark blue background with teal green accents 116 | style_duo( 117 | primary_color = "#002b36", 118 | secondary_color = "#31b09e", 119 | # Using basic fonts for this example, but the plot theme will 120 | # automatically use your theme font if you use Google fonts 121 | text_font_family = "sans", 122 | header_font_family = "serif", 123 | outfile = path_to_css_file 124 | ) 125 | 126 | # Here's some very basic example data 127 | ex <- data.frame( 128 | name = c("Couple", "Few", "Lots", "Many"), 129 | n = c(2, 3, 5, 7) 130 | ) 131 | 132 | # Fill color scales demo 133 | ggplot(ex) + 134 | aes(name, n, fill = n) + 135 | geom_col() + 136 | ggtitle("Matching fill scales") + 137 | # themed to match the slides: dark blue background with teal text 138 | theme_xaringan() + 139 | # Fill color matches teal text 140 | scale_xaringan_fill_continuous() 141 | 142 | # Color scales demo 143 | ggplot(ex) + 144 | aes(name, y = 1, color = name) + 145 | geom_point(size = 10) + 146 | ggtitle("Matching color scales") + 147 | # themed to match the slides: dark blue background with teal text 148 | theme_xaringan() + 149 | # Fill color matches teal text 150 | scale_xaringan_color_discrete(direction = -1) 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /man/style_extra_css.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/style_extra_css.R 3 | \name{style_extra_css} 4 | \alias{style_extra_css} 5 | \title{Add Extra CSS Styles} 6 | \usage{ 7 | style_extra_css( 8 | css, 9 | outfile = "xaringan-themer.css", 10 | append = TRUE, 11 | heading = "Extra CSS" 12 | ) 13 | } 14 | \arguments{ 15 | \item{css}{A named list of CSS definitions each containing a named list 16 | of CSS property-value pairs, i.e. 17 | \code{list(".class-id" = list("css-property" = "value"))}} 18 | 19 | \item{outfile}{Customized xaringan CSS output file name, default is "xaringan-themer.css"} 20 | 21 | \item{append}{If \code{TRUE} output will be appended to \code{outfile}; otherwise, 22 | it will overwrite the contents of \code{outfile}.} 23 | 24 | \item{heading}{Heading added above extra CSS. Use \code{NULL} to disable.} 25 | } 26 | \description{ 27 | Adds css elements to target \code{outfile}, typically a xaringanthemer css file. 28 | The \code{css} argument takes a list of CSS classes and definitions (see examples below) 29 | and appends CSS rules to \code{outfile}. 30 | } 31 | \section{css list}{ 32 | 33 | The \code{css} input must be a named list of css properties and values within a 34 | named list of class identifiers, for example 35 | \code{list(".class-id" = list("css-property" = "value"))}. 36 | } 37 | 38 | \examples{ 39 | style_extra_css( 40 | outfile = stdout(), 41 | css = list( 42 | ".red" = list(color = "red"), 43 | ".small" = list("font-size" = "90\%"), 44 | ".full-width" = list( 45 | display = "flex", 46 | width = "100\%", 47 | flex = "1 1 auto" 48 | ) 49 | ) 50 | ) 51 | } 52 | -------------------------------------------------------------------------------- /man/theme_xaringan.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggplot2.R 3 | \name{theme_xaringan} 4 | \alias{theme_xaringan} 5 | \title{A Plot Theme for ggplot2 by xaringanthemer} 6 | \usage{ 7 | theme_xaringan( 8 | text_color = NULL, 9 | background_color = NULL, 10 | accent_color = NULL, 11 | accent_secondary_color = NULL, 12 | css_file = NULL, 13 | set_ggplot_defaults = TRUE, 14 | text_font = NULL, 15 | text_font_use_google = NULL, 16 | text_font_size = NULL, 17 | title_font = NULL, 18 | title_font_use_google = NULL, 19 | title_font_size = NULL, 20 | use_showtext = NULL 21 | ) 22 | } 23 | \arguments{ 24 | \item{text_color}{Color for text and foreground, inherits from \code{text_color}} 25 | 26 | \item{background_color}{Color for background, inherits from 27 | \code{background_color}} 28 | 29 | \item{accent_color}{Color for titles and accents, inherits from 30 | \code{header_color}} 31 | 32 | \item{accent_secondary_color}{Color for secondary accents, inherits from 33 | \code{text_bold_color}} 34 | 35 | \item{css_file}{Path to a \pkg{xaringanthemer} CSS file, from which the 36 | theme variables and values will be inferred. In general, if you use the 37 | \pkg{xaringathemer} defaults, you will not need to set this. This feature 38 | lets you create a \pkg{ggplot2} theme for your \pkg{xaringan} slides, even 39 | if you have only saved your theme CSS file and you aren't creating your 40 | CSS theme with \pkg{xaringanthemer} in your slides' source file.} 41 | 42 | \item{set_ggplot_defaults}{Should defaults be set for \pkg{ggplot2} \emph{geoms}? 43 | Defaults to TRUE. To restore ggplot's defaults, or the previously set geom 44 | defaults, see \code{\link[=theme_xaringan_restore_defaults]{theme_xaringan_restore_defaults()}}.} 45 | 46 | \item{text_font}{Font to use for text elements, passed to 47 | \code{\link[sysfonts:font_add_google]{sysfonts::font_add_google()}}, if available and \code{text_font_use_google} is 48 | \code{TRUE}. Inherits from \code{text_font_family}. If manually specified, can be a 49 | \code{\link[=google_font]{google_font()}}.} 50 | 51 | \item{text_font_use_google}{Is \code{text_font} available on \href{https://fonts.google.com}{Google Fonts}?} 52 | 53 | \item{text_font_size}{Base text font size, inherits from \code{text_font_size}, or 54 | defaults to 11.} 55 | 56 | \item{title_font}{Font to use for title elements, passed to 57 | \code{\link[sysfonts:font_add_google]{sysfonts::font_add_google()}}, if available and \code{title_font_use_google} is 58 | \code{TRUE}. Inherits from \code{title_font_family}. If manually specified, can be a 59 | \code{\link[=google_font]{google_font()}}.} 60 | 61 | \item{title_font_use_google}{Is \code{title_font} available on \href{https://fonts.google.com}{Google Fonts}?} 62 | 63 | \item{title_font_size}{Base text font size, inherits from \code{title_font_size}, 64 | or defaults to 14.} 65 | 66 | \item{use_showtext}{If \code{TRUE} the \pkg{showtext} package will be 67 | used to register Google fonts. Set to \code{FALSE} to disable this feature 68 | entirely, which may result in errors during plotting if the fonts used are 69 | not available locally. The default is \code{TRUE} when the \pkg{showtext} 70 | package is installed.} 71 | } 72 | \value{ 73 | A ggplot2 theme 74 | } 75 | \description{ 76 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#maturing}{\figure{lifecycle-maturing.svg}{options: alt='[Maturing]'}}}{\strong{[Maturing]}} 77 | 78 | Creates \pkg{ggplot2} themes to match the xaringanthemer theme used in the 79 | \pkg{xaringan} slides that seamlessly matches the "normal" slide colors and 80 | styles. See \code{vignette("ggplot2-themes")} for more information and examples. 81 | } 82 | \examples{ 83 | # Requires ggplot2 84 | has_ggplot2 <- requireNamespace("ggplot2", quietly = TRUE) 85 | 86 | if (has_ggplot2) { 87 | # Because this is an example, we'll save the CSS to a temp file 88 | path_to_css_file <- tempfile(fileext = ".css") 89 | 90 | # Create the xaringan theme: dark blue background with teal green accents 91 | style_duo( 92 | primary_color = "#002b36", 93 | secondary_color = "#31b09e", 94 | # Using basic fonts for this example, but the plot theme will 95 | # automatically use your theme font if you use Google fonts 96 | text_font_family = "sans", 97 | header_font_family = "serif", 98 | outfile = path_to_css_file 99 | ) 100 | 101 | library(ggplot2) 102 | ggplot(mpg) + 103 | aes(cty, hwy) + 104 | geom_point() + 105 | ggtitle("Fuel Efficiency of Various Cars") + 106 | theme_xaringan() 107 | } 108 | } 109 | \seealso{ 110 | Other xaringanthemer ggplot2 themes: 111 | \code{\link{theme_xaringan_base}()}, 112 | \code{\link{theme_xaringan_inverse}()}, 113 | \code{\link{theme_xaringan_set_defaults}()} 114 | } 115 | \concept{xaringanthemer ggplot2 themes} 116 | -------------------------------------------------------------------------------- /man/theme_xaringan_base.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggplot2.R 3 | \name{theme_xaringan_base} 4 | \alias{theme_xaringan_base} 5 | \title{The ggplot2 xaringanthemer base plot theme} 6 | \usage{ 7 | theme_xaringan_base( 8 | text_color, 9 | background_color, 10 | ..., 11 | set_ggplot_defaults = TRUE, 12 | accent_color = NULL, 13 | accent_secondary_color = NULL, 14 | text_font = NULL, 15 | text_font_use_google = NULL, 16 | text_font_size = NULL, 17 | title_font = NULL, 18 | title_font_use_google = NULL, 19 | title_font_size = NULL, 20 | use_showtext = NULL 21 | ) 22 | } 23 | \arguments{ 24 | \item{text_color}{Color for text and foreground} 25 | 26 | \item{background_color}{Color for background} 27 | 28 | \item{...}{Ignored} 29 | 30 | \item{set_ggplot_defaults}{Should defaults be set for \pkg{ggplot2} \emph{geoms}? 31 | Defaults to TRUE. To restore ggplot's defaults, or the previously set geom 32 | defaults, see \code{\link[=theme_xaringan_restore_defaults]{theme_xaringan_restore_defaults()}}.} 33 | 34 | \item{accent_color}{Color for titles and accents, inherits from 35 | \code{header_color} or \code{text_color}. Used for the \code{title} base setting in 36 | \code{\link[ggplot2:theme]{ggplot2::theme()}}, and additionally for setting the \code{color} or \code{fill} of 37 | \pkg{ggplot2} geom defaults.} 38 | 39 | \item{accent_secondary_color}{Color for secondary accents, inherits from 40 | \code{text_bold_color} or \code{accent_color}. Used only when setting \pkg{ggplot2} geom 41 | defaults.} 42 | 43 | \item{text_font}{Font to use for text elements, passed to 44 | \code{\link[sysfonts:font_add_google]{sysfonts::font_add_google()}}, if available and \code{text_font_use_google} is 45 | \code{TRUE}. Inherits from \code{text_font_family}. If manually specified, can be a 46 | \code{\link[=google_font]{google_font()}}.} 47 | 48 | \item{text_font_use_google}{Is \code{text_font} available on \href{https://fonts.google.com}{Google Fonts}?} 49 | 50 | \item{text_font_size}{Base text font size, inherits from \code{text_font_size}, or 51 | defaults to 11.} 52 | 53 | \item{title_font}{Font to use for title elements, passed to 54 | \code{\link[sysfonts:font_add_google]{sysfonts::font_add_google()}}, if available and \code{title_font_use_google} is 55 | \code{TRUE}. Inherits from \code{title_font_family}. If manually specified, can be a 56 | \code{\link[=google_font]{google_font()}}.} 57 | 58 | \item{title_font_use_google}{Is \code{title_font} available on \href{https://fonts.google.com}{Google Fonts}?} 59 | 60 | \item{title_font_size}{Base text font size, inherits from \code{title_font_size}, 61 | or defaults to 14.} 62 | 63 | \item{use_showtext}{If \code{TRUE} the \pkg{showtext} package will be 64 | used to register Google fonts. Set to \code{FALSE} to disable this feature 65 | entirely, which may result in errors during plotting if the fonts used are 66 | not available locally. The default is \code{TRUE} when the \pkg{showtext} 67 | package is installed.} 68 | } 69 | \value{ 70 | A ggplot2 theme 71 | } 72 | \description{ 73 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#maturing}{\figure{lifecycle-maturing.svg}{options: alt='[Maturing]'}}}{\strong{[Maturing]}} 74 | 75 | Provides a base plot theme for \pkg{ggplot2} to match the \pkg{xaringan} 76 | slide theme created by \link{xaringanthemer}. The theme is designed to create a 77 | general plot style from two colors, a \code{background_color} and a \code{text_color} 78 | (or foreground color). Also accepts an \code{accent_color} and an 79 | \code{accent_secondary_color} that are \link{xaringanthemer} is not required for the 80 | base theme. Use \code{\link[=theme_xaringan]{theme_xaringan()}} or \code{\link[=theme_xaringan_inverse]{theme_xaringan_inverse()}} in xaringan 81 | slides styled by xaringanthemer for a plot theme that matches the slide 82 | style. See \code{vignette("ggplot2-themes")} for more information and examples. 83 | } 84 | \examples{ 85 | # Requires ggplot2 86 | has_ggplot2 <- requireNamespace("ggplot2", quietly = TRUE) 87 | 88 | if (has_ggplot2) { 89 | library(ggplot2) 90 | 91 | plot1 <- ggplot(mpg) + 92 | aes(cty, hwy) + 93 | geom_point() + 94 | theme_xaringan_base( 95 | text_color = "#602f6b", # imperial 96 | background_color = "#f8f8f8", # light gray 97 | accent_color = "#317873", # myrtle green 98 | title_font = "sans", 99 | text_font = "serif", 100 | set_ggplot_defaults = TRUE 101 | ) + 102 | labs( 103 | title = "Fuel Efficiency of Various Cars", 104 | subtitle = "+ theme_xaringan_base()", 105 | caption = "xaringanthemer" 106 | ) 107 | 108 | print(plot1) 109 | 110 | plot2 <- ggplot(mpg) + 111 | aes(hwy) + 112 | geom_histogram(binwidth = 2) + 113 | theme_xaringan_base( 114 | text_color = "#a8a9c8", # light purple 115 | background_color = "#303163", # deep slate purple 116 | accent_color = "#ffff99", # canary yellow 117 | title_font = "sans", 118 | text_font = "serif", 119 | set_ggplot_defaults = TRUE 120 | ) + 121 | labs( 122 | title = "Highway Fuel Efficiency", 123 | subtitle = "+ theme_xaringan_base()", 124 | caption = "xaringanthemer" 125 | ) 126 | 127 | print(plot2) 128 | } 129 | } 130 | \seealso{ 131 | Other xaringanthemer ggplot2 themes: 132 | \code{\link{theme_xaringan}()}, 133 | \code{\link{theme_xaringan_inverse}()}, 134 | \code{\link{theme_xaringan_set_defaults}()} 135 | } 136 | \concept{xaringanthemer ggplot2 themes} 137 | -------------------------------------------------------------------------------- /man/theme_xaringan_get_value.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggplot2.R 3 | \name{theme_xaringan_get_value} 4 | \alias{theme_xaringan_get_value} 5 | \title{Get the Value of xaringanthemer Style Setting} 6 | \usage{ 7 | theme_xaringan_get_value(setting, css_file = NULL) 8 | } 9 | \arguments{ 10 | \item{setting}{A xaringanthemer style setting} 11 | 12 | \item{css_file}{Path to a \pkg{xaringanthemer} CSS file, from which the 13 | theme variables and values will be inferred. In general, if you use the 14 | \pkg{xaringathemer} defaults, you will not need to set this. This feature 15 | lets you create a \pkg{ggplot2} theme for your \pkg{xaringan} slides, even 16 | if you have only saved your theme CSS file and you aren't creating your 17 | CSS theme with \pkg{xaringanthemer} in your slides' source file.} 18 | } 19 | \value{ 20 | The value of the xaringanthemer style parameter. 21 | } 22 | \description{ 23 | A helper function to retrieve the value of style settings as set by a 24 | xaringanthemer style function, for use in plotting and other circumstances. 25 | } 26 | \section{Style Settings}{ 27 | 28 | Style settings used by xaringanthemer include: 29 | \itemize{ 30 | \item \code{background_color} 31 | \item \code{background_image} 32 | \item \code{background_position} 33 | \item \code{background_size} 34 | \item \code{blockquote_left_border_color} 35 | \item \code{code_font_family} 36 | \item \code{code_font_family_fallback} 37 | \item \code{code_font_google} 38 | \item \code{code_font_is_google} 39 | \item \code{code_font_size} 40 | \item \code{code_font_url} 41 | \item \code{code_highlight_color} 42 | \item \code{code_inline_background_color} 43 | \item \code{code_inline_color} 44 | \item \code{code_inline_font_size} 45 | \item \code{extra_css} 46 | \item \code{extra_fonts} 47 | \item \code{footnote_color} 48 | \item \code{footnote_font_size} 49 | \item \code{footnote_position_bottom} 50 | \item \code{header_background_auto} 51 | \item \code{header_background_color} 52 | \item \code{header_background_content_padding_top} 53 | \item \code{header_background_ignore_classes} 54 | \item \code{header_background_padding} 55 | \item \code{header_background_text_color} 56 | \item \code{header_color} 57 | \item \code{header_font_family} 58 | \item \code{header_font_google} 59 | \item \code{header_font_is_google} 60 | \item \code{header_font_url} 61 | \item \code{header_font_weight} 62 | \item \code{header_h1_font_size} 63 | \item \code{header_h2_font_size} 64 | \item \code{header_h3_font_size} 65 | \item \code{inverse_background_color} 66 | \item \code{inverse_header_color} 67 | \item \code{inverse_text_color} 68 | \item \code{inverse_text_shadow} 69 | \item \code{left_column_selected_color} 70 | \item \code{left_column_subtle_color} 71 | \item \code{link_color} 72 | \item \code{padding} 73 | \item \code{table_border_color} 74 | \item \code{table_row_border_color} 75 | \item \code{table_row_even_background_color} 76 | \item \code{text_bold_color} 77 | \item \code{text_color} 78 | \item \code{text_font_base} 79 | \item \code{text_font_family} 80 | \item \code{text_font_family_fallback} 81 | \item \code{text_font_google} 82 | \item \code{text_font_is_google} 83 | \item \code{text_font_size} 84 | \item \code{text_font_url} 85 | \item \code{text_font_weight} 86 | \item \code{text_slide_number_color} 87 | \item \code{text_slide_number_font_size} 88 | \item \code{title_slide_background_color} 89 | \item \code{title_slide_background_image} 90 | \item \code{title_slide_background_position} 91 | \item \code{title_slide_background_size} 92 | \item \code{title_slide_text_color} 93 | } 94 | } 95 | 96 | \examples{ 97 | # Create a xaringanthemer style in a temporary file for this example 98 | xaringan_themer_css <- tempfile("xaringan-themer", fileext = ".css") 99 | 100 | style_solarized_light(outfile = xaringan_themer_css) 101 | 102 | theme_xaringan_get_value("text_color") 103 | theme_xaringan_get_value("background_color") 104 | theme_xaringan_get_value("header_color") 105 | theme_xaringan_get_value("text_bold_color") 106 | } 107 | -------------------------------------------------------------------------------- /man/theme_xaringan_inverse.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggplot2.R 3 | \name{theme_xaringan_inverse} 4 | \alias{theme_xaringan_inverse} 5 | \title{An Inverse Plot Theme for ggplot2 by xaringanthemer} 6 | \usage{ 7 | theme_xaringan_inverse( 8 | text_color = NULL, 9 | background_color = NULL, 10 | accent_color = NULL, 11 | accent_secondary_color = NULL, 12 | css_file = NULL, 13 | set_ggplot_defaults = TRUE, 14 | text_font = NULL, 15 | text_font_use_google = NULL, 16 | text_font_size = NULL, 17 | title_font = NULL, 18 | title_font_use_google = NULL, 19 | title_font_size = NULL, 20 | use_showtext = NULL 21 | ) 22 | } 23 | \arguments{ 24 | \item{text_color}{Color for text and foreground, inherits from \code{text_color}} 25 | 26 | \item{background_color}{Color for background, inherits from 27 | \code{background_color}} 28 | 29 | \item{accent_color}{Color for titles and accents, inherits from 30 | \code{header_color}} 31 | 32 | \item{accent_secondary_color}{Color for secondary accents, inherits from 33 | \code{text_bold_color}} 34 | 35 | \item{css_file}{Path to a \pkg{xaringanthemer} CSS file, from which the 36 | theme variables and values will be inferred. In general, if you use the 37 | \pkg{xaringathemer} defaults, you will not need to set this. This feature 38 | lets you create a \pkg{ggplot2} theme for your \pkg{xaringan} slides, even 39 | if you have only saved your theme CSS file and you aren't creating your 40 | CSS theme with \pkg{xaringanthemer} in your slides' source file.} 41 | 42 | \item{set_ggplot_defaults}{Should defaults be set for \pkg{ggplot2} \emph{geoms}? 43 | Defaults to TRUE. To restore ggplot's defaults, or the previously set geom 44 | defaults, see \code{\link[=theme_xaringan_restore_defaults]{theme_xaringan_restore_defaults()}}.} 45 | 46 | \item{text_font}{Font to use for text elements, passed to 47 | \code{\link[sysfonts:font_add_google]{sysfonts::font_add_google()}}, if available and \code{text_font_use_google} is 48 | \code{TRUE}. Inherits from \code{text_font_family}. If manually specified, can be a 49 | \code{\link[=google_font]{google_font()}}.} 50 | 51 | \item{text_font_use_google}{Is \code{text_font} available on \href{https://fonts.google.com}{Google Fonts}?} 52 | 53 | \item{text_font_size}{Base text font size, inherits from \code{text_font_size}, or 54 | defaults to 11.} 55 | 56 | \item{title_font}{Font to use for title elements, passed to 57 | \code{\link[sysfonts:font_add_google]{sysfonts::font_add_google()}}, if available and \code{title_font_use_google} is 58 | \code{TRUE}. Inherits from \code{title_font_family}. If manually specified, can be a 59 | \code{\link[=google_font]{google_font()}}.} 60 | 61 | \item{title_font_use_google}{Is \code{title_font} available on \href{https://fonts.google.com}{Google Fonts}?} 62 | 63 | \item{title_font_size}{Base text font size, inherits from \code{title_font_size}, 64 | or defaults to 14.} 65 | 66 | \item{use_showtext}{If \code{TRUE} the \pkg{showtext} package will be 67 | used to register Google fonts. Set to \code{FALSE} to disable this feature 68 | entirely, which may result in errors during plotting if the fonts used are 69 | not available locally. The default is \code{TRUE} when the \pkg{showtext} 70 | package is installed.} 71 | } 72 | \value{ 73 | A ggplot2 theme 74 | } 75 | \description{ 76 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#maturing}{\figure{lifecycle-maturing.svg}{options: alt='[Maturing]'}}}{\strong{[Maturing]}} 77 | 78 | A \pkg{ggplot2} xaringanthemer plot theme to seamlessly match the "inverse" 79 | \pkg{xaringan} slide colors and styles as styled by \link{xaringanthemer}. See 80 | \code{vignette("ggplot2-themes")} for more information and examples. 81 | } 82 | \examples{ 83 | # Requires ggplot2 84 | has_ggplot2 <- requireNamespace("ggplot2", quietly = TRUE) 85 | 86 | if (has_ggplot2) { 87 | # Because this is an example, we'll save the CSS to a temp file 88 | path_to_css_file <- tempfile(fileext = ".css") 89 | 90 | # Create the xaringan theme: dark blue background with teal green accents 91 | style_duo( 92 | primary_color = "#002b36", 93 | secondary_color = "#31b09e", 94 | # Using basic fonts for this example, but the plot theme will 95 | # automatically use your theme font if you use Google fonts 96 | text_font_family = "sans", 97 | header_font_family = "serif", 98 | outfile = path_to_css_file 99 | ) 100 | 101 | library(ggplot2) 102 | ggplot(mpg) + 103 | aes(cty, hwy) + 104 | geom_point() + 105 | ggtitle("Fuel Efficiency of Various Cars") + 106 | # themed to match the inverse slides: teal background with dark blue text 107 | theme_xaringan_inverse() 108 | } 109 | } 110 | \seealso{ 111 | Other xaringanthemer ggplot2 themes: 112 | \code{\link{theme_xaringan}()}, 113 | \code{\link{theme_xaringan_base}()}, 114 | \code{\link{theme_xaringan_set_defaults}()} 115 | } 116 | \concept{xaringanthemer ggplot2 themes} 117 | -------------------------------------------------------------------------------- /man/theme_xaringan_set_defaults.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggplot2.R 3 | \name{theme_xaringan_set_defaults} 4 | \alias{theme_xaringan_set_defaults} 5 | \alias{theme_xaringan_restore_defaults} 6 | \title{Set and Restore ggplot2 geom Defaults} 7 | \usage{ 8 | theme_xaringan_set_defaults( 9 | text_color = NULL, 10 | background_color = NULL, 11 | accent_color = text_color, 12 | accent_secondary_color = accent_color, 13 | text_font = NULL 14 | ) 15 | 16 | theme_xaringan_restore_defaults() 17 | } 18 | \arguments{ 19 | \item{text_color}{Color for text and foreground, inherits from \code{text_color}} 20 | 21 | \item{background_color}{Color for background, inherits from 22 | \code{background_color}} 23 | 24 | \item{accent_color}{Color for titles and accents, inherits from 25 | \code{header_color}} 26 | 27 | \item{accent_secondary_color}{Color for secondary accents, inherits from 28 | \code{text_bold_color}} 29 | 30 | \item{text_font}{Font to use for text elements, passed to 31 | \code{\link[sysfonts:font_add_google]{sysfonts::font_add_google()}}, if available and \code{text_font_use_google} is 32 | \code{TRUE}. Inherits from \code{text_font_family}. Must be a length-one character.} 33 | } 34 | \value{ 35 | Invisibly returns a list of the current ggplot2 geom defaults 36 | 37 | Invisibly returns a list of the current ggplot2 geom defaults 38 | } 39 | \description{ 40 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#maturing}{\figure{lifecycle-maturing.svg}{options: alt='[Maturing]'}}}{\strong{[Maturing]}} 41 | 42 | Set \pkg{ggplot2} \emph{geom} defaults to match \code{\link[=theme_xaringan]{theme_xaringan()}} with 43 | \code{theme_xaringan_set_defaults()} and restore the standard or previously-set 44 | defaults with \code{theme_xaringan_restore_defaults()}. By default, 45 | \code{theme_xaringan_set_defaults()} is run with \code{\link[=theme_xaringan]{theme_xaringan()}} or 46 | \code{\link[=theme_xaringan_inverse]{theme_xaringan_inverse()}}. 47 | } 48 | \section{Functions}{ 49 | \itemize{ 50 | \item \code{theme_xaringan_restore_defaults()}: Restore previous or standard 51 | \pkg{ggplot2} \emph{geom} defaults. 52 | 53 | }} 54 | \seealso{ 55 | Other xaringanthemer ggplot2 themes: 56 | \code{\link{theme_xaringan}()}, 57 | \code{\link{theme_xaringan_base}()}, 58 | \code{\link{theme_xaringan_inverse}()} 59 | } 60 | \concept{xaringanthemer ggplot2 themes} 61 | -------------------------------------------------------------------------------- /man/xaringanthemer-deprecated.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/xaringanthemer-deprecated.R 3 | \name{xaringanthemer-deprecated} 4 | \alias{xaringanthemer-deprecated} 5 | \alias{write_xaringan_theme} 6 | \alias{write_extra_css} 7 | \alias{mono_light} 8 | \alias{mono_dark} 9 | \alias{mono_accent} 10 | \alias{mono_accent_inverse} 11 | \alias{duo} 12 | \alias{duo_accent} 13 | \alias{duo_accent_inverse} 14 | \alias{solarized_light} 15 | \alias{solarized_dark} 16 | \title{Deprecated or renamed functions} 17 | \usage{ 18 | write_xaringan_theme(...) 19 | 20 | write_extra_css(...) 21 | 22 | mono_light(...) 23 | 24 | mono_dark(...) 25 | 26 | mono_accent(...) 27 | 28 | mono_accent_inverse(...) 29 | 30 | duo(...) 31 | 32 | duo_accent(...) 33 | 34 | duo_accent_inverse(...) 35 | 36 | solarized_light(...) 37 | 38 | solarized_dark(...) 39 | } 40 | \arguments{ 41 | \item{...}{Argumets passed to the new or renamed functions.} 42 | } 43 | \value{ 44 | The result of the new or renamed function. 45 | } 46 | \description{ 47 | These functions in xaringanthemer have been deprecated or renamed. 48 | 49 | Use \code{\link[=style_xaringan]{style_xaringan()}} instead of \code{write_xaringan_theme()}. 50 | 51 | Use \code{\link[=style_extra_css]{style_extra_css()}} instead of \code{write_extra_css()}. 52 | 53 | Use \code{\link[=style_mono_light]{style_mono_light()}} instead of \code{mono_light()}. 54 | 55 | Use \code{\link[=style_mono_dark]{style_mono_dark()}} instead of \code{mono_dark()}. 56 | 57 | Use \code{\link[=style_mono_accent]{style_mono_accent()}} instead of \code{mono_accent()}. 58 | 59 | Use \code{\link[=style_mono_accent_inverse]{style_mono_accent_inverse()}} instead of \code{mono_accent_inverse()}. 60 | 61 | Use \code{\link[=style_duo]{style_duo()}} instead of \code{duo()}. 62 | 63 | Use \code{\link[=style_duo_accent]{style_duo_accent()}} instead of \code{duo_accent()}. 64 | 65 | Use \code{\link[=style_duo_accent_inverse]{style_duo_accent_inverse()}} instead of \code{duo_accent_inverse()}. 66 | 67 | Use \code{\link[=style_solarized_light]{style_solarized_light()}} instead of \code{solarized_light()}. 68 | 69 | Use \code{\link[=style_solarized_dark]{style_solarized_dark()}} instead of \code{solarized_dark()}. 70 | } 71 | \keyword{internal} 72 | -------------------------------------------------------------------------------- /man/xaringanthemer-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/xaringanthemer-package.R 3 | \docType{package} 4 | \name{xaringanthemer-package} 5 | \alias{xaringanthemer} 6 | \alias{xaringanthemer-package} 7 | \title{xaringanthemer: Custom 'xaringan' CSS Themes} 8 | \description{ 9 | \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} 10 | 11 | Create beautifully color-coordinated and customized themes for your 'xaringan' slides, without writing any CSS. Complete your slide theme with 'ggplot2' themes that match the font and colors used in your slides. Customized styles can be created directly in your slides' 'R Markdown' source file or in a separate external script. 12 | } 13 | \seealso{ 14 | Useful links: 15 | \itemize{ 16 | \item \url{https://pkg.garrickadenbuie.com/xaringanthemer/} 17 | \item \url{https://github.com/gadenbuie/xaringanthemer} 18 | \item Report bugs at \url{https://github.com/gadenbuie/xaringanthemer/issues} 19 | } 20 | 21 | } 22 | \author{ 23 | \strong{Maintainer}: Garrick Aden-Buie \email{garrick@adenbuie.com} (\href{https://orcid.org/0000-0002-7111-0077}{ORCID}) 24 | 25 | } 26 | \keyword{internal} 27 | -------------------------------------------------------------------------------- /pkgdown/_pkgdown.yml: -------------------------------------------------------------------------------- 1 | authors: 2 | Garrick Aden-Buie: 3 | href: https://www.garrickadenbuie.com 4 | 5 | url: https://pkg.garrickadenbuie.com/xaringanthemer/ 6 | 7 | home: 8 | description: | 9 | Give your xaringan slides some style with xaringanthemer. 10 | Easy slide and plot themes for xaringan slides. 11 | 12 | development: 13 | mode: auto 14 | 15 | template: 16 | package: grkgdown 17 | 18 | navbar: 19 | type: light 20 | left: 21 | - text: Features 22 | href: articles/xaringanthemer.html 23 | - text: Reference 24 | href: reference/index.html 25 | - text: Themes 26 | menu: 27 | - text: Themes 28 | - text: Slide Themes 29 | href: articles/themes.html 30 | - text: ggplot2 Themes 31 | href: articles/ggplot2-themes.html 32 | - text: ------- 33 | - text: More Customization 34 | - text: Fonts 35 | href: articles/fonts.html 36 | - text: Template Variables 37 | href: articles/template-variables.html 38 | right: 39 | news: 40 | icon: far fa-newspaper fa-lg 41 | text: "" 42 | menu: 43 | - text: "xaringanthemer 0.3.0" 44 | href: https://garrickadenbuie.com/blog/xaringanthemer-v0-3-0/ 45 | - text: ------- 46 | - text: "Changelog" 47 | href: news/index.html 48 | github: 49 | icon: fab fa-github fa-lg 50 | href: https://github.com/gadenbuie/xaringanthemer 51 | twitter: 52 | icon: fab fa-twitter fa-lg 53 | href: https://twitter.com/grrrck 54 | home: 55 | icon: fas fa-home fa-lg 56 | href: https://www.garrickadenbuie.com 57 | 58 | reference: 59 | - title: Writing CSS 60 | desc: Functions that write CSS from inside a xaringan R markdown document. 61 | contents: 62 | - style_xaringan 63 | - style_extra_css 64 | - title: xaringan Themes 65 | desc: | 66 | Parameterized styles for xaringan slides using one (mono) 67 | or two (duo) base colors. Bonus: slide styles based on the 68 | solarized color palette. 69 | contents: 70 | - starts_with("style_mono") 71 | - starts_with("style_duo") 72 | - starts_with("style_solarized") 73 | - title: Google Fonts 74 | desc: Helper functions for using Google Fonts in your slide styles. 75 | contents: 76 | - starts_with("google_") 77 | - title: ggplot2 Themes 78 | desc: Plot themes for ggplot2 to match your xaringanthemer slide styles. 79 | contents: 80 | - theme_xaringan 81 | - theme_xaringan_inverse 82 | - theme_xaringan_base 83 | - theme_xaringan_set_defaults 84 | - starts_with("scale_xaringan") 85 | - title: Helper functions 86 | desc: Helpers for Google fonts and color adjustments. 87 | contents: 88 | - theme_xaringan_get_value 89 | - ends_with("color") 90 | - apply_alpha 91 | - choose_dark_or_light 92 | -------------------------------------------------------------------------------- /pkgdown/extra.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --bs-light-rgb: 249, 250, 250; 3 | } 4 | 5 | .bg-light { 6 | --bs-bg-opacity: 0.95; 7 | } 8 | 9 | pre { 10 | border: none; 11 | border-left: 2px solid #cfd5d8; 12 | border-radius: 0; 13 | background-color: var(--bs-body-bg); 14 | line-height: 1.33; 15 | } 16 | 17 | main pre a { 18 | text-decoration: none; 19 | } 20 | 21 | main pre a:hover { 22 | text-decoration: underline; 23 | } 24 | 25 | @media (max-width: 575.98px) { 26 | .container main pre { 27 | margin-left: calc(var(--bs-gutter-x) * -.5); 28 | margin-right: calc(var(--bs-gutter-x) * -.5 - 1px); 29 | border-radius: 0; 30 | padding-left: 1rem; 31 | padding-right: 1rem; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/xaringanthemer/51b100a9a42808ae1afc8761dfe262e38845d3e2/pkgdown/favicon/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/xaringanthemer/51b100a9a42808ae1afc8761dfe262e38845d3e2/pkgdown/favicon/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/xaringanthemer/51b100a9a42808ae1afc8761dfe262e38845d3e2/pkgdown/favicon/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/xaringanthemer/51b100a9a42808ae1afc8761dfe262e38845d3e2/pkgdown/favicon/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/xaringanthemer/51b100a9a42808ae1afc8761dfe262e38845d3e2/pkgdown/favicon/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/xaringanthemer/51b100a9a42808ae1afc8761dfe262e38845d3e2/pkgdown/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/xaringanthemer/51b100a9a42808ae1afc8761dfe262e38845d3e2/pkgdown/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/xaringanthemer/51b100a9a42808ae1afc8761dfe262e38845d3e2/pkgdown/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/xaringanthemer/51b100a9a42808ae1afc8761dfe262e38845d3e2/pkgdown/favicon/favicon.ico -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(xaringanthemer) 3 | 4 | test_check("xaringanthemer") 5 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/utils.md: -------------------------------------------------------------------------------- 1 | # printing google_font works 2 | 3 | Code 4 | google_font("Josefin Sans", "400", "400i", "600i", "700") 5 | Output 6 | Family: Josefin Sans 7 | Weights: 400,400i,600i,700 8 | URL: https://fonts.googleapis.com/css?family=Josefin+Sans:400,400i,600i,700&display=swap 9 | 10 | -------------------------------------------------------------------------------- /tests/testthat/css/google_fonts.css: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------- 2 | * 3 | * !! This file was generated by xaringanthemer !! 4 | * 5 | * Changes made to this file directly will be overwritten 6 | * if you used xaringanthemer in your xaringan slides Rmd 7 | * 8 | * Issues or likes? 9 | * - https://github.com/gadenbuie/xaringanthemer 10 | * - https://www.garrickadenbuie.com 11 | * 12 | * Need help? Try: 13 | * - vignette(package = "xaringanthemer") 14 | * - ?xaringanthemer::style_xaringan 15 | * - xaringan wiki: https://github.com/yihui/xaringan/wiki 16 | * - remarkjs wiki: https://github.com/gnab/remark/wiki 17 | * 18 | * Version: a.b.c.d.eeee 19 | * 20 | * ------------------------------------------------------- */ 21 | @import url(https://fonts.googleapis.com/css?family=Noto+Serif&display=swap); 22 | @import url(https://fonts.googleapis.com/css?family=IBM+Plex+Serif:700&display=swap); 23 | @import url(https://fonts.googleapis.com/css?family=IBM+Plex+Mono&display=swap); 24 | 25 | 26 | :root { 27 | /* Fonts */ 28 | --text-font-family: 'Noto Serif'; 29 | --text-font-is-google: 1; 30 | --text-font-family-fallback: -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, Ubuntu, roboto, noto, segoe ui, arial; 31 | --text-font-base: sans-serif; 32 | --header-font-family: 'IBM Plex Serif'; 33 | --header-font-is-google: 1; 34 | --header-font-family-fallback: Georgia, serif; 35 | --code-font-family: 'IBM Plex Mono'; 36 | --code-font-is-google: 1; 37 | --base-font-size: 20px; 38 | --text-font-size: 1rem; 39 | --code-font-size: 0.9rem; 40 | --code-inline-font-size: 1em; 41 | --header-h1-font-size: 2.75rem; 42 | --header-h2-font-size: 2.25rem; 43 | --header-h3-font-size: 1.75rem; 44 | 45 | /* Colors */ 46 | --text-color: #000; 47 | --header-color: #000; 48 | --background-color: #FFF; 49 | --link-color: rgb(249, 38, 114); 50 | --code-highlight-color: rgba(255,255,0,0.5); 51 | --inverse-text-color: #d6d6d6; 52 | --inverse-background-color: #272822; 53 | --inverse-header-color: #f3f3f3; 54 | --inverse-link-color: rgb(249, 38, 114); 55 | --title-slide-background-color: #272822; 56 | --title-slide-text-color: #d6d6d6; 57 | --header-background-color: #000; 58 | --header-background-text-color: #FFF; 59 | } 60 | 61 | html { 62 | font-size: var(--base-font-size); 63 | } 64 | 65 | body { 66 | font-family: var(--text-font-family), var(--text-font-family-fallback), var(--text-font-base); 67 | font-weight: normal; 68 | color: var(--text-color); 69 | } 70 | h1, h2, h3 { 71 | font-family: var(--header-font-family), var(--header-font-family-fallback); 72 | font-weight: 600; 73 | color: var(--header-color); 74 | } 75 | .remark-slide-content { 76 | background-color: var(--background-color); 77 | font-size: 1rem; 78 | padding: 16px 64px 16px 64px; 79 | width: 100%; 80 | height: 100%; 81 | } 82 | .remark-slide-content h1 { 83 | font-size: var(--header-h1-font-size); 84 | } 85 | .remark-slide-content h2 { 86 | font-size: var(--header-h2-font-size); 87 | } 88 | .remark-slide-content h3 { 89 | font-size: var(--header-h3-font-size); 90 | } 91 | .remark-code, .remark-inline-code { 92 | font-family: var(--code-font-family), Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace; 93 | } 94 | .remark-code { 95 | font-size: var(--code-font-size); 96 | } 97 | .remark-inline-code { 98 | font-size: var(--code-inline-font-size); 99 | color: #000; 100 | } 101 | .remark-slide-number { 102 | color: #272822; 103 | opacity: 1; 104 | font-size: 0.9rem; 105 | } 106 | strong { 107 | font-weight: bold; 108 | } 109 | a, a > code { 110 | color: var(--link-color); 111 | text-decoration: none; 112 | } 113 | .footnote { 114 | position: absolute; 115 | bottom: 60px; 116 | padding-right: 4em; 117 | font-size: 0.9em; 118 | } 119 | .remark-code-line-highlighted { 120 | background-color: var(--code-highlight-color); 121 | } 122 | .inverse { 123 | background-color: var(--inverse-background-color); 124 | color: var(--inverse-text-color); 125 | 126 | } 127 | .inverse h1, .inverse h2, .inverse h3 { 128 | color: var(--inverse-header-color); 129 | } 130 | .inverse a, .inverse a > code { 131 | color: var(--inverse-link-color); 132 | } 133 | .title-slide, .title-slide h1, .title-slide h2, .title-slide h3 { 134 | color: var(--title-slide-text-color); 135 | } 136 | .title-slide { 137 | background-color: var(--title-slide-background-color); 138 | } 139 | .title-slide .remark-slide-number { 140 | display: none; 141 | } 142 | /* Two-column layout */ 143 | .left-column { 144 | width: 20%; 145 | height: 92%; 146 | float: left; 147 | } 148 | .left-column h2, .left-column h3 { 149 | color: #777; 150 | } 151 | .left-column h2:last-of-type, .left-column h3:last-child { 152 | color: #000; 153 | } 154 | .right-column { 155 | width: 75%; 156 | float: right; 157 | padding-top: 1em; 158 | } 159 | .pull-left { 160 | float: left; 161 | width: 47%; 162 | } 163 | .pull-right { 164 | float: right; 165 | width: 47%; 166 | } 167 | .pull-right + * { 168 | clear: both; 169 | } 170 | img, video, iframe { 171 | max-width: 100%; 172 | } 173 | blockquote { 174 | border-left: solid 5px lightgray; 175 | padding-left: 1em; 176 | } 177 | .remark-slide table { 178 | margin: auto; 179 | border-top: 1px solid #666; 180 | border-bottom: 1px solid #666; 181 | } 182 | .remark-slide table thead th { 183 | border-bottom: 1px solid #ddd; 184 | } 185 | th, td { 186 | padding: 5px; 187 | } 188 | .remark-slide table:not(.table-unshaded) thead, 189 | .remark-slide table:not(.table-unshaded) tfoot, 190 | .remark-slide table:not(.table-unshaded) tr:nth-child(even) { 191 | background: #eee; 192 | } 193 | table.dataTable tbody { 194 | background-color: var(--background-color); 195 | color: var(--text-color); 196 | } 197 | table.dataTable.display tbody tr.odd { 198 | background-color: var(--background-color); 199 | } 200 | table.dataTable.display tbody tr.even { 201 | background-color: #eee; 202 | } 203 | table.dataTable.hover tbody tr:hover, table.dataTable.display tbody tr:hover { 204 | background-color: rgba(255, 255, 255, 0.5); 205 | } 206 | .dataTables_wrapper .dataTables_length, .dataTables_wrapper .dataTables_filter, .dataTables_wrapper .dataTables_info, .dataTables_wrapper .dataTables_processing, .dataTables_wrapper .dataTables_paginate { 207 | color: var(--text-color); 208 | } 209 | .dataTables_wrapper .dataTables_paginate .paginate_button { 210 | color: var(--text-color) !important; 211 | } 212 | 213 | /* Horizontal alignment of code blocks */ 214 | .remark-slide-content.left pre, 215 | .remark-slide-content.center pre, 216 | .remark-slide-content.right pre { 217 | text-align: start; 218 | width: max-content; 219 | max-width: 100%; 220 | } 221 | .remark-slide-content.left pre, 222 | .remark-slide-content.right pre { 223 | min-width: 50%; 224 | min-width: min(40ch, 100%); 225 | } 226 | .remark-slide-content.center pre { 227 | min-width: 66%; 228 | min-width: min(50ch, 100%); 229 | } 230 | .remark-slide-content.left pre { 231 | margin-left: unset; 232 | margin-right: auto; 233 | } 234 | .remark-slide-content.center pre { 235 | margin-left: auto; 236 | margin-right: auto; 237 | } 238 | .remark-slide-content.right pre { 239 | margin-left: auto; 240 | margin-right: unset; 241 | } 242 | 243 | /* Slide Header Background for h1 elements */ 244 | .remark-slide-content.header_background > h1 { 245 | display: block; 246 | position: absolute; 247 | top: 0; 248 | left: 0; 249 | width: 100%; 250 | background: var(--header-background-color); 251 | color: var(--header-background-text-color); 252 | padding: 2rem 64px 1.5rem 64px; 253 | margin-top: 0; 254 | box-sizing: border-box; 255 | } 256 | .remark-slide-content.header_background { 257 | padding-top: 7rem; 258 | } 259 | 260 | @page { margin: 0; } 261 | @media print { 262 | .remark-slide-scaler { 263 | width: 100% !important; 264 | height: 100% !important; 265 | transform: scale(1) !important; 266 | top: 0 !important; 267 | left: 0 !important; 268 | } 269 | } 270 | 271 | -------------------------------------------------------------------------------- /tests/testthat/css/solarized_dark.css: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------- 2 | * 3 | * !! This file was generated by xaringanthemer !! 4 | * 5 | * Changes made to this file directly will be overwritten 6 | * if you used xaringanthemer in your xaringan slides Rmd 7 | * 8 | * Issues or likes? 9 | * - https://github.com/gadenbuie/xaringanthemer 10 | * - https://www.garrickadenbuie.com 11 | * 12 | * Need help? Try: 13 | * - vignette(package = "xaringanthemer") 14 | * - ?xaringanthemer::style_xaringan 15 | * - xaringan wiki: https://github.com/yihui/xaringan/wiki 16 | * - remarkjs wiki: https://github.com/gnab/remark/wiki 17 | * 18 | * Version: a.b.c.d.eeee 19 | * 20 | * ------------------------------------------------------- */ 21 | @import url(https://fonts.googleapis.com/css?family=Noto+Serif&display=swap); 22 | @import url(https://fonts.googleapis.com/css?family=Cabin:600,600i&display=swap); 23 | @import url(https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700&display=swap); 24 | 25 | 26 | :root { 27 | /* Fonts */ 28 | --text-font-family: 'Noto Serif'; 29 | --text-font-is-google: 1; 30 | --text-font-family-fallback: -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, Ubuntu, roboto, noto, segoe ui, arial; 31 | --text-font-base: sans-serif; 32 | --header-font-family: Cabin; 33 | --header-font-is-google: 1; 34 | --header-font-family-fallback: Georgia, serif; 35 | --code-font-family: 'Source Code Pro'; 36 | --code-font-is-google: 1; 37 | --base-font-size: 20px; 38 | --text-font-size: 1rem; 39 | --code-font-size: 0.9rem; 40 | --code-inline-font-size: 1em; 41 | --header-h1-font-size: 2.75rem; 42 | --header-h2-font-size: 2.25rem; 43 | --header-h3-font-size: 1.75rem; 44 | 45 | /* Colors */ 46 | --text-color: #839496; 47 | --header-color: #dc322f; 48 | --background-color: #002b36; 49 | --link-color: #b58900; 50 | --text-bold-color: #d33682; 51 | --code-highlight-color: #268bd240; 52 | --inverse-text-color: #002b36; 53 | --inverse-background-color: #fdf6e3; 54 | --inverse-header-color: #002b36; 55 | --inverse-link-color: #b58900; 56 | --title-slide-background-color: #fdf6e3; 57 | --title-slide-text-color: #002b36; 58 | --header-background-color: #dc322f; 59 | --header-background-text-color: #002b36; 60 | } 61 | 62 | html { 63 | font-size: var(--base-font-size); 64 | } 65 | 66 | body { 67 | font-family: var(--text-font-family), var(--text-font-family-fallback), var(--text-font-base); 68 | font-weight: normal; 69 | color: var(--text-color); 70 | } 71 | h1, h2, h3 { 72 | font-family: var(--header-font-family), var(--header-font-family-fallback); 73 | font-weight: 600; 74 | color: var(--header-color); 75 | } 76 | .remark-slide-content { 77 | background-color: var(--background-color); 78 | font-size: 1rem; 79 | padding: 16px 64px 16px 64px; 80 | width: 100%; 81 | height: 100%; 82 | } 83 | .remark-slide-content h1 { 84 | font-size: var(--header-h1-font-size); 85 | } 86 | .remark-slide-content h2 { 87 | font-size: var(--header-h2-font-size); 88 | } 89 | .remark-slide-content h3 { 90 | font-size: var(--header-h3-font-size); 91 | } 92 | .remark-code, .remark-inline-code { 93 | font-family: var(--code-font-family), Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace; 94 | } 95 | .remark-code { 96 | font-size: var(--code-font-size); 97 | } 98 | .remark-inline-code { 99 | font-size: var(--code-inline-font-size); 100 | color: #6c71c4; 101 | } 102 | .remark-slide-number { 103 | color: #586e75; 104 | opacity: 1; 105 | font-size: 0.9rem; 106 | } 107 | strong { 108 | font-weight: bold; 109 | color: var(--text-bold-color); 110 | } 111 | a, a > code { 112 | color: var(--link-color); 113 | text-decoration: none; 114 | } 115 | .footnote { 116 | position: absolute; 117 | bottom: 60px; 118 | padding-right: 4em; 119 | font-size: 0.9em; 120 | } 121 | .remark-code-line-highlighted { 122 | background-color: var(--code-highlight-color); 123 | } 124 | .inverse { 125 | background-color: var(--inverse-background-color); 126 | color: var(--inverse-text-color); 127 | 128 | } 129 | .inverse h1, .inverse h2, .inverse h3 { 130 | color: var(--inverse-header-color); 131 | } 132 | .inverse a, .inverse a > code { 133 | color: var(--inverse-link-color); 134 | } 135 | .title-slide, .title-slide h1, .title-slide h2, .title-slide h3 { 136 | color: var(--title-slide-text-color); 137 | } 138 | .title-slide { 139 | background-color: var(--title-slide-background-color); 140 | } 141 | .title-slide .remark-slide-number { 142 | display: none; 143 | } 144 | /* Two-column layout */ 145 | .left-column { 146 | width: 20%; 147 | height: 92%; 148 | float: left; 149 | } 150 | .left-column h2, .left-column h3 { 151 | color: #586e75; 152 | } 153 | .left-column h2:last-of-type, .left-column h3:last-child { 154 | color: #93a1a1; 155 | } 156 | .right-column { 157 | width: 75%; 158 | float: right; 159 | padding-top: 1em; 160 | } 161 | .pull-left { 162 | float: left; 163 | width: 47%; 164 | } 165 | .pull-right { 166 | float: right; 167 | width: 47%; 168 | } 169 | .pull-right + * { 170 | clear: both; 171 | } 172 | img, video, iframe { 173 | max-width: 100%; 174 | } 175 | blockquote { 176 | border-left: solid 5px #cb4b16; 177 | padding-left: 1em; 178 | } 179 | .remark-slide table { 180 | margin: auto; 181 | border-top: 1px solid #657b83; 182 | border-bottom: 1px solid #657b83; 183 | } 184 | .remark-slide table thead th { 185 | border-bottom: 1px solid #657b83; 186 | } 187 | th, td { 188 | padding: 5px; 189 | } 190 | .remark-slide table:not(.table-unshaded) thead, 191 | .remark-slide table:not(.table-unshaded) tfoot, 192 | .remark-slide table:not(.table-unshaded) tr:nth-child(even) { 193 | background: #073642; 194 | } 195 | table.dataTable tbody { 196 | background-color: var(--background-color); 197 | color: var(--text-color); 198 | } 199 | table.dataTable.display tbody tr.odd { 200 | background-color: var(--background-color); 201 | } 202 | table.dataTable.display tbody tr.even { 203 | background-color: #073642; 204 | } 205 | table.dataTable.hover tbody tr:hover, table.dataTable.display tbody tr:hover { 206 | background-color: rgba(255, 255, 255, 0.5); 207 | } 208 | .dataTables_wrapper .dataTables_length, .dataTables_wrapper .dataTables_filter, .dataTables_wrapper .dataTables_info, .dataTables_wrapper .dataTables_processing, .dataTables_wrapper .dataTables_paginate { 209 | color: var(--text-color); 210 | } 211 | .dataTables_wrapper .dataTables_paginate .paginate_button { 212 | color: var(--text-color) !important; 213 | } 214 | 215 | /* Horizontal alignment of code blocks */ 216 | .remark-slide-content.left pre, 217 | .remark-slide-content.center pre, 218 | .remark-slide-content.right pre { 219 | text-align: start; 220 | width: max-content; 221 | max-width: 100%; 222 | } 223 | .remark-slide-content.left pre, 224 | .remark-slide-content.right pre { 225 | min-width: 50%; 226 | min-width: min(40ch, 100%); 227 | } 228 | .remark-slide-content.center pre { 229 | min-width: 66%; 230 | min-width: min(50ch, 100%); 231 | } 232 | .remark-slide-content.left pre { 233 | margin-left: unset; 234 | margin-right: auto; 235 | } 236 | .remark-slide-content.center pre { 237 | margin-left: auto; 238 | margin-right: auto; 239 | } 240 | .remark-slide-content.right pre { 241 | margin-left: auto; 242 | margin-right: unset; 243 | } 244 | 245 | /* Slide Header Background for h1 elements */ 246 | .remark-slide-content.header_background > h1 { 247 | display: block; 248 | position: absolute; 249 | top: 0; 250 | left: 0; 251 | width: 100%; 252 | background: var(--header-background-color); 253 | color: var(--header-background-text-color); 254 | padding: 2rem 64px 1.5rem 64px; 255 | margin-top: 0; 256 | box-sizing: border-box; 257 | } 258 | .remark-slide-content.header_background { 259 | padding-top: 7rem; 260 | } 261 | 262 | @page { margin: 0; } 263 | @media print { 264 | .remark-slide-scaler { 265 | width: 100% !important; 266 | height: 100% !important; 267 | transform: scale(1) !important; 268 | top: 0 !important; 269 | left: 0 !important; 270 | } 271 | } 272 | 273 | -------------------------------------------------------------------------------- /tests/testthat/css/solarized_light.css: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------- 2 | * 3 | * !! This file was generated by xaringanthemer !! 4 | * 5 | * Changes made to this file directly will be overwritten 6 | * if you used xaringanthemer in your xaringan slides Rmd 7 | * 8 | * Issues or likes? 9 | * - https://github.com/gadenbuie/xaringanthemer 10 | * - https://www.garrickadenbuie.com 11 | * 12 | * Need help? Try: 13 | * - vignette(package = "xaringanthemer") 14 | * - ?xaringanthemer::style_xaringan 15 | * - xaringan wiki: https://github.com/yihui/xaringan/wiki 16 | * - remarkjs wiki: https://github.com/gnab/remark/wiki 17 | * 18 | * Version: a.b.c.d.eeee 19 | * 20 | * ------------------------------------------------------- */ 21 | @import url(https://fonts.googleapis.com/css?family=Noto+Serif&display=swap); 22 | @import url(https://fonts.googleapis.com/css?family=Cabin:600,600i&display=swap); 23 | @import url(https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700&display=swap); 24 | 25 | 26 | :root { 27 | /* Fonts */ 28 | --text-font-family: 'Noto Serif'; 29 | --text-font-is-google: 1; 30 | --text-font-family-fallback: -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, Ubuntu, roboto, noto, segoe ui, arial; 31 | --text-font-base: sans-serif; 32 | --header-font-family: Cabin; 33 | --header-font-is-google: 1; 34 | --header-font-family-fallback: Georgia, serif; 35 | --code-font-family: 'Source Code Pro'; 36 | --code-font-is-google: 1; 37 | --base-font-size: 20px; 38 | --text-font-size: 1rem; 39 | --code-font-size: 0.9rem; 40 | --code-inline-font-size: 1em; 41 | --header-h1-font-size: 2.75rem; 42 | --header-h2-font-size: 2.25rem; 43 | --header-h3-font-size: 1.75rem; 44 | 45 | /* Colors */ 46 | --text-color: #657b83; 47 | --header-color: #dc322f; 48 | --background-color: #fdf6e3; 49 | --link-color: #b58900; 50 | --text-bold-color: #d33682; 51 | --code-highlight-color: #268bd240; 52 | --inverse-text-color: #fdf6e3; 53 | --inverse-background-color: #002b36; 54 | --inverse-header-color: #fdf6e3; 55 | --inverse-link-color: #b58900; 56 | --title-slide-background-color: #002b36; 57 | --title-slide-text-color: #fdf6e3; 58 | --header-background-color: #dc322f; 59 | --header-background-text-color: #fdf6e3; 60 | } 61 | 62 | html { 63 | font-size: var(--base-font-size); 64 | } 65 | 66 | body { 67 | font-family: var(--text-font-family), var(--text-font-family-fallback), var(--text-font-base); 68 | font-weight: normal; 69 | color: var(--text-color); 70 | } 71 | h1, h2, h3 { 72 | font-family: var(--header-font-family), var(--header-font-family-fallback); 73 | font-weight: 600; 74 | color: var(--header-color); 75 | } 76 | .remark-slide-content { 77 | background-color: var(--background-color); 78 | font-size: 1rem; 79 | padding: 16px 64px 16px 64px; 80 | width: 100%; 81 | height: 100%; 82 | } 83 | .remark-slide-content h1 { 84 | font-size: var(--header-h1-font-size); 85 | } 86 | .remark-slide-content h2 { 87 | font-size: var(--header-h2-font-size); 88 | } 89 | .remark-slide-content h3 { 90 | font-size: var(--header-h3-font-size); 91 | } 92 | .remark-code, .remark-inline-code { 93 | font-family: var(--code-font-family), Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace; 94 | } 95 | .remark-code { 96 | font-size: var(--code-font-size); 97 | } 98 | .remark-inline-code { 99 | font-size: var(--code-inline-font-size); 100 | color: #6c71c4; 101 | } 102 | .remark-slide-number { 103 | color: #93a1a1; 104 | opacity: 1; 105 | font-size: 0.9rem; 106 | } 107 | strong { 108 | font-weight: bold; 109 | color: var(--text-bold-color); 110 | } 111 | a, a > code { 112 | color: var(--link-color); 113 | text-decoration: none; 114 | } 115 | .footnote { 116 | position: absolute; 117 | bottom: 60px; 118 | padding-right: 4em; 119 | font-size: 0.9em; 120 | } 121 | .remark-code-line-highlighted { 122 | background-color: var(--code-highlight-color); 123 | } 124 | .inverse { 125 | background-color: var(--inverse-background-color); 126 | color: var(--inverse-text-color); 127 | 128 | } 129 | .inverse h1, .inverse h2, .inverse h3 { 130 | color: var(--inverse-header-color); 131 | } 132 | .inverse a, .inverse a > code { 133 | color: var(--inverse-link-color); 134 | } 135 | .title-slide, .title-slide h1, .title-slide h2, .title-slide h3 { 136 | color: var(--title-slide-text-color); 137 | } 138 | .title-slide { 139 | background-color: var(--title-slide-background-color); 140 | } 141 | .title-slide .remark-slide-number { 142 | display: none; 143 | } 144 | /* Two-column layout */ 145 | .left-column { 146 | width: 20%; 147 | height: 92%; 148 | float: left; 149 | } 150 | .left-column h2, .left-column h3 { 151 | color: #93a1a1; 152 | } 153 | .left-column h2:last-of-type, .left-column h3:last-child { 154 | color: #586e75; 155 | } 156 | .right-column { 157 | width: 75%; 158 | float: right; 159 | padding-top: 1em; 160 | } 161 | .pull-left { 162 | float: left; 163 | width: 47%; 164 | } 165 | .pull-right { 166 | float: right; 167 | width: 47%; 168 | } 169 | .pull-right + * { 170 | clear: both; 171 | } 172 | img, video, iframe { 173 | max-width: 100%; 174 | } 175 | blockquote { 176 | border-left: solid 5px #cb4b16; 177 | padding-left: 1em; 178 | } 179 | .remark-slide table { 180 | margin: auto; 181 | border-top: 1px solid #839496; 182 | border-bottom: 1px solid #839496; 183 | } 184 | .remark-slide table thead th { 185 | border-bottom: 1px solid #839496; 186 | } 187 | th, td { 188 | padding: 5px; 189 | } 190 | .remark-slide table:not(.table-unshaded) thead, 191 | .remark-slide table:not(.table-unshaded) tfoot, 192 | .remark-slide table:not(.table-unshaded) tr:nth-child(even) { 193 | background: #eee8d5; 194 | } 195 | table.dataTable tbody { 196 | background-color: var(--background-color); 197 | color: var(--text-color); 198 | } 199 | table.dataTable.display tbody tr.odd { 200 | background-color: var(--background-color); 201 | } 202 | table.dataTable.display tbody tr.even { 203 | background-color: #eee8d5; 204 | } 205 | table.dataTable.hover tbody tr:hover, table.dataTable.display tbody tr:hover { 206 | background-color: rgba(255, 255, 255, 0.5); 207 | } 208 | .dataTables_wrapper .dataTables_length, .dataTables_wrapper .dataTables_filter, .dataTables_wrapper .dataTables_info, .dataTables_wrapper .dataTables_processing, .dataTables_wrapper .dataTables_paginate { 209 | color: var(--text-color); 210 | } 211 | .dataTables_wrapper .dataTables_paginate .paginate_button { 212 | color: var(--text-color) !important; 213 | } 214 | 215 | /* Horizontal alignment of code blocks */ 216 | .remark-slide-content.left pre, 217 | .remark-slide-content.center pre, 218 | .remark-slide-content.right pre { 219 | text-align: start; 220 | width: max-content; 221 | max-width: 100%; 222 | } 223 | .remark-slide-content.left pre, 224 | .remark-slide-content.right pre { 225 | min-width: 50%; 226 | min-width: min(40ch, 100%); 227 | } 228 | .remark-slide-content.center pre { 229 | min-width: 66%; 230 | min-width: min(50ch, 100%); 231 | } 232 | .remark-slide-content.left pre { 233 | margin-left: unset; 234 | margin-right: auto; 235 | } 236 | .remark-slide-content.center pre { 237 | margin-left: auto; 238 | margin-right: auto; 239 | } 240 | .remark-slide-content.right pre { 241 | margin-left: auto; 242 | margin-right: unset; 243 | } 244 | 245 | /* Slide Header Background for h1 elements */ 246 | .remark-slide-content.header_background > h1 { 247 | display: block; 248 | position: absolute; 249 | top: 0; 250 | left: 0; 251 | width: 100%; 252 | background: var(--header-background-color); 253 | color: var(--header-background-text-color); 254 | padding: 2rem 64px 1.5rem 64px; 255 | margin-top: 0; 256 | box-sizing: border-box; 257 | } 258 | .remark-slide-content.header_background { 259 | padding-top: 7rem; 260 | } 261 | 262 | @page { margin: 0; } 263 | @media print { 264 | .remark-slide-scaler { 265 | width: 100% !important; 266 | height: 100% !important; 267 | transform: scale(1) !important; 268 | top: 0 !important; 269 | left: 0 !important; 270 | } 271 | } 272 | 273 | -------------------------------------------------------------------------------- /tests/testthat/css/xaringan.css: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------- 2 | * 3 | * !! This file was generated by xaringanthemer !! 4 | * 5 | * Changes made to this file directly will be overwritten 6 | * if you used xaringanthemer in your xaringan slides Rmd 7 | * 8 | * Issues or likes? 9 | * - https://github.com/gadenbuie/xaringanthemer 10 | * - https://www.garrickadenbuie.com 11 | * 12 | * Need help? Try: 13 | * - vignette(package = "xaringanthemer") 14 | * - ?xaringanthemer::style_xaringan 15 | * - xaringan wiki: https://github.com/yihui/xaringan/wiki 16 | * - remarkjs wiki: https://github.com/gnab/remark/wiki 17 | * 18 | * Version: a.b.c.d.eeee 19 | * 20 | * ------------------------------------------------------- */ 21 | @import url(https://fonts.googleapis.com/css?family=Noto+Serif&display=swap); 22 | @import url(https://fonts.googleapis.com/css?family=Cabin:600,600i&display=swap); 23 | @import url(https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700&display=swap); 24 | 25 | 26 | :root { 27 | /* Fonts */ 28 | --text-font-family: 'Noto Serif'; 29 | --text-font-is-google: 1; 30 | --text-font-family-fallback: -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, Ubuntu, roboto, noto, segoe ui, arial; 31 | --text-font-base: sans-serif; 32 | --header-font-family: Cabin; 33 | --header-font-is-google: 1; 34 | --header-font-family-fallback: Georgia, serif; 35 | --code-font-family: 'Source Code Pro'; 36 | --code-font-is-google: 1; 37 | --base-font-size: 20px; 38 | --text-font-size: 1rem; 39 | --code-font-size: 0.9rem; 40 | --code-inline-font-size: 1em; 41 | --header-h1-font-size: 2.75rem; 42 | --header-h2-font-size: 2.25rem; 43 | --header-h3-font-size: 1.75rem; 44 | 45 | /* Colors */ 46 | --text-color: #000; 47 | --header-color: #000; 48 | --background-color: #FFF; 49 | --link-color: rgb(249, 38, 114); 50 | --code-highlight-color: rgba(255,255,0,0.5); 51 | --inverse-text-color: #d6d6d6; 52 | --inverse-background-color: #272822; 53 | --inverse-header-color: #f3f3f3; 54 | --inverse-link-color: rgb(249, 38, 114); 55 | --title-slide-background-color: #272822; 56 | --title-slide-text-color: #d6d6d6; 57 | --header-background-color: #000; 58 | --header-background-text-color: #FFF; 59 | --light-blue: #bad4ed; 60 | } 61 | 62 | html { 63 | font-size: var(--base-font-size); 64 | } 65 | 66 | body { 67 | font-family: var(--text-font-family), var(--text-font-family-fallback), var(--text-font-base); 68 | font-weight: normal; 69 | color: var(--text-color); 70 | } 71 | h1, h2, h3 { 72 | font-family: var(--header-font-family), var(--header-font-family-fallback); 73 | font-weight: 600; 74 | color: var(--header-color); 75 | } 76 | .remark-slide-content { 77 | background-color: var(--background-color); 78 | font-size: 1rem; 79 | padding: 16px 64px 16px 64px; 80 | width: 100%; 81 | height: 100%; 82 | } 83 | .remark-slide-content h1 { 84 | font-size: var(--header-h1-font-size); 85 | } 86 | .remark-slide-content h2 { 87 | font-size: var(--header-h2-font-size); 88 | } 89 | .remark-slide-content h3 { 90 | font-size: var(--header-h3-font-size); 91 | } 92 | .remark-code, .remark-inline-code { 93 | font-family: var(--code-font-family), Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace; 94 | } 95 | .remark-code { 96 | font-size: var(--code-font-size); 97 | } 98 | .remark-inline-code { 99 | font-size: var(--code-inline-font-size); 100 | color: #000; 101 | } 102 | .remark-slide-number { 103 | color: #272822; 104 | opacity: 1; 105 | font-size: 0.9rem; 106 | } 107 | strong { 108 | font-weight: bold; 109 | } 110 | a, a > code { 111 | color: var(--link-color); 112 | text-decoration: none; 113 | } 114 | .footnote { 115 | position: absolute; 116 | bottom: 60px; 117 | padding-right: 4em; 118 | font-size: 0.9em; 119 | } 120 | .remark-code-line-highlighted { 121 | background-color: var(--code-highlight-color); 122 | } 123 | .inverse { 124 | background-color: var(--inverse-background-color); 125 | color: var(--inverse-text-color); 126 | 127 | } 128 | .inverse h1, .inverse h2, .inverse h3 { 129 | color: var(--inverse-header-color); 130 | } 131 | .inverse a, .inverse a > code { 132 | color: var(--inverse-link-color); 133 | } 134 | .title-slide, .title-slide h1, .title-slide h2, .title-slide h3 { 135 | color: var(--title-slide-text-color); 136 | } 137 | .title-slide { 138 | background-color: var(--title-slide-background-color); 139 | } 140 | .title-slide .remark-slide-number { 141 | display: none; 142 | } 143 | /* Two-column layout */ 144 | .left-column { 145 | width: 20%; 146 | height: 92%; 147 | float: left; 148 | } 149 | .left-column h2, .left-column h3 { 150 | color: #777; 151 | } 152 | .left-column h2:last-of-type, .left-column h3:last-child { 153 | color: #000; 154 | } 155 | .right-column { 156 | width: 75%; 157 | float: right; 158 | padding-top: 1em; 159 | } 160 | .pull-left { 161 | float: left; 162 | width: 47%; 163 | } 164 | .pull-right { 165 | float: right; 166 | width: 47%; 167 | } 168 | .pull-right + * { 169 | clear: both; 170 | } 171 | img, video, iframe { 172 | max-width: 100%; 173 | } 174 | blockquote { 175 | border-left: solid 5px lightgray; 176 | padding-left: 1em; 177 | } 178 | .remark-slide table { 179 | margin: auto; 180 | border-top: 1px solid #666; 181 | border-bottom: 1px solid #666; 182 | } 183 | .remark-slide table thead th { 184 | border-bottom: 1px solid #ddd; 185 | } 186 | th, td { 187 | padding: 5px; 188 | } 189 | .remark-slide table:not(.table-unshaded) thead, 190 | .remark-slide table:not(.table-unshaded) tfoot, 191 | .remark-slide table:not(.table-unshaded) tr:nth-child(even) { 192 | background: #eee; 193 | } 194 | table.dataTable tbody { 195 | background-color: var(--background-color); 196 | color: var(--text-color); 197 | } 198 | table.dataTable.display tbody tr.odd { 199 | background-color: var(--background-color); 200 | } 201 | table.dataTable.display tbody tr.even { 202 | background-color: #eee; 203 | } 204 | table.dataTable.hover tbody tr:hover, table.dataTable.display tbody tr:hover { 205 | background-color: rgba(255, 255, 255, 0.5); 206 | } 207 | .dataTables_wrapper .dataTables_length, .dataTables_wrapper .dataTables_filter, .dataTables_wrapper .dataTables_info, .dataTables_wrapper .dataTables_processing, .dataTables_wrapper .dataTables_paginate { 208 | color: var(--text-color); 209 | } 210 | .dataTables_wrapper .dataTables_paginate .paginate_button { 211 | color: var(--text-color) !important; 212 | } 213 | 214 | /* Horizontal alignment of code blocks */ 215 | .remark-slide-content.left pre, 216 | .remark-slide-content.center pre, 217 | .remark-slide-content.right pre { 218 | text-align: start; 219 | width: max-content; 220 | max-width: 100%; 221 | } 222 | .remark-slide-content.left pre, 223 | .remark-slide-content.right pre { 224 | min-width: 50%; 225 | min-width: min(40ch, 100%); 226 | } 227 | .remark-slide-content.center pre { 228 | min-width: 66%; 229 | min-width: min(50ch, 100%); 230 | } 231 | .remark-slide-content.left pre { 232 | margin-left: unset; 233 | margin-right: auto; 234 | } 235 | .remark-slide-content.center pre { 236 | margin-left: auto; 237 | margin-right: auto; 238 | } 239 | .remark-slide-content.right pre { 240 | margin-left: auto; 241 | margin-right: unset; 242 | } 243 | 244 | /* Slide Header Background for h1 elements */ 245 | .remark-slide-content.header_background > h1 { 246 | display: block; 247 | position: absolute; 248 | top: 0; 249 | left: 0; 250 | width: 100%; 251 | background: var(--header-background-color); 252 | color: var(--header-background-text-color); 253 | padding: 2rem 64px 1.5rem 64px; 254 | margin-top: 0; 255 | box-sizing: border-box; 256 | } 257 | .remark-slide-content.header_background { 258 | padding-top: 7rem; 259 | } 260 | 261 | @page { margin: 0; } 262 | @media print { 263 | .remark-slide-scaler { 264 | width: 100% !important; 265 | height: 100% !important; 266 | transform: scale(1) !important; 267 | top: 0 !important; 268 | left: 0 !important; 269 | } 270 | } 271 | 272 | .light-blue { 273 | color: var(--light-blue); 274 | } 275 | .bg-light-blue { 276 | background-color: var(--light-blue); 277 | } 278 | -------------------------------------------------------------------------------- /tests/testthat/helper-session.R: -------------------------------------------------------------------------------- 1 | with_clean_session <- function(.f, args = list()) { 2 | empty_wd <- tempfile() 3 | dir.create(empty_wd) 4 | owd <- setwd(empty_wd) 5 | on.exit({setwd(owd); unlink(empty_wd, TRUE)}) 6 | args$.f <- .f 7 | res <- callr::r_safe(function(.f, ...) { 8 | tryCatch( 9 | list(result = .f(...), error = NULL), 10 | error = function(e) list(result = NULL, error = e$message) 11 | ) 12 | }, args) 13 | if (!is.null(res$error)) { 14 | stop(res$error) 15 | } else { 16 | res$result 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/testthat/test-color.R: -------------------------------------------------------------------------------- 1 | # test_that() 2 | 3 | describe("prepare_colors()", { 4 | it("returns NULL if NULL or missing", { 5 | expect_null(prepare_colors()) 6 | expect_null(prepare_colors(NULL)) 7 | expect_null(prepare_colors(list())) 8 | }) 9 | 10 | it("requires a named vector or list", { 11 | expect_error(prepare_colors("#00FF00")) 12 | }) 13 | 14 | it("requires valid CSS names", { 15 | expect_error(prepare_colors(c("light blue" = "#88f"))) 16 | expect_warning(prepare_colors(c("light/blue" = "#88f")), "light/blue") 17 | expect_warning(prepare_colors(c("-lightblue" = "#88f")), "-lightblue") 18 | expect_warning(prepare_colors(c("_lightblue" = "#88f")), "_lightblue") 19 | 20 | colors <- c("light_blue" = "#88f", "light-blue" = "#88f") 21 | expect_silent( 22 | expect_equal( 23 | prepare_colors(colors), 24 | list( 25 | list(color_name = "light_blue", value = "#88f"), 26 | list(color_name = "light-blue", value = "#88f") 27 | ) 28 | ) 29 | ) 30 | }) 31 | 32 | 33 | it("returns list with color_name and value for each color", { 34 | colors <- c('test' = "#4ed4ed") 35 | prepared <- prepare_colors(colors) 36 | expect_equal(names(prepared[[1]]), c("color_name", "value")) 37 | expect_equal(prepared[[1]]$color_name, names(colors)[[1]]) 38 | expect_equal(prepared[[1]]$value, colors[[1]]) 39 | }) 40 | }) 41 | 42 | 43 | describe("full_length_hex()", { 44 | it("makes 3-length hex to 6-length", { 45 | expect_equal(full_length_hex("#123"), "#112233") 46 | }) 47 | 48 | it("keeps length 6 hex", { 49 | expect_equal(full_length_hex("#123456"), "#123456") 50 | }) 51 | 52 | it("errors if not a hex color", { 53 | expect_error(full_length_hex("123abc")) 54 | expect_error(full_length_hex("#1234567")) 55 | expect_error(full_length_hex("#00000Z")) 56 | }) 57 | }) 58 | 59 | describe("check_color_is_hex", { 60 | it("returns TRUE when color is valid hex", { 61 | expect_true(check_color_is_hex("#123456")) 62 | expect_true(check_color_is_hex("#abc123")) 63 | expect_true(check_color_is_hex("#abc")) 64 | expect_true(check_color_is_hex("#123")) 65 | }) 66 | 67 | it("returns FALSE and warns if requested", { 68 | expect_false(check_color_is_hex("123456", throw = NULL)) 69 | expect_false(check_color_is_hex("123", throw = NULL)) 70 | expect_false(check_color_is_hex("apple", throw = NULL)) 71 | expect_warning(check_color_is_hex("123456")) 72 | expect_warning(check_color_is_hex("123", msg = "{color} is bad"), "123 is bad") 73 | expect_warning(check_color_is_hex("apple")) 74 | }) 75 | 76 | it("errors if throw = stop", { 77 | expect_error(check_color_is_hex("123", throw = stop), "123 is not") 78 | }) 79 | }) 80 | 81 | 82 | describe("lighten_color() and darken_color()", { 83 | it("errors if strength not in [0, 1]", { 84 | expect_error(lighten_color("#123", 9)) 85 | expect_error(darken_color("#123", 9)) 86 | }) 87 | 88 | it("returns original color if strength = 0", { 89 | expect_equal(lighten_color("#808080", 0), "#808080") 90 | expect_equal(darken_color("#808080", 0), "#808080") 91 | }) 92 | 93 | it("returns entire blend color if strength = 0", { 94 | expect_equal(lighten_color("#808080", 1), "#FFFFFF") 95 | expect_equal(darken_color("#808080", 1), "#000000") 96 | }) 97 | 98 | it("returns midpoint if strength = 0.5", { 99 | expect_equal(lighten_color("#000000", 0.5), "#7F7F7F") 100 | expect_equal(darken_color("#FFFFFF", 0.5), "#7F7F7F") 101 | }) 102 | }) 103 | -------------------------------------------------------------------------------- /tests/testthat/test-css.R: -------------------------------------------------------------------------------- 1 | test_that("read theme settings from css variables", { 2 | expected_vars <- list( 3 | background_color = "#E9EBEE", 4 | text_color = "#18273F", 5 | header_color = "#23395b", 6 | text_bold_color = "#23395b", 7 | inverse_background_color = "#23395b", 8 | inverse_text_color = "#E9EBEE", 9 | inverse_header_color = "#E9EBEE", 10 | base_font_size = "20px", 11 | text_font_size = "1rem", 12 | header_h3_font_size = "1.75rem", 13 | text_font_family = "'Noto Serif'", 14 | text_font_is_google = TRUE, 15 | header_font_family = "Cabin", 16 | header_font_is_google = TRUE, 17 | header_background_color = "#23395b", 18 | header_background_text_color = "#E9EBEE", 19 | code_font_family = "'Source Code Pro'", 20 | code_font_is_google = TRUE 21 | ) 22 | 23 | css_vars <- read_css_vars(testthat::test_path("css/mono_light.css")) 24 | for (var in names(expected_vars)) { 25 | expect_equal(!!css_vars[[var]], !!expected_vars[[var]]) 26 | } 27 | }) 28 | 29 | describe("find and choose xaringan themer files", { 30 | tmpdir <- tempfile() 31 | dir.create(tmpdir) 32 | 33 | mono_light_css <- normalizePath(test_path("css/mono_light.css")) 34 | 35 | xaringan_css <- normalizePath(test_path("css/xaringan.css")) 36 | 37 | owd <- setwd(tmpdir) 38 | on.exit(setwd(owd)) 39 | 40 | file.copy(mono_light_css, tmpdir) 41 | 42 | it("finds xaringan themer files with non-standard names", { 43 | candidates <- find_xaringan_themer_css() 44 | picked <- choose_xaringan_themer_css(candidates) 45 | expect_equal(candidates, "./mono_light.css") 46 | expect_equal(picked, "./mono_light.css") 47 | }) 48 | 49 | it("finds xaringan themer files in presence of other .css files", { 50 | writeLines(c( 51 | "html {", 52 | " color: red;", 53 | "}" 54 | ), "styles.css") 55 | expect_equal(find_xaringan_themer_css(), "./mono_light.css") 56 | expect_equal(read_css_vars()$text_color, "#18273F") 57 | }) 58 | 59 | it("finds all xaringan themer files", { 60 | file.copy(xaringan_css, "xaringan-themer.css") 61 | candidates <- find_xaringan_themer_css() 62 | picked <- choose_xaringan_themer_css(candidates) 63 | expect_equal(candidates, c("./mono_light.css", "./xaringan-themer.css")) 64 | expect_equal(picked, "./xaringan-themer.css") 65 | expect_equal(read_css_vars()$text_color, "#000") 66 | }) 67 | 68 | it("chooses the first from the list if ambiguous", { 69 | file.rename("xaringan-themer.css", "xaringan.css") 70 | candidates <- find_xaringan_themer_css() 71 | expect_message(picked <- choose_xaringan_themer_css(candidates)) 72 | expect_equal(candidates, c("./mono_light.css", "./xaringan.css")) 73 | expect_equal(picked, "./mono_light.css") 74 | expect_message(expect_equal(read_css_vars()$text_color, "#18273F")) 75 | }) 76 | 77 | it("throws error if no xaringan themer css files", { 78 | file.remove("xaringan.css") 79 | file.remove("mono_light.css") 80 | candidates <- find_xaringan_themer_css() 81 | expect_equal(candidates, character()) 82 | expect_error(choose_xaringan_themer_css(candidates)) 83 | }) 84 | }) 85 | 86 | test_that("css_get_root() returns null if no :root exists", { 87 | tmpfile <- tempfile("style", fileext = ".css") 88 | writeLines(c( 89 | "html {", 90 | " color: red;", 91 | "}" 92 | ), tmpfile) 93 | expect_null(css_get_root(tmpfile)) 94 | unlink(tmpfile) 95 | }) 96 | 97 | describe("css_get_padding()", { 98 | it("processes 1 element padding", { 99 | p <- css_get_padding("1em") 100 | expect_equal(p$top, "1em") 101 | expect_equal(p$right, "1em") 102 | expect_equal(p$bottom, "1em") 103 | expect_equal(p$left, "1em") 104 | }) 105 | it("processes 2 element padding", { 106 | p <- css_get_padding("1em 2em") 107 | expect_equal(p$top, "1em") 108 | expect_equal(p$right, "2em") 109 | expect_equal(p$bottom, "1em") 110 | expect_equal(p$left, "2em") 111 | }) 112 | it("processes 4 element padding", { 113 | p <- css_get_padding("1em 2em 3em 4em") 114 | expect_equal(p$top, "1em") 115 | expect_equal(p$right, "2em") 116 | expect_equal(p$bottom, "3em") 117 | expect_equal(p$left, "4em") 118 | }) 119 | it("throws an error if padding is a vector", { 120 | expect_error(css_get_padding(c("1em", "2em"))) 121 | }) 122 | it("throws an error if result is not 1, 2, 4 element", { 123 | expect_error(css_get_padding("1em 2em 3em")) 124 | expect_error(css_get_padding("1em 2em 3em 4em 5em")) 125 | }) 126 | }) 127 | -------------------------------------------------------------------------------- /tests/testthat/test-helpers.R: -------------------------------------------------------------------------------- 1 | test_that("element_description", { 2 | text_in <- c("multiple", NA, "", ".remark-slide-content", "h1", "pre, code") 3 | text_out <- c( 4 | "Used in multiple CSS rules.", 5 | "", 6 | "", 7 | "Modifies the `.remark-slide-content` class.", 8 | "Modifies the `h1` element.", 9 | "Modifies the `pre, code` elements." 10 | ) 11 | expect_equal(element_description(text_in), text_out) 12 | }) 13 | -------------------------------------------------------------------------------- /tests/testthat/test-style_extra_css.R: -------------------------------------------------------------------------------- 1 | # test_that() 2 | 3 | 4 | # style_extra_css() ------------------------------------------------------- 5 | 6 | describe("style_extra_css", { 7 | css <- list(body = list(color = "#123")) 8 | 9 | it("returns text if outfile is NULL", { 10 | expect_equal( 11 | style_extra_css(css, NULL), 12 | "\n\n/* Extra CSS */\nbody {\n color: #123;\n}" 13 | ) 14 | expect_equal( 15 | style_extra_css(css, NULL, heading = NULL), 16 | "\nbody {\n color: #123;\n}" 17 | ) 18 | expect_equal( 19 | style_extra_css(css, NULL, append = FALSE, heading = NULL), 20 | "body {\n color: #123;\n}" 21 | ) 22 | expect_equal( 23 | style_extra_css(css, NULL, append = FALSE, heading = "TEST TEST"), 24 | "/* TEST TEST */\nbody {\n color: #123;\n}" 25 | ) 26 | }) 27 | 28 | tmpfile <- tempfile(fileext = ".css") 29 | first <- style_extra_css( 30 | css = list(.first = list(color = "#123")), 31 | outfile = tmpfile, 32 | append = FALSE, 33 | heading = "First CSS" 34 | ) 35 | first_exp <- "/* First CSS */\n.first {\n color: #123;\n}" 36 | 37 | it("writes text to the outfile", { 38 | expect_equal(first, first_exp) 39 | expect_equal( 40 | readLines(tmpfile, warn = FALSE), 41 | strsplit(first_exp, "\n")[[1]] 42 | ) 43 | }) 44 | 45 | second <- style_extra_css( 46 | css = list(.second = list(color = "#321")), 47 | outfile = tmpfile, 48 | append = TRUE, 49 | heading = "Second CSS" 50 | ) 51 | second_exp <- "\n\n/* Second CSS */\n.second {\n color: #321;\n}" 52 | 53 | it("appends to existing outfile", { 54 | expect_equal(second, second_exp) 55 | expect_equal( 56 | readLines(tmpfile, warn = FALSE), 57 | strsplit(paste0(first_exp, "\n", second_exp), "\n")[[1]] 58 | ) 59 | }) 60 | 61 | third <- style_extra_css( 62 | css = list(.third = list(color = "#333")), 63 | outfile = tmpfile, 64 | append = FALSE, 65 | heading = "Third CSS" 66 | ) 67 | third_exp <- "/* Third CSS */\n.third {\n color: #333;\n}" 68 | 69 | it("over writes text in the outfile if append=FALSE", { 70 | expect_equal(third, third_exp) 71 | expect_equal( 72 | readLines(tmpfile, warn = FALSE), 73 | strsplit(third_exp, "\n")[[1]] 74 | ) 75 | }) 76 | 77 | it("only adds prepends `heading` once", { 78 | css <- list(b = list(color = "red"), i = list(color = "blue")) 79 | out <- style_extra_css(css, outfile = NULL, heading = "Extra CSS") 80 | expect_equal(length(out), 1L) 81 | expect_equal(sum(grepl("Extra CSS", out)), 1L) 82 | }) 83 | }) 84 | 85 | 86 | # list2css() -------------------------------------------------------------- 87 | 88 | describe("list2css()", { 89 | it("converts lists to css", { 90 | css <- list( 91 | ".remark-slide" = list( 92 | "color" = "#FFF", 93 | "font-size" = "30px" 94 | ) 95 | ) 96 | expected <- ".remark-slide { 97 | color: #FFF; 98 | font-size: 30px; 99 | }" 100 | expect_equal(list2css(css), expected) 101 | 102 | css[[".new-class"]] <- list("background-color" = "#000") 103 | expected <- c(expected, ".new-class {\n background-color: #000;\n}") 104 | expect_equal(list2css(css), expected) 105 | }) 106 | 107 | it("errors if css list is not named", { 108 | css <- list(list( 109 | "color" = "#FFF", 110 | "font-size" = "30px" 111 | )) 112 | expect_error(list2css(css)) 113 | }) 114 | 115 | it("errors if css list has unnamed elements", { 116 | css <- list( 117 | list( 118 | "color" = "#FFF", 119 | "font-size" = "30px" 120 | ), 121 | ".test" = list(color = "red") 122 | ) 123 | expect_error(list2css(css)) 124 | }) 125 | 126 | it("errors if css list has unnamed properties", { 127 | css <- list( 128 | ".class" = list( 129 | color = "#FFF", 130 | "font-size" = "30px" 131 | ), 132 | ".test" = list("red") 133 | ) 134 | expect_error(list2css(css)) 135 | 136 | css <- list( 137 | ".class" = list( 138 | "#FFF", 139 | "font-size" = "30px" 140 | ), 141 | ".test" = list("red") 142 | ) 143 | expect_error(list2css(css)) 144 | }) 145 | 146 | it("errors if not list within list", { 147 | css <- list( 148 | ".class" = list( 149 | list(color = "red"), 150 | "font-size" = "30px" 151 | ), 152 | ".test" = list("red") 153 | ) 154 | expect_error(list2css(css)) 155 | }) 156 | 157 | it("errors if css contains unnamed elements", { 158 | expect_error(list2css(list(list(color = "#bad")))) 159 | expect_error( 160 | list2css(list(.a = list(color = "#bad"), list(`background-color` = "#bad"))), 161 | "elements.+must be named.+2 is" 162 | ) 163 | expect_error( 164 | list2css(list(.a = list(color = "#bad"), list(`background-color` = "#bad"), list(`border-color` = "#bad"))), 165 | "elements.+must be named.+2, 3 are" 166 | ) 167 | expect_error( 168 | list2css(list(body = list("#bad"))), 169 | "elements.+must be named.+body.+has" 170 | ) 171 | expect_error( 172 | list2css(list(body = list("#bad"), thing = list("#bad"))), 173 | "elements.+must be named.+body.+thing.+have" 174 | ) 175 | }) 176 | 177 | it("is okay for multiple entries with the same name", { 178 | expect_equal( 179 | list2css(list("a" = list(color = "red"), a = list(color = "blue"))), 180 | c("a {\n color: red;\n}", "a {\n color: blue;\n}") 181 | ) 182 | 183 | expect_equal( 184 | list2css(list("a" = list(color = "red", color = "blue"))), 185 | c("a {\n color: red;\n color: blue;\n}") 186 | ) 187 | }) 188 | }) 189 | 190 | 191 | # list2fonts() ------------------------------------------------------------ 192 | 193 | import <- function(x) paste0("@import url(", x, ");") 194 | 195 | describe("list2fonts()", { 196 | lato_url <- "https://fonts.googleapis.com/css?family=Lato&display=swap" 197 | worksans_url <- "https://fonts.googleapis.com/css?family=Work+Sans&display=swap" 198 | 199 | it("handles a list or c() of font urls", { 200 | expect_equal( 201 | list2fonts(list(lato_url, worksans_url)), 202 | import(c(lato_url, worksans_url)) 203 | ) 204 | expect_equal(list2fonts(c(lato_url, lato_url)), rep(import(lato_url), 2)) 205 | }) 206 | 207 | it("handles single character font name", { 208 | expect_equal(list2fonts(lato_url), import(lato_url)) 209 | }) 210 | 211 | it("handles list of google fonts", { 212 | expect_equal( 213 | list2fonts(list(google_font("Lato"), google_font("Work Sans"))), 214 | import(c(lato_url, worksans_url)) 215 | ) 216 | }) 217 | 218 | it("handles mix of google_font() and bare string", { 219 | expect_equal( 220 | list2fonts(list(google_font("Lato"), worksans_url)), 221 | import(c(lato_url, worksans_url)) 222 | ) 223 | }) 224 | 225 | it("handles bare google_font()", { 226 | expect_equal( 227 | list2fonts(google_font("Lato")), 228 | import(lato_url) 229 | ) 230 | }) 231 | 232 | it("throws an error when c() used to combine string and google_font()", { 233 | expect_error( 234 | list2fonts(c(lato_url, google_font("Lato"), google_font("Work Sans"))), 235 | "Multiple fonts" 236 | ) 237 | expect_error( 238 | list2fonts(c(google_font("Lato"), google_font("Work Sans"))), 239 | "Multiple fonts" 240 | ) 241 | }) 242 | }) 243 | -------------------------------------------------------------------------------- /tests/testthat/test-style_xaringan.R: -------------------------------------------------------------------------------- 1 | test_that("style_xaringan() writes to specified outfile", { 2 | tmpfile <- tempfile(fileext = ".css") 3 | expect_equal(style_xaringan(outfile = tmpfile), tmpfile) 4 | expect_true(file.exists(tmpfile)) 5 | expect_true(grepl("xaringanthemer", readLines(tmpfile)[3])) 6 | }) 7 | 8 | test_that("style_xaringan() warns if base_font_size is not absolute", { 9 | tmpfile <- tempfile(fileext = ".css") 10 | expect_warning( 11 | style_xaringan(outfile = tmpfile, base_font_size = "1em"), 12 | "absolute units" 13 | ) 14 | }) 15 | -------------------------------------------------------------------------------- /tests/testthat/test-themes.R: -------------------------------------------------------------------------------- 1 | test_theme_file <- function(theme = "duo", theme_file = paste0(theme, ".css"), ...) { 2 | local_edition(2) 3 | on.exit(local_edition(3)) 4 | 5 | theme_fun <- switch( 6 | theme, 7 | "duo" = style_duo, 8 | "duo_accent" = style_duo_accent, 9 | "duo_accent_inverse" = style_duo_accent_inverse, 10 | "mono_accent" = style_mono_accent, 11 | "mono_accent_inverse" = style_mono_accent_inverse, 12 | "mono_dark" = style_mono_dark, 13 | "mono_light" = style_mono_light, 14 | "solarized_dark" = style_solarized_dark, 15 | "solarized_light" = style_solarized_light, 16 | style_xaringan 17 | ) 18 | 19 | tmpfile <- tempfile() 20 | on.exit(unlink(tmpfile), add = TRUE) 21 | 22 | theme_fun(outfile = tmpfile, ..., text_font_google = google_font("Noto Serif")) 23 | theme_css <- readLines(tmpfile) 24 | # Mask package version in test files 25 | theme_css <- sub("( \\* Version: )[\\d.-]+", "\\1a.b.c.d.eeee", theme_css, perl = TRUE) 26 | theme_css <- paste(theme_css, collapse = "\n") 27 | expect_known_output(cat(theme_css), test_path("css", theme_file)) 28 | } 29 | 30 | test_that("style_duo()", { test_theme_file("duo") }) 31 | test_that("style_duo_accent()", { test_theme_file("duo_accent") }) 32 | test_that("style_duo_accent_inverse()", { test_theme_file("duo_accent_inverse") }) 33 | test_that("style_mono_accent()", { test_theme_file("mono_accent") }) 34 | test_that("style_mono_accent_inverse()", { test_theme_file("mono_accent_inverse") }) 35 | test_that("style_mono_dark()", { test_theme_file("mono_dark") }) 36 | test_that("style_mono_light()", { test_theme_file("mono_light") }) 37 | test_that("style_solarized_dark()", { test_theme_file("solarized_dark") }) 38 | test_that("style_solarized_light()", { test_theme_file("solarized_light") }) 39 | test_that("google fonts in theme", { 40 | test_theme_file( 41 | "google_fonts", 42 | header_font_google = google_font("IBM Plex Serif", "700"), 43 | code_font_google = google_font("IBM Plex Mono") 44 | ) 45 | }) 46 | 47 | test_that("header_background_auto = TRUE", { 48 | test_theme_file("duo", "duo-header_bg.css", header_background_auto = TRUE) 49 | test_theme_file("mono_light", "mono_light-header_bg.css", header_background_auto = TRUE) 50 | test_theme_file("solarized_dark", "solarized_dark-header_bg.css", header_background_auto = TRUE) 51 | }) 52 | 53 | test_that("style colors are added to themes", { 54 | test_theme_file("xaringan", colors = c('light-blue' = "#bad4ed")) 55 | }) 56 | 57 | test_that("setting google font overrides individual font", { 58 | theme_vars <- with_clean_session(function() { 59 | xf <- xaringanthemer::style_xaringan( 60 | text_font_family = "Damogran", 61 | header_font_family = "Magrathea", 62 | code_font_google = xaringanthemer::google_font("IBM Plex Mono") 63 | ) 64 | xaringanthemer:::read_css_vars(xf) 65 | }) 66 | 67 | expect_equal(theme_vars$text_font_family, "Damogran") 68 | expect_false(theme_vars$text_font_is_google) 69 | expect_equal(theme_vars$header_font_family, "Magrathea") 70 | expect_false(theme_vars$header_font_is_google) 71 | expect_equal(theme_vars$code_font_family, "'IBM Plex Mono'") 72 | expect_true(theme_vars$code_font_is_google) 73 | }) 74 | 75 | test_that("default fonts are correctly identified as google font", { 76 | theme_vars <- with_clean_session(function() { 77 | xf <- xaringanthemer::style_xaringan() 78 | xaringanthemer:::read_css_vars(xf) 79 | }) 80 | 81 | expect_equal(theme_vars$text_font_family, 82 | quote_elements_w_spaces(xaringanthemer_font_default("text_font_family"))) 83 | expect_true(theme_vars$text_font_is_google) 84 | expect_equal(theme_vars$header_font_family, 85 | quote_elements_w_spaces(xaringanthemer_font_default("header_font_family"))) 86 | expect_true(theme_vars$header_font_is_google) 87 | }) 88 | 89 | 90 | test_that("NULL output returns CSS as text", { 91 | expect_false( 92 | with_clean_session(function() { 93 | xaringanthemer::style_xaringan(outfile = NULL) 94 | file.exists("xaringan-themer.css") 95 | }) 96 | ) 97 | 98 | xt <- with_clean_session(function() { 99 | xaringanthemer::style_xaringan(outfile = NULL) 100 | }) 101 | 102 | expect_type(xt, "character") 103 | expect_true(any(grepl("generated by xaringanthemer", xt))) 104 | }) 105 | 106 | 107 | test_that("style_xaringan() warns about non-hex colors used by theme_xaringan()", { 108 | expect_error( 109 | with_clean_session(function() { 110 | options(warn = 2) 111 | xaringanthemer::style_xaringan(text_color = "rgb(100, 100, 100)", background_color = "white", outfile = NULL) 112 | }), 113 | regexp = "Colors.+used by.+theme_xaringan" 114 | ) 115 | }) 116 | -------------------------------------------------------------------------------- /tests/testthat/test-utils.R: -------------------------------------------------------------------------------- 1 | test_that("printing google_font works", { 2 | expect_snapshot( 3 | google_font("Josefin Sans", "400", "400i", "600i", "700") 4 | ) 5 | }) 6 | 7 | test_that("requires_package()", { 8 | expect_true(requires_package("purrr")) 9 | expect_error(requires_package("notapackage", "myFunction"), "myFunction") 10 | expect_warning(expect_false(requires_package("notapackage", required = FALSE))) 11 | }) 12 | -------------------------------------------------------------------------------- /tests/testthat/test-xaringanthemer-deprecated.R: -------------------------------------------------------------------------------- 1 | test_that("deprecation warnings", { 2 | expect_warning(write_xaringan_theme(outfile = NULL)) 3 | expect_warning(write_extra_css(list(.test = list(prop = 'value')), outfile = NULL)) 4 | expect_warning(mono_light(outfile = NULL)) 5 | expect_warning(mono_dark(outfile = NULL)) 6 | expect_warning(mono_accent(outfile = NULL)) 7 | expect_warning(mono_accent_inverse(outfile = NULL)) 8 | expect_warning(duo(outfile = NULL)) 9 | expect_warning(duo_accent(outfile = NULL)) 10 | expect_warning(duo_accent_inverse(outfile = NULL)) 11 | expect_warning(solarized_light(outfile = NULL)) 12 | expect_warning(solarized_dark(outfile = NULL)) 13 | }) 14 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /vignettes/fonts.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: Fonts 3 | --- 4 | 5 | [adding-custom-css]: xaringanthemer.html#adding-custom-css 6 | 7 | ```{r, results='asis', echo=FALSE} 8 | tvv <- xaringanthemer:::template_variables$variable 9 | ``` 10 | 11 | ```{r child="../man/fragments/_fonts.Rmd"} 12 | ``` 13 | -------------------------------------------------------------------------------- /vignettes/template-variables.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Template Variables" 3 | output: 4 | rmarkdown::html_vignette: default 5 | vignette: > 6 | %\VignetteIndexEntry{Template Variables} 7 | %\VignetteEncoding{UTF-8} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | --- 10 | 11 | ```{r setup, include = FALSE} 12 | knitr::opts_chunk$set( 13 | collapse = TRUE, 14 | comment = "#>" 15 | ) 16 | ``` 17 | 18 | The following table shows the template variables, 19 | their default values in the standard `xaringanthemer` theme, 20 | the primary element to which the property is applied, 21 | and a brief description of the template variable. 22 | 23 | For example, `background_color` by default sets the `background-color` CSS property of the `.remark-slide-content` class to `#FFF`. 24 | 25 | Use this table to find the template variable you would like to modify. 26 | You can also use this table to find the CSS class or element associated with a particular template item. 27 | 28 | Note that some theme functions, 29 | like `style_mono_accent()`, 30 | have additional parameters 31 | and a specific set of default values unique to the theme. 32 | However, with any theme function 33 | you can override the theme's defaults 34 | by directly setting any of the arguments listed below 35 | when calling the theme function. 36 | 37 | To be concrete, 38 | `style_mono_accent()` has three additional arguments: 39 | `base_color` (the accent color), `white_color`, and `black_color`. 40 | In this theme, 41 | the background slide color defaults to `white_color`, 42 | but you can choose a different slide background color 43 | by setting `background_color`, 44 | for example `background_color = "#EAEAEA"`. 45 | 46 | ```{r table, results = "asis", echo=FALSE} 47 | tv <- xaringanthemer:::template_variables 48 | tv$variable <- glue::glue_data(tv, "`{variable}`") 49 | tv[!is.na(tv$css_variable), "css_variable"] <- glue::glue("`{tv$css_variable[!is.na(tv$css_variable)]}`") 50 | tv[is.na(tv$css_variable), "css_variable"] <- "" 51 | tv[is.na(tv$css_property), "css_property"] <- "" 52 | tv$default <- gsub("[{}]", "", tv$default) 53 | tv <- tv[, c( 54 | "variable", "description", "element", "css_property", "default", "css_variable" 55 | )] 56 | knitr::kable( 57 | tv, 58 | col.names = c("Variable", "Description", "Element", "CSS Property", "Default", "CSS Variable") 59 | ) 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /vignettes/themes.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: Themes 3 | --- 4 | 5 | ```{r include=FALSE} 6 | library(xaringanthemer) 7 | knitr::opts_chunk$set(results = "asis", echo=FALSE) 8 | ``` 9 | 10 | ```{r child="../man/fragments/_themes.Rmd"} 11 | ``` 12 | 13 | 14 | ## Colors 15 | 16 | ```{r child="../man/fragments/_colors.Rmd"} 17 | ``` 18 | -------------------------------------------------------------------------------- /vignettes/xaringanthemer.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Xaringan CSS Theme Generator" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Overview of xaringanthemer} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r setup, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | results = "asis", 14 | echo = FALSE, 15 | comment = "#>", 16 | out.width = "100%" 17 | ) 18 | library(xaringanthemer) 19 | ``` 20 | 21 | ```{css echo=FALSE} 22 | img { max-width: 100%; } 23 | ``` 24 | 25 | [xaringan]: https://github.com/yihui/xaringan 26 | [remarkjs]: https://github.com/gnab/remark 27 | 28 | Jump to: 29 | [Quick Intro](#quick-intro), 30 | [Themes](#themes), 31 | [Theme Settings](#theme-settings), 32 | [Fonts](#fonts), 33 | [Colors](#colors), 34 | [Adding Custom CSS](#adding-custom-css) 35 | 36 | ## Quick Intro 37 | 38 | [theme-functions]: #themes 39 | [theme-settings]: #theme-settings 40 | [template-variables]: template-variables.html 41 | 42 | ```{r child="../man/fragments/_quick-intro.Rmd"} 43 | ``` 44 | 45 | ## Themes 46 | 47 | ```{r child="../man/fragments/_themes.Rmd"} 48 | ``` 49 | 50 | ## Theme Settings 51 | 52 | The theme functions listed above are just wrappers around the central function of this package, `style_xaringan()`. 53 | If you want to start from the default **xaringan** theme and make a few modifications, start there. 54 | 55 | All of the theme template variables are repeated in each of the theme functions (instead of relying on `...`) so that you can use autocompletion to find and change the defaults for any theme function. 56 | To override the default value of any theme functions, set the appropriate argument in the theme function. 57 | A table of all template variables is included in [`vignette("template-variables", "xaringanthemer")`](template-variables.html). 58 | 59 | As an example, try loading `xaringanthemer`, type out `style_duo_theme(` and then press Tab to see all of the theme options. 60 | 61 | All of the theme options are named so that you first think of the element you want to change, then the property of that element. 62 | 63 | Here are some of the `text_` theme options: 64 | 65 | ```{r, results='asis', echo=FALSE} 66 | tvv <- xaringanthemer:::template_variables$variable 67 | cat(paste0("- `", tvv[grepl("^text_", tvv)][1:5], "`"), sep = "\n") 68 | cat("- *and more ...*") 69 | ``` 70 | 71 | And here are the title slide theme options: 72 | 73 | ```{r results='asis', echo=FALSE} 74 | cat(paste0("- `", tvv[grepl("^title_slide_", tvv)], "`"), sep = "\n") 75 | ``` 76 | 77 | ## Fonts 78 | 79 | [adding-custom-css]: #adding-custom-css 80 | 81 | ```{r child="../man/fragments/_fonts.Rmd"} 82 | ``` 83 | 84 | ## Colors 85 | 86 | ```{r child="../man/fragments/_colors.Rmd"} 87 | ``` 88 | 89 | ## Adding Custom CSS 90 | 91 | You can also add custom CSS classes using the `extra_css` argument in the theme functions. 92 | This argument takes a named list of CSS definitions each containing a named list of CSS property-value pairs. 93 | 94 | ```r 95 | extra_css <- list( 96 | ".small" = list("font-size" = "90%"), 97 | ".full-width" = list( 98 | display = "flex", 99 | width = "100%", 100 | flex = "1 1 auto" 101 | ) 102 | ) 103 | ``` 104 | 105 | If you would rather keep your additional css definitions in a separate file, you can call `style_extra_css()` separately. 106 | Just be sure to include your new CSS file in the list of applied files in your YAML header. 107 | 108 | ```r 109 | style_extra_css(css = extra_css, outfile = "custom.css") 110 | ``` 111 | 112 | ```{r results='asis', echo=FALSE} 113 | extra_css <- list( 114 | ".small" = list("font-size" = "90%"), 115 | ".full-width" = list( 116 | display = "flex", 117 | width = "100%", 118 | flex = "1 1 auto" 119 | ) 120 | ) 121 | cat( 122 | "\n```css", 123 | "/* Extra CSS */", 124 | xaringanthemer:::list2css(extra_css), 125 | "```", 126 | sep = "\n" 127 | ) 128 | ``` 129 | 130 | This is most helpful when wanting to define helper classes to work with the [remark.js][remarkjs] `.class[]` syntax. 131 | Using the above example, we could add slide text `.small[in smaller font size]`. 132 | 133 | ```{r child="../man/fragments/_thanks.Rmd"} 134 | ``` 135 | -------------------------------------------------------------------------------- /xaringanthemer.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: XeLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageRoxygenize: rd,collate,namespace 22 | --------------------------------------------------------------------------------