diff --git a/app/src/main/java/im/vector/riotredesign/features/markdown/HtmlRenderer.kt b/app/src/main/java/im/vector/riotredesign/features/markdown/HtmlRenderer.kt index f3c659333a..30f5030ea9 100644 --- a/app/src/main/java/im/vector/riotredesign/features/markdown/HtmlRenderer.kt +++ b/app/src/main/java/im/vector/riotredesign/features/markdown/HtmlRenderer.kt @@ -19,19 +19,35 @@ package im.vector.riotredesign.features.markdown import android.content.Context +import org.commonmark.node.BlockQuote +import org.commonmark.node.HtmlBlock +import org.commonmark.node.HtmlInline +import org.commonmark.node.Node import ru.noties.markwon.AbstractMarkwonPlugin import ru.noties.markwon.Markwon +import ru.noties.markwon.MarkwonConfiguration import ru.noties.markwon.MarkwonVisitor -import ru.noties.markwon.html.HtmlPlugin +import ru.noties.markwon.SpannableBuilder import ru.noties.markwon.html.HtmlTag +import ru.noties.markwon.html.MarkwonHtmlParserImpl import ru.noties.markwon.html.MarkwonHtmlRenderer import ru.noties.markwon.html.TagHandler -import timber.log.Timber +import ru.noties.markwon.html.tag.BlockquoteHandler +import ru.noties.markwon.html.tag.EmphasisHandler +import ru.noties.markwon.html.tag.HeadingHandler +import ru.noties.markwon.html.tag.ImageHandler +import ru.noties.markwon.html.tag.LinkHandler +import ru.noties.markwon.html.tag.ListHandler +import ru.noties.markwon.html.tag.StrikeHandler +import ru.noties.markwon.html.tag.StrongEmphasisHandler +import ru.noties.markwon.html.tag.SubScriptHandler +import ru.noties.markwon.html.tag.SuperScriptHandler +import ru.noties.markwon.html.tag.UnderlineHandler +import java.util.Arrays.asList class HtmlRenderer(private val context: Context) { private val markwon = Markwon.builder(context) - .usePlugin(HtmlPlugin.create()) .usePlugin(MatrixPlugin.create()) .build() @@ -43,8 +59,65 @@ class HtmlRenderer(private val context: Context) { private class MatrixPlugin private constructor() : AbstractMarkwonPlugin() { + override fun configureConfiguration(builder: MarkwonConfiguration.Builder) { + builder.htmlParser(MarkwonHtmlParserImpl.create()) + } + override fun configureHtmlRenderer(builder: MarkwonHtmlRenderer.Builder) { - builder.addHandler("mx-reply", MxReplyTagHandler()) + builder + .addHandler( + "img", + ImageHandler.create()) + .addHandler( + "a", + LinkHandler()) + .addHandler( + "blockquote", + BlockquoteHandler()) + .addHandler( + "sub", + SubScriptHandler()) + .addHandler( + "sup", + SuperScriptHandler()) + .addHandler( + asList("b", "strong"), + StrongEmphasisHandler()) + .addHandler( + asList("s", "del"), + StrikeHandler()) + .addHandler( + asList("u", "ins"), + UnderlineHandler()) + .addHandler( + asList("ul", "ol"), + ListHandler()) + .addHandler( + asList("i", "em", "cite", "dfn"), + EmphasisHandler()) + .addHandler( + asList("h1", "h2", "h3", "h4", "h5", "h6"), + HeadingHandler()) + .addHandler("mx-reply", + MxReplyTagHandler()) + + } + + override fun afterRender(node: Node, visitor: MarkwonVisitor) { + val configuration = visitor.configuration() + configuration.htmlRenderer().render(visitor, configuration.htmlParser()) + } + + override fun configureVisitor(builder: MarkwonVisitor.Builder) { + builder + .on(HtmlBlock::class.java) { visitor, htmlBlock -> visitHtml(visitor, htmlBlock.literal) } + .on(HtmlInline::class.java) { visitor, htmlInline -> visitHtml(visitor, htmlInline.literal) } + } + + private fun visitHtml(visitor: MarkwonVisitor, html: String?) { + if (html != null) { + visitor.configuration().htmlParser().processFragment(visitor.builder(), html) + } } companion object { @@ -56,8 +129,20 @@ private class MatrixPlugin private constructor() : AbstractMarkwonPlugin() { } private class MxReplyTagHandler : TagHandler() { + override fun handle(visitor: MarkwonVisitor, renderer: MarkwonHtmlRenderer, tag: HtmlTag) { - Timber.v("Handle mx-reply") + val configuration = visitor.configuration() + val factory = configuration.spansFactory().get(BlockQuote::class.java) + if (factory != null) { + SpannableBuilder.setSpans( + visitor.builder(), + factory.getSpans(configuration, visitor.renderProps()), + tag.start(), + tag.end() + ) + val replyText = visitor.builder().removeFromEnd(tag.end()) + visitor.builder().append("\n\n").append(replyText) + } } -} \ No newline at end of file +}