Repository navigation
fix(android): toggle the tapped task item after a table, code block or quote - #1077
Merged
Merged
Conversation
…r quote In the GitHub flavor each text segment rendered with a fresh Renderer, so task indices restarted at 0 after every table, code block or blockquote, while the toggle rewrites the Nth task of the whole markdown source. Tapping a later task checked an earlier one. Port the library's fix (packages/enriched-markdown-android, #806): Renderer.renderContent takes a startingTaskIndex and reports getTaskItemCount(), and MarkdownSegmentRenderer threads a running taskIndexOffset through its text segments. RN also renders blockquotes as containers, so a Blockquote segment carries its first task index into its own render, and the count continues after it. A segment holding tasks mixes its first index into its signature, so a reused view never keeps stale indices when earlier tasks change. TaskListToggleUtils now also counts tasks behind `>` quote markers and in ordered lists, which the renderer numbers too.
There was a problem hiding this comment.
🟡 Changes recommended
The expanded source matcher still counts non-task text as tasks, causing checkbox taps to modify the wrong source line.
2 open issues
What changed in this PR
This PR fixes Android task-checkbox targeting across text segments separated by tables, code blocks, and blockquotes.
Changes:
- Carries document-wide task indices through rendering and blockquote views.
- Updates segment signatures when earlier tasks change their indices.
- Expands source matching for quoted and ordered tasks and adds regression tests.
| File | Description |
|---|---|
packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/MarkdownRenderTestSupport.kt |
Adds heading styles needed by segment tests. |
packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/segments/TaskIndexAcrossSegmentsTest.kt |
Tests task indexing, signatures, and source toggling. |
packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt |
Matches quoted and ordered task markers. |
packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/SegmentViewCreators.kt |
Passes task offsets to new blockquote views. |
packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/SegmentSignature.kt |
Incorporates task offsets into signatures. |
packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/RenderedSegment.kt |
Tracks task indices across segments. |
packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/BlockquoteContainerView.kt |
Propagates offsets through blockquote rendering and updates. |
packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/Renderer.kt |
Supports starting indices and exposes the task counter. |
packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteTextRenderer.kt |
Forwards starting task indices. |
packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt |
Preserves task offsets when updating blockquotes. |
Review effort: Balanced
| // A task item's line: any blockquote markers (`>`), then a bullet or ordered-list marker, then | ||
| // the checkbox. It must find every task the renderer numbers, in document order, or | ||
| // [toggleAtIndex] rewrites a different item than the one tapped. | ||
| private val TASK_PATTERN = Regex("""^((?:[ \t]*>)*[ \t]*(?:[-*+]|\d{1,9}[.)])[ \t]+)\[[ xX]]""", RegexOption.MULTILINE) |
| // A task item's line: any blockquote markers (`>`), then a bullet or ordered-list marker, then | ||
| // the checkbox. It must find every task the renderer numbers, in document order, or | ||
| // [toggleAtIndex] rewrites a different item than the one tapped. | ||
| private val TASK_PATTERN = Regex("""^((?:[ \t]*>)*[ \t]*(?:[-*+]|\d{1,9}[.)])[ \t]+)\[[ xX]]""", RegexOption.MULTILINE) |
jnowakow
marked this pull request as ready for review
October 27, 2026 11:17
maksg
approved these changes
Oct 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

What/Why?
In the GitHub flavor, tapping a task checkbox after a table, code block or blockquote toggled the wrong item. Each text segment (and each blockquote container) numbered its tasks from 0, so the tap toggled the Nth task of the whole document with a per-segment index.
startingTaskIndex/getTaskItemCount(), ported fromenriched-markdown-android). Blockquote containers get their starting index too.toggleAtIndexnow also counts tasks behind>and ordered tasks (1. [ ]), so its Nth task matches the renderer's.Known gaps, not changed here.
toggleAtIndexscans the source, so it still counts two kinds of lines the parser doesn't treat as tasks:- [ ]lines inside fenced code blocks.2. [ ]on the line after text. The parser doesn't allow it to interrupt the paragraph.iOS has the same per-segment restart.
Testing
Playground, "Reference links: Off" (GitHub flavor), Set Raw Markdown:
Tap each checkbox after the table. Before: it toggles "one" or "two". After: it toggles the tapped item.
PR Checklist