From f8898063c68611122d75b0371ab42a255f2b863e Mon Sep 17 00:00:00 2001 From: atusy <30277794+atusy@users.noreply.github.com> Date: Wed, 4 Sep 2019 12:25:00 +0900 Subject: [PATCH 1/6] Add blank lines when multiple plots are available with captions --- R/hooks-md.R | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/R/hooks-md.R b/R/hooks-md.R index 3a45fc3090..787b6dbca6 100644 --- a/R/hooks-md.R +++ b/R/hooks-md.R @@ -1,27 +1,37 @@ #' @rdname hook_plot #' @export hook_plot_md = function(x, options) { + add_lines = function(x) { + if ( + (isTRUE(options$echo) && options$fig.show != 'hold') || + is.null(options$fig.cap) || options$fig.num %in% c(1L, options$fig.cur) + ) { + return(x) + } + paste0(x, "\n\n") + } # if not using R Markdown v2 or output is HTML, just return v1 output if (is.null(to <- pandoc_to()) || is_html_output(to)) - return(hook_plot_md_base(x, options)) + return(add_lines(hook_plot_md_base(x, options))) if ((options$fig.show == 'animate' || is_tikz_dev(options)) && is_latex_output()) return(hook_plot_tex(x, options)) + office_output = to %in% c('docx', 'pptx', 'rtf', 'odt') if (need_special_plot_hook(options)) { if (is_latex_output()) { # Pandoc < 1.13 does not support \caption[]{} so suppress short caption if (is.null(options$fig.scap)) options$fig.scap = NA - return(hook_plot_tex(x, options)) + return(add_lines(hook_plot_tex(x, options))) } if (office_output) { if (options$fig.align != 'default') { warning('Chunk options fig.align is not supported for ', to, ' output') options$fig.align = 'default' } - return(hook_plot_md_pandoc(x, options)) + return(add_lines(hook_plot_md_pandoc(x, options))) } } - hook_plot_md_base(x, options) + add_lines(hook_plot_md_base(x, options)) } # decide if the markdown plot hook is not enough and needs special hooks like From b76f273a6cb35eadc9e84886cef7183b3a592c5b Mon Sep 17 00:00:00 2001 From: atusy <30277794+atusy@users.noreply.github.com> Date: Fri, 6 Sep 2019 10:25:14 +0900 Subject: [PATCH 2/6] add test for hook_plot_md_base --- tests/testit/test-hooks-md.R | 37 ++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/tests/testit/test-hooks-md.R b/tests/testit/test-hooks-md.R index 3e186b010a..2f13b6d331 100644 --- a/tests/testit/test-hooks-md.R +++ b/tests/testit/test-hooks-md.R @@ -67,8 +67,8 @@ x = "1.png" w = h = 1 ex = "style='margin: 0;'" cap = "foo" -opt <- function(w = NULL, h =NULL, ex = NULL, cap = NULL, show = 'asis', ...) { - list(out.width = w, out.height = h, out.extra = ex, fig.cap = cap, fig.show = show, ...) +opt <- function(w = NULL, h =NULL, ex = NULL, cap = NULL, show = 'asis', align = 'default', ...) { + list(out.width = w, out.height = h, out.extra = ex, fig.cap = cap, fig.show = show, fig.align = align, ...) } assert("Include a plot by pandoc md", { @@ -80,3 +80,36 @@ assert("Include a plot by pandoc md", { (hook_plot_md_pandoc(x, opt(w = w, cap = cap, ex = ex)) %==% sprintf("![%s](1.png){width=%s %s}", cap, w, ex)) }) + +align = 'left' +link = 'https://example.com' + +hook = hook_plot_md_base +assert("Include a plot in variety of formats with hook_plot_md_base", { + # width, height, and extra are null, and align is default + (hook(x, opt()) %==% "![](1.png)") + (hook(x, opt(cap = cap)) %==% sprintf("![%s](1.png)", cap)) + (hook(x, opt(fig.link = link)) %==% sprintf("[![](1.png)](%s)", link)) + opts_knit$set(rmarkdown.pandoc.to = 'latex') + (hook(x, opt(cap = '')) %==% "![](1.png) ") + opts_knit$set(rmarkdown.pandoc.to = 'html') + (hook(x, opt(cap = '')) %==% "![](1.png)") + # html output with caption or width + (hook(x, opt(align = align, cap = cap)) %==% + sprintf('
\n%s\n

%s

\n
', align, cap, cap)) + ## add link + (hook(x, opt(w = w, cap = cap, fig.link = link)) %==% + sprintf('
\n%s\n

%s

\n
', link, cap, w, cap)) + ## fig.caption is TRUE + (hook(x, opt(w = w, cap = cap, fig.topcaption = TRUE)) %==% + sprintf('
\n

%s

%s
', cap, cap, w)) + ## plot1 is FALSE + (hook(x, opt(w = w, cap = cap, show = 'hold', fig.cur = 2, fig.num = 2)) %==% + sprintf('%s\n

%s

\n', cap, w, cap)) + ## plot2 is FALSE + (hook(x, opt(w = w, cap = cap, show = 'hold', fig.cur = 1, fig.num = 2)) %==% + sprintf('
\n%s', cap, w, cap)) + # else + opts_knit$restore() + (hook(x, opt(align = 'center')) %==% '') +}) From 78c0104c5a48d9516d9f54b0178d28fa36c918ca Mon Sep 17 00:00:00 2001 From: atusy <30277794+atusy@users.noreply.github.com> Date: Fri, 6 Sep 2019 11:05:23 +0900 Subject: [PATCH 3/6] fix: echo can be TRUE, FALSE, or integers --- R/hooks-md.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/hooks-md.R b/R/hooks-md.R index 787b6dbca6..2ad21348bc 100644 --- a/R/hooks-md.R +++ b/R/hooks-md.R @@ -3,7 +3,7 @@ hook_plot_md = function(x, options) { add_lines = function(x) { if ( - (isTRUE(options$echo) && options$fig.show != 'hold') || + (!identical(options$echo, FALSE) && options$fig.show != 'hold') || is.null(options$fig.cap) || options$fig.num %in% c(1L, options$fig.cur) ) { return(x) From eb3ed65af68e1dfea68deed8db085db3c1404699 Mon Sep 17 00:00:00 2001 From: atusy <30277794+atusy@users.noreply.github.com> Date: Fri, 6 Sep 2019 17:50:30 +0900 Subject: [PATCH 4/6] factor out add_lines and rename it to append_blank_lines --- R/hooks-md.R | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/R/hooks-md.R b/R/hooks-md.R index 2ad21348bc..0fbc360ab1 100644 --- a/R/hooks-md.R +++ b/R/hooks-md.R @@ -1,18 +1,9 @@ #' @rdname hook_plot #' @export hook_plot_md = function(x, options) { - add_lines = function(x) { - if ( - (!identical(options$echo, FALSE) && options$fig.show != 'hold') || - is.null(options$fig.cap) || options$fig.num %in% c(1L, options$fig.cur) - ) { - return(x) - } - paste0(x, "\n\n") - } # if not using R Markdown v2 or output is HTML, just return v1 output if (is.null(to <- pandoc_to()) || is_html_output(to)) - return(add_lines(hook_plot_md_base(x, options))) + return(append_blank_lines(hook_plot_md_base(x, options), options)) if ((options$fig.show == 'animate' || is_tikz_dev(options)) && is_latex_output()) return(hook_plot_tex(x, options)) @@ -21,17 +12,17 @@ hook_plot_md = function(x, options) { if (is_latex_output()) { # Pandoc < 1.13 does not support \caption[]{} so suppress short caption if (is.null(options$fig.scap)) options$fig.scap = NA - return(add_lines(hook_plot_tex(x, options))) + return(append_blank_lines(hook_plot_tex(x, options), options)) } if (office_output) { if (options$fig.align != 'default') { warning('Chunk options fig.align is not supported for ', to, ' output') options$fig.align = 'default' } - return(add_lines(hook_plot_md_pandoc(x, options))) + return(append_blank_lines(hook_plot_md_pandoc(x, options), options)) } } - add_lines(hook_plot_md_base(x, options)) + append_blank_lines(hook_plot_md_base(x, options), options) } # decide if the markdown plot hook is not enough and needs special hooks like @@ -124,6 +115,16 @@ css_text_align = function(align) { if (align == 'default') '' else sprintf(' style="text-align: %s"', align) } +append_blank_lines = function(x, options) { + if ( + (!identical(options$echo, FALSE) && options$fig.show != 'hold') || + is.null(options$fig.cap) || options$fig.num == options$fig.cur + ) { + return(x) + } + paste0(x, "\n\n") +} + # turn a class string "a b" to c(".a", ".b") for Pandoc fenced code blocks block_class = function(x) { if (length(x) > 0) gsub('^[.]*', '.', unlist(strsplit(x, '\\s+'))) From 4d38103016b5e3bdd1c7be0c48a1ea4329569a0c Mon Sep 17 00:00:00 2001 From: atusy <30277794+atusy@users.noreply.github.com> Date: Fri, 6 Sep 2019 17:50:40 +0900 Subject: [PATCH 5/6] add tests --- tests/testit/test-hooks-md.R | 48 ++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/tests/testit/test-hooks-md.R b/tests/testit/test-hooks-md.R index 2f13b6d331..afbff9570f 100644 --- a/tests/testit/test-hooks-md.R +++ b/tests/testit/test-hooks-md.R @@ -67,8 +67,15 @@ x = "1.png" w = h = 1 ex = "style='margin: 0;'" cap = "foo" -opt <- function(w = NULL, h =NULL, ex = NULL, cap = NULL, show = 'asis', align = 'default', ...) { - list(out.width = w, out.height = h, out.extra = ex, fig.cap = cap, fig.show = show, fig.align = align, ...) +align = 'left' +link = 'https://example.com' +opt <- function( + w = NULL, h =NULL, ex = NULL, align = 'default', cap = NULL, show = 'asis', ... +) { + list( + out.width = w, out.height = h, out.extra = ex, + fig.align = align, fig.cap = cap, fig.show = show,... + ) } assert("Include a plot by pandoc md", { @@ -81,9 +88,6 @@ assert("Include a plot by pandoc md", { sprintf("![%s](1.png){width=%s %s}", cap, w, ex)) }) -align = 'left' -link = 'https://example.com' - hook = hook_plot_md_base assert("Include a plot in variety of formats with hook_plot_md_base", { # width, height, and extra are null, and align is default @@ -113,3 +117,37 @@ assert("Include a plot in variety of formats with hook_plot_md_base", { opts_knit$restore() (hook(x, opt(align = 'center')) %==% '') }) + +hook <- hook_plot_md +assert('Check if hook_plot_md passes arguments to sub-functions', { + opts_knit$set(rmarkdown.pandoc.to = 'html') + (hook(x, opt()) %==% hook_plot_md_base(x, opt())) + + opts_knit$set(rmarkdown.pandoc.to = 'latex') + o = opt(w = w) + (hook(x, o) %==% hook_plot_tex(x, o)) + + opts_knit$set(rmarkdown.pandoc.to = 'docx') + (hook(x, o) %==% hook_plot_md_pandoc(x, o)) + + opts_knit$set(rmarkdown.pandoc.to = 'markdown') + (hook(x, opt()) %==% hook_plot_md_base(x, opt())) + (hook(x, o) %==% hook_plot_md_base(x, o)) +}) + +assert('Conditionally append blank lines to figures so that figure captions are displayed correctly', { + # Append when echo is FALSE or fig.show is hold and the current figure is not the last one + (append_blank_lines('a', list(echo = FALSE, fig.cap = cap, fig.num = 3, fig.cur = 1)) %==% 'a\n\n') + (append_blank_lines('a', list(fig.show = 'hold', fig.cap = cap, fig.num = 3, fig.cur = 1)) %==% 'a\n\n') + + # Do not append when + ## echo is not FALSE + (append_blank_lines('', list(echo = TRUE)) %==% '') + ## fig.show is not hold + (append_blank_lines('', list(echo = FALSE, fig.show = 'asis')) %==% '') + ## fig.cap is NULL + (append_blank_lines('', list(echo = FALSE, fig.cap = NULL)) %==% '') + ## fig.num is equal to fig.cur + (append_blank_lines('', list(echo = FALSE, fig.cap = cap, fig.num = 1, fig.cur = 1)) %==% '') +}) + From e404aa865475fadb949c22206951d1a56047395d Mon Sep 17 00:00:00 2001 From: atusy <30277794+atusy@users.noreply.github.com> Date: Fri, 6 Sep 2019 18:57:28 +0900 Subject: [PATCH 6/6] update news [skip ci] --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index 2bf24ce42d..9c1449882b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,8 @@ - The chunk option `collapse = TRUE` now works as expected when the chunk option `attr.*` or `class.*` is provided. By this change, The chunk option `collapse = TRUE` forces `attr.*` and `class.*` be `NULL` except for the chunk options `attr.source` and `class.source` (thanks, @aosavi @cderv @atusy, #1902 #1906). +- Captions disappeared when a chunk generates multiple figures continuously (thanks, @atusy, #1760) + # CHANGES IN knitr VERSION 1.30 ## NEW FEATURES