Skip to content

Commit

Permalink
Merge pull request #245 from MohamedRejeb/1.x
Browse files Browse the repository at this point in the history
Improve markdown encoding
  • Loading branch information
MohamedRejeb authored Apr 8, 2024
2 parents 0fdb42c + 95c52fa commit 9c02483
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ internal object RichTextStateMarkdownParser : RichTextStateParser<String> {
@OptIn(ExperimentalRichTextApi::class)
override fun encode(input: String): RichTextState {
val openedNodes = mutableListOf<ASTNode>()
val stringBuilder = StringBuilder()
val richParagraphList = mutableListOf(RichParagraph())
var currentRichSpan: RichSpan? = null
var currentRichParagraphType: ParagraphType = DefaultParagraph()
Expand All @@ -36,8 +35,6 @@ internal object RichTextStateMarkdownParser : RichTextStateParser<String> {
onText = { text ->
if (text.isEmpty()) return@encodeMarkdownToRichText

stringBuilder.append(text)

if (richParagraphList.isEmpty())
richParagraphList.add(RichParagraph())

Expand All @@ -47,7 +44,10 @@ internal object RichTextStateMarkdownParser : RichTextStateParser<String> {
if (safeCurrentRichSpan.children.isEmpty()) {
safeCurrentRichSpan.text += text
} else {
val newRichSpan = RichSpan(paragraph = currentRichParagraph)
val newRichSpan = RichSpan(
paragraph = currentRichParagraph,
parent = safeCurrentRichSpan,
)
newRichSpan.text = text
safeCurrentRichSpan.children.add(newRichSpan)
}
Expand All @@ -63,8 +63,6 @@ internal object RichTextStateMarkdownParser : RichTextStateParser<String> {
val tagSpanStyle = markdownElementsSpanStyleEncodeMap[node.type]

if (node.type in markdownBlockElements) {
stringBuilder.append(' ')

val currentRichParagraph = richParagraphList.last()

// Get paragraph type from markdown element
Expand Down Expand Up @@ -127,6 +125,7 @@ internal object RichTextStateMarkdownParser : RichTextStateParser<String> {
currentRichSpan?.spanStyle = currentRichSpan?.spanStyle?.merge(child.spanStyle) ?: child.spanStyle
currentRichSpan?.style = child.style
currentRichSpan?.children?.clear()
currentRichSpan?.children?.addAll(child.children)
}
}

Expand Down Expand Up @@ -166,7 +165,7 @@ internal object RichTextStateMarkdownParser : RichTextStateParser<String> {

richTextState.richParagraphList.fastForEachIndexed { index, richParagraph ->
// Append paragraph start text
builder.append(richParagraph.type.startRichSpan.text)
builder.appendParagraphStartText(richParagraph)

richParagraph.getFirstNonEmptyChild()?.let { firstNonEmptyChild ->
if (firstNonEmptyChild.text.isNotEmpty()) {
Expand Down Expand Up @@ -222,6 +221,19 @@ internal object RichTextStateMarkdownParser : RichTextStateParser<String> {
return stringBuilder.toString()
}

private fun StringBuilder.appendParagraphStartText(paragraph: RichParagraph) {
when (val type = paragraph.type) {
is OrderedList ->
append("${type.number}. ")

is UnorderedList ->
append("- ")

else ->
Unit
}
}

/**
* Encodes Markdown elements to [SpanStyle].
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.mohamedrejeb.richeditor.parser.markdown

import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import kotlin.test.Test
import kotlin.test.assertEquals

class RichTextStateMarkdownParserTest {

@Test
fun testBold() {
val markdown = "**Hello World!**"
val expectedText = "Hello World!"
val state = RichTextStateMarkdownParser.encode(markdown)
val actualText = state.annotatedString.text

assertEquals(
expected = expectedText,
actual = actualText,
)

assertEquals(
expected = SpanStyle(fontWeight = FontWeight.Bold),
actual = state.richParagraphList.first().children.first().spanStyle
)
}

@Test
fun testBoldWithNestedItalic() {
val markdown = "**Hello *World!***"
val expectedText = "Hello World!"
val state = RichTextStateMarkdownParser.encode(markdown)
val actualText = state.annotatedString.text

assertEquals(
expected = expectedText,
actual = actualText,
)

val firstChild = state.richParagraphList.first().children.first()
val secondChild = firstChild.children.first()

assertEquals(
expected = SpanStyle(fontWeight = FontWeight.Bold),
actual = firstChild.spanStyle
)

assertEquals(
expected = SpanStyle(fontStyle = FontStyle.Italic),
actual = secondChild.spanStyle
)
}



@Test
fun testBoldWithNestedItalicAndUnderline() {
val markdown = "**Hello *World!***"
val expectedText = "Hello World!"
val state = RichTextStateMarkdownParser.encode(markdown)
val actualText = state.annotatedString.text

assertEquals(
expected = expectedText,
actual = actualText,
)

val firstChild = state.richParagraphList.first().children.first()
val secondChild = firstChild.children.first()

assertEquals(
expected = SpanStyle(fontWeight = FontWeight.Bold),
actual = firstChild.spanStyle
)

assertEquals(
expected = SpanStyle(fontStyle = FontStyle.Italic),
actual = secondChild.spanStyle
)
}

}

0 comments on commit 9c02483

Please sign in to comment.