From e1c155d09d2f4da95a33476fe4e68d2b3e7526d7 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Mon, 21 Sep 2015 12:08:16 +0900 Subject: [PATCH] Fix Markdown testcase --- .../scala/gitbucket/core/view/Markdown.scala | 228 +++++++++--------- ...erializerSpec.scala => MarkdownSpec.scala} | 4 +- 2 files changed, 118 insertions(+), 114 deletions(-) rename src/test/scala/gitbucket/core/view/{GitBucketHtmlSerializerSpec.scala => MarkdownSpec.scala} (95%) diff --git a/src/main/scala/gitbucket/core/view/Markdown.scala b/src/main/scala/gitbucket/core/view/Markdown.scala index 9be7ae97e..2e126eb6c 100644 --- a/src/main/scala/gitbucket/core/view/Markdown.scala +++ b/src/main/scala/gitbucket/core/view/Markdown.scala @@ -1,6 +1,7 @@ package gitbucket.core.view import java.text.Normalizer +import java.util.regex.Pattern import java.util.{Optional, Locale} import gitbucket.core.controller.Context @@ -19,7 +20,7 @@ object Markdown { * @param enableRefsLink if true then issue reference (e.g. #123) is rendered as link * @param enableAnchor if true then anchor for headline is generated * @param enableTaskList if true then task list syntax is available - * @param hasWritePermission + * @param hasWritePermission true if user has writable to ths given repository * @param pages the list of existing Wiki pages */ def toHtml(markdown: String, @@ -37,8 +38,7 @@ object Markdown { // escape task list val source = if(enableTaskList){ - s.replaceAll("""(?m)^( *)- \[([x| ])\] """, "$1* task:$2: ") -// escapeTaskList(s) + escapeTaskList(s) } else s val options = new Options() @@ -46,133 +46,137 @@ object Markdown { Marked.marked(source, options, renderer) } -// private def escapeTaskList(text: String): String = { -// Pattern.compile("""^( *)- \[([x| ])\] """, Pattern.MULTILINE).matcher(text).replaceAll("$1* task:$2: ") -// } + /** + * Extends markedj Renderer for GitBucket + */ + class GitBucketMarkedRenderer(options: Options, repository: RepositoryService.RepositoryInfo, + enableWikiLink: Boolean, enableRefsLink: Boolean, enableAnchor: Boolean, enableTaskList: Boolean, hasWritePermission: Boolean, + pages: List[String]) + (implicit val context: Context) extends Renderer(options) with LinkConverter with RequestCache { -} + override def heading(text: String, level: Int, raw: String): String = { + val id = generateAnchorName(text) + val out = new StringBuilder() -class GitBucketMarkedRenderer(options: Options, repository: RepositoryService.RepositoryInfo, - enableWikiLink: Boolean, enableRefsLink: Boolean, enableAnchor: Boolean, enableTaskList: Boolean, hasWritePermission: Boolean, - pages: List[String]) - (implicit val context: Context) extends Renderer(options) with LinkConverter with RequestCache { + out.append("") - override def heading(text: String, level: Int, raw: String): String = { - val id = generateAnchorName(text) - val out = new StringBuilder() - - out.append("") - - if(enableAnchor){ - out.append("") - out.append("") - } - - out.append(text) - out.append("\n") - out.toString() - } - - override def code(code: String, lang: Optional[String], escaped: Boolean): String = { - "
" +
-      (if(escaped) code else escape(code, true)) + "
" - } - - override def list(body: String, ordered: Boolean): String = { - var listType: String = null - if (ordered) { - listType = "ol" - } - else { - listType = "ul" - } - if(body.contains("""class="task-list-item-checkbox"""")){ - return "<" + listType + " class=\"task-list\">\n" + body + "\n" - } else { - return "<" + listType + ">\n" + body + "\n" - } - } - - override def listitem(text: String): String = { - if(text.contains("""class="task-list-item-checkbox" """)){ - return "
  • " + text + "
  • \n" - } else { - return "
  • " + text + "
  • \n" - } - } - - override def text(text: String): String = { - // convert commit id and username to link. - val t1 = if(enableRefsLink) convertRefsLinks(text, repository, "issue:") else text - - // convert task list to checkbox. - val t2 = if(enableTaskList) convertCheckBox(t1, hasWritePermission) else t1 - - t2 - } - - override def link(href: String, title: Optional[String], text: String): String = { - super.link(fixUrl(href, true), title, text) - } - - override def image(href: String, title: Optional[String], text: String): String = { - super.image(fixUrl(href, true), title, text) - } - - override def nolink(text: String): String = { - if(enableWikiLink && text.startsWith("[[") && text.endsWith("]]")){ - val link = text.replaceAll("(^\\[\\[|\\]\\]$)", "") - - val (label, page) = if(link.contains('|')){ - val i = link.indexOf('|') - (link.substring(0, i), link.substring(i + 1)) - } else { - (link, link) + if(enableAnchor){ + out.append("") + out.append("") } - val url = repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/wiki/" + StringUtil.urlEncode(page) - if(pages.contains(page)){ - "" + escape(label) + "" - } else { - "" + escape(label) + "" - } - } else { - escape(text) + out.append(text) + out.append("
    \n") + out.toString() } + + override def code(code: String, lang: Optional[String], escaped: Boolean): String = { + "
    " +
    +        (if(escaped) code else escape(code, true)) + "
    " + } + + override def list(body: String, ordered: Boolean): String = { + var listType: String = null + if (ordered) { + listType = "ol" + } + else { + listType = "ul" + } + if(body.contains("""class="task-list-item-checkbox"""")){ + return "<" + listType + " class=\"task-list\">\n" + body + "\n" + } else { + return "<" + listType + ">\n" + body + "\n" + } + } + + override def listitem(text: String): String = { + if(text.contains("""class="task-list-item-checkbox" """)){ + return "
  • " + text + "
  • \n" + } else { + return "
  • " + text + "
  • \n" + } + } + + override def text(text: String): String = { + // convert commit id and username to link. + val t1 = if(enableRefsLink) convertRefsLinks(text, repository, "issue:") else text + + // convert task list to checkbox. + val t2 = if(enableTaskList) convertCheckBox(t1, hasWritePermission) else t1 + + t2 + } + + override def link(href: String, title: Optional[String], text: String): String = { + super.link(fixUrl(href, true), title, text) + } + + override def image(href: String, title: Optional[String], text: String): String = { + super.image(fixUrl(href, true), title, text) + } + + override def nolink(text: String): String = { + if(enableWikiLink && text.startsWith("[[") && text.endsWith("]]")){ + val link = text.replaceAll("(^\\[\\[|\\]\\]$)", "") + + val (label, page) = if(link.contains('|')){ + val i = link.indexOf('|') + (link.substring(0, i), link.substring(i + 1)) + } else { + (link, link) + } + + val url = repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/wiki/" + StringUtil.urlEncode(page) + if(pages.contains(page)){ + "" + escape(label) + "" + } else { + "" + escape(label) + "" + } + } else { + escape(text) + } + } + + private def fixUrl(url: String, isImage: Boolean = false): String = { + if(url.startsWith("http://") || url.startsWith("https://") || url.startsWith("/")){ + url + } else if(url.startsWith("#")){ + ("#" + generateAnchorName(url.substring(1))) + } else if(!enableWikiLink){ + if(context.currentPath.contains("/blob/")){ + url + (if(isImage) "?raw=true" else "") + } else if(context.currentPath.contains("/tree/")){ + val paths = context.currentPath.split("/") + val branch = if(paths.length > 3) paths.drop(4).mkString("/") else repository.repository.defaultBranch + repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/blob/" + branch + "/" + url + (if(isImage) "?raw=true" else "") + } else { + val paths = context.currentPath.split("/") + val branch = if(paths.length > 3) paths.last else repository.repository.defaultBranch + repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/blob/" + branch + "/" + url + (if(isImage) "?raw=true" else "") + } + } else { + repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/wiki/_blob/" + url + } + } + } - private def fixUrl(url: String, isImage: Boolean = false): String = { - if(url.startsWith("http://") || url.startsWith("https://") || url.startsWith("/")){ - url - } else if(url.startsWith("#")){ - ("#" + generateAnchorName(url.substring(1))) - } else if(!enableWikiLink){ - if(context.currentPath.contains("/blob/")){ - url + (if(isImage) "?raw=true" else "") - } else if(context.currentPath.contains("/tree/")){ - val paths = context.currentPath.split("/") - val branch = if(paths.length > 3) paths.drop(4).mkString("/") else repository.repository.defaultBranch - repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/blob/" + branch + "/" + url + (if(isImage) "?raw=true" else "") - } else { - val paths = context.currentPath.split("/") - val branch = if(paths.length > 3) paths.last else repository.repository.defaultBranch - repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/blob/" + branch + "/" + url + (if(isImage) "?raw=true" else "") - } - } else { - repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/wiki/_blob/" + url - } + def escapeTaskList(text: String): String = { + Pattern.compile("""^( *)- \[([x| ])\] """, Pattern.MULTILINE).matcher(text).replaceAll("$1* task:$2: ") } - private def generateAnchorName(text: String): String = { + def generateAnchorName(text: String): String = { val normalized = Normalizer.normalize(text.replaceAll("<.*>", "").replaceAll("[\\s]", "-"), Normalizer.Form.NFD) val encoded = StringUtil.urlEncode(normalized) encoded.toLowerCase(Locale.ENGLISH) } - private def convertCheckBox(text: String, hasWritePermission: Boolean): String = { + def convertCheckBox(text: String, hasWritePermission: Boolean): String = { val disabled = if (hasWritePermission) "" else "disabled" text.replaceAll("task:x:", """") .replaceAll("task: :", """") } } + diff --git a/src/test/scala/gitbucket/core/view/GitBucketHtmlSerializerSpec.scala b/src/test/scala/gitbucket/core/view/MarkdownSpec.scala similarity index 95% rename from src/test/scala/gitbucket/core/view/GitBucketHtmlSerializerSpec.scala rename to src/test/scala/gitbucket/core/view/MarkdownSpec.scala index 82fb3d958..a2ec2e9c4 100644 --- a/src/test/scala/gitbucket/core/view/GitBucketHtmlSerializerSpec.scala +++ b/src/test/scala/gitbucket/core/view/MarkdownSpec.scala @@ -2,9 +2,9 @@ package gitbucket.core.view import org.specs2.mutable._ -class GitBucketHtmlSerializerSpec extends Specification { +class MarkdownSpec extends Specification { - import GitBucketHtmlSerializer._ + import Markdown._ "generateAnchorName" should { "convert whitespace characters to hyphens" in {