diff --git a/.idea/modules.xml b/.idea/modules.xml
index 1990c3ca8659a..cfa50d921e349 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -741,6 +741,7 @@
+
diff --git a/platform/jewel/art/docs/custom-chrome.png b/platform/jewel/art/docs/custom-chrome.png
index a8a331a18fe9e..92274515e5d03 100644
Binary files a/platform/jewel/art/docs/custom-chrome.png and b/platform/jewel/art/docs/custom-chrome.png differ
diff --git a/platform/jewel/art/docs/gfm-table-dark.png b/platform/jewel/art/docs/gfm-table-dark.png
new file mode 100644
index 0000000000000..64fe6bd200a09
Binary files /dev/null and b/platform/jewel/art/docs/gfm-table-dark.png differ
diff --git a/platform/jewel/art/docs/gfm-table-light.png b/platform/jewel/art/docs/gfm-table-light.png
new file mode 100644
index 0000000000000..23c914fe7f6a5
Binary files /dev/null and b/platform/jewel/art/docs/gfm-table-light.png differ
diff --git a/platform/jewel/art/docs/markdown-renderer.png b/platform/jewel/art/docs/markdown-renderer.png
new file mode 100644
index 0000000000000..e56d4765a56ef
Binary files /dev/null and b/platform/jewel/art/docs/markdown-renderer.png differ
diff --git a/platform/jewel/art/docs/merge-dialog.png b/platform/jewel/art/docs/merge-dialog.png
index d2bc1749ee1df..3ddcbefbd27c3 100644
Binary files a/platform/jewel/art/docs/merge-dialog.png and b/platform/jewel/art/docs/merge-dialog.png differ
diff --git a/platform/jewel/foundation/api/foundation.api b/platform/jewel/foundation/api/foundation.api
index 16651c5879052..068b52ab234c5 100644
--- a/platform/jewel/foundation/api/foundation.api
+++ b/platform/jewel/foundation/api/foundation.api
@@ -241,7 +241,7 @@ public final class org/jetbrains/jewel/foundation/code/MimeTypeKt {
}
public abstract interface class org/jetbrains/jewel/foundation/code/highlighting/CodeHighlighter {
- public abstract fun highlight-C7ITchA (Ljava/lang/String;Ljava/lang/String;)Lkotlinx/coroutines/flow/Flow;
+ public abstract fun highlight-zTGadEY (Ljava/lang/String;Ljava/lang/String;)Lkotlinx/coroutines/flow/Flow;
}
public final class org/jetbrains/jewel/foundation/code/highlighting/CodeHighlighterKt {
@@ -251,7 +251,11 @@ public final class org/jetbrains/jewel/foundation/code/highlighting/CodeHighligh
public final class org/jetbrains/jewel/foundation/code/highlighting/NoOpCodeHighlighter : org/jetbrains/jewel/foundation/code/highlighting/CodeHighlighter {
public static final field $stable I
public static final field INSTANCE Lorg/jetbrains/jewel/foundation/code/highlighting/NoOpCodeHighlighter;
- public fun highlight-C7ITchA (Ljava/lang/String;Ljava/lang/String;)Lkotlinx/coroutines/flow/Flow;
+ public fun highlight-zTGadEY (Ljava/lang/String;Ljava/lang/String;)Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class org/jetbrains/jewel/foundation/layout/BasicTableLayoutKt {
+ public static final fun BasicTableLayout-yE4rkUQ (IIJLandroidx/compose/ui/Modifier;FLjava/util/List;Landroidx/compose/runtime/Composer;II)V
}
public class org/jetbrains/jewel/foundation/lazy/DefaultMacOsSelectableColumnKeybindings : org/jetbrains/jewel/foundation/lazy/DefaultSelectableColumnKeybindings {
diff --git a/platform/jewel/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/code/highlighting/CodeHighlighter.kt b/platform/jewel/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/code/highlighting/CodeHighlighter.kt
index aa638f587295d..15c37fa4b6f1a 100644
--- a/platform/jewel/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/code/highlighting/CodeHighlighter.kt
+++ b/platform/jewel/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/code/highlighting/CodeHighlighter.kt
@@ -24,7 +24,7 @@ public interface CodeHighlighter {
*
* @see [NoOpCodeHighlighter]
*/
- public fun highlight(code: String, mimeType: MimeType): Flow
+ public fun highlight(code: String, mimeType: MimeType?): Flow
}
public val LocalCodeHighlighter: ProvidableCompositionLocal = staticCompositionLocalOf {
diff --git a/platform/jewel/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/code/highlighting/NoOpCodeHighlighter.kt b/platform/jewel/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/code/highlighting/NoOpCodeHighlighter.kt
index b99d90f800a78..1b21b1c68e70e 100644
--- a/platform/jewel/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/code/highlighting/NoOpCodeHighlighter.kt
+++ b/platform/jewel/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/code/highlighting/NoOpCodeHighlighter.kt
@@ -6,5 +6,5 @@ import kotlinx.coroutines.flow.flowOf
import org.jetbrains.jewel.foundation.code.MimeType
public object NoOpCodeHighlighter : CodeHighlighter {
- override fun highlight(code: String, mimeType: MimeType): Flow = flowOf(AnnotatedString(code))
+ override fun highlight(code: String, mimeType: MimeType?): Flow = flowOf(AnnotatedString(code))
}
diff --git a/platform/jewel/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/layout/BasicTableLayout.kt b/platform/jewel/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/layout/BasicTableLayout.kt
new file mode 100644
index 0000000000000..eb7d6d2d72b0b
--- /dev/null
+++ b/platform/jewel/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/layout/BasicTableLayout.kt
@@ -0,0 +1,222 @@
+package org.jetbrains.jewel.foundation.layout
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.drawBehind
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.drawscope.Stroke
+import androidx.compose.ui.layout.Layout
+import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+
+/**
+ * A simple table that sizes columns to take as much room as they need. If the horizontal space available is less than
+ * what the cells would take, all columns are sized proportionally to their intrinsic width so that they still can fit
+ * the available width.
+ *
+ * Cells **must** only contain one top-level component. If you need your cells to contain more than one, wrap your cell
+ * content in a [`Box`][Box], [`Column`][androidx.compose.foundation.layout.Column],
+ * [`Row`][androidx.compose.foundation.layout.Row], etc.
+ *
+ * Incoming height constraints are ignored. The table will always take up as much vertical room as it needs. If you want
+ * to constrain the table height consider wrapping it in a
+ * [`VerticallyScrollableContainer`][org.jetbrains.jewel.ui.component.VerticallyScrollableContainer].
+ *
+ * @param rowCount The number of rows this table has.
+ * @param columnCount The number of columns this table has.
+ * @param cellBorderColor The color of the cell borders. Set to [Color.Unspecified] to avoid drawing the borders — in
+ * which case, the [cellBorderWidth] acts as a padding.
+ * @param modifier Modifier to apply to the table.
+ * @param cellBorderWidth The width of the table's borders.
+ * @param rows The rows that make up the table. Each row is a list of composables, one per row cell.
+ */
+@Suppress("KDocUnresolvedReference")
+@Composable
+public fun BasicTableLayout(
+ rowCount: Int,
+ columnCount: Int,
+ cellBorderColor: Color,
+ modifier: Modifier = Modifier,
+ cellBorderWidth: Dp = 1.dp,
+ rows: List Unit>>,
+) {
+ var rowHeights by remember { mutableStateOf(emptyList()) }
+ var columnWidths by remember { mutableStateOf(emptyList()) }
+
+ Layout(
+ modifier =
+ modifier.thenIf(rowHeights.size == rowCount && columnWidths.size == columnCount) {
+ drawTableBorders(cellBorderColor, cellBorderWidth, rowHeights, columnWidths)
+ },
+ content = { rows.forEach { row -> row.forEach { cell -> cell() } } },
+ measurePolicy = { measurables, incomingConstraints ->
+ require(rows.size == rowCount) { "Found ${rows.size} rows, but expected $rowCount." }
+ require(measurables.size == rowCount * columnCount) {
+ "Found ${measurables.size} cells, but expected ${rowCount * columnCount}."
+ }
+
+ val intrinsicColumnWidths = IntArray(columnCount)
+ rows.forEachIndexed { rowIndex, row ->
+ require(row.size == columnCount) {
+ "Row $rowIndex contains ${row.size} cells, but it should have $columnCount cells."
+ }
+
+ row.forEachIndexed { columnIndex, cell ->
+ // Subcompose each cell individually
+ val measurable = measurables[rowIndex * columnIndex]
+
+ // Store the intrinsic width for each column, assuming we have infinite
+ // vertical space available to display each cell (which we do)
+ val intrinsicCellWidth = measurable.maxIntrinsicWidth(Int.MAX_VALUE)
+ intrinsicColumnWidths[columnIndex] =
+ intrinsicColumnWidths[columnIndex].coerceAtLeast(intrinsicCellWidth)
+
+ measurable
+ }
+ }
+
+ // The available width we can assign to cells is equal to the max width from the
+ // incoming
+ // constraints, minus the vertical borders applied between columns and to the sides of
+ // the
+ // table
+ val cellBorderWidthPx = cellBorderWidth.roundToPx()
+ val totalHorizontalBordersWidth = cellBorderWidthPx * (columnCount + 1)
+ val minTableIntrinsicWidth = intrinsicColumnWidths.sum() + totalHorizontalBordersWidth
+ val availableWidth = incomingConstraints.maxWidth
+
+ // We want to size the columns as a ratio of their intrinsic size to the available width
+ // if there is not enough room to show them all, or as their intrinsic width if they all
+ // fit
+ var tableWidth = 0
+
+ if (minTableIntrinsicWidth <= availableWidth) {
+ // We have enough room for all columns, use intrinsic column sizes
+ tableWidth = minTableIntrinsicWidth
+ } else {
+ // We can't fit all columns in the available width; set their size proportionally
+ // to the intrinsic width, so they all fit within the available horizontal space
+ val scaleRatio = availableWidth.toFloat() / minTableIntrinsicWidth
+ for (i in 0 until columnCount) {
+ // By truncating the decimal side, we may end up a few pixels short than the
+ // available width, but at least we're never exceeding it.
+ intrinsicColumnWidths[i] = (intrinsicColumnWidths[i] * scaleRatio).toInt()
+ tableWidth += intrinsicColumnWidths[i]
+ }
+ tableWidth += totalHorizontalBordersWidth
+ }
+ columnWidths = intrinsicColumnWidths.toList()
+
+ // The height of each row is the maximum intrinsic height of their cells, calculated
+ // from
+ // the (possibly scaled) intrinsic column widths we just computed
+ val intrinsicRowHeights = IntArray(rowCount)
+ var tableHeight = 0
+ measurables.chunked(columnCount).mapIndexed { rowIndex, rowMeasurables ->
+ val rowHeight =
+ rowMeasurables
+ .mapIndexed { columnIndex, cellMeasurable ->
+ val columnWidth = columnWidths[columnIndex]
+ cellMeasurable.maxIntrinsicHeight(columnWidth)
+ }
+ .max()
+
+ tableHeight += rowHeight
+ intrinsicRowHeights[rowIndex] = rowHeight
+ }
+ rowHeights = intrinsicRowHeights.toList()
+
+ // Add the horizontal borders drawn between rows and on top and bottom of the table
+ tableHeight += cellBorderWidthPx * (rowCount + 1)
+
+ // Measure all cells, using the fixed constraints we calculated for each row and column
+ val placeables =
+ measurables.chunked(columnCount).mapIndexed { rowIndex, cellMeasurables ->
+ cellMeasurables.mapIndexed { columnIndex, cellMeasurable ->
+ val cellConstraints = Constraints.fixed(columnWidths[columnIndex], rowHeights[rowIndex])
+ cellMeasurable.measure(cellConstraints)
+ }
+ }
+
+ layout(tableWidth, tableHeight) {
+ // Place cells. We start by leaving space for the top and start-side borders
+ var y = cellBorderWidthPx
+
+ placeables.forEachIndexed { rowIndex, cellPlaceables ->
+ var x = cellBorderWidthPx
+
+ var rowHeight = 0
+ cellPlaceables.forEach { cellPlaceable ->
+ cellPlaceable.placeRelative(x, y)
+ x += cellBorderWidthPx
+ x += cellPlaceable.width
+ rowHeight = cellPlaceable.height.coerceAtLeast(rowHeight)
+ }
+
+ y += cellBorderWidthPx
+ y += rowHeight
+ }
+ }
+ },
+ )
+}
+
+private fun Modifier.drawTableBorders(
+ cellBorderColor: Color,
+ cellBorderWidth: Dp,
+ rowHeights: List,
+ columnWidths: List,
+) = drawBehind {
+ val borderWidthPx = cellBorderWidth.toPx()
+ val halfBorderWidthPx = borderWidthPx / 2f
+
+ // First, draw the outer border
+ drawRect(
+ color = cellBorderColor,
+ topLeft = Offset(halfBorderWidthPx, halfBorderWidthPx),
+ size = Size(size.width - borderWidthPx, size.height - borderWidthPx),
+ style = Stroke(width = borderWidthPx),
+ )
+
+ // Then, draw all horizontal borders below rows.
+ // No need to draw the last horizontal border as it's covered by the border rect
+ var y = halfBorderWidthPx
+ val endX = size.width - borderWidthPx
+
+ for (i in 0 until rowHeights.lastIndex) {
+ y += rowHeights[i].toFloat() + borderWidthPx
+ drawLine(
+ color = cellBorderColor,
+ start = Offset(halfBorderWidthPx, y),
+ end = Offset(endX, y),
+ strokeWidth = borderWidthPx,
+ )
+ }
+
+ // Lastly, draw all vertical borders to the end of columns
+ // (minus the last one, as before)
+ var x = halfBorderWidthPx
+ val endY = size.height - borderWidthPx
+
+ for (i in 0 until columnWidths.lastIndex) {
+ x += columnWidths[i].toFloat() + borderWidthPx
+ drawLine(
+ color = cellBorderColor,
+ start = Offset(x, halfBorderWidthPx),
+ end = Offset(x, endY),
+ strokeWidth = borderWidthPx,
+ )
+ }
+}
+
+// TODO remove this once thenIf is moved to foundation
+private inline fun Modifier.thenIf(precondition: Boolean, action: Modifier.() -> Modifier): Modifier =
+ if (precondition) action() else this
diff --git a/platform/jewel/gradle/libs.versions.toml b/platform/jewel/gradle/libs.versions.toml
index 8787ebe45de52..921fd3a896df8 100644
--- a/platform/jewel/gradle/libs.versions.toml
+++ b/platform/jewel/gradle/libs.versions.toml
@@ -19,6 +19,7 @@ poko = "0.17.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" }
diff --git a/platform/jewel/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/code/highlighting/LexerBasedCodeHighlighter.kt b/platform/jewel/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/code/highlighting/LexerBasedCodeHighlighter.kt
index 4706c3cfad4b7..506e7466c0e5b 100644
--- a/platform/jewel/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/code/highlighting/LexerBasedCodeHighlighter.kt
+++ b/platform/jewel/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/code/highlighting/LexerBasedCodeHighlighter.kt
@@ -34,8 +34,8 @@ internal class LexerBasedCodeHighlighter(
private val reHighlightingRequests: Flow,
private val highlightDispatcher: CoroutineDispatcher = Dispatchers.Default,
) : CodeHighlighter {
- override fun highlight(code: String, mimeType: MimeType): Flow {
- val language = mimeType.toLanguageOrNull() ?: return flowOf(AnnotatedString(code))
+ override fun highlight(code: String, mimeType: MimeType?): Flow {
+ val language = mimeType?.toLanguageOrNull() ?: return flowOf(AnnotatedString(code))
val fileExtension = language.associatedFileType?.defaultExtension ?: return flowOf(AnnotatedString(code))
val virtualFile = LightVirtualFile("markdown_code_block_${code.hashCode()}.$fileExtension", language, code)
val colorScheme = EditorColorsManager.getInstance().globalScheme
diff --git a/platform/jewel/int-ui/int-ui-standalone/api/int-ui-standalone.api b/platform/jewel/int-ui/int-ui-standalone/api/int-ui-standalone.api
index 4b17de4433824..f524db9bf67b4 100644
--- a/platform/jewel/int-ui/int-ui-standalone/api/int-ui-standalone.api
+++ b/platform/jewel/int-ui/int-ui-standalone/api/int-ui-standalone.api
@@ -591,14 +591,22 @@ public final class org/jetbrains/jewel/intui/standalone/styling/IntUiWarningBann
}
public final class org/jetbrains/jewel/intui/standalone/theme/IntUiGlobalColorsKt {
- public static final fun dark-GyCwops (Lorg/jetbrains/jewel/foundation/BorderColors$Companion;JJJLandroidx/compose/runtime/Composer;II)Lorg/jetbrains/jewel/foundation/BorderColors;
- public static final fun dark-Hformbs (Lorg/jetbrains/jewel/foundation/OutlineColors$Companion;JJJJJLandroidx/compose/runtime/Composer;II)Lorg/jetbrains/jewel/foundation/OutlineColors;
- public static final fun dark-Hformbs (Lorg/jetbrains/jewel/foundation/TextColors$Companion;JJJJJLandroidx/compose/runtime/Composer;II)Lorg/jetbrains/jewel/foundation/TextColors;
- public static final fun dark-yrwZFoE (Lorg/jetbrains/jewel/foundation/GlobalColors$Companion;Lorg/jetbrains/jewel/foundation/BorderColors;Lorg/jetbrains/jewel/foundation/OutlineColors;Lorg/jetbrains/jewel/foundation/TextColors;JLandroidx/compose/runtime/Composer;II)Lorg/jetbrains/jewel/foundation/GlobalColors;
- public static final fun light-GyCwops (Lorg/jetbrains/jewel/foundation/BorderColors$Companion;JJJLandroidx/compose/runtime/Composer;II)Lorg/jetbrains/jewel/foundation/BorderColors;
- public static final fun light-Hformbs (Lorg/jetbrains/jewel/foundation/OutlineColors$Companion;JJJJJLandroidx/compose/runtime/Composer;II)Lorg/jetbrains/jewel/foundation/OutlineColors;
- public static final fun light-Hformbs (Lorg/jetbrains/jewel/foundation/TextColors$Companion;JJJJJLandroidx/compose/runtime/Composer;II)Lorg/jetbrains/jewel/foundation/TextColors;
- public static final fun light-yrwZFoE (Lorg/jetbrains/jewel/foundation/GlobalColors$Companion;Lorg/jetbrains/jewel/foundation/BorderColors;Lorg/jetbrains/jewel/foundation/OutlineColors;Lorg/jetbrains/jewel/foundation/TextColors;JLandroidx/compose/runtime/Composer;II)Lorg/jetbrains/jewel/foundation/GlobalColors;
+ public static final fun dark-jdqzblg (Lorg/jetbrains/jewel/foundation/OutlineColors$Companion;JJJJJ)Lorg/jetbrains/jewel/foundation/OutlineColors;
+ public static final fun dark-jdqzblg (Lorg/jetbrains/jewel/foundation/TextColors$Companion;JJJJJ)Lorg/jetbrains/jewel/foundation/TextColors;
+ public static synthetic fun dark-jdqzblg$default (Lorg/jetbrains/jewel/foundation/OutlineColors$Companion;JJJJJILjava/lang/Object;)Lorg/jetbrains/jewel/foundation/OutlineColors;
+ public static synthetic fun dark-jdqzblg$default (Lorg/jetbrains/jewel/foundation/TextColors$Companion;JJJJJILjava/lang/Object;)Lorg/jetbrains/jewel/foundation/TextColors;
+ public static final fun dark-xwkQ0AY (Lorg/jetbrains/jewel/foundation/GlobalColors$Companion;Lorg/jetbrains/jewel/foundation/BorderColors;Lorg/jetbrains/jewel/foundation/OutlineColors;Lorg/jetbrains/jewel/foundation/TextColors;J)Lorg/jetbrains/jewel/foundation/GlobalColors;
+ public static synthetic fun dark-xwkQ0AY$default (Lorg/jetbrains/jewel/foundation/GlobalColors$Companion;Lorg/jetbrains/jewel/foundation/BorderColors;Lorg/jetbrains/jewel/foundation/OutlineColors;Lorg/jetbrains/jewel/foundation/TextColors;JILjava/lang/Object;)Lorg/jetbrains/jewel/foundation/GlobalColors;
+ public static final fun dark-zSO0fhY (Lorg/jetbrains/jewel/foundation/BorderColors$Companion;JJJ)Lorg/jetbrains/jewel/foundation/BorderColors;
+ public static synthetic fun dark-zSO0fhY$default (Lorg/jetbrains/jewel/foundation/BorderColors$Companion;JJJILjava/lang/Object;)Lorg/jetbrains/jewel/foundation/BorderColors;
+ public static final fun light-jdqzblg (Lorg/jetbrains/jewel/foundation/OutlineColors$Companion;JJJJJ)Lorg/jetbrains/jewel/foundation/OutlineColors;
+ public static final fun light-jdqzblg (Lorg/jetbrains/jewel/foundation/TextColors$Companion;JJJJJ)Lorg/jetbrains/jewel/foundation/TextColors;
+ public static synthetic fun light-jdqzblg$default (Lorg/jetbrains/jewel/foundation/OutlineColors$Companion;JJJJJILjava/lang/Object;)Lorg/jetbrains/jewel/foundation/OutlineColors;
+ public static synthetic fun light-jdqzblg$default (Lorg/jetbrains/jewel/foundation/TextColors$Companion;JJJJJILjava/lang/Object;)Lorg/jetbrains/jewel/foundation/TextColors;
+ public static final fun light-xwkQ0AY (Lorg/jetbrains/jewel/foundation/GlobalColors$Companion;Lorg/jetbrains/jewel/foundation/BorderColors;Lorg/jetbrains/jewel/foundation/OutlineColors;Lorg/jetbrains/jewel/foundation/TextColors;J)Lorg/jetbrains/jewel/foundation/GlobalColors;
+ public static synthetic fun light-xwkQ0AY$default (Lorg/jetbrains/jewel/foundation/GlobalColors$Companion;Lorg/jetbrains/jewel/foundation/BorderColors;Lorg/jetbrains/jewel/foundation/OutlineColors;Lorg/jetbrains/jewel/foundation/TextColors;JILjava/lang/Object;)Lorg/jetbrains/jewel/foundation/GlobalColors;
+ public static final fun light-zSO0fhY (Lorg/jetbrains/jewel/foundation/BorderColors$Companion;JJJ)Lorg/jetbrains/jewel/foundation/BorderColors;
+ public static synthetic fun light-zSO0fhY$default (Lorg/jetbrains/jewel/foundation/BorderColors$Companion;JJJILjava/lang/Object;)Lorg/jetbrains/jewel/foundation/BorderColors;
}
public final class org/jetbrains/jewel/intui/standalone/theme/IntUiGlobalMetricsKt {
diff --git a/platform/jewel/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiGlobalColors.kt b/platform/jewel/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiGlobalColors.kt
index a6461a75ad75b..480e2910c45c9 100644
--- a/platform/jewel/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiGlobalColors.kt
+++ b/platform/jewel/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiGlobalColors.kt
@@ -1,6 +1,5 @@
package org.jetbrains.jewel.intui.standalone.theme
-import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import org.jetbrains.jewel.foundation.BorderColors
import org.jetbrains.jewel.foundation.GlobalColors
@@ -9,7 +8,6 @@ import org.jetbrains.jewel.foundation.TextColors
import org.jetbrains.jewel.intui.core.theme.IntUiDarkTheme
import org.jetbrains.jewel.intui.core.theme.IntUiLightTheme
-@Composable
public fun GlobalColors.Companion.light(
borders: BorderColors = BorderColors.light(),
outlines: OutlineColors = OutlineColors.light(),
@@ -17,7 +15,6 @@ public fun GlobalColors.Companion.light(
paneBackground: Color = IntUiLightTheme.colors.gray(13),
): GlobalColors = GlobalColors(borders = borders, outlines = outlines, text = text, panelBackground = paneBackground)
-@Composable
public fun GlobalColors.Companion.dark(
borders: BorderColors = BorderColors.dark(),
outlines: OutlineColors = OutlineColors.dark(),
@@ -25,21 +22,18 @@ public fun GlobalColors.Companion.dark(
paneBackground: Color = IntUiDarkTheme.colors.gray(2),
): GlobalColors = GlobalColors(borders = borders, outlines = outlines, text = text, panelBackground = paneBackground)
-@Composable
public fun BorderColors.Companion.light(
normal: Color = IntUiLightTheme.colors.gray(12),
focused: Color = IntUiLightTheme.colors.gray(14),
disabled: Color = IntUiLightTheme.colors.gray(11),
): BorderColors = BorderColors(normal, focused, disabled)
-@Composable
public fun BorderColors.Companion.dark(
normal: Color = IntUiDarkTheme.colors.gray(1),
focused: Color = IntUiDarkTheme.colors.gray(2),
disabled: Color = IntUiDarkTheme.colors.gray(4),
): BorderColors = BorderColors(normal, focused, disabled)
-@Composable
public fun TextColors.Companion.light(
normal: Color = IntUiLightTheme.colors.gray(1),
selected: Color = IntUiLightTheme.colors.gray(1),
@@ -48,7 +42,6 @@ public fun TextColors.Companion.light(
error: Color = IntUiLightTheme.colors.red(4),
): TextColors = TextColors(normal, selected, disabled, info, error)
-@Composable
public fun TextColors.Companion.dark(
normal: Color = IntUiDarkTheme.colors.gray(12),
selected: Color = IntUiDarkTheme.colors.gray(12),
@@ -57,7 +50,6 @@ public fun TextColors.Companion.dark(
error: Color = IntUiDarkTheme.colors.red(7),
): TextColors = TextColors(normal, selected, disabled, info, error)
-@Composable
public fun OutlineColors.Companion.light(
focused: Color = IntUiLightTheme.colors.blue(4),
focusedWarning: Color = IntUiLightTheme.colors.yellow(4),
@@ -66,7 +58,6 @@ public fun OutlineColors.Companion.light(
error: Color = IntUiLightTheme.colors.red(9),
): OutlineColors = OutlineColors(focused, focusedWarning, focusedError, warning, error)
-@Composable
public fun OutlineColors.Companion.dark(
focused: Color = IntUiDarkTheme.colors.blue(6),
focusedWarning: Color = IntUiDarkTheme.colors.yellow(4),
diff --git a/platform/jewel/markdown/README.md b/platform/jewel/markdown/README.md
index c41644a86d724..954cee544b720 100644
--- a/platform/jewel/markdown/README.md
+++ b/platform/jewel/markdown/README.md
@@ -12,12 +12,13 @@ Additional supported Markdown, via extensions:
* Alerts ([GitHub Flavored Markdown][alerts-specs]) — see [`extension-gfm-alerts`](extension/gfm-alerts)
* Autolink (standard CommonMark, but provided as extension) — see [`extension-autolink`](extension/autolink)
+* Tables ([GitHub Flavored Markdown](https://github.github.com/gfm/#tables-extension-)) — see [
+ `extension-gfm-tables`](extension/gfm-tables)
[alerts-specs]: https://github.com/orgs/community/discussions/16925
On the roadmap, but not currently supported — in no particular order:
-* Tables ([GitHub Flavored Markdown](https://github.github.com/gfm/#tables-extension-))
* Strikethrough ([GitHub Flavored Markdown](https://github.github.com/gfm/#strikethrough-extension-))
* Image loading (via [Coil 3](https://coil-kt.github.io/coil/upgrading_to_coil3/))
* Task list items ([GitHub Flavored Markdown](https://github.github.com/gfm/#task-list-items-extension-))
@@ -119,7 +120,7 @@ those.
By default, the processor will ignore any kind of Markdown it doesn't support. To support additional features, such as
ones found in GitHub Flavored Markdown, you can use extensions. If you don't specify any extension, the processor will
be restricted to the [CommonMark specs](https://specs.commonmark.org) as supported by
-[`commonmark-java`](https://github.com/commonmark/commonmark-java).
+[`commonmark-java`](https://github.com/commonmark/commonmark-java).
> [!NOTE]
> Images are not supported yet, even if they are part of the CommonMark specs.
@@ -136,7 +137,7 @@ val processor = MarkdownProcessor(parsingExtensions)
// Where the rendering happens...
val blockRenderer = remember(markdownStyling, isDark) {
val rendererExtensions = listOf(/*...*/)
-
+
if (isDark) {
MarkdownBlockRenderer.dark(rendererExtensions)
} else {
@@ -156,5 +157,6 @@ own inline renderer, this is something to be careful about.
You can see this in action running the Standalone sample, and selecting Markdown from the top-left menu.
-The following image shows Jewel Markdown rendering this very Jewel Markdown README.
-![Image showing the Markdown showcase from the Jewel standalone sample](https://github.com/JetBrains/jewel/assets/19003/67e2cc4e-c9b8-454b-884a-bba526ad2fe4)
+The following image shows the Jewel Markdown renderer displaying the Jewel readme.
+
+![Image showing the Markdown renderer page from the Jewel standalone sample](../art/docs/markdown-renderer.png)
diff --git a/platform/jewel/markdown/core/api/core.api b/platform/jewel/markdown/core/api/core.api
index 0c38528e9c194..cc78884d4b6f6 100644
--- a/platform/jewel/markdown/core/api/core.api
+++ b/platform/jewel/markdown/core/api/core.api
@@ -321,10 +321,16 @@ public final class org/jetbrains/jewel/markdown/processing/MarkdownProcessor {
public fun ()V
public fun (Ljava/util/List;Lorg/jetbrains/jewel/markdown/MarkdownMode;Lorg/commonmark/parser/Parser;)V
public synthetic fun (Ljava/util/List;Lorg/jetbrains/jewel/markdown/MarkdownMode;Lorg/commonmark/parser/Parser;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+ public final fun getExtensions ()Ljava/util/List;
public final fun processChildren (Lorg/commonmark/node/Node;)Ljava/util/List;
public final fun processMarkdownDocument (Ljava/lang/String;)Ljava/util/List;
}
+public final class org/jetbrains/jewel/markdown/processing/ProcessingUtilKt {
+ public static final fun readInlineContent (Lorg/commonmark/node/Node;Lorg/jetbrains/jewel/markdown/processing/MarkdownProcessor;)Ljava/util/List;
+ public static final fun toInlineMarkdownOrNull (Lorg/commonmark/node/Node;Lorg/jetbrains/jewel/markdown/processing/MarkdownProcessor;)Lorg/jetbrains/jewel/markdown/InlineMarkdown;
+}
+
public class org/jetbrains/jewel/markdown/rendering/DefaultInlineMarkdownRenderer : org/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer {
public static final field $stable I
public static final field Companion Lorg/jetbrains/jewel/markdown/rendering/DefaultInlineMarkdownRenderer$Companion;
@@ -340,6 +346,11 @@ public class org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer
public fun (Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;Ljava/util/List;Lorg/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer;)V
public synthetic fun (Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;Ljava/util/List;Lorg/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
protected final fun MaybeScrollingContainer (ZLandroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
+ public fun createCopy (Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;Ljava/util/List;Lorg/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer;)Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;
+ public fun getInlineRenderer ()Lorg/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer;
+ public fun getRendererExtensions ()Ljava/util/List;
+ public fun getRootStyling ()Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;
+ public fun plus (Lorg/jetbrains/jewel/markdown/extensions/MarkdownRendererExtension;)Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;
public fun render (Ljava/util/List;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;I)V
public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$BlockQuote;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$BlockQuote;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;I)V
public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Code$Fenced;Landroidx/compose/runtime/Composer;I)V
@@ -354,8 +365,8 @@ public class org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer
public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListItem;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;I)V
public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Paragraph;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Paragraph;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;I)V
public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;I)V
- public fun render-EWr_ITI (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock;Ljava/lang/String;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Code$Fenced;Landroidx/compose/runtime/Composer;I)V
public fun renderThematicBreak (Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$ThematicBreak;Landroidx/compose/runtime/Composer;I)V
+ public fun renderWithMimeType-EWr_ITI (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock;Ljava/lang/String;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Code$Fenced;Landroidx/compose/runtime/Composer;I)V
}
public abstract interface class org/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer {
@@ -393,6 +404,11 @@ public final class org/jetbrains/jewel/markdown/rendering/InlinesStyling$Compani
public abstract interface class org/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer {
public static final field Companion Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer$Companion;
+ public abstract fun createCopy (Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;Ljava/util/List;Lorg/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer;)Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;
+ public abstract fun getInlineRenderer ()Lorg/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer;
+ public abstract fun getRendererExtensions ()Ljava/util/List;
+ public abstract fun getRootStyling ()Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;
+ public abstract fun plus (Lorg/jetbrains/jewel/markdown/extensions/MarkdownRendererExtension;)Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;
public abstract fun render (Ljava/util/List;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;I)V
public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$BlockQuote;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$BlockQuote;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;I)V
public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Code$Fenced;Landroidx/compose/runtime/Composer;I)V
@@ -413,6 +429,10 @@ public abstract interface class org/jetbrains/jewel/markdown/rendering/MarkdownB
public final class org/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer$Companion {
}
+public final class org/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer$DefaultImpls {
+ public static synthetic fun createCopy$default (Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;Ljava/util/List;Lorg/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;
+}
+
public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling {
public static final field $stable I
public static final field Companion Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Companion;
@@ -783,7 +803,7 @@ public class org/jetbrains/jewel/markdown/scrolling/ScrollSyncMarkdownBlockRende
public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$IndentedCodeBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Code$Indented;Landroidx/compose/runtime/Composer;I)V
public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$HN;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;I)V
public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Paragraph;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Paragraph;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;I)V
- public fun render-EWr_ITI (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock;Ljava/lang/String;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Code$Fenced;Landroidx/compose/runtime/Composer;I)V
+ public fun renderWithMimeType-EWr_ITI (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock;Ljava/lang/String;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Code$Fenced;Landroidx/compose/runtime/Composer;I)V
}
public abstract class org/jetbrains/jewel/markdown/scrolling/ScrollingSynchronizer {
diff --git a/platform/jewel/markdown/core/build.gradle.kts b/platform/jewel/markdown/core/build.gradle.kts
index 135428bcd81ad..19e3dfb770d5b 100644
--- a/platform/jewel/markdown/core/build.gradle.kts
+++ b/platform/jewel/markdown/core/build.gradle.kts
@@ -16,7 +16,6 @@ dependencies {
}
publicApiValidation {
- // TODO Oleg remove this once migrated to value classes
excludedClassRegexes = setOf("org.jetbrains.jewel.markdown.MarkdownBlock.*")
}
diff --git a/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/MarkdownProcessor.kt b/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/MarkdownProcessor.kt
index ea1796f76fc2f..d0f19f7df8686 100644
--- a/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/MarkdownProcessor.kt
+++ b/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/MarkdownProcessor.kt
@@ -56,7 +56,7 @@ import org.jetbrains.jewel.markdown.scrolling.ScrollingSynchronizer
*/
@ExperimentalJewelApi
public class MarkdownProcessor(
- private val extensions: List = emptyList(),
+ public val extensions: List = emptyList(),
private val markdownMode: MarkdownMode = MarkdownMode.Standalone,
private val commonMarkParser: Parser =
MarkdownParserFactory.create(markdownMode is MarkdownMode.EditorPreview, extensions),
@@ -267,14 +267,14 @@ public class MarkdownProcessor(
}
private fun Paragraph.toMarkdownParagraph(): MarkdownBlock.Paragraph =
- MarkdownBlock.Paragraph(readInlineContent().toList())
+ MarkdownBlock.Paragraph(readInlineContent(this@MarkdownProcessor).toList())
private fun BlockQuote.toMarkdownBlockQuote(): MarkdownBlock.BlockQuote =
MarkdownBlock.BlockQuote(processChildren(this))
private fun Heading.toMarkdownHeadingOrNull(): MarkdownBlock.Heading? {
if (level < 1 || level > 6) return null
- return MarkdownBlock.Heading(inlineContent = readInlineContent().toList(), level = level)
+ return MarkdownBlock.Heading(inlineContent = readInlineContent(this@MarkdownProcessor).toList(), level = level)
}
private fun FencedCodeBlock.toMarkdownCodeBlockOrNull(): CodeBlock.FencedCodeBlock =
@@ -345,7 +345,5 @@ public class MarkdownProcessor(
return MarkdownBlock.HtmlBlock(literal.trimEnd('\n'))
}
- private fun Block.readInlineContent() = readInlineContent(this@MarkdownProcessor, extensions)
-
private data class State(val lines: List, val blocks: List, val indexes: List>)
}
diff --git a/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/ProcessingUtil.kt b/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/ProcessingUtil.kt
index b0f65dcfb9509..fee1d83bcf505 100644
--- a/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/ProcessingUtil.kt
+++ b/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/ProcessingUtil.kt
@@ -11,53 +11,39 @@ import org.commonmark.node.Node
import org.commonmark.node.SoftLineBreak as CMSoftLineBreak
import org.commonmark.node.StrongEmphasis as CMStrongEmphasis
import org.commonmark.node.Text as CMText
-import org.jetbrains.annotations.VisibleForTesting
import org.jetbrains.jewel.markdown.InlineMarkdown
import org.jetbrains.jewel.markdown.WithInlineMarkdown
import org.jetbrains.jewel.markdown.WithTextContent
-import org.jetbrains.jewel.markdown.extensions.MarkdownProcessorExtension
-@VisibleForTesting
-internal fun Node.readInlineContent(
- markdownProcessor: MarkdownProcessor,
- extensions: List,
-): List = buildList {
+public fun Node.readInlineContent(markdownProcessor: MarkdownProcessor): List = buildList {
var current = this@readInlineContent.firstChild
while (current != null) {
- val inline = current.toInlineMarkdownOrNull(markdownProcessor, extensions)
+ val inline = current.toInlineMarkdownOrNull(markdownProcessor)
if (inline != null) add(inline)
current = current.next
}
}
-@VisibleForTesting
-internal fun Node.toInlineMarkdownOrNull(
- markdownProcessor: MarkdownProcessor,
- extensions: List,
-) =
+public fun Node.toInlineMarkdownOrNull(markdownProcessor: MarkdownProcessor): InlineMarkdown? =
when (this) {
is CMText -> InlineMarkdown.Text(literal)
is CMLink ->
InlineMarkdown.Link(
destination = destination,
title = title,
- inlineContent = readInlineContent(markdownProcessor, extensions),
+ inlineContent = readInlineContent(markdownProcessor),
)
is CMEmphasis ->
- InlineMarkdown.Emphasis(
- delimiter = openingDelimiter,
- inlineContent = readInlineContent(markdownProcessor, extensions),
- )
+ InlineMarkdown.Emphasis(delimiter = openingDelimiter, inlineContent = readInlineContent(markdownProcessor))
- is CMStrongEmphasis ->
- InlineMarkdown.StrongEmphasis(openingDelimiter, readInlineContent(markdownProcessor, extensions))
+ is CMStrongEmphasis -> InlineMarkdown.StrongEmphasis(openingDelimiter, readInlineContent(markdownProcessor))
is CMCode -> InlineMarkdown.Code(literal)
is CMHtmlInline -> InlineMarkdown.HtmlInline(literal)
is CMImage -> {
- val inlineContent = readInlineContent(markdownProcessor, extensions)
+ val inlineContent = readInlineContent(markdownProcessor)
InlineMarkdown.Image(
source = destination,
alt = inlineContent.renderAsSimpleText().trim(),
@@ -69,7 +55,7 @@ internal fun Node.toInlineMarkdownOrNull(
is CMHardLineBreak -> InlineMarkdown.HardLineBreak
is CMSoftLineBreak -> InlineMarkdown.SoftLineBreak
is CMCustomNode ->
- extensions
+ markdownProcessor.extensions
.find { it.inlineProcessorExtension?.canProcess(this) == true }
?.inlineProcessorExtension
?.processInlineMarkdown(this, markdownProcessor)
diff --git a/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer.kt b/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer.kt
index 08ed08e3de867..a34f852a1f3d7 100644
--- a/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer.kt
+++ b/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer.kt
@@ -60,11 +60,15 @@ import org.jetbrains.jewel.ui.component.Divider
import org.jetbrains.jewel.ui.component.HorizontallyScrollableContainer
import org.jetbrains.jewel.ui.component.Text
+/**
+ * Default implementation of [MarkdownBlockRenderer] that uses the provided styling, extensions, and inline renderer to
+ * render [MarkdownBlock]s into Compose UI elements.
+ */
@ExperimentalJewelApi
public open class DefaultMarkdownBlockRenderer(
- private val rootStyling: MarkdownStyling,
- private val rendererExtensions: List = emptyList(),
- private val inlineRenderer: InlineMarkdownRenderer = DefaultInlineMarkdownRenderer(rendererExtensions),
+ override val rootStyling: MarkdownStyling,
+ override val rendererExtensions: List = emptyList(),
+ override val inlineRenderer: InlineMarkdownRenderer = DefaultInlineMarkdownRenderer(rendererExtensions),
) : MarkdownBlockRenderer {
@Composable
override fun render(
@@ -365,7 +369,7 @@ public open class DefaultMarkdownBlockRenderer(
)
}
- render(block, mimeType, styling)
+ renderWithMimeType(block, mimeType, styling)
if (styling.infoPosition.verticalAlignment == Alignment.Bottom) {
FencedBlockInfo(
@@ -381,7 +385,11 @@ public open class DefaultMarkdownBlockRenderer(
}
@Composable
- public open fun render(block: FencedCodeBlock, mimeType: MimeType, styling: MarkdownStyling.Code.Fenced) {
+ public open fun renderWithMimeType(
+ block: FencedCodeBlock,
+ mimeType: MimeType,
+ styling: MarkdownStyling.Code.Fenced,
+ ) {
val content = block.content
val highlightedCode by
LocalCodeHighlighter.current.highlight(content, mimeType).collectAsState(AnnotatedString(content))
@@ -451,4 +459,19 @@ public open class DefaultMarkdownBlockRenderer(
content()
}
}
+
+ public override fun createCopy(
+ rootStyling: MarkdownStyling?,
+ rendererExtensions: List?,
+ inlineRenderer: InlineMarkdownRenderer?,
+ ): MarkdownBlockRenderer =
+ DefaultMarkdownBlockRenderer(
+ rootStyling ?: this.rootStyling,
+ rendererExtensions ?: this.rendererExtensions,
+ inlineRenderer ?: this.inlineRenderer,
+ )
+
+ @ExperimentalJewelApi
+ override operator fun plus(extension: MarkdownRendererExtension): MarkdownBlockRenderer =
+ DefaultMarkdownBlockRenderer(rootStyling, rendererExtensions = rendererExtensions + extension, inlineRenderer)
}
diff --git a/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer.kt b/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer.kt
index b66ebc4979a6a..13704adedf7ee 100644
--- a/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer.kt
+++ b/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer.kt
@@ -13,9 +13,20 @@ import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock.OrderedList
import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock.UnorderedList
import org.jetbrains.jewel.markdown.MarkdownBlock.ListItem
import org.jetbrains.jewel.markdown.MarkdownBlock.Paragraph
-
+import org.jetbrains.jewel.markdown.extensions.MarkdownRendererExtension
+
+/**
+ * Renders one or more [MarkdownBlock]s into a Compose UI.
+ *
+ * @see render
+ */
+@Suppress("ComposableNaming")
@ExperimentalJewelApi
public interface MarkdownBlockRenderer {
+ public val rootStyling: MarkdownStyling
+ public val rendererExtensions: List
+ public val inlineRenderer: InlineMarkdownRenderer
+
@Composable
public fun render(
blocks: List,
@@ -103,5 +114,17 @@ public interface MarkdownBlockRenderer {
@Composable public fun render(block: HtmlBlock, styling: MarkdownStyling.HtmlBlock)
+ /**
+ * Creates a copy of this instance, using the provided non-null parameters, or the current values for the null ones.
+ */
+ public fun createCopy(
+ rootStyling: MarkdownStyling? = null,
+ rendererExtensions: List? = null,
+ inlineRenderer: InlineMarkdownRenderer? = null,
+ ): MarkdownBlockRenderer
+
+ /** Creates a copy of this [MarkdownBlockRenderer] with the same properties, plus the provided [extension]. */
+ @ExperimentalJewelApi public operator fun plus(extension: MarkdownRendererExtension): MarkdownBlockRenderer
+
public companion object
}
diff --git a/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/scrolling/ScrollSyncMarkdownBlockRenderer.kt b/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/scrolling/ScrollSyncMarkdownBlockRenderer.kt
index a1dc3ce32ff77..18717c8151431 100644
--- a/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/scrolling/ScrollSyncMarkdownBlockRenderer.kt
+++ b/platform/jewel/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/scrolling/ScrollSyncMarkdownBlockRenderer.kt
@@ -74,11 +74,11 @@ public open class ScrollSyncMarkdownBlockRenderer(
}
@Composable
- override fun render(block: FencedCodeBlock, mimeType: MimeType, styling: MarkdownStyling.Code.Fenced) {
+ override fun renderWithMimeType(block: FencedCodeBlock, mimeType: MimeType, styling: MarkdownStyling.Code.Fenced) {
val synchronizer =
(JewelTheme.markdownMode as? MarkdownMode.EditorPreview)?.scrollingSynchronizer
?: run {
- super.render(block, mimeType, styling)
+ super.renderWithMimeType(block, mimeType, styling)
return
}
diff --git a/platform/jewel/markdown/extension/gfm-alerts/build.gradle.kts b/platform/jewel/markdown/extension/gfm-alerts/build.gradle.kts
index 918e727a6e249..802a08600d14c 100644
--- a/platform/jewel/markdown/extension/gfm-alerts/build.gradle.kts
+++ b/platform/jewel/markdown/extension/gfm-alerts/build.gradle.kts
@@ -13,7 +13,6 @@ dependencies {
}
publicApiValidation {
- // TODO Oleg remove this once migrated to value classes
excludedClassRegexes = setOf("org.jetbrains.jewel.markdown.extensions.github.alerts.*")
}
diff --git a/platform/jewel/markdown/extension/gfm-tables/README.md b/platform/jewel/markdown/extension/gfm-tables/README.md
new file mode 100644
index 0000000000000..8c6bc26f05aae
--- /dev/null
+++ b/platform/jewel/markdown/extension/gfm-tables/README.md
@@ -0,0 +1,43 @@
+# GitHub Flavored Markdown — tables extension
+
+This extension adds support for tables, a [GFM extension](https://github.github.com/gfm/#tables-extension-) over
+CommonMark. Tables are parsed by the `commonmark-ext-gfm-tables` library, and rendered using a themed
+[`BasicTableLayout`](../../../foundation/src/main/kotlin/org/jetbrains/jewel/foundation/layout/BasicTableLayout.kt).
+
+The default table styling matches the GitHub styling:
+
+| Light theme | Dark theme |
+|-------------------------------------------------------------------------|-----------------------------------------------------------------------|
+| ![Screenshot in the light theme](../../../art/docs/gfm-table-light.png) | ![Screenshot in the dark theme](../../../art/docs/gfm-table-dark.png) |
+
+## Usage
+
+To use the tables extension, you need to add the `GitHubTableProcessorExtension` to your `MarkdownProcessor`, and the
+`GitHubTableRendererExtension` to the `MarkdownBlockRenderer`. For example, in standalone mode:
+
+```kotlin
+val isDark = JewelTheme.isDark
+
+val markdownStyling = remember(isDark) { if (isDark) MarkdownStyling.dark() else MarkdownStyling.light() }
+
+val processor = remember { MarkdownProcessor(listOf(GitHubTableProcessorExtension)) }
+
+val blockRenderer =
+ remember(markdownStyling) {
+ if (isDark) {
+ MarkdownBlockRenderer.dark(
+ styling = markdownStyling,
+ rendererExtensions = listOf(GitHubTableRendererExtension(GfmTableStyling.dark(), markdownStyling)),
+ )
+ } else {
+ MarkdownBlockRenderer.light(
+ styling = markdownStyling,
+ rendererExtensions = listOf(GitHubTableRendererExtension(GfmTableStyling.light(), markdownStyling)),
+ )
+ }
+ }
+
+ProvideMarkdownStyling(markdownStyling, blockRenderer, NoOpCodeHighlighter) {
+ // Your UI that renders Markdown goes here
+}
+```
diff --git a/platform/jewel/markdown/extension/gfm-tables/api/gfm-tables.api b/platform/jewel/markdown/extension/gfm-tables/api/gfm-tables.api
new file mode 100644
index 0000000000000..80434a86cf946
--- /dev/null
+++ b/platform/jewel/markdown/extension/gfm-tables/api/gfm-tables.api
@@ -0,0 +1,79 @@
+public final class org/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors {
+ public static final field $stable I
+ public static final field Companion Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors$Companion;
+ public synthetic fun (JJJLorg/jetbrains/jewel/markdown/extensions/github/tables/RowBackgroundStyle;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+ public fun equals (Ljava/lang/Object;)Z
+ public final fun getAlternateRowBackgroundColor-0d7_KjU ()J
+ public final fun getBorderColor-0d7_KjU ()J
+ public final fun getRowBackgroundColor-0d7_KjU ()J
+ public final fun getRowBackgroundStyle ()Lorg/jetbrains/jewel/markdown/extensions/github/tables/RowBackgroundStyle;
+ public fun hashCode ()I
+ public fun toString ()Ljava/lang/String;
+}
+
+public final class org/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors$Companion {
+}
+
+public final class org/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics {
+ public static final field $stable I
+ public static final field Companion Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics$Companion;
+ public synthetic fun (FLandroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/ui/Alignment$Horizontal;Landroidx/compose/ui/Alignment$Horizontal;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+ public fun equals (Ljava/lang/Object;)Z
+ public final fun getBorderWidth-D9Ej5fM ()F
+ public final fun getCellPadding ()Landroidx/compose/foundation/layout/PaddingValues;
+ public final fun getDefaultCellContentAlignment ()Landroidx/compose/ui/Alignment$Horizontal;
+ public final fun getHeaderDefaultCellContentAlignment ()Landroidx/compose/ui/Alignment$Horizontal;
+ public fun hashCode ()I
+ public fun toString ()Ljava/lang/String;
+}
+
+public final class org/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics$Companion {
+}
+
+public final class org/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling {
+ public static final field $stable I
+ public static final field Companion Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling$Companion;
+ public synthetic fun (JJJLorg/jetbrains/jewel/markdown/extensions/github/tables/RowBackgroundStyle;FLandroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/ui/Alignment$Horizontal;Landroidx/compose/ui/Alignment$Horizontal;Landroidx/compose/ui/text/font/FontWeight;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+ public fun (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors;Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics;Landroidx/compose/ui/text/font/FontWeight;)V
+ public fun equals (Ljava/lang/Object;)Z
+ public final fun getColors ()Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors;
+ public final fun getHeaderBaseFontWeight ()Landroidx/compose/ui/text/font/FontWeight;
+ public final fun getMetrics ()Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics;
+ public fun hashCode ()I
+ public fun toString ()Ljava/lang/String;
+}
+
+public final class org/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling$Companion {
+}
+
+public final class org/jetbrains/jewel/markdown/extensions/github/tables/GitHubTableBlockRenderer : org/jetbrains/jewel/markdown/extensions/MarkdownBlockRendererExtension {
+ public static final field $stable I
+ public fun (Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling;)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;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;I)V
+}
+
+public final class org/jetbrains/jewel/markdown/extensions/github/tables/GitHubTableProcessorExtension : org/jetbrains/jewel/markdown/extensions/MarkdownProcessorExtension {
+ public static final field $stable I
+ public static final field INSTANCE Lorg/jetbrains/jewel/markdown/extensions/github/tables/GitHubTableProcessorExtension;
+ public fun getBlockProcessorExtension ()Lorg/jetbrains/jewel/markdown/extensions/MarkdownBlockProcessorExtension;
+ public fun getInlineProcessorExtension ()Lorg/jetbrains/jewel/markdown/extensions/MarkdownInlineProcessorExtension;
+ public fun getParserExtension ()Lorg/commonmark/parser/Parser$ParserExtension;
+ public fun getTextRendererExtension ()Lorg/commonmark/renderer/text/TextContentRenderer$TextContentRendererExtension;
+}
+
+public final class org/jetbrains/jewel/markdown/extensions/github/tables/GitHubTableRendererExtension : org/jetbrains/jewel/markdown/extensions/MarkdownRendererExtension {
+ public static final field $stable I
+ public fun (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;)V
+ public fun getBlockRenderer ()Lorg/jetbrains/jewel/markdown/extensions/MarkdownBlockRendererExtension;
+ public fun getInlineRenderer ()Lorg/jetbrains/jewel/markdown/extensions/MarkdownInlineRendererExtension;
+}
+
+public final class org/jetbrains/jewel/markdown/extensions/github/tables/RowBackgroundStyle : java/lang/Enum {
+ public static final field Normal Lorg/jetbrains/jewel/markdown/extensions/github/tables/RowBackgroundStyle;
+ public static final field Striped Lorg/jetbrains/jewel/markdown/extensions/github/tables/RowBackgroundStyle;
+ public static fun getEntries ()Lkotlin/enums/EnumEntries;
+ public static fun valueOf (Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/RowBackgroundStyle;
+ public static fun values ()[Lorg/jetbrains/jewel/markdown/extensions/github/tables/RowBackgroundStyle;
+}
+
diff --git a/platform/jewel/markdown/extension/gfm-tables/build.gradle.kts b/platform/jewel/markdown/extension/gfm-tables/build.gradle.kts
new file mode 100644
index 0000000000000..b73c9d355ad4e
--- /dev/null
+++ b/platform/jewel/markdown/extension/gfm-tables/build.gradle.kts
@@ -0,0 +1,27 @@
+import org.jetbrains.kotlin.compose.compiler.gradle.ComposeFeatureFlag
+
+plugins {
+ jewel
+ `jewel-publish`
+ `jewel-check-public-api`
+ alias(libs.plugins.composeDesktop)
+ alias(libs.plugins.compose.compiler)
+}
+
+dependencies {
+ implementation(projects.markdown.core)
+ implementation(libs.commonmark.ext.gfm.tables)
+
+ testImplementation(compose.desktop.uiTestJUnit4)
+}
+
+publicApiValidation {
+ excludedClassRegexes = setOf("org.jetbrains.jewel.markdown.extensions.github.tables.*")
+}
+
+publishing.publications.named("main") {
+ val ijpTarget = project.property("ijp.target") as String
+ artifactId = "jewel-markdown-extension-${project.name}-$ijpTarget"
+}
+
+composeCompiler { featureFlags.add(ComposeFeatureFlag.OptimizeNonSkippingGroups) }
diff --git a/platform/jewel/markdown/extension/gfm-tables/intellij.platform.jewel.markdown.extension.gfmTables.iml b/platform/jewel/markdown/extension/gfm-tables/intellij.platform.jewel.markdown.extension.gfmTables.iml
new file mode 100644
index 0000000000000..185fa1181782b
--- /dev/null
+++ b/platform/jewel/markdown/extension/gfm-tables/intellij.platform.jewel.markdown.extension.gfmTables.iml
@@ -0,0 +1,375 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-compose-compiler-plugin/2.1.0/kotlin-compose-compiler-plugin-2.1.0.jar
+ $MAVEN_REPOSITORY$/dev/drewhamilton/poko/poko-compiler-plugin/0.18.2/poko-compiler-plugin-0.18.2.jar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ c53f675b2af4696e6022598145a44a9e9feb35216a188163ae5bf99a18e76bdb
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ f1e334b73d49ceab00afe776a4c393de77b4fc805e9ff488dac596a2663b1dc1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a7dfdfd2b9d6668c646275948eba357aab6407f635f2dc09fe90258a2f202337
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 34dfab5b4fa8b2913f00facdddc049e2fef4b176f8e7cde0ad306485674c3b5c
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 5c84c3bb1c1b636ae36030a0f98d4629afa29e192a9c78f57f22ce2c8ff6bc96
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ c106c0f705717889663555fe4cb7742612bd47b56a128bf7a9f589f24c64cb08
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 8ff9a2b8c93b0287d8fa837d5b0917923168cb97dea1ada1a8d4aa7bb17c9f15
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 41da5d61c56877b5b5d01e2a2bcb967cbfaf4d45c1a1aa124c0601c7a3de74e7
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 7b0f19724082cbfcbc66e5abea2b9bc92cf08a1ea11e191933ed43801eb3cd05
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bff3d1e895fd5abd54ee725dab59214acabf900e1a0784544d20cf20521bf9f3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 62c816073195cc0119dc1d66b178544bdb772ef8bee4879954528c6798b17ebe
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 5c84c3bb1c1b636ae36030a0f98d4629afa29e192a9c78f57f22ce2c8ff6bc96
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ c106c0f705717889663555fe4cb7742612bd47b56a128bf7a9f589f24c64cb08
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1b409141a9ee6ed38e76a8fb8f9cf280030bf45375ba7e07e60b2742039b573e
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ c5cfad0b125e978d915f8b4c38630bc5d548e59fe8a0e838c0cc84283c605943
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 5c84c3bb1c1b636ae36030a0f98d4629afa29e192a9c78f57f22ce2c8ff6bc96
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ b54dc332f931e6d07c2766144c087b08f3693677e368151a67020b4e95bb4b99
+
+
+ 679338e0b7fc15c02d275d598654b01a149893bc28a87992e90123c8d06af25b
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/platform/jewel/markdown/extension/gfm-tables/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/tables/GitHubTableBlockRenderer.kt b/platform/jewel/markdown/extension/gfm-tables/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/tables/GitHubTableBlockRenderer.kt
new file mode 100644
index 0000000000000..380a7abab8928
--- /dev/null
+++ b/platform/jewel/markdown/extension/gfm-tables/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/tables/GitHubTableBlockRenderer.kt
@@ -0,0 +1,198 @@
+package org.jetbrains.jewel.markdown.extensions.github.tables
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.font.FontWeight
+import org.jetbrains.jewel.foundation.ExperimentalJewelApi
+import org.jetbrains.jewel.foundation.layout.BasicTableLayout
+import org.jetbrains.jewel.foundation.theme.JewelTheme
+import org.jetbrains.jewel.markdown.MarkdownBlock
+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.InlinesStyling
+import org.jetbrains.jewel.markdown.rendering.MarkdownBlockRenderer
+import org.jetbrains.jewel.markdown.rendering.MarkdownStyling
+
+@OptIn(ExperimentalJewelApi::class)
+public class GitHubTableBlockRenderer(
+ private val rootStyling: MarkdownStyling,
+ private val tableStyling: GfmTableStyling,
+) : MarkdownBlockRendererExtension {
+ override fun canRender(block: CustomBlock): Boolean = block is TableBlock
+
+ @Composable
+ override fun render(
+ block: CustomBlock,
+ blockRenderer: MarkdownBlockRenderer,
+ inlineRenderer: InlineMarkdownRenderer,
+ enabled: Boolean,
+ onUrlClick: (String) -> Unit,
+ onTextClick: () -> Unit,
+ ) {
+ val tableBlock = block as TableBlock
+
+ // Headers usually have a tweaked font weight
+ val headerRootStyling =
+ remember(JewelTheme.name, blockRenderer, tableStyling.headerBaseFontWeight) {
+ val rootStyling = blockRenderer.rootStyling
+ val semiboldInlinesStyling =
+ rootStyling.paragraph.inlinesStyling.withFontWeight(tableStyling.headerBaseFontWeight)
+
+ // Given cells can only contain inlines, and not block-level nodes, we are ok with
+ // only overriding the Paragraph styling.
+ MarkdownStyling(
+ rootStyling.blockVerticalSpacing,
+ MarkdownStyling.Paragraph(semiboldInlinesStyling),
+ rootStyling.heading,
+ rootStyling.blockQuote,
+ rootStyling.code,
+ rootStyling.list,
+ rootStyling.image,
+ rootStyling.thematicBreak,
+ rootStyling.htmlBlock,
+ )
+ }
+
+ val headerRenderer = remember(headerRootStyling) { blockRenderer.createCopy(rootStyling = headerRootStyling) }
+
+ val rows =
+ remember(block, blockRenderer, inlineRenderer, tableStyling) {
+ val headerCells =
+ tableBlock.header.cells.map Unit> { cell ->
+ {
+ HeaderCell(
+ cell = cell,
+ backgroundColor = tableStyling.colors.rowBackgroundColor,
+ padding = tableStyling.metrics.cellPadding,
+ defaultAlignment = tableStyling.metrics.headerDefaultCellContentAlignment,
+ blockRenderer = headerRenderer,
+ enabled = enabled,
+ onUrlClick = onUrlClick,
+ onTextClick = onTextClick,
+ )
+ }
+ }
+
+ val rowsCells =
+ tableBlock.rows.map Unit>> { row ->
+ row.cells.map Unit> { cell ->
+ {
+ val backgroundColor =
+ if (tableStyling.colors.rowBackgroundStyle == RowBackgroundStyle.Striped) {
+ if (cell.rowIndex % 2 == 0) {
+ tableStyling.colors.alternateRowBackgroundColor
+ } else {
+ tableStyling.colors.rowBackgroundColor
+ }
+ } else {
+ tableStyling.colors.rowBackgroundColor
+ }
+
+ Cell(
+ cell = cell,
+ backgroundColor = backgroundColor,
+ padding = tableStyling.metrics.cellPadding,
+ defaultAlignment = tableStyling.metrics.defaultCellContentAlignment,
+ blockRenderer = blockRenderer,
+ enabled = enabled,
+ onUrlClick = onUrlClick,
+ onTextClick = onTextClick,
+ )
+ }
+ }
+ }
+
+ listOf(headerCells) + rowsCells
+ }
+
+ BasicTableLayout(
+ rowCount = tableBlock.rowCount,
+ columnCount = tableBlock.columnCount,
+ cellBorderColor = tableStyling.colors.borderColor,
+ cellBorderWidth = tableStyling.metrics.borderWidth,
+ rows = rows,
+ )
+ }
+
+ private fun InlinesStyling.withFontWeight(newFontWeight: FontWeight) =
+ InlinesStyling(
+ textStyle = textStyle.copy(fontWeight = newFontWeight),
+ inlineCode = inlineCode.copy(fontWeight = newFontWeight),
+ link = link.copy(fontWeight = newFontWeight),
+ linkDisabled = linkDisabled.copy(fontWeight = newFontWeight),
+ linkHovered = linkHovered.copy(fontWeight = newFontWeight),
+ linkFocused = linkFocused.copy(fontWeight = newFontWeight),
+ linkPressed = linkPressed.copy(fontWeight = newFontWeight),
+ linkVisited = linkVisited.copy(fontWeight = newFontWeight),
+ emphasis = emphasis.copy(fontWeight = newFontWeight),
+ strongEmphasis = strongEmphasis.copy(fontWeight = newFontWeight),
+ inlineHtml = inlineHtml.copy(fontWeight = newFontWeight),
+ renderInlineHtml = renderInlineHtml,
+ )
+
+ @Composable
+ private fun HeaderCell(
+ cell: TableCell,
+ backgroundColor: Color,
+ padding: PaddingValues,
+ defaultAlignment: Alignment.Horizontal,
+ blockRenderer: MarkdownBlockRenderer,
+ enabled: Boolean,
+ onUrlClick: (String) -> Unit,
+ onTextClick: () -> Unit,
+ ) {
+ Box(
+ modifier = Modifier.background(backgroundColor).padding(padding),
+ contentAlignment = (cell.alignment ?: defaultAlignment).asContentAlignment(),
+ ) {
+ blockRenderer.render(
+ MarkdownBlock.Paragraph(cell.content),
+ blockRenderer.rootStyling.paragraph,
+ enabled,
+ onUrlClick,
+ onTextClick,
+ )
+ }
+ }
+
+ @Composable
+ private fun Cell(
+ cell: TableCell,
+ backgroundColor: Color,
+ padding: PaddingValues,
+ defaultAlignment: Alignment.Horizontal,
+ blockRenderer: MarkdownBlockRenderer,
+ enabled: Boolean,
+ onUrlClick: (String) -> Unit,
+ onTextClick: () -> Unit,
+ ) {
+ Box(
+ modifier = Modifier.background(backgroundColor).padding(padding),
+ contentAlignment = (cell.alignment ?: defaultAlignment).asContentAlignment(),
+ ) {
+ blockRenderer.render(
+ MarkdownBlock.Paragraph(cell.content),
+ rootStyling.paragraph,
+ enabled,
+ onUrlClick,
+ onTextClick,
+ )
+ }
+ }
+
+ private fun Alignment.Horizontal.asContentAlignment() =
+ when {
+ this == Alignment.Start -> Alignment.TopStart
+ this == Alignment.CenterHorizontally -> Alignment.TopCenter
+ this == Alignment.End -> Alignment.TopEnd
+ else -> error("Unsupported alignment: $this")
+ }
+}
diff --git a/platform/jewel/markdown/extension/gfm-tables/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/tables/GitHubTableProcessorExtension.kt b/platform/jewel/markdown/extension/gfm-tables/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/tables/GitHubTableProcessorExtension.kt
new file mode 100644
index 0000000000000..21dc1543b80e6
--- /dev/null
+++ b/platform/jewel/markdown/extension/gfm-tables/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/tables/GitHubTableProcessorExtension.kt
@@ -0,0 +1,159 @@
+package org.jetbrains.jewel.markdown.extensions.github.tables
+
+import androidx.compose.ui.Alignment
+import org.commonmark.ext.gfm.tables.TableBlock as CommonMarkTableBlock
+import org.commonmark.ext.gfm.tables.TableBody as CommonMarkTableBody
+import org.commonmark.ext.gfm.tables.TableCell as CommonMarkTableCell
+import org.commonmark.ext.gfm.tables.TableCell.Alignment.CENTER
+import org.commonmark.ext.gfm.tables.TableCell.Alignment.LEFT
+import org.commonmark.ext.gfm.tables.TableCell.Alignment.RIGHT
+import org.commonmark.ext.gfm.tables.TableHead as CommonMarkTableHeader
+import org.commonmark.ext.gfm.tables.TableRow as CommonMarkTableRow
+import org.commonmark.ext.gfm.tables.TablesExtension
+import org.commonmark.node.CustomBlock
+import org.commonmark.node.Node
+import org.commonmark.parser.Parser.Builder
+import org.commonmark.parser.Parser.ParserExtension
+import org.commonmark.renderer.text.TextContentRenderer
+import org.commonmark.renderer.text.TextContentRenderer.TextContentRendererExtension
+import org.jetbrains.jewel.foundation.ExperimentalJewelApi
+import org.jetbrains.jewel.markdown.InlineMarkdown
+import org.jetbrains.jewel.markdown.MarkdownBlock
+import org.jetbrains.jewel.markdown.extensions.MarkdownBlockProcessorExtension
+import org.jetbrains.jewel.markdown.extensions.MarkdownBlockRendererExtension
+import org.jetbrains.jewel.markdown.extensions.MarkdownProcessorExtension
+import org.jetbrains.jewel.markdown.extensions.MarkdownRendererExtension
+import org.jetbrains.jewel.markdown.processing.MarkdownProcessor
+import org.jetbrains.jewel.markdown.processing.readInlineContent
+import org.jetbrains.jewel.markdown.rendering.MarkdownStyling
+
+@OptIn(ExperimentalJewelApi::class)
+public object GitHubTableProcessorExtension : MarkdownProcessorExtension {
+ override val parserExtension: ParserExtension = GitHubTablesCommonMarkExtension
+ override val textRendererExtension: TextContentRendererExtension = GitHubTablesCommonMarkExtension
+
+ override val blockProcessorExtension: MarkdownBlockProcessorExtension = GitHubTablesProcessorExtension
+
+ private object GitHubTablesProcessorExtension : MarkdownBlockProcessorExtension {
+ override fun canProcess(block: CustomBlock): Boolean = block is CommonMarkTableBlock
+
+ override fun processMarkdownBlock(
+ block: CustomBlock,
+ processor: MarkdownProcessor,
+ ): MarkdownBlock.CustomBlock? {
+ val tableBlock = block as CommonMarkTableBlock
+ val header = tableBlock.firstChild as? CommonMarkTableHeader ?: return null
+
+ val body = tableBlock.lastChild as? CommonMarkTableBody
+
+ return try {
+ TableBlock(
+ TableHeader(
+ // The header contains only one CommonMarkTableRow
+ (header.firstChild as CommonMarkTableRow).mapCellsIndexed { columnIndex, cell ->
+ TableCell(
+ rowIndex = 0,
+ columnIndex = columnIndex,
+ content = cell.readInlineContent(processor),
+ alignment = getAlignment(cell),
+ )
+ }
+ ),
+ body
+ ?.mapRowsIndexed { rowIndex, row ->
+ TableRow(
+ rowIndex = rowIndex,
+ row.mapCellsIndexed { columnIndex, cell ->
+ TableCell(
+ rowIndex = rowIndex + 1, // The header is row zero
+ columnIndex = columnIndex,
+ content = cell.readInlineContent(processor),
+ alignment = getAlignment(cell),
+ )
+ },
+ )
+ }
+ .orEmpty(),
+ )
+ } catch (_: IllegalArgumentException) {
+ null
+ }
+ }
+
+ private fun getAlignment(cell: CommonMarkTableCell) =
+ when (cell.alignment) {
+ LEFT -> Alignment.Start
+ CENTER -> Alignment.CenterHorizontally
+ RIGHT -> Alignment.End
+ null -> null
+ }
+
+ private inline fun CommonMarkTableRow.mapCellsIndexed(
+ mapper: (Int, CommonMarkTableCell) -> TableCell
+ ): List = buildList {
+ forEachChildIndexed { index, child -> if (child is CommonMarkTableCell) add(mapper(index, child)) }
+ }
+
+ private inline fun CommonMarkTableBody.mapRowsIndexed(
+ mapper: (Int, CommonMarkTableRow) -> TableRow
+ ): List = buildList {
+ forEachChildIndexed { index, child -> if (child is CommonMarkTableRow) add(mapper(index, child)) }
+ }
+
+ private inline fun Node.forEachChildIndexed(action: (Int, Node) -> Unit) {
+ var child = firstChild
+
+ var index = 0
+ while (child != null) {
+ action(index, child)
+ index++
+ child = child.next
+ }
+ }
+ }
+}
+
+private object GitHubTablesCommonMarkExtension : ParserExtension, TextContentRendererExtension {
+ override fun extend(parserBuilder: Builder) {
+ parserBuilder.extensions(listOf(TablesExtension.create()))
+ }
+
+ override fun extend(rendererBuilder: TextContentRenderer.Builder) {
+ rendererBuilder.extensions(listOf(TablesExtension.create()))
+ }
+}
+
+@OptIn(ExperimentalJewelApi::class)
+public class GitHubTableRendererExtension(tableStyling: GfmTableStyling, rootStyling: MarkdownStyling) :
+ MarkdownRendererExtension {
+ override val blockRenderer: MarkdownBlockRendererExtension = GitHubTableBlockRenderer(rootStyling, tableStyling)
+}
+
+internal data class TableBlock(val header: TableHeader, val rows: List) : MarkdownBlock.CustomBlock {
+ val rowCount: Int = rows.size + 1 // We always have a header
+ val columnCount: Int
+
+ init {
+ require(header.cells.isNotEmpty()) { "Header cannot be empty" }
+ val headerColumns = header.cells.size
+
+ if (rows.isNotEmpty()) {
+ val bodyColumns = rows.first().cells.size
+ require(rows.all { it.cells.size == bodyColumns }) { "Inconsistent cell count in table body" }
+ require(headerColumns == bodyColumns) { "Inconsistent cell count between table body and header" }
+ }
+
+ columnCount = headerColumns
+ }
+}
+
+internal data class TableHeader(val cells: List) : CustomBlock()
+
+internal data class TableRow(val rowIndex: Int, val cells: List) : CustomBlock()
+
+internal data class TableCell(
+ val rowIndex: Int,
+ val columnIndex: Int,
+ val content: List,
+ val alignment: Alignment.Horizontal?,
+) : CustomBlock()
diff --git a/platform/jewel/markdown/extension/gfm-tables/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/tables/GitHubTableStyling.kt b/platform/jewel/markdown/extension/gfm-tables/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/tables/GitHubTableStyling.kt
new file mode 100644
index 0000000000000..238e14ccc90fa
--- /dev/null
+++ b/platform/jewel/markdown/extension/gfm-tables/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/tables/GitHubTableStyling.kt
@@ -0,0 +1,72 @@
+// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the
+// Apache 2.0 license.
+package org.jetbrains.jewel.markdown.extensions.github.tables
+
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.Dp
+import org.jetbrains.jewel.foundation.ExperimentalJewelApi
+import org.jetbrains.jewel.foundation.GenerateDataFunctions
+
+@GenerateDataFunctions
+public class GfmTableStyling(
+ public val colors: GfmTableColors,
+ public val metrics: GfmTableMetrics,
+ public val headerBaseFontWeight: FontWeight,
+) {
+ @ExperimentalJewelApi
+ public constructor(
+ borderColor: Color,
+ rowBackgroundColor: Color,
+ alternateRowBackgroundColor: Color,
+ rowBackgroundStyle: RowBackgroundStyle,
+ borderWidth: Dp,
+ cellPadding: PaddingValues,
+ defaultCellContentAlignment: Alignment.Horizontal,
+ headerDefaultCellContentAlignment: Alignment.Horizontal,
+ headerBaseFontWeight: FontWeight,
+ ) : this(
+ colors = GfmTableColors(borderColor, rowBackgroundColor, alternateRowBackgroundColor, rowBackgroundStyle),
+ metrics =
+ GfmTableMetrics(borderWidth, cellPadding, defaultCellContentAlignment, headerDefaultCellContentAlignment),
+ headerBaseFontWeight = headerBaseFontWeight,
+ )
+
+ public companion object
+}
+
+@GenerateDataFunctions
+public class GfmTableColors(
+ public val borderColor: Color,
+ public val rowBackgroundColor: Color,
+ public val alternateRowBackgroundColor: Color,
+ public val rowBackgroundStyle: RowBackgroundStyle,
+) {
+ public companion object
+}
+
+public enum class RowBackgroundStyle {
+ /**
+ * All rows have the same background color, [GfmTableColors.rowBackgroundColor]. In this style,
+ * [GfmTableColors.alternateRowBackgroundColor] is ignored.
+ */
+ Normal,
+
+ /**
+ * Rows have alternate colors. Odd rows use [GfmTableColors.rowBackgroundColor] and even rows use
+ * [GfmTableColors.alternateRowBackgroundColor].
+ */
+ Striped,
+}
+
+@GenerateDataFunctions
+public class GfmTableMetrics(
+ public val borderWidth: Dp,
+ public val cellPadding: PaddingValues,
+ public val defaultCellContentAlignment: Alignment.Horizontal,
+ public val headerDefaultCellContentAlignment: Alignment.Horizontal,
+) {
+ public companion object
+}
diff --git a/platform/jewel/markdown/ide-laf-bridge-styling/api/ide-laf-bridge-styling.api b/platform/jewel/markdown/ide-laf-bridge-styling/api/ide-laf-bridge-styling.api
index f6d7cfbc72f6b..c8fd643b876d4 100644
--- a/platform/jewel/markdown/ide-laf-bridge-styling/api/ide-laf-bridge-styling.api
+++ b/platform/jewel/markdown/ide-laf-bridge-styling/api/ide-laf-bridge-styling.api
@@ -66,3 +66,12 @@ public final class org/jetbrains/jewel/intui/markdown/bridge/styling/extensions/
public static synthetic fun create-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;Lorg/jetbrains/jewel/ui/icon/IconKey;JJILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/extensions/github/alerts/WarningAlertStyling;
}
+public final class org/jetbrains/jewel/intui/markdown/bridge/styling/extensions/github/tables/BridgeGitHubTableStylingKt {
+ public static final fun create (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling$Companion;Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors;Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics;Landroidx/compose/ui/text/font/FontWeight;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling;
+ public static synthetic fun create$default (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling$Companion;Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors;Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics;Landroidx/compose/ui/text/font/FontWeight;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling;
+ public static final fun create-f1JAnFk (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors$Companion;JJJLorg/jetbrains/jewel/markdown/extensions/github/tables/RowBackgroundStyle;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors;
+ public static synthetic fun create-f1JAnFk$default (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors$Companion;JJJLorg/jetbrains/jewel/markdown/extensions/github/tables/RowBackgroundStyle;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors;
+ public static final fun create-rAjV9yQ (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics$Companion;FLandroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/ui/Alignment$Horizontal;Landroidx/compose/ui/Alignment$Horizontal;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics;
+ public static synthetic fun create-rAjV9yQ$default (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics$Companion;FLandroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/ui/Alignment$Horizontal;Landroidx/compose/ui/Alignment$Horizontal;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics;
+}
+
diff --git a/platform/jewel/markdown/ide-laf-bridge-styling/build.gradle.kts b/platform/jewel/markdown/ide-laf-bridge-styling/build.gradle.kts
index b421ece07a4a2..0763451712b5e 100644
--- a/platform/jewel/markdown/ide-laf-bridge-styling/build.gradle.kts
+++ b/platform/jewel/markdown/ide-laf-bridge-styling/build.gradle.kts
@@ -35,6 +35,7 @@ dependencies {
api(projects.markdown.core)
api(projects.ideLafBridge)
compileOnly(projects.markdown.extension.gfmAlerts)
+ compileOnly(projects.markdown.extension.gfmTables)
intellijPlatform {
intellijIdeaCommunity(libs.versions.idea)
diff --git a/platform/jewel/markdown/ide-laf-bridge-styling/intellij.platform.jewel.markdown.ideLafBridgeStyling.iml b/platform/jewel/markdown/ide-laf-bridge-styling/intellij.platform.jewel.markdown.ideLafBridgeStyling.iml
index 387d0cfaed4fb..1e17770b6a539 100644
--- a/platform/jewel/markdown/ide-laf-bridge-styling/intellij.platform.jewel.markdown.ideLafBridgeStyling.iml
+++ b/platform/jewel/markdown/ide-laf-bridge-styling/intellij.platform.jewel.markdown.ideLafBridgeStyling.iml
@@ -353,5 +353,6 @@
+
\ No newline at end of file
diff --git a/platform/jewel/markdown/ide-laf-bridge-styling/src/main/kotlin/org/jetbrains/jewel/intui/markdown/bridge/styling/Utils.kt b/platform/jewel/markdown/ide-laf-bridge-styling/src/main/kotlin/org/jetbrains/jewel/intui/markdown/bridge/styling/Utils.kt
new file mode 100644
index 0000000000000..64923dd1cdd73
--- /dev/null
+++ b/platform/jewel/markdown/ide-laf-bridge-styling/src/main/kotlin/org/jetbrains/jewel/intui/markdown/bridge/styling/Utils.kt
@@ -0,0 +1,5 @@
+package org.jetbrains.jewel.intui.markdown.bridge.styling
+
+import com.intellij.ui.JBColor
+
+internal val isLightTheme = JBColor.isBright()
diff --git a/platform/jewel/markdown/ide-laf-bridge-styling/src/main/kotlin/org/jetbrains/jewel/intui/markdown/bridge/styling/extensions/github/alerts/BridgeGitHubAlertStyling.kt b/platform/jewel/markdown/ide-laf-bridge-styling/src/main/kotlin/org/jetbrains/jewel/intui/markdown/bridge/styling/extensions/github/alerts/BridgeGitHubAlertStyling.kt
index 9fcefc8236d44..89f626451107d 100644
--- a/platform/jewel/markdown/ide-laf-bridge-styling/src/main/kotlin/org/jetbrains/jewel/intui/markdown/bridge/styling/extensions/github/alerts/BridgeGitHubAlertStyling.kt
+++ b/platform/jewel/markdown/ide-laf-bridge-styling/src/main/kotlin/org/jetbrains/jewel/intui/markdown/bridge/styling/extensions/github/alerts/BridgeGitHubAlertStyling.kt
@@ -8,7 +8,7 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
-import com.intellij.ui.JBColor
+import org.jetbrains.jewel.intui.markdown.bridge.styling.isLightTheme
import org.jetbrains.jewel.markdown.extensions.github.alerts.AlertStyling
import org.jetbrains.jewel.markdown.extensions.github.alerts.CautionAlertStyling
import org.jetbrains.jewel.markdown.extensions.github.alerts.GitHubAlertIcons
@@ -29,7 +29,7 @@ public fun AlertStyling.Companion.create(
public fun NoteAlertStyling.Companion.create(
padding: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 8.dp),
lineWidth: Dp = 3.dp,
- lineColor: Color = if (JBColor.isBright()) Color(0xFF0969DA) else Color(0xFF1F6EEB),
+ lineColor: Color = if (isLightTheme) Color(0xFF0969DA) else Color(0xFF1F6EEB),
pathEffect: PathEffect? = null,
strokeCap: StrokeCap = StrokeCap.Square,
titleTextStyle: TextStyle = TextStyle(fontWeight = FontWeight.Medium, color = lineColor),
@@ -52,7 +52,7 @@ public fun NoteAlertStyling.Companion.create(
public fun TipAlertStyling.Companion.create(
padding: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 8.dp),
lineWidth: Dp = 3.dp,
- lineColor: Color = if (JBColor.isBright()) Color(0xFF1F883D) else Color(0xFF238636),
+ lineColor: Color = if (isLightTheme) Color(0xFF1F883D) else Color(0xFF238636),
pathEffect: PathEffect? = null,
strokeCap: StrokeCap = StrokeCap.Square,
titleTextStyle: TextStyle = TextStyle(fontWeight = FontWeight.Medium, color = lineColor),
@@ -75,7 +75,7 @@ public fun TipAlertStyling.Companion.create(
public fun ImportantAlertStyling.Companion.create(
padding: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 8.dp),
lineWidth: Dp = 3.dp,
- lineColor: Color = if (JBColor.isBright()) Color(0xFF8250DF) else Color(0xFF8957E5),
+ lineColor: Color = if (isLightTheme) Color(0xFF8250DF) else Color(0xFF8957E5),
pathEffect: PathEffect? = null,
strokeCap: StrokeCap = StrokeCap.Square,
titleTextStyle: TextStyle = TextStyle(fontWeight = FontWeight.Medium, color = lineColor),
@@ -98,7 +98,7 @@ public fun ImportantAlertStyling.Companion.create(
public fun WarningAlertStyling.Companion.create(
padding: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 8.dp),
lineWidth: Dp = 3.dp,
- lineColor: Color = if (JBColor.isBright()) Color(0xFF9A6601) else Color(0xFF9E6A02),
+ lineColor: Color = if (isLightTheme) Color(0xFF9A6601) else Color(0xFF9E6A02),
pathEffect: PathEffect? = null,
strokeCap: StrokeCap = StrokeCap.Square,
titleTextStyle: TextStyle = TextStyle(fontWeight = FontWeight.Medium, color = lineColor),
@@ -121,7 +121,7 @@ public fun WarningAlertStyling.Companion.create(
public fun CautionAlertStyling.Companion.create(
padding: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 8.dp),
lineWidth: Dp = 3.dp,
- lineColor: Color = if (JBColor.isBright()) Color(0xFFCF222E) else Color(0xFFDA3633),
+ lineColor: Color = if (isLightTheme) Color(0xFFCF222E) else Color(0xFFDA3633),
pathEffect: PathEffect? = null,
strokeCap: StrokeCap = StrokeCap.Square,
titleTextStyle: TextStyle = TextStyle(fontWeight = FontWeight.Medium, color = lineColor),
diff --git a/platform/jewel/markdown/ide-laf-bridge-styling/src/main/kotlin/org/jetbrains/jewel/intui/markdown/bridge/styling/extensions/github/tables/BridgeGitHubTableStyling.kt b/platform/jewel/markdown/ide-laf-bridge-styling/src/main/kotlin/org/jetbrains/jewel/intui/markdown/bridge/styling/extensions/github/tables/BridgeGitHubTableStyling.kt
new file mode 100644
index 0000000000000..e8a1009637cad
--- /dev/null
+++ b/platform/jewel/markdown/ide-laf-bridge-styling/src/main/kotlin/org/jetbrains/jewel/intui/markdown/bridge/styling/extensions/github/tables/BridgeGitHubTableStyling.kt
@@ -0,0 +1,35 @@
+// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the
+// Apache 2.0 license.
+package org.jetbrains.jewel.intui.markdown.bridge.styling.extensions.github.tables
+
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import org.jetbrains.jewel.intui.markdown.bridge.styling.isLightTheme
+import org.jetbrains.jewel.markdown.extensions.github.tables.GfmTableColors
+import org.jetbrains.jewel.markdown.extensions.github.tables.GfmTableMetrics
+import org.jetbrains.jewel.markdown.extensions.github.tables.GfmTableStyling
+import org.jetbrains.jewel.markdown.extensions.github.tables.RowBackgroundStyle
+
+public fun GfmTableStyling.Companion.create(
+ colors: GfmTableColors = GfmTableColors.create(),
+ metrics: GfmTableMetrics = GfmTableMetrics.create(),
+ headerBaseFontWeight: FontWeight = FontWeight.SemiBold,
+): GfmTableStyling = GfmTableStyling(colors, metrics, headerBaseFontWeight)
+
+public fun GfmTableColors.Companion.create(
+ borderColor: Color = if (isLightTheme) Color(0xffd1d9e0) else Color(0xff3d444d),
+ rowBackgroundColor: Color = Color.Unspecified,
+ alternateRowBackgroundColor: Color = if (isLightTheme) Color(0xfff6f8fa) else Color(0xff151b23),
+ rowBackgroundStyle: RowBackgroundStyle = RowBackgroundStyle.Striped,
+) = GfmTableColors(borderColor, rowBackgroundColor, alternateRowBackgroundColor, rowBackgroundStyle)
+
+public fun GfmTableMetrics.Companion.create(
+ borderWidth: Dp = 1.dp,
+ cellPadding: PaddingValues = PaddingValues(horizontal = 13.dp, vertical = 6.dp),
+ defaultCellContentAlignment: Alignment.Horizontal = Alignment.Start,
+ headerDefaultCellContentAlignment: Alignment.Horizontal = Alignment.CenterHorizontally,
+) = GfmTableMetrics(borderWidth, cellPadding, defaultCellContentAlignment, headerDefaultCellContentAlignment)
diff --git a/platform/jewel/markdown/int-ui-standalone-styling/api/int-ui-standalone-styling.api b/platform/jewel/markdown/int-ui-standalone-styling/api/int-ui-standalone-styling.api
index 4e4693c68c7cd..4eacec1d82d24 100644
--- a/platform/jewel/markdown/int-ui-standalone-styling/api/int-ui-standalone-styling.api
+++ b/platform/jewel/markdown/int-ui-standalone-styling/api/int-ui-standalone-styling.api
@@ -118,3 +118,16 @@ public final class org/jetbrains/jewel/intui/markdown/standalone/styling/extensi
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;Lorg/jetbrains/jewel/ui/icon/IconKey;JJILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/extensions/github/alerts/WarningAlertStyling;
}
+public final class org/jetbrains/jewel/intui/markdown/standalone/styling/extensions/github/tables/IntUiGitHubTableStylingKt {
+ public static final fun dark (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling$Companion;Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors;Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics;Landroidx/compose/ui/text/font/FontWeight;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling;
+ public static synthetic fun dark$default (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling$Companion;Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors;Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics;Landroidx/compose/ui/text/font/FontWeight;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling;
+ public static final fun dark-f1JAnFk (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors$Companion;JJJLorg/jetbrains/jewel/markdown/extensions/github/tables/RowBackgroundStyle;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors;
+ public static synthetic fun dark-f1JAnFk$default (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors$Companion;JJJLorg/jetbrains/jewel/markdown/extensions/github/tables/RowBackgroundStyle;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors;
+ public static final fun defaults-rAjV9yQ (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics$Companion;FLandroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/ui/Alignment$Horizontal;Landroidx/compose/ui/Alignment$Horizontal;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics;
+ public static synthetic fun defaults-rAjV9yQ$default (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics$Companion;FLandroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/ui/Alignment$Horizontal;Landroidx/compose/ui/Alignment$Horizontal;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics;
+ public static final fun light (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling$Companion;Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors;Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics;Landroidx/compose/ui/text/font/FontWeight;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling;
+ public static synthetic fun light$default (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling$Companion;Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors;Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableMetrics;Landroidx/compose/ui/text/font/FontWeight;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableStyling;
+ public static final fun light-f1JAnFk (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors$Companion;JJJLorg/jetbrains/jewel/markdown/extensions/github/tables/RowBackgroundStyle;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors;
+ public static synthetic fun light-f1JAnFk$default (Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors$Companion;JJJLorg/jetbrains/jewel/markdown/extensions/github/tables/RowBackgroundStyle;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/extensions/github/tables/GfmTableColors;
+}
+
diff --git a/platform/jewel/markdown/int-ui-standalone-styling/build.gradle.kts b/platform/jewel/markdown/int-ui-standalone-styling/build.gradle.kts
index b80d7926a182c..15e3061835ad4 100644
--- a/platform/jewel/markdown/int-ui-standalone-styling/build.gradle.kts
+++ b/platform/jewel/markdown/int-ui-standalone-styling/build.gradle.kts
@@ -10,6 +10,7 @@ dependencies {
api(projects.markdown.core)
api(projects.intUi.intUiStandalone)
compileOnly(projects.markdown.extension.gfmAlerts)
+ compileOnly(projects.markdown.extension.gfmTables)
testImplementation(compose.desktop.uiTestJUnit4)
}
diff --git a/platform/jewel/markdown/int-ui-standalone-styling/intellij.platform.jewel.markdown.intUiStandaloneStyling.iml b/platform/jewel/markdown/int-ui-standalone-styling/intellij.platform.jewel.markdown.intUiStandaloneStyling.iml
index 71810cfebe47b..4e6875943a92f 100644
--- a/platform/jewel/markdown/int-ui-standalone-styling/intellij.platform.jewel.markdown.intUiStandaloneStyling.iml
+++ b/platform/jewel/markdown/int-ui-standalone-styling/intellij.platform.jewel.markdown.intUiStandaloneStyling.iml
@@ -349,5 +349,6 @@
+
\ No newline at end of file
diff --git a/platform/jewel/markdown/int-ui-standalone-styling/src/main/kotlin/org/jetbrains/jewel/intui/markdown/standalone/styling/extensions/github/tables/IntUiGitHubTableStyling.kt b/platform/jewel/markdown/int-ui-standalone-styling/src/main/kotlin/org/jetbrains/jewel/intui/markdown/standalone/styling/extensions/github/tables/IntUiGitHubTableStyling.kt
new file mode 100644
index 0000000000000..7c6667c2e6d56
--- /dev/null
+++ b/platform/jewel/markdown/int-ui-standalone-styling/src/main/kotlin/org/jetbrains/jewel/intui/markdown/standalone/styling/extensions/github/tables/IntUiGitHubTableStyling.kt
@@ -0,0 +1,45 @@
+package org.jetbrains.jewel.intui.markdown.standalone.styling.extensions.github.tables
+
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import org.jetbrains.jewel.markdown.extensions.github.tables.GfmTableColors
+import org.jetbrains.jewel.markdown.extensions.github.tables.GfmTableMetrics
+import org.jetbrains.jewel.markdown.extensions.github.tables.GfmTableStyling
+import org.jetbrains.jewel.markdown.extensions.github.tables.RowBackgroundStyle
+
+public fun GfmTableStyling.Companion.light(
+ colors: GfmTableColors = GfmTableColors.light(),
+ metrics: GfmTableMetrics = GfmTableMetrics.defaults(),
+ headerBaseFontWeight: FontWeight = FontWeight.SemiBold,
+): GfmTableStyling = GfmTableStyling(colors, metrics, headerBaseFontWeight)
+
+public fun GfmTableStyling.Companion.dark(
+ colors: GfmTableColors = GfmTableColors.dark(),
+ metrics: GfmTableMetrics = GfmTableMetrics.defaults(),
+ headerBaseFontWeight: FontWeight = FontWeight.SemiBold,
+): GfmTableStyling = GfmTableStyling(colors, metrics, headerBaseFontWeight)
+
+public fun GfmTableColors.Companion.light(
+ borderColor: Color = Color(0xffd1d9e0),
+ rowBackgroundColor: Color = Color.Unspecified,
+ alternateRowBackgroundColor: Color = Color(0xfff6f8fa),
+ rowBackgroundStyle: RowBackgroundStyle = RowBackgroundStyle.Striped,
+) = GfmTableColors(borderColor, rowBackgroundColor, alternateRowBackgroundColor, rowBackgroundStyle)
+
+public fun GfmTableColors.Companion.dark(
+ borderColor: Color = Color(0xff3d444d),
+ rowBackgroundColor: Color = Color.Unspecified,
+ alternateRowBackgroundColor: Color = Color(0xff151b23),
+ rowBackgroundStyle: RowBackgroundStyle = RowBackgroundStyle.Striped,
+) = GfmTableColors(borderColor, rowBackgroundColor, alternateRowBackgroundColor, rowBackgroundStyle)
+
+public fun GfmTableMetrics.Companion.defaults(
+ borderWidth: Dp = 1.dp,
+ cellPadding: PaddingValues = PaddingValues(horizontal = 13.dp, vertical = 6.dp),
+ defaultCellContentAlignment: Alignment.Horizontal = Alignment.Start,
+ headerDefaultCellContentAlignment: Alignment.Horizontal = Alignment.CenterHorizontally,
+) = GfmTableMetrics(borderWidth, cellPadding, defaultCellContentAlignment, headerDefaultCellContentAlignment)
diff --git a/platform/jewel/samples/standalone/build.gradle.kts b/platform/jewel/samples/standalone/build.gradle.kts
index 64734a8c55286..442c490073f89 100644
--- a/platform/jewel/samples/standalone/build.gradle.kts
+++ b/platform/jewel/samples/standalone/build.gradle.kts
@@ -16,6 +16,7 @@ dependencies {
implementation(projects.markdown.intUiStandaloneStyling)
implementation(projects.markdown.extension.gfmAlerts)
implementation(projects.markdown.extension.autolink)
+ implementation(projects.markdown.extension.gfmTables)
implementation(compose.desktop.currentOs) { exclude(group = "org.jetbrains.compose.material") }
implementation(compose.components.resources)
implementation(libs.intellijPlatform.icons)
@@ -62,4 +63,4 @@ tasks {
setExecutable(javaLauncher.map { it.executablePath.asFile.absolutePath }.get())
}
}
-}
\ No newline at end of file
+}
diff --git a/platform/jewel/samples/standalone/intellij.platform.jewel.samples.standalone.iml b/platform/jewel/samples/standalone/intellij.platform.jewel.samples.standalone.iml
index 66308dfbc703f..47ee186bc7f78 100644
--- a/platform/jewel/samples/standalone/intellij.platform.jewel.samples.standalone.iml
+++ b/platform/jewel/samples/standalone/intellij.platform.jewel.samples.standalone.iml
@@ -137,5 +137,6 @@
+
\ No newline at end of file
diff --git a/platform/jewel/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/markdown/MarkdownEditor.kt b/platform/jewel/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/markdown/MarkdownEditor.kt
index 73252dad6058e..13cf6b3d0f2cd 100644
--- a/platform/jewel/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/markdown/MarkdownEditor.kt
+++ b/platform/jewel/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/markdown/MarkdownEditor.kt
@@ -2,7 +2,6 @@ package org.jetbrains.jewel.samples.standalone.view.markdown
import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
-import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -47,16 +46,14 @@ internal fun MarkdownEditor(state: TextFieldState, modifier: Modifier = Modifier
@Composable
private fun ControlsRow(modifier: Modifier = Modifier, onLoadMarkdown: (String) -> Unit) {
- Row(
- modifier.horizontalScroll(rememberScrollState()),
- horizontalArrangement = Arrangement.spacedBy(16.dp),
- verticalAlignment = Alignment.CenterVertically,
- ) {
+ Row(modifier.horizontalScroll(rememberScrollState()), verticalAlignment = Alignment.CenterVertically) {
var showFilePicker by remember { mutableStateOf(false) }
OutlinedButton(onClick = { showFilePicker = true }, modifier = Modifier.padding(start = 2.dp)) {
Text("Load file...")
}
+ Spacer(Modifier.width(10.dp))
+
FilePicker(show = showFilePicker, fileExtensions = listOf("md")) { platformFile ->
showFilePicker = false
diff --git a/platform/jewel/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/markdown/MarkdownPreview.kt b/platform/jewel/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/markdown/MarkdownPreview.kt
index ce782d8a2c373..08d5238797a41 100644
--- a/platform/jewel/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/markdown/MarkdownPreview.kt
+++ b/platform/jewel/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/markdown/MarkdownPreview.kt
@@ -24,14 +24,18 @@ import org.jetbrains.jewel.intui.markdown.standalone.light
import org.jetbrains.jewel.intui.markdown.standalone.styling.dark
import org.jetbrains.jewel.intui.markdown.standalone.styling.extensions.github.alerts.dark
import org.jetbrains.jewel.intui.markdown.standalone.styling.extensions.github.alerts.light
+import org.jetbrains.jewel.intui.markdown.standalone.styling.extensions.github.tables.dark
+import org.jetbrains.jewel.intui.markdown.standalone.styling.extensions.github.tables.light
import org.jetbrains.jewel.intui.markdown.standalone.styling.light
import org.jetbrains.jewel.markdown.LazyMarkdown
import org.jetbrains.jewel.markdown.MarkdownBlock
import org.jetbrains.jewel.markdown.extension.autolink.AutolinkProcessorExtension
-import org.jetbrains.jewel.markdown.extensions.LocalMarkdownMode
import org.jetbrains.jewel.markdown.extensions.github.alerts.AlertStyling
import org.jetbrains.jewel.markdown.extensions.github.alerts.GitHubAlertProcessorExtension
import org.jetbrains.jewel.markdown.extensions.github.alerts.GitHubAlertRendererExtension
+import org.jetbrains.jewel.markdown.extensions.github.tables.GfmTableStyling
+import org.jetbrains.jewel.markdown.extensions.github.tables.GitHubTableProcessorExtension
+import org.jetbrains.jewel.markdown.extensions.github.tables.GitHubTableRendererExtension
import org.jetbrains.jewel.markdown.processing.MarkdownProcessor
import org.jetbrains.jewel.markdown.rendering.MarkdownBlockRenderer
import org.jetbrains.jewel.markdown.rendering.MarkdownStyling
@@ -45,12 +49,15 @@ internal fun MarkdownPreview(modifier: Modifier = Modifier, rawMarkdown: CharSeq
val markdownStyling = remember(isDark) { if (isDark) MarkdownStyling.dark() else MarkdownStyling.light() }
var markdownBlocks by remember { mutableStateOf(emptyList()) }
- val extensions = remember { listOf(GitHubAlertProcessorExtension, AutolinkProcessorExtension) }
- val markdownMode = LocalMarkdownMode.current
+
// We are doing this here for the sake of simplicity.
// In a real-world scenario you would be doing this outside your Composables,
// potentially involving ViewModels, dependency injection, etc.
- val processor = remember { MarkdownProcessor(extensions, markdownMode = markdownMode) }
+ val processor = remember {
+ MarkdownProcessor(
+ listOf(GitHubAlertProcessorExtension, AutolinkProcessorExtension, GitHubTableProcessorExtension)
+ )
+ }
LaunchedEffect(rawMarkdown) {
// TODO you may want to debounce or drop on backpressure, in real usages. You should also
@@ -61,16 +68,24 @@ internal fun MarkdownPreview(modifier: Modifier = Modifier, rawMarkdown: CharSeq
}
val blockRenderer =
- remember(markdownStyling, extensions) {
+ remember(markdownStyling) {
if (isDark) {
MarkdownBlockRenderer.dark(
styling = markdownStyling,
- rendererExtensions = listOf(GitHubAlertRendererExtension(AlertStyling.dark(), markdownStyling)),
+ rendererExtensions =
+ listOf(
+ GitHubAlertRendererExtension(AlertStyling.dark(), markdownStyling),
+ GitHubTableRendererExtension(GfmTableStyling.dark(), markdownStyling),
+ ),
)
} else {
MarkdownBlockRenderer.light(
styling = markdownStyling,
- rendererExtensions = listOf(GitHubAlertRendererExtension(AlertStyling.light(), markdownStyling)),
+ rendererExtensions =
+ listOf(
+ GitHubAlertRendererExtension(AlertStyling.light(), markdownStyling),
+ GitHubTableRendererExtension(GfmTableStyling.light(), markdownStyling),
+ ),
)
}
}
diff --git a/platform/jewel/settings.gradle.kts b/platform/jewel/settings.gradle.kts
index c6fba3a6f1645..b7a3a1796155f 100644
--- a/platform/jewel/settings.gradle.kts
+++ b/platform/jewel/settings.gradle.kts
@@ -12,6 +12,9 @@ pluginManagement {
gradlePluginPortal()
mavenCentral()
}
+ plugins {
+ kotlin("jvm") version "2.1.0"
+ }
}
dependencyResolutionManagement {
@@ -28,6 +31,7 @@ dependencyResolutionManagement {
plugins {
id("com.gradle.enterprise") version "3.15.1"
id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0"
+ id("org.danilopianini.gradle-pre-commit-git-hooks") version "2.0.9"
}
include(
@@ -40,6 +44,7 @@ include(
":markdown:core",
":markdown:extension:autolink",
":markdown:extension:gfm-alerts",
+ ":markdown:extension:gfm-tables",
":markdown:int-ui-standalone-styling",
":markdown:ide-laf-bridge-styling",
":samples:ide-plugin",
@@ -48,8 +53,6 @@ include(
":ui-test",
)
-project(":ide-laf-bridge-tests").projectDir = file("ide-laf-bridge/ide-laf-bridge-tests")
-
gradleEnterprise {
buildScan {
publishAlwaysIf(System.getenv("CI") == "true")
@@ -58,4 +61,46 @@ gradleEnterprise {
}
}
-include("ui-tests")
+val isWindows
+ get() = System.getProperty("os.name").contains("win", true)
+
+val gradleCommand: String by
+lazy(LazyThreadSafetyMode.NONE) {
+ val gradlewFilename =
+ if (isWindows) {
+ "gradlew.bat"
+ } else {
+ "gradlew"
+ }
+
+ val gradlew = File(rootProject.projectDir, gradlewFilename)
+ if (gradlew.exists() && gradlew.isFile && gradlew.canExecute()) {
+ logger.info("Using gradlew wrapper at ${gradlew.invariantSeparatorsPath}")
+ gradlew.invariantSeparatorsPath
+ } else {
+ "gradle"
+ }
+}
+
+val shebang = if (isWindows) "" else "#!/bin/sh"
+
+gitHooks {
+ hook("pre-push") {
+ from(shebang) {
+ // language=Shell Script
+ """
+ |#### Note: this hook was autogenerated. You can edit it in settings.gradle.kts
+ |GRADLEW=$gradleCommand
+ |if ! ${'$'}GRADLEW ktfmtCheck ; then
+ | ${'$'}GRADLEW ktfmtFormat
+ | echo 1>&2 "\nktfmt found problems; commit the result and re-push"
+ | exit 1
+ |fi
+ |
+ """
+ .trimMargin()
+ }
+ }
+
+ createHooks(overwriteExisting = true)
+}