Parse Android message links with matching punctuation rules
This commit is contained in:
1 parent
a76ba87501
commit
0a060d04ca
1 file changed
+34
@@ -0,0 +1,34 @@
|
||||
package com.utun.chat.data
|
||||
|
||||
import java.net.URI
|
||||
|
||||
/** Границы UTF-16 и полный адрес; разбор не меняет текст и не открывает ссылки. */
|
||||
data class MessageLink(val start: Int, val end: Int, val url: String)
|
||||
|
||||
object MessageLinks {
|
||||
private val pattern = Regex("utun://[A-Za-z0-9+/]+={0,2}|(?i:https?://)[^\\s\\p{Z}\\p{Cc}<>\"'`«»“”‘’]+")
|
||||
|
||||
/** Некорректные URL в пользовательском тексте остаются обычным текстом. */
|
||||
fun isWebUrl(url: String): Boolean = try {
|
||||
val uri = URI(url)
|
||||
(uri.scheme.equals("http", true) || uri.scheme.equals("https", true)) &&
|
||||
uri.toURL().let { it.host.isNotEmpty() && it.port in -1..65535 }
|
||||
} catch (_: IllegalArgumentException) { false }
|
||||
catch (_: java.net.URISyntaxException) { false }
|
||||
catch (_: java.net.MalformedURLException) { false }
|
||||
|
||||
fun parse(text: String): List<MessageLink> = pattern.findAll(text).mapNotNull { match ->
|
||||
var url = match.value
|
||||
if (!url.startsWith("utun://")) {
|
||||
while (url.isNotEmpty()) {
|
||||
val last = url.last()
|
||||
val closing = ")]}".indexOf(last)
|
||||
val unmatched = closing >= 0 && url.count { it == last } > url.count { it == "([{"[closing] }
|
||||
if (last !in ".,;:!?" && !unmatched) break
|
||||
url = url.dropLast(1)
|
||||
}
|
||||
if (!isWebUrl(url)) return@mapNotNull null
|
||||
}
|
||||
MessageLink(match.range.first, match.range.first + url.length, url)
|
||||
}.toList()
|
||||
}
|
||||
Reference in new issue
Block a user