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