Skip to content

Commit fd433f9

Browse files
Merge pull request #275 from rempsyc/scale_awesomecv_fonts
Adds new `font_scale` argument for `awesomecv()`
2 parents 588396c + 78d768c commit fd433f9

File tree

6 files changed

+113
-5
lines changed

6 files changed

+113
-5
lines changed

DESCRIPTION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: vitae
22
Title: Curriculum Vitae for R Markdown
3-
Version: 0.6.0
3+
Version: 0.6.0.1
44
Authors@R: c(
55
person("Mitchell", "O'Hara-Wild", role=c("aut", "cre"), email = "[email protected]", comment=c(ORCID = "0000-0001-6729-7695")),
66
person("Rob", "Hyndman", email="[email protected]", role=c("aut"), comment = c(ORCID = "0000-0002-2140-5352")),
@@ -34,5 +34,5 @@ Encoding: UTF-8
3434
BugReports: https://github.com/mitchelloharawild/vitae/issues
3535
URL: https://pkg.mitchelloharawild.com/vitae/, https://github.com/mitchelloharawild/vitae
3636
Roxygen: list(markdown = TRUE, roclets=c('rd', 'collate', 'namespace'))
37-
RoxygenNote: 7.3.1
37+
RoxygenNote: 7.3.2
3838
VignetteBuilder: knitr

NEWS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
# vitae 0.6.0.1
2+
3+
## New features
4+
5+
* `awesomecv`: added a `font_scale` argument to globally scale template font sizes.
6+
Scaling is applied to a temporary copy of `awesome-cv.cls` at render time; the
7+
default `1` preserves existing output. (@rempsyc, #275)
8+
19
# vitae 0.6.0
210

311
## New features

R/awesomecv.R

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#' @inheritParams rmarkdown::pdf_document
99
#' @param page_total If TRUE, the total number of pages is shown in the footer.
1010
#' @param show_footer If TRUE, a footer showing your name, document name, and page number.
11+
#' @param font_scale Numeric multiplier applied to hard-coded font sizes in the
12+
#' Awesome‑CV class (default = 1). Use values like 0.95–1.10.
1113
#'
1214
#' @section Preview:
1315
#' `r insert_preview("awesomecv")`
@@ -18,14 +20,18 @@
1820
#' ([@posquit0](https://github.com/posquit0))
1921
#'
2022
#' @export
21-
awesomecv <- function(..., latex_engine = "xelatex", page_total = FALSE,
22-
show_footer = TRUE) {
23+
awesomecv <- function(...,
24+
latex_engine = "xelatex",
25+
page_total = FALSE,
26+
show_footer = TRUE,
27+
font_scale = 1) {
2328
template <- system.file("rmarkdown", "templates", "awesomecv",
2429
"resources", "awesome-cv.tex",
2530
package = "vitae"
2631
)
2732
set_entry_formats(awesome_cv_entries)
2833
copy_supporting_files("awesomecv")
34+
font_size_scaling(scale = font_scale)
2935
pandoc_vars <- list()
3036
if(page_total) pandoc_vars$page_total <- TRUE
3137
if(show_footer) pandoc_vars$show_footer <- TRUE
@@ -61,3 +67,42 @@ awesome_cv_entries <- new_entry_formats(
6167
), collapse = "\n")
6268
}
6369
)
70+
71+
# Patches the local copy of awesome-cv.cls.
72+
# Strategy: inject \usepackage{xfp} and \newcommand\ACVscale{<scale>},
73+
# then convert \fontsize{<n>pt}{...} -> \fontsize{\fpeval{<n>*\ACVscale}pt}{...}
74+
font_size_scaling <- function(scale = 1, file_path = "awesome-cv.cls") {
75+
if (!file.exists(file_path)) {
76+
stop("Expected 'awesome-cv.cls' in the working directory after copy_supporting_files().")
77+
}
78+
79+
stopifnot(is.numeric(scale), length(scale) == 1, scale > 0)
80+
if (!file.exists(file_path)) stop("File not found: ", file_path)
81+
82+
x <- readLines(file_path, warn = FALSE)
83+
84+
# Insert just after fontspec so \fpeval is available before any uses
85+
anchor <- grep("\\\\RequirePackage\\[quiet\\]\\{fontspec\\}", x, perl = TRUE)[1]
86+
if (is.na(anchor)) anchor <- 0L
87+
88+
# Ensure xfp is loaded once
89+
if (!any(grepl("\\\\usepackage\\{xfp\\}", x, perl = TRUE))) {
90+
x <- append(x, "\\usepackage{xfp}", after = anchor); anchor <- anchor + 1L
91+
}
92+
93+
# Replace any prior ACVscale defs, then provide+renew (idempotent update)
94+
x <- x[!grepl("\\\\(re)?newcommand\\\\ACVscale|\\\\providecommand\\\\ACVscale", x, perl = TRUE)]
95+
x <- append(x,
96+
c("\\providecommand\\ACVscale{1}",
97+
sprintf("\\renewcommand\\ACVscale{%.6f}", scale)),
98+
after = anchor)
99+
100+
# Rewrite \fontsize{<n>pt}{...} -> \fontsize{\fpeval{<n>*\ACVscale}pt}{...}
101+
# (Note the doubled backslashes in the R string to yield single backslashes in .cls)
102+
x <- gsub("\\\\fontsize\\{([0-9.]+)pt\\}\\{",
103+
"\\\\fontsize{\\\\fpeval{\\1*\\\\ACVscale}pt}{",
104+
x, perl = TRUE)
105+
106+
writeLines(x, file_path)
107+
message("Font sizes will be scaled by LaTeX (xfp) using ACVscale = ", scale, ".")
108+
}

man/awesomecv.Rd

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-font-scale.R

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
skip_if_not(file.exists(system.file("rmarkdown","templates","awesomecv","resources","awesome-cv.tex", package = "vitae")))
2+
3+
test_that("font_size_scaling injects xfp, defines ACVscale, and rewrites \\fontsize", {
4+
cls <- tempfile(fileext = ".cls")
5+
writeLines(c(
6+
"\\ProvidesClass{awesome-cv}",
7+
"\\RequirePackage[quiet]{fontspec}",
8+
"\\newcommand*{\\headerfirstnamestyle}[1]{{\\fontsize{32pt}{1em}#1}}",
9+
"\\newcommand*{\\entrytitlestyle}[1]{{\\fontsize{10pt}{1em}#1}}"
10+
), cls)
11+
12+
font_size_scaling(scale = 1.10, file_path = cls)
13+
14+
out <- readLines(cls, warn = FALSE)
15+
expect_true(any(grepl("\\\\usepackage\\{xfp\\}", out)))
16+
expect_equal(sum(grepl("\\\\providecommand\\\\ACVscale\\{1\\}", out)), 1L)
17+
expect_true(any(grepl("\\\\renewcommand\\\\ACVscale\\{1\\.10", out)))
18+
expect_true(any(grepl("\\\\fontsize\\{\\\\fpeval\\{32\\*\\\\ACVscale\\}pt\\}\\{1em\\}", out)))
19+
expect_true(any(grepl("\\\\fontsize\\{\\\\fpeval\\{10\\*\\\\ACVscale\\}pt\\}\\{1em\\}", out)))
20+
21+
# Run again with a different scale: updates, no duplicates
22+
font_size_scaling(scale = 0.95, file_path = cls)
23+
out2 <- readLines(cls, warn = FALSE)
24+
expect_equal(sum(grepl("\\\\usepackage\\{xfp\\}", out2)), 1L)
25+
expect_equal(sum(grepl("\\\\providecommand\\\\ACVscale\\{1\\}", out2)), 1L)
26+
expect_true(any(grepl("\\\\renewcommand\\\\ACVscale\\{0\\.95", out2)))
27+
})
28+
29+
test_that("awesomecv copies resources and conditionally patches class", {
30+
tmp <- tempfile("vitae-fontscale-")
31+
dir.create(tmp)
32+
old <- getwd()
33+
on.exit({ setwd(old); unlink(tmp, recursive = TRUE, force = TRUE) }, add = TRUE)
34+
setwd(tmp)
35+
36+
# No patch when font_scale = 1
37+
awesomecv(font_scale = 1)
38+
expect_true(file.exists("awesome-cv.cls"))
39+
patched <- readLines("awesome-cv.cls", warn = FALSE)
40+
expect_true(any(grepl("\\\\usepackage\\{xfp\\}", patched)))
41+
expect_true(any(grepl("\\\\renewcommand\\\\ACVscale\\{1\\.00", patched)))
42+
expect_true(any(grepl("\\\\fontsize\\{\\\\fpeval\\{[0-9.]+\\*\\\\ACVscale\\}pt\\}\\{", patched)))
43+
44+
# Patch when font_scale != 1
45+
awesomecv(font_scale = 1.05)
46+
patched <- readLines("awesome-cv.cls", warn = FALSE)
47+
expect_true(any(grepl("\\\\usepackage\\{xfp\\}", patched)))
48+
expect_true(any(grepl("\\\\renewcommand\\\\ACVscale\\{1\\.05", patched)))
49+
expect_true(any(grepl("\\\\fontsize\\{\\\\fpeval\\{[0-9.]+\\*\\\\ACVscale\\}pt\\}\\{", patched)))
50+
})

vitae.Rproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Version: 1.0
2+
ProjectId: 1451009f-2dcb-4378-b90c-8826e7b4aae3
23

34
RestoreWorkspace: No
45
SaveWorkspace: No

0 commit comments

Comments
 (0)