11package com.halilibo.richtext.markdown
22
3+ import androidx.compose.foundation.layout.IntrinsicSize
4+ import androidx.compose.foundation.layout.fillMaxWidth
5+ import androidx.compose.foundation.layout.width
36import androidx.compose.foundation.text.BasicText
47import androidx.compose.runtime.Composable
8+ import androidx.compose.runtime.CompositionLocalProvider
59import androidx.compose.runtime.remember
610import androidx.compose.ui.Modifier
711import androidx.compose.ui.semantics.heading
812import androidx.compose.ui.semantics.semantics
13+ import com.halilibo.richtext.markdown.rtl.LocalCompatibilityTextAlignOverride
14+ import com.halilibo.richtext.markdown.rtl.firstStrongTextDirectionInFirstLine
15+ import com.halilibo.richtext.markdown.rtl.toCompatibilityTextAlign
16+ import com.halilibo.richtext.markdown.rtl.toCompatibilityTextDirection
917import com.halilibo.richtext.markdown.node.AstBlockNodeType
1018import com.halilibo.richtext.markdown.node.AstBlockQuote
1119import com.halilibo.richtext.markdown.node.AstDocument
@@ -27,6 +35,7 @@ import com.halilibo.richtext.markdown.node.AstTableRow
2735import com.halilibo.richtext.markdown.node.AstText
2836import com.halilibo.richtext.markdown.node.AstThematicBreak
2937import com.halilibo.richtext.markdown.node.AstUnorderedList
38+ import com.halilibo.richtext.ui.BasicRichText
3039import com.halilibo.richtext.ui.BlockQuote
3140import com.halilibo.richtext.ui.CodeBlock
3241import com.halilibo.richtext.ui.FormattedList
@@ -84,15 +93,31 @@ public fun RichTextScope.BasicMarkdown(
8493 richTextDecorations : RichTextDecorations = RichTextDecorations (),
8594 astBlockNodeComposer : AstBlockNodeComposer ? = null,
8695) {
87- RecursiveRenderMarkdownAst (
88- astNode = astNode,
89- contentOverride = contentOverride,
90- inlineContentOverride = inlineContentOverride,
91- richTextRenderOptions = richTextRenderOptions,
92- richTextDecorations = richTextDecorations,
93- markdownAnimationState = remember { MarkdownAnimationState () },
94- astNodeComposer = astBlockNodeComposer,
95- )
96+ val markdownAnimationState = remember { MarkdownAnimationState () }
97+
98+ if (richTextRenderOptions.enableRtlCompatibility && astNode.type is AstDocument ) {
99+ BasicRichText (modifier = Modifier .width(IntrinsicSize .Max )) {
100+ RecursiveRenderMarkdownAst (
101+ astNode = astNode,
102+ contentOverride = contentOverride,
103+ inlineContentOverride = inlineContentOverride,
104+ richTextRenderOptions = richTextRenderOptions,
105+ richTextDecorations = richTextDecorations,
106+ markdownAnimationState = markdownAnimationState,
107+ astNodeComposer = astBlockNodeComposer,
108+ )
109+ }
110+ } else {
111+ RecursiveRenderMarkdownAst (
112+ astNode = astNode,
113+ contentOverride = contentOverride,
114+ inlineContentOverride = inlineContentOverride,
115+ richTextRenderOptions = richTextRenderOptions,
116+ richTextDecorations = richTextDecorations,
117+ markdownAnimationState = markdownAnimationState,
118+ astNodeComposer = astBlockNodeComposer,
119+ )
120+ }
96121}
97122
98123/* *
@@ -238,46 +263,59 @@ private val DefaultAstNodeComposer = object : AstBlockNodeComposer {
238263 markdownAnimationState : MarkdownAnimationState ,
239264 visitChildren : @Composable (AstNode ) -> Unit
240265 ) {
266+ val compatibilityDirection = remember(astNode) {
267+ if (richTextRenderOptions.enableRtlCompatibility) {
268+ when (astNode.type) {
269+ is AstBlockQuote ,
270+ is AstIndentedCodeBlock ,
271+ is AstFencedCodeBlock -> astNode
272+ is AstUnorderedList ,
273+ is AstOrderedList -> astNode.links.firstChild
274+ else -> null
275+ }?.firstStrongTextDirectionInFirstLine()
276+ } else {
277+ null
278+ }
279+ }
280+
241281 when (val astNodeType = astNode.type) {
242282 is AstDocument -> visitChildren(astNode)
243283 is AstBlockQuote -> {
244284 BlockQuote (
245285 markdownAnimationState = markdownAnimationState,
246286 richTextRenderOptions = richTextRenderOptions,
287+ gutterDirection = compatibilityDirection,
247288 ) {
248- visitChildren(astNode)
249- }
250- }
251-
252- is AstUnorderedList -> {
253- FormattedList (
254- listType = Unordered ,
255- markdownAnimationState = markdownAnimationState,
256- richTextRenderOptions = richTextRenderOptions,
257- items = astNode.filterChildrenType<AstListItem >().toList()
258- ) { astListItem ->
259- // if this list item has no child, it should at least emit a single pixel layout.
260- if (astListItem.links.firstChild == null ) {
261- BasicText (" " )
262- } else {
263- visitChildren(astListItem)
289+ CompositionLocalProvider (
290+ LocalCompatibilityTextAlignOverride provides compatibilityDirection.toCompatibilityTextAlign(),
291+ ) {
292+ visitChildren(astNode)
264293 }
265294 }
266295 }
267296
297+ is AstUnorderedList ,
268298 is AstOrderedList -> {
299+ val items = remember(astNode) {
300+ astNode.childrenSequence().toList()
301+ }
269302 FormattedList (
270- listType = Ordered ,
303+ listType = if (astNodeType is AstOrderedList ) Ordered else Unordered ,
271304 markdownAnimationState = markdownAnimationState,
272305 richTextRenderOptions = richTextRenderOptions,
273- items = astNode.childrenSequence().toList(),
274- startIndex = astNodeType.startNumber - 1 ,
306+ items = items,
307+ startIndex = if (astNodeType is AstOrderedList ) astNodeType.startNumber - 1 else 0 ,
308+ markerDirection = compatibilityDirection,
275309 ) { astListItem ->
276- // if this list item has no child, it should at least emit a single pixel layout.
277- if (astListItem.links.firstChild == null ) {
278- BasicText (" " )
279- } else {
280- visitChildren(astListItem)
310+ CompositionLocalProvider (
311+ LocalCompatibilityTextAlignOverride provides compatibilityDirection.toCompatibilityTextAlign(),
312+ ) {
313+ // if this list item has no child, it should at least emit a single pixel layout.
314+ if (astListItem.links.firstChild == null ) {
315+ BasicText (" " )
316+ } else {
317+ visitChildren(astListItem)
318+ }
281319 }
282320 }
283321 }
@@ -307,6 +345,9 @@ private val DefaultAstNodeComposer = object : AstBlockNodeComposer {
307345 text = astNodeType.literal.trim(),
308346 markdownAnimationState = markdownAnimationState,
309347 richTextRenderOptions = richTextRenderOptions,
348+ modifier = if (compatibilityDirection != null ) Modifier .fillMaxWidth() else Modifier ,
349+ textDirection = compatibilityDirection.toCompatibilityTextDirection(),
350+ textAlign = compatibilityDirection.toCompatibilityTextAlign(),
310351 )
311352 }
312353
@@ -315,6 +356,9 @@ private val DefaultAstNodeComposer = object : AstBlockNodeComposer {
315356 text = astNodeType.literal.trim(),
316357 markdownAnimationState = markdownAnimationState,
317358 richTextRenderOptions = richTextRenderOptions,
359+ modifier = if (compatibilityDirection != null ) Modifier .fillMaxWidth() else Modifier ,
360+ textDirection = compatibilityDirection.toCompatibilityTextDirection(),
361+ textAlign = compatibilityDirection.toCompatibilityTextAlign(),
318362 )
319363 }
320364
0 commit comments