Merge pull request #342 from bati11/feature-tasklist

Implement "Task List" in markdown
This commit is contained in:
Naoki Takezoe
2014-11-01 03:09:24 +09:00
12 changed files with 210 additions and 22 deletions

View File

@@ -195,7 +195,7 @@ trait IssuesControllerBase extends ControllerBase {
org.json4s.jackson.Serialization.write(
Map("title" -> x.title,
"content" -> view.Markdown.toHtml(x.content getOrElse "No description given.",
repository, false, true)
repository, false, true, true, isEditable(x.userName, x.repositoryName, x.openedUserName))
))
}
} else Unauthorized
@@ -212,7 +212,7 @@ trait IssuesControllerBase extends ControllerBase {
contentType = formats("json")
org.json4s.jackson.Serialization.write(
Map("content" -> view.Markdown.toHtml(x.content,
repository, false, true)
repository, false, true, true, isEditable(x.userName, x.repositoryName, x.commentedUserName))
))
}
} else Unauthorized

View File

@@ -77,7 +77,9 @@ trait RepositoryViewerControllerBase extends ControllerBase {
contentType = "text/html"
view.helpers.markdown(params("content"), repository,
params("enableWikiLink").toBoolean,
params("enableRefsLink").toBoolean)
params("enableRefsLink").toBoolean,
params("enableTaskList").toBoolean,
hasWritePermission(repository.owner, repository.name, context.loginAccount))
})
/**

View File

@@ -9,6 +9,7 @@ import org.pegdown.ast._
import org.pegdown.LinkRenderer.Rendering
import java.text.Normalizer
import java.util.Locale
import java.util.regex.Pattern
import scala.collection.JavaConverters._
import service.{RequestCache, WikiService}
@@ -18,17 +19,23 @@ object Markdown {
* Converts Markdown of Wiki pages to HTML.
*/
def toHtml(markdown: String, repository: service.RepositoryService.RepositoryInfo,
enableWikiLink: Boolean, enableRefsLink: Boolean)(implicit context: app.Context): String = {
enableWikiLink: Boolean, enableRefsLink: Boolean,
enableTaskList: Boolean = false, hasWritePermission: Boolean = false)(implicit context: app.Context): String = {
// escape issue id
val source = if(enableRefsLink){
val s = if(enableRefsLink){
markdown.replaceAll("(?<=(\\W|^))#(\\d+)(?=(\\W|$))", "issue:$2")
} else markdown
// escape task list
val source = if(enableTaskList){
GitBucketHtmlSerializer.escapeTaskList(s)
} else s
val rootNode = new PegDownProcessor(
Extensions.AUTOLINKS | Extensions.WIKILINKS | Extensions.FENCED_CODE_BLOCKS | Extensions.TABLES | Extensions.HARDWRAPS
).parseMarkdown(source.toCharArray)
new GitBucketHtmlSerializer(markdown, repository, enableWikiLink, enableRefsLink).toHtml(rootNode)
new GitBucketHtmlSerializer(markdown, repository, enableWikiLink, enableRefsLink, enableTaskList, hasWritePermission).toHtml(rootNode)
}
}
@@ -82,7 +89,9 @@ class GitBucketHtmlSerializer(
markdown: String,
repository: service.RepositoryService.RepositoryInfo,
enableWikiLink: Boolean,
enableRefsLink: Boolean
enableRefsLink: Boolean,
enableTaskList: Boolean,
hasWritePermission: Boolean
)(implicit val context: app.Context) extends ToHtmlSerializer(
new GitBucketLinkRender(context, repository, enableWikiLink),
Map[String, VerbatimSerializer](VerbatimSerializer.DEFAULT -> new GitBucketVerbatimSerializer).asJava
@@ -143,7 +152,10 @@ class GitBucketHtmlSerializer(
override def visit(node: TextNode): Unit = {
// convert commit id and username to link.
val text = if(enableRefsLink) convertRefsLinks(node.getText, repository, "issue:") else node.getText
val t = if(enableRefsLink) convertRefsLinks(node.getText, repository, "issue:") else node.getText
// convert task list to checkbox.
val text = if(enableTaskList) GitBucketHtmlSerializer.convertCheckBox(t, hasWritePermission) else t
if (abbreviations.isEmpty) {
printer.print(text)
@@ -151,6 +163,28 @@ class GitBucketHtmlSerializer(
printWithAbbreviations(text)
}
}
override def visit(node: BulletListNode): Unit = {
if (printChildrenToString(node).contains("""class="task-list-item-checkbox" """)) {
printer.println().print("""<ul class="task-list">""").indent(+2)
visitChildren(node)
printer.indent(-2).println().print("</ul>")
} else {
printIndentedTag(node, "ul")
}
}
override def visit(node: ListItemNode): Unit = {
if (printChildrenToString(node).contains("""class="task-list-item-checkbox" """)) {
printer.println()
printer.print("""<li class="task-list-item">""")
visitChildren(node)
printer.print("</li>")
} else {
printer.println()
printTag(node, "li")
}
}
}
object GitBucketHtmlSerializer {
@@ -163,4 +197,14 @@ object GitBucketHtmlSerializer {
val noSpecialChars = StringUtil.urlEncode(normalized)
noSpecialChars.toLowerCase(Locale.ENGLISH)
}
def escapeTaskList(text: String): String = {
Pattern.compile("""^( *)- \[([x| ])\] """, Pattern.MULTILINE).matcher(text).replaceAll("$1* task:$2: ")
}
def convertCheckBox(text: String, hasWritePermission: Boolean): String = {
val disabled = if (hasWritePermission) "" else "disabled"
text.replaceAll("task:x:", """<input type="checkbox" class="task-list-item-checkbox" checked="checked" """ + disabled + "/>")
.replaceAll("task: :", """<input type="checkbox" class="task-list-item-checkbox" """ + disabled + "/>")
}
}

View File

@@ -48,8 +48,8 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache
* Converts Markdown of Wiki pages to HTML.
*/
def markdown(value: String, repository: service.RepositoryService.RepositoryInfo,
enableWikiLink: Boolean, enableRefsLink: Boolean)(implicit context: app.Context): Html =
Html(Markdown.toHtml(value, repository, enableWikiLink, enableRefsLink))
enableWikiLink: Boolean, enableRefsLink: Boolean, enableTaskList: Boolean = false, hasWritePermission: Boolean = false)(implicit context: app.Context): Html =
Html(Markdown.toHtml(value, repository, enableWikiLink, enableRefsLink, enableTaskList, hasWritePermission))
def renderMarkup(filePath: List[String], fileContent: String, branch: String,
repository: service.RepositoryService.RepositoryInfo,