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
@@ -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?,
@@ -9,8 +9,11 @@ import android.os.Looper
9
9
  import android.text.Layout
10
10
  import android.util.AttributeSet
11
11
  import android.util.Log
12
+ import android.util.TypedValue
13
+ import android.view.ActionMode
12
14
  import android.view.MotionEvent
13
15
  import com.facebook.react.bridge.ReadableMap
16
+ import com.facebook.react.uimanager.StateWrapper
14
17
  import com.swmansion.enriched.markdown.accessibility.AccessibilityLabels
15
18
  import com.swmansion.enriched.markdown.accessibility.AccessibleMarkdownTextView
16
19
  import com.swmansion.enriched.markdown.parser.Md4cFlags
@@ -60,6 +63,9 @@ class EnrichedMarkdownText
60
63
 
61
64
  val layoutManager = EnrichedMarkdownTextLayoutManager(this)
62
65
 
66
+ // used to force a Yoga re-measure when a block image resolves its box height
67
+ var stateWrapper: StateWrapper? = null
68
+
63
69
  private var contextMenuItemTexts: List<String> = emptyList()
64
70
  var onContextMenuItemPressCallback: ((itemText: String, selectedText: String, selectionStart: Int, selectionEnd: Int) -> Unit)? = null
65
71
 
@@ -78,6 +84,7 @@ class EnrichedMarkdownText
78
84
  private var allowFontScaling: Boolean = true
79
85
  private var maxFontSizeMultiplier: Float = 0f
80
86
  private var allowTrailingMargin: Boolean = false
87
+ private var imageRequestHeaders: Map<String, String> = emptyMap()
81
88
 
82
89
  private var streamingAnimation: Boolean = false
83
90
  private var previousTextLength: Int = 0
@@ -91,6 +98,8 @@ class EnrichedMarkdownText
91
98
  private var selectionColor: Int? = null
92
99
  private var selectionHandleColor: Int? = null
93
100
  private var selectionMenuConfig = SelectionMenuConfig()
101
+ private var contextMenuHidden = false
102
+ private var activeActionMode: ActionMode? = null
94
103
 
95
104
  init {
96
105
  setupAsMarkdownTextView()
@@ -99,12 +108,23 @@ class EnrichedMarkdownText
99
108
  this,
100
109
  getCustomItemTexts = { contextMenuItemTexts },
101
110
  getSelectionMenuConfig = { selectionMenuConfig },
111
+ isContextMenuHidden = { contextMenuHidden },
112
+ onActionModeChanged = { activeActionMode = it },
102
113
  onCustomItemPress = { itemText, selectedText, start, end ->
103
114
  onContextMenuItemPressCallback?.invoke(itemText, selectedText, start, end)
104
115
  },
105
116
  )
106
117
  }
107
118
 
119
+ fun setContextMenuHidden(hidden: Boolean) {
120
+ if (contextMenuHidden == hidden) return
121
+ contextMenuHidden = hidden
122
+ // Rebuild a toolbar that is already on screen; without this the flip
123
+ // would only take effect on the next selection, leaving a working Copy
124
+ // menu up after the app asked for it to be hidden.
125
+ activeActionMode?.invalidate()
126
+ }
127
+
108
128
  fun setMarkdownContent(markdown: String) {
109
129
  if (currentMarkdown == markdown) return
110
130
  currentMarkdown = markdown
@@ -116,12 +136,20 @@ class EnrichedMarkdownText
116
136
  // Register font scaling settings when style is set (view should have ID by now)
117
137
  updateMeasurementStoreFontScaling()
118
138
  val newStyle = style?.let { StyleConfig(it, context, allowFontScaling, maxFontSizeMultiplier) }
139
+ newStyle?.imageRequestHeaders = imageRequestHeaders
119
140
  if (markdownStyle == newStyle) return
120
141
  markdownStyle = newStyle
121
142
  updateJustificationMode(newStyle)
122
143
  scheduleRender()
123
144
  }
124
145
 
146
+ fun setImageRequestHeaders(headers: Map<String, String>) {
147
+ if (imageRequestHeaders == headers) return
148
+ imageRequestHeaders = headers
149
+ markdownStyle?.imageRequestHeaders = headers
150
+ scheduleRenderIfNeeded()
151
+ }
152
+
125
153
  override fun onConfigurationChanged(newConfig: Configuration) {
126
154
  super.onConfigurationChanged(newConfig)
127
155
 
@@ -177,6 +205,10 @@ class EnrichedMarkdownText
177
205
  }
178
206
  }
179
207
 
208
+ fun commitProps() {
209
+ updateMeasurementStoreFontScaling()
210
+ }
211
+
180
212
  private fun updateMeasurementStoreFontScaling() {
181
213
  MeasurementStore.updateFontScalingSettings(id, allowFontScaling, maxFontSizeMultiplier)
182
214
  }
@@ -189,7 +221,10 @@ class EnrichedMarkdownText
189
221
 
190
222
  private fun recreateStyleConfig() {
191
223
  markdownStyleMap?.let { styleMap ->
192
- markdownStyle = StyleConfig(styleMap, context, allowFontScaling, maxFontSizeMultiplier)
224
+ markdownStyle =
225
+ StyleConfig(styleMap, context, allowFontScaling, maxFontSizeMultiplier).also {
226
+ it.imageRequestHeaders = imageRequestHeaders
227
+ }
193
228
  updateJustificationMode(markdownStyle)
194
229
  }
195
230
  }
@@ -242,6 +277,10 @@ class EnrichedMarkdownText
242
277
  private fun applyRenderedText(styledText: CharSequence) {
243
278
  val tailStart = previousTextLength
244
279
 
280
+ markdownStyle?.paragraphStyle?.fontSize?.let {
281
+ setTextSize(TypedValue.COMPLEX_UNIT_PX, it)
282
+ }
283
+
245
284
  text = styledText
246
285
 
247
286
  if (movementMethod !is LinkLongPressMovementMethod) {
@@ -268,6 +307,10 @@ class EnrichedMarkdownText
268
307
  applySelectionColors(selectionColor, selectionHandleColor)
269
308
  }
270
309
 
310
+ // Trailing bottom margin included in the shadow-node measurement — must be
311
+ // mirrored when re-storing the measurement from the display text.
312
+ fun trailingMarginBottomPx(): Float = if (allowTrailingMargin) renderer.getLastElementMarginBottom() else 0f
313
+
271
314
  fun setContextMenuItems(items: List<String>) {
272
315
  contextMenuItemTexts = items
273
316
  }
@@ -326,6 +369,10 @@ class EnrichedMarkdownText
326
369
  checkboxTouchHelper.onCheckboxTap = callback
327
370
  }
328
371
 
372
+ fun setEnableTaskListItemToggle(enabled: Boolean) {
373
+ checkboxTouchHelper.isEnabled = enabled
374
+ }
375
+
329
376
  override fun onAttachedToWindow() {
330
377
  super.onAttachedToWindow()
331
378
  pendingStyledText?.let {
@@ -1,12 +1,21 @@
1
1
  package com.swmansion.enriched.markdown
2
2
 
3
+ import com.facebook.react.bridge.Arguments
4
+
3
5
  class EnrichedMarkdownTextLayoutManager(
4
6
  private val view: EnrichedMarkdownText,
5
7
  ) {
8
+ private var forceHeightRecalculationCounter = 0
9
+
6
10
  fun invalidateLayout() {
7
11
  val text = view.text
8
12
  val paint = view.paint
9
- MeasurementStore.store(view.id, text, paint)
13
+ val heightChanged = MeasurementStore.store(view.id, text, paint, view.trailingMarginBottomPx())
14
+ if (!heightChanged) return
15
+ val stateWrapper = view.stateWrapper ?: return
16
+ val state = Arguments.createMap()
17
+ state.putInt("forceHeightRecalculationCounter", ++forceHeightRecalculationCounter)
18
+ stateWrapper.updateState(state)
10
19
  }
11
20
 
12
21
  fun releaseMeasurementStore() {
@@ -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
@@ -19,6 +21,7 @@ import com.swmansion.enriched.markdown.utils.common.emitTaskListItemPress
19
21
  import com.swmansion.enriched.markdown.utils.common.markdownEventTypeConstants
20
22
  import com.swmansion.enriched.markdown.utils.common.parseAccessibilityLabels
21
23
  import com.swmansion.enriched.markdown.utils.common.parseContextMenuItems
24
+ import com.swmansion.enriched.markdown.utils.common.parseImageRequestHeaders
22
25
  import com.swmansion.enriched.markdown.utils.common.parseMd4cFlags
23
26
  import com.swmansion.enriched.markdown.utils.common.parseSelectionMenuConfig
24
27
  import com.swmansion.enriched.markdown.utils.text.interaction.TaskListTapUtils
@@ -69,6 +72,20 @@ class EnrichedMarkdownTextManager :
69
72
  return view
70
73
  }
71
74
 
75
+ override fun onAfterUpdateTransaction(view: EnrichedMarkdownText) {
76
+ super.onAfterUpdateTransaction(view)
77
+ view.commitProps()
78
+ }
79
+
80
+ override fun updateState(
81
+ view: EnrichedMarkdownText,
82
+ props: ReactStylesDiffMap?,
83
+ stateWrapper: StateWrapper?,
84
+ ): Any? {
85
+ view.stateWrapper = stateWrapper
86
+ return super.updateState(view, props, stateWrapper)
87
+ }
88
+
72
89
  override fun onDropViewInstance(view: EnrichedMarkdownText) {
73
90
  super.onDropViewInstance(view)
74
91
  MeasurementStore.clearFontScalingSettings(view.id)
@@ -148,6 +165,14 @@ class EnrichedMarkdownTextManager :
148
165
  view?.setAllowTrailingMargin(allowTrailingMargin)
149
166
  }
150
167
 
168
+ @ReactProp(name = "contextMenuHidden", defaultBoolean = false)
169
+ override fun setContextMenuHidden(
170
+ view: EnrichedMarkdownText?,
171
+ contextMenuHidden: Boolean,
172
+ ) {
173
+ view?.setContextMenuHidden(contextMenuHidden)
174
+ }
175
+
151
176
  @ReactProp(name = "enableLinkPreview", defaultBoolean = true)
152
177
  override fun setEnableLinkPreview(
153
178
  view: EnrichedMarkdownText?,
@@ -156,6 +181,14 @@ class EnrichedMarkdownTextManager :
156
181
  // No-op on Android — only used on iOS
157
182
  }
158
183
 
184
+ @ReactProp(name = "enableTaskListItemToggle", defaultBoolean = true)
185
+ override fun setEnableTaskListItemToggle(
186
+ view: EnrichedMarkdownText?,
187
+ enableTaskListItemToggle: Boolean,
188
+ ) {
189
+ view?.setEnableTaskListItemToggle(enableTaskListItemToggle)
190
+ }
191
+
159
192
  @ReactProp(name = "lineBreakStrategyIOS")
160
193
  override fun setLineBreakStrategyIOS(
161
194
  view: EnrichedMarkdownText?,
@@ -213,6 +246,15 @@ class EnrichedMarkdownTextManager :
213
246
  view.setContextMenuItems(parseContextMenuItems(value))
214
247
  }
215
248
 
249
+ @ReactProp(name = "imageRequestHeaders")
250
+ override fun setImageRequestHeaders(
251
+ view: EnrichedMarkdownText?,
252
+ value: ReadableArray?,
253
+ ) {
254
+ if (view == null) return
255
+ view.setImageRequestHeaders(parseImageRequestHeaders(value))
256
+ }
257
+
216
258
  @ReactProp(name = "selectionMenuConfig")
217
259
  override fun setSelectionMenuConfig(
218
260
  view: EnrichedMarkdownText?,
@@ -19,16 +19,21 @@ import com.swmansion.enriched.markdown.spans.MathMetrics
19
19
  import com.swmansion.enriched.markdown.spans.MathRenderMode
20
20
  import com.swmansion.enriched.markdown.styles.StyleConfig
21
21
  import com.swmansion.enriched.markdown.utils.common.BreakStrategyUtils
22
+ import com.swmansion.enriched.markdown.utils.common.CodeBlockStreamingMode
22
23
  import com.swmansion.enriched.markdown.utils.common.FeatureFlags
23
24
  import com.swmansion.enriched.markdown.utils.common.MarkdownSegmentRenderer
24
25
  import com.swmansion.enriched.markdown.utils.common.RenderedSegment
25
26
  import com.swmansion.enriched.markdown.utils.common.StreamingMarkdownFilter
26
27
  import com.swmansion.enriched.markdown.utils.common.TableStreamingMode
28
+ import com.swmansion.enriched.markdown.utils.common.getArrayOrNull
27
29
  import com.swmansion.enriched.markdown.utils.common.getBooleanOrDefault
30
+ import com.swmansion.enriched.markdown.utils.common.getFloatOrDefault
28
31
  import com.swmansion.enriched.markdown.utils.common.getMapOrNull
29
32
  import com.swmansion.enriched.markdown.utils.common.getStringOrDefault
33
+ import com.swmansion.enriched.markdown.utils.common.parseImageRequestHeaders
30
34
  import com.swmansion.enriched.markdown.utils.common.splitASTIntoSegments
31
35
  import com.swmansion.enriched.markdown.utils.text.extensions.replaceMathSpansWithPlaceholders
36
+ import com.swmansion.enriched.markdown.views.CodeBlockContainerView
32
37
  import com.swmansion.enriched.markdown.views.TableContainerView
33
38
  import java.util.concurrent.ConcurrentHashMap
34
39
  import kotlin.math.ceil
@@ -67,6 +72,8 @@ object MeasurementStore {
67
72
 
68
73
  private val streamingTableModes = ConcurrentHashMap<Int, TableStreamingMode>()
69
74
 
75
+ private val streamingCodeBlockModes = ConcurrentHashMap<Int, CodeBlockStreamingMode>()
76
+
70
77
  private fun resolveFontScalingSettings(
71
78
  viewId: Int?,
72
79
  props: ReadableMap?,
@@ -95,6 +102,7 @@ object MeasurementStore {
95
102
  id: Int,
96
103
  spannable: CharSequence?,
97
104
  paint: TextPaint,
105
+ trailingMarginBottomPx: Float = 0f,
98
106
  ): Boolean {
99
107
  val cached = data[id]
100
108
  val width = cached?.cachedWidth ?: 0f
@@ -102,7 +110,14 @@ object MeasurementStore {
102
110
  val existingHash = cached?.markdownHash ?: 0
103
111
  val paintParams = PaintParams(paint.typeface ?: Typeface.DEFAULT, paint.textSize)
104
112
 
105
- val newSize = measure(width, spannable, paint, id)
113
+ var newSize = measure(width, spannable, paint, id)
114
+ if (trailingMarginBottomPx > 0f) {
115
+ newSize =
116
+ YogaMeasureOutput.make(
117
+ YogaMeasureOutput.getWidth(newSize),
118
+ YogaMeasureOutput.getHeight(newSize) + PixelUtil.toDIPFromPixel(trailingMarginBottomPx),
119
+ )
120
+ }
106
121
  data[id] = MeasurementParams(width, newSize, spannable, paintParams, existingHash)
107
122
  return oldSize != newSize
108
123
  }
@@ -151,7 +166,11 @@ object MeasurementStore {
151
166
  allowFontScaling: Boolean,
152
167
  maxFontSizeMultiplier: Float,
153
168
  ) {
169
+ val previous = fontScalingSettings[viewId]
154
170
  fontScalingSettings[viewId] = FontScalingSettings(allowFontScaling, maxFontSizeMultiplier)
171
+ if (previous != null && (previous.allowFontScaling != allowFontScaling || previous.maxFontSizeMultiplier != maxFontSizeMultiplier)) {
172
+ data.remove(viewId)
173
+ }
155
174
  }
156
175
 
157
176
  fun clearFontScalingSettings(viewId: Int) {
@@ -182,6 +201,17 @@ object MeasurementStore {
182
201
  streamingTableModes.remove(viewId)
183
202
  }
184
203
 
204
+ fun updateStreamingCodeBlockMode(
205
+ viewId: Int,
206
+ mode: CodeBlockStreamingMode,
207
+ ) {
208
+ streamingCodeBlockModes[viewId] = mode
209
+ }
210
+
211
+ fun clearStreamingCodeBlockMode(viewId: Int) {
212
+ streamingCodeBlockModes.remove(viewId)
213
+ }
214
+
185
215
  private fun getMeasureByIdInternal(
186
216
  context: Context,
187
217
  id: Int?,
@@ -237,6 +267,7 @@ object MeasurementStore {
237
267
  val styleMap = props.getMapOrNull("markdownStyle")
238
268
  val md4cFlagsMap = props.getMapOrNull("md4cFlags")
239
269
  val allowTrailingMargin = props.getBooleanOrDefault("allowTrailingMargin", false)
270
+ val imageRequestHeaders = parseImageRequestHeaders(props.getArrayOrNull("imageRequestHeaders"))
240
271
  var result = markdown.hashCode()
241
272
  result = 31 * result + (styleMap?.hashCode() ?: 0)
242
273
  result = 31 * result + (md4cFlagsMap?.hashCode() ?: 0)
@@ -244,6 +275,7 @@ object MeasurementStore {
244
275
  result = 31 * result + allowFontScaling.hashCode()
245
276
  result = 31 * result + maxFontSizeMultiplier.toBits()
246
277
  result = 31 * result + allowTrailingMargin.hashCode()
278
+ result = 31 * result + imageRequestHeaders.hashCode()
247
279
  return result
248
280
  }
249
281
 
@@ -292,13 +324,23 @@ object MeasurementStore {
292
324
  superscript = props.getMapOrNull("md4cFlags").getBooleanOrDefault("superscript", false),
293
325
  subscript = props.getMapOrNull("md4cFlags").getBooleanOrDefault("subscript", false),
294
326
  highlight = props.getMapOrNull("md4cFlags").getBooleanOrDefault("highlight", false),
327
+ hardSoftBreaks = props.getMapOrNull("md4cFlags").getBooleanOrDefault("hardSoftBreaks", false),
295
328
  )
296
329
 
297
330
  val fontSize = getInitialFontSize(styleMap, context, allowFontScaling, fontScale, maxFontSizeMultiplier)
298
331
  val propsHash = computePropsHash(props, allowFontScaling, fontScale, maxFontSizeMultiplier)
299
332
 
300
333
  // 2. Render & Measure
301
- val spannable = tryRenderMarkdown(markdown, styleMap, context, md4cFlags, allowFontScaling, maxFontSizeMultiplier)
334
+ measurePaint.textSize = fontSize
335
+ val imageRequestHeaders = parseImageRequestHeaders(props.getArrayOrNull("imageRequestHeaders"))
336
+ val spannable =
337
+ tryRenderMarkdown(markdown, styleMap, context, md4cFlags, allowFontScaling, maxFontSizeMultiplier, imageRequestHeaders)
338
+ // Placeholders must be built with the same inlineMath.paddingVertical the real spans use,
339
+ // or the measured line box won't match the drawn one.
340
+ spannable?.replaceMathSpansWithPlaceholders(
341
+ context,
342
+ PixelUtil.toPixelFromDIP(styleMap.getMapOrNull("inlineMath").getFloatOrDefault("paddingVertical", 0f)),
343
+ )
302
344
  val textToMeasure = spannable ?: markdown
303
345
  val (size, _) = measureWithLayout(width, textToMeasure, measurePaint, id)
304
346
 
@@ -343,9 +385,17 @@ object MeasurementStore {
343
385
  } else {
344
386
  TableStreamingMode.PROGRESSIVE
345
387
  }
388
+ val codeBlockMode =
389
+ if (isStreaming) {
390
+ id?.let {
391
+ streamingCodeBlockModes[it]
392
+ } ?: CodeBlockStreamingMode.PROGRESSIVE
393
+ } else {
394
+ CodeBlockStreamingMode.PROGRESSIVE
395
+ }
346
396
  val markdown =
347
397
  if (isStreaming) {
348
- StreamingMarkdownFilter.renderableMarkdownForStreaming(rawMarkdown, tableMode)
398
+ StreamingMarkdownFilter.renderableMarkdownForStreaming(rawMarkdown, tableMode, codeBlockMode).markdown
349
399
  } else {
350
400
  rawMarkdown
351
401
  }
@@ -371,6 +421,7 @@ object MeasurementStore {
371
421
  superscript = props.getMapOrNull("md4cFlags").getBooleanOrDefault("superscript", false),
372
422
  subscript = props.getMapOrNull("md4cFlags").getBooleanOrDefault("subscript", false),
373
423
  highlight = props.getMapOrNull("md4cFlags").getBooleanOrDefault("highlight", false),
424
+ hardSoftBreaks = props.getMapOrNull("md4cFlags").getBooleanOrDefault("hardSoftBreaks", false),
374
425
  )
375
426
  val allowTrailingMargin = props.getBooleanOrDefault("allowTrailingMargin", false)
376
427
  val fontSize = getInitialFontSize(styleMap, context, allowFontScaling, fontScale, maxFontSizeMultiplier)
@@ -381,6 +432,7 @@ object MeasurementStore {
381
432
  ?: return YogaMeasureOutput.make(PixelUtil.toDIPFromPixel(width), 0f)
382
433
 
383
434
  val style = StyleConfig(styleMap, context, allowFontScaling, maxFontSizeMultiplier)
435
+ style.imageRequestHeaders = parseImageRequestHeaders(props.getArrayOrNull("imageRequestHeaders"))
384
436
  val segments = splitASTIntoSegments(ast)
385
437
  val renderedSegments = MarkdownSegmentRenderer.render(segments, style, context, null, null)
386
438
 
@@ -449,6 +501,15 @@ object MeasurementStore {
449
501
  totalHeightPx += style.mathStyle.marginBottom
450
502
  }
451
503
  }
504
+
505
+ is RenderedSegment.CodeBlock -> {
506
+ totalHeightPx += style.codeBlockStyle.marginTop
507
+ totalHeightPx += CodeBlockContainerView.measureCodeBlockNodeHeight(segment.node, style, context, width)
508
+ maxContentWidthPx = width
509
+ if (includeBottomMargin) {
510
+ totalHeightPx += style.codeBlockStyle.marginBottom
511
+ }
512
+ }
452
513
  }
453
514
  }
454
515
 
@@ -466,6 +527,18 @@ object MeasurementStore {
466
527
  }
467
528
  }
468
529
 
530
+ private fun prepareImageSpansForMeasurement(
531
+ text: CharSequence?,
532
+ widthPx: Int,
533
+ ) {
534
+ // widthPx == 1 is the coerceAtLeast(1) fallback for a not-yet-measured view
535
+ if (widthPx <= 1) return
536
+ val spanned = text as? android.text.Spanned ?: return
537
+ spanned
538
+ .getSpans(0, spanned.length, com.swmansion.enriched.markdown.spans.ImageSpan::class.java)
539
+ .forEach { it.prepareForMeasurement(spanned, widthPx) }
540
+ }
541
+
469
542
  private fun createStaticLayout(
470
543
  text: CharSequence,
471
544
  fontSize: Float,
@@ -473,6 +546,7 @@ object MeasurementStore {
473
546
  viewId: Int?,
474
547
  ): StaticLayout {
475
548
  measurePaint.textSize = fontSize
549
+ prepareImageSpansForMeasurement(text, widthPx)
476
550
  return StaticLayout.Builder
477
551
  .obtain(text, 0, text.length, measurePaint, widthPx)
478
552
  .setIncludePad(false)
@@ -495,12 +569,14 @@ object MeasurementStore {
495
569
  md4cFlags: Md4cFlags,
496
570
  allowFontScaling: Boolean,
497
571
  maxFontSizeMultiplier: Float,
572
+ imageRequestHeaders: Map<String, String> = emptyMap(),
498
573
  ): SpannableString? {
499
574
  if (styleMap == null) return null
500
575
 
501
576
  return try {
502
577
  val ast = Parser.shared.parseMarkdown(markdown, md4cFlags) ?: return null
503
578
  val style = StyleConfig(styleMap, context, allowFontScaling, maxFontSizeMultiplier)
579
+ style.imageRequestHeaders = imageRequestHeaders
504
580
  measureRenderer.configure(style, context)
505
581
  measureRenderer.renderDocument(ast, null).apply {
506
582
  replaceMathSpansWithPlaceholders(context, style.inlineMathStyle.paddingVertical)
@@ -518,7 +594,7 @@ object MeasurementStore {
518
594
  fontScale: Float,
519
595
  maxFontSizeMultiplier: Float,
520
596
  ): Float {
521
- val fontSizeSp = styleMap?.getMap("paragraph")?.getDouble("fontSize")?.toFloat() ?: 16f
597
+ val fontSizeSp = styleMap.getMapOrNull("paragraph").getFloatOrDefault("fontSize", 16f)
522
598
  val density = context.resources.displayMetrics.density
523
599
 
524
600
  if (!allowFontScaling) {
@@ -554,6 +630,7 @@ object MeasurementStore {
554
630
  ): Long {
555
631
  val content = text ?: ""
556
632
  val safeWidth = ceil(maxWidth).toInt().coerceAtLeast(1)
633
+ prepareImageSpansForMeasurement(content, safeWidth)
557
634
 
558
635
  val builder =
559
636
  StaticLayout.Builder
@@ -593,6 +670,7 @@ object MeasurementStore {
593
670
  ): Pair<Long, StaticLayout> {
594
671
  val content = text ?: ""
595
672
  val widthPx = ceil(maxWidth).toInt().coerceAtLeast(1)
673
+ prepareImageSpansForMeasurement(content, widthPx)
596
674
 
597
675
  val layout =
598
676
  StaticLayout.Builder
@@ -0,0 +1,24 @@
1
+ package com.swmansion.enriched.markdown.events
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.events.Event
6
+
7
+ class CopyPressEvent(
8
+ surfaceId: Int,
9
+ viewId: Int,
10
+ private val code: String,
11
+ private val language: String,
12
+ ) : Event<CopyPressEvent>(surfaceId, viewId) {
13
+ override fun getEventName(): String = EVENT_NAME
14
+
15
+ override fun getEventData(): WritableMap =
16
+ Arguments.createMap().apply {
17
+ putString("code", code)
18
+ putString("language", language)
19
+ }
20
+
21
+ companion object {
22
+ const val EVENT_NAME: String = "onCopyPress"
23
+ }
24
+ }