react-native-enriched-markdown-scaffold 0.7.4-scaffold.8 → 1.0.2-scaffold.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (469) hide show
  1. package/README.md +54 -8
  2. package/ReactNativeEnrichedMarkdown.podspec +82 -73
  3. package/android/build.gradle +191 -1
  4. package/android/consumer-rules.pro +1 -1
  5. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +9 -0
  6. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +3 -0
  7. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerDelegate.java +27 -0
  8. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +9 -0
  9. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +9 -0
  10. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +3 -0
  11. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
  12. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
  13. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +40 -0
  14. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +839 -23
  15. package/android/src/main/baseline-prof.txt +1 -1
  16. package/android/src/main/cpp/jni-adapter.cpp +74 -0
  17. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +175 -11
  18. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +17 -0
  19. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +50 -0
  20. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +48 -1
  21. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager.kt +10 -1
  22. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +42 -0
  23. package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +82 -4
  24. package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyPressEvent.kt +24 -0
  25. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +62 -4
  26. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +911 -460
  27. package/android/src/main/java/com/swmansion/enriched/markdown/input/MarkdownClipboard.kt +42 -0
  28. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/BlockEditCoordinator.kt +196 -0
  29. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/ClipboardCoordinator.kt +73 -0
  30. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditContext.kt +19 -0
  31. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditPipeline.kt +248 -0
  32. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditSession.kt +52 -0
  33. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/InputConnectionWrapper.kt +101 -7
  34. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/LinkCoordinator.kt +69 -0
  35. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MarkdownTextWatcher.kt +3 -3
  36. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MentionCoordinator.kt +118 -0
  37. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeStateEvent.kt +26 -0
  38. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnContextMenuItemPressEvent.kt +26 -0
  39. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnInputKeyPressEvent.kt +24 -0
  40. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnPasteEvent.kt +24 -0
  41. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockStore.kt +254 -0
  42. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockSyntaxSentinel.kt +69 -0
  43. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +80 -87
  44. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputFormatter.kt +109 -1
  45. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +180 -27
  46. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/MarkdownSerializer.kt +167 -38
  47. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/RangeEditAdjustment.kt +149 -0
  48. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputEventEmitter.kt +66 -5
  49. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +7 -2
  50. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockRange.kt +27 -0
  51. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockType.kt +48 -0
  52. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/FormattingRange.kt +9 -4
  53. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/InputFormatterStyle.kt +39 -2
  54. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathAtom.kt +20 -0
  55. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +1 -1
  56. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MutableRangeBounds.kt +11 -0
  57. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputBulletSpan.kt +82 -0
  58. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputHeadingSpan.kt +58 -0
  59. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputListItemSpacingSpan.kt +37 -0
  60. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputOrderedListMarkerSpan.kt +63 -0
  61. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/BlockHandler.kt +54 -0
  62. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/HeadingBlockHandler.kt +27 -0
  63. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/OrderedListBlockHandler.kt +38 -0
  64. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/UnorderedListBlockHandler.kt +37 -0
  65. package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +8 -26
  66. package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +1 -0
  67. package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +1 -0
  68. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +9 -2
  69. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +100 -12
  70. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +16 -1
  71. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +4 -0
  72. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +2 -1
  73. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +74 -18
  74. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +43 -4
  75. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +9 -1
  76. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SoftBreakRenderer.kt +16 -0
  77. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +30 -27
  78. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +24 -0
  79. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +174 -24
  80. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +27 -3
  81. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +13 -16
  82. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +1 -1
  83. package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +1 -1
  84. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +182 -46
  85. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListItemSpacingSpan.kt +33 -0
  86. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListMarkerAnchorSpan.kt +38 -0
  87. package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +2 -0
  88. package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +1 -1
  89. package/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +3 -2
  90. package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +3 -2
  91. package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +6 -0
  92. package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +26 -0
  93. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +7 -1
  94. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +4 -1
  95. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +13 -4
  96. package/android/src/main/java/com/swmansion/enriched/markdown/styles/TableStyle.kt +6 -0
  97. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockHighlighter.kt +90 -0
  98. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockNode.kt +57 -0
  99. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/FeatureFlags.kt +1 -0
  100. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownSegment.kt +9 -0
  101. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +33 -7
  102. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/ReadableMapExtensions.kt +3 -0
  103. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/RenderedSegment.kt +10 -0
  104. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentSignature.kt +1 -0
  105. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/StreamingMarkdownFilter.kt +83 -5
  106. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt +4 -0
  107. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +74 -44
  108. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/PasteTextUtils.kt +20 -0
  109. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageCache.kt +26 -3
  110. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageDownloader.kt +22 -9
  111. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/LocalImageLoader.kt +161 -0
  112. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/TextPaintExtensions.kt +23 -0
  113. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/CheckboxTouchHelper.kt +7 -0
  114. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +41 -21
  115. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/BlockSpacing.kt +15 -8
  116. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLongPressMovementMethod.kt +58 -27
  117. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +19 -2
  118. package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +388 -0
  119. package/android/src/main/java/com/swmansion/enriched/markdown/views/ContextMenuPopup.kt +9 -6
  120. package/android/src/main/java/com/swmansion/enriched/markdown/views/CopyGlyph.kt +101 -0
  121. package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +32 -5
  122. package/android/src/main/jni/CMakeLists.txt +53 -0
  123. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.cpp +10 -0
  124. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.h +11 -2
  125. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +10 -0
  126. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +12 -2
  127. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.cpp +9 -0
  128. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.h +24 -0
  129. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +16 -0
  130. package/android/src/math/java/com/swmansion/enriched/markdown/input/math/MathChipControllerImpl.kt +21 -4
  131. package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +7 -2
  132. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -1
  133. package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +2 -0
  134. package/cpp/highlight/CodeBlockHighlighter.cpp +284 -0
  135. package/cpp/highlight/CodeBlockHighlighter.hpp +66 -0
  136. package/cpp/highlight/CodeBlockLanguages.cpp +138 -0
  137. package/cpp/highlight/CodeBlockLanguages.hpp +25 -0
  138. package/cpp/highlight/HighlightGrammars.hpp +28 -0
  139. package/cpp/highlight/code_highlight_podspec.rb +211 -0
  140. package/cpp/highlight/gen-registry.mjs +155 -0
  141. package/cpp/highlight/grammar-versions.json +159 -0
  142. package/cpp/highlight/vendor/generated/generated_queries.h +1665 -0
  143. package/cpp/highlight/vendor/generated/generated_registry.cpp +59 -0
  144. package/cpp/parser/MD4CParser.cpp +173 -61
  145. package/cpp/parser/MD4CParser.hpp +1 -0
  146. package/cpp/parser/MarkdownASTNode.hpp +2 -1
  147. package/cpp/wasm/ASTSerializer.cpp +2 -0
  148. package/cpp/wasm/build.sh +1 -0
  149. package/cpp/wasm/md4c_wasm.cpp +3 -1
  150. package/docs/ACCESSIBILITY.md +14 -2
  151. package/docs/API_REFERENCE.md +231 -8
  152. package/docs/BREAKING_CHANGES.md +129 -0
  153. package/docs/CODE_HIGHLIGHT.md +133 -0
  154. package/docs/COPY_OPTIONS.md +21 -3
  155. package/docs/ELEMENTS_STRUCTURE.md +52 -4
  156. package/docs/IMAGE_CACHING.md +30 -0
  157. package/docs/INPUT.md +146 -5
  158. package/docs/LATEX_MATH.md +87 -45
  159. package/docs/MACOS.md +1 -1
  160. package/docs/MARKDOWN_STREAMING.md +27 -1
  161. package/docs/NATIVE_ASSETS.md +127 -0
  162. package/docs/RTL.md +1 -1
  163. package/docs/STYLES.md +46 -6
  164. package/docs/TESTING.md +112 -0
  165. package/docs/TEXT.md +16 -6
  166. package/docs/WEB.md +3 -1
  167. package/ios/EnrichedMarkdown.h +7 -0
  168. package/ios/EnrichedMarkdown.mm +262 -67
  169. package/ios/EnrichedMarkdownText.h +7 -0
  170. package/ios/EnrichedMarkdownText.mm +97 -68
  171. package/ios/attachments/ENRMImageAttachment.h +9 -0
  172. package/ios/attachments/ENRMImageAttachment.m +143 -40
  173. package/ios/attachments/ENRMMathInlineAttachment.h +2 -0
  174. package/ios/attachments/ENRMMathInlineAttachment.m +48 -81
  175. package/ios/attachments/ENRMMathInlineAttachmentShared.h +2 -0
  176. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
  177. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
  178. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +40 -0
  179. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +839 -23
  180. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +131 -0
  181. package/ios/input/ENRMAutoLinkDetector.h +2 -1
  182. package/ios/input/ENRMAutoLinkDetector.mm +79 -41
  183. package/ios/input/ENRMBlockEditCoordinator.h +71 -0
  184. package/ios/input/ENRMBlockEditCoordinator.mm +195 -0
  185. package/ios/input/ENRMBlockRange.h +28 -0
  186. package/ios/input/ENRMBlockRange.mm +30 -0
  187. package/ios/input/ENRMBlockStore.h +56 -0
  188. package/ios/input/ENRMBlockStore.mm +275 -0
  189. package/ios/input/ENRMBlockSyntaxSentinel.h +25 -0
  190. package/ios/input/ENRMBlockSyntaxSentinel.mm +80 -0
  191. package/ios/input/ENRMClipboardCoordinator.h +45 -0
  192. package/ios/input/ENRMClipboardCoordinator.mm +120 -0
  193. package/ios/input/ENRMDetectorPipeline.h +2 -1
  194. package/ios/input/ENRMEditPipeline.h +76 -0
  195. package/ios/input/ENRMEditPipeline.mm +228 -0
  196. package/ios/input/ENRMEditSession.h +36 -0
  197. package/ios/input/ENRMEditSession.mm +63 -0
  198. package/ios/input/ENRMFormattingStore.h +17 -0
  199. package/ios/input/ENRMFormattingStore.mm +95 -105
  200. package/ios/input/ENRMInputBlockType.h +91 -0
  201. package/ios/input/ENRMInputBlockType.mm +5 -0
  202. package/ios/input/ENRMInputDecorationDrawer.h +18 -0
  203. package/ios/input/ENRMInputEventEmitter.h +56 -0
  204. package/ios/input/ENRMInputEventEmitter.mm +308 -0
  205. package/ios/input/ENRMInputFormatter.h +29 -69
  206. package/ios/input/ENRMInputFormatter.mm +216 -124
  207. package/ios/input/ENRMInputFormatterStyle.h +99 -0
  208. package/ios/input/ENRMInputFormatterStyle.mm +188 -0
  209. package/ios/input/ENRMInputLayoutManager.h +9 -0
  210. package/ios/input/ENRMInputLayoutManager.mm +30 -0
  211. package/ios/input/ENRMInputListMarkerDrawer.h +32 -0
  212. package/ios/input/ENRMInputListMarkerDrawer.mm +426 -0
  213. package/ios/input/ENRMInputParser.h +10 -6
  214. package/ios/input/ENRMInputParser.mm +527 -171
  215. package/ios/input/ENRMInputRemend.mm +2 -2
  216. package/ios/input/ENRMInputStyleStateBuilder.h +40 -0
  217. package/ios/input/ENRMInputStyleStateBuilder.mm +60 -0
  218. package/ios/input/ENRMInputTextView.mm +103 -8
  219. package/ios/input/ENRMInputTypingAttributesController.h +42 -0
  220. package/ios/input/ENRMInputTypingAttributesController.mm +203 -0
  221. package/ios/input/ENRMLinkCoordinator.h +41 -0
  222. package/ios/input/ENRMLinkCoordinator.mm +89 -0
  223. package/ios/input/ENRMMarkdownSerializer.h +29 -5
  224. package/ios/input/ENRMMarkdownSerializer.mm +170 -48
  225. package/ios/input/ENRMMathAtom.h +26 -0
  226. package/ios/input/ENRMMathAtom.mm +12 -0
  227. package/ios/input/ENRMMentionCoordinator.h +45 -0
  228. package/ios/input/ENRMMentionCoordinator.mm +167 -0
  229. package/ios/input/ENRMRangeEditAdjustment.h +38 -0
  230. package/ios/input/ENRMRangeEditAdjustment.mm +91 -0
  231. package/ios/input/ENRMRangeStoreUtils.h +39 -0
  232. package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +6 -6
  233. package/ios/input/EnrichedMarkdownTextInput+Internal.h +11 -3
  234. package/ios/input/EnrichedMarkdownTextInput.h +7 -1
  235. package/ios/input/EnrichedMarkdownTextInput.mm +1104 -1024
  236. package/ios/input/InputStylePropsUtils.h +109 -68
  237. package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.mm +2 -1
  238. package/ios/input/styles/ENRMBlockHandler.h +46 -0
  239. package/ios/input/styles/ENRMHeadingBlockHandler.h +15 -0
  240. package/ios/input/styles/ENRMHeadingBlockHandler.mm +38 -0
  241. package/ios/input/styles/ENRMOrderedListBlockHandler.h +14 -0
  242. package/ios/input/styles/ENRMOrderedListBlockHandler.mm +48 -0
  243. package/ios/input/styles/ENRMUnorderedListBlockHandler.h +15 -0
  244. package/ios/input/styles/ENRMUnorderedListBlockHandler.mm +51 -0
  245. package/ios/internals/ENRMViewFreeMeasurement.h +331 -0
  246. package/ios/internals/EnrichedMarkdownShadowNode.h +1 -3
  247. package/ios/internals/EnrichedMarkdownShadowNode.mm +16 -20
  248. package/ios/internals/EnrichedMarkdownTextShadowNode.h +1 -3
  249. package/ios/internals/EnrichedMarkdownTextShadowNode.mm +15 -20
  250. package/ios/internals/MeasurementCache.h +33 -7
  251. package/ios/internals/ShadowMeasurementUtils.h +63 -58
  252. package/ios/math/ENRMMathChipController.h +74 -0
  253. package/ios/math/ENRMMathChipController.mm +476 -0
  254. package/ios/math/ENRMRaTeXBridge.swift +4 -1
  255. package/ios/parser/ENRMMarkdownParser.h +1 -8
  256. package/ios/parser/ENRMMarkdownParser.mm +2 -11
  257. package/ios/parser/MarkdownASTNode.h +2 -1
  258. package/ios/parser/MarkdownParserBridge.mm +4 -0
  259. package/ios/renderer/AttributedRenderer.m +20 -2
  260. package/ios/renderer/BaseRenderer.h +17 -2
  261. package/ios/renderer/BaseRenderer.m +30 -0
  262. package/ios/renderer/BlockquoteRenderer.h +1 -1
  263. package/ios/renderer/BlockquoteRenderer.m +144 -35
  264. package/ios/renderer/CodeBlockRenderer.h +1 -1
  265. package/ios/renderer/CodeBlockRenderer.m +27 -23
  266. package/ios/renderer/CodeRenderer.h +1 -1
  267. package/ios/renderer/CodeRenderer.m +3 -1
  268. package/ios/renderer/ENRMImageRenderer.h +1 -1
  269. package/ios/renderer/ENRMImageRenderer.m +5 -1
  270. package/ios/renderer/ENRMMathInlineRenderer.h +1 -1
  271. package/ios/renderer/ENRMMathInlineRenderer.m +5 -1
  272. package/ios/renderer/ENRMSpoilerRenderer.h +1 -1
  273. package/ios/renderer/ENRMSpoilerRenderer.m +3 -1
  274. package/ios/renderer/EmphasisRenderer.h +1 -1
  275. package/ios/renderer/EmphasisRenderer.m +3 -1
  276. package/ios/renderer/HeadingRenderer.h +1 -1
  277. package/ios/renderer/HeadingRenderer.m +13 -6
  278. package/ios/renderer/HighlightRenderer.h +1 -1
  279. package/ios/renderer/HighlightRenderer.m +3 -1
  280. package/ios/renderer/LinkRenderer.h +1 -1
  281. package/ios/renderer/LinkRenderer.m +3 -1
  282. package/ios/renderer/ListItemRenderer.h +13 -1
  283. package/ios/renderer/ListItemRenderer.m +102 -44
  284. package/ios/renderer/ListRenderer.h +2 -2
  285. package/ios/renderer/ListRenderer.m +63 -25
  286. package/ios/renderer/ParagraphRenderer.h +1 -1
  287. package/ios/renderer/ParagraphRenderer.m +16 -8
  288. package/ios/renderer/RenderContext.h +10 -0
  289. package/ios/renderer/RenderContext.m +44 -0
  290. package/ios/renderer/RendererFactory.m +14 -0
  291. package/ios/renderer/StrikethroughRenderer.h +1 -1
  292. package/ios/renderer/StrikethroughRenderer.m +3 -1
  293. package/ios/renderer/StrongRenderer.h +1 -1
  294. package/ios/renderer/StrongRenderer.m +3 -1
  295. package/ios/renderer/SubscriptRenderer.h +1 -1
  296. package/ios/renderer/SubscriptRenderer.m +3 -1
  297. package/ios/renderer/SuperscriptRenderer.h +1 -1
  298. package/ios/renderer/SuperscriptRenderer.m +3 -1
  299. package/ios/renderer/TextRenderer.h +2 -2
  300. package/ios/renderer/TextRenderer.m +3 -1
  301. package/ios/renderer/ThematicBreakRenderer.h +1 -1
  302. package/ios/renderer/ThematicBreakRenderer.m +3 -1
  303. package/ios/renderer/UnderlineRenderer.h +1 -1
  304. package/ios/renderer/UnderlineRenderer.m +3 -1
  305. package/ios/styles/StyleConfig.h +22 -0
  306. package/ios/styles/StyleConfig.mm +132 -0
  307. package/ios/utils/BlockquoteBorder.h +6 -0
  308. package/ios/utils/BlockquoteBorder.m +249 -52
  309. package/ios/utils/CodeBlockBackground.m +16 -2
  310. package/ios/utils/ENRMAtomicSize.h +65 -0
  311. package/ios/utils/ENRMCodeBlockContent.h +37 -0
  312. package/ios/utils/ENRMCodeBlockContent.mm +79 -0
  313. package/ios/utils/ENRMCodeBlockHighlighter.h +37 -0
  314. package/ios/utils/ENRMCodeBlockHighlighter.mm +51 -0
  315. package/ios/utils/ENRMFeatureFlags.h +7 -0
  316. package/ios/utils/ENRMImageDownloader.h +11 -1
  317. package/ios/utils/ENRMImageDownloader.m +60 -16
  318. package/ios/utils/ENRMLocalImageLoader.h +31 -0
  319. package/ios/utils/ENRMLocalImageLoader.m +68 -0
  320. package/ios/utils/ENRMMathFallback.h +26 -0
  321. package/ios/utils/ENRMMathFallback.m +18 -0
  322. package/ios/utils/ENRMTextViewSetup.h +35 -17
  323. package/ios/utils/EditMenuUtils.m +22 -1
  324. package/ios/utils/ImageRequestHeaderUtils.h +35 -0
  325. package/ios/utils/LastElementUtils.h +1 -0
  326. package/ios/utils/ListMarkerDrawer.m +29 -42
  327. package/ios/utils/MarkdownASTSerializer.m +4 -0
  328. package/ios/utils/ParagraphStyleUtils.h +5 -0
  329. package/ios/utils/ParagraphStyleUtils.m +77 -17
  330. package/ios/utils/RenderedMarkdownSegment.h +13 -1
  331. package/ios/utils/RenderedMarkdownSegment.m +20 -0
  332. package/ios/utils/SegmentRenderer.m +17 -4
  333. package/ios/utils/StreamingMarkdownFilter.h +11 -1
  334. package/ios/utils/StreamingMarkdownFilter.m +98 -2
  335. package/ios/utils/StylePropsUtils.h +63 -0
  336. package/ios/utils/TaskListTapUtils.m +24 -0
  337. package/ios/views/ENRMCodeBlockContainerView.h +46 -0
  338. package/ios/views/ENRMCodeBlockContainerView.m +566 -0
  339. package/ios/views/ENRMMathContainerView.h +12 -0
  340. package/ios/views/ENRMMathContainerView.m +71 -1
  341. package/ios/views/TableContainerView.h +18 -0
  342. package/ios/views/TableContainerView.m +259 -159
  343. package/jest.d.ts +1 -0
  344. package/jest.js +5 -0
  345. package/lib/module/EnrichedMarkdownNativeComponent.ts +65 -0
  346. package/lib/module/EnrichedMarkdownTextInput.js +86 -5
  347. package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
  348. package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +89 -5
  349. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +66 -0
  350. package/lib/module/headingDefaults.js +34 -0
  351. package/lib/module/headingDefaults.js.map +1 -0
  352. package/lib/module/index.js.map +1 -1
  353. package/lib/module/jest/index.js +191 -0
  354. package/lib/module/jest/index.js.map +1 -0
  355. package/lib/module/native/EnrichedMarkdownText.js +30 -4
  356. package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
  357. package/lib/module/normalizeMarkdownStyle.js +81 -19
  358. package/lib/module/normalizeMarkdownStyle.js.map +1 -1
  359. package/lib/module/normalizeMarkdownStyle.web.js +56 -18
  360. package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
  361. package/lib/module/normalizeMarkdownTextInputStyle.js +62 -15
  362. package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
  363. package/lib/module/normalizeMenuItem.js +1 -1
  364. package/lib/module/utils/textInputState.js +26 -0
  365. package/lib/module/utils/textInputState.js.map +1 -0
  366. package/lib/module/web/EnrichedMarkdownText.js +9 -5
  367. package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
  368. package/lib/module/web/parseMarkdown.js +4 -3
  369. package/lib/module/web/parseMarkdown.js.map +1 -1
  370. package/lib/module/web/renderers/InlineRenderers.js +6 -0
  371. package/lib/module/web/renderers/InlineRenderers.js.map +1 -1
  372. package/lib/module/web/renderers/ListRenderers.js +7 -2
  373. package/lib/module/web/renderers/ListRenderers.js.map +1 -1
  374. package/lib/module/web/renderers/index.js +7 -4
  375. package/lib/module/web/renderers/index.js.map +1 -1
  376. package/lib/module/web/styles.js +83 -6
  377. package/lib/module/web/styles.js.map +1 -1
  378. package/lib/module/web/utils.js +1 -0
  379. package/lib/module/web/utils.js.map +1 -1
  380. package/lib/module/web/wasm/md4c.js +0 -0
  381. package/lib/module/web/wasm/md4c.js.map +1 -1
  382. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +62 -0
  383. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
  384. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +95 -9
  385. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
  386. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +80 -5
  387. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
  388. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +62 -0
  389. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
  390. package/lib/typescript/src/headingDefaults.d.ts +9 -0
  391. package/lib/typescript/src/headingDefaults.d.ts.map +1 -0
  392. package/lib/typescript/src/index.d.ts +2 -2
  393. package/lib/typescript/src/index.d.ts.map +1 -1
  394. package/lib/typescript/src/index.web.d.ts +1 -1
  395. package/lib/typescript/src/index.web.d.ts.map +1 -1
  396. package/lib/typescript/src/jest/index.d.ts +6 -0
  397. package/lib/typescript/src/jest/index.d.ts.map +1 -0
  398. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +3 -3
  399. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
  400. package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
  401. package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
  402. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +19 -5
  403. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
  404. package/lib/typescript/src/types/MarkdownStyle.d.ts +72 -0
  405. package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
  406. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +27 -0
  407. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
  408. package/lib/typescript/src/types/MarkdownTextProps.d.ts +65 -1
  409. package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
  410. package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +19 -0
  411. package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
  412. package/lib/typescript/src/types/events.d.ts +19 -0
  413. package/lib/typescript/src/types/events.d.ts.map +1 -1
  414. package/lib/typescript/src/utils/textInputState.d.ts +24 -0
  415. package/lib/typescript/src/utils/textInputState.d.ts.map +1 -0
  416. package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +1 -1
  417. package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -1
  418. package/lib/typescript/src/web/parseMarkdown.d.ts +1 -1
  419. package/lib/typescript/src/web/parseMarkdown.d.ts.map +1 -1
  420. package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -1
  421. package/lib/typescript/src/web/renderers/ListRenderers.d.ts.map +1 -1
  422. package/lib/typescript/src/web/renderers/index.d.ts +2 -1
  423. package/lib/typescript/src/web/renderers/index.d.ts.map +1 -1
  424. package/lib/typescript/src/web/styles.d.ts +2 -1
  425. package/lib/typescript/src/web/styles.d.ts.map +1 -1
  426. package/lib/typescript/src/web/types.d.ts +6 -2
  427. package/lib/typescript/src/web/types.d.ts.map +1 -1
  428. package/lib/typescript/src/web/utils.d.ts.map +1 -1
  429. package/package.json +36 -9
  430. package/postinstall.mjs +131 -0
  431. package/ratex-version.json +21 -0
  432. package/src/EnrichedMarkdownNativeComponent.ts +65 -0
  433. package/src/EnrichedMarkdownTextInput.tsx +162 -8
  434. package/src/EnrichedMarkdownTextInputNativeComponent.ts +89 -5
  435. package/src/EnrichedMarkdownTextNativeComponent.ts +66 -0
  436. package/src/headingDefaults.ts +21 -0
  437. package/src/index.tsx +9 -0
  438. package/src/index.web.tsx +1 -0
  439. package/src/jest/index.tsx +215 -0
  440. package/src/native/EnrichedMarkdownText.tsx +40 -2
  441. package/src/normalizeMarkdownStyle.ts +102 -16
  442. package/src/normalizeMarkdownStyle.web.ts +63 -15
  443. package/src/normalizeMarkdownTextInputStyle.ts +110 -35
  444. package/src/normalizeMenuItem.ts +1 -1
  445. package/src/types/MarkdownStyle.ts +74 -0
  446. package/src/types/MarkdownStyleInternal.ts +39 -0
  447. package/src/types/MarkdownTextProps.ts +65 -0
  448. package/src/types/MarkdownTextProps.web.ts +19 -0
  449. package/src/types/events.ts +21 -0
  450. package/src/utils/textInputState.ts +35 -0
  451. package/src/web/EnrichedMarkdownText.tsx +16 -2
  452. package/src/web/parseMarkdown.ts +6 -2
  453. package/src/web/renderers/InlineRenderers.tsx +5 -0
  454. package/src/web/renderers/ListRenderers.tsx +14 -2
  455. package/src/web/renderers/index.tsx +6 -2
  456. package/src/web/styles.ts +89 -5
  457. package/src/web/types.ts +6 -1
  458. package/src/web/utils.ts +1 -0
  459. package/src/web/wasm/md4c.js +0 -0
  460. package/vendor-grammars.mjs +511 -0
  461. package/vendor-ratex.mjs +173 -0
  462. package/app.plugin.js +0 -2
  463. package/plugin/build/withAndroidMath.js +0 -19
  464. package/plugin/build/withIosMath.js +0 -28
  465. package/plugin/build/withReactNativeEnrichedMarkdown.js +0 -11
  466. package/plugin/src/withAndroidMath.ts +0 -24
  467. package/plugin/src/withIosMath.ts +0 -35
  468. package/plugin/src/withReactNativeEnrichedMarkdown.ts +0 -17
  469. package/plugin/tsconfig.build.json +0 -16
@@ -1,4 +1,4 @@
1
- # Baseline Profile for react-native-enriched-markdown
1
+ # Baseline Profile for react-native-enriched-markdown-scaffold
2
2
  # These classes will be AOT compiled during app install
3
3
  # to improve cold start performance.
4
4
 
@@ -1,7 +1,10 @@
1
+ #include "CodeBlockHighlighter.hpp"
2
+ #include "CodeBlockLanguages.hpp"
1
3
  #include "MD4CParser.hpp"
2
4
  #include <android/log.h>
3
5
  #include <jni.h>
4
6
  #include <string>
7
+ #include <vector>
5
8
 
6
9
  using namespace Markdown;
7
10
 
@@ -72,6 +75,8 @@ static jint nodeTypeToJavaOrdinal(NodeType type) {
72
75
  return 28;
73
76
  case NodeType::Highlight:
74
77
  return 29;
78
+ case NodeType::SoftBreak:
79
+ return 30;
75
80
  default:
76
81
  return 0;
77
82
  }
@@ -228,6 +233,10 @@ JNIEXPORT jobject JNICALL Java_com_swmansion_enriched_markdown_parser_Parser_nat
228
233
  if (permissiveAutolinksField) {
229
234
  md4cFlags.permissiveAutolinks = env->GetBooleanField(flags, permissiveAutolinksField) == JNI_TRUE;
230
235
  }
236
+ jfieldID hardSoftBreaksField = env->GetFieldID(flagsClass, "hardSoftBreaks", "Z");
237
+ if (hardSoftBreaksField) {
238
+ md4cFlags.hardSoftBreaks = env->GetBooleanField(flags, hardSoftBreaksField) == JNI_TRUE;
239
+ }
231
240
  env->DeleteLocalRef(flagsClass);
232
241
  }
233
242
  }
@@ -261,4 +270,69 @@ JNIEXPORT jobject JNICALL Java_com_swmansion_enriched_markdown_parser_Parser_nat
261
270
  }
262
271
  }
263
272
 
273
+ JNIEXPORT jstring JNICALL Java_com_swmansion_enriched_markdown_utils_common_CodeBlockNode_nativeDisplayLanguageName(
274
+ JNIEnv *env, jobject /* this */, jstring language) {
275
+ if (!language) {
276
+ return nullptr;
277
+ }
278
+ const char *languageStr = env->GetStringUTFChars(language, nullptr);
279
+ if (!languageStr) {
280
+ return nullptr;
281
+ }
282
+ std::string display = displayNameForLanguage(languageStr);
283
+ env->ReleaseStringUTFChars(language, languageStr);
284
+ return env->NewStringUTF(display.c_str());
285
+ }
286
+
287
+ // Returns highlight tokens as (start, end, type) int triplets with UTF-16
288
+ // offsets, or null when highlighting is unavailable. See
289
+ // cpp/highlight/CodeBlockHighlighter.hpp for the seam contract.
290
+ JNIEXPORT jintArray JNICALL Java_com_swmansion_enriched_markdown_utils_common_CodeBlockHighlighter_nativeHighlightCode(
291
+ JNIEnv *env, jobject /* this */, jstring code, jstring language) {
292
+ if (!code) {
293
+ return nullptr;
294
+ }
295
+
296
+ const char *codeStr = env->GetStringUTFChars(code, nullptr);
297
+ if (!codeStr) {
298
+ return nullptr;
299
+ }
300
+ const char *languageStr = language ? env->GetStringUTFChars(language, nullptr) : nullptr;
301
+
302
+ std::vector<HighlightToken> tokens;
303
+ try {
304
+ tokens = highlightCode(codeStr, languageStr ? languageStr : "");
305
+ } catch (const std::exception &e) {
306
+ LOGE("Exception during highlighting: %s", e.what());
307
+ tokens.clear();
308
+ } catch (...) {
309
+ LOGE("Unknown exception during highlighting");
310
+ tokens.clear();
311
+ }
312
+
313
+ env->ReleaseStringUTFChars(code, codeStr);
314
+ if (languageStr) {
315
+ env->ReleaseStringUTFChars(language, languageStr);
316
+ }
317
+
318
+ if (tokens.empty()) {
319
+ return nullptr;
320
+ }
321
+
322
+ std::vector<jint> flat;
323
+ flat.reserve(tokens.size() * 3);
324
+ for (const auto &token : tokens) {
325
+ flat.push_back(static_cast<jint>(token.start));
326
+ flat.push_back(static_cast<jint>(token.end));
327
+ flat.push_back(static_cast<jint>(token.type));
328
+ }
329
+
330
+ jintArray result = env->NewIntArray(static_cast<jsize>(flat.size()));
331
+ if (!result) {
332
+ return nullptr;
333
+ }
334
+ env->SetIntArrayRegion(result, 0, static_cast<jsize>(flat.size()), flat.data());
335
+ return result;
336
+ }
337
+
264
338
  } // extern "C"
@@ -9,13 +9,16 @@ import android.util.AttributeSet
9
9
  import android.util.Log
10
10
  import android.view.View
11
11
  import android.widget.FrameLayout
12
+ import com.facebook.react.bridge.Arguments
12
13
  import com.facebook.react.bridge.ReadableMap
14
+ import com.facebook.react.uimanager.StateWrapper
13
15
  import com.swmansion.enriched.markdown.accessibility.AccessibilityLabels
14
16
  import com.swmansion.enriched.markdown.parser.Md4cFlags
15
17
  import com.swmansion.enriched.markdown.parser.Parser
16
18
  import com.swmansion.enriched.markdown.spoiler.SpoilerOverlay
17
19
  import com.swmansion.enriched.markdown.styles.StyleConfig
18
20
  import com.swmansion.enriched.markdown.utils.common.BreakStrategyUtils
21
+ import com.swmansion.enriched.markdown.utils.common.CodeBlockStreamingMode
19
22
  import com.swmansion.enriched.markdown.utils.common.FeatureFlags
20
23
  import com.swmansion.enriched.markdown.utils.common.MarkdownSegmentRenderer
21
24
  import com.swmansion.enriched.markdown.utils.common.RenderedSegment
@@ -28,10 +31,13 @@ import com.swmansion.enriched.markdown.utils.text.TailFadeInAnimator
28
31
  import com.swmansion.enriched.markdown.utils.text.view.SelectionMenuConfig
29
32
  import com.swmansion.enriched.markdown.utils.text.view.applySelectionColors
30
33
  import com.swmansion.enriched.markdown.views.BlockSegmentView
34
+ import com.swmansion.enriched.markdown.views.CodeBlockContainerView
31
35
  import com.swmansion.enriched.markdown.views.TableContainerView
32
36
  import java.util.EnumSet
33
37
  import java.util.concurrent.ExecutorService
34
38
  import java.util.concurrent.Executors
39
+ import kotlin.math.ceil
40
+ import kotlin.math.max
35
41
 
36
42
  class EnrichedMarkdown
37
43
  @JvmOverloads
@@ -62,7 +68,12 @@ class EnrichedMarkdown
62
68
  private val dirtyFlags = EnumSet.noneOf(DirtyFlag::class.java)
63
69
  var streamingAnimation: Boolean = false
64
70
 
71
+ // used to force a Yoga re-measure when a block image resolves its box height
72
+ var stateWrapper: StateWrapper? = null
73
+ private var forceHeightRecalculationCounter = 0
74
+
65
75
  var tableStreamingMode: TableStreamingMode = TableStreamingMode.PROGRESSIVE
76
+ var codeBlockStreamingMode: CodeBlockStreamingMode = CodeBlockStreamingMode.PROGRESSIVE
66
77
  private var renderPending: Boolean = false
67
78
 
68
79
  var currentMarkdown: String = ""
@@ -79,7 +90,9 @@ class EnrichedMarkdown
79
90
  private var allowFontScaling: Boolean = true
80
91
  private var maxFontSizeMultiplier: Float = 0f
81
92
  private var allowTrailingMargin: Boolean = false
93
+ private var imageRequestHeaders: Map<String, String> = emptyMap()
82
94
  private var selectable: Boolean = true
95
+ private var contextMenuHidden: Boolean = false
83
96
  private var selectionColor: Int? = null
84
97
  private var selectionHandleColor: Int? = null
85
98
  private var selectionMenuConfig = SelectionMenuConfig()
@@ -89,6 +102,7 @@ class EnrichedMarkdown
89
102
  private var onLinkPressCallback: ((String) -> Unit)? = null
90
103
  private var onLinkLongPressCallback: ((String) -> Unit)? = null
91
104
  private var onTaskListItemPressCallback: ((Int, Boolean, String) -> Unit)? = null
105
+ private var onCopyPressCallback: ((String, String) -> Unit)? = null
92
106
  private var contextMenuItemTexts: List<String> = emptyList()
93
107
  var onContextMenuItemPressCallback: ((itemText: String, selectedText: String, selectionStart: Int, selectionEnd: Int) -> Unit)? = null
94
108
  var spoilerOverlay: SpoilerOverlay = SpoilerOverlay.PARTICLES
@@ -99,6 +113,14 @@ class EnrichedMarkdown
99
113
  it.spoilerOverlay = value
100
114
  }
101
115
  }
116
+ var enableTaskListItemToggle: Boolean = true
117
+ set(value) {
118
+ if (field == value) return
119
+ field = value
120
+ segmentViews.filterIsInstance<EnrichedMarkdownInternalText>().forEach {
121
+ it.enableTaskListItemToggle = value
122
+ }
123
+ }
102
124
 
103
125
  fun setMarkdownContent(markdown: String) {
104
126
  if (currentMarkdown == markdown) return
@@ -109,6 +131,7 @@ class EnrichedMarkdown
109
131
  fun setMarkdownStyle(style: ReadableMap?) {
110
132
  markdownStyleMap = style
111
133
  val newConfig = style?.let { StyleConfig(it, context, allowFontScaling, maxFontSizeMultiplier) }
134
+ newConfig?.imageRequestHeaders = imageRequestHeaders
112
135
  if (markdownStyle == newConfig) return
113
136
  markdownStyle = newConfig
114
137
  dirtyFlags += DirtyFlag.RECREATE_SEGMENTS
@@ -116,8 +139,18 @@ class EnrichedMarkdown
116
139
  renderPending = true
117
140
  }
118
141
 
142
+ fun setImageRequestHeaders(headers: Map<String, String>) {
143
+ if (imageRequestHeaders == headers) return
144
+ imageRequestHeaders = headers
145
+ markdownStyle?.imageRequestHeaders = headers
146
+ dirtyFlags += DirtyFlag.RECREATE_SEGMENTS
147
+ renderPending = true
148
+ }
149
+
119
150
  fun commitProps() {
120
151
  MeasurementStore.updateStreamingTableMode(id, tableStreamingMode)
152
+ MeasurementStore.updateStreamingCodeBlockMode(id, codeBlockStreamingMode)
153
+ MeasurementStore.updateFontScalingSettings(id, allowFontScaling, maxFontSizeMultiplier)
121
154
  if (renderPending) {
122
155
  renderPending = false
123
156
  scheduleRenderIfNeeded()
@@ -146,6 +179,7 @@ class EnrichedMarkdown
146
179
  fun setAllowFontScaling(allow: Boolean) {
147
180
  if (allowFontScaling == allow) return
148
181
  allowFontScaling = allow
182
+ MeasurementStore.updateFontScalingSettings(id, allowFontScaling, maxFontSizeMultiplier)
149
183
  recreateStyleConfig()
150
184
  dirtyFlags += DirtyFlag.RECREATE_SEGMENTS
151
185
  dirtyFlags += DirtyFlag.FORCE_HEIGHT
@@ -155,6 +189,7 @@ class EnrichedMarkdown
155
189
  fun setMaxFontSizeMultiplier(multiplier: Float) {
156
190
  if (maxFontSizeMultiplier == multiplier) return
157
191
  maxFontSizeMultiplier = multiplier
192
+ MeasurementStore.updateFontScalingSettings(id, allowFontScaling, maxFontSizeMultiplier)
158
193
  recreateStyleConfig()
159
194
  dirtyFlags += DirtyFlag.RECREATE_SEGMENTS
160
195
  dirtyFlags += DirtyFlag.FORCE_HEIGHT
@@ -177,6 +212,42 @@ class EnrichedMarkdown
177
212
  }
178
213
  }
179
214
 
215
+ fun setContextMenuHidden(value: Boolean) {
216
+ if (contextMenuHidden == value) return
217
+ contextMenuHidden = value
218
+ applyContextMenuHiddenToSegments()
219
+ }
220
+
221
+ /**
222
+ * Fans the flag out to every segment that owns a copy menu: text segments
223
+ * (floating ActionMode toolbar), tables, code blocks and math blocks (all use
224
+ * their own long-press popup, so none is covered by the ActionMode callback).
225
+ */
226
+ private fun applyContextMenuHiddenToSegments() {
227
+ segmentViews.forEach { view ->
228
+ when {
229
+ view is EnrichedMarkdownInternalText -> view.contextMenuHidden = contextMenuHidden
230
+ view is TableContainerView -> view.contextMenuHidden = contextMenuHidden
231
+ view is CodeBlockContainerView -> view.contextMenuHidden = contextMenuHidden
232
+ isMathContainerView(view) -> setMathContextMenuHidden(view)
233
+ }
234
+ }
235
+ }
236
+
237
+ /**
238
+ * MathContainerView lives in the optional `math` source set, so it is only
239
+ * reachable reflectively. The Kotlin `var` compiles to a setter taking a
240
+ * primitive boolean — `Boolean::class.java` would resolve to
241
+ * `java.lang.Boolean` and silently miss.
242
+ */
243
+ private fun setMathContextMenuHidden(view: View) {
244
+ runCatching {
245
+ view.javaClass
246
+ .getMethod("setContextMenuHidden", Boolean::class.javaPrimitiveType)
247
+ .invoke(view, contextMenuHidden)
248
+ }.onFailure { Log.e(TAG, "Failed to set contextMenuHidden on math view", it) }
249
+ }
250
+
180
251
  fun setSelectionColor(color: Int?) {
181
252
  if (selectionColor == color) return
182
253
  selectionColor = color
@@ -221,6 +292,10 @@ class EnrichedMarkdown
221
292
  onTaskListItemPressCallback = callback
222
293
  }
223
294
 
295
+ fun setOnCopyPressCallback(callback: ((code: String, language: String) -> Unit)?) {
296
+ onCopyPressCallback = callback
297
+ }
298
+
224
299
  fun setContextMenuItems(items: List<String>) {
225
300
  contextMenuItemTexts = items
226
301
  segmentViews.filterIsInstance<EnrichedMarkdownInternalText>().forEach {
@@ -249,6 +324,11 @@ class EnrichedMarkdown
249
324
  view.copyAsMarkdownLabel = copyAsMarkdownLabel
250
325
  }
251
326
 
327
+ view is CodeBlockContainerView -> {
328
+ view.copyLabel = copyLabel
329
+ view.copyAsMarkdownLabel = copyAsMarkdownLabel
330
+ }
331
+
252
332
  isMathContainerView(view) -> {
253
333
  runCatching {
254
334
  view.javaClass.getMethod("setCopyLabel", String::class.java).invoke(view, copyLabel)
@@ -292,7 +372,10 @@ class EnrichedMarkdown
292
372
 
293
373
  private fun recreateStyleConfig() {
294
374
  markdownStyleMap?.let {
295
- markdownStyle = StyleConfig(it, context, allowFontScaling, maxFontSizeMultiplier)
375
+ markdownStyle =
376
+ StyleConfig(it, context, allowFontScaling, maxFontSizeMultiplier).also { config ->
377
+ config.imageRequestHeaders = imageRequestHeaders
378
+ }
296
379
  }
297
380
  }
298
381
 
@@ -305,26 +388,29 @@ class EnrichedMarkdown
305
388
  val markdown = currentMarkdown.takeIf { it.isNotEmpty() } ?: return
306
389
  val isStreaming = streamingAnimation
307
390
  val tableMode = tableStreamingMode
391
+ val codeBlockMode = codeBlockStreamingMode
308
392
 
309
393
  val renderId = ++currentRenderId
310
394
 
311
395
  executor.execute {
312
396
  try {
313
- val renderableMarkdown =
397
+ val filtered =
314
398
  if (isStreaming) {
315
- StreamingMarkdownFilter.renderableMarkdownForStreaming(markdown, tableMode)
399
+ StreamingMarkdownFilter.renderableMarkdownForStreaming(markdown, tableMode, codeBlockMode)
316
400
  } else {
317
- markdown
401
+ null
318
402
  }
403
+ val renderableMarkdown = filtered?.markdown ?: markdown
404
+ val hasPendingCodeBlock = filtered?.endsInsideOpenCodeFence ?: false
319
405
 
320
406
  if (renderableMarkdown.isEmpty()) {
321
- postToMain(renderId) { applyRenderedSegments(emptyList(), style) }
407
+ postToMain(renderId) { applyRenderedSegments(emptyList(), style, false) }
322
408
  return@execute
323
409
  }
324
410
 
325
411
  val ast =
326
412
  parser.parseMarkdown(renderableMarkdown, md4cFlags) ?: run {
327
- postToMain(renderId) { applyRenderedSegments(emptyList(), style) }
413
+ postToMain(renderId) { applyRenderedSegments(emptyList(), style, false) }
328
414
  return@execute
329
415
  }
330
416
 
@@ -338,18 +424,25 @@ class EnrichedMarkdown
338
424
  onLinkLongPressCallback,
339
425
  )
340
426
 
341
- postToMain(renderId) { applyRenderedSegments(renderedSegments, style) }
427
+ postToMain(renderId) { applyRenderedSegments(renderedSegments, style, hasPendingCodeBlock) }
342
428
  } catch (e: Exception) {
343
429
  Log.e(TAG, "Render failed", e)
344
- postToMain(renderId) { applyRenderedSegments(emptyList(), style) }
430
+ postToMain(renderId) { applyRenderedSegments(emptyList(), style, false) }
345
431
  }
346
432
  }
347
433
  }
348
434
 
435
+ // Trailing code block whose closing fence hasn't streamed in yet, if any.
436
+ private var pendingCodeBlockSegment: RenderedSegment.CodeBlock? = null
437
+
349
438
  private fun applyRenderedSegments(
350
439
  renderedSegments: List<RenderedSegment>,
351
440
  style: StyleConfig,
441
+ hasPendingCodeBlock: Boolean,
352
442
  ) {
443
+ pendingCodeBlockSegment =
444
+ if (hasPendingCodeBlock) renderedSegments.lastOrNull() as? RenderedSegment.CodeBlock else null
445
+
353
446
  val reset = DirtyFlag.RECREATE_SEGMENTS in dirtyFlags
354
447
  val forceHeight = DirtyFlag.FORCE_HEIGHT in dirtyFlags
355
448
  dirtyFlags.clear()
@@ -377,6 +470,14 @@ class EnrichedMarkdown
377
470
  segmentSignatures.clear()
378
471
  segmentSignatures.addAll(result.signatures)
379
472
 
473
+ // A just-closed block has unchanged content, so the reconciler reuses it
474
+ // without an update; sync pending here to trigger its deferred highlight.
475
+ segmentViews.forEachIndexed { index, view ->
476
+ if (view is CodeBlockContainerView) {
477
+ view.pending = pendingCodeBlockSegment != null && index == segmentViews.size - 1
478
+ }
479
+ }
480
+
380
481
  val topologyChanged = result.viewsToAttach.isNotEmpty() || result.viewsToRemove.isNotEmpty()
381
482
 
382
483
  if (width > 0) {
@@ -399,6 +500,7 @@ class EnrichedMarkdown
399
500
  is RenderedSegment.Text -> view is EnrichedMarkdownInternalText
400
501
  is RenderedSegment.Table -> view is TableContainerView
401
502
  is RenderedSegment.Math -> isMathContainerView(view)
503
+ is RenderedSegment.CodeBlock -> view is CodeBlockContainerView
402
504
  }
403
505
 
404
506
  private fun isMathContainerView(view: View): Boolean = mathContainerClass?.isInstance(view) == true
@@ -411,6 +513,7 @@ class EnrichedMarkdown
411
513
  is RenderedSegment.Text -> createTextView(segment)
412
514
  is RenderedSegment.Table -> createTableView(segment, style)
413
515
  is RenderedSegment.Math -> createMathView(segment, style)
516
+ is RenderedSegment.CodeBlock -> createCodeBlockView(segment, style)
414
517
  }
415
518
 
416
519
  private fun updateSegmentView(
@@ -441,6 +544,13 @@ class EnrichedMarkdown
441
544
  ?.getMethod("applyLatex", String::class.java)
442
545
  ?.invoke(view, segment.latex)
443
546
  }
547
+
548
+ is RenderedSegment.CodeBlock -> {
549
+ (view as CodeBlockContainerView).apply {
550
+ pending = segment === pendingCodeBlockSegment
551
+ applyCodeBlockNode(segment.node)
552
+ }
553
+ }
444
554
  }
445
555
  }
446
556
 
@@ -451,7 +561,7 @@ class EnrichedMarkdown
451
561
  if (!streamingAnimation) return
452
562
  when (segment) {
453
563
  is RenderedSegment.Text -> animateTextViewTail(view as EnrichedMarkdownInternalText, 0)
454
- is RenderedSegment.Table, is RenderedSegment.Math -> animateBlockViewFadeIn(view)
564
+ is RenderedSegment.Table, is RenderedSegment.Math, is RenderedSegment.CodeBlock -> animateBlockViewFadeIn(view)
455
565
  }
456
566
  }
457
567
 
@@ -479,9 +589,12 @@ class EnrichedMarkdown
479
589
  private fun createTextView(segment: RenderedSegment.Text) =
480
590
  EnrichedMarkdownInternalText(context).apply {
481
591
  spoilerOverlay = this@EnrichedMarkdown.spoilerOverlay
592
+ enableTaskListItemToggle = this@EnrichedMarkdown.enableTaskListItemToggle
482
593
  selectionMenuConfig = this@EnrichedMarkdown.selectionMenuConfig
594
+ contextMenuHidden = this@EnrichedMarkdown.contextMenuHidden
483
595
  accessibilityLabels = this@EnrichedMarkdown.accessibilityLabels
484
596
  setIsSelectable(selectable)
597
+ markdownStyle?.paragraphStyle?.fontSize?.let { setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, it) }
485
598
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
486
599
  breakStrategy = BreakStrategyUtils.resolveBreakStrategy(textBreakStrategy)
487
600
  }
@@ -514,9 +627,24 @@ class EnrichedMarkdown
514
627
  onLinkLongPress = onLinkLongPressCallback
515
628
  copyLabel = this@EnrichedMarkdown.selectionMenuConfig.copyLabel
516
629
  copyAsMarkdownLabel = this@EnrichedMarkdown.selectionMenuConfig.copyAsMarkdownLabel
630
+ contextMenuHidden = this@EnrichedMarkdown.contextMenuHidden
517
631
  applyTableNode(segment.node)
518
632
  }
519
633
 
634
+ private fun createCodeBlockView(
635
+ segment: RenderedSegment.CodeBlock,
636
+ style: StyleConfig,
637
+ ) = CodeBlockContainerView(context, style).apply {
638
+ copyLabel = this@EnrichedMarkdown.selectionMenuConfig.copyLabel
639
+ copyAsMarkdownLabel = this@EnrichedMarkdown.selectionMenuConfig.copyAsMarkdownLabel
640
+ contextMenuHidden = this@EnrichedMarkdown.contextMenuHidden
641
+ onCopyPress = { code, language ->
642
+ this@EnrichedMarkdown.onCopyPressCallback?.invoke(code, language)
643
+ }
644
+ pending = segment === pendingCodeBlockSegment
645
+ applyCodeBlockNode(segment.node)
646
+ }
647
+
520
648
  private fun createMathView(
521
649
  segment: RenderedSegment.Math,
522
650
  style: StyleConfig,
@@ -539,6 +667,7 @@ class EnrichedMarkdown
539
667
  resolvedClass
540
668
  .getMethod("setCopyAsMarkdownLabel", String::class.java)
541
669
  .invoke(view, selectionMenuConfig.copyAsMarkdownLabel)
670
+ setMathContextMenuHidden(view)
542
671
  resolvedClass.getMethod("applyLatex", String::class.java).invoke(view, segment.latex)
543
672
  view
544
673
  } catch (e: Exception) {
@@ -566,10 +695,31 @@ class EnrichedMarkdown
566
695
  layoutSegments()
567
696
  }
568
697
 
698
+ fun onImageLayoutChanged() {
699
+ if (width > 0) {
700
+ layoutSegments()
701
+ requestLayout()
702
+ }
703
+ MeasurementStore.invalidate(id)
704
+ val wrapper = stateWrapper ?: return
705
+ val state = Arguments.createMap()
706
+ state.putInt("forceHeightRecalculationCounter", ++forceHeightRecalculationCounter)
707
+ wrapper.updateState(state)
708
+ }
709
+
569
710
  private fun layoutSegments() {
570
711
  val containerWidth = width
571
712
  if (containerWidth <= 0) return
572
713
 
714
+ val needsOverhang =
715
+ segmentViews.any { view ->
716
+ view is TableContainerView &&
717
+ ceil(view.tableStyle.horizontalOverflow.toDouble()).toInt() > 0
718
+ }
719
+ if (clipChildren == needsOverhang) {
720
+ clipChildren = !needsOverhang
721
+ }
722
+
573
723
  var currentY = 0
574
724
  val lastIndex = segmentViews.lastIndex
575
725
  val widthSpec = MeasureSpec.makeMeasureSpec(containerWidth, MeasureSpec.EXACTLY)
@@ -580,9 +730,23 @@ class EnrichedMarkdown
580
730
  val shouldAddBottomMargin = index != lastIndex || allowTrailingMargin
581
731
 
582
732
  currentY += segment?.segmentMarginTop ?: 0
583
- view.measure(widthSpec, heightSpec)
584
733
 
585
- view.layout(0, currentY, containerWidth, currentY + view.measuredHeight)
734
+ val overhang =
735
+ if (view is TableContainerView) {
736
+ max(ceil(view.tableStyle.horizontalOverflow.toDouble()).toInt(), 0)
737
+ } else {
738
+ 0
739
+ }
740
+
741
+ if (overhang > 0) {
742
+ val extendedWidth = containerWidth + overhang * 2
743
+ val extWidthSpec = MeasureSpec.makeMeasureSpec(extendedWidth, MeasureSpec.EXACTLY)
744
+ view.measure(extWidthSpec, heightSpec)
745
+ view.layout(-overhang, currentY, containerWidth + overhang, currentY + view.measuredHeight)
746
+ } else {
747
+ view.measure(widthSpec, heightSpec)
748
+ view.layout(0, currentY, containerWidth, currentY + view.measuredHeight)
749
+ }
586
750
  currentY += view.measuredHeight
587
751
 
588
752
  if (shouldAddBottomMargin) {
@@ -5,6 +5,7 @@ import android.graphics.Canvas
5
5
  import android.os.Build
6
6
  import android.text.Layout
7
7
  import android.util.AttributeSet
8
+ import android.view.ActionMode
8
9
  import android.view.MotionEvent
9
10
  import com.swmansion.enriched.markdown.accessibility.AccessibilityLabels
10
11
  import com.swmansion.enriched.markdown.accessibility.AccessibleMarkdownTextView
@@ -41,6 +42,12 @@ class EnrichedMarkdownInternalText
41
42
  checkboxTouchHelper.onCheckboxTap = value
42
43
  }
43
44
 
45
+ var enableTaskListItemToggle: Boolean
46
+ get() = checkboxTouchHelper.isEnabled
47
+ set(value) {
48
+ checkboxTouchHelper.isEnabled = value
49
+ }
50
+
44
51
  override val segmentMarginBottom: Int get() = lastElementMarginBottom.toInt()
45
52
 
46
53
  override var spoilerOverlayDrawer: SpoilerOverlayDrawer? = null
@@ -49,6 +56,14 @@ class EnrichedMarkdownInternalText
49
56
  private var contextMenuItemTexts: List<String> = emptyList()
50
57
  private var onContextMenuItemPress: ((itemText: String, selectedText: String, selectionStart: Int, selectionEnd: Int) -> Unit)? = null
51
58
  var selectionMenuConfig: SelectionMenuConfig = SelectionMenuConfig()
59
+ private var activeActionMode: ActionMode? = null
60
+ var contextMenuHidden: Boolean = false
61
+ set(value) {
62
+ if (field == value) return
63
+ field = value
64
+ // See EnrichedMarkdownText.setContextMenuHidden.
65
+ activeActionMode?.invalidate()
66
+ }
52
67
  var accessibilityLabels: AccessibilityLabels = AccessibilityLabels()
53
68
  set(value) {
54
69
  field = value
@@ -62,6 +77,8 @@ class EnrichedMarkdownInternalText
62
77
  this,
63
78
  getCustomItemTexts = { contextMenuItemTexts },
64
79
  getSelectionMenuConfig = { selectionMenuConfig },
80
+ isContextMenuHidden = { contextMenuHidden },
81
+ onActionModeChanged = { activeActionMode = it },
65
82
  onCustomItemPress = { itemText, selectedText, start, end ->
66
83
  onContextMenuItemPress?.invoke(itemText, selectedText, start, end)
67
84
  },
@@ -4,7 +4,9 @@ import android.content.Context
4
4
  import com.facebook.react.bridge.ReadableArray
5
5
  import com.facebook.react.bridge.ReadableMap
6
6
  import com.facebook.react.module.annotations.ReactModule
7
+ import com.facebook.react.uimanager.ReactStylesDiffMap
7
8
  import com.facebook.react.uimanager.SimpleViewManager
9
+ import com.facebook.react.uimanager.StateWrapper
8
10
  import com.facebook.react.uimanager.ThemedReactContext
9
11
  import com.facebook.react.uimanager.ViewManagerDelegate
10
12
  import com.facebook.react.uimanager.annotations.ReactProp
@@ -12,14 +14,17 @@ import com.facebook.react.viewmanagers.EnrichedMarkdownManagerDelegate
12
14
  import com.facebook.react.viewmanagers.EnrichedMarkdownManagerInterface
13
15
  import com.facebook.yoga.YogaMeasureMode
14
16
  import com.swmansion.enriched.markdown.spoiler.SpoilerOverlay
17
+ import com.swmansion.enriched.markdown.utils.common.CodeBlockStreamingMode
15
18
  import com.swmansion.enriched.markdown.utils.common.TableStreamingMode
16
19
  import com.swmansion.enriched.markdown.utils.common.emitContextMenuItemPress
20
+ import com.swmansion.enriched.markdown.utils.common.emitCopyPress
17
21
  import com.swmansion.enriched.markdown.utils.common.emitLinkLongPress
18
22
  import com.swmansion.enriched.markdown.utils.common.emitLinkPress
19
23
  import com.swmansion.enriched.markdown.utils.common.emitTaskListItemPress
20
24
  import com.swmansion.enriched.markdown.utils.common.markdownEventTypeConstants
21
25
  import com.swmansion.enriched.markdown.utils.common.parseAccessibilityLabels
22
26
  import com.swmansion.enriched.markdown.utils.common.parseContextMenuItems
27
+ import com.swmansion.enriched.markdown.utils.common.parseImageRequestHeaders
23
28
  import com.swmansion.enriched.markdown.utils.common.parseMd4cFlags
24
29
  import com.swmansion.enriched.markdown.utils.common.parseSelectionMenuConfig
25
30
  import com.swmansion.enriched.markdown.utils.text.interaction.TaskListToggleUtils
@@ -56,6 +61,10 @@ class EnrichedMarkdownManager :
56
61
  emitTaskListItemPress(view, taskIndex, newChecked, itemText)
57
62
  }
58
63
 
64
+ view.setOnCopyPressCallback { code, language ->
65
+ emitCopyPress(view, code, language)
66
+ }
67
+
59
68
  return view
60
69
  }
61
70
 
@@ -64,12 +73,23 @@ class EnrichedMarkdownManager :
64
73
  view.commitProps()
65
74
  }
66
75
 
76
+ override fun updateState(
77
+ view: EnrichedMarkdown,
78
+ props: ReactStylesDiffMap?,
79
+ stateWrapper: StateWrapper?,
80
+ ): Any? {
81
+ view.stateWrapper = stateWrapper
82
+ return super.updateState(view, props, stateWrapper)
83
+ }
84
+
67
85
  override fun onDropViewInstance(view: EnrichedMarkdown) {
68
86
  super.onDropViewInstance(view)
69
87
  view.cleanup()
70
88
  MeasurementStore.release(view.id)
71
89
  MeasurementStore.clearStreamingTableMode(view.id)
90
+ MeasurementStore.clearStreamingCodeBlockMode(view.id)
72
91
  MeasurementStore.clearBreakStrategy(view.id)
92
+ MeasurementStore.clearFontScalingSettings(view.id)
73
93
  }
74
94
 
75
95
  override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> = markdownEventTypeConstants()
@@ -144,6 +164,14 @@ class EnrichedMarkdownManager :
144
164
  view?.setAllowTrailingMargin(allowTrailingMargin)
145
165
  }
146
166
 
167
+ @ReactProp(name = "contextMenuHidden", defaultBoolean = false)
168
+ override fun setContextMenuHidden(
169
+ view: EnrichedMarkdown?,
170
+ contextMenuHidden: Boolean,
171
+ ) {
172
+ view?.setContextMenuHidden(contextMenuHidden)
173
+ }
174
+
147
175
  @ReactProp(name = "enableLinkPreview", defaultBoolean = true)
148
176
  override fun setEnableLinkPreview(
149
177
  view: EnrichedMarkdown?,
@@ -152,6 +180,14 @@ class EnrichedMarkdownManager :
152
180
  // No-op on Android — only used on iOS
153
181
  }
154
182
 
183
+ @ReactProp(name = "enableTaskListItemToggle", defaultBoolean = true)
184
+ override fun setEnableTaskListItemToggle(
185
+ view: EnrichedMarkdown?,
186
+ enableTaskListItemToggle: Boolean,
187
+ ) {
188
+ view?.enableTaskListItemToggle = enableTaskListItemToggle
189
+ }
190
+
155
191
  @ReactProp(name = "lineBreakStrategyIOS")
156
192
  override fun setLineBreakStrategyIOS(
157
193
  view: EnrichedMarkdown?,
@@ -188,6 +224,11 @@ class EnrichedMarkdownManager :
188
224
  else -> TableStreamingMode.PROGRESSIVE
189
225
  }
190
226
  view.tableStreamingMode = tableMode
227
+ view.codeBlockStreamingMode =
228
+ when (config?.getString("codeBlockMode")) {
229
+ "hidden" -> CodeBlockStreamingMode.HIDDEN
230
+ else -> CodeBlockStreamingMode.PROGRESSIVE
231
+ }
191
232
  }
192
233
 
193
234
  @ReactProp(name = "spoilerOverlay")
@@ -215,6 +256,15 @@ class EnrichedMarkdownManager :
215
256
  view.setContextMenuItems(parseContextMenuItems(value))
216
257
  }
217
258
 
259
+ @ReactProp(name = "imageRequestHeaders")
260
+ override fun setImageRequestHeaders(
261
+ view: EnrichedMarkdown?,
262
+ value: ReadableArray?,
263
+ ) {
264
+ if (view == null) return
265
+ view.setImageRequestHeaders(parseImageRequestHeaders(value))
266
+ }
267
+
218
268
  @ReactProp(name = "selectionMenuConfig")
219
269
  override fun setSelectionMenuConfig(
220
270
  view: EnrichedMarkdown?,