-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBasicMarkdownParser.kt
103 lines (90 loc) · 3.03 KB
/
BasicMarkdownParser.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/**
* @author Yiğit Can Yılmaz (ycannot, https://github.com/ycannot)
* @date 14.06.2022
*/
import android.graphics.Color
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan
import android.text.style.UnderlineSpan
import androidx.annotation.ColorInt
import androidx.annotation.Keep
import androidx.core.text.toSpannable
object BasicMarkdownParser {
val highlightIndicator = "::"
val underlineIndicator = "__"
private const val defaultColorCode = "#654FD3"
@ColorInt
var highlightColor = Color.parseColor(defaultColorCode)
private val specialCharset = arrayOf(highlightIndicator, underlineIndicator)
fun parseMarkdown(s: String): Spannable {
var temp = s
val recurrences = arrayListOf<Recurrence>()
specialCharset.forEach { specialChar ->
temp = temp.replace(specialChar, "")
recurrences.addAll(extractRecurrences(s, specialChar))
}
val attributed = SpannableStringBuilder(temp)
recurrences.forEach { recurrence ->
when (recurrence.stylingChar) {
highlightIndicator -> {
attributed.setSpan(
ForegroundColorSpan(highlightColor),
recurrence.startIndex,
recurrence.endIndex,
Spannable.SPAN_INCLUSIVE_INCLUSIVE
)
}
underlineIndicator -> {
attributed.setSpan(
UnderlineSpan(),
recurrence.startIndex,
recurrence.endIndex,
Spannable.SPAN_INCLUSIVE_INCLUSIVE
)
}
}
}
return attributed.toSpannable()
}
private fun extractRecurrences(
s: String,
specialChar: String
): ArrayList<Recurrence> {
val regex = Regex("\\$specialChar(.*?)\\$specialChar")
return regex.findAll(s).mapTo(arrayListOf()) { match ->
val startIndex = calculateRefinedStartIndex(s, match)
val endIndex = startIndex + match.value.length
specialCharset.forEach {
endIndex -= match.value.count(it)
}
Recurrence(
match.value,
startIndex,
endIndex,
specialChar
)
}
}
private fun calculateRefinedStartIndex(
s: String,
recurrence: MatchResult
): Int {
val rawIndex = recurrence.range.first
var specialCharCountBefore = 0
specialCharset.forEach {
specialCharCountBefore += s.substring(0, rawIndex).count(it)
}
return rawIndex - specialCharCountBefore
}
fun String.count(s: String): Int{
return this.split(s).size - 1
}
@Keep
private data class Recurrence(
val recurrence: String,
val startIndex: Int,
val endIndex: Int,
val stylingChar: String
)
}