Image Style serialization

Hello all,

I’d like to discuss with you different proposal regarding the representation of the image styles in XWiki Syntax, and in particular when taking into account the figures.

As a reminder, an image style is a way to provide uniform styling across the images of a wiki by assigning them css classes.

Lat’s start with a simple example, [[image:Sandbox.WebHome@XWikiLogo.png||class="mystyle"]] produces the following html:

<img src="/xwiki/bin/download/Sandbox/WebHome/XWikiLogo.png?rev=1.1" 
     class="mystyle wikigeneratedid" 
     id="ISandbox.WebHome40XWikiLogo.png-4" 
     alt="XWikiLogo.png">

Then, we can define images with captions. For instance [[XWikiLogo>>image:Sandbox.WebHome@XWikiLogo.png||class="mystyle"]] produces the following html:

<figure class="image">
  <img src="/xwiki/bin/download/Sandbox/WebHome/XWikiLogo.png?rev=1.1" 
           class="mystyle wikigeneratedid" 
           id="ISandbox.WebHome40XWikiLogo.png-4"
           alt="XWikiLogo.png">
  <figcaption><p>XWikiLogo</p></figcaption>
</figure>

In this example, myclass is only attached to the classes of the img tag, but the figure tag is not “styled” with a class.

The problem is that, it is important to be able to also select the figures of a given style when defining the css.
To give a concrete example, let say that we want all the image to be surrounded by a border, and we want this border to wrap the caption too when it exists.
This is not possible without attaching a class to the figure tag.

Proposal 1

Explicitly add a css class on the figure:

(% class="mystyle-figure" %)
[[XWikiLogo>>image:Sandbox.WebHome@XWikiLogo.png||class="mystyle"]]

And the corresponding html:

<figure class="mystyle-figure image">
  <img src="/xwiki/bin/download/Sandbox/WebHome/XWikiLogo.png?rev=1.1"
           class="mystyle wikigeneratedid"
           id="ISandbox.WebHome40XWikiLogo.png-4"
           alt="XWikiLogo.png">
  <figcaption><p>XWikiLogo</p></figcaption>
</figure>
  • Proposal 1.1: same css class as the image (e.g., myfigure)
  • Proposal 1.2: same css class as the image, but with a suffix (e.g., myfigure-figure)
  • Proposal 1.3; another css class that can be configured through the image style UI

Proposal 2

Add a new parameter in the links syntax to attach a css class to the figure, for instance:
[[XWikiLogo>>image:Sandbox.WebHome@XWikiLogo.png||class="mystyle" figure-class="mystyle-figure"]] (producing the same html as Proposal 1).

Proposal 3

Reuse the css class attached to the image and attach them to the figure too, in this case [[XWikiLogo>>image:Sandbox.WebHome@XWikiLogo.png||class="mystyle"]] would produce.

<figure class="mystyle image">
  <img src="/xwiki/bin/download/Sandbox/WebHome/XWikiLogo.png?rev=1.1"
           class="mystyle wikigeneratedid"
           id="ISandbox.WebHome40XWikiLogo.png-4"
           alt="XWikiLogo.png">
  <figcaption><p>XWikiLogo</p></figcaption>
</figure>

Conclusion
I have small preference for Proposal 1 as I feel like it is the less “magic” of the 3 options, and also the one that does not require changes in rendering.
The main cons of Proposal 1 is that the class is duplicated.
I did not find scenarios where using different classes for the figure and the img was important, except for clarity.

WDYT?

PS: I have other questions to discuss regarding how to represent variation points allowed by the image style (e.g., image with a border, or with a specific alignment). But I’d like to have answer for that first.

Maybe what’s missing for context, is that we’d like to support the ability to support both figures and images using CSS styles. And it means that whenever a user uses the wysiwyg image dialog, picks a non-default style (we wouldn’t generate any explicit style markup for the default), and selects a caption, the generated wiki syntax will be:

(% class="mystyle" %)
[[XWikiLogo>>image:Sandbox.WebHome@XWikiLogo.png||class="mystyle"]]

This syntax is a bit on the heavy side and not easy for a wiki markup reader to understand what happens (he/she probably shouldn’t have to know that, when rendered in HTML there’s a figure element inserted around the image and that styling it requires a block level parameter).

The duplicated mystyle is also not great but I guess that could be solved by introducing 2 CSS class mappings in the new Image Style Application (not documented yet AFAIK). So that would give:

(% class="mystyle1" %)
[[XWikiLogo>>image:Sandbox.WebHome@XWikiLogo.png||class="mystyle2"]]

Ideally, from a wiki markup POV, since we use the same syntax for images with captions and without captions, the user shouldn’t need to know the impl details to pass a style. But I don’t have any great idea on how to achieve this…

One other solution could be to wrap the image/figure in a macro, for instance

{{style type='mystyle'}}
[[XWikiLogo>>image:Sandbox.WebHome@XWikiLogo.png]]
{{/style}}

And the style macro could either:

  • Produce a simple span with a class attribute
  • Transform the content of the macro to add the class to the images and figures

I’m just not sure how well we can integrate that in CKEditor.

In principle, I find that interesting for several reasons:

  1. It leads to something very legible in wiki markup
  2. It doesn’t expose “internal” implementation and/or magic values such as “class” or others
  3. It hides the difference between figure and images for the user

The Image Style Application would provide this macro for easy application of styles to images. Either {{style}} or something specific to images like {{imageStyle}}.

Re CK, the issue is that it requires a special plugin handling for this macro I guess to convert back and forth between HTML and wiki syntax.

In additional to the special plugin handling, an other issue I can think of is. What happens if the content is inconsistent? For instance, no images, several images, an image + some other content?

Not sure I understand. Each macro defines what its content supports.

e.g. if you use the gallery macro but don’t put images in it, it won’t display images.

So that style macro could support for example a single content corresponding to an ImageBlock.

For me proposal 3 is the best. If the user wants to style a particular image then they should simply write:

[[XWikiLogo>>image:Sandbox.WebHome@XWikiLogo.png||class="mystyle"]]

no matter whether the image is alone in a paragraph or inside a paragraph’s text. The fact that the generated HTML uses a figure element or not is more of an implementation detail. The HTML renderer should put the specified CSS class both on the img tag and on the figure tag. I’m also fine to set on the figure tag a different CSS class, say mystyle-figure as in proposal 1.1, but to keep it simple I think we can use the same CSS class. What’s important for me is that this CSS class is added automatically and that the way to specify the CSS class in wiki syntax is the same no matter the context (standalone or inline).

I don’t see the point in adding a wiki macro for something that you can already do with simple wiki syntax.

Thanks,
Marius

Definitely.

I’m far fro sure that this would work in all cases. @mleduc as a POC, could you provide the CSS to use to have the caption displayed just under the image and using the same width as the image?

That would be a bit confusing for the user since there’s would be 2 ways to set the class attribute without understanding what the differences are (and it would be hard to explain).

I think an additional caption-style (or style-caption) as in proposal 2 could work (inside the link) as it would be a style applied only when there’s a caption and that wouldn’t expose any implementation detail.

It’s not simple wiki syntax. It’s actually more complicated than using a macro. Now I agree that it would ne nicer if we could find a simple way to do it with wiki syntax and that doesn’t expose the internal implementation and ideally that doesn’t use parameters ((% ... %)) since that makes it quite complex.

While this proposal looks clean at first, it comes with some technical difficulties.

Let say you have [[XWikiLogo>>image:Sandbox.WebHome@XWikiLogo.png||class="mystyle someotherclass"]]
How do you know with class to apply on the figure, and which one to apply on the img?
Of course we could choose to apply all the classes on both but it could lead to some style breaking.
In addition, this requires some change in the rendering code.

The solution for this is to set the same width on the figure and the image, which is possible using CSS only if the figure has an identifiable class (i.e., the image style class).
Note that this does not work with the width defined in the image dialog, as it is only applied on the image.

[[The sandbox is a part of your wiki that you can freely modify. It's meant to let you practice editing. You will discover how page editing works and create new pages. Simply click on Edit to get started!>>image:XWikiLogo2.png||width="100"]]

Result in the html below, where the width is only applied on the img and not the figure.

<figure class="image">
  <img src="/xwiki/bin/download/Sandbox/WebHome/XWikiLogo2.png?width=100&amp;rev=1.1" id="IXWikiLogo2.png-1" class="wikigeneratedid" alt="XWikiLogo2.png" width="100">
  <figcaption>
    <p>The sandbox is a part of your wiki that you can freely modify. It's meant to let you practice editing. You will discover how page editing works and create new pages. Simply click on Edit to get started!</p>
  </figcaption>
</figure>

Note that @MichaelHamann proposed the following css

figure.image {
  display: inline-table;
}

figure.image figcaption {
  display: table-caption;
  caption-side: bottom;
}

But, quoting him:

This has the following side effects:

  • The caption is always displayed below the image regardless where it is in the source.
  • No possibility anymore to set a border or background color to the figure including the caption (the caption will be excluded from it).

Actually, a parameter that does not mention ‘class’, but use ‘style’ instead could be better:

[[XWikiLogo>>image:Sandbox.WebHome@XWikiLogo.png||class="some-other-class" style="mystyleid"]]

Then we can choose to :

  • use the class attached to the style both the image and the figure
  • derive a special class for the figure ${cssclass}-figure
  • add a new property to the image style XClass with the css class for the figure

You are aware that this would make it impossible to specify custom CSS styles on images as they cannot be represented in XWiki syntax anymore? How would you render an image with style="border: 1px solid red;" to XWiki syntax? If you want something custom instead of a class, I would rather propose to use a data-attribute and then define CSS styles based on this data-attribute instead of the class (otherwise you have the same problem again in the HTML parser: which classes are image styles and should be transformed into the custom attribute?).

To me, it is not just an implementation detail that HTML uses a figure element, as the XDOM also contains a figure block if you use this syntax - I didn’t want to introduce yet another way how to represent a captioned image in the XDOM but instead used the existing and straightforward one. It is more an implementation detail of the XWiki syntax that we represent figures with just an image as content as the image syntax.

From a syntax specification point of view, what we have as captioned image syntax is a paragraph that contains a single image. Both the paragraph and the image support parameters. It seems natural to me that the parameters of the paragraph are applied to the figure while the parameters of the image are just applied to the image itself. If we now decide that certain parameters on the image should influence the figure, this seems like quite a hack in XWiki rendering. On the other hand, applying all parameters to the figure (only) doesn’t make sense, either - for example, a width attribute should be on the image to specify its width, on the figure it would be a legacy attribute that should be replaced by CSS. Also, where should this hack happen? On the way from/to XWiki syntax such that the attributes are already on the FigureBlock in the XDOM?

As apparently some of you don’t like the paragraph parameters: What about storing all attributes of the figure as figure-XXX, where XXX is the original attribute name, on the image and putting these attributes back on the figure block (merged with the paragraph attributes, if there should be any) when parsing XWiki syntax? Then you could use

[[XWikiLogo>>image:Sandbox.WebHome@XWikiLogo.png||figure-class="mystyle"]]

As there aren’t any HTML attributes starting with figure-, we can be sure that this won’t conflict with existing attributes on the image. Note that this prefix would only exist in XWiki syntax, not in the XDOM or the HTML code (where it would be invalid). Of course this proposal could also be combined with a data-attribute instead of a class. We would need to decide what to do if such an attribute is used on an image without caption - should it be ignored or should we just keep the attribute on the image (without the prefix)?

This is essentially proposal 2 from what I see. However IMO the problem remains: users have no idea what a figure is. This is an implementation detail. For example if you render to LaTeX there’s no such “figure”. Even if the XDOM has a figure event, this is still implementation and users are not supposed to know nor understand the XDOM structure. All they see is the syntax.

What they understand is whether the image has a caption or not, which is why I was suggesting caption-style above (but I admit it’s not perfect either since it’s not easy to understand what a caption style means).

This is also why I also liked the idea of using a macro (whether it’s {{figure}} or {{style}}). It exposes the concept of figure or style to the syntax. If we can do with a pure syntax that is natural, all the better but right now the proposals don’t seem very natural to me (since we’re reusing the same syntax for 2 different structures - with and without caption). However, I agree that the best is probably proposal 2 so far.

This is not true, in LaTeX there is \begin{figure} which we generate on a figure event, so I’m quite sure LaTeX users are aware what a figure is. Any syntax that doesn’t support figures will loose the image caption, for example this is the case with Markdown at the moment (I explicitly disabled caption support in CKEditor when the syntax is Markdown).

When I implemented caption support, we decided against using a macro even though I would have preferred that option. I don’t understand why you are suddenly suggesting we should use a macro now for figures.

Since we seems to converge to a variant of Proposal 2 where the figure/caption specific parameters have a specific prefix, I’ll try to give some examples (with the figure caption, but that can be changed).

Using the class attribute

  • Image with style [[image:Sandbox.WebHome@XWikiLogo.png||class="mystyle"]]
  • Image with caption and style(s) [[Caption>>image:Sandbox.WebHome@XWikiLogo.png||class="mystyle" figure-class="mystyle]] Note: we can opt of two distinct classes for the image and caption

Using data attributes (I couldn’t find the discussion regarding the data-* naming convention)

  • Image with style [[image:Sandbox.WebHome@XWikiLogo.png||data-ckeditor-style="mystyle"]]
  • Image with caption and style(s) [[Caption>>image:Sandbox.WebHome@XWikiLogo.png||data-ckeditor-style="mystyle" figure-data-ckeditor-style="mystyle]] Note: we can opt of two distinct classes for the image and caption

I tend to prefer “data attributes” styles as it does not conflict with use of classes which feels too generic for what we want to do. Afaik using data attributes does not limit us when expressing styles in CSS (expect maybe for slightly longer selectors).

WDYT?

To be more precise, I propose to use the following set of image style data attributes:

  • data-ckeditor-image-style: the identifier of the style (side note. If we use this solution, configuring a class in the image style is not required anymore)
  • figure-data-ckeditor-image-style: the same value as data-ckeditor-image-style, only inserted on images with a caption.
  • data-ckeditor-image-style-border: this attribute is present when the style must have a border
  • data-ckeditor-image-style-alignement: left|center|right the desired alignment of the image
  • data-ckeditor-image-style-textWrap: this attribute is present when this image should wrap around the text

I don’t understand what you mean by “2 ways”. There’s a single way, using the class parameter on the image syntax.

What style breaking are you referring to? Classes are meant to be duplicated, to appear multiple times, even on different HTML elements. There’s no rule preventing us from using the same class on the figure and img elements. And we can easily distinguish between them using a proper CSS selector figure.my-class vs. img.my-class.

Is this a problem? Should the end user care about this? I still think proposal 3 is the best for the end user, i.e the content writer. The developer writing the CSS for the image style can handle easily the CSS as long as there is a CSS class on the image and figure, even if it’s the same.

I was referring to existing selector that are just using the class name alone, but I agree the risk of breaking something are low.

+1

Note that I have created a vote to agree on an option: Image Style serialization class vs data attribute