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

figure labels for use with pandoc-fignos filter #417

Closed
HJAllen opened this issue Apr 23, 2015 · 8 comments
Closed

figure labels for use with pandoc-fignos filter #417

HJAllen opened this issue Apr 23, 2015 · 8 comments

Comments

@HJAllen
Copy link

HJAllen commented Apr 23, 2015

Is is possible to get knitr to add labels for figures (and tables) to the markdown files so that the pandoc-fignos filter could be used?
Particulars of the filter at
https://github.com/tomduck/pandoc-fignos
The filter requires the following format to create a reference

![Caption.](image.png) {#fig:description}

I have tried using fig.lp='#fig:' and extra.out='{#fig:description}' for both pdf and html output to no avail. if I knit to html and add the {#fig:description} to the .md file manually, pandoc will compile the pdf as expected.
Thanks!
Joel

@yihui
Copy link
Member

yihui commented Apr 24, 2015

I think we either wait for the official pandoc support (jgm/pandoc#813), or ask you to DIY by redefining the plot hook function in knitr (https://github.com/yihui/knitr/blob/master/R/hooks-md.R).

@HJAllen
Copy link
Author

HJAllen commented Apr 27, 2015

Ok. I think I want to change hook_plot_md_base as in

    hook_plot_md_base = function(x, options) {
      cat('Using JA hook_plot_md_base')
      if (options$fig.show == 'animate') return(hook_plot_html(x, options))
      base = opts_knit$get('base.url') %n% ''
      cap = .img.cap(options)
      if (is.null(w <- options$out.width) & is.null(h <- options$out.height) &
            is.null(s <- options$out.extra) & options$fig.align == 'default') {
        return(sprintf('![%s](%s%s){#fig:%s} ', cap, base, .upload.url(x),options$label))
        }
      # use HTML syntax <img src=...>
      .img.tag(
        .upload.url(x), w, h, cap,
        c(s, sprintf('style="%s"', css_align(options$fig.align)))
        )
      }

I don't know where to go from here. If I load the function into the global env it seems to not be called from hook_plot_md. how to get knitr to use the modified function?

@yihui
Copy link
Member

yihui commented Apr 27, 2015

Add this to the first code chunk of your Rmd document:

library(knitr)
knit_hooks$set(plot = YOUR_OWN_HOOK_FUNCTION)

Note there are a few internal functions in hook_plot_md_base above, and you probably need knitr::: to access them.

@yihui yihui closed this as completed May 1, 2015
@HJAllen
Copy link
Author

HJAllen commented May 11, 2015

I have gotten back to this issue and have tried the following without success. I am sure it is due to lack of fundamental understanding.
Also not sure how to get all of this into code block. wrapping all in ``` broke it into several blocks.


---
title: "plot.knit.md demo"
author: "Joel Allen"
date: "04/23/2015"
output:
  pdf_document:
    fig_caption: yes
    keep_tex: yes
    pandoc_args:
    - --filter
    - pandoc-fignos

  md_document:
    pandoc_args:
    - --filter
    - pandoc-fignos
    toc: yes


  html_document:
    keep_md: yes
    pandoc_args:
    - --filter
    - pandoc-fignos
  word_document:
    pandoc_args:
    - --filter
    - pandoc-fignos
---

```{r setup, echo=TRUE,eval=TRUE}
library(knitr)
 knit_hooks$get()$plot

plot_JA<-function (x, options)
  {
  if (is.null(to <- knitr:::pandoc_to()) || grepl("^markdown", to) ||
        to %in% c("html", "html5", "revealjs", "s5", "slideous",
                  "slidy"))
    return(hook_plot_md_base_JA(x, options))
  if (!is.null(options$out.width) || !is.null(options$out.height) ||
        !is.null(options$out.extra) || options$fig.align != "default") {
    if (to %in% c("beamer", "latex")) {
      if (is.null(options$fig.scap))
        options$fig.scap = NA
      return(knitr:::hook_plot_tex(x, options))
      }
    if (to == "docx") {
      warning("Chunk options fig.align, out.width, out.height, out.extra ",
              "are not supported for Word output")
      options$out.width = options$out.height = options$out.extra = NULL
      options$fig.align = "default"
      }
    }
  hook_plot_md_base_JA(x, options)
  }

# 
render_markdown()
hook_plot_md_JA<-function(x, options) {
  # if not using R Markdown v2 or output is HTML, just return v1 output
  if (is.null(to <- knitr:::pandoc_to()) || grepl('^markdown', to) ||
        to %in% c('html', 'html5', 'revealjs', 's5', 'slideous', 'slidy'))
    return(hook_plot_md_base_JA(x, options))
  if (!is.null(options$out.width) || !is.null(options$out.height) ||
        !is.null(options$out.extra) || options$fig.align != 'default') {
    if (to %in% c('beamer', 'latex')) {
      # Pandoc < 1.13 does not support \caption[]{} so suppress short caption
      if (is.null(options$fig.scap)) options$fig.scap = NA
      return(knitr:::hook_plot_tex(x, options))
      }
    if (to == 'docx') {
      warning('Chunk options fig.align, out.width, out.height, out.extra ',
              'are not supported for Word output')
      options$out.width = options$out.height = options$out.extra = NULL
      options$fig.align = 'default'
      }
    }
  hook_plot_md_base_JA(x, options)
  }

hook_plot_md_base_JA = function(x, options) {

  if (options$fig.show == 'animate') return(knitr:::hook_plot_html(x, options))
  base = opts_knit$get('base.url') %in% ''
  cap = knitr:::.img.cap(options)
  if (is.null(w <- options$out.width) & is.null(h <- options$out.height) &
        is.null(s <- options$out.extra) & options$fig.align == 'default') {
    return(sprintf('![%s](%s%s){#fig:%s} ', cap, base, knitr:::.upload.url(x),options$label))
    }
  # use HTML syntax <img src=...>
  knitr:::.img.tag(
    knitr:::.upload.url(x), w, h, cap,
    c(s, sprintf('style="%s"', knitr:::css_align(options$fig.align)))
    )
  }

knit_hooks$set(plot = plot_JA)
knit_hooks$get()$plot

debug(plot_JA)

This is an R Markdown document to demonstrate the generation of self-contained code chunks in a markdown file. It is particularly useful for situations where multiple plots are generated in a single code chunk allowing for dynamic label and caption support. See Figure @fig:carsPlot

This example draws on

http://stackoverflow.com/questions/21685885/knitr-plots-labels-and-captions-within-one-chunk

in response to

https://stackoverflow.com/questions/27443019/knitr-plots-labels-and-captions-within-one-chunk-rmd-files

Items to note:

#. output pdf_document fig_caption option must be set to yes

#. plot.knit has been modified to plot.knit.md to account for the different syntax needed.

suppressPackageStartupMessages(require(ggplot2))
cars.p<-ggplot(cars,aes(x=speed,y=dist))+
  geom_point()
plot(cars.p)

@tomduck
Copy link

tomduck commented Jun 6, 2015

Hi @HJAllen. Did this issue get resolved?

@HJAllen
Copy link
Author

HJAllen commented Jun 7, 2015

yes thanks

@dcomtois
Copy link

I know this is a rather old issue, but I just want to share a few observations about this topic, more specifically about the fact that column widths are being calculated from the cell's content, including when this content is a link to something else. (Thus a long path/filename creates huge columns, unrelated to the size of the image).

While links are made possible when creating images inside an Rmd document's chunks, when the markdown table itself comes from a package using functions such as pander::pander(), it's a whole other kettle of fish.

See this issue for all the details, but here's the TL;DR version :

  • I doubt there will be native support for image refs any time soon as most Pandoc users got used to filters that do the job quite well, it appears
  • The problem of column widths can be avoided with relative ease when the column containing the images is the last column...
  • ... But otherwise there is no real good solution to the problem, at least as far as I can figure this thing out

The best workaround I could find is to store the images into a subfolder using short names, such as img/001.png and fill the cells with, for instance, ![](img/001.png). But this implies writing temporary files in the users' directories, which is quite uncomfortable. If there was a way to automatically cleanup those temporary files upon knitr's termination, that would be much less of an annoyance, but I have no clue how this would be done.

So that's it. I know it's probably not a priority for many R developers, but I thought this should be the place to give a try and maybe revive the discussion. Some unexpected solutions could come up, who knows!

@github-actions
Copy link

github-actions bot commented Nov 3, 2020

This old thread has been automatically locked. If you think you have found something related to this, please open a new issue by following the issue guide (https://yihui.org/issue/), and link to this old issue if necessary.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 3, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants