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

Attributes Not Properly Applied to Images #642

Open
solonovamax opened this issue Dec 24, 2024 · 0 comments
Open

Attributes Not Properly Applied to Images #642

solonovamax opened this issue Dec 24, 2024 · 0 comments

Comments

@solonovamax
Copy link

Describe the Bug

When using the Attributes extension, attributes cannot be applied to an img tag, instead they are always applied to the parent tag.

Reproducing

Note: code here is in kotlin as that's what my project is in and it's easier to write. It is decently trivial to translate it back to java.

val options = MutableDataSet()

options[Parser.EXTENSIONS] = listOf(
    AttributesExtension.create(),
)

val parser = Parser.builder(flexmarkOptions).build()
val htmlRenderer = HtmlRenderer.builder(flexmarkOptions).build()

@Language("Markdown")
val document = parser.parse(
    """
        ![image](/my-image.png){class="my-class"}
    """.trimIndent()
)

val renderedResult = renderer.render(document)

println(renderedResult)

Expected Result

<p>
    <img src="/my-image.png" alt="image" class="my-class">
</p>
<p>
    <a href="/my-link" class="my-class">link</a>
</p>

Actual Result

<p class="my-class">
    <img src="/my-image.png" alt="image">
</p>
<p>
    <a href="/my-link" class="my-class">link</a>
</p>

Notice how it still adds the class to the <a> tag as expected, however it is not added to the <img> tag as expected.

Additional Context

I have determined exactly what is causing the bug, it is particular piece of code right here in AttributesNodePostProcessor.java:

} else {
if ((!myOptions.assignTextAttributes && (previous instanceof Text || previous instanceof TextBase)) || previous.getEndOffset() < attributesNode.getStartOffset()) {
// either previous is text and no text attributes or not attached to the previous node

The issue has to do with the comparison between previous.getEndOffset() and attributesNode.getStartOffset(). In image tags, attributesNode.getStartOffset() is always greater than previous.getEndOffset(), which then causes it to always be true.

Here is a fix that I've implemented in my own project in the meantime:

val endOffset = previous.endOffset
val startOffset = attributesNode.startOffset - if (previous is Image || previous is ResizableImage) 1 else 0
if ((!options.assignTextAttributes && (previous is Text || previous is TextBase)) || endOffset < startOffset) {
    // ...

in java, you would do

int endOffset = previous.getEndOffset();
int startOffset = attributesNode.getStartOffset() - (previous instanceof Image || previous instanceof ResizableImage ? 1 : 0);
if ((!myOptions.assignTextAttributes && (previous instanceof Text || previous instanceof TextBase)) || endOffset < startOffset) {
    // ...

I'm checking if it's an instance of either Image or ResizableImage (to support the Resizable Image extension)

This is also likely an issue with the Media Tags extension, however I have not tested it. If it is, you would fix this by also checking if it's an instance of AbstractMediaLink.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant