From bef238f8510d493c9c2ad42889df63ee587b51ff Mon Sep 17 00:00:00 2001 From: David Langley Date: Tue, 14 Dec 2021 20:40:44 +0000 Subject: [PATCH] Add simple parser for use with just quotes/replies --- .../sdk/internal/session/room/RoomModule.kt | 20 +++++++++++++++++++ .../room/send/LocalEchoEventFactory.kt | 14 ++++++------- .../session/room/send/MarkdownParser.kt | 8 +++++--- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt index dbd0ae6f06..6497c997ed 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt @@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.session.room import dagger.Binds import dagger.Module import dagger.Provides +import org.commonmark.node.BlockQuote import org.commonmark.parser.Parser import org.commonmark.renderer.html.HtmlRenderer import org.matrix.android.sdk.api.session.file.FileService @@ -98,6 +99,14 @@ import org.matrix.android.sdk.internal.session.room.version.DefaultRoomVersionUp import org.matrix.android.sdk.internal.session.room.version.RoomVersionUpgradeTask import org.matrix.android.sdk.internal.session.space.DefaultSpaceService import retrofit2.Retrofit +import javax.inject.Qualifier + +/** + * Used to inject the simple commonmark Parser + */ +@Qualifier +@Retention(AnnotationRetention.RUNTIME) +internal annotation class SimpleCommonmarkParser @Module internal abstract class RoomModule { @@ -124,6 +133,17 @@ internal abstract class RoomModule { return Parser.builder().build() } + @Provides + @SimpleCommonmarkParser + @JvmStatic + fun providesSimpleParser(): Parser { + // The simple parser disables all blocks but quotes. + // Inline parsing(bold, italic, etc) is also enabled and is not easy to disable in commonmark currently. + return Parser.builder() + .enabledBlockTypes(setOf(BlockQuote::class.java)) + .build() + } + @Provides @JvmStatic fun providesHtmlRenderer(): HtmlRenderer { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt index 52cdf94dbb..9e279dfa44 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt @@ -91,9 +91,9 @@ internal class LocalEchoEventFactory @Inject constructor( return createMessageEvent(roomId, content) } - private fun createTextContent(text: CharSequence, autoMarkdown: Boolean, forceMarkdownParse: Boolean = false): TextContent { + private fun createTextContent(text: CharSequence, autoMarkdown: Boolean): TextContent { if (autoMarkdown) { - return markdownParser.parse(text, force = forceMarkdownParse) + return markdownParser.parse(text) } else { // Try to detect pills textPillsUtils.processSpecialSpansToHtml(text)?.let { @@ -206,9 +206,9 @@ internal class LocalEchoEventFactory @Inject constructor( val body = bodyForReply(originalEvent.getLastMessageContent(), originalEvent.isReply()) // As we always supply formatted body for replies we should force the MarkdownParser to produce html. - val newBodyFormatted = createTextContent(newBodyText, true, forceMarkdownParse = true).takeFormatted() + val newBodyFormatted = markdownParser.parse(newBodyText, force = true, advanced = false).takeFormatted() // Body of the original message may not have formatted version, so may also have to convert to html. - val bodyFormatted = body.formattedText ?: createTextContent(body.text, true, forceMarkdownParse = true).takeFormatted() + val bodyFormatted = body.formattedText ?: markdownParser.parse(newBodyText, force = true, advanced = false).takeFormatted() val replyFormatted = REPLY_PATTERN.format( permalink, userLink, @@ -396,9 +396,9 @@ internal class LocalEchoEventFactory @Inject constructor( val body = bodyForReply(eventReplied.getLastMessageContent(), eventReplied.isReply()) // As we always supply formatted body for replies we should force the MarkdownParser to produce html. - val replyTextFormatted = createTextContent(replyText, true, forceMarkdownParse = true).takeFormatted() + val replyTextFormatted = markdownParser.parse(replyText, force = true, advanced = false).takeFormatted() // Body of the original message may not have formatted version, so may also have to convert to html. - val bodyFormatted = body.formattedText ?: createTextContent(body.text, true, forceMarkdownParse = true).takeFormatted() + val bodyFormatted = body.formattedText ?: markdownParser.parse(replyText, force = true, advanced = false).takeFormatted() val replyFormatted = REPLY_PATTERN.format( permalink, userLink, @@ -514,7 +514,7 @@ internal class LocalEchoEventFactory @Inject constructor( val messageContent = quotedEvent.getLastMessageContent() val textMsg = messageContent?.body val quoteText = legacyRiotQuoteText(textMsg, text) - return createFormattedTextEvent(roomId, createTextContent(quoteText, autoMarkdown=true, forceMarkdownParse = true), MessageType.MSGTYPE_TEXT) + return createFormattedTextEvent(roomId, markdownParser.parse(quoteText, force = true, advanced = false), MessageType.MSGTYPE_TEXT) } private fun legacyRiotQuoteText(quotedText: String?, myText: String): String { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt index 2df668bf40..8f963ba16d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt @@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.room.send import org.commonmark.parser.Parser import org.commonmark.renderer.html.HtmlRenderer +import org.matrix.android.sdk.internal.session.room.SimpleCommonmarkParser import org.matrix.android.sdk.internal.session.room.send.pills.TextPillsUtils import javax.inject.Inject @@ -27,7 +28,8 @@ import javax.inject.Inject * If any change is required, please add a test covering the problem and make sure all the tests are still passing. */ internal class MarkdownParser @Inject constructor( - private val parser: Parser, + private val advancedParser: Parser, + @SimpleCommonmarkParser private val simpleParser: Parser, private val htmlRenderer: HtmlRenderer, private val textPillsUtils: TextPillsUtils ) { @@ -40,7 +42,7 @@ internal class MarkdownParser @Inject constructor( * @param force Skips the check for detecting if the input contains markdown and always converts to html. * @return TextContent containing the plain text and the formatted html if generated. */ - fun parse(text: CharSequence, force: Boolean = false): TextContent { + fun parse(text: CharSequence, force: Boolean = false, advanced: Boolean = true): TextContent { val source = textPillsUtils.processSpecialSpansToMarkdown(text) ?: text.toString() // If no special char are detected, just return plain text @@ -48,7 +50,7 @@ internal class MarkdownParser @Inject constructor( return TextContent(source) } - val document = parser.parse(source) + val document = if (advanced) advancedParser.parse(source) else simpleParser.parse(source) val htmlText = htmlRenderer.render(document) // Cleanup extra paragraph