diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala
index c4fd085..75e1dee 100644
--- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala
+++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala
@@ -1,6 +1,7 @@
package gitbucket.core.controller
import gitbucket.core.api._
+import gitbucket.core.plugin.PluginRegistry
import gitbucket.core.repo.html
import gitbucket.core.helper
import gitbucket.core.service._
@@ -546,7 +547,9 @@
}
- private val readmeFiles = view.helpers.renderableSuffixes.map(suffix => s"readme${suffix}") ++ Seq("readme.txt", "readme")
+ private val readmeFiles = PluginRegistry().renderableExtensions.map { extension =>
+ s"readme.${extension}"
+ } ++ Seq("readme.txt", "readme")
/**
* Provides HTML of the file list.
diff --git a/src/main/scala/gitbucket/core/plugin/Plugin.scala b/src/main/scala/gitbucket/core/plugin/Plugin.scala
index f51224b..2d3535c 100644
--- a/src/main/scala/gitbucket/core/plugin/Plugin.scala
+++ b/src/main/scala/gitbucket/core/plugin/Plugin.scala
@@ -33,6 +33,11 @@
val javaScripts: Seq[(String, String)] = Nil
/**
+ * Override to declare this plug-in provides renderers.
+ */
+ val renderers: Seq[(String, Renderer)] = Nil
+
+ /**
* This method is invoked in initialization of plugin system.
* Register plugin functionality to PluginRegistry.
*/
@@ -46,6 +51,9 @@
javaScripts.foreach { case (path, script) =>
registry.addJavaScript(path, script)
}
+ renderers.foreach { case (extension, renderer) =>
+ registry.addRenderer(extension, renderer)
+ }
}
/**
diff --git a/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala b/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala
index fd2c329..374ac8a 100644
--- a/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala
+++ b/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala
@@ -24,6 +24,10 @@
private val javaScripts = new ListBuffer[(String, String)]
private val controllers = new ListBuffer[(ControllerBase, String)]
private val images = mutable.Map[String, String]()
+ private val renderers = mutable.Map[String, Renderer]()
+ renderers ++= Seq(
+ "md" -> MarkdownRenderer, "markdown" -> MarkdownRenderer
+ )
def addPlugin(pluginInfo: PluginInfo): Unit = {
plugins += pluginInfo
@@ -60,15 +64,23 @@
def getControllers(): List[(ControllerBase, String)] = controllers.toList
def addJavaScript(path: String, script: String): Unit = {
- javaScripts += Tuple2(path, script)
+ javaScripts += ((path, script))
}
- //def getJavaScripts(): List[(String, String)] = javaScripts.toList
-
def getJavaScript(currentPath: String): List[String] = {
javaScripts.filter(x => currentPath.matches(x._1)).toList.map(_._2)
}
+ def addRenderer(extension: String, renderer: Renderer): Unit = {
+ renderers += ((extension, renderer))
+ }
+
+ def getRenderer(extension: String): Renderer = {
+ renderers.get(extension).getOrElse(DefaultRenderer)
+ }
+
+ def renderableExtensions: Seq[String] = renderers.keys.toSeq
+
private case class GlobalAction(
method: String,
path: String,
@@ -97,6 +109,10 @@
*/
def apply(): PluginRegistry = instance
+ def isRenderable(fileName: String): Boolean = {
+ instance.renderableExtensions.exists(extension => fileName.toLowerCase.endsWith("." + extension))
+ }
+
/**
* Initializes all installed plugins.
*/
diff --git a/src/main/scala/gitbucket/core/plugin/Renderer.scala b/src/main/scala/gitbucket/core/plugin/Renderer.scala
new file mode 100644
index 0000000..8efb125
--- /dev/null
+++ b/src/main/scala/gitbucket/core/plugin/Renderer.scala
@@ -0,0 +1,44 @@
+package gitbucket.core.plugin
+
+import gitbucket.core.controller.Context
+import gitbucket.core.service.RepositoryService
+import gitbucket.core.view.Markdown
+import play.twirl.api.Html
+
+/**
+ * A render engine to render content to HTML.
+ */
+trait Renderer {
+
+ /**
+ * Render the given request to HTML.
+ */
+ def render(request: RenderRequest): Html
+
+}
+
+object MarkdownRenderer extends Renderer {
+ override def render(request: RenderRequest): Html = {
+ import request._
+ Html(Markdown.toHtml(fileContent, repository, enableWikiLink, enableRefsLink)(context))
+ }
+}
+
+object DefaultRenderer extends Renderer {
+ override def render(request: RenderRequest): Html = {
+ import request._
+ Html(
+ s"${
+ fileContent.split("(\\r\\n)|\\n").map(xml.Utility.escape(_)).mkString("
")
+ }"
+ )
+ }
+}
+
+case class RenderRequest(filePath: List[String],
+ fileContent: String,
+ branch: String,
+ repository: RepositoryService.RepositoryInfo,
+ enableWikiLink: Boolean,
+ enableRefsLink: Boolean,
+ context: Context)
\ No newline at end of file
diff --git a/src/main/scala/gitbucket/core/view/helpers.scala b/src/main/scala/gitbucket/core/view/helpers.scala
index 3d52c21..1642353 100644
--- a/src/main/scala/gitbucket/core/view/helpers.scala
+++ b/src/main/scala/gitbucket/core/view/helpers.scala
@@ -5,8 +5,9 @@
import gitbucket.core.controller.Context
import gitbucket.core.model.CommitState
+import gitbucket.core.plugin.{RenderRequest, PluginRegistry, Renderer}
import gitbucket.core.service.{RepositoryService, RequestCache}
-import gitbucket.core.util.{JGitUtil, StringUtil}
+import gitbucket.core.util.{FileUtil, JGitUtil, StringUtil}
import play.twirl.api.Html
@@ -83,14 +84,6 @@
def plural(count: Int, singular: String, plural: String = ""): String =
if(count == 1) singular else if(plural.isEmpty) singular + "s" else plural
- private[this] val renderersBySuffix: Seq[(String, (List[String], String, String, RepositoryService.RepositoryInfo, Boolean, Boolean, Context) => Html)] =
- Seq(
- ".md" -> ((filePath, fileContent, branch, repository, enableWikiLink, enableRefsLink, context) => markdown(fileContent, repository, enableWikiLink, enableRefsLink)(context)),
- ".markdown" -> ((filePath, fileContent, branch, repository, enableWikiLink, enableRefsLink, context) => markdown(fileContent, repository, enableWikiLink, enableRefsLink)(context))
- )
-
- def renderableSuffixes: Seq[String] = renderersBySuffix.map(_._1)
-
/**
* Converts Markdown of Wiki pages to HTML.
*/
@@ -107,15 +100,10 @@
repository: RepositoryService.RepositoryInfo,
enableWikiLink: Boolean, enableRefsLink: Boolean)(implicit context: Context): Html = {
- val fileNameLower = filePath.reverse.head.toLowerCase
- renderersBySuffix.find { case (suffix, _) => fileNameLower.endsWith(suffix) } match {
- case Some((_, handler)) => handler(filePath, fileContent, branch, repository, enableWikiLink, enableRefsLink, context)
- case None => Html(
- s"${
- fileContent.split("(\\r\\n)|\\n").map(xml.Utility.escape(_)).mkString("
")
- }"
- )
- }
+ val fileName = filePath.reverse.head.toLowerCase
+ val extension = FileUtil.getExtension(fileName)
+ val renderer = PluginRegistry().getRenderer(extension)
+ renderer.render(RenderRequest(filePath, fileContent, branch, repository, enableWikiLink, enableRefsLink, context))
}
/**
diff --git a/src/main/twirl/gitbucket/core/repo/blob.scala.html b/src/main/twirl/gitbucket/core/repo/blob.scala.html
index 37b2e73..026e97c 100644
--- a/src/main/twirl/gitbucket/core/repo/blob.scala.html
+++ b/src/main/twirl/gitbucket/core/repo/blob.scala.html
@@ -7,6 +7,7 @@
isBlame: Boolean)(implicit context: gitbucket.core.controller.Context)
@import context._
@import gitbucket.core.view.helpers._
+@import gitbucket.core.plugin.PluginRegistry
@html.main(s"${repository.owner}/${repository.name}", Some(repository)) {
@html.menu("code", repository){