Skip to content

Commit bdcf366

Browse files
committed
Merge pull request #48 from atlassian/issue-31-attribute-provider-images
Make AttributeProvider work for Image nodes (#31)
2 parents b1cb623 + 86d8efb commit bdcf366

3 files changed

Lines changed: 75 additions & 38 deletions

File tree

commonmark/src/main/java/org/commonmark/html/HtmlRenderer.java

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -304,20 +304,20 @@ public void visit(OrderedList orderedList) {
304304

305305
@Override
306306
public void visit(Image image) {
307-
if (html.isTagAllowed()) {
308-
String url = optionallyPercentEncodeUrl(image.getDestination());
309-
html.raw("<img src=\"" + escape(url, true) +
310-
"\" alt=\"");
311-
}
312-
html.disableTags();
313-
visitChildren(image);
314-
html.enableTags();
315-
if (html.isTagAllowed()) {
316-
if (image.getTitle() != null) {
317-
html.raw("\" title=\"" + escape(image.getTitle(), true));
318-
}
319-
html.raw("\" />");
307+
String url = optionallyPercentEncodeUrl(image.getDestination());
308+
309+
AltTextVisitor altTextVisitor = new AltTextVisitor();
310+
image.accept(altTextVisitor);
311+
String altText = altTextVisitor.getAltText();
312+
313+
Map<String, String> attrs = new LinkedHashMap<>();
314+
attrs.put("src", url);
315+
attrs.put("alt", altText);
316+
if (image.getTitle() != null) {
317+
attrs.put("title", image.getTitle());
320318
}
319+
320+
html.tag("img", getAttrs(image, attrs), true);
321321
}
322322

323323
@Override
@@ -434,4 +434,28 @@ private void setCustomAttributes(Node node, Map<String, String> attrs) {
434434
}
435435
}
436436
}
437+
438+
private static class AltTextVisitor extends AbstractVisitor {
439+
440+
private final StringBuilder sb = new StringBuilder();
441+
442+
String getAltText() {
443+
return sb.toString();
444+
}
445+
446+
@Override
447+
public void visit(Text text) {
448+
sb.append(text.getLiteral());
449+
}
450+
451+
@Override
452+
public void visit(SoftLineBreak softLineBreak) {
453+
sb.append('\n');
454+
}
455+
456+
@Override
457+
public void visit(HardLineBreak hardLineBreak) {
458+
sb.append('\n');
459+
}
460+
}
437461
}

commonmark/src/main/java/org/commonmark/html/HtmlWriter.java

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,20 @@
55
import java.io.IOException;
66
import java.util.Collections;
77
import java.util.Map;
8-
import java.util.regex.Pattern;
98

109
public class HtmlWriter {
1110

1211
private static final Map<String, String> NO_ATTRIBUTES = Collections.emptyMap();
13-
private static final Pattern HTML_TAG_PATTERN = Pattern.compile("<[^>]*>");
1412

1513
private final Appendable buffer;
16-
private int nesting = 0;
1714
private char lastChar = 0;
1815

1916
public HtmlWriter(Appendable out) {
2017
this.buffer = out;
2118
}
2219

2320
public void raw(String s) {
24-
if (isTagAllowed()) {
25-
append(s);
26-
} else {
27-
append(HTML_TAG_PATTERN.matcher(s).replaceAll(""));
28-
}
29-
}
30-
31-
public boolean isTagAllowed() {
32-
return nesting == 0;
33-
}
34-
35-
public void disableTags() {
36-
nesting++;
37-
}
38-
39-
public void enableTags() {
40-
nesting--;
21+
append(s);
4122
}
4223

4324
public void tag(String name) {
@@ -50,10 +31,6 @@ public void tag(String name, Map<String, String> attrs) {
5031

5132
// Helper function to produce an HTML tag.
5233
public void tag(String name, Map<String, String> attrs, boolean voidElement) {
53-
if (!isTagAllowed()) {
54-
return;
55-
}
56-
5734
append("<");
5835
append(name);
5936
if (attrs != null && !attrs.isEmpty()) {

commonmark/src/test/java/org/commonmark/test/HtmlRendererTest.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.commonmark.html.AttributeProvider;
44
import org.commonmark.html.HtmlRenderer;
55
import org.commonmark.node.FencedCodeBlock;
6+
import org.commonmark.node.Image;
67
import org.commonmark.node.Node;
78
import org.commonmark.parser.Parser;
89
import org.junit.Test;
@@ -77,7 +78,7 @@ public void percentEncodeUrl() {
7778
}
7879

7980
@Test
80-
public void attributeProvider() {
81+
public void attributeProviderForCodeBlock() {
8182
AttributeProvider custom = new AttributeProvider() {
8283
@Override
8384
public void setAttributes(Node node, Map<String, String> attributes) {
@@ -99,11 +100,46 @@ public void setAttributes(Node node, Map<String, String> attributes) {
99100
assertEquals("<pre><code data-custom=\"evil&quot;\">content\n</code></pre>\n", rendered2);
100101
}
101102

103+
@Test
104+
public void attributeProviderForImage() {
105+
AttributeProvider custom = new AttributeProvider() {
106+
@Override
107+
public void setAttributes(Node node, Map<String, String> attributes) {
108+
if (node instanceof Image) {
109+
attributes.remove("alt");
110+
attributes.put("test", "hey");
111+
}
112+
}
113+
};
114+
115+
HtmlRenderer renderer = HtmlRenderer.builder().attributeProvider(custom).build();
116+
String rendered = renderer.render(parse("![foo](/url)\n"));
117+
assertEquals("<p><img src=\"/url\" test=\"hey\" /></p>\n", rendered);
118+
}
119+
102120
@Test
103121
public void orderedListStartZero() {
104122
assertEquals("<ol start=\"0\">\n<li>Test</li>\n</ol>\n", defaultRenderer().render(parse("0. Test\n")));
105123
}
106124

125+
@Test
126+
public void imageAltTextWithSoftLineBreak() {
127+
assertEquals("<p><img src=\"/url\" alt=\"foo\nbar\" /></p>\n",
128+
defaultRenderer().render(parse("![foo\nbar](/url)\n")));
129+
}
130+
131+
@Test
132+
public void imageAltTextWithHardLineBreak() {
133+
assertEquals("<p><img src=\"/url\" alt=\"foo\nbar\" /></p>\n",
134+
defaultRenderer().render(parse("![foo \nbar](/url)\n")));
135+
}
136+
137+
@Test
138+
public void imageAltTextWithEntities() {
139+
assertEquals("<p><img src=\"/url\" alt=\"foo \u00E4\" /></p>\n",
140+
defaultRenderer().render(parse("![foo &auml;](/url)\n")));
141+
}
142+
107143
private static HtmlRenderer defaultRenderer() {
108144
return HtmlRenderer.builder().build();
109145
}

0 commit comments

Comments
 (0)