- Fixes new lines after images

- Fixes urls with - https://github.com/vitorpamplona/amethyst/issues/536
This commit is contained in:
Vitor Pamplona
2023-08-02 18:56:01 -04:00
parent da3cecd324
commit 4bdb5a28d0
2 changed files with 60 additions and 43 deletions

View File

@@ -668,7 +668,7 @@ class RichTextParserTest {
fun testTextToParse() { fun testTextToParse() {
val state = RichTextParser().parseText(textToParse, ImmutableListOfLists()) val state = RichTextParser().parseText(textToParse, ImmutableListOfLists())
Assert.assertEquals( Assert.assertEquals(
"relay.shitforce.one, relayable.org, universe.nostrich.land, nos.lol, universe.nostrich.land?lang=zh, universe.nostrich.land?lang=en, relay.damus.io, relay.nostr.wirednet.jp, offchain.pub, nostr.rocks, relay.wellorder.net, nostr.oxtr.dev, universe.nostrich.land?lang=ja, relay.mostr.pub, nostr.bitcoiner.social, ⚡41.7M, Nostr-Check.com, MR.Rabbit, Ancap.su,satscoinsv@getalby.com, miceliomad@miceliomad.github.io/nostr/, zapper.lol, smies.me, baller.hodl", "relay.shitforce.one, relayable.org, universe.nostrich.land, nos.lol, universe.nostrich.land?lang=zh, universe.nostrich.land?lang=en, relay.damus.io, relay.nostr.wirednet.jp, offchain.pub, nostr.rocks, relay.wellorder.net, nostr.oxtr.dev, universe.nostrich.land?lang=ja, relay.mostr.pub, nostr.bitcoiner.social, Nostr-Check.com, MR.Rabbit, Ancap.su, zapper.lol, smies.me, baller.hodl",
state.urlSet.joinToString(", ") state.urlSet.joinToString(", ")
) )
@@ -806,134 +806,101 @@ class RichTextParserTest {
"HashTag(#bitcoin,)", "HashTag(#bitcoin,)",
"RegularText(1.7K,)", "RegularText(1.7K,)",
"RegularText(109)", "RegularText(109)",
"RegularText()",
"HashTag(#concussion,)", "HashTag(#concussion,)",
"RegularText(1.1K,)", "RegularText(1.1K,)",
"RegularText(25)", "RegularText(25)",
"RegularText()",
"HashTag(#press,)", "HashTag(#press,)",
"RegularText(0.9K,)", "RegularText(0.9K,)",
"RegularText(65)", "RegularText(65)",
"RegularText()",
"HashTag(#france,)", "HashTag(#france,)",
"RegularText(492,)", "RegularText(492,)",
"RegularText(46)", "RegularText(46)",
"RegularText()",
"HashTag(#presse,)", "HashTag(#presse,)",
"RegularText(480,)", "RegularText(480,)",
"RegularText(42)", "RegularText(42)",
"RegularText()",
"HashTag(#covid19,)", "HashTag(#covid19,)",
"RegularText(465,)", "RegularText(465,)",
"RegularText(65)", "RegularText(65)",
"RegularText()",
"HashTag(#nostr,)", "HashTag(#nostr,)",
"RegularText(414,)", "RegularText(414,)",
"RegularText(109)", "RegularText(109)",
"RegularText()",
"HashTag(#zapathon,)", "HashTag(#zapathon,)",
"RegularText(386,)", "RegularText(386,)",
"RegularText(76)", "RegularText(76)",
"RegularText()",
"HashTag(#rssfeed,)", "HashTag(#rssfeed,)",
"RegularText(309,)", "RegularText(309,)",
"RegularText(53)", "RegularText(53)",
"RegularText()",
"HashTag(#btc,)", "HashTag(#btc,)",
"RegularText(299,)", "RegularText(299,)",
"RegularText(109)", "RegularText(109)",
"RegularText()",
"HashTag(#news,)", "HashTag(#news,)",
"RegularText(294,)", "RegularText(294,)",
"RegularText(91)", "RegularText(91)",
"RegularText()",
"HashTag(#zap,)", "HashTag(#zap,)",
"RegularText(283,)", "RegularText(283,)",
"RegularText(109)", "RegularText(109)",
"RegularText()",
"HashTag(#linux,)", "HashTag(#linux,)",
"RegularText(253,)", "RegularText(253,)",
"RegularText(88)", "RegularText(88)",
"RegularText()",
"HashTag(#respond,)", "HashTag(#respond,)",
"RegularText(246,)", "RegularText(246,)",
"RegularText(90)", "RegularText(90)",
"RegularText()",
"HashTag(#kompost,)", "HashTag(#kompost,)",
"RegularText(240,)", "RegularText(240,)",
"RegularText(31)", "RegularText(31)",
"RegularText()",
"HashTag(#plebchain,)", "HashTag(#plebchain,)",
"RegularText(236,)", "RegularText(236,)",
"RegularText(109)", "RegularText(109)",
"RegularText()",
"HashTag(#gardenaward,)", "HashTag(#gardenaward,)",
"RegularText(236,)", "RegularText(236,)",
"RegularText(31)", "RegularText(31)",
"RegularText()",
"HashTag(#start,)", "HashTag(#start,)",
"RegularText(236,)", "RegularText(236,)",
"RegularText(31)", "RegularText(31)",
"RegularText()",
"HashTag(#unicef,)", "HashTag(#unicef,)",
"RegularText(233,)", "RegularText(233,)",
"RegularText(32)", "RegularText(32)",
"RegularText()",
"HashTag(#coronavirus,)", "HashTag(#coronavirus,)",
"RegularText(233,)", "RegularText(233,)",
"RegularText(33)", "RegularText(33)",
"RegularText()",
"HashTag(#bew,)", "HashTag(#bew,)",
"RegularText(229,)", "RegularText(229,)",
"RegularText(31)", "RegularText(31)",
"RegularText()",
"HashTag(#balkon,)", "HashTag(#balkon,)",
"RegularText(229,)", "RegularText(229,)",
"RegularText(31)", "RegularText(31)",
"RegularText()",
"HashTag(#terrasse,)", "HashTag(#terrasse,)",
"RegularText(229,)", "RegularText(229,)",
"RegularText(31)", "RegularText(31)",
"RegularText()",
"HashTag(#braininjuryawareness,)", "HashTag(#braininjuryawareness,)",
"RegularText(229,)", "RegularText(229,)",
"RegularText(24)", "RegularText(24)",
"RegularText()",
"HashTag(#garten,)", "HashTag(#garten,)",
"RegularText(220,)", "RegularText(220,)",
"RegularText(21)", "RegularText(21)",
"RegularText()",
"HashTag(#smart,)", "HashTag(#smart,)",
"RegularText(220,)", "RegularText(220,)",
"RegularText(21)", "RegularText(21)",
"RegularText()",
"HashTag(#nsfw,)", "HashTag(#nsfw,)",
"RegularText(211,)", "RegularText(211,)",
"RegularText(85)", "RegularText(85)",
"RegularText()",
"HashTag(#protoncalendar,)", "HashTag(#protoncalendar,)",
"RegularText(206,)", "RegularText(206,)",
"RegularText(31)", "RegularText(31)",
"RegularText()",
"HashTag(#stacksats,)", "HashTag(#stacksats,)",
"RegularText(195,)", "RegularText(195,)",
"RegularText(99)", "RegularText(99)",
"RegularText()",
"HashTag(#nokyc,)", "HashTag(#nokyc,)",
"RegularText(179,)", "RegularText(179,)",
"RegularText(98)", "RegularText(98)",
"RegularText()", "RegularText()",
"RegularText()",
"RegularText(Emoji sentiment today)", "RegularText(Emoji sentiment today)",
"RegularText()", "RegularText()",
"RegularText(⚡ (1.6K) 👉 (1.4K) 🇪🇺 (1.2K) 🫂 (1.2K) 🇺🇸 (1.1K) 💜 (875) 🧠 (858) 😂 (830) 🔥 (690) 🤣 (566) 🤙 (525) ☕ (444) 👇 (443) 🙌🏻 (425) ☀ (307) 😎 (305) 🥳 (301) 🤔 (276) 🌻 (270) 🧡 (270) 🥇 (269) 🗓 (269) 🙏 (268) 🏆 (267) 🌱 (264) 📰 (230) 🏉 (221) 😭 (220) 💰 (219) 🔗 (209) 👀 (201) 😅 (199) ✨ (193) 🇷🇺 (182) 💪 (167) ✅ (164) 💤 (163) 🐶 (151) 🇨🇭 (141) 📝 (137) 😁 (136) 🌞 (136) 🐾 (136) ❤ (132) 💻 (126) 🚀 (125) 👍 (125) 🇧🇷 (125) 😊 (121) 📚 (120) ➡ (120) 👏 (118) 🎉 (117) 🎮 (115) 🤷 (113) 👋 (112) 💃 (108) 🕺🏻 (106) 💡 (104) 🚨 (99) 😆 (97) 💯 (95) ⚠ (92) 📢 (92) 🤗 (89) 😴 (87) 🔁 (83) 🐰 (81) 😀 (79) 🎟 (78) ⛏ (78) 🐦 (76) 💸 (76) ✌🏻 (75) 🤍 (73) 🇬🇧 (73) 🌽 (70) 🤡 (69) 🤮 (69) ❗ (66) 🤝 (65) 😉 (65) 🙇 (65) 🍻 (64) 🌍 (64) 💕 (63) 🌸 (62) 💬 (61) ☺ (61) 🇦🇷 (59) 🇮🇩 (57) 😳 (57) 😄 (57) 🎶 (57) 🥷🏻 (56) 🎵 (56) 😃 (56) 🔍 (55) 💥 (55) 🎲 (54) ✍ (54) 🕒 (53) ⬇ (53) 💙 (51) 🔒 (50) 📈 (50) 🪙 (50) 🌧 (50) 🥰 (50) 🕸 (50) 🌐 (50) 💭 (49) 🌙 (49) 😍 (49) 📱 (48) 🌟 (48) 🤩 (48) 💔 (47) 🔌 (47) 😋 (47) 🎖 (47) 🍣 (46) 📷 (46) 💼 (45) ⭐ (45) 🥔 (45) 🥺 (45) 👌 (44) 👷🏼 (43) 😱 (43) 📅 (43) 🤖 (43) 📸 (42) 📊 (42) 🦑 (40) 💵 (40) 🤦 (39) ❣ (38) 💎 (38) 🖤 (38) 📺 (37) 🇵🇱 (37) 🇯🇵 (36) 🔧 (36) 🤘 (36) 💖 (36) ‼ (35) 😢 (35) 😺 (34) 🔊 (34) 😏 (34) 🇸🇰 (34) 🏃 (34) 👩‍👧 (34) ⏰ (33) 👨‍💻 (33) 👑 (33) 👥 (32) 🖥 (32) 💨 (32) 💗 (31) 🇲🇽 (31) 📖 (31) 🚫 (31) 👊🏻 (31) 😡 (31) 🌎 (31) 👁 (30) 🗞 (30) 🍀 (30) 🍽 (29) 🐸 (29) 🥚 (29) 💩 (29) ✊🏾 (29) 😮 (29) 🌡 (29) 🙃 (28) 🔔 (28) 🇻🇪 (28) 💦 (28) 🎯 (28) 🎨 (28) 🍛 (28) 🖼 (27) ☝🏻 (27) 🛑 (27) 🙄 (27) 🧑🏻‍🤝‍🧑🏽 (27) 🌈 (27) 🥂 (26) 🇫🇮 (26) 🎥 (26) 😬 (26) 🥲 (25) 🦾 (24) 🤜 (24) 🙂 (24) 🖕 (24) 😩 (24) )", "RegularText(⚡ (1.6K) 👉 (1.4K) 🇪🇺 (1.2K) 🫂 (1.2K) 🇺🇸 (1.1K) 💜 (875) 🧠 (858) 😂 (830) 🔥 (690) 🤣 (566) 🤙 (525) ☕ (444) 👇 (443) 🙌🏻 (425) ☀ (307) 😎 (305) 🥳 (301) 🤔 (276) 🌻 (270) 🧡 (270) 🥇 (269) 🗓 (269) 🙏 (268) 🏆 (267) 🌱 (264) 📰 (230) 🏉 (221) 😭 (220) 💰 (219) 🔗 (209) 👀 (201) 😅 (199) ✨ (193) 🇷🇺 (182) 💪 (167) ✅ (164) 💤 (163) 🐶 (151) 🇨🇭 (141) 📝 (137) 😁 (136) 🌞 (136) 🐾 (136) ❤ (132) 💻 (126) 🚀 (125) 👍 (125) 🇧🇷 (125) 😊 (121) 📚 (120) ➡ (120) 👏 (118) 🎉 (117) 🎮 (115) 🤷 (113) 👋 (112) 💃 (108) 🕺🏻 (106) 💡 (104) 🚨 (99) 😆 (97) 💯 (95) ⚠ (92) 📢 (92) 🤗 (89) 😴 (87) 🔁 (83) 🐰 (81) 😀 (79) 🎟 (78) ⛏ (78) 🐦 (76) 💸 (76) ✌🏻 (75) 🤍 (73) 🇬🇧 (73) 🌽 (70) 🤡 (69) 🤮 (69) ❗ (66) 🤝 (65) 😉 (65) 🙇 (65) 🍻 (64) 🌍 (64) 💕 (63) 🌸 (62) 💬 (61) ☺ (61) 🇦🇷 (59) 🇮🇩 (57) 😳 (57) 😄 (57) 🎶 (57) 🥷🏻 (56) 🎵 (56) 😃 (56) 🔍 (55) 💥 (55) 🎲 (54) ✍ (54) 🕒 (53) ⬇ (53) 💙 (51) 🔒 (50) 📈 (50) 🪙 (50) 🌧 (50) 🥰 (50) 🕸 (50) 🌐 (50) 💭 (49) 🌙 (49) 😍 (49) 📱 (48) 🌟 (48) 🤩 (48) 💔 (47) 🔌 (47) 😋 (47) 🎖 (47) 🍣 (46) 📷 (46) 💼 (45) ⭐ (45) 🥔 (45) 🥺 (45) 👌 (44) 👷🏼 (43) 😱 (43) 📅 (43) 🤖 (43) 📸 (42) 📊 (42) 🦑 (40) 💵 (40) 🤦 (39) ❣ (38) 💎 (38) 🖤 (38) 📺 (37) 🇵🇱 (37) 🇯🇵 (36) 🔧 (36) 🤘 (36) 💖 (36) ‼ (35) 😢 (35) 😺 (34) 🔊 (34) 😏 (34) 🇸🇰 (34) 🏃 (34) 👩‍👧 (34) ⏰ (33) 👨‍💻 (33) 👑 (33) 👥 (32) 🖥 (32) 💨 (32) 💗 (31) 🇲🇽 (31) 📖 (31) 🚫 (31) 👊🏻 (31) 😡 (31) 🌎 (31) 👁 (30) 🗞 (30) 🍀 (30) 🍽 (29) 🐸 (29) 🥚 (29) 💩 (29) ✊🏾 (29) 😮 (29) 🌡 (29) 🙃 (28) 🔔 (28) 🇻🇪 (28) 💦 (28) 🎯 (28) 🎨 (28) 🍛 (28) 🖼 (27) ☝🏻 (27) 🛑 (27) 🙄 (27) 🧑🏻‍🤝‍🧑🏽 (27) 🌈 (27) 🥂 (26) 🇫🇮 (26) 🎥 (26) 😬 (26) 🥲 (25) 🦾 (24) 🤜 (24) 🙂 (24) 🖕 (24) 😩 (24) )",
"RegularText()", "RegularText()",
"RegularText(Zap economy)", "RegularText(Zap economy)",
"RegularText()", "RegularText()",
"Link(⚡41.7M)", "RegularText(⚡41.7M sats (₿0.417) )",
"RegularText(sats)",
"RegularText((₿0.417))",
"RegularText()",
"RegularText(1,816 zappers & 920 zapped (unique pubkeys))", "RegularText(1,816 zappers & 920 zapped (unique pubkeys))",
"RegularText(🌩️ 33,248 zaps, 1,253 sats per zap (avg))", "RegularText(🌩️ 33,248 zaps, 1,253 sats per zap (avg))",
"RegularText()", "RegularText()",
@@ -2248,7 +2215,7 @@ class RichTextParserTest {
"HashTag(#214)", "HashTag(#214)",
"RegularText(2%)", "RegularText(2%)",
"RegularText(Satscoinsv,)", "RegularText(Satscoinsv,)",
"Link(⚡satscoinsv@getalby.com)", "RegularText(⚡satscoinsv@getalby.com)",
"RegularText(-)", "RegularText(-)",
"RegularText(80db64657ea0358c5332c5cca01565eeddd4b8799688b1c46d3cb2d7c966671f)", "RegularText(80db64657ea0358c5332c5cca01565eeddd4b8799688b1c46d3cb2d7c966671f)",
"HashTag(#215)", "HashTag(#215)",
@@ -2458,7 +2425,7 @@ class RichTextParserTest {
"HashTag(#249)", "HashTag(#249)",
"RegularText(2%)", "RegularText(2%)",
"RegularText(micmad,)", "RegularText(micmad,)",
"Link(miceliomad@miceliomad.github.io/nostr/)", "RegularText(miceliomad@miceliomad.github.io/nostr/)",
"RegularText(-)", "RegularText(-)",
"RegularText(cd806edcf8ff40ea94fa574ea9cd97da16e5beb2b85aac6e1d648b8388504343)", "RegularText(cd806edcf8ff40ea94fa574ea9cd97da16e5beb2b85aac6e1d648b8388504343)",
"HashTag(#250)", "HashTag(#250)",
@@ -3805,7 +3772,7 @@ class RichTextParserTest {
"HashTag(#471)", "HashTag(#471)",
"RegularText(1%)", "RegularText(1%)",
"RegularText(leonwankum,)", "RegularText(leonwankum,)",
"SchemelessUrl(@leonawankum@BitcoinNostr.com)", "RegularText(@leonawankum@BitcoinNostr.com)",
"RegularText()", "RegularText()",
"RegularText(-)", "RegularText(-)",
"RegularText(652d58acafa105af8475c0fe8029a52e7ddbc337b2bd9c98bb17a111dc4cde60)", "RegularText(652d58acafa105af8475c0fe8029a52e7ddbc337b2bd9c98bb17a111dc4cde60)",
@@ -4098,7 +4065,6 @@ https://nostr.build/i/fd53fcf5ad950fbe45127e4bcee1b59e8301d41de6beee211f45e344db
"RegularText(here:)", "RegularText(here:)",
"Link(https://lnshort.it/live-stream-embeds/)", "Link(https://lnshort.it/live-stream-embeds/)",
"RegularText()", "RegularText()",
"RegularText()",
"Image(https://nostr.build/i/fd53fcf5ad950fbe45127e4bcee1b59e8301d41de6beee211f45e344db214e8a.jpg)" "Image(https://nostr.build/i/fd53fcf5ad950fbe45127e4bcee1b59e8301d41de6beee211f45e344db214e8a.jpg)"
) )
@@ -4110,6 +4076,57 @@ https://nostr.build/i/fd53fcf5ad950fbe45127e4bcee1b59e8301d41de6beee211f45e344db
} }
} }
@Test
fun testNewLineAfterImage() {
val text = "Thats it ! Thats the #note https://cdn.nostr.build/i/1dc0726b6cb0f94a92bd66765ffb90f6c67e90c17bb957fc3d5d4782cbd73de7.jpg "
val state = RichTextParser().parseText(text, ImmutableListOfLists())
printStateForDebug(state)
val expectedResult = listOf<String>(
"RegularText(Thats)",
"RegularText(it)",
"RegularText(!)",
"RegularText(Thats)",
"RegularText(the)",
"HashTag(#note)",
"Image(https://cdn.nostr.build/i/1dc0726b6cb0f94a92bd66765ffb90f6c67e90c17bb957fc3d5d4782cbd73de7.jpg)"
)
state.paragraphs.map { it.words }.flatten().forEachIndexed { index, seg ->
Assert.assertEquals(
expectedResult[index],
"${seg.javaClass.simpleName.replace("Segment", "")}(${seg.segmentText})"
)
}
}
@Test
fun testSapceAfterImage() {
val text = "Thats it! https://cdn.nostr.build/i/1dc0726b6cb0f94a92bd66765ffb90f6c67e90c17bb957fc3d5d4782cbd73de7.jpg Thats the #note"
val state = RichTextParser().parseText(text, ImmutableListOfLists())
printStateForDebug(state)
val expectedResult = listOf<String>(
"RegularText(Thats)",
"RegularText(it!)",
"Image(https://cdn.nostr.build/i/1dc0726b6cb0f94a92bd66765ffb90f6c67e90c17bb957fc3d5d4782cbd73de7.jpg)",
"RegularText(Thats)",
"RegularText(the)",
"HashTag(#note)"
)
state.paragraphs.map { it.words }.flatten().forEachIndexed { index, seg ->
Assert.assertEquals(
expectedResult[index],
"${seg.javaClass.simpleName.replace("Segment", "")}(${seg.segmentText})"
)
}
}
private fun printStateForDebug(state: RichTextViewerState) { private fun printStateForDebug(state: RichTextViewerState) {
state.paragraphs.forEachIndexed { index, paragraph -> state.paragraphs.forEachIndexed { index, paragraph ->
paragraph.words.forEach { seg -> paragraph.words.forEach { seg ->

View File

@@ -54,7 +54,7 @@ object CachedRichTextParser {
// Android9 seems to have an issue starting this regex. // Android9 seems to have an issue starting this regex.
val noProtocolUrlValidator = try { val noProtocolUrlValidator = try {
Pattern.compile("(([\\w\\d-]+\\.)*[a-zA-Z][\\w-]+[\\.\\:]\\w+([\\/\\?\\=\\&\\#\\.]?[\\w-]*[^\\p{IsHan}\\p{IsHiragana}\\p{IsKatakana}])*\\/?)(.*)") Pattern.compile("(([\\w\\d-]+\\.)*[a-zA-Z][\\w-]+[\\.\\:]\\w+([\\/\\?\\=\\&\\#\\.]?[\\w-]+[^\\p{IsHan}\\p{IsHiragana}\\p{IsKatakana}])*\\/?)(.*)")
} catch (e: Exception) { } catch (e: Exception) {
Pattern.compile("(([\\w\\d-]+\\.)*[a-zA-Z][\\w-]+[\\.\\:]\\w+([\\/\\?\\=\\&\\#\\.]?[\\w-]+)*\\/?)(.*)") Pattern.compile("(([\\w\\d-]+\\.)*[a-zA-Z][\\w-]+[\\.\\:]\\w+([\\/\\?\\=\\&\\#\\.]?[\\w-]+)*\\/?)(.*)")
} }
@@ -119,7 +119,7 @@ class RichTextParser() {
val isRTL = isArabic(paragraph) val isRTL = isArabic(paragraph)
val wordList = paragraph.split(' ') val wordList = paragraph.trimEnd().split(' ')
wordList.forEach { word -> wordList.forEach { word ->
val wordSegment = wordIdentifier(word, images, urls, emojis, tags) val wordSegment = wordIdentifier(word, images, urls, emojis, tags)
if (wordSegment !is RegularTextSegment) { if (wordSegment !is RegularTextSegment) {
@@ -182,8 +182,8 @@ class RichTextParser() {
} else if (schemelessMatcher.find()) { } else if (schemelessMatcher.find()) {
val url = schemelessMatcher.group(1) // url val url = schemelessMatcher.group(1) // url
val additionalChars = schemelessMatcher.group(4) // additional chars val additionalChars = schemelessMatcher.group(4) // additional chars
val pattern = "^([A-Za-z0-9-]+(\\.[A-Za-z0-9]+)+)(:[0-9]+)?(/[^?#]*)?(\\?[^#]*)?(#.*)?".toRegex(RegexOption.IGNORE_CASE) val pattern = "^([A-Za-z0-9-_]+(\\.[A-Za-z0-9-_]+)+)(:[0-9]+)?(/[^?#]*)?(\\?[^#]*)?(#.*)?".toRegex(RegexOption.IGNORE_CASE)
if (pattern.matches(word)) { if (pattern.find(word) != null) {
SchemelessUrlSegment(word, url, additionalChars) SchemelessUrlSegment(word, url, additionalChars)
} else { } else {
RegularTextSegment(word) RegularTextSegment(word)