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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +140 -140
  3. package/ReactNativeRenderRichText.podspec +23 -23
  4. package/android/build.gradle +86 -86
  5. package/android/consumer-rules.pro +3 -3
  6. package/android/src/main/AndroidManifest.xml +2 -2
  7. package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextLayoutManager.kt +24 -24
  8. package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextPackage.kt +13 -13
  9. package/android/src/main/java/com/renderrichtext/MeasurementStore.kt +644 -644
  10. package/android/src/main/java/com/renderrichtext/accessibility/AccessibilityLabels.kt +17 -17
  11. package/android/src/main/java/com/renderrichtext/accessibility/AccessibleTiptapTextView.kt +112 -112
  12. package/android/src/main/java/com/renderrichtext/accessibility/TiptapAccessibilityHelper.kt +576 -576
  13. package/android/src/main/java/com/renderrichtext/events/CodeBlockPressEvent.kt +24 -24
  14. package/android/src/main/java/com/renderrichtext/events/ContextMenuItemPressEvent.kt +28 -28
  15. package/android/src/main/java/com/renderrichtext/events/CopyPressEvent.kt +24 -24
  16. package/android/src/main/java/com/renderrichtext/events/ImagePressEvent.kt +25 -25
  17. package/android/src/main/java/com/renderrichtext/events/LatexErrorEvent.kt +29 -29
  18. package/android/src/main/java/com/renderrichtext/events/LinkLongPressEvent.kt +23 -23
  19. package/android/src/main/java/com/renderrichtext/events/LinkPressEvent.kt +23 -23
  20. package/android/src/main/java/com/renderrichtext/events/MentionLongPressEvent.kt +25 -25
  21. package/android/src/main/java/com/renderrichtext/events/MentionPressEvent.kt +25 -25
  22. package/android/src/main/java/com/renderrichtext/events/TaskListItemPressEvent.kt +26 -26
  23. package/android/src/main/java/com/renderrichtext/math/LatexErrorReporter.kt +9 -9
  24. package/android/src/main/java/com/renderrichtext/parser/Parser.kt +59 -59
  25. package/android/src/main/java/com/renderrichtext/parser/TextLinkMatching.kt +35 -35
  26. package/android/src/main/java/com/renderrichtext/renderer/BaselineShiftRenderer.kt +45 -45
  27. package/android/src/main/java/com/renderrichtext/renderer/BlankLineRenderer.kt +39 -39
  28. package/android/src/main/java/com/renderrichtext/renderer/BlockquoteRenderer.kt +243 -243
  29. package/android/src/main/java/com/renderrichtext/renderer/BlockquoteTextRenderer.kt +56 -56
  30. package/android/src/main/java/com/renderrichtext/renderer/CodeBlockRenderer.kt +135 -135
  31. package/android/src/main/java/com/renderrichtext/renderer/CodeRenderer.kt +37 -37
  32. package/android/src/main/java/com/renderrichtext/renderer/EmphasisRenderer.kt +28 -28
  33. package/android/src/main/java/com/renderrichtext/renderer/HeadingRenderer.kt +81 -81
  34. package/android/src/main/java/com/renderrichtext/renderer/HighlightRenderer.kt +26 -26
  35. package/android/src/main/java/com/renderrichtext/renderer/LineBreakRenderer.kt +17 -17
  36. package/android/src/main/java/com/renderrichtext/renderer/LinkRenderer.kt +90 -90
  37. package/android/src/main/java/com/renderrichtext/renderer/ListContextManager.kt +109 -109
  38. package/android/src/main/java/com/renderrichtext/renderer/ListItemRenderer.kt +211 -211
  39. package/android/src/main/java/com/renderrichtext/renderer/ListRenderer.kt +133 -133
  40. package/android/src/main/java/com/renderrichtext/renderer/MentionRenderer.kt +85 -85
  41. package/android/src/main/java/com/renderrichtext/renderer/ParagraphRenderer.kt +91 -91
  42. package/android/src/main/java/com/renderrichtext/renderer/Renderer.kt +148 -148
  43. package/android/src/main/java/com/renderrichtext/renderer/SoftBreakRenderer.kt +17 -17
  44. package/android/src/main/java/com/renderrichtext/renderer/SpanStyleCache.kt +143 -143
  45. package/android/src/main/java/com/renderrichtext/renderer/StrikethroughRenderer.kt +28 -28
  46. package/android/src/main/java/com/renderrichtext/renderer/StrongRenderer.kt +28 -28
  47. package/android/src/main/java/com/renderrichtext/renderer/TextRenderer.kt +31 -31
  48. package/android/src/main/java/com/renderrichtext/renderer/ThematicBreakRenderer.kt +46 -46
  49. package/android/src/main/java/com/renderrichtext/renderer/UnderlineRenderer.kt +28 -28
  50. package/android/src/main/java/com/renderrichtext/spans/BaseListSpan.kt +164 -164
  51. package/android/src/main/java/com/renderrichtext/spans/BaselineShiftSpan.kt +27 -27
  52. package/android/src/main/java/com/renderrichtext/spans/BlockquoteSpan.kt +302 -302
  53. package/android/src/main/java/com/renderrichtext/spans/CodeBackgroundSpan.kt +205 -205
  54. package/android/src/main/java/com/renderrichtext/spans/CodeBlockSpan.kt +216 -216
  55. package/android/src/main/java/com/renderrichtext/spans/CodeSpan.kt +32 -32
  56. package/android/src/main/java/com/renderrichtext/spans/EmphasisSpan.kt +42 -42
  57. package/android/src/main/java/com/renderrichtext/spans/FadeInSpan.kt +29 -29
  58. package/android/src/main/java/com/renderrichtext/spans/HeadingSpan.kt +38 -38
  59. package/android/src/main/java/com/renderrichtext/spans/HighlightSpan.kt +80 -80
  60. package/android/src/main/java/com/renderrichtext/spans/ImageSpan.kt +481 -481
  61. package/android/src/main/java/com/renderrichtext/spans/InlineBackgroundGeometry.kt +42 -42
  62. package/android/src/main/java/com/renderrichtext/spans/LineHeightSpan.kt +39 -39
  63. package/android/src/main/java/com/renderrichtext/spans/LinkPillIconCache.kt +154 -154
  64. package/android/src/main/java/com/renderrichtext/spans/LinkPillSpan.kt +381 -381
  65. package/android/src/main/java/com/renderrichtext/spans/LinkSpan.kt +68 -68
  66. package/android/src/main/java/com/renderrichtext/spans/ListItemSpacingSpan.kt +33 -33
  67. package/android/src/main/java/com/renderrichtext/spans/ListMarkerAnchorSpan.kt +38 -38
  68. package/android/src/main/java/com/renderrichtext/spans/MarginBottomSpan.kt +76 -76
  69. package/android/src/main/java/com/renderrichtext/spans/MentionChipSpan.kt +132 -132
  70. package/android/src/main/java/com/renderrichtext/spans/MentionSpan.kt +46 -46
  71. package/android/src/main/java/com/renderrichtext/spans/OrderedListSpan.kt +127 -127
  72. package/android/src/main/java/com/renderrichtext/spans/SpoilerSpan.kt +33 -33
  73. package/android/src/main/java/com/renderrichtext/spans/StrikethroughSpan.kt +12 -12
  74. package/android/src/main/java/com/renderrichtext/spans/StrongSpan.kt +39 -39
  75. package/android/src/main/java/com/renderrichtext/spans/TaskListSpan.kt +143 -143
  76. package/android/src/main/java/com/renderrichtext/spans/TextSpan.kt +26 -26
  77. package/android/src/main/java/com/renderrichtext/spans/ThematicBreakSpan.kt +69 -69
  78. package/android/src/main/java/com/renderrichtext/spans/UnorderedListSpan.kt +96 -96
  79. package/android/src/main/java/com/renderrichtext/spoiler/SpoilerStubs.kt +46 -46
  80. package/android/src/main/java/com/renderrichtext/styles/BaseBlockStyle.kt +11 -11
  81. package/android/src/main/java/com/renderrichtext/styles/BlockquoteStyle.kt +83 -83
  82. package/android/src/main/java/com/renderrichtext/styles/CodeBlockStyle.kt +80 -80
  83. package/android/src/main/java/com/renderrichtext/styles/CodeStyle.kt +26 -26
  84. package/android/src/main/java/com/renderrichtext/styles/EmphasisStyle.kt +21 -21
  85. package/android/src/main/java/com/renderrichtext/styles/FactoidStyle.kt +21 -21
  86. package/android/src/main/java/com/renderrichtext/styles/HeadingStyle.kt +33 -33
  87. package/android/src/main/java/com/renderrichtext/styles/HighlightStyle.kt +19 -19
  88. package/android/src/main/java/com/renderrichtext/styles/ImageStyle.kt +29 -29
  89. package/android/src/main/java/com/renderrichtext/styles/InlineImageStyle.kt +17 -17
  90. package/android/src/main/java/com/renderrichtext/styles/InlineMathStyle.kt +17 -17
  91. package/android/src/main/java/com/renderrichtext/styles/LinkPillContent.kt +36 -36
  92. package/android/src/main/java/com/renderrichtext/styles/LinkPillStyle.kt +44 -44
  93. package/android/src/main/java/com/renderrichtext/styles/LinkStyle.kt +23 -23
  94. package/android/src/main/java/com/renderrichtext/styles/LinkVariantEntry.kt +34 -34
  95. package/android/src/main/java/com/renderrichtext/styles/ListStyle.kt +65 -65
  96. package/android/src/main/java/com/renderrichtext/styles/MathStyle.kt +29 -29
  97. package/android/src/main/java/com/renderrichtext/styles/MentionStyle.kt +19 -19
  98. package/android/src/main/java/com/renderrichtext/styles/ParagraphStyle.kt +33 -33
  99. package/android/src/main/java/com/renderrichtext/styles/SpoilerStyle.kt +27 -27
  100. package/android/src/main/java/com/renderrichtext/styles/StrikethroughStyle.kt +17 -17
  101. package/android/src/main/java/com/renderrichtext/styles/StrongStyle.kt +21 -21
  102. package/android/src/main/java/com/renderrichtext/styles/StyleConfig.kt +411 -411
  103. package/android/src/main/java/com/renderrichtext/styles/StyleParser.kt +92 -92
  104. package/android/src/main/java/com/renderrichtext/styles/SubscriptStyle.kt +16 -16
  105. package/android/src/main/java/com/renderrichtext/styles/SuperscriptStyle.kt +16 -16
  106. package/android/src/main/java/com/renderrichtext/styles/TableStyle.kt +75 -75
  107. package/android/src/main/java/com/renderrichtext/styles/TaskListStyle.kt +29 -29
  108. package/android/src/main/java/com/renderrichtext/styles/TextAlignment.kt +32 -32
  109. package/android/src/main/java/com/renderrichtext/styles/ThematicBreakStyle.kt +23 -23
  110. package/android/src/main/java/com/renderrichtext/styles/UnderlineStyle.kt +17 -17
  111. package/android/src/main/java/com/renderrichtext/styles/VideoStyle.kt +31 -31
  112. package/android/src/main/java/com/renderrichtext/utils/common/BorderStyleUtils.kt +86 -86
  113. package/android/src/main/java/com/renderrichtext/utils/common/BreakStrategyUtils.kt +32 -32
  114. package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockHighlighter.kt +36 -36
  115. package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockNode.kt +42 -42
  116. package/android/src/main/java/com/renderrichtext/utils/common/EllipsizeUtils.kt +27 -27
  117. package/android/src/main/java/com/renderrichtext/utils/common/EnrichedTiptapAncestorUtils.kt +10 -10
  118. package/android/src/main/java/com/renderrichtext/utils/common/FeatureFlags.kt +9 -9
  119. package/android/src/main/java/com/renderrichtext/utils/common/LinkRecognitionProps.kt +31 -31
  120. package/android/src/main/java/com/renderrichtext/utils/common/LinkRegexConfig.kt +56 -56
  121. package/android/src/main/java/com/renderrichtext/utils/common/MotionPreferences.kt +18 -18
  122. package/android/src/main/java/com/renderrichtext/utils/common/ReadableMapExtensions.kt +28 -28
  123. package/android/src/main/java/com/renderrichtext/utils/common/layout/RTLUtils.kt +6 -6
  124. package/android/src/main/java/com/renderrichtext/utils/common/serialization/TiptapASTSerializer.kt +368 -368
  125. package/android/src/main/java/com/renderrichtext/utils/text/ImageCache.kt +88 -88
  126. package/android/src/main/java/com/renderrichtext/utils/text/ImageDownloader.kt +203 -203
  127. package/android/src/main/java/com/renderrichtext/utils/text/LocalImageLoader.kt +167 -167
  128. package/android/src/main/java/com/renderrichtext/utils/text/TailFadeInAnimator.kt +84 -84
  129. package/android/src/main/java/com/renderrichtext/utils/text/conversion/HTMLGenerator.kt +1105 -1105
  130. package/android/src/main/java/com/renderrichtext/utils/text/conversion/TiptapExtractor.kt +423 -423
  131. package/android/src/main/java/com/renderrichtext/utils/text/extensions/ParagraphUtils.kt +9 -9
  132. package/android/src/main/java/com/renderrichtext/utils/text/extensions/SpannableExtensions.kt +9 -9
  133. package/android/src/main/java/com/renderrichtext/utils/text/extensions/TextPaintExtensions.kt +76 -76
  134. package/android/src/main/java/com/renderrichtext/utils/text/interaction/CheckboxTouchHelper.kt +61 -61
  135. package/android/src/main/java/com/renderrichtext/utils/text/interaction/TaskListTapUtils.kt +286 -286
  136. package/android/src/main/java/com/renderrichtext/utils/text/span/ApplyLineHeight.kt +39 -39
  137. package/android/src/main/java/com/renderrichtext/utils/text/span/BlockSpacing.kt +142 -142
  138. package/android/src/main/java/com/renderrichtext/utils/text/span/SpanFlags.kt +43 -43
  139. package/android/src/main/java/com/renderrichtext/utils/text/span/WidthAwareSpans.kt +30 -30
  140. package/android/src/main/java/com/renderrichtext/utils/text/view/CodeBlockPressHost.kt +15 -15
  141. package/android/src/main/java/com/renderrichtext/utils/text/view/ImagePressHost.kt +19 -19
  142. package/android/src/main/java/com/renderrichtext/utils/text/view/SelectionActionMode.kt +235 -235
  143. package/android/src/main/java/com/renderrichtext/utils/text/view/TextSelectionColors.kt +48 -48
  144. package/android/src/main/java/com/renderrichtext/utils/text/view/TextViewSetup.kt +119 -119
  145. package/android/src/main/java/com/renderrichtext/views/ContextMenuPopup.kt +217 -217
  146. package/android/src/main/java/com/renderrichtext/views/CopyGlyph.kt +101 -101
  147. package/android/src/main/java/com/renderrichtext/views/WrapGlyph.kt +40 -40
  148. package/android/src/main/jni/CMakeLists.txt +52 -52
  149. package/android/src/main/jni/react/renderer/components/RichTextSpec/ComponentDescriptors.h +30 -30
  150. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextComponentDescriptor.h +29 -29
  151. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.cpp +45 -45
  152. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.h +21 -21
  153. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.cpp +38 -38
  154. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.h +53 -53
  155. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.cpp +9 -9
  156. package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.h +24 -24
  157. package/android/src/main/jni/react/renderer/components/RichTextSpec/conversions.h +40 -40
  158. package/cpp/parser/TiptapParser.hpp +13 -13
  159. package/cpp/vendor/nlohmann/json.hpp +24765 -24765
  160. package/ios/EnrichedTiptapText.h +27 -27
  161. package/ios/attachments/ENRMImageAttachment.h +51 -51
  162. package/ios/attachments/ENRMImageAttachment.m +398 -398
  163. package/ios/attachments/ENRMLinkPillAttachment.h +47 -47
  164. package/ios/attachments/ENRMLinkPillAttachment.m +324 -324
  165. package/ios/attachments/ENRMLinkPillIconCache.h +28 -28
  166. package/ios/attachments/ENRMLinkPillIconCache.m +181 -181
  167. package/ios/attachments/ENRMLinkPillText.h +27 -27
  168. package/ios/attachments/ENRMLinkPillText.m +118 -118
  169. package/ios/attachments/ENRMMathInlineAttachment.h +7 -7
  170. package/ios/attachments/ENRMMathInlineAttachment.m +4 -4
  171. package/ios/attachments/ThematicBreakAttachment.h +15 -15
  172. package/ios/attachments/ThematicBreakAttachment.m +33 -33
  173. package/ios/internals/ENRMViewFreeMeasurement.h +208 -208
  174. package/ios/internals/EnrichedTiptapTextComponentDescriptor.h +19 -19
  175. package/ios/internals/EnrichedTiptapTextShadowNode.h +43 -43
  176. package/ios/internals/EnrichedTiptapTextShadowNode.mm +69 -69
  177. package/ios/internals/EnrichedTiptapTextState.h +24 -24
  178. package/ios/internals/MeasurementCache.h +308 -308
  179. package/ios/internals/ShadowMeasurementUtils.h +145 -145
  180. package/ios/parser/ENRMTextLinkAttributes.h +7 -7
  181. package/ios/parser/ENRMTiptapParser.h +33 -33
  182. package/ios/parser/ENRMTiptapParser.mm +73 -73
  183. package/ios/parser/TiptapASTNode.m +52 -52
  184. package/ios/renderer/AttributedRenderer.h +23 -23
  185. package/ios/renderer/AttributedRenderer.m +229 -229
  186. package/ios/renderer/BaseRenderer.h +33 -33
  187. package/ios/renderer/BaseRenderer.m +46 -46
  188. package/ios/renderer/BaselineShiftTextAttributes.h +10 -10
  189. package/ios/renderer/BaselineShiftTextAttributes.m +26 -26
  190. package/ios/renderer/BlankLineRenderer.h +4 -4
  191. package/ios/renderer/BlankLineRenderer.m +51 -51
  192. package/ios/renderer/BlockquoteRenderer.h +6 -6
  193. package/ios/renderer/BlockquoteRenderer.m +258 -258
  194. package/ios/renderer/CodeBlockRenderer.h +9 -9
  195. package/ios/renderer/CodeBlockRenderer.m +99 -99
  196. package/ios/renderer/CodeRenderer.h +9 -9
  197. package/ios/renderer/CodeRenderer.m +69 -69
  198. package/ios/renderer/ENRMBlockquoteTextRenderer.h +25 -25
  199. package/ios/renderer/ENRMBlockquoteTextRenderer.m +48 -48
  200. package/ios/renderer/EmphasisRenderer.h +5 -5
  201. package/ios/renderer/EmphasisRenderer.m +99 -99
  202. package/ios/renderer/HeadingRenderer.h +6 -6
  203. package/ios/renderer/HeadingRenderer.m +102 -102
  204. package/ios/renderer/HighlightRenderer.h +7 -7
  205. package/ios/renderer/HighlightRenderer.m +33 -33
  206. package/ios/renderer/LinkRenderer.h +6 -6
  207. package/ios/renderer/LinkRenderer.m +157 -157
  208. package/ios/renderer/ListItemRenderer.h +24 -24
  209. package/ios/renderer/ListItemRenderer.m +283 -283
  210. package/ios/renderer/ListRenderer.h +13 -13
  211. package/ios/renderer/ListRenderer.m +126 -126
  212. package/ios/renderer/MentionRenderer.h +9 -9
  213. package/ios/renderer/MentionRenderer.m +96 -96
  214. package/ios/renderer/NodeRenderer.h +8 -8
  215. package/ios/renderer/ParagraphRenderer.h +6 -6
  216. package/ios/renderer/ParagraphRenderer.m +85 -85
  217. package/ios/renderer/RenderContext.h +145 -145
  218. package/ios/renderer/RenderContext.m +402 -402
  219. package/ios/renderer/RendererFactory.h +12 -12
  220. package/ios/renderer/StrikethroughRenderer.h +5 -5
  221. package/ios/renderer/StrikethroughRenderer.m +30 -30
  222. package/ios/renderer/StrongRenderer.h +5 -5
  223. package/ios/renderer/StrongRenderer.m +87 -87
  224. package/ios/renderer/TextRenderer.h +6 -6
  225. package/ios/renderer/TextRenderer.m +18 -18
  226. package/ios/renderer/ThematicBreakRenderer.h +4 -4
  227. package/ios/renderer/ThematicBreakRenderer.m +41 -41
  228. package/ios/renderer/UnderlineRenderer.h +4 -4
  229. package/ios/renderer/UnderlineRenderer.m +41 -41
  230. package/ios/styles/ENRMFontSlot.h +12 -12
  231. package/ios/styles/ENRMFontSlot.m +24 -24
  232. package/ios/styles/StyleConfig.h +488 -488
  233. package/ios/styles/StyleConfig.mm +2820 -2820
  234. package/ios/utils/AccessibilityInfo.h +35 -35
  235. package/ios/utils/AccessibilityInfo.m +24 -24
  236. package/ios/utils/BlockquoteBorder.h +26 -26
  237. package/ios/utils/BlockquoteBorder.m +294 -294
  238. package/ios/utils/CodeBackground.h +19 -19
  239. package/ios/utils/CodeBackground.m +196 -196
  240. package/ios/utils/CodeBlockBackground.h +17 -17
  241. package/ios/utils/CodeBlockBackground.m +102 -102
  242. package/ios/utils/ContextMenuUtils.h +76 -76
  243. package/ios/utils/ContextMenuUtils.mm +75 -75
  244. package/ios/utils/ENRMAccessibilityLabels.h +40 -40
  245. package/ios/utils/ENRMAccessibilityLabels.m +5 -5
  246. package/ios/utils/ENRMAsyncRenderCoordinator.h +24 -24
  247. package/ios/utils/ENRMAsyncRenderCoordinator.m +37 -37
  248. package/ios/utils/ENRMAtomicSize.h +65 -65
  249. package/ios/utils/ENRMCodeBlockContent.h +37 -37
  250. package/ios/utils/ENRMCodeBlockContent.mm +89 -89
  251. package/ios/utils/ENRMFeatureFlags.h +25 -25
  252. package/ios/utils/ENRMImageDownloader.h +30 -30
  253. package/ios/utils/ENRMImageDownloader.m +168 -168
  254. package/ios/utils/ENRMLatexErrorCoordinator.h +27 -27
  255. package/ios/utils/ENRMLatexErrorCoordinator.mm +75 -75
  256. package/ios/utils/ENRMLatexErrorReporting.h +13 -13
  257. package/ios/utils/ENRMLinkContextMenus.h +93 -93
  258. package/ios/utils/ENRMLinkContextMenus.m +178 -178
  259. package/ios/utils/ENRMLinkRegexConfig.h +30 -30
  260. package/ios/utils/ENRMLinkRegexConfig.mm +104 -104
  261. package/ios/utils/ENRMLinkRegexProps.h +23 -23
  262. package/ios/utils/ENRMLocalImageLoader.h +35 -35
  263. package/ios/utils/ENRMLocalImageLoader.m +111 -111
  264. package/ios/utils/ENRMMenuAction.h +27 -27
  265. package/ios/utils/ENRMMenuAction.m +33 -33
  266. package/ios/utils/ENRMSpoilerOverlayManager.h +15 -15
  267. package/ios/utils/ENRMSpoilerOverlayManager.m +19 -19
  268. package/ios/utils/ENRMSpoilerTapUtils.h +6 -6
  269. package/ios/utils/ENRMSpoilerTapUtils.m +11 -11
  270. package/ios/utils/ENRMTailFadeInAnimator.h +16 -16
  271. package/ios/utils/ENRMTailFadeInAnimator.m +161 -161
  272. package/ios/utils/ENRMTextHitTest.h +23 -23
  273. package/ios/utils/ENRMTextHitTest.m +20 -20
  274. package/ios/utils/ENRMTextInteractionUtils.h +20 -20
  275. package/ios/utils/ENRMTextInteractionUtils.m +15 -15
  276. package/ios/utils/ENRMTextRenderer.h +38 -38
  277. package/ios/utils/ENRMTextRenderer.m +54 -54
  278. package/ios/utils/ENRMTextViewSetup.h +132 -132
  279. package/ios/utils/ENRMUIKit.h +429 -429
  280. package/ios/utils/EditMenuUtils.h +105 -105
  281. package/ios/utils/EditMenuUtils.m +143 -143
  282. package/ios/utils/FontScaleObserver.h +10 -10
  283. package/ios/utils/FontScaleObserver.m +55 -55
  284. package/ios/utils/FontUtils.h +31 -31
  285. package/ios/utils/FontUtils.m +63 -63
  286. package/ios/utils/HTMLGenerator.h +25 -25
  287. package/ios/utils/HTMLGenerator.m +1041 -1041
  288. package/ios/utils/HeightUpdateUtils.h +25 -25
  289. package/ios/utils/ImageRequestHeaderUtils.h +35 -35
  290. package/ios/utils/LastElementUtils.h +97 -97
  291. package/ios/utils/LinkContextMenuUtils.h +55 -55
  292. package/ios/utils/LinkPillContentUtils.h +46 -46
  293. package/ios/utils/ListMarkerDrawer.h +15 -15
  294. package/ios/utils/ListMarkerDrawer.m +239 -239
  295. package/ios/utils/MentionBackground.h +26 -26
  296. package/ios/utils/MentionBackground.m +86 -86
  297. package/ios/utils/ParagraphStyleUtils.h +87 -87
  298. package/ios/utils/ParagraphStyleUtils.m +484 -484
  299. package/ios/utils/PasteboardUtils.h +48 -48
  300. package/ios/utils/PasteboardUtils.m +166 -166
  301. package/ios/utils/RTFExportUtils.h +24 -24
  302. package/ios/utils/RTFExportUtils.m +299 -299
  303. package/ios/utils/SelectionColorUtils.h +14 -14
  304. package/ios/utils/StylePropsUtils.h +1340 -1340
  305. package/ios/utils/TaskListTapUtils.h +6 -6
  306. package/ios/utils/TaskListTapUtils.m +14 -14
  307. package/ios/utils/TextViewLayoutManager.h +14 -14
  308. package/ios/utils/TiptapAccessibilityElementBuilder.h +43 -43
  309. package/ios/utils/TiptapAccessibilityElementBuilder.m +432 -432
  310. package/ios/utils/TiptapExtractor.h +17 -17
  311. package/ios/utils/TiptapExtractor.m +367 -367
  312. package/ios/views/ENRMTiptapTextView.h +25 -25
  313. package/ios/views/ENRMTiptapTextView.m +247 -247
  314. package/package.json +65 -70
  315. package/react-native.config.js +10 -10
  316. package/src/admonitionDefaults.ts +58 -58
  317. package/src/darkModeTextStyle.ts +99 -99
  318. package/src/headingDefaults.ts +21 -21
  319. package/src/index.tsx +4 -4
  320. package/src/linkVariantUtils.ts +120 -120
  321. package/src/normalizeTiptapStyle.ts +397 -397
  322. package/src/rn-globals.d.ts +1 -1
  323. package/src/styleUtils.ts +107 -107
  324. package/src/types/TiptapStyle.ts +532 -532
  325. package/src/types/TiptapStyleInternal.ts +299 -299
  326. package/src/types/linkPill.ts +9 -9
  327. package/src/utils/isDev.ts +4 -4
@@ -1,294 +1,294 @@
1
- #import "BlockquoteBorder.h"
2
- #import "ParagraphStyleUtils.h"
3
- #import "StyleConfig.h"
4
-
5
- // Attribute constants for identifying blockquote segments in text storage
6
- NSString *const BlockquoteDepthAttributeName = @"BlockquoteDepth";
7
- NSString *const BlockquoteBackgroundColorAttributeName = @"BlockquoteBackgroundColor";
8
- NSString *const BlockquoteSpacerAttributeName = @"BlockquoteSpacer";
9
-
10
- @implementation BlockquoteBorder {
11
- StyleConfig *_config;
12
- }
13
-
14
- - (instancetype)initWithConfig:(StyleConfig *)config
15
- {
16
- if (self = [super init]) {
17
- _config = config;
18
- }
19
- return self;
20
- }
21
-
22
- /**
23
- * Main drawing entry point called by the LayoutManager.
24
- * Collects contiguous blockquote regions and draws each as one rounded box:
25
- * background fill first, then the vertical borders clipped to the box shape.
26
- * When a border radius is set, each nested quote's stripes are additionally
27
- * clipped to that quote's own rounded box, mirroring per-element CSS
28
- * border-radius on web.
29
- * Regions are discovered by scanning only the drawn character range; regions
30
- * touching its edges are extended run-by-run to their true boundaries, so the
31
- * cost scales with the visible text plus the intersecting quotes rather than
32
- * the whole document.
33
- */
34
- - (void)drawBordersForGlyphRange:(NSRange)glyphsToShow
35
- layoutManager:(NSLayoutManager *)layoutManager
36
- textContainer:(NSTextContainer *)textContainer
37
- atPoint:(CGPoint)origin
38
- {
39
- NSTextStorage *textStorage = layoutManager.textStorage;
40
- if (!textStorage || textStorage.length == 0) {
41
- return;
42
- }
43
-
44
- NSRange charRange = [layoutManager characterRangeForGlyphRange:glyphsToShow actualGlyphRange:NULL];
45
- if (charRange.location == NSNotFound || charRange.length == 0) {
46
- return;
47
- }
48
-
49
- NSMutableArray<NSValue *> *regions = [NSMutableArray array];
50
- __block NSRange currentRegion = NSMakeRange(NSNotFound, 0);
51
- [textStorage enumerateAttribute:BlockquoteDepthAttributeName
52
- inRange:charRange
53
- options:0
54
- usingBlock:^(id value, NSRange range, BOOL *stop) {
55
- if (!value) {
56
- if (currentRegion.location != NSNotFound) {
57
- [regions addObject:[NSValue valueWithRange:currentRegion]];
58
- currentRegion = NSMakeRange(NSNotFound, 0);
59
- }
60
- return;
61
- }
62
- currentRegion =
63
- currentRegion.location == NSNotFound ? range : NSUnionRange(currentRegion, range);
64
- }];
65
- if (currentRegion.location != NSNotFound) {
66
- [regions addObject:[NSValue valueWithRange:currentRegion]];
67
- }
68
-
69
- if (regions.count == 0) {
70
- return;
71
- }
72
-
73
- NSRange firstRegion = regions.firstObject.rangeValue;
74
- if (firstRegion.location == charRange.location) {
75
- while (firstRegion.location > 0) {
76
- NSRange runRange;
77
- if (![textStorage attribute:BlockquoteDepthAttributeName
78
- atIndex:firstRegion.location - 1
79
- effectiveRange:&runRange]) {
80
- break;
81
- }
82
- firstRegion = NSUnionRange(firstRegion, runRange);
83
- }
84
- regions[0] = [NSValue valueWithRange:firstRegion];
85
- }
86
-
87
- NSRange lastRegion = regions.lastObject.rangeValue;
88
- if (NSMaxRange(lastRegion) == NSMaxRange(charRange)) {
89
- while (NSMaxRange(lastRegion) < textStorage.length) {
90
- NSRange runRange;
91
- if (![textStorage attribute:BlockquoteDepthAttributeName
92
- atIndex:NSMaxRange(lastRegion)
93
- effectiveRange:&runRange]) {
94
- break;
95
- }
96
- lastRegion = NSUnionRange(lastRegion, runRange);
97
- }
98
- regions[regions.count - 1] = [NSValue valueWithRange:lastRegion];
99
- }
100
-
101
- for (NSValue *value in regions) {
102
- [self drawBlockquoteRegion:value.rangeValue layoutManager:layoutManager textContainer:textContainer atPoint:origin];
103
- }
104
- }
105
-
106
- /**
107
- * Groups the depth runs of a region into nested quote boxes: for each level
108
- * >= 1, a box is a maximal contiguous stretch where depth >= level (a nested
109
- * quote's own range). Outputs parallel arrays of ranges and levels.
110
- */
111
- static void collectNestedBoxes(NSArray<NSValue *> *runRanges, NSArray<NSNumber *> *runDepths,
112
- NSMutableArray<NSValue *> *boxRanges, NSMutableArray<NSNumber *> *boxLevels)
113
- {
114
- NSInteger maxDepth = 0;
115
- for (NSNumber *depth in runDepths) {
116
- maxDepth = MAX(maxDepth, depth.integerValue);
117
- }
118
-
119
- for (NSInteger level = 1; level <= maxDepth; level++) {
120
- NSRange current = NSMakeRange(NSNotFound, 0);
121
- for (NSUInteger i = 0; i < runRanges.count; i++) {
122
- if (runDepths[i].integerValue >= level) {
123
- NSRange runRange = runRanges[i].rangeValue;
124
- current = current.location == NSNotFound ? runRange : NSUnionRange(current, runRange);
125
- } else if (current.location != NSNotFound) {
126
- [boxRanges addObject:[NSValue valueWithRange:current]];
127
- [boxLevels addObject:@(level)];
128
- current = NSMakeRange(NSNotFound, 0);
129
- }
130
- }
131
- if (current.location != NSNotFound) {
132
- [boxRanges addObject:[NSValue valueWithRange:current]];
133
- [boxLevels addObject:@(level)];
134
- }
135
- }
136
- }
137
-
138
- - (void)drawBlockquoteRegion:(NSRange)region
139
- layoutManager:(NSLayoutManager *)layoutManager
140
- textContainer:(NSTextContainer *)textContainer
141
- atPoint:(CGPoint)origin
142
- {
143
- NSTextStorage *textStorage = layoutManager.textStorage;
144
-
145
- // Cache configuration values to minimize pointer chasing and method lookups in the loop
146
- StyleConfig *c = _config;
147
- CGFloat borderWidth = c.blockquoteBorderWidth;
148
- CGFloat gapWidth = c.blockquoteGapWidth;
149
- CGFloat levelSpacing = borderWidth + gapWidth;
150
- CGFloat borderRadius = c.blockquoteBorderRadius;
151
- CGFloat containerWidth = textContainer.size.width;
152
- RCTUIColor *defaultBgColor = c.blockquoteBackgroundColor;
153
- RCTUIColor *borderColor = c.blockquoteBorderColor;
154
-
155
- NSRange glyphRange = [layoutManager glyphRangeForCharacterRange:region actualCharacterRange:NULL];
156
- CGRect blockRect = [layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer];
157
- if (CGRectIsEmpty(blockRect)) {
158
- return;
159
- }
160
-
161
- blockRect.origin.x = origin.x;
162
- blockRect.origin.y += origin.y;
163
- blockRect.size.width = containerWidth;
164
-
165
- BOOL isLastBlockquote = (NSMaxRange(region) == textStorage.length);
166
- if (isLastBlockquote) {
167
- blockRect.size.height += c.blockquotePadding;
168
- }
169
-
170
- NSMutableArray<NSValue *> *boxRanges = [NSMutableArray array];
171
- NSMutableArray<NSNumber *> *boxLevels = [NSMutableArray array];
172
- NSMutableArray<UIBezierPath *> *boxStripePaths = [NSMutableArray array];
173
- if (borderRadius > 0) {
174
- NSMutableArray<NSValue *> *runRanges = [NSMutableArray array];
175
- NSMutableArray<NSNumber *> *runDepths = [NSMutableArray array];
176
- [textStorage enumerateAttribute:BlockquoteDepthAttributeName
177
- inRange:region
178
- options:0
179
- usingBlock:^(id value, NSRange range, BOOL *stop) {
180
- if (!value) {
181
- return;
182
- }
183
- [runRanges addObject:[NSValue valueWithRange:range]];
184
- [runDepths addObject:value];
185
- }];
186
- collectNestedBoxes(runRanges, runDepths, boxRanges, boxLevels);
187
- for (NSUInteger i = 0; i < boxRanges.count; i++) {
188
- [boxStripePaths addObject:[UIBezierPath bezierPath]];
189
- }
190
- }
191
-
192
- CGContextRef ctx = UIGraphicsGetCurrentContext();
193
- CGContextSaveGState(ctx);
194
- {
195
- UIBezierPath *boxPath = UIBezierPathWithRoundedRect(blockRect, MAX(0, borderRadius));
196
- [boxPath addClip];
197
-
198
- // 1. Draw Background (Painter's algorithm: draw backgrounds before borders)
199
- RCTUIColor *bgColor = [textStorage attribute:BlockquoteBackgroundColorAttributeName
200
- atIndex:region.location
201
- effectiveRange:NULL]
202
- ?: defaultBgColor;
203
- if (bgColor && bgColor != [RCTUIColor clearColor]) {
204
- [bgColor setFill];
205
- CGContextFillRect(ctx, blockRect);
206
- }
207
-
208
- // 2. Aggregate vertical borders into batch paths; level-0 stripes are
209
- // rounded by the region clip, nested stripes by their own box clip below
210
- UIBezierPath *borderPath = [UIBezierPath bezierPath];
211
- [layoutManager
212
- enumerateLineFragmentsForGlyphRange:glyphRange
213
- usingBlock:^(CGRect rect, CGRect usedRect, NSTextContainer *container,
214
- NSRange lineGlyphRange, BOOL *stop) {
215
- NSRange lineCharRange = [layoutManager characterRangeForGlyphRange:lineGlyphRange
216
- actualGlyphRange:NULL];
217
- if (lineCharRange.location == NSNotFound || lineCharRange.length == 0) {
218
- return;
219
- }
220
-
221
- NSDictionary *attrs = [textStorage attributesAtIndex:lineCharRange.location
222
- effectiveRange:NULL];
223
- NSNumber *depthNum = attrs[BlockquoteDepthAttributeName];
224
-
225
- if (!depthNum) {
226
- return;
227
- }
228
-
229
- NSInteger depth = [depthNum integerValue];
230
- CGFloat baseY = origin.y + rect.origin.y;
231
- CGFloat lineHeight = rect.size.height;
232
- BOOL isLastLine = NSMaxRange(lineGlyphRange) == NSMaxRange(glyphRange);
233
- if (isLastBlockquote && isLastLine) {
234
- lineHeight += c.blockquotePadding;
235
- }
236
- BOOL isRTL = ENRMParagraphIsRTL(attrs[NSParagraphStyleAttributeName]);
237
-
238
- for (NSInteger level = 0; level <= depth; level++) {
239
- CGFloat borderX =
240
- isRTL ? origin.x + containerWidth - borderWidth - (levelSpacing * level)
241
- : origin.x + (levelSpacing * level);
242
- CGRect borderRect = CGRectMake(borderX, baseY, borderWidth, lineHeight);
243
-
244
- UIBezierPath *target = borderPath;
245
- for (NSUInteger b = 0; b < boxRanges.count; b++) {
246
- if (boxLevels[b].integerValue == level &&
247
- NSLocationInRange(lineCharRange.location, boxRanges[b].rangeValue)) {
248
- target = boxStripePaths[b];
249
- break;
250
- }
251
- }
252
- UIBezierPathAppendPath(target, [UIBezierPath bezierPathWithRect:borderRect]);
253
- }
254
- }];
255
-
256
- // 3. Perform a single batch fill for the root-level borders
257
- if (!borderPath.isEmpty) {
258
- [borderColor setFill];
259
- [borderPath fill];
260
- }
261
-
262
- // 4. Nested stripes: clip each to its own quote's rounded box (the clips
263
- // compose with the still-active region clip)
264
- for (NSUInteger b = 0; b < boxRanges.count; b++) {
265
- UIBezierPath *stripes = boxStripePaths[b];
266
- if (stripes.isEmpty) {
267
- continue;
268
- }
269
-
270
- NSRange boxRange = boxRanges[b].rangeValue;
271
- NSRange boxGlyphRange = [layoutManager glyphRangeForCharacterRange:boxRange actualCharacterRange:NULL];
272
- CGRect boxRect = [layoutManager boundingRectForGlyphRange:boxGlyphRange inTextContainer:textContainer];
273
- if (CGRectIsEmpty(boxRect)) {
274
- continue;
275
- }
276
-
277
- NSDictionary *boxAttrs = [textStorage attributesAtIndex:boxRange.location effectiveRange:NULL];
278
- BOOL boxRTL = ENRMParagraphIsRTL(boxAttrs[NSParagraphStyleAttributeName]);
279
- CGFloat leadingInset = levelSpacing * boxLevels[b].integerValue;
280
- boxRect.origin.x = boxRTL ? origin.x : origin.x + leadingInset;
281
- boxRect.origin.y += origin.y;
282
- boxRect.size.width = containerWidth - leadingInset;
283
-
284
- CGContextSaveGState(ctx);
285
- [UIBezierPathWithRoundedRect(boxRect, borderRadius) addClip];
286
- [borderColor setFill];
287
- [stripes fill];
288
- CGContextRestoreGState(ctx);
289
- }
290
- }
291
- CGContextRestoreGState(ctx);
292
- }
293
-
294
- @end
1
+ #import "BlockquoteBorder.h"
2
+ #import "ParagraphStyleUtils.h"
3
+ #import "StyleConfig.h"
4
+
5
+ // Attribute constants for identifying blockquote segments in text storage
6
+ NSString *const BlockquoteDepthAttributeName = @"BlockquoteDepth";
7
+ NSString *const BlockquoteBackgroundColorAttributeName = @"BlockquoteBackgroundColor";
8
+ NSString *const BlockquoteSpacerAttributeName = @"BlockquoteSpacer";
9
+
10
+ @implementation BlockquoteBorder {
11
+ StyleConfig *_config;
12
+ }
13
+
14
+ - (instancetype)initWithConfig:(StyleConfig *)config
15
+ {
16
+ if (self = [super init]) {
17
+ _config = config;
18
+ }
19
+ return self;
20
+ }
21
+
22
+ /**
23
+ * Main drawing entry point called by the LayoutManager.
24
+ * Collects contiguous blockquote regions and draws each as one rounded box:
25
+ * background fill first, then the vertical borders clipped to the box shape.
26
+ * When a border radius is set, each nested quote's stripes are additionally
27
+ * clipped to that quote's own rounded box, mirroring per-element CSS
28
+ * border-radius on web.
29
+ * Regions are discovered by scanning only the drawn character range; regions
30
+ * touching its edges are extended run-by-run to their true boundaries, so the
31
+ * cost scales with the visible text plus the intersecting quotes rather than
32
+ * the whole document.
33
+ */
34
+ - (void)drawBordersForGlyphRange:(NSRange)glyphsToShow
35
+ layoutManager:(NSLayoutManager *)layoutManager
36
+ textContainer:(NSTextContainer *)textContainer
37
+ atPoint:(CGPoint)origin
38
+ {
39
+ NSTextStorage *textStorage = layoutManager.textStorage;
40
+ if (!textStorage || textStorage.length == 0) {
41
+ return;
42
+ }
43
+
44
+ NSRange charRange = [layoutManager characterRangeForGlyphRange:glyphsToShow actualGlyphRange:NULL];
45
+ if (charRange.location == NSNotFound || charRange.length == 0) {
46
+ return;
47
+ }
48
+
49
+ NSMutableArray<NSValue *> *regions = [NSMutableArray array];
50
+ __block NSRange currentRegion = NSMakeRange(NSNotFound, 0);
51
+ [textStorage enumerateAttribute:BlockquoteDepthAttributeName
52
+ inRange:charRange
53
+ options:0
54
+ usingBlock:^(id value, NSRange range, BOOL *stop) {
55
+ if (!value) {
56
+ if (currentRegion.location != NSNotFound) {
57
+ [regions addObject:[NSValue valueWithRange:currentRegion]];
58
+ currentRegion = NSMakeRange(NSNotFound, 0);
59
+ }
60
+ return;
61
+ }
62
+ currentRegion =
63
+ currentRegion.location == NSNotFound ? range : NSUnionRange(currentRegion, range);
64
+ }];
65
+ if (currentRegion.location != NSNotFound) {
66
+ [regions addObject:[NSValue valueWithRange:currentRegion]];
67
+ }
68
+
69
+ if (regions.count == 0) {
70
+ return;
71
+ }
72
+
73
+ NSRange firstRegion = regions.firstObject.rangeValue;
74
+ if (firstRegion.location == charRange.location) {
75
+ while (firstRegion.location > 0) {
76
+ NSRange runRange;
77
+ if (![textStorage attribute:BlockquoteDepthAttributeName
78
+ atIndex:firstRegion.location - 1
79
+ effectiveRange:&runRange]) {
80
+ break;
81
+ }
82
+ firstRegion = NSUnionRange(firstRegion, runRange);
83
+ }
84
+ regions[0] = [NSValue valueWithRange:firstRegion];
85
+ }
86
+
87
+ NSRange lastRegion = regions.lastObject.rangeValue;
88
+ if (NSMaxRange(lastRegion) == NSMaxRange(charRange)) {
89
+ while (NSMaxRange(lastRegion) < textStorage.length) {
90
+ NSRange runRange;
91
+ if (![textStorage attribute:BlockquoteDepthAttributeName
92
+ atIndex:NSMaxRange(lastRegion)
93
+ effectiveRange:&runRange]) {
94
+ break;
95
+ }
96
+ lastRegion = NSUnionRange(lastRegion, runRange);
97
+ }
98
+ regions[regions.count - 1] = [NSValue valueWithRange:lastRegion];
99
+ }
100
+
101
+ for (NSValue *value in regions) {
102
+ [self drawBlockquoteRegion:value.rangeValue layoutManager:layoutManager textContainer:textContainer atPoint:origin];
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Groups the depth runs of a region into nested quote boxes: for each level
108
+ * >= 1, a box is a maximal contiguous stretch where depth >= level (a nested
109
+ * quote's own range). Outputs parallel arrays of ranges and levels.
110
+ */
111
+ static void collectNestedBoxes(NSArray<NSValue *> *runRanges, NSArray<NSNumber *> *runDepths,
112
+ NSMutableArray<NSValue *> *boxRanges, NSMutableArray<NSNumber *> *boxLevels)
113
+ {
114
+ NSInteger maxDepth = 0;
115
+ for (NSNumber *depth in runDepths) {
116
+ maxDepth = MAX(maxDepth, depth.integerValue);
117
+ }
118
+
119
+ for (NSInteger level = 1; level <= maxDepth; level++) {
120
+ NSRange current = NSMakeRange(NSNotFound, 0);
121
+ for (NSUInteger i = 0; i < runRanges.count; i++) {
122
+ if (runDepths[i].integerValue >= level) {
123
+ NSRange runRange = runRanges[i].rangeValue;
124
+ current = current.location == NSNotFound ? runRange : NSUnionRange(current, runRange);
125
+ } else if (current.location != NSNotFound) {
126
+ [boxRanges addObject:[NSValue valueWithRange:current]];
127
+ [boxLevels addObject:@(level)];
128
+ current = NSMakeRange(NSNotFound, 0);
129
+ }
130
+ }
131
+ if (current.location != NSNotFound) {
132
+ [boxRanges addObject:[NSValue valueWithRange:current]];
133
+ [boxLevels addObject:@(level)];
134
+ }
135
+ }
136
+ }
137
+
138
+ - (void)drawBlockquoteRegion:(NSRange)region
139
+ layoutManager:(NSLayoutManager *)layoutManager
140
+ textContainer:(NSTextContainer *)textContainer
141
+ atPoint:(CGPoint)origin
142
+ {
143
+ NSTextStorage *textStorage = layoutManager.textStorage;
144
+
145
+ // Cache configuration values to minimize pointer chasing and method lookups in the loop
146
+ StyleConfig *c = _config;
147
+ CGFloat borderWidth = c.blockquoteBorderWidth;
148
+ CGFloat gapWidth = c.blockquoteGapWidth;
149
+ CGFloat levelSpacing = borderWidth + gapWidth;
150
+ CGFloat borderRadius = c.blockquoteBorderRadius;
151
+ CGFloat containerWidth = textContainer.size.width;
152
+ RCTUIColor *defaultBgColor = c.blockquoteBackgroundColor;
153
+ RCTUIColor *borderColor = c.blockquoteBorderColor;
154
+
155
+ NSRange glyphRange = [layoutManager glyphRangeForCharacterRange:region actualCharacterRange:NULL];
156
+ CGRect blockRect = [layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer];
157
+ if (CGRectIsEmpty(blockRect)) {
158
+ return;
159
+ }
160
+
161
+ blockRect.origin.x = origin.x;
162
+ blockRect.origin.y += origin.y;
163
+ blockRect.size.width = containerWidth;
164
+
165
+ BOOL isLastBlockquote = (NSMaxRange(region) == textStorage.length);
166
+ if (isLastBlockquote) {
167
+ blockRect.size.height += c.blockquotePadding;
168
+ }
169
+
170
+ NSMutableArray<NSValue *> *boxRanges = [NSMutableArray array];
171
+ NSMutableArray<NSNumber *> *boxLevels = [NSMutableArray array];
172
+ NSMutableArray<UIBezierPath *> *boxStripePaths = [NSMutableArray array];
173
+ if (borderRadius > 0) {
174
+ NSMutableArray<NSValue *> *runRanges = [NSMutableArray array];
175
+ NSMutableArray<NSNumber *> *runDepths = [NSMutableArray array];
176
+ [textStorage enumerateAttribute:BlockquoteDepthAttributeName
177
+ inRange:region
178
+ options:0
179
+ usingBlock:^(id value, NSRange range, BOOL *stop) {
180
+ if (!value) {
181
+ return;
182
+ }
183
+ [runRanges addObject:[NSValue valueWithRange:range]];
184
+ [runDepths addObject:value];
185
+ }];
186
+ collectNestedBoxes(runRanges, runDepths, boxRanges, boxLevels);
187
+ for (NSUInteger i = 0; i < boxRanges.count; i++) {
188
+ [boxStripePaths addObject:[UIBezierPath bezierPath]];
189
+ }
190
+ }
191
+
192
+ CGContextRef ctx = UIGraphicsGetCurrentContext();
193
+ CGContextSaveGState(ctx);
194
+ {
195
+ UIBezierPath *boxPath = UIBezierPathWithRoundedRect(blockRect, MAX(0, borderRadius));
196
+ [boxPath addClip];
197
+
198
+ // 1. Draw Background (Painter's algorithm: draw backgrounds before borders)
199
+ RCTUIColor *bgColor = [textStorage attribute:BlockquoteBackgroundColorAttributeName
200
+ atIndex:region.location
201
+ effectiveRange:NULL]
202
+ ?: defaultBgColor;
203
+ if (bgColor && bgColor != [RCTUIColor clearColor]) {
204
+ [bgColor setFill];
205
+ CGContextFillRect(ctx, blockRect);
206
+ }
207
+
208
+ // 2. Aggregate vertical borders into batch paths; level-0 stripes are
209
+ // rounded by the region clip, nested stripes by their own box clip below
210
+ UIBezierPath *borderPath = [UIBezierPath bezierPath];
211
+ [layoutManager
212
+ enumerateLineFragmentsForGlyphRange:glyphRange
213
+ usingBlock:^(CGRect rect, CGRect usedRect, NSTextContainer *container,
214
+ NSRange lineGlyphRange, BOOL *stop) {
215
+ NSRange lineCharRange = [layoutManager characterRangeForGlyphRange:lineGlyphRange
216
+ actualGlyphRange:NULL];
217
+ if (lineCharRange.location == NSNotFound || lineCharRange.length == 0) {
218
+ return;
219
+ }
220
+
221
+ NSDictionary *attrs = [textStorage attributesAtIndex:lineCharRange.location
222
+ effectiveRange:NULL];
223
+ NSNumber *depthNum = attrs[BlockquoteDepthAttributeName];
224
+
225
+ if (!depthNum) {
226
+ return;
227
+ }
228
+
229
+ NSInteger depth = [depthNum integerValue];
230
+ CGFloat baseY = origin.y + rect.origin.y;
231
+ CGFloat lineHeight = rect.size.height;
232
+ BOOL isLastLine = NSMaxRange(lineGlyphRange) == NSMaxRange(glyphRange);
233
+ if (isLastBlockquote && isLastLine) {
234
+ lineHeight += c.blockquotePadding;
235
+ }
236
+ BOOL isRTL = ENRMParagraphIsRTL(attrs[NSParagraphStyleAttributeName]);
237
+
238
+ for (NSInteger level = 0; level <= depth; level++) {
239
+ CGFloat borderX =
240
+ isRTL ? origin.x + containerWidth - borderWidth - (levelSpacing * level)
241
+ : origin.x + (levelSpacing * level);
242
+ CGRect borderRect = CGRectMake(borderX, baseY, borderWidth, lineHeight);
243
+
244
+ UIBezierPath *target = borderPath;
245
+ for (NSUInteger b = 0; b < boxRanges.count; b++) {
246
+ if (boxLevels[b].integerValue == level &&
247
+ NSLocationInRange(lineCharRange.location, boxRanges[b].rangeValue)) {
248
+ target = boxStripePaths[b];
249
+ break;
250
+ }
251
+ }
252
+ UIBezierPathAppendPath(target, [UIBezierPath bezierPathWithRect:borderRect]);
253
+ }
254
+ }];
255
+
256
+ // 3. Perform a single batch fill for the root-level borders
257
+ if (!borderPath.isEmpty) {
258
+ [borderColor setFill];
259
+ [borderPath fill];
260
+ }
261
+
262
+ // 4. Nested stripes: clip each to its own quote's rounded box (the clips
263
+ // compose with the still-active region clip)
264
+ for (NSUInteger b = 0; b < boxRanges.count; b++) {
265
+ UIBezierPath *stripes = boxStripePaths[b];
266
+ if (stripes.isEmpty) {
267
+ continue;
268
+ }
269
+
270
+ NSRange boxRange = boxRanges[b].rangeValue;
271
+ NSRange boxGlyphRange = [layoutManager glyphRangeForCharacterRange:boxRange actualCharacterRange:NULL];
272
+ CGRect boxRect = [layoutManager boundingRectForGlyphRange:boxGlyphRange inTextContainer:textContainer];
273
+ if (CGRectIsEmpty(boxRect)) {
274
+ continue;
275
+ }
276
+
277
+ NSDictionary *boxAttrs = [textStorage attributesAtIndex:boxRange.location effectiveRange:NULL];
278
+ BOOL boxRTL = ENRMParagraphIsRTL(boxAttrs[NSParagraphStyleAttributeName]);
279
+ CGFloat leadingInset = levelSpacing * boxLevels[b].integerValue;
280
+ boxRect.origin.x = boxRTL ? origin.x : origin.x + leadingInset;
281
+ boxRect.origin.y += origin.y;
282
+ boxRect.size.width = containerWidth - leadingInset;
283
+
284
+ CGContextSaveGState(ctx);
285
+ [UIBezierPathWithRoundedRect(boxRect, borderRadius) addClip];
286
+ [borderColor setFill];
287
+ [stripes fill];
288
+ CGContextRestoreGState(ctx);
289
+ }
290
+ }
291
+ CGContextRestoreGState(ctx);
292
+ }
293
+
294
+ @end
@@ -1,19 +1,19 @@
1
- #pragma once
2
- #import "ENRMUIKit.h"
3
- #import "StyleConfig.h"
4
-
5
- NS_ASSUME_NONNULL_BEGIN
6
-
7
- extern NSString *const CodeAttributeName;
8
-
9
- @interface CodeBackground : NSObject
10
-
11
- - (instancetype)initWithConfig:(StyleConfig *)config;
12
- - (void)drawBackgroundsForGlyphRange:(NSRange)glyphsToShow
13
- layoutManager:(NSLayoutManager *)layoutManager
14
- textContainer:(NSTextContainer *)textContainer
15
- atPoint:(CGPoint)origin;
16
-
17
- @end
18
-
19
- NS_ASSUME_NONNULL_END
1
+ #pragma once
2
+ #import "ENRMUIKit.h"
3
+ #import "StyleConfig.h"
4
+
5
+ NS_ASSUME_NONNULL_BEGIN
6
+
7
+ extern NSString *const CodeAttributeName;
8
+
9
+ @interface CodeBackground : NSObject
10
+
11
+ - (instancetype)initWithConfig:(StyleConfig *)config;
12
+ - (void)drawBackgroundsForGlyphRange:(NSRange)glyphsToShow
13
+ layoutManager:(NSLayoutManager *)layoutManager
14
+ textContainer:(NSTextContainer *)textContainer
15
+ atPoint:(CGPoint)origin;
16
+
17
+ @end
18
+
19
+ NS_ASSUME_NONNULL_END