Skip to content

Commit

Permalink
Merge pull request #257 from mikepenz/feature-add-table-support
Browse files Browse the repository at this point in the history
Add support for simple tables
  • Loading branch information
mikepenz authored Dec 31, 2024
2 parents f137a52 + 1584276 commit 7c8365a
Show file tree
Hide file tree
Showing 17 changed files with 284 additions and 54 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,21 @@ Markdown(
)
```

### Table Support

Starting with 0.30.0, the library includes support for rendering tables in markdown. The `Markdown` composable will automatically handle table elements in your markdown content.

```kotlin
val markdown = """
| Header 1 | Header 2 |
|----------|----------|
| Cell 1 | Cell 2 |
| Cell 3 | Cell 4 |
""".trimIndent()

Markdown(markdown)
```

</p>
</details>

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,47 +1,39 @@
package com.mikepenz.markdown.ui

import android.content.res.Configuration
import android.graphics.Color
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import com.mikepenz.markdown.m2.Markdown

class SnapshotTests {
@Preview(showBackground = true, backgroundColor = Color.WHITE.toLong(), heightDp = 1750)
@Preview(showBackground = true, backgroundColor = Color.BLACK.toLong(), heightDp = 1750, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun DefaultTest() = TestThemeSetup {
Markdown(MARKDOWN_DEFAULT)
}

@Preview(showBackground = true, backgroundColor = Color.BLACK.toLong(), heightDp = 1750)
@Composable
fun DefaultDarkTest() = TestThemeSetup(true) {
fun DefaultTest() = SampleTheme(isSystemInDarkTheme()) {
Markdown(MARKDOWN_DEFAULT)
}

@Preview(showBackground = true, backgroundColor = Color.WHITE.toLong(), heightDp = 1000)
@Preview(showBackground = true, backgroundColor = Color.BLACK.toLong(), heightDp = 1000, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun RandomTest() = TestThemeSetup {
Markdown(MARKDOWN_RANDOM)
}

@Preview(showBackground = true, backgroundColor = Color.BLACK.toLong(), heightDp = 1000)
@Composable
fun RandomDarkTest() = TestThemeSetup(true) {
fun RandomTest() = SampleTheme(isSystemInDarkTheme()) {
Markdown(MARKDOWN_RANDOM)
}

@Preview(showBackground = true, backgroundColor = Color.WHITE.toLong(), heightDp = 380)
@Preview(showBackground = true, backgroundColor = Color.BLACK.toLong(), heightDp = 380, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun ListCodeBlockTest() = TestThemeSetup {
fun ListCodeBlockTest() = SampleTheme(isSystemInDarkTheme()) {
Markdown(MARKDOWN_LIST_CODE_BLOCK)
}

/**Helper to have a single place setting up the theme*/
@Preview(showBackground = true, backgroundColor = Color.WHITE.toLong(), heightDp = 1250)
@Preview(showBackground = true, backgroundColor = Color.BLACK.toLong(), heightDp = 1250, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun TestThemeSetup(dark: Boolean = false, block: @Composable () -> Unit) {
SampleTheme(dark) {
block()
}
fun TableTest() = SampleTheme(isSystemInDarkTheme()) {
Markdown(MARKDOWN_TABLE)
}
}

Expand Down Expand Up @@ -149,4 +141,48 @@ private val MARKDOWN_LIST_CODE_BLOCK = """
```
- Sub-subitem 2
- Subitem 3
""".trimIndent()

private val MARKDOWN_TABLE = """
// simple table
| First Header | Second Header |
| ------------- | ------------- |
| Content Cell | Content Cell |
| Content Cell | Content Cell |
// simple table with long rows
| Command | Description |
| --- | --- |
| git status | List all new or modified files |
| git diff | Show file differences that haven't been staged |
// formatting table content
| Command | Description |
| --- | --- |
| `git status` | List all *new or modified* files |
| `git diff` | Show file differences that **haven't been** staged |
// alignment - not supported as of yet
| Left-aligned | Center-aligned | Right-aligned |
| :--- | :---: | ---: |
| git status | git status | git status |
| git diff | git diff | git diff |
// special content
| Name | Character |
| --- | --- |
| Backtick | ` |
| Pipe | \| |
// incorrect columns
| abc | def |
| --- | --- |
| bar |
| bar | baz | boo |
""".trimIndent()
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@ fun markdownColor(
codeBackground: Color = MaterialTheme.colors.onBackground.copy(alpha = 0.1f),
inlineCodeBackground: Color = codeBackground,
dividerColor: Color = MaterialTheme.colors.onSurface.copy(alpha = 0.12f),
tableText: Color = text,
tableBackground: Color = MaterialTheme.colors.onBackground.copy(alpha = 0.02f),
): MarkdownColors = DefaultMarkdownColors(
text = text,
codeText = codeText,
inlineCodeText = inlineCodeText,
linkText = linkText,
codeBackground = codeBackground,
inlineCodeBackground = inlineCodeBackground,
dividerColor = dividerColor
dividerColor = dividerColor,
tableText = tableText,
tableBackground = tableBackground,
)
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ fun markdownColor(
codeBackground: Color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.1f),
inlineCodeBackground: Color = codeBackground,
dividerColor: Color = MaterialTheme.colorScheme.outlineVariant,
tableText: Color = text,
tableBackground: Color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.02f),
): MarkdownColors = DefaultMarkdownColors(
text = text,
codeText = codeText,
Expand All @@ -23,4 +25,6 @@ fun markdownColor(
codeBackground = codeBackground,
inlineCodeBackground = inlineCodeBackground,
dividerColor = dividerColor,
tableText = tableText,
tableBackground = tableBackground,
)
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import org.intellij.markdown.MarkdownTokenTypes.Companion.HORIZONTAL_RULE
import org.intellij.markdown.MarkdownTokenTypes.Companion.TEXT
import org.intellij.markdown.ast.ASTNode
import org.intellij.markdown.flavours.MarkdownFlavourDescriptor
import org.intellij.markdown.flavours.gfm.GFMElementTypes.TABLE
import org.intellij.markdown.flavours.gfm.GFMFlavourDescriptor
import org.intellij.markdown.parser.MarkdownParser

Expand Down Expand Up @@ -106,6 +107,7 @@ internal fun ColumnScope.handleElement(
IMAGE -> components.image(this@handleElement, model)
LINK_DEFINITION -> components.linkDefinition(this@handleElement, model)
HORIZONTAL_RULE -> components.horizontalRule(this@handleElement, model)
TABLE -> components.table(this@handleElement, model)
else -> {
handled = components.custom?.invoke(this@handleElement, node.type, model) != null
}
Expand All @@ -118,4 +120,4 @@ internal fun ColumnScope.handleElement(
}

return handled
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ fun markdownComponents(
image: MarkdownComponent = CurrentComponentsBridge.image,
linkDefinition: MarkdownComponent = CurrentComponentsBridge.linkDefinition,
horizontalRule: MarkdownComponent = CurrentComponentsBridge.horizontalRule,
table: MarkdownComponent = CurrentComponentsBridge.table,
custom: CustomMarkdownComponent? = CurrentComponentsBridge.custom,
): MarkdownComponents = DefaultMarkdownComponents(
text = text,
Expand All @@ -72,6 +73,7 @@ fun markdownComponents(
image = image,
linkDefinition = linkDefinition,
horizontalRule = horizontalRule,
table = table,
custom = custom,
)

Expand Down Expand Up @@ -99,6 +101,7 @@ interface MarkdownComponents {
val image: MarkdownComponent
val linkDefinition: MarkdownComponent
val horizontalRule: MarkdownComponent
val table: MarkdownComponent
val custom: CustomMarkdownComponent?
}

Expand All @@ -122,6 +125,7 @@ private class DefaultMarkdownComponents(
override val image: MarkdownComponent,
override val linkDefinition: MarkdownComponent,
override val horizontalRule: MarkdownComponent,
override val table: MarkdownComponent,
override val custom: CustomMarkdownComponent?,
) : MarkdownComponents

Expand Down Expand Up @@ -194,5 +198,8 @@ object CurrentComponentsBridge {
val horizontalRule: MarkdownComponent = {
MarkdownDivider(Modifier.fillMaxWidth())
}
val table: MarkdownComponent = {
MarkdownTable(it.content, it.node, style = it.typography.text)
}
val custom: CustomMarkdownComponent? = null
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package com.mikepenz.markdown.compose.elements

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
Expand Down Expand Up @@ -31,3 +29,23 @@ fun MarkdownDivider(
.background(color = color)
)
}


@Composable
fun VerticalMarkdownDivider(
modifier: Modifier = Modifier,
color: Color = LocalMarkdownColors.current.dividerColor,
thickness: Dp = LocalMarkdownDimens.current.dividerThickness,
) {
val targetThickness = if (thickness == Dp.Hairline) {
(1f / LocalDensity.current.density).dp
} else {
thickness
}
Box(
modifier
.width(targetThickness)
.fillMaxHeight()
.background(color = color)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,14 @@ package com.mikepenz.markdown.compose.elements

import androidx.compose.runtime.Composable
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.buildAnnotatedString
import com.mikepenz.markdown.compose.LocalMarkdownAnnotator
import com.mikepenz.markdown.compose.LocalMarkdownTypography
import com.mikepenz.markdown.utils.buildMarkdownAnnotatedString
import com.mikepenz.markdown.utils.codeSpanStyle
import com.mikepenz.markdown.utils.linkTextSpanStyle
import org.intellij.markdown.IElementType
import org.intellij.markdown.MarkdownTokenTypes
import org.intellij.markdown.ast.ASTNode
import org.intellij.markdown.ast.findChildOfType

@Composable
fun MarkdownHeader(
content: String,
node: ASTNode,
style: TextStyle,
contentChildType: IElementType = MarkdownTokenTypes.ATX_CONTENT,
) {
val annotator = LocalMarkdownAnnotator.current
val linkTextSpanStyle = LocalMarkdownTypography.current.linkTextSpanStyle
val codeSpanStyle = LocalMarkdownTypography.current.codeSpanStyle

node.findChildOfType(contentChildType)?.let {
val styledText = buildAnnotatedString {
pushStyle(style.toSpanStyle())
buildMarkdownAnnotatedString(content, it, linkTextSpanStyle, codeSpanStyle, annotator)
pop()
}

MarkdownText(styledText, style = style)
}
}
) = MarkdownText(content = content, node = node, style = style, contentChildType = contentChildType)
Loading

0 comments on commit 7c8365a

Please sign in to comment.