mirror of
				https://github.com/gitbucket/gitbucket.git
				synced 2025-10-30 18:15:59 +01:00 
			
		
		
		
	Rewrite relative links to reflect the base url of the repo.
This commit is contained in:
		| @@ -44,7 +44,8 @@ object MyBuild extends Build { | |||||||
|         "org.eclipse.jetty" % "jetty-webapp" % "8.1.8.v20121106" % "container;provided", |         "org.eclipse.jetty" % "jetty-webapp" % "8.1.8.v20121106" % "container;provided", | ||||||
|         "org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" % "container;provided;test" artifacts Artifact("javax.servlet", "jar", "jar"), |         "org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" % "container;provided;test" artifacts Artifact("javax.servlet", "jar", "jar"), | ||||||
|         "junit" % "junit" % "4.11" % "test", |         "junit" % "junit" % "4.11" % "test", | ||||||
|         "org.asciidoctor" % "asciidoctor-java-integration" % "0.1.4" |         "org.asciidoctor" % "asciidoctor-java-integration" % "0.1.4", | ||||||
|  |         "net.sourceforge.htmlcleaner" % "htmlcleaner" % "2.7" | ||||||
|       ), |       ), | ||||||
|       EclipseKeys.withSource := true, |       EclipseKeys.withSource := true, | ||||||
|       javacOptions in compile ++= Seq("-target", "6", "-source", "6"), |       javacOptions in compile ++= Seq("-target", "6", "-source", "6"), | ||||||
|   | |||||||
| @@ -1,17 +1,14 @@ | |||||||
| package view | package view | ||||||
|  |  | ||||||
| import util.StringUtil | import org.asciidoctor.Asciidoctor | ||||||
| import util.ControlUtil._ | import org.asciidoctor.AttributesBuilder | ||||||
| import util.Directory._ | import org.asciidoctor.OptionsBuilder | ||||||
| import org.parboiled.common.StringUtils | import org.asciidoctor.SafeMode | ||||||
| import org.pegdown._ | import org.htmlcleaner.HtmlCleaner | ||||||
| import org.pegdown.ast._ | import org.htmlcleaner.HtmlNode | ||||||
| import org.pegdown.LinkRenderer.Rendering | import org.htmlcleaner.SimpleHtmlSerializer | ||||||
| import java.text.Normalizer | import org.htmlcleaner.TagNode | ||||||
| import java.util.Locale | import org.htmlcleaner.TagNodeVisitor | ||||||
| import scala.collection.JavaConverters._ |  | ||||||
| import service.{ RequestCache, WikiService } |  | ||||||
| import org.asciidoctor.{ Asciidoctor, Attributes, AttributesBuilder, OptionsBuilder, SafeMode } |  | ||||||
|  |  | ||||||
| object Asciidoc { | object Asciidoc { | ||||||
|  |  | ||||||
| @@ -20,14 +17,41 @@ object Asciidoc { | |||||||
|   /** |   /** | ||||||
|    * Converts Markdown of Wiki pages to HTML. |    * Converts Markdown of Wiki pages to HTML. | ||||||
|    */ |    */ | ||||||
|   def toHtml(asciidoc: String, repository: service.RepositoryService.RepositoryInfo, |   def toHtml(asciidoc: String, branch: String, repository: service.RepositoryService.RepositoryInfo, | ||||||
|              enableWikiLink: Boolean, enableRefsLink: Boolean)(implicit context: app.Context): String = { |              enableWikiLink: Boolean, enableRefsLink: Boolean)(implicit context: app.Context): String = { | ||||||
|  |  | ||||||
|     val options = OptionsBuilder.options() |     val options = OptionsBuilder.options() | ||||||
|     options.safe(SafeMode.SECURE) |     options.safe(SafeMode.SECURE) | ||||||
|     val attributes = AttributesBuilder.attributes() |     val attributes = AttributesBuilder.attributes() | ||||||
|     attributes.showTitle(true) |     attributes.showTitle(true) | ||||||
|     options.attributes(attributes.get()) |     options.attributes(attributes.get()) | ||||||
|     asciidoctor.render(asciidoc, options) |     val rendered = asciidoctor.render(asciidoc, options) | ||||||
|  |  | ||||||
|  |     // this is always relative to the base dir of the repo, as we currently only render README files. | ||||||
|  |     val relativeUrlPrefix = s"${helpers.url(repository)}/blob/${branch}/" | ||||||
|  |     prefixRelativeUrls(rendered, relativeUrlPrefix) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   def prefixRelativeUrls(html: String, urlPrefix: String): String = { | ||||||
|  |     val cleaner = new HtmlCleaner() | ||||||
|  |     val node = cleaner.clean(html) | ||||||
|  |     node.traverse(new TagNodeVisitor() { | ||||||
|  |       override def visit(tagNode: TagNode, htmlNode: HtmlNode): Boolean = { | ||||||
|  |         htmlNode match { | ||||||
|  |           case tag: TagNode if tag.getName == "a" => | ||||||
|  |             Option(tag.getAttributeByName("href")) foreach { href => | ||||||
|  |               if (!href.startsWith("/") && !href.startsWith("http://") && !href.startsWith("https://")) { | ||||||
|  |                 tag.addAttribute("href", s"${urlPrefix}${href}") | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  |           case _ => | ||||||
|  |         } | ||||||
|  |         // continue traversal | ||||||
|  |         true | ||||||
|  |       } | ||||||
|  |     }) | ||||||
|  |     new SimpleHtmlSerializer(cleaner.getProperties()).getAsString(node) | ||||||
|  |   } | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -27,12 +27,12 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache | |||||||
|   def plural(count: Int, singular: String, plural: String = ""): String = |   def plural(count: Int, singular: String, plural: String = ""): String = | ||||||
|     if(count == 1) singular else if(plural.isEmpty) singular + "s" else plural |     if(count == 1) singular else if(plural.isEmpty) singular + "s" else plural | ||||||
|  |  | ||||||
|   private[this] val renderersBySuffix: Seq[(String, (String, service.RepositoryService.RepositoryInfo, Boolean, Boolean, app.Context) => Html)] =  |   private[this] val renderersBySuffix: Seq[(String, (String, String, service.RepositoryService.RepositoryInfo, Boolean, Boolean, app.Context) => Html)] = | ||||||
|     Seq( |     Seq( | ||||||
|       ".md" -> ((fileContent, repository, enableWikiLink, enableRefsLink, context) => markdown(fileContent, repository, enableWikiLink, enableRefsLink)(context)), |       ".md" -> ((fileContent, branch, repository, enableWikiLink, enableRefsLink, context) => markdown(fileContent, repository, enableWikiLink, enableRefsLink)(context)), | ||||||
|       ".markdown" -> ((fileContent, repository, enableWikiLink, enableRefsLink, context) => markdown(fileContent, repository, enableWikiLink, enableRefsLink)(context)), |       ".markdown" -> ((fileContent, branch, repository, enableWikiLink, enableRefsLink, context) => markdown(fileContent, repository, enableWikiLink, enableRefsLink)(context)), | ||||||
|       ".adoc" -> ((fileContent, repository, enableWikiLink, enableRefsLink, context) => asciidoc(fileContent, repository, enableWikiLink, enableRefsLink)(context)), |       ".adoc" -> ((fileContent, branch, repository, enableWikiLink, enableRefsLink, context) => asciidoc(fileContent,  branch, repository, enableWikiLink, enableRefsLink)(context)), | ||||||
|       ".asciidoc" -> ((fileContent, repository, enableWikiLink, enableRefsLink, context) => asciidoc(fileContent, repository, enableWikiLink, enableRefsLink)(context)) |       ".asciidoc" -> ((fileContent, branch, repository, enableWikiLink, enableRefsLink, context) => asciidoc(fileContent,  branch, repository, enableWikiLink, enableRefsLink)(context)) | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|   def renderableSuffixes: Seq[String] = renderersBySuffix.map(_._1) |   def renderableSuffixes: Seq[String] = renderersBySuffix.map(_._1) | ||||||
| @@ -44,13 +44,13 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache | |||||||
|                enableWikiLink: Boolean, enableRefsLink: Boolean)(implicit context: app.Context): Html = |                enableWikiLink: Boolean, enableRefsLink: Boolean)(implicit context: app.Context): Html = | ||||||
|     Html(Markdown.toHtml(value, repository, enableWikiLink, enableRefsLink)) |     Html(Markdown.toHtml(value, repository, enableWikiLink, enableRefsLink)) | ||||||
|  |  | ||||||
|   def renderMarkup(fileName: String, fileContent: String, |   def renderMarkup(fileName: String, fileContent: String, branch: String, | ||||||
|                    repository: service.RepositoryService.RepositoryInfo, |                    repository: service.RepositoryService.RepositoryInfo, | ||||||
|                    enableWikiLink: Boolean, enableRefsLink: Boolean)(implicit context: app.Context): Html = { |                    enableWikiLink: Boolean, enableRefsLink: Boolean)(implicit context: app.Context): Html = { | ||||||
|  |  | ||||||
|     val fileNameLower = fileName.toLowerCase |     val fileNameLower = fileName.toLowerCase | ||||||
|     renderersBySuffix.find { case (suffix, _) => fileNameLower.endsWith(suffix) } match { |     renderersBySuffix.find { case (suffix, _) => fileNameLower.endsWith(suffix) } match { | ||||||
|       case Some((_, handler)) => handler(fileContent, repository, enableWikiLink, enableRefsLink, context) |       case Some((_, handler)) => handler(fileContent, branch, repository, enableWikiLink, enableRefsLink, context) | ||||||
|       case None => Html( |       case None => Html( | ||||||
|         s"<tt>${ |         s"<tt>${ | ||||||
|           fileContent.split("(\\r\\n)|\\n").map(xml.Utility.escape(_)).mkString("<br/>") |           fileContent.split("(\\r\\n)|\\n").map(xml.Utility.escape(_)).mkString("<br/>") | ||||||
| @@ -59,9 +59,9 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   def asciidoc(value: String, repository: service.RepositoryService.RepositoryInfo, |   def asciidoc(value: String, branch: String, repository: service.RepositoryService.RepositoryInfo, | ||||||
|                enableWikiLink: Boolean, enableRefsLink: Boolean)(implicit context: app.Context): Html = |                enableWikiLink: Boolean, enableRefsLink: Boolean)(implicit context: app.Context): Html = | ||||||
|     Html(Asciidoc.toHtml(value, repository, enableWikiLink, enableRefsLink)) |     Html(Asciidoc.toHtml(value, branch, repository, enableWikiLink, enableRefsLink)) | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * Returns <img> which displays the avatar icon for the given user name. |    * Returns <img> which displays the avatar icon for the given user name. | ||||||
|   | |||||||
| @@ -80,7 +80,7 @@ | |||||||
|   @readme.map { case(file, content) => |   @readme.map { case(file, content) => | ||||||
|   <div id="readme" class="box"> |   <div id="readme" class="box"> | ||||||
|     <div class="box-header">@file.name</div> |     <div class="box-header">@file.name</div> | ||||||
|     <div class="box-content markdown-body">@renderMarkup(file.name, content, repository, false, false)</div> |     <div class="box-content markdown-body">@renderMarkup(file.name, content, branch, repository, false, false)</div> | ||||||
|   </div> |   </div> | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user