Description
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(
"""
{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:
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
.