feat: add Quarto themes and templates (revealjs, HTML, PDF, Typst)
R-CMD-check / R CMD check (push) Successful in 3m52s

Integrate Civilytics Reveal.js slide extension, HTML/PDF/Typst document
themes, and _brand.yml into the package under inst/quarto/. Three new
helper functions (use_civilytics_revealjs, use_civilytics_theme,
use_civilytics_brand) copy assets into a user's Quarto project. Logos
are stored once in inst/img/ and distributed at install time.
This commit is contained in:
2026-05-20 09:39:27 -06:00
parent 41fe2b6170
commit 136c53643c
25 changed files with 3641 additions and 2 deletions
+7
View File
@@ -19,6 +19,13 @@
#' \item [scale_color_civilytics()] / [scale_fill_civilytics()] -- ggplot2 scales
#' }
#'
#' @section Quarto templates:
#' \itemize{
#' \item [use_civilytics_revealjs()] -- install Reveal.js slide extension
#' \item [use_civilytics_theme()] -- install HTML/PDF/Typst document theme
#' \item [use_civilytics_brand()] -- install brand.yml only (Quarto 1.5+)
#' }
#'
#' @keywords internal
#' @importFrom stats qbeta
#' @importFrom stats qnorm
+193
View File
@@ -0,0 +1,193 @@
#' Install Civilytics Quarto Themes and Templates
#'
#' Helper functions that copy Civilytics Quarto assets from the installed
#' package into your Quarto project directory. Logos are stored in a single
#' canonical location (`inst/img/`) and copied to the paths expected by each
#' template at install time.
#'
#' @name quarto-helpers
NULL
# -- internal utilities -------------------------------------------------------
#' Copy a package file to a project directory
#'
#' @param src Relative path within the installed package (under `inst/`).
#' @param dst Destination path relative to `path`.
#' @param path Project root.
#' @param force Overwrite existing files?
#' @return Invisible logical indicating success.
#' @keywords internal
.copy_pkg_file <- function(src, dst, path, force) {
from <- system.file(src, package = "civilytics", mustWork = TRUE)
to <- file.path(path, dst)
dir.create(dirname(to), recursive = TRUE, showWarnings = FALSE)
if (file.exists(to) && !force) {
message(" skip: ", dst, " (already exists; use force = TRUE to overwrite)")
return(invisible(FALSE))
}
file.copy(from, to, overwrite = force)
message(" copy: ", dst)
invisible(TRUE)
}
#' Copy logo SVGs from inst/img/ to a target directory
#'
#' @param dest_dir Destination directory relative to `path`.
#' @param path Project root.
#' @param force Overwrite existing files?
#' @param files Character vector of logo filenames to copy.
#' @keywords internal
.copy_logos <- function(dest_dir, path, force,
files = c("civilytics-mark.svg",
"civilytics-mark-reverse.svg",
"civilytics-wordmark.svg",
"civilytics-wordmark-reverse.svg",
"civilytics-pulse.svg")) {
for (f in files) {
.copy_pkg_file(file.path("img", f), file.path(dest_dir, f), path, force)
}
}
# -- public API ----------------------------------------------------------------
#' Install the Civilytics Reveal.js extension
#'
#' Copies the Civilytics Reveal.js Quarto extension into
#' `_extensions/civilytics-reveal/` under `path`, including brand logos
#' from the package. After running this function, add
#' `format: civilytics-reveal-revealjs` to your `.qmd` YAML front-matter.
#'
#' @param path Character. Project directory to install into. Default `"."`.
#' @param force Logical. Overwrite existing files? Default `FALSE`.
#'
#' @return Invisible `NULL`.
#' @export
#'
#' @examples
#' \dontrun{
#' use_civilytics_revealjs()
#' }
use_civilytics_revealjs <- function(path = ".", force = FALSE) {
path <- normalizePath(path, mustWork = TRUE)
message("Installing Civilytics Reveal.js extension into: ", path)
ext_src <- "quarto/extensions/civilytics-reveal"
ext_dst <- "_extensions/civilytics-reveal"
ext_files <- c(
"_extension.yml",
"civilytics.scss",
"civilytics.css",
"civilytics-head.html",
"civilytics-after.html"
)
for (f in ext_files) {
.copy_pkg_file(file.path(ext_src, f), file.path(ext_dst, f), path, force)
}
# Logos — single source from inst/img/
.copy_logos(file.path(ext_dst, "assets"), path, force)
message("\nDone! Add this to your .qmd front-matter:\n")
message("---")
message("format: civilytics-reveal-revealjs")
message("---")
invisible(NULL)
}
#' Install the Civilytics document theme
#'
#' Copies Civilytics HTML, PDF (LaTeX), and Typst theme files into
#' your Quarto project. Also installs `_brand.yml` and the logo
#' assets it references.
#'
#' @inheritParams use_civilytics_revealjs
#'
#' @return Invisible `NULL`.
#' @export
#'
#' @examples
#' \dontrun{
#' use_civilytics_theme()
#' }
use_civilytics_theme <- function(path = ".", force = FALSE) {
path <- normalizePath(path, mustWork = TRUE)
message("Installing Civilytics document theme into: ", path)
# Brand file
.copy_pkg_file("quarto/_brand.yml", "_brand.yml", path, force)
# HTML theme
theme_files <- c("civilytics.scss", "_tokens.scss", "extras.css")
for (f in theme_files) {
.copy_pkg_file(file.path("quarto/theme", f), file.path("theme", f), path, force)
}
# LaTeX
latex_files <- c("civilytics.tex", "civilytics-title.tex")
for (f in latex_files) {
.copy_pkg_file(file.path("quarto/latex", f), file.path("latex", f), path, force)
}
# Typst
.copy_pkg_file(
"quarto/typst/civilytics-typst.typ",
"typst/civilytics-typst.typ",
path, force
)
# Logos — for _brand.yml (expects assets/logo/)
.copy_logos("assets/logo", path, force)
# Example report
.copy_pkg_file("quarto/examples/report.qmd", "examples/report.qmd", path, force)
message("\nDone! Example YAML for a report:\n")
message("---")
message("format:")
message(" html:")
message(" theme: theme/civilytics.scss")
message(" css: theme/extras.css")
message(" pdf:")
message(" include-in-header: latex/civilytics.tex")
message(" include-before-body: latex/civilytics-title.tex")
message(" typst:")
message(" template: typst/civilytics-typst.typ")
message("---")
message("\nSee examples/report.qmd for a complete example.")
invisible(NULL)
}
#' Install the Civilytics brand file only
#'
#' Copies `_brand.yml` and the logo assets it references into your
#' Quarto project. This gives you Quarto 1.5+ automatic brand
#' styling (colors, fonts, logos) without the full theme SCSS.
#'
#' @inheritParams use_civilytics_revealjs
#'
#' @return Invisible `NULL`.
#' @export
#'
#' @examples
#' \dontrun{
#' use_civilytics_brand()
#' }
use_civilytics_brand <- function(path = ".", force = FALSE) {
path <- normalizePath(path, mustWork = TRUE)
message("Installing Civilytics brand file into: ", path)
.copy_pkg_file("quarto/_brand.yml", "_brand.yml", path, force)
.copy_logos("assets/logo", path, force)
message("\nDone! Quarto 1.5+ will auto-apply brand colors, fonts, and logos.")
message("See: https://quarto.org/docs/authoring/brand.html")
invisible(NULL)
}