lierdakil / pandoc-crossref

Pandoc filter for cross-references
https://lierdakil.github.io/pandoc-crossref/
GNU General Public License v2.0
953 stars 77 forks source link

Subfigures side-by-side without latex #306

Open widlarizer opened 3 years ago

widlarizer commented 3 years ago

I'd like to have two subfigures side-by-side. I'm using the pandoc-crossref filter method of subfigures. I tried turning them into a subsubfigure, and also the column layout method as described in https://bookdown.org/yihui/rmarkdown-cookbook/multi-column.html , but neither worked. I have been informed in the pandoc-discuss mailing list, that output-specific solutions exist in latex and CSS, and I think generic features like this should be available through (maybe extended) markdown on its own. Does a solution exist? Should it be implemented?

lierdakil commented 3 years ago

Workarounds are very format-specific. The least format-specific workaround is subfigGrid option. See http://lierdakil.github.io/pandoc-crossref/#subfigure-grid. It may still produce questionable results in many output formats though, but last time I checked it seemed to work with html and docx.

widlarizer commented 3 years ago

My bad for not being clear, I wanted to have two subfigure grids next to each other, and I can't nest subfigure grids, which I have tried. This is what I wanted to achieve, to make a simulation report use available space efficiently: image

lierdakil commented 3 years ago

Ah, I see. Sorry for misunderstanding. I'll be honest, I would just make a single picture with multiple graphs and put it in as a single figure at this point. The workaround I can suggest at the moment is to manually typeset subfigures in a grid table, e.g.

+----------------------------------------------+-------------------------------------+
|<div id="fig:coolFig">                        |<div id="fig:otherfig">              |
|![caption a](coolfiga.png){#fig:cfa width=30%}|![caption d](coolfigd.png){#fig:cfd} |
|                                              |                                     |
|![caption b](coolfigb.png){#fig:cfb width=60%}|![caption e](coolfige.png){#fig:cfe} |
|                                              |                                     |
|![caption c](coolfigb.png){#fig:cfc width=10%}|![caption f](coolfigf.png){#fig:cff} |
|                                              |                                     |
|Cool figure!                                  |Other figure!                        |
|</div>                                        |</div>                               |
+----------------------------------------------+-------------------------------------+

This is however rather tedious and error-prone. If you're targeting HTML specifically, you could instead opt to use pandoc's column layout:

:::columns
:::{.column width=50%}
<div id="fig:coolFig">
![caption a](coolfiga.png){#fig:cfa width=30%}

![caption b](coolfigb.png){#fig:cfb width=60%}

![caption c](coolfigb.png){#fig:cfc width=10%}

Cool figure!
</div>
:::
:::{.column width=50%}
<div id="fig:otherfig">
![caption d](coolfigd.png){#fig:cfd}

![caption e](coolfige.png){#fig:cfe}

![caption f](coolfigf.png){#fig:cff}

Other figure!
</div>
:::
:::

this only works with HTML with the default template (because it has the necessary CSS) -- but with HTML it should be easy to hack something together with a non-default template as well.

Finally, I think we can try to turn (2) into (1) with a filter. Let's see...

local function width(div)
  local s = div.attributes.width
  return pandoc.text.sub(s, 1, pandoc.text.len(s)-1)/100
end

local function cell(cont)
  return cont.content
end

local function align(cont)
  return pandoc.AlignDefault
end

function Div(el)
  if el.classes:includes("columns") then
    local row = el.content:map(cell)
    local widths = el.content:map(width)
    local aligns = el.content:map(align)
    local tbl = pandoc.SimpleTable({},aligns,widths,{},{row})
    return pandoc.utils.from_simple_table(tbl)
  end
end

this assumes a recent pandoc release.

EDIT: to be clear, it's a lua filter, save it as somefilename.lua and run with pandoc -L somefilename.lua -F pandoc-crossref ...

widlarizer commented 3 years ago

Sadly, I'm doing things that require direct LaTeX, and my output format is PDF, but I still think we should try to unify the pandoc syntax. If line ending escaped variables worked, it would be easy to use and generic. Sadly, this doesn't work with pandoc-mustache:

---
mustache: ./figs.yaml
header-includes:
    \usepackage{siunitx}
---
+-----------+------------+
|{{leftfig}}|{{rightfig}}|
+-----------+------------+

figs.yaml:

leftfig: "<div id=\"fig:spectra\">
  ![před průchodem SMF](podklady/2/spec_source.PNG){#fig:spectraa width=40%}
  ![po průchodu SMF](podklady/2/spec_no_comp.PNG){#fig:spectrab width=40%}

  ![po průchodu DCF, pak SMF](podklady/2/spec_pre_comp.PNG){#fig:spectrac width=40%}
  ![po průchodu SMF, pak DCF](podklady/2/spec_post_comp.PNG){#fig:spectrad width=40%}

  ![po průchodu Bragg.\ filtrem](podklady/2/spec_bragg_pre_comp.PNG){#fig:spectrae width=40%}
  ![po průchodu Bragg.\ filtrem](podklady/2/spec_bragg_post_comp.PNG){#fig:spectraf width=40%}

  Optická spektra
  </div>"
rightfig: "<div id=\"fig:eye\">
  <!-- ![před průchodem SMF](podklady/2/eye_source.PNG){#fig:eyea width=25%} -->
  ![po průchodu SMF](podklady/2/eye_no.PNG){#fig:eyeb width=40%}

  ![po průchodu DCF, pak SMF](podklady/2/eye_pre.PNG){#fig:eyec width=40%}
  ![po průchodu SMF, pak DCF](podklady/2/eye_post.PNG){#fig:eyed width=40%}

  ![po průchodu Bragg.\ filtrem, DCF, pak SMF](podklady/2/eye_bragg_pre.PNG){#fig:eyee width=40%}
  ![po průchodu Bragg.\ filtrem, SMF, pak DCF](podklady/2/eye_bragg_post.PNG){#fig:eyef width=40%}

  Diagramy oka
  </div>"

It doesn't throw an error, but it doesn't render the crossref subfigures. It also messes up the unicode. image Any ideas for making this work? Ran with pandoc .\mustache.md --filter pandoc-mustache --filter pandoc-crossref -o mustache.pdf

lierdakil commented 3 years ago

From what I see of the output, yaml contents isn't parsed as Markdown. But that's beside the point.

I didn't realize you're targeting LaTeX ("without latex" confused me). With LaTeX this workaround won't work at all because of some unfortunate interactions between how pandoc converts tables to LaTeX and how pandoc-crossref handles subfigures (TL;DR, floats inside minipages don't -- can't -- work, and that's exactly what subfigures in a table is). It is perhaps possible to hack around that somehow, but your best bet at the moment is to just break out into raw LaTeX.

widlarizer commented 3 years ago

Well, that's a bit disappointing, I like pandoc and I hoped I could abstract things away more. Anyway, thank you for your time. Should I close the issue or leave it sticking around as a proposed feature?