test and implement markdown autolink underscore unescaping

closes #9767
pull/9777/head
Thibault Duplessis 2021-09-11 09:31:01 +02:00
parent 2cd20d46f3
commit 4d9b7a8910
3 changed files with 54 additions and 5 deletions

View File

@ -22,6 +22,8 @@ final class Env(
ec: scala.concurrent.ExecutionContext
) {
import net.{ assetBaseUrl, baseUrl }
private val colls = new UblogColls(db(CollName("ublog_blog")), db(CollName("ublog_post")))
val topic = wire[UblogTopicApi]

View File

@ -1,10 +1,12 @@
package lila.ublog
import scala.concurrent.duration._
import lila.common.Chronometer
import lila.common.config
import lila.common.config.NetConfig
final class UblogMarkup(net: NetConfig) {
final class UblogMarkup(baseUrl: config.BaseUrl, assetBaseUrl: config.AssetBaseUrl) {
private val renderer =
new lila.common.Markdown(
@ -21,11 +23,11 @@ final class UblogMarkup(net: NetConfig) {
type Html = String
def apply(post: UblogPost): String =
cache.get(post.markdown, str => postProcess(renderer(s"ublog:${post.id}")(preProcess(str))))
cache.get(post.markdown, str => postProcess(renderer(s"ublog:${post.id}")(preProcess(str)).pp))
private def preProcess = replaceGameGifs.apply _
private def postProcess(html: String) = imageParagraph(html)
private def postProcess(html: String) = unescapeUnderscoreInLinks(imageParagraph(html))
private val cache = lila.memo.CacheApi.scaffeineNoScheduler
.maximumSize(2048)
@ -33,11 +35,23 @@ final class UblogMarkup(net: NetConfig) {
// replace game GIFs URLs with actual game URLs that can be embedded
private object replaceGameGifs {
val regex = (net.assetBaseUrl + """/game/export/gif(/white|/black|)/(\w{8})\.gif""").r
def apply(markdown: Text) = regex.replaceAllIn(markdown, net.baseUrl.value + "/$2$1")
private val regex = (assetBaseUrl.value + """/game/export/gif(/white|/black|)/(\w{8})\.gif""").r
def apply(markdown: Text) = regex.replaceAllIn(markdown, baseUrl.value + "/$2$1")
}
// put images into a container for styling
private def imageParagraph(markup: Html) =
markup.replace("""<p><img src=""", """<p class="img-container"><img src=""")
// https://github.com/ornicar/lila/issues/9767
// toastui editor escapes `_` as `\_` and it breaks autolinks
private[ublog] object unescapeUnderscoreInLinks {
private val hrefRegex = """href="([^"]+)"""".r
private val contentRegex = """>([^<]+)</a>""".r
private def unescape(txt: String) = txt.replace("""\\_""", "_")
def apply(markup: Html) = contentRegex.replaceAllIn(
hrefRegex.replaceAllIn(markup, m => s"""href="${unescape(m group 1)}""""),
m => s""">${unescape(m group 1)}</a>"""
)
}
}

View File

@ -0,0 +1,33 @@
package lila.ublog
import org.specs2.execute.Result
import org.specs2.mutable.Specification
import scalatags.Text.all._
import lila.common.config
class UblogMarkupTest extends Specification {
val m = new UblogMarkup(config.BaseUrl("https://lichess.org"), config.AssetBaseUrl("https://lichess1.org"))
"backslashUnderscore" should {
"fix href" in {
m.unescapeUnderscoreInLinks(
"""<p><a rel="nofollow noopener noreferrer" href="https://youtu.be/di6W\_i3NiJA">text</a></p>"""
) must_==
"""<p><a rel="nofollow noopener noreferrer" href="https://youtu.be/di6W_i3NiJA">text</a></p>"""
}
"fix link text" in {
m.unescapeUnderscoreInLinks(
"""<p><a rel="nofollow noopener noreferrer" href="#">https://youtu.be/di6W\_i3NiJA</a></p>"""
) must_==
"""<p><a rel="nofollow noopener noreferrer" href="#">https://youtu.be/di6W_i3NiJA</a></p>"""
}
"fix href and link text" in {
m.unescapeUnderscoreInLinks(
"""<p><a rel="nofollow noopener noreferrer" href="https://youtu.be/di6W\_i3NiJA">https://youtu.be/di6W\_i3NiJA</a></p>"""
) must_==
"""<p><a rel="nofollow noopener noreferrer" href="https://youtu.be/di6W_i3NiJA">https://youtu.be/di6W_i3NiJA</a></p>"""
}
}
}