From ff79965a265eab4fa9cdd41067351b9db80ca8c1 Mon Sep 17 00:00:00 2001 From: Robbert Ruiter Date: Mon, 27 Oct 2025 14:15:50 +0100 Subject: [PATCH 1/3] Feat: Add custom styling support for block quote content --- buildSrc/src/main/kotlin/BuildConstants.kt | 2 +- .../markymark/composable/MarkyMarkQuote.kt | 19 +++++++++--- .../markymark/theme/quote/BlockQuoteStyle.kt | 29 +++++++++++++++++-- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/buildSrc/src/main/kotlin/BuildConstants.kt b/buildSrc/src/main/kotlin/BuildConstants.kt index 948835b..33351f4 100644 --- a/buildSrc/src/main/kotlin/BuildConstants.kt +++ b/buildSrc/src/main/kotlin/BuildConstants.kt @@ -23,5 +23,5 @@ object BuildConstants { const val Namespace = "com.moveagency.markymark" const val MinSdk = 24 - const val TargetSdk = 34 + const val TargetSdk = 35 } diff --git a/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkQuote.kt b/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkQuote.kt index 32d058b..99cca96 100644 --- a/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkQuote.kt +++ b/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkQuote.kt @@ -79,12 +79,23 @@ fun MarkyMarkQuote( } .padding(style.innerPadding) ) { - if (theme?.colors != null) { - CompositionLocalProvider(LocalMarkyMarkColors provides theme.colors) { + val parent = LocalMarkyMarkTheme.current.styles.composable + val inner = style.contentStyle?.invoke(parent) ?: parent + + CompositionLocalProvider( + LocalMarkyMarkTheme provides LocalMarkyMarkTheme.current.copy( + styles = LocalMarkyMarkTheme.current.styles.copy( + composable = inner + ) + ) + ) { + if (theme?.colors != null) { + CompositionLocalProvider(LocalMarkyMarkColors provides theme.colors) { + children() + } + } else { children() } - } else { - children() } } } diff --git a/markymark/src/main/java/com/moveagency/markymark/theme/quote/BlockQuoteStyle.kt b/markymark/src/main/java/com/moveagency/markymark/theme/quote/BlockQuoteStyle.kt index 442035d..c04b536 100644 --- a/markymark/src/main/java/com/moveagency/markymark/theme/quote/BlockQuoteStyle.kt +++ b/markymark/src/main/java/com/moveagency/markymark/theme/quote/BlockQuoteStyle.kt @@ -23,10 +23,12 @@ package com.moveagency.markymark.theme.quote import androidx.compose.runtime.Immutable import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.moveagency.markymark.composable.MarkyMarkQuote import com.moveagency.markymark.model.composable.BlockQuote +import com.moveagency.markymark.theme.ComposableStyles import com.moveagency.markymark.theme.MarkyMarkThemeBuilderMarker import com.moveagency.markymark.theme.Padding import kotlinx.collections.immutable.ImmutableList @@ -40,9 +42,9 @@ import kotlinx.collections.immutable.toImmutableList * @property innerPadding The padding inside the block quote. * @property outerPadding The padding outside the block quote, around the entire block. * @property indicatorThickness The thickness of the block quote indicator, defined in [Dp]. - * @property indicatorTint The color tint applied to the block quote indicator. * @property themes A list of themes used for rendering the block quote's content. * @property shape The shape of the block quote, such as a rectangle or other custom shape. + * @property contentStyle The text style applied to the content inside the code block. */ @Immutable data class BlockQuoteStyle private constructor( @@ -51,6 +53,7 @@ data class BlockQuoteStyle private constructor( val indicatorThickness: Dp, val themes: ImmutableList, val shape: Shape, + val contentStyle: ((parent: ComposableStyles) -> ComposableStyles)? = null, ) { /** @@ -84,6 +87,11 @@ data class BlockQuoteStyle private constructor( */ var shape: Shape = RectangleShape + /** + * The text style applied to the content inside the code block. Default is an empty [TextStyle]. + */ + var contentStyle: ((ComposableStyles) -> ComposableStyles)? = null + /** * Includes another [Builder] instance's configuration into `this` builder. * @@ -97,6 +105,7 @@ data class BlockQuoteStyle private constructor( indicatorThickness = builder.indicatorThickness themes.include(builder.themes) shape = builder.shape + contentStyle = builder.contentStyle } /** @@ -112,6 +121,7 @@ data class BlockQuoteStyle private constructor( indicatorThickness = style.indicatorThickness themes.include(style.themes) shape = style.shape + contentStyle = style.contentStyle } /** @@ -135,17 +145,32 @@ data class BlockQuoteStyle private constructor( */ fun themes(block: BlockQuoteThemesBuilder.() -> Unit) = block(themes) + /** + * Configures the content style for the block quote. + * + * @param overrides A lambda to override the [ComposableStyles.Builder] for the content. + */ + fun contentStyle(overrides: ComposableStyles.Builder.() -> Unit) { + contentStyle = { parent -> + ComposableStyles.Builder().apply { + include(parent) + overrides() + }.build() + } + } + /** * Builds a new [BlockQuoteStyle] instance with the current configuration. * * @return A [BlockQuoteStyle] object with the set properties for the block quote. */ - internal fun build() = BlockQuoteStyle( + internal fun build(): BlockQuoteStyle = BlockQuoteStyle( innerPadding = innerPadding.build(), outerPadding = outerPadding.build(), indicatorThickness = indicatorThickness, themes = themes.build(), shape = shape, + contentStyle = contentStyle ) } From da039b5b65bbf0763f6fe8f15aee561da7a5ff4b Mon Sep 17 00:00:00 2001 From: Robbert Ruiter Date: Mon, 27 Oct 2025 14:29:12 +0100 Subject: [PATCH 2/3] Chore: update comment and update version name --- buildSrc/src/main/kotlin/BuildConstants.kt | 2 +- .../com/moveagency/markymark/theme/quote/BlockQuoteStyle.kt | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/kotlin/BuildConstants.kt b/buildSrc/src/main/kotlin/BuildConstants.kt index 33351f4..beade17 100644 --- a/buildSrc/src/main/kotlin/BuildConstants.kt +++ b/buildSrc/src/main/kotlin/BuildConstants.kt @@ -18,7 +18,7 @@ object BuildConstants { - const val VersionName = "3.0.0-alpha11" + const val VersionName = "3.0.0-alpha12" const val Namespace = "com.moveagency.markymark" diff --git a/markymark/src/main/java/com/moveagency/markymark/theme/quote/BlockQuoteStyle.kt b/markymark/src/main/java/com/moveagency/markymark/theme/quote/BlockQuoteStyle.kt index c04b536..337821f 100644 --- a/markymark/src/main/java/com/moveagency/markymark/theme/quote/BlockQuoteStyle.kt +++ b/markymark/src/main/java/com/moveagency/markymark/theme/quote/BlockQuoteStyle.kt @@ -23,7 +23,6 @@ package com.moveagency.markymark.theme.quote import androidx.compose.runtime.Immutable import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.moveagency.markymark.composable.MarkyMarkQuote @@ -88,7 +87,7 @@ data class BlockQuoteStyle private constructor( var shape: Shape = RectangleShape /** - * The text style applied to the content inside the code block. Default is an empty [TextStyle]. + * The text style applied to the content inside the code block. Default is an empty [ComposableStyles]. */ var contentStyle: ((ComposableStyles) -> ComposableStyles)? = null From 04d60d64fd512dc0a3273ca6ef30cb85b137968e Mon Sep 17 00:00:00 2001 From: Robbert Ruiter Date: Mon, 27 Oct 2025 15:43:33 +0100 Subject: [PATCH 3/3] Chore: fix some detekt issues --- detekt-config.yml | 9 +++++- .../markymark/composable/MarkyMarkCode.kt | 30 ++++++++----------- .../markymark/composable/MarkyMarkImage.kt | 9 +++--- .../markymark/composable/MarkyMarkListItem.kt | 8 ++--- .../markymark/composable/MarkyMarkQuote.kt | 2 +- .../composer/DefaultMarkyMarkComposer.kt | 2 +- .../markymark/model/composable/Headline.kt | 12 ++++---- .../markymark/theme/MarkyMarkThemeDefaults.kt | 2 +- .../markymark/theme/heading/HeadingsStyle.kt | 1 + .../theme/list/UnorderedListItemStyle.kt | 2 +- .../markymark/theme/quote/BlockQuoteStyle.kt | 6 ++-- 11 files changed, 43 insertions(+), 40 deletions(-) diff --git a/detekt-config.yml b/detekt-config.yml index eff217e..005dcc9 100644 --- a/detekt-config.yml +++ b/detekt-config.yml @@ -1,6 +1,6 @@ build: excludeCorrectable: true - maxIssues: 10 + maxIssues: 25 comments: CommentOverPrivateFunction: @@ -69,6 +69,7 @@ formatting: naming: BooleanPropertyNaming: active: true + allowedPattern: '^[a-z][A-Za-z0-9]*$' EnumNaming: active: true enumEntryPattern: '^(?:[A-Z]+[a-z0-9]+)[A-Za-z0-9]*$' @@ -142,6 +143,12 @@ style: ignoreAnnotated: [ 'Preview', 'Composable' ] SerialVersionUIDInSerializableClass: active: false + MaxLineLength: + active: true + maxLineLength: 120 + excludePackageStatements: true + excludeImportStatements: true + excludeCommentStatements: true compose: ReusedModifierInstance: diff --git a/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkCode.kt b/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkCode.kt index 6dff139..75be37b 100644 --- a/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkCode.kt +++ b/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkCode.kt @@ -93,20 +93,22 @@ private fun rememberHighlights(language: SyntaxLanguage, code: String): Highligh } } +private val previewMarkdownContent = """ + val someText = "I am text" + + fun something() { + println(someText.clean()) + } + + fun String.clean() = trim() +""".trimIndent() + @Preview @Composable private fun PreviewCodeBlock() { val node = CodeBlock( metadata = Root, - content = """ - val someText = "I am text" - - fun something() { - println(someText.clean()) - } - - fun String.clean() = trim() - """.trimIndent(), + content = previewMarkdownContent, language = "kotlin", ) @@ -123,15 +125,7 @@ private fun PreviewCodeBlock() { private fun PreviewCodeBlockNoLanguage() { val node = CodeBlock( metadata = Root, - content = """ - val someText = "I am text" - - fun something() { - println(someText.clean()) - } - - fun String.clean() = trim() - """.trimIndent(), + content = previewMarkdownContent, language = null, ) diff --git a/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkImage.kt b/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkImage.kt index ad64bc0..3a1561c 100644 --- a/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkImage.kt +++ b/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkImage.kt @@ -94,13 +94,15 @@ private fun CaptionedImage( } } +private const val previewImageUrl = "https://images.unsplash.com/photo-1459262838948-3e2de6c1ec80?q=80&w=3269&auto=format" + + "&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" + @Preview @Composable private fun PreviewImage() { val node = Image( metadata = Root, - url = "https://images.unsplash.com/photo-1459262838948-3e2de6c1ec80?q=80&w=3269&auto=format&fit=crop&ixlib" + - "=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + url = previewImageUrl, altText = "A cute koala", title = null, ) @@ -116,8 +118,7 @@ private fun PreviewImage() { private fun PreviewImageCaptioned() { val node = Image( metadata = Root, - url = "https://images.unsplash.com/photo-1459262838948-3e2de6c1ec80?q=80&w=3269&auto=format&fit=crop&ixlib" + - "=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + url = previewImageUrl, altText = "A cute koala", title = "A cute koala in a tree", ) diff --git a/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkListItem.kt b/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkListItem.kt index a859985..53f053e 100644 --- a/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkListItem.kt +++ b/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkListItem.kt @@ -243,7 +243,7 @@ private fun TaskIndicator(type: Task) { @Preview @Composable -fun PreviewOrderedListItem() { +private fun PreviewOrderedListItem() { MarkyMarkListItem( item = ListItem( type = Ordered(index = 1), @@ -263,7 +263,7 @@ fun PreviewOrderedListItem() { @Preview @Composable -fun PreviewUnorderedListItem() { +private fun PreviewUnorderedListItem() { Column { MarkyMarkListItem( item = ListItem( @@ -330,7 +330,7 @@ fun PreviewUnorderedListItem() { @Preview @Composable -fun PreviewUnorderedListItemCustom() { +private fun PreviewUnorderedListItemCustom() { val theme = LocalMarkyMarkTheme.current val previewTheme = remember(theme) { markyMarkTheme { @@ -597,7 +597,7 @@ fun PreviewUnorderedListItemCustom() { @Preview @Composable -fun PreviewTaskListItem() { +private fun PreviewTaskListItem() { Column { MarkyMarkListItem( item = ListItem( diff --git a/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkQuote.kt b/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkQuote.kt index 99cca96..bf7ff65 100644 --- a/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkQuote.kt +++ b/markymark/src/main/java/com/moveagency/markymark/composable/MarkyMarkQuote.kt @@ -81,7 +81,7 @@ fun MarkyMarkQuote( ) { val parent = LocalMarkyMarkTheme.current.styles.composable val inner = style.contentStyle?.invoke(parent) ?: parent - + CompositionLocalProvider( LocalMarkyMarkTheme provides LocalMarkyMarkTheme.current.copy( styles = LocalMarkyMarkTheme.current.styles.copy( diff --git a/markymark/src/main/java/com/moveagency/markymark/composer/DefaultMarkyMarkComposer.kt b/markymark/src/main/java/com/moveagency/markymark/composer/DefaultMarkyMarkComposer.kt index 6d38000..d4fdca2 100644 --- a/markymark/src/main/java/com/moveagency/markymark/composer/DefaultMarkyMarkComposer.kt +++ b/markymark/src/main/java/com/moveagency/markymark/composer/DefaultMarkyMarkComposer.kt @@ -111,8 +111,8 @@ open class DefaultMarkyMarkComposer : MarkyMarkComposer { @Composable protected open fun Image( - modifier: Modifier, node: Image, + modifier: Modifier, ) = MarkyMarkImage( modifier = modifier.fillMaxWidth(), node = node, diff --git a/markymark/src/main/java/com/moveagency/markymark/model/composable/Headline.kt b/markymark/src/main/java/com/moveagency/markymark/model/composable/Headline.kt index e555c5d..4baba07 100644 --- a/markymark/src/main/java/com/moveagency/markymark/model/composable/Headline.kt +++ b/markymark/src/main/java/com/moveagency/markymark/model/composable/Headline.kt @@ -97,7 +97,7 @@ data class Headline( /** * The top-level heading, typically used for document titles or major section headings. - * + * * __Syntax:__ * * ```markdown @@ -118,7 +118,7 @@ data class Headline( /** * Second-level heading, used for major sections within the document. - * + * * __Syntax:__ * * ```markdown @@ -139,7 +139,7 @@ data class Headline( /** * Third-level heading, used for subsections within major sections. - * + * * __Syntax:__ * * ```markdown @@ -153,7 +153,7 @@ data class Headline( /** * Fourth-level heading, used for smaller divisions within subsections. - * + * * __Syntax:__ * * ```markdown @@ -167,7 +167,7 @@ data class Headline( /** * Fifth-level heading, used for fine-grained content organization. - * + * * __Syntax:__ * * ```markdown @@ -181,7 +181,7 @@ data class Headline( /** * Sixth-level heading, the lowest level available in Markdown. - * + * * __Syntax:__ * * ```markdown diff --git a/markymark/src/main/java/com/moveagency/markymark/theme/MarkyMarkThemeDefaults.kt b/markymark/src/main/java/com/moveagency/markymark/theme/MarkyMarkThemeDefaults.kt index 5de3875..94fc688 100644 --- a/markymark/src/main/java/com/moveagency/markymark/theme/MarkyMarkThemeDefaults.kt +++ b/markymark/src/main/java/com/moveagency/markymark/theme/MarkyMarkThemeDefaults.kt @@ -239,7 +239,7 @@ object MarkyMarkThemeDefaults { indicator { shape = UnorderedListItemStyle.Indicator.Shape.Rectangle } - indicator { // Line + indicator { // Line shape = UnorderedListItemStyle.Indicator.Shape.Rectangle size = DpSize(width = 6.dp, height = 2.dp) } diff --git a/markymark/src/main/java/com/moveagency/markymark/theme/heading/HeadingsStyle.kt b/markymark/src/main/java/com/moveagency/markymark/theme/heading/HeadingsStyle.kt index 92392c7..5c8ab4a 100644 --- a/markymark/src/main/java/com/moveagency/markymark/theme/heading/HeadingsStyle.kt +++ b/markymark/src/main/java/com/moveagency/markymark/theme/heading/HeadingsStyle.kt @@ -98,6 +98,7 @@ data class HeadingsStyle( h3 = builder.h3 h4 = builder.h4 h5 = builder.h5 + h6 = builder.h6 } /** diff --git a/markymark/src/main/java/com/moveagency/markymark/theme/list/UnorderedListItemStyle.kt b/markymark/src/main/java/com/moveagency/markymark/theme/list/UnorderedListItemStyle.kt index 4a12ba6..baa4d30 100644 --- a/markymark/src/main/java/com/moveagency/markymark/theme/list/UnorderedListItemStyle.kt +++ b/markymark/src/main/java/com/moveagency/markymark/theme/list/UnorderedListItemStyle.kt @@ -315,7 +315,7 @@ data class UnorderedListItemStyle private constructor( /** * Builder for constructing the list of indicators for the unordered list item. */ - private var indicators = UnorderedListIndicatorsBuilder() + private val indicators = UnorderedListIndicatorsBuilder() /** * Includes another [Builder] instance's configuration into `this` builder. diff --git a/markymark/src/main/java/com/moveagency/markymark/theme/quote/BlockQuoteStyle.kt b/markymark/src/main/java/com/moveagency/markymark/theme/quote/BlockQuoteStyle.kt index 337821f..92dba43 100644 --- a/markymark/src/main/java/com/moveagency/markymark/theme/quote/BlockQuoteStyle.kt +++ b/markymark/src/main/java/com/moveagency/markymark/theme/quote/BlockQuoteStyle.kt @@ -43,7 +43,7 @@ import kotlinx.collections.immutable.toImmutableList * @property indicatorThickness The thickness of the block quote indicator, defined in [Dp]. * @property themes A list of themes used for rendering the block quote's content. * @property shape The shape of the block quote, such as a rectangle or other custom shape. - * @property contentStyle The text style applied to the content inside the code block. + * @property contentStyle The composable style to be applied to the content inside the block quote. */ @Immutable data class BlockQuoteStyle private constructor( @@ -79,7 +79,7 @@ data class BlockQuoteStyle private constructor( /** * Builder for configuring the themes used for rendering the block quote's content. */ - private var themes = BlockQuoteThemesBuilder() + private val themes = BlockQuoteThemesBuilder() /** * The shape of the block quote. Default is [RectangleShape]. @@ -87,7 +87,7 @@ data class BlockQuoteStyle private constructor( var shape: Shape = RectangleShape /** - * The text style applied to the content inside the code block. Default is an empty [ComposableStyles]. + * The composable style applied to the content inside the code block. Default is an empty [ComposableStyles]. */ var contentStyle: ((ComposableStyles) -> ComposableStyles)? = null