]> source.dussan.org Git - gitblit.git/commitdiff
Refactor markup processing in preparation for supporting other formats
authorJames Moger <james.moger@gitblit.com>
Tue, 12 Nov 2013 13:04:40 +0000 (08:04 -0500)
committerJames Moger <james.moger@gitblit.com>
Tue, 12 Nov 2013 21:12:59 +0000 (16:12 -0500)
Change-Id: I0eb217064abc4f4b0f6bfbbc21302c470cc2f9c6

14 files changed:
src/main/java/com/gitblit/PagesServlet.java
src/main/java/com/gitblit/utils/StringUtils.java
src/main/java/com/gitblit/wicket/GitBlitWebApp.java
src/main/java/com/gitblit/wicket/MarkupProcessor.java [new file with mode: 0644]
src/main/java/com/gitblit/wicket/WicketUtils.java
src/main/java/com/gitblit/wicket/pages/BlobPage.java
src/main/java/com/gitblit/wicket/pages/DocPage.html [new file with mode: 0644]
src/main/java/com/gitblit/wicket/pages/DocPage.java [new file with mode: 0644]
src/main/java/com/gitblit/wicket/pages/DocsPage.java
src/main/java/com/gitblit/wicket/pages/MarkdownPage.html [deleted file]
src/main/java/com/gitblit/wicket/pages/MarkdownPage.java [deleted file]
src/main/java/com/gitblit/wicket/pages/RepositoryPage.java
src/main/java/com/gitblit/wicket/pages/SummaryPage.java
src/main/resources/gitblit.css

index ce4239ce2ec14725d6eec4e51670cb7261e24759..e121f8aa8b00234bfbe6e6c4195e0824a898c347 100644 (file)
@@ -38,6 +38,8 @@ import com.gitblit.utils.ArrayUtils;
 import com.gitblit.utils.JGitUtils;\r
 import com.gitblit.utils.MarkdownUtils;\r
 import com.gitblit.utils.StringUtils;\r
+import com.gitblit.wicket.MarkupProcessor;\r
+import com.gitblit.wicket.MarkupProcessor.MarkupDocument;\r
 \r
 /**\r
  * Serves the content of a gh-pages branch.\r
@@ -142,21 +144,20 @@ public class PagesServlet extends HttpServlet {
                                return;\r
                        }\r
 \r
+                       MarkupProcessor processor = new MarkupProcessor(GitBlit.getSettings());\r
                        String [] encodings = GitBlit.getEncodings();\r
 \r
                        RevTree tree = commit.getTree();\r
                        byte[] content = null;\r
                        if (StringUtils.isEmpty(resource)) {\r
                                // find resource\r
-                               List<String> markdownExtensions = GitBlit.getStrings(Keys.web.markdownExtensions);\r
-                               List<String> extensions = new ArrayList<String>(markdownExtensions.size() + 2);\r
+                               List<String> extensions = new ArrayList<String>(processor.getMarkupExtensions());\r
                                extensions.add("html");\r
                                extensions.add("htm");\r
-                               extensions.addAll(markdownExtensions);\r
-                               for (String ext : extensions){\r
+                               for (String ext : extensions) {\r
                                        String file = "index." + ext;\r
                                        String stringContent = JGitUtils.getStringContent(r, tree, file, encodings);\r
-                                       if(stringContent == null){\r
+                                       if (stringContent == null) {\r
                                                continue;\r
                                        }\r
                                        content = stringContent.getBytes(Constants.ENCODING);\r
@@ -213,14 +214,13 @@ public class PagesServlet extends HttpServlet {
                                return;\r
                        }\r
 \r
-                       // check to see if we should transform markdown files\r
-                       for (String ext : GitBlit.getStrings(Keys.web.markdownExtensions)) {\r
-                               if (resource.endsWith(ext)) {\r
-                                       String mkd = new String(content, Constants.ENCODING);\r
-                                       content = MarkdownUtils.transformMarkdown(mkd).getBytes(Constants.ENCODING);\r
-                                       response.setContentType("text/html; charset=" + Constants.ENCODING);\r
-                                       break;\r
-                               }\r
+                       // check to see if we should transform markup files\r
+                       String ext = StringUtils.getFileExtension(resource);\r
+                       if (processor.getMarkupExtensions().contains(ext)) {\r
+                               String markup = new String(content, Constants.ENCODING);\r
+                               MarkupDocument markupDoc = processor.parse(repository, commit.getName(), resource, markup);\r
+                               content = markupDoc.html.getBytes("UTF-8");\r
+                               response.setContentType("text/html; charset=" + Constants.ENCODING);\r
                        }\r
 \r
                        try {\r
index 5e627781238e7bc3b16ce6dfbbfee689b314ea64..e18bdc4f0f8d83567c62ae46f54df994cb6f13eb 100644 (file)
@@ -555,6 +555,20 @@ public class StringUtils {
                return "";\r
        }\r
 \r
+       /**\r
+        * Returns the file extension of a path.\r
+        *\r
+        * @param path\r
+        * @return a blank string or a file extension\r
+        */\r
+       public static String stripFileExtension(String path) {\r
+               int lastDot = path.lastIndexOf('.');\r
+               if (lastDot > -1) {\r
+                       return path.substring(0, lastDot);\r
+               }\r
+               return path;\r
+       }\r
+\r
        /**\r
         * Replace all occurences of a substring within a string with\r
         * another string.\r
index fa02c4fec00a915d006ace39ffa5366bb65605c0..9adbb94342a16b0195ddaddd161d0fcf74487985 100644 (file)
@@ -39,6 +39,7 @@ import com.gitblit.wicket.pages.BranchesPage;
 import com.gitblit.wicket.pages.CommitDiffPage;\r
 import com.gitblit.wicket.pages.CommitPage;\r
 import com.gitblit.wicket.pages.ComparePage;\r
+import com.gitblit.wicket.pages.DocPage;\r
 import com.gitblit.wicket.pages.DocsPage;\r
 import com.gitblit.wicket.pages.FederationRegistrationPage;\r
 import com.gitblit.wicket.pages.ForkPage;\r
@@ -49,7 +50,6 @@ import com.gitblit.wicket.pages.HistoryPage;
 import com.gitblit.wicket.pages.LogPage;\r
 import com.gitblit.wicket.pages.LogoutPage;\r
 import com.gitblit.wicket.pages.LuceneSearchPage;\r
-import com.gitblit.wicket.pages.MarkdownPage;\r
 import com.gitblit.wicket.pages.MetricsPage;\r
 import com.gitblit.wicket.pages.MyDashboardPage;\r
 import com.gitblit.wicket.pages.OverviewPage;\r
@@ -121,9 +121,9 @@ public class GitBlitWebApp extends WebApplication {
                mount("/users", UsersPage.class);\r
                mount("/logout", LogoutPage.class);\r
 \r
-               // setup the markdown urls\r
+               // setup the markup document urls\r
                mount("/docs", DocsPage.class, "r");\r
-               mount("/markdown", MarkdownPage.class, "r", "h", "f");\r
+               mount("/doc", DocPage.class, "r", "h", "f");\r
 \r
                // federation urls\r
                mount("/proposal", ReviewProposalPage.class, "t");\r
diff --git a/src/main/java/com/gitblit/wicket/MarkupProcessor.java b/src/main/java/com/gitblit/wicket/MarkupProcessor.java
new file mode 100644 (file)
index 0000000..4b4bee6
--- /dev/null
@@ -0,0 +1,216 @@
+/*\r
+ * Copyright 2013 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.wicket;\r
+\r
+import java.io.Serializable;\r
+import java.io.UnsupportedEncodingException;\r
+import java.net.URLEncoder;\r
+import java.text.MessageFormat;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.apache.wicket.Page;\r
+import org.apache.wicket.RequestCycle;\r
+import org.eclipse.jgit.lib.Repository;\r
+import org.eclipse.jgit.revwalk.RevCommit;\r
+import org.pegdown.LinkRenderer;\r
+import org.pegdown.ast.WikiLinkNode;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import com.gitblit.IStoredSettings;\r
+import com.gitblit.Keys;\r
+import com.gitblit.models.PathModel;\r
+import com.gitblit.utils.JGitUtils;\r
+import com.gitblit.utils.MarkdownUtils;\r
+import com.gitblit.utils.StringUtils;\r
+import com.gitblit.wicket.pages.DocPage;\r
+\r
+/**\r
+ * Processes markup content and generates html with repository-relative page and\r
+ * image linking.\r
+ *\r
+ * @author James Moger\r
+ *\r
+ */\r
+public class MarkupProcessor {\r
+\r
+       public enum MarkupSyntax {\r
+               PLAIN, MARKDOWN\r
+       }\r
+\r
+       private Logger logger = LoggerFactory.getLogger(getClass());\r
+\r
+       private final IStoredSettings settings;\r
+\r
+       public MarkupProcessor(IStoredSettings settings) {\r
+               this.settings = settings;\r
+       }\r
+\r
+       public List<String> getMarkupExtensions() {\r
+               List<String> list = new ArrayList<String>();\r
+               list.addAll(settings.getStrings(Keys.web.markdownExtensions));\r
+               return list;\r
+       }\r
+\r
+       private MarkupSyntax determineSyntax(String documentPath) {\r
+               String ext = StringUtils.getFileExtension(documentPath).toLowerCase();\r
+               if (StringUtils.isEmpty(ext)) {\r
+                       return MarkupSyntax.PLAIN;\r
+               }\r
+\r
+               if (settings.getStrings(Keys.web.markdownExtensions).contains(ext)) {\r
+                       return MarkupSyntax.MARKDOWN;\r
+               }\r
+\r
+               return MarkupSyntax.PLAIN;\r
+       }\r
+\r
+       public MarkupDocument parseReadme(Repository r, String repositoryName, String commitId) {\r
+               String readme = null;\r
+               RevCommit commit = JGitUtils.getCommit(r, commitId);\r
+               List<PathModel> paths = JGitUtils.getFilesInPath(r, null, commit);\r
+               for (PathModel path : paths) {\r
+                       if (!path.isTree()) {\r
+                               String name = path.name.toLowerCase();\r
+                               if (name.equals("readme") || name.equals("readme.txt")) {\r
+                                       readme = path.name;\r
+                                       break;\r
+                               } else if (name.startsWith("readme.")) {\r
+                                       String ext = StringUtils.getFileExtension(name).toLowerCase();\r
+                                       if (getMarkupExtensions().contains(ext)) {\r
+                                               readme = path.name;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if (!StringUtils.isEmpty(readme)) {\r
+                       String [] encodings = settings.getStrings(Keys.web.blobEncodings).toArray(new String[0]);\r
+                       String markup = JGitUtils.getStringContent(r, commit.getTree(), readme, encodings);\r
+                       return parse(repositoryName, commitId, readme, markup);\r
+               }\r
+\r
+               return null;\r
+       }\r
+\r
+       public MarkupDocument parse(String repositoryName, String commitId, String documentPath, String markupText) {\r
+               final MarkupSyntax syntax = determineSyntax(documentPath);\r
+               final MarkupDocument doc = new MarkupDocument(documentPath, markupText, syntax);\r
+\r
+               if (markupText != null) {\r
+                       try {\r
+                               switch (syntax){\r
+                               case MARKDOWN:\r
+                                       parse(doc, repositoryName, commitId);\r
+                                       break;\r
+                               default:\r
+                                       doc.html = MarkdownUtils.transformPlainText(markupText);\r
+                                       break;\r
+                               }\r
+                       } catch (Exception e) {\r
+                               logger.error("failed to transform " + syntax, e);\r
+                       }\r
+               }\r
+\r
+               if (doc.html == null) {\r
+                       // failed to transform markup\r
+                       if (markupText == null) {\r
+                               markupText = String.format("Document <b>%1$s</b> not found in <em>%2$s</em>", documentPath, repositoryName);\r
+                       }\r
+                       markupText = MessageFormat.format("<div class=\"alert alert-error\"><strong>{0}:</strong> {1}</div>{2}", "Error", "failed to parse markup", markupText);\r
+                       doc.html = StringUtils.breakLinesForHtml(markupText);\r
+               }\r
+\r
+               return doc;\r
+       }\r
+\r
+       /**\r
+        * Parses the document as Markdown using Pegdown.\r
+        *\r
+        * @param doc\r
+        * @param repositoryName\r
+        * @param commitId\r
+        */\r
+       private void parse(final MarkupDocument doc, final String repositoryName, final String commitId) {\r
+               LinkRenderer renderer = new LinkRenderer() {\r
+                       @Override\r
+                       public Rendering render(WikiLinkNode node) {\r
+                               String path = doc.getRelativePath(node.getText());\r
+                               String name = getDocumentName(path);\r
+                               String url = getWicketUrl(DocPage.class, repositoryName, commitId, path);\r
+                               return new Rendering(url, name);\r
+                       }\r
+               };\r
+               doc.html = MarkdownUtils.transformMarkdown(doc.markup, renderer);\r
+       }\r
+\r
+       private String getWicketUrl(Class<? extends Page> pageClass, final String repositoryName, final String commitId, final String document) {\r
+               String fsc = settings.getString(Keys.web.forwardSlashCharacter, "/");\r
+               String encodedPath = document.replace(' ', '-');\r
+               try {\r
+                       encodedPath = URLEncoder.encode(encodedPath, "UTF-8");\r
+               } catch (UnsupportedEncodingException e) {\r
+                       logger.error(null, e);\r
+               }\r
+               encodedPath = encodedPath.replace("/", fsc).replace("%2F", fsc);\r
+\r
+               String url = RequestCycle.get().urlFor(pageClass, WicketUtils.newPathParameter(repositoryName, commitId, encodedPath)).toString();\r
+               return url;\r
+       }\r
+\r
+       private String getDocumentName(final String document) {\r
+               // extract document name\r
+               String name = StringUtils.stripFileExtension(document);\r
+               name = name.replace('_', ' ');\r
+               if (name.indexOf('/') > -1) {\r
+                       name = name.substring(name.lastIndexOf('/') + 1);\r
+               }\r
+               return name;\r
+       }\r
+\r
+       public static class MarkupDocument implements Serializable {\r
+\r
+               private static final long serialVersionUID = 1L;\r
+\r
+               public final String documentPath;\r
+               public final String markup;\r
+               public final MarkupSyntax syntax;\r
+               public String html;\r
+\r
+               MarkupDocument(String documentPath, String markup, MarkupSyntax syntax) {\r
+                       this.documentPath = documentPath;\r
+                       this.markup = markup;\r
+                       this.syntax = syntax;\r
+               }\r
+\r
+               String getCurrentPath() {\r
+                       String basePath = "";\r
+                       if (documentPath.indexOf('/') > -1) {\r
+                               basePath = documentPath.substring(0, documentPath.lastIndexOf('/') + 1);\r
+                               if (basePath.charAt(0) == '/') {\r
+                                       return basePath.substring(1);\r
+                               }\r
+                       }\r
+                       return basePath;\r
+               }\r
+\r
+               String getRelativePath(String ref) {\r
+                       return ref.charAt(0) == '/' ? ref.substring(1) : (getCurrentPath() + ref);\r
+               }\r
+       }\r
+}\r
index a2522ef51d30ff5b78c62a70b03c6a19f108950a..6e3d932f777a54955ef317e3e5139a6554367e78 100644 (file)
@@ -21,7 +21,6 @@ import java.text.SimpleDateFormat;
 import java.util.Collection;\r
 import java.util.Date;\r
 import java.util.HashMap;\r
-import java.util.List;\r
 import java.util.Map;\r
 import java.util.TimeZone;\r
 \r
@@ -190,11 +189,10 @@ public class WicketUtils {
                        return newImage(wicketId, "file_settings_16x16.png");\r
                }\r
 \r
-               List<String> mdExtensions = GitBlit.getStrings(Keys.web.markdownExtensions);\r
-               for (String ext : mdExtensions) {\r
-                       if (filename.endsWith('.' + ext.toLowerCase())) {\r
-                               return newImage(wicketId, "file_world_16x16.png");\r
-                       }\r
+               MarkupProcessor processor = new MarkupProcessor(GitBlit.getSettings());\r
+               String ext = StringUtils.getFileExtension(filename).toLowerCase();\r
+               if (processor.getMarkupExtensions().contains(ext)) {\r
+                       return newImage(wicketId, "file_world_16x16.png");\r
                }\r
                return newImage(wicketId, "file_16x16.png");\r
        }\r
index 0c93d48ca37da77160b12a349993a2a0ffb4002a..56ad5b96329beb7035c9ab92620946035cfeb8e9 100644 (file)
@@ -35,6 +35,7 @@ import com.gitblit.utils.StringUtils;
 import com.gitblit.wicket.CacheControl;\r
 import com.gitblit.wicket.CacheControl.LastModified;\r
 import com.gitblit.wicket.ExternalImage;\r
+import com.gitblit.wicket.MarkupProcessor;\r
 import com.gitblit.wicket.WicketUtils;\r
 import com.gitblit.wicket.panels.CommitHeaderPanel;\r
 import com.gitblit.wicket.panels.PathBreadcrumbsPanel;\r
@@ -73,10 +74,11 @@ public class BlobPage extends RepositoryPage {
                                extension = blobPath.substring(blobPath.lastIndexOf('.') + 1).toLowerCase();\r
                        }\r
 \r
-                       // see if we should redirect to the markdown page\r
-                       for (String ext : GitBlit.getStrings(Keys.web.markdownExtensions)) {\r
+                       // see if we should redirect to the doc page\r
+                       MarkupProcessor processor = new MarkupProcessor(GitBlit.getSettings());\r
+                       for (String ext : processor.getMarkupExtensions()) {\r
                                if (ext.equals(extension)) {\r
-                                       setResponsePage(MarkdownPage.class, params);\r
+                                       setResponsePage(DocPage.class, params);\r
                                        return;\r
                                }\r
                        }\r
diff --git a/src/main/java/com/gitblit/wicket/pages/DocPage.html b/src/main/java/com/gitblit/wicket/pages/DocPage.html
new file mode 100644 (file)
index 0000000..beb8e4d
--- /dev/null
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml"  \r
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"  \r
+      xml:lang="en"  \r
+      lang="en">\r
+\r
+<body>\r
+<wicket:extend>\r
+               <!-- doc nav links -->  \r
+               <div class="page_nav2">\r
+                       <a wicket:id="blameLink"><wicket:message key="gb.blame"></wicket:message></a>  | <a wicket:id="historyLink"><wicket:message key="gb.history"></wicket:message></a> | <a wicket:id="rawLink"><wicket:message key="gb.raw"></wicket:message></a> | <a wicket:id="headLink"><wicket:message key="gb.head"></wicket:message></a>\r
+               </div>  \r
+       \r
+               <!--  document content -->\r
+               <div class="markdown" style="padding-bottom:5px;" wicket:id="content">[content]</div>\r
+</wicket:extend>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/pages/DocPage.java b/src/main/java/com/gitblit/wicket/pages/DocPage.java
new file mode 100644 (file)
index 0000000..2c1308a
--- /dev/null
@@ -0,0 +1,92 @@
+/*\r
+ * Copyright 2011 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.wicket.pages;\r
+\r
+import java.util.List;\r
+\r
+import org.apache.wicket.PageParameters;\r
+import org.apache.wicket.markup.html.basic.Label;\r
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;\r
+import org.eclipse.jgit.lib.Constants;\r
+import org.eclipse.jgit.lib.Repository;\r
+import org.eclipse.jgit.revwalk.RevCommit;\r
+\r
+import com.gitblit.GitBlit;\r
+import com.gitblit.utils.JGitUtils;\r
+import com.gitblit.utils.StringUtils;\r
+import com.gitblit.wicket.CacheControl;\r
+import com.gitblit.wicket.CacheControl.LastModified;\r
+import com.gitblit.wicket.MarkupProcessor;\r
+import com.gitblit.wicket.MarkupProcessor.MarkupDocument;\r
+import com.gitblit.wicket.WicketUtils;\r
+\r
+@CacheControl(LastModified.BOOT)\r
+public class DocPage extends RepositoryPage {\r
+\r
+       public DocPage(PageParameters params) {\r
+               super(params);\r
+\r
+               final String path = WicketUtils.getPath(params).replace("%2f", "/").replace("%2F", "/");\r
+               MarkupProcessor processor = new MarkupProcessor(GitBlit.getSettings());\r
+\r
+               Repository r = getRepository();\r
+               RevCommit commit = JGitUtils.getCommit(r, objectId);\r
+               String [] encodings = GitBlit.getEncodings();\r
+\r
+               // Read raw markup content and transform it to html\r
+               String documentPath = path;\r
+               String markupText = JGitUtils.getStringContent(r, commit.getTree(), path, encodings);\r
+\r
+               // Hunt for document\r
+               if (StringUtils.isEmpty(markupText)) {\r
+                       String name = StringUtils.stripFileExtension(path);\r
+\r
+                       List<String> docExtensions = processor.getMarkupExtensions();\r
+                       for (String ext : docExtensions) {\r
+                               String checkName = name + "." + ext;\r
+                               markupText = JGitUtils.getStringContent(r, commit.getTree(), checkName, encodings);\r
+                               if (!StringUtils.isEmpty(markupText)) {\r
+                                       // found it\r
+                                       documentPath = path;\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               // document page links\r
+               add(new BookmarkablePageLink<Void>("blameLink", BlamePage.class,\r
+                               WicketUtils.newPathParameter(repositoryName, objectId, documentPath)));\r
+               add(new BookmarkablePageLink<Void>("historyLink", HistoryPage.class,\r
+                               WicketUtils.newPathParameter(repositoryName, objectId, documentPath)));\r
+               add(new BookmarkablePageLink<Void>("rawLink", RawPage.class, WicketUtils.newPathParameter(\r
+                               repositoryName, objectId, documentPath)));\r
+               add(new BookmarkablePageLink<Void>("headLink", DocPage.class,\r
+                               WicketUtils.newPathParameter(repositoryName, Constants.HEAD, documentPath)));\r
+\r
+               MarkupDocument markupDoc = processor.parse(repositoryName, getBestCommitId(commit), documentPath, markupText);\r
+               add(new Label("content", markupDoc.html).setEscapeModelStrings(false));\r
+       }\r
+\r
+       @Override\r
+       protected String getPageName() {\r
+               return getString("gb.docs");\r
+       }\r
+\r
+       @Override\r
+       protected Class<? extends BasePage> getRepoNavPageClass() {\r
+               return DocsPage.class;\r
+       }\r
+}\r
index 2634ea8e36fcf5378e3ae2f02feb1e9e3a5bee7a..37ecb35c5bbccb28fa9cb962a7abb9851c4ea238 100644 (file)
@@ -30,14 +30,14 @@ import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevCommit;\r
 \r
 import com.gitblit.GitBlit;\r
-import com.gitblit.Keys;\r
 import com.gitblit.models.PathModel;\r
 import com.gitblit.utils.ByteFormat;\r
 import com.gitblit.utils.JGitUtils;\r
-import com.gitblit.utils.MarkdownUtils;\r
 import com.gitblit.utils.StringUtils;\r
 import com.gitblit.wicket.CacheControl;\r
 import com.gitblit.wicket.CacheControl.LastModified;\r
+import com.gitblit.wicket.MarkupProcessor;\r
+import com.gitblit.wicket.MarkupProcessor.MarkupDocument;\r
 import com.gitblit.wicket.WicketUtils;\r
 import com.gitblit.wicket.panels.LinkPanel;\r
 \r
@@ -47,13 +47,15 @@ public class DocsPage extends RepositoryPage {
        public DocsPage(PageParameters params) {\r
                super(params);\r
 \r
+               MarkupProcessor processor = new MarkupProcessor(GitBlit.getSettings());\r
+\r
                Repository r = getRepository();\r
                RevCommit head = JGitUtils.getCommit(r, null);\r
-               List<String> extensions = GitBlit.getStrings(Keys.web.markdownExtensions);\r
+               List<String> extensions = processor.getMarkupExtensions();\r
                List<PathModel> paths = JGitUtils.getDocuments(r, extensions);\r
 \r
                String doc = null;\r
-               String markdown = null;\r
+               String markup = null;\r
                String html = null;\r
 \r
                List<String> roots = Arrays.asList("home");\r
@@ -61,9 +63,7 @@ public class DocsPage extends RepositoryPage {
                // try to find a custom index/root page\r
                for (PathModel path : paths) {\r
                        String name = path.name.toLowerCase();\r
-                       if (name.indexOf('.') > -1) {\r
-                               name = name.substring(0, name.lastIndexOf('.'));\r
-                       }\r
+                       name = StringUtils.stripFileExtension(name);\r
                        if (roots.contains(name)) {\r
                                doc = path.name;\r
                                break;\r
@@ -73,8 +73,11 @@ public class DocsPage extends RepositoryPage {
                if (!StringUtils.isEmpty(doc)) {\r
                        // load the document\r
                        String [] encodings = GitBlit.getEncodings();\r
-                       markdown = JGitUtils.getStringContent(r, head.getTree(), doc, encodings);\r
-                       html = MarkdownUtils.transformMarkdown(markdown, getMarkdownLinkRenderer());\r
+                       markup = JGitUtils.getStringContent(r, head.getTree(), doc, encodings);\r
+\r
+                       // parse document\r
+                       MarkupDocument markupDoc = processor.parse(repositoryName, getBestCommitId(head), doc, markup);\r
+                       html = markupDoc.html;\r
                }\r
 \r
                Fragment fragment = null;\r
@@ -103,11 +106,11 @@ public class DocsPage extends RepositoryPage {
                                PathModel entry = item.getModelObject();\r
                                item.add(WicketUtils.newImage("docIcon", "file_world_16x16.png"));\r
                                item.add(new Label("docSize", byteFormat.format(entry.size)));\r
-                               item.add(new LinkPanel("docName", "list", entry.name, MarkdownPage.class, WicketUtils\r
+                               item.add(new LinkPanel("docName", "list", entry.name, DocPage.class, WicketUtils\r
                                                .newPathParameter(repositoryName, id, entry.path)));\r
 \r
                                // links\r
-                               item.add(new BookmarkablePageLink<Void>("view", MarkdownPage.class, WicketUtils\r
+                               item.add(new BookmarkablePageLink<Void>("view", DocPage.class, WicketUtils\r
                                                .newPathParameter(repositoryName, id, entry.path)));\r
                                item.add(new BookmarkablePageLink<Void>("raw", RawPage.class, WicketUtils\r
                                                .newPathParameter(repositoryName, id, entry.path)));\r
diff --git a/src/main/java/com/gitblit/wicket/pages/MarkdownPage.html b/src/main/java/com/gitblit/wicket/pages/MarkdownPage.html
deleted file mode 100644 (file)
index 7900625..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
-<html xmlns="http://www.w3.org/1999/xhtml"  \r
-      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"  \r
-      xml:lang="en"  \r
-      lang="en">\r
-\r
-<body>\r
-<wicket:extend>\r
-               <!-- markdown nav links -->     \r
-               <div class="page_nav2">\r
-                       <a wicket:id="blameLink"><wicket:message key="gb.blame"></wicket:message></a>  | <a wicket:id="historyLink"><wicket:message key="gb.history"></wicket:message></a> | <a wicket:id="rawLink"><wicket:message key="gb.raw"></wicket:message></a> | <a wicket:id="headLink"><wicket:message key="gb.head"></wicket:message></a>\r
-               </div>  \r
-       \r
-               <!--  markdown content -->\r
-               <div class="markdown" style="padding-bottom:5px;" wicket:id="markdownText">[markdown content]</div>\r
-</wicket:extend>\r
-</body>\r
-</html>
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/pages/MarkdownPage.java b/src/main/java/com/gitblit/wicket/pages/MarkdownPage.java
deleted file mode 100644 (file)
index 0034984..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*\r
- * Copyright 2011 gitblit.com.\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package com.gitblit.wicket.pages;\r
-\r
-import java.text.MessageFormat;\r
-import java.util.List;\r
-\r
-import org.apache.wicket.PageParameters;\r
-import org.apache.wicket.markup.html.basic.Label;\r
-import org.apache.wicket.markup.html.link.BookmarkablePageLink;\r
-import org.eclipse.jgit.lib.Constants;\r
-import org.eclipse.jgit.lib.Repository;\r
-import org.eclipse.jgit.revwalk.RevCommit;\r
-\r
-import com.gitblit.GitBlit;\r
-import com.gitblit.Keys;\r
-import com.gitblit.utils.JGitUtils;\r
-import com.gitblit.utils.MarkdownUtils;\r
-import com.gitblit.utils.StringUtils;\r
-import com.gitblit.wicket.CacheControl;\r
-import com.gitblit.wicket.CacheControl.LastModified;\r
-import com.gitblit.wicket.WicketUtils;\r
-\r
-@CacheControl(LastModified.BOOT)\r
-public class MarkdownPage extends RepositoryPage {\r
-\r
-       public MarkdownPage(PageParameters params) {\r
-               super(params);\r
-\r
-               final String path = WicketUtils.getPath(params).replace("%2f", "/").replace("%2F", "/");\r
-\r
-               Repository r = getRepository();\r
-               RevCommit commit = JGitUtils.getCommit(r, objectId);\r
-               String [] encodings = GitBlit.getEncodings();\r
-               List<String> extensions = GitBlit.getStrings(Keys.web.markdownExtensions);\r
-\r
-               // Read raw markdown content and transform it to html\r
-               String markdownPath = path;\r
-               String markdownText = JGitUtils.getStringContent(r, commit.getTree(), path, encodings);\r
-               if (StringUtils.isEmpty(markdownText)) {\r
-                       String name = path;\r
-                       if (path.indexOf('.') > -1) {\r
-                               name = path.substring(0, path.lastIndexOf('.'));\r
-                       }\r
-\r
-                       for (String ext : extensions) {\r
-                               String checkName = name + "." + ext;\r
-                               markdownText = JGitUtils.getStringContent(r, commit.getTree(), checkName, encodings);\r
-                               if (!StringUtils.isEmpty(markdownText)) {\r
-                                       // found it\r
-                                       markdownPath = path;\r
-                                       break;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               // markdown page links\r
-               add(new BookmarkablePageLink<Void>("blameLink", BlamePage.class,\r
-                               WicketUtils.newPathParameter(repositoryName, objectId, markdownPath)));\r
-               add(new BookmarkablePageLink<Void>("historyLink", HistoryPage.class,\r
-                               WicketUtils.newPathParameter(repositoryName, objectId, markdownPath)));\r
-               add(new BookmarkablePageLink<Void>("rawLink", RawPage.class, WicketUtils.newPathParameter(\r
-                               repositoryName, objectId, markdownPath)));\r
-               add(new BookmarkablePageLink<Void>("headLink", MarkdownPage.class,\r
-                               WicketUtils.newPathParameter(repositoryName, Constants.HEAD, markdownPath)));\r
-\r
-               String htmlText;\r
-               try {\r
-                       htmlText = MarkdownUtils.transformMarkdown(markdownText, getMarkdownLinkRenderer());\r
-               } catch (Exception e) {\r
-                       logger.error("failed to transform markdown", e);\r
-                       if (markdownText == null) {\r
-                               markdownText = String.format("Markdown document <b>%1$s</b> not found in <em>%2$s</em>", markdownPath, repositoryName);\r
-                       }\r
-                       markdownText = MessageFormat.format("<div class=\"alert alert-error\"><strong>{0}:</strong> {1}</div>{2}", getString("gb.error"), getString("gb.markdownFailure"), markdownText);\r
-                       htmlText = StringUtils.breakLinesForHtml(markdownText);\r
-               }\r
-\r
-               // Add the html to the page\r
-               add(new Label("markdownText", htmlText).setEscapeModelStrings(false));\r
-       }\r
-\r
-       @Override\r
-       protected String getPageName() {\r
-               return getString("gb.markdown");\r
-       }\r
-\r
-       @Override\r
-       protected Class<? extends BasePage> getRepoNavPageClass() {\r
-               return DocsPage.class;\r
-       }\r
-}\r
index bc7dfa93a264b882072e8a3d715674f6118dbb8a..d0d801efe795e04dbf0fb7bbdc9d240e0f36bcd0 100644 (file)
@@ -16,8 +16,6 @@
 package com.gitblit.wicket.pages;\r
 \r
 import java.io.Serializable;\r
-import java.io.UnsupportedEncodingException;\r
-import java.net.URLEncoder;\r
 import java.text.MessageFormat;\r
 import java.util.ArrayList;\r
 import java.util.Arrays;\r
@@ -44,8 +42,6 @@ import org.eclipse.jgit.diff.DiffEntry.ChangeType;
 import org.eclipse.jgit.lib.PersonIdent;\r
 import org.eclipse.jgit.lib.Repository;\r
 import org.eclipse.jgit.revwalk.RevCommit;\r
-import org.pegdown.LinkRenderer;\r
-import org.pegdown.ast.WikiLinkNode;\r
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
 \r
@@ -647,47 +643,6 @@ public abstract class RepositoryPage extends RootPage {
                return isOwner;\r
        }\r
 \r
-       /**\r
-        * Returns a Pegdown/Markdown link renderer which renders WikiLinks.\r
-        *\r
-        * @return a link renderer\r
-        */\r
-       protected LinkRenderer getMarkdownLinkRenderer() {\r
-               RevCommit head = JGitUtils.getCommit(r, "HEAD");\r
-               final String id = getBestCommitId(head);\r
-               LinkRenderer renderer = new LinkRenderer() {\r
-                       @Override\r
-                       public Rendering render(WikiLinkNode node) {\r
-                               try {\r
-                                       String fsc = GitBlit.getString(Keys.web.forwardSlashCharacter, "/");\r
-                                       // adjust the request path\r
-                                       String path = node.getText().charAt(0) == '/' ? node.getText().substring(1) : node.getText();\r
-                                       path = URLEncoder.encode(path.replace(' ', '-'), "UTF-8").replace("%2F", fsc);\r
-\r
-                                       // extract document name\r
-                                       String name = node.getText().replace('_', ' ');\r
-                                       if (name.indexOf('/') > -1) {\r
-                                               name = name.substring(name.lastIndexOf('/') + 1);\r
-                                       }\r
-\r
-                                       // strip Markdown extension\r
-                                       for (String ext : GitBlit.getStrings(Keys.web.markdownExtensions)) {\r
-                                               String x = "." + ext;\r
-                                               if (name.endsWith(x)) {\r
-                                                       name = name.substring(0, name.length() - x.length());\r
-                                                       break;\r
-                                               }\r
-                                       }\r
-                                       String url = urlFor(MarkdownPage.class, WicketUtils.newPathParameter(repositoryName, id, path)).toString();\r
-                                       return new Rendering(url, name);\r
-                               } catch (UnsupportedEncodingException e) {\r
-                                       throw new IllegalStateException();\r
-                               }\r
-                       }\r
-               };\r
-               return renderer;\r
-       }\r
-\r
        private class SearchForm extends SessionlessForm<Void> implements Serializable {\r
                private static final long serialVersionUID = 1L;\r
 \r
index 3ea71d675acd88174247219b490b4507428ba3b9..872f038cc22e24b543add54e7e82133d765ca9df 100644 (file)
@@ -43,15 +43,16 @@ import org.wicketstuff.googlecharts.ShapeMarker;
 import com.gitblit.GitBlit;\r
 import com.gitblit.Keys;\r
 import com.gitblit.models.Metric;\r
-import com.gitblit.models.PathModel;\r
 import com.gitblit.models.RepositoryModel;\r
 import com.gitblit.models.UserModel;\r
 import com.gitblit.utils.JGitUtils;\r
-import com.gitblit.utils.MarkdownUtils;\r
 import com.gitblit.utils.StringUtils;\r
 import com.gitblit.wicket.CacheControl;\r
 import com.gitblit.wicket.CacheControl.LastModified;\r
 import com.gitblit.wicket.GitBlitWebSession;\r
+import com.gitblit.wicket.MarkupProcessor;\r
+import com.gitblit.wicket.MarkupProcessor.MarkupDocument;\r
+import com.gitblit.wicket.MarkupProcessor.MarkupSyntax;\r
 import com.gitblit.wicket.WicketUtils;\r
 import com.gitblit.wicket.charting.SecureChart;\r
 import com.gitblit.wicket.panels.BranchesPanel;\r
@@ -137,55 +138,17 @@ public class SummaryPage extends RepositoryPage {
                add(new TagsPanel("tagsPanel", repositoryName, r, numberRefs).hideIfEmpty());\r
                add(new BranchesPanel("branchesPanel", getRepositoryModel(), r, numberRefs, false).hideIfEmpty());\r
 \r
-               String htmlText = null;\r
-               String markdownText = null;\r
-               String readme = null;\r
-               boolean isMarkdown = false;\r
-               try {\r
-                       RevCommit head = JGitUtils.getCommit(r, null);\r
-                       List<String> markdownExtensions = GitBlit.getStrings(Keys.web.markdownExtensions);\r
-                       List<PathModel> paths = JGitUtils.getFilesInPath(r, null, head);\r
-                       for (PathModel path : paths) {\r
-                               if (!path.isTree()) {\r
-                                       String name = path.name.toLowerCase();\r
-                                       if (name.equals("readme") || name.equals("readme.txt")) {\r
-                                               readme = path.name;\r
-                                               isMarkdown = false;\r
-                                       } else if (name.startsWith("readme")) {\r
-                                               if (name.indexOf('.') > -1) {\r
-                                                       String ext = name.substring(name.lastIndexOf('.') + 1);\r
-                                                       if (markdownExtensions.contains(ext)) {\r
-                                                               readme = path.name;\r
-                                                               isMarkdown = true;\r
-                                                               break;\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                               }\r
-                       }\r
-                       if (!StringUtils.isEmpty(readme)) {\r
-                               String [] encodings = GitBlit.getEncodings();\r
-                               markdownText = JGitUtils.getStringContent(r, head.getTree(), readme, encodings);\r
-                               if (isMarkdown) {\r
-                                       htmlText = MarkdownUtils.transformMarkdown(markdownText, getMarkdownLinkRenderer());\r
-                               } else {\r
-                                       htmlText = MarkdownUtils.transformPlainText(markdownText);\r
-                               }\r
-                       }\r
-               } catch (Exception e) {\r
-                       logger.error("failed to transform markdown", e);\r
-                       markdownText = MessageFormat.format("<div class=\"alert alert-error\"><strong>{0}:</strong> {1}</div>{2}", getString("gb.error"), getString("gb.markdownFailure"), markdownText);\r
-                       htmlText = MarkdownUtils.transformPlainText(markdownText);\r
-               }\r
-\r
-               if (StringUtils.isEmpty(htmlText)) {\r
+               RevCommit head = JGitUtils.getCommit(r, null);\r
+               MarkupProcessor processor = new MarkupProcessor(GitBlit.getSettings());\r
+               MarkupDocument markupDoc = processor.parseReadme(r, repositoryName, getBestCommitId(head));\r
+               if (markupDoc.markup == null) {\r
                        add(new Label("readme").setVisible(false));\r
                } else {\r
-                       Fragment fragment = new Fragment("readme", isMarkdown ? "markdownPanel" : "plaintextPanel", this);\r
-                       fragment.add(new Label("readmeFile", readme));\r
+                       Fragment fragment = new Fragment("readme", MarkupSyntax.PLAIN.equals(markupDoc.syntax) ? "plaintextPanel" : "markdownPanel", this);\r
+                       fragment.add(new Label("readmeFile", markupDoc.documentPath));\r
                        // Add the html to the page\r
-                       Component content = new Label("readmeContent", htmlText).setEscapeModelStrings(false);\r
-                       fragment.add(content.setVisible(!StringUtils.isEmpty(htmlText)));\r
+                       Component content = new Label("readmeContent", markupDoc.html).setEscapeModelStrings(false);\r
+                       fragment.add(content.setVisible(!StringUtils.isEmpty(markupDoc.html)));\r
                        add(fragment);\r
                }\r
 \r
index 91bd4aa0525dc1bf084b35b67c793b5961505c6a..9e75fa65856a8103dfa31c917702d80c35d63237 100644 (file)
@@ -1540,6 +1540,29 @@ div.markdown a {
        text-decoration: underline;     \r
 }\r
 \r
+div.markdown table {\r
+       max-width: 100%;\r
+       background-color: transparent;\r
+       border-collapse: collapse;\r
+       border-spacing: 0px;\r
+       font-size: inherit;\r
+       border-width: 0px 1px 1px 0px;\r
+    border-style: solid solid solid none;\r
+    border-color: rgb(221, 221, 221);\r
+    border-image: none;\r
+    border-collapse: separate;\r
+    margin: 10px 0px 20px;\r
+}\r
+\r
+div.markdown table td, div.markdown table th {\r
+       padding: 8px;\r
+       line-height: 20px;\r
+       text-align: left;\r
+       vertical-align: top;\r
+       border-top: 1px solid rgb(221, 221, 221);\r
+       border-left: 1px solid rgb(221, 221, 221);\r
+}\r
+\r
 div.markdown table.text th, div.markdown table.text td {\r
        vertical-align: top;\r
        border-top: 1px solid #ccc;\r