@mathers101/react-native-render-rich-text 0.0.0-stage → 0.1.9

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 (358) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +140 -3
  3. package/ReactNativeRenderRichText.podspec +23 -0
  4. package/android/build.gradle +86 -0
  5. package/android/consumer-rules.pro +3 -0
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/cpp/jni-adapter.cpp +191 -0
  8. package/android/src/main/java/com/renderrichtext/EnrichedTiptapText.kt +673 -0
  9. package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextLayoutManager.kt +24 -0
  10. package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextManager.kt +405 -0
  11. package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextPackage.kt +13 -0
  12. package/android/src/main/java/com/renderrichtext/MeasurementStore.kt +644 -0
  13. package/android/src/main/java/com/renderrichtext/accessibility/AccessibilityLabels.kt +17 -0
  14. package/android/src/main/java/com/renderrichtext/accessibility/AccessibleTiptapTextView.kt +112 -0
  15. package/android/src/main/java/com/renderrichtext/accessibility/TiptapAccessibilityHelper.kt +576 -0
  16. package/android/src/main/java/com/renderrichtext/events/CodeBlockPressEvent.kt +24 -0
  17. package/android/src/main/java/com/renderrichtext/events/ContextMenuItemPressEvent.kt +28 -0
  18. package/android/src/main/java/com/renderrichtext/events/CopyPressEvent.kt +24 -0
  19. package/android/src/main/java/com/renderrichtext/events/FactoidPressEvent.kt +23 -0
  20. package/android/src/main/java/com/renderrichtext/events/ImagePressEvent.kt +25 -0
  21. package/android/src/main/java/com/renderrichtext/events/LatexErrorEvent.kt +29 -0
  22. package/android/src/main/java/com/renderrichtext/events/LinkLongPressEvent.kt +23 -0
  23. package/android/src/main/java/com/renderrichtext/events/LinkPressEvent.kt +23 -0
  24. package/android/src/main/java/com/renderrichtext/events/MentionLongPressEvent.kt +25 -0
  25. package/android/src/main/java/com/renderrichtext/events/MentionPressEvent.kt +25 -0
  26. package/android/src/main/java/com/renderrichtext/events/TaskListItemPressEvent.kt +26 -0
  27. package/android/src/main/java/com/renderrichtext/math/LatexErrorReporter.kt +9 -0
  28. package/android/src/main/java/com/renderrichtext/parser/Parser.kt +59 -0
  29. package/android/src/main/java/com/renderrichtext/parser/TextLinkMatching.kt +35 -0
  30. package/android/src/main/java/com/renderrichtext/parser/TiptapASTNode.kt +69 -0
  31. package/android/src/main/java/com/renderrichtext/renderer/BaselineShiftRenderer.kt +45 -0
  32. package/android/src/main/java/com/renderrichtext/renderer/BlankLineRenderer.kt +39 -0
  33. package/android/src/main/java/com/renderrichtext/renderer/BlockStyleContext.kt +181 -0
  34. package/android/src/main/java/com/renderrichtext/renderer/BlockquoteRenderer.kt +243 -0
  35. package/android/src/main/java/com/renderrichtext/renderer/BlockquoteTextRenderer.kt +56 -0
  36. package/android/src/main/java/com/renderrichtext/renderer/CodeBlockRenderer.kt +135 -0
  37. package/android/src/main/java/com/renderrichtext/renderer/CodeRenderer.kt +37 -0
  38. package/android/src/main/java/com/renderrichtext/renderer/EmphasisRenderer.kt +28 -0
  39. package/android/src/main/java/com/renderrichtext/renderer/FactoidRenderer.kt +97 -0
  40. package/android/src/main/java/com/renderrichtext/renderer/HeadingRenderer.kt +81 -0
  41. package/android/src/main/java/com/renderrichtext/renderer/HighlightRenderer.kt +26 -0
  42. package/android/src/main/java/com/renderrichtext/renderer/LineBreakRenderer.kt +17 -0
  43. package/android/src/main/java/com/renderrichtext/renderer/LinkRenderer.kt +90 -0
  44. package/android/src/main/java/com/renderrichtext/renderer/ListContextManager.kt +109 -0
  45. package/android/src/main/java/com/renderrichtext/renderer/ListItemRenderer.kt +211 -0
  46. package/android/src/main/java/com/renderrichtext/renderer/ListRenderer.kt +133 -0
  47. package/android/src/main/java/com/renderrichtext/renderer/MentionRenderer.kt +85 -0
  48. package/android/src/main/java/com/renderrichtext/renderer/NodeRenderer.kt +207 -0
  49. package/android/src/main/java/com/renderrichtext/renderer/ParagraphRenderer.kt +91 -0
  50. package/android/src/main/java/com/renderrichtext/renderer/Renderer.kt +148 -0
  51. package/android/src/main/java/com/renderrichtext/renderer/SoftBreakRenderer.kt +17 -0
  52. package/android/src/main/java/com/renderrichtext/renderer/SpanStyleCache.kt +143 -0
  53. package/android/src/main/java/com/renderrichtext/renderer/StrikethroughRenderer.kt +28 -0
  54. package/android/src/main/java/com/renderrichtext/renderer/StrongRenderer.kt +28 -0
  55. package/android/src/main/java/com/renderrichtext/renderer/TextRenderer.kt +31 -0
  56. package/android/src/main/java/com/renderrichtext/renderer/ThematicBreakRenderer.kt +46 -0
  57. package/android/src/main/java/com/renderrichtext/renderer/UnderlineRenderer.kt +28 -0
  58. package/android/src/main/java/com/renderrichtext/spans/BaseListSpan.kt +164 -0
  59. package/android/src/main/java/com/renderrichtext/spans/BaselineShiftSpan.kt +27 -0
  60. package/android/src/main/java/com/renderrichtext/spans/BlockquoteSpan.kt +302 -0
  61. package/android/src/main/java/com/renderrichtext/spans/CodeBackgroundSpan.kt +205 -0
  62. package/android/src/main/java/com/renderrichtext/spans/CodeBlockSpan.kt +216 -0
  63. package/android/src/main/java/com/renderrichtext/spans/CodeSpan.kt +32 -0
  64. package/android/src/main/java/com/renderrichtext/spans/EmphasisSpan.kt +42 -0
  65. package/android/src/main/java/com/renderrichtext/spans/FactoidBackgroundSpan.kt +265 -0
  66. package/android/src/main/java/com/renderrichtext/spans/FactoidPaddingSpan.kt +258 -0
  67. package/android/src/main/java/com/renderrichtext/spans/FactoidSpan.kt +32 -0
  68. package/android/src/main/java/com/renderrichtext/spans/FadeInSpan.kt +29 -0
  69. package/android/src/main/java/com/renderrichtext/spans/HeadingSpan.kt +38 -0
  70. package/android/src/main/java/com/renderrichtext/spans/HighlightSpan.kt +80 -0
  71. package/android/src/main/java/com/renderrichtext/spans/ImageSpan.kt +481 -0
  72. package/android/src/main/java/com/renderrichtext/spans/InlineBackgroundGeometry.kt +42 -0
  73. package/android/src/main/java/com/renderrichtext/spans/LineHeightSpan.kt +39 -0
  74. package/android/src/main/java/com/renderrichtext/spans/LinkPillIconCache.kt +154 -0
  75. package/android/src/main/java/com/renderrichtext/spans/LinkPillSpan.kt +381 -0
  76. package/android/src/main/java/com/renderrichtext/spans/LinkSpan.kt +68 -0
  77. package/android/src/main/java/com/renderrichtext/spans/ListItemSpacingSpan.kt +33 -0
  78. package/android/src/main/java/com/renderrichtext/spans/ListMarkerAnchorSpan.kt +38 -0
  79. package/android/src/main/java/com/renderrichtext/spans/MarginBottomSpan.kt +76 -0
  80. package/android/src/main/java/com/renderrichtext/spans/MentionChipSpan.kt +132 -0
  81. package/android/src/main/java/com/renderrichtext/spans/MentionSpan.kt +46 -0
  82. package/android/src/main/java/com/renderrichtext/spans/OrderedListSpan.kt +127 -0
  83. package/android/src/main/java/com/renderrichtext/spans/SpoilerSpan.kt +33 -0
  84. package/android/src/main/java/com/renderrichtext/spans/StrikethroughSpan.kt +12 -0
  85. package/android/src/main/java/com/renderrichtext/spans/StrongSpan.kt +39 -0
  86. package/android/src/main/java/com/renderrichtext/spans/TaskListSpan.kt +143 -0
  87. package/android/src/main/java/com/renderrichtext/spans/TextSpan.kt +26 -0
  88. package/android/src/main/java/com/renderrichtext/spans/ThematicBreakSpan.kt +69 -0
  89. package/android/src/main/java/com/renderrichtext/spans/UnorderedListSpan.kt +96 -0
  90. package/android/src/main/java/com/renderrichtext/spoiler/SpoilerStubs.kt +46 -0
  91. package/android/src/main/java/com/renderrichtext/styles/BaseBlockStyle.kt +11 -0
  92. package/android/src/main/java/com/renderrichtext/styles/BlockquoteStyle.kt +83 -0
  93. package/android/src/main/java/com/renderrichtext/styles/CodeBlockStyle.kt +80 -0
  94. package/android/src/main/java/com/renderrichtext/styles/CodeStyle.kt +26 -0
  95. package/android/src/main/java/com/renderrichtext/styles/EmphasisStyle.kt +21 -0
  96. package/android/src/main/java/com/renderrichtext/styles/FactoidStyle.kt +21 -0
  97. package/android/src/main/java/com/renderrichtext/styles/HeadingStyle.kt +33 -0
  98. package/android/src/main/java/com/renderrichtext/styles/HighlightStyle.kt +19 -0
  99. package/android/src/main/java/com/renderrichtext/styles/ImageStyle.kt +29 -0
  100. package/android/src/main/java/com/renderrichtext/styles/InlineImageStyle.kt +17 -0
  101. package/android/src/main/java/com/renderrichtext/styles/InlineMathStyle.kt +17 -0
  102. package/android/src/main/java/com/renderrichtext/styles/LinkPillContent.kt +36 -0
  103. package/android/src/main/java/com/renderrichtext/styles/LinkPillStyle.kt +44 -0
  104. package/android/src/main/java/com/renderrichtext/styles/LinkStyle.kt +23 -0
  105. package/android/src/main/java/com/renderrichtext/styles/LinkVariantEntry.kt +34 -0
  106. package/android/src/main/java/com/renderrichtext/styles/ListStyle.kt +65 -0
  107. package/android/src/main/java/com/renderrichtext/styles/MathStyle.kt +29 -0
  108. package/android/src/main/java/com/renderrichtext/styles/MentionStyle.kt +19 -0
  109. package/android/src/main/java/com/renderrichtext/styles/ParagraphStyle.kt +33 -0
  110. package/android/src/main/java/com/renderrichtext/styles/SpoilerStyle.kt +27 -0
  111. package/android/src/main/java/com/renderrichtext/styles/StrikethroughStyle.kt +17 -0
  112. package/android/src/main/java/com/renderrichtext/styles/StrongStyle.kt +21 -0
  113. package/android/src/main/java/com/renderrichtext/styles/StyleConfig.kt +411 -0
  114. package/android/src/main/java/com/renderrichtext/styles/StyleParser.kt +92 -0
  115. package/android/src/main/java/com/renderrichtext/styles/SubscriptStyle.kt +16 -0
  116. package/android/src/main/java/com/renderrichtext/styles/SuperscriptStyle.kt +16 -0
  117. package/android/src/main/java/com/renderrichtext/styles/TableStyle.kt +75 -0
  118. package/android/src/main/java/com/renderrichtext/styles/TaskListStyle.kt +29 -0
  119. package/android/src/main/java/com/renderrichtext/styles/TextAlignment.kt +32 -0
  120. package/android/src/main/java/com/renderrichtext/styles/ThematicBreakStyle.kt +23 -0
  121. package/android/src/main/java/com/renderrichtext/styles/UnderlineStyle.kt +17 -0
  122. package/android/src/main/java/com/renderrichtext/styles/VideoStyle.kt +31 -0
  123. package/android/src/main/java/com/renderrichtext/utils/common/BorderStyleUtils.kt +86 -0
  124. package/android/src/main/java/com/renderrichtext/utils/common/BreakStrategyUtils.kt +32 -0
  125. package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockHighlighter.kt +36 -0
  126. package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockNode.kt +42 -0
  127. package/android/src/main/java/com/renderrichtext/utils/common/EllipsizeUtils.kt +27 -0
  128. package/android/src/main/java/com/renderrichtext/utils/common/EnrichedTiptapAncestorUtils.kt +10 -0
  129. package/android/src/main/java/com/renderrichtext/utils/common/FeatureFlags.kt +9 -0
  130. package/android/src/main/java/com/renderrichtext/utils/common/LinkRecognitionProps.kt +31 -0
  131. package/android/src/main/java/com/renderrichtext/utils/common/LinkRegexConfig.kt +56 -0
  132. package/android/src/main/java/com/renderrichtext/utils/common/MotionPreferences.kt +18 -0
  133. package/android/src/main/java/com/renderrichtext/utils/common/ReadableMapExtensions.kt +28 -0
  134. package/android/src/main/java/com/renderrichtext/utils/common/TiptapViewManagerUtils.kt +242 -0
  135. package/android/src/main/java/com/renderrichtext/utils/common/layout/RTLUtils.kt +6 -0
  136. package/android/src/main/java/com/renderrichtext/utils/common/serialization/TiptapASTSerializer.kt +368 -0
  137. package/android/src/main/java/com/renderrichtext/utils/text/ImageCache.kt +88 -0
  138. package/android/src/main/java/com/renderrichtext/utils/text/ImageDownloader.kt +203 -0
  139. package/android/src/main/java/com/renderrichtext/utils/text/LocalImageLoader.kt +167 -0
  140. package/android/src/main/java/com/renderrichtext/utils/text/TailFadeInAnimator.kt +84 -0
  141. package/android/src/main/java/com/renderrichtext/utils/text/conversion/HTMLGenerator.kt +1105 -0
  142. package/android/src/main/java/com/renderrichtext/utils/text/conversion/TiptapExtractor.kt +423 -0
  143. package/android/src/main/java/com/renderrichtext/utils/text/extensions/ParagraphUtils.kt +9 -0
  144. package/android/src/main/java/com/renderrichtext/utils/text/extensions/SpannableExtensions.kt +9 -0
  145. package/android/src/main/java/com/renderrichtext/utils/text/extensions/TextPaintExtensions.kt +76 -0
  146. package/android/src/main/java/com/renderrichtext/utils/text/interaction/CheckboxTouchHelper.kt +61 -0
  147. package/android/src/main/java/com/renderrichtext/utils/text/interaction/TaskListTapUtils.kt +286 -0
  148. package/android/src/main/java/com/renderrichtext/utils/text/span/ApplyLineHeight.kt +39 -0
  149. package/android/src/main/java/com/renderrichtext/utils/text/span/BlockSpacing.kt +142 -0
  150. package/android/src/main/java/com/renderrichtext/utils/text/span/SpanFlags.kt +43 -0
  151. package/android/src/main/java/com/renderrichtext/utils/text/span/WidthAwareSpans.kt +30 -0
  152. package/android/src/main/java/com/renderrichtext/utils/text/view/CodeBlockPressHost.kt +15 -0
  153. package/android/src/main/java/com/renderrichtext/utils/text/view/ImagePressHost.kt +19 -0
  154. package/android/src/main/java/com/renderrichtext/utils/text/view/LinkEvents.kt +88 -0
  155. package/android/src/main/java/com/renderrichtext/utils/text/view/LinkLongPressMovementMethod.kt +449 -0
  156. package/android/src/main/java/com/renderrichtext/utils/text/view/SelectionActionMode.kt +235 -0
  157. package/android/src/main/java/com/renderrichtext/utils/text/view/TextSelectionColors.kt +48 -0
  158. package/android/src/main/java/com/renderrichtext/utils/text/view/TextViewSetup.kt +119 -0
  159. package/android/src/main/java/com/renderrichtext/views/ContextMenuPopup.kt +217 -0
  160. package/android/src/main/java/com/renderrichtext/views/CopyGlyph.kt +101 -0
  161. package/android/src/main/java/com/renderrichtext/views/WrapGlyph.kt +40 -0
  162. package/android/src/main/jni/CMakeLists.txt +52 -0
  163. package/android/src/main/jni/react/renderer/components/RichTextSpec/ComponentDescriptors.h +30 -0
  164. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextComponentDescriptor.h +29 -0
  165. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.cpp +45 -0
  166. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.h +21 -0
  167. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.cpp +38 -0
  168. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.h +53 -0
  169. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.cpp +9 -0
  170. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.h +24 -0
  171. package/android/src/main/jni/react/renderer/components/RichTextSpec/conversions.h +40 -0
  172. package/cpp/parser/TiptapASTNode.hpp +68 -0
  173. package/cpp/parser/TiptapParser.cpp +233 -0
  174. package/cpp/parser/TiptapParser.hpp +13 -0
  175. package/cpp/vendor/nlohmann/json.hpp +24765 -0
  176. package/ios/EnrichedTiptapText.h +27 -0
  177. package/ios/EnrichedTiptapText.mm +1222 -0
  178. package/ios/attachments/ENRMImageAttachment.h +51 -0
  179. package/ios/attachments/ENRMImageAttachment.m +398 -0
  180. package/ios/attachments/ENRMLinkPillAttachment.h +47 -0
  181. package/ios/attachments/ENRMLinkPillAttachment.m +324 -0
  182. package/ios/attachments/ENRMLinkPillIconCache.h +28 -0
  183. package/ios/attachments/ENRMLinkPillIconCache.m +181 -0
  184. package/ios/attachments/ENRMLinkPillText.h +27 -0
  185. package/ios/attachments/ENRMLinkPillText.m +118 -0
  186. package/ios/attachments/ENRMMathInlineAttachment.h +7 -0
  187. package/ios/attachments/ENRMMathInlineAttachment.m +4 -0
  188. package/ios/attachments/ThematicBreakAttachment.h +15 -0
  189. package/ios/attachments/ThematicBreakAttachment.m +33 -0
  190. package/ios/internals/ENRMViewFreeMeasurement.h +208 -0
  191. package/ios/internals/EnrichedTiptapTextComponentDescriptor.h +19 -0
  192. package/ios/internals/EnrichedTiptapTextShadowNode.h +43 -0
  193. package/ios/internals/EnrichedTiptapTextShadowNode.mm +69 -0
  194. package/ios/internals/EnrichedTiptapTextState.h +24 -0
  195. package/ios/internals/MeasurementCache.h +308 -0
  196. package/ios/internals/ShadowMeasurementUtils.h +145 -0
  197. package/ios/parser/ENRMTextLinkAttributes.h +7 -0
  198. package/ios/parser/ENRMTiptapParser.h +33 -0
  199. package/ios/parser/ENRMTiptapParser.mm +73 -0
  200. package/ios/parser/TiptapASTNode.h +57 -0
  201. package/ios/parser/TiptapASTNode.m +52 -0
  202. package/ios/parser/TiptapParserBridge.mm +179 -0
  203. package/ios/renderer/AttributedRenderer.h +23 -0
  204. package/ios/renderer/AttributedRenderer.m +229 -0
  205. package/ios/renderer/BaseRenderer.h +33 -0
  206. package/ios/renderer/BaseRenderer.m +46 -0
  207. package/ios/renderer/BaselineShiftTextAttributes.h +10 -0
  208. package/ios/renderer/BaselineShiftTextAttributes.m +26 -0
  209. package/ios/renderer/BlankLineRenderer.h +4 -0
  210. package/ios/renderer/BlankLineRenderer.m +51 -0
  211. package/ios/renderer/BlockquoteRenderer.h +6 -0
  212. package/ios/renderer/BlockquoteRenderer.m +258 -0
  213. package/ios/renderer/CodeBlockRenderer.h +9 -0
  214. package/ios/renderer/CodeBlockRenderer.m +99 -0
  215. package/ios/renderer/CodeRenderer.h +9 -0
  216. package/ios/renderer/CodeRenderer.m +69 -0
  217. package/ios/renderer/ENRMBlockquoteTextRenderer.h +25 -0
  218. package/ios/renderer/ENRMBlockquoteTextRenderer.m +48 -0
  219. package/ios/renderer/EmphasisRenderer.h +5 -0
  220. package/ios/renderer/EmphasisRenderer.m +100 -0
  221. package/ios/renderer/FactoidRenderer.h +9 -0
  222. package/ios/renderer/FactoidRenderer.m +130 -0
  223. package/ios/renderer/HeadingRenderer.h +6 -0
  224. package/ios/renderer/HeadingRenderer.m +103 -0
  225. package/ios/renderer/HighlightRenderer.h +7 -0
  226. package/ios/renderer/HighlightRenderer.m +33 -0
  227. package/ios/renderer/LinkRenderer.h +6 -0
  228. package/ios/renderer/LinkRenderer.m +158 -0
  229. package/ios/renderer/ListItemRenderer.h +24 -0
  230. package/ios/renderer/ListItemRenderer.m +283 -0
  231. package/ios/renderer/ListRenderer.h +13 -0
  232. package/ios/renderer/ListRenderer.m +126 -0
  233. package/ios/renderer/MentionRenderer.h +9 -0
  234. package/ios/renderer/MentionRenderer.m +96 -0
  235. package/ios/renderer/NodeRenderer.h +8 -0
  236. package/ios/renderer/ParagraphRenderer.h +6 -0
  237. package/ios/renderer/ParagraphRenderer.m +85 -0
  238. package/ios/renderer/RenderContext.h +145 -0
  239. package/ios/renderer/RenderContext.m +403 -0
  240. package/ios/renderer/RendererFactory.h +12 -0
  241. package/ios/renderer/RendererFactory.m +158 -0
  242. package/ios/renderer/StrikethroughRenderer.h +5 -0
  243. package/ios/renderer/StrikethroughRenderer.m +30 -0
  244. package/ios/renderer/StrongRenderer.h +5 -0
  245. package/ios/renderer/StrongRenderer.m +88 -0
  246. package/ios/renderer/TextRenderer.h +6 -0
  247. package/ios/renderer/TextRenderer.m +18 -0
  248. package/ios/renderer/ThematicBreakRenderer.h +4 -0
  249. package/ios/renderer/ThematicBreakRenderer.m +42 -0
  250. package/ios/renderer/UnderlineRenderer.h +4 -0
  251. package/ios/renderer/UnderlineRenderer.m +41 -0
  252. package/ios/styles/ENRMFontSlot.h +12 -0
  253. package/ios/styles/ENRMFontSlot.m +24 -0
  254. package/ios/styles/StyleConfig.h +488 -0
  255. package/ios/styles/StyleConfig.mm +2820 -0
  256. package/ios/utils/AccessibilityInfo.h +35 -0
  257. package/ios/utils/AccessibilityInfo.m +24 -0
  258. package/ios/utils/BlockquoteBorder.h +26 -0
  259. package/ios/utils/BlockquoteBorder.m +294 -0
  260. package/ios/utils/CodeBackground.h +19 -0
  261. package/ios/utils/CodeBackground.m +197 -0
  262. package/ios/utils/CodeBlockBackground.h +17 -0
  263. package/ios/utils/CodeBlockBackground.m +103 -0
  264. package/ios/utils/ContextMenuUtils.h +76 -0
  265. package/ios/utils/ContextMenuUtils.mm +75 -0
  266. package/ios/utils/ENRMAccessibilityLabels.h +40 -0
  267. package/ios/utils/ENRMAccessibilityLabels.m +5 -0
  268. package/ios/utils/ENRMAsyncRenderCoordinator.h +24 -0
  269. package/ios/utils/ENRMAsyncRenderCoordinator.m +37 -0
  270. package/ios/utils/ENRMAtomicSize.h +65 -0
  271. package/ios/utils/ENRMCodeBlockContent.h +37 -0
  272. package/ios/utils/ENRMCodeBlockContent.mm +89 -0
  273. package/ios/utils/ENRMFeatureFlags.h +25 -0
  274. package/ios/utils/ENRMImageDownloader.h +30 -0
  275. package/ios/utils/ENRMImageDownloader.m +168 -0
  276. package/ios/utils/ENRMLatexErrorCoordinator.h +27 -0
  277. package/ios/utils/ENRMLatexErrorCoordinator.mm +75 -0
  278. package/ios/utils/ENRMLatexErrorReporting.h +13 -0
  279. package/ios/utils/ENRMLinkContextMenus.h +93 -0
  280. package/ios/utils/ENRMLinkContextMenus.m +178 -0
  281. package/ios/utils/ENRMLinkRegexConfig.h +30 -0
  282. package/ios/utils/ENRMLinkRegexConfig.mm +104 -0
  283. package/ios/utils/ENRMLinkRegexProps.h +23 -0
  284. package/ios/utils/ENRMLocalImageLoader.h +35 -0
  285. package/ios/utils/ENRMLocalImageLoader.m +111 -0
  286. package/ios/utils/ENRMMenuAction.h +27 -0
  287. package/ios/utils/ENRMMenuAction.m +33 -0
  288. package/ios/utils/ENRMSpoilerOverlayManager.h +15 -0
  289. package/ios/utils/ENRMSpoilerOverlayManager.m +19 -0
  290. package/ios/utils/ENRMSpoilerTapUtils.h +6 -0
  291. package/ios/utils/ENRMSpoilerTapUtils.m +11 -0
  292. package/ios/utils/ENRMTailFadeInAnimator.h +16 -0
  293. package/ios/utils/ENRMTailFadeInAnimator.m +161 -0
  294. package/ios/utils/ENRMTextHitTest.h +23 -0
  295. package/ios/utils/ENRMTextHitTest.m +20 -0
  296. package/ios/utils/ENRMTextInteractionUtils.h +20 -0
  297. package/ios/utils/ENRMTextInteractionUtils.m +15 -0
  298. package/ios/utils/ENRMTextRenderer.h +38 -0
  299. package/ios/utils/ENRMTextRenderer.m +54 -0
  300. package/ios/utils/ENRMTextViewSetup.h +132 -0
  301. package/ios/utils/ENRMUIKit.h +429 -0
  302. package/ios/utils/EditMenuUtils.h +105 -0
  303. package/ios/utils/EditMenuUtils.m +143 -0
  304. package/ios/utils/FactoidBackground.h +20 -0
  305. package/ios/utils/FactoidBackground.m +161 -0
  306. package/ios/utils/FontScaleObserver.h +10 -0
  307. package/ios/utils/FontScaleObserver.m +55 -0
  308. package/ios/utils/FontUtils.h +31 -0
  309. package/ios/utils/FontUtils.m +63 -0
  310. package/ios/utils/HTMLGenerator.h +25 -0
  311. package/ios/utils/HTMLGenerator.m +1041 -0
  312. package/ios/utils/HeightUpdateUtils.h +25 -0
  313. package/ios/utils/ImageRequestHeaderUtils.h +35 -0
  314. package/ios/utils/LastElementUtils.h +97 -0
  315. package/ios/utils/LinkContextMenuUtils.h +55 -0
  316. package/ios/utils/LinkPillContentUtils.h +46 -0
  317. package/ios/utils/LinkTapUtils.h +56 -0
  318. package/ios/utils/LinkTapUtils.m +139 -0
  319. package/ios/utils/ListMarkerDrawer.h +15 -0
  320. package/ios/utils/ListMarkerDrawer.m +239 -0
  321. package/ios/utils/MentionBackground.h +26 -0
  322. package/ios/utils/MentionBackground.m +86 -0
  323. package/ios/utils/ParagraphStyleUtils.h +87 -0
  324. package/ios/utils/ParagraphStyleUtils.m +484 -0
  325. package/ios/utils/PasteboardUtils.h +48 -0
  326. package/ios/utils/PasteboardUtils.m +166 -0
  327. package/ios/utils/RTFExportUtils.h +24 -0
  328. package/ios/utils/RTFExportUtils.m +299 -0
  329. package/ios/utils/RuntimeKeys.h +44 -0
  330. package/ios/utils/RuntimeKeys.m +13 -0
  331. package/ios/utils/SelectionColorUtils.h +14 -0
  332. package/ios/utils/StylePropsUtils.h +1340 -0
  333. package/ios/utils/TaskListTapUtils.h +6 -0
  334. package/ios/utils/TaskListTapUtils.m +14 -0
  335. package/ios/utils/TextViewLayoutManager.h +14 -0
  336. package/ios/utils/TextViewLayoutManager.mm +198 -0
  337. package/ios/utils/TiptapAccessibilityElementBuilder.h +43 -0
  338. package/ios/utils/TiptapAccessibilityElementBuilder.m +432 -0
  339. package/ios/utils/TiptapExtractor.h +17 -0
  340. package/ios/utils/TiptapExtractor.m +367 -0
  341. package/ios/views/ENRMTiptapTextView.h +25 -0
  342. package/ios/views/ENRMTiptapTextView.m +247 -0
  343. package/package.json +70 -6
  344. package/react-native.config.js +10 -0
  345. package/src/EnrichedTiptapTextNativeComponent.ts +739 -0
  346. package/src/RichText.tsx +164 -0
  347. package/src/admonitionDefaults.ts +58 -0
  348. package/src/darkModeTextStyle.ts +99 -0
  349. package/src/headingDefaults.ts +21 -0
  350. package/src/index.tsx +4 -0
  351. package/src/linkVariantUtils.ts +120 -0
  352. package/src/normalizeTiptapStyle.ts +397 -0
  353. package/src/rn-globals.d.ts +1 -0
  354. package/src/styleUtils.ts +107 -0
  355. package/src/types/TiptapStyle.ts +532 -0
  356. package/src/types/TiptapStyleInternal.ts +299 -0
  357. package/src/types/linkPill.ts +9 -0
  358. package/src/utils/isDev.ts +4 -0
@@ -0,0 +1,92 @@
1
+ package com.renderrichtext.styles
2
+
3
+ import android.content.Context
4
+ import com.facebook.react.bridge.ColorPropConverter
5
+ import com.facebook.react.bridge.ReadableMap
6
+ import com.facebook.react.uimanager.PixelUtil
7
+
8
+ class StyleParser(
9
+ private val context: Context,
10
+ private val allowFontScaling: Boolean,
11
+ private val maxFontSizeMultiplier: Float,
12
+ ) {
13
+ fun parseOptionalColor(
14
+ map: ReadableMap,
15
+ key: String,
16
+ ): Int? {
17
+ if (!map.hasKey(key) || map.isNull(key)) {
18
+ return null
19
+ }
20
+ val colorValue = map.getDouble(key)
21
+ return ColorPropConverter.getColor(colorValue, context)
22
+ }
23
+
24
+ fun parseColor(
25
+ map: ReadableMap,
26
+ key: String,
27
+ ): Int =
28
+ parseOptionalColor(map, key)
29
+ ?: throw IllegalArgumentException("Color key '$key' is missing, null, or invalid")
30
+
31
+ fun parseOptionalDouble(
32
+ map: ReadableMap,
33
+ key: String,
34
+ default: Double = 0.0,
35
+ ): Double =
36
+ if (map.hasKey(key) && !map.isNull(key)) {
37
+ map.getDouble(key)
38
+ } else {
39
+ default
40
+ }
41
+
42
+ fun parseOptionalInt(
43
+ map: ReadableMap,
44
+ key: String,
45
+ default: Int = 0,
46
+ ): Int =
47
+ if (map.hasKey(key) && !map.isNull(key)) {
48
+ map.getInt(key)
49
+ } else {
50
+ default
51
+ }
52
+
53
+ fun parseString(
54
+ map: ReadableMap,
55
+ key: String,
56
+ default: String = "",
57
+ ): String = map.getString(key) ?: default
58
+
59
+ fun parseBoolean(
60
+ map: ReadableMap,
61
+ key: String,
62
+ default: Boolean = false,
63
+ ): Boolean =
64
+ if (map.hasKey(key) && !map.isNull(key)) {
65
+ map.getBoolean(key)
66
+ } else {
67
+ default
68
+ }
69
+
70
+ fun toPixelFromSP(value: Float): Float {
71
+ val metrics = context.resources.displayMetrics
72
+ val baseDensity = metrics.density
73
+
74
+ if (!allowFontScaling) {
75
+ return value * baseDensity
76
+ }
77
+
78
+ var fontScale = metrics.scaledDensity / baseDensity
79
+ if (maxFontSizeMultiplier >= 1.0f && fontScale > maxFontSizeMultiplier) {
80
+ fontScale = maxFontSizeMultiplier
81
+ }
82
+
83
+ return value * baseDensity * fontScale
84
+ }
85
+
86
+ fun toPixelFromDIP(value: Float): Float = PixelUtil.toPixelFromDIP(value)
87
+
88
+ fun parseTextAlign(
89
+ map: ReadableMap,
90
+ key: String,
91
+ ): TextAlignment = TextAlignment.fromString(parseString(map, key, "left"))
92
+ }
@@ -0,0 +1,16 @@
1
+ package com.renderrichtext.styles
2
+
3
+ import com.facebook.react.bridge.ReadableMap
4
+
5
+ data class SubscriptStyle(
6
+ val fontScale: Float,
7
+ val baselineOffsetScale: Float,
8
+ ) {
9
+ companion object {
10
+ fun fromReadableMap(map: ReadableMap): SubscriptStyle =
11
+ SubscriptStyle(
12
+ fontScale = map.getDouble("fontScale").toFloat(),
13
+ baselineOffsetScale = map.getDouble("baselineOffsetScale").toFloat(),
14
+ )
15
+ }
16
+ }
@@ -0,0 +1,16 @@
1
+ package com.renderrichtext.styles
2
+
3
+ import com.facebook.react.bridge.ReadableMap
4
+
5
+ data class SuperscriptStyle(
6
+ val fontScale: Float,
7
+ val baselineOffsetScale: Float,
8
+ ) {
9
+ companion object {
10
+ fun fromReadableMap(map: ReadableMap): SuperscriptStyle =
11
+ SuperscriptStyle(
12
+ fontScale = map.getDouble("fontScale").toFloat(),
13
+ baselineOffsetScale = map.getDouble("baselineOffsetScale").toFloat(),
14
+ )
15
+ }
16
+ }
@@ -0,0 +1,75 @@
1
+ package com.renderrichtext.styles
2
+
3
+ import com.facebook.react.bridge.ReadableMap
4
+
5
+ data class TableStyle(
6
+ override val fontSize: Float,
7
+ override val fontFamily: String,
8
+ override val fontWeight: String,
9
+ override val color: Int,
10
+ override val marginTop: Float,
11
+ override val marginBottom: Float,
12
+ override val lineHeight: Float,
13
+ val headerFontFamily: String,
14
+ val headerBackgroundColor: Int,
15
+ val headerTextColor: Int,
16
+ val rowEvenBackgroundColor: Int,
17
+ val rowOddBackgroundColor: Int,
18
+ val borderColor: Int,
19
+ val borderWidth: Float,
20
+ val borderRadius: Float,
21
+ val cellPaddingHorizontal: Float,
22
+ val cellPaddingVertical: Float,
23
+ val horizontalOverflow: Float,
24
+ val align: String,
25
+ ) : BaseBlockStyle {
26
+ companion object {
27
+ fun fromReadableMap(
28
+ map: ReadableMap,
29
+ parser: StyleParser,
30
+ ): TableStyle {
31
+ val fontSize = parser.toPixelFromSP(map.getDouble("fontSize").toFloat())
32
+ val fontFamily = parser.parseString(map, "fontFamily")
33
+ val fontWeight = parser.parseString(map, "fontWeight", "normal")
34
+ val color = parser.parseColor(map, "color")
35
+ val marginTop = parser.toPixelFromDIP(map.getDouble("marginTop").toFloat())
36
+ val marginBottom = parser.toPixelFromDIP(map.getDouble("marginBottom").toFloat())
37
+ val lineHeightRaw = map.getDouble("lineHeight").toFloat()
38
+ val lineHeight = if (lineHeightRaw > 0f) parser.toPixelFromSP(lineHeightRaw) else 0f
39
+ val headerFontFamily = parser.parseString(map, "headerFontFamily")
40
+ val headerBackgroundColor = parser.parseColor(map, "headerBackgroundColor")
41
+ val headerTextColor = parser.parseColor(map, "headerTextColor")
42
+ val rowEvenBackgroundColor = parser.parseColor(map, "rowEvenBackgroundColor")
43
+ val rowOddBackgroundColor = parser.parseColor(map, "rowOddBackgroundColor")
44
+ val borderColor = parser.parseColor(map, "borderColor")
45
+ val borderWidth = parser.toPixelFromDIP(map.getDouble("borderWidth").toFloat())
46
+ val borderRadius = parser.toPixelFromDIP(map.getDouble("borderRadius").toFloat())
47
+ val cellPaddingHorizontal = parser.toPixelFromDIP(map.getDouble("cellPaddingHorizontal").toFloat())
48
+ val cellPaddingVertical = parser.toPixelFromDIP(map.getDouble("cellPaddingVertical").toFloat())
49
+ val horizontalOverflow = parser.toPixelFromDIP(map.getDouble("horizontalOverflow").toFloat())
50
+ val align = parser.parseString(map, "align")
51
+
52
+ return TableStyle(
53
+ fontSize = fontSize,
54
+ fontFamily = fontFamily,
55
+ fontWeight = fontWeight,
56
+ color = color,
57
+ marginTop = marginTop,
58
+ marginBottom = marginBottom,
59
+ lineHeight = lineHeight,
60
+ headerFontFamily = headerFontFamily,
61
+ headerBackgroundColor = headerBackgroundColor,
62
+ headerTextColor = headerTextColor,
63
+ rowEvenBackgroundColor = rowEvenBackgroundColor,
64
+ rowOddBackgroundColor = rowOddBackgroundColor,
65
+ borderColor = borderColor,
66
+ borderWidth = borderWidth,
67
+ borderRadius = borderRadius,
68
+ cellPaddingHorizontal = cellPaddingHorizontal,
69
+ cellPaddingVertical = cellPaddingVertical,
70
+ horizontalOverflow = horizontalOverflow,
71
+ align = align,
72
+ )
73
+ }
74
+ }
75
+ }
@@ -0,0 +1,29 @@
1
+ package com.renderrichtext.styles
2
+
3
+ import com.facebook.react.bridge.ReadableMap
4
+
5
+ data class TaskListStyle(
6
+ val checkedColor: Int,
7
+ val borderColor: Int,
8
+ val checkboxSize: Float,
9
+ val checkboxBorderRadius: Float,
10
+ val checkmarkColor: Int,
11
+ val checkedTextColor: Int,
12
+ val checkedStrikethrough: Boolean,
13
+ ) {
14
+ companion object {
15
+ fun fromReadableMap(
16
+ map: ReadableMap,
17
+ parser: StyleParser,
18
+ ): TaskListStyle =
19
+ TaskListStyle(
20
+ checkedColor = parser.parseColor(map, "checkedColor"),
21
+ borderColor = parser.parseColor(map, "borderColor"),
22
+ checkboxSize = parser.toPixelFromDIP(map.getDouble("checkboxSize").toFloat()),
23
+ checkboxBorderRadius = parser.toPixelFromDIP(map.getDouble("checkboxBorderRadius").toFloat()),
24
+ checkmarkColor = parser.parseColor(map, "checkmarkColor"),
25
+ checkedTextColor = parser.parseColor(map, "checkedTextColor"),
26
+ checkedStrikethrough = map.getBoolean("checkedStrikethrough"),
27
+ )
28
+ }
29
+ }
@@ -0,0 +1,32 @@
1
+ package com.renderrichtext.styles
2
+
3
+ import android.text.Layout
4
+
5
+ enum class TextAlignment(
6
+ val layoutAlignment: Layout.Alignment,
7
+ val needsJustify: Boolean,
8
+ ) {
9
+ LEFT(Layout.Alignment.ALIGN_NORMAL, false),
10
+ CENTER(Layout.Alignment.ALIGN_CENTER, false),
11
+ RIGHT(Layout.Alignment.ALIGN_OPPOSITE, false),
12
+ JUSTIFY(Layout.Alignment.ALIGN_NORMAL, true),
13
+ AUTO(Layout.Alignment.ALIGN_NORMAL, false),
14
+ ;
15
+
16
+ /**
17
+ * Whether an AlignmentSpan is needed.
18
+ * Only CENTER and RIGHT need explicit spans; LEFT/AUTO use default, JUSTIFY is handled at TextView level.
19
+ */
20
+ val needsAlignmentSpan: Boolean get() = this == CENTER || this == RIGHT
21
+
22
+ companion object {
23
+ fun fromString(value: String): TextAlignment =
24
+ when (value.lowercase()) {
25
+ "center" -> CENTER
26
+ "right" -> RIGHT
27
+ "justify" -> JUSTIFY
28
+ "auto" -> AUTO
29
+ else -> LEFT
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,23 @@
1
+ package com.renderrichtext.styles
2
+
3
+ import com.facebook.react.bridge.ReadableMap
4
+
5
+ data class ThematicBreakStyle(
6
+ val color: Int,
7
+ val height: Float,
8
+ val marginTop: Float,
9
+ val marginBottom: Float,
10
+ ) {
11
+ companion object {
12
+ fun fromReadableMap(
13
+ map: ReadableMap,
14
+ parser: StyleParser,
15
+ ): ThematicBreakStyle {
16
+ val color = parser.parseColor(map, "color")
17
+ val height = parser.toPixelFromDIP(map.getDouble("height").toFloat())
18
+ val marginTop = parser.toPixelFromDIP(map.getDouble("marginTop").toFloat())
19
+ val marginBottom = parser.toPixelFromDIP(map.getDouble("marginBottom").toFloat())
20
+ return ThematicBreakStyle(color, height, marginTop, marginBottom)
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,17 @@
1
+ package com.renderrichtext.styles
2
+
3
+ import com.facebook.react.bridge.ReadableMap
4
+
5
+ data class UnderlineStyle(
6
+ val color: Int,
7
+ ) {
8
+ companion object {
9
+ fun fromReadableMap(
10
+ map: ReadableMap,
11
+ parser: StyleParser,
12
+ ): UnderlineStyle {
13
+ val color = parser.parseColor(map, "color")
14
+ return UnderlineStyle(color)
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,31 @@
1
+ package com.renderrichtext.styles
2
+
3
+ import com.facebook.react.bridge.ReadableMap
4
+
5
+ data class VideoStyle(
6
+ val marginTop: Float,
7
+ val marginBottom: Float,
8
+ val borderRadius: Float,
9
+ val aspectRatio: Float,
10
+ val backgroundColor: Int,
11
+ ) {
12
+ /** Aspect ratio guaranteed to be positive. Falls back to 16:9 if the raw value is ≤ 0. */
13
+ val resolvedAspectRatio: Float
14
+ get() = if (aspectRatio > 0f) aspectRatio else DEFAULT_ASPECT_RATIO
15
+
16
+ companion object {
17
+ private const val DEFAULT_ASPECT_RATIO = 16f / 9f
18
+
19
+ fun fromReadableMap(
20
+ map: ReadableMap,
21
+ parser: StyleParser,
22
+ ): VideoStyle {
23
+ val marginTop = parser.toPixelFromDIP(map.getDouble("marginTop").toFloat())
24
+ val marginBottom = parser.toPixelFromDIP(map.getDouble("marginBottom").toFloat())
25
+ val borderRadius = parser.toPixelFromDIP(map.getDouble("borderRadius").toFloat())
26
+ val aspectRatio = map.getDouble("aspectRatio").toFloat()
27
+ val backgroundColor = parser.parseColor(map, "backgroundColor")
28
+ return VideoStyle(marginTop, marginBottom, borderRadius, aspectRatio, backgroundColor)
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,86 @@
1
+ package com.renderrichtext.utils.common
2
+
3
+ import android.view.View
4
+ import com.facebook.react.bridge.ColorPropConverter
5
+ import com.facebook.react.uimanager.BackgroundStyleApplicator
6
+ import com.facebook.react.uimanager.LengthPercentage
7
+ import com.facebook.react.uimanager.ReactStylesDiffMap
8
+ import com.facebook.react.uimanager.style.BorderRadiusProp
9
+ import com.facebook.react.uimanager.style.BorderStyle
10
+ import com.facebook.react.uimanager.style.LogicalEdge
11
+
12
+ // BaseViewManagerDelegate (used by our SimpleViewManagers) ignores border
13
+ // width/color/style and no-ops borderRadius, so `containerStyle` borders vanish on
14
+ // Android. Replay them via BackgroundStyleApplicator like ReactViewManager does.
15
+ // Call after super.updateProperties so the composite background drawable exists.
16
+ fun applyReactBorderProps(
17
+ view: View,
18
+ props: ReactStylesDiffMap,
19
+ ) {
20
+ for ((name, edge) in BORDER_WIDTH_EDGES) {
21
+ if (!props.hasKey(name)) continue
22
+ val width = if (props.isNull(name)) null else props.getFloat(name, Float.NaN).takeUnless { it.isNaN() }
23
+ BackgroundStyleApplicator.setBorderWidth(view, edge, width)
24
+ }
25
+
26
+ if (BORDER_COLOR_EDGES.keys.any { props.hasKey(it) }) {
27
+ val rawProps = props.toMap()
28
+ for ((name, edge) in BORDER_COLOR_EDGES) {
29
+ if (!props.hasKey(name)) continue
30
+ val color = if (props.isNull(name)) null else ColorPropConverter.getColor(rawProps[name], view.context)
31
+ BackgroundStyleApplicator.setBorderColor(view, edge, color)
32
+ }
33
+ }
34
+
35
+ if (props.hasKey("borderStyle")) {
36
+ val style = if (props.isNull("borderStyle")) null else BorderStyle.fromString(props.getString("borderStyle") ?: "")
37
+ BackgroundStyleApplicator.setBorderStyle(view, style)
38
+ }
39
+
40
+ // Radius last, so the border drawable created above already exists and picks
41
+ // up the rounded corners.
42
+ for ((name, corner) in BORDER_RADIUS_PROPS) {
43
+ if (!props.hasKey(name)) continue
44
+ val radius = if (props.isNull(name)) null else LengthPercentage.setFromDynamic(props.getDynamic(name))
45
+ BackgroundStyleApplicator.setBorderRadius(view, corner, radius)
46
+ }
47
+ }
48
+
49
+ private val BORDER_WIDTH_EDGES =
50
+ linkedMapOf(
51
+ "borderWidth" to LogicalEdge.ALL,
52
+ "borderLeftWidth" to LogicalEdge.LEFT,
53
+ "borderRightWidth" to LogicalEdge.RIGHT,
54
+ "borderTopWidth" to LogicalEdge.TOP,
55
+ "borderBottomWidth" to LogicalEdge.BOTTOM,
56
+ "borderStartWidth" to LogicalEdge.START,
57
+ "borderEndWidth" to LogicalEdge.END,
58
+ )
59
+
60
+ private val BORDER_COLOR_EDGES =
61
+ linkedMapOf(
62
+ "borderColor" to LogicalEdge.ALL,
63
+ "borderLeftColor" to LogicalEdge.LEFT,
64
+ "borderRightColor" to LogicalEdge.RIGHT,
65
+ "borderTopColor" to LogicalEdge.TOP,
66
+ "borderBottomColor" to LogicalEdge.BOTTOM,
67
+ "borderStartColor" to LogicalEdge.START,
68
+ "borderEndColor" to LogicalEdge.END,
69
+ )
70
+
71
+ private val BORDER_RADIUS_PROPS =
72
+ linkedMapOf(
73
+ "borderRadius" to BorderRadiusProp.BORDER_RADIUS,
74
+ "borderTopLeftRadius" to BorderRadiusProp.BORDER_TOP_LEFT_RADIUS,
75
+ "borderTopRightRadius" to BorderRadiusProp.BORDER_TOP_RIGHT_RADIUS,
76
+ "borderBottomRightRadius" to BorderRadiusProp.BORDER_BOTTOM_RIGHT_RADIUS,
77
+ "borderBottomLeftRadius" to BorderRadiusProp.BORDER_BOTTOM_LEFT_RADIUS,
78
+ "borderTopStartRadius" to BorderRadiusProp.BORDER_TOP_START_RADIUS,
79
+ "borderTopEndRadius" to BorderRadiusProp.BORDER_TOP_END_RADIUS,
80
+ "borderBottomStartRadius" to BorderRadiusProp.BORDER_BOTTOM_START_RADIUS,
81
+ "borderBottomEndRadius" to BorderRadiusProp.BORDER_BOTTOM_END_RADIUS,
82
+ "borderEndEndRadius" to BorderRadiusProp.BORDER_END_END_RADIUS,
83
+ "borderEndStartRadius" to BorderRadiusProp.BORDER_END_START_RADIUS,
84
+ "borderStartEndRadius" to BorderRadiusProp.BORDER_START_END_RADIUS,
85
+ "borderStartStartRadius" to BorderRadiusProp.BORDER_START_START_RADIUS,
86
+ )
@@ -0,0 +1,32 @@
1
+ package com.renderrichtext.utils.common
2
+
3
+ import android.text.Layout
4
+
5
+ /**
6
+ * Resolves a textBreakStrategy prop value (string) to the integer constant used
7
+ * by StaticLayout.Builder.setBreakStrategy() and TextView.setBreakStrategy().
8
+ *
9
+ * Stateless on purpose: textBreakStrategy is a per-view prop. Storage lives in
10
+ * [com.renderrichtext.MeasurementStore] (per viewId), and each
11
+ * view applies the resolved value to its own TextView. Both measurement and
12
+ * render paths must use the same value — mismatch causes measured line count
13
+ * to differ from the rendered line count, sizing the view incorrectly and
14
+ * causing ScrollingMovementMethod (inherited via LinkMovementMethod) to
15
+ * silently scroll the overflow.
16
+ *
17
+ * Note: call sites in StaticLayout.Builder suppress "WrongConstant" lint. This is
18
+ * intentional - Layout.BREAK_STRATEGY_SIMPLE and LineBreaker.BREAK_STRATEGY_SIMPLE
19
+ * are the same integer (0), but the @IntDef annotation on StaticLayout.Builder
20
+ * .setBreakStrategy() was changed from Layout.* to LineBreaker.* in API 29.
21
+ * The suppression is safe; the Layout.* constants share the same integer values.
22
+ */
23
+ object BreakStrategyUtils {
24
+ const val DEFAULT_STRATEGY = "highQuality"
25
+
26
+ fun resolveBreakStrategy(strategy: String?): Int =
27
+ when (strategy) {
28
+ "simple" -> Layout.BREAK_STRATEGY_SIMPLE
29
+ "balanced" -> Layout.BREAK_STRATEGY_BALANCED
30
+ else -> Layout.BREAK_STRATEGY_HIGH_QUALITY
31
+ }
32
+ }
@@ -0,0 +1,36 @@
1
+ package com.renderrichtext.utils.common
2
+
3
+ import android.text.Spannable
4
+ import com.renderrichtext.styles.CodeBlockStyle
5
+
6
+ /**
7
+ * Syntax highlighting is not part of this library. Code blocks stay plain
8
+ * monospace; the language attribute is kept on the node and not colored.
9
+ */
10
+ enum class HighlightTokenType {
11
+ Keyword,
12
+ Operator,
13
+ Punctuation,
14
+ String,
15
+ Number,
16
+ Constant,
17
+ Comment,
18
+ Function,
19
+ Type,
20
+ Variable,
21
+ Property,
22
+ Tag,
23
+ Attribute,
24
+ Embedded,
25
+ }
26
+
27
+ object CodeBlockHighlighter {
28
+ fun highlight(
29
+ target: Spannable,
30
+ code: String,
31
+ language: String?,
32
+ style: CodeBlockStyle,
33
+ offset: Int = 0,
34
+ ) {
35
+ }
36
+ }
@@ -0,0 +1,42 @@
1
+ package com.renderrichtext.utils.common
2
+
3
+ import com.renderrichtext.parser.TiptapASTNode
4
+
5
+ /**
6
+ * Shared code block node semantics, used by both tiptap flavors so the
7
+ * meaning of a CodeBlock AST node (its text, language, fence) is defined in
8
+ * one place. Language display names come from the shared C++ core
9
+ * (cpp/highlight/CodeBlockLanguages.hpp) so all platforms label fences
10
+ * identically; when the native library is unavailable the raw fence string
11
+ * is shown instead.
12
+ */
13
+ object CodeBlockNode {
14
+ fun extractCode(node: TiptapASTNode): String {
15
+ val builder = StringBuilder()
16
+
17
+ fun append(current: TiptapASTNode) {
18
+ builder.append(current.content)
19
+ current.children.forEach { append(it) }
20
+ }
21
+ append(node)
22
+ return builder.toString().trimEnd('\n')
23
+ }
24
+
25
+ fun language(node: TiptapASTNode): String? = node.getAttribute("language")?.takeIf { it.isNotEmpty() }
26
+
27
+ fun fenceChar(node: TiptapASTNode): String = node.getAttribute("fenceChar")?.takeIf { it.isNotEmpty() } ?: "`"
28
+
29
+ fun fencedTiptap(
30
+ code: String,
31
+ language: String?,
32
+ fenceChar: String,
33
+ ): String {
34
+ val fence = fenceChar.repeat(3)
35
+ return "$fence${language.orEmpty()}\n$code\n$fence"
36
+ }
37
+
38
+ fun displayLanguageName(language: String?): String {
39
+ if (language.isNullOrEmpty()) return ""
40
+ return language
41
+ }
42
+ }
@@ -0,0 +1,27 @@
1
+ package com.renderrichtext.utils.common
2
+
3
+ import android.text.TextUtils.TruncateAt
4
+
5
+ /**
6
+ * Resolves an ellipsizeMode prop value (string) to the TruncateAt used by
7
+ * StaticLayout.Builder.setEllipsize() and TextView.setEllipsize().
8
+ *
9
+ * "clip" maps to null: with maxLines set, the layout still truncates but draws
10
+ * no ellipsis glyph. Mirrors React Native's TextAttributeProps.getEllipsizeMode.
11
+ *
12
+ * Stateless like [BreakStrategyUtils]: the mode is a per-view prop stored per
13
+ * viewId in [com.renderrichtext.MeasurementStore]. Measurement and
14
+ * render paths must resolve the same value, or the measured line count diverges
15
+ * from the rendered one and the view is sized incorrectly.
16
+ */
17
+ object EllipsizeUtils {
18
+ const val DEFAULT_MODE = "tail"
19
+
20
+ fun resolveTruncateAt(mode: String?): TruncateAt? =
21
+ when (mode) {
22
+ "head" -> TruncateAt.START
23
+ "middle" -> TruncateAt.MIDDLE
24
+ "clip" -> null
25
+ else -> TruncateAt.END
26
+ }
27
+ }
@@ -0,0 +1,10 @@
1
+ package com.renderrichtext.utils.common
2
+
3
+ import android.view.View
4
+ import com.renderrichtext.EnrichedTiptapText
5
+
6
+ fun View.findEnrichedTiptapTextAncestor(): EnrichedTiptapText? {
7
+ var current: android.view.ViewParent? = parent
8
+ while (current != null && current !is EnrichedTiptapText) current = current.parent
9
+ return current as? EnrichedTiptapText
10
+ }
@@ -0,0 +1,9 @@
1
+ package com.renderrichtext.utils.common
2
+
3
+ import com.renderrichtext.BuildConfig
4
+
5
+ object FeatureFlags {
6
+ const val IS_MATH_ENABLED: Boolean = BuildConfig.ENABLE_MATH
7
+ const val IS_VIDEO_ENABLED: Boolean = BuildConfig.ENABLE_VIDEO
8
+ const val IS_CODE_HIGHLIGHT_ENABLED: Boolean = BuildConfig.ENABLE_CODE_HIGHLIGHT
9
+ }
@@ -0,0 +1,31 @@
1
+ package com.renderrichtext.utils.common
2
+
3
+ import com.facebook.react.bridge.ReadableMap
4
+
5
+ data class LinkRecognition(
6
+ val text: LinkRegexConfig? = null,
7
+ val inlineCode: LinkRegexConfig? = null,
8
+ ) {
9
+ companion object {
10
+ val NONE = LinkRecognition()
11
+ }
12
+ }
13
+
14
+ internal fun parseLinkRecognition(map: ReadableMap?): LinkRecognition {
15
+ if (map == null) return LinkRecognition.NONE
16
+ return LinkRecognition(
17
+ text = parseLinkRegexConfig(map.getMapOrNull("text")),
18
+ inlineCode = parseLinkRegexConfig(map.getMapOrNull("inlineCode")),
19
+ )
20
+ }
21
+
22
+ internal fun parseLinkRegexConfig(map: ReadableMap?): LinkRegexConfig? {
23
+ if (map == null) return null
24
+ return LinkRegexConfig(
25
+ pattern = if (map.hasKey("pattern")) map.getString("pattern") ?: "" else "",
26
+ caseInsensitive = map.hasKey("caseInsensitive") && map.getBoolean("caseInsensitive"),
27
+ dotAll = map.hasKey("dotAll") && map.getBoolean("dotAll"),
28
+ isDisabled = !map.hasKey("isDisabled") || map.getBoolean("isDisabled"),
29
+ isDefault = map.hasKey("isDefault") && map.getBoolean("isDefault"),
30
+ )
31
+ }
@@ -0,0 +1,56 @@
1
+ package com.renderrichtext.utils.common
2
+
3
+ import java.util.regex.Pattern
4
+ import java.util.regex.PatternSyntaxException
5
+
6
+ /** A regex sent from JS. Equal configs share compiled patterns. */
7
+ data class LinkRegexConfig(
8
+ val pattern: String,
9
+ val caseInsensitive: Boolean,
10
+ val dotAll: Boolean,
11
+ val isDisabled: Boolean,
12
+ val isDefault: Boolean,
13
+ ) {
14
+ private val isActive: Boolean
15
+ get() = !isDisabled && !isDefault && pattern.isNotEmpty()
16
+
17
+ /** Null when inactive or invalid. */
18
+ val compiled: Pattern?
19
+ get() = if (isActive) compiledPattern(pattern, flags) else null
20
+
21
+ /** Anchored to the whole string, for inline-code spans. */
22
+ val compiledWholeSpan: Pattern?
23
+ get() = if (isActive) compiledPattern("\\A(?:$pattern)\\z", flags) else null
24
+
25
+ private val flags: Int
26
+ get() = (if (caseInsensitive) Pattern.CASE_INSENSITIVE else 0) or (if (dotAll) Pattern.DOTALL else 0)
27
+
28
+ private companion object {
29
+ private const val MAX_CACHED_PATTERNS = 64
30
+ private val invalid = Pattern.compile("(?!)")
31
+
32
+ // Bounded LRU keyed by flags and source.
33
+ private val cache =
34
+ object : LinkedHashMap<String, Pattern>(MAX_CACHED_PATTERNS, 0.75f, true) {
35
+ override fun removeEldestEntry(eldest: MutableMap.MutableEntry<String, Pattern>): Boolean = size > MAX_CACHED_PATTERNS
36
+ }
37
+
38
+ @Synchronized
39
+ fun compiledPattern(
40
+ source: String,
41
+ flags: Int,
42
+ ): Pattern? {
43
+ val key = "$flags\u0000$source"
44
+ val cached = cache[key]
45
+ if (cached != null) return cached.takeUnless { it === invalid }
46
+ val compiled =
47
+ try {
48
+ Pattern.compile(source, flags)
49
+ } catch (_: PatternSyntaxException) {
50
+ invalid
51
+ }
52
+ cache[key] = compiled
53
+ return compiled.takeUnless { it === invalid }
54
+ }
55
+ }
56
+ }