Skip to content

Commit 6d81d98

Browse files
committed
close #855: add a helper function to customize caption numbering
1 parent a39e8f4 commit 6d81d98

File tree

3 files changed

+123
-0
lines changed

3 files changed

+123
-0
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export(html_notebook2)
2222
export(html_vignette2)
2323
export(ioslides_presentation2)
2424
export(markdown_document2)
25+
export(number_caption)
2526
export(odt_document2)
2627
export(pdf_book)
2728
export(pdf_document2)

R/utils.R

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,18 @@ lua_filter = function (filters = NULL) {
621621
bookdown_yml_arg = function(config = load_config(), path = tempfile()) {
622622
# this is supported for Pandoc >= 2.3 only
623623
if (!rmarkdown::pandoc_available('2.3') || length(config) == 0) return()
624+
# remove functions in config values since they are meaningless to Pandoc
625+
remove_func = function(x) {
626+
if (is.list(x)) {
627+
for (i in seq_along(x)) {
628+
if (is.function(x[[i]])) x[i] = list(NULL) else {
629+
if (is.list(x[[i]])) x[[i]] = remove_func(x[[i]])
630+
}
631+
}
632+
}
633+
x
634+
}
635+
config = remove_func(config)
624636
yaml::write_yaml(list(bookdown = config), path)
625637
c("--metadata-file", rmarkdown::pandoc_path_arg(path))
626638
}
@@ -687,3 +699,64 @@ stop_if_not_exists = function(inputs) {
687699
is_empty = function(x) {
688700
length(x) == 0 || !nzchar(x)
689701
}
702+
703+
#' Customize numbering of figures and tables
704+
#'
705+
#' Figure/table numbering can be customized via functions (see
706+
#' \url{https://bookdown.org/yihui/bookdown/internationalization.html}). This
707+
#' function provides a way to customize the numbering of captions according to
708+
#' the ranges of caption numbers. For example, a different caption label can be
709+
#' used if the caption number is greater than a value.
710+
#' @param n A vector of breakpoints (sorted increasingly). It can be either
711+
#' numeric or character. If a breakpoint contains a fraction that ends with 0,
712+
#' it must be written in character, e.g., \code{"2.10"} (otherwise it will be
713+
#' treated as \code{2.1}).
714+
#' @param labels A vector of caption labels of \code{length(n) + 1}. The first
715+
#' label is used when the current caption number \code{i} is smaller than or
716+
#' equal to \code{n[1]}, and the second label is used when \code{i <= n[2]},
717+
#' etc.
718+
#' @param format A function that accepts the current label and number, and
719+
#' returns a character string as the caption prefix, e.g., \samp{Figure 1:}.
720+
#' @param format2 A function to generate the caption prefix when the caption
721+
#' number is not numeric, e.g., when the caption is in an appendix and the
722+
#' number may be \samp{A.1}.
723+
#' @return A function that can be passed to the \code{fig} or \code{tab} fields
724+
#' in \file{_bookdown.yml}.
725+
#' @export
726+
#' @examples
727+
#' f = bookdown::number_caption(8, c('Table', 'Supplementary table'))
728+
#' f(1)
729+
#' f(8)
730+
#' f(8.5)
731+
#' f(9.1)
732+
number_caption = function(
733+
n, labels, format = function(label, i) sprintf('%s %s: ', label, i),
734+
format2 = function(labels, i) sprintf('%s %s: ', labels[1], i)
735+
) {
736+
if (length(n) != length(labels) - 1) stop("length(n) must be equal to length(labels) - 1")
737+
# caption numbers are essentially version numbers instead of real numbers
738+
# (e.g., '2.10' > '2.9', but 2.10 < 2.9)
739+
n = as.numeric_version(n)
740+
function(i) {
741+
# use format2() when the caption number is not numeric (e.g., 'A.1' in appendix)
742+
if (!grepl('^[0-9]+([.][0-9]+)?$', i)) return(format2(labels, i))
743+
# i may be either integer or fractional
744+
i = as.numeric_version(i)
745+
k = 1
746+
while (k <= length(n)) {
747+
if (i <= n[k]) break
748+
k = k + 1L
749+
}
750+
label = labels[k]
751+
if (k > 1) {
752+
m = unlist(n[k - 1])
753+
i = unlist(i)
754+
if (length(i) == 1) i = i - m[1] else {
755+
if (length(m) > 1 && i[1] == m[1]) i[2] = i[2] - m[2]
756+
i[1] = i[1] - m[1] + 1
757+
}
758+
i = paste(as.character(i), collapse = '.')
759+
}
760+
format(label, i)
761+
}
762+
}

man/number_caption.Rd

Lines changed: 49 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)