diff --git a/src/main/scala/gitbucket/core/view/LinkConverter.scala b/src/main/scala/gitbucket/core/view/LinkConverter.scala index 36d55f5..3f2abf8 100644 --- a/src/main/scala/gitbucket/core/view/LinkConverter.scala +++ b/src/main/scala/gitbucket/core/view/LinkConverter.scala @@ -7,13 +7,31 @@ trait LinkConverter { self: RequestCache => /** - * Converts issue id, username and commit id to link. + * Creates a link to the issue or the pull request from the issue id. */ - protected def convertRefsLinks(value: String, repository: RepositoryService.RepositoryInfo, + protected def createIssueLink(repository: RepositoryService.RepositoryInfo, issueId: Int)(implicit context: Context): String = { + val userName = repository.repository.userName + val repositoryName = repository.repository.repositoryName + + getIssue(userName, repositoryName, issueId.toString) match { + case Some(issue) if (issue.isPullRequest) => + s"""Pull #${issueId}""" + case Some(_) => + s"""Issue #${issueId}""" + case None => + s"Unknown #${issueId}" + } + } + + + /** + * Converts issue id, username and commit id to link in the given text. + */ + protected def convertRefsLinks(text: String, repository: RepositoryService.RepositoryInfo, issueIdPrefix: String = "#", escapeHtml: Boolean = true)(implicit context: Context): String = { // escape HTML tags - val escaped = if(escapeHtml) value.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """) else value + val escaped = if(escapeHtml) text.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """) else text escaped // convert username/project@SHA to link @@ -26,10 +44,12 @@ // convert username/project#Num to link .replaceBy( ("(?<=(^|\\W))([a-zA-Z0-9\\-_]+)/([a-zA-Z0-9\\-_\\.]+)" + issueIdPrefix + "([0-9]+)(?=(\\W|$))").r){ m => getIssue(m.group(2), m.group(3), m.group(4)) match { - case Some(issue) if (issue.isPullRequest) - => Some( s"""${m.group(2)}/${m.group(3)}#${m.group(4)}""") - case Some(_) => Some( s"""${m.group(2)}/${m.group(3)}#${m.group(4)}""") - case None => Some( s"""${m.group(2)}/${m.group(3)}#${m.group(4)}""") + case Some(issue) if (issue.isPullRequest) => + Some(s"""${m.group(2)}/${m.group(3)}#${m.group(4)}""") + case Some(_) => + Some(s"""${m.group(2)}/${m.group(3)}#${m.group(4)}""") + case None => + Some(s"""${m.group(2)}/${m.group(3)}#${m.group(4)}""") } } @@ -43,10 +63,12 @@ // convert username#Num to link .replaceBy( ("(?<=(^|\\W))([a-zA-Z0-9\\-_]+)" + issueIdPrefix + "([0-9]+)(?=(\\W|$))").r ) { m => getIssue(m.group(2), repository.name, m.group(3)) match { - case Some(issue) if(issue.isPullRequest) - => Some(s"""${m.group(2)}#${m.group(3)}""") - case Some(_) => Some(s"""${m.group(2)}#${m.group(3)}""") - case None => Some(s"""${m.group(2)}#${m.group(3)}""") + case Some(issue) if(issue.isPullRequest) => + Some(s"""${m.group(2)}#${m.group(3)}""") + case Some(_) => + Some(s"""${m.group(2)}#${m.group(3)}""") + case None => + Some(s"""${m.group(2)}#${m.group(3)}""") } } @@ -54,10 +76,12 @@ .replaceBy(("(?<=(^|\\W))(GH-|" + issueIdPrefix + ")([0-9]+)(?=(\\W|$))").r){ m => val prefix = if(m.group(2) == "issue:") "#" else m.group(2) getIssue(repository.owner, repository.name, m.group(3)) match { - case Some(issue) if(issue.isPullRequest) - => Some(s"""${prefix}${m.group(3)}""") - case Some(_) => Some(s"""${prefix}${m.group(3)}""") - case None => Some(s"""${m.group(2)}${m.group(3)}""") + case Some(issue) if(issue.isPullRequest) => + Some(s"""${prefix}${m.group(3)}""") + case Some(_) => + Some(s"""${prefix}${m.group(3)}""") + case None => + Some(s"""${m.group(2)}${m.group(3)}""") } } diff --git a/src/main/scala/gitbucket/core/view/helpers.scala b/src/main/scala/gitbucket/core/view/helpers.scala index 8f7dd03..3ee2c91 100644 --- a/src/main/scala/gitbucket/core/view/helpers.scala +++ b/src/main/scala/gitbucket/core/view/helpers.scala @@ -93,6 +93,10 @@ pages: List[String] = Nil)(implicit context: Context): Html = Html(Markdown.toHtml(value, repository, enableWikiLink, enableRefsLink, true, enableTaskList, hasWritePermission, pages)) + /** + * Render the given source (only markdown is supported in default) as HTML. + * You can test if a file is renderable in this method by [[isRenderable()]]. + */ def renderMarkup(filePath: List[String], fileContent: String, branch: String, repository: RepositoryService.RepositoryInfo, enableWikiLink: Boolean, enableRefsLink: Boolean, enableAnchor: Boolean)(implicit context: Context): Html = { @@ -103,11 +107,21 @@ renderer.render(RenderRequest(filePath, fileContent, branch, repository, enableWikiLink, enableRefsLink, enableAnchor, context)) } + /** + * Tests whether the given file is renderable. It's tested by the file extension. + */ def isRenderable(fileName: String): Boolean = { PluginRegistry().renderableExtensions.exists(extension => fileName.toLowerCase.endsWith("." + extension)) } /** + * Creates a link to the issue or the pull request from the issue id. + */ + def issueLink(repository: RepositoryService.RepositoryInfo, issueId: Int)(implicit context: Context): Html = { + Html(createIssueLink(repository, issueId)) + } + + /** * Returns <img> which displays the avatar icon for the given user name. * This method looks up Gravatar if avatar icon has not been configured in user settings. */ diff --git a/src/main/twirl/gitbucket/core/issues/commentlist.scala.html b/src/main/twirl/gitbucket/core/issues/commentlist.scala.html index f6a7ec7..bed5ea8 100644 --- a/src/main/twirl/gitbucket/core/issues/commentlist.scala.html +++ b/src/main/twirl/gitbucket/core/issues/commentlist.scala.html @@ -55,7 +55,7 @@ } else { @if(comment.action == "refer"){ @defining(comment.content.split(":")){ case Array(issueId, rest @ _*) => - Issue #@issueId: @rest.mkString(":") + @issueLink(repository, issueId.toInt): @rest.mkString(":") } } else {
@markdown(comment.content, repository, false, true, true, hasWritePermission)