Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ public class CoreMarkdownNodeRenderer extends AbstractVisitor implements NodeRen
private final CharMatcher textEscapeInHeading;
private final CharMatcher linkDestinationNeedsAngleBrackets =
AsciiMatcher.builder().c(' ').c('(').c(')').c('<').c('>').c('\n').c('\\').build();
private final CharMatcher linkDestinationEscapeInAngleBrackets =
AsciiMatcher.builder().c('<').c('>').c('\n').c('\\').build();
private final CharMatcher linkDestinationEscape =
AsciiMatcher.builder().c('<').c('>').c('\n').c('\\').c('&').build();
private final CharMatcher linkTitleEscapeInQuotes =
AsciiMatcher.builder().c('"').c('\n').c('\\').build();
AsciiMatcher.builder().c('"').c('\n').c('\\').c('&').build();

private final Pattern orderedListMarkerPattern = Pattern.compile("^([0-9]{1,9})([.)])");

Expand Down Expand Up @@ -523,10 +523,10 @@ private void writeLinkLike(String title, String destination, Node node, String o
writer.raw('(');
if (contains(destination, linkDestinationNeedsAngleBrackets)) {
writer.raw('<');
writer.text(destination, linkDestinationEscapeInAngleBrackets);
writer.text(destination, linkDestinationEscape);
writer.raw('>');
} else {
writer.raw(destination);
writer.text(destination, linkDestinationEscape);
}
if (title != null) {
writer.raw(' ');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import org.commonmark.parser.Parser;
import org.commonmark.renderer.NodeRenderer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

public class MarkdownRendererTest {

Expand Down Expand Up @@ -297,6 +299,60 @@ public void testImages() {
assertRoundTrip("![a](/uri \"foo \\\" bar\")\n");
}

@ParameterizedTest
@ValueSource(
strings = {
"/url?value=&copy;",
"/my uri?value=&copy;",
"/url?value=&#65;",
"/url?value=&#x41;",
"/url?a=1&b=2"
})
public void testLinkDestinationPreservesLiteralAmpersands(String destination) {
Link link = new Link(destination, null);
link.appendChild(new Text("link"));

Link reparsed = (Link) parse(render(link)).getFirstChild().getFirstChild();
assertThat(reparsed.getDestination()).isEqualTo(destination);
}

@ParameterizedTest
@ValueSource(
strings = {
"/url?value=&copy;",
"/my uri?value=&copy;",
"/url?value=&#65;",
"/url?value=&#x41;",
"/url?a=1&b=2"
})
public void testImageDestinationPreservesLiteralAmpersands(String destination) {
Image image = new Image(destination, null);
image.appendChild(new Text("image"));

Image reparsed = (Image) parse(render(image)).getFirstChild().getFirstChild();
assertThat(reparsed.getDestination()).isEqualTo(destination);
}

@ParameterizedTest
@ValueSource(strings = {"literal &copy;", "literal &#65;", "literal &#x41;", "bread & butter"})
public void testLinkTitlePreservesLiteralAmpersands(String title) {
Link link = new Link("/url", title);
link.appendChild(new Text("link"));

Link reparsed = (Link) parse(render(link)).getFirstChild().getFirstChild();
assertThat(reparsed.getTitle()).isEqualTo(title);
}

@ParameterizedTest
@ValueSource(strings = {"literal &copy;", "literal &#65;", "literal &#x41;", "bread & butter"})
public void testImageTitlePreservesLiteralAmpersands(String title) {
Image image = new Image("/url", title);
image.appendChild(new Text("image"));

Image reparsed = (Image) parse(render(image)).getFirstChild().getFirstChild();
assertThat(reparsed.getTitle()).isEqualTo(title);
}

@Test
public void testHtmlInline() {
assertRoundTrip("<del>*foo*</del>\n");
Expand Down