James Moger
2015-11-22 ed552ba47c02779c270ffd62841d6d1048dade70
commit | author | age
f13c4c 1 /*
JM 2  * Copyright 2011 gitblit.com.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
cf9550 16 package com.gitblit.utils;
JM 17
0365f6 18 import static org.pegdown.Extensions.ALL;
269404 19 import static org.pegdown.Extensions.ANCHORLINKS;
ba2970 20 import static org.pegdown.Extensions.SMARTYPANTS;
0365f6 21
cf9550 22 import java.io.IOException;
JM 23 import java.io.Reader;
24 import java.io.StringWriter;
021198 25 import java.text.MessageFormat;
cf9550 26
0365f6 27 import org.apache.commons.io.IOUtils;
a7317a 28 import org.pegdown.LinkRenderer;
d2d0c6 29 import org.pegdown.ParsingTimeoutException;
0365f6 30 import org.pegdown.PegDownProcessor;
d2d0c6 31 import org.pegdown.ast.RootNode;
021198 32
JM 33 import com.gitblit.IStoredSettings;
34 import com.gitblit.Keys;
d2d0c6 35 import com.gitblit.wicket.MarkupProcessor.WorkaroundHtmlSerializer;
cf9550 36
d9f687 37 /**
JM 38  * Utility methods for transforming raw markdown text to html.
699e71 39  *
d9f687 40  * @author James Moger
699e71 41  *
d9f687 42  */
cf9550 43 public class MarkdownUtils {
JM 44
d9f687 45     /**
90d5e0 46      * Returns the html version of the plain source text.
JM 47      *
48      * @param text
49      * @return html version of plain text
50      * @throws java.text.ParseException
51      */
52     public static String transformPlainText(String text) {
53         // url auto-linking
54         text = text.replaceAll("((http|https)://[0-9A-Za-z-_=\\?\\.\\$#&/]*)", "<a href=\"$1\">$1</a>");
55         String html = "<pre>" + text + "</pre>";
56         return html;
57     }
58
59
60     /**
d9f687 61      * Returns the html version of the markdown source text.
699e71 62      *
d9f687 63      * @param markdown
JM 64      * @return html version of markdown text
65      * @throws java.text.ParseException
66      */
0365f6 67     public static String transformMarkdown(String markdown) {
a7317a 68         return transformMarkdown(markdown, null);
JM 69     }
70
71     /**
72      * Returns the html version of the markdown source text.
73      *
74      * @param markdown
75      * @return html version of markdown text
76      * @throws java.text.ParseException
77      */
78     public static String transformMarkdown(String markdown, LinkRenderer linkRenderer) {
d2d0c6 79         try {
269404 80             PegDownProcessor pd = new PegDownProcessor(ALL & ~SMARTYPANTS & ~ANCHORLINKS);
d2d0c6 81             RootNode astRoot = pd.parseMarkdown(markdown.toCharArray());
JM 82             return new WorkaroundHtmlSerializer(linkRenderer == null ? new LinkRenderer() : linkRenderer).toHtml(astRoot);
83         } catch (ParsingTimeoutException e) {
84             return null;
85         }
cf9550 86     }
JM 87
d9f687 88     /**
JM 89      * Returns the html version of the markdown source reader. The reader is
90      * closed regardless of success or failure.
699e71 91      *
d9f687 92      * @param markdownReader
JM 93      * @return html version of the markdown text
94      * @throws java.text.ParseException
95      */
0365f6 96     public static String transformMarkdown(Reader markdownReader) throws IOException {
2a7306 97         // Read raw markdown content and transform it to html
cf9550 98         StringWriter writer = new StringWriter();
JM 99         try {
0365f6 100             IOUtils.copy(markdownReader, writer);
JM 101             String markdown = writer.toString();
102             return transformMarkdown(markdown);
cf9550 103         } finally {
JM 104             try {
105                 writer.close();
106             } catch (IOException e) {
2a7306 107                 // IGNORE
cf9550 108             }
JM 109         }
110     }
021198 111
JM 112
113     /**
114      * Transforms GFM (Github Flavored Markdown) to html.
115      * Gitblit does not support the complete GFM specification.
116      *
117      * @param input
118      * @param repositoryName
119      * @return html
120      */
121     public static String transformGFM(IStoredSettings settings, String input, String repositoryName) {
122         String text = input;
123
124         // strikethrough
125         text = text.replaceAll("~~(.*)~~", "<s>$1</s>");
126         text = text.replaceAll("\\{(?:-){2}(.*)(?:-){2}}", "<s>$1</s>");
127
128         // underline
129         text = text.replaceAll("\\{(?:\\+){2}(.*)(?:\\+){2}}", "<u>$1</u>");
130
131         // strikethrough, replacement
132         text = text.replaceAll("\\{~~(.*)~>(.*)~~}", "<s>$1</s><u>$2</u>");
133
134         // highlight
135         text = text.replaceAll("\\{==(.*)==}", "<span class='highlight'>$1</span>");
136
137         String canonicalUrl = settings.getString(Keys.web.canonicalUrl, "https://localhost:8443");
138
139         // emphasize and link mentions
fd8cea 140         String mentionReplacement = String.format(" **[@$1](%1s/user/$1)**", canonicalUrl);
021198 141         text = text.replaceAll("\\s@([A-Za-z0-9-_]+)", mentionReplacement);
JM 142
5e3521 143         // link ticket refs
JM 144         String ticketReplacement = MessageFormat.format("$1[#$2]({0}/tickets?r={1}&h=$2)$3", canonicalUrl, repositoryName);
145         text = text.replaceAll("([\\s,]+)#(\\d+)([\\s,:\\.\\n])", ticketReplacement);
146
021198 147         // link commit shas
JM 148         int shaLen = settings.getInteger(Keys.web.shortCommitIdLength, 6);
149         String commitPattern = MessageFormat.format("\\s([A-Fa-f0-9]'{'{0}'}')([A-Fa-f0-9]'{'{1}'}')", shaLen, 40 - shaLen);
fd8cea 150         String commitReplacement = String.format(" [`$1`](%1$s/commit?r=%2$s&h=$1$2)", canonicalUrl, repositoryName);
021198 151         text = text.replaceAll(commitPattern, commitReplacement);
JM 152
153         String html = transformMarkdown(text);
154         return html;
155     }
cf9550 156 }