@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,76 @@
1
+ package com.renderrichtext.spans
2
+
3
+ import android.graphics.Paint
4
+ import android.text.style.LineHeightSpan
5
+
6
+ /**
7
+ * Adds bottom margin to a block element (paragraphs/headings) using LineHeightSpan.
8
+ *
9
+ * For spacer lines (single newline), sets the line height to exactly marginBottom.
10
+ * For regular lines, adds marginBottom only at paragraph boundaries to preserve lineHeight.
11
+ *
12
+ * @param marginBottom The margin in pixels to add below the block (0 = no margin)
13
+ */
14
+ class MarginBottomSpan(
15
+ val marginBottom: Float,
16
+ ) : LineHeightSpan {
17
+ override fun chooseHeight(
18
+ text: CharSequence,
19
+ start: Int,
20
+ end: Int,
21
+ spanstartv: Int,
22
+ lineHeight: Int,
23
+ fm: Paint.FontMetricsInt,
24
+ ) {
25
+ // Only process lines that end with a newline
26
+ if (end <= start || text[end - 1] != '\n') {
27
+ return
28
+ }
29
+
30
+ val marginPixels = marginBottom.toInt()
31
+
32
+ // Handle spacer lines (single newline character)
33
+ if (end - start == 1 && text[start] == '\n') {
34
+ if (hasContentAfter(text, end)) {
35
+ // Set line height to exactly marginBottom for spacer lines
36
+ fm.top = 0
37
+ fm.ascent = 0
38
+ fm.descent = marginPixels
39
+ fm.bottom = marginPixels
40
+ } else {
41
+ // No content after - collapse the spacer line to zero height
42
+ fm.top = 0
43
+ fm.ascent = 0
44
+ fm.descent = 0
45
+ fm.bottom = 0
46
+ }
47
+ return
48
+ }
49
+
50
+ // For regular lines, add spacing only if there's content after
51
+ if (hasContentAfter(text, end)) {
52
+ fm.descent += marginPixels
53
+ fm.bottom += marginPixels
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Checks if there's non-newline content after the given position.
59
+ * Used to determine if spacing should be applied (between items) or skipped (after last item).
60
+ */
61
+ private fun hasContentAfter(
62
+ text: CharSequence,
63
+ pos: Int,
64
+ ): Boolean {
65
+ if (pos >= text.length) return false
66
+
67
+ // If the next character is a newline, check the character after that
68
+ if (text[pos] == '\n') {
69
+ val nextPos = pos + 1
70
+ if (nextPos >= text.length) return false
71
+ return text[nextPos] != '\n' // Non-newline = content exists
72
+ }
73
+
74
+ return true // Non-newline content immediately after
75
+ }
76
+ }
@@ -0,0 +1,132 @@
1
+ package com.renderrichtext.spans
2
+
3
+ import android.graphics.Canvas
4
+ import android.graphics.Color
5
+ import android.graphics.Paint
6
+ import android.graphics.RectF
7
+ import android.graphics.Typeface
8
+ import android.os.Build
9
+ import android.text.style.ReplacementSpan
10
+ import kotlin.math.ceil
11
+
12
+ /**
13
+ * One unbreakable chip for a mention. Material chips stay on a single line, so the
14
+ * whole `@name` is one replacement run: the line breaker wraps it as a unit, and the
15
+ * horizontal padding is part of that width rather than a separate gap that can be
16
+ * left behind on the previous line.
17
+ *
18
+ * Each line fragment of an iOS mention is its own rounded rect. Android does not
19
+ * split the chip, which is how inline people-chips behave in Material text.
20
+ */
21
+ class MentionChipSpan(
22
+ private val backgroundColor: Int,
23
+ private val textColor: Int,
24
+ private val paddingX: Float,
25
+ private val paddingY: Float,
26
+ ) : ReplacementSpan() {
27
+ /** True while a finger is down. The movement method sets this and re-sets the span so the new fill is recorded. */
28
+ var pressed: Boolean = false
29
+
30
+ private val fillPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.FILL }
31
+ private val rect = RectF()
32
+ private var cachedSource: Typeface? = null
33
+ private var cachedMedium: Typeface? = null
34
+
35
+ override fun getSize(
36
+ paint: Paint,
37
+ text: CharSequence,
38
+ start: Int,
39
+ end: Int,
40
+ fm: Paint.FontMetricsInt?,
41
+ ): Int {
42
+ var width = 0
43
+ paint.usingMedium {
44
+ if (fm != null) {
45
+ paint.getFontMetricsInt(fm)
46
+ val extra = ceil(paddingY).toInt()
47
+ fm.ascent -= extra
48
+ fm.top -= extra
49
+ fm.descent += extra
50
+ fm.bottom += extra
51
+ }
52
+ width = ceil(paint.measureText(text, start, end) + paddingX * 2f).toInt()
53
+ }
54
+ return width
55
+ }
56
+
57
+ override fun draw(
58
+ canvas: Canvas,
59
+ text: CharSequence,
60
+ start: Int,
61
+ end: Int,
62
+ x: Float,
63
+ top: Int,
64
+ y: Int,
65
+ bottom: Int,
66
+ paint: Paint,
67
+ ) {
68
+ paint.usingMedium {
69
+ val textWidth = paint.measureText(text, start, end)
70
+ val metrics = paint.fontMetrics
71
+ rect.set(
72
+ x,
73
+ y + metrics.ascent - paddingY,
74
+ x + textWidth + paddingX * 2f,
75
+ y + metrics.descent + paddingY,
76
+ )
77
+ val radius = 10f
78
+ var fill = backgroundColor
79
+ if (pressed) fill = darken(fill)
80
+ if (Color.alpha(fill) > 0) {
81
+ fillPaint.color = fill
82
+ canvas.drawRoundRect(rect, radius, radius, fillPaint)
83
+ }
84
+
85
+ val previousColor = paint.color
86
+ paint.color = textColor
87
+ canvas.drawText(text, start, end, x + paddingX, y.toFloat(), paint)
88
+ paint.color = previousColor
89
+ }
90
+ }
91
+
92
+ private fun darken(color: Int): Int =
93
+ Color.argb(
94
+ Color.alpha(color),
95
+ (Color.red(color) * PRESSED_DARKEN).toInt(),
96
+ (Color.green(color) * PRESSED_DARKEN).toInt(),
97
+ (Color.blue(color) * PRESSED_DARKEN).toInt(),
98
+ )
99
+
100
+ /**
101
+ * Medium is the Android weight for a name in body text. API 28 keeps the surrounding
102
+ * family. Older releases have no weight axis, so the face becomes sans-serif-medium.
103
+ */
104
+ private fun mediumTypeface(base: Typeface?): Typeface {
105
+ if (cachedMedium != null && cachedSource === base) return cachedMedium!!
106
+ val source = base ?: Typeface.SANS_SERIF
107
+ val italic = source.style and Typeface.ITALIC != 0
108
+ val created =
109
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
110
+ Typeface.create(source, 500, italic)
111
+ } else {
112
+ Typeface.create("sans-serif-medium", if (italic) Typeface.ITALIC else Typeface.NORMAL)
113
+ }
114
+ cachedSource = base
115
+ cachedMedium = created
116
+ return created
117
+ }
118
+
119
+ private inline fun Paint.usingMedium(block: () -> Unit) {
120
+ val original = typeface
121
+ typeface = mediumTypeface(original)
122
+ try {
123
+ block()
124
+ } finally {
125
+ typeface = original
126
+ }
127
+ }
128
+
129
+ companion object {
130
+ private const val PRESSED_DARKEN = 0.82f
131
+ }
132
+ }
@@ -0,0 +1,46 @@
1
+ package com.renderrichtext.spans
2
+
3
+ import android.text.TextPaint
4
+ import android.text.style.ClickableSpan
5
+ import android.view.View
6
+ import com.renderrichtext.EnrichedTiptapText
7
+
8
+ /**
9
+ * Click and long-press target for a mention. The chip span draws the glyphs, so this
10
+ * only supplies the text color and the gestures. No underline: a mention is a chip,
11
+ * not a link.
12
+ */
13
+ class MentionSpan(
14
+ val mentionId: String,
15
+ val label: String,
16
+ private val textColor: Int,
17
+ private val onMentionPress: ((String, String) -> Unit)?,
18
+ private val onMentionLongPress: ((String, String) -> Unit)?,
19
+ ) : ClickableSpan() {
20
+ /** True while a finger is down on this mention. The chip's own flag is what it draws. */
21
+ var pressed: Boolean = false
22
+
23
+ @Volatile
24
+ private var longPressTriggered = false
25
+
26
+ override fun onClick(widget: View) {
27
+ if (longPressTriggered) {
28
+ longPressTriggered = false
29
+ return
30
+ }
31
+ onMentionPress?.invoke(mentionId, label)
32
+ ?: (widget as? EnrichedTiptapText)?.emitOnMentionPress(mentionId, label)
33
+ }
34
+
35
+ fun onLongClick(widget: View): Boolean {
36
+ longPressTriggered = true
37
+ onMentionLongPress?.invoke(mentionId, label)
38
+ ?: (widget as? EnrichedTiptapText)?.emitOnMentionLongPress(mentionId, label)
39
+ return true
40
+ }
41
+
42
+ override fun updateDrawState(textPaint: TextPaint) {
43
+ textPaint.color = textColor
44
+ textPaint.isUnderlineText = false
45
+ }
46
+ }
@@ -0,0 +1,127 @@
1
+ package com.renderrichtext.spans
2
+
3
+ import android.content.Context
4
+ import android.graphics.Canvas
5
+ import android.graphics.Paint
6
+ import android.graphics.Typeface
7
+ import android.text.Layout
8
+ import android.text.TextPaint
9
+ import com.facebook.react.common.ReactConstants
10
+ import com.facebook.react.views.text.ReactTypefaceUtils.applyStyles
11
+ import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
12
+ import com.renderrichtext.renderer.BlockStyle
13
+ import com.renderrichtext.renderer.SpanStyleCache
14
+ import com.renderrichtext.styles.ListStyle
15
+ import kotlin.math.ceil
16
+
17
+ class OrderedListSpan(
18
+ private val listStyle: ListStyle,
19
+ depth: Int,
20
+ context: Context,
21
+ styleCache: SpanStyleCache,
22
+ drawsMarker: Boolean = true,
23
+ override val markerExtraWidth: Float = 0f,
24
+ ancestorMarkerOffset: Float = 0f,
25
+ parentMarkerWidth: Float? = null,
26
+ ) : BaseListSpan(
27
+ depth = depth,
28
+ context = context,
29
+ styleCache = styleCache,
30
+ blockStyle =
31
+ BlockStyle(
32
+ fontSize = listStyle.fontSize,
33
+ fontFamily = listStyle.fontFamily,
34
+ fontWeight = listStyle.fontWeight,
35
+ color = listStyle.color,
36
+ ),
37
+ marginLeft = listStyle.marginLeft,
38
+ gapWidth = listStyle.gapWidth,
39
+ drawsMarker = drawsMarker,
40
+ ancestorMarkerOffset = ancestorMarkerOffset,
41
+ parentMarkerWidth = parentMarkerWidth,
42
+ ) {
43
+ companion object {
44
+ private val sharedMarkerPaint = TextPaint().apply { isAntiAlias = true }
45
+
46
+ /** Column every bullet and numbered list reserves, wide enough for `99.`. */
47
+ fun defaultMarkerColumnWidth(
48
+ listStyle: ListStyle,
49
+ context: Context,
50
+ ): Float {
51
+ val paint = markerPaint(listStyle, markerTypeface(listStyle, context))
52
+ return listStyle.effectiveMarkerWidth(paint.measureText("99."))
53
+ }
54
+
55
+ /**
56
+ * How far the `99.` column every ordered list reserves must grow to fit each of [numbers].
57
+ * Whole pixels, so the Int leading margins and the float marker positions agree at every depth.
58
+ */
59
+ fun measureExtraWidth(
60
+ listStyle: ListStyle,
61
+ context: Context,
62
+ numbers: Iterable<Int>,
63
+ ): Float {
64
+ val paint = markerPaint(listStyle, markerTypeface(listStyle, context))
65
+ val default = paint.measureText("99.")
66
+ val widest = numbers.fold(default) { width, number -> maxOf(width, paint.measureText("$number.")) }
67
+ return ceil(listStyle.effectiveMarkerWidth(widest) - listStyle.effectiveMarkerWidth(default))
68
+ }
69
+
70
+ private fun markerTypeface(
71
+ listStyle: ListStyle,
72
+ context: Context,
73
+ ): Typeface =
74
+ applyStyles(
75
+ null,
76
+ ReactConstants.UNSET,
77
+ parseFontWeight(listStyle.markerFontWeight),
78
+ listStyle.fontFamily.takeIf { it.isNotEmpty() },
79
+ context.assets,
80
+ )
81
+
82
+ private fun markerPaint(
83
+ listStyle: ListStyle,
84
+ typeface: Typeface,
85
+ ): TextPaint =
86
+ sharedMarkerPaint.apply {
87
+ textSize = listStyle.fontSize
88
+ color = listStyle.markerColor
89
+ this.typeface = typeface
90
+ }
91
+ }
92
+
93
+ private val markerTypeface = markerTypeface(listStyle, context)
94
+ private val defaultMarkerWidth = defaultMarkerColumnWidth(listStyle, context)
95
+
96
+ override fun getMarkerWidth(): Float = defaultMarkerWidth + markerExtraWidth
97
+
98
+ override val baselineMarkerWidth: Float get() = defaultMarkerWidth
99
+
100
+ var itemNumber: Int = 1
101
+ private set
102
+
103
+ override fun drawMarker(
104
+ canvas: Canvas,
105
+ paint: Paint,
106
+ x: Int,
107
+ dir: Int,
108
+ top: Int,
109
+ baseline: Int,
110
+ bottom: Int,
111
+ layout: Layout?,
112
+ start: Int,
113
+ ) {
114
+ val markerPaint = markerPaint(listStyle, markerTypeface)
115
+ val text = if (dir < 0) ".$itemNumber" else "$itemNumber."
116
+ val textWidth = markerPaint.measureText(text)
117
+
118
+ val markerRightEdge = x + (depth * marginLeft + ancestorMarkerOffset + getMarkerWidth()) * dir
119
+ val markerX = if (dir > 0) markerRightEdge - textWidth else markerRightEdge
120
+
121
+ canvas.drawText(text, markerX, baseline.toFloat(), markerPaint)
122
+ }
123
+
124
+ fun setItemNumber(number: Int) {
125
+ itemNumber = number
126
+ }
127
+ }
@@ -0,0 +1,33 @@
1
+ package com.renderrichtext.spans
2
+
3
+ import android.text.TextPaint
4
+ import android.text.style.MetricAffectingSpan
5
+ import com.renderrichtext.renderer.BlockStyle
6
+ import com.renderrichtext.renderer.SpanStyleCache
7
+
8
+ class SpoilerSpan(
9
+ val styleCache: SpanStyleCache,
10
+ val blockStyle: BlockStyle,
11
+ ) : MetricAffectingSpan() {
12
+ var revealed = false
13
+ private set
14
+ var revealing = false
15
+ private set
16
+
17
+ fun markRevealing() {
18
+ revealing = true
19
+ }
20
+
21
+ fun markRevealed() {
22
+ revealed = true
23
+ revealing = false
24
+ }
25
+
26
+ override fun updateDrawState(tp: TextPaint) {
27
+ tp.textSize = blockStyle.fontSize
28
+ }
29
+
30
+ override fun updateMeasureState(tp: TextPaint) {
31
+ tp.textSize = blockStyle.fontSize
32
+ }
33
+ }
@@ -0,0 +1,12 @@
1
+ package com.renderrichtext.spans
2
+
3
+ import android.text.TextPaint
4
+ import android.text.style.CharacterStyle
5
+
6
+ class StrikethroughSpan(
7
+ private val strikethroughColor: Int,
8
+ ) : CharacterStyle() {
9
+ override fun updateDrawState(tp: TextPaint) {
10
+ tp.isStrikeThruText = true
11
+ }
12
+ }
@@ -0,0 +1,39 @@
1
+ package com.renderrichtext.spans
2
+
3
+ import android.graphics.Typeface
4
+ import android.text.TextPaint
5
+ import android.text.style.MetricAffectingSpan
6
+ import com.renderrichtext.renderer.BlockStyle
7
+ import com.renderrichtext.renderer.SpanStyleCache
8
+ import com.renderrichtext.utils.text.extensions.applyColorPreserving
9
+
10
+ class StrongSpan(
11
+ private val styleCache: SpanStyleCache,
12
+ private val blockStyle: BlockStyle,
13
+ ) : MetricAffectingSpan() {
14
+ private val strongColor = styleCache.getStrongColorFor(blockStyle.color)
15
+
16
+ override fun updateDrawState(tp: TextPaint) {
17
+ applyStrongStyle(tp)
18
+ tp.applyColorPreserving(strongColor, *styleCache.colorsToPreserve)
19
+ }
20
+
21
+ override fun updateMeasureState(tp: TextPaint) {
22
+ applyStrongStyle(tp)
23
+ }
24
+
25
+ private fun applyStrongStyle(tp: TextPaint) {
26
+ tp.textSize = blockStyle.fontSize
27
+
28
+ val currentTypeface = tp.typeface ?: Typeface.DEFAULT
29
+ val isItalic = (currentTypeface.style) and Typeface.ITALIC != 0
30
+ val style = if (isItalic) Typeface.BOLD_ITALIC else Typeface.BOLD
31
+ tp.typeface =
32
+ if (styleCache.strongFontFamily.isNotEmpty()) {
33
+ val resolvedStyle = if (styleCache.strongFontWeight == "normal") Typeface.NORMAL else style
34
+ styleCache.getTypeface(styleCache.strongFontFamily, resolvedStyle)
35
+ } else {
36
+ Typeface.create(currentTypeface, style)
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,143 @@
1
+ package com.renderrichtext.spans
2
+
3
+ import android.content.Context
4
+ import android.graphics.Canvas
5
+ import android.graphics.Paint
6
+ import android.graphics.Path
7
+ import android.graphics.RectF
8
+ import android.text.Layout
9
+ import com.renderrichtext.renderer.BlockStyle
10
+ import com.renderrichtext.renderer.SpanStyleCache
11
+ import com.renderrichtext.styles.ListStyle
12
+ import com.renderrichtext.styles.TaskListStyle
13
+
14
+ class TaskListSpan(
15
+ private val taskStyle: TaskListStyle,
16
+ private val listStyle: ListStyle,
17
+ depth: Int,
18
+ context: Context,
19
+ styleCache: SpanStyleCache,
20
+ val taskIndex: Int,
21
+ val isChecked: Boolean,
22
+ drawsMarker: Boolean = true,
23
+ ancestorMarkerOffset: Float = 0f,
24
+ override val markerExtraWidth: Float = 0f,
25
+ parentMarkerWidth: Float? = null,
26
+ ) : BaseListSpan(
27
+ depth = depth,
28
+ context = context,
29
+ styleCache = styleCache,
30
+ blockStyle =
31
+ BlockStyle(
32
+ fontSize = listStyle.fontSize,
33
+ fontFamily = listStyle.fontFamily,
34
+ fontWeight = listStyle.fontWeight,
35
+ color = listStyle.color,
36
+ ),
37
+ marginLeft = listStyle.marginLeft,
38
+ gapWidth = listStyle.gapWidth,
39
+ drawsMarker = drawsMarker,
40
+ ancestorMarkerOffset = ancestorMarkerOffset,
41
+ parentMarkerWidth = parentMarkerWidth,
42
+ ) {
43
+ private val checkboxSize = taskStyle.checkboxSize
44
+ private val checkboxColumnWidth = listStyle.effectiveMarkerWidth(checkboxSize)
45
+ private val markerColumnWidth = checkboxColumnWidth + markerExtraWidth
46
+ private val cornerRadius = taskStyle.checkboxBorderRadius
47
+ private val rect = RectF()
48
+ private val checkPath = Path()
49
+
50
+ companion object {
51
+ private const val CAP_HEIGHT_RATIO = 0.72f
52
+ private const val HALF_DIVISOR = 2f
53
+ private const val CHECKMARK_MIN_STROKE_WIDTH = 1.5f
54
+ private const val CHECKMARK_STROKE_RATIO = 0.12f
55
+ private const val CHECKMARK_INSET_RATIO = 0.22f
56
+ private const val CHECKMARK_MID_OFFSET_RATIO = 0.05f
57
+ private const val BORDER_MIN_STROKE_WIDTH = 1f
58
+ private const val BORDER_STROKE_RATIO = 0.09f
59
+ }
60
+
61
+ private val boxPaint =
62
+ Paint(Paint.ANTI_ALIAS_FLAG).apply {
63
+ strokeCap = Paint.Cap.ROUND
64
+ strokeJoin = Paint.Join.ROUND
65
+ }
66
+
67
+ override fun getMarkerWidth(): Float = markerColumnWidth
68
+
69
+ override val baselineMarkerWidth: Float get() = checkboxColumnWidth
70
+
71
+ override fun drawMarker(
72
+ canvas: Canvas,
73
+ paint: Paint,
74
+ x: Int,
75
+ dir: Int,
76
+ top: Int,
77
+ baseline: Int,
78
+ bottom: Int,
79
+ layout: Layout?,
80
+ start: Int,
81
+ ) {
82
+ val capHeight = -markerFontMetrics.ascent * CAP_HEIGHT_RATIO
83
+ val centerY = baseline - capHeight / HALF_DIVISOR
84
+ // Right-align the checkbox inside the reserved marker column so it hugs
85
+ // the gap before the text. At the default (markerColumnWidth ==
86
+ // checkboxSize) this is identical to the previous flush-left layout.
87
+ val centerX = x + (depth * marginLeft + ancestorMarkerOffset + markerColumnWidth - checkboxSize / HALF_DIVISOR) * dir
88
+ val half = checkboxSize / HALF_DIVISOR
89
+ rect.set(centerX - half, centerY - half, centerX + half, centerY + half)
90
+
91
+ if (isChecked) {
92
+ drawChecked(canvas, centerY)
93
+ } else {
94
+ drawUnchecked(canvas)
95
+ }
96
+ }
97
+
98
+ private fun drawChecked(
99
+ canvas: Canvas,
100
+ centerY: Float,
101
+ ) {
102
+ boxPaint.apply {
103
+ style = Paint.Style.FILL
104
+ color = taskStyle.checkedColor
105
+ }
106
+ canvas.drawRoundRect(rect, cornerRadius, cornerRadius, boxPaint)
107
+
108
+ boxPaint.apply {
109
+ style = Paint.Style.STROKE
110
+ color = taskStyle.checkmarkColor
111
+ strokeWidth = maxOf(CHECKMARK_MIN_STROKE_WIDTH, checkboxSize * CHECKMARK_STROKE_RATIO)
112
+ }
113
+
114
+ val inset = checkboxSize * CHECKMARK_INSET_RATIO
115
+ val midOffset = checkboxSize * CHECKMARK_MID_OFFSET_RATIO
116
+
117
+ checkPath.run {
118
+ reset()
119
+ moveTo(rect.left + inset, centerY)
120
+ lineTo(rect.centerX() - midOffset, rect.bottom - inset)
121
+ lineTo(rect.right - inset, rect.top + inset)
122
+ }
123
+ canvas.drawPath(checkPath, boxPaint)
124
+ }
125
+
126
+ private fun drawUnchecked(canvas: Canvas) {
127
+ boxPaint.apply {
128
+ style = Paint.Style.STROKE
129
+ color = taskStyle.borderColor
130
+ strokeWidth = maxOf(BORDER_MIN_STROKE_WIDTH, checkboxSize * BORDER_STROKE_RATIO)
131
+ }
132
+
133
+ val halfStroke = boxPaint.strokeWidth / 2f
134
+ val insetRect =
135
+ RectF(
136
+ rect.left + halfStroke,
137
+ rect.top + halfStroke,
138
+ rect.right - halfStroke,
139
+ rect.bottom - halfStroke,
140
+ )
141
+ canvas.drawRoundRect(insetRect, cornerRadius, cornerRadius, boxPaint)
142
+ }
143
+ }
@@ -0,0 +1,26 @@
1
+ package com.renderrichtext.spans
2
+
3
+ import android.content.Context
4
+ import android.text.TextPaint
5
+ import android.text.style.MetricAffectingSpan
6
+ import com.renderrichtext.renderer.BlockStyle
7
+ import com.renderrichtext.utils.text.extensions.applyBlockStyleFont
8
+
9
+ class TextSpan(
10
+ private val blockStyle: BlockStyle,
11
+ private val context: Context,
12
+ ) : MetricAffectingSpan() {
13
+ override fun updateDrawState(tp: TextPaint) {
14
+ applyBlockStyle(tp)
15
+ }
16
+
17
+ override fun updateMeasureState(tp: TextPaint) {
18
+ applyBlockStyle(tp)
19
+ }
20
+
21
+ private fun applyBlockStyle(tp: TextPaint) {
22
+ tp.textSize = blockStyle.fontSize
23
+ tp.color = blockStyle.color
24
+ tp.applyBlockStyleFont(blockStyle, context)
25
+ }
26
+ }