Skip to content

Commit

Permalink
- introduce first draft of extended-spans by porting https://github…
Browse files Browse the repository at this point in the history
….com/saket/extended-spans into this library

  - Offer ability to define extended spans for the Markdown class used by the internal text component
  • Loading branch information
mikepenz committed Apr 26, 2024
1 parent 54b4e7c commit 828b553
Show file tree
Hide file tree
Showing 15 changed files with 820 additions and 33 deletions.
60 changes: 50 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ dependencies {
</details>

> [!TIP]
> Since 0.13.0 the core library does not depend on a Material theme anymore. Include the `-m2` or `-m3` module to get
> Since 0.13.0 the core library does not depend on a Material theme anymore. Include the `-m2`
> or `-m3` module to get
> access to the defaults.

Expand Down Expand Up @@ -121,6 +122,35 @@ Markdown(
)
```

### Extended spans

Starting with 0.16.0 the library includes support
for [extended-spans](https://github.com/saket/extended-spans).
> The library was integrated to to make it multiplatform compatible. All credits for its
> functionality goes to [
Saket Narayan](https://github.com/saket).

It is not enabled by default, however you can enable it quickly by configuring the `extendedSpans`
for your `Markdown` composeable.
Define the `ExtendedSpans` you want to apply (including optionally your own custom ones) and return
it.

```kotlin
Markdown(
content,
extendedSpans = markdownExtendedSpans {
val animator = rememberSquigglyUnderlineAnimator()
remember {
ExtendedSpans(
RoundedCornerSpanPainter(),
SquigglyUnderlineSpanPainter(animator = animator)
)
}
},
modifier = Modifier.fillMaxSize().verticalScroll(scrollState).padding(16.dp)
)
```

### Adjust List Ordering

```kotlin
Expand All @@ -142,7 +172,8 @@ This can be done by providing the components `MarkdownComponents` to the `Markdo

Use the `markdownComponents()` to keep defaults for non overwritten components.

The `MarkdownComponent` will expose access to the `content: String`, `node: ASTNode`, `typography: MarkdownTypography`,
The `MarkdownComponent` will expose access to
the `content: String`, `node: ASTNode`, `typography: MarkdownTypography`,
offering full flexibility.

```kotlin
Expand Down Expand Up @@ -185,18 +216,20 @@ Markdown(

In the current versions of the library, image loading is included in different variants.

- Android: Uses `coil` to load images (Default configuration). The global `ImageLoader` is respected.
- Android: Uses `coil` to load images (Default configuration). The global `ImageLoader` is
respected.
- JVM: Load image as HTTPUrlConnection and set to the view
- JS / Native: No image loading provided at this time

Provide your own `ImageTransformer` to the `Markdown` compose function to modify this behavior.
Provide your own `ImageTransformer` to the `Markdown` compose function to modify this behavior.

> [!NOTE]
> It is planned to update to coil3 for all platforms once it reaches a more stable release cycle.
## Dependency

This project uses JetBrains [markdown](https://github.com/JetBrains/markdown/) Multiplatform Markdown processor as
This project uses JetBrains [markdown](https://github.com/JetBrains/markdown/) Multiplatform
Markdown processor as
dependency to parse the markdown content.

## Developed By
Expand All @@ -207,20 +240,27 @@ dependency to parse the markdown content.

## Contributors

This free, open source software was also made possible by a group of volunteers that put many hours of hard work into
This free, open source software was also made possible by a group of volunteers that put many hours
of hard work into
it. See the [CONTRIBUTORS.md](CONTRIBUTORS.md) file for details.

## Credits

Big thanks to [Erik Hellman](https://twitter.com/ErikHellman) and his awesome article
on [Rendering Markdown with Jetpack Compose](https://www.hellsoft.se/rendering-markdown-with-jetpack-compose/), and the
related source [MarkdownComposer](https://github.com/ErikHellman/MarkdownComposer).
on [Rendering Markdown with Jetpack Compose](https://www.hellsoft.se/rendering-markdown-with-jetpack-compose/),
and the related source [MarkdownComposer](https://github.com/ErikHellman/MarkdownComposer).

Also huge thanks to [Saket Narayan](https://github.com/saket/) for his great work on
the [extended-spans](https://github.com/saket/extended-spans) project. Ported into this project to
make it multiplatform.

## Fork License

Copyright for portions of the code are held by [Erik Hellman, 2020] as part of
project [MarkdownComposer](https://github.com/ErikHellman/MarkdownComposer) under the MIT license. All other copyright
for project multiplatform-markdown-renderer are held by [Mike Penz, 2023] under the Apache License, Version 2.0.
project [MarkdownComposer](https://github.com/ErikHellman/MarkdownComposer) under the MIT license.
All other copyright
for project multiplatform-markdown-renderer are held by [Mike Penz, 2023] under the Apache License,
Version 2.0.

## License

Expand Down
17 changes: 16 additions & 1 deletion compose-desktop/src/main/kotlin/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import com.mikepenz.markdown.compose.extendedspans.ExtendedSpans
import com.mikepenz.markdown.compose.extendedspans.RoundedCornerSpanPainter
import com.mikepenz.markdown.compose.extendedspans.SquigglyUnderlineSpanPainter
import com.mikepenz.markdown.compose.extendedspans.rememberSquigglyUnderlineAnimator
import com.mikepenz.markdown.m2.Markdown
import com.mikepenz.markdown.model.markdownExtendedSpans

fun main() = application {
Window(onCloseRequest = ::exitApplication, title = "Markdown Sample") {
Expand Down Expand Up @@ -40,7 +46,6 @@ fun main() = application {
There are many more things which can be experimented with like, inline `code`.
Title 1
======
Expand All @@ -51,8 +56,18 @@ fun main() = application {
[https://github.com/mikepenz](https://github.com/mikepenz)
[Mike Penz's Blog](https://blog.mikepenz.dev/)
""".trimIndent()

Markdown(
content,
extendedSpans = markdownExtendedSpans {
val animator = rememberSquigglyUnderlineAnimator()
remember {
ExtendedSpans(
RoundedCornerSpanPainter(),
SquigglyUnderlineSpanPainter(animator = animator)
)
}
},
modifier = Modifier.fillMaxSize().verticalScroll(scrollState).padding(16.dp)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,16 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.mikepenz.markdown.compose.components.MarkdownComponents
import com.mikepenz.markdown.compose.components.markdownComponents
import com.mikepenz.markdown.model.*
import com.mikepenz.markdown.model.ImageTransformer
import com.mikepenz.markdown.model.ImageTransformerImpl
import com.mikepenz.markdown.model.MarkdownColors
import com.mikepenz.markdown.model.MarkdownDimens
import com.mikepenz.markdown.model.MarkdownExtendedSpans
import com.mikepenz.markdown.model.MarkdownPadding
import com.mikepenz.markdown.model.MarkdownTypography
import com.mikepenz.markdown.model.markdownDimens
import com.mikepenz.markdown.model.markdownExtendedSpans
import com.mikepenz.markdown.model.markdownPadding
import org.intellij.markdown.flavours.MarkdownFlavourDescriptor
import org.intellij.markdown.flavours.gfm.GFMFlavourDescriptor

Expand All @@ -19,6 +28,7 @@ fun Markdown(
dimens: MarkdownDimens = markdownDimens(),
flavour: MarkdownFlavourDescriptor = GFMFlavourDescriptor(),
imageTransformer: ImageTransformer = ImageTransformerImpl(),
extendedSpans: MarkdownExtendedSpans = markdownExtendedSpans(),
components: MarkdownComponents = markdownComponents(),
) = com.mikepenz.markdown.compose.Markdown(
content,
Expand All @@ -29,5 +39,6 @@ fun Markdown(
dimens,
flavour,
imageTransformer,
extendedSpans,
components,
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,16 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.mikepenz.markdown.compose.components.MarkdownComponents
import com.mikepenz.markdown.compose.components.markdownComponents
import com.mikepenz.markdown.model.*
import com.mikepenz.markdown.model.ImageTransformer
import com.mikepenz.markdown.model.ImageTransformerImpl
import com.mikepenz.markdown.model.MarkdownColors
import com.mikepenz.markdown.model.MarkdownDimens
import com.mikepenz.markdown.model.MarkdownExtendedSpans
import com.mikepenz.markdown.model.MarkdownPadding
import com.mikepenz.markdown.model.MarkdownTypography
import com.mikepenz.markdown.model.markdownDimens
import com.mikepenz.markdown.model.markdownExtendedSpans
import com.mikepenz.markdown.model.markdownPadding
import org.intellij.markdown.flavours.MarkdownFlavourDescriptor
import org.intellij.markdown.flavours.gfm.GFMFlavourDescriptor

Expand All @@ -19,6 +28,7 @@ fun Markdown(
dimens: MarkdownDimens = markdownDimens(),
flavour: MarkdownFlavourDescriptor = GFMFlavourDescriptor(),
imageTransformer: ImageTransformer = ImageTransformerImpl(),
extendedSpans: MarkdownExtendedSpans = markdownExtendedSpans(),
components: MarkdownComponents = markdownComponents(),
) = com.mikepenz.markdown.compose.Markdown(
content,
Expand All @@ -29,5 +39,6 @@ fun Markdown(
dimens,
flavour,
imageTransformer,
extendedSpans,
components,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@ package com.mikepenz.markdown.compose

import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.staticCompositionLocalOf
import com.mikepenz.markdown.model.*
import com.mikepenz.markdown.model.BulletHandler
import com.mikepenz.markdown.model.DefaultMarkdownExtendedSpans
import com.mikepenz.markdown.model.ImageTransformer
import com.mikepenz.markdown.model.MarkdownColors
import com.mikepenz.markdown.model.MarkdownDimens
import com.mikepenz.markdown.model.MarkdownExtendedSpans
import com.mikepenz.markdown.model.MarkdownPadding
import com.mikepenz.markdown.model.MarkdownTypography
import com.mikepenz.markdown.model.ReferenceLinkHandler

/**
* The CompositionLocal to provide functionality related to transforming the bullet of an ordered list
Expand Down Expand Up @@ -53,10 +61,16 @@ val LocalMarkdownDimens = compositionLocalOf<MarkdownDimens> {
error("No local MarkdownDimens")
}


/**
* Local [ImageTransformer] provider
*/
val LocalImageTransformer = staticCompositionLocalOf<ImageTransformer> {
error("No local ImageTransformer")
}

/**
* Local [MarkdownExtendedSpans] provider
*/
val LocalMarkdownExtendedSpans = compositionLocalOf<MarkdownExtendedSpans> {
return@compositionLocalOf DefaultMarkdownExtendedSpans(null)
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
package com.mikepenz.markdown.compose

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import com.mikepenz.markdown.compose.components.MarkdownComponentModel
import com.mikepenz.markdown.compose.components.MarkdownComponents
import com.mikepenz.markdown.compose.components.markdownComponents
import com.mikepenz.markdown.model.*
import com.mikepenz.markdown.model.ImageTransformer
import com.mikepenz.markdown.model.ImageTransformerImpl
import com.mikepenz.markdown.model.MarkdownColors
import com.mikepenz.markdown.model.MarkdownDimens
import com.mikepenz.markdown.model.MarkdownExtendedSpans
import com.mikepenz.markdown.model.MarkdownPadding
import com.mikepenz.markdown.model.MarkdownTypography
import com.mikepenz.markdown.model.ReferenceLinkHandlerImpl
import com.mikepenz.markdown.model.markdownDimens
import com.mikepenz.markdown.model.markdownExtendedSpans
import com.mikepenz.markdown.model.markdownPadding
import org.intellij.markdown.MarkdownElementTypes.ATX_1
import org.intellij.markdown.MarkdownElementTypes.ATX_2
import org.intellij.markdown.MarkdownElementTypes.ATX_3
Expand Down Expand Up @@ -42,6 +56,7 @@ fun Markdown(
dimens: MarkdownDimens = markdownDimens(),
flavour: MarkdownFlavourDescriptor = GFMFlavourDescriptor(),
imageTransformer: ImageTransformer = ImageTransformerImpl(),
extendedSpans: MarkdownExtendedSpans = markdownExtendedSpans(),
components: MarkdownComponents = markdownComponents(),
) {
CompositionLocalProvider(
Expand All @@ -50,7 +65,8 @@ fun Markdown(
LocalMarkdownDimens provides dimens,
LocalMarkdownColors provides colors,
LocalMarkdownTypography provides typography,
LocalImageTransformer provides imageTransformer
LocalImageTransformer provides imageTransformer,
LocalMarkdownExtendedSpans provides extendedSpans
) {
Column(modifier) {
val parsedTree = MarkdownParser(flavour).buildMarkdownTreeFromString(content)
Expand All @@ -66,7 +82,11 @@ fun Markdown(
}

@Composable
private fun ColumnScope.handleElement(node: ASTNode, components: MarkdownComponents, content: String): Boolean {
private fun ColumnScope.handleElement(
node: ASTNode,
components: MarkdownComponents,
content: String
): Boolean {
val model = MarkdownComponentModel(
content = content,
node = node,
Expand Down Expand Up @@ -99,7 +119,7 @@ private fun ColumnScope.handleElement(node: ASTNode, components: MarkdownCompone
}
}

if(!handled) {
if (!handled) {
node.children.forEach { child ->
handleElement(child, components, content)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,17 @@ fun MarkdownParagraph(
content: String,
node: ASTNode,
modifier: Modifier = Modifier,
style: TextStyle = LocalMarkdownTypography.current.paragraph
style: TextStyle = LocalMarkdownTypography.current.paragraph,
) {
val styledText = buildAnnotatedString {
pushStyle(style.toSpanStyle())
buildMarkdownAnnotatedString(content, node)
pop()
}
MarkdownText(styledText, modifier = modifier, style = style)

MarkdownText(
styledText,
modifier = modifier,
style = style,
)
}
Loading

0 comments on commit 828b553

Please sign in to comment.