@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,403 +1,403 @@
1
- #import "RenderContext.h"
2
- #import "CodeBackground.h"
3
- #import "FontUtils.h"
4
- #import <React/RCTFont.h>
5
-
6
- @implementation BlockStyle
7
- @end
8
-
9
- static NSArray<NSString *> *ENRMScopedKeyPaths(void)
10
- {
11
- static NSArray<NSString *> *keyPaths;
12
- static dispatch_once_t onceToken;
13
- dispatch_once(&onceToken, ^{
14
- keyPaths = @[
15
- @"currentBlockType",
16
- @"currentHeadingLevel",
17
- @"currentBlockStyle.fontSize",
18
- @"currentBlockStyle.fontFamily",
19
- @"currentBlockStyle.fontWeight",
20
- @"currentBlockStyle.color",
21
- @"currentBlockStyle.cachedFont",
22
- @"currentBlockStyle.cachedTextAttributes",
23
- @"blockquoteDepth",
24
- @"listDepth",
25
- @"listType",
26
- @"listItemNumber",
27
- @"listMarkerWidth",
28
- @"listMarkerExtra",
29
- @"ancestorMarkerOffset",
30
- @"listItemMarkerExtra",
31
- @"accumulatedIndent",
32
- ];
33
- });
34
- return keyPaths;
35
- }
36
-
37
- @implementation RenderContext {
38
- NSMutableDictionary<NSString *, UIFont *> *_fontCache;
39
- NSParagraphStyle *_baseSpacerTemplate;
40
- NSParagraphStyle *_baseBlockSpacerTemplate;
41
- }
42
-
43
- - (instancetype)init
44
- {
45
- if (self = [super init]) {
46
- _linkRanges = [NSMutableArray array];
47
- _linkURLs = [NSMutableArray array];
48
- _headingRanges = [NSMutableArray array];
49
- _headingLevels = [NSMutableArray array];
50
- _imageRanges = [NSMutableArray array];
51
- _imageAltTexts = [NSMutableArray array];
52
- _imageURLs = [NSMutableArray array];
53
- _listItemRanges = [NSMutableArray array];
54
- _listItemPositions = [NSMutableArray array];
55
- _listItemDepths = [NSMutableArray array];
56
- _listItemOrdered = [NSMutableArray array];
57
- _mathReporters = [NSMutableArray array];
58
- _fontCache = [NSMutableDictionary dictionary];
59
- _currentBlockStyle = [[BlockStyle alloc] init];
60
- _allowFontScaling = YES;
61
- _maxFontSizeMultiplier = 0;
62
-
63
- NSMutableParagraphStyle *spacerTemplate = [[NSMutableParagraphStyle alloc] init];
64
- _baseSpacerTemplate = [spacerTemplate copy];
65
-
66
- NSMutableParagraphStyle *blockSpacerTemplate = [[NSMutableParagraphStyle alloc] init];
67
- blockSpacerTemplate.minimumLineHeight = 1;
68
- blockSpacerTemplate.maximumLineHeight = 1;
69
- _baseBlockSpacerTemplate = [blockSpacerTemplate copy];
70
-
71
- [self reset];
72
- }
73
- return self;
74
- }
75
-
76
- #pragma mark - Font Cache
77
-
78
- - (UIFont *)cachedFontForSize:(CGFloat)fontSize family:(NSString *)fontFamily weight:(NSString *)fontWeight
79
- {
80
- CGFloat effectiveMultiplier = _allowFontScaling ? RCTFontSizeMultiplierWithMax(_maxFontSizeMultiplier) : 1.0;
81
-
82
- NSString *weightKey = (fontWeight.length > 0) ? fontWeight : @"";
83
- NSString *key =
84
- [NSString stringWithFormat:@"%.1f|%@|%@|%.2f", fontSize, fontFamily ?: @"", weightKey, effectiveMultiplier];
85
-
86
- UIFont *cached = _fontCache[key];
87
- if (cached) {
88
- return cached;
89
- }
90
-
91
- NSString *effectiveWeight = (fontWeight.length > 0) ? fontWeight : nil;
92
-
93
- UIFont *font = [RCTFont updateFont:nil
94
- withFamily:fontFamily
95
- size:@(fontSize)
96
- weight:effectiveWeight
97
- style:nil
98
- variant:nil
99
- scaleMultiplier:effectiveMultiplier];
100
-
101
- if (font) {
102
- _fontCache[key] = font;
103
- }
104
- return font;
105
- }
106
-
107
- #pragma mark - Paragraph Style Factory
108
-
109
- - (NSMutableParagraphStyle *)spacerStyleWithHeight:(CGFloat)height spacing:(CGFloat)spacing
110
- {
111
- NSMutableParagraphStyle *style = [_baseSpacerTemplate mutableCopy];
112
- style.minimumLineHeight = height;
113
- style.maximumLineHeight = height;
114
- style.paragraphSpacing = spacing;
115
- return style;
116
- }
117
-
118
- - (NSMutableParagraphStyle *)blockSpacerStyleWithMargin:(CGFloat)margin
119
- {
120
- NSMutableParagraphStyle *style = [_baseBlockSpacerTemplate mutableCopy];
121
- style.paragraphSpacing = margin;
122
- return style;
123
- }
124
-
125
- #pragma mark - Link Registry
126
-
127
- - (void)registerLinkRange:(NSRange)range url:(NSString *)url
128
- {
129
- if (range.length == 0)
130
- return;
131
- [self.linkRanges addObject:[NSValue valueWithRange:range]];
132
- [self.linkURLs addObject:url ?: @""];
133
- }
134
-
135
- - (void)applyLinkAttributesToString:(NSMutableAttributedString *)attributedString
136
- {
137
- NSUInteger length = attributedString.length;
138
- for (NSUInteger i = 0; i < self.linkRanges.count; i++) {
139
- NSRange range = [self.linkRanges[i] rangeValue];
140
- if (NSMaxRange(range) > length)
141
- continue;
142
- [attributedString addAttribute:@"linkURL" value:self.linkURLs[i] range:range];
143
- }
144
- }
145
-
146
- - (void)applyImageAttributesToString:(NSMutableAttributedString *)attributedString
147
- {
148
- NSUInteger length = attributedString.length;
149
- for (NSUInteger i = 0; i < self.imageRanges.count; i++) {
150
- NSRange range = [self.imageRanges[i] rangeValue];
151
- if (NSMaxRange(range) > length)
152
- continue;
153
- [attributedString addAttribute:@"imageURL" value:self.imageURLs[i] range:range];
154
- [attributedString addAttribute:@"imageAltText" value:self.imageAltTexts[i] range:range];
155
- }
156
- }
157
-
158
- - (void)registerHeadingRange:(NSRange)range level:(NSInteger)level text:(NSString *)text
159
- {
160
- if (range.length == 0)
161
- return;
162
- [self.headingRanges addObject:[NSValue valueWithRange:range]];
163
- [self.headingLevels addObject:@(level)];
164
- }
165
-
166
- - (void)registerImageRange:(NSRange)range altText:(NSString *)altText url:(NSString *)url
167
- {
168
- if (range.length == 0)
169
- return;
170
- [self.imageRanges addObject:[NSValue valueWithRange:range]];
171
- [self.imageAltTexts addObject:altText ?: @""];
172
- [self.imageURLs addObject:url ?: @""];
173
- }
174
-
175
- #pragma mark - Registration Helpers
176
-
177
- - (void)registerListItemRange:(NSRange)range
178
- position:(NSInteger)position
179
- depth:(NSInteger)depth
180
- isOrdered:(BOOL)isOrdered
181
- {
182
- if (![self isValidRange:range])
183
- return;
184
-
185
- [self.listItemRanges addObject:[NSValue valueWithRange:range]];
186
- [self.listItemPositions addObject:@(position)];
187
- [self.listItemDepths addObject:@(depth)];
188
- [self.listItemOrdered addObject:@(isOrdered)];
189
- }
190
-
191
- #pragma mark - Private
192
-
193
- - (BOOL)isValidRange:(NSRange)range
194
- {
195
- return range.length > 0 && range.location != NSNotFound;
196
- }
197
-
198
- #pragma mark - Block Style Management
199
-
200
- /**
201
- * Updates the shared BlockStyle object with new traits.
202
- * This avoids allocating a new object for every block node in the AST.
203
- */
204
- - (void)setBlockStyle:(BlockType)type
205
- fontSize:(CGFloat)fontSize
206
- fontFamily:(NSString *)fontFamily
207
- fontWeight:(NSString *)fontWeight
208
- color:(RCTUIColor *)color
209
- headingLevel:(NSInteger)headingLevel
210
- {
211
- _currentBlockType = type;
212
- _currentHeadingLevel = headingLevel;
213
-
214
- _currentBlockStyle.fontSize = fontSize;
215
- _currentBlockStyle.fontFamily = fontFamily ?: @"";
216
- _currentBlockStyle.fontWeight = fontWeight ?: @"normal";
217
- _currentBlockStyle.color = color ?: [RCTUIColor blackColor];
218
- }
219
-
220
- - (void)setBlockStyle:(BlockType)type
221
- fontSize:(CGFloat)fontSize
222
- fontFamily:(NSString *)fontFamily
223
- fontWeight:(NSString *)fontWeight
224
- color:(RCTUIColor *)color
225
- {
226
- [self setBlockStyle:type fontSize:fontSize fontFamily:fontFamily fontWeight:fontWeight color:color headingLevel:0];
227
- }
228
-
229
- - (void)setBlockStyle:(BlockType)type font:(UIFont *)font color:(RCTUIColor *)color headingLevel:(NSInteger)headingLevel
230
- {
231
- _currentBlockType = type;
232
- _currentHeadingLevel = headingLevel;
233
-
234
- RCTUIColor *finalColor = color ?: [RCTUIColor blackColor];
235
- _currentBlockStyle.cachedFont = font;
236
- _currentBlockStyle.color = finalColor;
237
-
238
- // Pre-create text attributes dictionary if we have both font and color
239
- if (font) {
240
- _currentBlockStyle.cachedTextAttributes =
241
- @{NSFontAttributeName : font, NSForegroundColorAttributeName : finalColor};
242
- }
243
- }
244
-
245
- - (BlockStyle *)getBlockStyle
246
- {
247
- return _currentBlockStyle;
248
- }
249
-
250
- - (NSDictionary *)getTextAttributes
251
- {
252
- BlockStyle *style = _currentBlockStyle;
253
-
254
- // Return pre-cached attributes if available
255
- if (style.cachedTextAttributes) {
256
- return style.cachedTextAttributes;
257
- }
258
-
259
- // Fall back to creating attributes from font cache
260
- UIFont *font = style.cachedFont;
261
- if (!font) {
262
- font = [self cachedFontForSize:style.fontSize family:style.fontFamily weight:style.fontWeight];
263
- }
264
- RCTUIColor *color = style.color ?: [RCTUIColor blackColor];
265
-
266
- // Cache for future calls within same block
267
- style.cachedTextAttributes = @{NSFontAttributeName : font, NSForegroundColorAttributeName : color};
268
- return style.cachedTextAttributes;
269
- }
270
-
271
- - (void)clearBlockStyle
272
- {
273
- _currentBlockType = BlockTypeNone;
274
- _currentHeadingLevel = 0;
275
- _currentBlockStyle.cachedFont = nil;
276
- _currentBlockStyle.cachedTextAttributes = nil;
277
- }
278
-
279
- - (id)snapshotScope
280
- {
281
- NSArray<NSString *> *keyPaths = ENRMScopedKeyPaths();
282
- NSMutableDictionary *snapshot = [NSMutableDictionary dictionaryWithCapacity:keyPaths.count];
283
- for (NSString *keyPath in keyPaths) {
284
- snapshot[keyPath] = [self valueForKeyPath:keyPath] ?: [NSNull null];
285
- }
286
- return snapshot;
287
- }
288
-
289
- - (void)restoreScope:(id)snapshot
290
- {
291
- NSDictionary *frame = snapshot;
292
- for (NSString *keyPath in ENRMScopedKeyPaths()) {
293
- id value = frame[keyPath];
294
- [self setValue:(value == [NSNull null] ? nil : value) forKeyPath:keyPath];
295
- }
296
- }
297
-
298
- #pragma mark - Reset
299
-
300
- - (void)reset
301
- {
302
- [_linkRanges removeAllObjects];
303
- [_linkURLs removeAllObjects];
304
- [_headingRanges removeAllObjects];
305
- [_headingLevels removeAllObjects];
306
- [_imageRanges removeAllObjects];
307
- [_imageAltTexts removeAllObjects];
308
- [_imageURLs removeAllObjects];
309
- [_listItemRanges removeAllObjects];
310
- [_listItemPositions removeAllObjects];
311
- [_listItemDepths removeAllObjects];
312
- [_listItemOrdered removeAllObjects];
313
- [_mathReporters removeAllObjects];
314
- [self clearBlockStyle];
315
-
316
- _blockquoteDepth = 0;
317
- _listDepth = 0;
318
- _listType = ListTypeUnordered;
319
- _listItemNumber = 0;
320
- _listMarkerWidth = 0;
321
- _listMarkerExtra = 0;
322
- _ancestorMarkerOffset = 0;
323
- _listItemMarkerExtra = 0;
324
- _accumulatedIndent = 0;
325
- _taskItemCount = 0;
326
-
327
- // Revert shared style object to baseline defaults
328
- _currentBlockStyle.fontSize = 0;
329
- _currentBlockStyle.fontFamily = @"";
330
- _currentBlockStyle.fontWeight = @"";
331
- _currentBlockStyle.color = [RCTUIColor blackColor];
332
- }
333
-
334
- #pragma mark - Static Utilities
335
-
336
- /**
337
- * Determines if specific inline attributes should protect the current color.
338
- */
339
- + (BOOL)shouldPreserveColors:(NSDictionary *)attrs
340
- {
341
- return (attrs[NSLinkAttributeName] != nil || attrs[CodeAttributeName] != nil);
342
- }
343
-
344
- // TODO: Unify calculateStrongColor and calculateHighlightColor into a single helper that
345
- // resolves inline foreground color from (configColor, inheritanceBaseline, blockColor).
346
-
347
- /**
348
- * Calculates whether a strong color should override the block color.
349
- */
350
- + (RCTUIColor *)calculateStrongColor:(RCTUIColor *)configStrongColor blockColor:(RCTUIColor *)blockColor
351
- {
352
- if (!configStrongColor || [configStrongColor isEqual:blockColor]) {
353
- return blockColor;
354
- }
355
- return configStrongColor;
356
- }
357
-
358
- + (RCTUIColor *)calculateHighlightColor:(RCTUIColor *)configHighlightColor
359
- paragraphColor:(RCTUIColor *)paragraphColor
360
- blockColor:(RCTUIColor *)blockColor
361
- {
362
- if ([configHighlightColor isEqual:paragraphColor]) {
363
- return blockColor;
364
- }
365
- return configHighlightColor;
366
- }
367
-
368
- /**
369
- * Safely calculates a range based on a start point and the current output length.
370
- */
371
- + (NSRange)rangeForRenderedContent:(NSMutableAttributedString *)output start:(NSUInteger)start
372
- {
373
- if (output.length < start)
374
- return NSMakeRange(start, 0);
375
- return NSMakeRange(start, output.length - start);
376
- }
377
-
378
- /**
379
- * Surgically applies attributes only if they differ from current values.
380
- * This minimizes "dirtying" the AttributedString, which improves layout performance.
381
- */
382
- + (void)applyFontAndColorAttributes:(NSMutableAttributedString *)output
383
- range:(NSRange)range
384
- font:(UIFont *)font
385
- color:(RCTUIColor *)color
386
- existingAttributes:(NSDictionary *)attrs
387
- shouldPreserveColors:(BOOL)shouldPreserve
388
- {
389
- if (range.length == 0)
390
- return;
391
-
392
- // Font Update: Only if it exists and is different
393
- if (font && ![font isEqual:attrs[NSFontAttributeName]]) {
394
- [output addAttribute:NSFontAttributeName value:font range:range];
395
- }
396
-
397
- // Color Update: Only if not a link/code and different from existing
398
- if (color && !shouldPreserve && ![color isEqual:attrs[NSForegroundColorAttributeName]]) {
399
- [output addAttribute:NSForegroundColorAttributeName value:color range:range];
400
- }
401
- }
402
-
1
+ #import "RenderContext.h"
2
+ #import "CodeBackground.h"
3
+ #import "FontUtils.h"
4
+ #import <React/RCTFont.h>
5
+
6
+ @implementation BlockStyle
7
+ @end
8
+
9
+ static NSArray<NSString *> *ENRMScopedKeyPaths(void)
10
+ {
11
+ static NSArray<NSString *> *keyPaths;
12
+ static dispatch_once_t onceToken;
13
+ dispatch_once(&onceToken, ^{
14
+ keyPaths = @[
15
+ @"currentBlockType",
16
+ @"currentHeadingLevel",
17
+ @"currentBlockStyle.fontSize",
18
+ @"currentBlockStyle.fontFamily",
19
+ @"currentBlockStyle.fontWeight",
20
+ @"currentBlockStyle.color",
21
+ @"currentBlockStyle.cachedFont",
22
+ @"currentBlockStyle.cachedTextAttributes",
23
+ @"blockquoteDepth",
24
+ @"listDepth",
25
+ @"listType",
26
+ @"listItemNumber",
27
+ @"listMarkerWidth",
28
+ @"listMarkerExtra",
29
+ @"ancestorMarkerOffset",
30
+ @"listItemMarkerExtra",
31
+ @"accumulatedIndent",
32
+ ];
33
+ });
34
+ return keyPaths;
35
+ }
36
+
37
+ @implementation RenderContext {
38
+ NSMutableDictionary<NSString *, UIFont *> *_fontCache;
39
+ NSParagraphStyle *_baseSpacerTemplate;
40
+ NSParagraphStyle *_baseBlockSpacerTemplate;
41
+ }
42
+
43
+ - (instancetype)init
44
+ {
45
+ if (self = [super init]) {
46
+ _linkRanges = [NSMutableArray array];
47
+ _linkURLs = [NSMutableArray array];
48
+ _headingRanges = [NSMutableArray array];
49
+ _headingLevels = [NSMutableArray array];
50
+ _imageRanges = [NSMutableArray array];
51
+ _imageAltTexts = [NSMutableArray array];
52
+ _imageURLs = [NSMutableArray array];
53
+ _listItemRanges = [NSMutableArray array];
54
+ _listItemPositions = [NSMutableArray array];
55
+ _listItemDepths = [NSMutableArray array];
56
+ _listItemOrdered = [NSMutableArray array];
57
+ _mathReporters = [NSMutableArray array];
58
+ _fontCache = [NSMutableDictionary dictionary];
59
+ _currentBlockStyle = [[BlockStyle alloc] init];
60
+ _allowFontScaling = YES;
61
+ _maxFontSizeMultiplier = 0;
62
+
63
+ NSMutableParagraphStyle *spacerTemplate = [[NSMutableParagraphStyle alloc] init];
64
+ _baseSpacerTemplate = [spacerTemplate copy];
65
+
66
+ NSMutableParagraphStyle *blockSpacerTemplate = [[NSMutableParagraphStyle alloc] init];
67
+ blockSpacerTemplate.minimumLineHeight = 1;
68
+ blockSpacerTemplate.maximumLineHeight = 1;
69
+ _baseBlockSpacerTemplate = [blockSpacerTemplate copy];
70
+
71
+ [self reset];
72
+ }
73
+ return self;
74
+ }
75
+
76
+ #pragma mark - Font Cache
77
+
78
+ - (UIFont *)cachedFontForSize:(CGFloat)fontSize family:(NSString *)fontFamily weight:(NSString *)fontWeight
79
+ {
80
+ CGFloat effectiveMultiplier = _allowFontScaling ? RCTFontSizeMultiplierWithMax(_maxFontSizeMultiplier) : 1.0;
81
+
82
+ NSString *weightKey = (fontWeight.length > 0) ? fontWeight : @"";
83
+ NSString *key =
84
+ [NSString stringWithFormat:@"%.1f|%@|%@|%.2f", fontSize, fontFamily ?: @"", weightKey, effectiveMultiplier];
85
+
86
+ UIFont *cached = _fontCache[key];
87
+ if (cached) {
88
+ return cached;
89
+ }
90
+
91
+ NSString *effectiveWeight = (fontWeight.length > 0) ? fontWeight : nil;
92
+
93
+ UIFont *font = [RCTFont updateFont:nil
94
+ withFamily:fontFamily
95
+ size:@(fontSize)
96
+ weight:effectiveWeight
97
+ style:nil
98
+ variant:nil
99
+ scaleMultiplier:effectiveMultiplier];
100
+
101
+ if (font) {
102
+ _fontCache[key] = font;
103
+ }
104
+ return font;
105
+ }
106
+
107
+ #pragma mark - Paragraph Style Factory
108
+
109
+ - (NSMutableParagraphStyle *)spacerStyleWithHeight:(CGFloat)height spacing:(CGFloat)spacing
110
+ {
111
+ NSMutableParagraphStyle *style = [_baseSpacerTemplate mutableCopy];
112
+ style.minimumLineHeight = height;
113
+ style.maximumLineHeight = height;
114
+ style.paragraphSpacing = spacing;
115
+ return style;
116
+ }
117
+
118
+ - (NSMutableParagraphStyle *)blockSpacerStyleWithMargin:(CGFloat)margin
119
+ {
120
+ NSMutableParagraphStyle *style = [_baseBlockSpacerTemplate mutableCopy];
121
+ style.paragraphSpacing = margin;
122
+ return style;
123
+ }
124
+
125
+ #pragma mark - Link Registry
126
+
127
+ - (void)registerLinkRange:(NSRange)range url:(NSString *)url
128
+ {
129
+ if (range.length == 0)
130
+ return;
131
+ [self.linkRanges addObject:[NSValue valueWithRange:range]];
132
+ [self.linkURLs addObject:url ?: @""];
133
+ }
134
+
135
+ - (void)applyLinkAttributesToString:(NSMutableAttributedString *)attributedString
136
+ {
137
+ NSUInteger length = attributedString.length;
138
+ for (NSUInteger i = 0; i < self.linkRanges.count; i++) {
139
+ NSRange range = [self.linkRanges[i] rangeValue];
140
+ if (NSMaxRange(range) > length)
141
+ continue;
142
+ [attributedString addAttribute:@"linkURL" value:self.linkURLs[i] range:range];
143
+ }
144
+ }
145
+
146
+ - (void)applyImageAttributesToString:(NSMutableAttributedString *)attributedString
147
+ {
148
+ NSUInteger length = attributedString.length;
149
+ for (NSUInteger i = 0; i < self.imageRanges.count; i++) {
150
+ NSRange range = [self.imageRanges[i] rangeValue];
151
+ if (NSMaxRange(range) > length)
152
+ continue;
153
+ [attributedString addAttribute:@"imageURL" value:self.imageURLs[i] range:range];
154
+ [attributedString addAttribute:@"imageAltText" value:self.imageAltTexts[i] range:range];
155
+ }
156
+ }
157
+
158
+ - (void)registerHeadingRange:(NSRange)range level:(NSInteger)level text:(NSString *)text
159
+ {
160
+ if (range.length == 0)
161
+ return;
162
+ [self.headingRanges addObject:[NSValue valueWithRange:range]];
163
+ [self.headingLevels addObject:@(level)];
164
+ }
165
+
166
+ - (void)registerImageRange:(NSRange)range altText:(NSString *)altText url:(NSString *)url
167
+ {
168
+ if (range.length == 0)
169
+ return;
170
+ [self.imageRanges addObject:[NSValue valueWithRange:range]];
171
+ [self.imageAltTexts addObject:altText ?: @""];
172
+ [self.imageURLs addObject:url ?: @""];
173
+ }
174
+
175
+ #pragma mark - Registration Helpers
176
+
177
+ - (void)registerListItemRange:(NSRange)range
178
+ position:(NSInteger)position
179
+ depth:(NSInteger)depth
180
+ isOrdered:(BOOL)isOrdered
181
+ {
182
+ if (![self isValidRange:range])
183
+ return;
184
+
185
+ [self.listItemRanges addObject:[NSValue valueWithRange:range]];
186
+ [self.listItemPositions addObject:@(position)];
187
+ [self.listItemDepths addObject:@(depth)];
188
+ [self.listItemOrdered addObject:@(isOrdered)];
189
+ }
190
+
191
+ #pragma mark - Private
192
+
193
+ - (BOOL)isValidRange:(NSRange)range
194
+ {
195
+ return range.length > 0 && range.location != NSNotFound;
196
+ }
197
+
198
+ #pragma mark - Block Style Management
199
+
200
+ /**
201
+ * Updates the shared BlockStyle object with new traits.
202
+ * This avoids allocating a new object for every block node in the AST.
203
+ */
204
+ - (void)setBlockStyle:(BlockType)type
205
+ fontSize:(CGFloat)fontSize
206
+ fontFamily:(NSString *)fontFamily
207
+ fontWeight:(NSString *)fontWeight
208
+ color:(RCTUIColor *)color
209
+ headingLevel:(NSInteger)headingLevel
210
+ {
211
+ _currentBlockType = type;
212
+ _currentHeadingLevel = headingLevel;
213
+
214
+ _currentBlockStyle.fontSize = fontSize;
215
+ _currentBlockStyle.fontFamily = fontFamily ?: @"";
216
+ _currentBlockStyle.fontWeight = fontWeight ?: @"normal";
217
+ _currentBlockStyle.color = color ?: [RCTUIColor blackColor];
218
+ }
219
+
220
+ - (void)setBlockStyle:(BlockType)type
221
+ fontSize:(CGFloat)fontSize
222
+ fontFamily:(NSString *)fontFamily
223
+ fontWeight:(NSString *)fontWeight
224
+ color:(RCTUIColor *)color
225
+ {
226
+ [self setBlockStyle:type fontSize:fontSize fontFamily:fontFamily fontWeight:fontWeight color:color headingLevel:0];
227
+ }
228
+
229
+ - (void)setBlockStyle:(BlockType)type font:(UIFont *)font color:(RCTUIColor *)color headingLevel:(NSInteger)headingLevel
230
+ {
231
+ _currentBlockType = type;
232
+ _currentHeadingLevel = headingLevel;
233
+
234
+ RCTUIColor *finalColor = color ?: [RCTUIColor blackColor];
235
+ _currentBlockStyle.cachedFont = font;
236
+ _currentBlockStyle.color = finalColor;
237
+
238
+ // Pre-create text attributes dictionary if we have both font and color
239
+ if (font) {
240
+ _currentBlockStyle.cachedTextAttributes =
241
+ @{NSFontAttributeName : font, NSForegroundColorAttributeName : finalColor};
242
+ }
243
+ }
244
+
245
+ - (BlockStyle *)getBlockStyle
246
+ {
247
+ return _currentBlockStyle;
248
+ }
249
+
250
+ - (NSDictionary *)getTextAttributes
251
+ {
252
+ BlockStyle *style = _currentBlockStyle;
253
+
254
+ // Return pre-cached attributes if available
255
+ if (style.cachedTextAttributes) {
256
+ return style.cachedTextAttributes;
257
+ }
258
+
259
+ // Fall back to creating attributes from font cache
260
+ UIFont *font = style.cachedFont;
261
+ if (!font) {
262
+ font = [self cachedFontForSize:style.fontSize family:style.fontFamily weight:style.fontWeight];
263
+ }
264
+ RCTUIColor *color = style.color ?: [RCTUIColor blackColor];
265
+
266
+ // Cache for future calls within same block
267
+ style.cachedTextAttributes = @{NSFontAttributeName : font, NSForegroundColorAttributeName : color};
268
+ return style.cachedTextAttributes;
269
+ }
270
+
271
+ - (void)clearBlockStyle
272
+ {
273
+ _currentBlockType = BlockTypeNone;
274
+ _currentHeadingLevel = 0;
275
+ _currentBlockStyle.cachedFont = nil;
276
+ _currentBlockStyle.cachedTextAttributes = nil;
277
+ }
278
+
279
+ - (id)snapshotScope
280
+ {
281
+ NSArray<NSString *> *keyPaths = ENRMScopedKeyPaths();
282
+ NSMutableDictionary *snapshot = [NSMutableDictionary dictionaryWithCapacity:keyPaths.count];
283
+ for (NSString *keyPath in keyPaths) {
284
+ snapshot[keyPath] = [self valueForKeyPath:keyPath] ?: [NSNull null];
285
+ }
286
+ return snapshot;
287
+ }
288
+
289
+ - (void)restoreScope:(id)snapshot
290
+ {
291
+ NSDictionary *frame = snapshot;
292
+ for (NSString *keyPath in ENRMScopedKeyPaths()) {
293
+ id value = frame[keyPath];
294
+ [self setValue:(value == [NSNull null] ? nil : value) forKeyPath:keyPath];
295
+ }
296
+ }
297
+
298
+ #pragma mark - Reset
299
+
300
+ - (void)reset
301
+ {
302
+ [_linkRanges removeAllObjects];
303
+ [_linkURLs removeAllObjects];
304
+ [_headingRanges removeAllObjects];
305
+ [_headingLevels removeAllObjects];
306
+ [_imageRanges removeAllObjects];
307
+ [_imageAltTexts removeAllObjects];
308
+ [_imageURLs removeAllObjects];
309
+ [_listItemRanges removeAllObjects];
310
+ [_listItemPositions removeAllObjects];
311
+ [_listItemDepths removeAllObjects];
312
+ [_listItemOrdered removeAllObjects];
313
+ [_mathReporters removeAllObjects];
314
+ [self clearBlockStyle];
315
+
316
+ _blockquoteDepth = 0;
317
+ _listDepth = 0;
318
+ _listType = ListTypeUnordered;
319
+ _listItemNumber = 0;
320
+ _listMarkerWidth = 0;
321
+ _listMarkerExtra = 0;
322
+ _ancestorMarkerOffset = 0;
323
+ _listItemMarkerExtra = 0;
324
+ _accumulatedIndent = 0;
325
+ _taskItemCount = 0;
326
+
327
+ // Revert shared style object to baseline defaults
328
+ _currentBlockStyle.fontSize = 0;
329
+ _currentBlockStyle.fontFamily = @"";
330
+ _currentBlockStyle.fontWeight = @"";
331
+ _currentBlockStyle.color = [RCTUIColor blackColor];
332
+ }
333
+
334
+ #pragma mark - Static Utilities
335
+
336
+ /**
337
+ * Determines if specific inline attributes should protect the current color.
338
+ */
339
+ + (BOOL)shouldPreserveColors:(NSDictionary *)attrs
340
+ {
341
+ return (attrs[NSLinkAttributeName] != nil || attrs[CodeAttributeName] != nil);
342
+ }
343
+
344
+ // TODO: Unify calculateStrongColor and calculateHighlightColor into a single helper that
345
+ // resolves inline foreground color from (configColor, inheritanceBaseline, blockColor).
346
+
347
+ /**
348
+ * Calculates whether a strong color should override the block color.
349
+ */
350
+ + (RCTUIColor *)calculateStrongColor:(RCTUIColor *)configStrongColor blockColor:(RCTUIColor *)blockColor
351
+ {
352
+ if (!configStrongColor || [configStrongColor isEqual:blockColor]) {
353
+ return blockColor;
354
+ }
355
+ return configStrongColor;
356
+ }
357
+
358
+ + (RCTUIColor *)calculateHighlightColor:(RCTUIColor *)configHighlightColor
359
+ paragraphColor:(RCTUIColor *)paragraphColor
360
+ blockColor:(RCTUIColor *)blockColor
361
+ {
362
+ if ([configHighlightColor isEqual:paragraphColor]) {
363
+ return blockColor;
364
+ }
365
+ return configHighlightColor;
366
+ }
367
+
368
+ /**
369
+ * Safely calculates a range based on a start point and the current output length.
370
+ */
371
+ + (NSRange)rangeForRenderedContent:(NSMutableAttributedString *)output start:(NSUInteger)start
372
+ {
373
+ if (output.length < start)
374
+ return NSMakeRange(start, 0);
375
+ return NSMakeRange(start, output.length - start);
376
+ }
377
+
378
+ /**
379
+ * Surgically applies attributes only if they differ from current values.
380
+ * This minimizes "dirtying" the AttributedString, which improves layout performance.
381
+ */
382
+ + (void)applyFontAndColorAttributes:(NSMutableAttributedString *)output
383
+ range:(NSRange)range
384
+ font:(UIFont *)font
385
+ color:(RCTUIColor *)color
386
+ existingAttributes:(NSDictionary *)attrs
387
+ shouldPreserveColors:(BOOL)shouldPreserve
388
+ {
389
+ if (range.length == 0)
390
+ return;
391
+
392
+ // Font Update: Only if it exists and is different
393
+ if (font && ![font isEqual:attrs[NSFontAttributeName]]) {
394
+ [output addAttribute:NSFontAttributeName value:font range:range];
395
+ }
396
+
397
+ // Color Update: Only if not a link/code and different from existing
398
+ if (color && !shouldPreserve && ![color isEqual:attrs[NSForegroundColorAttributeName]]) {
399
+ [output addAttribute:NSForegroundColorAttributeName value:color range:range];
400
+ }
401
+ }
402
+
403
403
  @end