diff --git a/markdown/core/api/core.api b/markdown/core/api/core.api index afcec05114..5a9783a854 100644 --- a/markdown/core/api/core.api +++ b/markdown/core/api/core.api @@ -332,6 +332,12 @@ public final class org/jetbrains/jewel/markdown/MarkdownBlock$ThematicBreak : or public static final field INSTANCE Lorg/jetbrains/jewel/markdown/MarkdownBlock$ThematicBreak; } +public final class org/jetbrains/jewel/markdown/MarkdownKt { + public static final fun LazyMarkdown (Ljava/util/List;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/foundation/lazy/LazyListState;ZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;Landroidx/compose/runtime/Composer;II)V + public static final fun Markdown (Ljava/lang/String;Landroidx/compose/ui/Modifier;ZZLkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;Lorg/jetbrains/jewel/markdown/processing/MarkdownProcessor;Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;Landroidx/compose/runtime/Composer;II)V + public static final fun Markdown (Ljava/util/List;Ljava/lang/String;Landroidx/compose/ui/Modifier;ZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;Landroidx/compose/runtime/Composer;II)V +} + public final class org/jetbrains/jewel/markdown/MimeType { public static final field ATTR_FOLDER_TYPE Ljava/lang/String; public static final field ATTR_ROLE Ljava/lang/String; @@ -401,6 +407,12 @@ public final class org/jetbrains/jewel/markdown/MimeTypeKt { public static final fun isXml-K9GpHcc (Ljava/lang/String;)Z } +public final class org/jetbrains/jewel/markdown/SemanticsKt { + public static final fun getRawMarkdown ()Landroidx/compose/ui/semantics/SemanticsPropertyKey; + public static final fun getRawMarkdown (Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;)Ljava/lang/String; + public static final fun setRawMarkdown (Landroidx/compose/ui/semantics/SemanticsPropertyReceiver;Ljava/lang/String;)V +} + public abstract interface class org/jetbrains/jewel/markdown/extensions/MarkdownBlockProcessorExtension { public abstract fun canProcess (Lorg/commonmark/node/CustomBlock;)Z public abstract fun processMarkdownBlock (Lorg/commonmark/node/CustomBlock;Lorg/jetbrains/jewel/markdown/processing/MarkdownProcessor;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock; @@ -412,9 +424,6 @@ public abstract interface class org/jetbrains/jewel/markdown/extensions/Markdown } public final class org/jetbrains/jewel/markdown/extensions/MarkdownKt { - public static final fun LazyMarkdown (Ljava/util/List;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/foundation/lazy/LazyListState;ZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;Landroidx/compose/runtime/Composer;II)V - public static final fun Markdown (Ljava/lang/String;Landroidx/compose/ui/Modifier;ZZLkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;Lorg/jetbrains/jewel/markdown/processing/MarkdownProcessor;Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;Landroidx/compose/runtime/Composer;II)V - public static final fun Markdown (Ljava/util/List;Landroidx/compose/ui/Modifier;ZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;Landroidx/compose/runtime/Composer;II)V public static final fun getLocalMarkdownBlockRenderer ()Landroidx/compose/runtime/ProvidableCompositionLocal; public static final fun getLocalMarkdownProcessor ()Landroidx/compose/runtime/ProvidableCompositionLocal; public static final fun getLocalMarkdownStyling ()Landroidx/compose/runtime/ProvidableCompositionLocal; @@ -457,6 +466,7 @@ public final class org/jetbrains/jewel/markdown/rendering/DefaultInlineMarkdownR public class org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer : org/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer { public static final field $stable I 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 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 diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/Markdown.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/Markdown.kt new file mode 100644 index 0000000000..1fe15f3692 --- /dev/null +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/Markdown.kt @@ -0,0 +1,138 @@ +package org.jetbrains.jewel.markdown + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.text.selection.SelectionContainer +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +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.semantics.semantics +import androidx.compose.ui.unit.dp +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.intellij.lang.annotations.Language +import org.jetbrains.jewel.foundation.ExperimentalJewelApi +import org.jetbrains.jewel.foundation.theme.JewelTheme +import org.jetbrains.jewel.markdown.extensions.markdownBlockRenderer +import org.jetbrains.jewel.markdown.extensions.markdownProcessor +import org.jetbrains.jewel.markdown.extensions.markdownStyling +import org.jetbrains.jewel.markdown.processing.MarkdownProcessor +import org.jetbrains.jewel.markdown.rendering.DefaultMarkdownBlockRenderer +import org.jetbrains.jewel.markdown.rendering.MarkdownBlockRenderer +import org.jetbrains.jewel.markdown.rendering.MarkdownStyling + +@ExperimentalJewelApi +@Composable +public fun Markdown( + @Language("Markdown") markdown: String, + modifier: Modifier = Modifier, + selectable: Boolean = false, + enabled: Boolean = true, + renderingDispatcher: CoroutineDispatcher = Dispatchers.Default, + onUrlClick: (String) -> Unit = {}, + onTextClick: () -> Unit = {}, + markdownStyling: MarkdownStyling = JewelTheme.markdownStyling, + processor: MarkdownProcessor = JewelTheme.markdownProcessor, + blockRenderer: MarkdownBlockRenderer = DefaultMarkdownBlockRenderer(markdownStyling), +) { + var markdownBlocks by remember { mutableStateOf(emptyList()) } + LaunchedEffect(markdown, processor) { + markdownBlocks = + withContext(renderingDispatcher) { processor.processMarkdownDocument(markdown) } + } + + Markdown( + markdownBlocks = markdownBlocks, + markdown = markdown, + modifier = modifier, + selectable = selectable, + enabled = enabled, + onUrlClick = onUrlClick, + onTextClick = onTextClick, + markdownStyling = markdownStyling, + blockRenderer = blockRenderer, + ) +} + +@ExperimentalJewelApi +@Composable +public fun Markdown( + markdownBlocks: List, + markdown: String, + modifier: Modifier = Modifier, + enabled: Boolean = true, + selectable: Boolean = false, + onUrlClick: (String) -> Unit = {}, + onTextClick: () -> Unit = {}, + markdownStyling: MarkdownStyling = JewelTheme.markdownStyling, + blockRenderer: MarkdownBlockRenderer = DefaultMarkdownBlockRenderer(markdownStyling), +) { + if (selectable) { + SelectionContainer(modifier.semantics { rawMarkdown = markdown }) { + Column(verticalArrangement = Arrangement.spacedBy(markdownStyling.blockVerticalSpacing)) { + for (block in markdownBlocks) { + blockRenderer.render(block, enabled, onUrlClick, onTextClick) + } + } + } + } else { + Column( + modifier.semantics { rawMarkdown = markdown }, + verticalArrangement = Arrangement.spacedBy(markdownStyling.blockVerticalSpacing), + ) { + for (block in markdownBlocks) { + blockRenderer.render(block, enabled, onUrlClick, onTextClick) + } + } + } +} + +@ExperimentalJewelApi +@Composable +public fun LazyMarkdown( + markdownBlocks: List, + modifier: Modifier = Modifier, + contentPadding: PaddingValues = PaddingValues(0.dp), + state: LazyListState = rememberLazyListState(), + enabled: Boolean = true, + selectable: Boolean = false, + onUrlClick: (String) -> Unit = {}, + onTextClick: () -> Unit = {}, + markdownStyling: MarkdownStyling = JewelTheme.markdownStyling, + blockRenderer: MarkdownBlockRenderer = JewelTheme.markdownBlockRenderer, +) { + if (selectable) { + SelectionContainer(modifier) { + LazyColumn( + state = state, + contentPadding = contentPadding, + verticalArrangement = Arrangement.spacedBy(markdownStyling.blockVerticalSpacing), + ) { + items(markdownBlocks) { block -> + blockRenderer.render(block, enabled, onUrlClick, onTextClick) + } + } + } + } else { + LazyColumn( + modifier = modifier, + state = state, + contentPadding = contentPadding, + verticalArrangement = Arrangement.spacedBy(markdownStyling.blockVerticalSpacing), + ) { + items(markdownBlocks) { block -> + blockRenderer.render(block, enabled, onUrlClick, onTextClick) + } + } + } +} diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/Semantics.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/Semantics.kt new file mode 100644 index 0000000000..6a1dc81287 --- /dev/null +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/Semantics.kt @@ -0,0 +1,7 @@ +package org.jetbrains.jewel.markdown + +import androidx.compose.ui.semantics.SemanticsPropertyKey +import androidx.compose.ui.semantics.SemanticsPropertyReceiver + +public val RawMarkdown: SemanticsPropertyKey = SemanticsPropertyKey("RawMarkdown") +public var SemanticsPropertyReceiver.rawMarkdown: String by RawMarkdown diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/Markdown.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/Markdown.kt index 478d78e468..e42195c241 100644 --- a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/Markdown.kt +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/Markdown.kt @@ -1,30 +1,9 @@ package org.jetbrains.jewel.markdown.extensions -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.ProvidableCompositionLocal -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.runtime.staticCompositionLocalOf -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import org.intellij.lang.annotations.Language -import org.jetbrains.jewel.foundation.ExperimentalJewelApi import org.jetbrains.jewel.foundation.theme.JewelTheme -import org.jetbrains.jewel.markdown.MarkdownBlock import org.jetbrains.jewel.markdown.processing.MarkdownProcessor import org.jetbrains.jewel.markdown.rendering.MarkdownBlockRenderer import org.jetbrains.jewel.markdown.rendering.MarkdownStyling @@ -49,107 +28,3 @@ public val LocalMarkdownBlockRenderer: ProvidableCompositionLocal Unit = {}, - onTextClick: () -> Unit = {}, - markdownStyling: MarkdownStyling = JewelTheme.markdownStyling, - processor: MarkdownProcessor = JewelTheme.markdownProcessor, - blockRenderer: MarkdownBlockRenderer = JewelTheme.markdownBlockRenderer, -) { - var markdownBlocks by remember { mutableStateOf(emptyList()) } - LaunchedEffect(markdown) { - markdownBlocks = - withContext(renderingDispatcher) { processor.processMarkdownDocument(markdown) } - } - - Markdown( - markdownBlocks = markdownBlocks, - modifier = modifier, - selectable = selectable, - enabled = enabled, - onUrlClick = onUrlClick, - onTextClick = onTextClick, - markdownStyling = markdownStyling, - blockRenderer = blockRenderer, - ) -} - -@ExperimentalJewelApi -@Composable -public fun Markdown( - markdownBlocks: List, - modifier: Modifier = Modifier, - enabled: Boolean = true, - selectable: Boolean = false, - onUrlClick: (String) -> Unit = {}, - onTextClick: () -> Unit = {}, - markdownStyling: MarkdownStyling = JewelTheme.markdownStyling, - blockRenderer: MarkdownBlockRenderer = JewelTheme.markdownBlockRenderer, -) { - if (selectable) { - SelectionContainer(modifier) { - Column(verticalArrangement = Arrangement.spacedBy(markdownStyling.blockVerticalSpacing)) { - for (block in markdownBlocks) { - blockRenderer.render(block, enabled, onUrlClick, onTextClick) - } - } - } - } else { - Column( - modifier, - verticalArrangement = Arrangement.spacedBy(markdownStyling.blockVerticalSpacing), - ) { - for (block in markdownBlocks) { - blockRenderer.render(block, enabled, onUrlClick, onTextClick) - } - } - } -} - -@ExperimentalJewelApi -@Composable -public fun LazyMarkdown( - markdownBlocks: List, - modifier: Modifier = Modifier, - contentPadding: PaddingValues = PaddingValues(0.dp), - state: LazyListState = rememberLazyListState(), - enabled: Boolean = true, - selectable: Boolean = false, - onUrlClick: (String) -> Unit = {}, - onTextClick: () -> Unit = {}, - markdownStyling: MarkdownStyling = JewelTheme.markdownStyling, - blockRenderer: MarkdownBlockRenderer = JewelTheme.markdownBlockRenderer, -) { - if (selectable) { - SelectionContainer(modifier) { - LazyColumn( - state = state, - contentPadding = contentPadding, - verticalArrangement = Arrangement.spacedBy(markdownStyling.blockVerticalSpacing), - ) { - items(markdownBlocks) { block -> - blockRenderer.render(block, enabled, onUrlClick, onTextClick) - } - } - } - } else { - LazyColumn( - modifier = modifier, - state = state, - contentPadding = contentPadding, - verticalArrangement = Arrangement.spacedBy(markdownStyling.blockVerticalSpacing), - ) { - items(markdownBlocks) { block -> - blockRenderer.render(block, enabled, onUrlClick, onTextClick) - } - } - } -} diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer.kt index baad4c7a53..425f603c8c 100644 --- a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer.kt +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer.kt @@ -73,8 +73,8 @@ import org.jetbrains.jewel.ui.component.Text @ExperimentalJewelApi public open class DefaultMarkdownBlockRenderer( private val rootStyling: MarkdownStyling, - private val rendererExtensions: List, - private val inlineRenderer: InlineMarkdownRenderer, + private val rendererExtensions: List = emptyList(), + private val inlineRenderer: InlineMarkdownRenderer = DefaultInlineMarkdownRenderer(), ) : MarkdownBlockRenderer { @Composable diff --git a/samples/ide-plugin/src/main/kotlin/org/jetbrains/jewel/samples/ideplugin/ComponentShowcaseTab.kt b/samples/ide-plugin/src/main/kotlin/org/jetbrains/jewel/samples/ideplugin/ComponentShowcaseTab.kt index 29d5227638..1aa7ae78fd 100644 --- a/samples/ide-plugin/src/main/kotlin/org/jetbrains/jewel/samples/ideplugin/ComponentShowcaseTab.kt +++ b/samples/ide-plugin/src/main/kotlin/org/jetbrains/jewel/samples/ideplugin/ComponentShowcaseTab.kt @@ -40,7 +40,7 @@ import org.jetbrains.jewel.foundation.modifier.trackComponentActivation import org.jetbrains.jewel.foundation.theme.JewelTheme import org.jetbrains.jewel.foundation.theme.LocalContentColor import org.jetbrains.jewel.intui.markdown.bridge.ProvideMarkdownStyling -import org.jetbrains.jewel.markdown.extensions.Markdown +import org.jetbrains.jewel.markdown.Markdown import org.jetbrains.jewel.ui.Orientation import org.jetbrains.jewel.ui.Outline import org.jetbrains.jewel.ui.component.CheckboxRow diff --git a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/markdown/MarkdownPreview.kt b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/markdown/MarkdownPreview.kt index 63afc53eef..b218406ab1 100644 --- a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/markdown/MarkdownPreview.kt +++ b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/markdown/MarkdownPreview.kt @@ -27,9 +27,9 @@ import org.jetbrains.jewel.intui.markdown.standalone.styling.dark import org.jetbrains.jewel.intui.markdown.standalone.styling.extension.github.alerts.dark import org.jetbrains.jewel.intui.markdown.standalone.styling.extension.github.alerts.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.LazyMarkdown 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