pandoc icon indicating copy to clipboard operation
pandoc copied to clipboard

Link attributes on implicit figures

Open iandol opened this issue 7 years ago • 18 comments

Hi, figures in their own paragraph get marked up to become implicit figures wrapped in a <figure> element. Images can also receive link attributes. When inline it makes sense to apply the atribute to the <img>, but I don't think this assumption is ideal for implicit figures:

>  pandoc

![Fig. 1](fig.png){.nofloat}

<figure>
<img src="fig.png" alt="Fig. 1" class="nofloat" /><figcaption>Fig. 1</figcaption>
</figure>

I think it would be more useful to treat the containing <figure> itself as the target for the attributes for implicit figures:

<figure class="nofloat" >
<img src="fig.png" alt="Fig. 1" /><figcaption>Fig. 1</figcaption>
</figure>

The implicit figure should treat image and caption as one "unit".

iandol avatar Sep 18 '17 05:09 iandol

I see how this might be handy for the class and id attributes, but some attributes like e.g. width and height should probably continue to go in the img tag...

mb21 avatar Sep 18 '17 13:09 mb21

Yes, the #id and .class are all that really should be applied to the implicit <figure>.

One could be to apply at least the class to BOTH <img> and <figure> and then use CSS rules to override behaviour for each element even though they have the same class.

If there was a parent selector in CSS we could also target a <figure> that was the parent a img.class but this is not possible I think...

iandol avatar Sep 18 '17 14:09 iandol

Or maybe ![](){.myclass} should be converted to:

<figure class="myclass-figure">
  <img class="myclass">
</figure>

mb21 avatar Sep 21 '17 14:09 mb21

That is a neat solution!

iandol avatar Sep 22 '17 05:09 iandol

I don't think an image class/id is necessary. The image can be targetted using css as follows:

figure.myclass > img

This keeps things simpler.

I am interested in having this feature for use with the pandoc-fignos/eqnos/tablenos filters.

tomduck avatar Dec 17 '17 16:12 tomduck

@tomduck that is how it probably should have been from the beginning but I think doing that now would wreak havoc in many documents.

@mb21 would you accept a PR adding a class to the figure with "Figure" appended to the given class name?

madgen avatar Jan 16 '18 11:01 madgen

@madgen, I still think that approach would work for us, but @jgm merges pull request.

P.S. In light of https://github.com/jgm/pandoc/pull/4009 it should probably be myclass-figure (i.e. append -figure)

mb21 avatar Jan 16 '18 11:01 mb21

The proposed solution handles class but not id. What about id?

I find the -figure suffixed classes a bit inelegant. I'd rather move all the classes and the id to the figure, but I'm worried that this would break things that work now.

jgm avatar Jan 17 '18 17:01 jgm

@jgm I agree it is inelegant but sadly it certainly would break existing documents. I can amend #4269 to behave the same way with IDs if you like?

madgen avatar Jan 17 '18 17:01 madgen

Meanwhile for others struggling with this, here's an ugly JS workaround based on @mb21's solution to the problem.

var figures =
  Array.prototype.slice.call(document.getElementsByClassName("figure"),0)
  .concat(
    Array.prototype.slice.call(document.getElementsByTagName("figure"),0));

for (var i = 0; i < figures.length; i++) {
  var figure = figures[i];
  var imgs = figure.getElementsByTagName("img");
  if (imgs.length > 0) {
    classes = imgs[0].classList;
    for (var j = 0; j < classes.length; j++) {
      figure.classList.add(classes[j] + "-figure");
    }
  }
}

madgen avatar Jan 17 '18 18:01 madgen

I find the -figure suffixed classes a bit inelegant. I'd rather move all the classes and the id to the figure, but I'm worried that this would break things that work now.

I'm afraid those are the only two options that come to my mind.

mb21 avatar Mar 10 '18 18:03 mb21

Hi, I thought I could work around the issue using a small filter but the problem (as far as I understand) was that there is no placeholder for such information inside Image.

Though the output contains figure and figcaption, the native data is Image and there is no placeholder for the class data to move into.

I don't know much about the internals but is it possible to have kind of "container attribute" field or similar inside Image data structure so that it ensures backward functionality as well as providing some extensibility?

With a bit of additional field, the following command may be able to put hello class to there.(no loss of information!)

pandoc -f html -t native
<figure class="hello"><img src="foo.png"><figcaption>bar</figcaption></figure>
[Para [Image ("",[],[]) [Str "bar"] ("foo.png","fig:")]] --> today
[Para [Image ("",[],[], ["hello"]) [Str "bar"] ("foo.png","fig:")]] --> with modification 

In reverse scenario, pandoc can still push those information to img element as usual(to keep the behavior) and a small filter can move that information to its intended place if necessary. The following is just an example. (probably, the actual implementation would be different)

pandoc -f markdown -t native
![](){.hello}
[Para [Image ("",["hello"],[]) [] ("","")]] <-- today
[Para [Image ("",["hello"],[], []) [] ("","")]] <-- with modification, a filter can move that to new location like below
[Para [Image ("",[],[], ["hello"]) [] ("","")]]

I started using Pandoc recently for epub3 generation and it gives me a lot of fun and pain :) This is my first comment and please pardon my showing gratitude in issue thread.

Thank you @jgm. My highest respect to you.

Regards,

minsu avatar Jan 06 '19 04:01 minsu

@minsu - when we get around to adding an explicit Figure element (#3177), this issue will go away. That's the right AST change to solve the problem. In the mean time, one must use ~~filters and the like...~~ (EDIT: of course you're right, filters don't really help).

EDIT: a better workaround is to use a fenced div.

::: {.figclass}
![my caption](img.jpg){.imgclass}
:::

This will give you (in epub/html)

<div class="figclass">
<figure>
<img class="imgclass"...

and you can use CSS .figclass figure to style the figure.

jgm avatar Jan 06 '19 06:01 jgm

@jgm, Thanks for your suggestions.

Just ended up with regex hacks on xhtmls and rezipping the files.(A Korean ebook to be published on 14th. Pandoc rocks.) Fenced divs seem Swiss army knives for sure and I didn't know that I could put markdown inside(!). Great~

Best,

minsu avatar Jan 06 '19 07:01 minsu

After reading relevant threads and having used Pandoc for epub3 generation, I think having a separate Figure element won't solve the problem clearly. Here is my thought about the situation and 2-cent proposal to solve this problem and others without adding Figure or similar.

background

First of all, the intention of attaching attributes to the markdown syntax is vague and I think it is reasonable to attach those attributes to img as before.

Also, though having a separate element per necessity is of some use, but on going trend is custom element for better javascript control and custom presentation. Most markup languages don't support this custom element trend. and the following proposal may turn out to serve various cases.

add custom element designation to fenced divs

Fenced divs are .. just divs but I think it would be great if we can specify the element itself (default is div). Even for EPUB3, there are various recommendations that specify exact elements for specific purposes. So how about adding one more syntax to the {}? As far as I understand the most basic text pattern wasn't assigned yet and it is just "letters" without #, ., =. Here is an example for the figure case:

::::: {figure .class1 .class2 attr1=val1}
![hello.jpg](Hello){.imgcls}
::: {figcaption} 
Fig.1 Hello Image
:::
:::::

this translates into (thanks to nested divs!)

<figure class="class1 class2" attr=val1>
  <img class="imgcls" src="hello.jpg" alt="Hello">
  <figcaption>Fig. 1 Hello Image</figcaption>
</figure>

I understand that this may be too much verbosity but this may open great opportunity to filters and those who use Pandoc for precise HTML construction(not only the presentation but the details of structure and elements) Also, we don't have to concern about figure with markdown image markup. I think the actual problem was due to translating images into figure blocks, which is nice but not consistent.

EDIT. For example, EPUB3 recommends to put short description in alt and to put a detailed description in figcaption. Also for Aria accessibility, it is also recommended to role in img element and to blank alt if the image itself is not important. In these various cases, simple divs don't help much.

Best,

Minsu

minsu avatar Jan 07 '19 10:01 minsu

@minsu You present an alternative proposal, but you don't say why you think a Figure element in the AST would solve the problem. (EDIT: a Figure element could be rendered to HTML in exactly the way you describe above, and the role attribute could even be added.)

The alternative proposal is nice in many ways. One drawback is that it requires the use of English words (figure, figcaption), which is something we've tried to avoid in designing pandoc's syntax. Other writers would also have to be taught what to do with these words.

jgm avatar Jan 07 '19 23:01 jgm

@jgm First of all, sorry about my unclear proposal that may have confused you.

My proposal is not specific to Figure element but to change "fenced divs" to "custom element defaulting to div" element. It is not specific to figure element but is more general mechanism for custom element. So, in summary:

  • No Figure AST element for ![](){} markup.
  • Keep {} attributes to img element as before. (no sudden change of interpretation)
  • Extend fenced divs to let users designate specific element including custom element if div is not what he/she wants.
  • Even for EPUB3 conversion, the default behavior is not to have figure container automatically but it faithfully converts to img element and attach all properties to it.
  • No English word learning barrier involved. I guess.

This will incur a few drawbacks but may open good opportunity for filters. If applied correctly, this generic Div AST element may be more widely used in handling wrapping scenarios as well like automatically adding Div element if necessary. For example, even if fenced divs are not used in figure issue, Pandoc may be able to wrap it with generic Div element with element designation of figure and putting another Div element of figcaption that will translate into figure, figcaption element in EPUB3 generation accordingly. Also, converting from HTML, if unknown element is met, Pandoc may create this generic Div element with that specific element name with all the supplied attributes in it.

for example, Instead of:

pandoc -f html -t native
<address class="hello">Hi</address>
[Plain [Str "Hi"]]

this can be translated into:

pandoc -f html -t native
<address class="hello">Hi</address>
[Div [Str "Hi"] ..["hello"] ... ['address']] <-- `hello`, `address`are saved somewhere.

Regards,

minsu avatar Jan 08 '19 04:01 minsu

With the new CSS :has pseudo-class it's possible to target the parent element like the following:

Markdown

![Fig. 1](fig.png){.nofloat}

HTML

<figure>
<img src="fig.png" alt="Fig. 1" class="nofloat"/><figcaption>Fig. 1</figcaption>
</figure>

CSS

figure:has(img.nofloat) {
  /* Styles for <figure> with an <img class="nofloat"> inside */
}

jpesce avatar Mar 09 '24 14:03 jpesce