Skip to content

Commit

Permalink
Wire up GFM Tables extension
Browse files Browse the repository at this point in the history
  • Loading branch information
obask committed Mar 31, 2024
1 parent 2dc4fae commit 49ce567
Show file tree
Hide file tree
Showing 19 changed files with 272 additions and 6 deletions.
1 change: 1 addition & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ poko = "0.13.1"

[libraries]
commonmark-core = { module = "org.commonmark:commonmark", version.ref = "commonmark" }
commonmark-ext-gfm-tables = { module = "org.commonmark:commonmark-ext-gfm-tables", version.ref = "commonmark" }

filePicker = { module = "com.darkrockstudios:mpfilepicker", version = "3.1.0" }

Expand Down
23 changes: 23 additions & 0 deletions markdown/core/api/core.api
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,20 @@ public final class org/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$Indented
public abstract interface class org/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock : org/jetbrains/jewel/markdown/MarkdownBlock {
}

public final class org/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock$DefaultCustomBlock : org/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock {
public static final synthetic fun box-impl (Lorg/commonmark/node/CustomBlock;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock$DefaultCustomBlock;
public static fun constructor-impl (Lorg/commonmark/node/CustomBlock;)Lorg/commonmark/node/CustomBlock;
public fun equals (Ljava/lang/Object;)Z
public static fun equals-impl (Lorg/commonmark/node/CustomBlock;Ljava/lang/Object;)Z
public static final fun equals-impl0 (Lorg/commonmark/node/CustomBlock;Lorg/commonmark/node/CustomBlock;)Z
public final fun getNativeBlock ()Lorg/commonmark/node/CustomBlock;
public fun hashCode ()I
public static fun hashCode-impl (Lorg/commonmark/node/CustomBlock;)I
public fun toString ()Ljava/lang/String;
public static fun toString-impl (Lorg/commonmark/node/CustomBlock;)Ljava/lang/String;
public final synthetic fun unbox-impl ()Lorg/commonmark/node/CustomBlock;
}

public final class org/jetbrains/jewel/markdown/MarkdownBlock$Heading : org/jetbrains/jewel/markdown/BlockWithInlineMarkdown, org/jetbrains/jewel/markdown/MarkdownBlock {
public static final field $stable I
public fun <init> (Ljava/util/List;I)V
Expand Down Expand Up @@ -418,6 +432,11 @@ public abstract interface class org/jetbrains/jewel/markdown/extensions/Markdown
public abstract fun processMarkdownBlock (Lorg/commonmark/node/CustomBlock;Lorg/jetbrains/jewel/markdown/processing/MarkdownProcessor;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock;
}

public final class org/jetbrains/jewel/markdown/extensions/MarkdownBlockProcessorExtension$DefaultImpls {
public static fun canProcess (Lorg/jetbrains/jewel/markdown/extensions/MarkdownBlockProcessorExtension;Lorg/commonmark/node/CustomBlock;)Z
public static fun processMarkdownBlock (Lorg/jetbrains/jewel/markdown/extensions/MarkdownBlockProcessorExtension;Lorg/commonmark/node/CustomBlock;Lorg/jetbrains/jewel/markdown/processing/MarkdownProcessor;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock;
}

public abstract interface class org/jetbrains/jewel/markdown/extensions/MarkdownBlockRendererExtension {
public abstract fun canRender (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock;)Z
public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;Lorg/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer;Landroidx/compose/runtime/Composer;I)V
Expand All @@ -429,6 +448,10 @@ public abstract interface class org/jetbrains/jewel/markdown/extensions/Markdown
public abstract fun getTextRendererExtension ()Lorg/commonmark/renderer/text/TextContentRenderer$TextContentRendererExtension;
}

public final class org/jetbrains/jewel/markdown/extensions/MarkdownProcessorExtension$DefaultImpls {
public static fun getProcessorExtension (Lorg/jetbrains/jewel/markdown/extensions/MarkdownProcessorExtension;)Lorg/jetbrains/jewel/markdown/extensions/MarkdownBlockProcessorExtension;
}

public abstract interface class org/jetbrains/jewel/markdown/extensions/MarkdownRendererExtension {
public abstract fun getBlockRenderer ()Lorg/jetbrains/jewel/markdown/extensions/MarkdownBlockRendererExtension;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.jetbrains.jewel.markdown

import org.commonmark.node.CustomBlock as CMCustomBlock

public sealed interface MarkdownBlock {

public data class BlockQuote(val children: List<MarkdownBlock>) : MarkdownBlock
Expand All @@ -18,7 +20,10 @@ public sealed interface MarkdownBlock {
) : CodeBlock
}

public interface CustomBlock : MarkdownBlock
public interface CustomBlock : MarkdownBlock {
@JvmInline
public value class DefaultCustomBlock(public val nativeBlock: CMCustomBlock) : CustomBlock
}

public data class Heading(
override val inlineContent: List<InlineMarkdown>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ public interface MarkdownBlockProcessorExtension {
*
* @param block The [CustomBlock] to parse
*/
public fun canProcess(block: CustomBlock): Boolean
public fun canProcess(block: CustomBlock): Boolean = false

/**
* Processes the [block] as a [MarkdownBlock.CustomBlock], if possible. Note
* that you should always check that [canProcess] returns true for the same
* [block], as implementations might throw an exception for unsupported
* block types.
*/
public fun processMarkdownBlock(block: CustomBlock, processor: MarkdownProcessor): MarkdownBlock.CustomBlock?
public fun processMarkdownBlock(block: CustomBlock, processor: MarkdownProcessor): MarkdownBlock.CustomBlock? = null
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ public interface MarkdownProcessorExtension {
* [MarkdownBlock.CustomBlock].
*/
public val processorExtension: MarkdownBlockProcessorExtension
get() = object : MarkdownBlockProcessorExtension {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import org.jetbrains.jewel.foundation.ExperimentalJewelApi
import org.jetbrains.jewel.markdown.InlineMarkdown
import org.jetbrains.jewel.markdown.MarkdownBlock
import org.jetbrains.jewel.markdown.MarkdownBlock.CodeBlock
import org.jetbrains.jewel.markdown.MarkdownBlock.CustomBlock.DefaultCustomBlock
import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock
import org.jetbrains.jewel.markdown.MimeType
import org.jetbrains.jewel.markdown.extensions.MarkdownProcessorExtension
Expand Down Expand Up @@ -192,6 +193,7 @@ public class MarkdownProcessor(
is CustomBlock -> {
extensions.find { it.processorExtension.canProcess(this) }
?.processorExtension?.processMarkdownBlock(this, this@MarkdownProcessor)
?: DefaultCustomBlock(this)
}

else -> null
Expand Down
35 changes: 35 additions & 0 deletions markdown/extension/gfm-tables/api/gfm-tables.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
public final class org/jetbrains/jewel/markdown/extensions/tables/GitHubTableBlockRenderer : org/jetbrains/jewel/markdown/extensions/MarkdownBlockRendererExtension {
public static final field $stable I
public fun <init> (Lorg/jetbrains/jewel/markdown/extensions/tables/TableStyling;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;)V
public fun canRender (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock;)Z
public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;Lorg/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer;Landroidx/compose/runtime/Composer;I)V
}

public final class org/jetbrains/jewel/markdown/extensions/tables/GitHubTableProcessorExtension : org/jetbrains/jewel/markdown/extensions/MarkdownProcessorExtension {
public static final field $stable I
public static final field INSTANCE Lorg/jetbrains/jewel/markdown/extensions/tables/GitHubTableProcessorExtension;
public fun getParserExtension ()Lorg/commonmark/parser/Parser$ParserExtension;
public fun getProcessorExtension ()Lorg/jetbrains/jewel/markdown/extensions/MarkdownBlockProcessorExtension;
public fun getTextRendererExtension ()Lorg/commonmark/renderer/text/TextContentRenderer$TextContentRendererExtension;
}

public final class org/jetbrains/jewel/markdown/extensions/tables/GitHubTableRendererExtension : org/jetbrains/jewel/markdown/extensions/MarkdownRendererExtension {
public static final field $stable I
public fun <init> (Lorg/jetbrains/jewel/markdown/extensions/tables/TableStyling;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;)V
public fun getBlockRenderer ()Lorg/jetbrains/jewel/markdown/extensions/MarkdownBlockRendererExtension;
}

public final class org/jetbrains/jewel/markdown/extensions/tables/TableStyling {
public static final field $stable I
public static final field Companion Lorg/jetbrains/jewel/markdown/extensions/tables/TableStyling$Companion;
public synthetic fun <init> (JJLkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun equals (Ljava/lang/Object;)Z
public final fun getBorderColor-0d7_KjU ()J
public final fun getHeadColor-0d7_KjU ()J
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class org/jetbrains/jewel/markdown/extensions/tables/TableStyling$Companion {
}

23 changes: 23 additions & 0 deletions markdown/extension/gfm-tables/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
plugins {
jewel
`jewel-publish`
`jewel-check-public-api`
alias(libs.plugins.composeDesktop)
}

dependencies {
implementation(projects.markdown.core)
implementation(libs.commonmark.ext.gfm.tables)

testImplementation(compose.desktop.uiTestJUnit4)
}

publicApiValidation {
// TODO Oleg remove this once migrated to value classes
excludedClassRegexes = setOf("org.jetbrains.jewel.markdown.extensions.github.alerts.*")
}

publishing.publications.named<MavenPublication>("main") {
val ijpTarget = project.property("ijp.target") as String
artifactId = "jewel-markdown-extension-${project.name}-$ijpTarget"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package org.jetbrains.jewel.markdown.extensions.tables

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import org.commonmark.ext.gfm.tables.TableBlock
import org.commonmark.ext.gfm.tables.TableBody
import org.commonmark.ext.gfm.tables.TableHead
import org.commonmark.node.Node
import org.jetbrains.jewel.markdown.InlineMarkdown
import org.jetbrains.jewel.markdown.MarkdownBlock.CustomBlock
import org.jetbrains.jewel.markdown.extensions.MarkdownBlockRendererExtension
import org.jetbrains.jewel.markdown.rendering.InlineMarkdownRenderer
import org.jetbrains.jewel.markdown.rendering.MarkdownBlockRenderer
import org.jetbrains.jewel.markdown.rendering.MarkdownStyling
import org.jetbrains.jewel.markdown.toInlineNode
import org.jetbrains.jewel.ui.component.Text

public class GitHubTableBlockRenderer(
private val styling: TableStyling,
private val rootStyling: MarkdownStyling,
) : MarkdownBlockRendererExtension {

override fun canRender(block: CustomBlock): Boolean =
block is CustomBlock.DefaultCustomBlock && block.nativeBlock is TableBlock

@Composable
private fun RowScope.TableCell(
text: List<InlineMarkdown>,
inlineRenderer: InlineMarkdownRenderer,
) {
Text(
text = inlineRenderer.renderAsAnnotatedString(text, rootStyling.paragraph.inlinesStyling),
Modifier
.border(1.dp, styling.borderColor)
.weight(1.0f)
.padding(8.dp),
)
}

@Composable
override fun render(
block: CustomBlock,
blockRenderer: MarkdownBlockRenderer,
inlineRenderer: InlineMarkdownRenderer,
) {
if (block !is CustomBlock.DefaultCustomBlock) return

val head = block.nativeBlock.firstChild as TableHead
val body = block.nativeBlock.lastChild as TableBody

Column(Modifier.fillMaxSize().padding(16.dp)) {
head.forEachChild { row ->
Row(Modifier.background(styling.headColor)) {
row.forEachChild { cell ->
TableCell(text = cell.children().map { it.toInlineNode() }, inlineRenderer)
}
}
}
body.forEachChild { row ->
Row(Modifier.fillMaxWidth()) {
row.forEachChild { cell ->
TableCell(text = cell.children().map { it.toInlineNode() }, inlineRenderer)
}
}
}
}
}

@Composable
private fun Node.children(): List<Node> = buildList {
var child = firstChild

while (child != null) {
add(child)
child = child.next
}
}
}

@Composable
private fun Node.forEachChild(action: @Composable (Node) -> Unit) {
var child = firstChild

while (child != null) {
action(child)
child = child.next
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.jetbrains.jewel.markdown.extensions.tables

import org.commonmark.ext.gfm.tables.TablesExtension
import org.commonmark.parser.Parser.ParserExtension
import org.commonmark.renderer.text.TextContentRenderer.TextContentRendererExtension
import org.jetbrains.jewel.markdown.extensions.MarkdownProcessorExtension

public object GitHubTableProcessorExtension : MarkdownProcessorExtension {

override val parserExtension: ParserExtension = TablesExtension.create() as ParserExtension
override val textRendererExtension: TextContentRendererExtension = TablesExtension.create() as TextContentRendererExtension
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.jetbrains.jewel.markdown.extensions.tables

import org.jetbrains.jewel.markdown.extensions.MarkdownBlockRendererExtension
import org.jetbrains.jewel.markdown.extensions.MarkdownRendererExtension
import org.jetbrains.jewel.markdown.rendering.MarkdownStyling

public class GitHubTableRendererExtension(
alertStyling: TableStyling,
rootStyling: MarkdownStyling,
) : MarkdownRendererExtension {

override val blockRenderer: MarkdownBlockRendererExtension =
GitHubTableBlockRenderer(alertStyling, rootStyling)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.jetbrains.jewel.markdown.extensions.tables

import androidx.compose.ui.graphics.Color
import org.jetbrains.jewel.foundation.GenerateDataFunctions

@GenerateDataFunctions
public class TableStyling(
public val headColor: Color,
public val borderColor: Color,
) {

public companion object
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,10 @@ public final class org/jetbrains/jewel/intui/markdown/styling/extension/github/a
public static synthetic fun light-gaOEZmc$default (Lorg/jetbrains/jewel/markdown/extensions/github/alerts/WarningAlertStyling$Companion;Landroidx/compose/foundation/layout/PaddingValues;FJLandroidx/compose/ui/graphics/PathEffect;ILandroidx/compose/ui/text/TextStyle;Ljava/lang/String;JJILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/extensions/github/alerts/WarningAlertStyling;
}

public final class org/jetbrains/jewel/intui/markdown/styling/extension/github/alerts/GitHubTableDefaultStylingKt {
public static final fun dark-WkMS-hQ (Lorg/jetbrains/jewel/markdown/extensions/tables/TableStyling$Companion;JJ)Lorg/jetbrains/jewel/markdown/extensions/tables/TableStyling;
public static synthetic fun dark-WkMS-hQ$default (Lorg/jetbrains/jewel/markdown/extensions/tables/TableStyling$Companion;JJILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/extensions/tables/TableStyling;
public static final fun light-WkMS-hQ (Lorg/jetbrains/jewel/markdown/extensions/tables/TableStyling$Companion;JJ)Lorg/jetbrains/jewel/markdown/extensions/tables/TableStyling;
public static synthetic fun light-WkMS-hQ$default (Lorg/jetbrains/jewel/markdown/extensions/tables/TableStyling$Companion;JJILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/extensions/tables/TableStyling;
}

1 change: 1 addition & 0 deletions markdown/int-ui-standalone-styling/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ dependencies {
api(projects.markdown.core)
api(projects.intUi.intUiStandalone)
compileOnly(projects.markdown.extension.gfmAlerts)
compileOnly(projects.markdown.extension.gfmTables)

testImplementation(compose.desktop.uiTestJUnit4)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.jetbrains.jewel.intui.markdown.styling.extension.github.alerts

import androidx.compose.ui.graphics.Color
import org.jetbrains.jewel.markdown.extensions.tables.TableStyling

public fun TableStyling.Companion.dark(
headColor: Color = Color.DarkGray,
borderColor: Color = Color.Gray,
): TableStyling = TableStyling(
headColor,
borderColor,
)

public fun TableStyling.Companion.light(
headColor: Color = Color.LightGray,
borderColor: Color = Color.Gray,
): TableStyling = TableStyling(
headColor,
borderColor,
)
1 change: 1 addition & 0 deletions samples/standalone/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies {
implementation(projects.intUi.intUiDecoratedWindow)
implementation(projects.markdown.intUiStandaloneStyling)
implementation(projects.markdown.extension.gfmAlerts)
implementation(projects.markdown.extension.gfmTables)

implementation(compose.desktop.currentOs) {
exclude(group = "org.jetbrains.compose.material")
Expand Down
Loading

0 comments on commit 49ce567

Please sign in to comment.