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 authored and Oleg Baskakov committed Apr 2, 2024
1 parent 5d33bd5 commit cdf90a7
Show file tree
Hide file tree
Showing 20 changed files with 276 additions and 12 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 @@ -17,6 +17,7 @@ poko = "0.13.1"
[libraries]
commonmark-core = { module = "org.commonmark:commonmark", version.ref = "commonmark" }
commonmark-ext-autolink = { module = "org.commonmark:commonmark-ext-autolink", 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 @@ -233,6 +233,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 synthetic fun box-impl (Lorg/commonmark/node/Heading;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading;
public static fun constructor-impl (Lorg/commonmark/node/Heading;)Lorg/commonmark/node/Heading;
Expand Down Expand Up @@ -406,6 +420,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 @@ -417,6 +436,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,6 +1,7 @@
package org.jetbrains.jewel.markdown

import org.commonmark.node.Block
import org.commonmark.node.CustomBlock as CMCustomBlock
import org.commonmark.node.Heading as CMHeading
import org.commonmark.node.Paragraph as CMParagraph

Expand All @@ -22,7 +23,10 @@ public sealed interface MarkdownBlock {
) : CodeBlock
}

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

@JvmInline
public value class Heading(
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 @@ -32,5 +32,6 @@ public interface MarkdownProcessorExtension {
* is already be handled by [org.jetbrains.jewel.markdown.processing.MarkdownProcessor]
* or another [org.jetbrains.jewel.markdown.extensions.MarkdownProcessorExtension].
*/
public val processorExtension: MarkdownBlockProcessorExtension?
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 @@ -189,8 +190,9 @@ public class MarkdownProcessor(
is ThematicBreak -> MarkdownBlock.ThematicBreak
is HtmlBlock -> toMarkdownHtmlBlockOrNull()
is CustomBlock -> {
extensions.find { it.processorExtension?.canProcess(this) == true }
extensions.find { it.processorExtension.canProcess(this) }
?.processorExtension?.processMarkdownBlock(this, this@MarkdownProcessor)
?: DefaultCustomBlock(this)
}

else -> null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package org.jetbrains.jewel.markdown.extension.autolink
import org.commonmark.ext.autolink.AutolinkExtension
import org.commonmark.parser.Parser.ParserExtension
import org.commonmark.renderer.text.TextContentRenderer
import org.jetbrains.jewel.markdown.extensions.MarkdownBlockProcessorExtension
import org.jetbrains.jewel.markdown.extensions.MarkdownProcessorExtension

public object AutolinkProcessorExtension : MarkdownProcessorExtension {

override val parserExtension: ParserExtension
get() = AutolinkExtension.create() as ParserExtension

Expand All @@ -15,6 +15,4 @@ public object AutolinkProcessorExtension : MarkdownProcessorExtension {
*/
override val textRendererExtension: TextContentRenderer.TextContentRendererExtension?
get() = null
override val processorExtension: MarkdownBlockProcessorExtension?
get() = null
}
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,
)
4 changes: 3 additions & 1 deletion samples/standalone/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ dependencies {
implementation(projects.intUi.intUiStandalone)
implementation(projects.intUi.intUiDecoratedWindow)
implementation(projects.markdown.intUiStandaloneStyling)
implementation(projects.markdown.extension.gfmAlerts)
implementation(projects.markdown.extension.autolink)
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 cdf90a7

Please sign in to comment.