@mathers101/react-native-render-rich-text 0.1.9 → 0.1.14

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 (327) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +140 -140
  3. package/ReactNativeRenderRichText.podspec +23 -23
  4. package/android/build.gradle +86 -86
  5. package/android/consumer-rules.pro +3 -3
  6. package/android/src/main/AndroidManifest.xml +2 -2
  7. package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextLayoutManager.kt +24 -24
  8. package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextPackage.kt +13 -13
  9. package/android/src/main/java/com/renderrichtext/MeasurementStore.kt +644 -644
  10. package/android/src/main/java/com/renderrichtext/accessibility/AccessibilityLabels.kt +17 -17
  11. package/android/src/main/java/com/renderrichtext/accessibility/AccessibleTiptapTextView.kt +112 -112
  12. package/android/src/main/java/com/renderrichtext/accessibility/TiptapAccessibilityHelper.kt +576 -576
  13. package/android/src/main/java/com/renderrichtext/events/CodeBlockPressEvent.kt +24 -24
  14. package/android/src/main/java/com/renderrichtext/events/ContextMenuItemPressEvent.kt +28 -28
  15. package/android/src/main/java/com/renderrichtext/events/CopyPressEvent.kt +24 -24
  16. package/android/src/main/java/com/renderrichtext/events/ImagePressEvent.kt +25 -25
  17. package/android/src/main/java/com/renderrichtext/events/LatexErrorEvent.kt +29 -29
  18. package/android/src/main/java/com/renderrichtext/events/LinkLongPressEvent.kt +23 -23
  19. package/android/src/main/java/com/renderrichtext/events/LinkPressEvent.kt +23 -23
  20. package/android/src/main/java/com/renderrichtext/events/MentionLongPressEvent.kt +25 -25
  21. package/android/src/main/java/com/renderrichtext/events/MentionPressEvent.kt +25 -25
  22. package/android/src/main/java/com/renderrichtext/events/TaskListItemPressEvent.kt +26 -26
  23. package/android/src/main/java/com/renderrichtext/math/LatexErrorReporter.kt +9 -9
  24. package/android/src/main/java/com/renderrichtext/parser/Parser.kt +59 -59
  25. package/android/src/main/java/com/renderrichtext/parser/TextLinkMatching.kt +35 -35
  26. package/android/src/main/java/com/renderrichtext/renderer/BaselineShiftRenderer.kt +45 -45
  27. package/android/src/main/java/com/renderrichtext/renderer/BlankLineRenderer.kt +39 -39
  28. package/android/src/main/java/com/renderrichtext/renderer/BlockquoteRenderer.kt +243 -243
  29. package/android/src/main/java/com/renderrichtext/renderer/BlockquoteTextRenderer.kt +56 -56
  30. package/android/src/main/java/com/renderrichtext/renderer/CodeBlockRenderer.kt +135 -135
  31. package/android/src/main/java/com/renderrichtext/renderer/CodeRenderer.kt +37 -37
  32. package/android/src/main/java/com/renderrichtext/renderer/EmphasisRenderer.kt +28 -28
  33. package/android/src/main/java/com/renderrichtext/renderer/HeadingRenderer.kt +81 -81
  34. package/android/src/main/java/com/renderrichtext/renderer/HighlightRenderer.kt +26 -26
  35. package/android/src/main/java/com/renderrichtext/renderer/LineBreakRenderer.kt +17 -17
  36. package/android/src/main/java/com/renderrichtext/renderer/LinkRenderer.kt +90 -90
  37. package/android/src/main/java/com/renderrichtext/renderer/ListContextManager.kt +109 -109
  38. package/android/src/main/java/com/renderrichtext/renderer/ListItemRenderer.kt +211 -211
  39. package/android/src/main/java/com/renderrichtext/renderer/ListRenderer.kt +133 -133
  40. package/android/src/main/java/com/renderrichtext/renderer/MentionRenderer.kt +85 -85
  41. package/android/src/main/java/com/renderrichtext/renderer/ParagraphRenderer.kt +91 -91
  42. package/android/src/main/java/com/renderrichtext/renderer/Renderer.kt +148 -148
  43. package/android/src/main/java/com/renderrichtext/renderer/SoftBreakRenderer.kt +17 -17
  44. package/android/src/main/java/com/renderrichtext/renderer/SpanStyleCache.kt +143 -143
  45. package/android/src/main/java/com/renderrichtext/renderer/StrikethroughRenderer.kt +28 -28
  46. package/android/src/main/java/com/renderrichtext/renderer/StrongRenderer.kt +28 -28
  47. package/android/src/main/java/com/renderrichtext/renderer/TextRenderer.kt +31 -31
  48. package/android/src/main/java/com/renderrichtext/renderer/ThematicBreakRenderer.kt +46 -46
  49. package/android/src/main/java/com/renderrichtext/renderer/UnderlineRenderer.kt +28 -28
  50. package/android/src/main/java/com/renderrichtext/spans/BaseListSpan.kt +164 -164
  51. package/android/src/main/java/com/renderrichtext/spans/BaselineShiftSpan.kt +27 -27
  52. package/android/src/main/java/com/renderrichtext/spans/BlockquoteSpan.kt +302 -302
  53. package/android/src/main/java/com/renderrichtext/spans/CodeBackgroundSpan.kt +205 -205
  54. package/android/src/main/java/com/renderrichtext/spans/CodeBlockSpan.kt +216 -216
  55. package/android/src/main/java/com/renderrichtext/spans/CodeSpan.kt +32 -32
  56. package/android/src/main/java/com/renderrichtext/spans/EmphasisSpan.kt +42 -42
  57. package/android/src/main/java/com/renderrichtext/spans/FadeInSpan.kt +29 -29
  58. package/android/src/main/java/com/renderrichtext/spans/HeadingSpan.kt +38 -38
  59. package/android/src/main/java/com/renderrichtext/spans/HighlightSpan.kt +80 -80
  60. package/android/src/main/java/com/renderrichtext/spans/ImageSpan.kt +481 -481
  61. package/android/src/main/java/com/renderrichtext/spans/InlineBackgroundGeometry.kt +42 -42
  62. package/android/src/main/java/com/renderrichtext/spans/LineHeightSpan.kt +39 -39
  63. package/android/src/main/java/com/renderrichtext/spans/LinkPillIconCache.kt +154 -154
  64. package/android/src/main/java/com/renderrichtext/spans/LinkPillSpan.kt +381 -381
  65. package/android/src/main/java/com/renderrichtext/spans/LinkSpan.kt +68 -68
  66. package/android/src/main/java/com/renderrichtext/spans/ListItemSpacingSpan.kt +33 -33
  67. package/android/src/main/java/com/renderrichtext/spans/ListMarkerAnchorSpan.kt +38 -38
  68. package/android/src/main/java/com/renderrichtext/spans/MarginBottomSpan.kt +76 -76
  69. package/android/src/main/java/com/renderrichtext/spans/MentionChipSpan.kt +132 -132
  70. package/android/src/main/java/com/renderrichtext/spans/MentionSpan.kt +46 -46
  71. package/android/src/main/java/com/renderrichtext/spans/OrderedListSpan.kt +127 -127
  72. package/android/src/main/java/com/renderrichtext/spans/SpoilerSpan.kt +33 -33
  73. package/android/src/main/java/com/renderrichtext/spans/StrikethroughSpan.kt +12 -12
  74. package/android/src/main/java/com/renderrichtext/spans/StrongSpan.kt +39 -39
  75. package/android/src/main/java/com/renderrichtext/spans/TaskListSpan.kt +143 -143
  76. package/android/src/main/java/com/renderrichtext/spans/TextSpan.kt +26 -26
  77. package/android/src/main/java/com/renderrichtext/spans/ThematicBreakSpan.kt +69 -69
  78. package/android/src/main/java/com/renderrichtext/spans/UnorderedListSpan.kt +96 -96
  79. package/android/src/main/java/com/renderrichtext/spoiler/SpoilerStubs.kt +46 -46
  80. package/android/src/main/java/com/renderrichtext/styles/BaseBlockStyle.kt +11 -11
  81. package/android/src/main/java/com/renderrichtext/styles/BlockquoteStyle.kt +83 -83
  82. package/android/src/main/java/com/renderrichtext/styles/CodeBlockStyle.kt +80 -80
  83. package/android/src/main/java/com/renderrichtext/styles/CodeStyle.kt +26 -26
  84. package/android/src/main/java/com/renderrichtext/styles/EmphasisStyle.kt +21 -21
  85. package/android/src/main/java/com/renderrichtext/styles/FactoidStyle.kt +21 -21
  86. package/android/src/main/java/com/renderrichtext/styles/HeadingStyle.kt +33 -33
  87. package/android/src/main/java/com/renderrichtext/styles/HighlightStyle.kt +19 -19
  88. package/android/src/main/java/com/renderrichtext/styles/ImageStyle.kt +29 -29
  89. package/android/src/main/java/com/renderrichtext/styles/InlineImageStyle.kt +17 -17
  90. package/android/src/main/java/com/renderrichtext/styles/InlineMathStyle.kt +17 -17
  91. package/android/src/main/java/com/renderrichtext/styles/LinkPillContent.kt +36 -36
  92. package/android/src/main/java/com/renderrichtext/styles/LinkPillStyle.kt +44 -44
  93. package/android/src/main/java/com/renderrichtext/styles/LinkStyle.kt +23 -23
  94. package/android/src/main/java/com/renderrichtext/styles/LinkVariantEntry.kt +34 -34
  95. package/android/src/main/java/com/renderrichtext/styles/ListStyle.kt +65 -65
  96. package/android/src/main/java/com/renderrichtext/styles/MathStyle.kt +29 -29
  97. package/android/src/main/java/com/renderrichtext/styles/MentionStyle.kt +19 -19
  98. package/android/src/main/java/com/renderrichtext/styles/ParagraphStyle.kt +33 -33
  99. package/android/src/main/java/com/renderrichtext/styles/SpoilerStyle.kt +27 -27
  100. package/android/src/main/java/com/renderrichtext/styles/StrikethroughStyle.kt +17 -17
  101. package/android/src/main/java/com/renderrichtext/styles/StrongStyle.kt +21 -21
  102. package/android/src/main/java/com/renderrichtext/styles/StyleConfig.kt +411 -411
  103. package/android/src/main/java/com/renderrichtext/styles/StyleParser.kt +92 -92
  104. package/android/src/main/java/com/renderrichtext/styles/SubscriptStyle.kt +16 -16
  105. package/android/src/main/java/com/renderrichtext/styles/SuperscriptStyle.kt +16 -16
  106. package/android/src/main/java/com/renderrichtext/styles/TableStyle.kt +75 -75
  107. package/android/src/main/java/com/renderrichtext/styles/TaskListStyle.kt +29 -29
  108. package/android/src/main/java/com/renderrichtext/styles/TextAlignment.kt +32 -32
  109. package/android/src/main/java/com/renderrichtext/styles/ThematicBreakStyle.kt +23 -23
  110. package/android/src/main/java/com/renderrichtext/styles/UnderlineStyle.kt +17 -17
  111. package/android/src/main/java/com/renderrichtext/styles/VideoStyle.kt +31 -31
  112. package/android/src/main/java/com/renderrichtext/utils/common/BorderStyleUtils.kt +86 -86
  113. package/android/src/main/java/com/renderrichtext/utils/common/BreakStrategyUtils.kt +32 -32
  114. package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockHighlighter.kt +36 -36
  115. package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockNode.kt +42 -42
  116. package/android/src/main/java/com/renderrichtext/utils/common/EllipsizeUtils.kt +27 -27
  117. package/android/src/main/java/com/renderrichtext/utils/common/EnrichedTiptapAncestorUtils.kt +10 -10
  118. package/android/src/main/java/com/renderrichtext/utils/common/FeatureFlags.kt +9 -9
  119. package/android/src/main/java/com/renderrichtext/utils/common/LinkRecognitionProps.kt +31 -31
  120. package/android/src/main/java/com/renderrichtext/utils/common/LinkRegexConfig.kt +56 -56
  121. package/android/src/main/java/com/renderrichtext/utils/common/MotionPreferences.kt +18 -18
  122. package/android/src/main/java/com/renderrichtext/utils/common/ReadableMapExtensions.kt +28 -28
  123. package/android/src/main/java/com/renderrichtext/utils/common/layout/RTLUtils.kt +6 -6
  124. package/android/src/main/java/com/renderrichtext/utils/common/serialization/TiptapASTSerializer.kt +368 -368
  125. package/android/src/main/java/com/renderrichtext/utils/text/ImageCache.kt +88 -88
  126. package/android/src/main/java/com/renderrichtext/utils/text/ImageDownloader.kt +203 -203
  127. package/android/src/main/java/com/renderrichtext/utils/text/LocalImageLoader.kt +167 -167
  128. package/android/src/main/java/com/renderrichtext/utils/text/TailFadeInAnimator.kt +84 -84
  129. package/android/src/main/java/com/renderrichtext/utils/text/conversion/HTMLGenerator.kt +1105 -1105
  130. package/android/src/main/java/com/renderrichtext/utils/text/conversion/TiptapExtractor.kt +423 -423
  131. package/android/src/main/java/com/renderrichtext/utils/text/extensions/ParagraphUtils.kt +9 -9
  132. package/android/src/main/java/com/renderrichtext/utils/text/extensions/SpannableExtensions.kt +9 -9
  133. package/android/src/main/java/com/renderrichtext/utils/text/extensions/TextPaintExtensions.kt +76 -76
  134. package/android/src/main/java/com/renderrichtext/utils/text/interaction/CheckboxTouchHelper.kt +61 -61
  135. package/android/src/main/java/com/renderrichtext/utils/text/interaction/TaskListTapUtils.kt +286 -286
  136. package/android/src/main/java/com/renderrichtext/utils/text/span/ApplyLineHeight.kt +39 -39
  137. package/android/src/main/java/com/renderrichtext/utils/text/span/BlockSpacing.kt +142 -142
  138. package/android/src/main/java/com/renderrichtext/utils/text/span/SpanFlags.kt +43 -43
  139. package/android/src/main/java/com/renderrichtext/utils/text/span/WidthAwareSpans.kt +30 -30
  140. package/android/src/main/java/com/renderrichtext/utils/text/view/CodeBlockPressHost.kt +15 -15
  141. package/android/src/main/java/com/renderrichtext/utils/text/view/ImagePressHost.kt +19 -19
  142. package/android/src/main/java/com/renderrichtext/utils/text/view/SelectionActionMode.kt +235 -235
  143. package/android/src/main/java/com/renderrichtext/utils/text/view/TextSelectionColors.kt +48 -48
  144. package/android/src/main/java/com/renderrichtext/utils/text/view/TextViewSetup.kt +119 -119
  145. package/android/src/main/java/com/renderrichtext/views/ContextMenuPopup.kt +217 -217
  146. package/android/src/main/java/com/renderrichtext/views/CopyGlyph.kt +101 -101
  147. package/android/src/main/java/com/renderrichtext/views/WrapGlyph.kt +40 -40
  148. package/android/src/main/jni/CMakeLists.txt +52 -52
  149. package/android/src/main/jni/react/renderer/components/RichTextSpec/ComponentDescriptors.h +30 -30
  150. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextComponentDescriptor.h +29 -29
  151. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.cpp +45 -45
  152. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.h +21 -21
  153. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.cpp +38 -38
  154. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.h +53 -53
  155. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.cpp +9 -9
  156. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.h +24 -24
  157. package/android/src/main/jni/react/renderer/components/RichTextSpec/conversions.h +40 -40
  158. package/cpp/parser/TiptapParser.hpp +13 -13
  159. package/cpp/vendor/nlohmann/json.hpp +24765 -24765
  160. package/ios/EnrichedTiptapText.h +27 -27
  161. package/ios/attachments/ENRMImageAttachment.h +51 -51
  162. package/ios/attachments/ENRMImageAttachment.m +398 -398
  163. package/ios/attachments/ENRMLinkPillAttachment.h +47 -47
  164. package/ios/attachments/ENRMLinkPillAttachment.m +324 -324
  165. package/ios/attachments/ENRMLinkPillIconCache.h +28 -28
  166. package/ios/attachments/ENRMLinkPillIconCache.m +181 -181
  167. package/ios/attachments/ENRMLinkPillText.h +27 -27
  168. package/ios/attachments/ENRMLinkPillText.m +118 -118
  169. package/ios/attachments/ENRMMathInlineAttachment.h +7 -7
  170. package/ios/attachments/ENRMMathInlineAttachment.m +4 -4
  171. package/ios/attachments/ThematicBreakAttachment.h +15 -15
  172. package/ios/attachments/ThematicBreakAttachment.m +33 -33
  173. package/ios/internals/ENRMViewFreeMeasurement.h +208 -208
  174. package/ios/internals/EnrichedTiptapTextComponentDescriptor.h +19 -19
  175. package/ios/internals/EnrichedTiptapTextShadowNode.h +43 -43
  176. package/ios/internals/EnrichedTiptapTextShadowNode.mm +69 -69
  177. package/ios/internals/EnrichedTiptapTextState.h +24 -24
  178. package/ios/internals/MeasurementCache.h +308 -308
  179. package/ios/internals/ShadowMeasurementUtils.h +145 -145
  180. package/ios/parser/ENRMTextLinkAttributes.h +7 -7
  181. package/ios/parser/ENRMTiptapParser.h +33 -33
  182. package/ios/parser/ENRMTiptapParser.mm +73 -73
  183. package/ios/parser/TiptapASTNode.m +52 -52
  184. package/ios/renderer/AttributedRenderer.h +23 -23
  185. package/ios/renderer/AttributedRenderer.m +229 -229
  186. package/ios/renderer/BaseRenderer.h +33 -33
  187. package/ios/renderer/BaseRenderer.m +46 -46
  188. package/ios/renderer/BaselineShiftTextAttributes.h +10 -10
  189. package/ios/renderer/BaselineShiftTextAttributes.m +26 -26
  190. package/ios/renderer/BlankLineRenderer.h +4 -4
  191. package/ios/renderer/BlankLineRenderer.m +51 -51
  192. package/ios/renderer/BlockquoteRenderer.h +6 -6
  193. package/ios/renderer/BlockquoteRenderer.m +258 -258
  194. package/ios/renderer/CodeBlockRenderer.h +9 -9
  195. package/ios/renderer/CodeBlockRenderer.m +99 -99
  196. package/ios/renderer/CodeRenderer.h +9 -9
  197. package/ios/renderer/CodeRenderer.m +69 -69
  198. package/ios/renderer/ENRMBlockquoteTextRenderer.h +25 -25
  199. package/ios/renderer/ENRMBlockquoteTextRenderer.m +48 -48
  200. package/ios/renderer/EmphasisRenderer.h +5 -5
  201. package/ios/renderer/EmphasisRenderer.m +99 -99
  202. package/ios/renderer/HeadingRenderer.h +6 -6
  203. package/ios/renderer/HeadingRenderer.m +102 -102
  204. package/ios/renderer/HighlightRenderer.h +7 -7
  205. package/ios/renderer/HighlightRenderer.m +33 -33
  206. package/ios/renderer/LinkRenderer.h +6 -6
  207. package/ios/renderer/LinkRenderer.m +157 -157
  208. package/ios/renderer/ListItemRenderer.h +24 -24
  209. package/ios/renderer/ListItemRenderer.m +283 -283
  210. package/ios/renderer/ListRenderer.h +13 -13
  211. package/ios/renderer/ListRenderer.m +126 -126
  212. package/ios/renderer/MentionRenderer.h +9 -9
  213. package/ios/renderer/MentionRenderer.m +96 -96
  214. package/ios/renderer/NodeRenderer.h +8 -8
  215. package/ios/renderer/ParagraphRenderer.h +6 -6
  216. package/ios/renderer/ParagraphRenderer.m +85 -85
  217. package/ios/renderer/RenderContext.h +145 -145
  218. package/ios/renderer/RenderContext.m +402 -402
  219. package/ios/renderer/RendererFactory.h +12 -12
  220. package/ios/renderer/StrikethroughRenderer.h +5 -5
  221. package/ios/renderer/StrikethroughRenderer.m +30 -30
  222. package/ios/renderer/StrongRenderer.h +5 -5
  223. package/ios/renderer/StrongRenderer.m +87 -87
  224. package/ios/renderer/TextRenderer.h +6 -6
  225. package/ios/renderer/TextRenderer.m +18 -18
  226. package/ios/renderer/ThematicBreakRenderer.h +4 -4
  227. package/ios/renderer/ThematicBreakRenderer.m +41 -41
  228. package/ios/renderer/UnderlineRenderer.h +4 -4
  229. package/ios/renderer/UnderlineRenderer.m +41 -41
  230. package/ios/styles/ENRMFontSlot.h +12 -12
  231. package/ios/styles/ENRMFontSlot.m +24 -24
  232. package/ios/styles/StyleConfig.h +488 -488
  233. package/ios/styles/StyleConfig.mm +2820 -2820
  234. package/ios/utils/AccessibilityInfo.h +35 -35
  235. package/ios/utils/AccessibilityInfo.m +24 -24
  236. package/ios/utils/BlockquoteBorder.h +26 -26
  237. package/ios/utils/BlockquoteBorder.m +294 -294
  238. package/ios/utils/CodeBackground.h +19 -19
  239. package/ios/utils/CodeBackground.m +196 -196
  240. package/ios/utils/CodeBlockBackground.h +17 -17
  241. package/ios/utils/CodeBlockBackground.m +102 -102
  242. package/ios/utils/ContextMenuUtils.h +76 -76
  243. package/ios/utils/ContextMenuUtils.mm +75 -75
  244. package/ios/utils/ENRMAccessibilityLabels.h +40 -40
  245. package/ios/utils/ENRMAccessibilityLabels.m +5 -5
  246. package/ios/utils/ENRMAsyncRenderCoordinator.h +24 -24
  247. package/ios/utils/ENRMAsyncRenderCoordinator.m +37 -37
  248. package/ios/utils/ENRMAtomicSize.h +65 -65
  249. package/ios/utils/ENRMCodeBlockContent.h +37 -37
  250. package/ios/utils/ENRMCodeBlockContent.mm +89 -89
  251. package/ios/utils/ENRMFeatureFlags.h +25 -25
  252. package/ios/utils/ENRMImageDownloader.h +30 -30
  253. package/ios/utils/ENRMImageDownloader.m +168 -168
  254. package/ios/utils/ENRMLatexErrorCoordinator.h +27 -27
  255. package/ios/utils/ENRMLatexErrorCoordinator.mm +75 -75
  256. package/ios/utils/ENRMLatexErrorReporting.h +13 -13
  257. package/ios/utils/ENRMLinkContextMenus.h +93 -93
  258. package/ios/utils/ENRMLinkContextMenus.m +178 -178
  259. package/ios/utils/ENRMLinkRegexConfig.h +30 -30
  260. package/ios/utils/ENRMLinkRegexConfig.mm +104 -104
  261. package/ios/utils/ENRMLinkRegexProps.h +23 -23
  262. package/ios/utils/ENRMLocalImageLoader.h +35 -35
  263. package/ios/utils/ENRMLocalImageLoader.m +111 -111
  264. package/ios/utils/ENRMMenuAction.h +27 -27
  265. package/ios/utils/ENRMMenuAction.m +33 -33
  266. package/ios/utils/ENRMSpoilerOverlayManager.h +15 -15
  267. package/ios/utils/ENRMSpoilerOverlayManager.m +19 -19
  268. package/ios/utils/ENRMSpoilerTapUtils.h +6 -6
  269. package/ios/utils/ENRMSpoilerTapUtils.m +11 -11
  270. package/ios/utils/ENRMTailFadeInAnimator.h +16 -16
  271. package/ios/utils/ENRMTailFadeInAnimator.m +161 -161
  272. package/ios/utils/ENRMTextHitTest.h +23 -23
  273. package/ios/utils/ENRMTextHitTest.m +20 -20
  274. package/ios/utils/ENRMTextInteractionUtils.h +20 -20
  275. package/ios/utils/ENRMTextInteractionUtils.m +15 -15
  276. package/ios/utils/ENRMTextRenderer.h +38 -38
  277. package/ios/utils/ENRMTextRenderer.m +54 -54
  278. package/ios/utils/ENRMTextViewSetup.h +132 -132
  279. package/ios/utils/ENRMUIKit.h +429 -429
  280. package/ios/utils/EditMenuUtils.h +105 -105
  281. package/ios/utils/EditMenuUtils.m +143 -143
  282. package/ios/utils/FontScaleObserver.h +10 -10
  283. package/ios/utils/FontScaleObserver.m +55 -55
  284. package/ios/utils/FontUtils.h +31 -31
  285. package/ios/utils/FontUtils.m +63 -63
  286. package/ios/utils/HTMLGenerator.h +25 -25
  287. package/ios/utils/HTMLGenerator.m +1041 -1041
  288. package/ios/utils/HeightUpdateUtils.h +25 -25
  289. package/ios/utils/ImageRequestHeaderUtils.h +35 -35
  290. package/ios/utils/LastElementUtils.h +97 -97
  291. package/ios/utils/LinkContextMenuUtils.h +55 -55
  292. package/ios/utils/LinkPillContentUtils.h +46 -46
  293. package/ios/utils/ListMarkerDrawer.h +15 -15
  294. package/ios/utils/ListMarkerDrawer.m +239 -239
  295. package/ios/utils/MentionBackground.h +26 -26
  296. package/ios/utils/MentionBackground.m +86 -86
  297. package/ios/utils/ParagraphStyleUtils.h +87 -87
  298. package/ios/utils/ParagraphStyleUtils.m +484 -484
  299. package/ios/utils/PasteboardUtils.h +48 -48
  300. package/ios/utils/PasteboardUtils.m +166 -166
  301. package/ios/utils/RTFExportUtils.h +24 -24
  302. package/ios/utils/RTFExportUtils.m +299 -299
  303. package/ios/utils/SelectionColorUtils.h +14 -14
  304. package/ios/utils/StylePropsUtils.h +1340 -1340
  305. package/ios/utils/TaskListTapUtils.h +6 -6
  306. package/ios/utils/TaskListTapUtils.m +14 -14
  307. package/ios/utils/TextViewLayoutManager.h +14 -14
  308. package/ios/utils/TiptapAccessibilityElementBuilder.h +43 -43
  309. package/ios/utils/TiptapAccessibilityElementBuilder.m +432 -432
  310. package/ios/utils/TiptapExtractor.h +17 -17
  311. package/ios/utils/TiptapExtractor.m +367 -367
  312. package/ios/views/ENRMTiptapTextView.h +25 -25
  313. package/ios/views/ENRMTiptapTextView.m +247 -247
  314. package/package.json +65 -70
  315. package/react-native.config.js +10 -10
  316. package/src/admonitionDefaults.ts +58 -58
  317. package/src/darkModeTextStyle.ts +99 -99
  318. package/src/headingDefaults.ts +21 -21
  319. package/src/index.tsx +4 -4
  320. package/src/linkVariantUtils.ts +120 -120
  321. package/src/normalizeTiptapStyle.ts +397 -397
  322. package/src/rn-globals.d.ts +1 -1
  323. package/src/styleUtils.ts +107 -107
  324. package/src/types/TiptapStyle.ts +532 -532
  325. package/src/types/TiptapStyleInternal.ts +299 -299
  326. package/src/types/linkPill.ts +9 -9
  327. package/src/utils/isDev.ts +4 -4
@@ -1,27 +1,27 @@
1
- package com.renderrichtext.spans
2
-
3
- import android.text.TextPaint
4
- import android.text.style.MetricAffectingSpan
5
- import kotlin.math.roundToInt
6
-
7
- class BaselineShiftSpan(
8
- private val fontScale: Float,
9
- private val baselineOffsetScale: Float,
10
- val spanType: SpanType,
11
- ) : MetricAffectingSpan() {
12
- enum class SpanType { SUPERSCRIPT, SUBSCRIPT }
13
-
14
- override fun updateDrawState(tp: TextPaint) {
15
- applyShift(tp)
16
- }
17
-
18
- override fun updateMeasureState(tp: TextPaint) {
19
- applyShift(tp)
20
- }
21
-
22
- private fun applyShift(tp: TextPaint) {
23
- val originalTextSize = tp.textSize
24
- tp.textSize = originalTextSize * fontScale
25
- tp.baselineShift -= (originalTextSize * baselineOffsetScale).roundToInt()
26
- }
27
- }
1
+ package com.renderrichtext.spans
2
+
3
+ import android.text.TextPaint
4
+ import android.text.style.MetricAffectingSpan
5
+ import kotlin.math.roundToInt
6
+
7
+ class BaselineShiftSpan(
8
+ private val fontScale: Float,
9
+ private val baselineOffsetScale: Float,
10
+ val spanType: SpanType,
11
+ ) : MetricAffectingSpan() {
12
+ enum class SpanType { SUPERSCRIPT, SUBSCRIPT }
13
+
14
+ override fun updateDrawState(tp: TextPaint) {
15
+ applyShift(tp)
16
+ }
17
+
18
+ override fun updateMeasureState(tp: TextPaint) {
19
+ applyShift(tp)
20
+ }
21
+
22
+ private fun applyShift(tp: TextPaint) {
23
+ val originalTextSize = tp.textSize
24
+ tp.textSize = originalTextSize * fontScale
25
+ tp.baselineShift -= (originalTextSize * baselineOffsetScale).roundToInt()
26
+ }
27
+ }
@@ -1,302 +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
- }
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
+ }