From c1e1496fd4e81fac5e103ccd5865c1e036d28b56 Mon Sep 17 00:00:00 2001 From: christophe dervieux Date: Fri, 15 May 2026 14:19:14 +0200 Subject: [PATCH 1/7] Define no-op \authormark fallback for OUP v1 template (#603) The November 2025 update to oup-authoring-template.cls on CTAN (v1.2) removed the \authormark macro definition while still referencing it from the class' own \@@title. Documents using the rticles oup_v1 template fail to compile with "! Undefined control sequence \authormark" because the template emits \authormark{...} for the running head and the class no longer defines it. Add a \providecommand\authormark[1]{} fallback so rendering works whether or not the upstream macro is available. --- NEWS.md | 2 ++ inst/rmarkdown/templates/oup_v1/resources/template.tex | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/NEWS.md b/NEWS.md index 3c57d6a0..0b908130 100644 --- a/NEWS.md +++ b/NEWS.md @@ -42,6 +42,8 @@ supported by the `copernicus.cls`, and fix an issue where the section headers we - Added `\setlength{\emergencystretch}{3em}` to prevent overfull lines. - Updated CSL citation helper commands (`\CSLBlock`, `\CSLLeftMargin`, `\CSLRightInline`) to match current Pandoc defaults, improving bibliography spacing and baseline alignment. +- Fix `oup_article(oup_version = 1)` rendering with the November 2025 update of `oup-authoring-template.cls` (v1.2) on CTAN, which removed the `\authormark` macro definition but still references it from the class' own `\@@title`. The template now defines a no-op `\authormark` fallback so documents render whether or not the upstream macro is available (#603). + - Adapt all templates to new Pandoc 3.8.2.1 change regarding table counter definition (#595). - Patch `WileyNDJ` template used in `sim_article()` to fix an issue with `etex` package not being useful anymore in recent LaTeX distributions (#593). diff --git a/inst/rmarkdown/templates/oup_v1/resources/template.tex b/inst/rmarkdown/templates/oup_v1/resources/template.tex index 4e72e5d0..43cbf18d 100644 --- a/inst/rmarkdown/templates/oup_v1/resources/template.tex +++ b/inst/rmarkdown/templates/oup_v1/resources/template.tex @@ -281,6 +281,11 @@ % Add missing \city command mentioned in documentation but absent from cls \providecommand\city[1]{#1} +% \authormark was removed from oup-authoring-template.cls (v1.2, 2025/11/17) +% but is still referenced in the class' own \@@title. Define a no-op fallback +% so documents render whether or not the upstream macro is available. +\providecommand\authormark[1]{} + % Create labels for Addresses if the are given in Elsevier format $for(address)$ $if(address.code)$ From a2c9d6399d3d7cbd901ca2f0b747a6e21746fa0f Mon Sep 17 00:00:00 2001 From: christophe dervieux Date: Fri, 15 May 2026 14:19:15 +0200 Subject: [PATCH 2/7] Drop \authormark block from OUP v1 template (#603) Replaces the no-op \providecommand fallback with simply removing the template block that emitted \authormark{...}. \authormark was an internal macro of oup-authoring-template.cls that was never part of the class' documented public API, and it was removed in the v1.2 update (17 November 2025). The documented running-head mechanism in v1.2 is the optional argument of \title (\title[short]{long}), which the template already uses. This matches OUP's own example file on CTAN, which no longer references \authormark either. Cosmetic side effect on TeX Live <= 2024 (cls v1.1): the even-page running head changes from "Author et al." to the short title, which is what OUP's v1.2 docs now prescribe on both pages anyway. --- NEWS.md | 2 +- .../templates/oup_v1/resources/template.tex | 14 -------------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/NEWS.md b/NEWS.md index 0b908130..32ba5f56 100644 --- a/NEWS.md +++ b/NEWS.md @@ -42,7 +42,7 @@ supported by the `copernicus.cls`, and fix an issue where the section headers we - Added `\setlength{\emergencystretch}{3em}` to prevent overfull lines. - Updated CSL citation helper commands (`\CSLBlock`, `\CSLLeftMargin`, `\CSLRightInline`) to match current Pandoc defaults, improving bibliography spacing and baseline alignment. -- Fix `oup_article(oup_version = 1)` rendering with the November 2025 update of `oup-authoring-template.cls` (v1.2) on CTAN, which removed the `\authormark` macro definition but still references it from the class' own `\@@title`. The template now defines a no-op `\authormark` fallback so documents render whether or not the upstream macro is available (#603). +- Fix `oup_article(oup_version = 1)` rendering with the November 2025 update of `oup-authoring-template.cls` (v1.2) on CTAN, which removed the (undocumented) `\authormark` macro that the template was emitting for the running head. The block is now dropped from the template, matching OUP's own example file and current author manual: the running head is set via the optional argument of `\title` (`\title[short]{long}`), which is the documented mechanism in v1.2 (#603). - Adapt all templates to new Pandoc 3.8.2.1 change regarding table counter definition (#595). diff --git a/inst/rmarkdown/templates/oup_v1/resources/template.tex b/inst/rmarkdown/templates/oup_v1/resources/template.tex index 43cbf18d..901c3377 100644 --- a/inst/rmarkdown/templates/oup_v1/resources/template.tex +++ b/inst/rmarkdown/templates/oup_v1/resources/template.tex @@ -281,11 +281,6 @@ % Add missing \city command mentioned in documentation but absent from cls \providecommand\city[1]{#1} -% \authormark was removed from oup-authoring-template.cls (v1.2, 2025/11/17) -% but is still referenced in the class' own \@@title. Define a no-op fallback -% so documents render whether or not the upstream macro is available. -\providecommand\authormark[1]{} - % Create labels for Addresses if the are given in Elsevier format $for(address)$ $if(address.code)$ @@ -384,15 +379,6 @@ $endfor$ -% Add author mark -$if(authormark)$ -\authormark{$authormark$} -$elseif(author)$ -\authormark{$for(author/first)$$it.name$$endfor$$if(author/rest/rest)$ et al.$else$$for(author/rest)$ \and $author.name$$endfor$$endif$} -$elseif(authors)$ -\authormark{$for(authors/first)$$it.name$$endfor$$if(authors/rest/rest)$ et al.$else$$for(authors/rest)$ \and $authors.name$$endfor$$endif$} -$endif$ - \received{Date}{0}{Year} \revised{Date}{0}{Year} \accepted{Date}{0}{Year} From 9f7ee351927e938d7315e1a023827c8c7b537548 Mon Sep 17 00:00:00 2001 From: christophe dervieux Date: Fri, 15 May 2026 14:19:16 +0200 Subject: [PATCH 3/7] bump dev version --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index f6f70e35..674cd536 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: rticles Title: Article Formats for R Markdown -Version: 0.27.13 +Version: 0.27.14 Authors@R: c( person("JJ", "Allaire", , "jj@posit.co", role = "aut"), person("Yihui", "Xie", , "xie@yihui.name", role = "aut", From 415d52741353e6ead8dd38da788490c29272e432 Mon Sep 17 00:00:00 2001 From: christophe dervieux Date: Fri, 15 May 2026 14:19:17 +0200 Subject: [PATCH 4/7] Warn at render time when YAML still sets removed `authormark` (#603) Mirrors the existing pattern in `ams_article()`, `tf_article()`, and the springer-related warning in `R/article.R`: attach a `pre_knit` hook that checks the parsed YAML metadata and emits an immediate warning when the user supplies a field that is no longer wired up. Since the YAML `authormark` key was undocumented but accepted by the oup_v1 Pandoc template before this fix, users who discovered it would otherwise silently lose the value after the upgrade. The warning makes the removal visible. Adds three testthat tests: - warning fires when metadata contains `authormark` - no warning for unrelated metadata - template no longer contains the literal `\authormark` string (guards against re-introduction) --- NEWS.md | 2 +- R/oup_article.R | 18 +++++++++++++++++- tests/testthat/test-oup_article.R | 21 +++++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 tests/testthat/test-oup_article.R diff --git a/NEWS.md b/NEWS.md index 32ba5f56..7eb049b1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -42,7 +42,7 @@ supported by the `copernicus.cls`, and fix an issue where the section headers we - Added `\setlength{\emergencystretch}{3em}` to prevent overfull lines. - Updated CSL citation helper commands (`\CSLBlock`, `\CSLLeftMargin`, `\CSLRightInline`) to match current Pandoc defaults, improving bibliography spacing and baseline alignment. -- Fix `oup_article(oup_version = 1)` rendering with the November 2025 update of `oup-authoring-template.cls` (v1.2) on CTAN, which removed the (undocumented) `\authormark` macro that the template was emitting for the running head. The block is now dropped from the template, matching OUP's own example file and current author manual: the running head is set via the optional argument of `\title` (`\title[short]{long}`), which is the documented mechanism in v1.2 (#603). +- Fix `oup_article(oup_version = 1)` rendering with the November 2025 update of `oup-authoring-template.cls` (v1.2) on CTAN, which removed the (undocumented) `\authormark` macro that the template was emitting for the running head. The block is now dropped from the template, matching OUP's own example file and current author manual: the running head is set via the optional argument of `\title` (`\title[short]{long}`), which is the documented mechanism in v1.2. Setting `authormark` in YAML is now ignored and emits a warning at render time (#603). - Adapt all templates to new Pandoc 3.8.2.1 change regarding table counter definition (#595). diff --git a/R/oup_article.R b/R/oup_article.R index 395a69c6..9ab22b09 100644 --- a/R/oup_article.R +++ b/R/oup_article.R @@ -126,7 +126,7 @@ oup_article <- function( # Controls template to use. 1 for newer template. } } - pdf_document_format( + base <- pdf_document_format( "oup_v1", keep_tex = keep_tex, md_extensions = md_extensions, @@ -135,4 +135,20 @@ oup_article <- function( # Controls template to use. 1 for newer template. number_sections = number_sections, ... ) + + # Warn if YAML metadata still sets the removed `authormark` field + # (oup-authoring-template.cls v1.2, 2025-11-17, dropped the \authormark macro) + pre_knit <- base$pre_knit + base$pre_knit <- function(input, metadata, ...) { + if (is.function(pre_knit)) pre_knit(input, metadata, ...) + if ("authormark" %in% names(metadata)) { + warning( + "`oup_article(oup_version = 1)` now ignores the 'authormark' field in YAML header. ", + "The \\authormark macro was removed from oup-authoring-template.cls v1.2 (2025-11-17); ", + "running heads are now set from the optional short title argument of \\title.", + immediate. = TRUE, call. = FALSE + ) + } + } + base } diff --git a/tests/testthat/test-oup_article.R b/tests/testthat/test-oup_article.R new file mode 100644 index 00000000..6b75f976 --- /dev/null +++ b/tests/testthat/test-oup_article.R @@ -0,0 +1,21 @@ +test_that("oup_article(oup_version = 1) warns when `authormark` is set in YAML", { + fmt <- oup_article(oup_version = 1) + expect_warning( + fmt$pre_knit(input = "", metadata = list(authormark = "Anonymous et al.")), + regexp = "authormark" + ) +}) + +test_that("oup_article(oup_version = 1) does not warn for unrelated metadata", { + fmt <- oup_article(oup_version = 1) + expect_no_warning( + fmt$pre_knit(input = "", metadata = list(title = "A title")) + ) +}) + +test_that("oup_v1 template no longer emits \\authormark", { + tex <- xfun::read_utf8( + pkg_file_template("oup_v1", "resources", "template.tex") + ) + expect_false(any(grepl("\\authormark", tex, fixed = TRUE))) +}) From 67f812f6400c429e3c0b4c1ac68b5e85eea961b7 Mon Sep 17 00:00:00 2001 From: christophe dervieux Date: Fri, 15 May 2026 14:19:18 +0200 Subject: [PATCH 5/7] Add render-based test for the oup_article pre_knit hook (#603) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The direct `fmt$pre_knit(...)` unit test verifies the warning logic but not that rmarkdown actually invokes the hook with the parsed YAML metadata. Add a knit-only render (run_pandoc = FALSE) of an Rmd whose YAML sets `authormark`, asserting the warning surfaces — covers the hook-wiring contract regardless of rmarkdown internals. Skips when pandoc <2.10 (the format already requires it). --- tests/testthat/test-oup_article.R | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/testthat/test-oup_article.R b/tests/testthat/test-oup_article.R index 6b75f976..1ea5e82c 100644 --- a/tests/testthat/test-oup_article.R +++ b/tests/testthat/test-oup_article.R @@ -13,6 +13,30 @@ test_that("oup_article(oup_version = 1) does not warn for unrelated metadata", { ) }) +test_that("rmarkdown::render() actually invokes the pre_knit hook", { + # Guards against regressions where pre_knit stops being wired into the + # format returned by oup_article(): asserts the warning surfaces from a + # real (knit-only, no LaTeX) render of an Rmd whose YAML sets `authormark`. + skip_if_not_installed("rmarkdown") + skip_if_not(rmarkdown::pandoc_available("2.10")) + rmd <- withr::local_tempfile(fileext = ".Rmd") + xfun::write_utf8(c( + "---", + "title: t", + "authormark: \"X et al.\"", + "output:", + " rticles::oup_article:", + " oup_version: 1", + "---", + "", + "Body." + ), rmd) + expect_warning( + rmarkdown::render(rmd, quiet = TRUE, run_pandoc = FALSE), + regexp = "authormark" + ) +}) + test_that("oup_v1 template no longer emits \\authormark", { tex <- xfun::read_utf8( pkg_file_template("oup_v1", "resources", "template.tex") From c4d5305bdee9616ce72e5342fb014f8fcca3b61c Mon Sep 17 00:00:00 2001 From: christophe dervieux Date: Fri, 15 May 2026 16:09:35 +0200 Subject: [PATCH 6/7] Skip oup_article(oup_version = 1) pre_knit tests on pandoc <2.10 (#603) `oup_article(oup_version = 1)` rejects construction below pandoc 2.10, so the direct pre_knit unit tests can't even build the format object on older runners. Mirrors the existing skip on the render-based test in the same file, and matches the package-wide convention in `tests/testit/test-formats.R` where `oup_v1` is skipped under the same constraint. --- tests/testthat/test-oup_article.R | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/tests/testthat/test-oup_article.R b/tests/testthat/test-oup_article.R index 1ea5e82c..b2fa434b 100644 --- a/tests/testthat/test-oup_article.R +++ b/tests/testthat/test-oup_article.R @@ -1,4 +1,5 @@ test_that("oup_article(oup_version = 1) warns when `authormark` is set in YAML", { + skip_if_not_pandoc("2.10") fmt <- oup_article(oup_version = 1) expect_warning( fmt$pre_knit(input = "", metadata = list(authormark = "Anonymous et al.")), @@ -7,6 +8,7 @@ test_that("oup_article(oup_version = 1) warns when `authormark` is set in YAML", }) test_that("oup_article(oup_version = 1) does not warn for unrelated metadata", { + skip_if_not_pandoc("2.10") fmt <- oup_article(oup_version = 1) expect_no_warning( fmt$pre_knit(input = "", metadata = list(title = "A title")) @@ -20,17 +22,20 @@ test_that("rmarkdown::render() actually invokes the pre_knit hook", { skip_if_not_installed("rmarkdown") skip_if_not(rmarkdown::pandoc_available("2.10")) rmd <- withr::local_tempfile(fileext = ".Rmd") - xfun::write_utf8(c( - "---", - "title: t", - "authormark: \"X et al.\"", - "output:", - " rticles::oup_article:", - " oup_version: 1", - "---", - "", - "Body." - ), rmd) + xfun::write_utf8( + c( + "---", + "title: t", + "authormark: \"X et al.\"", + "output:", + " rticles::oup_article:", + " oup_version: 1", + "---", + "", + "Body." + ), + rmd + ) expect_warning( rmarkdown::render(rmd, quiet = TRUE, run_pandoc = FALSE), regexp = "authormark" From 65e999bb5f05c5567667744d4ed4a6f914cf9af6 Mon Sep 17 00:00:00 2001 From: christophe dervieux Date: Fri, 15 May 2026 16:10:00 +0200 Subject: [PATCH 7/7] skip testing on old pandoc --- tests/testthat/helpers.R | 36 +++++++++++++++++++++++++++++++ tests/testthat/test-oup_article.R | 3 +-- 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 tests/testthat/helpers.R diff --git a/tests/testthat/helpers.R b/tests/testthat/helpers.R new file mode 100644 index 00000000..297a1dfc --- /dev/null +++ b/tests/testthat/helpers.R @@ -0,0 +1,36 @@ +local_rmd_file <- function(..., .env = parent.frame()) { + path <- withr::local_tempfile(.local_envir = .env, fileext = ".Rmd") + xfun::write_utf8(c(...), path) + path +} + +.render_and_read <- function(input, ...) { + skip_if_not_pandoc() + output_file <- withr::local_tempfile() + res <- rmarkdown::render(input, output_file = output_file, quiet = TRUE, ...) + xfun::read_utf8(res) +} + +# Use to test pandoc availability or version lower than +skip_if_not_pandoc <- function(ver = NULL) { + if (!rmarkdown::pandoc_available(ver)) { + msg <- if (is.null(ver)) { + "Pandoc is not available" + } else { + sprintf("Version of Pandoc is lower than %s.", ver) + } + skip(msg) + } +} + +# Use to test version greater than +skip_if_pandoc <- function(ver = NULL) { + if (rmarkdown::pandoc_available(ver)) { + msg <- if (is.null(ver)) { + "Pandoc is available" + } else { + sprintf("Version of Pandoc is greater than %s.", ver) + } + skip(msg) + } +} diff --git a/tests/testthat/test-oup_article.R b/tests/testthat/test-oup_article.R index b2fa434b..c7b19d82 100644 --- a/tests/testthat/test-oup_article.R +++ b/tests/testthat/test-oup_article.R @@ -19,8 +19,7 @@ test_that("rmarkdown::render() actually invokes the pre_knit hook", { # Guards against regressions where pre_knit stops being wired into the # format returned by oup_article(): asserts the warning surfaces from a # real (knit-only, no LaTeX) render of an Rmd whose YAML sets `authormark`. - skip_if_not_installed("rmarkdown") - skip_if_not(rmarkdown::pandoc_available("2.10")) + skip_if_not_pandoc("2.10") rmd <- withr::local_tempfile(fileext = ".Rmd") xfun::write_utf8( c(