diff --git a/core/util-jvm/src/main/java/org/signal/core/util/Linkifier.kt b/core/util-jvm/src/main/java/org/signal/core/util/Linkifier.kt index 14acc78153..cca9e7310d 100644 --- a/core/util-jvm/src/main/java/org/signal/core/util/Linkifier.kt +++ b/core/util-jvm/src/main/java/org/signal/core/util/Linkifier.kt @@ -28,11 +28,11 @@ object Linkifier { private val CLOSING_BRACKETS = mapOf(')' to '(', ']' to '[', '}' to '{') /** - * Characters we treat as definitely-not-part-of-a-URL when extending past the host. Excluding - * commas/semicolons here lets `https://a.com,https://b.com` resolve to two URLs rather than one. + * Characters we treat as definitely-not-part-of-a-URL when extending past the host. Commas are + * allowed inside a URL, but not when they are acting as a separator before another obvious URL. */ private const val URL_CHAR = - "[^\\s\\u0085\\u00A0\\u1680\\u2000-\\u200D\\u2028\\u2029\\u202A-\\u202F\\u205F\\u2066-\\u2069\\u3000\\uFEFF<>\"'`,;|\\\\]" + "(?:[^\\s\\u0085\\u00A0\\u1680\\u2000-\\u200D\\u2028\\u2029\\u202A-\\u202F\\u205F\\u2066-\\u2069\\u3000\\uFEFF<>\"'`,;|\\\\]|,(?!https?://|www\\.))" /** * A single domain label: letter/digit, optional letter/digit/hyphen body. Used for intermediate diff --git a/core/util-jvm/src/test/java/org/signal/core/util/LinkifierTest.kt b/core/util-jvm/src/test/java/org/signal/core/util/LinkifierTest.kt index 3c06e0e7d1..318b5d041a 100644 --- a/core/util-jvm/src/test/java/org/signal/core/util/LinkifierTest.kt +++ b/core/util-jvm/src/test/java/org/signal/core/util/LinkifierTest.kt @@ -103,6 +103,8 @@ class LinkifierTest(private val case: Case) { Case("multiple trailing punctuation chars are all trimmed", "Wow https://signal.org!!! amazing", listOf(web("https://signal.org"))), Case("trailing slash is preserved", "https://signal.org/ end", listOf(web("https://signal.org/"))), Case("trailing underscore is preserved", "https://example.com/path_ tail", listOf(web("https://example.com/path_"))), + Case("comma in url path is preserved", "Go to https://example.com/a,b/c", listOf(web("https://example.com/a,b/c"))), + Case("comma in url query is preserved", "Go to https://example.com/search?q=a,b", listOf(web("https://example.com/search?q=a,b"))), // ----- bracket / paren handling ----- Case("trailing closing paren without opener is trimmed", "(see https://signal.org)", listOf(web("https://signal.org"))),