mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-08 14:35:52 +01:00
Fix emoji conversion
This commit is contained in:
@@ -6,7 +6,7 @@ import java.util.Locale
|
|||||||
|
|
||||||
import gitbucket.core.controller.Context
|
import gitbucket.core.controller.Context
|
||||||
import gitbucket.core.service.{RepositoryService, RequestCache}
|
import gitbucket.core.service.{RepositoryService, RequestCache}
|
||||||
import gitbucket.core.util.StringUtil
|
import gitbucket.core.util.{EmojiUtil, StringUtil}
|
||||||
import io.github.gitbucket.markedj._
|
import io.github.gitbucket.markedj._
|
||||||
import io.github.gitbucket.markedj.Utils._
|
import io.github.gitbucket.markedj.Utils._
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ object Markdown {
|
|||||||
val renderer = new GitBucketMarkedRenderer(options, repository,
|
val renderer = new GitBucketMarkedRenderer(options, repository,
|
||||||
enableWikiLink, enableRefsLink, enableAnchor, enableTaskList, hasWritePermission, pages)
|
enableWikiLink, enableRefsLink, enableAnchor, enableTaskList, hasWritePermission, pages)
|
||||||
|
|
||||||
helpers.decorateHtml(Marked.marked(source, options, renderer), repository)
|
EmojiUtil.convertEmojis(Marked.marked(source, options, renderer))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache
|
|||||||
* Converts commit id, issue id and username to the link.
|
* Converts commit id, issue id and username to the link.
|
||||||
*/
|
*/
|
||||||
def link(value: String, repository: RepositoryService.RepositoryInfo)(implicit context: Context): Html =
|
def link(value: String, repository: RepositoryService.RepositoryInfo)(implicit context: Context): Html =
|
||||||
Html(decorateHtml(convertRefsLinks(value, repository), repository))
|
Html(EmojiUtil.convertEmojis(convertRefsLinks(value, repository)))
|
||||||
|
|
||||||
def cut(value: String, length: Int): String =
|
def cut(value: String, length: Int): String =
|
||||||
if(value.length > length){
|
if(value.length > length){
|
||||||
@@ -321,7 +321,7 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache
|
|||||||
// This pattern comes from: http://stackoverflow.com/a/4390768/1771641 (extract-url-from-string)
|
// This pattern comes from: http://stackoverflow.com/a/4390768/1771641 (extract-url-from-string)
|
||||||
private[this] val detectAndRenderLinksRegex = """(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,13}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))""".r
|
private[this] val detectAndRenderLinksRegex = """(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,13}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))""".r
|
||||||
|
|
||||||
def detectAndRenderLinks(text: String): Html = {
|
def detectAndRenderLinks(text: String)(implicit context: Context): String = {
|
||||||
val matches = detectAndRenderLinksRegex.findAllMatchIn(text).toSeq
|
val matches = detectAndRenderLinksRegex.findAllMatchIn(text).toSeq
|
||||||
|
|
||||||
val (x, pos) = matches.foldLeft((collection.immutable.Seq.empty[Html], 0)){ case ((x, pos), m) =>
|
val (x, pos) = matches.foldLeft((collection.immutable.Seq.empty[Html], 0)){ case ((x, pos), m) =>
|
||||||
@@ -335,36 +335,38 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache
|
|||||||
// append rest fragment
|
// append rest fragment
|
||||||
val out = if (pos < text.length) x :+ HtmlFormat.escape(text.substring(pos)) else x
|
val out = if (pos < text.length) x :+ HtmlFormat.escape(text.substring(pos)) else x
|
||||||
|
|
||||||
HtmlFormat.fill(out)
|
EmojiUtil.convertEmojis(HtmlFormat.fill(out).toString)
|
||||||
|
//HtmlFormat.fill(out).toString
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Decorate text in HTML by TextDecorator.
|
// * Decorate text in HTML by TextDecorator.
|
||||||
*
|
// *
|
||||||
* TODO Move to the other place.
|
// * TODO Move to the other place.
|
||||||
*/
|
// */
|
||||||
def decorateHtml(text: String, repository: RepositoryInfo)(implicit context: Context): String = {
|
// def decorateHtml(text: String, repository: RepositoryInfo)(implicit context: Context): String = {
|
||||||
// val textDecorators = PluginRegistry().getTextDecorators
|
//
|
||||||
|
//// val textDecorators = PluginRegistry().getTextDecorators
|
||||||
def processNode(n: Node): Unit = {
|
//
|
||||||
n match {
|
// def processNode(n: Node): Unit = {
|
||||||
case x: Element => {
|
// n match {
|
||||||
if(x.hasText && x.ownText.nonEmpty){
|
// case x: Element => {
|
||||||
val text = EmojiUtil.convertEmojis(x.ownText)
|
// if(x.hasText && x.ownText.nonEmpty){
|
||||||
// val text = textDecorators.foldLeft(x.ownText){ case (text, textDecorator) =>
|
// val text = EmojiUtil.convertEmojis(x.ownText)
|
||||||
// textDecorator.decorate(text, repository)
|
//// val text = textDecorators.foldLeft(x.ownText){ case (text, textDecorator) =>
|
||||||
// }
|
//// textDecorator.decorate(text, repository)
|
||||||
x.html(text)
|
//// }
|
||||||
}
|
// x.html(text)
|
||||||
x.children.toArray.foreach { c =>
|
// }
|
||||||
processNode(c.asInstanceOf[Node])
|
// x.children.toArray.foreach { c =>
|
||||||
}
|
// processNode(c.asInstanceOf[Node])
|
||||||
}
|
// }
|
||||||
case _ => ()
|
// }
|
||||||
}
|
// case _ => ()
|
||||||
}
|
// }
|
||||||
val body = Jsoup.parseBodyFragment(text).getElementsByTag("body").get(0)
|
// }
|
||||||
processNode(body)
|
// val body = Jsoup.parseBodyFragment(text).getElementsByTag("body").get(0)
|
||||||
body.html
|
// processNode(body)
|
||||||
}
|
// body.html
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@x.description.map { description =>
|
@x.description.map { description =>
|
||||||
<div class="normal muted" style="margin-left: 36px; font-size: 80%;">@helpers.detectAndRenderLinks(description)</div>
|
<div class="normal muted" style="margin-left: 36px; font-size: 80%;">@Html(helpers.detectAndRenderLinks(description))</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,58 +1,62 @@
|
|||||||
package gitbucket.core.view
|
package gitbucket.core.view
|
||||||
|
|
||||||
|
import gitbucket.core.controller.Context
|
||||||
|
import gitbucket.core.service.RepositoryService.RepositoryInfo
|
||||||
import org.scalatest.FunSpec
|
import org.scalatest.FunSpec
|
||||||
|
import org.scalatest.mock.MockitoSugar
|
||||||
|
|
||||||
class HelpersSpec extends FunSpec {
|
class HelpersSpec extends FunSpec with MockitoSugar {
|
||||||
|
|
||||||
|
implicit val context = mock[Context]
|
||||||
import helpers._
|
import helpers._
|
||||||
|
|
||||||
describe("detect and render links") {
|
describe("detect and render links") {
|
||||||
|
|
||||||
it("should pass identical string when no link is present") {
|
it("should pass identical string when no link is present") {
|
||||||
val before = "Description"
|
val before = "Description"
|
||||||
val after = detectAndRenderLinks(before).toString()
|
val after = detectAndRenderLinks(before)
|
||||||
assert(after == before)
|
assert(after == before)
|
||||||
}
|
}
|
||||||
|
|
||||||
it("should convert a single link") {
|
it("should convert a single link") {
|
||||||
val before = "http://example.com"
|
val before = "http://example.com"
|
||||||
val after = detectAndRenderLinks(before).toString()
|
val after = detectAndRenderLinks(before)
|
||||||
assert(after == """<a href="http://example.com">http://example.com</a>""")
|
assert(after == """<a href="http://example.com">http://example.com</a>""")
|
||||||
}
|
}
|
||||||
|
|
||||||
it("should convert a single link within trailing text") {
|
it("should convert a single link within trailing text") {
|
||||||
val before = "Example Project. http://example.com"
|
val before = "Example Project. http://example.com"
|
||||||
val after = detectAndRenderLinks(before).toString()
|
val after = detectAndRenderLinks(before)
|
||||||
assert(after == """Example Project. <a href="http://example.com">http://example.com</a>""")
|
assert(after == """Example Project. <a href="http://example.com">http://example.com</a>""")
|
||||||
}
|
}
|
||||||
|
|
||||||
it("should convert a mulitple links within text") {
|
it("should convert a mulitple links within text") {
|
||||||
val before = "Example Project. http://example.com. (See also https://github.com/)"
|
val before = "Example Project. http://example.com. (See also https://github.com/)"
|
||||||
val after = detectAndRenderLinks(before).toString()
|
val after = detectAndRenderLinks(before)
|
||||||
assert(after == """Example Project. <a href="http://example.com">http://example.com</a>. (See also <a href="https://github.com/">https://github.com/</a>)""")
|
assert(after == """Example Project. <a href="http://example.com">http://example.com</a>. (See also <a href="https://github.com/">https://github.com/</a>)""")
|
||||||
}
|
}
|
||||||
|
|
||||||
it("should properly escape html metacharacters") {
|
it("should properly escape html metacharacters") {
|
||||||
val before = "<>&"
|
val before = "<>&"
|
||||||
val after = detectAndRenderLinks(before).toString()
|
val after = detectAndRenderLinks(before)
|
||||||
assert(after == """<>&""")
|
assert(after == """<>&""")
|
||||||
}
|
}
|
||||||
|
|
||||||
it("should escape html metacharacters adjacent to a link") {
|
it("should escape html metacharacters adjacent to a link") {
|
||||||
val before = "<http://example.com>"
|
val before = "<http://example.com>"
|
||||||
val after = detectAndRenderLinks(before).toString()
|
val after = detectAndRenderLinks(before)
|
||||||
assert(after == """<<a href="http://example.com">http://example.com</a>>""")
|
assert(after == """<<a href="http://example.com">http://example.com</a>>""")
|
||||||
}
|
}
|
||||||
|
|
||||||
it("should stop link recognition at a metacharacter") {
|
it("should stop link recognition at a metacharacter") {
|
||||||
val before = "http://exa<mple.com"
|
val before = "http://exa<mple.com"
|
||||||
val after = detectAndRenderLinks(before).toString()
|
val after = detectAndRenderLinks(before)
|
||||||
assert(after == """<a href="http://exa">http://exa</a><mple.com""")
|
assert(after == """<a href="http://exa">http://exa</a><mple.com""")
|
||||||
}
|
}
|
||||||
|
|
||||||
it("should make sure there are no double quotes in the href attribute") {
|
it("should make sure there are no double quotes in the href attribute") {
|
||||||
val before = "http://exa\"mple.com"
|
val before = "http://exa\"mple.com"
|
||||||
val after = detectAndRenderLinks(before).toString()
|
val after = detectAndRenderLinks(before)
|
||||||
assert(after == """<a href="http://exa"mple.com">http://exa"mple.com</a>""")
|
assert(after == """<a href="http://exa"mple.com">http://exa"mple.com</a>""")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user