# Explicit Figure element in Block #3177

Open
opened this issue Oct 23, 2016 · 50 comments
Open

# Explicit Figure element in Block#3177

opened this issue Oct 23, 2016 · 50 comments
Labels

### jgm commented Oct 23, 2016

 Currently we represent figures in the AST using this hack: a figure is an Image whose title attribute starts with fig: and which is by itself in a Para. Short of a full-featured figure environment in the AST, it would make sense to move to a less hacky representation: a Div with class figure containing the image (which need not have a title starting with fig:). This would involve changes to readers and writers. Indeed, if we did this, we could support figures containing multiple images, via explicit Divs.

### jgm commented Oct 23, 2016

 Another advantage is that attributes could be added explicitly to the Div. 
![my image](img.jpg){.imageclass}
 See #3094.

### hrehfeld commented Oct 24, 2016 • edited

 Seconded, I just spent an hour figuring out why multiple images in a paragraph don't create a figure. Is there any way to create a figure with multiple images right now? (I guess creating Rawblocks will work?) Relevant code is here? https://github.com/jgm/pandoc/blob/master/src/Text/Pandoc/Writers/HTML.hs#L450 Why is the match only for one image and not multiple ones in the first place?

### jgm commented Oct 25, 2016

 If multiple images were allowed, which one would form the figure's caption? (There is only one caption.) What would determine how the images are arrayed in the figure? In retrospect, some kind of more explicit syntax for figures would have been desirable, and maybe that's the direction we should move in.

### hrehfeld commented Oct 25, 2016 • edited

 Layout: Hm, I only use html and latex backends, but both of those handle multiple images in a figure in a reasonable way without extra specification. However, in latex IIRC it makes a difference if there is a SoftBreak between images (break vs. no break). IMHO it would be up to the writer/backend to break up figures if multiple images are not supported. Caption: None unless explicitely stated? That's legal in both html and latex iirc. However I believe Paras do not support extra data like attrs, so that a div or figure node would be easier.

### jgm commented Oct 25, 2016

 +++ Hauke Rehfeld [Oct 24 16 16:42 ]: Seconded, I just spent an hour figuring out why multiple images in a paragraph don't create a figure. Is there any way to create a figure right now (I guess creating Rawblocks will work?) You can paste the images together into one image, I suppose, or use a filter. Relevant code is here? [1]https://github.com/jgm/pandoc/blob/master/src/Text/Pandoc/Writers/HT ML.hs#L450 Why is the match only for one image and not multiple ones in the first place? Good question. I suppose that since I'm in a field where pictorial figures aren't used much, I didn't realize how common figures with multiple images and a single caption are. But how would it work to allow a paragraph with multiple images (and nothing else) to form a figure? From which image would the figure's caption be taken? What determines how the images are arranged in the figure (side by side, in a square, etc.)? Really we need a more explicit syntax for figures if this kind of thing is going to be allowed.
mentioned this issue Dec 5, 2016

### jgm commented Feb 26, 2017

 I think we need an explicit Block element for Figure.
added the label Feb 26, 2017

### mb21 commented Feb 26, 2017 • edited

 The question is whether this figure element should only contain images, or if it should be a general floating-container more analogous to the LaTeX \begin{figure} and HTML5 figure elements (emphasis added): Usually a 

### jgm commented Feb 26, 2017

 +++ Mauro Bieg [Feb 26 17 05:07 ]: If so, the figure element should contains a caption (multiple paragraphs allowed) and arbitrary block content: Figure Attr [Block] [Block] That's what I was thinking.
mentioned this issue Apr 16, 2017
added this to the pandoc 2.0 milestone Aug 15, 2017

### jgm commented Aug 20, 2017 • edited

 Development on figures branch for pandoc, pandoc-types.

### jgm commented Aug 20, 2017 • edited

 Thinking about about explicit Markdown syntaxes for figures. If we had a native syntax for divs, we could treat any div with a following caption as a figure: ;--- {#foo .right} ![my image](img.jpg){.imageclass} ![second image](img2.jpg) ;--- ^^ [This is the optional short caption.] This is the long caption. It can span multiple blocks. Syntax like footnotes. Subsequent paragraphs indented. We automatically treat a div as a figure if it is followed by a caption. Or is it too confusing if the caption comes outside the div?  Another possibility would be to have a special kind of marking for figures, like: !--- {#foo .right} ![my image](img.jpg){.imageclass} ![second image](img2.jpg) [This is the optional short caption.] This is the long caption. It can span multiple blocks. Syntax like footnotes. In this version, all the Para elements at the end of the structure are treated as the caption, so we don't need an explicit syntax to mark the caption. !---  I'm trying to avoid syntaxes that require you to use the word figure. I like the ^^ syntax for attaching captions; we might want to use this for tables as well (INS: and code blocks) if we use it for this.
changed the title Better handling of implicit figures Explicit Figure element in Block Aug 20, 2017

### TODO on figures branch on pandoc and pandoc-citeproc

• Finish updating writers to handle Figure
• RST
• Markdown
• LaTeX
• HTML
• Org/Blocks
• MediaWiki
• Get everything to compile
• Update tests
• Update ToJSON, FromJSON instance in pandoc-types to include Figure, Caption
• Update Arbitary in pandoc-types (it lacks Div, Figure, Span, probably others)
• Markdown syntax, new extension?
• Figure numbering and internal refs?

### jgm commented Aug 20, 2017 • edited

 Having second thoughts about the type now. I suspect that allowing ANY kind of block content inside a figure is not going to work well in many output formats. E.g. in docbook, only certain elements are allowed inside a figure element. http://tdg.docbook.org/tdg/4.5/figure.html Perhaps instead the contents should be limited to a list of images (or perhaps a list of lists of images, so they can be organized on lines? -- though it may be better to let the layout happen automatically, given width information). Perhaps listings could go in figures as well?

### jgm commented Aug 20, 2017

 I think I'm going to remove this from the 2.0 milestone as it still needs more thought.
removed this from the pandoc 2.0 milestone Aug 20, 2017

### mb21 commented Aug 21, 2017

 Having second thoughts about the type now. I suspect that allowing ANY kind of block content inside a figure is not going to work well in many output formats. I still think taking the most general approach in the AST makes sense. There are always going to be some formats that don't support certain things, but that should be handled by the respective writers and the AST design shouldn't be held up by those. It would be great to have a general block figure element to output to HTML/ePUB/LaTeX...

### mb21 commented Aug 21, 2017 • edited

 Concerning the caption syntax, I kind of prefer the second one, since it is clearly placed inside the figure/div element. A third variant: ;--- {#foo .right} ![my image](img.jpg){.imageclass} ![second image](img2.jpg) ;-- This is the long caption. It can span multiple blocks. Syntax like footnotes. ;-- This is the optional short caption. Since it's optional, it needs to go at the end in this syntax. ;--- 

### jgm commented Aug 22, 2017

 What kinds of things do people really put in figures, besides images?

### mb21 commented Aug 23, 2017 • edited

 Maybe the element I have in mind is more of a Float than a Figure. Again the MDN extract posted above: Usually a 

### jgm commented Aug 23, 2017

 Yes, this is the big conceptual issue to decide. Whether to have separate elements for (possibly floating) figures, tables, and listings with captions, or to make all of these non-floating and non-captioned, but add a container element that makes them floating and adds a caption.

### mb21 commented Aug 26, 2017

 I'm leaning currently towards the second option (general float/caption container). Use cases include floating more than just images (e.g. float two tables that share a caption), or having one figure with a caption, that contains subfigures (or images) with each having a caption, e.g: It's probably true that it gets a bit trickier to consider all cases in all writers, but it is a more flexible option.
mentioned this issue Oct 17, 2017
This was referenced Dec 25, 2017

### jgm commented Sep 11, 2018

 Btw, I'm not wild about autogenerating ids for these. I'd rather require people to specify ids manually. And this would be consistent with current Div syntax, which does require attributes.

### hrehfeld commented Sep 12, 2018

 I think you have most of the points down. The only thing I can add at the moment is: I'm not sure what pandoc's philosophy is here usually, but only supporting the common denominator between all formats makes pandoc a much less attractive product to convert between formats that you specifically choose for their feature set. If I'm choosing latex and html as the formats, I would definitely expect pandoc to be able to convert figure elements between the two. I'm frequently using pandoc's ast. An implicit figure is much harder to work with than an Explicit. It's the difference between node.classname is Figure and a bunch of nested node has child, child has caption, caption begins with "figure:", etc.

### hrehfeld commented Sep 12, 2018

 One more thought: maybe if would be nice to have some formal way of generating documentation on what actually gets lost in conversion between formats. Not sure if this is possible with code reflection and without a lot of manual work, but if you could do e.g.: pandoc conversion-loss -t latex -o odt and it would display a list of lossage in the conversion from latex to odt, it would make it much more transparent.

### mb21 commented Sep 12, 2018 • edited

 It's fairly rare to have a captioned equation. But numbered equations are common. Agreed, but If you google "equation caption", you'll see a lot of people asking for it, including a SO question with 40 upvotes (and google image search for some examples). Admittedly, if you google something you'll inevitably find it, so it may still be fringe use-case, but it does exist. I'm not wild about autogenerating ids for these. I'd rather require people to specify ids manually. I agree that's usually for the best, but eventually people will want to generate a toc-like list of figures in HTML, with links to the figures. So eventually someone will probably write a filter to autogenerate the ids of those figures that aren't referenced in the text. Just something to keep in mind... if people use fifteen different labels, we'd need fifteen numbering sequences, and we'd need to override a lot of the automatic LaTeX figure machinery, leading to unidiomatic LaTeX. My takeaway from the discussion in #813 was, that generating unidiomatic LaTeX is unfortunately not a good choice, because people need to submit it to journals etc. So I think we're stuck with having to do both: generate idiomatic LaTeX, and reimplement an equivalent logic for HTML etc. However, the fig: prefix in LaTeX is just a convention as well, so maybe the people that need idiomatic LaTeX should just stick to those conventions, even in their markdown. Anyway, the big question: Should we have figures that act as generic floats for all sorts of content, or should we restrict readers to fallback to divs with class figure, or even strip figures that don't contain 'canonical' content? While I like the idea of keeping things as simple as possible (e.g. in terms of permutations of possible inputs to consider), restricting the markdown input doesn't really solve the problem, since we still have to consider other inputs. For example, what should this output? pandoc -f html -t markdown ^D  Finally, about the AST question, I guess you're best qualified to decide, since you already started implementing this on the figures branch. I would imagine, that it's easier to pattern-match on Figure attr capt blk instead of Div attr ((Para (Image i)):capt). But yes, it would break backwards-compatibility. But maybe we could works towards pandoc 2.5, along with PageBreak and the new Table elements? I'm happy to contribute code once the design is decided.

### jgm commented Sep 12, 2018

 One more thought: maybe if would be nice to have some formal way of generating documentation on what actually gets lost in conversion between formats. Not sure if this is possible with code reflection and without a lot of manual work, but if you could do e.g.: pandoc conversion-loss -t latex -o odt and it would display a list of lossage in the conversion from latex to odt, it would make it much more transparent. If you use the --verbose option you should get loss warnings for most formats. If you use --log you can get this in a machine-readable JSON format.

### mb21 commented Sep 14, 2018

 Yet another syntax variant: ::: {} ![](gull.jpg) > A gull :::  Using the contents of the last blockquote in a div as the caption. Can include arbitrary block content in both content and caption. Obvious syntax and fallback for other markdown parsers, even though a blockquote is of course not semantically comparable to a caption. For the short caption, the quote should end in a span (or maybe don't require the span-attribute and maybe require it to be in its own paragraph?): ::: {} ![](gull.jpg) > A gull with a very long caption > > [A gull] ::: 

### lierdakil commented Sep 14, 2018

A div would be treated as a figure if it starts with a paragraph containing one or more images (and nothing else).

For my 2 cents, I'm not at all a fan of this idea, tbh. In my experience, explicit is almost always better than implicit, and it raises a question of "how do I make a proper div with an image that's not interpreted as a figure". Some sort of extension (kinda like implicit_figures) might work, e.g. impicit_figure_divs, so that "figure divs" would require an explicit figure class without it enabled, but that sounds very similar to what we're trying to avoid here, no? My vote here is for non-ambiguous syntax.

As for subfigures, I kinda like my approach taken in pandoc-crossref. Subfigures are a list of Para of Image (with optional SoftBreak or Space inbetween). So, f.ex.,

:::{#fig:subfigure}
![a](image-in-row-1-1.png)
![b](image-in-row-1-2.png)
![c](image-in-row-1-3.png)

![d](image-in-row-2-1.png)
![e](image-in-row-2-2.png)
![f](image-in-row-2-3.png)

Figure caption
:::

will be rendered in 3x2 grid kinda like this:

a b c
d e f

Figure caption

Line breaks and spaces are optional, this would be equivalent:

:::{#fig:subfigure}
![a](image-in-row-1-1.png) ![b](image-in-row-1-2.png)![c](image-in-row-1-3.png)

![d](image-in-row-2-1.png)![e](image-in-row-2-2.png)
![f](image-in-row-2-3.png)

Figure caption
:::

Note, however, that this syntax kinda only makes sense if figures are explicit in Markdown syntax, with none of that "if a Div contains X, then it's a figure" business. Otherwise, too much overlap for my taste.

If you go implicit figure divs route, I'd like to at least have an explicit marker for figure captions, that is, I'm not really a fan of using the first/last Para that's not an Image. Perhaps taking a page from current table caption syntax might work, requiring captions to have <word>: in the first paragraph (where <word> is any sequence of characters, including no characters, without spaces/breaks)? I.e.

:::
![](some-image.png)

: Caption
:::

Otherwise, it'd be very tricky to do something like

:::{.warning}
![](screenshot-snippet.png)

:::

### jgm commented Sep 14, 2018

 For my 2 cents, I'm not at all a fan of this idea, tbh. In my experience, explicit is almost always better than implicit, and it raises a question of "how do I make a proper div with an image that's not interpreted as a figure". Some sort of extension (kinda like implicit_figures) might work, e.g. impicit_figure_divs, so that "figure divs" would require an explicit figure class without it enabled, but that sounds very similar to what we're trying to avoid here, no? My vote here is for non-ambiguous syntax. In pandoc we've tried to avoid using English language words to mark things, which tells against using an explicit figure class. (A document in Chinese should not be strewn with latin characters.) My guess was that divs that start with a paragraph containing just images but aren't meant to big figures are rare enough that the implicit approach would work (together with a way to defeat it in rare cases, e.g. a nofigure class). This would be much like the current implicit_figures extension, which hasn't been a big problem from that point of view (paragraphs just containing an image being pretty rare). :::{.warning} ![](screenshot-snippet.png) If you see something like this on your screen, your computer is about to explode, RUN! :::  I'll concede that this is a good counterexample to my claim! As for subfigures, I kinda like my approach taken in pandoc-crossref. Subfigures are a list of Para of Image (with optional SoftBreak or Space inbetween). So, f.ex., ![a](image-in-row-1-1.png) ![b](image-in-row-1-2.png) ![c](image-in-row-1-3.png) ![d](image-in-row-2-1.png) ![e](image-in-row-2-2.png) ![f](image-in-row-2-3.png) Figure caption :::  will be rendered in 3x2 grid kinda like this: I like the grid idea and propose we adopt it in whatever we end up with. (Do you actually use a tabular to render this, or just let the images adjoin each other on the line?) I'm not really a fan of using the first/last Para that's not an Image. That's not exactly the proposal. Everything after the images part would be the caption. It can contain arbitrary block-level content, on this proposal. That may actually be a bit too liberal. For example, do we want to allow other captioned elements, like tables, in a caption? Probably not. But I can imagine lots of people who will want to have (non-captioned) tabular content inside a caption. One of the motivations for this issue is expanding what can go in a figure caption. As I see it, our options are: Go with the full implicit div approach, with some way of manually disabling it (nofigure class). Require a more explicit marking of the div, using some English (or other) language terms. This could be fairly unobtrusive, as with your #fig:, but this would still jump out in a Chinese text. Try to be cleverer about the implicit div approach, putting more restrictions on what the container looks like. For example, as @mb21 suggests, we could require that it start with images and end with a blockquote, which would be the caption. Or as I mentioned earlier, we could require an hrule to separate the image part and the caption.

### mb21 commented Sep 14, 2018

 If we use the dash in # my unnumbered title {-} as a precedent for "here comes an English word that shall not be spoken", we could do: ::: - something :::  Now, the question is: should - stand for .nofigure or .figure :S

### lierdakil commented Sep 14, 2018

 Do you actually use a tabular to render this, or just let the images adjoin each other on the line? Both, actually. There are switches (metadata variables) that control whether it's rendered as a table, or just adjoined images with line breaks. And it's a whole another story with LaTeX (long story short: subfloat from subfig package, and a mix of RawBlocks and RawInlines; it might be a good idea to use subcaption package instead) It [caption] can contain arbitrary block-level content, on this proposal. This... doesn't really make much sense to me, tbh. I struggle coming up with a reasonable example of a figure/float caption that would even consist of more than one paragraph, let alone contain tables or other block-level elements. But okay, maybe I'm just hung up on LaTeX limitations. As I see it, our options are ... Out of these three, I'm kinda leaning towards the last option, "blockquoted" caption in particular, since it looks the least ambiguous. That said, actual use might be somewhat cumbersome -- there would be lots of extraneous > which don't actually have any semantic meaning and are just there as a quirk of the syntax (which sounds rather bad if I put it this way I guess). It wouldn't be that bad for reasonably short captions though (1-2 paragraphs), and as I said, I can't imagine a reasonable use-case for something much longer than that. If we use the dash in # my unnumbered title {-} as a precedent for "here comes an English word that shall not be spoken", we could do Only I believe that should be ::: {-} something ::: for the sake of consistency? Now, the question is: should - stand for .nofigure or .figure :S My intuition would suggest that {-} disables something, so I would expect - standing for .nofigure. Maybe that's just me though.

### jgm commented Sep 14, 2018

 It [caption] can contain arbitrary block-level content, on this proposal. This... doesn't really make much sense to me, tbh. I struggle coming up with a reasonable example of a figure/float caption that would even consist of more than one paragraph, let alone contain tables or other block-level elements. But okay, maybe I'm just hung up on LaTeX limitations. See #4229 for one request for multiparagraph captions. As far as I can see, there's no LaTeX limitation preventing this (except that if you have multiple paragraphs, you must specify the optional short caption argument to \caption). Certainly it might be sensible to have a list in a caption, or a block quote. See also #1024 for a proposal for block-level content in table captions. If this posed a problem in multiple output formats, that could be a reason for disallowing it. But it seems possible in LaTeX, HTML, ... It's definitely worth making sure there's a strong reason for multiparagraph captions before we take that step. there would be lots of extraneous > which don't actually have any semantic meaning and are just there as a quirk of the syntax (which sounds rather bad if I put it this way I guess). Yes, I have the same reservation. The hrule proposal might be nicer, actually: ::: {#myfig} ![the image](img.jpg) ____ caption goes here :::  I'm not wild about the {-} idea. {-} is already used for unnumbered headers. And it's pretty cryptic what it's supposed to mean.

### mb21 commented Sep 15, 2018

 [block captions are] possible in LaTeX, HTML, ... That's enough of a reason to make the AST so, I think. About the hrule vs >: I really think both are fine. I agree that semantically, the hrule makes more sense. But for the most common use-case of one-paragraph captions, the > is less to type and takes up one line less. But if we keep the current implicit_figures extension around for the most common use-case, then we can err on the side of making things more explicit for more complex figures: then I would be totally fine with requiring the attribute with id, and using one more line for the hrule.

### lierdakil commented Sep 15, 2018

 But if we keep the current implicit_figures extension Please do, because backwards compatibility. Rewriting all those documents using a new figure syntax would be a huge pain. A side question: since as far as I understand the intention is to introduce a new AST element for figures specifically, why are we hung up on re-using existing syntax elements to define a new one? I mean, can't we invent a syntax for figures (or, more generally, "floats" in LaTeX terms) specifically?

### mb21 commented Sep 15, 2018

 can't we invent a syntax for figures (or, more generally, "floats" in LaTeX terms) specifically? We certainly could, but considering how long it took to agree on a native div syntax, the reasoning was to use something that resembles that, so that people don't have to learn yet another completely new syntax.

### jgm commented Sep 15, 2018

 Nikolay Yakimov writes: A side question: since as far as I understand the intention is to introduce a new AST element for figures specifically, why are we hung up on re-using existing syntax elements to define a new one? I mean, can't we invent a syntax for figures (or, more generally, "floats" in LaTeX terms) specifically? It's not decided to introduce a new AST element for figures. In fact, my current preference is still just to use regular Divs, in the same way we currently use regular Paras for implicit_figures. But this is one of the things that needs to be decided. It would also be possible to start out with regular Divs and switch to Caption later. The syntax issue is orthogonal to this. In principle, we could even have a special syntax for figures that produces a regular Div in the AST. But my preference at this point is not to introduce new syntax. One advantage to using Div syntax is that it will degrade nicely in processors that support the fenced Div syntax but not whatever we might come up with for figures. Anyway, this is another thing that should be decided. My thought in my original proposal above was this: we already have fenced divs, so we already have what it takes to fix most of the limitations of the current implicit_figures syntax: allowing multiple images in a figure, more complex captions, and attributes that go on the figure rather than the image itself. It would be quite easy to do this, and it wouldn't require the kind of large changes that would be needed if we modified the AST (not to mention backwards-compatibility issues with filters and software using pandoc as a library).

### lierdakil commented Sep 16, 2018

 It's not decided to introduce a new AST element for figures. Okay then, the AST change label on this issue confused me. The syntax issue is orthogonal to this. Well, certainly. Obviously, any syntax could be within reason parsed as any AST element, that's pretty much the meaning of A in AST. There's a catch to that though, in my experience, it's good to have at least some correspondence between AST and the syntax, to keep parser complexity reasonably low and yourself reasonably sane ^_^ While pondering this, I came up with a bit of a middle ground between reusing div syntax and coming up with a new one, that might be agreeable. So here's a quick proposal: We'd, generally, like to avoid ambiguity between figure divs and regular divs. Besides heuristics, classes seem like an obvious (and explicit) choice, but using english is discouraged for i18n reasons. But we don't really have to use alphanumerics for classes now, do we? So how about "figure divs" requiring ! class? (! because Markdown image syntax uses ! to differentiate from links -- seems like an obvious choice). Case 1: :::{#regulardiv} ![](picture.png) --- This is a regular div, despite starting with an image and containing
::: Case 2: :::! ![](picture.png) --- This is a figure div without an id (or possibly with automatic id?) ::: Case 3: :::{.! #figureId} ![](picture.png) --- This is a figure div with an id ::: Case 4: :::! {#figureId} ![](picture.png) --- This syntax doesn't really work as of Pandoc 2.2.1, but seems like an obvious extension of case 2 ::: IIRC, CSS doesn't really understand non-alphanumeric classes anyway, so ! class by itself wouldn't be too meaningful in most output formats, consequently it doesn't seem to shadow anything in terms of functionality. This syntax is also ambivalent wrt AST representation -- if down the line AST is changed to include explicit "float" elements, it's distinct enough as to not be considered "stealing" syntax from divs.

### jgm commented Sep 16, 2018

 Interesting idea. Currently pandoc doesn't accept .! as a class, but that could be changed. Still, I'd be worried about introducing problems by allowing classes like this. And the syntax is also sort of line-noisy. {.! #myfig} I suppose another approach would be to rely on the fact that we now have translations of 'Figure' into multiple languages (data/translations; see Text.Pandoc.Translations). In principle, then, we could allow something like this: {.Slika #myid} or {#Slika:myfig} I can see problems with this approach, though. It requires setting the language properly in metadata (or through the locale). Changing the language of the document would break figures. And we only support 50 or so languages.

### lierdakil commented Sep 17, 2018 • edited

 Actually, Pandoc allows ! class. Well, kind of: $pandoc --version pandoc 2.2.1 Compiled with pandoc-types 1.17.5.1, texmath 0.11.0.1, skylighting 0.7.2$ echo -e ':::!\ntest\n:::\n' | pandoc -t native [Div ("",["!"],[]) [Para [Str "test"]]]  It doesn't parse in the attribute list though (that is, inside {})
mentioned this issue Sep 27, 2018
mentioned this issue Oct 7, 2018
mentioned this issue Jan 6, 2019
mentioned this issue Feb 2, 2019
mentioned this issue Apr 18, 2019
mentioned this issue Jun 12, 2019
mentioned this issue Jun 14, 2019
mentioned this issue Jun 25, 2019
mentioned this issue Aug 21, 2019
mentioned this issue Aug 26, 2019
mentioned this issue Feb 13, 2020