-
-
Notifications
You must be signed in to change notification settings - Fork 73
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce richtext-markdown as a generic Markdown renderer
Markdown unfortunately does not have a universally agreed standard. Different flavors, libraries can parse Markdown content in their own ways. `richtext-commonmark` uses `Commonmark` spec and parser to convert any given markdown String into an intermediate Abstract Syntax Tree that has been defined internally since its release. The idea has always been to extract this ASTNode structure out of this module to enable custom parsing logic to be supplied from outside, and make `richtext-commonmark` only responsible for rendering the given tree using `richtext-ui`. This change introduces a new module named `richtext-markdown` which is actually just a rename of the existing `richtext-commonmark`. This new module also exposes its internal `AstNode` APIs to enable other modules to render their own AstNode structures. `richtext-commonmark` becomes a helper module which can parse any given string into an AstNode via `CommonmarkAstNodeParser`. Also, it still provides a `RichTextScope.Markdown` function that simply does the conversion asynchronously, then calls the `Markdown(AstNode)` flavor from `richtext-markdown`.
- Loading branch information
1 parent
8920e78
commit 39b991d
Showing
34 changed files
with
385 additions
and
169 deletions.
There are no files selected for viewing
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
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
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Markdown | ||
|
||
[![Android Library](https://img.shields.io/badge/Platform-Android-green.svg?style=for-the-badge)](https://developer.android.com/studio/build/dependencies) | ||
[![JVM Library](https://img.shields.io/badge/Platform-JVM-red.svg?style=for-the-badge)](https://kotlinlang.org/docs/mpp-intro.html) | ||
|
||
Library for rendering Markdown tree defined as an `AstNode`. | ||
|
||
## Gradle | ||
|
||
```kotlin | ||
dependencies { | ||
implementation("com.halilibo.compose-richtext:richtext-markdown:${richtext_version}") | ||
} | ||
``` | ||
|
||
## Usage | ||
|
||
`richtext-markdown` module renders a given Markdown Abstract Syntax Tree. It accepts a root | ||
`AstNode`. However, this library does not include a parser to convert a regular Markdown String into | ||
an `AstNode`. Please refer to `richtext-commonmark` for a sample implementation or a quick way to | ||
render Markdown. | ||
|
||
## Rendering | ||
|
||
The simplest way to render markdown is just pass an `AstNode` to the [`Markdown`](../api/richtext-commonmark/com.halilibo.richtext.markdown/-markdown.html) | ||
composable under RichText scope: | ||
|
||
~~~kotlin | ||
RichText( | ||
modifier = Modifier.padding(16.dp) | ||
) { | ||
val parser = remember(options) { CommonmarkAstNodeParser(options) } | ||
val astNode = remember(parser) { | ||
parser.parse( | ||
""" | ||
# Demo | ||
Emphasis, aka italics, with *asterisks* or _underscores_. Strong emphasis, aka bold, with **asterisks** or __underscores__. Combined emphasis with **asterisks and _underscores_**. [Links with two blocks, text in square-brackets, destination is in parentheses.](https://www.example.com). Inline `code` has `back-ticks around` it. | ||
1. First ordered list item | ||
2. Another item | ||
* Unordered sub-list. | ||
3. And another item. | ||
You can have properly indented paragraphs within list items. Notice the blank line above, and the leading spaces (at least one, but we'll use three here to also align the raw Markdown). | ||
* Unordered list can use asterisks | ||
- Or minuses | ||
+ Or pluses | ||
""".trimIndent() | ||
) | ||
} | ||
Markdown(astNode) | ||
} | ||
~~~ |
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
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
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
1 change: 1 addition & 0 deletions
1
...richtext/markdown/AstNodeConvertKtTest.kt → ...chtext/commonmark/AstNodeConvertKtTest.kt
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
52 changes: 52 additions & 0 deletions
52
richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/commonmark/Markdown.kt
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package com.halilibo.richtext.commonmark | ||
|
||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.getValue | ||
import androidx.compose.runtime.produceState | ||
import androidx.compose.runtime.remember | ||
import com.halilibo.richtext.markdown.Markdown | ||
import com.halilibo.richtext.commonmark.MarkdownParseOptions.Companion | ||
import com.halilibo.richtext.markdown.node.AstNode | ||
import com.halilibo.richtext.ui.RichTextScope | ||
|
||
/** | ||
* A composable that renders Markdown content according to Commonmark specification using RichText. | ||
* | ||
* @param content Markdown text. No restriction on length. | ||
* @param markdownParseOptions Options for the Markdown parser. | ||
* @param onLinkClicked A function to invoke when a link is clicked from rendered content. | ||
*/ | ||
@Composable | ||
public fun RichTextScope.Markdown( | ||
content: String, | ||
markdownParseOptions: MarkdownParseOptions = Companion.Default, | ||
onLinkClicked: ((String) -> Unit)? = null | ||
) { | ||
val commonmarkAstNodeParser = remember(markdownParseOptions) { | ||
CommonmarkAstNodeParser(markdownParseOptions) | ||
} | ||
|
||
val astRootNode by produceState<AstNode?>(null, commonmarkAstNodeParser) { | ||
value = commonmarkAstNodeParser.parse(content) | ||
} | ||
|
||
astRootNode?.let { | ||
Markdown(astNode = it, onLinkClicked = onLinkClicked) | ||
} | ||
} | ||
|
||
/** | ||
* A helper class that can convert any text content into an ASTNode tree and return its root. | ||
*/ | ||
public expect class CommonmarkAstNodeParser( | ||
options: MarkdownParseOptions = MarkdownParseOptions.Default | ||
) { | ||
|
||
/** | ||
* Parse markdown content and return Abstract Syntax Tree(AST). | ||
* | ||
* @param text Markdown text to be parsed. | ||
* @param options Options for the Commonmark Markdown parser. | ||
*/ | ||
public fun parse(text: String): AstNode | ||
} |
2 changes: 1 addition & 1 deletion
2
...richtext/markdown/MarkdownParseOptions.kt → ...chtext/commonmark/MarkdownParseOptions.kt
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
12 changes: 0 additions & 12 deletions
12
richtext-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstNode.kt
This file was deleted.
Oops, something went wrong.
32 changes: 0 additions & 32 deletions
32
...text-commonmark/src/commonMain/kotlin/com/halilibo/richtext/markdown/node/AstNodeLinks.kt
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.