react-native-enriched-markdown-scaffold 0.6.0-scaffold.4

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 (678) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +53 -0
  3. package/ReactNativeEnrichedMarkdown.podspec +67 -0
  4. package/android/build.gradle +94 -0
  5. package/android/consumer-rules.pro +19 -0
  6. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +87 -0
  7. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +37 -0
  8. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerDelegate.java +159 -0
  9. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +59 -0
  10. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +87 -0
  11. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +37 -0
  12. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ComponentDescriptors.cpp +22 -0
  13. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ComponentDescriptors.h +24 -0
  14. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +318 -0
  15. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +259 -0
  16. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +375 -0
  17. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +5174 -0
  18. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ShadowNodes.cpp +17 -0
  19. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ShadowNodes.h +23 -0
  20. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/States.cpp +16 -0
  21. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/States.h +20 -0
  22. package/android/gradle.properties +5 -0
  23. package/android/src/main/AndroidManifest.xml +2 -0
  24. package/android/src/main/baseline-prof.txt +254 -0
  25. package/android/src/main/cpp/jni-adapter.cpp +264 -0
  26. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +554 -0
  27. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +122 -0
  28. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +255 -0
  29. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +363 -0
  30. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager.kt +15 -0
  31. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +253 -0
  32. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextPackage.kt +20 -0
  33. package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +653 -0
  34. package/android/src/main/java/com/swmansion/enriched/markdown/accessibility/AccessibleMarkdownTextView.kt +33 -0
  35. package/android/src/main/java/com/swmansion/enriched/markdown/accessibility/MarkdownAccessibilityHelper.kt +482 -0
  36. package/android/src/main/java/com/swmansion/enriched/markdown/events/ContextMenuItemPressEvent.kt +28 -0
  37. package/android/src/main/java/com/swmansion/enriched/markdown/events/LinkLongPressEvent.kt +23 -0
  38. package/android/src/main/java/com/swmansion/enriched/markdown/events/LinkPressEvent.kt +23 -0
  39. package/android/src/main/java/com/swmansion/enriched/markdown/events/TaskListItemPressEvent.kt +26 -0
  40. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +465 -0
  41. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +1066 -0
  42. package/android/src/main/java/com/swmansion/enriched/markdown/input/autolink/AutoDetectedLinkSpan.kt +29 -0
  43. package/android/src/main/java/com/swmansion/enriched/markdown/input/autolink/AutoLinkDetector.kt +188 -0
  44. package/android/src/main/java/com/swmansion/enriched/markdown/input/autolink/LinkRegexConfig.kt +9 -0
  45. package/android/src/main/java/com/swmansion/enriched/markdown/input/detection/DetectorPipeline.kt +40 -0
  46. package/android/src/main/java/com/swmansion/enriched/markdown/input/detection/TextDetector.kt +27 -0
  47. package/android/src/main/java/com/swmansion/enriched/markdown/input/detection/WordResult.kt +7 -0
  48. package/android/src/main/java/com/swmansion/enriched/markdown/input/detection/WordsUtils.kt +65 -0
  49. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/InputConnectionWrapper.kt +69 -0
  50. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MarkdownEditableFactory.kt +15 -0
  51. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MarkdownTextWatcher.kt +41 -0
  52. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnCaretRectChangeEvent.kt +20 -0
  53. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeMarkdownEvent.kt +22 -0
  54. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeMentionEvent.kt +24 -0
  55. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeSelectionEvent.kt +24 -0
  56. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeStateEvent.kt +50 -0
  57. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeTextEvent.kt +22 -0
  58. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnContextMenuItemPressEvent.kt +48 -0
  59. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnEndMentionEvent.kt +22 -0
  60. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnInputBlurEvent.kt +18 -0
  61. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnInputFocusEvent.kt +18 -0
  62. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnLinkDetectedEvent.kt +28 -0
  63. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnMathPressEvent.kt +36 -0
  64. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnRequestCaretRectResultEvent.kt +25 -0
  65. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnRequestMarkdownResultEvent.kt +24 -0
  66. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnStartMentionEvent.kt +22 -0
  67. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +192 -0
  68. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputFormatter.kt +117 -0
  69. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +117 -0
  70. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputRemend.kt +120 -0
  71. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/MarkdownSerializer.kt +176 -0
  72. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputEventEmitter.kt +216 -0
  73. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputLayoutManager.kt +28 -0
  74. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +137 -0
  75. package/android/src/main/java/com/swmansion/enriched/markdown/input/math/MathChipController.kt +113 -0
  76. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/CaretRect.kt +17 -0
  77. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/FormattingRange.kt +10 -0
  78. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/InputFormatterStyle.kt +28 -0
  79. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathAtom.kt +7 -0
  80. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +47 -0
  81. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/StyleType.kt +10 -0
  82. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/BoldStyleHandler.kt +35 -0
  83. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/ItalicStyleHandler.kt +35 -0
  84. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/LinkStyleHandler.kt +75 -0
  85. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/SpoilerStyleHandler.kt +36 -0
  86. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/StrikethroughStyleHandler.kt +24 -0
  87. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/StyleHandler.kt +18 -0
  88. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/StyleMergingConfig.kt +10 -0
  89. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/UnderlineStyleHandler.kt +24 -0
  90. package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +181 -0
  91. package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +43 -0
  92. package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +68 -0
  93. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BaselineShiftRenderer.kt +44 -0
  94. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +152 -0
  95. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +87 -0
  96. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +104 -0
  97. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeRenderer.kt +36 -0
  98. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/DocumentRenderer.kt +16 -0
  99. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/EmphasisRenderer.kt +27 -0
  100. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +71 -0
  101. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HighlightRenderer.kt +25 -0
  102. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ImageRenderer.kt +61 -0
  103. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LineBreakRenderer.kt +16 -0
  104. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LinkRenderer.kt +29 -0
  105. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +89 -0
  106. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +127 -0
  107. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +74 -0
  108. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +161 -0
  109. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ParagraphRenderer.kt +75 -0
  110. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/Renderer.kt +113 -0
  111. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +134 -0
  112. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpoilerRenderer.kt +25 -0
  113. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/StrikethroughRenderer.kt +27 -0
  114. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/StrongRenderer.kt +27 -0
  115. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SubscriptRenderer.kt +11 -0
  116. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SuperscriptRenderer.kt +11 -0
  117. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/TextRenderer.kt +30 -0
  118. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ThematicBreakRenderer.kt +45 -0
  119. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/UnderlineRenderer.kt +27 -0
  120. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +127 -0
  121. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaselineShiftSpan.kt +27 -0
  122. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +152 -0
  123. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +180 -0
  124. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +196 -0
  125. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +32 -0
  126. package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +42 -0
  127. package/android/src/main/java/com/swmansion/enriched/markdown/spans/FadeInSpan.kt +25 -0
  128. package/android/src/main/java/com/swmansion/enriched/markdown/spans/HeadingSpan.kt +38 -0
  129. package/android/src/main/java/com/swmansion/enriched/markdown/spans/HighlightSpan.kt +26 -0
  130. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +335 -0
  131. package/android/src/main/java/com/swmansion/enriched/markdown/spans/LineHeightSpan.kt +27 -0
  132. package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkSpan.kt +66 -0
  133. package/android/src/main/java/com/swmansion/enriched/markdown/spans/MarginBottomSpan.kt +76 -0
  134. package/android/src/main/java/com/swmansion/enriched/markdown/spans/MathModels.kt +18 -0
  135. package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +85 -0
  136. package/android/src/main/java/com/swmansion/enriched/markdown/spans/SpoilerSpan.kt +33 -0
  137. package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrikethroughSpan.kt +12 -0
  138. package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +39 -0
  139. package/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +134 -0
  140. package/android/src/main/java/com/swmansion/enriched/markdown/spans/TextSpan.kt +26 -0
  141. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ThematicBreakSpan.kt +69 -0
  142. package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +92 -0
  143. package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/ParticleStrategy.kt +68 -0
  144. package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SegmentKey.kt +13 -0
  145. package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SolidStrategy.kt +95 -0
  146. package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerAnimator.kt +89 -0
  147. package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerCapable.kt +5 -0
  148. package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerConstants.kt +3 -0
  149. package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerDrawContext.kt +33 -0
  150. package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerDrawUtils.kt +40 -0
  151. package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerOverlay.kt +17 -0
  152. package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerOverlayDrawer.kt +152 -0
  153. package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerParticleDrawable.kt +237 -0
  154. package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerStrategy.kt +53 -0
  155. package/android/src/main/java/com/swmansion/enriched/markdown/styles/BaseBlockStyle.kt +11 -0
  156. package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +51 -0
  157. package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +54 -0
  158. package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeStyle.kt +26 -0
  159. package/android/src/main/java/com/swmansion/enriched/markdown/styles/EmphasisStyle.kt +21 -0
  160. package/android/src/main/java/com/swmansion/enriched/markdown/styles/HeadingStyle.kt +33 -0
  161. package/android/src/main/java/com/swmansion/enriched/markdown/styles/HighlightStyle.kt +19 -0
  162. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +23 -0
  163. package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineImageStyle.kt +17 -0
  164. package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineMathStyle.kt +17 -0
  165. package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkStyle.kt +23 -0
  166. package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkVariantEntry.kt +29 -0
  167. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +62 -0
  168. package/android/src/main/java/com/swmansion/enriched/markdown/styles/MathStyle.kt +29 -0
  169. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ParagraphStyle.kt +33 -0
  170. package/android/src/main/java/com/swmansion/enriched/markdown/styles/SpoilerStyle.kt +27 -0
  171. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StrikethroughStyle.kt +17 -0
  172. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StrongStyle.kt +21 -0
  173. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +364 -0
  174. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleParser.kt +92 -0
  175. package/android/src/main/java/com/swmansion/enriched/markdown/styles/SubscriptStyle.kt +16 -0
  176. package/android/src/main/java/com/swmansion/enriched/markdown/styles/SuperscriptStyle.kt +16 -0
  177. package/android/src/main/java/com/swmansion/enriched/markdown/styles/TableStyle.kt +69 -0
  178. package/android/src/main/java/com/swmansion/enriched/markdown/styles/TaskListStyle.kt +29 -0
  179. package/android/src/main/java/com/swmansion/enriched/markdown/styles/TextAlignment.kt +32 -0
  180. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ThematicBreakStyle.kt +23 -0
  181. package/android/src/main/java/com/swmansion/enriched/markdown/styles/UnderlineStyle.kt +17 -0
  182. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/BreakStrategyUtils.kt +32 -0
  183. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/FeatureFlags.kt +7 -0
  184. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownSegment.kt +56 -0
  185. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +100 -0
  186. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MotionPreferences.kt +18 -0
  187. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/ReadableMapExtensions.kt +20 -0
  188. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/RenderedSegment.kt +78 -0
  189. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentReconciler.kt +118 -0
  190. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentSignature.kt +78 -0
  191. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/StreamingMarkdownFilter.kt +142 -0
  192. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/layout/RTLUtils.kt +6 -0
  193. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt +115 -0
  194. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/AutoCapitalizeUtils.kt +27 -0
  195. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/BorderPropsApplicator.kt +77 -0
  196. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +184 -0
  197. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageCache.kt +53 -0
  198. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageDownloader.kt +156 -0
  199. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/TailFadeInAnimator.kt +84 -0
  200. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/HTMLGenerator.kt +1067 -0
  201. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/MarkdownExtractor.kt +419 -0
  202. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/ParagraphUtils.kt +9 -0
  203. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/SpannableExtensions.kt +65 -0
  204. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/TextPaintExtensions.kt +53 -0
  205. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/CheckboxTouchHelper.kt +54 -0
  206. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +249 -0
  207. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/BlockSpacing.kt +89 -0
  208. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/SpanFlags.kt +17 -0
  209. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkEvents.kt +43 -0
  210. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLongPressMovementMethod.kt +187 -0
  211. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +205 -0
  212. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/TextSelectionColors.kt +48 -0
  213. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/TextViewSetup.kt +40 -0
  214. package/android/src/main/java/com/swmansion/enriched/markdown/views/BlockSegmentView.kt +10 -0
  215. package/android/src/main/java/com/swmansion/enriched/markdown/views/ContextMenuPopup.kt +214 -0
  216. package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +501 -0
  217. package/android/src/main/jni/CMakeLists.txt +70 -0
  218. package/android/src/main/jni/EnrichedMarkdownTextSpec.cpp +21 -0
  219. package/android/src/main/jni/EnrichedMarkdownTextSpec.h +15 -0
  220. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/ComponentDescriptors.h +67 -0
  221. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerComponentDescriptor.h +26 -0
  222. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerMeasurementManager.cpp +45 -0
  223. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerMeasurementManager.h +21 -0
  224. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.cpp +20 -0
  225. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.h +34 -0
  226. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextComponentDescriptor.h +29 -0
  227. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextInputMeasurementManager.cpp +44 -0
  228. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextInputMeasurementManager.h +21 -0
  229. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextInputShadowNode.cpp +30 -0
  230. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextInputShadowNode.h +43 -0
  231. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextInputState.cpp +9 -0
  232. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextInputState.h +24 -0
  233. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextMeasurementManager.cpp +45 -0
  234. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextMeasurementManager.h +21 -0
  235. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +20 -0
  236. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +37 -0
  237. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +45 -0
  238. package/android/src/math/java/com/swmansion/enriched/markdown/input/math/MathChipControllerImpl.kt +217 -0
  239. package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +47 -0
  240. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +208 -0
  241. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlinePlaceholderSpan.kt +41 -0
  242. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlineSpan.kt +92 -0
  243. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathMeasureHelper.kt +57 -0
  244. package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +148 -0
  245. package/app.plugin.js +1 -0
  246. package/cpp/md4c/md4c.c +7235 -0
  247. package/cpp/md4c/md4c.h +475 -0
  248. package/cpp/parser/MD4CParser.cpp +539 -0
  249. package/cpp/parser/MD4CParser.hpp +32 -0
  250. package/cpp/parser/MarkdownASTNode.hpp +63 -0
  251. package/cpp/wasm/ASTSerializer.cpp +158 -0
  252. package/cpp/wasm/ASTSerializer.hpp +17 -0
  253. package/cpp/wasm/build.sh +58 -0
  254. package/cpp/wasm/md4c_wasm.cpp +43 -0
  255. package/ios/EnrichedMarkdown.h +20 -0
  256. package/ios/EnrichedMarkdown.mm +1121 -0
  257. package/ios/EnrichedMarkdownText.h +20 -0
  258. package/ios/EnrichedMarkdownText.mm +802 -0
  259. package/ios/attachments/ENRMImageAttachment.h +27 -0
  260. package/ios/attachments/ENRMImageAttachment.m +305 -0
  261. package/ios/attachments/ENRMMathInlineAttachment+macOS.m +60 -0
  262. package/ios/attachments/ENRMMathInlineAttachment.h +47 -0
  263. package/ios/attachments/ENRMMathInlineAttachment.m +142 -0
  264. package/ios/attachments/ENRMMathInlineAttachmentShared.h +17 -0
  265. package/ios/attachments/ThematicBreakAttachment.h +15 -0
  266. package/ios/attachments/ThematicBreakAttachment.m +33 -0
  267. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/ComponentDescriptors.cpp +22 -0
  268. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/ComponentDescriptors.h +24 -0
  269. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +318 -0
  270. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +259 -0
  271. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +375 -0
  272. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +5174 -0
  273. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +436 -0
  274. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/ShadowNodes.cpp +17 -0
  275. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/ShadowNodes.h +23 -0
  276. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/States.cpp +16 -0
  277. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/States.h +20 -0
  278. package/ios/input/ENRMAutoLinkDetector.h +32 -0
  279. package/ios/input/ENRMAutoLinkDetector.mm +211 -0
  280. package/ios/input/ENRMDetectorPipeline.h +28 -0
  281. package/ios/input/ENRMDetectorPipeline.mm +53 -0
  282. package/ios/input/ENRMFormattingRange.h +19 -0
  283. package/ios/input/ENRMFormattingRange.mm +28 -0
  284. package/ios/input/ENRMFormattingStore.h +29 -0
  285. package/ios/input/ENRMFormattingStore.mm +278 -0
  286. package/ios/input/ENRMInputFormatter.h +84 -0
  287. package/ios/input/ENRMInputFormatter.mm +222 -0
  288. package/ios/input/ENRMInputLayoutManager.h +11 -0
  289. package/ios/input/ENRMInputLayoutManager.mm +5 -0
  290. package/ios/input/ENRMInputLinkPrompt.h +9 -0
  291. package/ios/input/ENRMInputLinkPrompt.mm +71 -0
  292. package/ios/input/ENRMInputMentionCandidate.h +21 -0
  293. package/ios/input/ENRMInputMentionCandidate.mm +18 -0
  294. package/ios/input/ENRMInputParser.h +27 -0
  295. package/ios/input/ENRMInputParser.mm +556 -0
  296. package/ios/input/ENRMInputRemend.h +9 -0
  297. package/ios/input/ENRMInputRemend.mm +136 -0
  298. package/ios/input/ENRMInputStyledRange.h +29 -0
  299. package/ios/input/ENRMInputStyledRange.mm +4 -0
  300. package/ios/input/ENRMInputTextView.h +13 -0
  301. package/ios/input/ENRMInputTextView.mm +175 -0
  302. package/ios/input/ENRMLinkRegexConfig.h +26 -0
  303. package/ios/input/ENRMLinkRegexConfig.mm +60 -0
  304. package/ios/input/ENRMMarkdownSerializer.h +19 -0
  305. package/ios/input/ENRMMarkdownSerializer.mm +283 -0
  306. package/ios/input/ENRMTextDetector.h +30 -0
  307. package/ios/input/ENRMWordsUtils.h +28 -0
  308. package/ios/input/ENRMWordsUtils.mm +88 -0
  309. package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +157 -0
  310. package/ios/input/EnrichedMarkdownTextInput+Internal.h +30 -0
  311. package/ios/input/EnrichedMarkdownTextInput.h +20 -0
  312. package/ios/input/EnrichedMarkdownTextInput.mm +2008 -0
  313. package/ios/input/InputStylePropsUtils.h +261 -0
  314. package/ios/input/internals/EnrichedMarkdownTextInputComponentDescriptor.h +19 -0
  315. package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.h +40 -0
  316. package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.mm +83 -0
  317. package/ios/input/internals/EnrichedMarkdownTextInputState.h +23 -0
  318. package/ios/input/styles/ENRMBoldStyleHandler.h +10 -0
  319. package/ios/input/styles/ENRMBoldStyleHandler.mm +29 -0
  320. package/ios/input/styles/ENRMItalicStyleHandler.h +10 -0
  321. package/ios/input/styles/ENRMItalicStyleHandler.mm +29 -0
  322. package/ios/input/styles/ENRMLinkStyleHandler.h +10 -0
  323. package/ios/input/styles/ENRMLinkStyleHandler.mm +52 -0
  324. package/ios/input/styles/ENRMSpoilerStyleHandler.h +10 -0
  325. package/ios/input/styles/ENRMSpoilerStyleHandler.mm +33 -0
  326. package/ios/input/styles/ENRMStrikethroughStyleHandler.h +10 -0
  327. package/ios/input/styles/ENRMStrikethroughStyleHandler.mm +28 -0
  328. package/ios/input/styles/ENRMStyleHandler.h +26 -0
  329. package/ios/input/styles/ENRMStyleMergingConfig.h +26 -0
  330. package/ios/input/styles/ENRMStyleMergingConfig.mm +21 -0
  331. package/ios/input/styles/ENRMUnderlineStyleHandler.h +10 -0
  332. package/ios/input/styles/ENRMUnderlineStyleHandler.mm +28 -0
  333. package/ios/internals/EnrichedMarkdownComponentDescriptor.h +18 -0
  334. package/ios/internals/EnrichedMarkdownShadowNode.h +43 -0
  335. package/ios/internals/EnrichedMarkdownShadowNode.mm +73 -0
  336. package/ios/internals/EnrichedMarkdownState.h +23 -0
  337. package/ios/internals/EnrichedMarkdownTextComponentDescriptor.h +19 -0
  338. package/ios/internals/EnrichedMarkdownTextShadowNode.h +45 -0
  339. package/ios/internals/EnrichedMarkdownTextShadowNode.mm +74 -0
  340. package/ios/internals/EnrichedMarkdownTextState.h +24 -0
  341. package/ios/internals/MeasurementCache.h +223 -0
  342. package/ios/internals/ShadowMeasurementUtils.h +135 -0
  343. package/ios/math/ENRMRaTeXBridge.swift +58 -0
  344. package/ios/parser/ENRMMarkdownParser.h +21 -0
  345. package/ios/parser/ENRMMarkdownParser.mm +50 -0
  346. package/ios/parser/MarkdownASTNode.h +47 -0
  347. package/ios/parser/MarkdownASTNode.m +32 -0
  348. package/ios/parser/MarkdownParserBridge.mm +161 -0
  349. package/ios/renderer/AttributedRenderer.h +11 -0
  350. package/ios/renderer/AttributedRenderer.m +153 -0
  351. package/ios/renderer/BaseRenderer.h +18 -0
  352. package/ios/renderer/BaseRenderer.m +16 -0
  353. package/ios/renderer/BaselineShiftTextAttributes.h +6 -0
  354. package/ios/renderer/BaselineShiftTextAttributes.m +22 -0
  355. package/ios/renderer/BlockquoteRenderer.h +6 -0
  356. package/ios/renderer/BlockquoteRenderer.m +148 -0
  357. package/ios/renderer/CodeBlockRenderer.h +9 -0
  358. package/ios/renderer/CodeBlockRenderer.m +90 -0
  359. package/ios/renderer/CodeRenderer.h +9 -0
  360. package/ios/renderer/CodeRenderer.m +64 -0
  361. package/ios/renderer/ENRMImageRenderer.h +9 -0
  362. package/ios/renderer/ENRMImageRenderer.m +65 -0
  363. package/ios/renderer/ENRMMathInlineRenderer.h +9 -0
  364. package/ios/renderer/ENRMMathInlineRenderer.m +56 -0
  365. package/ios/renderer/ENRMSpoilerRenderer.h +5 -0
  366. package/ios/renderer/ENRMSpoilerRenderer.m +32 -0
  367. package/ios/renderer/EmphasisRenderer.h +5 -0
  368. package/ios/renderer/EmphasisRenderer.m +98 -0
  369. package/ios/renderer/HeadingRenderer.h +6 -0
  370. package/ios/renderer/HeadingRenderer.m +94 -0
  371. package/ios/renderer/HighlightRenderer.h +7 -0
  372. package/ios/renderer/HighlightRenderer.m +31 -0
  373. package/ios/renderer/LinkRenderer.h +6 -0
  374. package/ios/renderer/LinkRenderer.m +82 -0
  375. package/ios/renderer/ListItemRenderer.h +12 -0
  376. package/ios/renderer/ListItemRenderer.m +175 -0
  377. package/ios/renderer/ListRenderer.h +13 -0
  378. package/ios/renderer/ListRenderer.m +70 -0
  379. package/ios/renderer/NodeRenderer.h +8 -0
  380. package/ios/renderer/ParagraphRenderer.h +6 -0
  381. package/ios/renderer/ParagraphRenderer.m +70 -0
  382. package/ios/renderer/RenderContext.h +118 -0
  383. package/ios/renderer/RenderContext.m +337 -0
  384. package/ios/renderer/RendererFactory.h +12 -0
  385. package/ios/renderer/RendererFactory.m +147 -0
  386. package/ios/renderer/StrikethroughRenderer.h +5 -0
  387. package/ios/renderer/StrikethroughRenderer.m +28 -0
  388. package/ios/renderer/StrongRenderer.h +5 -0
  389. package/ios/renderer/StrongRenderer.m +86 -0
  390. package/ios/renderer/SubscriptRenderer.h +5 -0
  391. package/ios/renderer/SubscriptRenderer.m +22 -0
  392. package/ios/renderer/SuperscriptRenderer.h +5 -0
  393. package/ios/renderer/SuperscriptRenderer.m +22 -0
  394. package/ios/renderer/TextRenderer.h +6 -0
  395. package/ios/renderer/TextRenderer.m +16 -0
  396. package/ios/renderer/ThematicBreakRenderer.h +4 -0
  397. package/ios/renderer/ThematicBreakRenderer.m +40 -0
  398. package/ios/renderer/UnderlineRenderer.h +4 -0
  399. package/ios/renderer/UnderlineRenderer.m +27 -0
  400. package/ios/styles/ENRMFontSlot.h +12 -0
  401. package/ios/styles/ENRMFontSlot.m +24 -0
  402. package/ios/styles/StyleConfig.h +407 -0
  403. package/ios/styles/StyleConfig.mm +2515 -0
  404. package/ios/utils/AccessibilityInfo.h +35 -0
  405. package/ios/utils/AccessibilityInfo.m +24 -0
  406. package/ios/utils/BlockquoteBorder.h +20 -0
  407. package/ios/utils/BlockquoteBorder.m +97 -0
  408. package/ios/utils/CodeBackground.h +19 -0
  409. package/ios/utils/CodeBackground.m +197 -0
  410. package/ios/utils/CodeBlockBackground.h +17 -0
  411. package/ios/utils/CodeBlockBackground.m +89 -0
  412. package/ios/utils/ContextMenuUtils.h +76 -0
  413. package/ios/utils/ContextMenuUtils.mm +73 -0
  414. package/ios/utils/ENRMAsyncRenderCoordinator.h +24 -0
  415. package/ios/utils/ENRMAsyncRenderCoordinator.m +37 -0
  416. package/ios/utils/ENRMFeatureFlags.h +12 -0
  417. package/ios/utils/ENRMImageDownloader.h +16 -0
  418. package/ios/utils/ENRMImageDownloader.m +108 -0
  419. package/ios/utils/ENRMMenuAction.h +27 -0
  420. package/ios/utils/ENRMMenuAction.m +33 -0
  421. package/ios/utils/ENRMParticleOverlayView.h +12 -0
  422. package/ios/utils/ENRMParticleOverlayView.m +159 -0
  423. package/ios/utils/ENRMSolidOverlayView.h +12 -0
  424. package/ios/utils/ENRMSolidOverlayView.m +25 -0
  425. package/ios/utils/ENRMSpoilerCapable.h +15 -0
  426. package/ios/utils/ENRMSpoilerOverlayManager.h +21 -0
  427. package/ios/utils/ENRMSpoilerOverlayManager.m +181 -0
  428. package/ios/utils/ENRMSpoilerOverlayView.h +49 -0
  429. package/ios/utils/ENRMSpoilerOverlayView.m +144 -0
  430. package/ios/utils/ENRMSpoilerTapUtils.h +25 -0
  431. package/ios/utils/ENRMSpoilerTapUtils.m +68 -0
  432. package/ios/utils/ENRMTailFadeInAnimator.h +16 -0
  433. package/ios/utils/ENRMTailFadeInAnimator.m +161 -0
  434. package/ios/utils/ENRMTextHitTest.h +23 -0
  435. package/ios/utils/ENRMTextHitTest.m +20 -0
  436. package/ios/utils/ENRMTextInteractionUtils.h +20 -0
  437. package/ios/utils/ENRMTextInteractionUtils.m +15 -0
  438. package/ios/utils/ENRMTextRenderer.h +30 -0
  439. package/ios/utils/ENRMTextRenderer.m +38 -0
  440. package/ios/utils/ENRMTextViewSetup.h +78 -0
  441. package/ios/utils/ENRMUIKit.h +418 -0
  442. package/ios/utils/EditMenuUtils+macOS.m +60 -0
  443. package/ios/utils/EditMenuUtils.h +35 -0
  444. package/ios/utils/EditMenuUtils.m +119 -0
  445. package/ios/utils/FontScaleObserver.h +10 -0
  446. package/ios/utils/FontScaleObserver.m +55 -0
  447. package/ios/utils/FontUtils.h +30 -0
  448. package/ios/utils/FontUtils.m +47 -0
  449. package/ios/utils/HTMLGenerator.h +25 -0
  450. package/ios/utils/HTMLGenerator.m +1019 -0
  451. package/ios/utils/HeightUpdateUtils.h +25 -0
  452. package/ios/utils/LastElementUtils.h +53 -0
  453. package/ios/utils/LinkTapUtils.h +24 -0
  454. package/ios/utils/LinkTapUtils.m +32 -0
  455. package/ios/utils/ListMarkerDrawer.h +15 -0
  456. package/ios/utils/ListMarkerDrawer.m +212 -0
  457. package/ios/utils/MarkdownASTSerializer.h +24 -0
  458. package/ios/utils/MarkdownASTSerializer.m +114 -0
  459. package/ios/utils/MarkdownAccessibilityElementBuilder.h +41 -0
  460. package/ios/utils/MarkdownAccessibilityElementBuilder.m +450 -0
  461. package/ios/utils/MarkdownExtractor.h +17 -0
  462. package/ios/utils/MarkdownExtractor.m +355 -0
  463. package/ios/utils/ParagraphStyleUtils.h +53 -0
  464. package/ios/utils/ParagraphStyleUtils.m +349 -0
  465. package/ios/utils/PasteboardUtils.h +48 -0
  466. package/ios/utils/PasteboardUtils.m +162 -0
  467. package/ios/utils/RTFExportUtils.h +24 -0
  468. package/ios/utils/RTFExportUtils.m +297 -0
  469. package/ios/utils/RenderedMarkdownSegment.h +49 -0
  470. package/ios/utils/RenderedMarkdownSegment.m +130 -0
  471. package/ios/utils/RuntimeKeys.h +38 -0
  472. package/ios/utils/RuntimeKeys.m +11 -0
  473. package/ios/utils/SegmentReconciler.h +32 -0
  474. package/ios/utils/SegmentReconciler.m +118 -0
  475. package/ios/utils/SegmentRenderer.h +24 -0
  476. package/ios/utils/SegmentRenderer.m +88 -0
  477. package/ios/utils/SegmentViewRegistry.h +36 -0
  478. package/ios/utils/SegmentViewRegistry.m +67 -0
  479. package/ios/utils/SelectionColorUtils.h +14 -0
  480. package/ios/utils/StreamingMarkdownFilter.h +22 -0
  481. package/ios/utils/StreamingMarkdownFilter.m +165 -0
  482. package/ios/utils/StylePropsUtils.h +1146 -0
  483. package/ios/utils/TaskListTapUtils.h +43 -0
  484. package/ios/utils/TaskListTapUtils.m +227 -0
  485. package/ios/utils/TextViewLayoutManager.h +14 -0
  486. package/ios/utils/TextViewLayoutManager.mm +113 -0
  487. package/ios/views/ENRMContextMenuTextView+macOS.h +17 -0
  488. package/ios/views/ENRMContextMenuTextView+macOS.m +97 -0
  489. package/ios/views/ENRMMathContainerView.h +20 -0
  490. package/ios/views/ENRMMathContainerView.m +227 -0
  491. package/ios/views/ENRMTableGridView.h +36 -0
  492. package/ios/views/ENRMTableGridView.m +98 -0
  493. package/ios/views/EnrichedMarkdownInternalText.h +42 -0
  494. package/ios/views/EnrichedMarkdownInternalText.m +161 -0
  495. package/ios/views/TableContainerView.h +39 -0
  496. package/ios/views/TableContainerView.m +686 -0
  497. package/lib/module/EnrichedMarkdownNativeComponent.ts +429 -0
  498. package/lib/module/EnrichedMarkdownTextInput.js +310 -0
  499. package/lib/module/EnrichedMarkdownTextInput.js.map +1 -0
  500. package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +364 -0
  501. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +428 -0
  502. package/lib/module/index.js +5 -0
  503. package/lib/module/index.js.map +1 -0
  504. package/lib/module/index.web.js +4 -0
  505. package/lib/module/index.web.js.map +1 -0
  506. package/lib/module/linkVariantUtils.js +28 -0
  507. package/lib/module/linkVariantUtils.js.map +1 -0
  508. package/lib/module/native/EnrichedMarkdownText.js +158 -0
  509. package/lib/module/native/EnrichedMarkdownText.js.map +1 -0
  510. package/lib/module/normalizeMarkdownStyle.js +337 -0
  511. package/lib/module/normalizeMarkdownStyle.js.map +1 -0
  512. package/lib/module/normalizeMarkdownStyle.web.js +264 -0
  513. package/lib/module/normalizeMarkdownStyle.web.js.map +1 -0
  514. package/lib/module/normalizeMarkdownTextInputStyle.js +146 -0
  515. package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -0
  516. package/lib/module/package.json +1 -0
  517. package/lib/module/plugin/withAndroidMath.js +20 -0
  518. package/lib/module/plugin/withAndroidMath.js.map +1 -0
  519. package/lib/module/plugin/withIosMath.js +23 -0
  520. package/lib/module/plugin/withIosMath.js.map +1 -0
  521. package/lib/module/plugin/withReactNativeEnrichedMarkdown.js +16 -0
  522. package/lib/module/plugin/withReactNativeEnrichedMarkdown.js.map +1 -0
  523. package/lib/module/styleUtils.js +64 -0
  524. package/lib/module/styleUtils.js.map +1 -0
  525. package/lib/module/types/MarkdownStyle.js +2 -0
  526. package/lib/module/types/MarkdownStyle.js.map +1 -0
  527. package/lib/module/types/MarkdownStyleInternal.js +2 -0
  528. package/lib/module/types/MarkdownStyleInternal.js.map +1 -0
  529. package/lib/module/types/MarkdownTextProps.js +4 -0
  530. package/lib/module/types/MarkdownTextProps.js.map +1 -0
  531. package/lib/module/types/MarkdownTextProps.web.js +4 -0
  532. package/lib/module/types/MarkdownTextProps.web.js.map +1 -0
  533. package/lib/module/types/events.js +2 -0
  534. package/lib/module/types/events.js.map +1 -0
  535. package/lib/module/utils/regexParser.js +43 -0
  536. package/lib/module/utils/regexParser.js.map +1 -0
  537. package/lib/module/web/EnrichedMarkdownText.js +120 -0
  538. package/lib/module/web/EnrichedMarkdownText.js.map +1 -0
  539. package/lib/module/web/globalStyles.js +10 -0
  540. package/lib/module/web/globalStyles.js.map +1 -0
  541. package/lib/module/web/injectStyle.js +20 -0
  542. package/lib/module/web/injectStyle.js.map +1 -0
  543. package/lib/module/web/katex.js +22 -0
  544. package/lib/module/web/katex.js.map +1 -0
  545. package/lib/module/web/parseMarkdown.js +35 -0
  546. package/lib/module/web/parseMarkdown.js.map +1 -0
  547. package/lib/module/web/renderers/BlockRenderers.js +115 -0
  548. package/lib/module/web/renderers/BlockRenderers.js.map +1 -0
  549. package/lib/module/web/renderers/InlineRenderers.js +160 -0
  550. package/lib/module/web/renderers/InlineRenderers.js.map +1 -0
  551. package/lib/module/web/renderers/KaTeXRenderer.js +43 -0
  552. package/lib/module/web/renderers/KaTeXRenderer.js.map +1 -0
  553. package/lib/module/web/renderers/ListRenderers.js +92 -0
  554. package/lib/module/web/renderers/ListRenderers.js.map +1 -0
  555. package/lib/module/web/renderers/TableRenderers.js +77 -0
  556. package/lib/module/web/renderers/TableRenderers.js.map +1 -0
  557. package/lib/module/web/renderers/index.js +49 -0
  558. package/lib/module/web/renderers/index.js.map +1 -0
  559. package/lib/module/web/styles.js +454 -0
  560. package/lib/module/web/styles.js.map +1 -0
  561. package/lib/module/web/types.js +4 -0
  562. package/lib/module/web/types.js.map +1 -0
  563. package/lib/module/web/utils.js +56 -0
  564. package/lib/module/web/utils.js.map +1 -0
  565. package/lib/module/web/wasm/md4c.d.js +4 -0
  566. package/lib/module/web/wasm/md4c.d.js.map +1 -0
  567. package/lib/module/web/wasm/md4c.js +0 -0
  568. package/lib/module/web/wasm/md4c.js.map +1 -0
  569. package/lib/typescript/package.json +1 -0
  570. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +384 -0
  571. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -0
  572. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +173 -0
  573. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -0
  574. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +285 -0
  575. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -0
  576. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +384 -0
  577. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -0
  578. package/lib/typescript/src/index.d.ts +6 -0
  579. package/lib/typescript/src/index.d.ts.map +1 -0
  580. package/lib/typescript/src/index.web.d.ts +5 -0
  581. package/lib/typescript/src/index.web.d.ts.map +1 -0
  582. package/lib/typescript/src/linkVariantUtils.d.ts +5 -0
  583. package/lib/typescript/src/linkVariantUtils.d.ts.map +1 -0
  584. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +9 -0
  585. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -0
  586. package/lib/typescript/src/normalizeMarkdownStyle.d.ts +4 -0
  587. package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -0
  588. package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts +4 -0
  589. package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -0
  590. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +48 -0
  591. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -0
  592. package/lib/typescript/src/plugin/withAndroidMath.d.ts +5 -0
  593. package/lib/typescript/src/plugin/withAndroidMath.d.ts.map +1 -0
  594. package/lib/typescript/src/plugin/withIosMath.d.ts +5 -0
  595. package/lib/typescript/src/plugin/withIosMath.d.ts.map +1 -0
  596. package/lib/typescript/src/plugin/withReactNativeEnrichedMarkdown.d.ts +6 -0
  597. package/lib/typescript/src/plugin/withReactNativeEnrichedMarkdown.d.ts.map +1 -0
  598. package/lib/typescript/src/styleUtils.d.ts +6 -0
  599. package/lib/typescript/src/styleUtils.d.ts.map +1 -0
  600. package/lib/typescript/src/types/MarkdownStyle.d.ts +300 -0
  601. package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -0
  602. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +178 -0
  603. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -0
  604. package/lib/typescript/src/types/MarkdownTextProps.d.ts +249 -0
  605. package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -0
  606. package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +83 -0
  607. package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -0
  608. package/lib/typescript/src/types/events.d.ts +29 -0
  609. package/lib/typescript/src/types/events.d.ts.map +1 -0
  610. package/lib/typescript/src/utils/regexParser.d.ts +3 -0
  611. package/lib/typescript/src/utils/regexParser.d.ts.map +1 -0
  612. package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +4 -0
  613. package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -0
  614. package/lib/typescript/src/web/globalStyles.d.ts +3 -0
  615. package/lib/typescript/src/web/globalStyles.d.ts.map +1 -0
  616. package/lib/typescript/src/web/injectStyle.d.ts +9 -0
  617. package/lib/typescript/src/web/injectStyle.d.ts.map +1 -0
  618. package/lib/typescript/src/web/katex.d.ts +11 -0
  619. package/lib/typescript/src/web/katex.d.ts.map +1 -0
  620. package/lib/typescript/src/web/parseMarkdown.d.ts +4 -0
  621. package/lib/typescript/src/web/parseMarkdown.d.ts.map +1 -0
  622. package/lib/typescript/src/web/renderers/BlockRenderers.d.ts +3 -0
  623. package/lib/typescript/src/web/renderers/BlockRenderers.d.ts.map +1 -0
  624. package/lib/typescript/src/web/renderers/InlineRenderers.d.ts +3 -0
  625. package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -0
  626. package/lib/typescript/src/web/renderers/KaTeXRenderer.d.ts +11 -0
  627. package/lib/typescript/src/web/renderers/KaTeXRenderer.d.ts.map +1 -0
  628. package/lib/typescript/src/web/renderers/ListRenderers.d.ts +3 -0
  629. package/lib/typescript/src/web/renderers/ListRenderers.d.ts.map +1 -0
  630. package/lib/typescript/src/web/renderers/TableRenderers.d.ts +3 -0
  631. package/lib/typescript/src/web/renderers/TableRenderers.d.ts.map +1 -0
  632. package/lib/typescript/src/web/renderers/index.d.ts +14 -0
  633. package/lib/typescript/src/web/renderers/index.d.ts.map +1 -0
  634. package/lib/typescript/src/web/styles.d.ts +49 -0
  635. package/lib/typescript/src/web/styles.d.ts.map +1 -0
  636. package/lib/typescript/src/web/types.d.ts +51 -0
  637. package/lib/typescript/src/web/types.d.ts.map +1 -0
  638. package/lib/typescript/src/web/utils.d.ts +21 -0
  639. package/lib/typescript/src/web/utils.d.ts.map +1 -0
  640. package/package.json +125 -0
  641. package/react-native.config.js +17 -0
  642. package/src/EnrichedMarkdownNativeComponent.ts +429 -0
  643. package/src/EnrichedMarkdownTextInput.tsx +547 -0
  644. package/src/EnrichedMarkdownTextInputNativeComponent.ts +364 -0
  645. package/src/EnrichedMarkdownTextNativeComponent.ts +428 -0
  646. package/src/index.tsx +28 -0
  647. package/src/index.web.tsx +8 -0
  648. package/src/linkVariantUtils.ts +42 -0
  649. package/src/native/EnrichedMarkdownText.tsx +187 -0
  650. package/src/normalizeMarkdownStyle.ts +310 -0
  651. package/src/normalizeMarkdownStyle.web.ts +281 -0
  652. package/src/normalizeMarkdownTextInputStyle.ts +242 -0
  653. package/src/plugin/withAndroidMath.ts +24 -0
  654. package/src/plugin/withIosMath.ts +35 -0
  655. package/src/plugin/withReactNativeEnrichedMarkdown.ts +17 -0
  656. package/src/styleUtils.ts +98 -0
  657. package/src/types/MarkdownStyle.ts +326 -0
  658. package/src/types/MarkdownStyleInternal.ts +208 -0
  659. package/src/types/MarkdownTextProps.ts +253 -0
  660. package/src/types/MarkdownTextProps.web.ts +90 -0
  661. package/src/types/events.ts +32 -0
  662. package/src/utils/regexParser.ts +54 -0
  663. package/src/web/EnrichedMarkdownText.tsx +154 -0
  664. package/src/web/globalStyles.ts +15 -0
  665. package/src/web/injectStyle.ts +17 -0
  666. package/src/web/katex.ts +31 -0
  667. package/src/web/parseMarkdown.ts +78 -0
  668. package/src/web/renderers/BlockRenderers.tsx +90 -0
  669. package/src/web/renderers/InlineRenderers.tsx +121 -0
  670. package/src/web/renderers/KaTeXRenderer.tsx +49 -0
  671. package/src/web/renderers/ListRenderers.tsx +110 -0
  672. package/src/web/renderers/TableRenderers.tsx +61 -0
  673. package/src/web/renderers/index.tsx +75 -0
  674. package/src/web/styles.ts +549 -0
  675. package/src/web/types.ts +92 -0
  676. package/src/web/utils.ts +52 -0
  677. package/src/web/wasm/md4c.d.ts +21 -0
  678. package/src/web/wasm/md4c.js +0 -0
@@ -0,0 +1,1066 @@
1
+ package com.swmansion.enriched.markdown.input
2
+
3
+ import android.content.Context
4
+ import android.graphics.BlendMode
5
+ import android.graphics.BlendModeColorFilter
6
+ import android.graphics.Color
7
+ import android.graphics.Rect
8
+ import android.os.Build
9
+ import android.text.Editable
10
+ import android.text.InputType
11
+ import android.text.Layout
12
+ import android.util.TypedValue
13
+ import android.view.Gravity
14
+ import android.view.KeyEvent
15
+ import android.view.MotionEvent
16
+ import android.view.View.OnFocusChangeListener
17
+ import android.view.inputmethod.EditorInfo
18
+ import android.view.inputmethod.InputConnection
19
+ import android.view.inputmethod.InputMethodManager
20
+ import androidx.appcompat.widget.AppCompatEditText
21
+ import com.facebook.react.common.ReactConstants
22
+ import com.facebook.react.uimanager.BackgroundStyleApplicator
23
+ import com.facebook.react.uimanager.PixelUtil
24
+ import com.facebook.react.uimanager.StateWrapper
25
+ import com.facebook.react.views.text.ReactTypefaceUtils
26
+ import com.swmansion.enriched.markdown.input.autolink.AutoLinkDetector
27
+ import com.swmansion.enriched.markdown.input.autolink.LinkRegexConfig
28
+ import com.swmansion.enriched.markdown.input.detection.DetectorPipeline
29
+ import com.swmansion.enriched.markdown.input.detection.WordsUtils
30
+ import com.swmansion.enriched.markdown.input.editing.InputConnectionWrapper
31
+ import com.swmansion.enriched.markdown.input.editing.MarkdownEditableFactory
32
+ import com.swmansion.enriched.markdown.input.editing.MarkdownTextWatcher
33
+ import com.swmansion.enriched.markdown.input.formatting.FormattingStore
34
+ import com.swmansion.enriched.markdown.input.formatting.InputFormatter
35
+ import com.swmansion.enriched.markdown.input.formatting.InputParser
36
+ import com.swmansion.enriched.markdown.input.layout.InputEventEmitter
37
+ import com.swmansion.enriched.markdown.input.layout.InputLayoutManager
38
+ import com.swmansion.enriched.markdown.input.math.MathChipController
39
+ import com.swmansion.enriched.markdown.input.model.FormattingRange
40
+ import com.swmansion.enriched.markdown.input.model.InputFormatterStyle
41
+ import com.swmansion.enriched.markdown.input.model.MathChipStyle
42
+ import com.swmansion.enriched.markdown.input.model.StyleType
43
+ import com.swmansion.enriched.markdown.input.toolbar.InputContextMenu
44
+ import com.swmansion.enriched.markdown.utils.input.AutoCapitalizeUtils
45
+ import kotlin.math.ceil
46
+
47
+ class EnrichedMarkdownTextInputView(
48
+ context: Context,
49
+ ) : AppCompatEditText(context) {
50
+ private var isComponentReady = false
51
+
52
+ val formattingStore = FormattingStore()
53
+ val formatter = InputFormatter()
54
+ val pendingStyles = mutableSetOf<StyleType>()
55
+ val pendingStyleRemovals = mutableSetOf<StyleType>()
56
+
57
+ var isDuringTransaction = false
58
+ private set
59
+
60
+ var blockEmitting = false
61
+
62
+ private var isTextChanging = false
63
+ var isProcessingTextChange = false
64
+ private set
65
+ private var didTextChangeRecently = false
66
+ private var lastProcessedText: String = ""
67
+ private var preEditSelectionStart = 0
68
+ private var preEditSelectionEnd = 0
69
+
70
+ var emitMarkdown = false
71
+ var autoFocusRequested = false
72
+ var stateWrapper: StateWrapper? = null
73
+ val layoutManager = InputLayoutManager(this)
74
+
75
+ private var typefaceDirty = false
76
+ private var fontFamilyValue: String? = null
77
+ private var fontWeightValue: Int = ReactConstants.UNSET
78
+
79
+ val contextMenu = InputContextMenu(this)
80
+ val eventEmitter = InputEventEmitter(this)
81
+ private val autoLinkDetector = AutoLinkDetector(formattingStore)
82
+ private val detectorPipeline = DetectorPipeline()
83
+
84
+ val mathChipController: MathChipController? = MathChipController.resolve(context)
85
+ private var inputStyle: InputFormatterStyle? = null
86
+ private var activeMathChipPosition: Int = -1
87
+ private var pendingMathAtoms: List<com.swmansion.enriched.markdown.input.model.MathAtom> = emptyList()
88
+ private var lastReportedBlockWidth: Int = -1
89
+
90
+ private var textWatcher: MarkdownTextWatcher? = null
91
+ private var inputMethodManager: InputMethodManager? = null
92
+ private var detectScrollMovement = false
93
+ var scrollEnabled: Boolean = true
94
+
95
+ private var mentionIndicators: LinkedHashSet<String> = linkedSetOf()
96
+ private var activeMentionIndicator: String? = null
97
+ private var activeMentionStart = -1
98
+ private var activeMentionEnd = -1
99
+ private var activeMentionText = ""
100
+
101
+ init {
102
+ setupDetectorPipeline()
103
+ prepareComponent()
104
+ mathChipController?.blockWidthSupplier = { availableBlockWidth() }
105
+ isComponentReady = true
106
+ }
107
+
108
+ /**
109
+ * Width a full-bleed block math chip can claim. Read late (every layout pass),
110
+ * because TextView's width is established after measure. Falls back to 0 when
111
+ * we haven't been measured yet — span will then use its intrinsic width.
112
+ */
113
+ private fun availableBlockWidth(): Int {
114
+ val w = width - totalPaddingLeft - totalPaddingRight
115
+ return w.coerceAtLeast(0)
116
+ }
117
+
118
+ private fun setupDetectorPipeline() {
119
+ autoLinkDetector.onLinkDetected = { text, url, start, end ->
120
+ eventEmitter.emitLinkDetected(text, url, start, end)
121
+ }
122
+ detectorPipeline.addDetector(autoLinkDetector)
123
+ }
124
+
125
+ private fun prepareComponent() {
126
+ isSingleLine = false
127
+ isHorizontalScrollBarEnabled = false
128
+ isVerticalScrollBarEnabled = true
129
+ inputType = InputType.TYPE_CLASS_TEXT or
130
+ InputType.TYPE_TEXT_FLAG_MULTI_LINE or
131
+ InputType.TYPE_TEXT_FLAG_CAP_SENTENCES or
132
+ InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
133
+ gravity = Gravity.TOP or Gravity.START
134
+
135
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
136
+ breakStrategy = android.graphics.text.LineBreaker.BREAK_STRATEGY_HIGH_QUALITY
137
+ }
138
+
139
+ setEditableFactory(MarkdownEditableFactory(this))
140
+ setPadding(0, 0, 0, 0)
141
+ background = null
142
+ BackgroundStyleApplicator.setBackgroundColor(this, Color.TRANSPARENT)
143
+ contextMenu.install()
144
+
145
+ inputMethodManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
146
+
147
+ onFocusChangeListener =
148
+ OnFocusChangeListener { _, hasFocus ->
149
+ if (hasFocus) {
150
+ eventEmitter.emitFocus()
151
+ } else {
152
+ eventEmitter.emitBlur()
153
+ }
154
+ }
155
+ }
156
+
157
+ override fun onAttachedToWindow() {
158
+ super.onAttachedToWindow()
159
+ runAsATransaction { super.setTextIsSelectable(true) }
160
+ }
161
+
162
+ override fun onSizeChanged(
163
+ w: Int,
164
+ h: Int,
165
+ oldw: Int,
166
+ oldh: Int,
167
+ ) {
168
+ super.onSizeChanged(w, h, oldw, oldh)
169
+ if (mathChipController == null) return
170
+ val available = availableBlockWidth()
171
+ if (available == lastReportedBlockWidth) return
172
+ lastReportedBlockWidth = available
173
+ // First measurement (oldw==0) is the moment block chips get a real width;
174
+ // we need to invalidate their cached layout so getSize returns the new
175
+ // full-bleed width. Same for rotation / resize.
176
+ refreshAllMathChips()
177
+ }
178
+
179
+ override fun clearFocus() {
180
+ super.clearFocus()
181
+ inputMethodManager?.hideSoftInputFromWindow(windowToken, 0)
182
+ }
183
+
184
+ override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection? {
185
+ val base = super.onCreateInputConnection(outAttrs) ?: return null
186
+ return InputConnectionWrapper(base, this)
187
+ }
188
+
189
+ override fun onKeyDown(
190
+ keyCode: Int,
191
+ event: KeyEvent?,
192
+ ): Boolean {
193
+ if (keyCode == KeyEvent.KEYCODE_DEL && deleteLinkBeforeCursor()) {
194
+ return true
195
+ }
196
+ return super.onKeyDown(keyCode, event)
197
+ }
198
+
199
+ // Prevents TextView from deferring its internal layout when a Fabric
200
+ // state-update (height change) triggers requestLayout(). Without this
201
+ // override the deferred relayout causes a visible flicker of styled spans.
202
+ // See: ReactEditText in React Native core.
203
+ override fun isLayoutRequested(): Boolean = false
204
+
205
+ override fun onTouchEvent(ev: MotionEvent): Boolean {
206
+ when (ev.action) {
207
+ MotionEvent.ACTION_DOWN -> {
208
+ detectScrollMovement = true
209
+ parent?.requestDisallowInterceptTouchEvent(true)
210
+ }
211
+
212
+ MotionEvent.ACTION_MOVE -> {
213
+ if (detectScrollMovement) {
214
+ if (!canScrollVertically(-1) && !canScrollVertically(1) &&
215
+ !canScrollHorizontally(-1) && !canScrollHorizontally(1)
216
+ ) {
217
+ parent?.requestDisallowInterceptTouchEvent(false)
218
+ }
219
+ detectScrollMovement = false
220
+ }
221
+ }
222
+
223
+ MotionEvent.ACTION_UP -> {
224
+ val chipPosition = mathChipPositionAtTouch(ev.x, ev.y)
225
+ if (chipPosition >= 0 && handleMathChipTap(chipPosition)) {
226
+ return true
227
+ }
228
+ }
229
+ }
230
+ return super.onTouchEvent(ev)
231
+ }
232
+
233
+ override fun performClick(): Boolean = super.performClick()
234
+
235
+ // In auto-grow mode (scrollEnabled=false) TextView's internal bringPointIntoView
236
+ // scrolls content before Fabric has resized the view, causing a visible flicker.
237
+ override fun scrollTo(
238
+ x: Int,
239
+ y: Int,
240
+ ) {
241
+ if (!scrollEnabled) return
242
+ super.scrollTo(x, y)
243
+ }
244
+
245
+ override fun canScrollVertically(direction: Int): Boolean = scrollEnabled && super.canScrollVertically(direction)
246
+
247
+ override fun canScrollHorizontally(direction: Int): Boolean = scrollEnabled && super.canScrollHorizontally(direction)
248
+
249
+ fun attachTextWatcher(editable: Editable) {
250
+ if (textWatcher != null) {
251
+ editable.removeSpan(textWatcher)
252
+ }
253
+ textWatcher = MarkdownTextWatcher(this)
254
+ addTextChangedListener(textWatcher)
255
+ }
256
+
257
+ fun runAsATransaction(block: () -> Unit) {
258
+ try {
259
+ isDuringTransaction = true
260
+ block()
261
+ } finally {
262
+ isDuringTransaction = false
263
+ }
264
+ }
265
+
266
+ fun onBeforeTextChanged() {
267
+ if (isProcessingTextChange) return
268
+ isTextChanging = true
269
+ preEditSelectionStart = selectionStart
270
+ preEditSelectionEnd = selectionEnd
271
+ }
272
+
273
+ fun onAfterTextChanged(
274
+ editStart: Int,
275
+ deletedLength: Int,
276
+ insertedLength: Int,
277
+ ) {
278
+ if (isProcessingTextChange) return
279
+
280
+ val currentText = text?.toString() ?: ""
281
+ if (currentText == lastProcessedText) return
282
+
283
+ isProcessingTextChange = true
284
+ try {
285
+ formattingStore.adjustForEdit(editStart, deletedLength, insertedLength)
286
+ applyPendingStyles(editStart, insertedLength)
287
+ applyFormatting()
288
+
289
+ val editable = text
290
+ if (editable != null) {
291
+ detectorPipeline.processTextChange(editable, currentText, editStart, insertedLength)
292
+ }
293
+
294
+ forceScrollToSelection()
295
+ eventEmitter.emitChangeText()
296
+ if (emitMarkdown) eventEmitter.emitChangeMarkdown()
297
+ updateActiveMention()
298
+ eventEmitter.emitCaretRectChangeIfNeeded()
299
+ isTextChanging = false
300
+ didTextChangeRecently = true
301
+ lastProcessedText = currentText
302
+ } finally {
303
+ isProcessingTextChange = false
304
+ }
305
+ }
306
+
307
+ override fun onSelectionChanged(
308
+ selStart: Int,
309
+ selEnd: Int,
310
+ ) {
311
+ super.onSelectionChanged(selStart, selEnd)
312
+ if (!isComponentReady || isDuringTransaction) return
313
+
314
+ if (!isTextChanging) {
315
+ if (didTextChangeRecently) {
316
+ didTextChangeRecently = false
317
+ } else {
318
+ pendingStyles.clear()
319
+ pendingStyleRemovals.clear()
320
+ }
321
+ }
322
+
323
+ val isCaretOnChip =
324
+ selStart == selEnd &&
325
+ activeMathChipPosition >= 0 &&
326
+ (selStart == activeMathChipPosition || selStart == activeMathChipPosition + 1)
327
+ if (!isCaretOnChip) {
328
+ clearMathChipSelections()
329
+ activeMathChipPosition = -1
330
+ }
331
+
332
+ eventEmitter.emitSelection(selStart, selEnd)
333
+ updateActiveMention()
334
+ eventEmitter.emitState()
335
+ eventEmitter.emitCaretRectChangeIfNeeded()
336
+ }
337
+
338
+ private fun applyPendingStyles(
339
+ editStart: Int,
340
+ insertedLength: Int,
341
+ ) {
342
+ if (insertedLength == 0) return
343
+ if (pendingStyles.isEmpty() && pendingStyleRemovals.isEmpty()) return
344
+
345
+ val rangeStart = if (preEditSelectionStart != preEditSelectionEnd) preEditSelectionStart else editStart
346
+ val rangeEnd = rangeStart + insertedLength
347
+
348
+ for (style in pendingStyles) {
349
+ formattingStore.addRange(FormattingRange(style, rangeStart, rangeEnd))
350
+ }
351
+
352
+ for (style in pendingStyleRemovals) {
353
+ formattingStore.removeType(style, rangeStart, rangeEnd)
354
+ }
355
+ }
356
+
357
+ fun applyFormatting() {
358
+ val editable = text ?: return
359
+ formatter.applyFormatting(editable, formattingStore.allRanges)
360
+ }
361
+
362
+ private fun applyFormattingAndEmit() {
363
+ applyFormatting()
364
+ forceScrollToSelection()
365
+ if (emitMarkdown) eventEmitter.emitChangeMarkdown()
366
+ eventEmitter.emitState()
367
+ }
368
+
369
+ private fun forceScrollToSelection() {
370
+ val textLayout = layout ?: return
371
+ val cursorOffset = selectionStart
372
+ if (cursorOffset <= 0) return
373
+
374
+ val selectedLineIndex = textLayout.getLineForOffset(cursorOffset)
375
+ val selectedLineTop = textLayout.getLineTop(selectedLineIndex)
376
+ val selectedLineBottom = textLayout.getLineBottom(selectedLineIndex)
377
+ val visibleTextHeight = height - paddingTop - paddingBottom
378
+ if (visibleTextHeight <= 0) return
379
+
380
+ val visibleTop = scrollY
381
+ val visibleBottom = scrollY + visibleTextHeight
382
+ var targetScrollY = scrollY
383
+
384
+ if (selectedLineTop < visibleTop) {
385
+ targetScrollY = selectedLineTop
386
+ } else if (selectedLineBottom > visibleBottom) {
387
+ targetScrollY = selectedLineBottom - visibleTextHeight
388
+ }
389
+
390
+ val maxScrollY = (textLayout.height - visibleTextHeight).coerceAtLeast(0)
391
+ targetScrollY = targetScrollY.coerceIn(0, maxScrollY)
392
+ scrollTo(scrollX, targetScrollY)
393
+ }
394
+
395
+ fun toggleInlineStyle(styleType: StyleType) {
396
+ val handler = formatter.handlers[styleType] ?: return
397
+ val mergingConfig = handler.mergingConfig
398
+
399
+ val selStart = selectionStart
400
+ val selEnd = selectionEnd
401
+
402
+ // Check blocking rules: if any blocking style is active, refuse to toggle on.
403
+ if (mergingConfig.blockingStyles.isNotEmpty()) {
404
+ val isCurrentlyActive = formattingStore.isStyleActive(styleType, selStart)
405
+ if (!isCurrentlyActive) {
406
+ for (blocker in mergingConfig.blockingStyles) {
407
+ if (formattingStore.isStyleActive(blocker, selStart)) {
408
+ return
409
+ }
410
+ }
411
+ }
412
+ }
413
+
414
+ if (selStart == selEnd) {
415
+ if (pendingStyleRemovals.contains(styleType)) {
416
+ pendingStyleRemovals.remove(styleType)
417
+ pendingStyles.add(styleType)
418
+ } else if (pendingStyles.contains(styleType)) {
419
+ pendingStyles.remove(styleType)
420
+ pendingStyleRemovals.add(styleType)
421
+ } else if (formattingStore.isStyleActive(styleType, selStart)) {
422
+ pendingStyleRemovals.add(styleType)
423
+ } else {
424
+ pendingStyles.add(styleType)
425
+ }
426
+ eventEmitter.emitState()
427
+ } else {
428
+ val isActive = formattingStore.isStyleActive(styleType, selStart)
429
+ if (isActive) {
430
+ formattingStore.removeType(styleType, selStart, selEnd)
431
+ } else {
432
+ // Remove conflicting styles from the range before applying.
433
+ for (conflict in mergingConfig.conflictingStyles) {
434
+ formattingStore.removeType(conflict, selStart, selEnd)
435
+ }
436
+ formattingStore.addRange(FormattingRange(styleType, selStart, selEnd))
437
+ }
438
+ applyFormattingAndEmit()
439
+ }
440
+ }
441
+
442
+ fun setLinkForSelection(url: String) {
443
+ val selStart = selectionStart
444
+ val selEnd = selectionEnd
445
+ if (selStart == selEnd) return
446
+
447
+ val editable = text
448
+ if (editable != null) {
449
+ autoLinkDetector.clearAutoLinkInRange(editable, selStart, selEnd)
450
+ }
451
+ formattingStore.addRange(FormattingRange(StyleType.LINK, selStart, selEnd, url))
452
+ applyFormattingAndEmit()
453
+ }
454
+
455
+ fun insertLinkAtCursor(
456
+ displayText: String,
457
+ url: String,
458
+ ) {
459
+ val editable = text ?: return
460
+ val selStart = selectionStart
461
+ val selEnd = selectionEnd
462
+ val linkEnd = selStart + displayText.length
463
+
464
+ isProcessingTextChange = true
465
+ try {
466
+ editable.replace(selStart, selEnd, displayText)
467
+ formattingStore.adjustForEdit(selStart, selEnd - selStart, displayText.length)
468
+ autoLinkDetector.clearAutoLinkInRange(editable, selStart, linkEnd)
469
+ formattingStore.addRange(FormattingRange(StyleType.LINK, selStart, linkEnd, sanitizeLinkUrl(url)))
470
+ lastProcessedText = editable.toString()
471
+
472
+ setSelection(linkEnd)
473
+ applyFormattingAndEmit()
474
+ eventEmitter.emitChangeText()
475
+ } finally {
476
+ isProcessingTextChange = false
477
+ }
478
+ }
479
+
480
+ fun insertMention(
481
+ displayText: String,
482
+ url: String,
483
+ ) {
484
+ if (displayText.isEmpty()) return
485
+ val indicator = activeMentionIndicator ?: return
486
+ val start = activeMentionStart
487
+ val end = activeMentionEnd
488
+ val editable = text ?: return
489
+ if (start < 0 || end < start || end > editable.length) return
490
+
491
+ val sanitizedUrl = sanitizeLinkUrl(url)
492
+ val shouldAppendSpace = end >= editable.length || !editable[end].isWhitespace()
493
+ val replacement = if (shouldAppendSpace) "$displayText " else displayText
494
+ val linkEnd = start + displayText.length
495
+
496
+ isProcessingTextChange = true
497
+ try {
498
+ editable.replace(start, end, replacement)
499
+ formattingStore.adjustForEdit(start, end - start, replacement.length)
500
+ autoLinkDetector.clearAutoLinkInRange(editable, start, linkEnd)
501
+ formattingStore.addRange(FormattingRange(StyleType.LINK, start, linkEnd, sanitizedUrl))
502
+ lastProcessedText = editable.toString()
503
+
504
+ clearActiveMention(emit = true, indicatorOverride = indicator)
505
+ setSelection(start + replacement.length)
506
+ applyFormattingAndEmit()
507
+ eventEmitter.emitChangeText()
508
+ } finally {
509
+ isProcessingTextChange = false
510
+ }
511
+ }
512
+
513
+ fun startMention(indicator: String) {
514
+ if (indicator.isEmpty() || indicator !in mentionIndicators) return
515
+ val editable = text ?: return
516
+ val selStart = selectionStart
517
+ val selEnd = selectionEnd
518
+
519
+ isProcessingTextChange = true
520
+ try {
521
+ editable.replace(selStart, selEnd, indicator)
522
+ formattingStore.adjustForEdit(selStart, selEnd - selStart, indicator.length)
523
+ lastProcessedText = editable.toString()
524
+ setSelection(selStart + indicator.length)
525
+ applyFormattingAndEmit()
526
+ eventEmitter.emitChangeText()
527
+ updateActiveMention()
528
+ } finally {
529
+ isProcessingTextChange = false
530
+ }
531
+ }
532
+
533
+ fun removeLinkAtCursor() {
534
+ val pos = selectionStart
535
+ val linkRange = formattingStore.rangeOfType(StyleType.LINK, pos) ?: return
536
+ formattingStore.removeRange(linkRange)
537
+ applyFormattingAndEmit()
538
+ }
539
+
540
+ fun deleteLinkBeforeCursor(): Boolean {
541
+ val editable = text ?: return false
542
+ val cursorStart = selectionStart
543
+ val cursorEnd = selectionEnd
544
+ if (cursorStart != cursorEnd || cursorStart <= 0) return false
545
+
546
+ val linkRange = formattingStore.rangeOfType(StyleType.LINK, cursorStart - 1) ?: return false
547
+
548
+ isProcessingTextChange = true
549
+ try {
550
+ editable.delete(linkRange.start, linkRange.end)
551
+ formattingStore.adjustForEdit(linkRange.start, linkRange.length, 0)
552
+ lastProcessedText = editable.toString()
553
+ setSelection(linkRange.start.coerceAtMost(editable.length))
554
+ applyFormattingAndEmit()
555
+ eventEmitter.emitChangeText()
556
+ clearActiveMention()
557
+ } finally {
558
+ isProcessingTextChange = false
559
+ }
560
+ return true
561
+ }
562
+
563
+ fun setMentionIndicators(indicators: List<String>) {
564
+ val newIndicators = LinkedHashSet(indicators)
565
+ if (newIndicators == mentionIndicators) return
566
+ mentionIndicators = newIndicators
567
+ activeMentionIndicator?.let { indicator ->
568
+ if (indicator !in mentionIndicators) {
569
+ clearActiveMention(emit = true, indicatorOverride = indicator)
570
+ }
571
+ }
572
+ updateActiveMention()
573
+ }
574
+
575
+ fun dismissActiveMention() {
576
+ clearActiveMention(emit = false)
577
+ }
578
+
579
+ fun setContextMenuItems(items: List<String>) {
580
+ contextMenu.setContextMenuItems(items)
581
+ }
582
+
583
+ fun setLinkRegex(config: LinkRegexConfig) {
584
+ autoLinkDetector.setRegexConfig(config)
585
+ }
586
+
587
+ fun setAutoLinkStyle(style: InputFormatterStyle) {
588
+ autoLinkDetector.style = style
589
+ }
590
+
591
+ fun allFormattingRangesForSerialization(): List<FormattingRange> {
592
+ val editable = text ?: return formattingStore.allRanges
593
+ val transientRanges = detectorPipeline.allTransientFormattingRanges(editable)
594
+ if (transientRanges.isEmpty()) return formattingStore.allRanges
595
+ return formattingStore.allRanges + transientRanges
596
+ }
597
+
598
+ fun setValueFromJS(markdown: String) {
599
+ val parsed = InputParser.parseToPlainTextAndRanges(markdown)
600
+ blockEmitting = true
601
+ try {
602
+ runAsATransaction {
603
+ formattingStore.clearAll()
604
+ formattingStore.setRanges(parsed.formattingRanges)
605
+ setText(parsed.plainText)
606
+ val editable = text
607
+ if (editable != null && parsed.mathAtoms.isNotEmpty()) {
608
+ applyMathAtoms(editable, parsed.mathAtoms)
609
+ }
610
+ setSelection(text?.length ?: 0)
611
+ }
612
+ applyFormatting()
613
+ forceScrollToSelection()
614
+ layoutManager.invalidateLayout()
615
+ lastProcessedText = text?.toString() ?: ""
616
+ } finally {
617
+ blockEmitting = false
618
+ }
619
+ }
620
+
621
+ private fun applyMathAtoms(
622
+ editable: Editable,
623
+ atoms: List<com.swmansion.enriched.markdown.input.model.MathAtom>,
624
+ ) {
625
+ val controller = mathChipController ?: return
626
+ val style = inputStyle
627
+ if (style == null) {
628
+ // `markdownStyle` hasn't arrived yet — defer until applyInputStyle runs.
629
+ // @ReactProp setters fire in undefined order, so defaultValue may run first.
630
+ pendingMathAtoms = atoms
631
+ return
632
+ }
633
+ pendingMathAtoms = emptyList()
634
+ isProcessingTextChange = true
635
+ try {
636
+ controller.applyAtoms(editable, atoms, style.math, style.mathBlock)
637
+ } finally {
638
+ isProcessingTextChange = false
639
+ }
640
+ }
641
+
642
+ fun refreshAllMathChips() {
643
+ val controller = mathChipController ?: return
644
+ val editable = text ?: return
645
+ val style = inputStyle ?: return
646
+ controller.refreshAll(editable, style.math, style.mathBlock)
647
+ invalidate()
648
+ requestLayout()
649
+ }
650
+
651
+ fun applyInputStyle(style: InputFormatterStyle): Boolean {
652
+ val previous = inputStyle
653
+ inputStyle = style
654
+ val changed = previous != style
655
+ val mathStyleChanged =
656
+ previous == null ||
657
+ previous.math != style.math ||
658
+ previous.mathBlock != style.mathBlock
659
+
660
+ val controller = mathChipController
661
+ val editable = text
662
+ if (controller != null && editable != null && pendingMathAtoms.isNotEmpty()) {
663
+ val atoms = pendingMathAtoms
664
+ pendingMathAtoms = emptyList()
665
+ isProcessingTextChange = true
666
+ try {
667
+ controller.applyAtoms(editable, atoms, style.math, style.mathBlock)
668
+ } finally {
669
+ isProcessingTextChange = false
670
+ }
671
+ invalidate()
672
+ requestLayout()
673
+ } else if (mathStyleChanged) {
674
+ refreshAllMathChips()
675
+ }
676
+ return changed
677
+ }
678
+
679
+ fun insertMath(
680
+ latex: String,
681
+ displayMode: Boolean,
682
+ ) {
683
+ if (latex.isEmpty()) return
684
+ val controller = mathChipController ?: return
685
+ val style = inputStyle ?: return
686
+ val editable = text ?: return
687
+
688
+ val selStart = selectionStart.coerceAtLeast(0)
689
+ val selEnd = selectionEnd.coerceAtLeast(selStart)
690
+ val safeStart = selStart.coerceAtMost(editable.length)
691
+ val safeEnd = selEnd.coerceAtMost(editable.length)
692
+
693
+ val prefix = StringBuilder()
694
+ val suffix = StringBuilder()
695
+ if (displayMode) {
696
+ val atLineStart = safeStart == 0 || editable[safeStart - 1] == '\n'
697
+ val atLineEnd = safeEnd >= editable.length || editable[safeEnd] == '\n'
698
+ if (!atLineStart) prefix.append('\n')
699
+ if (!atLineEnd) suffix.append('\n')
700
+ }
701
+ val replacement = "$prefix$suffix"
702
+ val chipPositionInReplacement = prefix.length
703
+
704
+ isProcessingTextChange = true
705
+ try {
706
+ editable.replace(safeStart, safeEnd, replacement)
707
+ val chipPosition = safeStart + chipPositionInReplacement
708
+ val chipStyle: MathChipStyle = if (displayMode) style.mathBlock else style.math
709
+ controller.insertChip(editable, chipPosition, latex, displayMode, chipStyle)
710
+ formattingStore.adjustForEdit(safeStart, safeEnd - safeStart, replacement.length)
711
+ lastProcessedText = editable.toString()
712
+ setSelection(safeStart + replacement.length)
713
+ } finally {
714
+ isProcessingTextChange = false
715
+ }
716
+
717
+ applyFormatting()
718
+ invalidate()
719
+ requestLayout()
720
+ eventEmitter.emitChangeText()
721
+ if (emitMarkdown) eventEmitter.emitChangeMarkdown()
722
+ eventEmitter.emitSelection(selectionStart, selectionEnd)
723
+ eventEmitter.emitState()
724
+ eventEmitter.emitCaretRectChangeIfNeeded()
725
+ }
726
+
727
+ fun updateMath(
728
+ start: Int,
729
+ latex: String,
730
+ displayMode: Boolean,
731
+ ) {
732
+ val controller = mathChipController ?: return
733
+ val style = inputStyle ?: return
734
+ val editable = text ?: return
735
+ val chipStyle: MathChipStyle = if (displayMode) style.mathBlock else style.math
736
+ val result = controller.updateChip(editable, start, latex, displayMode, chipStyle)
737
+ if (!result.applied) return
738
+ invalidate()
739
+ requestLayout()
740
+ if (emitMarkdown) eventEmitter.emitChangeMarkdown()
741
+ }
742
+
743
+ fun removeMath(start: Int) {
744
+ val controller = mathChipController ?: return
745
+ val editable = text ?: return
746
+
747
+ isProcessingTextChange = true
748
+ val didRemove =
749
+ try {
750
+ controller.removeChip(editable, start)
751
+ } finally {
752
+ isProcessingTextChange = false
753
+ }
754
+ if (!didRemove) return
755
+ formattingStore.adjustForEdit(start, 1, 0)
756
+ lastProcessedText = editable.toString()
757
+ applyFormatting()
758
+ eventEmitter.emitChangeText()
759
+ if (emitMarkdown) eventEmitter.emitChangeMarkdown()
760
+ eventEmitter.emitSelection(selectionStart, selectionEnd)
761
+ }
762
+
763
+ private fun clearMathChipSelections(except: Int = -1) {
764
+ val controller = mathChipController ?: return
765
+ val editable = text ?: return
766
+ val changed =
767
+ if (except < 0) {
768
+ controller.clearAllSelections(editable)
769
+ } else {
770
+ var didChange = false
771
+ for (chip in controller.allChips(editable)) {
772
+ if (chip.position == except) continue
773
+ if (chip.isSelected) {
774
+ if (controller.setSelected(editable, chip.position, false)) didChange = true
775
+ }
776
+ }
777
+ didChange
778
+ }
779
+ if (changed) invalidate()
780
+ }
781
+
782
+ private fun handleMathChipTap(chipPosition: Int): Boolean {
783
+ val controller = mathChipController ?: return false
784
+ val editable = text ?: return false
785
+ val info = controller.chipAt(editable, chipPosition) ?: return false
786
+ val layoutNow = layout ?: return false
787
+
788
+ clearMathChipSelections(except = info.position)
789
+ controller.setSelected(editable, info.position, true)
790
+ invalidate()
791
+ activeMathChipPosition = info.position
792
+ // Caret-after-chip (length 0). A length-1 selection would make the system
793
+ // draw selection handles over the chip glyph, and also trip the
794
+ // `selStart == selEnd` guard in onSelectionChanged that keeps the chip's
795
+ // selected style alive.
796
+ setSelection((info.position + 1).coerceAtMost(editable.length))
797
+
798
+ val bounds = computeChipBounds(layoutNow, info.position)
799
+ val density = resources.displayMetrics.density.toDouble()
800
+ eventEmitter.emitMathPress(
801
+ info.latex,
802
+ info.position,
803
+ info.position + 1,
804
+ info.displayMode,
805
+ bounds.left.toDouble() / density,
806
+ bounds.top.toDouble() / density,
807
+ bounds.width().toDouble() / density,
808
+ bounds.height().toDouble() / density,
809
+ )
810
+ return true
811
+ }
812
+
813
+ private fun computeChipBounds(
814
+ layout: Layout,
815
+ start: Int,
816
+ ): Rect {
817
+ val line = layout.getLineForOffset(start)
818
+ val xStart = (layout.getPrimaryHorizontal(start)).toInt() + totalPaddingLeft - scrollX
819
+ val xEnd = (layout.getPrimaryHorizontal(start + 1)).toInt() + totalPaddingLeft - scrollX
820
+ val top = layout.getLineTop(line) + totalPaddingTop - scrollY
821
+ val bottom = layout.getLineBottom(line) + totalPaddingTop - scrollY
822
+ return Rect(xStart, top, xEnd, bottom)
823
+ }
824
+
825
+ fun mathChipPositionAtTouch(
826
+ x: Float,
827
+ y: Float,
828
+ ): Int {
829
+ val controller = mathChipController ?: return -1
830
+ val editable = text ?: return -1
831
+ val layoutNow = layout ?: return -1
832
+ val adjustedX = (x - totalPaddingLeft + scrollX).toInt()
833
+ val adjustedY = (y - totalPaddingTop + scrollY).toInt()
834
+ if (adjustedY < 0) return -1
835
+ val line = layoutNow.getLineForVertical(adjustedY)
836
+ val offset = layoutNow.getOffsetForHorizontal(line, adjustedX.toFloat())
837
+ if (offset < 0 || offset >= editable.length) return -1
838
+ val candidates = intArrayOf(offset, offset - 1).filter { it in 0 until editable.length }
839
+ for (candidate in candidates) {
840
+ val range = controller.chipRangeAt(editable, candidate) ?: continue
841
+ return range.first
842
+ }
843
+ return -1
844
+ }
845
+
846
+ /**
847
+ * Shrink the IME composing region so it never overlaps a math chip. Returns
848
+ * the adjusted (start, end) pair, or null if no chip lies in the range. The
849
+ * caller should fall back to the original range when null is returned.
850
+ *
851
+ * If the region intersects a chip we collapse to the side furthest from the
852
+ * chip so a Korean/Japanese composing block can't accidentally swallow the
853
+ * chip's `` placeholder character.
854
+ */
855
+ fun adjustComposingRegionAwayFromChips(
856
+ start: Int,
857
+ end: Int,
858
+ ): Pair<Int, Int>? {
859
+ val controller = mathChipController ?: return null
860
+ val editable = text ?: return null
861
+ if (start < 0 || end < 0 || start > editable.length || end > editable.length) return null
862
+ if (start >= end) return start to end
863
+
864
+ var adjustedStart = start
865
+ var adjustedEnd = end
866
+ var i = adjustedStart
867
+ while (i < adjustedEnd) {
868
+ val range = controller.chipRangeAt(editable, i)
869
+ if (range == null) {
870
+ i++
871
+ continue
872
+ }
873
+ // Composing region overlaps a chip — push the edge that's nearest to the chip out.
874
+ val distFromStart = range.first - adjustedStart
875
+ val distFromEnd = adjustedEnd - (range.last + 1)
876
+ if (distFromStart >= distFromEnd) {
877
+ adjustedEnd = range.first
878
+ } else {
879
+ adjustedStart = range.last + 1
880
+ }
881
+ if (adjustedStart >= adjustedEnd) break
882
+ i = adjustedStart
883
+ }
884
+ if (adjustedStart >= adjustedEnd) return adjustedStart to adjustedStart
885
+ return adjustedStart to adjustedEnd
886
+ }
887
+
888
+ override fun setBackgroundColor(color: Int) {
889
+ BackgroundStyleApplicator.setBackgroundColor(this, color)
890
+ }
891
+
892
+ fun setFontSizeFromProps(size: Float) {
893
+ if (size <= 0f) return
894
+ val sizePx = ceil(PixelUtil.toPixelFromSP(size))
895
+ setTextSize(TypedValue.COMPLEX_UNIT_PX, sizePx)
896
+ layoutManager.invalidateLayout()
897
+ }
898
+
899
+ fun setColorFromProps(colorInt: Int?) {
900
+ setTextColor(colorInt ?: Color.BLACK)
901
+ }
902
+
903
+ fun setCursorColorFromProps(colorInt: Int?) {
904
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
905
+ val cursorDrawable = textCursorDrawable ?: return
906
+ if (colorInt != null) {
907
+ cursorDrawable.colorFilter = BlendModeColorFilter(colorInt, BlendMode.SRC_IN)
908
+ } else {
909
+ cursorDrawable.clearColorFilter()
910
+ }
911
+ textCursorDrawable = cursorDrawable
912
+ }
913
+ }
914
+
915
+ fun setFontFamily(family: String?) {
916
+ if (family != fontFamilyValue) {
917
+ fontFamilyValue = family
918
+ typefaceDirty = true
919
+ }
920
+ }
921
+
922
+ fun setFontWeight(weight: String?) {
923
+ val parsed = ReactTypefaceUtils.parseFontWeight(weight)
924
+ if (parsed != fontWeightValue) {
925
+ fontWeightValue = parsed
926
+ typefaceDirty = true
927
+ }
928
+ }
929
+
930
+ private fun updateTypeface() {
931
+ if (!typefaceDirty) return
932
+ typefaceDirty = false
933
+
934
+ val newTypeface =
935
+ ReactTypefaceUtils.applyStyles(
936
+ typeface,
937
+ ReactConstants.UNSET,
938
+ fontWeightValue,
939
+ fontFamilyValue,
940
+ context.assets,
941
+ )
942
+ typeface = newTypeface
943
+ paint.typeface = newTypeface
944
+ layoutManager.invalidateLayout()
945
+ }
946
+
947
+ fun setAutoCapitalize(flagName: String?) {
948
+ AutoCapitalizeUtils.apply(this, flagName)
949
+ }
950
+
951
+ fun requestFocusProgrammatically() {
952
+ requestFocus()
953
+ inputMethodManager?.showSoftInput(this, 0)
954
+ setSelection(selectionStart.coerceAtLeast(0))
955
+ }
956
+
957
+ fun afterUpdateTransaction() {
958
+ updateTypeface()
959
+ if (autoFocusRequested) {
960
+ autoFocusRequested = false
961
+ requestFocusProgrammatically()
962
+ }
963
+ }
964
+
965
+ fun applyStyleToRange(
966
+ styleType: StyleType,
967
+ start: Int,
968
+ end: Int,
969
+ ) {
970
+ if (start >= end) return
971
+ val handler = formatter.handlers[styleType] ?: return
972
+ val isActive = formattingStore.isStyleActive(styleType, start)
973
+ if (isActive) {
974
+ formattingStore.removeType(styleType, start, end)
975
+ } else {
976
+ for (conflict in handler.mergingConfig.conflictingStyles) {
977
+ formattingStore.removeType(conflict, start, end)
978
+ }
979
+ formattingStore.addRange(FormattingRange(styleType, start, end))
980
+ }
981
+ applyFormattingAndEmit()
982
+ }
983
+
984
+ fun applyLinkToRange(
985
+ url: String,
986
+ start: Int,
987
+ end: Int,
988
+ ) {
989
+ if (start >= end) return
990
+ formattingStore.addRange(FormattingRange(StyleType.LINK, start, end, url))
991
+ applyFormattingAndEmit()
992
+ }
993
+
994
+ private fun updateActiveMention() {
995
+ val plainText = text?.toString() ?: return
996
+ val cursor = selectionStart
997
+ if (selectionStart != selectionEnd || cursor < 0 || cursor > plainText.length) {
998
+ clearActiveMention()
999
+ return
1000
+ }
1001
+
1002
+ val candidate = detectMentionAtCursor(plainText, cursor)
1003
+ if (candidate == null) {
1004
+ clearActiveMention()
1005
+ return
1006
+ }
1007
+
1008
+ if (activeMentionIndicator != candidate.indicator || activeMentionStart != candidate.start) {
1009
+ activeMentionIndicator?.let { eventEmitter.emitEndMention(it) }
1010
+ activeMentionIndicator = candidate.indicator
1011
+ activeMentionStart = candidate.start
1012
+ eventEmitter.emitStartMention(candidate.indicator)
1013
+ }
1014
+
1015
+ activeMentionEnd = candidate.end
1016
+ if (activeMentionText != candidate.text) {
1017
+ activeMentionText = candidate.text
1018
+ eventEmitter.emitChangeMention(candidate.indicator, candidate.text)
1019
+ }
1020
+ }
1021
+
1022
+ private fun detectMentionAtCursor(
1023
+ plainText: String,
1024
+ cursor: Int,
1025
+ ): MentionCandidate? {
1026
+ if (mentionIndicators.isEmpty()) return null
1027
+
1028
+ val start = WordsUtils.tokenStart(plainText, cursor)
1029
+ val token = plainText.substring(start, cursor)
1030
+ val indicator = mentionIndicators.firstOrNull { token.startsWith(it) } ?: return null
1031
+ if (formattingStore.rangeOfType(StyleType.LINK, start) != null) return null
1032
+
1033
+ return MentionCandidate(
1034
+ indicator = indicator,
1035
+ start = start,
1036
+ end = cursor,
1037
+ text = token.substring(indicator.length),
1038
+ )
1039
+ }
1040
+
1041
+ private fun clearActiveMention(
1042
+ emit: Boolean = true,
1043
+ indicatorOverride: String? = null,
1044
+ ) {
1045
+ val indicator = indicatorOverride ?: activeMentionIndicator
1046
+ activeMentionIndicator = null
1047
+ activeMentionStart = -1
1048
+ activeMentionEnd = -1
1049
+ activeMentionText = ""
1050
+ if (emit && indicator != null) {
1051
+ eventEmitter.emitEndMention(indicator)
1052
+ }
1053
+ }
1054
+
1055
+ private fun sanitizeLinkUrl(url: String): String =
1056
+ url
1057
+ .replace("(", "%28")
1058
+ .replace(")", "%29")
1059
+
1060
+ private data class MentionCandidate(
1061
+ val indicator: String,
1062
+ val start: Int,
1063
+ val end: Int,
1064
+ val text: String,
1065
+ )
1066
+ }