@@ -697,6 +697,108 @@ private static void assertContains(String needle, String haystack) {
697697 "Expected to find '" + needle + "' in: " + haystack );
698698 }
699699
700+ @ Test
701+ public void testLinkTextEscaped () throws Exception {
702+ ToMarkdownContentHandler handler = new ToMarkdownContentHandler ();
703+ handler .startDocument ();
704+
705+ startElement (handler , "p" );
706+ startElement (handler , "a" , "href" , "https://good.example" );
707+ chars (handler , "x](https://evil.example)" );
708+ endElement (handler , "a" );
709+ endElement (handler , "p" );
710+
711+ handler .endDocument ();
712+
713+ String result = handler .toString ();
714+ // the ] in the link text must be escaped so it cannot close the link early
715+ assertTrue (result .contains ("x\\ ]" ), result );
716+ assertFalse (result .contains ("[x](https://evil.example)" ), result );
717+ }
718+
719+ @ Test
720+ public void testLinkHrefNoBreakout () throws Exception {
721+ ToMarkdownContentHandler handler = new ToMarkdownContentHandler ();
722+ handler .startDocument ();
723+
724+ startElement (handler , "p" );
725+ startElement (handler , "a" , "href" , "https://evil.example) text" );
726+ chars (handler , "click" );
727+ endElement (handler , "a" );
728+ endElement (handler , "p" );
729+
730+ handler .endDocument ();
731+
732+ String result = handler .toString ();
733+ // a destination with spaces/parens must be wrapped so it cannot terminate (..) early
734+ assertTrue (result .contains ("](<https://evil.example" ), result );
735+ assertFalse (result .contains ("](https://evil.example)" ), result );
736+ }
737+
738+ @ Test
739+ public void testImageAltAndSrcEscaped () throws Exception {
740+ ToMarkdownContentHandler handler = new ToMarkdownContentHandler ();
741+ handler .startDocument ();
742+
743+ startElement (handler , "p" );
744+ AttributesImpl atts = new AttributesImpl ();
745+ atts .addAttribute ("" , "alt" , "alt" , "CDATA" , "a]b" );
746+ atts .addAttribute ("" , "src" , "src" , "CDATA" , "https://evil.example) x" );
747+ startElement (handler , "img" , atts );
748+ endElement (handler , "img" );
749+ endElement (handler , "p" );
750+
751+ handler .endDocument ();
752+
753+ String result = handler .toString ();
754+ assertTrue (result .contains ("a\\ ]b" ), result );
755+ assertTrue (result .contains ("](<https://evil.example" ), result );
756+ assertFalse (result .contains ("](https://evil.example)" ), result );
757+ }
758+
759+ @ Test
760+ public void testTableCellPipeEscaped () throws Exception {
761+ ToMarkdownContentHandler handler = new ToMarkdownContentHandler ();
762+ handler .startDocument ();
763+
764+ startElement (handler , "table" );
765+ startElement (handler , "tr" );
766+ startElement (handler , "td" );
767+ chars (handler , "a|b" );
768+ endElement (handler , "td" );
769+ startElement (handler , "td" );
770+ chars (handler , "c" );
771+ endElement (handler , "td" );
772+ endElement (handler , "tr" );
773+ endElement (handler , "table" );
774+
775+ handler .endDocument ();
776+
777+ String result = handler .toString ();
778+ // a pipe inside a cell must be escaped so it does not inject an extra column
779+ assertTrue (result .contains ("| a\\ |b | c |" ), result );
780+ }
781+
782+ @ Test
783+ public void testTableCellNewlineFolded () throws Exception {
784+ ToMarkdownContentHandler handler = new ToMarkdownContentHandler ();
785+ handler .startDocument ();
786+
787+ startElement (handler , "table" );
788+ startElement (handler , "tr" );
789+ startElement (handler , "td" );
790+ chars (handler , "a\n b" );
791+ endElement (handler , "td" );
792+ endElement (handler , "tr" );
793+ endElement (handler , "table" );
794+
795+ handler .endDocument ();
796+
797+ String result = handler .toString ();
798+ // a newline inside a cell must not terminate the table row
799+ assertTrue (result .contains ("| a b |" ), result );
800+ }
801+
700802 @ Test
701803 public void testHandlerTypeParsingMarkdown () {
702804 assertEquals (BasicContentHandlerFactory .HANDLER_TYPE .MARKDOWN ,
0 commit comments