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
@@ -5,6 +5,27 @@ import android.view.inputmethod.InputConnection
5
5
  import com.swmansion.enriched.markdown.input.EnrichedMarkdownTextInputView
6
6
  import android.view.inputmethod.InputConnectionWrapper as AndroidInputConnectionWrapper
7
7
 
8
+ /**
9
+ * Intercepts IME traffic for two purposes: atomic link deletion (a backspace
10
+ * right after a link removes the whole link) and the `onKeyPress` event.
11
+ *
12
+ * Key derivation mirrors React Native's ReactEditTextInputConnectionWrapper.
13
+ * Soft keyboards don't report discrete key presses; the pressed key is inferred
14
+ * from InputConnection side effects:
15
+ * - [setComposingText] receives the whole composing region, not a one-character
16
+ * diff, so the key is derived from cursor movement: a cursor that moved
17
+ * backwards (or stayed put while collapsing a selection) means "Backspace",
18
+ * otherwise the key is the character left of the cursor.
19
+ * - [commitText] with an empty string means "Backspace"; short strings (a char,
20
+ * or a surrogate pair) are the key itself; longer strings are autocomplete
21
+ * insertions, not key presses.
22
+ * - [deleteSurroundingText] is a backspace with nothing to compose.
23
+ * - [sendKeyEvent] is used by some keyboards (e.g. SwiftKey) for delete/enter
24
+ * and by number-pad keys.
25
+ * IMEs wrap composed-word commits in a batch edit that ends with the actual
26
+ * user input, so during a batch only the last inferred key is emitted at
27
+ * [endBatchEdit]. Newlines are normalized to "Enter".
28
+ */
8
29
  class InputConnectionWrapper(
9
30
  target: InputConnection,
10
31
  private val editText: EnrichedMarkdownTextInputView,
@@ -12,6 +33,8 @@ class InputConnectionWrapper(
12
33
  var isBatchEdit = false
13
34
  private set
14
35
 
36
+ private var pendingKey: String? = null
37
+
15
38
  override fun beginBatchEdit(): Boolean {
16
39
  isBatchEdit = true
17
40
  return super.beginBatchEdit()
@@ -19,13 +42,46 @@ class InputConnectionWrapper(
19
42
 
20
43
  override fun endBatchEdit(): Boolean {
21
44
  isBatchEdit = false
45
+ pendingKey?.let {
46
+ dispatchKeyPress(it)
47
+ pendingKey = null
48
+ }
22
49
  return super.endBatchEdit()
23
50
  }
24
51
 
25
52
  override fun setComposingText(
26
53
  text: CharSequence,
27
54
  newCursorPosition: Int,
28
- ): Boolean = super.setComposingText(text, newCursorPosition)
55
+ ): Boolean {
56
+ val previousSelectionStart = editText.selectionStart
57
+ val previousSelectionEnd = editText.selectionEnd
58
+
59
+ val consumed = super.setComposingText(text, newCursorPosition)
60
+
61
+ val currentSelectionStart = editText.selectionStart
62
+ val noPreviousSelection = previousSelectionStart == previousSelectionEnd
63
+ val cursorDidNotMove = currentSelectionStart == previousSelectionStart
64
+ val cursorMovedBackwardsOrAtBeginningOfInput =
65
+ currentSelectionStart < previousSelectionStart || currentSelectionStart <= 0
66
+
67
+ val key =
68
+ if (cursorMovedBackwardsOrAtBeginningOfInput || (!noPreviousSelection && cursorDidNotMove)) {
69
+ BACKSPACE_KEY_VALUE
70
+ } else {
71
+ codePointBeforeCursor(currentSelectionStart)
72
+ }
73
+ if (key.isNotEmpty()) {
74
+ dispatchKeyPressOrEnqueue(key)
75
+ }
76
+ return consumed
77
+ }
78
+
79
+ private fun codePointBeforeCursor(cursor: Int): String {
80
+ val content = editText.text ?: return ""
81
+ val end = cursor.coerceAtMost(content.length)
82
+ if (end < 1) return ""
83
+ return String(Character.toChars(Character.codePointBefore(content, end)))
84
+ }
29
85
 
30
86
  override fun setComposingRegion(
31
87
  start: Int,
@@ -45,12 +101,19 @@ class InputConnectionWrapper(
45
101
  override fun commitText(
46
102
  text: CharSequence,
47
103
  newCursorPosition: Int,
48
- ): Boolean = super.commitText(text, newCursorPosition)
104
+ ): Boolean {
105
+ val key = text.toString()
106
+ if (key.length <= 2) {
107
+ dispatchKeyPressOrEnqueue(key.ifEmpty { BACKSPACE_KEY_VALUE })
108
+ }
109
+ return super.commitText(text, newCursorPosition)
110
+ }
49
111
 
50
112
  override fun deleteSurroundingText(
51
113
  beforeLength: Int,
52
114
  afterLength: Int,
53
115
  ): Boolean {
116
+ dispatchKeyPress(BACKSPACE_KEY_VALUE)
54
117
  if (beforeLength == 1 && afterLength == 0 && editText.deleteLinkBeforeCursor()) {
55
118
  return true
56
119
  }
@@ -58,12 +121,43 @@ class InputConnectionWrapper(
58
121
  }
59
122
 
60
123
  override fun sendKeyEvent(event: KeyEvent): Boolean {
61
- if (event.action == KeyEvent.ACTION_DOWN &&
62
- event.keyCode == KeyEvent.KEYCODE_DEL &&
63
- editText.deleteLinkBeforeCursor()
64
- ) {
65
- return true
124
+ if (event.action == KeyEvent.ACTION_DOWN) {
125
+ val isNumberKey = event.unicodeChar in 48..57
126
+ when (event.keyCode) {
127
+ KeyEvent.KEYCODE_DEL -> dispatchKeyPress(BACKSPACE_KEY_VALUE)
128
+ KeyEvent.KEYCODE_ENTER -> dispatchKeyPress(ENTER_KEY_VALUE)
129
+ else -> if (isNumberKey) dispatchKeyPress(event.number.toString())
130
+ }
131
+ if (event.keyCode == KeyEvent.KEYCODE_DEL && editText.deleteLinkBeforeCursor()) {
132
+ return true
133
+ }
66
134
  }
67
135
  return super.sendKeyEvent(event)
68
136
  }
137
+
138
+ private fun dispatchKeyPressOrEnqueue(key: String) {
139
+ if (isBatchEdit) {
140
+ pendingKey = key
141
+ } else {
142
+ dispatchKeyPress(key)
143
+ }
144
+ }
145
+
146
+ private fun dispatchKeyPress(key: String) {
147
+ val resolved =
148
+ when (key) {
149
+ NEWLINE_RAW_VALUE -> ENTER_KEY_VALUE
150
+ TAB_RAW_VALUE -> TAB_KEY_VALUE
151
+ else -> key
152
+ }
153
+ editText.eventEmitter.emitKeyPress(resolved)
154
+ }
155
+
156
+ companion object {
157
+ private const val NEWLINE_RAW_VALUE = "\n"
158
+ private const val TAB_RAW_VALUE = "\t"
159
+ private const val BACKSPACE_KEY_VALUE = "Backspace"
160
+ private const val ENTER_KEY_VALUE = "Enter"
161
+ private const val TAB_KEY_VALUE = "Tab"
162
+ }
69
163
  }
@@ -0,0 +1,69 @@
1
+ package com.swmansion.enriched.markdown.input.editing
2
+
3
+ import android.text.Spannable
4
+ import com.swmansion.enriched.markdown.input.autolink.AutoLinkDetector
5
+ import com.swmansion.enriched.markdown.input.formatting.FormattingStore
6
+ import com.swmansion.enriched.markdown.input.model.FormattingRange
7
+ import com.swmansion.enriched.markdown.input.model.StyleType
8
+
9
+ class LinkCoordinator(
10
+ private val formattingStore: FormattingStore,
11
+ private val autoLinkDetector: AutoLinkDetector,
12
+ ) {
13
+ fun sanitizeUrl(url: String): String =
14
+ url
15
+ .replace("(", "%28")
16
+ .replace(")", "%29")
17
+
18
+ fun linkAtPosition(position: Int): FormattingRange? = formattingStore.rangeOfType(StyleType.LINK, position)
19
+
20
+ fun setLinkForRange(
21
+ url: String,
22
+ start: Int,
23
+ end: Int,
24
+ editable: Spannable?,
25
+ ) {
26
+ if (start == end) return
27
+ if (editable != null) {
28
+ autoLinkDetector.clearAutoLinkInRange(editable, start, end)
29
+ }
30
+ formattingStore.addRange(FormattingRange(StyleType.LINK, start, end, url))
31
+ }
32
+
33
+ fun addLink(
34
+ url: String,
35
+ start: Int,
36
+ end: Int,
37
+ editable: Spannable?,
38
+ ) {
39
+ if (start >= end) return
40
+ if (editable != null) {
41
+ autoLinkDetector.clearAutoLinkInRange(editable, start, end)
42
+ }
43
+ formattingStore.addRange(FormattingRange(StyleType.LINK, start, end, sanitizeUrl(url)))
44
+ }
45
+
46
+ fun addLinkDirect(
47
+ url: String,
48
+ start: Int,
49
+ end: Int,
50
+ ) {
51
+ if (start >= end) return
52
+ formattingStore.addRange(FormattingRange(StyleType.LINK, start, end, url))
53
+ }
54
+
55
+ fun removeLink(position: Int): Boolean {
56
+ val linkRange = formattingStore.rangeOfType(StyleType.LINK, position) ?: return false
57
+ formattingStore.removeRange(linkRange)
58
+ return true
59
+ }
60
+
61
+ /**
62
+ * Finds the link containing `position - 1` and returns its range for deletion.
63
+ * Returns null if no link is found.
64
+ */
65
+ fun linkRangeForDeletion(position: Int): FormattingRange? {
66
+ if (position <= 0) return null
67
+ return formattingStore.rangeOfType(StyleType.LINK, position - 1)
68
+ }
69
+ }
@@ -17,7 +17,7 @@ class MarkdownTextWatcher(
17
17
  count: Int,
18
18
  after: Int,
19
19
  ) {
20
- if (view.isDuringTransaction || view.isProcessingTextChange) return
20
+ if (view.editSession.shouldSuppressTextWatcher) return
21
21
  editStart = start
22
22
  deletedLength = count
23
23
  insertedLength = after
@@ -30,12 +30,12 @@ class MarkdownTextWatcher(
30
30
  before: Int,
31
31
  count: Int,
32
32
  ) {
33
- if (view.isDuringTransaction || view.isProcessingTextChange) return
33
+ if (view.editSession.shouldSuppressTextWatcher) return
34
34
  view.layoutManager.invalidateLayout()
35
35
  }
36
36
 
37
37
  override fun afterTextChanged(editable: Editable) {
38
- if (view.isDuringTransaction || view.isProcessingTextChange) return
38
+ if (view.editSession.shouldSuppressTextWatcher) return
39
39
  view.onAfterTextChanged(editStart, deletedLength, insertedLength)
40
40
  }
41
41
  }
@@ -0,0 +1,118 @@
1
+ package com.swmansion.enriched.markdown.input.editing
2
+
3
+ import com.swmansion.enriched.markdown.input.detection.WordsUtils
4
+ import com.swmansion.enriched.markdown.input.formatting.FormattingStore
5
+ import com.swmansion.enriched.markdown.input.model.StyleType
6
+
7
+ sealed class MentionEvent {
8
+ data class Start(
9
+ val indicator: String,
10
+ ) : MentionEvent()
11
+
12
+ data class Change(
13
+ val indicator: String,
14
+ val text: String,
15
+ ) : MentionEvent()
16
+
17
+ data class End(
18
+ val indicator: String,
19
+ ) : MentionEvent()
20
+ }
21
+
22
+ class MentionCoordinator(
23
+ private val formattingStore: FormattingStore,
24
+ ) {
25
+ private var indicators: LinkedHashSet<String> = linkedSetOf()
26
+ private var activeIndicator: String? = null
27
+ private var activeStart = -1
28
+ private var activeEnd = -1
29
+ private var activeText = ""
30
+
31
+ val isActive: Boolean get() = activeIndicator != null
32
+ val currentIndicator: String? get() = activeIndicator
33
+ val currentStart: Int get() = activeStart
34
+ val currentEnd: Int get() = activeEnd
35
+
36
+ fun containsIndicator(indicator: String): Boolean = indicator in indicators
37
+
38
+ fun setIndicators(newIndicators: List<String>): List<MentionEvent> {
39
+ val newSet = LinkedHashSet(newIndicators)
40
+ if (newSet == indicators) return emptyList()
41
+ indicators = newSet
42
+ val events = mutableListOf<MentionEvent>()
43
+ activeIndicator?.let { indicator ->
44
+ if (indicator !in indicators) {
45
+ events.addAll(clear(indicatorOverride = indicator))
46
+ }
47
+ }
48
+ return events
49
+ }
50
+
51
+ /**
52
+ * Re-evaluates the active mention based on the current cursor and text.
53
+ * Pass null [plainText] to force-clear (e.g. when the editable is absent).
54
+ */
55
+ fun update(
56
+ plainText: String?,
57
+ selStart: Int,
58
+ selEnd: Int,
59
+ ): List<MentionEvent> {
60
+ if (plainText == null || selStart != selEnd || selStart < 0 || selStart > plainText.length) {
61
+ return clear()
62
+ }
63
+
64
+ val candidate = detectCandidate(plainText, selStart) ?: return clear()
65
+ val events = mutableListOf<MentionEvent>()
66
+
67
+ if (activeIndicator != candidate.indicator || activeStart != candidate.start) {
68
+ activeIndicator?.let { events.add(MentionEvent.End(it)) }
69
+ activeIndicator = candidate.indicator
70
+ activeStart = candidate.start
71
+ events.add(MentionEvent.Start(candidate.indicator))
72
+ }
73
+
74
+ activeEnd = candidate.end
75
+ if (activeText != candidate.text) {
76
+ activeText = candidate.text
77
+ events.add(MentionEvent.Change(candidate.indicator, candidate.text))
78
+ }
79
+ return events
80
+ }
81
+
82
+ fun clear(
83
+ emit: Boolean = true,
84
+ indicatorOverride: String? = null,
85
+ ): List<MentionEvent> {
86
+ val indicator = indicatorOverride ?: activeIndicator
87
+ activeIndicator = null
88
+ activeStart = -1
89
+ activeEnd = -1
90
+ activeText = ""
91
+ return if (emit && indicator != null) listOf(MentionEvent.End(indicator)) else emptyList()
92
+ }
93
+
94
+ private fun detectCandidate(
95
+ plainText: String,
96
+ cursor: Int,
97
+ ): MentionCandidate? {
98
+ if (indicators.isEmpty()) return null
99
+ val start = WordsUtils.tokenStart(plainText, cursor)
100
+ val token = plainText.substring(start, cursor)
101
+ val indicator = indicators.firstOrNull { token.startsWith(it) } ?: return null
102
+ if (formattingStore.rangeOfType(StyleType.LINK, start) != null) return null
103
+
104
+ return MentionCandidate(
105
+ indicator = indicator,
106
+ start = start,
107
+ end = cursor,
108
+ text = token.substring(indicator.length),
109
+ )
110
+ }
111
+
112
+ private data class MentionCandidate(
113
+ val indicator: String,
114
+ val start: Int,
115
+ val end: Int,
116
+ val text: String,
117
+ )
118
+ }
@@ -13,6 +13,11 @@ class OnChangeStateEvent(
13
13
  private val isStrikethrough: Boolean,
14
14
  private val isSpoiler: Boolean,
15
15
  private val isLink: Boolean,
16
+ private val headingLevel: Int,
17
+ private val isUnorderedList: Boolean,
18
+ private val unorderedListDepth: Int,
19
+ private val isOrderedList: Boolean,
20
+ private val orderedListDepth: Int,
16
21
  ) : Event<OnChangeStateEvent>(surfaceId, viewId) {
17
22
  override fun getEventName(): String = EVENT_NAME
18
23
 
@@ -42,6 +47,27 @@ class OnChangeStateEvent(
42
47
  "link",
43
48
  Arguments.createMap().apply { putBoolean("isActive", isLink) },
44
49
  )
50
+ putMap(
51
+ "heading",
52
+ Arguments.createMap().apply {
53
+ putBoolean("isActive", headingLevel > 0)
54
+ putInt("level", headingLevel)
55
+ },
56
+ )
57
+ putMap(
58
+ "unorderedList",
59
+ Arguments.createMap().apply {
60
+ putBoolean("isActive", isUnorderedList)
61
+ putInt("depth", unorderedListDepth)
62
+ },
63
+ )
64
+ putMap(
65
+ "orderedList",
66
+ Arguments.createMap().apply {
67
+ putBoolean("isActive", isOrderedList)
68
+ putInt("depth", orderedListDepth)
69
+ },
70
+ )
45
71
  }
46
72
 
47
73
  companion object {
@@ -17,6 +17,11 @@ class OnContextMenuItemPressEvent(
17
17
  private val isStrikethrough: Boolean,
18
18
  private val isSpoiler: Boolean,
19
19
  private val isLink: Boolean,
20
+ private val headingLevel: Int,
21
+ private val isUnorderedList: Boolean,
22
+ private val unorderedListDepth: Int,
23
+ private val isOrderedList: Boolean,
24
+ private val orderedListDepth: Int,
20
25
  ) : Event<OnContextMenuItemPressEvent>(surfaceId, viewId) {
21
26
  override fun getEventName(): String = EVENT_NAME
22
27
 
@@ -37,6 +42,27 @@ class OnContextMenuItemPressEvent(
37
42
  putMap("strikethrough", styleEntry(isStrikethrough))
38
43
  putMap("spoiler", styleEntry(isSpoiler))
39
44
  putMap("link", styleEntry(isLink))
45
+ putMap(
46
+ "heading",
47
+ Arguments.createMap().apply {
48
+ putBoolean("isActive", headingLevel > 0)
49
+ putInt("level", headingLevel)
50
+ },
51
+ )
52
+ putMap(
53
+ "unorderedList",
54
+ Arguments.createMap().apply {
55
+ putBoolean("isActive", isUnorderedList)
56
+ putInt("depth", unorderedListDepth)
57
+ },
58
+ )
59
+ putMap(
60
+ "orderedList",
61
+ Arguments.createMap().apply {
62
+ putBoolean("isActive", isOrderedList)
63
+ putInt("depth", orderedListDepth)
64
+ },
65
+ )
40
66
  },
41
67
  )
42
68
  }
@@ -0,0 +1,24 @@
1
+ package com.swmansion.enriched.markdown.input.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 OnInputKeyPressEvent(
8
+ surfaceId: Int,
9
+ viewId: Int,
10
+ private val key: String,
11
+ ) : Event<OnInputKeyPressEvent>(surfaceId, viewId) {
12
+ override fun getEventName(): String = EVENT_NAME
13
+
14
+ override fun getEventData(): WritableMap =
15
+ Arguments.createMap().apply {
16
+ putString("key", key)
17
+ }
18
+
19
+ override fun canCoalesce(): Boolean = false
20
+
21
+ companion object {
22
+ const val EVENT_NAME = "onInputKeyPress"
23
+ }
24
+ }
@@ -0,0 +1,24 @@
1
+ package com.swmansion.enriched.markdown.input.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 OnPasteEvent(
8
+ surfaceId: Int,
9
+ viewId: Int,
10
+ private val text: String,
11
+ private val markdown: String,
12
+ ) : Event<OnPasteEvent>(surfaceId, viewId) {
13
+ override fun getEventName(): String = EVENT_NAME
14
+
15
+ override fun getEventData(): WritableMap =
16
+ Arguments.createMap().apply {
17
+ putString("text", text)
18
+ putString("markdown", markdown)
19
+ }
20
+
21
+ companion object {
22
+ const val EVENT_NAME = "onPaste"
23
+ }
24
+ }