@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,302 @@
1
+ package com.renderrichtext.spans
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.content.Context
5
+ import android.graphics.Canvas
6
+ import android.graphics.Color
7
+ import android.graphics.Paint
8
+ import android.graphics.Path
9
+ import android.graphics.RectF
10
+ import android.graphics.Typeface
11
+ import android.text.Layout
12
+ import android.text.Spanned
13
+ import android.text.TextPaint
14
+ import android.text.style.LeadingMarginSpan
15
+ import android.text.style.LineBackgroundSpan
16
+ import android.text.style.MetricAffectingSpan
17
+ import androidx.core.graphics.withSave
18
+ import com.renderrichtext.renderer.BlockStyle
19
+ import com.renderrichtext.renderer.SpanStyleCache
20
+ import com.renderrichtext.styles.BlockquoteStyle
21
+ import com.renderrichtext.utils.text.extensions.applyBlockStyleFont
22
+ import com.renderrichtext.utils.text.extensions.applyColorPreserving
23
+
24
+ class BlockquoteSpan(
25
+ private val blockquoteStyle: BlockquoteStyle,
26
+ val depth: Int,
27
+ private val context: Context,
28
+ private val styleCache: SpanStyleCache,
29
+ ) : MetricAffectingSpan(),
30
+ LeadingMarginSpan,
31
+ LineBackgroundSpan {
32
+ private val levelSpacing: Float = blockquoteStyle.borderWidth + blockquoteStyle.gapWidth
33
+ private val blockStyle =
34
+ BlockStyle(
35
+ fontSize = blockquoteStyle.fontSize,
36
+ fontFamily = blockquoteStyle.fontFamily,
37
+ fontWeight = blockquoteStyle.fontWeight,
38
+ color = blockquoteStyle.color,
39
+ )
40
+
41
+ // Cache for shouldSkipDrawing to avoid repeated getSpans() calls during draw passes
42
+ private var cachedText: CharSequence? = null
43
+ private var cachedSpansByPosition = mutableMapOf<Int, Array<BlockquoteSpan>>()
44
+ private var boxLeft = 0f
45
+ private var boxRight = 0f
46
+
47
+ private val path = Path()
48
+ private val rect = RectF()
49
+ private val radiiArray = FloatArray(8)
50
+
51
+ override fun updateMeasureState(tp: TextPaint) = applyTextStyle(tp)
52
+
53
+ override fun updateDrawState(tp: TextPaint) = applyTextStyle(tp)
54
+
55
+ override fun getLeadingMargin(first: Boolean): Int = levelSpacing.toInt()
56
+
57
+ override fun drawLeadingMargin(
58
+ c: Canvas,
59
+ p: Paint,
60
+ x: Int,
61
+ dir: Int,
62
+ top: Int,
63
+ baseline: Int,
64
+ bottom: Int,
65
+ text: CharSequence?,
66
+ start: Int,
67
+ end: Int,
68
+ first: Boolean,
69
+ layout: Layout?,
70
+ ) {
71
+ // Essential check from original: only the deepest span draws to prevent over-rendering background
72
+ if (shouldSkipDrawing(text, start)) return
73
+
74
+ val borderPaint = configureBorderPaint()
75
+ val radius = blockquoteStyle.borderRadius
76
+ val spanned = text as? Spanned
77
+
78
+ if (spanned == null) {
79
+ drawBorders(c, x, dir, top, bottom, borderPaint)
80
+ return
81
+ }
82
+
83
+ val rootSpan = spanAtMinDepth(spanned, start)
84
+ val clipToRoot =
85
+ radius > 0f && boxRight > boxLeft && rootSpan != null && isBoundaryLine(spanned, start, end, rootSpan)
86
+
87
+ val padding = blockquoteStyle.padding
88
+ var topInset = 0f
89
+ var bottomInset = 0f
90
+
91
+ for (level in 0..depth) {
92
+ val borderX = x + (levelSpacing * level * dir)
93
+ val borderRight = borderX + (blockquoteStyle.borderWidth * dir)
94
+ val stripeLeft = minOf(borderX, borderRight)
95
+ val stripeRight = maxOf(borderX, borderRight)
96
+ val stripeTop = top.toFloat() + topInset
97
+ val stripeBottom = bottom.toFloat() - bottomInset
98
+
99
+ val levelSpan = if (level == 0) rootSpan else spanAtDepth(spanned, start, level)
100
+ val clipToOwn =
101
+ radius > 0f && level > 0 && levelSpan != null && isBoundaryLine(spanned, start, end, levelSpan)
102
+
103
+ if (!clipToRoot && !clipToOwn) {
104
+ c.drawRect(stripeLeft, stripeTop, stripeRight, stripeBottom, borderPaint)
105
+ } else {
106
+ c.withSave {
107
+ if (clipToRoot) {
108
+ buildBoundaryPath(spanned, start, end, rootSpan!!, boxLeft, top.toFloat(), boxRight, bottom.toFloat())
109
+ clipPath(path)
110
+ }
111
+ if (clipToOwn) {
112
+ val clipLeft = if (dir >= 0) stripeLeft else boxLeft
113
+ val clipRight = if (dir >= 0) boxRight else stripeRight
114
+ buildBoundaryPath(spanned, start, end, levelSpan!!, clipLeft, stripeTop, clipRight, stripeBottom)
115
+ clipPath(path)
116
+ }
117
+ drawRect(stripeLeft, stripeTop, stripeRight, stripeBottom, borderPaint)
118
+ }
119
+ }
120
+
121
+ if (padding > 0 && levelSpan != null) {
122
+ if (start == spanned.getSpanStart(levelSpan)) topInset += padding
123
+ if (isLastLineOf(spanned, end, levelSpan)) bottomInset += padding
124
+ }
125
+ }
126
+ }
127
+
128
+ override fun drawBackground(
129
+ canvas: Canvas,
130
+ paint: Paint,
131
+ left: Int,
132
+ right: Int,
133
+ top: Int,
134
+ baseline: Int,
135
+ bottom: Int,
136
+ text: CharSequence,
137
+ start: Int,
138
+ end: Int,
139
+ lineNum: Int,
140
+ ) {
141
+ if (shouldSkipDrawing(text, start)) return
142
+
143
+ boxLeft = left.toFloat()
144
+ boxRight = right.toFloat()
145
+
146
+ val bgColor = blockquoteStyle.backgroundColor?.takeIf { it != Color.TRANSPARENT } ?: return
147
+ val backgroundPaint = configureBackgroundPaint(bgColor)
148
+ val radius = blockquoteStyle.borderRadius
149
+ val rootSpan = (text as? Spanned)?.let { spanAtMinDepth(it, start) }
150
+
151
+ if (radius <= 0f || rootSpan == null) {
152
+ canvas.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat(), backgroundPaint)
153
+ return
154
+ }
155
+
156
+ buildBoundaryPath(text as Spanned, start, end, rootSpan, left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat())
157
+ canvas.drawPath(path, backgroundPaint)
158
+ }
159
+
160
+ private fun drawBorders(
161
+ c: Canvas,
162
+ x: Int,
163
+ dir: Int,
164
+ top: Int,
165
+ bottom: Int,
166
+ borderPaint: Paint,
167
+ ) {
168
+ val borderTop = top.toFloat()
169
+ val borderBottom = bottom.toFloat()
170
+
171
+ for (level in 0..depth) {
172
+ val borderX = x + (levelSpacing * level * dir)
173
+ val borderRight = borderX + (blockquoteStyle.borderWidth * dir)
174
+ c.drawRect(minOf(borderX, borderRight), borderTop, maxOf(borderX, borderRight), borderBottom, borderPaint)
175
+ }
176
+ }
177
+
178
+ @SuppressLint("WrongConstant") // Result of mask is always valid: 0, 1, 2, or 3
179
+ private fun applyTextStyle(tp: TextPaint) {
180
+ tp.textSize = blockStyle.fontSize
181
+ val preserved = (tp.typeface?.style ?: 0) and BOLD_ITALIC_MASK
182
+ tp.applyBlockStyleFont(blockStyle, context)
183
+ if (preserved != 0) {
184
+ tp.typeface = Typeface.create(tp.typeface ?: Typeface.DEFAULT, preserved)
185
+ }
186
+ tp.applyColorPreserving(blockStyle.color, *styleCache.colorsToPreserve)
187
+ }
188
+
189
+ companion object {
190
+ private const val BOLD_ITALIC_MASK = Typeface.BOLD or Typeface.ITALIC
191
+
192
+ private val sharedBorderPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.FILL }
193
+ private val sharedBackgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.FILL }
194
+ }
195
+
196
+ private fun configureBorderPaint(): Paint =
197
+ sharedBorderPaint.apply {
198
+ color = blockquoteStyle.borderColor
199
+ }
200
+
201
+ private fun configureBackgroundPaint(bgColor: Int): Paint =
202
+ sharedBackgroundPaint.apply {
203
+ color = bgColor
204
+ }
205
+
206
+ private fun spansAt(
207
+ text: Spanned,
208
+ start: Int,
209
+ ): Array<BlockquoteSpan> {
210
+ if (cachedText !== text) {
211
+ cachedText = text
212
+ cachedSpansByPosition.clear()
213
+ }
214
+ return cachedSpansByPosition.getOrPut(start) {
215
+ text.getSpans(start, start + 1, BlockquoteSpan::class.java)
216
+ }
217
+ }
218
+
219
+ private fun shouldSkipDrawing(
220
+ text: CharSequence?,
221
+ start: Int,
222
+ ): Boolean {
223
+ if (text !is Spanned) return false
224
+ val maxDepth = spansAt(text, start).maxOfOrNull { it.depth } ?: -1
225
+ return maxDepth > depth
226
+ }
227
+
228
+ private fun spanAtMinDepth(
229
+ text: Spanned,
230
+ start: Int,
231
+ ): BlockquoteSpan? = spansAt(text, start).minByOrNull { it.depth }
232
+
233
+ private fun spanAtDepth(
234
+ text: Spanned,
235
+ start: Int,
236
+ level: Int,
237
+ ): BlockquoteSpan? = spansAt(text, start).firstOrNull { it.depth == level }
238
+
239
+ /**
240
+ * The span range can include trailing '\n'(s) that form no visible line (e.g. a
241
+ * paragraph break closing the quote), so the last drawn line ends before getSpanEnd;
242
+ * this compares against the end of visible content instead.
243
+ */
244
+ private fun isLastLineOf(
245
+ text: Spanned,
246
+ lineEnd: Int,
247
+ box: BlockquoteSpan,
248
+ ): Boolean {
249
+ var boxEnd = text.getSpanEnd(box)
250
+ while (boxEnd > 0 && text[boxEnd - 1] == '\n') {
251
+ boxEnd--
252
+ }
253
+ return lineEnd >= boxEnd
254
+ }
255
+
256
+ private fun isBoundaryLine(
257
+ text: Spanned,
258
+ lineStart: Int,
259
+ lineEnd: Int,
260
+ box: BlockquoteSpan,
261
+ ): Boolean {
262
+ val boxStart = text.getSpanStart(box)
263
+ val boxEnd = text.getSpanEnd(box)
264
+ if (boxStart !in 0 until boxEnd) return false
265
+ return lineStart == boxStart || isLastLineOf(text, lineEnd, box)
266
+ }
267
+
268
+ private fun buildBoundaryPath(
269
+ text: Spanned,
270
+ lineStart: Int,
271
+ lineEnd: Int,
272
+ box: BlockquoteSpan,
273
+ left: Float,
274
+ top: Float,
275
+ right: Float,
276
+ bottom: Float,
277
+ ) {
278
+ val boxStart = text.getSpanStart(box)
279
+
280
+ val isFirstLine = lineStart == boxStart
281
+ val isLastLine = isLastLineOf(text, lineEnd, box)
282
+
283
+ val radius = blockquoteStyle.borderRadius
284
+ radiiArray.fill(0f)
285
+ if (isFirstLine) {
286
+ radiiArray[0] = radius
287
+ radiiArray[1] = radius // Top-Left
288
+ radiiArray[2] = radius
289
+ radiiArray[3] = radius // Top-Right
290
+ }
291
+ if (isLastLine) {
292
+ radiiArray[4] = radius
293
+ radiiArray[5] = radius // Bottom-Right
294
+ radiiArray[6] = radius
295
+ radiiArray[7] = radius // Bottom-Left
296
+ }
297
+
298
+ rect.set(left, top, right, bottom)
299
+ path.reset()
300
+ path.addRoundRect(rect, radiiArray, Path.Direction.CW)
301
+ }
302
+ }
@@ -0,0 +1,205 @@
1
+ package com.renderrichtext.spans
2
+
3
+ import android.graphics.Canvas
4
+ import android.graphics.Paint
5
+ import android.graphics.Path
6
+ import android.graphics.RectF
7
+ import android.text.Spanned
8
+ import android.text.style.LineBackgroundSpan
9
+ import com.renderrichtext.spoiler.isConcealedBySpoiler
10
+ import com.renderrichtext.styles.StyleConfig
11
+ import kotlin.math.max
12
+ import kotlin.math.min
13
+
14
+ class CodeBackgroundSpan(
15
+ private val styleConfig: StyleConfig,
16
+ ) : LineBackgroundSpan {
17
+ companion object {
18
+ private const val CORNER_RADIUS = 10.0f
19
+ private const val BORDER_WIDTH = 1.0f
20
+
21
+ private val sharedBackgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.FILL }
22
+ private val sharedBorderPaint =
23
+ Paint(Paint.ANTI_ALIAS_FLAG).apply {
24
+ style = Paint.Style.STROKE
25
+ strokeWidth = BORDER_WIDTH
26
+ strokeJoin = Paint.Join.ROUND
27
+ strokeCap = Paint.Cap.ROUND
28
+ }
29
+ }
30
+
31
+ // Reusable drawing objects per instance
32
+ private val rect = RectF()
33
+ private val path = Path()
34
+
35
+ override fun drawBackground(
36
+ canvas: Canvas,
37
+ p: Paint,
38
+ left: Int,
39
+ right: Int,
40
+ top: Int,
41
+ baseline: Int,
42
+ bottom: Int,
43
+ text: CharSequence,
44
+ start: Int,
45
+ end: Int,
46
+ lineNum: Int,
47
+ ) {
48
+ if (text !is Spanned) return
49
+
50
+ val spanStart = text.getSpanStart(this)
51
+ val spanEnd = text.getSpanEnd(this)
52
+ if (spanStart !in 0 until spanEnd) return
53
+
54
+ // The spoiler overlay only covers the text's glyph box, so a background drawn to the line's bounds
55
+ // would outline the hidden code around it.
56
+ if (text.isConcealedBySpoiler(maxOf(spanStart, start), minOf(spanEnd, end))) return
57
+
58
+ // Keep CodeSpan and this background span intact for semantic extraction. Draw only
59
+ // portions outside replacement pills, including code surrounding a partially covered run.
60
+ fun drawUncoveredRange(
61
+ rangeStart: Int,
62
+ rangeEnd: Int,
63
+ ) {
64
+ if (max(rangeStart, start) >= min(rangeEnd, end)) return
65
+ // 1. Determine relative positioning
66
+ val isFirst = rangeStart >= start
67
+ val isLast = rangeEnd <= end
68
+
69
+ // 2. Calculate coordinates
70
+ val finalBottom = adjustBottomForMargin(text, end, bottom)
71
+ val leadingMargin = InlineBackgroundGeometry.leadingMarginAt(text, start)
72
+ val startX =
73
+ if (isFirst) {
74
+ InlineBackgroundGeometry.horizontalOffset(text, start, end, rangeStart, p, leadingMargin) + left
75
+ } else {
76
+ left.toFloat() + leadingMargin
77
+ }
78
+ val endX =
79
+ if (isLast) {
80
+ InlineBackgroundGeometry.horizontalOffset(text, start, end, rangeEnd, p, leadingMargin) + left
81
+ } else {
82
+ right.toFloat()
83
+ }
84
+
85
+ rect.set(min(startX, endX), top.toFloat(), max(startX, endX), finalBottom.toFloat())
86
+
87
+ // 3. Apply Style
88
+ val codeStyle = styleConfig.codeStyle
89
+ sharedBackgroundPaint.color = codeStyle.backgroundColor
90
+ sharedBorderPaint.color = codeStyle.borderColor
91
+
92
+ drawShapes(canvas, isFirst, isLast)
93
+ }
94
+
95
+ // Runs per code span, per line, per draw: only query for pills if the style can produce any.
96
+ val pills = if (styleConfig.hasLinkPills) text.getSpans(spanStart, spanEnd, LinkPillSpan::class.java) else emptyArray()
97
+ if (pills.isEmpty()) {
98
+ drawUncoveredRange(spanStart, spanEnd)
99
+ return
100
+ }
101
+ if (pills.size > 1) pills.sortBy { text.getSpanStart(it) }
102
+ var cursor = spanStart
103
+ for (pill in pills) {
104
+ val coveredStart = max(spanStart, text.getSpanStart(pill))
105
+ val coveredEnd = min(spanEnd, text.getSpanEnd(pill))
106
+ if (coveredStart >= coveredEnd) continue
107
+ if (cursor < coveredStart) drawUncoveredRange(cursor, coveredStart)
108
+ cursor = max(cursor, coveredEnd)
109
+ }
110
+ drawUncoveredRange(cursor, spanEnd)
111
+ }
112
+
113
+ private fun drawShapes(
114
+ canvas: Canvas,
115
+ isFirst: Boolean,
116
+ isLast: Boolean,
117
+ ) {
118
+ val radii = createRadii(isFirst, isLast)
119
+
120
+ path.reset()
121
+ path.addRoundRect(rect, radii, Path.Direction.CW)
122
+ canvas.drawPath(path, sharedBackgroundPaint)
123
+
124
+ if (isFirst && isLast) {
125
+ canvas.drawPath(path, sharedBorderPaint)
126
+ } else {
127
+ drawOpenBorders(canvas, isFirst, isLast)
128
+ }
129
+ }
130
+
131
+ private fun drawOpenBorders(
132
+ canvas: Canvas,
133
+ isFirst: Boolean,
134
+ isLast: Boolean,
135
+ ) {
136
+ val r = CORNER_RADIUS
137
+ path.reset()
138
+
139
+ if (isFirst) {
140
+ path.moveTo(rect.right, rect.top)
141
+ path.lineTo(rect.left + r, rect.top)
142
+ path.quadTo(rect.left, rect.top, rect.left, rect.top + r)
143
+ path.lineTo(rect.left, rect.bottom - r)
144
+ path.quadTo(rect.left, rect.bottom, rect.left + r, rect.bottom)
145
+ path.lineTo(rect.right, rect.bottom)
146
+ } else if (isLast) {
147
+ path.moveTo(rect.left, rect.top)
148
+ path.lineTo(rect.right - r, rect.top)
149
+ path.quadTo(rect.right, rect.top, rect.right, rect.top + r)
150
+ path.lineTo(rect.right, rect.bottom - r)
151
+ path.quadTo(rect.right, rect.bottom, rect.right - r, rect.bottom)
152
+ path.lineTo(rect.left, rect.bottom)
153
+ } else {
154
+ path.moveTo(rect.left, rect.top)
155
+ path.lineTo(rect.right, rect.top)
156
+ path.moveTo(rect.left, rect.bottom)
157
+ path.lineTo(rect.right, rect.bottom)
158
+ }
159
+ canvas.drawPath(path, sharedBorderPaint)
160
+ }
161
+
162
+ private fun createRadii(
163
+ isFirst: Boolean,
164
+ isLast: Boolean,
165
+ ) = when {
166
+ isFirst && isLast -> {
167
+ floatArrayOf(
168
+ CORNER_RADIUS,
169
+ CORNER_RADIUS,
170
+ CORNER_RADIUS,
171
+ CORNER_RADIUS,
172
+ CORNER_RADIUS,
173
+ CORNER_RADIUS,
174
+ CORNER_RADIUS,
175
+ CORNER_RADIUS,
176
+ )
177
+ }
178
+
179
+ isFirst -> {
180
+ floatArrayOf(CORNER_RADIUS, CORNER_RADIUS, 0f, 0f, 0f, 0f, CORNER_RADIUS, CORNER_RADIUS)
181
+ }
182
+
183
+ isLast -> {
184
+ floatArrayOf(0f, 0f, CORNER_RADIUS, CORNER_RADIUS, CORNER_RADIUS, CORNER_RADIUS, 0f, 0f)
185
+ }
186
+
187
+ else -> {
188
+ floatArrayOf(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f)
189
+ }
190
+ }
191
+
192
+ private fun adjustBottomForMargin(
193
+ text: Spanned,
194
+ lineEnd: Int,
195
+ bottom: Int,
196
+ ): Int {
197
+ if (lineEnd <= 0 || lineEnd > text.length || text[lineEnd - 1] != '\n') return bottom
198
+ val marginSpans = text.getSpans(lineEnd - 1, lineEnd, MarginBottomSpan::class.java)
199
+ var adjusted = bottom
200
+ for (span in marginSpans) {
201
+ if (text.getSpanEnd(span) == lineEnd) adjusted -= span.marginBottom.toInt()
202
+ }
203
+ return adjusted
204
+ }
205
+ }