@mathers101/react-native-render-rich-text 0.1.10 → 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,25 +1,25 @@
1
- #pragma once
2
- #import "ENRMUIKit.h"
3
-
4
- #import "ENRMLinkContextMenus.h"
5
-
6
- #if !TARGET_OS_OSX
7
- NS_ASSUME_NONNULL_BEGIN
8
-
9
- /**
10
- * The read-only text view tiptap renders into. A link pill is one placeholder character
11
- * in text storage; what the system reads for the selection (Look Up, Translate, Share,
12
- * drag, the Copy key command) is answered here with the link text the pill stands for.
13
- *
14
- * It also presents the menu of a pill that has one, taken from a delegate that is an
15
- * `ENRMLinkContextMenuSource`: UIKit lifts a pressed text item on a tinted box of its own,
16
- * which hides the pill's look.
17
- */
18
- @interface ENRMTiptapTextView : UITextView <ENRMLinkMenuPresenting>
19
- /// Copies a selection the way the menu Copy does. Set by the hosting view, which knows the
20
- /// source Tiptap and style; without it the Copy key command writes plain text and RTF only.
21
- @property (nonatomic, copy, nullable) void (^copySelectionHandler)(NSRange selectedRange);
22
- @end
23
-
24
- NS_ASSUME_NONNULL_END
25
- #endif
1
+ #pragma once
2
+ #import "ENRMUIKit.h"
3
+
4
+ #import "ENRMLinkContextMenus.h"
5
+
6
+ #if !TARGET_OS_OSX
7
+ NS_ASSUME_NONNULL_BEGIN
8
+
9
+ /**
10
+ * The read-only text view tiptap renders into. A link pill is one placeholder character
11
+ * in text storage; what the system reads for the selection (Look Up, Translate, Share,
12
+ * drag, the Copy key command) is answered here with the link text the pill stands for.
13
+ *
14
+ * It also presents the menu of a pill that has one, taken from a delegate that is an
15
+ * `ENRMLinkContextMenuSource`: UIKit lifts a pressed text item on a tinted box of its own,
16
+ * which hides the pill's look.
17
+ */
18
+ @interface ENRMTiptapTextView : UITextView <ENRMLinkMenuPresenting>
19
+ /// Copies a selection the way the menu Copy does. Set by the hosting view, which knows the
20
+ /// source Tiptap and style; without it the Copy key command writes plain text and RTF only.
21
+ @property (nonatomic, copy, nullable) void (^copySelectionHandler)(NSRange selectedRange);
22
+ @end
23
+
24
+ NS_ASSUME_NONNULL_END
25
+ #endif
@@ -1,247 +1,247 @@
1
- #import "ENRMTiptapTextView.h"
2
- #import "ENRMLinkPillAttachment.h"
3
- #import "ENRMLinkPillText.h"
4
- #import "ENRMTextHitTest.h"
5
- #import "LinkTapUtils.h"
6
- #import "PasteboardUtils.h"
7
-
8
- #if !TARGET_OS_OSX
9
- @interface ENRMTiptapTextView () <UIContextMenuInteractionDelegate>
10
- @end
11
-
12
- @implementation ENRMTiptapTextView {
13
- ENRMLinkMenuLift *_pillLift;
14
- // The pill whose menu is being presented. It draws nothing for as long as its lifted image
15
- // stands in for it: it would show through that image.
16
- ENRMLinkPillAttachment *_liftedPill;
17
- NSUInteger _pillMenuIndex;
18
- }
19
-
20
- - (instancetype)initWithFrame:(CGRect)frame textContainer:(NSTextContainer *)textContainer
21
- {
22
- if (self = [super initWithFrame:frame textContainer:textContainer]) {
23
- _pillLift = [[ENRMLinkMenuLift alloc] init];
24
- __weak ENRMTiptapTextView *weakSelf = self;
25
- _pillLift.onEnd = ^{ [weakSelf restoreLiftedPill]; };
26
- [self addInteraction:[[UIContextMenuInteraction alloc] initWithDelegate:self]];
27
- }
28
- return self;
29
- }
30
-
31
- /// A tap places the caret, and UITextView then scrolls that caret into view. This view is
32
- /// already sized to its text and sits in the screen's scroll view, so that scroll shifts
33
- /// the page and the tapped line jumps toward the top. Scrolling stays off, and these
34
- /// requests are dropped. Copy and selection are unchanged.
35
- - (void)setContentOffset:(CGPoint)contentOffset
36
- {
37
- if (!self.scrollEnabled && !CGPointEqualToPoint(contentOffset, CGPointZero)) {
38
- if (!CGPointEqualToPoint(self.contentOffset, CGPointZero)) {
39
- [super setContentOffset:CGPointZero];
40
- }
41
- return;
42
- }
43
- [super setContentOffset:contentOffset];
44
- }
45
-
46
- - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
47
- {
48
- if (!self.scrollEnabled) {
49
- [self setContentOffset:CGPointZero];
50
- return;
51
- }
52
- [super setContentOffset:contentOffset animated:animated];
53
- }
54
-
55
- - (void)scrollRangeToVisible:(NSRange)range
56
- {
57
- if (self.scrollEnabled)
58
- [super scrollRangeToVisible:range];
59
- }
60
-
61
- - (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated
62
- {
63
- if (self.scrollEnabled)
64
- [super scrollRectToVisible:rect animated:animated];
65
- }
66
-
67
- /// New text moves or replaces the pill under its lifted image.
68
- - (void)setAttributedText:(NSAttributedString *)attributedText
69
- {
70
- [_pillLift end];
71
- [super setAttributedText:attributedText];
72
- }
73
-
74
- /// The selection with pills expanded, or nil when `range` is not the selection or holds no pill.
75
- /// Only the selection is rewritten: UIKit also reads arbitrary ranges to find word boundaries,
76
- /// and those must keep matching storage offsets.
77
- - (nullable NSAttributedString *)expandedSelectionForRange:(UITextRange *)range
78
- {
79
- UITextRange *selection = self.selectedTextRange;
80
- if (!range || !selection || selection.isEmpty || ![range isEqual:selection])
81
- return nil;
82
- NSRange selected = self.selectedRange;
83
- NSTextStorage *storage = self.textStorage;
84
- if (selected.location == NSNotFound || NSMaxRange(selected) > storage.length)
85
- return nil;
86
- NSAttributedString *text = [storage attributedSubstringFromRange:selected];
87
- NSAttributedString *expanded = ENRMAttributedStringByExpandingLinkPills(text, NULL);
88
- return expanded == text ? nil : expanded;
89
- }
90
-
91
- - (NSString *)textInRange:(UITextRange *)range
92
- {
93
- return [self expandedSelectionForRange:range].string ?: [super textInRange:range];
94
- }
95
-
96
- - (NSAttributedString *)attributedTextInRange:(UITextRange *)range
97
- {
98
- return [self expandedSelectionForRange:range] ?: [super attributedTextInRange:range];
99
- }
100
-
101
- /// The menu's Copy is already replaced by the library's own action; this covers the key command.
102
- - (void)copy:(id)sender
103
- {
104
- NSRange selected = self.selectedRange;
105
- if (self.copySelectionHandler && selected.location != NSNotFound && selected.length > 0) {
106
- self.copySelectionHandler(selected);
107
- return;
108
- }
109
- NSAttributedString *expanded = [self expandedSelectionForRange:self.selectedTextRange];
110
- if (!expanded) {
111
- [super copy:sender];
112
- return;
113
- }
114
- copyAttributedStringToPasteboard(expanded, nil, nil);
115
- }
116
-
117
- #pragma mark - Pill menus
118
-
119
- - (nullable ENRMLinkContextMenus *)linkContextMenus
120
- {
121
- id delegate = self.delegate;
122
- return [delegate conformsToProtocol:@protocol(ENRMLinkContextMenuSource)]
123
- ? [(id<ENRMLinkContextMenuSource>)delegate linkContextMenusForTextView:self]
124
- : nil;
125
- }
126
-
127
- /// Where the pill at `index` is drawn, in the text view's coordinates.
128
- - (CGRect)pillFrameAtIndex:(NSUInteger)index
129
- {
130
- NSLayoutManager *layoutManager = self.layoutManager;
131
- NSUInteger glyph = [layoutManager glyphIndexForCharacterAtIndex:index];
132
- CGSize size = [layoutManager attachmentSizeForGlyphAtIndex:glyph];
133
- if (size.width <= 0 || size.height <= 0)
134
- return CGRectNull;
135
- CGRect line = [layoutManager lineFragmentRectForGlyphAtIndex:glyph effectiveRange:NULL];
136
- // TextKit places an attachment glyph at the bottom edge of its bounds.
137
- CGPoint location = [layoutManager locationForGlyphAtIndex:glyph];
138
- UIEdgeInsets inset = self.textContainerInset;
139
- return CGRectMake(inset.left + line.origin.x + location.x, inset.top + line.origin.y + location.y - size.height,
140
- size.width, size.height);
141
- }
142
-
143
- /// Whether the character at `index` is a pill whose link has a menu.
144
- - (BOOL)presentsLinkMenuAtIndex:(NSUInteger)index
145
- {
146
- ENRMLinkContextMenus *menus = [self linkContextMenus];
147
- NSTextStorage *storage = self.textStorage;
148
- if (menus.entries.count == 0 || index >= storage.length)
149
- return NO;
150
- id attachment = [storage attribute:NSAttachmentAttributeName atIndex:index effectiveRange:NULL];
151
- return [attachment isKindOfClass:ENRMLinkPillAttachment.class] &&
152
- [menus hasMenuForURL:linkURLAtRange(self, NSMakeRange(index, 1))];
153
- }
154
-
155
- /// The character index of the pill under `point` when its link has a menu, else NSNotFound.
156
- - (NSUInteger)menuPillIndexAtPoint:(CGPoint)point
157
- {
158
- if ([self linkContextMenus].entries.count == 0)
159
- return NSNotFound;
160
- NSUInteger index = ENRMCharacterIndexAtPoint(self, point);
161
- if (index == NSNotFound || ![self presentsLinkMenuAtIndex:index] ||
162
- !CGRectContainsPoint([self pillFrameAtIndex:index], point))
163
- return NSNotFound;
164
- return index;
165
- }
166
-
167
- - (void)setPill:(ENRMLinkPillAttachment *)pill lifted:(BOOL)lifted
168
- {
169
- pill.lifted = lifted;
170
- NSTextStorage *storage = self.textStorage;
171
- [storage enumerateAttribute:NSAttachmentAttributeName
172
- inRange:NSMakeRange(0, storage.length)
173
- options:0
174
- usingBlock:^(id value, NSRange range, BOOL *stop) {
175
- if (value != pill)
176
- return;
177
- [self.layoutManager invalidateDisplayForCharacterRange:range];
178
- *stop = YES;
179
- }];
180
- }
181
-
182
- - (void)restoreLiftedPill
183
- {
184
- if (_liftedPill)
185
- [self setPill:_liftedPill lifted:NO];
186
- _liftedPill = nil;
187
- }
188
-
189
- - (UIContextMenuConfiguration *)contextMenuInteraction:(UIContextMenuInteraction *)interaction
190
- configurationForMenuAtLocation:(CGPoint)location
191
- {
192
- [_pillLift end];
193
- _pillMenuIndex = [self menuPillIndexAtPoint:location];
194
- if (_pillMenuIndex == NSNotFound)
195
- return nil;
196
- UIMenu *menu = [[self linkContextMenus] menuForURL:linkURLAtRange(self, NSMakeRange(_pillMenuIndex, 1))
197
- title:linkTitleAtIndex(self.textStorage, _pillMenuIndex)];
198
- if (!menu)
199
- return nil;
200
- return [UIContextMenuConfiguration
201
- configurationWithIdentifier:nil
202
- previewProvider:nil
203
- actionProvider:^UIMenu *(NSArray<UIMenuElement *> *suggestedActions) { return menu; }];
204
- }
205
-
206
- /// The pill is lifted as an image of itself, see `ENRMLinkMenuLift`.
207
- - (UITargetedPreview *)pillMenuPreview
208
- {
209
- if (![_pillLift isOverView:self]) {
210
- NSTextStorage *storage = self.textStorage;
211
- if (self.window == nil || _pillMenuIndex >= storage.length)
212
- return nil;
213
- id attachment = [storage attribute:NSAttachmentAttributeName atIndex:_pillMenuIndex effectiveRange:NULL];
214
- CGRect frame = [self pillFrameAtIndex:_pillMenuIndex];
215
- if (![attachment isKindOfClass:ENRMLinkPillAttachment.class] || CGRectIsNull(frame))
216
- return nil;
217
- UIImage *image = [(ENRMLinkPillAttachment *)attachment imageForBounds:(CGRect){CGPointZero, frame.size}
218
- textContainer:self.textContainer
219
- characterIndex:_pillMenuIndex];
220
- [_pillLift layImage:image atFrame:frame overView:self];
221
- _liftedPill = attachment;
222
- [self setPill:_liftedPill lifted:YES];
223
- }
224
- return [_pillLift previewWithCornerRadius:_liftedPill.cornerRadius backgroundColor:UIColor.clearColor];
225
- }
226
-
227
- - (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction
228
- previewForHighlightingMenuWithConfiguration:(UIContextMenuConfiguration *)configuration
229
- {
230
- return [self pillMenuPreview];
231
- }
232
-
233
- - (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction
234
- previewForDismissingMenuWithConfiguration:(UIContextMenuConfiguration *)configuration
235
- {
236
- return [self pillMenuPreview];
237
- }
238
-
239
- - (void)contextMenuInteraction:(UIContextMenuInteraction *)interaction
240
- willEndForConfiguration:(UIContextMenuConfiguration *)configuration
241
- animator:(id<UIContextMenuInteractionAnimating>)animator
242
- {
243
- [_pillLift endWithAnimator:animator];
244
- }
245
-
246
- @end
247
- #endif
1
+ #import "ENRMTiptapTextView.h"
2
+ #import "ENRMLinkPillAttachment.h"
3
+ #import "ENRMLinkPillText.h"
4
+ #import "ENRMTextHitTest.h"
5
+ #import "LinkTapUtils.h"
6
+ #import "PasteboardUtils.h"
7
+
8
+ #if !TARGET_OS_OSX
9
+ @interface ENRMTiptapTextView () <UIContextMenuInteractionDelegate>
10
+ @end
11
+
12
+ @implementation ENRMTiptapTextView {
13
+ ENRMLinkMenuLift *_pillLift;
14
+ // The pill whose menu is being presented. It draws nothing for as long as its lifted image
15
+ // stands in for it: it would show through that image.
16
+ ENRMLinkPillAttachment *_liftedPill;
17
+ NSUInteger _pillMenuIndex;
18
+ }
19
+
20
+ - (instancetype)initWithFrame:(CGRect)frame textContainer:(NSTextContainer *)textContainer
21
+ {
22
+ if (self = [super initWithFrame:frame textContainer:textContainer]) {
23
+ _pillLift = [[ENRMLinkMenuLift alloc] init];
24
+ __weak ENRMTiptapTextView *weakSelf = self;
25
+ _pillLift.onEnd = ^{ [weakSelf restoreLiftedPill]; };
26
+ [self addInteraction:[[UIContextMenuInteraction alloc] initWithDelegate:self]];
27
+ }
28
+ return self;
29
+ }
30
+
31
+ /// A tap places the caret, and UITextView then scrolls that caret into view. This view is
32
+ /// already sized to its text and sits in the screen's scroll view, so that scroll shifts
33
+ /// the page and the tapped line jumps toward the top. Scrolling stays off, and these
34
+ /// requests are dropped. Copy and selection are unchanged.
35
+ - (void)setContentOffset:(CGPoint)contentOffset
36
+ {
37
+ if (!self.scrollEnabled && !CGPointEqualToPoint(contentOffset, CGPointZero)) {
38
+ if (!CGPointEqualToPoint(self.contentOffset, CGPointZero)) {
39
+ [super setContentOffset:CGPointZero];
40
+ }
41
+ return;
42
+ }
43
+ [super setContentOffset:contentOffset];
44
+ }
45
+
46
+ - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
47
+ {
48
+ if (!self.scrollEnabled) {
49
+ [self setContentOffset:CGPointZero];
50
+ return;
51
+ }
52
+ [super setContentOffset:contentOffset animated:animated];
53
+ }
54
+
55
+ - (void)scrollRangeToVisible:(NSRange)range
56
+ {
57
+ if (self.scrollEnabled)
58
+ [super scrollRangeToVisible:range];
59
+ }
60
+
61
+ - (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated
62
+ {
63
+ if (self.scrollEnabled)
64
+ [super scrollRectToVisible:rect animated:animated];
65
+ }
66
+
67
+ /// New text moves or replaces the pill under its lifted image.
68
+ - (void)setAttributedText:(NSAttributedString *)attributedText
69
+ {
70
+ [_pillLift end];
71
+ [super setAttributedText:attributedText];
72
+ }
73
+
74
+ /// The selection with pills expanded, or nil when `range` is not the selection or holds no pill.
75
+ /// Only the selection is rewritten: UIKit also reads arbitrary ranges to find word boundaries,
76
+ /// and those must keep matching storage offsets.
77
+ - (nullable NSAttributedString *)expandedSelectionForRange:(UITextRange *)range
78
+ {
79
+ UITextRange *selection = self.selectedTextRange;
80
+ if (!range || !selection || selection.isEmpty || ![range isEqual:selection])
81
+ return nil;
82
+ NSRange selected = self.selectedRange;
83
+ NSTextStorage *storage = self.textStorage;
84
+ if (selected.location == NSNotFound || NSMaxRange(selected) > storage.length)
85
+ return nil;
86
+ NSAttributedString *text = [storage attributedSubstringFromRange:selected];
87
+ NSAttributedString *expanded = ENRMAttributedStringByExpandingLinkPills(text, NULL);
88
+ return expanded == text ? nil : expanded;
89
+ }
90
+
91
+ - (NSString *)textInRange:(UITextRange *)range
92
+ {
93
+ return [self expandedSelectionForRange:range].string ?: [super textInRange:range];
94
+ }
95
+
96
+ - (NSAttributedString *)attributedTextInRange:(UITextRange *)range
97
+ {
98
+ return [self expandedSelectionForRange:range] ?: [super attributedTextInRange:range];
99
+ }
100
+
101
+ /// The menu's Copy is already replaced by the library's own action; this covers the key command.
102
+ - (void)copy:(id)sender
103
+ {
104
+ NSRange selected = self.selectedRange;
105
+ if (self.copySelectionHandler && selected.location != NSNotFound && selected.length > 0) {
106
+ self.copySelectionHandler(selected);
107
+ return;
108
+ }
109
+ NSAttributedString *expanded = [self expandedSelectionForRange:self.selectedTextRange];
110
+ if (!expanded) {
111
+ [super copy:sender];
112
+ return;
113
+ }
114
+ copyAttributedStringToPasteboard(expanded, nil, nil);
115
+ }
116
+
117
+ #pragma mark - Pill menus
118
+
119
+ - (nullable ENRMLinkContextMenus *)linkContextMenus
120
+ {
121
+ id delegate = self.delegate;
122
+ return [delegate conformsToProtocol:@protocol(ENRMLinkContextMenuSource)]
123
+ ? [(id<ENRMLinkContextMenuSource>)delegate linkContextMenusForTextView:self]
124
+ : nil;
125
+ }
126
+
127
+ /// Where the pill at `index` is drawn, in the text view's coordinates.
128
+ - (CGRect)pillFrameAtIndex:(NSUInteger)index
129
+ {
130
+ NSLayoutManager *layoutManager = self.layoutManager;
131
+ NSUInteger glyph = [layoutManager glyphIndexForCharacterAtIndex:index];
132
+ CGSize size = [layoutManager attachmentSizeForGlyphAtIndex:glyph];
133
+ if (size.width <= 0 || size.height <= 0)
134
+ return CGRectNull;
135
+ CGRect line = [layoutManager lineFragmentRectForGlyphAtIndex:glyph effectiveRange:NULL];
136
+ // TextKit places an attachment glyph at the bottom edge of its bounds.
137
+ CGPoint location = [layoutManager locationForGlyphAtIndex:glyph];
138
+ UIEdgeInsets inset = self.textContainerInset;
139
+ return CGRectMake(inset.left + line.origin.x + location.x, inset.top + line.origin.y + location.y - size.height,
140
+ size.width, size.height);
141
+ }
142
+
143
+ /// Whether the character at `index` is a pill whose link has a menu.
144
+ - (BOOL)presentsLinkMenuAtIndex:(NSUInteger)index
145
+ {
146
+ ENRMLinkContextMenus *menus = [self linkContextMenus];
147
+ NSTextStorage *storage = self.textStorage;
148
+ if (menus.entries.count == 0 || index >= storage.length)
149
+ return NO;
150
+ id attachment = [storage attribute:NSAttachmentAttributeName atIndex:index effectiveRange:NULL];
151
+ return [attachment isKindOfClass:ENRMLinkPillAttachment.class] &&
152
+ [menus hasMenuForURL:linkURLAtRange(self, NSMakeRange(index, 1))];
153
+ }
154
+
155
+ /// The character index of the pill under `point` when its link has a menu, else NSNotFound.
156
+ - (NSUInteger)menuPillIndexAtPoint:(CGPoint)point
157
+ {
158
+ if ([self linkContextMenus].entries.count == 0)
159
+ return NSNotFound;
160
+ NSUInteger index = ENRMCharacterIndexAtPoint(self, point);
161
+ if (index == NSNotFound || ![self presentsLinkMenuAtIndex:index] ||
162
+ !CGRectContainsPoint([self pillFrameAtIndex:index], point))
163
+ return NSNotFound;
164
+ return index;
165
+ }
166
+
167
+ - (void)setPill:(ENRMLinkPillAttachment *)pill lifted:(BOOL)lifted
168
+ {
169
+ pill.lifted = lifted;
170
+ NSTextStorage *storage = self.textStorage;
171
+ [storage enumerateAttribute:NSAttachmentAttributeName
172
+ inRange:NSMakeRange(0, storage.length)
173
+ options:0
174
+ usingBlock:^(id value, NSRange range, BOOL *stop) {
175
+ if (value != pill)
176
+ return;
177
+ [self.layoutManager invalidateDisplayForCharacterRange:range];
178
+ *stop = YES;
179
+ }];
180
+ }
181
+
182
+ - (void)restoreLiftedPill
183
+ {
184
+ if (_liftedPill)
185
+ [self setPill:_liftedPill lifted:NO];
186
+ _liftedPill = nil;
187
+ }
188
+
189
+ - (UIContextMenuConfiguration *)contextMenuInteraction:(UIContextMenuInteraction *)interaction
190
+ configurationForMenuAtLocation:(CGPoint)location
191
+ {
192
+ [_pillLift end];
193
+ _pillMenuIndex = [self menuPillIndexAtPoint:location];
194
+ if (_pillMenuIndex == NSNotFound)
195
+ return nil;
196
+ UIMenu *menu = [[self linkContextMenus] menuForURL:linkURLAtRange(self, NSMakeRange(_pillMenuIndex, 1))
197
+ title:linkTitleAtIndex(self.textStorage, _pillMenuIndex)];
198
+ if (!menu)
199
+ return nil;
200
+ return [UIContextMenuConfiguration
201
+ configurationWithIdentifier:nil
202
+ previewProvider:nil
203
+ actionProvider:^UIMenu *(NSArray<UIMenuElement *> *suggestedActions) { return menu; }];
204
+ }
205
+
206
+ /// The pill is lifted as an image of itself, see `ENRMLinkMenuLift`.
207
+ - (UITargetedPreview *)pillMenuPreview
208
+ {
209
+ if (![_pillLift isOverView:self]) {
210
+ NSTextStorage *storage = self.textStorage;
211
+ if (self.window == nil || _pillMenuIndex >= storage.length)
212
+ return nil;
213
+ id attachment = [storage attribute:NSAttachmentAttributeName atIndex:_pillMenuIndex effectiveRange:NULL];
214
+ CGRect frame = [self pillFrameAtIndex:_pillMenuIndex];
215
+ if (![attachment isKindOfClass:ENRMLinkPillAttachment.class] || CGRectIsNull(frame))
216
+ return nil;
217
+ UIImage *image = [(ENRMLinkPillAttachment *)attachment imageForBounds:(CGRect){CGPointZero, frame.size}
218
+ textContainer:self.textContainer
219
+ characterIndex:_pillMenuIndex];
220
+ [_pillLift layImage:image atFrame:frame overView:self];
221
+ _liftedPill = attachment;
222
+ [self setPill:_liftedPill lifted:YES];
223
+ }
224
+ return [_pillLift previewWithCornerRadius:_liftedPill.cornerRadius backgroundColor:UIColor.clearColor];
225
+ }
226
+
227
+ - (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction
228
+ previewForHighlightingMenuWithConfiguration:(UIContextMenuConfiguration *)configuration
229
+ {
230
+ return [self pillMenuPreview];
231
+ }
232
+
233
+ - (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction
234
+ previewForDismissingMenuWithConfiguration:(UIContextMenuConfiguration *)configuration
235
+ {
236
+ return [self pillMenuPreview];
237
+ }
238
+
239
+ - (void)contextMenuInteraction:(UIContextMenuInteraction *)interaction
240
+ willEndForConfiguration:(UIContextMenuConfiguration *)configuration
241
+ animator:(id<UIContextMenuInteractionAnimating>)animator
242
+ {
243
+ [_pillLift endWithAnimator:animator];
244
+ }
245
+
246
+ @end
247
+ #endif