Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix disappearance of figure captions when a chunk generates multiple figures continuously #1760

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 15 additions & 4 deletions R/hooks-md.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,26 @@
hook_plot_md = function(x, options) {
# 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(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))

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(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(hook_plot_md_pandoc(x, options))
return(append_blank_lines(hook_plot_md_pandoc(x, options), options))
}
}
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
Expand Down Expand Up @@ -114,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+')))
Expand Down
75 changes: 73 additions & 2 deletions tests/testit/test-hooks-md.R
Original file line number Diff line number Diff line change
Expand Up @@ -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', ...) {
list(out.width = w, out.height = h, out.extra = ex, fig.cap = cap, fig.show = show, ...)
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", {
Expand All @@ -80,3 +87,67 @@ 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))
})

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('<div class="figure" style="text-align: %s">\n<img src="1.png" alt="%s" />\n<p class="caption">%s</p>\n</div>', align, cap, cap))
## add link
(hook(x, opt(w = w, cap = cap, fig.link = link)) %==%
sprintf('<div class="figure">\n<a href="%s" target="_blank"><img src="1.png" alt="%s" width="%s" /></a>\n<p class="caption">%s</p>\n</div>', link, cap, w, cap))
## fig.caption is TRUE
(hook(x, opt(w = w, cap = cap, fig.topcaption = TRUE)) %==%
sprintf('<div class="figure">\n<p class="caption">%s</p><img src="1.png" alt="%s" width="%s" /></div>', cap, cap, w))
## plot1 is FALSE
(hook(x, opt(w = w, cap = cap, show = 'hold', fig.cur = 2, fig.num = 2)) %==%
sprintf('<img src="1.png" alt="%s" width="%s" />\n<p class="caption">%s</p>\n</div>', cap, w, cap))
## plot2 is FALSE
(hook(x, opt(w = w, cap = cap, show = 'hold', fig.cur = 1, fig.num = 2)) %==%
sprintf('<div class="figure">\n<img src="1.png" alt="%s" width="%s" />', cap, w, cap))
# else
opts_knit$restore()
(hook(x, opt(align = 'center')) %==% '<img src="1.png" style="display: block; margin: auto;" />')
})

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)) %==% '')
})