Skip to content

Commit 8343d17

Browse files
authored
Merge pull request #419 from keta1/feat/code
Use coroutine to offload code highlighting to background thread
2 parents e47b1fc + 267de30 commit 8343d17

File tree

6 files changed

+91
-64
lines changed

6 files changed

+91
-64
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,14 +426,14 @@ Markdown(
426426
MarkdownHighlightedCodeBlock(
427427
content = it.content,
428428
node = it.node,
429-
highlights = highlightsBuilder
429+
highlightsBuilder = highlightsBuilder
430430
)
431431
},
432432
codeFence = {
433433
MarkdownHighlightedCodeFence(
434434
content = it.content,
435435
node = it.node,
436-
highlights = highlightsBuilder
436+
highlightsBuilder = highlightsBuilder
437437
)
438438
},
439439
)

multiplatform-markdown-renderer-code/api/android/multiplatform-markdown-renderer-code.api

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ public final class com/mikepenz/markdown/compose/elements/ComposableSingletons$M
66
}
77

88
public final class com/mikepenz/markdown/compose/elements/MarkdownHighlightedCodeKt {
9-
public static final fun MarkdownHighlightedCode (Ljava/lang/String;Ljava/lang/String;Ldev/snipme/highlights/Highlights$Builder;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/runtime/Composer;II)V
9+
public static final fun MarkdownHighlightedCode (Ljava/lang/String;Ljava/lang/String;Landroidx/compose/ui/text/TextStyle;Ldev/snipme/highlights/Highlights$Builder;Landroidx/compose/runtime/Composer;II)V
1010
public static final fun MarkdownHighlightedCodeBlock (Ljava/lang/String;Lorg/intellij/markdown/ast/ASTNode;Landroidx/compose/ui/text/TextStyle;Ldev/snipme/highlights/Highlights$Builder;Landroidx/compose/runtime/Composer;II)V
1111
public static final fun MarkdownHighlightedCodeFence (Ljava/lang/String;Lorg/intellij/markdown/ast/ASTNode;Landroidx/compose/ui/text/TextStyle;Ldev/snipme/highlights/Highlights$Builder;Landroidx/compose/runtime/Composer;II)V
1212
public static final fun getHighlightedCodeBlock ()Lkotlin/jvm/functions/Function3;

multiplatform-markdown-renderer-code/api/jvm/multiplatform-markdown-renderer-code.api

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ public final class com/mikepenz/markdown/compose/elements/ComposableSingletons$M
66
}
77

88
public final class com/mikepenz/markdown/compose/elements/MarkdownHighlightedCodeKt {
9-
public static final fun MarkdownHighlightedCode (Ljava/lang/String;Ljava/lang/String;Ldev/snipme/highlights/Highlights$Builder;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/runtime/Composer;II)V
9+
public static final fun MarkdownHighlightedCode (Ljava/lang/String;Ljava/lang/String;Landroidx/compose/ui/text/TextStyle;Ldev/snipme/highlights/Highlights$Builder;Landroidx/compose/runtime/Composer;II)V
1010
public static final fun MarkdownHighlightedCodeBlock (Ljava/lang/String;Lorg/intellij/markdown/ast/ASTNode;Landroidx/compose/ui/text/TextStyle;Ldev/snipme/highlights/Highlights$Builder;Landroidx/compose/runtime/Composer;II)V
1111
public static final fun MarkdownHighlightedCodeFence (Ljava/lang/String;Lorg/intellij/markdown/ast/ASTNode;Landroidx/compose/ui/text/TextStyle;Ldev/snipme/highlights/Highlights$Builder;Landroidx/compose/runtime/Composer;II)V
1212
public static final fun getHighlightedCodeBlock ()Lkotlin/jvm/functions/Function3;

multiplatform-markdown-renderer-code/api/multiplatform-markdown-renderer-code.klib.api

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ final val com.mikepenz.markdown.compose.elements/highlightedCodeBlock // com.mik
1111
final val com.mikepenz.markdown.compose.elements/highlightedCodeFence // com.mikepenz.markdown.compose.elements/highlightedCodeFence|{}highlightedCodeFence[0]
1212
final fun <get-highlightedCodeFence>(): kotlin/Function3<com.mikepenz.markdown.compose.components/MarkdownComponentModel, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit> // com.mikepenz.markdown.compose.elements/highlightedCodeFence.<get-highlightedCodeFence>|<get-highlightedCodeFence>(){}[0]
1313

14-
final fun com.mikepenz.markdown.compose.elements/MarkdownHighlightedCode(kotlin/String, kotlin/String?, dev.snipme.highlights/Highlights.Builder?, androidx.compose.ui.text/TextStyle?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.mikepenz.markdown.compose.elements/MarkdownHighlightedCode|MarkdownHighlightedCode(kotlin.String;kotlin.String?;dev.snipme.highlights.Highlights.Builder?;androidx.compose.ui.text.TextStyle?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
14+
final fun com.mikepenz.markdown.compose.elements/MarkdownHighlightedCode(kotlin/String, kotlin/String?, androidx.compose.ui.text/TextStyle?, dev.snipme.highlights/Highlights.Builder?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.mikepenz.markdown.compose.elements/MarkdownHighlightedCode|MarkdownHighlightedCode(kotlin.String;kotlin.String?;androidx.compose.ui.text.TextStyle?;dev.snipme.highlights.Highlights.Builder?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
1515
final fun com.mikepenz.markdown.compose.elements/MarkdownHighlightedCodeBlock(kotlin/String, org.intellij.markdown.ast/ASTNode, androidx.compose.ui.text/TextStyle?, dev.snipme.highlights/Highlights.Builder?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.mikepenz.markdown.compose.elements/MarkdownHighlightedCodeBlock|MarkdownHighlightedCodeBlock(kotlin.String;org.intellij.markdown.ast.ASTNode;androidx.compose.ui.text.TextStyle?;dev.snipme.highlights.Highlights.Builder?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
1616
final fun com.mikepenz.markdown.compose.elements/MarkdownHighlightedCodeFence(kotlin/String, org.intellij.markdown.ast/ASTNode, androidx.compose.ui.text/TextStyle?, dev.snipme.highlights/Highlights.Builder?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.mikepenz.markdown.compose.elements/MarkdownHighlightedCodeFence|MarkdownHighlightedCodeFence(kotlin.String;org.intellij.markdown.ast.ASTNode;androidx.compose.ui.text.TextStyle?;dev.snipme.highlights.Highlights.Builder?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]

multiplatform-markdown-renderer-code/src/commonMain/kotlin/com/mikepenz/markdown/compose/elements/MarkdownHighlightedCode.kt

Lines changed: 84 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,17 @@ import androidx.compose.foundation.layout.fillMaxWidth
66
import androidx.compose.foundation.layout.padding
77
import androidx.compose.foundation.rememberScrollState
88
import androidx.compose.foundation.shape.RoundedCornerShape
9-
import androidx.compose.runtime.*
9+
import androidx.compose.runtime.Composable
10+
import androidx.compose.runtime.State
11+
import androidx.compose.runtime.getValue
12+
import androidx.compose.runtime.produceState
13+
import androidx.compose.runtime.remember
1014
import androidx.compose.ui.Modifier
1115
import androidx.compose.ui.graphics.Color
12-
import androidx.compose.ui.text.*
16+
import androidx.compose.ui.text.AnnotatedString
17+
import androidx.compose.ui.text.SpanStyle
18+
import androidx.compose.ui.text.TextStyle
19+
import androidx.compose.ui.text.buildAnnotatedString
1320
import androidx.compose.ui.text.font.FontWeight
1421
import androidx.compose.ui.unit.dp
1522
import com.mikepenz.markdown.compose.LocalMarkdownColors
@@ -23,27 +30,34 @@ import dev.snipme.highlights.model.BoldHighlight
2330
import dev.snipme.highlights.model.ColorHighlight
2431
import dev.snipme.highlights.model.SyntaxLanguage
2532
import dev.snipme.highlights.model.SyntaxThemes
33+
import kotlinx.coroutines.Dispatchers
34+
import kotlinx.coroutines.launch
2635
import org.intellij.markdown.ast.ASTNode
2736

2837
/** Default definition for the [MarkdownHighlightedCodeFence]. Uses default theme, attempts to apply language from markdown. */
29-
val highlightedCodeFence: MarkdownComponent = { MarkdownHighlightedCodeFence(content = it.content, node = it.node, style = it.typography.code) }
38+
val highlightedCodeFence: MarkdownComponent = {
39+
MarkdownHighlightedCodeFence(content = it.content, node = it.node, style = it.typography.code)
40+
}
3041

3142
/** Default definition for the [MarkdownHighlightedCodeBlock]. Uses default theme, attempts to apply language from markdown. */
32-
val highlightedCodeBlock: MarkdownComponent = { MarkdownHighlightedCodeBlock(content = it.content, node = it.node, style = it.typography.code) }
43+
val highlightedCodeBlock: MarkdownComponent = {
44+
MarkdownHighlightedCodeBlock(content = it.content, node = it.node, style = it.typography.code)
45+
}
3346

3447
@Composable
3548
fun MarkdownHighlightedCodeFence(
3649
content: String,
3750
node: ASTNode,
3851
style: TextStyle = LocalMarkdownTypography.current.code,
39-
highlights: Highlights.Builder = Highlights.Builder(
40-
theme = SyntaxThemes.default(
41-
darkMode = isSystemInDarkTheme()
42-
)
43-
),
52+
highlightsBuilder: Highlights.Builder = rememberHighlightsBuilder(),
4453
) {
4554
MarkdownCodeFence(content, node, style) { code, language, style ->
46-
MarkdownHighlightedCode(code = code, language = language, highlights = highlights, style = style)
55+
MarkdownHighlightedCode(
56+
code = code,
57+
language = language,
58+
style = style,
59+
highlightsBuilder = highlightsBuilder,
60+
)
4761
}
4862
}
4963

@@ -52,37 +66,33 @@ fun MarkdownHighlightedCodeBlock(
5266
content: String,
5367
node: ASTNode,
5468
style: TextStyle = LocalMarkdownTypography.current.code,
55-
highlights: Highlights.Builder = Highlights.Builder(
56-
theme = SyntaxThemes.default(
57-
darkMode = isSystemInDarkTheme()
58-
)
59-
),
69+
highlightsBuilder: Highlights.Builder = rememberHighlightsBuilder(),
6070
) {
6171
MarkdownCodeBlock(content, node, style) { code, language, style ->
62-
MarkdownHighlightedCode(code = code, language = language, highlights = highlights, style = style)
72+
MarkdownHighlightedCode(
73+
code = code,
74+
language = language,
75+
style = style,
76+
highlightsBuilder = highlightsBuilder,
77+
)
6378
}
6479
}
6580

6681
@Composable
6782
fun MarkdownHighlightedCode(
6883
code: String,
6984
language: String?,
70-
highlights: Highlights.Builder = Highlights.Builder(),
7185
style: TextStyle = LocalMarkdownTypography.current.code,
86+
highlightsBuilder: Highlights.Builder = rememberHighlightsBuilder(),
7287
) {
7388
val backgroundCodeColor = LocalMarkdownColors.current.codeBackground
7489
val codeBackgroundCornerSize = LocalMarkdownDimens.current.codeBackgroundCornerSize
7590
val codeBlockPadding = LocalMarkdownPadding.current.codeBlock
76-
val syntaxLanguage = remember(language) { language?.let { SyntaxLanguage.getByName(it) } }
77-
78-
val codeHighlights by remembering(code) {
79-
derivedStateOf {
80-
highlights
81-
.code(code)
82-
.let { if (syntaxLanguage != null) it.language(syntaxLanguage) else it }
83-
.build()
84-
}
85-
}
91+
val codeHighlights: AnnotatedString by produceHighlightsState(
92+
code = code,
93+
language = language,
94+
highlightsBuilder = highlightsBuilder,
95+
)
8696

8797
MarkdownCodeBackground(
8898
color = backgroundCodeColor,
@@ -91,39 +101,56 @@ fun MarkdownHighlightedCode(
91101
) {
92102
@Suppress("DEPRECATION")
93103
MarkdownBasicText(
94-
text = buildAnnotatedString {
95-
text(codeHighlights.getCode())
96-
codeHighlights.getHighlights()
97-
.filterIsInstance<ColorHighlight>()
98-
.forEach {
99-
addStyle(
100-
SpanStyle(color = Color(it.rgb).copy(alpha = 1f)),
101-
start = it.location.start,
102-
end = it.location.end,
103-
)
104-
}
105-
codeHighlights.getHighlights()
106-
.filterIsInstance<BoldHighlight>()
107-
.forEach {
108-
addStyle(
109-
SpanStyle(fontWeight = FontWeight.Bold),
110-
start = it.location.start,
111-
end = it.location.end,
112-
)
113-
}
114-
},
115-
modifier = Modifier.horizontalScroll(rememberScrollState()).padding(codeBlockPadding),
116-
style = style
104+
text = codeHighlights,
105+
style = style,
106+
modifier = Modifier
107+
.horizontalScroll(rememberScrollState())
108+
.padding(codeBlockPadding),
117109
)
118110
}
119111
}
120112

121113
@Composable
122-
internal inline fun <T, K> remembering(
123-
key1: K,
124-
crossinline calculation: @DisallowComposableCalls (K) -> T,
125-
): T = remember(key1) { calculation(key1) }
114+
private fun rememberHighlightsBuilder(
115+
isDarkTheme: Boolean = isSystemInDarkTheme(),
116+
): Highlights.Builder {
117+
return remember(isDarkTheme) {
118+
Highlights.Builder().theme(SyntaxThemes.default(darkMode = isDarkTheme))
119+
}
120+
}
126121

127-
internal fun AnnotatedString.Builder.text(text: String, style: SpanStyle = SpanStyle()) = withStyle(style = style) {
128-
append(text)
129-
}
122+
@Composable
123+
private fun produceHighlightsState(
124+
code: String,
125+
language: String?,
126+
highlightsBuilder: Highlights.Builder,
127+
): State<AnnotatedString> = produceState(
128+
initialValue = AnnotatedString(text = code),
129+
key1 = code,
130+
) {
131+
val syntaxLanguage = language?.let { SyntaxLanguage.getByName(it) }
132+
val job = launch(Dispatchers.Default) {
133+
val codeHighlights = highlightsBuilder
134+
.code(code)
135+
.let { if (syntaxLanguage != null) it.language(syntaxLanguage) else it }
136+
.build()
137+
.getHighlights()
138+
value = buildAnnotatedString {
139+
append(code)
140+
codeHighlights.forEach {
141+
val style = when (it) {
142+
is ColorHighlight -> SpanStyle(color = Color(it.rgb).copy(alpha = 1f))
143+
is BoldHighlight -> SpanStyle(fontWeight = FontWeight.Bold)
144+
}
145+
addStyle(
146+
style = style,
147+
start = it.location.start,
148+
end = it.location.end,
149+
)
150+
}
151+
}
152+
}
153+
awaitDispose {
154+
job.cancel()
155+
}
156+
}

sample/shared/src/commonMain/kotlin/com/mikepenz/markdown/sample/MarkDownPage.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ internal fun MarkDownPage(modifier: Modifier = Modifier) {
4848
MarkdownHighlightedCodeBlock(
4949
content = it.content,
5050
node = it.node,
51-
highlights = highlightsBuilder
51+
highlightsBuilder = highlightsBuilder
5252
)
5353
},
5454
codeFence = {
5555
MarkdownHighlightedCodeFence(
5656
content = it.content,
5757
node = it.node,
58-
highlights = highlightsBuilder
58+
highlightsBuilder = highlightsBuilder
5959
)
6060
},
6161
checkbox = { MarkdownCheckBox(it.content, it.node, it.typography.text) }

0 commit comments

Comments
 (0)