Merge pull request 'fix: resolve locked namespace binding in civilytics_load_fonts() and default theme to transparent background' (#19) from kodor/fix-18-fonts-and-theme into master
R-CMD-check / R CMD check (push) Successful in 4m25s
R-CMD-check / R CMD check (push) Successful in 4m25s
Reviewed-on: #19
This commit was merged in pull request #19.
This commit is contained in:
@@ -5,32 +5,45 @@ CV_FONT_SANS <- "Inter" # axis text, legends, UI elements
|
||||
CV_FONT_SERIF <- "Source Serif 4" # body prose / editorial long-form
|
||||
CV_FONT_MONO <- "JetBrains Mono" # code, data tables, numeric callouts
|
||||
|
||||
# Internal flag so civilytics_load_fonts() is idempotent within a session.
|
||||
.cv_fonts_loaded <- FALSE
|
||||
# Mutable package state held in an environment so the binding itself stays
|
||||
# locked (R locks all namespace bindings at load time) while the contents
|
||||
# remain writable. See https://adv-r.hadley.nz/environments.html#environments-as-containers
|
||||
.cv_state <- new.env(parent = emptyenv())
|
||||
.cv_state$fonts_loaded <- FALSE
|
||||
|
||||
#' Load Civilytics brand fonts
|
||||
#'
|
||||
#' Downloads Inter and Libre Franklin from Google Fonts via
|
||||
#' [sysfonts::font_add_google()], then calls [showtext::showtext_auto()] so
|
||||
#' that all graphics devices render text with those fonts. This is called
|
||||
#' automatically when the package loads; use this function to retry if the
|
||||
#' initial load failed (e.g., the machine was offline at load time).
|
||||
#' Downloads Inter, Libre Franklin, Source Serif 4 and JetBrains Mono from
|
||||
#' Google Fonts via [sysfonts::font_add_google()], then calls
|
||||
#' [showtext::showtext_auto()] so that all graphics devices render text with
|
||||
#' those fonts. This is called automatically when the package loads; use this
|
||||
#' function to retry if the initial load failed (e.g., the machine was offline
|
||||
#' at load time).
|
||||
#'
|
||||
#' @return Invisibly returns `NULL`.
|
||||
#' Subsequent calls within the same session are no-ops unless `force = TRUE`.
|
||||
#'
|
||||
#' @param force Logical. If `TRUE`, reload fonts even if they were already
|
||||
#' loaded in this session. Default `FALSE`.
|
||||
#'
|
||||
#' @return Invisibly returns `TRUE` if fonts were loaded, `FALSE` if skipped
|
||||
#' (already loaded and `force = FALSE`).
|
||||
#' @export
|
||||
#'
|
||||
#' @examples
|
||||
#' \dontrun{
|
||||
#' civilytics_load_fonts()
|
||||
#' }
|
||||
civilytics_load_fonts <- function() {
|
||||
civilytics_load_fonts <- function(force = FALSE) {
|
||||
if (.cv_state$fonts_loaded && !force) return(invisible(FALSE))
|
||||
|
||||
sysfonts::font_add_google("Inter", family = "Inter")
|
||||
sysfonts::font_add_google("Libre Franklin", family = "Libre Franklin")
|
||||
sysfonts::font_add_google("Source Serif 4", family = "Source Serif 4")
|
||||
sysfonts::font_add_google("JetBrains Mono", family = "JetBrains Mono")
|
||||
showtext::showtext_auto()
|
||||
.cv_fonts_loaded <<- TRUE
|
||||
invisible(NULL)
|
||||
|
||||
.cv_state$fonts_loaded <- TRUE
|
||||
invisible(TRUE)
|
||||
}
|
||||
|
||||
.onLoad <- function(libname, pkgname) {
|
||||
|
||||
@@ -36,10 +36,12 @@
|
||||
#' to [civilytics_colors]`["paper_2"]` (`#F2EDE4`).
|
||||
#' @param grid Character. Which major gridlines to draw: `"y"` (default,
|
||||
#' horizontal only), `"x"` (vertical only), `"both"`, or `"none"`.
|
||||
#' @param paper_bg Logical. If `TRUE` (default), fill the plot and panel
|
||||
#' backgrounds with the warm `paper` color. Set to `FALSE` for a
|
||||
#' transparent background (useful for slides or overlay on colored
|
||||
#' surfaces).
|
||||
#' @param paper_bg Logical. If `TRUE`, fill the plot and panel backgrounds
|
||||
#' with the warm `paper` color (Civilytics cream). Default is `FALSE`
|
||||
#' (transparent) so that figures composite cleanly onto any background.
|
||||
#' Set to `TRUE` for the branded cream canvas. Note: a transparent device
|
||||
#' background (e.g., `dev = "ragg_png"`, `dev.args = list(background =
|
||||
#' "transparent")`) is also needed for fully-transparent PNG exports.
|
||||
#'
|
||||
#' @section Font size hierarchy:
|
||||
#' All text sizes are derived from `font_size` using relative scale factors.
|
||||
@@ -68,7 +70,7 @@
|
||||
#' \dontrun{
|
||||
#' library(ggplot2)
|
||||
#'
|
||||
#' # Default editorial theme
|
||||
#' # Default — transparent background for embedding
|
||||
#' ggplot(mpg, aes(displ, hwy)) +
|
||||
#' geom_point() +
|
||||
#' theme_civilytics()
|
||||
@@ -79,10 +81,10 @@
|
||||
#' scale_color_civilytics() +
|
||||
#' theme_civilytics(grid = "both")
|
||||
#'
|
||||
#' # Transparent background for embedding
|
||||
#' # Branded cream background (opt-in)
|
||||
#' ggplot(mpg, aes(displ, hwy)) +
|
||||
#' geom_point() +
|
||||
#' theme_civilytics(paper_bg = FALSE)
|
||||
#' theme_civilytics(paper_bg = TRUE)
|
||||
#'
|
||||
#' # Larger text for poster or display
|
||||
#' ggplot(mpg, aes(displ, hwy)) +
|
||||
@@ -102,7 +104,7 @@ theme_civilytics <- function(
|
||||
accent = unname(civilytics_colors["ember_600"]),
|
||||
strip_color = unname(civilytics_colors["paper_2"]),
|
||||
grid = c("y", "x", "both", "none"),
|
||||
paper_bg = TRUE) {
|
||||
paper_bg = FALSE) {
|
||||
|
||||
grid <- match.arg(grid)
|
||||
half_line <- font_size / 2
|
||||
|
||||
@@ -4,17 +4,25 @@
|
||||
\alias{civilytics_load_fonts}
|
||||
\title{Load Civilytics brand fonts}
|
||||
\usage{
|
||||
civilytics_load_fonts()
|
||||
civilytics_load_fonts(force = FALSE)
|
||||
}
|
||||
\arguments{
|
||||
\item{force}{Logical. If \code{TRUE}, reload fonts even if they were already
|
||||
loaded in this session. Default \code{FALSE}.}
|
||||
}
|
||||
\value{
|
||||
Invisibly returns `NULL`.
|
||||
Invisibly returns \code{TRUE} if fonts were loaded, \code{FALSE} if skipped
|
||||
(already loaded and \code{force = FALSE}).
|
||||
}
|
||||
\description{
|
||||
Downloads Inter and Libre Franklin from Google Fonts via
|
||||
[sysfonts::font_add_google()], then calls [showtext::showtext_auto()] so
|
||||
that all graphics devices render text with those fonts. This is called
|
||||
automatically when the package loads; use this function to retry if the
|
||||
initial load failed (e.g., the machine was offline at load time).
|
||||
Downloads Inter, Libre Franklin, Source Serif 4 and JetBrains Mono from
|
||||
Google Fonts via \code{sysfonts::font_add_google()}, then calls
|
||||
\code{showtext::showtext_auto()} so that all graphics devices render text with
|
||||
those fonts. This is called automatically when the package loads; use this
|
||||
function to retry if the initial load failed (e.g., the machine was offline
|
||||
at load time).
|
||||
|
||||
Subsequent calls within the same session are no-ops unless \code{force = TRUE}.
|
||||
}
|
||||
\examples{
|
||||
\dontrun{
|
||||
|
||||
+10
-8
@@ -17,7 +17,7 @@ theme_civilytics(
|
||||
accent = unname(civilytics_colors["ember_600"]),
|
||||
strip_color = unname(civilytics_colors["paper_2"]),
|
||||
grid = c("y", "x", "both", "none"),
|
||||
paper_bg = TRUE
|
||||
paper_bg = FALSE
|
||||
)
|
||||
}
|
||||
\arguments{
|
||||
@@ -56,10 +56,12 @@ to [civilytics_colors]`["paper_2"]` (`#F2EDE4`).}
|
||||
\item{grid}{Character. Which major gridlines to draw: `"y"` (default,
|
||||
horizontal only), `"x"` (vertical only), `"both"`, or `"none"`.}
|
||||
|
||||
\item{paper_bg}{Logical. If `TRUE` (default), fill the plot and panel
|
||||
backgrounds with the warm `paper` color. Set to `FALSE` for a
|
||||
transparent background (useful for slides or overlay on colored
|
||||
surfaces).}
|
||||
\item{paper_bg}{Logical. If `TRUE`, fill the plot and panel backgrounds
|
||||
with the warm `paper` color (Civilytics cream). Default is `FALSE`
|
||||
(transparent) so that figures composite cleanly onto any background.
|
||||
Set to `TRUE` for the branded cream canvas. Note: a transparent device
|
||||
background (e.g., `dev = "ragg_png"`, `dev.args = list(background =
|
||||
"transparent")`) is also needed for fully-transparent PNG exports.}
|
||||
}
|
||||
\value{
|
||||
A complete ggplot2 [ggplot2::theme()] object.
|
||||
@@ -105,7 +107,7 @@ shrinkage.
|
||||
\dontrun{
|
||||
library(ggplot2)
|
||||
|
||||
# Default editorial theme
|
||||
# Default — transparent background for embedding
|
||||
ggplot(mpg, aes(displ, hwy)) +
|
||||
geom_point() +
|
||||
theme_civilytics()
|
||||
@@ -116,10 +118,10 @@ ggplot(mpg, aes(displ, hwy, colour = class)) +
|
||||
scale_color_civilytics() +
|
||||
theme_civilytics(grid = "both")
|
||||
|
||||
# Transparent background for embedding
|
||||
# Branded cream background (opt-in)
|
||||
ggplot(mpg, aes(displ, hwy)) +
|
||||
geom_point() +
|
||||
theme_civilytics(paper_bg = FALSE)
|
||||
theme_civilytics(paper_bg = TRUE)
|
||||
|
||||
# Larger text for poster or display
|
||||
ggplot(mpg, aes(displ, hwy)) +
|
||||
|
||||
@@ -56,10 +56,10 @@ to [civilytics_colors]`["paper_2"]` (`#F2EDE4`).}
|
||||
\item{grid}{Character. Which major gridlines to draw: `"y"` (default,
|
||||
horizontal only), `"x"` (vertical only), `"both"`, or `"none"`.}
|
||||
|
||||
\item{paper_bg}{Logical. If `TRUE` (default), fill the plot and panel
|
||||
backgrounds with the warm `paper` color. Set to `FALSE` for a
|
||||
transparent background (useful for slides or overlay on colored
|
||||
surfaces).}
|
||||
\item{paper_bg}{Logical. If `TRUE`, fill the plot and panel backgrounds
|
||||
with the warm `paper` color (Civilytics cream). Default is `FALSE`
|
||||
(transparent) so that figures composite cleanly onto any background.
|
||||
Set to `TRUE` for the branded cream canvas.}
|
||||
}
|
||||
\value{
|
||||
A complete ggplot2 [ggplot2::theme()] object.
|
||||
|
||||
@@ -52,10 +52,10 @@ design system.}
|
||||
\item{strip_color}{Character. Hex code for facet strip background. Defaults
|
||||
to [civilytics_colors]`["paper_2"]` (`#F2EDE4`).}
|
||||
|
||||
\item{paper_bg}{Logical. If `TRUE` (default), fill the plot and panel
|
||||
backgrounds with the warm `paper` color. Set to `FALSE` for a
|
||||
transparent background (useful for slides or overlay on colored
|
||||
surfaces).}
|
||||
\item{paper_bg}{Logical. If `TRUE`, fill the plot and panel backgrounds
|
||||
with the warm `paper` color (Civilytics cream). Default is `FALSE`
|
||||
(transparent) so that figures composite cleanly onto any background.
|
||||
Set to `TRUE` for the branded cream canvas.}
|
||||
}
|
||||
\value{
|
||||
A complete ggplot2 [ggplot2::theme()] object.
|
||||
|
||||
@@ -52,10 +52,10 @@ design system.}
|
||||
\item{strip_color}{Character. Hex code for facet strip background. Defaults
|
||||
to [civilytics_colors]`["paper_2"]` (`#F2EDE4`).}
|
||||
|
||||
\item{paper_bg}{Logical. If `TRUE` (default), fill the plot and panel
|
||||
backgrounds with the warm `paper` color. Set to `FALSE` for a
|
||||
transparent background (useful for slides or overlay on colored
|
||||
surfaces).}
|
||||
\item{paper_bg}{Logical. If `TRUE`, fill the plot and panel backgrounds
|
||||
with the warm `paper` color (Civilytics cream). Default is `FALSE`
|
||||
(transparent) so that figures composite cleanly onto any background.
|
||||
Set to `TRUE` for the branded cream canvas.}
|
||||
}
|
||||
\value{
|
||||
A complete ggplot2 [ggplot2::theme()] object.
|
||||
|
||||
@@ -56,10 +56,10 @@ to [civilytics_colors]`["paper_2"]` (`#F2EDE4`).}
|
||||
\item{grid}{Character. Which major gridlines to draw: `"y"` (default,
|
||||
horizontal only), `"x"` (vertical only), `"both"`, or `"none"`.}
|
||||
|
||||
\item{paper_bg}{Logical. If `TRUE` (default), fill the plot and panel
|
||||
backgrounds with the warm `paper` color. Set to `FALSE` for a
|
||||
transparent background (useful for slides or overlay on colored
|
||||
surfaces).}
|
||||
\item{paper_bg}{Logical. If `TRUE`, fill the plot and panel backgrounds
|
||||
with the warm `paper` color (Civilytics cream). Default is `FALSE`
|
||||
(transparent) so that figures composite cleanly onto any background.
|
||||
Set to `TRUE` for the branded cream canvas.}
|
||||
}
|
||||
\value{
|
||||
A complete ggplot2 [ggplot2::theme()] object.
|
||||
|
||||
@@ -52,10 +52,10 @@ design system.}
|
||||
\item{strip_color}{Character. Hex code for facet strip background. Defaults
|
||||
to [civilytics_colors]`["paper_2"]` (`#F2EDE4`).}
|
||||
|
||||
\item{paper_bg}{Logical. If `TRUE` (default), fill the plot and panel
|
||||
backgrounds with the warm `paper` color. Set to `FALSE` for a
|
||||
transparent background (useful for slides or overlay on colored
|
||||
surfaces).}
|
||||
\item{paper_bg}{Logical. If `TRUE`, fill the plot and panel backgrounds
|
||||
with the warm `paper` color (Civilytics cream). Default is `FALSE`
|
||||
(transparent) so that figures composite cleanly onto any background.
|
||||
Set to `TRUE` for the branded cream canvas.}
|
||||
}
|
||||
\value{
|
||||
A complete ggplot2 [ggplot2::theme()] object.
|
||||
|
||||
@@ -133,8 +133,13 @@ test_that("theme_civilytics uses brand ink color for text", {
|
||||
expect_equal(th$text$colour, unname(civilytics_colors["ink"]))
|
||||
})
|
||||
|
||||
test_that("theme_civilytics uses brand paper color for plot background", {
|
||||
test_that("theme_civilytics has transparent background by default", {
|
||||
th <- theme_civilytics()
|
||||
expect_true(is.na(th$plot.background$fill))
|
||||
})
|
||||
|
||||
test_that("theme_civilytics uses brand paper color when paper_bg = TRUE", {
|
||||
th <- theme_civilytics(paper_bg = TRUE)
|
||||
expect_equal(th$plot.background$fill, unname(civilytics_colors["paper"]))
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user