-
-
Save Nohus/bac151623a287777208f8d66b4731497 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private fun parseMarkdown( | |
markdown: String, | |
typography: Typography, | |
headingColor: Color | |
): AnnotatedString { | |
val parser = Parser.builder().build() | |
val document = parser.parse(markdown) | |
val annotatedString = buildAnnotatedString { | |
visitMarkdownNode(document, typography, headingColor) | |
} | |
return annotatedString.trim() as AnnotatedString | |
} | |
private fun AnnotatedString.Builder.visitMarkdownNode( | |
node: Node, | |
typography: Typography, | |
headingColor: Color | |
) { | |
when (node) { | |
is Heading -> { | |
val style = when (node.level) { | |
in 1..3 -> typography.titleLarge | |
4 -> typography.titleMedium | |
5 -> typography.bodySmall | |
else -> typography.bodySmall | |
} | |
withStyle(style.toParagraphStyle()) { | |
withStyle(style.toSpanStyle().copy(color = headingColor)) { | |
visitChildren(node, typography, headingColor) | |
appendLine() | |
} | |
} | |
} | |
is Paragraph -> { | |
if (node.parents.any { it is BulletList || it is OrderedList }) { | |
visitChildren(node, typography, headingColor) | |
} else { | |
withStyle(typography.bodyLarge.toParagraphStyle()) { | |
visitChildren(node, typography, headingColor) | |
appendLine() | |
} | |
} | |
} | |
is Emphasis -> { | |
withStyle(SpanStyle(fontStyle = FontStyle.Italic)) { | |
visitChildren(node, typography, headingColor) | |
} | |
} | |
is StrongEmphasis -> { | |
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { | |
visitChildren(node, typography, headingColor) | |
} | |
} | |
is Text -> { | |
append(node.literal) | |
visitChildren(node, typography, headingColor) | |
} | |
is SoftLineBreak -> { | |
append(" ") | |
} | |
is HardLineBreak -> { | |
appendLine() | |
} | |
is ThematicBreak -> { | |
withStyle(ParagraphStyle(textAlign = TextAlign.Center)) { | |
withStyle(SpanStyle(letterSpacing = 0.sp)) { | |
appendLine("─".repeat(10)) | |
} | |
} | |
} | |
is OrderedList -> { | |
withStyle(ParagraphStyle(textIndent = TextIndent(firstLine = 10.sp, restLine = 20.sp))) { | |
visitChildren(node, typography, headingColor) | |
} | |
} | |
is BulletList -> { | |
withStyle(ParagraphStyle(textIndent = TextIndent(firstLine = 10.sp, restLine = 20.sp))) { | |
visitChildren(node, typography, headingColor) | |
} | |
} | |
is ListItem -> { | |
if (node.parents.any { it is BulletList }) { | |
append("• ") | |
} else if (node.parents.any { it is OrderedList }) { | |
val startNumber = (node.parents.first { it is OrderedList } as OrderedList).startNumber | |
val index = startNumber + node.previousSiblings.filterIsInstance<ListItem>().size | |
append("$index. ") | |
} | |
visitChildren(node, typography, headingColor) | |
appendLine() | |
} | |
is Document -> { | |
visitChildren(node, typography, headingColor) | |
} | |
else -> { | |
Log.e("MarkdownText", "Traversing unhandled node: $node") | |
visitChildren(node, typography, headingColor) | |
} | |
} | |
} | |
private fun AnnotatedString.Builder.visitChildren( | |
node: Node, | |
typography: Typography, | |
headingColor: Color | |
) { | |
var child = node.firstChild | |
while (child != null) { | |
visitMarkdownNode(child, typography, headingColor) | |
child = child.next | |
} | |
} | |
private val Node.parents: List<Node> get() { | |
val list = mutableListOf<Node>() | |
var current = this | |
while (true) { | |
current = current.parent ?: return list | |
list += current | |
} | |
} | |
private val Node.previousSiblings: List<Node> get() { | |
val list = mutableListOf<Node>() | |
var current = this | |
while (true) { | |
current = current.previous ?: return list | |
list += current | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment