]> source.dussan.org Git - gitblit.git/commitdiff
Workaround pegdown bug and improve relative image path processing 24/24/1
authorJames Moger <james.moger@gitblit.com>
Tue, 11 Mar 2014 14:02:28 +0000 (10:02 -0400)
committerJames Moger <james.moger@gitblit.com>
Tue, 11 Mar 2014 14:02:28 +0000 (10:02 -0400)
src/main/java/com/gitblit/utils/MarkdownUtils.java
src/main/java/com/gitblit/wicket/MarkupProcessor.java

index dcd79f16ec7568fb212292a63fe371d48387b8fa..da0db79da9d2ae889770ef4a5fa4a0fc513c5e88 100644 (file)
@@ -25,10 +25,13 @@ import java.text.MessageFormat;
 \r
 import org.apache.commons.io.IOUtils;\r
 import org.pegdown.LinkRenderer;\r
+import org.pegdown.ParsingTimeoutException;\r
 import org.pegdown.PegDownProcessor;\r
+import org.pegdown.ast.RootNode;\r
 \r
 import com.gitblit.IStoredSettings;\r
 import com.gitblit.Keys;\r
+import com.gitblit.wicket.MarkupProcessor.WorkaroundHtmlSerializer;\r
 \r
 /**\r
  * Utility methods for transforming raw markdown text to html.\r
@@ -72,9 +75,13 @@ public class MarkdownUtils {
         * @throws java.text.ParseException\r
         */\r
        public static String transformMarkdown(String markdown, LinkRenderer linkRenderer) {\r
-               PegDownProcessor pd = new PegDownProcessor(ALL & ~SMARTYPANTS);\r
-               String html = pd.markdownToHtml(markdown, linkRenderer == null ? new LinkRenderer() : linkRenderer);\r
-               return html;\r
+               try {\r
+                       PegDownProcessor pd = new PegDownProcessor(ALL & ~SMARTYPANTS);\r
+                       RootNode astRoot = pd.parseMarkdown(markdown.toCharArray());\r
+                       return new WorkaroundHtmlSerializer(linkRenderer == null ? new LinkRenderer() : linkRenderer).toHtml(astRoot);\r
+               } catch (ParsingTimeoutException e) {\r
+                       return null;\r
+               }\r
        }\r
 \r
        /**\r
index d8344390339f15341a9082e4a0b68801136a1192..ff6fbce24195bc676a78d27c7f52a40e80599eb5 100644 (file)
@@ -24,6 +24,7 @@ import java.net.URLEncoder;
 import java.text.MessageFormat;\r
 import java.util.ArrayList;\r
 import java.util.Arrays;\r
+import java.util.Collections;\r
 import java.util.HashMap;\r
 import java.util.List;\r
 import java.util.Map;\r
@@ -41,10 +42,14 @@ import org.eclipse.mylyn.wikitext.mediawiki.core.MediaWikiLanguage;
 import org.eclipse.mylyn.wikitext.textile.core.TextileLanguage;\r
 import org.eclipse.mylyn.wikitext.tracwiki.core.TracWikiLanguage;\r
 import org.eclipse.mylyn.wikitext.twiki.core.TWikiLanguage;\r
+import org.pegdown.DefaultVerbatimSerializer;\r
 import org.pegdown.LinkRenderer;\r
+import org.pegdown.ToHtmlSerializer;\r
+import org.pegdown.VerbatimSerializer;\r
 import org.pegdown.ast.ExpImageNode;\r
 import org.pegdown.ast.RefImageNode;\r
 import org.pegdown.ast.WikiLinkNode;\r
+import org.pegdown.plugins.ToHtmlSerializerPlugin;\r
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
 \r
@@ -56,6 +61,7 @@ import com.gitblit.utils.MarkdownUtils;
 import com.gitblit.utils.StringUtils;\r
 import com.gitblit.wicket.pages.DocPage;\r
 import com.gitblit.wicket.pages.RawPage;\r
+import com.google.common.base.Joiner;\r
 \r
 /**\r
  * Processes markup content and generates html with repository-relative page and\r
@@ -390,7 +396,59 @@ public class MarkupProcessor {
                }\r
 \r
                String getRelativePath(String ref) {\r
-                       return ref.charAt(0) == '/' ? ref.substring(1) : (getCurrentPath() + ref);\r
+                       if (ref.charAt(0) == '/') {\r
+                               // absolute path in repository\r
+                               return ref.substring(1);\r
+                       } else {\r
+                               // resolve relative repository path\r
+                               String cp = getCurrentPath();\r
+                               if (StringUtils.isEmpty(cp)) {\r
+                                       return ref;\r
+                               }\r
+                               // this is a simple relative path resolver\r
+                               List<String> currPathStrings = new ArrayList<String>(Arrays.asList(cp.split("/")));\r
+                               String file = ref;\r
+                               while (file.startsWith("../")) {\r
+                                       // strip ../ from the file reference\r
+                                       // drop the last path element\r
+                                       file = file.substring(3);\r
+                                       currPathStrings.remove(currPathStrings.size() - 1);\r
+                               }\r
+                               currPathStrings.add(file);\r
+                               String path = Joiner.on("/").join(currPathStrings);\r
+                               return path;\r
+                       }\r
                }\r
        }\r
+\r
+       /**\r
+        * This class implements a workaround for a bug reported in issue-379.\r
+        * The bug was introduced by my own pegdown pull request #115.\r
+        *\r
+        * @author James Moger\r
+        *\r
+        */\r
+       public static class WorkaroundHtmlSerializer extends ToHtmlSerializer {\r
+\r
+                public WorkaroundHtmlSerializer(final LinkRenderer linkRenderer) {\r
+                        super(linkRenderer,\r
+                                        Collections.<String, VerbatimSerializer>singletonMap(VerbatimSerializer.DEFAULT, DefaultVerbatimSerializer.INSTANCE),\r
+                                        Collections.<ToHtmlSerializerPlugin>emptyList());\r
+                   }\r
+           private void printAttribute(String name, String value) {\r
+               printer.print(' ').print(name).print('=').print('"').print(value).print('"');\r
+           }\r
+\r
+           /* Reimplement print image tag to eliminate a trailing double-quote */\r
+               @Override\r
+           protected void printImageTag(LinkRenderer.Rendering rendering) {\r
+               printer.print("<img");\r
+               printAttribute("src", rendering.href);\r
+               printAttribute("alt", rendering.text);\r
+               for (LinkRenderer.Attribute attr : rendering.attributes) {\r
+                   printAttribute(attr.name, attr.value);\r
+               }\r
+               printer.print("/>");\r
+           }\r
+       }\r
 }\r