react-native-enriched-markdown-scaffold 0.7.4-scaffold.9 → 1.0.2-scaffold.2

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 +186 -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 +24 -0
  8. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +8 -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 +35 -0
  14. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +886 -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 +189 -13
  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 +54 -4
  26. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +901 -462
  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/FormattingStore.kt +80 -87
  43. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputFormatter.kt +109 -1
  44. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +116 -22
  45. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/MarkdownSerializer.kt +167 -38
  46. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/RangeEditAdjustment.kt +149 -0
  47. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputEventEmitter.kt +66 -5
  48. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +4 -2
  49. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockRange.kt +27 -0
  50. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockType.kt +48 -0
  51. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/FormattingRange.kt +9 -4
  52. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/InputFormatterStyle.kt +39 -2
  53. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathAtom.kt +20 -0
  54. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +1 -1
  55. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MutableRangeBounds.kt +11 -0
  56. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputBulletSpan.kt +82 -0
  57. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputHeadingSpan.kt +58 -0
  58. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputListItemSpacingSpan.kt +37 -0
  59. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputOrderedListMarkerSpan.kt +63 -0
  60. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/BlockHandler.kt +54 -0
  61. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/HeadingBlockHandler.kt +27 -0
  62. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/OrderedListBlockHandler.kt +38 -0
  63. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/UnorderedListBlockHandler.kt +37 -0
  64. package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +8 -26
  65. package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +1 -0
  66. package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +1 -0
  67. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +9 -2
  68. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +100 -12
  69. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +16 -1
  70. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +4 -0
  71. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +2 -1
  72. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +74 -18
  73. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +43 -4
  74. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +9 -1
  75. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SoftBreakRenderer.kt +16 -0
  76. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +30 -27
  77. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +24 -0
  78. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +174 -24
  79. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +27 -3
  80. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +13 -16
  81. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +1 -1
  82. package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +1 -1
  83. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +182 -46
  84. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListItemSpacingSpan.kt +33 -0
  85. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListMarkerAnchorSpan.kt +38 -0
  86. package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +2 -0
  87. package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +1 -1
  88. package/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +3 -2
  89. package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +3 -2
  90. package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +6 -0
  91. package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +26 -0
  92. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +7 -1
  93. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +4 -1
  94. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +13 -4
  95. package/android/src/main/java/com/swmansion/enriched/markdown/styles/TableStyle.kt +6 -0
  96. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockHighlighter.kt +90 -0
  97. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockNode.kt +57 -0
  98. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/FeatureFlags.kt +1 -0
  99. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownSegment.kt +9 -0
  100. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +37 -7
  101. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/ReadableMapExtensions.kt +3 -0
  102. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/RenderedSegment.kt +10 -0
  103. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentSignature.kt +1 -0
  104. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/StreamingMarkdownFilter.kt +83 -5
  105. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt +4 -0
  106. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +74 -44
  107. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/PasteTextUtils.kt +20 -0
  108. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageCache.kt +26 -3
  109. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageDownloader.kt +22 -9
  110. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/LocalImageLoader.kt +161 -0
  111. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/TextPaintExtensions.kt +23 -0
  112. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/CheckboxTouchHelper.kt +7 -0
  113. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +41 -21
  114. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/BlockSpacing.kt +15 -8
  115. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLongPressMovementMethod.kt +58 -27
  116. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +49 -15
  117. package/android/src/main/java/com/swmansion/enriched/markdown/views/BlockMenuOptions.kt +45 -0
  118. package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +396 -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 +36 -9
  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 +6 -4
  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 +234 -12
  152. package/docs/BREAKING_CHANGES.md +129 -0
  153. package/docs/CODE_HIGHLIGHT.md +133 -0
  154. package/docs/COPY_OPTIONS.md +47 -3
  155. package/docs/ELEMENTS_STRUCTURE.md +52 -4
  156. package/docs/IMAGE_CACHING.md +30 -0
  157. package/docs/INPUT.md +108 -11
  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 +284 -75
  169. package/ios/EnrichedMarkdownText.h +7 -0
  170. package/ios/EnrichedMarkdownText.mm +101 -73
  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 +35 -0
  179. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +886 -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/ENRMClipboardCoordinator.h +45 -0
  190. package/ios/input/ENRMClipboardCoordinator.mm +120 -0
  191. package/ios/input/ENRMDetectorPipeline.h +2 -1
  192. package/ios/input/ENRMEditPipeline.h +76 -0
  193. package/ios/input/ENRMEditPipeline.mm +228 -0
  194. package/ios/input/ENRMEditSession.h +36 -0
  195. package/ios/input/ENRMEditSession.mm +63 -0
  196. package/ios/input/ENRMFormattingStore.h +17 -0
  197. package/ios/input/ENRMFormattingStore.mm +95 -105
  198. package/ios/input/ENRMInputBlockType.h +91 -0
  199. package/ios/input/ENRMInputBlockType.mm +5 -0
  200. package/ios/input/ENRMInputDecorationDrawer.h +18 -0
  201. package/ios/input/ENRMInputEventEmitter.h +56 -0
  202. package/ios/input/ENRMInputEventEmitter.mm +308 -0
  203. package/ios/input/ENRMInputFormatter.h +29 -69
  204. package/ios/input/ENRMInputFormatter.mm +216 -124
  205. package/ios/input/ENRMInputFormatterStyle.h +99 -0
  206. package/ios/input/ENRMInputFormatterStyle.mm +188 -0
  207. package/ios/input/ENRMInputLayoutManager.h +9 -0
  208. package/ios/input/ENRMInputLayoutManager.mm +30 -0
  209. package/ios/input/ENRMInputListMarkerDrawer.h +32 -0
  210. package/ios/input/ENRMInputListMarkerDrawer.mm +426 -0
  211. package/ios/input/ENRMInputParser.h +5 -6
  212. package/ios/input/ENRMInputParser.mm +461 -178
  213. package/ios/input/ENRMInputRemend.mm +2 -2
  214. package/ios/input/ENRMInputStyleStateBuilder.h +40 -0
  215. package/ios/input/ENRMInputStyleStateBuilder.mm +60 -0
  216. package/ios/input/ENRMInputTextView.mm +103 -8
  217. package/ios/input/ENRMInputTypingAttributesController.h +42 -0
  218. package/ios/input/ENRMInputTypingAttributesController.mm +203 -0
  219. package/ios/input/ENRMLinkCoordinator.h +41 -0
  220. package/ios/input/ENRMLinkCoordinator.mm +89 -0
  221. package/ios/input/ENRMMarkdownSerializer.h +29 -5
  222. package/ios/input/ENRMMarkdownSerializer.mm +170 -48
  223. package/ios/input/ENRMMathAtom.h +26 -0
  224. package/ios/input/ENRMMathAtom.mm +12 -0
  225. package/ios/input/ENRMMentionCoordinator.h +45 -0
  226. package/ios/input/ENRMMentionCoordinator.mm +167 -0
  227. package/ios/input/ENRMRangeEditAdjustment.h +38 -0
  228. package/ios/input/ENRMRangeEditAdjustment.mm +91 -0
  229. package/ios/input/ENRMRangeStoreUtils.h +39 -0
  230. package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +6 -6
  231. package/ios/input/EnrichedMarkdownTextInput+Internal.h +11 -3
  232. package/ios/input/EnrichedMarkdownTextInput.h +7 -1
  233. package/ios/input/EnrichedMarkdownTextInput.mm +1089 -1023
  234. package/ios/input/InputStylePropsUtils.h +109 -68
  235. package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.mm +2 -1
  236. package/ios/input/styles/ENRMBlockHandler.h +46 -0
  237. package/ios/input/styles/ENRMHeadingBlockHandler.h +15 -0
  238. package/ios/input/styles/ENRMHeadingBlockHandler.mm +38 -0
  239. package/ios/input/styles/ENRMOrderedListBlockHandler.h +14 -0
  240. package/ios/input/styles/ENRMOrderedListBlockHandler.mm +48 -0
  241. package/ios/input/styles/ENRMUnorderedListBlockHandler.h +15 -0
  242. package/ios/input/styles/ENRMUnorderedListBlockHandler.mm +51 -0
  243. package/ios/internals/ENRMViewFreeMeasurement.h +331 -0
  244. package/ios/internals/EnrichedMarkdownShadowNode.h +1 -3
  245. package/ios/internals/EnrichedMarkdownShadowNode.mm +16 -20
  246. package/ios/internals/EnrichedMarkdownTextShadowNode.h +1 -3
  247. package/ios/internals/EnrichedMarkdownTextShadowNode.mm +15 -20
  248. package/ios/internals/MeasurementCache.h +33 -7
  249. package/ios/internals/ShadowMeasurementUtils.h +63 -58
  250. package/ios/math/ENRMMathChipController.h +74 -0
  251. package/ios/math/ENRMMathChipController.mm +476 -0
  252. package/ios/math/ENRMRaTeXBridge.swift +4 -1
  253. package/ios/parser/ENRMMarkdownParser.h +1 -8
  254. package/ios/parser/ENRMMarkdownParser.mm +2 -11
  255. package/ios/parser/MarkdownASTNode.h +2 -1
  256. package/ios/parser/MarkdownParserBridge.mm +4 -0
  257. package/ios/renderer/AttributedRenderer.m +20 -2
  258. package/ios/renderer/BaseRenderer.h +17 -2
  259. package/ios/renderer/BaseRenderer.m +30 -0
  260. package/ios/renderer/BlockquoteRenderer.h +1 -1
  261. package/ios/renderer/BlockquoteRenderer.m +144 -35
  262. package/ios/renderer/CodeBlockRenderer.h +1 -1
  263. package/ios/renderer/CodeBlockRenderer.m +27 -23
  264. package/ios/renderer/CodeRenderer.h +1 -1
  265. package/ios/renderer/CodeRenderer.m +3 -1
  266. package/ios/renderer/ENRMImageRenderer.h +1 -1
  267. package/ios/renderer/ENRMImageRenderer.m +5 -1
  268. package/ios/renderer/ENRMMathInlineRenderer.h +1 -1
  269. package/ios/renderer/ENRMMathInlineRenderer.m +5 -1
  270. package/ios/renderer/ENRMSpoilerRenderer.h +1 -1
  271. package/ios/renderer/ENRMSpoilerRenderer.m +3 -1
  272. package/ios/renderer/EmphasisRenderer.h +1 -1
  273. package/ios/renderer/EmphasisRenderer.m +3 -1
  274. package/ios/renderer/HeadingRenderer.h +1 -1
  275. package/ios/renderer/HeadingRenderer.m +13 -6
  276. package/ios/renderer/HighlightRenderer.h +1 -1
  277. package/ios/renderer/HighlightRenderer.m +3 -1
  278. package/ios/renderer/LinkRenderer.h +1 -1
  279. package/ios/renderer/LinkRenderer.m +3 -1
  280. package/ios/renderer/ListItemRenderer.h +13 -1
  281. package/ios/renderer/ListItemRenderer.m +102 -44
  282. package/ios/renderer/ListRenderer.h +2 -2
  283. package/ios/renderer/ListRenderer.m +63 -25
  284. package/ios/renderer/ParagraphRenderer.h +1 -1
  285. package/ios/renderer/ParagraphRenderer.m +16 -8
  286. package/ios/renderer/RenderContext.h +10 -0
  287. package/ios/renderer/RenderContext.m +44 -0
  288. package/ios/renderer/RendererFactory.m +14 -0
  289. package/ios/renderer/StrikethroughRenderer.h +1 -1
  290. package/ios/renderer/StrikethroughRenderer.m +3 -1
  291. package/ios/renderer/StrongRenderer.h +1 -1
  292. package/ios/renderer/StrongRenderer.m +3 -1
  293. package/ios/renderer/SubscriptRenderer.h +1 -1
  294. package/ios/renderer/SubscriptRenderer.m +3 -1
  295. package/ios/renderer/SuperscriptRenderer.h +1 -1
  296. package/ios/renderer/SuperscriptRenderer.m +3 -1
  297. package/ios/renderer/TextRenderer.h +2 -2
  298. package/ios/renderer/TextRenderer.m +3 -1
  299. package/ios/renderer/ThematicBreakRenderer.h +1 -1
  300. package/ios/renderer/ThematicBreakRenderer.m +3 -1
  301. package/ios/renderer/UnderlineRenderer.h +1 -1
  302. package/ios/renderer/UnderlineRenderer.m +3 -1
  303. package/ios/styles/StyleConfig.h +22 -0
  304. package/ios/styles/StyleConfig.mm +132 -0
  305. package/ios/utils/BlockquoteBorder.h +6 -0
  306. package/ios/utils/BlockquoteBorder.m +249 -52
  307. package/ios/utils/CodeBlockBackground.m +16 -2
  308. package/ios/utils/ENRMAtomicSize.h +65 -0
  309. package/ios/utils/ENRMBlockMenu.h +57 -0
  310. package/ios/utils/ENRMCodeBlockContent.h +37 -0
  311. package/ios/utils/ENRMCodeBlockContent.mm +79 -0
  312. package/ios/utils/ENRMCodeBlockHighlighter.h +37 -0
  313. package/ios/utils/ENRMCodeBlockHighlighter.mm +51 -0
  314. package/ios/utils/ENRMFeatureFlags.h +7 -0
  315. package/ios/utils/ENRMImageDownloader.h +11 -1
  316. package/ios/utils/ENRMImageDownloader.m +60 -16
  317. package/ios/utils/ENRMLocalImageLoader.h +31 -0
  318. package/ios/utils/ENRMLocalImageLoader.m +68 -0
  319. package/ios/utils/ENRMMathFallback.h +26 -0
  320. package/ios/utils/ENRMMathFallback.m +18 -0
  321. package/ios/utils/ENRMTextViewSetup.h +35 -17
  322. package/ios/utils/EditMenuUtils.h +22 -5
  323. package/ios/utils/EditMenuUtils.m +53 -9
  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 +53 -0
  338. package/ios/views/ENRMCodeBlockContainerView.m +559 -0
  339. package/ios/views/ENRMMathContainerView.h +16 -0
  340. package/ios/views/ENRMMathContainerView.m +74 -19
  341. package/ios/views/TableContainerView.h +22 -0
  342. package/ios/views/TableContainerView.m +261 -175
  343. package/jest.d.ts +1 -0
  344. package/jest.js +5 -0
  345. package/lib/module/EnrichedMarkdownNativeComponent.ts +73 -0
  346. package/lib/module/EnrichedMarkdownTextInput.js +84 -5
  347. package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
  348. package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
  349. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +74 -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 +37 -5
  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 +66 -0
  383. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
  384. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +94 -9
  385. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
  386. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +69 -5
  387. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
  388. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +66 -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 +104 -9
  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 +73 -0
  433. package/src/EnrichedMarkdownTextInput.tsx +159 -8
  434. package/src/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
  435. package/src/EnrichedMarkdownTextNativeComponent.ts +74 -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 +53 -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 +101 -9
  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
@@ -27,11 +30,15 @@ import com.swmansion.enriched.markdown.utils.common.splitASTIntoSegments
27
30
  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
33
+ import com.swmansion.enriched.markdown.views.BlockMenuOptions
30
34
  import com.swmansion.enriched.markdown.views.BlockSegmentView
35
+ import com.swmansion.enriched.markdown.views.CodeBlockContainerView
31
36
  import com.swmansion.enriched.markdown.views.TableContainerView
32
37
  import java.util.EnumSet
33
38
  import java.util.concurrent.ExecutorService
34
39
  import java.util.concurrent.Executors
40
+ import kotlin.math.ceil
41
+ import kotlin.math.max
35
42
 
36
43
  class EnrichedMarkdown
37
44
  @JvmOverloads
@@ -62,7 +69,12 @@ class EnrichedMarkdown
62
69
  private val dirtyFlags = EnumSet.noneOf(DirtyFlag::class.java)
63
70
  var streamingAnimation: Boolean = false
64
71
 
72
+ // used to force a Yoga re-measure when a block image resolves its box height
73
+ var stateWrapper: StateWrapper? = null
74
+ private var forceHeightRecalculationCounter = 0
75
+
65
76
  var tableStreamingMode: TableStreamingMode = TableStreamingMode.PROGRESSIVE
77
+ var codeBlockStreamingMode: CodeBlockStreamingMode = CodeBlockStreamingMode.PROGRESSIVE
66
78
  private var renderPending: Boolean = false
67
79
 
68
80
  var currentMarkdown: String = ""
@@ -79,7 +91,9 @@ class EnrichedMarkdown
79
91
  private var allowFontScaling: Boolean = true
80
92
  private var maxFontSizeMultiplier: Float = 0f
81
93
  private var allowTrailingMargin: Boolean = false
94
+ private var imageRequestHeaders: Map<String, String> = emptyMap()
82
95
  private var selectable: Boolean = true
96
+ private var contextMenuHidden: Boolean = false
83
97
  private var selectionColor: Int? = null
84
98
  private var selectionHandleColor: Int? = null
85
99
  private var selectionMenuConfig = SelectionMenuConfig()
@@ -89,6 +103,7 @@ class EnrichedMarkdown
89
103
  private var onLinkPressCallback: ((String) -> Unit)? = null
90
104
  private var onLinkLongPressCallback: ((String) -> Unit)? = null
91
105
  private var onTaskListItemPressCallback: ((Int, Boolean, String) -> Unit)? = null
106
+ private var onCopyPressCallback: ((String, String) -> Unit)? = null
92
107
  private var contextMenuItemTexts: List<String> = emptyList()
93
108
  var onContextMenuItemPressCallback: ((itemText: String, selectedText: String, selectionStart: Int, selectionEnd: Int) -> Unit)? = null
94
109
  var spoilerOverlay: SpoilerOverlay = SpoilerOverlay.PARTICLES
@@ -99,6 +114,14 @@ class EnrichedMarkdown
99
114
  it.spoilerOverlay = value
100
115
  }
101
116
  }
117
+ var enableTaskListItemToggle: Boolean = true
118
+ set(value) {
119
+ if (field == value) return
120
+ field = value
121
+ segmentViews.filterIsInstance<EnrichedMarkdownInternalText>().forEach {
122
+ it.enableTaskListItemToggle = value
123
+ }
124
+ }
102
125
 
103
126
  fun setMarkdownContent(markdown: String) {
104
127
  if (currentMarkdown == markdown) return
@@ -109,6 +132,7 @@ class EnrichedMarkdown
109
132
  fun setMarkdownStyle(style: ReadableMap?) {
110
133
  markdownStyleMap = style
111
134
  val newConfig = style?.let { StyleConfig(it, context, allowFontScaling, maxFontSizeMultiplier) }
135
+ newConfig?.imageRequestHeaders = imageRequestHeaders
112
136
  if (markdownStyle == newConfig) return
113
137
  markdownStyle = newConfig
114
138
  dirtyFlags += DirtyFlag.RECREATE_SEGMENTS
@@ -116,8 +140,18 @@ class EnrichedMarkdown
116
140
  renderPending = true
117
141
  }
118
142
 
143
+ fun setImageRequestHeaders(headers: Map<String, String>) {
144
+ if (imageRequestHeaders == headers) return
145
+ imageRequestHeaders = headers
146
+ markdownStyle?.imageRequestHeaders = headers
147
+ dirtyFlags += DirtyFlag.RECREATE_SEGMENTS
148
+ renderPending = true
149
+ }
150
+
119
151
  fun commitProps() {
120
152
  MeasurementStore.updateStreamingTableMode(id, tableStreamingMode)
153
+ MeasurementStore.updateStreamingCodeBlockMode(id, codeBlockStreamingMode)
154
+ MeasurementStore.updateFontScalingSettings(id, allowFontScaling, maxFontSizeMultiplier)
121
155
  if (renderPending) {
122
156
  renderPending = false
123
157
  scheduleRenderIfNeeded()
@@ -146,6 +180,7 @@ class EnrichedMarkdown
146
180
  fun setAllowFontScaling(allow: Boolean) {
147
181
  if (allowFontScaling == allow) return
148
182
  allowFontScaling = allow
183
+ MeasurementStore.updateFontScalingSettings(id, allowFontScaling, maxFontSizeMultiplier)
149
184
  recreateStyleConfig()
150
185
  dirtyFlags += DirtyFlag.RECREATE_SEGMENTS
151
186
  dirtyFlags += DirtyFlag.FORCE_HEIGHT
@@ -155,6 +190,7 @@ class EnrichedMarkdown
155
190
  fun setMaxFontSizeMultiplier(multiplier: Float) {
156
191
  if (maxFontSizeMultiplier == multiplier) return
157
192
  maxFontSizeMultiplier = multiplier
193
+ MeasurementStore.updateFontScalingSettings(id, allowFontScaling, maxFontSizeMultiplier)
158
194
  recreateStyleConfig()
159
195
  dirtyFlags += DirtyFlag.RECREATE_SEGMENTS
160
196
  dirtyFlags += DirtyFlag.FORCE_HEIGHT
@@ -177,6 +213,42 @@ class EnrichedMarkdown
177
213
  }
178
214
  }
179
215
 
216
+ fun setContextMenuHidden(value: Boolean) {
217
+ if (contextMenuHidden == value) return
218
+ contextMenuHidden = value
219
+ applyContextMenuHiddenToSegments()
220
+ }
221
+
222
+ /**
223
+ * Fans the flag out to every segment that owns a copy menu: text segments
224
+ * (floating ActionMode toolbar), tables, code blocks and math blocks (all use
225
+ * their own long-press popup, so none is covered by the ActionMode callback).
226
+ */
227
+ private fun applyContextMenuHiddenToSegments() {
228
+ segmentViews.forEach { view ->
229
+ when {
230
+ view is EnrichedMarkdownInternalText -> view.contextMenuHidden = contextMenuHidden
231
+ view is TableContainerView -> view.contextMenuHidden = contextMenuHidden
232
+ view is CodeBlockContainerView -> view.contextMenuHidden = contextMenuHidden
233
+ isMathContainerView(view) -> setMathContextMenuHidden(view)
234
+ }
235
+ }
236
+ }
237
+
238
+ /**
239
+ * MathContainerView lives in the optional `math` source set, so it is only
240
+ * reachable reflectively. The Kotlin `var` compiles to a setter taking a
241
+ * primitive boolean — `Boolean::class.java` would resolve to
242
+ * `java.lang.Boolean` and silently miss.
243
+ */
244
+ private fun setMathContextMenuHidden(view: View) {
245
+ runCatching {
246
+ view.javaClass
247
+ .getMethod("setContextMenuHidden", Boolean::class.javaPrimitiveType)
248
+ .invoke(view, contextMenuHidden)
249
+ }.onFailure { Log.e(TAG, "Failed to set contextMenuHidden on math view", it) }
250
+ }
251
+
180
252
  fun setSelectionColor(color: Int?) {
181
253
  if (selectionColor == color) return
182
254
  selectionColor = color
@@ -221,6 +293,10 @@ class EnrichedMarkdown
221
293
  onTaskListItemPressCallback = callback
222
294
  }
223
295
 
296
+ fun setOnCopyPressCallback(callback: ((code: String, language: String) -> Unit)?) {
297
+ onCopyPressCallback = callback
298
+ }
299
+
224
300
  fun setContextMenuItems(items: List<String>) {
225
301
  contextMenuItemTexts = items
226
302
  segmentViews.filterIsInstance<EnrichedMarkdownInternalText>().forEach {
@@ -234,19 +310,27 @@ class EnrichedMarkdown
234
310
  segmentViews.filterIsInstance<EnrichedMarkdownInternalText>().forEach {
235
311
  it.selectionMenuConfig = config
236
312
  }
237
- // Table and math views cache the copy labels, so re-push them on update
238
- // (e.g. a language change without a remount) to avoid stale labels.
313
+ // Block views cache the copy labels and menu options, so re-push them on
314
+ // update (e.g. a language change without a remount) to avoid stale values.
239
315
  pushCopyLabelsToBlockSegments()
240
316
  }
241
317
 
242
318
  private fun pushCopyLabelsToBlockSegments() {
243
319
  val copyLabel = selectionMenuConfig.copyLabel
244
320
  val copyAsMarkdownLabel = selectionMenuConfig.copyAsMarkdownLabel
321
+ val menuOptions = BlockMenuOptions.from(selectionMenuConfig)
245
322
  segmentViews.forEach { view ->
246
323
  when {
247
324
  view is TableContainerView -> {
248
325
  view.copyLabel = copyLabel
249
326
  view.copyAsMarkdownLabel = copyAsMarkdownLabel
327
+ view.menuOptions = menuOptions
328
+ }
329
+
330
+ view is CodeBlockContainerView -> {
331
+ view.copyLabel = copyLabel
332
+ view.copyAsMarkdownLabel = copyAsMarkdownLabel
333
+ view.menuOptions = menuOptions
250
334
  }
251
335
 
252
336
  isMathContainerView(view) -> {
@@ -255,6 +339,9 @@ class EnrichedMarkdown
255
339
  view.javaClass
256
340
  .getMethod("setCopyAsMarkdownLabel", String::class.java)
257
341
  .invoke(view, copyAsMarkdownLabel)
342
+ view.javaClass
343
+ .getMethod("setMenuOptions", BlockMenuOptions::class.java)
344
+ .invoke(view, menuOptions)
258
345
  }
259
346
  }
260
347
  }
@@ -292,7 +379,10 @@ class EnrichedMarkdown
292
379
 
293
380
  private fun recreateStyleConfig() {
294
381
  markdownStyleMap?.let {
295
- markdownStyle = StyleConfig(it, context, allowFontScaling, maxFontSizeMultiplier)
382
+ markdownStyle =
383
+ StyleConfig(it, context, allowFontScaling, maxFontSizeMultiplier).also { config ->
384
+ config.imageRequestHeaders = imageRequestHeaders
385
+ }
296
386
  }
297
387
  }
298
388
 
@@ -305,26 +395,29 @@ class EnrichedMarkdown
305
395
  val markdown = currentMarkdown.takeIf { it.isNotEmpty() } ?: return
306
396
  val isStreaming = streamingAnimation
307
397
  val tableMode = tableStreamingMode
398
+ val codeBlockMode = codeBlockStreamingMode
308
399
 
309
400
  val renderId = ++currentRenderId
310
401
 
311
402
  executor.execute {
312
403
  try {
313
- val renderableMarkdown =
404
+ val filtered =
314
405
  if (isStreaming) {
315
- StreamingMarkdownFilter.renderableMarkdownForStreaming(markdown, tableMode)
406
+ StreamingMarkdownFilter.renderableMarkdownForStreaming(markdown, tableMode, codeBlockMode)
316
407
  } else {
317
- markdown
408
+ null
318
409
  }
410
+ val renderableMarkdown = filtered?.markdown ?: markdown
411
+ val hasPendingCodeBlock = filtered?.endsInsideOpenCodeFence ?: false
319
412
 
320
413
  if (renderableMarkdown.isEmpty()) {
321
- postToMain(renderId) { applyRenderedSegments(emptyList(), style) }
414
+ postToMain(renderId) { applyRenderedSegments(emptyList(), style, false) }
322
415
  return@execute
323
416
  }
324
417
 
325
418
  val ast =
326
419
  parser.parseMarkdown(renderableMarkdown, md4cFlags) ?: run {
327
- postToMain(renderId) { applyRenderedSegments(emptyList(), style) }
420
+ postToMain(renderId) { applyRenderedSegments(emptyList(), style, false) }
328
421
  return@execute
329
422
  }
330
423
 
@@ -338,18 +431,25 @@ class EnrichedMarkdown
338
431
  onLinkLongPressCallback,
339
432
  )
340
433
 
341
- postToMain(renderId) { applyRenderedSegments(renderedSegments, style) }
434
+ postToMain(renderId) { applyRenderedSegments(renderedSegments, style, hasPendingCodeBlock) }
342
435
  } catch (e: Exception) {
343
436
  Log.e(TAG, "Render failed", e)
344
- postToMain(renderId) { applyRenderedSegments(emptyList(), style) }
437
+ postToMain(renderId) { applyRenderedSegments(emptyList(), style, false) }
345
438
  }
346
439
  }
347
440
  }
348
441
 
442
+ // Trailing code block whose closing fence hasn't streamed in yet, if any.
443
+ private var pendingCodeBlockSegment: RenderedSegment.CodeBlock? = null
444
+
349
445
  private fun applyRenderedSegments(
350
446
  renderedSegments: List<RenderedSegment>,
351
447
  style: StyleConfig,
448
+ hasPendingCodeBlock: Boolean,
352
449
  ) {
450
+ pendingCodeBlockSegment =
451
+ if (hasPendingCodeBlock) renderedSegments.lastOrNull() as? RenderedSegment.CodeBlock else null
452
+
353
453
  val reset = DirtyFlag.RECREATE_SEGMENTS in dirtyFlags
354
454
  val forceHeight = DirtyFlag.FORCE_HEIGHT in dirtyFlags
355
455
  dirtyFlags.clear()
@@ -377,6 +477,14 @@ class EnrichedMarkdown
377
477
  segmentSignatures.clear()
378
478
  segmentSignatures.addAll(result.signatures)
379
479
 
480
+ // A just-closed block has unchanged content, so the reconciler reuses it
481
+ // without an update; sync pending here to trigger its deferred highlight.
482
+ segmentViews.forEachIndexed { index, view ->
483
+ if (view is CodeBlockContainerView) {
484
+ view.pending = pendingCodeBlockSegment != null && index == segmentViews.size - 1
485
+ }
486
+ }
487
+
380
488
  val topologyChanged = result.viewsToAttach.isNotEmpty() || result.viewsToRemove.isNotEmpty()
381
489
 
382
490
  if (width > 0) {
@@ -399,6 +507,7 @@ class EnrichedMarkdown
399
507
  is RenderedSegment.Text -> view is EnrichedMarkdownInternalText
400
508
  is RenderedSegment.Table -> view is TableContainerView
401
509
  is RenderedSegment.Math -> isMathContainerView(view)
510
+ is RenderedSegment.CodeBlock -> view is CodeBlockContainerView
402
511
  }
403
512
 
404
513
  private fun isMathContainerView(view: View): Boolean = mathContainerClass?.isInstance(view) == true
@@ -411,6 +520,7 @@ class EnrichedMarkdown
411
520
  is RenderedSegment.Text -> createTextView(segment)
412
521
  is RenderedSegment.Table -> createTableView(segment, style)
413
522
  is RenderedSegment.Math -> createMathView(segment, style)
523
+ is RenderedSegment.CodeBlock -> createCodeBlockView(segment, style)
414
524
  }
415
525
 
416
526
  private fun updateSegmentView(
@@ -441,6 +551,13 @@ class EnrichedMarkdown
441
551
  ?.getMethod("applyLatex", String::class.java)
442
552
  ?.invoke(view, segment.latex)
443
553
  }
554
+
555
+ is RenderedSegment.CodeBlock -> {
556
+ (view as CodeBlockContainerView).apply {
557
+ pending = segment === pendingCodeBlockSegment
558
+ applyCodeBlockNode(segment.node)
559
+ }
560
+ }
444
561
  }
445
562
  }
446
563
 
@@ -451,7 +568,7 @@ class EnrichedMarkdown
451
568
  if (!streamingAnimation) return
452
569
  when (segment) {
453
570
  is RenderedSegment.Text -> animateTextViewTail(view as EnrichedMarkdownInternalText, 0)
454
- is RenderedSegment.Table, is RenderedSegment.Math -> animateBlockViewFadeIn(view)
571
+ is RenderedSegment.Table, is RenderedSegment.Math, is RenderedSegment.CodeBlock -> animateBlockViewFadeIn(view)
455
572
  }
456
573
  }
457
574
 
@@ -479,9 +596,12 @@ class EnrichedMarkdown
479
596
  private fun createTextView(segment: RenderedSegment.Text) =
480
597
  EnrichedMarkdownInternalText(context).apply {
481
598
  spoilerOverlay = this@EnrichedMarkdown.spoilerOverlay
599
+ enableTaskListItemToggle = this@EnrichedMarkdown.enableTaskListItemToggle
482
600
  selectionMenuConfig = this@EnrichedMarkdown.selectionMenuConfig
601
+ contextMenuHidden = this@EnrichedMarkdown.contextMenuHidden
483
602
  accessibilityLabels = this@EnrichedMarkdown.accessibilityLabels
484
603
  setIsSelectable(selectable)
604
+ markdownStyle?.paragraphStyle?.fontSize?.let { setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, it) }
485
605
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
486
606
  breakStrategy = BreakStrategyUtils.resolveBreakStrategy(textBreakStrategy)
487
607
  }
@@ -514,9 +634,26 @@ class EnrichedMarkdown
514
634
  onLinkLongPress = onLinkLongPressCallback
515
635
  copyLabel = this@EnrichedMarkdown.selectionMenuConfig.copyLabel
516
636
  copyAsMarkdownLabel = this@EnrichedMarkdown.selectionMenuConfig.copyAsMarkdownLabel
637
+ contextMenuHidden = this@EnrichedMarkdown.contextMenuHidden
638
+ menuOptions = BlockMenuOptions.from(this@EnrichedMarkdown.selectionMenuConfig)
517
639
  applyTableNode(segment.node)
518
640
  }
519
641
 
642
+ private fun createCodeBlockView(
643
+ segment: RenderedSegment.CodeBlock,
644
+ style: StyleConfig,
645
+ ) = CodeBlockContainerView(context, style).apply {
646
+ copyLabel = this@EnrichedMarkdown.selectionMenuConfig.copyLabel
647
+ copyAsMarkdownLabel = this@EnrichedMarkdown.selectionMenuConfig.copyAsMarkdownLabel
648
+ contextMenuHidden = this@EnrichedMarkdown.contextMenuHidden
649
+ menuOptions = BlockMenuOptions.from(this@EnrichedMarkdown.selectionMenuConfig)
650
+ onCopyPress = { code, language ->
651
+ this@EnrichedMarkdown.onCopyPressCallback?.invoke(code, language)
652
+ }
653
+ pending = segment === pendingCodeBlockSegment
654
+ applyCodeBlockNode(segment.node)
655
+ }
656
+
520
657
  private fun createMathView(
521
658
  segment: RenderedSegment.Math,
522
659
  style: StyleConfig,
@@ -539,6 +676,10 @@ class EnrichedMarkdown
539
676
  resolvedClass
540
677
  .getMethod("setCopyAsMarkdownLabel", String::class.java)
541
678
  .invoke(view, selectionMenuConfig.copyAsMarkdownLabel)
679
+ resolvedClass
680
+ .getMethod("setMenuOptions", BlockMenuOptions::class.java)
681
+ .invoke(view, BlockMenuOptions.from(selectionMenuConfig))
682
+ setMathContextMenuHidden(view)
542
683
  resolvedClass.getMethod("applyLatex", String::class.java).invoke(view, segment.latex)
543
684
  view
544
685
  } catch (e: Exception) {
@@ -566,10 +707,31 @@ class EnrichedMarkdown
566
707
  layoutSegments()
567
708
  }
568
709
 
710
+ fun onImageLayoutChanged() {
711
+ if (width > 0) {
712
+ layoutSegments()
713
+ requestLayout()
714
+ }
715
+ MeasurementStore.invalidate(id)
716
+ val wrapper = stateWrapper ?: return
717
+ val state = Arguments.createMap()
718
+ state.putInt("forceHeightRecalculationCounter", ++forceHeightRecalculationCounter)
719
+ wrapper.updateState(state)
720
+ }
721
+
569
722
  private fun layoutSegments() {
570
723
  val containerWidth = width
571
724
  if (containerWidth <= 0) return
572
725
 
726
+ val needsOverhang =
727
+ segmentViews.any { view ->
728
+ view is TableContainerView &&
729
+ ceil(view.tableStyle.horizontalOverflow.toDouble()).toInt() > 0
730
+ }
731
+ if (clipChildren == needsOverhang) {
732
+ clipChildren = !needsOverhang
733
+ }
734
+
573
735
  var currentY = 0
574
736
  val lastIndex = segmentViews.lastIndex
575
737
  val widthSpec = MeasureSpec.makeMeasureSpec(containerWidth, MeasureSpec.EXACTLY)
@@ -580,9 +742,23 @@ class EnrichedMarkdown
580
742
  val shouldAddBottomMargin = index != lastIndex || allowTrailingMargin
581
743
 
582
744
  currentY += segment?.segmentMarginTop ?: 0
583
- view.measure(widthSpec, heightSpec)
584
745
 
585
- view.layout(0, currentY, containerWidth, currentY + view.measuredHeight)
746
+ val overhang =
747
+ if (view is TableContainerView) {
748
+ max(ceil(view.tableStyle.horizontalOverflow.toDouble()).toInt(), 0)
749
+ } else {
750
+ 0
751
+ }
752
+
753
+ if (overhang > 0) {
754
+ val extendedWidth = containerWidth + overhang * 2
755
+ val extWidthSpec = MeasureSpec.makeMeasureSpec(extendedWidth, MeasureSpec.EXACTLY)
756
+ view.measure(extWidthSpec, heightSpec)
757
+ view.layout(-overhang, currentY, containerWidth + overhang, currentY + view.measuredHeight)
758
+ } else {
759
+ view.measure(widthSpec, heightSpec)
760
+ view.layout(0, currentY, containerWidth, currentY + view.measuredHeight)
761
+ }
586
762
  currentY += view.measuredHeight
587
763
 
588
764
  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
  },